Skip to main content

imp Network Interface Management (Pre-Release Documentation)

Understand impOS’ New Mechanism For Network Selection

This is draft documentation which covers impOS™ functionality that, though currently in internal development, has been made available to a number of customers for testing purposes only. Both the functionality described here and the documentation itself are subject to change, including breaking changes, and may differ significantly from their final release versions.


impOS™ has been able to support multiple network interfaces since release 34. However, from release 42, impOS contains a new network interface management system to provide Squirrel with better access to and control of these interfaces. It has been developed to provide support for not only multiple types of interface in the same product, such as WiFi and cellular, but also multiple interfaces of the same type: for example, a device with two or more Ethernet ports both under impOS management.

The new mechanism’s default mode of operation is to leave network interface management to impOS, but it also provides tools which allow your application to select the order in which these interfaces are utilized and even to pick and choose which interface is used at any given moment.

This document introduces you to the new network interface management modes, and to the new imp API methods they encompass, to help you understand if it will be beneficial to adopt the new technology in your application and, if that’s the case, how to do so.

Network Management Modes

impOS 42's network interface management system provides three application-selectable usage modes: legacy, automatic and manual. These modes determine how network interfaces are chosen for use. There are other modes too, but they are not user-selectable. We discuss these additional modes at the end of this guide.

  • Legacy mode is the default mode: it will step through all of the available network interfaces in a default order until it has successfully connected. It is sufficient for the vast majority of use-cases and is the closest to the management system used by earlier versions of impOS. Indeed, if you make no changes to your code, your application will continue to operate as it did before the introduction of impOS 42.

  • Automatic mode extends legacy mode by allowing you to replace the default interface connection order with a sequence of your own.

  • Manual mode puts connection management fully in the hands of your code. You choose which interface is used to host the imp’s connection to the impCloud, and when. It is also the responsibility of your code to decide how to deal with connection failures: for example, which interface to attempt to connect to next, which might depend upon the device’s location, whether the device connects over a primary interface and falls back to a secondary one when the first is unavailable for some reason, or some other application-specific factor.

Choosing A Mode

Legacy mode is the default mode and is enabled when an imp running impOS 42 first cold-boots. If you are happy to make use of legacy mode, your code needs not be altered. If you do not wish to change your code, it will continue to run exactly as before, and impOS 42’s changes will not affect you.

This is because your code only selects automatic mode when it calls a specific imp API method, imp.net.setserverinterfaces(). Your code only selects manual mode when it calls a specific imp API method, server.connectwith(). Until your code makes either of these calls, which it might never do, the imp remains in legacy mode.

Default Interface Order

The default order is Ethernet, then WiFi and, finally, cellular. Within each of these types, impOS will run through the available interfaces, if any, of that type. imps which lack any of these interfaces will not include the unavailable interfaces in their default sequences.

Single-interface Products

If your product makes use of an imp with a single network interface, it is not necessary to make use of impOS 42’s network management system: you can continue to use existing impOS methods, such as server.connect(). Even though legacy mode is enabled by default, with only one interface available it behaves exactly like earlier versions of impOS did. Again, you do not need to make any changes to your code.

However, you may make use of the new system if you wish, which you might want to do to future-proof your application firmware, you wish to make use of impOS 42’s new local networking functionality, or your application has to switch between a number of network or proxy configurations.

Let’s now look at each of the new modes in more detail.

Legacy Mode

This mode, which is the default, operates just like earlier versions of impOS but adds some optional extra functionality to support the use of more than one network interface if your product makes use of multiple network interfaces.

Under legacy mode, impOS will attempt to connect to the impCloud one interface at a time. If the interface currently in use cannot be used to connect or reconnect to the impCloud, impOS will move on to the next available interface in a set sequence at the next connection attempt. When it gets to the last interface on the list and cannot connect, it goes back to the first interface on the list, repeating the sequence.

