--- /dev/null
+/config.lua
+/ESPlorer.Log
+/ESPlorer.Log.lck
+
--- /dev/null
+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.
+
--- /dev/null
+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()
--- /dev/null
+-- 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 }
+}
--- /dev/null
+local modname = ...\r
+local M = {} -- public interface\r
+_G[modname] = M\r
+\r
+require('bit')\r
+require('ow')\r
+\r
+M.CONVERT = 0x44\r
+M.READ_SCRATCHPAD = 0xBE\r
+\r
+local function hexstring(...)\r
+ local len = select('#', ...)\r
+ local r = {}\r
+ for n = 1, len do r[n] = string.format("%02x", select(n,...)) end\r
+ return table.concat(r, ':')\r
+end\r
+\r
+local function find_devices(pin)\r
+ ow.setup(pin)\r
+ ow.reset_search(pin)\r
+ local devices = {}\r
+ repeat\r
+ local addr = ow.search(pin)\r
+ if addr ~= nil then table.insert(devices, addr) end\r
+ tmr.wdclr()\r
+ until addr == nil\r
+ return devices\r
+end\r
+\r
+function M.init(pin)\r
+ M.pin = pin\r
+ M.timerid = 1\r
+ M.delay = 800\r
+ M.pending = 0\r
+ M.values = {}\r
+ M.sensors = find_devices(pin)\r
+end\r
+\r
+function M.read_sensors()\r
+ local pin = M.pin\r
+ for i,addr in ipairs(M.sensors) do\r
+ local id = hexstring(addr:byte(1,8))\r
+ ow.reset(pin)\r
+ ow.select(pin,addr)\r
+ ow.write(pin,M.READ_SCRATCHPAD,1)\r
+ local data = nil\r
+ data = string.char(ow.read(pin))\r
+ for i = 1, 8 do\r
+ data = data .. string.char(ow.read(pin))\r
+ end\r
+ local crc = ow.crc8(string.sub(data,1,8))\r
+ if (crc == data:byte(9)) then\r
+ local t = data:byte(1) + data:byte(2) * 256\r
+ if (t > 32768) then\r
+ -- convert unsigned to signed twos complement.\r
+ t = (bit.bxor(t, 0xffff) + 1) * -1\r
+ end\r
+ t = t * 625\r
+ print(id, t)\r
+ M.values[id] = t\r
+ else\r
+ print(id, "bad crc")\r
+ end\r
+ M.pending = M.pending - 1\r
+ end\r
+end\r
+\r
+function M.update()\r
+ local t = 0\r
+ M.pending = 0\r
+ for i,addr in ipairs(M.sensors) do\r
+ ow.reset(M.pin)\r
+ ow.select(M.pin, addr)\r
+ ow.write(M.pin, M.CONVERT, 1)\r
+ M.pending = M.pending + 1\r
+ end\r
+ tmr.alarm(M.timerid, M.delay, tmr.ALARM_SINGLE, M.read_sensors)\r
+end\r
+\r
+return M\r
--- /dev/null
+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)