diff --git a/Adafruit_MQTT.cpp b/Adafruit_MQTT.cpp index 5d98279..5558a65 100644 --- a/Adafruit_MQTT.cpp +++ b/Adafruit_MQTT.cpp @@ -38,6 +38,7 @@ void printBuffer(uint8_t *buffer, uint8_t len) { DEBUG_PRINTER.println(); } +/* Not used now, but might be useful in the future static uint8_t *stringprint(uint8_t *p, char *s) { uint16_t len = strlen(s); p[0] = len >> 8; p++; @@ -45,6 +46,7 @@ static uint8_t *stringprint(uint8_t *p, char *s) { memcpy(p, s, len); return p+len; } +*/ static uint8_t *stringprint_P(uint8_t *p, const char *s, uint16_t maxlen=0) { // If maxlen is specified (has a non-zero value) then use it as the maximum @@ -81,6 +83,20 @@ Adafruit_MQTT::Adafruit_MQTT(const char *server, uint16_t port, const char *cid, } } +Adafruit_MQTT::Adafruit_MQTT(const __FlashStringHelper *server, uint16_t port, const __FlashStringHelper *cid, + const __FlashStringHelper *user, const __FlashStringHelper *pass) { + servername = (const char *)server; + portnum = port; + clientid = (const char *)cid; + username = (const char *)user; + password = (const char *)pass; + + for (uint8_t i=0; ilastread, buffer+4+topiclen, datalen); + subscriptions[i]->datalen = datalen; DEBUG_PRINT(F("Data len: ")); DEBUG_PRINTLN(datalen); DEBUG_PRINT(F("Data: ")); DEBUG_PRINTLN((char *)subscriptions[i]->lastread); @@ -294,7 +323,7 @@ uint8_t Adafruit_MQTT::connectPacket(uint8_t *packet) { } uint8_t Adafruit_MQTT::publishPacket(uint8_t *packet, const char *topic, - char *data, uint8_t qos) { + const char *data, uint8_t qos) { uint8_t *p = packet; uint16_t len; @@ -357,6 +386,13 @@ Adafruit_MQTT_Publish::Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, qos = q; } +Adafruit_MQTT_Publish::Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, + const __FlashStringHelper *feed, uint8_t q) { + mqtt = mqttserver; + topic = (const char *)feed; + qos = q; +} + bool Adafruit_MQTT_Publish::publish(int32_t i) { char payload[18]; itoa(i, payload, 10); @@ -375,7 +411,7 @@ bool Adafruit_MQTT_Publish::publish(uint32_t i) { return mqtt->publish(topic, payload, qos); } -bool Adafruit_MQTT_Publish::publish(char *payload) { +bool Adafruit_MQTT_Publish::publish(const char *payload) { return mqtt->publish(topic, payload, qos); } @@ -388,3 +424,10 @@ Adafruit_MQTT_Subscribe::Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver, topic = feed; qos = q; } + +Adafruit_MQTT_Subscribe::Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver, + const __FlashStringHelper *feed, uint8_t q) { + mqtt = mqttserver; + topic = (const char *)feed; + qos = q; +} diff --git a/Adafruit_MQTT.h b/Adafruit_MQTT.h index c5c76aa..e18110e 100644 --- a/Adafruit_MQTT.h +++ b/Adafruit_MQTT.h @@ -94,6 +94,8 @@ class Adafruit_MQTT { public: Adafruit_MQTT(const char *server, uint16_t port, const char *cid, const char *user, const char *pass); + Adafruit_MQTT(const __FlashStringHelper *server, uint16_t port, const __FlashStringHelper *cid, + const __FlashStringHelper *user, const __FlashStringHelper *pass); virtual ~Adafruit_MQTT() {} // Connect to the MQTT server. Returns 0 on success, otherwise an error code @@ -105,8 +107,16 @@ class Adafruit_MQTT { // 4 = Bad username or password // 5 = Not authenticated // 6 = Failed to subscribe + // Use connectErrorString() to get a printable string version of the + // error. int8_t connect(); + // Return a printable string version of the error code returned by + // connect(). This returns a __FlashStringHelper*, which points to a + // string stored in flash, but can be directly passed to e.g. + // Serial.println without any further processing. + const __FlashStringHelper* connectErrorString(int8_t code); + // Disconnect from the MQTT server. Returns true if disconnected, false // otherwise. virtual bool disconnect() = 0; // Subclasses need to fill this in! @@ -116,10 +126,17 @@ class Adafruit_MQTT { // Publish a message to a topic using the specified QoS level. Returns true // if the message was published, false otherwise. - bool publish(const char *topic, char *payload, uint8_t qos); + // The topic must be stored in PROGMEM. It can either be a + // char*, or a __FlashStringHelper* (the result of the F() macro). + bool publish(const char *topic, const char *payload, uint8_t qos = 0); + bool publish(const __FlashStringHelper *topic, const char *payload, uint8_t qos = 0) { + return publish((const char *)topic, payload, qos); + } // Add a subscription to receive messages for a topic. Returns true if the - // subscription could be added, false otherwise. + // subscription could be added or was already present, false otherwise. + // Must be called before connect(), subscribing after the connection + // is made is not currently supported. bool subscribe(Adafruit_MQTT_Subscribe *sub); // Check if any subscriptions have new messages. Will return a reference to @@ -161,7 +178,7 @@ class Adafruit_MQTT { // Functions to generate MQTT packets. uint8_t connectPacket(uint8_t *packet); - uint8_t publishPacket(uint8_t *packet, const char *topic, char *payload, uint8_t qos); + uint8_t publishPacket(uint8_t *packet, const char *topic, const char *payload, uint8_t qos); uint8_t subscribePacket(uint8_t *packet, const char *topic, uint8_t qos); uint8_t pingPacket(uint8_t *packet); }; @@ -170,8 +187,9 @@ class Adafruit_MQTT { class Adafruit_MQTT_Publish { public: Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, const char *feed, uint8_t qos = 0); + Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, const __FlashStringHelper *feed, uint8_t qos = 0); - bool publish(char *s); + bool publish(const char *s); bool publish(double f, uint8_t precision=2); // Precision controls the minimum number of digits after decimal. // This might be ignored and a higher precision value sent. bool publish(int32_t i); @@ -186,13 +204,17 @@ private: class Adafruit_MQTT_Subscribe { public: Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver, const char *feedname, uint8_t q=0); + Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver, const __FlashStringHelper *feedname, uint8_t q=0); bool setCallback(void (*callback)(char *)); const char *topic; uint8_t qos; - uint8_t * lastread[SUBSCRIPTIONDATALEN]; + uint8_t lastread[SUBSCRIPTIONDATALEN]; + // Number valid bytes in lastread. Limited to SUBSCRIPTIONDATALEN-1 to + // ensure nul terminating lastread. + uint8_t datalen; private: Adafruit_MQTT *mqtt; }; diff --git a/examples/mqtt_cc3k/mqtt_cc3k.ino b/examples/mqtt_cc3k/mqtt_cc3k.ino index d2490f4..e9731a2 100644 --- a/examples/mqtt_cc3k/mqtt_cc3k.ino +++ b/examples/mqtt_cc3k/mqtt_cc3k.ino @@ -121,7 +121,7 @@ void loop() { // this is our 'wait for incoming subscription packets' busy subloop Adafruit_MQTT_Subscribe *subscription; - while (subscription = mqtt.readSubscription(1000)) { + while ((subscription = mqtt.readSubscription(1000))) { if (subscription == &onoffbutton) { Serial.print(F("Got: ")); Serial.println((char *)onoffbutton.lastread); @@ -152,18 +152,9 @@ void MQTT_connect() { Serial.print("Connecting to MQTT... "); while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected - switch (ret) { - case 1: Serial.println("Wrong protocol"); break; - case 2: Serial.println("ID rejected"); break; - case 3: Serial.println("Server unavailable"); break; - case 4: Serial.println("Bad user/password"); break; - case 5: Serial.println("Not authenticated"); break; - case 6: Serial.println("Failed to subscribe"); break; - default: - Serial.println(F("Connection failed")); + Serial.println(mqtt.connectErrorString(ret)); + if (ret < 0) CC3000connect(WLAN_SSID, WLAN_PASS, WLAN_SECURITY); // y0w, lets connect to wifi again - break; - } Serial.println("Retrying MQTT connection in 5 seconds..."); mqtt.disconnect(); delay(5000); // wait 5 seconds diff --git a/examples/mqtt_esp8266/mqtt_esp8266.ino b/examples/mqtt_esp8266/mqtt_esp8266.ino index 5a7d217..528f002 100644 --- a/examples/mqtt_esp8266/mqtt_esp8266.ino +++ b/examples/mqtt_esp8266/mqtt_esp8266.ino @@ -104,7 +104,7 @@ void loop() { // this is our 'wait for incoming subscription packets' busy subloop Adafruit_MQTT_Subscribe *subscription; - while (subscription = mqtt.readSubscription(1000)) { + while ((subscription = mqtt.readSubscription(1000))) { if (subscription == &onoffbutton) { Serial.print(F("Got: ")); Serial.println((char *)onoffbutton.lastread); @@ -137,17 +137,7 @@ void MQTT_connect() { Serial.print("Connecting to MQTT... "); while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected - switch (ret) { - case 1: Serial.println("Wrong protocol"); break; - case 2: Serial.println("ID rejected"); break; - case 3: Serial.println("Server unavailable"); break; - case 4: Serial.println("Bad user/password"); break; - case 5: Serial.println("Not authenticated"); break; - case 6: Serial.println("Failed to subscribe"); break; - default: Serial.print("Couldn't connect to server, code: "); - Serial.println(ret); - break; - } + Serial.println(mqtt.connectErrorString(ret)); Serial.println("Retrying MQTT connection in 5 seconds..."); mqtt.disconnect(); delay(5000); // wait 5 seconds diff --git a/examples/mqtt_fona/mqtt_fona.ino b/examples/mqtt_fona/mqtt_fona.ino index fd95690..e14dcf6 100644 --- a/examples/mqtt_fona/mqtt_fona.ino +++ b/examples/mqtt_fona/mqtt_fona.ino @@ -122,18 +122,7 @@ void loop() { Serial.println(F("Connecting to MQTT...")); int8_t ret, retries = 5; while (retries && (ret = mqtt.connect()) != 0) { - switch (ret) { - case 1: Serial.println(F("Wrong protocol")); break; - case 2: Serial.println(F("ID rejected")); break; - case 3: Serial.println(F("Server unavail")); break; - case 4: Serial.println(F("Bad user/pass")); break; - case 5: Serial.println(F("Not authed")); break; - case 6: Serial.println(F("Failed to subscribe")); break; - default: { - Serial.println(F("Connection failed")); - break; - } - } + Serial.println(mqtt.connectErrorString(ret)); Serial.println(F("Retrying MQTT connection")); retries--; if (retries == 0) halt("Resetting system"); @@ -155,7 +144,7 @@ void loop() { // this is our 'wait for incoming subscription packets' busy subloop Adafruit_MQTT_Subscribe *subscription; - while (subscription = mqtt.readSubscription(5000)) { + while ((subscription = mqtt.readSubscription(5000))) { if (subscription == &onoffbutton) { Serial.print(F("Got: ")); Serial.println((char *)onoffbutton.lastread);