Connection attempts will occur this way whether they are initiated automatically or by your code. For example, whether your reconnection policy (applied by calling server.setsendtimeoutpolicy()) is set to SUSPEND_ON_ERROR or RETURN_ON_ERROR/RETURN_ON_ERROR_NO_DISCONNECT, respectively.

If, for example, you are using SUSPEND_ON_ERROR, your imp will follow the existing procedure: a loss of connectivity will cause Squirrel to suspend while impOS attempts to reconnect. If it connects, Squirrel is restarted; otherwise the imp will snooze for nine minutes then attempt to reconnect automatically. This reconnection attempt will use the next available interface.

If you are using RETURN_ON_ERROR and following a disconnection you are attempting to reconnect with server.connect(), impOS will attempt to use the current interface. If it fails to connect, your app will be informed in the usual way, and impOS will set the next interface in sequence as the current one so that when you next try to connect (you call server.connect() again, or call server.log(), server.error() or agent.send()), it will be used. This behavior ensures compatibility with older code, but if your product has multiple interfaces, the use of RETURN_ON_ERROR makes your code a good candidate for conversion to manual mode, though this is not mandatory. However, you will not be able to make use of manual mode unless you also make use of either RETURN_ON_ERROR or RETURN_ON_ERROR_NO_DISCONNECT.

You need make no changes to your Squirrel application code to take advantage of legacy mode. However, you may do so if you wish to discover which is the current interface. Calling the new imp imp.net.getcurrentconfig() will return an object representing the current interface configuration. We’ll look at this method in more detail shortly. Calling imp.net.getserverinterfaces() will return a list of available interfaces. Again, we’ll discuss this method in more detail below.

Automatic Mode

If impOS’ default interface order is not be optimal for your application, you can set a preferred order using the new imp API method imp.net.setserverinterfaces(). This method takes as an argument an array of Network Interface Identifiers (NIIs) in the order you require.

Network Interface Identifiers

NIIs are pre-defined strings which can be used to specify one or more network interfaces. These include:

  • "wifi", "ethernet", "cell" — These are general identifiers indicating the type of interface. For imps with, for example, a single Ethernet port, "ethernet" will reference that port. If you are working with an imp with multiple Ethernet ports under impOS control, then "ethernet" will reference the first of these ports.
  • "wl0", "wl1", "wl2", etc. — Specific WiFi interfaces, as many as there are WiFi interfaces under impOS control. If there is only one such interface available, then "wl0" and "wifi" both identify that interface.
  • "eth0", "eth1", "eth2", etc. — Specific Ethernet interfaces, as many as there are Ethernet interfaces under impOS control. If there is only one such interface available, then "eth0" and "ethernet" both identify that interface.
  • "cell0", "cell1", "cell2", etc. — Specific cellular interfaces, as many as there are cellular interfaces under impOS control. If there is only one such interface available, then "cell0" and "cell" both identify that interface.

All of these identifiers are available even if your application lacks the interfaces they reference. It is possible to refer to, say, "ethernet" in code running on an imp equipped with only a WiFi interface. Under automatic mode, any references your code makes to unavailable interfaces when it calls imp.net.setserverinterfaces() are ignored, as are repeated references.

If you don’t include an available interface in your list, impOS will not make use of it if other interfaces fail to connect. However, this does not mean that the omitted network interface is disabled — it is simply not used as a failover and may continue to draw power if it has previously been enabled. Interfaces which have never been enabled will not draw power, but it is possible that they may be enabled by impOS itself (see Override Mode, below).

Setting The Current Interface List

The following examples show how you can apply imp.net.setserverinterfaces() using NIIs.

// Attempt to connect to WiFi first, and if this fails,
// failover to cellular
imp.net.setserverinterfaces(["wifi", "cell"]);

// Attempt to connect to Ethernet first (ports in sequence) and then
// failover to WiFi and then to cellular
interfaceArray <- ["eth0", "eth1", "wifi", "cell"];
imp.net.setserverinterfaces(interfaceArray);

The Squirrel array passed into imp.net.setserverinterfaces() may be retained, as in the second example above, but subsequently altering that array will not affect the interface usage order unless your code calls imp.net.setserverinterfaces() again with the updated array as its argument.

