Вступление

Моя задача сечас - научиться отправлять команды кондиционерам и другим устройствам в доме. Исходно эти устройства имеют только IR remote control. Для решения этой задачи у меня есть Raspberry Pi и IR transceiver hat (о нем написано ниже).

Гугл подсказал, что задачу можно решить с помощью LIRC (Linux Infrared Remote Control). В процессе исследования выяснил, что LIRC работает как с передатчиками, так и с приемниками IR сигналов, может декодировать принятый сигнал и выполнять какие-то действия в связи с этим. Сейчас прием сигналов мне не нужен, но в будущем может оказаться полезным. Прочтение LIRC Configuration Guide крайне рекомендуется.

Конфигурация

apt-get update
apt-get install lirc
# /etc/modules (добавить в конец)
lirc_dev
lirc_rpi gpio_in_pin=18 gpio_out_pin=17
# /etc/lirc/hardware.conf (по умолчанию файла нет, надо создать)
LIRCD_ARGS="--uinput --listen"
LOAD_MODULES=true
DRIVER="default"
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"
# /boot/config.txt (в конце уже есть заготовка секции про lirc, исходно пустая)
dtoverlay=lirc-rpi,gpio_in_pin=18,gpio_out_pin=17

# /etc/lirc/lirc_options.conf (найти и заменить эти параметры)
driver    = default
device    = /dev/lirc0
reboot
sudo /etc/init.d/lircd status

Запись

Сначала необходимо создать конфигурационный файл с последовательностями данных для всех необходимых команд. Я дальше называю этот файл lircd.conf, но на самом для каждого устройства создается свой файл my_device_name.lircd.conf в каталоге /etc/lirc/lircd.conf.d.

Формат файла описан здесь. Если есть пульт, то можно записать передаваенмые им сигналы в файл с помощью утилиты irrecord.

/etc/init.d/lircd stop
irrecord -d /dev/lirc0 ~/my_device.lircd.conf
mv ~/my_device.lircd.conf /etc/lirc/lircd.conf.d/

irrecord анализирует последовательности и пытается определить протокол и временные параметры. В некоторых случаях irrecord терпит неудачу в анализе, поэтому есть возможность сохранить последовательность как она была принята, в “сыром” (raw) виде, для этого есть ключ --force.

Но даже с --force irrecord пытается что-то анализировать, и тоже может потерпеть неудачу. Тогда можно записать последовательности с помощью mode2 и создать файл самостоятельно.

mode2 печатает последовательно длительности наличия и отсутствия сигнала, из которых и складываются передаваемые данные. Длительность измеряется в микросекундах (1e-6 секунды). В raw формате в lircd.conf указыватся эти же длительности, начиная с ‘pulse’ (ведущий ‘space’ не нужен). Сответственно, всегда должно быть нечетное количество чисел (начинается и заканчивается наличием сигнала – ‘pulse’).

Мой скрипт для записи, спрашивает имя команды, запускает mode2 на 5 секунд, печатает результат в формате, готовом для lircd.conf:

Созданный файл можно еще раз попытаться “распознать” с помощью irrecord --analyse. Не всегда это проходит удачно, не спешите выбрасывать старый файл. Моя статистика такая: пульт от телевизора LG был понят с легкостью, все кондиционеры и пылесос потребовали ручного создания, пылесос был потом обработан --analyse.

Для коллекции:

Стандартные имена команд

LIRC по своему прямому назначению должен принятый и распознанный IR сигнал превратить в событие Linux input. Поэтому по умолчанию от нас требуют, чтобы имена команд в lircd.conf были из стандартного списка. Можно посмотреть список допустимых имен:

irrecord --list-namespace

Кондиционеры под этот шаблон не попадают. Требование к именам можно выключить, добавив при записи параметр:

irrecord  --disable-namespace ....

Отладка

Проверить приемник помогает утилита mode2, которая печатает все видимые сигналы.

/etc/init.d/lircd stop
mode2 -d /dev/lirc0

Проверить передачу проще всего, если есть другой приемник и запущенная на нем mode2. В особо безнадежных случаях можно самому менять значение на выходе GPIO и проверять тестером или осцилографом, куда доходит сигнал.

while sleep 1; do
  gpio -g toggle 17
done

Посмотреть на логи можно с помощью journalctl, в частности это позволяет увидеть ошибки в файле конфигурации:

journalctl -b 0 /usr/sbin/lircd

Отправка команд

Для передачи записанных команд есть утилита irsend. Она же может показать список известных устройств, и список известных команд для каждого устройства. Обратите внимание на “пустые аргументы” в примере ниже, они там нужны.

irsend – это клиент для lircd, поэтому если что-то пошло не так, заглядывайте в логи (см. выше).

# список устройств
irsend LIST "" ""

# список команд для устройства LG_TV
irsend LIST LG_TV ""

# отправить команду ON
irsend SEND_ONCE LG_TV ON

Теоретически, есть еще одна возможность - отправлять команды в lircd через его сокет. Не разбирался.

Вызов из Python

Почти все библиотеки являются всего лишь обвесок над irsend. Единственное исключение, которое компилирует клиента для API через сокет, не работает на Raspberry (нужна другая версия lircd). Поэтому смысла в них мало, команду вызвать я могу сам:

import subprocess

subprocess.call(["irsend", "send_once", "BEDROOM_AC", "OFF"])

Hardware

Я использую готовую плату, их много на Amazon и AliExpress. Она использует GPIO 17 на выход, и GPIO 18 на вход, что видно из конфигов выше.

На плате есть место для второго (дополнительного) светодиода D2, который по умолчанию не установлен. При использовании двух светодиодов, они подключаются последовательно. Поэтому при отсутствии светодиода D2 нужно замкнуть перемычку SJ1. С удивлением обнаружил, что на всех моих платах перемычка исходно была разомкнута. Пришлось доработать паяльником.

IRDA Hat

Итоги

Работает: сигнал передается, устройства его видят и правильно распознают.

Многое зависит от положения диода-излучателя, он должен быть точно направлен на приемник. Один неподвижный передатчик не может управлять всеми устройствами в комнате. Клонировать решение на базе Raspberry Pi для каждого гаджета дорого, нужно или доработать излучатель для “покрытия большей площади”, или найти более дешевую платформу.

LIRC исходно создавался для преобразования IR сигналов в стандарнтные линуксовые события устройств ввода. Поэтому для него ествественно, что одна кнопка - один код. Для некоторых устройств (болшинства Air conditioner) это не так: при нажатии на любую кнопку пульт передает пакет данных, содержащий полное состояние устройства (включено, режим работы, температура, режимы работы вентилятора, время, таймер и т.д.). Возможности собирать многокомпонентный пакет на основе нескольких параметров в LIRC нет, поэтому как быстрый инструмент “из коробки” он помогает, но дальше придется искать что-то еще. Хотя для большинства случаев записанных данных с привычными настройками вентилятора и без экзотических режимов вполне достаточно.