Введение
В данной статье мы детально разберем как управлять термостатом Terneo SX через HomeKit, используя при этом Node-Red.
Требования
Для интеграции терморегулятора Terneo SX в HomeKit нам потребуется следующее:
- установленный где-либо Node-Red;
- плагин node-red-contrib-homekit-bridged для взаимодействия с HomeKit;
- регистрация в облаке My.Terneo;
- IP-адрес нашего термостата (Как узнать IP-адрес?);
- прошивка терморегулятора версии 9.23 и выше;
- документация к локальному API Terneo.
Подготовка
Получение access token'a
Для работы с локальным API нам нужно получить auth-key из облачного API. Сделать это можно с помощью POST запроса на URL - https://my.hmarex.com/api/login/ с передачей вашего логина (email) и пароля от облака Terneo в формате JSON.
Данный флоу будет выглядеть так:
После применения изменений и запуска данного флоу в debug-панели, вы сможете увидеть ответ сервера:
Снятие блокировок на работу с API
В устройствах Terneo по умолчанию стоит блокировка на управление через локальное API. О том, как ее отключить, замечательно написано в документации к API:
HomeKit сервис Thermostat
Чтобы интегрировать терморегулятор в HomeKit, нам нужно понять, как работает сервис Thermostat в HomeKit. В нашем случае используется только нагревание (без охлаждения). Исходя из примера мы понимаем, что термостат получает от терморегулятора несколько параметров:
- текущую температуру;
- температуру уставки (ту, которую мы выставляем на терморегуляторе);
- текущий режим (включен/выключен).
В свою очередь, нода термостата отправляет следующие параметры на терморегулятор:
- установка температуры уставки;
- установка режима (включен/выключен).
Получается, что нам нужно получить статус и параметры с терморегулятора, а также отправить на терморегулятор выставленные в HomeKit'e параметры.
Непосредственно flow
Именно так выглядит мой flow для Node-Red.
Слева от HomeKit-ноды Terneo происходит сбор данных с терморегулятора. А также преобразование значений в HomeKit формат. В правой части мы обрабатываем полученные от HomeKit команды и передаем их терморегулятору с помощью http-запроса к API.
Мы производим два запроса к API терморегулятора. Почему два? Потому что, к сожалению, нам требуется информация из двух разных запросов к АПИ. Рассмотрим детально все ноды.
{ "cmd": 4 }
Inject-нода. Запускается с задержкой в 1 секунду и повторяется с интервалом 1 минуту. В ответе на данный запрос мы получим массив данных, в котором нас интересуют только значения ключей sn, f.0, t.1 и t.5.
{ "sn": "08000A000C43504735323620000159", "t.0": "533", "t.1": "387", "t.5": "432", "m.0": "0", "m.1": "3", "m.2": "96", "m.3": "0", "f.1": "0", "f.2": "0", "f.3": "0", "f.4": "0", "f.7": "0", "f.8": "0", "f.13": "0", "f.14": "0", "f.0": "0", "f.9": "0", "f.10": "0", "f.11": "0", "f.12": "0", "o.0": "-75", "o.1": "6", "f.15": "0", "par.26": "45", "par.27": "5" }
"sn" - это серийный номер терморегулятора. Его требуется указывать в запросах на изменение параметров.
"f.0" - данный параметр показывает включена ли нагрузка. Если по простому то греет ли в данный момент пол.
"t.1" - это текущая температура с датчика терморегулятора. Но она отдается, умноженная на 16. Чтобы получить температуру в градусах Цельсия, нужно разделить данное число на 16. В данном примере получим, что сейчас температура теплого пола 24.18℃.
"t.5" - данный параметр отдает значение температуры уставки. В нашем случае задана температура 432/16=27℃.
Но из данного запроса мы не можем узнать, включен ли сейчас терморегулятор и нагрев соответственно, поэтому нам требуется выполнить еще один запрос.
{ "cmd": 1 }
Inject-нода запускается с задержкой 30 секунд и повторяется с интервалом в 1 минуту. Задержка в 30 секунд обусловлена тем, чтобы запрос не пересекался с запросом телеметрии. В ответе мы получим JSON, в котором нам интересен 26-ой ключ массива "par"(последний), а именно [125,7,"1"]. Данный параметр отображает, включен или нет терморегулятор. Значение "1" означает, что терморегулятор выключен и нагрев не осуществляется. Если терморегулятор включен, то значение будет "0".
{ "sn":"08000A000C43504735323620000159", "par":[[23,2,"6"], [114,7,"0"], [115,7,"0"], [0,6,"0"], [1,6,"0"], [2,2,"1"], [3,2,"0"], [4,1,"30"], [5,1,"27"], [6,1,"25"], [7,1,"5"], [18,2,"2"], [19,2,"10"], [21,1,"0"], [25,2,"15"], [26,1,"45"], [27,1,"5"], [28,2,"16"], [29,1,"26"], [17,4,"80"], [116,7,"0"], [117,7,"0"], [118,7,"0"], [121,7,"0"], [122,7,"0"], [124,7,"0"], [125,7,"1"]] }
Таких нод в нашем флоу 4 штуки и все они одинаковые. Используется метод POST и URL - http://IP_адрес_терморегулятора/api.cgi
Для удобства отображения выбран вывод ответа в виде parsed JSON.
//Получаем текущую температуру в градусах Цельсия Current = Number(msg.payload["t.1"]/16); //Округляем текущую температуру до 1 десятичного знака Current = Math.round(Current*10)/10 //Получаем температуру уставки в градусах Цельсия Target = Number(msg.payload["t.5"]/16); //Округляем температуру уставки до 1 десятичного знака Target = Math.round(Target*10)/10 //Получаем текущий статус нагрузки CurrentState = Number(msg.payload["f.0"]) //Приводим значения температур к виду который примет HomeKit-нода и записываем их в msg.payload msg.payload = {"CurrentTemperature":Current,"TargetTemperature":Target, "CurrentHeatingCoolingState":CurrentState} //Приводим значения температур к виду который примет HomeKit-нода и записываем их в msg.payload return msg;
Данная нода получает данные из запроса к API, делает некоторя е преобразования (описано в комментариях в коде) и подготавливает данные для HomeKit ноды.
//Записываем значение 26-го параметра в переменную State = Number(msg.payload.par[26][2]); //Условие при котором значение 0 меняется на значение 1 и наоборот if (State == 1) { State = 0; } else { State = 1; } //Подготовка данных для передачи в HomeKit-ноду msg.payload = {"TargetHeatingCoolingState":State} return msg;
Данная нода получает значение "1", если терморегулятор выключен. Но в HomeKit ноде значение "1" означает, что терморегулятор включен. Поэтому в функции используем условие и меняем значение на противоположные.
Данная нода, в зависимости от данных, которые пришли в нее, отправляет эти данные в разные ветки.
В нашем случае, нода получает либо режим работы термостата TargetHeatingCoolingState, либо температуру уставки TargetTemperature.
//Условие при котором меняем 1 на 0 и наоборот if (msg.payload.TargetHeatingCoolingState == 1) { msg.payload.TargetHeatingCoolingState = 0; } else { msg.payload.TargetHeatingCoolingState = 1; } //Записываем значение в переменную v v = String(msg.payload.TargetHeatingCoolingState) //Создаем JSON из серийного номера терморегулятора, access-token'a полученного из облака Terneo и параметра на включение/выключение и записываем его в msg.payload msg.payload = {"sn":"08000A000C43504735323620000159","auth":"76c51a6625d1b474d54fad768002caddcd56dd1c","par":[[125,7,v]]}; return msg;
В данной функции мы преобразуем значение, полученное из Homekit ноды, в значение, которое примет API терморегулятора. Функция выходит из первого (верхнего) выхода ноды Switch.
Также мы формируем JSON, в котором прописываем следующие ключи:
sn - серийный номер терморегулятора, который можно получить из вывода ноды http-request.
- auth - это тот самый access-token, который я просил вас записать где-нибудь в подготовительной части.
- par - список параметров, которые мы передаем терморегулятору. В данном случае только один параметр - на включение/выключение.
Далее с помощью ноды http-reaquest отправляем данные через API непосредственно терморегулятору.
//Записываем полученное из Homekit значение температуры уставки в переменную v v = String(msg.payload.TargetTemperature) //Создаем JSON из серийного номера терморегулятора, access-token'a полученного из облака Terneo и параметра температуры уставки и записываем его в msg.payload msg.payload = {"sn":"08000A000C43504735323620000159","auth":"76c51a6625d1b474d54fad768002caddcd56dd1c","par":[[5,1,v]]}; return msg;
В данной функции мы формируем JSON для отправки терморегулятору.
Функция выходит из второго (нижнего) выхода ноды Switch.
Используются те же ключи, что и в функции включения/выключения:
- sn - серийный номер терморегулятора, который можно получить из вывода ноды http-request.
- auth - это тот самый access-token, который я просил вас записать где-нибудь в подготовительной части.
- par - список параметров, которые мы передаем терморегулятору. В данном случае только один параметр - на изменение температуры уставки.
Далее с помощью ноды http-request отправляем данные через API непосредственно терморегулятору.
Демонстрация работы
В видео ниже я продемонстрировал управление терморегулятором Terneo SX через HomeKit. Справа в кадре имеется панель облака my.terneo.ru, в которой виден результат управления. Данные в облаке обновляются с некоторой задержкой. На самом терморегуляторе задержка отсутствует.
Исходник
- Скачать файл.flow можно по данной ссылке.
- Скопировать из библиотеки Node-Red.
Заключение
Я буду очень рад, если кому-то пригодится данный флоу. Я постарался описать все максимально подробно, чтобы данная статья могла помочь кому-то самостоятельно создать флоу к похожему девайсу. Приглашаю в комментарии спецов по Node-Red и JavaScript для коллективной оптимизации и исправления данного флоу, а если кто-то захочет помочь мне с созданием отдельной ноды для данного терморегулятора, то я буду безмерно благодарен. Пишите в телеграм).
P.S.: Моя первая статья на портале, не судите строго =)
Отличная статья =) хорошо когда на модерации нечего править
Спасибо) Прочитал все гайды как писать и оформлять статьи. Постарался выполнить все требования)
Для работы с локальным API не требуется никакого ключа
https://github.com/wiistriker/homebridge-terneo-heatfloor">https://github.com/wiistriker/...
Судя по https://terneo-api.readthedocs.io/ru/latest/ru/safety_ru.html">документации ключ нужен в версии прошивки 2.4
увидел, спасибо! обновлю свой плагин
Статья применима к модели Terneo AX?
Я полагаю что да, напишите мне в телеграмме, посмотрим-проверим.
Спасибо. Попробую сам, если не получится - напишу.
Отлично!
Сергей, спасибо! Это просто блеск! Давно откладывал задачку затянуть в HomeKit эти терморегуляторы. Побежал реализовывать!
Спасибо за проделанный труд!