Power/link usage on wakeup

Hi, I’m wondering how the WiFi connections is handled on wakeup after deep sleep.
I’m doing some benchmarking on total power usage in very low power mode at the far end of the range. The sequence is wake up every 15minutes and take a battery reading, capture time() and generate a sequenceId.

On wakeup, if there isn’t a WiFi link - what’s the algorithim for connecting?.

There are two issues - and maybe they are the same thing

  1. if there is no signal received from AcessPoint(AP), that is wireless fade or AP turned off
  2. if the IMP Tx signal doesn’t make it back to the AP, so there are Tx timeouts

I ask, because while doing some testing with a range extender ENH202 AP I found that the IMP hadn’t got a signal for about 30minutes. When it did connect the sequence Id was incremented by 1 and I was thinking it would be trying - and failing - to make a connecting.
Instead it seems to have waited for the WiFi link to come up OR gone back to sleep.

The core is
voltage = hardware.voltage();
local snapshotTime = time();
local seqId_cnt = nv.seqId_cnt;
if ( ++seqId_cnt >0x7fff) seqId_cnt=1;
nv.seqId_cnt =seqId_cnt;
agent.send(“putPsTs”,{ …});

    imp.onidle(function(){server.sleepfor(cSleepTime_sec-(time() % cSleepTime_sec));});

It would seem the answer is to to use
imp.setpowersave(true) just before sleeping and
imp.setpowersave(false) just before comms with the agent.
What happens to any debug statements to the server while the WiFi is powersaved.?

many thanks for any insights - had a look over the forums and couldn’t see anything on this topic.
Neil

When asleep, setpowersave() does nothing - this is only for when the link is up. If you’re sleeping and waking, it’s generally not useful either, because it takes a few seconds for it to take effect (it drops into powersave mode only when no packets have been sent or received for a while).

The default behavior of the system is to try to connect for 1 minute, then sleep for 9 minutes. If it wakes and doesn’t manage to connect in a minute, it will sleep for 9 and then repeat the cycle.

If this doesn’t work for you, you need to set the policy and implement manual connections; this way you can try for as long as you want, continuing buffering in case of failed connect, etc.

setpowersave() doesn’t affect anything but the latency of I/O. All logs etc will continue to be printed.

I’m also seeing a possible bug with the rssi reading.
On download its OK, but thereafter after reports at 0 dBm

Wed Aug 14 2013 15:39:06: Power state: online=>offline
Wed Aug 14 2013 15:40:06: Power state: offline=>online
Wed Aug 14 2013 15:40:06: Device booting
Wed Aug 14 2013 15:40:06: rssi 0 dBm WakeReason 1 @ time=1376520004 seqId=6
Wed Aug 14 2013 15:40:06: Vbat=3.6V
Wed Aug 14 2013 15:40:06: sleeping until 1376520064000
Wed Aug 14 2013 15:40:06: Power state: online=>asleep
Wed Aug 14 2013 15:40:06: Power state: online=>offline
Wed Aug 14 2013 15:41:05: Power state: offline=>online
Wed Aug 14 2013 15:41:05: Device booting
Wed Aug 14 2013 15:41:05: rssi 0 dBm WakeReason 1 @ time=1376520064 seqId=7
Wed Aug 14 2013 15:41:05: Vbat=3.6V
Wed Aug 14 2013 15:41:05: AgtResultTsFail: 502
Wed Aug 14 2013 15:41:05: sleeping until 1376520124000
Wed Aug 14 2013 15:41:05: Power state: online=>asleep
Wed Aug 14 2013 15:41:05 : Power state: online=>offline
Wed Aug 14 2013 15:42:06: Power state: offline=>online
Wed Aug 14 2013 15:42:06: Downloading new code
Wed Aug 14 2013 15:42:06: Downloading new code
Wed Aug 14 2013 15:42:06: Device configured to be "Logger (ver0.0ab)"
Wed Aug 14 2013 15:42:06: impMac 0c2a69002275 impId 2374af3643fc42ee SwVer 0e967a4 - Fri Jul 19 10:04:28 2013
Wed Aug 14 2013 15:42:06: ssidMac 88dc96035d86 FreeMem=60K
Wed Aug 14 2013 15:42:06: rssi -70 dBm WakeReason 4 @ time=1376520126 seqId=0
Wed Aug 14 2013 15:42:06: Vbat=3.6V
Wed Aug 14 2013 15:42:06: sleeping until 1376520184000
Wed Aug 14 2013 15:42:06: Power state: online=>asleep
Wed Aug 14 2013 15:42:06: Power state: online=>offline
Wed Aug 14 2013 15:43:06: Power state: offline=>online
Wed Aug 14 2013 15:43:06 Device booting
Wed Aug 14 2013 15:43:06: rssi 0 dBm WakeReason 1 @ time=1376520184 seqId=1
Wed Aug 14 2013 15:43:06: Vbat=3.6V
Wed Aug 14 2013 15:43:07: sleeping until 1376520244000
Wed Aug 14 2013 15:43:07: Power state: online=>asleep
Wed Aug 14 2013 15:43:07: Power state: online=>offline

