Умный дом на ESP8266+MajorDoMo. Часть 5. Подключение преобразователя влажности AM2302.

На этот раз решил подключить преобразователь влажности AM2302. Кроме влажности он выдает данные и по-температуре. Написание кода не составило труда, т.к. библиотека для датчика влажности, как и для датчика температуры из прошлой статьи, встроена в прошивку (см. часть 1). И нам остается только запрашивать готовые данные, минуя написание кода по их получению из самого преобразователя.

Как обычно, код состоит из 4 файлов. Когда-нибудь руки все же дойдут до написания кода для перепрошивки ESP8266 по-воздуху, но пока будем только мониторить данные )))

Код файла init.lua (автозагрузка модуля):

dofile("config.lua") -- подгружаем файл config.lua 
dofile("main.lua") -- подгружаем основной файл программы main.lua

Код файла config.lua (файл общих настроек):

-- Для дальнейшего удобства лучше хранить данные в таблице, а не в переменной. 
-- При изменении какого-либо значения по-воздуху POST-запросом 
-- удобнее будет перезаписывать данные. 
-- Для редактирования в ESPlorer тип значений может быть любой 

config = {} 
config.LanSSID = "ssid" -- название wifi-сети 
config.LanPWD = "password" -- пароль wifi-сети 
config.LanServer = "192.168.1.15" -- IP-адрес сервера с установленной системой MajorDoMo

Код файла main.lua (основной файл выполнения программы):

--Конфигурируем чип как клиента, присоединяемся к существующей сети WiFi
--Присоединяемся к сети WiFi
--При неудачном соединении создаем свою точку доступа 192.168.1.200
--При удачном - поднимаем веб-сервер, выводим список доступных дочек доступа
--Опрашиваем датчик HC-SR501 каждые 500 мс

connect=0 --статус присоединеия к существующей сети WiFi

-- поднимаем точку доступа
function setSOFTAP()
 local cfg={}
 cfg.ssid="ApESP8266"
 cfg.pwd="password"

 wifi.setmode(wifi.SOFTAP)
 wifi.ap.config(cfg)
 print(wifi.ap.getip())

end

-- Проверка на соединение с точкой доступа (проверка получения IP)
function getConnect()
 if wifi.sta.getip() ~= nil then -- если IP-адрес получен (не равен NIL)
 connect = 1 -- ставим статус получения адреса
 print("IP-адрес получен: "..wifi.sta.getip())
 startWork() -- запускаем функцию начала цикла работы
 else
 connect = 0
 print("IP-адрес не получен, поднимаем точку доступа")
 setSOFTAP() -- если присоединиться не удалось, поднимаем свою точку доступа

 end
end

-- Конфигурируем чип как клиента, присоединяемся к существующей сети WiFi
-- Заводим таймер на 5 сек. Если по прошествии этого времени не получили IP?
-- то поднимаем свою точку доступа, свой веб-сервер
wifi.setmode(wifi.STATION) -- конфигурируем чип как клиент
wifi.sta.autoconnect(1) -- включаем автоприсоединение к сети
wifi.sta.config(config.LanSSID, config.LanPWD, true) -- присоединяемся к сети, сохраняем настройки конфигурации во FLASH
tmr.alarm(0, 5000, tmr.ALARM_SINGLE, getConnect) --заводим таймер на 5 секунд



