├── LICENSE ├── README.md └── mqtt_test.lua /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 pprimm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | nodemcu-lua-mqtt 3 | =========== 4 | Lua scripts for Nodemcu mostly testing MQTT protocol and CoAP (planned upon future Lua release by Nodemcu). Please use at will to jump start your MQTT prototyping on the Nodemcu platform. I use the following tools for Nodemcu and Lua: 5 | 6 | - [Nodemcu Lua API Reference](https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en) 7 | - [Nodemcu Flasher for firmware updates](https://github.com/nodemcu/nodemcu-flasher) 8 | - [Lua Uploader for Windows](https://github.com/hwiguna/g33k/tree/master/ArduinoProjects/Windows/ESP8266_Related) 9 | 10 | > *A note on Nodemcu firmware* 11 | 12 | > I have been unable to get the majority of my Lua test code to work properly on any Nodemcu firmware version after Version 0.9.5 build 20150127. Issues with later firmware version have ranged from connection errors with broker to crashes of various sorts. These Lua test scripts will probably only run on firmware **Version 0.9.5 build 20150127**! 13 | 14 | mqtt_test.lua 15 | ---------------- 16 | This lua script creates an MQTT accessible counter service. A service is defined as: 17 | 18 | - a list of ***get*** topics which indicate the service ***state***; observable by all MQTT clients 19 | - a list of ***set*** topics for requesting ***state*** be set to particular values; writable by all MQTT clients 20 | - a list of ***RPC*** topics for performing direct method calls on the service; responses are directed a calling MQTT client 21 | 22 | > *Service API* 23 | > 24 | > - **status**: state variable to show whether offline or online (enhanced by use of Last Will Testament) 25 | > - **counterValue**: main state variable with value of counter (read: get/ESP8266/counterValue) (write: set/ESP8266/counterValue). The allow value is clipped at 0..100. The counterValue will cycle up/down between 0 and 100; inc/dec by 1 every second. 26 | > - **counterCmd**: this set topic will control whether the counter goes up or down. Allowed values are "up" or "down" 27 | > - **echo**: whatever you write to the set topic gets echoed to the get topic (read: get/ESP8266/echo) (write: set/ESP8266/echo) 28 | 29 | The script also handles reconnecting to the MQTT broker after loss of connection. 30 | 31 | There is a bit of code that needs a little explanation: it's the following section for handeling subscribing to a MQTT topic in the connect callback: 32 | 33 | ``` 34 | m:on("connect", function(con) 35 | print("connected") 36 | mqttOnline = true 37 | m:publish("get/ESP8266/status", "online", 0, 1) 38 | -- hack to prevent stdio bomb calling subscribe in this callback 39 | tmr.alarm(hackTimerID, hackTimerInterval, 0, function() 40 | m:subscribe("set/ESP8266/#",0, function(con) 41 | print("subscribe success") 42 | mqttSubSuccess = true 43 | end) 44 | end) 45 | end) 46 | ``` 47 | The alarm timer callback is used to subscribe to the *set/ESP8266/#* topic from within the onConnect MQTT callback. If I called the subscribe() function inline in the onConnect callback, the ESP8266 would crash on an stdin error. I tried several different methods for triggering the subscribe whenever the MQTT client connects without success until I "decoupled" the subscribe() call from the callback(s) that were performing other MQTT calls. This, I believe, is a bug; as one should be able to make a series of MQTT calls from the onConnect callback. 48 | 49 | I hope this test script helps you do effective IoT prototyping with the Nodemcu. -------------------------------------------------------------------------------- /mqtt_test.lua: -------------------------------------------------------------------------------- 1 | -- https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en 2 | mqttOnline = false 3 | mqttSubSuccess = false 4 | COUNTER_CMD_UP = "up" 5 | counterUp = true 6 | COUNTER_MAX = 100 7 | COUNTER_MIN = 0 8 | counter = 0 9 | 10 | -- timer vars 11 | mainTimerId = 0 -- we have seven timers! 0..6 12 | mainInterval = 1000 -- milliseconds 13 | statusTimerID = 1 14 | statusInterval = 10000 15 | hackTimerID = 2 16 | hackTimerInterval = 100 17 | -- client ID, keepalive (seconds), user, password 18 | m = mqtt.Client("ESP8266_dev", 30) 19 | 20 | m:lwt("get/ESP8266/status", "offline", 0, 0) 21 | 22 | m:on("connect", function(con) 23 | print("connected") 24 | mqttOnline = true 25 | m:publish("get/ESP8266/status", "online", 0, 1) 26 | -- hack to prevent stdio bomb calling subscribe in this callback 27 | tmr.alarm(hackTimerID, hackTimerInterval, 0, function() 28 | m:subscribe("set/ESP8266/#",0, function(con) 29 | print("subscribe success") 30 | mqttSubSuccess = true 31 | end) 32 | end) 33 | end) 34 | 35 | m:on("offline", function(con) 36 | print("offline") 37 | mqttOnline = false 38 | mqttSubSuccess = false 39 | end) 40 | 41 | counterValueGetTopic = "get/ESP8266/counterValue" 42 | counterValueSetTopic = "set/ESP8266/counterValue" 43 | function counterValueGetReceived(msg) 44 | newValue = tonumber(msg) 45 | if newValue ~= nil then 46 | counter = newValue 47 | end 48 | end 49 | 50 | counterCmdSetTopic = "set/ESP8266/counterCmd" 51 | function counterCmdReceived(msg) 52 | if msg == COUNTER_CMD_UP then 53 | counterUp = true 54 | else 55 | counterUp = false 56 | end 57 | end 58 | 59 | echoGetTopic = "get/ESP8266/echo" 60 | echoSetTopic = "set/ESP8266/echo" 61 | function echoReceived(msg) 62 | if msg ~= nil then 63 | m:publish(echoGetTopic, msg, 0, 0) 64 | end 65 | end 66 | 67 | m:on("message", function(con, topic, msg) 68 | print("callback "..topic..":"..msg) 69 | if topic == echoSetTopic then 70 | echoReceived(msg) 71 | elseif topic == counterCmdSetTopic then 72 | counterCmdReceived(msg) 73 | elseif topic == counterValueSetTopic then 74 | counterValueGetReceived(msg) 75 | end 76 | end) 77 | 78 | function updateCounter() 79 | if counter >= COUNTER_MAX then 80 | counter = COUNTER_MAX 81 | counterUp = false 82 | elseif counter <= COUNTER_MIN then 83 | counter = COUNTER_MIN 84 | counterUp = true 85 | end 86 | if counterUp then 87 | counter = counter + 1 88 | else 89 | counter = counter - 1 90 | end 91 | end 92 | 93 | function updateMQTT() 94 | if wifi.sta.status() == 5 then 95 | if mqttOnline then 96 | m:publish(counterValueGetTopic, counter, 0, 0) 97 | else 98 | print("calling m:connect()") 99 | m:connect("10.10.101.24", 1883) 100 | end 101 | end 102 | end 103 | 104 | tmr.alarm(mainTimerId, mainInterval, 1, function() 105 | -- counter updates whether online or not 106 | updateCounter() 107 | updateMQTT() 108 | end) 109 | 110 | -- print status of wifi and online every 10 sec -- 111 | tmr.alarm(statusTimerID, statusInterval, 1, function() 112 | print("wifi status:"..wifi.sta.status()..", MQTT Online:"..tostring(mqttOnline)) 113 | end) --------------------------------------------------------------------------------