Пульт от телевизора в мастерской умер в четверг, а в субботу планировался матч со звуком через колонки. Новый пульт ехал бы неделю, и тогда я впервые собрал сниффер: та же читалка кодов, что уже стоит на вашей макетке, плюс дисциплина журнала. Через полчаса у меня была таблица команд родного пульта, ещё через час колонки включались самодельным передатчиком, а пульт так и не купили — экономия вышла размером с обед. С тех пор сниффер — первый инструмент при переезде на новую технику: до покупок я смотрю, что шлёт родной пульт.
Сразу обозначим границу, которую обходят почти все туториалы. Сниффинг — не универсальная отмычка: телевизоры и музыкальные центры сдаются за вечер, кондиционеры требуют другой стратегии, а гаражные ворота и автоключи не сдадутся никогда — их коды меняются при каждом нажатии по замыслу производителя. В уроке — методика, журнал, воспроизведение и та черта, за которой копирование заканчивается. Честная граница экономит недели: до сих пор мне попадались вопросы на форумах «почему записанный кадр кондиционера не срабатывает», когда ответ был ровно один — кадр и не должен срабатывать, он устарел в момент записи.
Инструменты уже знакомы: приём и поля decodedIRData из урока про decode, передатчик IrSender из урока про sendNEC. Кондиционер мы разбирали по байтам в уроке про климатические протоколы — сегодня он вернётся одной строкой таблицы, а в центре будет телевизор и журнал, который не стыдно показать. Схема при этом не меняется ни на провод: сниффер читает кадры из эфира, журнальные строки превращаются в числа, а числа — в вызовы передатчика.
Журнал сниффера: протокол, адрес, команда
Сниффер отличается от читалки не схемой, а дисциплиной. Читалка печатает всё подряд, журнал же держит три колонки на каждый кадр: протокол, адрес устройства, команда. Адрес — половина успеха: у телевизора он свой, у пульта люстры другой, и в комнате с тремя пультами журнал без адреса превращается в свалку чисел. Кадры-повторы NEC в журнал не пишем — флаг IRDATA_FLAGS_IS_REPEAT отсеивает удержания, иначе таблица распухает втрое от одинаковых строк. Три колонки — не эстетика: каждая отвечает на свой вопрос — «кто сказал», «кому» и «что именно», и без любой из них реплей превращается в лотерею.
Каждый код я записываю в двух формах сразу: hex — для сверки с чужими таблицами и форумами, dec — для собственного скетча. Привычка из урока про bin, hex и dec: команда 0x43 на форуме находится глазами, а её десятичная версия 67 — мгновенно в моей таблице. И подпишите журнал сразу, какие кнопки жали: три столбца безымянных цифр через неделю читаются как археология, проверено не раз.
Журнал имеет свойство превращаться в скетч без перепечатки: строка с протоколом NEC уходит в заголовок как справка, адрес — в константу фильтра, а команды — в словарь из предыдущего урока. Я веду журнал прямо в текстовом файле рядом со скетчем и копирую столбцы вручную: за вечер набегает пятнадцать-двадцать строк, и ручной перенос заодно проверяет каждую цифру глазами. Автоматизировать это можно, но цена опечатки в адресе уже съела у меня вечер — теперь двойной контроль стоит бесплатно.
#include <IRremote.hpp> const int IR_PIN = 2; void setup() { Serial.begin(9600); IrReceiver.begin(IR_PIN, ENABLE_LED_FEEDBACK); Serial.println("zhurnal: protocol; address; command(hex); command(dec)");} void loop() { if (IrReceiver.decode()) { bool povtor = IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT; if (!povtor) { Serial.print(IrReceiver.getProtocolString()); Serial.print("; addr=0x"); Serial.print(IrReceiver.decodedIRData.address, HEX); Serial.print("; cmd=0x"); Serial.print(IrReceiver.decodedIRData.command, HEX); Serial.print(" ("); Serial.print(IrReceiver.decodedIRData.command); Serial.println(")"); } IrReceiver.resume(); }}Воспроизведение начинается с передатчика: ИК-светодиод через резистор 100–150 Ом на пин 3, где живёт аппаратная несущая Timer2 — та же развязка таймеров, что и в уроке про конфликт tone и приёмника. Дальше один вызов: IrSender.sendNEC(адрес, команда, 0) посылает кадр той же формы, что ушёл с родного пульта, инверсии байтов библиотека доложит сама. Ноль в третьем аргументе — счётчик повторных кадров: большинству устройств хватает одного полного кадра на нажатие. Повторы пригождаются точечно: регулировке громкости два-три повторных кадра заменяют удержание, а команде-переключателю они строго противопоказаны — каждое повторение переключает её заново.
Проверяю с полуметра, приёмником устройства в упор. Ресивер ждёт свой адрес и молча игнорирует чужие — тот самый фильтр по decodedIRData.address, который мы проходили на приёме. Протокол тоже копируется один в один: ресивер, выросший на RC5, на честный кадр NEC ответит тем же молчанием, и перепутанный протокол в журнале — второй кандидат после опечатки в адресе. Если устройство молчит на честный кадр, порядок проверки короткий: адрес (опечатка в hex съедает вечер — у меня девять из десяти неудач были именно там), затем протокол, затем жив ли передатчик — камера телефона покажет вспышки на диоде даже там, где глаз не видит ничего.
#include <IRremote.hpp> // числа — из журнала сниффера, не из головыconst uint16_t TV_ADDRESS = 0x00FF;const uint8_t TV_CMD_VOLP = 0x15; void setup() { IrReceiver.begin(2, ENABLE_LED_FEEDBACK); // свой пульт — в приёмник IrSender.begin(3); // передатчик — в эфир Serial.begin(9600);} void loop() { if (IrReceiver.decode()) { if (IrReceiver.decodedIRData.command == 9) { // EQ IrSender.sendNEC(TV_ADDRESS, TV_CMD_VOLP, 0); Serial.println("kadr ushel k televizoru"); } IrReceiver.resume(); }}Граница: фиксированный кадр, пульт-состояние, rolling code
Все устройства делятся на три класса, и методика для каждого своя. Первый — кнопочные: телевизор, музыкальный центр, люстра. Кадр несёт номер кнопки, состояние живёт в приёмнике устройства, и записанная команда честно повторяется годами. Здесь сниффинг заканчивается за вечер, и вся сложность — в аккуратном журнале. Именно на этом классе построена пара плат-реплеев, которые у меня живут годами: одна держит колонки, вторая — вентилятор в кладовке. У класса есть и обратная сторона: два устройства одной партии делят адрес, и команда уйдёт обоим — у меня одинаковые сетевые фильтры включались в паре, и адресом их не развести, только физически разнести.
Второй класс — пульты-состояния: кондиционеры и климатическая техника. Кадр несёт весь паспорт — градусы, режим, скорость вентилятора, жалюзи, — и кнопки «плюс один градус» в эфире не существует: пульт каждый раз пересобирает кадр целиком. Записывать надо не кнопки, а режимы, по одному кадру на состояние. Полный разбор с контрольными суммами и готовыми классами — в уроке про кондиционер; здесь важен вывод: журнал для климата — таблица состояний, а не кнопок.
Третий класс не сдаётся в принципе: гаражные шлюзы, автоключи, часть дверных звонков работают на rolling code — число в кадре меняется при каждом нажатии по алгоритму, зашитому в брелок и приёмник парно. Записанный кадр проигрывается вхолостую: приёмник ждёт следующее число последовательности, а не прошлое. Это защита от копирования как класс, и переступать её я не советую ни в каком виде — включая юридический: сниффим свою технику, чужую — только с разрешения владельца.
| Класс устройства | Примеры | Что в кадре | Сдаётся ли снифферу |
|---|---|---|---|
| Кнопочный | ТВ, музыкальный центр, люстра | номер кнопки; состояние живёт в приёмнике | да: журнал команд за один вечер |
| Пульт-состояние | кондиционеры, обогреватели | весь паспорт: режим, градусы, жалюзи | да, но по кадру на режим, а не на кнопку |
| Rolling code | гаражные шлюзы, автоключи | меняющееся число последовательности | нет: повтор вхолостую, защита как класс |
| Не ИК вовсе | колонки и шлюзы с Bluetooth или Wi-Fi | кадров нет — там радиоканал | не в этом разделе: другой инструмент |
Журнал из симулятора — готовая форма для реальной платы: столбцы протокол, адрес, команда переносятся в таблицу один к одному. Восемь строк в симуляторе — макет того, что на плате превращается в слоты EEPROM, а довести сниффер до конца поможет энергонезависимая память: журнал, который переживает отключение питания, — это уже обучаемый пульт из прошлой тройки, там те же слоты, только запись долгосрочная и с защитой от перезаписи.
Дальше — последний урок тройки: границы самого канала. Почему ИК не ходит через стены, чем отражения работают на вас и в каких задачах честнее радио. У сниффера и у самодельного передатчика эти границы общие: свет остаётся светом, от кого бы он ни исходил. И замер надёжности оттуда же пригодится немедленно: записанный кадр проверяйте с той же дистанции, на которой планировалась эксплуатация, иначе цифры дальности будут лгать.
- 1. Чем журнал сниффера отличается от обычной читалки кодов?
- 2. Устройство молчит на sendNEC с записанным кадром. Что проверять первым?
- 3. Что несёт кадр пульта-состояния, например кондиционера?
- 4. Почему записанный кадр гаражного шлюза не срабатывает?
- 5. Зачем повторам NEC запрет в журнале сниффера?
- Сниффер — та же читалка плюс дисциплина: протокол, адрес, команда на каждый кадр; повторы в журнал не пишем
- Код держите в двух формах: hex для сверки с чужими таблицами, dec для своего скетча
- Воспроизведение — IrSender.sendNEC(адрес, команда, 0) с пина 3; чужие адреса приёмник игнорирует молча
- Три класса устройств: кнопочные — таблица команд, климат — таблица состояний, rolling code — не сдаётся
- Граница законности: сниффим свою технику; чужая — только с разрешения владельца
Частые вопросы по теме урока
- Чем журнал сниффера отличается от обычной читалки кодов?
- Схема та же. Дисциплина другая: каждый кадр записывается с протоколом и адресом, а кадры-повторы NEC отсеиваются флагом IRDATA_FLAGS_IS_REPEAT. Тремя колонками на кадр — протокол, адрес, команда — и фильтром повторов
- Устройство молчит на sendNEC с записанным кадром. Что проверять первым?
- Приёмник ждёт свой адрес и выбрасывает чужие без ответа. По опыту — девять из десяти провалов сниффинга опечатка в адресе, проверяется за минуту. Адрес в hex — одна опечатка в байте, и ресивер молча игнорирует кадр
- Что несёт кадр пульта-состояния, например кондиционера?
- Состояние живёт в пульте, поэтому каждая кнопка уводит в эфир полный кадр состояния. Кнопки «плюс один градус» в эфире нет — есть пересобранный паспорт. Весь паспорт: градусы, режим, вентилятор, жалюзи
- Почему записанный кадр гаражного шлюза не срабатывает?
- Брелок и приёмник хранят общий счётчик: каждое нажатие сдвигает его. Повтор старого кадра выпадает из последовательности и отбрасывается — защита как класс. Rolling code: приёмник ждёт следующее число последовательности, а не прошлое
- Зачем повторам NEC запрет в журнале сниффера?
- Полсекунды удержания — четыре-пять одинаковых строк. Флаг IRDATA_FLAGS_IS_REPEAT отделяет первое нажатие, журнал остаётся коротким и честным. Удержание раздувает журнал одинаковыми кадрами каждые 108–110 мс