You can apply a new list at any time, but unless you manually disconnect and reconnect, the current interface will not change until there is an unexpected disconnection, ie. when impOS next connects automatically. However impOS reconnects at this point, it will start working with the first interface in the current sequence.

Any list you apply to enable automatic mode, or to change the sequence while the imp is already in automatic mode, will be maintained across subsequent device restarts, including power-cycles. The sequence is written to non-volatile memory and so will also persist after Squirrel changes such as a change of Device Group. To return to legacy mode, you must first explicitly re-enable the default network interface list.

Getting The Current Interface List

To retrieve the current network interface failover sequence, whether impOS' default or one set by you, call imp.net.getserverinterfaces(). It returns an array of NII strings. Again, if you subsequently alter the array you receive, the change will not be applied until you call imp.net.setserverinterfaces().

Resetting The Interface List To The Default

If you wish to clear a sequence of interfaces that you have provided, and revert to impOS’ default list, call imp.net.setserverinterfaces() with an empty array as its argument:

// Go back to default interface list
imp.net.setserverinterfaces([]);

This moves the imp from automatic mode into legacy mode.

Manual Mode

Manual mode allows your code to specify which of the available network interfaces is used to connect, and when. New imp API methods are available to your code for this purpose. These methods make use of a new data structure called a Network Interface Configuration (NIC).

To make use of manual mode, you must first have set the imp’s reconnection policy to either RETURN_ON_ERROR or RETURN_ON_ERROR_NO_DISCONNECT using server.setsendtimeoutpolicy(). Attempting to use manual mode under the SUSPEND_ON_ERROR policy will cause an exception to be thrown.

Important Manual mode allows you to bring up multiple interfaces and have them operate simultaneously: for example, cellular for connection to the impCloud server and Ethernet for connections to local devices. You should consider the power implications of having multiple interfaces operating at the same time, as this may have a significant impact on your product’s power consumption.

What Is A NIC?

A NIC is a Squirrel table containing one or more of the following keys. Only interface is mandatory; the other keys are optional and should only be used if the network you are connecting to requires them.

NIC Key Data Type Required? Relevant Interfaces Description
interface String Yes Ethernet, WiFi, cellular The name or type of the interface through which to attempt the connection. Example values are listed above
staticconfig Table No Ethernet, WiFi Optional static network configuration. For a list of accepted keys, see below
proxy Table No Ethernet, WiFi Optional proxy server configuration. For a list of accepted keys, see below
wificonfig Table No WiFi Optional WiFi configuration. For a list of accepted keys, see below

Static Network Configurations

Key Data Type Required Description
ip String Yes The desired static IPv4 address, eg. "192.168.0.128"
netmask String Yes The network’s IPv4 address mask, eg. "255.255.255.0"
gateway String Yes The network gateway’s IPv4 address, eg. "192.168.0.0"
dns Array of strings Yes An array of 1-2 strings, each the IPv4 address of a DNS server

Proxy Configurations

Key Data Type Required Description
proxyType Constant Yes Currently must be PROXY_TYPE_HTTP
address String Yes The proxy server address in dotted quad or a resolvable form, eg. "192.168.0.128" or "proxy.electricimp.com". Up to 64 characters in length
port Integer Yes Port number between 0 and 65535
username String No An optional server login username. Up to 32 characters in length
password String See Description The server login password. This is required if a username is included in the configuration. Up to 32 characters in length

WiFi Configurations

Key Data Type Required? Description
ssid String Yes The name of the wireless network
key String or Blob No The key for the wireless network (if any). Plain text keys are passed as strings; encrypted keys are blobs

Manual Mode Methods

Manual mode introduces two new imp API methods:

These methods both rely on NICs to communicate interface settings with your application. For example, to initiate a connection to a specific interface, create a new NIC (or retrieve an existing one), and pass it into server.connectwith() as the method’s first argument. The method also takes a callback function which will be executed whether the connection attempt succeeds, fails or times out.

