What simple Squirrel code will give me always-connected WiFi-priority cellular-backup?

I need to have an imp006 breakout board in a place where it will be uploading a decent amount of data where there is both WiFi and cellular.

The site is at a different site from my home test site where there is different WiFi.

So I need code to 1) always maintain a connection and reconnect if lost, 2) memorize two WiFi networks (test and deployment) and use whichever is available, 3) switch over to cellular in the event that the WiFi becomes unavailable, and 4) switch back to WiFi from cellular once it resumes.

Q: How do I do this?

I have put a certain level of effort into reading the docs and trying to do this myself. However, what I have now is always eventually disconnecting. So figured I should be lazy and ask here, especially given the noble amount of help @hugo has given me, rather than further trying to figure it out myself since I am very new.

I am hoping to use this imp006 in a real-world deployment in 2 weeks if and when I can get the advertised WiFi and Cellular radio abilities to work seamlessly in software to maintain a WiFi-preferred connection.

Thank you for your help.

There’s no example code for this; you can rely on automatic fallback and just specify a long connection timeout (when you initialize connectionmanager), which is the easiest path. By default, wifi takes priority over cellular.

See https://developer.electricimp.com/reference/impnetworkmanagement for more detail.

In terms of multiple credentials, you’ll need to use the API to set each stored ssid/password in turn, or just scan for networks and set the one which you see available.

I’d recommend you hook up a UART to help debug connection switching code - see https://developer.electricimp.com/resources/disconnecteddebugging for some pointers.

Thank you @hugo.

I was befuddled why my imp006 was always permanently disconnecting. Then I realized that my usage of the example code line:

// Set the server connection behavior policy (makes server.connect() asynchronous)
server.setsendtimeoutpolicy(RETURN_ON_ERROR, WAIT_TIL_SENT, 10);

disabled the automatic behavior.

I would be happy to use the automatic behavior.

I would love to use imp.net.setserverinterfaces([“wifi”, “cell”]); and let impOS take care of the switching.

But, as you note, I would need to program both potential WiFi networks.

TL;DR Here: But imp.setwificonfiguration(ssid, key) does not take an array of networks. It only takes one WiFi network.

So it would appear that:
imp.setwificonfiguration(ssid, key)
imp.net.setserverinterfaces([“wifi”, “cell”]);

…would come close to my requirement by offering 1 WiFi network and cellular, but I have 2 WiFi networks I need to program, only one of which will be available at a given time (whether it is at my house for testing or in deployment).

So how can I program the automatic impOS management to take multiple WiFi ssid/key pairs without having to manually deal with confusing manual mode disconnection callbacks and the necessity for me to engage in more minutes/hours of perscrutation of the docs that I may be willing or able, to ensure that my selection of customized-behavior code calls do not create a circumstance where it can enter permanent disconnectivity, like I already have (above) by simply pasting example code and failing to realize that RETURN_ON_ERROR made there be a responsibility to me to handle switching/reconnection code that I was failing to fulfill?

Thank you again.

No, that line doesn’t affect automatic connection type cycling. That line lets code run when there’s no network connection. Connection type cycling will happen as long as there’s a long enough connect timeout in your server.connect() call (or in your connection manager initialization if you’re using that).

Correct, setwifi doesn’t take an array. You’ll need to write code for this - I suggested scanning for wifi networks before a connection and then setting credentials for the one that is found. Wifi scan is very easy to use.

As I said, there’s no code I can point you to here, it’s something you’ll need to write yourself.

@hugo Thank you for the reply. I am asking for additional assistance given my experience below, because it is very time-consuming to write and test custom Squirrel code (especially something so specific to the impOS like this), and test it, and make sure it is right.

The time it would require for me to do all this by myself is less than using Particle for cellular and a separate ESP8266 for WiFi - but, I want to use imp006 for this deployment.

I also think this question will come up against as ElectricImp grows, so I am not being selfish (and least not totally).

Here is what I tried with an unsatisfactory result:

cm <- ConnectionManager({
          "stayConnected": true,
          "connectTimeout": 600.0,
          "retryOnTimeout" : true
        });
imp.setwificonfiguration("wifi", "password")
imp.net.setserverinterfaces(["wifi", "cell"]);

I was under the impression this would automatically revert to WiFi connection when, having established a cellular back-up connection in the necessity (i.e., momentary WiFi loss), the WiFi became available again.

But I have found my device seemingly permanently in cell mode using the above code even when there was strong WiFi.

