0

Mqtt subscribe and deepsleep
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Mqtt subscribe and deepsleep

by yodrack on Mon May 21, 2018 10:34 am

Hi,

I want to create a remote control using MQTT. The command is issued with a smartphone.

The remote harware is based on ESP8266 working on batteries. In order to save the power and make the batteries last long time, the ESP8266 is in Deepsleep mode most of the time. For example 5 seconds wake-up and 2 minutes in deepsleep.

I created a feed named "actionne les volets", In the code of ESP, I subscribe to the MQTT using :

Adafruit_MQTT_Subscribe monte_descend = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/actionne les volets");
and after the end of deepsleep (ie after reset) I check the incoming command with

while ((subscription = mqtt.readSubscription(5000))) {
if (subscription == &monte_descend) {
Serial.print(F("Got: "));
Serial.println((char *)monte_descend.lastread);}}

It works when the command is issued from my smartphone within the wake-up time (ie. 5 secondes)
but I cannot retrieve the last command if the command is issued during the deepsleep time (before wake-up)

The question is : how to get the latest command issued by the smartphone ? (could be anytime during wake-up or not)

please give me some ideas, thanks

yodrack
 
Posts: 6
Joined: Mon May 21, 2018 10:16 am

Re: Mqtt subscribe and deepsleep

by MikeTeachman on Wed May 23, 2018 4:25 pm

I think the topic "MQTT /get and the case of the missing retain flag" might help.

in

https://io.adafruit.com/blog/

MikeTeachman
 
Posts: 14
Joined: Mon Nov 25, 2013 10:52 pm

Re: Mqtt subscribe and deepsleep

by tawen on Wed May 23, 2018 6:20 pm

Thank you,
I have already seen this topic, but I don't know how to implement /get in my example.

here after is the part of code I use :
-----------------
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

/****************************** Feeds ***************************************/

// initialisation d'un feed 'monte_descend' pour souscription aux changements d'état
Adafruit_MQTT_Subscribe monte_descend = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/actionne les volets");

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());

// initialisation MQTT pour la souscription
mqtt.subscribe(&monte_descend);
MQTT_connect();
}

void loop() {

Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(5000))) {
if (subscription == &monte_descend) {

if(strcmp((char*)monte_descend.lastread,"FERME")== 0) { valeur_etat_volet = ferme; Serial.println("--> fermer"); }
if(strcmp((char*)monte_descend.lastread,"OUVRE")== 0) { valeur_etat_volet = ouvert; Serial.println("--> ouvert"); }
}
}
delay (100);
//mise en deepsleep ici
Serial.print( "entree en deepsleep pour " ) ; Serial.print(dormir) ; Serial.println( "secondes" ); ESP.deepSleep( 60*1000 * 1000, WAKE_RF_DEFAULT); // c'est en micro seconde !

}
all example given with get() are related to the declaration :

AdafruitIO_Feed *counter = io.feed("counter");
if I use this type declaration I cannot complile the program (compilation error)

I am a bit lost in this code, canyou help me ?

tawen
 
Posts: 1
Joined: Wed May 23, 2018 12:34 pm

Re: Mqtt subscribe and deepsleep

by abachman on Tue Jun 05, 2018 1:58 pm

tawen,


I've published an example Arduino sketch that demonstrates the /get topic here: https://gist.github.com/abachman/f6c2c4 ... 10ac580c0d

In your case, you'd add an Adafruit_MQTT_Publish object whose topic is the Subscribe topic plus "/get". Something like:
Code: Select all | TOGGLE FULL SIZE
Adafruit_MQTT_Subscribe monte_descend = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/actionne les volets"); // your original code
Adafruit_MQTT_Publish monte_descend_get = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/actionne les volets/get"); // added Publish object


Then, after connecting, maybe at the bottom of your MQTT_connect function, send a value to monte_descend_get with .publish:
Code: Select all | TOGGLE FULL SIZE
monte_descend_get.publish(0);


That asks IO to resend the last value on the `actionne les volets` feed, which is the same that the Adafruit_IO_Arduino library is using behind the scenes with the .get() method.


- adam b.

abachman
 
Posts: 212
Joined: Mon Feb 01, 2010 12:48 pm

Re: Mqtt subscribe and deepsleep

by yodrack on Wed Jun 06, 2018 5:59 am

Hi Adam,

Thank you for your answer and suggested modifications.
Unfortunatly, it does not work with deepsleep
I used you own sketch (on Github), I changed the ssid, pwd, username, feed name and key in order to use my dashboard


