Access impCentral And User-defined Values From Within Your Squirrel Code
Electric Imp provides a series of pre-set environmental variables which allow your Squirrel code to gather information about the impCentral entities of which it is a part: the Device Group it has been deployed to and the Product to which that Device Group belongs. Deployment details — ID, SHA and creation date — are included too.
In addition, impCentral™ now allows you to define your own, application-specific environment variables.
The pre-set environment variables are accessible to code via the reserved identifier __EI
, which is a Squirrel enum
. You should ensure your code does not make use of such an identifier except for the purposes of reading the impCentral data; if your code sets __EI
, it will overwrite the impCentral values. Should further Electric Imp enumerations be added to code in the future, these too will be identifiable by a double-underscore prefix.
__EI
has the following structure. Each property is a constant that is populated when Squirrel code is compiled before being sent to the agent server and to devices.
enum __EI { PRODUCT_ID = "...",
PRODUCT_NAME = "...",
DEVICEGROUP_ID = "...",
DEVICEGROUP_NAME = "...",
DEVICEGROUP_TYPE = "<development|factoryfixture|pre_factoryfixture|pre_production|production
|pre_dut|dut>",
DEPLOYMENT_ID = "...",
DEPLOYMENT_SHA = "...",
DEPLOYMENT_CREATED_AT = "..." }
The value of each key is a string. Read a given property using dot syntax:
local myDevGrpID = __EI.DEVICEGROUP_ID;
The structure is automatically inserted into your code immediately prior to compilation, whether you upload your source to the impCloud™ using impCentral or a third-party tool based on the impCentral API. As such, the enumeration will not appear in your source code. Because the enumeration is a constant, the compiler will only add to the compiled code values which are explicitly referenced by your Squirrel. If you do not read any part of __EI
, there will be no impact on your code size.
The following code provides a function which can be added to development code to output useful information when the device restarts. In addition to network and impOS™ version information, the function uses __EI
to add impCentral data to the readout.
function bootMessage() {
// Present OS version and network connection information
// Take the software version string and extract the version number
local a = split(imp.getsoftwareversion(), "-");
server.log("impOS version " + a[2]);
// Get current networking information
local i = imp.net.info();
// Get the active network interface (or the first network on
// the list if there is no network marked as active)
local w = i.interface["active" in i ? i.active : 0];
if (w != null) {
// Get the SSID of the network the device is connected to or fallback to the last known network)
local s = w.type == "wifi" ? ("connectedssid" in w ? w.connectedssid : ("ssid" in w ? w.ssid : "Unknown")) : "Unknown";
// Get the type of network we are using (WiFi or Ethernet)
local t = "Connected by " + (w.type == "wifi" ? "WiFi on SSID \"" + s + "\"" : "Ethernet");
server.log(t + " with IP address " + i.ipv4.address);
}
// Present impCentral data
server.log(format("Code SHA %s created at %s", __EI.DEPLOYMENT_SHA, __EI.DEPLOYMENT_CREATED_AT));
server.log(format("Deployed to Device Group \"%s\" (ID: %s)", __EI.DEVICEGROUP_NAME, __EI.DEVICEGROUP_ID));
server.log(format("Product \'%s\'", __EI.PRODUCT_NAME));
}
// Present device information now
bootMessage();
Squirrel code can also use the data to perform logic. For example, production code might read the name of the Production Device Group to which the device on which it is running has been assigned, and parse that name to perform different configuration flows accordingly:
local deviceGroup = __EI.DEVICEGROUP_NAME;
// Get country code from the last two chars of the device group name,
// eg. "CONNECTED_PRODUCT_SKU1234_US"
local country = deviceGroup.slice(deviceGroup.len() - 2);
// Set LCD UI language according to country
switch (country) {
case "FR":
setupForFrenchLanguage();
break;
case "DE":
setupForGermanLanguage();
break;
case "IT":
setupForItalianLanguage();
break;
case "CN":
setupForChineseLanguage();
break;
default:
setupForEnglishLanguage();
}
User-defined environment variables are accessible to code via the reserved identifier __VARS
, which also operates like a Squirrel enum
. You should ensure your code does not make use of such an identifier except for the purposes of reading the application-specific data; if your code sets __VARS
, it will overwrite your values.
While the __EI
values are set by impCentral, it is up to you to add keys and values to __VARS
. You may set your keys and their values when you create a Device Group, or by updating the group’s attributes. In impCentral, you do this by going to a Product’s list of Device Groups and clicking on Settings under Actions for the chosen Device Group. In the panel that appears, you can enter your keys and values in JSON format:
Click Update to save your environment variables.
This task can also be performed using the impCentral API and making a PATCH
request to the /v5/devicegroups/{devicegroup_id}
endpoint. The request’s body is a JSON structure which identifies the Device Group and includes the attribute env_vars, which is an object containing your key-value pairs:
{ "data": {
"type": "development_devicegroup",
"id": "01560db4-1ca2-5af3-de74-fb5cc7c2bf9e",
"attributes": {
"env_vars": {
"dataSourceURL" : "https://example.com/v1",
"dataSourceAPIVersion" : 1
}
}
}
}
Once you have added your application-specific environment variables, they will be available to running application code via __VARS
.
For example, you might set a key called dataSourceURL to https://example.com/api/v1
. All if the Device Group’s devices’ agents will read __VARS.dataSourceURL to get the current URL they need to contact for data. If you update your API to version 2, you can simply change the value of dataSourceURL to https://example.com/api/v2
and redeploy your code secure in the knowledge that future agent requests based on the value of __VARS.dataSourceURL will be made to the new, correct URL.
The following agent code snippet shows this in action:
local currentURL = __VARS.dataSourceURL;
local header = { "content-type" : "application/json" };
local request = http.get(currentURL + "/boot_graphic", header);
request.sendasync(function(resp) {
if (resp.statuscode == 200) {
local data = http.jsondecode(resp.body);
if ("boot_graphic" in data) {
device.send("update.lcd.boot.image", data.boot_graphic);
}
// All done; log the version
server.log("Retrieved app data version " + __VARS.dataSourceAPIVersion);
}
});
While __VARS
are not updated within the agent or device in real time, this mechanism does provide you with a way to separate confidential data from your code, which is especially important if your source is ever likely to be made accessible publicly, for example through a public git repo.
The following rules apply to the creation and modification of the keys and their values:
__VARS.henryTheEigthIAm
, __VARS.henrytheeigthiam
and __VARS.HENRYTHEEIGTHIAM
all represent different application-specific environment variables.__VARS
is baked in at compile time, so you will need to redeploy your application code to take advantage of updated values.