Unverified Commit 80280a5d authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

initial commit

parents
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+1 −0
Original line number Diff line number Diff line
config.lua

.reuse/dep5

0 → 100644
+9 −0
Original line number Diff line number Diff line
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

README.md

0 → 100644
+103 −0
Original line number Diff line number Diff line
# 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)
+407 KiB

File added.

No diff preview for this file type.

init.lua

0 → 100644
+96 −0
Original line number Diff line number Diff line
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()