adafruit / Adafruit_MQTT_Library

Arduino library for MQTT support
MIT License
573 stars 291 forks source link

Support MQTT retain flag on publishing. #88

Open patthoyts opened 7 years ago

patthoyts commented 7 years ago

This resolves issue #20 by allowing the user to specify the retain flag on the publisher object. This flag is useful for slow publishers so that a new subscription will immediately receive the last published message.

This change adds a new boolean parameter to the Adafruit_MQTT_Publish constructor to set the retention flag for this publisher instance. To preserve existing compatibility the parameter is defaulted to false. This flag is then propagated to the implementing function Adafruit_MQTT::publishPacket where it is combined into the MQTT_CTRL_PUBLISH flags as a single bit flag.

This has then been confirmed using a Mosquitto MQTT broker to check that resulting messages were being retained and presented promptly to new subscribers.

robertcjchi commented 6 years ago

Using 43f78c7 library. It seems still unable to read the retained last published value when using io.adafruit.com as broker. I have tried modified Adafruit MQTT Library ESP8266 Example and set the retain flag to be "true" as below Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/photocell", 0, true); but after pressing reset button, the retained value was not able to read back immediately before now publication happen on the same ESP8266 board. What could the problem?

Attache the code below:

/****/

include

include "Adafruit_MQTT.h"

include "Adafruit_MQTT_Client.h"

/* WiFi Access Point *****/

define WLAN_SSID "SSID" //"...your SSID..."

define WLAN_PASS "password" //"...your password..."

/* Adafruit.io Setup *****/

define AIO_SERVER "io.adafruit.com"

define AIO_SERVERPORT 1883 // use 8883 for SSL

define AIO_USERNAME "fruitsboard" //"...your AIO username (see https://accounts.adafruit.com)..."

define AIO_KEY "your AIO key" //"...your AIO key..."

long num4=0; /**** Global State (you don't need to change this!) **/

WiFiClient client;

Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

/** Feeds ***/

Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/photocell", 0, true); Adafruit_MQTT_Subscribe nV4_value = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/photocell",1);//Increase QOS to 1 /*** Sketch Code ****/

void MQTT_connect();

void setup() { Serial.begin(115200); delay(10);

Serial.println(F("Adafruit MQTT demo"));

// Connect to WiFi access point. Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(WLAN_SSID);

WiFi.begin(WLAN_SSID, WLAN_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println();

Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP());

mqtt.subscribe(&nV4_value); //Sub #6

}

uint32_t x; void loop() { MQTT_connect(); Adafruit_MQTT_Subscribe subscription; while ((subscription = mqtt.readSubscription(5000))) { if (subscription == &nV4_value) { Serial.print(F("Got: nV4 ")); Serial.println((char )nV4_value.lastread); } // end of if (subscription == &nV4_value) }

// Now we can publish stuff! Serial.print(F("\nSending photocell val ")); Serial.print(x); Serial.print("..."); if (! photocell.publish(x++,1)) { Serial.println(F("Failed")); } else { Serial.println(F("OK!")); } }

// Function to connect and reconnect as necessary to the MQTT server. // Should be called in the loop function and it will take care if connecting. void MQTT_connect() { int8_t ret;

// Stop if already connected. if (mqtt.connected()) { return; }

Serial.print("Connecting to MQTT... ");

uint8_t retries = 3; while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected Serial.println(mqtt.connectErrorString(ret)); Serial.println("Retrying MQTT connection in 5 seconds..."); mqtt.disconnect(); delay(5000); // wait 5 seconds retries--; if (retries == 0) { // basically die and wait for WDT to reset me while (1); } } Serial.println("MQTT Connected!"); }

The series monitor show the following respond:

Connecting to SSID .......... WiFi connected IP address: 192.168.1.7 Connecting to MQTT... MQTT Connected!

Sending photocell val 0...OK! Got: nV4 0.0

Sending photocell val 1...OK! Got: nV4 1.0

Sending photocell val 2...OK! Got: nV4 2.0

Sending photocell val 3...OK! Got: nV4 3.0

Sending photocell val 4...OK! Got: nV4 4.0

Sending photocell val 5...OK! Got: nV4 5.0

Sending photocell val 6...OK!

*Press Reset button on the hardware to restart the hardware***** Here try to see if it will read the retained value 6 immediately after restart. Ans the below is the result. Observing after the "MQTT Connected!" There is nothing read back from subscription which supposed to read Got: nV4 6.0" before the "Sending photocell val 0...OK!".

So it seem still not function properly for this commit??? *****Below showed the respond after reset the hardware**

Connecting to SSID ...... WiFi connected IP address: 192.168.1.7 Connecting to MQTT... MQTT Connected!

Sending photocell val 0...OK! Got: nV4 0.0

Sending photocell val 1...OK! Got: nV4 1.0

Sending photocell val 2...OK! Got: nV4 2.0

Sending photocell val 3...OK! Got: nV4 3.0

Sending photocell val 4...OK! Got: nV4 4.0