then, I add at the end of
loop() {
.................
//Serial.print( "start delay 20s " ) ; delay(20000);
//Serial.print( "start deepsleep " ) ; ESP.deepSleep( 20000* 1000, WAKE_RF_DEFAULT);
}

If I use Serial.print( "start delay 20s " ) ; delay(20000);
it works, the last action occured within the delay can be read after the delay

If I use Serial.print( "start deepsleep " ) ; ESP.deepSleep( 20000* 1000, WAKE_RF_DEFAULT);
it does not work, the last action occured within the deepsleep time cannot be read

it seems that a reset issued by "end of deepsleep" is not the same than a manuel reset on the reset button.

do you have any explanation
regards
Y

yodrack
 
Posts: 6
Joined: Mon May 21, 2018 10:16 am

Re: Mqtt subscribe and deepsleep

by yodrack on Tue Jun 12, 2018 7:51 am

Hi,
I made several test and I find out that "last value" cannot be read after any kind of reset of the ESP8266 (deepsleep is one kind of reset).

Does It means that there is no solution ?

however I have an idea :
- as we can read on the web site (https://io.adafruit.com/xxxx/feeds/zzzzz) the historical list of all events including the time of the event.it is also possible to download this list with JSON format

{"id":"0DWD2QDX1K2076Y6CPG3RSG7YD",
"value":"OUVRE",
"feed_id":809435,
"created_at":"2018-05-22T08:23:36.094Z"},

{"id":"0DWD3XJQQN48NCN25GB8JDB6FD",
"value":"FERME",
"feed_id":809435,
"created_at":"2018-05-22T09:30:16.523Z"},.....

is it possible to read or download this historical list (with the time) after reconnexion of the ESP ?

if it is possible to download tje JSON format, we have just to compare the time of the event with NTP time and do the action if the time of the last event is within the deepsleep delay.

But how can I read (download) this list in the ESP ?

yodrack
 
Posts: 6
Joined: Mon May 21, 2018 10:16 am

Re: Mqtt subscribe and deepsleep

by abachman on Wed Jun 13, 2018 12:25 pm

Hi yodrack,


Regarding the deepSleep function on the ESP8266, it looks like programs written with deep sleeping in mind have a very different look from a normal Arduino app: https://www.esp8266.com/wiki/doku.php?id=esp8266_power_usage. For example, it's not clear that the loop() function is called at all once the device wakes from sleep. I don't personally have any experience with deep sleeping the ESP8266 and I'm not familiar enough with the Arduino framework on that device to say for sure, though.

You might try starting with a working example program that uses ESP.deepSleep and add an MQTT connection to it, rather than starting with an MQTT example program and adding deepSleep.


- adam

abachman
 
Posts: 212
Joined: Mon Feb 01, 2010 12:48 pm

Re: Mqtt subscribe and deepsleep

by yodrack on Wed Jun 13, 2018 1:30 pm

Hi Adam,
thank you for your answer.

This is what I have done, first I wrote the program with deepsleep then I added MQTT.

In my opinion and regarding my tests the problem comes from a lost of connection between ESP and MQTT server.

As all the data is erased when deepsleep (because no power on most sections of ESP), the MQTT data structure has to be rebuilt after reset with executing the method "MQTT_connect()" this will cause the server to re-initialize the data.

One way to explore is to map or copy (with system_rtc_mem_write(RTC_start, xxxxx, nnn) the MQTT data (on the ESP) in the RTC memory (this memory is still powered during deepsleep and will not loose data)

In that case, after reset, there is no need to redo MQTT_connect() because the connection data are still alive.

but the problem is that I don't know how to map the MQTT data structure to RTC memory

do you think it is correct ? and how to do ?
regards

yodrack
 
Posts: 6
Joined: Mon May 21, 2018 10:16 am

Re: Mqtt subscribe and deepsleep

by pdh on Wed Jun 13, 2018 1:38 pm

> it's not clear that the loop() function is called at all once the device wakes from sleep

I've been using a battery-powered Feather Huzzah 8266 board to send data to an MQTT broker every few minutes, deep-sleeping in between MQTT calls. Based on my experience, I think you have to tie GPIO #16 to RESET to make it work. I think that once it wakes from deep sleep, it bounces GPIO #16 which will reset the board, making your sketch restart and run setup() again. If you don't connect GPIO #16 to RESET then nothing at all seems to happen when it wakes up.

Note however that you can't upload a sketch when GPIO #16 is tied to RESET -- so you have to disconnect those pins when uploading your sketch, then connect them afterwards.
pdh
 
Posts: 161
Joined: Wed Dec 25, 2013 12:59 pm
Location: Northwest Pennsylvania

Re: Mqtt subscribe and deepsleep

by yodrack on Wed Jun 13, 2018 2:17 pm

Hi

OF COURSE, GPIO16 and RST are connected !

yodrack
 
Posts: 6
Joined: Mon May 21, 2018 10:16 am

Re: Mqtt subscribe and deepsleep

by abachman on Wed Jun 13, 2018 5:09 pm

I updated the Adafruit_MQTT + /get sketch I posted earlier to include a ESP.deepSleep cycle and it seems to be working for me. This is the updated code: https://gist.github.com/abachman/f1f7fad5413b8ea2baf1e0a743f2ce9b. The sketch doesn't get any published updates while it's sleeping, but is picking up the most recent state of the subscribed feed when it wakes up thanks to the /get topic. That code (feed subscription + /get) is unchanged from the last version.

This is what my board looks like now:
IMG_20180613_164158456.jpg
IMG_20180613_164158456.jpg (156.36 KiB) Viewed 98 times


The only change to the previous sketch is that I added a 7 LED NeoPixel jewel I had handy to use as an indicator since the deepSleep reset pin is the same as the Huzzah's on board LED, which my old sketch was using to show the state of the feed. This variation of the sketch sets all the LEDs to green when my feed gets the value "ON". One LED lights red while the board is connecting and flashes blue once when the MQTT connection has been established.

The other hardware I added is a wire connecting Huzzah Arduino pin 0 (the GPIO pin 16 mentioned in ESP8266 documentation, marked by the purple zero in this pic) with a switch inline so I can disconnect it while uploading the code. I had trouble getting this part of the sketch working until I figured out: 1) which actual pin to connect, 2) that it's never safe to use pin 0 in the sketch, 3) and it needs to be disconnected while uploading.

