diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index a04d03e..8780448 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -76,7 +76,7 @@ void setup() #endif // ETHERNET_ON #if MQTT_ON - DccMQTT::get()->setup(); + DccMQTT::get()->setup(LOCAL_MQTT_BROKER); #endif diff --git a/DccMQTT.cpp b/DccMQTT.cpp index 6f7e845..7422d1e 100644 --- a/DccMQTT.cpp +++ b/DccMQTT.cpp @@ -30,20 +30,96 @@ #include #include #include // Base (sync) MQTT library +#include #include +//--------- +// Defines +//--------- + +#define MAXTBUF 50 //!< max length of the buffer for building the topic name ;to be checked +#define MAXTMSG 120 //!< max length of the messages for a topic ;to be checked PROGMEM ? +#define MAXTSTR 30 //!< max length of a topic string + +//--------- +// Variables +//--------- + +char topicName[MAXTBUF]; +char topicMessage[MAXTMSG]; +// char keyword[MAX_KEYWORD_LENGTH]; + DccMQTT DccMQTT::singleton; + + +// callback when a message arrives from the broker +void mqttCallback(char *topic, byte *payload, unsigned int length) +{ + topicName[0] = '\0'; + topicMessage[0] = '\0'; + strcpy(topicName, topic); + strlcpy(topicMessage, (char *)payload, length + 1); + + DIAG(F("MQTT Message arrived [%s]: %s"), topicName, topicMessage); + +} + +/** + * @brief MQTT broker connection / reconnection + * + */ +static void reconnect() +{ + DIAG(F("MQTT (re)connecting ...")); + + while (!mqttClient.connected()) + { + DIAG(F("Attempting MQTT Broker connection...")); + // Attempt to connect +#ifdef CLOUDBROKER + char *connectID = new char[40]; + + connectID[0] = '\0'; + strcat(connectID, MQTT_BROKER_CLIENTID_PREFIX); + strcat(connectID,DccMQTT::getDeviceID()); + + INFO(F("ConnectID: %s %s %s"), connectID, MQTT_BROKER_USER, MQTT_BROKER_PASSWD); + #ifdef MQTT_BROKER_USER + DBG(F("MQTT (re)connecting (Cloud/User) ...")); + if (mqttClient.connect(connectID, MQTT_BROKER_USER, MQTT_BROKER_PASSWD, "$connected", 0, true, "0", 0)) + #else + DBG(F("MQTT (re)connecting (Cloud) ...")); + if (mqttClient.connect(DccMQTT::getDeviceID())) + #endif +#else + #ifdef MQTT_BROKER_USER + DBG(F("MQTT (re)connecting (Local/User) ...")); + if (mqttClient.connect(DccMQTT::getDeviceID(), MQTT_BROKER_USER, MQTT_BROKER_PASSWD)) + #else + DBG(F("MQTT (re)connecting (Local) ...")); + if (mqttClient.connect(DccMQTT::getDeviceID())) + #endif +#endif + { + INFO(F("MQTT broker connected ...")); + // publish on the $connected topic + DccMQTT::subscribe(); // required in case of a connection loss to do it again (this causes a mem leak !! of 200bytes each time!!) + } + else + { + INFO(F("MQTT broker connection failed, rc=%d, trying to reconnect"), mqttClient.state()); + } + } +} + + + + void DccMQTT::setup() { - - // IPAddress server(MQTT_BROKER_ADDRESS); -// EthernetClient ethClient = ETHNetwork::getServer().available(); - -// // MQTT connection -// PubSubClient mqttClient(ethClient); -// PubSubClient *DccMQTT::mqClient = &mqttClient; + //Create the MQTT environment and establish inital connection to the Broker // get a eth client session ethClient = EthernetInterface::get()->getServer()->available(); @@ -52,18 +128,19 @@ void DccMQTT::setup() mqttClient = PubSubClient(ethClient); mqttClient.setServer(IPAddress(MQTT_BROKER_ADDRESS), MQTT_BROKER_PORT); - // DBG(F("MQTT Client : Server ok ...")); - // mqttClient.setCallback(mqttCallback); // Initalize callback function for incomming messages - // DBG(F("MQTT Client : Callback set ...")); + DIAG(F("MQTT Client : Server ok ...")); + + mqttClient.setCallback(mqttCallback); // Initalize callback function for incomming messages + + DIAG(F("MQTT Client : Callback set ...")); // DccMQTT::setDeviceID(); // set the unique device ID to bu used for creating / listening to topic - // /** - // * @todo check for connection failure - // */ - // reconnect(); // inital connection as well as reconnects + + reconnect(); // inital connection as well as reconnects // DccMQTT::subscribe(); // set up all subscriptionn - // INFO(F("MQTT subscriptons done...")); + DIAG(F("MQTT subscriptons done...")); + // sprintf_P(_csidMsg, csidfmt, DccMQTT::getDeviceID()); // mqttClient.publish(DccMQTT::topics[ADMIN], _csidMsg); // say hello to the broker and the API who listens to this topic diff --git a/DccMQTT.h b/DccMQTT.h index c195f28..b2ddac5 100644 --- a/DccMQTT.h +++ b/DccMQTT.h @@ -16,6 +16,23 @@ #define MAXPAYLOAD 64 +// 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-" + + +#define LOCAL_MQTT_BROKER F("LOCAL_MQTT_BROKER"), new MQTTBroker( 1883, {10, 0, 0, 2}, "my.local.server", MQ_UNUSED, MQ_UNUSED, MQ_UNUSED) +#define DCCEX_MQTT_BROKER F("DCCEX_MQTT_BROKER"), new MQTTBroker( 9883, {51, 210, 151, 143}, "dcclms.modelrailroad.ovh", "dcccs", "dcccs$3020", "dcc$lms-") + +struct MQTTBroker { + int port; + + MQTTBroker(int p)(port(p)){}; +}; struct DccMQTTMsg { char payload[MAXPAYLOAD]; };