Skip to content

Commit dee3e38

Browse files
author
Michael Rüttgers
committed
Merge branch 'release/2.3.0'
2 parents 349826d + dd3be15 commit dee3e38

File tree

5 files changed

+71
-96
lines changed

5 files changed

+71
-96
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7-
## [Unreleased]
7+
## [2.3.0] - 2023-03-14
8+
### Changed
9+
- Upgraded IotWebConf to version 3
10+
### Fixed
11+
- [Issue #47](https://github.com/mruettgers/SMLReader/issues/47), Broken MQTT reconnect after WiFi disconnect
812

913
## [2.2.1] - 2022-03-17
1014
### Changed

platformio.ini

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
; https://docs.platformio.org/page/projectconf.html
1010

1111
[common]
12-
platform = espressif8266@2.3.1
12+
platform = espressif8266@^2.4.2
1313
lib_deps =
1414
git+https://github.com/volkszaehler/libsml
1515
EspSoftwareSerial
1616
MicroDebug
17-
IotWebConf@^2.3.3
18-
ESPAsyncTCP
19-
git+https://github.com/philbowles/PangolinMQTT.git#v1.0.0
17+
IotWebConf@3.2.0
18+
ESP AsyncTCP
19+
AsyncMqttClient
2020
jled
2121

2222
env_default = d1_mini
@@ -47,7 +47,7 @@ board = d1_mini
4747
framework = arduino
4848
lib_deps = ${common.lib_deps}
4949
lib_ldf_mode = ${common.lib_ldf_mode}
50-
build_flags = ${common.build_flags} -DSERIAL_DEBUG=true -DSERIAL_DEBUG_VERBOSE=true
50+
build_flags = ${common.build_flags} -DSERIAL_DEBUG=true -DSERIAL_DEBUG_VERBOSE=false
5151
upload_port = /dev/ttyUSB0
5252
monitor_port = /dev/ttyUSB0
5353
monitor_speed = 115200

src/MqttPublisher.h

Lines changed: 26 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#include "config.h"
55
#include "debug.h"
66
#include <Ticker.h>
7-
#include <PangolinMQTT.h>
7+
8+
#include <AsyncMqttClient.h>
89
#include <string.h>
910
#include <sml/sml_file.h>
10-
#include <Ticker.h>
1111

1212
#define MQTT_RECONNECT_DELAY 5
1313
#define MQTT_LWT_TOPIC "LWT"
@@ -35,18 +35,25 @@ class MqttPublisher
3535
config = _config;
3636
uint8_t lastCharOfTopic = strlen(config.topic) - 1;
3737
baseTopic = String(config.topic) + (lastCharOfTopic >= 0 && config.topic[lastCharOfTopic] == '/' ? "" : "/");
38-
38+
lastWillTopic = String(baseTopic + MQTT_LWT_TOPIC);
39+
40+
DEBUG(F("MQTT: Setting up..."));
41+
DEBUG(F("MQTT: Server: %s"),config.server);
42+
DEBUG(F("MQTT: Port: %d"),atoi(config.port));
43+
DEBUG(F("MQTT: Username: %s"),config.username);
44+
DEBUG(F("MQTT: Password: <hidden>"));
45+
DEBUG(F("MQTT: Topic: %s"), baseTopic.c_str());
46+
3947
client.setServer(const_cast<const char *>(config.server), atoi(config.port));
4048
if (strlen(config.username) > 0 || strlen(config.password) > 0)
4149
{
4250
client.setCredentials(config.username, config.password);
4351
}
44-
4552
client.setCleanSession(true);
46-
client.setWill(String(baseTopic + MQTT_LWT_TOPIC).c_str(), MQTT_LWT_QOS, MQTT_LWT_RETAIN, MQTT_LWT_PAYLOAD_OFFLINE);
53+
client.setWill(lastWillTopic.c_str(), MQTT_LWT_QOS, MQTT_LWT_RETAIN, MQTT_LWT_PAYLOAD_OFFLINE);
4754
client.setKeepAlive(MQTT_RECONNECT_DELAY * 3);
48-
4955
this->registerHandlers();
56+
5057
}
5158