As such, it operates exactly like the existing method server.connect() but allows you to specify which interface is used. You will typically use server.connectwith() where you might previously have used server.connect() (you can still use both, if you wish) and so manual mode is solely intended to be used on imps whose connection policy has been set to RETURN_ON_ERROR or RETURN_ON_ERROR_NO_DISCONNECT. Indeed, it can’t be used under SUSPEND_ON_ERROR; an exception will thrown if it is.

If the connection attempt succeeded, then the interface described by the NIC is said to be active and is now the current interface. Your code can use imp.net.getcurrentconfig() to retrieve a NIC which describes the current interface.

Note The use of imp.net.getcurrentconfig() is also available in any mode. Even if the imp connects automatically under impOS control, or connection is mediated by the existing imp API method such as server.connect() or agent.send(), it will have a current interface which is described in the NIC returned by imp.net.getcurrentconfig().

Encrypted Attributes

When generated in Squirrel, certain NIC attributes, such as a static network configuration’s password and a WiFi network’s passphrase, will be provided in plain text. Once a NIC has been successfully used to connect to the impCloud, it can be retrieved using imp.net.getcurrentconfig(). The NIC returned by this method will not contain passwords in plain text but in encrypted form for security. Passwords are encrypted using a per-device key and cannot be recovered from a NIC, but they can be saved for future re-use on the device, as can the NIC itself.

However, please bear in mind that if the network’s SSID, password and/or security type (eg. WEP, WPA2) change, then the stored NIC can no longer be used to connect to that network.

Network Configuration Persistence

