В первой части мы рассмотрели достаточно простое подключение двухканального модуля WiFi реле, сегодня, в преддверии отопительного сезона, подключим к OpenHAB термостат MP3502.
Термостат представляет из себя модуль на базе ESP8266 с цифровым датчиком температуры DS18B20. Настройка термостата возможна по сети Wi-Fi с помощью бесплатного приложения для Андроид, либо с помощью команд, передаваемых в модуль по сетевому протоколу UDP. Модуль после исполнения каждой полученной команды передает ответное сообщение, по которому можно отслеживать факт выполнения команды. Воспользуемся возможностями работы через UDP и подключим модуль к системе OpenHAB.
Для «разогрева» можно посмотреть видеоверсию, а за детальной проработкой нюансов милости прошу вернуться обратно, к этой статье.
Видео:
Тестовая конфигурация OpenHAB здесь.
Итак, термостат о котором пойдет речь на фотографии крайний слева, одно реле и 1 датчик температуры.
Тест-драйв № 2
Wi-Fi-термостат MP3502, на базе ESP8266
Температура может регулироваться в пределах 1…99 градусов Цельсия, гистерезис (точность поддержания температуры) – 1…5 0С, с шагом 1 градус. Питание постоянное – 12 Вольт, потребляемый ток порядка 250 мА.
Все файлы, которые мы будем менять находятся в папке C:\OpenHab\configurations. Именно эту папку следует сохранять в качестве резервной копии. Скопируйте в нее файлы из архива с нашего сайта configurations_testdive2.zip.
1. Общие настройки. В файл openhab.cfg ничего менять не будем. Подойдут те же настройки TCP/UDP биндинга, что мы использовали в первой части для подключения Wi-Fi.
2. Интерфейс системы. Название конфигурации осталось прежним, поэтому и запускать ее будем так же. Наберите в командной строке браузера. (предполагаем, что OpenHAB у вас установлен на этом же компьютере, иначе вместо localhost следует набрать IP- адрес сервера OpenHAB в вашей сети).
Главная страница не изменилась
А вот на второй странице появился новый раздел MP3502 Wi-Fi термостат, при этом содержимое файла testdrive.sitemap я не трогал.
Все настройки сделаны в файле testdrive.Items и сам экран управления термостатом выглядит так:
3. Описание в системе модуля MP3500 и способов управления им. Все элементы управления описываются в файле с расширением .items и находится он в папке C:\OpenHab\configurations\items. Приведу только строки, которые я добавил для этой статьи и которые относятся к термостату и определяют вид приведенной выше страницы:
Group WIFI_3502 «MP3502 Wi-Fi термостат» (gFF)
/* MP3502 WiFi — термостат */
Number MP3502_T «Текущая температура :[ %.1f °C]» (WIFI_3502)
Number MP3502_T_UST «Термостат установлен :[ %s °C]» (WIFI_3502)
Dimmer MP3502_InputU «Установить Tемпературу ЭКОНОМ/КОМФОРТ[%.1f °C]» (WIFI_3502)
Dimmer MP3502_InputG «Поддержание температуры ГРУБО / ТОЧНО[%.1f °C]» (WIFI_3502)
Switch MP3502_Set «Установить» (WIFI_3502)
{ udp=">[OFF:192.168.2.108:7777:MAP(MP3502_Info.map)]" }
String MP3502_R «Нагреватель :[:%s]» (WIFI_3502)
Напомню, каждый Item описывается в одну строку, при редактировании в NotePad обратите на это внимание. Возьмите заготовку из моего файла testrive.items.
Это были понятные органы управления. В полях отображаются параметры, смысл которых следует из их названий. Но мне пришлось прибегнуть к помощи еще некоторого количества Items, которые я не отображаю в интерфейсе, но они присутствуют и работают.
Немного пояснений. Применение скрытых Inems обусловлено это тем, что TCP/UDP Binding к сожалению не может передавать в модуль непосредственно из строки команды типа !SetR0_1\r, которые понимает модуль. Он может лишь при получении Item-ом команды OFF заглянуть в соответствующий файл с правилами трансформации и взять в нем команду, которая соответствует команде OFF. Вот пример,
>[OFF:192.168.2.108:7777:MAP(MP3502_U_eco.map)
На человеческий язык переводится так: при получении Item-ом команды OFF сделать исходящее обращение > по протоколу UDP на адрес: порт 192.168.2.108:7777 и передать в него строку, которую надо взять из файла трансформации MP3502_U_eco.map и которая соответствует команде OFF.
Содержимое моего файла MP3502_U_eco.map, который расположен в папке C:\OpenHab\configurations\transform, состоит из двух строк, которые выглядит так:
ON=!GetAll\r
OFF=!GetAll\r
В данном случае я хочу, чтобы при любой команде, которую получает Item с типом Switch ON или OFF в модуль термостата уходил запрос соcтояния. Список команд модуля есть в описании на сайте. Других команд модуль типа Switch просто не понимает. Подробнее об Items.
Теперь делаю вывод: скрытые элементы мне нужны, чтобы вызвать необходимый файл трансформации с нужными настройками модуля при ограниченном наборе команд каждого элемента (всего ON и OFF)
Теперь сами скрытые элементы, вот они:
/*Вспомогательные Items для передачи установок в модуль"
Number MP3502_G «Гистерезис :[%s °C]»
String MP3502_Stat «Получен ответ от модуля: [:%s]» (WIFI_3502) { udp="<[192.168.2.108:*:'REGEX((.*))']" }
Switch MP3502_Request «MP3502 Запросить состояние»
{ udp=">[ON:192.168.2.108:7777:MAP(MP3502_Info.map)]" }
Switch MP3502_SetU_eco «MP3502 Установить эконом „
{udp=“>[ON:192.168.2.108:7777:MAP(MP3502_U_eco.map)], >[OFF:192.168.2.108:7777:MAP(MP3502_U_eco.map)]» }
Switch MP3502_SetU_comf «MP3502 Установить комфорт »
{udp=">[ON:192.168.2.108:7777:MAP(MP3502_U_comf.map)], >[OFF:192.168.2.108:7777:MAP(MP3502_U_comf.map)]" }
Switch MP3502_SetG_prec «MP3502 Гистерезис точно »
{udp=">[ON:192.168.2.108:7777:MAP(MP3502_G_prec.map)], >[OFF:192.168.2.108:7777:MAP(MP3502_G_prec.map)]" }
Switch MP3502_SetG_aprox «MP3502 Гистерезис грубо „
{udp=“>[ON:192.168.2.108:7777:MAP(MP3502_G_aprox.map)], >[OFF:192.168.2.108:7777:MAP(MP3502_G_aprox.map)]» }
/* Конец вспомогательных Items */
Эти элементы не отображаются в интерфейсе. Чтобы отобразить — надо вставить признак группы (WIFI_3502).
Назначение элементов станет понятнее, если вы посмотрите на алгоритм управления модулем и описание правил (Rules).
4. Правила. Testdrive.rules – в этом файле наиболее интересная и новая информация, связанная с управлением модулем термостата. Во-первых я использовал новый для себя элемент управления с типом Dimmer, причем умышленно усек его возможности и свел их к двум функциям: при нажатии на стрелку вниз выставляется минимальное значение, на стрелку вверх – максимальное и научился настраивать эти значения, вот часть кода, который я старался снабдить понятными комментариями:
rule «MP3502 Set U»
when
Item MP3502_InputU received command
then
var Number percent = 22 // задаем значение температуры для старта
if(MP3502_InputU.state instanceof DecimalType) percent = MP3502_InputU.state as DecimalType //задаем тип переменной для отображения в элементе управления
if(receivedCommand==ON) percent = 22 //если нажата стрелка вверх ставим 22
if(receivedCommand==OFF) percent = 5 //если нажата стрелка вниз ставим 5
if(percent<1) percent = 5 //контроль выхода за допустимый диапазон — сколько не жми, все равно будет 5
if(percent>99) percent = 22 //...22
postUpdate(MP3502_InputU, percent); //отображаем установленное значение
end
У элемента Dimmer есть еще две команды INCREASE и DECREASE (увеличить и уменьшить) соответственно. Срабатывают они в случае, когда вы нажимаете и удерживаете одну из стрелок. Если захочется их задействовать, то потребуется дополнить правило строками такого содержания:
if(receivedCommand==INCREASE) percent =percent + 1
if(receivedCommand==DECREASE) percent =percent — 1
Понятно, что результатом выполнения этих команд будет последовательное увеличение температуры с шагом в 1 градус. Чтобы передать произвольное значение температуры в термостат, потребуется создать большое количество скрытых элементов управления типа Установить Т = 15, Установить Т = 16 и т.д. Каждый этот элемент должен будет ссылаться к своему файлу трансформации. Я попробовал сделать это для диапазона температур 5-30 градусов – в принципе не сложно, учитывая, что есть замечательные клавиши Ctrl_C b Ctrl_V. Cделать это надо только один раз, потом будет надежно работать. Любители тонких настроек могут реализовать это на досуге в качестве домашнего задания.
Во-вторых, я научился «разбирать» ответ модуля на части и извлекать значения температуры, гистерезиса… с помощью REGEX – регулярных выражений. Столкнулся я с ними впервые и убил достаточно много времени на то, чтобы найти в OpenHAB место, где можно сделать такую обработку и затем, как правильно написать правило (скрипт) и шаблон для поиска в ответе модуля нужного параметра. Напомню, что сам ответ модуля мы получаем по Команде OFF, которую файл трансформации MP3502_U_eco.map преобразует в команду модулю OFF=!GetAll\r (см. выше). Сам ответ модуля считывается элементом
String MP3502_Stat «Получен ответ модуля: [:%s]» (WIFI_3502) {udp="<[192.168.2.108:*:'REGEX((.*))']"}
Обращаю внимание, что в OpenHAB нельзя в настройке биндинга указывать конкретный порт, в нашем случае это мог быть бы порт 7777, но почему-то корректная работа началась только когда я поставил звездочку вместе с адресом 192.168.2.108:* Помните? Посмотрите, в предыдущей статье мы настраивали файл конфигурации и в нем разрешали биндингу UDP использовать маскирование… Вот, пригодилось!
Итак, как разобрать строку на части, надеюсь по комментариям вы сможете без труда повторить и для своих случаев:
rule «MP3502_Stat change»
when
Item MP3502_Stat changed //получили ответ от модуля
then
var String sAppo = "" //определяем новую пустую строчную переменную sAppo
sAppo = MP3502_Stat.state.toString //считываем ответ модуля в переменную sAppo как строчную переменную, далее вытаскиваем состояние реле, для этого пишем регулярное выражение — шаблон поиска для новой переменной sExpr
var String sExpr = "^!LED(ON|OFF).*" //читается так: находим в начале строки ^ текст !LED и сразу после него (ON|OFF) — захватываем символы либо ON либо OFF затем: .* — может быть любой символ любое количество раз. Берем все в кавычки.
var Pattern pattern = Pattern::compile(sExpr) //переводим в машинный код шаблон поиска из переменной sExpr
var Matcher matcher = pattern.matcher(sAppo) //переменная типа Matcher — связывает шаблон поиска с исходным текстом (ответом модуля) переменная sAppo
matcher.find() //запускаем процесс поиска, в общем случае процесс может найти несколько совпадений текста с шаблоном
var tmp = matcher.group(1) //присваиваем переменной tmp первое найденное совпадение, другие нам не нужны
postUpdate(MP3502_R, tmp ) //меняем значение в Item MP3502_R на значение tmp, в которой как раз сейчас находится состояние реле
tmp="" //«обнуляем» переменную для следующего значения
… и т.д.
Внимание! Сам код выделен жирным, при копировании в свой файл правильно отработайте знаками // комментарии.
На этом пока все, успехов!
Продолжение следует! Думаю, это будет подключение устройств через COM-порт и освоение
облачной технологии MQTT.