If you have questions about any parts of this setup (code or hardware) I'm happy to answer them. If you're able to post your full sketch and even a picture or diagram of your current wiring, that might be helpful in tracking down the issue.


- adam

abachman
 
Posts: 212
Joined: Mon Feb 01, 2010 12:48 pm

Re: Mqtt subscribe and deepsleep

by yodrack on Thu Jun 14, 2018 3:18 pm

Hi Adam,
Thank you for your reply. I tried your sketch and ... it works. Then I started to modify it gradually to become similar to mine.
I did not go very far because I quickly found what was wrong.

I feel so stupid that I have not seen this before.

The problem is 'the name of the feeds'
My original feed is "actionne les volets". In the description of the page the feed name is "actionne les volets" but the corresponding key is "actionne-les-volets"

so, I modified my original statement:
Adafruit_MQTT_Subscribe (& mqtt, AIO_USERNAME "/ feeds / actionne les volets")

it becomes:
Adafruit_MQTT_Subscribe (& mqtt, AIO_USERNAME "/ feeds / actionne-les-volets")

and that's all. It works as required.

If you want to see my program finished, I'll send it to you quickly.
thank you
cordially

yodrack
 
Posts: 6
Joined: Mon May 21, 2018 10:16 am

Re: Mqtt subscribe and deepsleep

by abachman on Thu Jun 14, 2018 3:29 pm

Ah ha! Good news.

Thank you for your reply. I tried your sketch and ... it works. Then I started to modify it gradually to become similar to mine.
I did not go very far because I quickly found what was wrong.


Glad it was something simple in the end and glad I could help. This was my first time playing with the ESP8266 deepSleep features, so it was useful for me too.

If you want to see my program finished, I'll send it to you quickly.


No, that's fine, if it works it works :)

abachman
 
Posts: 212
Joined: Mon Feb 01, 2010 12:48 pm

Re: Mqtt subscribe and deepsleep

by LucianR on Thu Jun 21, 2018 9:36 am

Adam,

Any chance you could post an example of using /get with micropython?

Lu

LucianR
 
Posts: 5
Joined: Tue Mar 22, 2016 6:27 pm

Re: Mqtt subscribe and deepsleep

by brubell on Thu Jun 21, 2018 10:00 am

LucianR wrote:Adam,

Any chance you could post an example of using /get with micropython?

Lu


MikeTeachMan has a great MicroPython library for Adafruit IO (also compatible with CircuitPython): https://github.com/MikeTeachman/micropy ... tt-esp8266

brubell
 
Posts: 35
Joined: Fri Jul 17, 2015 10:33 pm

Please be positive and constructive with your questions and comments.