Всем добра! Речь пойдет о ресивере Yamaha RX-V575 и телевизоре Samsung UE50F6800AB. Оба устройства не первой свежести, более того, телевизор имеет устаревший и не развиваемый более интерфейс. Однако, полученные результаты могут оказаться полезными для владельцев множества других устройств Yamaha и Samsung. Не все ведь меняют технику ежегодно 🙂
Статья является логическим продолжением материала об универсальном голосовом шлюзе в том смысле, что показывает куда может двигаться мысль в части улучшения комфорта. Т.е., как и раньше, идея состоит не в том, чтобы разбирать детали, а в том чтобы показать ход мысли. Для деталей есть репозиторий с комментариями.
Сразу оговорюсь, что не стоит дальше читать, если вы:
-
Чтите информационную безопасность больше комфорта и удовольствия от созидательного творчества. Очень не хотелось бы получать комментарии типа «Моим устройствам запрещено смотреть в Интернет» или «Голосовые помощники — открытые ворота для взлома». Не потому, что я с этим согласен или не согласен, а потому что статья не об этом. И разрабатываемый софт не смотрит в Интернет.
-
Не любите умный дом и всякие разные порождаемые им удобства. Один мой коллега по работе, айтишник, говорил так: «Если бы я купил недвижимость с умным домом, то первым делом обрезал бы все провода умного дома и поставил бы обычные выключатели».
Небольшая предыстория. Когда-то были популярны программируемые IR-пульты, поддерживающие сценарии. И это было удобно. Например, если у вас ресивер, телевизор, плеер — устройства разных производителей, но все с IR-управлением, то настроив сценарий и направив пульт примерно в сторону всего этого хозяйства, можно было всё включить, настроить нужные входы и режимы. Правда, приходилось долго держать пульт в руках. Отличное устройство для этого — Logitech Harmony 555. Этот пульт не только поддерживает кодовые таблицы огромного количества медиаустройств, но и обучаем.
Например, на нём я настроил управление локомотивами и стрелками железной дороги Piko. В общем очень мощная вещь. Но, прожорливая, и как любая аппаратная платформа, ограничена в универсальности. Работает и сейчас, но пользоваться я перестал.
Когда занимаешься умным домом, такие устройства кажутся анахронизмом. Они ведь не подключены к локальной сети и не могут управляться из умного дома.
В свою очередь все современные медиаустройства подключены к сети и могут управляться по сети. И к ним есть программные пульты управления. Например, для Yamaha — AV Controller , а для Samsung вообще множество. Но, вероятно, не все поддерживают старые протоколы. Я пользуюсь этим. Наверное, есть и пульты поддерживающие сценарии для совместного управления устройствами разных брендов, но я не искал. Потому что самый верх комфорта — это командовать голосом. А для его «поимки» служат голосовые помощники. Другими словами, сел на диван, сказал: «Салют, включи кинотеатр», и смотришь кино. Забегая вперед скажу, что почти так и получилось. Единственное, что пока не получилось — это не научил систему сразу ставить нужный фильм в локальной сети 🙂 Но, эта задача решаемая.
Итак задача: создать инструмент, который позволит управлять Yamaha и Samsung по локальной сети. Управлять будем, передавая исполняемому файлу соответствующие параметры/команды. Хардкор, чёрный экран, командная строка. Выбор платформы для разработки я описывал здесь. Повторюсь, это Linux, С++.
Кто читал мои предыдущие статьи, знает, что в основе домашней автоматизации лежат ОpenHAB и HomeAssistant. И к ним, конечно, есть дополнения, которые позволяют управлять устройствами из их интерфейса или даже с помощью Plug&Play. Однако, печальный опыт дополнения для интеграции с Алисой сразу повёл по пути создания собственного приложения, которое будет просто вызываться по команде. Трудно придумать что-то надёжнее. А вызывать можно и из умного дома штатными функциями, и из универсального голосового шлюза, и просто запустив bash-скрипт, иконкой с рабочего стола или по расписанию. Как угодно, в общем.
Итак, заряжаем искусственный интеллект на поиск готовых библиотек. И для Yamaha сразу находим это и вот это. По второй ссылке есть описание множества доступных команд. Становится понятно, что управлять ресивером можно просто с помощью curl. Вот такой скрипт позволит включать, выключать ресивер и отключать/включать звук:
#!/bin/bashcmd1='<YAMAHA_AV cmd="PUT"><Main_Zone>'cmd3='</Main_Zone></YAMAHA_AV>'url='http://192.168.0.100/YamahaRemoteControl/ctrl'case $1 in "ON") cmd2='<Power_Control><Power>On</Power></Power_Control>' ;; "OFF") cmd2='<Power_Control><Power>Standby</Power></Power_Control>' ;; "MUTE") cmd2='<Volume><Mute>On/Off</Mute></Volume>' ;; *) echo -n "Команда не определена" echo "" exit -1 ;;esacecho "Команда на ресивер: "$cmd1$cmd2$cmd3echo "Адрес ресивера: "$urlcurl -X POST -H "Content-Type: text/xml" -d "$cmd1$cmd2$cmd3" "$url"
Скрытый текст
Отступление. Можно воспользоваться и Wireshark для прослушивания трафика и увидеть команды, приходящие со штатного Android пульта.
Кроме скрипта, управление Yamaha можно сразу настроить в голосовом шлюзе. Однако, раз мы управляем по сети, то должны получать ответы устройства, чтобы быть уверенными, что команда получена адресатом. Поскольку команды GET позволяют получить состояние устройства, например уровень громкости, то ответ придется еще и парсить. Все это наводит на мысль, что просто curl и bash-скриптом не обойтись. Забегая вперёд, окажется, что с Samsung’ом curl уже не справится. Результат: пишем программу. Используем код из из первой ссылки с сокращением и некоторыми изменениями. Замечу, что код использует ту же самую библиотеку curl для отправки запросов. Изменён способ хранения команд. Сразу сделал так, чтобы устройств могло быть много, в т.ч. одинаковых, а также чтобы в дальнейшем общую логику можно было наращивать просто добавляя программный код управления новыми устройствами не меняя логику настройки системы и хранения команд. Все это описывается в классическом конфигурационном файле:
# имена управляемых устройств. Используются как ключи для поиска их параметров [Devices] Yamaha= Samsung= #Параметров у каждого устройства два [Yamaha] #type - справочное значение, зашиты в коде "YamahaAVR" и "SamsungOldTV"type=YamahaAVR ip=RX-V575.local #Для типа устройства список команд [YamahaAVR] HDMI1=<YAMAHA_AV cmd="PUT"><Main_Zone><Input><Input_Sel>HDMI1</Input_Sel></Input></Main_Zone></YAMAHA_AV> HDMI2=<YAMAHA_AV cmd="PUT"><Main_Zone><Input><Input_Sel>HDMI2</Input_Sel></Input></Main_Zone></YAMAHA_AV>...[Samsung] type=SamsungOldTV ip=192.168.0.100 [SamsungOldTV] HDMI=KEY_HDMI TV=KEY_TV...
Сначала определяем имена устройств, потом для каждого определяем их параметры, IP-адрес или mDNS-имя и тип. Далее, описываем какие команды относятся к типу устройства. Таким образом, в сети может быть два-три-…-n телевизора(ов), поддерживающих этот тип команд и дважды определять их не надо.
В исходном примере используется сторонняя библиотека для парсинга XML-ответов ресивера. Сначала мне показалось это лишним. Ведь классический пульт управления не имеет обратной связи. Однако, раз уж решено писать программу вместо простого использования curl, придётся все же научиться читать ответы Yamaha на запросы статусов. На всякий случай. А чтобы не подключать стороннюю библиотеку, которая явно тяжелее потребности прочитать простой XML, GigaCode написал мне базовый XML-парсер. Он сделал всего одну небольшую ошибку, которую можно найти в коде с моим комментарием. XML-ответ, правда, оказался все же многоуровневым, так что уже без ИИ добавил небольшую рекурсию. См. xml_parser.cpp. Теперь можно обрабатывать команды GET и GET_CONF. Это, кстати, позволило найти команду для установки режима DSP «7 channels». Этой команды нет в указанных выше исходниках.
Сложнее оказалось с телевизором. Прежде всего потому, что он не поддерживает взаимодействие по HTTP. Открываем socket и работаем на низком уровне. Библиотек на C++ не нашлось, зато нашлась весьма полная библиотека на Python. Проверяем ее работоспособность, вычисляем нужный нам исходник и отдаем его на переписывание ГигаКоду. С этим он справился почти отлично, но немного намудрил с протоколом. На самом деле это сущая мелочь, но повозиться пришлось часа 2, сравнивая побайтно формирование пакетов на Питоне и на C++. Вывод сообщений заменил на логирование. В итоге всё работает и вписывается в логику хранения команд, разработанную для Yamaha. См. tv_control.cpp.
Однако, есть нюансы:
-
Состояние телевизора считывать не получается. Возможно, считывание и есть в протоколе, но тогда надо изучать оригинальную документацию Samsung. Пока остаёмся в рамках классического пульта: «выстрелил и забыл», тем более что доставку команды до телевизора, в отличие от IR-пультов, мы всё-таки видим.
-
Команды ON нет! Есть только OFF. GigaCode предложил сделать Wake-On-LAN. Но, телевизор этого не поддерживает, проверил в т.ч. сторонним приложением.
Второй нюанс серьёзный, ибо ставит под сомнение целевой сюжет: сидеть на диване и командовать «Алиса/Салют/Маруся, включи…». Впрочем, у меня на этот случай уже было решение, а именно самодельный обучаемый IR-пульт на базе ESP8266, и он уже умеет управлять этим телевизором. Спросите, зачем еще управлять по LAN? Ответ прост: так надежнее, раз. И, два, в этом случае можно высвободить IR-пульт для чего-то еще. Что, правда, по описанной причине не получилось.
Для тех, кто идёт тем же путём, есть решения без пайки и программирования. Например, Broadlink RM 4 Pro. Его даже перешивать не надо. Есть несколько проектов, перехватывающих управление им, и позволяющих вживить его в вашу логику без использования облака Broadlink. Я использую этот для управления еще более почтенным телевизором Sony с помощью OpenHAB. Еще один вариант посложнее. На AliExpress есть множество WiFi IR-пультов за совершенно смешные деньги. Например, Tuya WiFi IR Remote (ссылка может устареть). Выглядит так:
Если он на базе ESP8266, то его можно перепрошить на Tasmota, в Интернете есть инструкции. И тогда у вас будет полностью подконтрольный пульт промышленного изготовления без выхода в Интернет. Правда, для перепрошивки, вероятно, придется подпаяться к плате пульта. По крайней мере мне пришлось подпаиваться. Но, результат того стоил. Встроил его в электрокамин и теперь могу управлять электрокамином из умного дома. Возможно, добавлю его и в голосовой шлюз со временем.
В общем для включения телевизора Samsung используем управляемый IR-пульт, а дальше командуем по локальной сети.
Теперь приступаем к голосовой части. Сначала настраиваем новые устройства (пульты) в универсальном голосовом шлюзе. Описания приведены здесь. Затем остается настроить сценарий в умном доме от Яндекса. Сценарий запускаем по фразе, дальше последовательно включаем и настраиваем устройства, не забывая о задержках между действиями, чтобы устройство успело закончить выполнение команды. Всё вроде есть и всё работает, но мне пришлось отказаться от этой идеи. Что и почему, отвечу в комментариях, если будут вопросы. Здесь могу только сказать, что почувствовал ту же зависимость от кого-то, какая бывает при использовании дополнений для OpenHAB или HomeAssistant. Что в итоге? Поскольку сам по себе умный дом от Яндекса работает безупречно, то добавляем в него виртуальный пульт с двумя кнопками «Вкл» и «Выкл». Проще и надежнее некуда. А на стороне голосового шлюза просто запускаем скрипт. По команде «Алиса, включи кинотеатр» голосовой шлюз запускает:
#!/bin/bash#командыcmd="your_path_to/lanremote"cmd_tv="your_path_to/send_ir.sh ON"cmd_kodi="kodi"#имена устройств из lanremote.confsamsung=Samsungyamaha=Yamaha#адрес телевизораIP_TV="192.168.0.100"if [ "$1" = "ON" ]; then echo "Включаем всё" #Запускаем kodi $cmd_kodi #Включаем ресивер $cmd $yamaha ON #проверяем наличие телевизора в сети. Если в сети, значит включен if ping -c 1 "$IP_TV" > /dev/null 2>&1; then echo "Телевизор включен" else echo "Телевизор выключен" #Включаем телевизор IR-пультом, потому что по сети телевизор недоступен, когда выключен $cmd_tv fi sleep 3 #Устанавливаем вход на ресивере $cmd $yamaha HDMI1 sleep 10 #Устанавливаем вход на телевизоре $cmd $samsung HDMI #Устанавливаем режим на ресивере $cmd $yamaha DSP_7CH #убираем громкость на телевизоре for ((i=1; i<=20; i++)) do $cmd $samsung VOLUMEDOWN done exit 0elif [ "$1" = "OFF" ]; then echo "Выключаем всё" #Выключаем телевизор м ресивер LAN-пультом $cmd $samsung OFF $yamaha OFF exit 0else echo "Ошибка: ожидаемый параметр — ON или OFF" exit 1fi
И это оказывается самым магическим способом, потому что позволяет выполнять операции параллельно, а еще выполнять что-то еще, например запустить Kodi на ПК, который используется в качестве проигрывателя. А можно еще включить установку для попкорна и сварить чашечку кофе. По крайней мере во всех рекламах умных домов или чайник утром кипятится или кофе варится. Важно, на самом деле не что именно кипятится/варится, а что можно всё, что хочешь. Не в терминах Достоевского, конечно 🙂 Полный текст скрипта здесь, в нем у меня запускается не Kodi с попкорном, а FireFox с Кинопоиском. А для включения Samsung вызывается другой скрипт, ir_send.sh.
Скрытый текст
Отступление. Пока писал эту статью, подумал, что следующим типом устройств в этом проекте может стать Kodi, у которого есть API. И у него тоже будет аналогичная Samsung’у проблема — его сначала надо запустить, а потом им можно управлять. К счастью, для запуска Kodi ничего паять не надо 🙂
Ну и последнее. Рядом с телевизором и ресивером у меня нет Алисы. Зато есть Салют от Сбера. Что нужно сделать: 1) разработать новый простейший смартап для запуска кинотеатра или доработать имеющийся; 2) добавить необходимое соответствие в базу данных голосового шлюза, одну запись в одной таблице.
Смартап для запуска кинотеатра получился настолько простым, что не могу не привести скриншот из среды разработки:

В итоге по команде «Салют, включи кинотеатр» голосовой шлюз запускает тот самый пульт, с двумя кнопками, который был настроен ранее для Яндекса и нажимает на нем кнопку «Вкл». Пульт запускает описанный выше скрипт с попкорном. Остается выбрать и запустить собственно кино. По факту пришлось чуть дополнить и разработанный ранее смартап. Как минимум для того, чтобы выключать кинотеатр. Но, и запускать тоже можно.
Итого:
-
Разработан универсальный расширяемый инструмент для управления медиаустройствами по сети. Все исходники и инструкции здесь. Написано под Linux, но с небольшими изменениями будет работать и под Windows.
-
Использован разработанный ранее голосовой шлюз для запуска сценария «Включи кинотеатр» голосом. Настроено два пульта + 1 виртуальный в умном доме Яндекса. Разработан смартап для Салюта.
-
Можно запускать кинотеатр щелчком по иконке на рабочем столе ПК без всяких умных домов, голосовых помощников и прочей «бесовщины».
-
Активно использован GigaCode в среде Visual Studio Code. Результат впечатляет. С той оговоркой, что на жизнь я зарабатываю не программированием, это хобби. В итоге текст программы lanremote был написан за 1 день вместе с изучением и адаптацией библиотек, реализующих протоколы работы с устройствами. Плюс еще 1 день на корректировку вывода, подготовку к выкладке на Github, настройку и отладку голосовых помощников и разработку скрипта.
Куда можно двигаться дальше:
-
Добавить Kodi.
-
Научиться управлять функциями Smart TV на самом телевизоре. Не изучал тему.
-
Добавить сценарий запуска только музыки, без ТВ.
-
Научиться ставить нужный фильм или нужный музыкальный альбом в локальной сети через домашнюю аудио/видео систему. Да еще и голосом. Это можно, конечно, сделать за счет штатной подписки и голосового помощника с HDMI-выходом. Но, это слишком просто и не интересно, тем более что звук по HDMI он не передает. Это раз. И два: смотреть можно только то, что есть в подписке.
ссылка на оригинал статьи https://habr.com/ru/articles/1036350/