Then I encountered the following fine-print (it is cathartic for me to use the term “fine print” and please do not take offense as I have no accusation) from the docs,

"imp.net.setserverinterfaces([“wifi”, “cell”]);

In this case, impOS will first attempt to connect to the server through any available WiFi interface. If that fails, however, impOS will attempt to connect via any available cellular interface. To ensure that the imp connects to WiFi when it can, your code may need to manually disconnect after any cellular connection is made."

So the built-in functionality doesn’t do what I need. It just prioritizes WiFi over cell on the initial connection but not throughout the course of eternal microcontroller life (unlike a Windows PC program or web browser application, I am building a 24/7/365 connected monitoring software so the software needs to have eternal execution built into its design). So with any inevitable drop in WiFi, it will permanently go to cellular and spend money that can be avoided with WiFi.

Question: Could you generously share code which reverts back to WiFi once it becomes available, having previously switched-over to cellular? We can forget about my original two-WiFi-networks requirement. I can just program the deployment network credentials later.

Thank you. Given the whole ConnectionManager and extensive documentation, it would be difficult and unwise for me to take a stab at this on my own. And it seems like very basic behavior that will benefit other users. Thank you Hugo I know you’re busy and you’ve already been very generous to me.

As the docs say, if the device is happily connected, it will stay in that state until disturbed, then go back to the interfaces to try to connect in the prescribed order. It doesn’t seem hard for you to periodically scan wifi and if you see a usable wifi SSID in the scan results, then call disconnect and let the system retry the connections - falling back to cellular if the wifi network wasn’t usable.

We don’t have any code to share, as I noted before. If you need someone to write you some code, we can put you in touch with some partners who can quote for for this work.

@hugo

I am inhibited in my ability to implement my desired behavior by the seeming lack of clarity and necessary information in https://developer.electricimp.com/libraries/utilities/connectionmanager

  1. I am inhibited by the seeming lack of information on how “stayConnected = true” interacts with the callbacks. It does not appear to be stated whether “stayConnected = true” foils the onDisconnect callback for automated functionality. If I wish to implement WiFi scanning upon disconnect, it is not clear what “stayConnected” should be.

  2. I am inhibited by the difficulty in understanding how to set the interface with which imp will connect upon disconnects. “imp.net.setserverinterfaces([“wifi”, “cell”]);” already sets WiFi and Cell. Upon a WiFi disconnection, it is unclear how I would make imp reconnect using WiFi assuming the WiFi-unavailability was fleeting and immediately restored.

  3. I am inhibited by the lack of clarity on how ConnectionManager interacts with attempts to check for restored WiFi during cellular and attempt to switch back to WiFi. The documentation is crystal clear that the imp.wakeup() method can be used to schedule occasional tasks. The documentation is likewise crystal clear about how to detect whether the imp is currently connected over cell or wifi. However, it is not obvious what connection code should follow a cellular-connected WiFi-detected desired-switchover condition. It is not clear whether cm.disconnect() should be called, whether server.disconnect() should be called, and how this interacts with cm.stayConnected = true nor subsequent reconnection using WiFi (see #2 above).

  4. These difficulties are exacerbated by a paucity of community forum posts and Squirrel code content on the internet compared to traditional C-based Arduino platforms. This becomes a business consideration because there is a time cost associated with figuring out how to stably implement what I want in Squirrel where experimentation is necessary in view of less-than-thorough documentation/examples, unless I am missing something. I hope this thread can be of benefit to other new imp users if a solution is attained. I have promoted ElectricImp to a few people.

Thank you.

The connection manager is fully open source; many of your questions about CM are not hard to answer if you look at the code. It has a lot of comments.

Connectionmanager does not deal with switching; it deals with making a connection and keeping the connection up. Anything above that is application-specific behavior.

At any wifi connect attempt, if the wifi network is not found then it’ll move onto the next network interface. It doesn’t matter if the network is unavailable for 10 seconds - the device has no way to tell that the network is just about to come back. As noted, the easy solution here is to scan wifi regularly when you’re on cellular and call disconnect if you see your target network. Have you actually tried this? Seems like a very simple solution to your problem.

If you look at the CM source you’ll see what the CM disconnect call does; it sets the internal flag (which is checked by the watchdog to see if a reconnection attempt is needed) to false, so no automated connection attempts will happen again, then it calls server.disconnect. You would want to call cm.disconnect, then cm.connect to start a fresh connection attempt.

1 Like

Thank you @hugo. Let me put some more effort into this with your guidance.