From: Pat Thoyts Date: Mon, 9 Jan 2017 22:17:58 +0000 (+0000) Subject: ESP8266 temperature logging to MQTT device. X-Git-Url: https://privyetmir.co.uk/gitweb.cgi?a=commitdiff_plain;ds=sidebyside;p=esp8266%2Fmqtt_sensor.git ESP8266 temperature logging to MQTT device. Signed-off-by: Pat Thoyts --- 458ab0d7a91276e1e8a82ae532565b82ae9de05c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07da015 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/config.lua +/ESPlorer.Log +/ESPlorer.Log.lck + diff --git a/README.md b/README.md new file mode 100644 index 0000000..ff12389 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +MQTT Temperature Sensor +----------------------- + +Publish temperature over MQTT every 10 minutes + +Timer 4 reads the temperature every second and other +timers cause the last temperature reading to be published at intervals +over mqtt as defined in the config.lua file. We are sending to the local +server each minute and to a public one every 10 minutes. + + +The circuit board is an MP1584 based step-down board to provide 3V3 power +and two DS18B20 sensors hooked onto GPIO0 (aka pin 3 in nodemcu). +Also added 4K7 pullups to RST and EN and the 1-wire data line and +connected the ESP8266 serial lines to a molex RA header. + +Setup +----- + +Copy 'config.lua.example' to 'config.lua' and modify to suit your setup. +Upload to the ESP8266 device using luaload or esplorer etc. + diff --git a/application.lua b/application.lua new file mode 100644 index 0000000..36df79a --- /dev/null +++ b/application.lua @@ -0,0 +1,90 @@ +require('ds18b20') +require('mqtt') +require('gpio') + +dofile('config.lua') + +function mqtt_build_message() + local r = {} + for id,t in pairs(ds18b20.values) do + local t1 = t / 10000 + local t2 = (t >= 0 and t % 10000) or (10000 - t % 10000) + table.insert(r, string.format("{\"id\":\"%s\",\"temp\":%d.%04d}", id, t1, t2)) + end + return "[" .. table.concat(r, ",") .. "]" +end + +function mqtt_publish(m, prefix) + local topic = prefix .. '/' .. node.chipid() + m:publish(topic .. '/temperature', mqtt_build_message(), 0, 0, nil) +end + +function mqtt_create_client(server, prefix, timerid, interval) + local m = mqtt.Client(node.chipid(), 60, MQTT_USERNAME, MQTT_PASSWORD, 0) + m:lwt(prefix .. '/' .. node.chipid() .. '/error', 'disconnected', 0, 0) + m:on("connect", function(client) + mqtt_publish(client, prefix) + -- max time is 6870947 (1:54:30.947) + tmr.alarm(timerid, interval, 1, function() mqtt_publish(client, prefix) end) + end) + m:on("offline", function(client) + tmr.stop(timerid) + m:connect(server, MQTT_PORT, 0, 1) + end) + m:connect(server, MQTT_PORT, 0, 1) + return m +end + +function mqtt_start() + local clients = {} + ds18b20.update() + tmr.alarm(SENSOR_TIMER, SENSOR_INTERVAL * 1000, tmr.ALARM_AUTO, ds18b20.update) + for index,broker in ipairs(MQTT_BROKERS) do + local interval = broker.interval * 1000 + local m = mqtt_create_client(broker.host, broker.prefix, broker.timer, interval) + table.insert(clients, m) + end + return clients +end + +function mqtt_stop() + print("mqtt_stop") + for index,broker in ipairs(MQTT_BROKERS) do + tmr.stop(broker.timer) + tmr.unregister(broker.timer) + end + for index,client in ipairs(clients) do + if pcall(client.close) then + print("closed client") + else + print("failed to close client") + end + end + tmr.stop(SENSOR_TIMER) + tmr.unregister(SENSOR_TIMER) +end + +LED_STATE = 1 + +function blink() + if LED_STATE == 1 then + LED_STATE = 0 + else + LED_STATE = 1 + end + gpio.write(LED_PIN, LED_STATE) +end + +function blink_start() + gpio.mode(LED_PIN, gpio.OUTPUT) + tmr.alarm(LED_TIMER, LED_INTERVAL, tmr.ALARM_AUTO, blink) +end + +function blink_stop() + tmr.stop(LED_TIMER) + tmr.unregister(LED_TIMER) +end + +ds18b20.init(SENSOR_PIN) +blink_start() +clients = mqtt_start() diff --git a/config.lua.example b/config.lua.example new file mode 100644 index 0000000..c8069cc --- /dev/null +++ b/config.lua.example @@ -0,0 +1,26 @@ +-- WiFi network to join and the PSK password + +SSID='WIFI_SSID_HERE' +PASSWORD='WIFI_PASSWORD' + +SENSOR_PIN = 3 +SENSOR_TIMER = 2 +SENSOR_INTERVAL = 10 -- seconds + +LED_PIN = 4 +LED_TIMER = 5 +LED_INTERVAL = 1000 + +-- Username and password to use for MQTT +MQTT_PORT = 1883 +MQTT_USERNAME='' +MQTT_PASSWORD='' + +-- MQTT brokers and prefixes +-- +-- a list of MQTT brokers to publish too with a custom prefix for +-- each broker. Use a separate timer id for each broker. +MQTT_BROKERS = { + -- iot.eclipse.org + { host='198.41.30.241', prefix='mqtt_sensor_demo/nodemcu', timer=4, interval=600 } +} diff --git a/ds18b20.lua b/ds18b20.lua new file mode 100644 index 0000000..208ec9b --- /dev/null +++ b/ds18b20.lua @@ -0,0 +1,80 @@ +local modname = ... +local M = {} -- public interface +_G[modname] = M + +require('bit') +require('ow') + +M.CONVERT = 0x44 +M.READ_SCRATCHPAD = 0xBE + +local function hexstring(...) + local len = select('#', ...) + local r = {} + for n = 1, len do r[n] = string.format("%02x", select(n,...)) end + return table.concat(r, ':') +end + +local function find_devices(pin) + ow.setup(pin) + ow.reset_search(pin) + local devices = {} + repeat + local addr = ow.search(pin) + if addr ~= nil then table.insert(devices, addr) end + tmr.wdclr() + until addr == nil + return devices +end + +function M.init(pin) + M.pin = pin + M.timerid = 1 + M.delay = 800 + M.pending = 0 + M.values = {} + M.sensors = find_devices(pin) +end + +function M.read_sensors() + local pin = M.pin + for i,addr in ipairs(M.sensors) do + local id = hexstring(addr:byte(1,8)) + ow.reset(pin) + ow.select(pin,addr) + ow.write(pin,M.READ_SCRATCHPAD,1) + local data = nil + data = string.char(ow.read(pin)) + for i = 1, 8 do + data = data .. string.char(ow.read(pin)) + end + local crc = ow.crc8(string.sub(data,1,8)) + if (crc == data:byte(9)) then + local t = data:byte(1) + data:byte(2) * 256 + if (t > 32768) then + -- convert unsigned to signed twos complement. + t = (bit.bxor(t, 0xffff) + 1) * -1 + end + t = t * 625 + print(id, t) + M.values[id] = t + else + print(id, "bad crc") + end + M.pending = M.pending - 1 + end +end + +function M.update() + local t = 0 + M.pending = 0 + for i,addr in ipairs(M.sensors) do + ow.reset(M.pin) + ow.select(M.pin, addr) + ow.write(M.pin, M.CONVERT, 1) + M.pending = M.pending + 1 + end + tmr.alarm(M.timerid, M.delay, tmr.ALARM_SINGLE, M.read_sensors) +end + +return M diff --git a/esp01_sensor.pdf b/esp01_sensor.pdf new file mode 100644 index 0000000..73705b8 Binary files /dev/null and b/esp01_sensor.pdf differ diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..bfe3ec3 --- /dev/null +++ b/init.lua @@ -0,0 +1,37 @@ +require('tmr') +require('wifi') +require('file') + +-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there +dofile("config.lua") + +function startup() + if file.exists("application.lua") then + -- the actual application is stored in 'application.lua' + print("Running application.lua") + dofile("application.lua") + else + print('warning: missing file "application.lua"') + end +end + +function abort() + tmr.stop(1) +end + +print("Connecting to WiFi access point...") +wifi.setmode(wifi.STATION) +print('MAC: ' .. wifi.sta.getmac()) +wifi.sta.config(SSID, PASSWORD) +-- wifi.sta.connect() not necessary because config() uses auto-connect=true by default +tmr.alarm(1, 1000, tmr.ALARM_AUTO, function() + if wifi.sta.getip() == nil then + print("Waiting for IP address...") + else + tmr.stop(1) + print("WiFi connection established, IP address: " .. wifi.sta.getip()) + print("You have 5 seconds to abort (abort())") + print("Waiting...") + tmr.alarm(1, 5000, tmr.ALARM_SINGLE, startup) + end +end)