У частині 1 статті ми описали необхідні попередні кроки для підключення модуля ESP8266 / ESP32 а також пристроїв на базі цих модулів:
- Мова програмування
- Прошивка NodeMCU з мовою Lua
- Сервер Home Assistant
- Локальна мережа
- Протокол передачі даних
- Серверний інтерфейс інтеграції Home Assistant
- Надсилання та отримання даних
- Токен довготривалого доступу
- Запити контролера до сервера з рівня Lua (NodeMCU)
Тепер напишемо повний Луа код для обміну даними.
Робочий код надсилання та отримання даних на Lua
Робочий Lua-код завдяки функції post()
і таймеру, може надсилати дані на сервер щохвилини, а також за запитом користувача, може отримувати дані з сервера засобами функції get()
.
Функції lua-модуля виконують запити до сервера по HTTP. Отримуючи їх, сервер виконує автентифікацію токена, і відповідно до власних правил API, створює тимчасові структури і сутності. Адміністратор сервера, може створити віджети дашборда, які будуть показувати стан чи значення сенсорів.
Примітка. Якщо у вас декілька сенсорів на одному контролері, потрібно виконати декілька запитів
HTTP POST
, щоб розмістити їх дані на сервері.
Примітка. Якщо у вас декілька різних типів сутностей на контролері, приміром, не лише сенсор, а і дискретний перемикач (switch) то потрібно змінити шлях запиту до API на відповідний. В цій статті ми не розглядаємо сутності відмінні від сенсора. Можливо, ми присвятимо switch, cover та іншим, окрему статтю.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
CHIPID = node.chipid() or 0 hass_ip = '192.168.0.109' -- Fixed at WiFi router’s DHCP IP address of Home Assistant Server device_name = 'GGreg20_V1_' -- Unique ESP8266 Device Name is set by User token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIzZDI2NWMy'.. 'YzBiMDI0Y2RiYmEwNmIwZGEyZDA1ZWE4MSIsImlhdCI6MTYxOTg1OTQ2OCwiZXhwIjoxOTM1MjE5NDY'.. '4fQ.y9AVoopELWxSpXhCLBvPrYztGFv5o2_lg8hkQ4EO9M8' unit_of_measurement = 'uSv/Hour' friendly_name = 'Ionizing Radiation Power' -- GGreg20_V1 sensor value friendly name is set by User value = 0.1 -- initial sensor value by default -- This lua-module is used here as GGreg20_V1 sensor driver and data source example: radCounter = require('radCounter') -- radCounter software lua-module init radCounter.init(3, 0, 60000, 'OFF', 'ON', 0) -- pin=D3; direction=falling edge; count for 60 seconds. See more on module info at: https://alterstrategy.com/product/radcounter/ function post(val) if val == nil then val = value end http.post('http://'..hass_ip..':8123/api/states/sensor.'..device_name..CHIPID, -- Home Assistant Server address and device's entity path 'Content-Type: application/json\r\n'.. -- Headers 'Authorization: Bearer '..token..'\r\n', -- Headers '{"state": "'..val..'", "attributes": {"unit_of_measurement": "'..unit_of_measurement..'", "friendly_name": "'..friendly_name..'"}}', -- Data to post function(code, data) if (code < 0) then print("HTTP POST request failed") else print(code, data) -- request result code and server response data end end ) end function get() http.get('http://'..hass_ip..':8123/api/states/sensor.'..device_name..CHIPID, -- Home Assistant Server address and device's entity path 'Content-Type: application/json\r\n'.. -- Headers 'Authorization: Bearer '..token..'\r\n', -- Headers function(code, data) if (code < 0) then print("HTTP GET request failed") else print(code, data) res, str = code, data -- request result code and data to get end end ) return res, str end -- As radCounter.read() method returns: -- state: current event status state Ok/Warn/Danger -- avg_rad_lvl: current moving avgerage radiation level value in uSV/hour -- meas_min: total current minimum level radiation measured in uSV/hour -- meas_max: total current maximum level radiation measured in uSV/hour -- dose: total cumulative dose measured in uSv -- g_count: total current impulses count -- minutes_passed: total minutes passed from measuring start -- then: function timedPost() _, value, _, _, _, _, _ = radCounter.read() -- using radCounter module method to obtain one of sensor values post(value) -- sending current moving average ionizing radiation power level value end post_tmr = tmr.create() post_tmr:register(60000, tmr.ALARM_AUTO, function() timedPost() end) -- Run timedPost() every minute post_tmr:start() |
На рисунках далі за текстом, наведено результати роботи програми, а також як ці результати виглядають на боці сервера Home Assistant.
Для початку ми написали зовсім простий скрипт, який щоразу надсилав HTTP POST
запит на сервер:
Як можна бачити, перший запит завершився з кодом 201 – сервер повертає такий код для випадку, коли нову сутність на сервері було створено (її не існувало). У випадку, якщо сутність існувала і її значення було оновлено – код завершення операції буде 200.
Після нашого першого запиту, який ми виконали з контролера, у внутрішніх структурах сутностей сервера з’явилася sensor.ggreg20_v1_chipid
:
Це означає, що ми тепер маємо доступ до цієї сутності з усіх наявних у сервері Home Assistant інструментів та плагінів.
Наприклад, ми тепер можемо створити віджет дашборду, щоб відображати значення у фронтенд.
Або ж, ми можемо утворити сценарій автоматизації.
Наприклад, якщо значення потужності випромінювання вище 0.3 – включити сирену. І це далеко не всі можливості, які ми тепер можемо реалізувати щодо отриманого з контролера у сервер значення з сенсора.
Втім, спробуємо створити простий віджет для дашборду користувача:
Результат – віджет на дашборді, що відображає поточне значення потужності іонізуючого випромінювання:
Але для того, що покращити користувацький досвід та полегшити сприйняття інформації користувачами, створимо ще кілька веджетів, які крім поточного значення з сенсора, показують ще й важливі характеристики зміни значення у часі:
Один з віджетів – показує кольором перетин порогів. Інший віджет показує зміну значень з плином часу у форматі графіка.
Обидва віджети налаштовано на наступні діапазони: 0 – 0.3 мкЗв/год норма (зелений); 0.3 – 0.6 підвищений (помаранчевий), 0.6 – і вище – небезпека (червоний).
1 2 3 4 5 6 7 8 9 10 |
### Наводимо yaml-код для віджету тигу Gauge: type: gauge min: 0 max: 1 entity: sensor.ggreg20_v1_3222059 severity: green: 0 yellow: 0.3 red: 0.6 ## END # |
Для того, щоб перевірити, як працюють нові віджети, надішлемо з контролера кілька порцій тестових значень:
Як можемо бачити, все працює так, як і було задумано:
Під час зміни значень – віджети реагують відповідною візуалізацією:
Також нам варто звіритися з тим, які сирі дані отримує сервер від контролера:
Ну і наостанок, перевіряємо, що ми у разі необхідності, зможемо отримати від сервера останнє йому відоме значення сенсора. Для цього застосовуємо метод HTTP GET
:
Все працює.
У випадку, якщо контролер з якихось причин має взнати попереднє значення чи стан своїх сенсорів або виконавчих механізмів з сервера – ми це можемо забезпечити шляхом запиту HTTP GET
.
Висновки
Ми з вами спробували і успішно виконали інтеграцію довільного пристрою з WIFi до екосистеми Home Assistant. – Пристрою, що працює під керуванням прошивки NodeMCU з мовою програмування Lua.
Ба більше! Ми у декілька кліків вивели на дашборд потрібні нам дані з сенсора радіації GGreg20_V1, підключеного до модуля ESP12.OLED.
Lua-код, що ми приводимо як приклад, є простим і теж був написаний за кілька хвилин. Готовий до використання модуль radCounter, звісно, дуже спростив нам цю задачу, адже розрахунок показників сенсора відбувається всередині radcounter.lua
, який ми викликаємо через require().
У такий же спосіб є можливим інтегрувати до сервера Home Assistant будь-який сенсор чи пристрій з виконавчим механізмом. Через post()
передаємо свої дані на сервер, а через get()
отримуємо завдання для виконавчого механізму.
Бажаємо успіхів!