Моя задача сейчас — научиться отправлять команды кондиционерам и другим устройствам в доме. Исходно эти устройства имеют только IR remote control. Для решения этой задачи у меня есть Raspberry Pi и IR transceiver shield. В статье можно найти конфиги, команды, советы и немного теории. Из софта будут LIRC (Linux Infrared Remote Control) и Python.


LIRC я нашел с помощью Гугла. В процессе исследования выяснил, что LIRC работает как с передатчиками, так и с приемниками IR сигналов, может декодировать принятый сигнал и выполнять какие-то действия в связи с этим. Сейчас прием сигналов мне не нужен, но в будущем может оказаться полезным. Если будете возиться с LIRC сами, прочтение 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 (см. под спойлером).


Скрипт
#!/usr/bin/env python3

import io
import sys
import os

r = """begin remote

  name  DEVICE_NAME_CHANGE_ME
  flags RAW_CODES
  eps            30
  aeps          100

  gap          19037

  begin raw_codes

"""

while True:
        print()
        print("enter the command name, or just press Enter to finish")

        a = sys.stdin.readline().rstrip("\n\r")
        if not a:
                break

        first_space = True
        n = 0

        r += "    name " + a + "\n"

        for line in os.popen('timeout 5s mode2 -d /dev/lirc0 2> /dev/null').read().split('\n'):
                words = line.split()
                if len(words) < 2:
                        continue

                if words[0] != 'space' and words[0] != 'pulse':
                        continue
                if first_space and words[0] == 'space':
                        first_space = False
                        continue

                if n % 4 == 0:
                        r += "\n        "

                r += words[1] + "  "
                n = n+1

        if n > 5:
                print ("got", n, "values, looks good")
        else:
                print ("no signal, something went wrong")

        r += "\n\n"

r += """  end raw_codes
end remote
"""

print()
print(r)
print()

Созданный файл можно еще раз попытаться "распознать" с помощью 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 и проверять тестером или осцилографом, куда доходит сигнал. Команда gpio входит в состав пакета wiringpi.


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


IR hat

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


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


Фотография крупнее для желающих поразглядывать

IRDA Hat


Итоги


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


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


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

Комментарии (12)


  1. vitaly_KF
    24.07.2019 18:00

    Понимаю что у Вас речь идет о самостоятельном изучении работы с IR, спасибо за статью! Просто дополню, похожую задачу я лично решал при помощи Aqara Air Conditioning Companion, это такая розетка от Xiaomi с IR и Wi-Fi, может бысть использована как через приложения Xiaomi так и интегрироваться с Android или Apple HomeKit (через homebridge на Raspberry PI), а также может управляться вручную через протокол MIIO. При этом сам Raspberry может находиться где-то в кладовке, а рядом с кондером будет лишь данная розетка-переходник и связь по Wi-Fi.

    Вот в этом репозитории можно почитать подробнее github.com/LASER-Yi/homebridge-mi-acpartner, там же в issues#64 есть дополнение как завести с любым кондером.

    PS: Сорри если слегка не в тему)



  1. apple01
    24.07.2019 19:12
    +1

    Статьи про ИК управление кондиционером:
    habr.com/ru/company/iridiummobile/blog/389049
    habr.com/ru/post/419963
    habr.com/ru/post/189142
    habr.com/ru/post/419797


    1. tse Автор
      24.07.2019 19:22

      Спасибо.


  1. cat_crash
    24.07.2019 19:38

    Имхо немного «из пушки по воробьям». Подобные задачи с легкостью решал на ESP8266 + светодиодик или фотодиодик. В какой то момент даже запилил управление через облако прикрутив обычный websocket клиент к 8266


    1. Arcanum7
      25.07.2019 01:28

      А исходничками и схемкой не поделитесь? как раз есть свободная есп8266 и зоопарк техники с кучей пультов. Спасибо.


      1. cat_crash
        25.07.2019 01:50

        Поищу свои исходники (баловался с год тому назад). Если найду — дополню. Но за отправную точку использовал www.instructables.com/id/Universal-Remote-Using-ESP8266Wifi-Controlled


    1. tse Автор
      25.07.2019 03:33

      Откровенное из пушки по воробьям, совершенно согласен, я об этом в конце пишу. Когда с общей архитектурой своего «дома» определюсь, перепилю все на ESP32. Но как прототип свою роль выполняет прекрасно: там обычный линукс внутри, и можно связь с облаком сделать любым привычным способом.


  1. Andrey2007
    24.07.2019 22:28

    А как правильно получить lircd.conf для работы с несколькими устройствами? Я например, ручками копирую и вставляю секцию begin-end в общий lircd.conf из каждого, созданного для одного пульта.


    1. natan555
      25.07.2019 02:27

      именно так и указано в мануалах lirc


  1. Daniyar94
    25.07.2019 02:38
    +1

    Хахахаха как раз вчера в Инстаграме постил: https://www.instagram.com/s/aGlnaGxpZ2h0OjE3ODcyODQyOTE5NDIwNTQz?igshid=1qsnk768yh2vq


  1. Daniyar94
    25.07.2019 02:47

    От себя добавлю, если хотите проверить правильно ли замапились сигналы, используйте irw


    При нажатии будет печатать какая мапа сдетектилась.