diff --git a/examples/tinymqtt-test/tinymqtt-test.ino b/examples/tinymqtt-test/tinymqtt-test.ino index 50ec323..64c1993 100644 --- a/examples/tinymqtt-test/tinymqtt-test.ino +++ b/examples/tinymqtt-test/tinymqtt-test.ino @@ -1,5 +1,6 @@ -// vim: ts=2 sw=2 +// vim: ts=2 sw=2 expandtab smartindent #define TINY_MQTT_DEBUG +#include #include // https://github.com/hsaturn/TinyMqtt #include #if defined(ESP8266) @@ -15,6 +16,10 @@ #include bool echo_on = true; +auto green = TinyConsole::green; +auto red = TinyConsole::red; +auto white = TinyConsole::white; +auto cyan = TinyConsole::cyan; /** Very complex example * Console allowing to make any kind of test, @@ -27,26 +32,26 @@ bool echo_on = true; * TODO examples of scripts */ -const char* ssid = ""; -const char* password = ""; +const char* ssid = "Freebox-786A2F"; +const char* password = "usurpavi8dalum64lumine?"; std::string topic="sensor/temperature"; void onPublish(const MqttClient* srce, const Topic& topic, const char* payload, size_t length) { - Serial << "--> " << srce->id().c_str() << ": ======> received " << topic.c_str(); + Console << cyan << "--> " << srce->id().c_str() << ": received " << topic.c_str() << white; if (payload) { - Serial << ", payload[" << length << "]=["; + Console << ", payload[" << length << "]=["; while(length--) { const char c=*payload++; if (c<32) - Serial << '?'; + Console << '?'; else - Serial << c; + Console << c; } - Serial << ']' << endl; + Console << ']' << endl; } } @@ -57,23 +62,26 @@ void setup() { WiFi.persistent(false); // https://github.com/esp8266/Arduino/issues/1054 Serial.begin(115200); + Console.begin(Serial); + Console.setPrompt("> "); + Console.setCallback(onCommand); delay(500); - Serial << endl << endl; - Serial << "***************************************************************" << endl; - Serial << "* Welcome to the TinyMqtt console" << endl; - Serial << endl; - Serial << "* The console allows to test all features of the libraries." << endl; - Serial << endl; + Console.cls(); + Console << endl << endl; + Console << yellow + << "***************************************************************" << endl; + Console << "* Welcome to the TinyMqtt console" << endl; + Console << "* The console allows to test all features of the libraries." << endl; + Console << "* Enter help to view the list of commands." << endl; + Console << "***************************************************************" << endl; + Console << endl; if (strlen(ssid)==0) - Serial << "* WARNING: You may want to modify ssid/password in order" << endl - << " to reflect your Wifi configuration." << endl; - Serial << endl; - Serial << "* Enter help to view the list of commands." << endl; - Serial << "***************************************************************" << endl; - Serial << endl; + Console << red << "* ERROR: You must modify ssid/password in order" << endl + << " to be able to connect to your Wifi network." << endl; + Console << endl << white; - Serial << "Connecting to '" << ssid << "' "; + Console << "Connecting to '" << ssid << "' "; WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); @@ -81,16 +89,16 @@ void setup() WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) - { Serial << '-'; delay(500); } + { Console << '-'; delay(500); } - Serial << endl << "Connected to " << ssid << "IP address: " << WiFi.localIP() << endl; + Console << endl << "Connected to " << ssid << "IP address: " << WiFi.localIP() << endl; const char* name="tinytest"; - Serial << "Starting MDNS, name= " << name; + Console << "Starting MDNS, name= " << name; if (!MDNS.begin(name)) - Serial << " error, not available." << endl; + Console << " error, not available." << endl; else - Serial << " ok." << endl; + Console << " ok." << endl; MqttBroker* broker = new MqttBroker(1883); @@ -144,7 +152,7 @@ std::string getword(std::string& str, const char* if_empty/*=nullptr*/, char sep { sword.erase(0,1); to = getint(sword); - if (sword[0]!=')') Serial << "Missing ')'" << endl; + if (sword[0]!=')') Console << "Missing ')'" << endl; } else { @@ -155,7 +163,7 @@ std::string getword(std::string& str, const char* if_empty/*=nullptr*/, char sep } else { - Serial << "Missing '('" << endl; + Console << "Missing '('" << endl; } } while(str[0]==' ') str.erase(0,1); @@ -229,7 +237,7 @@ void convertToCommand(std::string& search) search = matches; else if (count>1) { - Serial << "Ambiguous command: " << matches << endl; + Console << "Ambiguous command: " << matches << endl; search.clear(); } } @@ -268,10 +276,10 @@ void replaceVars(std::string& cmd) } // publish at regular interval -class automatic +class Automatic { public: - automatic(MqttClient* clt, uint32_t intervl) + Automatic(MqttClient* clt, uint32_t intervl) : client(clt), topic_(::topic) { interval(intervl); @@ -290,7 +298,7 @@ class automatic if (!bon) return; if (interval_ && millis() > timer_) { - Serial << "AUTO PUBLISH " << interval_ << endl; + Console << "AUTO PUBLISH " << interval_ << endl; timer_ += interval_; client->publish(topic_, std::string(String(15+millis()%10).c_str())); } @@ -306,7 +314,7 @@ class automatic static void command(MqttClient* who, std::string cmd) { - automatic* autop = nullptr; + Automatic* autop = nullptr; if (autos.find(who) != autos.end()) { autop=autos[who]; @@ -317,10 +325,10 @@ class automatic std::string seconds=getword(cmd, "10000"); if (autop) delete autop; std::string top = getword(cmd, ::topic.c_str()); - autos[who] = new automatic(who, atol(seconds.c_str())); + autos[who] = new Automatic(who, atol(seconds.c_str())); autos[who]->topic(top); autos[who]->bon=true; - Serial << "New auto (" << seconds.c_str() << " topic:" << top.c_str() << ')' << endl; + Console << "New auto (" << seconds.c_str() << " topic:" << top.c_str() << ')' << endl; } else if (autop) { @@ -339,18 +347,18 @@ class automatic if (i) autop->interval(atol(s.c_str())); else - Serial << "Bad value" << endl; + Console << "Bad value" << endl; } else if (s=="view") { - Serial << " automatic " + Console << " Automatic " << (int32_t)autop->client << " interval " << autop->interval_ << (autop->bon ? " on" : " off") << endl; } else { - Serial << "Unknown auto command (" << s.c_str() << ")" << endl; + Console << "Unknown auto command (" << s.c_str() << ")" << endl; break; } s=getword(cmd); @@ -362,15 +370,15 @@ class automatic command(it.first, s+' '+cmd); } else - Serial << "what ? (" << s.c_str() << ")" << endl; + Console << "what ? (" << s.c_str() << ")" << endl; } static void help() { - Serial << " auto [$id] on/off" << endl; - Serial << " auto [$id] view" << endl; - Serial << " auto [$id] interval [s]" << endl; - Serial << " auto [$id] create [millis] [topic]" << endl; + Console << " auto [$id] on/off" << endl; + Console << " auto [$id] view" << endl; + Console << " auto [$id] interval [s]" << endl; + Console << " auto [$id] create [millis] [topic]" << endl; } private: @@ -379,10 +387,10 @@ class automatic uint32_t timer_; std::string topic_; bool bon=false; - static std::map autos; + static std::map autos; float temp=19; }; -std::map automatic::autos; +std::map Automatic::autos; bool compare(std::string s, const char* cmd) { @@ -407,13 +415,18 @@ struct Every void dump() { - Serial << (active ? "enabled " : "disabled "); - auto mill=millis(); - Serial << ms << "ms [" << cmd << "] next in "; - if (mill > next) - Serial << "now"; + if (active) + Console << green << "enabled"; else - Serial << next-mill << "ms"; + Console << red << "disabled"; + + Console << white << + auto mill=millis(); + Console << ms << "ms [" << cmd << "] next in "; + if (mill > next) + Console << "now"; + else + Console << next-mill << "ms"; } }; @@ -425,6 +438,13 @@ int16_t blink; std::vector everies; +void onCommand(const std::string& command) +{ + std::string cmd=command; + if (cmd.substr(0,3)!="set") replaceVars(cmd); + eval(cmd); +} + void eval(std::string& cmd) { while(cmd.length()) @@ -453,7 +473,7 @@ void eval(std::string& cmd) } else { - Serial << "Unknown class (" << s.c_str() << ")" << endl; + Console << red << "Unknown class (" << s.c_str() << ")" << white << endl; cmd.clear(); } } @@ -477,14 +497,14 @@ void eval(std::string& cmd) broker = brokers[s]; } else - Serial << "Unable to find (" << s.c_str() << ")" << endl; + Console << red << "Unable to find (" << s.c_str() << ")" << << white << endl; } if (client) { for (auto it: clients) { if (it.second != client) continue; - Serial << "deleted" << endl; + Console << "deleted" << endl; delete (it.second); clients.erase(it.first); break; @@ -496,7 +516,7 @@ void eval(std::string& cmd) for(auto it: brokers) { if (broker != it.second) continue; - Serial << "deleted" << endl; + Console << "deleted" << endl; delete (it.second); brokers.erase(it.first); break; @@ -504,13 +524,13 @@ void eval(std::string& cmd) cmd += " ls"; } else - Serial << "Nothing to delete" << endl; + Console << "Nothing to delete" << endl; } else if (broker) { if (compare(s,"connect")) { - Serial << "NYI" << endl; + Console << "NYI" << endl; } else if (compare(s, "view")) { @@ -518,7 +538,7 @@ void eval(std::string& cmd) } else { - Serial << "Unknown broker command (" << s << ")" << endl; + Console << "Unknown broker command (" << s << ")" << endl; s.clear(); } } @@ -527,7 +547,7 @@ void eval(std::string& cmd) if (compare(s,"connect")) { client->connect(getip(cmd,"192.168.1.40").c_str(), getint(cmd, 1883), getint(cmd, 60)); - Serial << (client->connected() ? "connected." : "not connected") << endl; + Console << (client->connected() ? "connected." : "not connected") << endl; } else if (compare(s,"publish")) { @@ -547,7 +567,7 @@ void eval(std::string& cmd) } else { - Serial << "Unknown client command (" << s << ")" << endl; + Console << "Unknown client command (" << s << ")" << endl; s.clear(); } } @@ -572,10 +592,10 @@ void eval(std::string& cmd) echo_on = false; else { - Serial << s << ' '; + Console << s << ' '; while(cmd.length()) { - Serial << getword(cmd) << ' '; + Console << getword(cmd) << ' '; } } } @@ -592,7 +612,7 @@ void eval(std::string& cmd) every.next=millis()+ms; everies.push_back(every); every.dump(); - Serial << endl; + Console << endl; cmd.clear(); } } @@ -607,7 +627,7 @@ void eval(std::string& cmd) { if (every.active != active) { - Serial << "every #" << count << (active ? " on" :" off") << endl; + Console << "every #" << count << (active ? " on" :" off") << endl; every.active = active; every.underrun = 0; } @@ -618,19 +638,19 @@ void eval(std::string& cmd) else if (compare(cmd, "list") or cmd.length()==0) { getword(cmd); - Serial << "List of everies (ms=" << millis() << ")" << endl; + Console << "List of everies (ms=" << millis() << ")" << endl; uint8_t count=0; for(auto& every: everies) { - Serial << count << ": "; + Console << count << ": "; every.dump(); - Serial << endl; + Console << endl; count++; } } else if (compare(cmd, "remove")) { - Serial << "Removing..." << endl; + Console << "Removing..." << endl; getword(cmd); int8_t every=getint(cmd, -1); if (every==-1 and compare(cmd, "last") and everies.size()) @@ -648,10 +668,10 @@ void eval(std::string& cmd) everies.erase(everies.begin()+every); } else - Serial << "Bad colmmand" << endl; + Console << "Bad colmmand" << endl; } else - Serial << "Bad command" << endl; + Console << "Bad command" << endl; } else if (compare(s, "blink")) { @@ -662,7 +682,7 @@ void eval(std::string& cmd) blink_ms_off[blink_nr]=getint(cmd, blink_ms_on[blink_nr]); pinMode(blink_nr, OUTPUT); blink_next[blink_nr] = millis(); - Serial << "Blink " << blink_nr << ' ' << (blink_ms_on[blink_nr] ? "on" : "off") << endl; + Console << "Blink " << blink_nr << ' ' << (blink_ms_on[blink_nr] ? "on" : "off") << endl; if (blink_ms_on[blink_nr]) blink |= 1<< blink_nr; else @@ -673,7 +693,7 @@ void eval(std::string& cmd) } else if (compare(s, "auto")) { - automatic::command(client, cmd); + Automatic::command(client, cmd); if (client == nullptr) cmd.clear(); } @@ -682,7 +702,7 @@ void eval(std::string& cmd) std::string id=getword(cmd); if (clients.find(id) != clients.end()) { - Serial << "A client already have that name" << endl; + Console << "A client already have that name" << endl; cmd.clear(); } else if (id.length() or brokers.find(id)!=brokers.end()) @@ -694,17 +714,17 @@ void eval(std::string& cmd) broker->begin(); brokers[id] = broker; - Serial << "new broker (" << id.c_str() << ")" << endl; + Console << "new broker (" << id.c_str() << ")" << endl; } else { - Serial << "Missing port" << endl; + Console << "Missing port" << endl; cmd.clear(); } } else { - Serial << "Missing or existing broker name (" << id.c_str() << ")" << endl; + Console << "Missing or existing broker name (" << id.c_str() << ")" << endl; cmd.clear(); } } @@ -713,7 +733,7 @@ void eval(std::string& cmd) std::string id=getword(cmd); if (brokers.find(id) != brokers.end()) { - Serial << "A broker have that name" << endl; + Console << "A broker have that name" << endl; cmd.clear(); } else if (id.length() or clients.find(id)!=clients.end()) @@ -728,17 +748,17 @@ void eval(std::string& cmd) clients[id]=client; client->setCallback(onPublish); client->subscribe(topic); - Serial << "new client (" << id.c_str() << ", " << s.c_str() << ')' << endl; + Console << "new client (" << id.c_str() << ", " << s.c_str() << ')' << endl; } else if (s.length()) { - Serial << " not found." << endl; + Console << " not found." << endl; cmd.clear(); } } else { - Serial << "Missing or existing client name" << endl; + Console << "Missing or existing client name" << endl; cmd.clear(); } } @@ -749,12 +769,12 @@ void eval(std::string& cmd) { for(auto it: vars) { - Serial << " " << it.first << " -> " << it.second << endl; + Console << " " << it.first << " -> " << it.second << endl; } } else if (commands.find(name) != commands.end()) { - Serial << "Reserved keyword (" << name << ")" << endl; + Console << "Reserved keyword (" << name << ")" << endl; cmd.clear(); } else @@ -770,66 +790,66 @@ void eval(std::string& cmd) } else if (compare(s, "ls") or compare(s, "view")) { - Serial << "--< " << clients.size() << " client/s. >--" << endl; + Console << "--< " << clients.size() << " client/s. >--" << endl; for(auto it: clients) { it.second->dump(" "); } - Serial << "--< " << brokers.size() << " brokers/s. >--" << endl; + Console << "--< " << brokers.size() << " brokers/s. >--" << endl; for(auto it: brokers) { - Serial << " +-- '" << it.first.c_str() << "' " << it.second->clientsCount() << " client/s."<< endl; + Console << " +-- '" << it.first.c_str() << "' " << it.second->clientsCount() << " client/s."<< endl; it.second->dump(" "); } } else if (compare(s, "reset")) ESP.restart(); else if (compare(s, "ip")) - Serial << "IP: " << WiFi.localIP() << endl; + Console << "IP: " << WiFi.localIP() << endl; else if (compare(s,"help")) { - Serial << "syntax:" << endl; - Serial << " MqttBroker:" << endl; - Serial << " broker {broker_name} {port} : create a new broker" << endl; - Serial << " broker_name.delete : delete a broker (buggy)" << endl; - Serial << " broker_name.view : dump a broker" << endl; - Serial << endl; - Serial << " MqttClient:" << endl; - Serial << " client {name} {parent broker} : create a client then" << endl; - Serial << " name.connect [ip] [port] [alive]" << endl; - Serial << " name.[un]subscribe [topic]" << endl; - Serial << " name.publish [topic][payload]" << endl; - Serial << " name.view" << endl; - Serial << " name.delete" << endl; - Serial << endl; + Console << "syntax:" << endl; + Console << " MqttBroker:" << endl; + Console << " broker {broker_name} {port} : create a new broker" << endl; + Console << " broker_name.delete : delete a broker (buggy)" << endl; + Console << " broker_name.view : dump a broker" << endl; + Console << endl; + Console << " MqttClient:" << endl; + Console << " client {name} {parent broker} : create a client then" << endl; + Console << " name.connect [ip] [port] [alive]" << endl; + Console << " name.[un]subscribe [topic]" << endl; + Console << " name.publish [topic][payload]" << endl; + Console << " name.view" << endl; + Console << " name.delete" << endl; + Console << endl; - automatic::help(); - Serial << endl; - Serial << " help" << endl; - Serial << " blink [Dx on_ms off_ms] : make pin blink" << endl; - Serial << " ls / ip / reset" << endl; - Serial << " set [name][value]" << endl; - Serial << " ! repeat last command" << endl; - Serial << endl; - Serial << " echo [on|off] or strings" << endl; - Serial << " every ms [command]; every list; every remove [nr|all]; every (on|off) [#]" << endl; - Serial << " on {output}; off {output}" << endl; - Serial << " $id : name of the client." << endl; - Serial << " rnd[(min[,max])] random number." << endl; - Serial << " default topic is '" << topic.c_str() << "'" << endl; - Serial << endl; + Automatic::help(); + Console << endl; + Console << " help" << endl; + Console << " blink [Dx on_ms off_ms] : make pin blink" << endl; + Console << " ls / ip / reset" << endl; + Console << " set [name][value]" << endl; + Console << " ! repeat last command" << endl; + Console << endl; + Console << " echo [on|off] or strings" << endl; + Console << " every ms [command]; every list; every remove [nr|all]; every (on|off) [#]" << endl; + Console << " on {output}; off {output}" << endl; + Console << " $id : name of the client." << endl; + Console << " rnd[(min[,max])] random number." << endl; + Console << " default topic is '" << topic.c_str() << "'" << endl; + Console << endl; } else { while(s[0]==' ') s.erase(0,1); if (s.length()) - Serial << "Unknown command (" << s.c_str() << ")" << endl; + Console << "Unknown command (" << s.c_str() << ")" << endl; } if (retval != MqttOk) { - Serial << "# MQTT ERROR " << retval << endl; + Console << "# MQTT ERROR " << retval << endl; } } } @@ -851,7 +871,7 @@ void loop() every.next += every.ms; if (ms > every.next and ms > every.underrun) { - Serial << "Underrun every #" << e << ", " << (ms - every.next) << "ms late" << endl; + Console << "Underrun every #" << e << ", " << (ms - every.next) << "ms late" << endl; every.underrun = ms+5000; } } @@ -889,30 +909,6 @@ void loop() for(auto it: clients) it.second->loop(); - automatic::loop(); - - if (Serial.available()) - { - static std::string cmd; - char c=Serial.read(); - if (echo_on) - Serial << c; - - if (c==10 or c==13) - { - Serial << "----------------[ " << cmd.c_str() << " ]--------------" << endl; - static std::string last_cmd; - if (cmd=="!") - cmd=last_cmd; - else - last_cmd=cmd; - - if (cmd.substr(0,3)!="set") replaceVars(cmd); - eval(cmd); - } - else - { - cmd=cmd+c; - } - } + Automatic::loop(); + Console::loop(); } diff --git a/library.properties b/library.properties index 0c19e88..4b5164c 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,5 @@ paragraph=MQTT is a lightweight messaging protocol ideal for small devices. This category=Communication url=https://github.com/hsaturn/TinyMqtt architectures=* +depends=TinyConsole includes=TinyMqtt.h diff --git a/src/TinyMqtt.cpp b/src/TinyMqtt.cpp index cd3030c..b6de552 100644 --- a/src/TinyMqtt.cpp +++ b/src/TinyMqtt.cpp @@ -1,6 +1,16 @@ #include "TinyMqtt.h" #include +static auto green = TinyConsole::green; +static auto cyan = TinyConsole::cyan; +static auto white = TinyConsole::white; +static auto red = TinyConsole::red; +static auto yellow = TinyConsole::yellow; + +#ifdef TINY_MQTT_DEBUG +int TinyMqtt::debug=2; +#endif + #ifdef EPOXY_DUINO std::map MqttClient::counters; #endif @@ -64,6 +74,7 @@ void MqttClient::close(bool bSendDisconnect) if (bSendDisconnect and client->connected()) { message.create(MqttMessage::Type::Disconnect); + message.hexdump("close"); message.sendTo(this); } client->stop(); @@ -78,13 +89,14 @@ void MqttClient::close(bool bSendDisconnect) void MqttClient::connect(MqttBroker* parentBroker) { + debug("MqttClient::connect_1"); close(); parent = parentBroker; } void MqttClient::connect(std::string broker, uint16_t port, uint16_t ka) { - debug("MqttClient::connect"); + debug("MqttClient::connect_3"); keep_alive = ka; close(); if (client) delete client; @@ -105,11 +117,13 @@ void MqttClient::connect(std::string broker, uint16_t port, uint16_t ka) void MqttBroker::addClient(MqttClient* client) { - clients.push_back(client); + debug("MqttBroker::addClient"); + clients.push_back(client); } void MqttBroker::connect(const std::string& host, uint16_t port) { + debug("MqttBroker::connect_2"); if (broker == nullptr) broker = new MqttClient; broker->connect(host, port); broker->parent = this; // Because connect removed the link @@ -117,6 +131,7 @@ void MqttBroker::connect(const std::string& host, uint16_t port) void MqttBroker::removeClient(MqttClient* remove) { + debug("removeClient"); for(auto it=clients.begin(); it!=clients.end(); it++) { auto client=*it; @@ -133,11 +148,12 @@ void MqttBroker::removeClient(MqttClient* remove) return; } } - debug("Error cannot remove client"); // TODO should not occur + debug(red << "Error cannot remove client"); // TODO should not occur } void MqttBroker::onClient(void* broker_ptr, TcpClient* client) { + debug("MqttBroker::onClient"); MqttBroker* broker = static_cast(broker_ptr); broker->addClient(new MqttClient(broker, client)); @@ -183,6 +199,7 @@ void MqttBroker::loop() MqttError MqttBroker::subscribe(const Topic& topic, uint8_t qos) { + debug("MqttBroker::subscribe"); if (broker && broker->connected()) { return broker->subscribe(topic, qos); @@ -194,13 +211,13 @@ MqttError MqttBroker::publish(const MqttClient* source, const Topic& topic, Mqtt { MqttError retval = MqttOk; - debug("publish "); + debug("MqttBroker::publish"); int i=0; for(auto client: clients) { i++; #ifdef TINY_MQTT_DEBUG - Serial << "brk_" << (broker && broker->connected() ? "con" : "dis") << + Console << __LINE__ << " broker:" << (broker && broker->connected() ? "linked" : "alone") << " srce=" << (source->isLocal() ? "loc" : "rem") << " clt#" << i << ", local=" << client->isLocal() << ", con=" << client->connected() << endl; #endif bool doit = false; @@ -221,7 +238,7 @@ MqttError MqttBroker::publish(const MqttClient* source, const Topic& topic, Mqtt doit = true; } #ifdef TINY_MQTT_DEBUG - Serial << ", doit=" << doit << ' '; + Console << ", doit=" << doit << ' '; #endif if (doit) retval = client->publishIfSubscribed(topic, msg); @@ -248,6 +265,7 @@ void MqttMessage::getString(const char* &buff, uint16_t& len) void MqttClient::clientAlive(uint32_t more_seconds) { + debug("MqttClient::clientAlive"); if (keep_alive) { #ifdef EPOXY_DUINO @@ -266,9 +284,9 @@ void MqttClient::loop() { if (parent) { - debug("timeout client"); + debug(red << "timeout client"); close(); - debug("closed"); + debug(red << "closed"); } else if (client && client->connected()) { @@ -297,7 +315,7 @@ void MqttClient::loop() void MqttClient::onConnect(void *mqttclient_ptr, TcpClient*) { MqttClient* mqtt = static_cast(mqttclient_ptr); - debug("cnx: connecting"); + debug("MqttClient::onConnect"); MqttMessage msg(MqttMessage::Type::Connect); msg.add("MQTT",4); msg.add(0x4); // Mqtt protocol version 3.1.1 @@ -354,7 +372,7 @@ void MqttClient::resubscribe() MqttError MqttClient::subscribe(Topic topic, uint8_t qos) { - debug("subsribe(" << topic.c_str() << ")"); + debug("MqttClient::subsribe(" << topic.c_str() << ")"); MqttError ret = MqttOk; subscriptions.insert(topic); @@ -372,6 +390,7 @@ MqttError MqttClient::subscribe(Topic topic, uint8_t qos) MqttError MqttClient::unsubscribe(Topic topic) { + debug("MqttClient::unsubscribe"); auto it=subscriptions.find(topic); if (it != subscriptions.end()) { @@ -386,6 +405,7 @@ MqttError MqttClient::unsubscribe(Topic topic) MqttError MqttClient::sendTopic(const Topic& topic, MqttMessage::Type type, uint8_t qos) { + debug("MqttClient::sendTopic"); MqttMessage msg(type, 2); // TODO manage packet identifier @@ -402,16 +422,7 @@ MqttError MqttClient::sendTopic(const Topic& topic, MqttMessage::Type type, uint void MqttClient::processMessage(MqttMessage* mesg) { #ifdef TINY_MQTT_DEBUG -if (mesg->type() != MqttMessage::Type::PingReq && mesg->type() != MqttMessage::Type::PingResp) -{ - #ifdef NOT_ESP_CORE - Serial << "---> INCOMING " << _HEX(mesg->type()) << " client(" << (dbg_ptr)client << ':' << clientId << ") mem=" << " ESP.getFreeHeap() "<< endl; - #else - Serial << "---> INCOMING " << _HEX(mesg->type()) << " client(" << (dbg_ptr)client << ':' << clientId << ") mem=" << ESP.getFreeHeap() << endl; - #endif - // mesg->hexdump("Incoming"); mesg->hexdump("Incoming"); -} #endif auto header = mesg->getVHeader(); const char* payload; @@ -472,7 +483,7 @@ if (mesg->type() != MqttMessage::Type::PingReq && mesg->type() != MqttMessage::T } #ifdef TINY_MQTT_DEBUG - Serial << "Connected client:" << clientId.c_str() << ", keep alive=" << keep_alive << '.' << endl; + Console << yellow << "Client connected :" << clientId.c_str() << ", keep alive=" << keep_alive << '.' << white << endl; #endif bclose = false; mqtt_connected=true; @@ -507,12 +518,13 @@ if (mesg->type() != MqttMessage::Type::PingReq && mesg->type() != MqttMessage::T if (client) { uint16_t pingreq = MqttMessage::Type::PingResp; + debug(cyan << "Ping response to client "); client->write((const char*)(&pingreq), 2); bclose = false; } else { - debug("internal pingreq ?"); + debug(red << "internal pingreq ?"); } break; @@ -569,7 +581,7 @@ if (mesg->type() != MqttMessage::Type::PingReq && mesg->type() != MqttMessage::T case MqttMessage::Type::Publish: #ifdef TINY_MQTT_DEBUG - Serial << "publish " << mqtt_connected << '/' << (long) client << endl; + Console << "publish " << mqtt_connected << '/' << (long) client << endl; #endif if (mqtt_connected or client == nullptr) { @@ -578,7 +590,9 @@ if (mesg->type() != MqttMessage::Type::PingReq && mesg->type() != MqttMessage::T mesg->getString(payload, len); Topic published(payload, len); payload += len; - // Serial << "Received Publish (" << published.str().c_str() << ") size=" << (int)len + #ifdef TINY_MQTT_DEBUG + Console << "Received Publish (" << published.str().c_str() << ") size=" << (int)len << endl; + #endif // << '(' << std::string(payload, len).c_str() << ')' << " msglen=" << mesg->length() << endl; if (qos) payload+=2; // ignore packet identifier if any len=mesg->end()-payload; @@ -588,8 +602,8 @@ if (mesg->type() != MqttMessage::Type::PingReq && mesg->type() != MqttMessage::T if (parent==nullptr or client==nullptr) // internal MqttClient receives publish { #ifdef TINY_MQTT_DEBUG - Serial << (isSubscribedTo(published) ? "not" : "") << " subscribed.\n"; - Serial << "has " << (callback ? "" : "no ") << " callback.\n"; + Console << (isSubscribedTo(published) ? "not" : "") << " subscribed.\n"; + Console << "has " << (callback ? "" : "no ") << " callback.\n"; #endif if (callback and isSubscribedTo(published)) { @@ -620,10 +634,10 @@ if (mesg->type() != MqttMessage::Type::PingReq && mesg->type() != MqttMessage::T if (bclose) { #ifdef TINY_MQTT_DEBUG - Serial << "*************** Error msg 0x" << _HEX(mesg->type()); + Console << red << "*************** Error msg 0x" << _HEX(mesg->type()); mesg->hexdump("-------ERROR ------"); dump(); - Serial << endl; + Console << white << endl; #endif close(); } @@ -719,7 +733,7 @@ MqttError MqttClient::publishIfSubscribed(const Topic& topic, MqttMessage& msg) { MqttError retval=MqttOk; - debug("mqttclient publish " << subscriptions.size()); + debug("mqttclient publishIfSubscribed " << topic.c_str() << ' ' << subscriptions.size()); if (isSubscribedTo(topic)) { if (client) @@ -729,7 +743,7 @@ MqttError MqttClient::publishIfSubscribed(const Topic& topic, MqttMessage& msg) processMessage(&msg); #ifdef TINY_MQTT_DEBUG - Serial << "Should call the callback ?\n"; + Console << "Should call the callback ?\n"; #endif // callback(this, topic, nullptr, 0); // TODO Payload } @@ -798,7 +812,7 @@ void MqttMessage::incoming(char in_byte) case Complete: default: #ifdef TINY_MQTT_DEBUG - Serial << "Spurious " << _HEX(in_byte) << endl; + Console << red << "Spurious " << _HEX(in_byte) << white << endl; hexdump("spurious"); #endif reset(); @@ -824,6 +838,7 @@ void MqttMessage::add(const char* p, size_t len, bool addLength) void MqttMessage::encodeLength() { + debug("encodingLength"); if (state != Complete) { int length = buffer.size()-3; // 3 = 1 byte for header + 2 bytes for pre-reserved length field. @@ -849,14 +864,14 @@ MqttError MqttMessage::sendTo(MqttClient* client) { if (buffer.size()) { - debug("sending " << buffer.size() << " bytes"); + debug(cyan << "sending " << buffer.size() << " bytes to " << client->id()); encodeLength(); - // hexdump("snd"); + hexdump("Sending "); client->write(&buffer[0], buffer.size()); } else { - debug("??? Invalid send"); + debug(red << "??? Invalid send"); return MqttInvalidMessage; } return MqttOk; @@ -866,6 +881,32 @@ void MqttMessage::hexdump(const char* prefix) const { (void)prefix; #ifdef TINY_MQTT_DEBUG + if (TinyMqtt::debug<2) return; + static std::map tts={ + { Connect, "Connect" }, + { ConnAck, "Connack" }, + { Publish, "Publish" }, + { PubAck, "Puback" }, + { Subscribe, "Subscribe" }, + { SubAck, "Suback" }, + { UnSubscribe, "Unsubscribe" }, + { UnSuback, "Unsuback" }, + { PingReq, "Pingreq" }, + { PingResp, "Pingresp" }, + { Disconnect, "Disconnect" } + }; + std::string t("Unknown"); + Type typ=static_cast(buffer[0] & 0xF0); + if (tts.find(typ) != tts.end()) + t=tts[typ]; + Console.fg(cyan); +#ifdef NOT_ESP_CORE + Console << "---> MESSAGE " << t << ' ' << _HEX(typ) << ' ' << (Complete ? "complete" : "uncomplete") << " mem=???" << endl; +#else + Console << "---> MESSAGE " << t << ' ' << _HEX(typ) << ' ' << (Complete ? "complete" : "uncomplete") << " mem=" << ESP.getFreeHeap() << endl; +#endif + Console.fg(white); + uint16_t addr=0; const int bytes_per_row = 8; const char* hex_to_str = " | "; @@ -873,19 +914,19 @@ void MqttMessage::hexdump(const char* prefix) const const char* half_sep = " - "; std::string ascii; - Serial << prefix << " size(" << buffer.size() << "), state=" << state << endl; + Console << prefix << " size(" << buffer.size() << "), state=" << state << endl; for(const char chr: buffer) { if ((addr % bytes_per_row) == 0) { - if (ascii.length()) Serial << hex_to_str << ascii << separator << endl; - if (prefix) Serial << prefix << separator; + if (ascii.length()) Console << hex_to_str << ascii << separator << endl; + if (prefix) Console << prefix << separator; ascii.clear(); } addr++; - if (chr<16) Serial << '0'; - Serial << _HEX(chr) << ' '; + if (chr<16) Console << '0'; + Console << _HEX(chr) << ' '; ascii += (chr<32 ? '.' : chr); if (ascii.length() == (bytes_per_row/2)) ascii += half_sep; @@ -894,12 +935,12 @@ void MqttMessage::hexdump(const char* prefix) const { while(ascii.length() < bytes_per_row+strlen(half_sep)) { - Serial << " "; // spaces per hexa byte + Console << " "; // spaces per hexa byte ascii += ' '; } - Serial << hex_to_str << ascii << separator; + Console << hex_to_str << ascii << separator; } - Serial << endl; + Console << endl; #endif } diff --git a/src/TinyMqtt.h b/src/TinyMqtt.h index 0e3c8af..57a7bd1 100644 --- a/src/TinyMqtt.h +++ b/src/TinyMqtt.h @@ -34,10 +34,14 @@ #include "StringIndexer.h" #include -// #define TINY_MQTT_DEBUG - #ifdef TINY_MQTT_DEBUG - #define debug(what) { Serial << (int)__LINE__ << ' ' << what << endl; delay(100); } +#include // https://github.com/hsaturn/TinyConsole + struct TinyMqtt + { + static int debug; + }; + + #define debug(what) { if (TinyMqtt::debug>=1) Console << (int)__LINE__ << ' ' << what << TinyConsole::white << endl; delay(100); } #else #define debug(what) {} #endif @@ -176,7 +180,9 @@ class MqttClient (parent!=nullptr and client==nullptr) or (client and client->connected()); } void write(const char* buf, size_t length) - { if (client) client->write(buf, length); } + { + if (client) client->write(buf, length); + } const std::string& id() const { return clientId; } void id(std::string& new_id) { clientId = new_id; } @@ -188,7 +194,7 @@ class MqttClient { callback=fun; #ifdef TINY_MQTT_DEBUG - Serial << "Callback set to " << (long)fun << endl; + Console << TinyConsole::magenta << "Callback set to " << (long)fun << TinyConsole::white << endl; if (callback) callback(this, "test/topic", "value", 5); #endif }; @@ -213,22 +219,29 @@ class MqttClient (void)indent; #ifdef TINY_MQTT_DEBUG uint32_t ms=millis(); - Serial << indent << "+-- " << '\'' << clientId.c_str() << "' " << (connected() ? " ON " : " OFF"); - Serial << ", alive=" << alive << '/' << ms << ", ka=" << keep_alive << ' '; - Serial << (client && client->connected() ? "" : "dis") << "connected"; + Console << indent << "+-- " << '\'' << clientId.c_str() << "' " << (connected() ? " ON " : " OFF"); + Console << ", alive=" << alive << '/' << ms << ", ka=" << keep_alive << ' '; + if (client) + { + if (client->connected()) + Console << TinyConsole::green << "connected"; + else + Console << TinyConsole::red << "disconnected"; + Console << TinyConsole::white; + } if (subscriptions.size()) { bool c = false; - Serial << " ["; + Console << " ["; for(auto s: subscriptions) { - if (c) Serial << ", "; - Serial << s.str().c_str(); + if (c) Console << ", "; + Console << s.str().c_str(); c=true; } - Serial << ']'; + Console << ']'; } - Serial << endl; + Console << TinyConsole::erase_to_end << endl; #endif } @@ -256,7 +269,7 @@ class MqttClient bool mqtt_connected = false; char mqtt_flags; - uint32_t keep_alive = 60; + uint32_t keep_alive = 30; uint32_t alive; MqttMessage message; @@ -319,7 +332,7 @@ class MqttBroker bool compareString(const char* good, const char* str, uint8_t str_len) const; std::vector clients; - TcpServer* server; + TcpServer* server = nullptr; const char* auth_user = "guest"; const char* auth_password = "guest";