5259
void debug(const char *message)
@@ -128,6 +135,7 @@ class MqttPublisher
128135
DEBUG(F("MQTT: Connecting to broker..."));
129136
client.connect();
130137
}
138+
131139
void disconnect()
132140
{
133141
if (!this->connected)
@@ -137,15 +145,16 @@ class MqttPublisher
137145
}
138146
DEBUG(F("MQTT: Disconnecting from broker..."));
139147
client.disconnect();
148+
this->reconnectTimer.detach();
140149
}
141150

142151
private:
143152
bool connected = false;
144153
MqttConfig config;
145-
WiFiClient net;
146-
PangolinMQTT client;
154+
AsyncMqttClient client;
147155
Ticker reconnectTimer;
148156
String baseTopic;
157+
String lastWillTopic;
149158

150159
void publish(const String &topic, const String &payload, uint8_t qos=0, bool retain=false)
151160
{
@@ -167,77 +176,31 @@ class MqttPublisher
167176
{
168177
DEBUG(F("MQTT: Publishing to %s:"), topic);
169178
DEBUG(F("%s\n"), payload);
170-
client.publish(topic, payload, strlen(payload), qos, retain);
179+
client.publish(topic, qos, retain, payload, strlen(payload));
171180
}
172181
}
173182

174183
void registerHandlers()
175184
{
185+
176186
client.onConnect([this](bool sessionPresent) {
177187
this->connected = true;
178-
reconnectTimer.detach();
179-
DEBUG(F("MQTT client connection established."));
188+
this->reconnectTimer.detach();
189+
DEBUG(F("MQTT: Connection established."));
180190
char message[64];
181191
snprintf(message, 64, "Hello from %08X, running SMLReader version %s.", ESP.getChipId(), VERSION);
182192
info(message);
183193
publish(baseTopic + MQTT_LWT_TOPIC, MQTT_LWT_PAYLOAD_ONLINE, MQTT_LWT_QOS, MQTT_LWT_RETAIN);
184194
});
185-
client.onDisconnect([this](int8_t reason) {
195+
client.onDisconnect([this](AsyncMqttClientDisconnectReason reason) {
186196
this->connected = false;
187-
DEBUG("MQTT client disconnected with reason=%d", reason);
197+
DEBUG(F("MQTT: Disconnected. Reason: %d."), reason);
188198
reconnectTimer.attach(MQTT_RECONNECT_DELAY, [this]() {
189-
this->connect();
199+
if (WiFi.isConnected()) {
200+
this->connect();
201+
}
190202
});
191203
});
192-
client.onError([this](uint8_t e, uint32_t info) {
193-
switch (e)
194-
{
195-
case TCP_DISCONNECTED:
196-
// usually because your structure is wrong and you called a function before onMqttConnect
197-
DEBUG(F("MQTT: NOT CONNECTED info=%d"), info);
198-
break;
199-
case MQTT_SERVER_UNAVAILABLE:
200-
// server has gone away - network problem? server crash?
201-
DEBUG(F("MQTT: MQTT_SERVER_UNAVAILABLE info=%d"), info);
202-
break;
203-
case UNRECOVERABLE_CONNECT_FAIL:
204-
// there is something wrong with your connection parameters? IP:port incorrect? user credentials typo'd?
205-
DEBUG(F("MQTT: UNRECOVERABLE_CONNECT_FAIL info=%d"), info);
206-
break;
207-
case TLS_BAD_FINGERPRINT:
208-
DEBUG(F("MQTT: TLS_BAD_FINGERPRINT info=%d"), info);
209-
break;
210-
case SUBSCRIBE_FAIL:
211-
// you tried to subscribe to an invalid topic
212-
DEBUG(F("MQTT: SUBSCRIBE_FAIL info=%d"), info);
213-
break;
214-
case INBOUND_QOS_ACK_FAIL:
215-
DEBUG(F("MQTT: OUTBOUND_QOS_ACK_FAIL id=%d"), info);
216-
break;
217-
case OUTBOUND_QOS_ACK_FAIL:
218-
DEBUG(F("MQTT: OUTBOUND_QOS_ACK_FAIL id=%d"), info);
219-
break;
220-
case INBOUND_PUB_TOO_BIG:
221-
// someone sent you a p[acket that this MCU does not have enough FLASH to handle
222-
DEBUG(F("MQTT: INBOUND_PUB_TOO_BIG size=%d Max=%d"), info, client.getMaxPayloadSize());
223-
break;
224-
case OUTBOUND_PUB_TOO_BIG:
225-
// you tried to send a packet that this MCU does not have enough FLASH to handle
226-
DEBUG(F("MQTT: OUTBOUND_PUB_TOO_BIG size=%d Max=%d"), info, client.getMaxPayloadSize());
227-
break;
228-
case BOGUS_PACKET: // Your server sent a control packet type unknown to MQTT 3.1.1
229-
// 99.99% unlikely to ever happen, but this message is better than a crash, non?
230-
DEBUG(F("MQTT: BOGUS_PACKET info=%02x"), info);
231-
break;
232-
case X_INVALID_LENGTH: // An x function rcvd a msg with an unexpected length: probale data corruption or malicious msg
233-
// 99.99% unlikely to ever happen, but this message is better than a crash, non?
234-
DEBUG(F("MQTT: X_INVALID_LENGTH info=%02x"), info);
235-
break;
236-
default:
237-
DEBUG(F("MQTT: UNKNOWN ERROR: %u extra info %d"), e, info);
238-
break;
239-
}
240-
});
241204
}
242205
};
243206

src/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "Arduino.h"
55
#include "Sensor.h"
66

7-
const char *VERSION = "2.2.1";
7+
const char *VERSION = "2.3.0";
88

99
// Modifying the config version will probably cause a loss of the existig configuration.
1010
// Be careful!

src/main.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,32 @@
77
#include "MqttPublisher.h"
88
#include "EEPROM.h"
99
#include <ESP8266WiFi.h>
10+
#include <ESP8266WebServer.h>
11+
#include <ESP8266HTTPUpdateServer.h>
1012

11-
std::list<Sensor*> *sensors = new std::list<Sensor*>();
13+
std::list<Sensor *> *sensors = new std::list<Sensor *>();
1214

1315
void wifiConnected();
1416
void configSaved();
1517

1618
DNSServer dnsServer;
1719
WebServer server(80);
18-
HTTPUpdateServer httpUpdater;
20+
ESP8266HTTPUpdateServer httpUpdater;
1921
WiFiClient net;
2022

2123
MqttConfig mqttConfig;
2224
MqttPublisher publisher;
2325

2426
IotWebConf iotWebConf(WIFI_AP_SSID, &dnsServer, &server, WIFI_AP_DEFAULT_PASSWORD, CONFIG_VERSION);
25-
IotWebConfParameter params[] = {
26-
IotWebConfParameter("MQTT server", "mqttServer", mqttConfig.server, sizeof(mqttConfig.server), "text", NULL, mqttConfig.server, NULL, true),
27-
IotWebConfParameter("MQTT port", "mqttPort", mqttConfig.port, sizeof(mqttConfig.port), "text", NULL, mqttConfig.port, NULL, true),
28-
IotWebConfParameter("MQTT username", "mqttUsername", mqttConfig.username, sizeof(mqttConfig.username), "text", NULL, mqttConfig.username, NULL, true),
29-
IotWebConfParameter("MQTT password", "mqttPassword", mqttConfig.password, sizeof(mqttConfig.password), "password", NULL, mqttConfig.password, NULL, true),
30-
IotWebConfParameter("MQTT topic", "mqttTopic", mqttConfig.topic, sizeof(mqttConfig.topic), "text", NULL, mqttConfig.topic, NULL, true)};
3127

32-
boolean needReset = false;
33-
boolean connected = false;
28+
iotwebconf::TextParameter mqttServerParam = iotwebconf::TextParameter("MQTT server", "mqttServer", mqttConfig.server, sizeof(mqttConfig.server), nullptr, mqttConfig.server);
29+
iotwebconf::NumberParameter mqttPortParam = iotwebconf::NumberParameter("MQTT port", "mqttPort", mqttConfig.port, sizeof(mqttConfig.port), nullptr, mqttConfig.port);
30+
iotwebconf::TextParameter mqttUsernameParam = iotwebconf::TextParameter("MQTT username", "mqttUsername", mqttConfig.username, sizeof(mqttConfig.username), nullptr, mqttConfig.username);
31+
iotwebconf::PasswordParameter mqttPasswordParam = iotwebconf::PasswordParameter("MQTT password", "mqttPassword", mqttConfig.password, sizeof(mqttConfig.password), nullptr, mqttConfig.password);
32+
iotwebconf::TextParameter mqttTopicParam = iotwebconf::TextParameter("MQTT topic", "mqttTopic", mqttConfig.topic, sizeof(mqttConfig.topic), nullptr, mqttConfig.topic);
33+
iotwebconf::ParameterGroup paramGroup = iotwebconf::ParameterGroup("MQTT Settings", "");
3434

35+
boolean needReset = false;
3536

3637
void process_message(byte *buffer, size_t len, Sensor *sensor)
3738
{
@@ -58,7 +59,7 @@ void setup()
5859

5960
// Setup reading heads
6061
DEBUG("Setting up %d configured sensors...", NUM_OF_SENSORS);
61-
const SensorConfig *config = SENSOR_CONFIGS;
62+
const SensorConfig *config = SENSOR_CONFIGS;
6263
for (uint8_t i = 0; i < NUM_OF_SENSORS; i++, config++)
6364
{
6465
Sensor *sensor = new Sensor(config, process_message);
@@ -70,34 +71,42 @@ void setup()
7071
// Setup WiFi and config stuff
7172
DEBUG("Setting up WiFi and config stuff.");
7273

73-
for (uint8_t i = 0; i < sizeof(params) / sizeof(params[0]); i++)
74-
{
75-
DEBUG("Adding parameter %s.", params[i].label);
76-
iotWebConf.addParameter(&params[i]);
77-
}
74+
paramGroup.addItem(&mqttServerParam);
75+
paramGroup.addItem(&mqttPortParam);
76+
paramGroup.addItem(&mqttUsernameParam);
77+
paramGroup.addItem(&mqttPasswordParam);
78+
paramGroup.addItem(&mqttTopicParam);
79+
80+
iotWebConf.addParameterGroup(&paramGroup);
81+
7882
iotWebConf.setConfigSavedCallback(&configSaved);
7983
iotWebConf.setWifiConnectionCallback(&wifiConnected);
80-
iotWebConf.setupUpdateServer(&httpUpdater);
84+
85+
86+
WiFi.onStationModeDisconnected([](const WiFiEventStationModeDisconnected& event) {
87+
publisher.disconnect();
88+
});
89+
90+
// -- Define how to handle updateServer calls.
91+
iotWebConf.setupUpdateServer(
92+
[](const char *updatePath)
93+
{ httpUpdater.setup(&server, updatePath); },
94+
[](const char *userName, char *password)
95+
{ httpUpdater.updateCredentials(userName, password); });
8196

8297
boolean validConfig = iotWebConf.init();
8398
if (!validConfig)
8499
{
85100
DEBUG("Missing or invalid config. MQTT publisher disabled.");
86-
MqttConfig defaults;
87-
// Resetting to default values
88-
strcpy(mqttConfig.server, defaults.server);
89-
strcpy(mqttConfig.port, defaults.port);
90-
strcpy(mqttConfig.username, defaults.username);
91-
strcpy(mqttConfig.password, defaults.password);
92-
strcpy(mqttConfig.topic, defaults.topic);
93101
}
94102
else
95103
{
96104
// Setup MQTT publisher
97105
publisher.setup(mqttConfig);
98106
}
99107

100-
server.on("/", [] { iotWebConf.handleConfig(); });
108+
server.on("/", []() { iotWebConf.handleConfig(); });
109+
server.on("/reset", []() { needReset = true; });
101110
server.onNotFound([]() { iotWebConf.handleNotFound(); });
102111

103112
DEBUG("Setup done.");
@@ -130,6 +139,5 @@ void configSaved()
130139
void wifiConnected()
131140
{
132141
DEBUG("WiFi connection established.");
133-
connected = true;
134142
publisher.connect();
135143
}

0 commit comments

Comments
 (0)