Главная chevron_right Функции chevron_right Связь chevron_right Stream.find()

Stream.find()

Stream.find() читает поток побайтово и возвращает true, если заданная строка найдена до истечения таймаута — при этом все просмотренные байты извлекаются из буфера и недоступны для read().

Полная статья

Описание

find() последовательно читает данные из потока и ищет заданную строку символов. Как только цель найдена, функция возвращает true и останавливается. Если данные закончились или истёк таймаут — возвращает false. Длину таймаута можно задать с помощью Stream.setTimeout().

Функция принадлежит базовому классу Stream, поэтому работает со всеми его наследниками: Serial, Wire, сетевыми клиентами и другими. Подробнее об иерархии классов — на странице Stream.

Важно понимать: find() не просто проверяет буфер, а именно читает поток. Все байты, которые функция просмотрела в процессе поиска, извлекаются из буфера и становятся недоступны для последующих вызовов read().

Синтаксис

  • stream.find(target)
  • stream.find(target, length)

Параметры

  • target — строка символов, которую нужно найти в потоке. Тип данных: char*.
  • length — количество байт в строке target, которые нужно учитывать при поиске. Тип данных: size_t.

Возвращает

true — если целевая последовательность найдена до истечения таймаута. false — если таймаут истёк раньше, чем цель появилась в потоке.

Тип данных: bool.

Пример кода

Скетч ждёт ответ OK от устройства, подключённого к последовательному порту:

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(2000);
}

void loop() {
  Serial.println("AT");

  if (Serial.find("OK")) {
    Serial.println("Device answered");
  } else {
    Serial.println("No OK before timeout");
  }

  delay(1000);
}

Где применяется

  • Ожидание ответа от модуля по AT-командам — например OK, READY, ERROR или другого текстового маркера.
  • Поиск начала пакета в потоке — когда перед полезными данными идут лишние байты, а нужный фрагмент начинается после известной метки.
  • Синхронизация с устройством — скетч дожидается признака готовности, прежде чем продолжить обмен данными.
  • Быстрая проверка текстового протокола — удобно убедиться, что нужный фрагмент вообще появляется в ответе, не разбирая весь поток вручную.

Практические замечания

  • Функция блокирует выполнение. Пока find() ищет цель, остальной код не выполняется. Если устройство молчит, ожидание продолжается вплоть до истечения таймаута — учитывайте это при проектировании скетча.
  • Прочитанные байты теряются. find() потребляет данные из потока. Если позже понадобятся все входящие байты, читайте их вручную через read() и сохраняйте в собственный буфер.
  • Подбирайте таймаут под реальный обмен. Слишком короткий таймаут прервёт поиск раньше, чем придёт ответ; слишком длинный сделает программу «вязкой». Для большинства команд достаточно 200–1000 мс, для медленных модулей может потребоваться больше.
  • Ищите уникальные маркеры. Чем короче target, тем выше вероятность случайного совпадения с другими данными в потоке. Там, где формат позволяет, лучше искать "OK\r\n" вместо просто "OK".
  • Для сложных протоколов предпочтительнее ручной парсер. find() удобна для простых сценариев, но если нужно обрабатывать ошибки, частичные пакеты или несколько типов сообщений, надёжнее читать поток вручную и явно управлять состоянием разбора.

Примечания и предупреждения

find() зависит от таймаута потока. Если функция неожиданно возвращает false, сначала убедитесь, что устройство действительно отправляет нужную последовательность, и проверьте, достаточно ли времени задано через Stream.setTimeout().