Захотелось мне интегрировать в систему УД управление телевизором. Первое, что услышал по поводу идеи: «а на кой?! Есть же пульт!» Сразу вспомнился диалог двух героинь из известного новогоднего фильма.
-- Послушайте, я вам все сейчас объясню. Вчера Женя пошел в баню.
-- Девушка,… какая баня?! У него в квартире есть ванная!
Ну, собственно, основной задачей, которую хотелось воплотить, было автоматическое выключение телевизора, когда в помещении длительное время никого нет. Тут можно поступить проще, обесточив на несколько секунд потребителя. Но это в наш современный век выглядит совсем уж по-варварски.
Кроме того, полноценное управление открывает перед нами и другие возможности. Например, становится возможным использовать любой телевизор с пультом дистанционного управления как будильник, даже если в нем самом функции включения по времени не предусмотрено. Если при входе в калитку фотография входящего отправляется на телевизор, можно его включать на какое-то время для показа картинки с входящим посетителем (при условии, что в помещении с телевизором недавно наблюдалось движение). Если используется SIP-телефония, при начале разговора можно автоматически немного «приглушать» звук и возвращать громкость в исходное состояние по окончании разговора. Различных сценариев можно «насочинять» много. Но как говорили классики марксизма-ленинизма -– это все «надстройка». А нам надо для начала разобраться с «базисом», т.е. ИК передатчиками и командами.
Современными телевизорами можно управлять не только через ИК передатчик. Вот, например, реализовано управление через HDMI-порт (https://majordomo.smartliving.ru/forum/ ... =23&t=3853). Но я буду писать только о том, что использовал сам. А это были 2 варианта.
Вариант 1
Если кто не в курсе, Мега прекрасно умеет управлять техникой по ИК каналу (https://ab-log.ru/smart-house/ethernet/megad-2561-ir). Основная сложность, с которой я столкнулся – поиск команд для моего телевизора. С электроникой и паяльником, имею лишь «шапошное» знакомство. Поэтому мастерить самостоятельно ИК-приемник и распознавать команды пульта какой-нибудь Ардуиной даже не пытался.
На приведенном в статье Андрея ресурсе по командам LIRC нужные команды для моего старенького телевизора Panasonic найти не удалось. Однако указанная Андреем для примера команда, переключающая его телевизор Panasonic на 2-й канал, сработала и у меня. В итоге нашел на ресурсе LIRC команды очень похожие на сработавшую, которые отличались от нее длиной (в них отсутствовал фрагмент начальной части). Кроме того, предлагаемые паузы были другими (https://sourceforge.net/p/lirc-remotes/ ... lircd.conf). Для конструирования команд для остальных кнопок помогла операция по «скрещиванию» начальной части сработавшей команды с четырьмя последними символами найденных команд.
Выложу на всякий случай получившиеся команды, вдруг кому пригодится.
KEY_POWER - BFFBFEFF4342 (команду повторять несколько раз подряд)
1 - BFFBFEFFF7F6
2 - BFFBFEFF7776
3 - BFFBFEFFB7B6
4 - BFFBFEFF3736
5 - BFFBFEFFD7D6
6 - BFFBFEFF5756
7 - BFFBFEFF9796
8 - BFFBFEFF1716
9 - BFFBFEFFE7E6
0 - BFFBFEFF6766
KEY_102ND - BFFBFEFF2322
KEY_CHANNELUP - BFFBFEFFD3D2
KEY_CHANNELDOWN - BFFBFEFF5352
KEY_VOLUMEUP - BFFBFEFFFBFA
KEY_VOLUMEDOWN - BFFBFEFF7B7A
KEY_MUTE - BFFBFEFFB3B2
Надо заметить, что сигнал, видимо, получается очень мощным. ИК излучатель лежит у меня за телевизором (в заднем полупространстве) и немного сбоку от него и направлен в ту же сторону, что и ИК приемник телевизора. Команды от родного пульта с относительно свежими батарейками, расположенного точно также, даже не думают срабатывать.
Вариант 2
Незадолго до того, как Андрей разместил свою статью про управление техникой через ИК канал и сочинил соответствующую «железяку», в моих руках оказалась изделие от небезызвестной фирмы Broadlink. Для управления телевизором я приобрел самое простое и недорогое устройство из их линейки -– RM3 mini (https://ru.aliexpress.com/item/433-Broa ... 0.0.ZvzP4v). В нем есть ИК передатчик, ИК приемник (для обучения командам от пультов) и Wi-Fi-модуль.
Для использования по назначению первым делом устройство надо «ввести в сеть». Потребуется смартфон или планшет (с iOS или Android), на котором скачивается и устанавливается приложение E-control. Устройство находится, скачивается понравившийся пульт, путем обучения кнопкам виртуального пульта назначаются команды реального пульта. И, собственно, мы получаем управление нашим телевизором со смартфона/планшета.
Только система УД пока еще у нас оказалась не при чем. Попробуем интегрировать в нее все это хозяйство.
Интеграция устройства Broadlink в Мажордомо
Для интеграции оборудования Broadlink в Мажордомо есть специальный модуль с одноименным названием (https://majordomo.smartliving.ru/forum/ ... 16d6b7ebc4). Устанавливаем модуль (Панель управления >>> СИСТЕМА >>> Маркет дополнений >>> Вкладка «Оборудование»). После этого в разделе «УСТРОЙСТВА» появляется «Broadlink». Выбираем режим работы «PHP only». Если в результате сканирования устройство не обнаружилось автоматически, его надо добавить вручную. При этом указывается:
Тип устройства;
Название;
IP устройства;
Марка устройства;
MAC-адрес.
Сканирование в моем случае (Win10) к добавлению устройства не привело, поэтому все параметры я внес вручную. Поскольку у меня Windows, IP-адрес и MAC-адрес устройства мне помогла узнать команда «arp –a» (клавиша Майкрософт + "R" >>> команда cmd, а потом >>> arp –a). Данные для поля «Марка устройства» можно взять отсюда (http://majordomo.smartliving.ru/forum/v ... 446#p44446) или отсюда (/modules/dev_broadlink/broadlink.class.php). Для RM3 mini у меня подошло 0x273d. Кстати, в обновленной версии модуля и на другом компьютере (Win7) мое устройство после сканирования появилось автоматически и с другой кодировкой марки устройства.
После того, как устройство добавлено, надо обучить его командам от пульта. Нажимаем кнопку «Обучить коду» жмем на кнопку физического пульта от телевизора, направив его на устройство, и на вкладке «Данные» у нас должна появиться новая команда. Присваиваем ей название и сохраняем. К присвоению названий я бы относился вдумчиво, поскольку обращение к командам будет происходить именно по названию. Кроме того, когда команд много, хорошо бы чтобы они сортировались согласно какой-то логике.
В коде (в методах, в сценариях, в PHP-коде у различных объектов) полученные команды надо использовать так (пример).
Код: Выделить всё
brLinkCommand('TV_Panasonic_1_Mute');
Код: Выделить всё
brLinkCommand($this->object_title."_Mute");
Код: Выделить всё
26006600713a0d100c2d0c100d100d0f0d100d0f0d100d0f0d100d0f0d100d100c2d0c100d100c100d100c100d100c100d100c100d2c0d100d0f0d100d0f0d100d0f0d100d100c100d100c100d2c0d2c0d100c100d100c100d100d0f0d2c0d2c0d100d0f0d2d0c000d050000
По поводу присвоения названий командам в модуле для себя пришел к следующим выводам. Названия команд в пределах всего модуля Broadlink должны быть уникальными. Название у меня будет содержать указание на конкретный управляемый объект (например, «TV_Panasonic_1») и начинаться с имени этого объекта в Мажордомо (например, «TV_Panasonic_1_Mute», «TV_Panasonic_1_7_Channel» и т.д.). Это мне позволит использовать общеклассовые методы Мажордомо, что значительно упростит добавление новых управляемых устройств. Если я захочу управлять другим телевизором, к примеру, Samsung, то объект в классе получит имя «TV_ Samsung_1», а команды в модуле будут названы по аналогии: «TV_Samsung_1_Mute», «TV_Samsung_1_7_Channel» и т.д.
Рисуем пульт в Мажордомо
Попадались мне варианты красивых пультов, реализованных средствами html/css/javascript. Но поскольку повторить сеи шедевры мне не под силу, пойдем рабоче-крестьянским путем. Раздобудем нужные иконки-кнопки в интернете. Для номеров каналов мне приглянулась такая картинка.
Вырезаем нужные фрагменты в графическом редакторе. Остальные кнопки тоже найдем в интернете или нарисуем. Выложу архив с использованными иконками.
Видно, что пульт занимает немало ценного места. Поэтому я решил, что было бы полезно скрывать/отображать пульт с помощью клика по отдельной кнопке ().
Еще бы хотелось видеть даже при скрытом пульте, включен телевизор или выключен. Значит у нашей кнопки будет 2 состояния ( / ).
Еще у нас будет пара сложных кнопок с 2-мя состояниями (хотя, по факту вышло с 4-мя). Это вкл/выкл ( / ) и отключение звука ( / ).
Четыре состояния такие.
Для кнопки вкл/выкл:
0 – телевизор выключен, пульт отображается ();
1 – телевизор выключен, пульт скрыт (иконка на сцене не отображается);
2 – телевизор включен, пульт отображается ();
3 – телевизор включен, пульт скрыт (иконка на сцене не отображается).
Для кнопки отключения звука:
0 – звук выключен, пульт отображается ();
1 – звук выключен, пульт скрыт (иконка на сцене не отображается);
2 – звук включен, пульт отображается ();
3 – звук включен, пульт скрыт (иконка на сцене не отображается).
Чтобы получить такой же результат, проще всего выполнить следующую последовательность действий (в качестве ИК передатчика я буду использовать Broadlink RM3 mini).
1. Поместить использованные иконки по пути C:\_majordomo\htdocs\cms\scenes\styles\images
2. Импортировать класс «TV» (Объекты >>> Инструменты [кнопка внизу] >>> Выберите файл [выбираем файл «TV.txt»] >>> Импортировать). Для теста можно сделать это вместе с объектами. 3. Импортировать элементы сцены (Сцены >>> Вкладка «Элементы» >>> Выберите файл [выбираем файл «Elements.elements»] >>> Импортировать). 4. Импортировать позиции меню (Меню управления >>> Инструменты [кнопка внизу] >>> Выберите файл [выбираем файл «items.menu»] >>> Указываем «Родительский пункт меню» [я выбрал «Управление»] >>> Импортировать). Если в первой строке иконок иконка для переключения каналов вниз () «перепрыгнула» на другую строку, то в HTML-блоке надо уменьшить ширину картинок ( и ), указав вместо width="24", другое значение (например, ="22"). У меня такое было в IE и в Opera на Win7. А в такой же Опере на Win10 все умещалось.
Все элементы HTML-блока располагаются от начала строки и чтобы соблюсти такое же расположение кнопок как и у пульта на сцене, я не придумал ничего другого, как начать некоторые строки с иконки типа «белый квадрат». Ибо, увы, в данном случае «чукча не писатель».
Чего мне не удалось добиться, так это чтобы в меню при скрытом пульте в блоке оставалась только одна строка (а не как сейчас, три или четыре).
5. Установить в Мажордомо модуль Broadlink (если он еще не установлен) и обучить командам от пульта. Поскольку команды вызываются (из метода класса) по названию, приведу перечень использованных в моем примере названий.
TV_Panasonic_1_0_Channel
TV_Panasonic_1_1_Channel
TV_Panasonic_1_2_Channel
TV_Panasonic_1_3_Channel
TV_Panasonic_1_4_Channel
TV_Panasonic_1_5_Channel
TV_Panasonic_1_6_Channel
TV_Panasonic_1_7_Channel
TV_Panasonic_1_8_Channel
TV_Panasonic_1_9_Channel
TV_Panasonic_1_Channel_Down
TV_Panasonic_1_Channel_Up
TV_Panasonic_1_Mute
TV_Panasonic_1_NN
TV_Panasonic_1_On_Off
TV_Panasonic_1_Sound_+
TV_Panasonic_1_Sound_-
(Жаль, не нашел, как можно спрятать это хозяйство под спойлер.)
А как быть, если вместо устройства Broadlink применить ИК передатчик от Андрея? В данном случае модуль Broadlink нам не понадобится и придется несколько переделать коды методов, заменив броадлинковские команды на команды для Меги, а также расширить состав свойств в классе. Выложу экспортированный класс «TV» с командами для Меги. Теперь наша тестовая команда,
Код: Выделить всё
http://192.168.0.14/sec/?pt=12&ir=BFFBFEFF7776&irp0=3450&irp1=1740&irp2=400&irp3=470&irp4=1300
Код: Выделить всё
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('2_Channel')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
Автовыключение «забытого» телевизора
Для обнаружения того факта, что телевизор забыли выключить, можно воспользоваться показаниями датчика движения. Скажем, если в помещении отсутствовало движения в течении 50 минут, а телевизор включен, то его можно смело выключать. И тут мы натыкаемся на «грабли». Система управления у нас без обратной связи. Допустим, кто-то уже выключил телевизор со «штатного» пульта, но наша система УД об этом ничего «не знает». И тогда вместо выключения мы, наоборот, телевизор включим.
Можно, конечно, «вывернуться» так. В моих командах на переключение на 1-й канал (и для broadlink и для Меги) имитируется длительное нажатие на кнопку (удержание клавиши). При этом происходит включение телевизора. Т.е. мы можем таким образом выполнить включение телевизора, а потом выполнить команду его выключения. Но как-то не хочется подвергать лишний раз телевизор пиковым нагрузкам. Так что нужно обеспечить установление факта работы телевизора «средствами объективного контроля».
На форуме по Мажордомо кто-то предложил неплохую, на мой взгляд, идею. Можно отследить факт работы телевизора по наличию питания на его USB-порту. Т.е. понадобится протащить к телевизору две жилы провода и подключить U-sensor, который поможет «отловить» напряжение 5В (https://ab-log.ru/smart-house/ethernet/u-sensor). Правда, при длине проводов в несколько десятков метров неизбежно будет падение напряжения и справится ли в этой ситуации U-sensor с возложенной на него миссией, можно будет сказать только по результатам «натурных испытаний». В моем случае не поможет даже положительный результат, поскольку телевизор произведен во времена, когда о USB-портах еще слыхом не слыхивали.
Поэтому замыслил применить другое решение, но для его воплощения мне необходимо дождаться получения некоторых «железок» (что, видимо, будет не скоро). И чтобы не задерживать «выход номера в тираж» публикую свою заметку без «развязки» истории. После получения «железок» «антиобщественные опыты», безусловно, получат продолжение.
Итак, «железки» приехали.
На фото -- датчики тока ТП03С-0,1А-00-З/0 (ОК) (клеммы). Радует, что это отечественный производитель (http://www.eltranstech.ru/products/izme ... t03s-200a/). Вдвойне радует, что там работают, как оказалось, адекватные люди. А то как иногда бывает, обращаешься к производителю, чтобы приобрести что-нибудь или сделать, а они «меньше восьми вагонов в одни руки не отгружаем» или «щас прям разбежались из-за вас производственную линию переналаживать». А тут пишу им, объясняю ситуацию. Мол, хорошие датчики делаете, удобные для подключения. И тот, что выпускаете серийно (ТП03С-0,35А-00-З/0 (ОК) подходит в большинстве случаев (стиральные машины, кондиционеры, скваженные насосы), в том числе и для моего телевизора, который всяко потребляет ватт 200-250, поскольку порог срабатывания у датчика примерно 80 Вт (при 220 В). Но вот куплю я более энергоэффективный, современный телевизор, который может потреблять ватт 60-70, как тогда быть? В то же время отслеживать «абсолютный ноль» мне тоже не нужно, поскольку телевизор обычно находится в режиме «standby» и потребляет несколько ватт (современные модели) или ватт 10 в моем случае. Спрашиваю, сможете сделать для меня датчик с порогом срабатывания 0,07 А (15 Вт)? Они взяли небольшую паузу для изучения технических деталей и ответили «ЗАПРОСТО». Спросили, устроит ли меня датчик с порогом 100 mA, чтобы не применять более крупный (и более дорогой) корпус? Говорю, да, вполне устроит. С учетом доставки датчик мне обошелся примерно в 480 руб./шт. Еще говорю им, поскольку тема УД становится все более популярной, может быть вашим маркетинговым службам стоит рассмотреть вопрос о включении такого датчика в линейку производимых «серийно»? Они как-то засомневались, думают, что не будет пользоваться существенным спросом. Ну, им, наверное, виднее.
Но, вернемся к нашим бара… телевизору. Теперь его состояние (включен или выключен) мы можем отследить «вооруженным глазом», пропустив через датчик фазную или нулевую жилу питающего телевизор провода и подключив сам датчик к обычному входу Меги. Очевидный момент, но я все же отмечу, что телевизионная розетка должна «висеть» на отдельном питающем проводе. И если розетка двойная для правильности картины не следует от нее запитывать других потребителей, иначе датчик будет измерять ток «набрудершафт».
Статус телевизора в интерфейсе будем теперь не просто менять по нажатию на кнопку «Вкл./Выкл.», но и верифицировать по состоянию датчика. Поскольку он может быть подключен к другой Меге, чем та, к которой подключен ИК передатчик, добавим несколько новых свойств в класс «TV», которые помогут организовать опрос датчика:
ChkPower_ipAddress
ChkPower_Password
ChkPower_Port
Вынесем выставление статуса телевизора в отдельный метод «StatusSet» со следующим кодом.
Код: Выделить всё
$state = file_get_contents("http://".$this->getProperty('ChkPower_ipAddress')."/".$this->getProperty('ChkPower_Password')."/?pt=".$this->getProperty('ChkPower_Port')."&cmd=get");
$state = substr($state,0,2);
if ($state == "ON") {
If ($this->getProperty('RemoteVisible') <> 0) {
$this->setProperty('Status', 2);
} else {
$this->setProperty('Status', 3);
}
} else {
If ($this->getProperty('RemoteVisible') <> 0) {
$this->setProperty('Status', 0);
} else {
$this->setProperty('Status', 1);
}
}
Также будем запускать этот метод при выполнении метода «turn_On_Off». Допишем в конец метода «turn_On_Off» строчку
Код: Выделить всё
SetTimeOut($this->object_title."_StatusCheck_Timer","$this->callMethod('StatusSet');",3);
Еще в класс «TV» надо добавить методы
turnOn
Код: Выделить всё
$state = file_get_contents("http://".$this->getProperty('ChkPower_ipAddress')."/".$this->getProperty('ChkPower_Password')."/?pt=".$this->getProperty('ChkPower_Port')."&cmd=get");
$state = substr($state,0,3);
if ($state == "OFF") {
//Команда на вкл./выкл., подаваемая на Мегу (повторенная несколько раз, как имитация удержания кнопки пульта)
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('On_Off')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
usleep(50000);
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('On_Off')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
usleep(50000);
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('On_Off')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
usleep(50000);
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('On_Off')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
//или на устройство Broadlink, если для управления используется оно
//brLinkCommand($this->object_title."_On_Off");
}
Код: Выделить всё
$state = file_get_contents("http://".$this->getProperty('ChkPower_ipAddress')."/".$this->getProperty('ChkPower_Password')."/?pt=".$this->getProperty('ChkPower_Port')."&cmd=get");
$state = substr($state,0,2);
if ($state == "ON") {
//Команда на вкл./выкл., подаваемая на Мегу (повторенная несколько раз, как имитация удержания кнопки пульта)
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('On_Off')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
usleep(50000);
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('On_Off')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
usleep(50000);
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('On_Off')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
usleep(50000);
file_get_contents("http://".$this->getProperty('ipAddress')."/".$this->getProperty('Password')."/?pt=".$this->getProperty('Port')."&ir=".$this->getProperty('On_Off')."&irp0=".$this->getProperty('irp0')."&irp1=".$this->getProperty('irp1')."&irp2=".$this->getProperty('irp2')."&irp3=".$this->getProperty('irp3')."&irp4=".$this->getProperty('irp4'));
//или на устройство Broadlink, если для управления используется оно
//brLinkCommand($this->object_title."_On_Off");
}
Код: Выделить всё
$objects=getObjectsByClass("TV");
foreach($objects as $obj) {
callMethod($obj['TITLE'].".turnOff");
}
Срабатывание датчика движения будет запускать таймер на 50 минут. И если таймер завершит свой отсчет (а не перезапустится в результате нового срабатывания датчика движения), то будет выполнена команда на выключение конкретного телевизора. Допишем строчку в тот код, который запускается при срабатывании датчика (в моем случае -- это Объект.Метод «MotionSensor2.statusChanged»).
Код: Выделить всё
SetTimeOut("TV_Panasonic_1_OffTimer","callMethod('TV_Panasonic_1.turnOff');",60*50);