Skip to content

Commit

Permalink
Add Wifi and mqtt broker configuration over MQTT commands (#971)
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
h2zero authored Jun 5, 2021
1 parent 31efcb3 commit b8b99c6
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 31 deletions.
25 changes: 25 additions & 0 deletions docs/use/gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,31 @@ If you want the settings to be kept upon gateway restart, you can publish the co
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.
:::

## Change the WiFi credentials

`mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m '{"wifi_ssid":"ssid", "wifi_pass":"password"}'`

::: tip
If the new connection fails the gateway will fallback to the previous connection.
:::

## Change the MQTT broker credentials
```
mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m
'{
"mqtt_user": "user_name",
"mqtt_pass": "password",
"mqtt_server": "host",
"mqtt_port": "port",
"mqtt_secure": "false"
}'
```
::: tip
Server, port, and secure_flag are only required if changing connection to another broker.
If the new connection fails the gateway will fallback to the previous connection.
:::


# Firmware update from MQTT (ESP only)

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.
Expand Down
162 changes: 131 additions & 31 deletions main/main.ino
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ bool to_bool(String const& s) { // thanks Chris Jester-Young from stackoverflow
}

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

Expand All @@ -281,7 +281,7 @@ void pub(const char* topicori, JsonObject& data) {
digitalWrite(LED_RECEIVE, LED_RECEIVE_ON);
logJson(data);
if (client.connected()) {
String topic = String(mqtt_topic) + String(topicori);
String topic = String(mqtt_topic) + String(gateway_name) + String(topicori);
#ifdef valueAsASubject
# ifdef ZgatewayPilight
String value = data["value"];
Expand Down Expand Up @@ -337,7 +337,7 @@ void pub(const char* topicori, JsonObject& data) {

void pub(const char* topicori, const char* payload) {
if (client.connected()) {
String topic = String(mqtt_topic) + String(topicori);
String topic = String(mqtt_topic) + String(gateway_name) + String(topicori);
Log.trace(F("Pub ack %s into: %s" CR), payload, topic.c_str());
pubMQTT(topic, payload);
} else {
Expand Down Expand Up @@ -460,6 +460,7 @@ void logJson(JsonObject& jsondata) {
bool cmpToMainTopic(const char* topicOri, const char* toAdd) {
char topic[mqtt_topic_max_size];
strcpy(topic, mqtt_topic);
strcat(topic, gateway_name);
strcat(topic, toAdd);
if (strstr(topicOri, topic) != NULL) {
return true;
Expand All @@ -478,6 +479,7 @@ void connectMQTT() {
Log.warning(F("MQTT connection..." CR));
char topic[mqtt_topic_max_size];
strcpy(topic, mqtt_topic);
strcat(topic, gateway_name);
strcat(topic, will_Topic);
client.setBufferSize(mqtt_max_packet_size);
if (client.connect(gateway_name, mqtt_user, mqtt_pass, topic, will_QoS, will_Retain, will_Message)) {
Expand All @@ -494,6 +496,7 @@ void connectMQTT() {
//Subscribing to topic
char topic2[mqtt_topic_max_size];
strcpy(topic2, mqtt_topic);
strcat(topic2, gateway_name);
strcat(topic2, subjectMQTTtoX);
if (client.subscribe(topic2)) {
#ifdef ZgatewayRF
Expand Down Expand Up @@ -545,10 +548,6 @@ void callback(char* topic, byte* payload, unsigned int length) {
free(p);
}

void setup_parameters() {
strcat(mqtt_topic, gateway_name);
}

void setup() {
//Launch serial for debugging purposes
Serial.begin(SERIAL_BAUD);
Expand Down Expand Up @@ -623,8 +622,6 @@ void setup() {
client.setServer(mqtt_server, port);
#endif

setup_parameters();

client.setCallback(callback);

delay(1500);
Expand Down Expand Up @@ -961,6 +958,29 @@ void eraseAndRestart() {
# endif
}

void saveMqttConfig() {
Log.trace(F("saving config" CR));
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["mqtt_server"] = mqtt_server;
json["mqtt_port"] = mqtt_port;
json["mqtt_user"] = mqtt_user;
json["mqtt_pass"] = mqtt_pass;
json["mqtt_topic"] = mqtt_topic;
json["gateway_name"] = gateway_name;
json["mqtt_broker_secure"] = mqtt_secure;
json["mqtt_broker_cert"] = mqtt_cert;

File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Log.error(F("failed to open config file for writing" CR));
}

json.printTo(Serial);
json.printTo(configFile);
configFile.close();
}

void setup_wifimanager(bool reset_settings) {
# ifdef TRIGGER_GPIO
pinMode(TRIGGER_GPIO, INPUT_PULLUP);
Expand Down Expand Up @@ -1128,27 +1148,7 @@ void setup_wifimanager(bool reset_settings) {
}

//save the custom parameters to FS
Log.trace(F("saving config" CR));
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["mqtt_server"] = mqtt_server;
json["mqtt_port"] = mqtt_port;
json["mqtt_user"] = mqtt_user;
json["mqtt_pass"] = mqtt_pass;
json["mqtt_topic"] = mqtt_topic;
json["gateway_name"] = gateway_name;
json["mqtt_secure"] = mqtt_secure;
json["mqtt_cert"] = mqtt_cert;

File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Log.error(F("failed to open config file for writing" CR));
}

json.printTo(Serial);
json.printTo(configFile);
configFile.close();
//end save
saveMqttConfig();
}
}
# ifdef ESP32_ETHERNET
Expand Down Expand Up @@ -1809,7 +1809,107 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
stateMeasures();
}
}

if (SYSdata.containsKey("wifi_ssid") && SYSdata.containsKey("wifi_pass")) {
# if defined(ZgatewayBT) && defined(ESP32)
stopProcessing();
# endif
String prev_ssid = WiFi.SSID();
String prev_pass = WiFi.psk();
client.disconnect();
WiFi.disconnect(true);

Log.warning(F("Attempting connection to new AP" CR));
WiFi.begin((const char*)SYSdata["wifi_ssid"], (const char*)SYSdata["wifi_pass"]);
WiFi.waitForConnectResult();

if (WiFi.status() != WL_CONNECTED) {
Log.error(F("Failed to connect to new AP; falling back" CR));
WiFi.disconnect(true);
WiFi.begin(prev_ssid.c_str(), prev_pass.c_str());
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
# if defined(ESP8266)
ESP.reset();
# else
ESP.restart();
# endif
}
}
# if defined(ZgatewayBT) && defined(ESP32)
startProcessing();
# endif
}

if (SYSdata.containsKey("mqtt_user") && SYSdata.containsKey("mqtt_pass")) {
# if defined(ZgatewayBT) && defined(ESP32)
stopProcessing();
# endif
client.disconnect();
bool update_server = false;
void* prev_client = nullptr;

if (SYSdata.containsKey("mqtt_server") && SYSdata.containsKey("mqtt_port")) {
if (!SYSdata.containsKey("mqtt_secure")) {
Log.warning(F("mqtt_server provided without mqtt_secure defined - ignoring command" CR));
return;
}
update_server = true;

if (SYSdata.get<bool>("mqtt_secure") != mqtt_secure) {
prev_client = eClient;
if (!mqtt_secure) {
eClient = new WiFiClientSecure;
setupTLS();
} else {
Log.warning(F("Switching to unsecure MQTT broker" CR));
eClient = new WiFiClient;
}

client.setClient(*(Client*)eClient);
}

client.setServer(SYSdata.get<const char*>("mqtt_server"), SYSdata.get<unsigned int>("mqtt_port"));
}

String prev_user = mqtt_user;
String prev_pass = mqtt_pass;
strcpy(mqtt_user, SYSdata["mqtt_user"]);
strcpy(mqtt_pass, SYSdata["mqtt_pass"]);

connectMQTT();

if (client.connected()) {
if (update_server) {
strcpy(mqtt_server, SYSdata["mqtt_server"]);
strcpy(mqtt_port, SYSdata["mqtt_port"]);
if (prev_client != nullptr) {
mqtt_secure = !mqtt_secure;
delete prev_client;
}
}
# ifndef ESPWifiManualSetup
saveMqttConfig();
# endif
} else {
if (update_server) {
if (prev_client != nullptr) {
delete eClient;
eClient = prev_client;
client.setClient(*(Client*)eClient);
}
uint16_t port = strtol(mqtt_port, NULL, 10);
client.setServer(mqtt_server, port);
}
strcpy(mqtt_user, prev_user.c_str());
strcpy(mqtt_pass, prev_pass.c_str());
connectMQTT();
}
# if defined(ZgatewayBT) && defined(ESP32)
startProcessing();
# endif
}
#endif

#ifdef ZmqttDiscovery
if (SYSdata.containsKey("discovery")) {
if (SYSdata.is<bool>("discovery")) {
Expand Down Expand Up @@ -1852,4 +1952,4 @@ String toString(uint32_t input) {
return result;
}
# endif
#endif
#endif

0 comments on commit b8b99c6

Please sign in to comment.