On wakeup after deep sleep, the wifi isn’t turned on until the first time it’s used, i.e. the first time something needs to be sent to the server – that’s imp.configure(), agent.send(), and most of the server.* calls. If, in your code, the first time it’s used is when server.log-ing the rssi, then it will come out zero – because it assembles the logging string first (with wifi still off) and only brings up the wifi inside the call to server.log (when the string to be logged has already been decided).

Peter

Peter - many thanks - thats what is happening - I haven’t yet had some comms with the host.
Hugo - thanks very helpful.
So if I design it for the target environment after wakeup to do all the data collection first, and then only use the comms at the end, I can then let it use the standard profile for server connection, and or later add more management as needed.
I need to put in some debug variables/gates for managing the server reporting.
Many thanks very useful.

The default behavior of the system is to try to connect for 1 minute, then sleep for 9 minutes. If it wakes and doesn't manage to connect in a minute, it will sleep for 9 and then repeat the cycle.

If this doesn’t work for you, you need to set the policy and implement manual connections; this way you can try for as long as you want, continuing buffering in case of failed connect, etc.

Can someone elaborate on this? Does this mean we can set the connection failure behavior? If so, how? Does the code execute during this time?

Also is blinkup active only during this 1 minute try time?

If you turn off the automatic connection behavior then yes, you can define your own behavior totally.

See http://devwiki.electricimp.com/doku.php?id=impwificontrol and the example code here http://devwiki.electricimp.com/doku.php?id=electricimpapi:server:disconnect

Basically, your squirrel would initiate the connection, and perform whatever actions were necessary when it happened. If the connection failed, then again you could do whatever was required (including sleeping with imp.deepsleepfor, which won’t wake wifi up when it comes back up).

Blinkup is active any time it’s enabled with imp.enableblinkup(). You can tell it’s active because the LED flashes - no LED flashes means the imp isn’t listening. This allows you to control when blinkup is available to users too.

If we try to enter deep sleep while we are blinking up, will the blink up override the sleep until the blink up is done or will it enter sleep regardless?

also is it possible to brick the imp if we improperly code the connection behavior or are there safeguards?

It will enter deep sleep regardless.

It’s not possible to brick the imp completely with bad code. Right now, it will ALWAYS verify there is no newer code to run on a cold boot (ie, it must connect to the server). No squirrel is run until it’s connected to the server.

On release 26 onwards, on a cold boot it will verify there is no newer code available, BUT if it cannot connect in 10 seconds it will give up and run the cached code anyway. If a blinkup attempt is started in this period, it will wait for the blinkup to complete before doing anything.

This allows you to always get the imp back if you put bad code on it - it just requires a cold boot.

i want my imp to attempt connection for 30 seconds and on failure enter deepsleep for 30 minutes to retry again. does this code make sense?

`
server.setsendtimeoutpolicy(RETURN_ON_ERROR, WAIT_FOR_ACK, 10);

function callback(status)
{
if(status == SERVER_CONNECTED)
{
//do/transmit stuff
}
else
{
server.sleepfor(30*60) //sleep for 30 minutes between failed attempts
}
}

server.connect(callback, 30) //attempt to connect for 30 seconds
`

this is assuming wakeup from warm boot. On cold boot for release < 26 the imp will default to the 1/9 minute schedule right?

also does having a server.log before the connect call essentially cancel out my setup?

This would be very useful! A simple template where 60 seconds and 9 min are used by default as constant values. Then it would be so easy to change them?

If you’re already connected, which you will be on cold boot or when you reloaded squirrel, then your callback won’t be called. It’s only called if a connect actually happens.

That code looks right for code to be run when the imp is offline though.

How can we change the 1 min and 9 min values from the default?

theoretically my code would do that but i havent tested it yet. you would just need to change the connect timeout and sleepfor times. you also shouldnt have any code that would initiate server communication before calling server.connect.

does server.connect return an int or something if we are already connected since the callback is not executed? or is it on us to check server.isconnected() before hand?

server.connect doesn’t return anything if already connected, it just does nothing. Use if (server.connected()) to work out whether you need to do a server.connect or not as you noted.

tested code that tests custom connection failure policy:

`
//constants below in seconds
local RETRY_DELAY=60;
local CONNECT_TIMEOUT=30;
local deepSleepPeriod=60

server.setsendtimeoutpolicy(RETURN_ON_ERROR, WAIT_FOR_ACK, 10);

function sleep()
{
local sleepTime = deepSleepPeriod - (time() % deepSleepPeriod)
server.sleepfor(sleepTime);
}

function main()
{
imp.configure(“policyTest”, [], []);
server.log(“hello”);
imp.wakeup(30, function() { imp.onidle(sleep) }); //Enter deep sleep
}
function callback(status)
{
if(status == SERVER_CONNECTED)
{
main();
}
else
{
server.sleepfor(RETRY_DELAY) //sleep between failed attempts
}
}

if(server.isconnected())
{
main();
}
else
{
server.connect(callback, CONNECT_TIMEOUT) //attempt to connect for timeout time
}
`