Skip to content

Commit b8b99c6

Browse files
authored
Add Wifi and mqtt broker configuration over MQTT commands (#971)
- Adds MQTT command to change the WiFi access point. - Adds MQTT command to change the MQTT broker and update username and password. This will test the connection changes first and, if unsuccessful, fallback to the current connection. If successful the new configuration will be saved in non-volatile memory.
1 parent 31efcb3 commit b8b99c6

File tree

2 files changed

+156
-31
lines changed

2 files changed

+156
-31
lines changed

docs/use/gateway.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,31 @@ If you want the settings to be kept upon gateway restart, you can publish the co
3333
Auto discovery is enable by default on release binaries, on platformio (except for UNO). With Arduino IDE please read the [advanced configuration section](../upload/advanced-configuration#auto-discovery) of the documentation.
3434
:::
3535

36+
## Change the WiFi credentials
37+
38+
`mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m '{"wifi_ssid":"ssid", "wifi_pass":"password"}'`
39+
40+
::: tip
41+
If the new connection fails the gateway will fallback to the previous connection.
42+
:::
43+
44+
## Change the MQTT broker credentials
45+
```
46+
mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m
47+
'{
48+
"mqtt_user": "user_name",
49+
"mqtt_pass": "password",
50+
"mqtt_server": "host",
51+
"mqtt_port": "port",
52+
"mqtt_secure": "false"
53+
}'
54+
```
55+
::: tip
56+
Server, port, and secure_flag are only required if changing connection to another broker.
57+
If the new connection fails the gateway will fallback to the previous connection.
58+
:::
59+
60+
3661
# Firmware update from MQTT (ESP only)
3762

3863
The gateway can be updated through an MQTT message by providing a JSON formatted message with a version number, OTA password (optional, see below), and URL to fetch the update from.

main/main.ino

Lines changed: 131 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ bool to_bool(String const& s) { // thanks Chris Jester-Young from stackoverflow
272272
}
273273

274274
void pub(const char* topicori, const char* payload, bool retainFlag) {
275-
String topic = String(mqtt_topic) + String(topicori);
275+
String topic = String(mqtt_topic) + String(gateway_name) + String(topicori);
276276
pubMQTT(topic.c_str(), payload, retainFlag);
277277
}
278278

@@ -281,7 +281,7 @@ void pub(const char* topicori, JsonObject& data) {
281281
digitalWrite(LED_RECEIVE, LED_RECEIVE_ON);
282282
logJson(data);
283283
if (client.connected()) {
284-
String topic = String(mqtt_topic) + String(topicori);
284+
String topic = String(mqtt_topic) + String(gateway_name) + String(topicori);
285285
#ifdef valueAsASubject
286286
# ifdef ZgatewayPilight
287287
String value = data["value"];
@@ -337,7 +337,7 @@ void pub(const char* topicori, JsonObject& data) {
337337

338338
void pub(const char* topicori, const char* payload) {
339339
if (client.connected()) {
340-
String topic = String(mqtt_topic) + String(topicori);
340+
String topic = String(mqtt_topic) + String(gateway_name) + String(topicori);
341341
Log.trace(F("Pub ack %s into: %s" CR), payload, topic.c_str());
342342
pubMQTT(topic, payload);
343343
} else {
@@ -460,6 +460,7 @@ void logJson(JsonObject& jsondata) {
460460
bool cmpToMainTopic(const char* topicOri, const char* toAdd) {
461461
char topic[mqtt_topic_max_size];
462462
strcpy(topic, mqtt_topic);
463+
strcat(topic, gateway_name);
463464
strcat(topic, toAdd);
464465
if (strstr(topicOri, topic) != NULL) {
465466
return true;
@@ -478,6 +479,7 @@ void connectMQTT() {
478479
Log.warning(F("MQTT connection..." CR));
479480
char topic[mqtt_topic_max_size];
480481
strcpy(topic, mqtt_topic);
482+
strcat(topic, gateway_name);
481483
strcat(topic, will_Topic);
482484
client.setBufferSize(mqtt_max_packet_size);
483485
if (client.connect(gateway_name, mqtt_user, mqtt_pass, topic, will_QoS, will_Retain, will_Message)) {
@@ -494,6 +496,7 @@ void connectMQTT() {
494496
//Subscribing to topic
495497
char topic2[mqtt_topic_max_size];
496498
strcpy(topic2, mqtt_topic);
499+
strcat(topic2, gateway_name);
497500
strcat(topic2, subjectMQTTtoX);
498501
if (client.subscribe(topic2)) {
499502
#ifdef ZgatewayRF
@@ -545,10 +548,6 @@ void callback(char* topic, byte* payload, unsigned int length) {
545548
free(p);
546549
}
547550

548-
void setup_parameters() {
549-
strcat(mqtt_topic, gateway_name);
550-
}
551-
552551
void setup() {
553552
//Launch serial for debugging purposes
554553
Serial.begin(SERIAL_BAUD);
@@ -623,8 +622,6 @@ void setup() {
623622
client.setServer(mqtt_server, port);
624623
#endif
625624

626-
setup_parameters();
627-
628625
client.setCallback(callback);
629626

630627
delay(1500);
@@ -961,6 +958,29 @@ void eraseAndRestart() {
961958
# endif
962959
}
963960

961+
void saveMqttConfig() {
962+
Log.trace(F("saving config" CR));
963+
DynamicJsonBuffer jsonBuffer;
964+
JsonObject& json = jsonBuffer.createObject();
965+
json["mqtt_server"] = mqtt_server;
966+
json["mqtt_port"] = mqtt_port;
967+
json["mqtt_user"] = mqtt_user;
968+
json["mqtt_pass"] = mqtt_pass;
969+
json["mqtt_topic"] = mqtt_topic;
970+
json["gateway_name"] = gateway_name;
971+
json["mqtt_broker_secure"] = mqtt_secure;
972+
json["mqtt_broker_cert"] = mqtt_cert;
973+
974+
File configFile = SPIFFS.open("/config.json", "w");
975+
if (!configFile) {
976+
Log.error(F("failed to open config file for writing" CR));
977+
}
978+
979+
json.printTo(Serial);
980+
json.printTo(configFile);
981+
configFile.close();
982+
}
983+
964984
void setup_wifimanager(bool reset_settings) {
965985
# ifdef TRIGGER_GPIO
966986
pinMode(TRIGGER_GPIO, INPUT_PULLUP);
@@ -1128,27 +1148,7 @@ void setup_wifimanager(bool reset_settings) {
11281148
}
11291149

11301150
//save the custom parameters to FS
1131-
Log.trace(F("saving config" CR));
1132-
DynamicJsonBuffer jsonBuffer;
1133-
JsonObject& json = jsonBuffer.createObject();
1134-
json["mqtt_server"] = mqtt_server;
1135-
json["mqtt_port"] = mqtt_port;
1136-
json["mqtt_user"] = mqtt_user;
1137-
json["mqtt_pass"] = mqtt_pass;
1138-
json["mqtt_topic"] = mqtt_topic;
1139-
json["gateway_name"] = gateway_name;
1140-
json["mqtt_secure"] = mqtt_secure;
1141-
json["mqtt_cert"] = mqtt_cert;
1142-
1143-
File configFile = SPIFFS.open("/config.json", "w");
1144-
if (!configFile) {
1145-
Log.error(F("failed to open config file for writing" CR));
1146-
}
1147-
1148-
json.printTo(Serial);
1149-
json.printTo(configFile);
1150-
configFile.close();
1151-
//end save
1151+
saveMqttConfig();
11521152
}
11531153
}
11541154
# ifdef ESP32_ETHERNET
@@ -1809,7 +1809,107 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
18091809
stateMeasures();
18101810
}
18111811
}
1812+
1813+
if (SYSdata.containsKey("wifi_ssid") && SYSdata.containsKey("wifi_pass")) {
1814+
# if defined(ZgatewayBT) && defined(ESP32)
1815+
stopProcessing();
1816+
# endif
1817+
String prev_ssid = WiFi.SSID();
1818+
String prev_pass = WiFi.psk();
1819+
client.disconnect();
1820+
WiFi.disconnect(true);
1821+
1822+
Log.warning(F("Attempting connection to new AP" CR));
1823+
WiFi.begin((const char*)SYSdata["wifi_ssid"], (const char*)SYSdata["wifi_pass"]);
1824+
WiFi.waitForConnectResult();
1825+
1826+
if (WiFi.status() != WL_CONNECTED) {
1827+
Log.error(F("Failed to connect to new AP; falling back" CR));
1828+
WiFi.disconnect(true);
1829+
WiFi.begin(prev_ssid.c_str(), prev_pass.c_str());
1830+
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
1831+
# if defined(ESP8266)
1832+
ESP.reset();
1833+
# else
1834+
ESP.restart();
1835+
# endif
1836+
}
1837+
}
1838+
# if defined(ZgatewayBT) && defined(ESP32)
1839+
startProcessing();
1840+
# endif
1841+
}
1842+
1843+
if (SYSdata.containsKey("mqtt_user") && SYSdata.containsKey("mqtt_pass")) {
1844+
# if defined(ZgatewayBT) && defined(ESP32)
1845+
stopProcessing();
1846+
# endif
1847+
client.disconnect();
1848+
bool update_server = false;
1849+
void* prev_client = nullptr;
1850+
1851+
if (SYSdata.containsKey("mqtt_server") && SYSdata.containsKey("mqtt_port")) {
1852+
if (!SYSdata.containsKey("mqtt_secure")) {
1853+
Log.warning(F("mqtt_server provided without mqtt_secure defined - ignoring command" CR));
1854+
return;
1855+
}
1856+
update_server = true;
1857+
1858+
if (SYSdata.get<bool>("mqtt_secure") != mqtt_secure) {
1859+
prev_client = eClient;
1860+
if (!mqtt_secure) {
1861+
eClient = new WiFiClientSecure;
1862+
setupTLS();
1863+
} else {
1864+
Log.warning(F("Switching to unsecure MQTT broker" CR));
1865+
eClient = new WiFiClient;
1866+
}
1867+
1868+
client.setClient(*(Client*)eClient);
1869+
}
1870+
1871+
client.setServer(SYSdata.get<const char*>("mqtt_server"), SYSdata.get<unsigned int>("mqtt_port"));
1872+
}
1873+
1874+
String prev_user = mqtt_user;
1875+
String prev_pass = mqtt_pass;
1876+
strcpy(mqtt_user, SYSdata["mqtt_user"]);
1877+
strcpy(mqtt_pass, SYSdata["mqtt_pass"]);
1878+
1879+
connectMQTT();
1880+
1881+
if (client.connected()) {
1882+
if (update_server) {
1883+
strcpy(mqtt_server, SYSdata["mqtt_server"]);
1884+
strcpy(mqtt_port, SYSdata["mqtt_port"]);
1885+
if (prev_client != nullptr) {
1886+
mqtt_secure = !mqtt_secure;
1887+
delete prev_client;
1888+
}
1889+
}
1890+
# ifndef ESPWifiManualSetup
1891+
saveMqttConfig();
1892+
# endif
1893+
} else {
1894+
if (update_server) {
1895+
if (prev_client != nullptr) {
1896+
delete eClient;
1897+
eClient = prev_client;
1898+
client.setClient(*(Client*)eClient);
1899+
}
1900+
uint16_t port = strtol(mqtt_port, NULL, 10);
1901+
client.setServer(mqtt_server, port);
1902+
}
1903+
strcpy(mqtt_user, prev_user.c_str());
1904+
strcpy(mqtt_pass, prev_pass.c_str());
1905+
connectMQTT();
1906+
}
1907+
# if defined(ZgatewayBT) && defined(ESP32)
1908+
startProcessing();
1909+
# endif
1910+
}
18121911
#endif
1912+
18131913
#ifdef ZmqttDiscovery
18141914
if (SYSdata.containsKey("discovery")) {
18151915
if (SYSdata.is<bool>("discovery")) {
@@ -1852,4 +1952,4 @@ String toString(uint32_t input) {
18521952
return result;
18531953
}
18541954
# endif
1855-
#endif
1955+
#endif

0 commit comments

Comments
 (0)