Skip to main content

server.connectwith(nic, callback, timeout)

Attempt to connect to the impCloud using a specified network interface

Availability

Device

Parameters

Name Type Description
nic Table Settings for the network interface to be used to connect
callback Function A function to be called when the connection attempt succeeds or fails
timeout Integer An optional timeout in seconds for the connection attempt.
Default: 120s for cellular; 60s for WiFi/Ethernet

Returns

Nothing

Description

This method attempts to connect the imp to the Electric Imp impCloud™ using a specific imp Network Interface Configuration (NIC) which is passed into the method’s first parameter. A NIC is a table containing one or more of the following keys, the first of which is mandatory:

Key Data Type Required? Description
interface String Yes An identifier for the interface through which to attempt the connection, eg. "wl0", "eth0", "cell0"
proxyconfig Table No Optional proxy server configuration. Not applicable to cellular connections, only Ethernet and WiFi. For a list of accepted keys, please see imp.setproxy()
staticconfig Table No Optional static network configuration. Not applicable to cellular connections, only Ethernet and WiFi. For a list of accepted keys, please see imp.setstaticnetworkconfiguration()
wificonfig Table No Optional WiFi configuration. Not applicable to ethernet or cellular connections, only WiFi. The keys are listed below

The keys used in the wificonfig table are:

Key Data Type Required? Description
key String or blob Yes The key for the wireless network (if any). Plain text keys are passed as strings; encrypted keys are blobs. In the case of an open network, pass in null or an empty string ("")
ssid String Yes The name of the wireless network

server.connectwith() is only available if you have selected the RETURN_ON_ERROR or RETURN_ON_ERROR_NO_DISCONNECT reconnection policies, as applied using server.setsendtimeoutpolicy(). Calling server.connectwith() while the SUSPEND_ON_ERROR policy is in force — the default policy at start-up — will cause an exception to be thrown.

For example:

local nic = { "interface"  : "wl0",
              "wificonfig" : { "ssid" : "fintlewoodlewix",
                             "key"  : "verybadpassw0rd!" }
};

server.connectwith(nic, function(result, interfaceName) {
    if (result == SERVER_CONNECTED) {
        server.log("Connected to impCloud via interface " + interfaceName);
    } else {
        server.error("Could not connect to impCloud via interface " + interfaceName);
    }
});

If you call server.connectwith() on interface B, while there is an existing impCloud server connection on interface A, the imp will immediately disconnect from interface and power it down. It will then attempt to connect with interface B. Interface A will have to be opened again if it is to be re-used, eg. for local networking.

Calling server.connectwith() and providing a NIC that defines a WiFi network will not cause that network’s SSID and password to be recorded in the imp’s persistent storage. If the imp subsequently reboots (eg. after deep sleep or a power-cycle), the current WiFi network will be set to whichever network is recorded in persistent storage and will be used in any attempt to connect automatically, eg. by calling agent.send(), server.connect() or server.log(). To ensure the network activated via server.connectwith() is used in these circumstances, call imp.setwificonfiguration() to store its SSID and password in persistent storage.

The Callback

Once called, server.connectwith() will attempt to connect to the server using the supplied settings. It does not block. Whether it succeeds, fails or the timeout period is exceeded, the function passed into the method’s callback parameter will be executed. This function should have two parameters of its own: result and interfaceIdentifier. The latter is the interface’s identifier string (set in the NIC, above). The result parameter receives an integer status code. It can take any of the following standard (as per server.connect()) outcome values:

Constant Value Description
SERVER_CONNECTED 5 The server is connected
NOT_CONNECTED 0 The imp is not able to connect for a reason other than those listed below
NO_WIFI 1 Failed to join WiFi
NO_LINK 1 Failed to connect via Ethernet. imp005 only
NO_IP_ADDRESS 2 Failed to get an IP address
NOT_RESOLVED 3 The IP address of an Electric Imp server or proxy could not be resolved
NO_SERVER 4 Failed to connect to the Electric Imp server
NO_PROXY 6 The imp cannot connect via saved proxy address and port
NOT_AUTHORISED 7 The imp cannot connect because its proxy access credentials have been rejected
NO_MODEM 8 The imp cannot detect a modem. Cellular specific
SIM_ERROR 9 The imp cannot communicate with the modem’s SIM card. Cellular specific
NO_REGISTRATION 10 The imp could not detect a cellular network. Cellular specific
REGISTRATION_DENIED 11 The imp was not allowed to access the cellular network. Cellular specific
NO_PPP_CONNECTION 12 The imp could not establish a PPP connection. Cellular specific
PPP_NO_CONNECTIVITY 13 The imp could not establish an Internet connection. Cellular specific

The values assigned to the constants may change in a future impOS release.

Your code should always check the value of result before proceeding.

Timeouts

The default timeout is 120 seconds for cellular connection attempts; for connections using WiFi or Ethernet it is 60 seconds.

Re-using Interface Tables

If the connection made with server.connectwith() was successful, the NIC can be retrieved using imp.net.getcurrentconfig(). The NIC can then be saved to persistent storage for future server connection attempts using server.connectwith(). You should use the NIC returned by imp.net.getcurrentconfig() in preference to the NIC used to initiate the connection (as in the example, above) because impOS encrypts sensitive data, such as a supplied WiFi password or proxy password. The NIC returned by imp.net.getcurrentconfig() includes the encrypted forms of these values, if present.

Network Configuration Persistence

impOS preserves network configuration information in persistent storage, but it only does so in certain circumstances: when BlinkUp™ takes place, and when code calls the imp API methods imp.setwificonfiguration(), imp.setstaticnetworkconfiguration() or imp.setproxy().

If you provide extended configuration information in a call to server.connectwith(), ie. you include any of the ...config keys described above, impOS will not retain this information in persistent storage. If the connection attempt fails, or if the attempt to connect is successful but the connection is subsequently lost for any reason at all, including Squirrel virtual machine restarts, device power-cycles, and manual and unexpected disconnections, then the supplied configuration will be discarded and will not be used by impOS in any further connection attempts.

This is also the case if you call server.connect() while the imp is connected after making a call to server.connectwith() that included an extended NIC.

Under the RETURN_ON_ERROR policy, the imp does not reconnect automatically upon waking from sleep or a 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() or agent.send(). If reconnection is not initiated by a call to server.connectwith() that includes an extended NIC, it will connect using a stored network configuration, if there is one.

The only way to re-use an extended NIC in any connection attempt is to pass it in to a server.connectwith() call. See Re-using Interface Tables, above.

If you call server.connectwith() and simply name an interface in your NIC, eg. {"interface" : "wl0"}, then impOS will use that interface for all future connections, or until an alternative interface is specified. Interfaces that required extra information to connect — for example, WiFi connections may require an SSID and password to be supplied — will make use of persisted configuration data in this instance. If there is no relevant configuration data available, the connection attempt will fail.

Note The identifier wifi refers to a class of interface. You cannot include a config key when you are referencing a class identifier — you must reference a specific interface instance, as in the code example below. To address a specific instance of that interface, use wl0, wl1, cell0, eth0, etc. Unless you have multiple interfaces of a given class, you typically only need to reference the ..0 interface of that class when applying settings. But though wl0 and wifi are synonymous in this case, they are not identical.

Example Code

The following code demonstrates the use of server.connectwith() to switch between multiple WiFi networks to which the host imp is allowed to join.

// 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"  : "wl0",
             "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();
});