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

Stream.findUntil()

findUntil() ищет строку target в потоке данных и возвращает true, если нашла её раньше, чем встретился terminator или истёк таймаут.

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

Описание

findUntil() просматривает входящие данные из потока побайтово и ищет целевую строку target. В отличие от обычного find(), у этой функции есть дополнительный ограничитель — терминатор terminator. Поиск завершится в одном из трёх случаев: целевая последовательность найдена, в потоке раньше появился терминатор, или истёк таймаут ожидания новых данных. Таймаут настраивается через Stream.setTimeout().

Если target найден раньше терминатора, функция возвращает true. Если первым пришёл terminator или время ожидания вышло — false.

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

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

Синтаксис

stream.findUntil(target, terminator)

Параметры

  • target — строка символов, которую нужно найти в потоке. Тип данных: char*.
  • terminator — строка-ограничитель, при появлении которой поиск немедленно прекращается, даже если target ещё не найден. Тип данных: char*.

Возвращает

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

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

Пример кода

Скетч ожидает слово OK в ответе устройства, но прекращает ожидание сразу, как только в потоке появится строка ERROR:

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

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

  if (Serial.findUntil("OK", "ERROR")) {
    Serial.println("Command accepted");
  } else {
    Serial.println("OK was not found before ERROR or timeout");
  }

  delay(1000);
}

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

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

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

  • Функция блокирует выполнение. Пока ни target, ни terminator не получены, скетч стоит на месте и ждёт. Проектируйте логику с учётом этого поведения.
  • Прочитанные байты теряются. После вызова вернуться к данным, через которые прошёл поиск, уже нельзя. Если содержимое потока нужно сохранить, читайте его вручную через read() до вызова функции.
  • Терминатор — главное отличие от find(). Он позволяет ограничить область поиска одним сообщением и не «проваливаться» в следующие данные, если нужный маркер так и не появился.
  • Выбирайте уникальные маркеры. Однобуквенные строки вроде "O" или "E" могут случайно встретиться внутри полезных данных. Надёжнее использовать полные строки: "OK\r\n", "ERROR\r\n", "</packet>".
  • Подбирайте таймаут под устройство. Если устройство отвечает медленно, увеличьте значение через Stream.setTimeout(). Если важна отзывчивость скетча — уменьшите его, чтобы не зависать надолго в ожидании.

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

findUntil() сообщает только о факте нахождения целевой строки — true или false. Она не возвращает найденный текст и не запоминает промежуточные данные. Если нужно получить само содержимое сообщения, читайте поток вручную или используйте функции чтения строк, подходящие для вашего сценария.