From b5520f13ba3875ec1d72354529f4ed74242372c3 Mon Sep 17 00:00:00 2001 From: Gregor Baues Date: Wed, 19 May 2021 15:31:30 +0200 Subject: [PATCH] Broker handling / connection updated --- MQTTBrokers.h | 47 +++++++++++++++++++++------------ MQTTInterface.cpp | 66 +++++++++++++++++++++++++++++++++++++---------- MQTTInterface.h | 52 ++++++++++++++++++++++++++++++++----- Queue.h | 17 +++++++++++- config.example.h | 21 ++++++++++++++- 5 files changed, 165 insertions(+), 38 deletions(-) diff --git a/MQTTBrokers.h b/MQTTBrokers.h index aa48960..3e6d7af 100644 --- a/MQTTBrokers.h +++ b/MQTTBrokers.h @@ -1,27 +1,42 @@ + +/* + * © 2021, Gregor Baues, All rights reserved. + * + * This file is part of DCC-EX/CommandStation-EX + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * It is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CommandStation. If not, see . + * + */ #ifndef _MQTTBrokers_h_ #define _MQTTBrokers_h_ -// Define Broker configurations; Values are provided in the following order -// MQTT_BROKER_PORT 9883 -// MQTT_BROKER_DOMAIN "dcclms.modelrailroad.ovh" -// MQTT_BROKER_ADDRESS 51, 210, 151, 143 -// MQTT_BROKER_USER "dcccs" -// MQTT_BROKER_PASSWD "dcccs$3020" -// MQTT_BROKER_CLIENTID_PREFIX "dcc$lms-" +// Defines preconfigured mqtt broker configurations -// Local server no user / pwd / prefix required -// EthernetShields / Arduino do not support securte transport i.e. on either port 443 or 8883 for MQTTS on most broker installations +// EthernetShields / Arduino do not support secure transport i.e. on either port 443 or 8883 for MQTTS on most broker installations // Once we support the ESP / Wifi as Transport medium we may get TLS capabilities for data in transit i.e. can use the 443/8883 ports -#define LOCAL_MQTT_BROKER F("LOCALMQ"), new MQTTBroker( 1883, {192, 168, 0, 51}, F("my.local.server")) -// Local server with user / pwd and no prefix -#define LOCAL_MQTT_USER_BROKER F("LOCALMQ"), new MQTTBroker( 1883, {192, 168, 0, 51}, F("my.local.server"), F("myuser"), F("mypassword")) -// Cloud server -#define DCCEX_MQTT_BROKER F("DCCEXMQ"), new MQTTBroker( 9883, {51, 210, 151, 143}, F("dcclms.modelrailroad.ovh"), F("dcccs"), F("dcccs$3020"), F("dcc$lms-")) -// Cloud server -#define DCCEX_MQTT_DOMAIN_BROKER F("DCCEXMQ"), new MQTTBroker( 9883, F("dcclms.modelrailroad.ovh"), F("dcccs"), F("dcccs$3020"), F("dcc$lms-")) + + +#define MQPWD F(MQTT_PWD) +#define MQUID F(MQTT_USER) +#define MQPREFIX F(MQTT_PREFIX) + +// Cloud server provided by the DccEX team for testing purposes; apply for a uid/pwd on discord +#define DCCEX_MQTT_BROKER F("DccexMQ"), new MQTTBroker( 9883, F("dcclms.modelrailroad.ovh"), MQUID, MQPWD, MQPREFIX) // Mosquitto test server #define DCCEX_MOSQUITTO F("Mosquitto"), new MQTTBroker(1883, F("test.mosquitto.org")) // HiveMQ test server #define DCCEX_HIVEMQ F("HiveMQ"), new MQTTBroker(1883, F("broker.hivemq.com")) + #endif \ No newline at end of file diff --git a/MQTTInterface.cpp b/MQTTInterface.cpp index 1f48ae7..af9d25a 100644 --- a/MQTTInterface.cpp +++ b/MQTTInterface.cpp @@ -1,3 +1,23 @@ +/* + * © 2021, Gregor Baues, All rights reserved. + * + * This file is part of DCC-EX/CommandStation-EX + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * It is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CommandStation. If not, see . + * + */ + #if __has_include("config.h") #include "config.h" #else @@ -274,9 +294,9 @@ void MQTTInterface::connect() switch (broker->cType) { // no uid no pwd - case 6: case 1: { // port(p), ip(i), domain(d), + DIAG(F("MQTT Broker connecting anonymous ...")); if (mqttClient->connect(connectID)) { DIAG(F("MQTT Broker connected ...")); @@ -288,24 +308,37 @@ void MQTTInterface::connect() else { DIAG(F("MQTT broker connection failed, rc=%d, trying to reconnect"), mqttClient->state()); - mqState = CONNECTION_FAILED; reconnectCount++; } break; } // with uid passwd - case 5: case 2: - { // port(p), ip(i), domain(d), user(uid), pwd(pass), - break; - } - // with uid, passwd & prefix - case 4: - case 3: - { // port(p), ip(i), domain(d), user(uid), pwd(pass), prefix(pfix) - // port(p), domain(d), user(uid), pwd(pass), prefix(pfix) - // mqttClient.connect(connectID, MQTT_BROKER_USER, MQTT_BROKER_PASSWD, "$connected", 0, true, "0", 0)) - break; + { + DIAG(F("MQTT Broker connecting with uid/pwd ...")); + char user[strlen_P((const char *) broker->user)]; + char pwd[strlen_P((const char *) broker->pwd)]; + + // need to copy from progmem to lacal + strcpy_P(user, (const char *)broker->user); + strcpy_P(pwd, (const char *)broker->pwd); + + if (mqttClient->connect(connectID, user, pwd)) + { + DIAG(F("MQTT Broker connected ...")); + auto sub = subscribe(clientID); // set up the main subscription on which we will recieve the intal mi message from a subscriber + if (Diag::MQTT) + DIAG(F("MQTT subscriptons %s..."), sub ? "ok" : "failed"); + mqState = CONNECTED; + } + else + { + DIAG(F("MQTT broker connection failed, rc=%d, trying to reconnect"), mqttClient->state()); + reconnectCount++; + } + break; + // ! add last will messages for the client + // (connectID, MQTT_BROKER_USER, MQTT_BROKER_PASSWD, "$connected", 0, true, "0", 0)) } } if (reconnectCount == MAXRECONNECT) @@ -500,12 +533,17 @@ void MQTTInterface::loop() singleton->loop2(); } + +bool showonce = false; void MQTTInterface::loop2() { // Connection impossible so just don't do anything if (singleton->mqState == CONNECTION_FAILED) { - DIAG(F("MQTT connection failed...")); + if(!showonce) { + DIAG(F("MQTT connection failed...")); + showonce = true; + } return; } if (!mqttClient->connected()) diff --git a/MQTTInterface.h b/MQTTInterface.h index 28bc6f5..d6cc72d 100644 --- a/MQTTInterface.h +++ b/MQTTInterface.h @@ -1,3 +1,23 @@ +/* + * © 2021, Gregor Baues, All rights reserved. + * + * This file is part of DCC-EX/CommandStation-EX + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * It is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CommandStation. If not, see . + * + */ + #ifndef _MQTTInterface_h_ #define _MQTTInterface_h_ @@ -67,21 +87,41 @@ struct MQTTBroker return bip; } - MQTTBroker(int p, IPAddress i, const FSH *d) : port(p), ip(i), domain(d), cType(1){}; - MQTTBroker(int p, IPAddress i, const FSH *d, const FSH *uid, const FSH *pass) : port(p), ip(i), domain(d), user(uid), pwd(pass), cType(2){}; - MQTTBroker(int p, IPAddress i, const FSH *d, const FSH *uid, const FSH *pass, const FSH *pfix) : port(p), ip(i), domain(d), user(uid), pwd(pass), prefix(pfix), cType(3){}; - MQTTBroker(int p, const FSH *d, const FSH *uid, const FSH *pass, const FSH *pfix) : port(p), domain(d), user(uid), pwd(pass), prefix(pfix), cType(4) + // all boils down to the ip address type = 1 without user authentication 2 with user authentication + // no ssl support ! + + // port & ip address + MQTTBroker(int p, IPAddress i) : port(p), ip(i), cType(1){}; + // port & domain name + MQTTBroker(int p, const FSH *d) : port(p), domain(d), cType(1) { ip = resovleBroker(d); }; - MQTTBroker(int p, const FSH *d, const FSH *uid, const FSH *pass) : port(p), domain(d), user(uid), pwd(pass), cType(5) + + // port & ip & prefix + MQTTBroker(int p, IPAddress i, const FSH *uid, const FSH *pass, const FSH *pfix) : port(p), ip(i), prefix(pfix), cType(1){}; + // port & domain & prefix + MQTTBroker(int p, const FSH *d, const FSH *uid, const FSH *pass, const FSH *pfix) : port(p), domain(d), prefix(pfix), cType(1) { ip = resovleBroker(d); }; - MQTTBroker(int p, const FSH *d) : port(p), domain(d), cType(6) + + // port & ip & user & pwd + MQTTBroker(int p, IPAddress i, const FSH *uid, const FSH *pass) : port(p), ip(i), user(uid), pwd(pass), cType(2){}; + // port & domain & user & pwd + MQTTBroker(int p, const FSH *d, const FSH *uid, const FSH *pass) : port(p), domain(d), user(uid), pwd(pass), cType(2) { ip = resovleBroker(d); }; + + // port & ip & user & pwd & prefix + MQTTBroker(int p, IPAddress i, const FSH *uid, const FSH *pass, const FSH *pfix) : port(p), ip(i), user(uid), pwd(pass), prefix(pfix), cType(2){}; + // port & domain & user & pwd & prefix + MQTTBroker(int p, const FSH *d, const FSH *uid, const FSH *pass, const FSH *pfix) : port(p), domain(d), user(uid), pwd(pass), prefix(pfix), cType(2) + { + ip = resovleBroker(d); + }; + }; /** diff --git a/Queue.h b/Queue.h index 3f3256d..04cfa3d 100644 --- a/Queue.h +++ b/Queue.h @@ -1,5 +1,20 @@ /* - * Queue.h + * © 2021, Gregor Baues, All rights reserved. + * + * This file is part of DCC-EX/CommandStation-EX + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * It is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CommandStation. If not, see . * */ diff --git a/config.example.h b/config.example.h index 6097acd..c562136 100644 --- a/config.example.h +++ b/config.example.h @@ -98,15 +98,34 @@ The configuration file for DCC-EX Command Station // library from or get via the libray manager either from the IDE // or PIO +#define MQTT_USER "your broker user name" +#define MQTT_PWD "your broker passwd" +#define MQTT_PREFIX "prefix if required by the broker" // #define ENABLE_MQTT true // Set the used broker to one of the configurations from MQTTBrokers.h where some // public freely avaiable brokers are configured +// DEFINE THE MQTT BROKER BELOW ACCORDING TO THE FOLLOWING TABLE: +// +// DCCEX_MQTT_BROKER : DCCEX Team best effort operated MQTT broker; pls apply for user/pwd on discord in the mqtt channel if you want to try it +// DCCEX_MOSQUITTO : Mosquitto.org public test broker no user / pwd required so anyone can subscribe/publish to any topic here; good for testing only +// DCCEX_HIVEMQ : Provided by HiveMQ; Public no user / pwd required +// | +// +-----------------------v + #define CSMQTTBROKER DCCEX_MOSQUITTO -// Example for configuring your own MQTT broker +// -------------------------- +// CUSTOMIZED EXAMPLE +// Configuration for a broker installed on a machine on you home netowrk where the IP address of the machine runing the broker +// is 192.168.0.2 and requires user authentication. The uid ad pwd are set in the config.h file +// Port IPAddress Username (opt) Password(opt) Prefix (opt) +// #define MY_PERSONAL_BROKER F("MYBROKERMQ"), new MQTTBroker( 1883, {192, 168, 0, 2}, F("username"), F("password"), F("prefix-if-required")) +// +// If you have access to a broker on the internet replace the IPAddress by F("my-broker-domain-name") +// ------------------------- /////////////////////////////////////////////////////////////////////////////////////