function startWork()
 -- поднимаем сервер на 80 порту с таймаутом 30 сек
 srv = net.createServer(net.TCP, 30)
 -- формируем ответ из нескольких строк клиенту и отправляем
 function receiver(sck, data)

 --print(data) --отправляем данные о подключении на UART

 local response = {}

 response[#response + 1] = "<html><body style=\"font-family: Verdana, Arial, Helvetica, sans-serif;\"><center>"
 response[#response + 1] = "<h1>Ap SmartHome</h1> <br/>Температура: "..AM2302_READ_T().." °C"
 response[#response + 1] = "<br/>Влажность: "..AM2302_READ_H().." %"
 response[#response + 1] = "</center></body></html>"

 -- отправляем и удаляем первый элемент из таблицы response, пока не отправим все
 local function send(localSocket)
 if #response > 0 then --пока длина таблицы response не равна нулю
 localSocket:send(table.remove(response, 1))
 else
 localSocket:close() -- если все отправили - закрываем сокет
 response = nil -- удаляем переменную "response"
 end
 end

 -- triggers the send() function again once the first chunk of data was sent
 sck:on("sent", send) --если отправили посылку - отправляем еще раз
 send(sck)
 end

 -- Мониторим 80 порт. Если есть запрос от клиента - выполняем функцию "receiver"
 if srv then
 srv:listen(80, function(conn)
 conn:on("receive", receiver)
 end)
 end

 local function am2302()
 print("Память:"..node.heap())
 dofile("AM2302.lua")
 print("DHT Temperature:"..am2302_data.t.."; Humidity:"..am2302_data.h)

 -- Отправка данных о температуре и влажности
 -- Т.к. за 1 раз можно установить только 1 свойство, то устанавливаем
 -- 2 соединения по очереди, в каждом меняем нужную переменную
 srv = net.createConnection(net.TCP, 0) -- создаем новое TCP-соединение
 srv:connect(81,"192.168.1.15") -- коннектимся к серверу с установленным MajorDoMo
 srv:on("connection", function(sck, c) -- если соединение установлено, отправляем данные на сервер
 sck:send("GET /objects/?object=humidityKitchen&op=set&p=humidity&v="..AM2302_READ_H().." HTTP/1.1\r\nHost: 192.168.1.15\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
 end)

 srv = net.createConnection(net.TCP, 0) -- создаем новое TCP-соединение
 srv:connect(81,"192.168.1.15") -- коннектимся к серверу с установленным MajorDoMo
 srv:on("connection", function(sck, c) -- если соединение установлено, отправляем данные на сервер
 sck:send("GET /objects/?object=humidityKitchen&op=set&p=temperature&v="..AM2302_READ_T().." HTTP/1.1\r\nHost: 192.168.1.15\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
 end)

 collectgarbage()
 tmr.wdclr()
 end

 -- Таймер на опрос am2302 каждые 5 секунд
 tmr.alarm(0, 5000, tmr.ALARM_AUTO, am2302)

end

Небольшой особенностью  является то, что датчик выдает данные и по-влажности, и по-температуре. Т.е. нам придется устанавливать 2 свойства в 1 объекте. А т.к. за 1 раз можно установить 2 свойства, мы просто создаем подключение к МДМ 2 раза, и передает данные о температуре и влажности по-отдельности. Можно сделать это циклом FOR, но я решил просто продублировать код для наглядности.

Код файла AM2302.lua (библиотека преобразователя AM2302. Основная функция — чтение влажности и температуры):

am2302_data = {} --Глобальная таблица данных датчика DS18B20


am2302_data.t=0 --температура
am2302_data.h=0 --ID датчика DS18B20

function am2302_start()
 local pin = 1
 local status, temp, humi, temp_dec, humi_dec = dht.read(pin)
 if status == dht.OK then
 am2302_data.t=temp.."."..temp_dec
 am2302_data.h=humi.."."..humi_dec
 elseif status == dht.ERROR_CHECKSUM then
 print( "Неверная контрольная сумма" )
 elseif status == dht.ERROR_TIMEOUT then
 print( "DHT timed out" )
 end
 collectgarbage()
end

function AM2302_READ_T()
return am2302_data.t
end

function AM2302_READ_H()
return am2302_data.h
end

am2302_start() -- запускаем 1 цикл опроса датчика

Опрос датчика влажности происходит каждые 5000 мс. По окончании измерения создаем соединение к серверу с установленной системой МДМ, и отправляем GET-запросом данные о температуре и влажности, где они и сохраняются. Также показания выводятся в UART.

При заходе на веб-сервер ESP8266 получаем температуру и влажность на экран браузера

Ну и непосредственно отправка данных на МДМ. Опять создаем дочерний класс HumiditySensor от класса ESP8266

Добавляем 2 свойства: humidity и temperature

Общий вид свойств класса выглядит так

Теперь можно создать объект класса HumiditySensor, т.е. физическое устройство. Как обычно, размещаем на кухне ))))

Сохраняем. Все, теперь значения свойств будут обновляться каждые 5 секунд. Повесим их на главный экран. Создадим новый элемент меню управления (Панель управления -> Объекты -> Меню управления).

Наблюдаем на главном экране:

Ну и для наглядности выведем график. Создаем новый элемент Charts (Панель управления -> Объекты -> Меню управления -> Charts). И добавляем в него новый график, и два свойства — значения и влажности. Сохраняемся, наблюдаем красоту )))

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.