From 80280a5d28ccf04262e35917ac9f806b3c91cf59 Mon Sep 17 00:00:00 2001 From: Birte Kristina Friesel Date: Sun, 4 Feb 2024 14:39:20 +0100 Subject: initial commit --- .gitignore | 1 + .reuse/dep5 | 9 ++ README.md | 103 +++++++++++++++++++++ ...ster-15-modules-2017-01-03-14-04-53-integer.bin | Bin 0 -> 416483 bytes init.lua | 96 +++++++++++++++++++ 5 files changed, 209 insertions(+) create mode 100644 .gitignore create mode 100644 .reuse/dep5 create mode 100644 README.md create mode 100644 firmware/nodemcu-master-15-modules-2017-01-03-14-04-53-integer.bin create mode 100644 init.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..338c30b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.lua diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 0000000..55e41dd --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,9 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + +Files: init.lua +Copyright: 2024 Birte Kristina Friesel +License: BSD-2-Clause + +Files: README.md .gitignore +Copyright: 2024 Birte Kristina Friesel +License: CC0-1.0 diff --git a/README.md b/README.md new file mode 100644 index 0000000..619b268 --- /dev/null +++ b/README.md @@ -0,0 +1,103 @@ +# ESP8266 Lua/NodeMCU MQTT to UART bridge + +[esp8266-nodemcu-uart-bridge](https://finalrewind.org/projects/esp8266-nodemcu-uart-bridge/) +provides an ESP8266 NodeMCU Lua application (`init.lua`) that mirrors +incoming MQTT messages to the ESP8266's UART and can also transmit messages +received by UART to an MQTT broker or to InfluxDB. This way, it can add simple +MQTT/InfluxDB connectivity to devices that do not have a WiFi / ethernet +connection. + +## Dependencies + +`init.lua` has been tested with Lua 5.1 on NodeMCU firmware 1.5.4.1(39cb9a32) +(commit 81ec3665cb5fe68eb8596612485cc206b65659c9, integer build). This allows +it to run on old ESP8266-01 boards with just 512kB of Flash. It requires the +following modules. + +* http +* mqtt +* node +* tmr +* wifi + +## Usage + +### Startup + +Once connected, the ESP8266 will output the following lines on its TX line: + +* `WiFi:Rdy` *IP-address* +* `MQTT:Rdy` *MQTT-prefix* + +The default MQTT prefix is `uart/esp8266_`*Chip-ID*, e.g. +`uart/esp8266_82B45C`. Additionally, the ESP8266 will publish a retained +"online" message under *MQTT-prefix*/**state** and subscribe to +*MQTT-prefix*/**in**. + +### MQTT to UART + +The ESP8266 prints each received *message* with an "RX:" prefix on its TX line, +like so: + +`RX:`*message* + +### UART to MQTT + +When the ESP8266 receives **publish_mqtt**(*topic*, *payload*, *retain*) on its +RX line, it will publish the specified payload under the specified topic. +The *retain* flag defaults to false. For instance, the following input will +publish "hello" under `uart/esp8266_`*Chip-ID*`/out`: + +`publish_mqtt(mqtt_prefix .. "/out", "hello")` + +If the message has been sent out successfully, it will reply with `MQTT:OK` or +`> MQTT:OK`. Otherwise, it will reply with `MQTT:Err` or `> MQTT:Err` + +### Watchdog + +If none of the following four events happen for a time span of 90 seconds, the +ESP8266 will reset itself, causing a re-connection to WiFi and MQTT server. + +* The ESP8266 receives a message via MQTT +* The ESP8266 receives a **publish_mqtt** command via RX and the command + completes successfully +* The ESP8266 receives a **publish_influx** command via RX and the command + completes successfully +* The ESP8266 receiveds a **wdr()** command via RX. + +### Error Handling + +The following messages on the ESP8266 TX line indicate errors. +Note that some errors can have several reasons. + +* `MQTT:Err` or `> MQTT:Err` – Failed to publish MQTT message (another message was still being + processed) +* `MQTT:Err` or `> MQTT:Err` – Connection to MQTT broker has been lost +* `WiFi:Err` or `> WiFi:Err` – Unable to establish WiFi connection +* `WiFi:Err` or `> WiFi:Err` – WiFi connection has been lost +* `Watchdog:Err` or `> Watchdog: Err` – watchdog timeout, the device will reset (see above) + +## Configuration + +To use this application, you need to create a **config.lua** file with WiFI and +MQTT settings: + +```lua +station_cfg = {ssid = "...", pwd = "..."} +mqtt_host = "..." +``` + +To use InfluxDB, configure URL and (optional) header: + +```lua +influx_url = "..." +influx_header = "..." +``` + +## Resources + +Mirrors of this repository are maintained at the following locations: + +* [Chaosdorf](https://chaosdorf.de/git/derf/esp8266-nodemcu-uart-bridge) +* [git.finalrewind.org](https://git.finalrewind.org/esp8266-nodemcu-uart-bridge/) +* [GitHub](https://github.com/derf/esp8266-nodemcu-uart-bridge) diff --git a/firmware/nodemcu-master-15-modules-2017-01-03-14-04-53-integer.bin b/firmware/nodemcu-master-15-modules-2017-01-03-14-04-53-integer.bin new file mode 100644 index 0000000..90ac0b9 Binary files /dev/null and b/firmware/nodemcu-master-15-modules-2017-01-03-14-04-53-integer.bin differ diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..8277536 --- /dev/null +++ b/init.lua @@ -0,0 +1,96 @@ +publishing_mqtt = false +publishing_http = false + +watchdog = tmr.create() +chip_id = string.format("%06X", node.chipid()) +device_id = "esp8266_" .. chip_id +mqtt_prefix = "uart/" .. device_id +mqttclient = mqtt.Client(device_id, 120) + +dofile("config.lua") + +function wdr() + watchdog:stop() + watchdog:start() +end + +function wd_err() + print("Watchdog:Err") + node.restart() +end + +function mqtt_err(client) + print("MQTT:Err") +end + +function wifi_err() + print("WiFi:Err " .. wifi.sta.status()) +end + +function setup_client() + print("MQTT:Rdy " .. mqtt_prefix) + publishing_mqtt = true + mqttclient:publish(mqtt_prefix .. "/state", "online", 0, 1, function(client) + client:subscribe(mqtt_prefix .. "/in", 0) + publishing_mqtt = false + end) +end + +function connect_mqtt() + print("") + print("WiFi:Rdy " .. wifi.sta.getip()) + mqttclient:on("connect", setup_client) + mqttclient:on("offline", mqtt_err) + --mqttclient:on("connfail", mqtt_err) + mqttclient:on("message", print_mqtt) + mqttclient:lwt(mqtt_prefix .. "/state", "offline", 0, 1) + mqttclient:connect(mqtt_host) +end + +function connect_wifi() + wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, connect_mqtt) + wifi.eventmon.register(wifi.eventmon.STA_DHCP_TIMEOUT, wifi_err) + wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, wifi_err) + wifi.setmode(wifi.STATION) + wifi.sta.config(station_cfg) + wifi.sta.connect() +end + +function print_mqtt(client, topic, message) + print("RX:" .. message) + wdr() + collectgarbage() +end + +function publish_mqtt(topic, payload, retain) + if publishing_mqtt then + print("MQTT:Err") + else + publishing_mqtt = true + mqttclient:publish(topic, payload, 0, retain or 0, function(client) + publishing_mqtt = false + print("MQTT:OK") + wdr() + collectgarbage() + end) + end +end + +function publish_influx(payload) + if publishing_http then + print("Influx:Err") + else + publishing_http = true + http.post(influx_url, influx_header, payload, function(code, data) + publishing_http = false + print("Influx:OK") + wdr() + collectgarbage() + end) + end +end + +watchdog:register(90 * 1000, tmr.ALARM_SEMI, wd_err) +watchdog:start() + +connect_wifi() -- cgit v1.2.3