What Happens To A Production imp When It Starts Up
When a production (ie. blessed) imp-enabled device is powered up, its on-board imp can be in one of four different states (excluding factory states). These states may be entered both from a cold boot or a warm boot.
A cold boot occurs when an unpowered imp receives power. This can be simulated in Squirrel using the imp API method imp.reset() which restarts the imp as if it had been powered for the first time.
A warm boot is a wake from sleep triggered by a pin transition or the firing of a timer. The imp’s non-volatile RAM (NVRAM) table and real-time clock (RTC) are preserved during sleep but not across a power outage.
The four states are as follows:
Unactivated The imp has no stored production plan ID or production enrollment token and has not yet connected to the server. If the imp is powered, its BlinkUp™ status LED will be flashing orange. This is the state in which devices leave the factory.
Pending Activation The imp has been passed a production plan ID and a production enrollment token that were retrieved by the BlinkUp SDK (embedded within a host mobile app) and sent to the imp by optical BlinkUp or Bluetooth. The imp has not yet contacted the impCloud™.
Activated: No Squirrel The imp has been activated, ie. has been authorized to access the impCloud, but has no Squirrel application firmware to run. It must (re)connect to the impCloud to download the device portion of its application firmware.
Activated: Has Squirrel The imp has been activated and has Squirrel application code. How the imp proceeds will depend on how it started:
When an imp cold-boots in the Unactivated state, it enables BlinkUp sensing and sets the device‘s BlinkUp status LED to flash orange. This signals to the end-user that they should perform a device activation with BlinkUp. WiFi-enabled devices cannot connect to the impCloud at this point because they have no local wireless network credentials stored, unless this information was pre-loaded in the factory.
Ethernet and cellular devices can connect to the network. However, no imp can gain access to the impCloud until it has a plan ID and an enrollment token. BlinkUp will provide these and cause the imp to transition to the Pending Activation state. This is why BlinkUp is required for all imp-enabled devices even if they do not make use of WiFi.
Note Calling the imp API method imp.clearconfiguration() within your factory DUT firmware once blessing has taken place wipes the factory enrollment token installed on the imp during factory BlinkUp. It is this call which ensures the imp is in the Unactivated state when it is powered up by an end-user.
When impOS is able to communicate with the impCloud (ie. after it has connected to the Internet, verified the target impCloud server’s identity and established a secure connection to that server), the imp and impCloud exchange a series of messages. For most imps, this conversation takes place over port 31314; ports 993 and 443 are set as fallbacks. For cellular imps, the conversation takes place through port 52753.
If the imp is not yet activated, it will first send a message requesting activation. This message includes the plan ID and enrollment token it received during BlinkUp. Upon receipt of these credentials, the impCloud checks that the information that the imp has supplied is valid then sends a message back indicating whether the imp has been activated or not. In either case, the conversation between the imp and the server continues.
The imp sends a message containing information about its state, eg. its MAC address and device ID. The impCloud does not respond to this message.
The imp sends a message which includes a hash of the Squirrel application code it has stored. If the imp has no Squirrel code yet, it sends a hash value of zero.
The impCloud matches the received hash against that of the code currently deployed to the Production Device Group to which the imp was assigned when it was blessed. If the hashes do not match, the impCloud’s response will include the Device Group’s current code deployment and a new hash value. A hash of zeroes sent by an imp with no Squirrel will always fail to match the current value. Whether the hashes match or not, the server’s response also contains other data, including real-time clock (RTC) sync data and the information delivered through the imp API property imp.configparams.
Note This response may also include a trigger that will cause impOS to erase any stored WiFi and enrollment credentials it has stored. This is used to force rejected devices (those not activated in step 1) to return to the Unactivated state and not proceed to step 5.
On receipt of the impCloud’s response, the imp writes the application code and the hash, if it was sent them, to secure storage. It now instantiates a new Squirrel VM into which it loads the code from secure storage. It updates its RTC and sets the data store that is accessible in Squirrel via imp.configparams.
Following a cold boot, the imp’s wake reason will be set to WAKEREASON_POWER_ON or WAKEREASON_SW_RESET, depending on what triggered the cold start: a power-cycle or imp.reset() call, respectively. WAKEREASON_SW_RESET is also used in the case of out-of-memory errors. However, if BlinkUp took place (as is the case with an unactivated imp) then the wake reason will be WAKEREASON_BLINKUP. If an impOS update took place, the wake reason will be WAKEREASON_NEW_FIRMWARE.
After a warm boot the imp does not attempt to connect to the impCloud. Instead it proceeds straight to starting Squirrel. Since the imp cannot undergo a warm start without Squirrel having been run previously, you can be sure a warm-starting imp has application code to run. A warm start occurs when the imp wakes from deep sleep, a state into which it was placed by the application code or by impOS. Waking may result from the triggering of a timer (eg. by calling server.sleepfor()) or from the imp’s wakeup pin being asserted (if the pin was so configured). Sufficient impOS code is running during deep sleep to support these triggers.
The imp’s non-volatile RAM (NVRAM) table and real-time clock (RTC) are preserved during sleep. The wake reason will be set to WAKEREASON_TIMER or WAKEREASON_PIN, depending on which of these events triggered the warm start.
After a warm start, the imp does not attempt to establish a network connection and contact the impCloud. This connection instead takes place under application control, either directly with a call to server.connect(), or indirectly (ie. automatically) through any attempt to send data to the server (server.log(), server.error(), agent.send(), etc). Whether the imp reconnects automatically or manually is determined by its current reconnection policy, either the default (automatic) or as set using the imp API method server.setsendtimeoutpolicy().
When a connection does occur, impOS runs through steps 2 through 5, above. Squirrel continues to run, but will be interrupted if new Squirrel has been downloaded in step 4.
If an uncaught Squirrel exception occurs, impOS tears down the Squirrel VM and then jumps to step 2, above. Either new Squirrel is available, in which case it is received in step 4, or not; in either case, the imp progresses to step 5 when the old, error-triggering code is run again, or new, hopefully error-free code is run for the first time. The wake reason will be set to WAKEREASON_SQUIRREL_ERROR.
Note One exception to this rule is the case of out-of-memory errors. These trigger a de facto cold start and the wake reason being set to WAKEREASON_SW_RESET.
The imp API method imp.onunhandledexception() provides a high-level way to trap Squirrel exceptions (cf. the more local Squirrel
try... catch structure) but will nonetheless result in the tearing down of the Squirrel VM and a jump to step 2, above.
During the sequence described above and afterwards, the server can send further messages to the imp. For example, devices are restarted when new code is deployed to the Device Group to which they have been assigned. Upon the deployment of the new code, the server sends a message to online devices which causes impOS to tear down the Squirrel VM and jump to step 2 in the sequence above. The new Squirrel is received in step 4 and started in step 5.
If a device is not online, it will not receive this ‘reload’ message from the server. However, it will receive the new code when it next connects. Connection, whenever or however it takes place, is followed by the conversation outlined in steps 2 through 5, above.
impOS’ polite Squirrel deployment functionality allows application code running on online devices to trap the ‘reload’ message and prevent the Squirrel VM being taken down at that point. This is done to delay the update from interrupting mission-critical tasks. When such a task is complete, the application calls server.restart(), which tells impOS to tear down the Squirrel VM and jump to step 2 in the message sequence. The new Squirrel is received in step 4 and started in step 5. The wake reason WAKEREASON_NEW_SQUIRREL will be set.
A variant on the reload message is one which informs impOS that a new impOS release is available. Again, installation of the new release can be deferred (though Electric Imp reserves the right to mandate such updates if necessary to maintain platform security) but when server.restart() is called, impOS will tear down the Squirrel VM and jump to step 2 in the sequence above. However, the imp will again receive the ‘new impOS’ method from the server, causing the imp to initiate the impOS update procedure. After the installation, the imp restarts cold, as above, ensuring any new Squirrel code will be downloaded. The wake reason will be set to WAKEREASON_NEW_FIRMWARE.
Note If server.restart() is called for any reason other than triggering an impOS or Squirrel update, the wake reason will be set to WAKEREASON_SW_RESTART.
The server may also send a message at any time containing a list of contactable servers (‘server list’) for the imp to cache for future use. Each imp has a built-in list of impCloud servers; it runs through the servers on the list until it finds one it can communicate with. Specific servers on the list may be incommunicado because they are down for maintenance, are fully loaded or are inaccessible for some other reason. The imp can be provided with an alternative list which it will work through instead.
You can think of an agent as a virtual imp hosted by the impCloud. Each agent has its own Squirrel VM and will receive similar messages to those received by devices. For example, when updated application code is deployed, agents receive a reload message just as devices do, with the same effect: the agent tears down the Squirrel VM in which the agent code is running then begins an interchange of messages with the code-provision server that ensures it receives the updated code, instantiates a new VM and loads the updated code into it.
Agent reload messages are triggered by device restarts and this ensures device and agent always run the same version of the application code.
An agent will also be sent a message when it is about to be load-balanced to a different server. This allows agent code to preserve its state with a server.save() call, if the application requires this. Again, agent closes down the Squirrel VM and ‘reboots’ but this time the restarted agent may be on a different server.