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().