Selecting a WiFi network interface and using it to connect to the impCloud by calling server.connectwith() does not cause that network to be saved in the imp’s persistent storage for use when the imp next reboots (ie. following a power-cycle, a wake from deep sleep, a call to server.restart() or a call to [imp.reset()(/api/imp/reset)). After such circumstances, the imp will typically reconnect using the network details written to persistent storage during BlinkUp™ or by a call to the imp API method imp.setwificonfiguration().

You should therefore consider any network connection changes made using the new network interface management system as limited to the current runtime only. If your application uses server.connectwith() to change from the persisted network to another network, it will need to do so every time the imp is power-cycled or wakes from sleep.

Note The interface sequence set by calling imp.net.setserverinterfaces() is written to non-volatile memory and will persist even after a cold boot and after Squirrel changes such as a change of Device Group.

If you are using the RETURN_ON_ERROR policy, the imp will not reconnect automatically upon waking from sleep or server.restart() call until your code calls server.connectwith(), server.connect() or any other imp API method that communicates with the server, such as server.log(). Be aware of how your code might reconnect after a restart: if reconnection is not initiated by server.connectwith() but by these other imp API methods, it will connect using the persisted WiFi network, if any.

Adding Network Persistence

If you want the imp to reconnect to the network defined in the NIC passed into server.connectwith(), you must either check the network in use after the reboot and, if necessary, switch to a NIC that you have persisted manually, or call imp.setwificonfiguration() when you call server.connectwith() when you first use server.connectwith() in order to record the change. For example:

local nic = { "interface"  : "wl0",
              "wificonfig" : { "ssid" : "fintlewoodlewix",
                               "key"  : "verybadpassw0rd!" }};
server.connectwith(nic, function(result, interfaceName) {
    if (result == SERVER_CONNECTED) {
        // Persist the WiFi config for the next reboot
        imp.setwificonfiguration(nic.wificonfig.ssid, nic.wificonfig.key);
    }
});

You can clear the persisted WiFi settings with imp.clearconfiguration() but beware that, until you apply new persistent WiFi settings, this will cause the imp to fail to connect upon restart.

The Persisted Network As A Back-up

This process enables some new use-cases. For example, you might choose to activate your production devices in the factory to a default network. This is the persisted network. As part of end-user set-up, you capture the end-user's network and apply it not by BlinkUp but by embedding the local network details in a NIC (which can be saved in Squirrel-accessible SPI flash) and passing that NIC into server.connectwith(). This way, the factory-set network is always present as a back-up — perhaps field engineers use a cellular-enabled WiFi hotspot set to host this default network.

When you consider such applications, you should bear in mind that, a power-cycled imp will always try to connect to the network to determine if it needs to download fresh Squirrel. If it cannot contact the default network, this will be signalled on the status LED. However, after ten seconds it will start its current Squirrel, which will presumably load a NIC and connect using it early on.

Single-interface imps

As noted above, on imps equipped with a single network interface, such as the imp001 through imp004m, it is not necessary to use NICs or the manual mode imp API methods; server.connect() and other existing imp API methods, such as imp.setwificonfiguration(), are sufficient.

However, you may use the new interface management system if you wish. For example, if your product is based on the imp003 and uses only the impOS-managed WiFi sub-system, the following code blocks, though different (the first uses existing calls; the second the new calls), are equivalent in all but one respect: the first overwrites the persistent configuration (set by BlinkUp™; see ‘Network Configuration Persistence’) while the second does not.

Old Mechanism

// Assume we have an array of accessible WiFi networks...
local wlans = [];
local currentwlan = 0;

function doSwitch() {
    // Switch to the next WLAN on the list...
    switchwifi();

    // ...and attempt to connect to it
    reconnect();
}

function switchwifi() {
    // Switch to the next WLAN on the list
    currentwlan++;
    if (currentwlan >= wlans.len()) currentwlan = 0;
    local wlan = wlans[currentwlan];
    imp.setwificonfiguration(wlan.ssid, wlan.psk);
}

function reconnect() {
    // Make sure we've sent all we're currently trying to send
    server.flush(30);

    // Disconnect from the current network
    server.disconnect();

    // Connect to the new proposed current network
    server.connect(function(outcome) {
        local wlan = wlans[currentwlan];
        if (outcome == SERVER_CONNECTED) {
            server.log("Connected via " + wlan.ssid);
        } else {
            server.error("Could not connect to " + wlan.ssid);

            // Try the next WLAN on the list
            doSwitch();
        }
    });
}

// Wait for a message from the agent (via control app or web UI)
// to trigger a network configuration change
agent.on("change.wifi", function(ignored) {
   doSwitch();
});

New Mechanism

// Assume we have an array of accessible WiFi networks...
local wlans = [];
local currentwlan = 0;

function doSwitch() {
    // Switch to the next WLAN on the list...
    local nic = switchwifi();

    // ...and attempt to connect to it
    reconnect(nic);
}

function switchwifi() {
    // Switch to the next WLAN on the list
    currentwlan++;
    if (currentwlan >= wlans.len()) currentwlan = 0;
    local wlan = wlans[currentwlan];
    return { "interface"  : "wifi",
             "wificonfig" : { "ssid" : wlan.ssid,
                              "key"  : wlan.psk }
    };
}

function reconnect(nic) {
    // Make sure we've sent all we're currently trying to send
    server.flush(30);

    // Disconnect from the current network
    server.disconnect();

    // Connect to the new proposed current network
    server.connectwith(nic, function(outcome, ifname) {
        local wlan = wlans[currentwlan];
        if (outcome == SERVER_CONNECTED) {
            server.log("Connected via " + wlan.ssid);
        } else {
            server.error("Could not connect to " + wlan.ssid);

            // Try the next WLAN on the list
            doSwitch();
        }
    });
}

// Wait for a message from the agent (via control app or web UI)
// to trigger a network configuration change
agent.on("change.wifi", function(ignored) {
    doSwitch();
});

Override Mode

There is a fourth network management mode, but this is one which is not application-selectable. Automatic mode may be temporarily overridden by impOS if it needs to do so in order to complete an operating system upgrade or perform a Squirrel recovery. Once the override mechanism activates, the imp goes back to legacy mode until imp.net.setserverinterfaces() is called again. It can also be overridden in server.connect() calls if all of the interfaces from the applied interface list fail to connect.