diff --git a/DIAG.h b/DIAG.h index e223639..e0b243d 100644 --- a/DIAG.h +++ b/DIAG.h @@ -16,14 +16,15 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ + #ifndef DIAG_h #define DIAG_h #include "StringFormatter.h" -#include "StringLogger.h" +#include "DiagLogger.h" -// #define DIAG StringFormatter::diag -#define DIAG StringLogger::get().diag // allows to add other log writers +// #define DIAG StringFormatter::diag // Std logging to serial only +#define DIAG DiagLogger::get().diag // allows to add other log writers #define LCD StringFormatter::lcd #endif diff --git a/DiagLogger.cpp b/DiagLogger.cpp new file mode 100644 index 0000000..51fdc23 --- /dev/null +++ b/DiagLogger.cpp @@ -0,0 +1,63 @@ +/* + * © 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 . + * + */ + +#include "DiagLogger.h" + +// DIAG.h the #define DIAG points to here ... +// EthernetSetup , Wifisetup, etc can register a function to be called allowing the channel +// to publish the diag info to +// serial is default end enabled all the time + +DiagLogger DiagLogger::singleton; // static instantiation; + +void DiagLogger::addDiagWriter(DiagWriter l) { + if ( registered == MAXWRITERS ) { + Serial.println("Error: Max amount of writers exceeded."); + return; + } + writers[registered] = l; + registered++; +} + + +void DiagLogger::diag(const FSH *input,...) +{ + + va_list args; + va_start(args, input); + + int len = 0; + len += sprintf(&b1[len], "<* "); + len += vsprintf_P(&b1[len], (const char *)input, args); + len += sprintf(&b1[len], " *>\n"); + + if ( len >= 256 ) { Serial.print("ERROR : Diag Buffer overflow"); return; } + // allways print to Serial + Serial.print(b1); + + // callback the other registered diag writers + for (size_t i = 0; i < (size_t) registered; i++) + { + writers[i](b1, len); + } + + va_end(args); + +} \ No newline at end of file diff --git a/DiagLogger.h b/DiagLogger.h new file mode 100644 index 0000000..3b7105b --- /dev/null +++ b/DiagLogger.h @@ -0,0 +1,59 @@ +/* + * © 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 DiagLogger_h +#define DiagLogger_h + +#include "StringFormatter.h" + + +#define MAXWRITERS 10 +typedef void (*DiagWriter)(const char *msg, const int length); + +class DiagLogger +{ + +private: + // Methods + DiagLogger() = default; + DiagLogger(const DiagLogger &); // non construction-copyable + DiagLogger &operator=(const DiagLogger &); // non copyable + + // Members + static DiagLogger singleton; // unique instance of the MQTTInterface object + DiagWriter writers[MAXWRITERS]; + int registered = 0; // number of registered writers ( Serial is not counted as always used ) + char b1[256]; + +public: + // Methods + static DiagLogger &get() noexcept + { // return a reference to the unique instance + return singleton; + } + + void diag(const FSH *input...); + void addDiagWriter(DiagWriter l); + ~DiagLogger() = default; + + // Members +}; + +#endif \ No newline at end of file diff --git a/MQTTInterface.cpp b/MQTTInterface.cpp index f93546a..80a0039 100644 --- a/MQTTInterface.cpp +++ b/MQTTInterface.cpp @@ -75,14 +75,17 @@ void mqttDiag(const char *msg, const int length) { sprintf(topic, "%s/%ld/diag", MQTTInterface::get()->getClientID(), MQTTInterface::get()->getClients()[mqSocket].topic); } - // Serial.print(" ---- MQTT pub to: "); Serial.print(topic); Serial.print(" Msg: "); Serial.print(msg); + // Serial.print(" ---- MQTT pub to: "); + // Serial.print(topic); + // Serial.print(" Msg: "); + // Serial.print(msg); MQTTInterface::get()->publish(topic, msg); } } void MQTTInterface::setup() { - StringLogger::get().addDiagWriter(mqttDiag); + DiagLogger::get().addDiagWriter(mqttDiag); singleton = new MQTTInterface(); if (!singleton->connected) @@ -108,6 +111,42 @@ MQTTInterface::MQTTInterface() this->outboundRing = new RingStream(OUT_BOUND_SIZE); }; +/** + * @brief determine the mqsocket from a topic + * + * @return byte the mqsocketid for the message recieved + */ +byte senderMqSocket(MQTTInterface *mqtt, char *topic) +{ + // list of all available clients from which we can determine the mqsocket + auto clients = mqtt->getClients(); + const char s[2] = "/"; // topic delimiter is / + char *token; + byte mqsocket = 0; + + /* get the first token = ClientID */ + token = strtok(topic, s); + /* get the second token = topicID */ + token = strtok(NULL, s); + if (token != NULL) // topic didn't contain any topicID + { + auto topicid = atoi(token); + // verify that there is a MQTT client with that topic id connected + // check in the array of clients if we have one with the topicid + // start at 1 as 0 is not allocated as mqsocket + for (int i = 1; i <= mqtt->getClientSize(); i++) + { + if (clients[i].topic == topicid) + { + mqsocket = i; + break; // we are done + } + } + // if we get here we have a topic but no associated client + } + // if mqsocket == 0 here we haven't got any Id in the topic string + return mqsocket; +} /** * @brief MQTT Interface callback recieving all incomming messages from the PubSubClient * @@ -115,96 +154,68 @@ MQTTInterface::MQTTInterface() * @param payload * @param length */ -void mqttCallback(char *topic, byte *payload, unsigned int length) +void mqttCallback(char *topic, byte *pld, unsigned int length) { + // it's a bounced diag message ignore in all cases + // but it should not be necessary here .. that means the active mqsocket is wrong when sending to diag message + if ( (pld[0] == '<') && (pld[1] == '*')) + { + return; + } + // ignore anything above the PAYLOAD limit of 64 char which should be enough + // in general things rejected here is the bounce of the inital messages setting up the chnanel etc + if (length >= MAXPAYLOAD) + { + return; + } + MQTTInterface *mqtt = MQTTInterface::get(); auto clients = mqtt->getClients(); - errno = 0; - payload[length] = '\0'; // make sure we have the string terminator in place - if (Diag::MQTT) - DIAG(F("MQTT Callback:[%s] [%s] [%d] on interface [%x]"), topic, (char *)payload, length, mqtt); - switch (payload[0]) - { - case '<': // Recieved a DCC-EX Command - { - if (payload[1] == '*') { return;} // it's a bounced diag message - const char s[2] = "/"; // topic delimiter is / - char *token; - byte mqsocket; + csmsg_t tm; // topic message - /* get the first token = ClientID */ - token = strtok(topic, s); - /* get the second token = topicID */ - token = strtok(NULL, s); - if (token == NULL) - { - DIAG(F("MQTT Can't identify sender #1; command send on wrong topic")); + // FOR DIAGS and MQTT ON in the callback we need to copy the payload buffer + // as during the publish of the diag messages the original payload gets destroyed + // so we setup the csmsg_t now to save yet another buffer + // if tm not used it will just be discarded at the end of the function call + + memset(tm.cmd, 0, MAXPAYLOAD); // Clean up the cmd buffer - should not be necessary + strlcpy(tm.cmd, (char *)pld, length + 1); // Message payload + tm.mqsocket = senderMqSocket(mqtt,topic); // On which socket did we recieve the mq message + mqtt->setActive(tm.mqsocket); // connection from where we recieved the command is active now + + if (Diag::MQTT) DIAG(F("MQTT Callback:[%s/%d] [%s] [%d] on interface [%x]"), topic, tm.mqsocket, tm.cmd, length, mqtt); + + switch (tm.cmd[0]) + { + case '<': // Recieved a DCC-EX Command + { + if(!tm.mqsocket) { + DIAG(F("MQTT Can't identify sender; command send on wrong topic")); return; - // don't do anything as we wont know where to send the results - // normally the topicid shall be valid as we only have subscribed to that one and nothing else - // comes here; The only issue is when recieveing on the open csid channel ( which stays open in order to - // able to accept other connections ) } - else - { - auto topicid = atoi(token); - // verify that there is a MQTT client with that topic id connected - bool isClient = false; - // check in the array of clients if we have one with the topicid - // start at 1 as 0 is not allocated as mqsocket - for (int i = 1; i <= mqtt->getClientSize(); i++) - // for (int i = 1; i <= subscriberid; i++) - { - if (clients[i].topic == topicid) - { - isClient = true; - mqsocket = i; - break; - } - } - if (!isClient) - { - // no such client connected - DIAG(F("MQTT Can't identify sender #2; command send on wrong topic")); - return; - } - } - // if we make it until here we dont even need to test the last "cmd" element from the topic as there is no - // subscription for anything else - - // Prepare the DCC-EX command - csmsg_t tm; // topic message - - if (length >= MAXPAYLOAD) - { - DIAG(F("MQTT Command too long (> [%d] characters)"), MAXPAYLOAD); - } - memset(tm.cmd, 0, MAXPAYLOAD); // Clean up the cmd buffer - should not be necessary - strlcpy(tm.cmd, (char *)payload, length + 1); // Message payload - tm.mqsocket = mqsocket; // On which socket did we recieve the mq message int idx = mqtt->getPool()->setItem(tm); // Add the recieved command to the pool - if (idx == -1) { DIAG(F("MQTT Command pool full. Could not handle recieved command.")); return; } - mqtt->getIncomming()->push(idx); // Add the index of the pool item to the incomming queue - + + // don't show the topic as we would have to save it also just like the payload if (Diag::MQTT) - DIAG(F("MQTT Message arrived [%s]: [%s]"), topic, tm.cmd); + DIAG(F("MQTT Message arrived: [%s]"), tm.cmd); + break; } - case 'm': // Recieved an MQTT Connection management message + case 'm': // Recieved an MQTT Connection management message { - switch (payload[1]) + switch (tm.cmd[1]) { - case 'i': // Inital handshake message to create the tunnel + case 'i': // Inital handshake message to create the tunnel { char buffer[MAXPAYLOAD]; - char *tmp = (char *)payload + 3; + char *tmp = tm.cmd + 3; strlcpy(buffer, tmp, length); buffer[length - 4] = '\0'; @@ -244,18 +255,14 @@ void mqttCallback(char *topic, byte *payload, unsigned int length) return; } - default: // Invalid message + default: { - // ignore return; } } } - default: // invalid command / message - { - // this may be the echo comming back on the main channel to which we are also subscribed - // si just ignore for now - // DIAG(F("MQTT Invalid DCC-EX command: %s"), (char *)payload); + default: + { break; } } @@ -302,7 +309,7 @@ void MQTTInterface::setup(const FSH *id, MQTTBroker *b) DIAG(F("MQTT Client created ok...")); array_to_string(mac, CLIENTIDSIZE, clientID); DIAG(F("MQTT Client ID : %s"), clientID); - connect(); // inital connection as well as reconnects + connect(); // inital connection as well as reconnects } /** @@ -335,7 +342,7 @@ void MQTTInterface::connect() if (mqttClient->connect(connectID)) { 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 + 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; @@ -349,10 +356,10 @@ void MQTTInterface::connect() } // with uid passwd case 2: - { + { DIAG(F("MQTT Broker connecting with uid/pwd ...")); - char user[strlen_P((const char *) broker->user)]; - char pwd[strlen_P((const char *) broker->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); @@ -361,7 +368,7 @@ void MQTTInterface::connect() 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 + 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; @@ -371,8 +378,8 @@ void MQTTInterface::connect() DIAG(F("MQTT broker connection failed, rc=%d, trying to reconnect"), mqttClient->state()); reconnectCount++; } - break; - // ! add last will messages for the client + break; + // ! add last will messages for the client // (connectID, MQTT_BROKER_USER, MQTT_BROKER_PASSWD, "$connected", 0, true, "0", 0)) } } @@ -457,6 +464,7 @@ void inLoop(Queue &in, ObjectPool &pool, RingStream * int idx = in.pop(); csmsg_t *c = pool.getItem(idx, &state); + MQTTInterface::get()->setActive(c->mqsocket); // connection from where we recieved the command is active now // execute the command and collect results outboundRing->mark((uint8_t)c->mqsocket); CommandDistributor::parse(c->mqsocket, (byte *)c->cmd, outboundRing); @@ -535,24 +543,23 @@ void checkSubscribers(Queue &sq, csmqttclient_t *clients) // ignored // JSON message { init: channels: {result: , diag: }} - char buffer[MAXPAYLOAD*2]; - memset(buffer, 0, MAXPAYLOAD*2); + char buffer[MAXPAYLOAD * 2]; + memset(buffer, 0, MAXPAYLOAD * 2); // sprintf(buffer, "mc(%d,%ld)", (int)clients[s].distant, clients[s].topic); - sprintf(buffer, "{ \"init\": %d, \"subscribeto\": {\"result\": \"%s/%ld/result\" , \"diag\": \"%s/%ld/diag\" }, \"publishto\": {\"cmd\": \"%s/%ld/cmd\" } }", - (int)clients[s].distant, - mqtt->getClientID(), - clients[s].topic, - mqtt->getClientID(), - clients[s].topic, - mqtt->getClientID(), - clients[s].topic - ); + sprintf(buffer, "{ \"init\": %d, \"subscribeto\": {\"result\": \"%s/%ld/result\" , \"diag\": \"%s/%ld/diag\" }, \"publishto\": {\"cmd\": \"%s/%ld/cmd\" } }", + (int)clients[s].distant, + mqtt->getClientID(), + clients[s].topic, + mqtt->getClientID(), + clients[s].topic, + mqtt->getClientID(), + clients[s].topic); if (Diag::MQTT) DIAG(F("MQTT channel setup message: [%s]"), buffer); - + mqtt->publish(mqtt->getClientID(), buffer); // on the cs side all is set and we declare that the cs is open for business @@ -562,15 +569,14 @@ void checkSubscribers(Queue &sq, csmqttclient_t *clients) void MQTTInterface::loop() { - if (!singleton) return; singleton->loop2(); } - bool showonce = false; auto s = millis(); + void loopPing(int interval) { auto c = millis(); @@ -581,15 +587,15 @@ void loopPing(int interval) } } - void MQTTInterface::loop2() { - - loopPing(2000); // ping every 2 sec + + // loopPing(2000); // ping every 2 sec // Connection impossible so just don't do anything if (singleton->mqState == CONNECTION_FAILED) { - if(!showonce) { + if (!showonce) + { DIAG(F("MQTT connection failed...")); showonce = true; } diff --git a/MQTTInterface.h b/MQTTInterface.h index e6f5db2..ee45535 100644 --- a/MQTTInterface.h +++ b/MQTTInterface.h @@ -41,23 +41,17 @@ #define MAXPAYLOAD 64 // max length of a payload recieved #define MAXDOMAINLENGTH 32 // domain name length for the broker e.g. test.mosquitto.org -#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 -#define MAXCONNECTID 40 // broker connection id length incl possible prefixes +#define MAXTBUF 64 //!< max length of the buffer for building the topic name ;to be checked +#define MAXTMSG 64 //!< max length of the messages for a topic ;to be checked PROGMEM ? +#define MAXTSTR 32 //!< max length of a topic string +#define MAXCONNECTID 32 // broker connection id length incl possible prefixes #define CLIENTIDSIZE 6 // max length of the clientid used for connection to the broker #define MAXRECONNECT 5 // reconnection tries before final failure #define MAXMQTTCONNECTIONS 20 // maximum number of unique tpoics available for subscribers -#define OUT_BOUND_SIZE 256 // Size of the RingStream used to provide results from the parser and publish -#define MAX_POOL_SIZE 32 // recieved command store size +#define OUT_BOUND_SIZE 128 // Size of the RingStream used to provide results from the parser and publish +#define MAX_POOL_SIZE 16 // recieved command store size +#define MAX_CALLBACKS 10 -// 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-" struct MQTTBroker { int port; diff --git a/MemStream.cpp b/MemStream.cpp deleted file mode 100644 index ca443e2..0000000 --- a/MemStream.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - - (c) 2015 Ingo Fischer - buffer serial device - based on Arduino SoftwareSerial - - Constructor warning messages fixed by Chris Harlow. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include "MemStream.h" - -MemStream::MemStream(uint8_t *buffer, const uint16_t len, uint16_t content_len, bool allowWrite) -:_buffer(buffer),_len(len), _buffer_overflow(false), _pos_read(0), _allowWrite(allowWrite) -{ - if (content_len==0) memset(_buffer, 0, _len); - _pos_write=(content_len>len)? len: content_len; -} - -size_t MemStream::write(uint8_t byte) { - if (! _allowWrite) return -1; - if (_pos_write >= _len) { - _buffer_overflow = true; - return 0; - } - _buffer[_pos_write] = byte; - ++_pos_write; - return 1; -} - -void MemStream::flush() { - memset(_buffer, 0, _len); - _pos_write = 0; - _pos_read = 0; -} - -int MemStream::read() { - if (_pos_read >= _len) { - _buffer_overflow = true; - return -1; - } - if (_pos_read >= _pos_write) { - return -1; - } - return _buffer[_pos_read++]; -} - -int MemStream::peek() { - if (_pos_read >= _len) { - _buffer_overflow = true; - return -1; - } - if (_pos_read >= _pos_write) { - return -1; - } - return _buffer[_pos_read+1]; -} - -int MemStream::available() { - int ret=_pos_write-_pos_read; - if (ret<0) ret=0; - return ret; -} - -void MemStream::setBufferContent(uint8_t *buffer, uint16_t content_len) { - memset(_buffer, 0, _len); - memcpy(_buffer, buffer, content_len); - _buffer_overflow=false; - _pos_write=content_len; - _pos_read=0; -} - -void MemStream::setBufferContentFromProgmem(uint8_t *buffer, uint16_t content_len) { - memset(_buffer, 0, _len); - memcpy_P(_buffer, buffer, content_len); - _buffer_overflow=false; - _pos_write=content_len; - _pos_read=0; -} - -void MemStream::setBufferContentPosition(uint16_t read_pos, uint16_t write_pos) { - _pos_write=write_pos; - _pos_read=read_pos; -} \ No newline at end of file diff --git a/MemStream.h b/MemStream.h deleted file mode 100644 index 4c5c154..0000000 --- a/MemStream.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - - (c) 2015 Ingo FIscher - buffer serial device - based on Arduino SoftwareSerial - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#ifndef MemStream_h -#define MemStream_h - -#include -#if defined(ARDUINO_ARCH_MEGAAVR) -#include -#else -#include -#endif - -#include - -class MemStream : public Stream -{ -private: - uint8_t *_buffer; - const uint16_t _len; - bool _buffer_overflow; - uint16_t _pos_read; - uint16_t _pos_write; - bool _allowWrite; - -public: - // public methods - MemStream(uint8_t *buffer, const uint16_t len, uint16_t content_len = 0, bool allowWrite = true); - ~MemStream() {} - - operator const uint8_t *() const { return _buffer; } - operator const char *() const { return (const char *)_buffer; } - - uint16_t current_length() const { return _pos_write; } - - bool listen() { return true; } - void end() {} - bool isListening() { return true; } - bool overflow() - { - bool ret = _buffer_overflow; - _buffer_overflow = false; - return ret; - } - int peek(); - - virtual size_t write(uint8_t byte); - virtual int read(); - virtual int available(); - virtual void flush(); - - void setBufferContent(uint8_t *buffer, uint16_t content_len); - void setBufferContentFromProgmem(uint8_t *buffer, uint16_t content_len); - void setBufferContentPosition(uint16_t read_pos, uint16_t write_pos); - - using Print::write; -}; - -#endif \ No newline at end of file diff --git a/ObjectPool.h b/ObjectPool.h index 54691bc..b32e34b 100644 --- a/ObjectPool.h +++ b/ObjectPool.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 _ObjectPool_h_ #define _ObjectPool_h_ diff --git a/StringLogger.cpp b/StringLogger.cpp deleted file mode 100644 index 4b22279..0000000 --- a/StringLogger.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "StringLogger.h" - -// DIAG.h the #define DIAG points to here ... -// EthernetSetup , Wifisetup, etc can register a function to be called allowing the channel -// to publish the diag info to -// serial is default end enabled all the time - -StringLogger StringLogger::singleton; // static instantiation; - -void StringLogger::addDiagWriter(DiagWriter l) { - if ( registered == MAXWRITERS ) { - Serial.println("Error: Max amount of writers exceeded."); - return; - } - writers[registered] = l; - registered++; -} - - -void StringLogger::diag(const FSH *input,...) -{ - - char b1[128]; - - va_list args; - va_start(args, input); - - int len = 0; - len += sprintf(&b1[len], "<* "); - len += vsprintf_P(&b1[len], (const char *)input, args); - len += sprintf(&b1[len], " *>\n"); - - // allways print to Serial - Serial.print(b1); - - // callback the other registered diag writers - for (size_t i = 0; i < (size_t) registered; i++) - { - writers[i](b1, len); - } - - va_end(args); - -} \ No newline at end of file diff --git a/StringLogger.h b/StringLogger.h deleted file mode 100644 index 72a2c4f..0000000 --- a/StringLogger.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef StringLogger_h -#define StringLogger_h - -#include "MemStream.h" -#include "RingStream.h" -#include "StringFormatter.h" -#include - -// stream for diagnostics in addition to serial you should be able to configure -// additional (besides Serial) 'outputs' to e.g. Ethernet or MQTT or WIFI etc ... -// Serial outpout is managed in StringFormatter on top for formatting the message -// which gets printed char by char - -#define MAXWRITERS 10 - -typedef void (*DiagWriter)(const char *msg, const int length); - -class StringLogger -{ - -private: - // Methods - StringLogger() = default; - StringLogger(const StringLogger &); // non construction-copyable - StringLogger &operator=(const StringLogger &); // non copyable - - // Members - static StringLogger singleton; // unique instance of the MQTTInterface object - DiagWriter writers[MAXWRITERS]; - int registered = 0; // number of registered writers ( Serial is not counted as always used ) - -public: - // Methods - static StringLogger &get() noexcept - { // return a reference to the unique instance - return singleton; - } - void diag(const FSH *input...); - void addDiagWriter(DiagWriter l); - ~StringLogger() = default; - - // Members -}; - -#endif \ No newline at end of file diff --git a/defines.h b/defines.h index 8517440..5d2f286 100644 --- a/defines.h +++ b/defines.h @@ -42,14 +42,16 @@ #if ENABLE_MQTT && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO) || defined(TEENSYDUINO)) #if ENABLE_ETHERNET #error Ethernet and MQTT can not be enabled simultaneaously +#elif ENABLE_WIFI + #error WIFI and MQTT can not be enabled simultaneaously #else #define MQTT_ON true #endif #endif -// #if WIFI_ON && ETHERNET_ON -// #error Command Station does not support WIFI and ETHERNET at the same time. -// #endif +#if WIFI_ON && ETHERNET_ON + #error Command Station does not support WIFI and ETHERNET at the same time. +#endif //////////////////////////////////////////////////////////////////////////////// //