Robust Wi-Fi Connections
A solid and robust Wi-Fi® link forms the backbone of safe and high-performing Web, MQTT, SSH, SSL/TLS, and other Internet Protocol sessions.
The Wi-Fi article describes how to automatically start the Wi-Fi service at boot time. Once you have that initial connection, we provide here some hints on restoring it when needed.
Knowing When to Retry
The "remote" Arduino sketch from our ARTIK Cloud Actions tutorial uses the following code to reconnect if the Wi-Fi connection is lost.
1 2 3 4 5 6 7 8 9 10 | if (!mqttClient.connected()) { DebugSerial.println("reconnecting"); mqttClient.connect(mqttClientName); delay(500); if (mqttClient.connected()) { retryCount = 0; mqttClient.subscribe("compOnCtl"); } else retryCount = retryCount + 1; if (retryCount > 10) mqttClient.disconnect(); |
The key requirements are:
- Put the
connect()
command andconnected()
test in the mainloop
code. - If not connected, try a new
connect
to see if the system can reconnect on its own. - If still not connected after several retries, force a
disconnect
and then try connecting again. - Remember to re-subscribe to MQTT topics after a new connection is made.
The "master" sketch does not have this reconnect mechanism, but if you choose to put it in, just follow the "remote" code as a guide.
Keeping a Closer Watch
The mqttClient.connected()
test may take a long time (maybe even minutes) to return a false
status after a loss of connection. If you need something more timely, you may want to experiment with this command:
iw wlan0 link
It tells you the current link status. You can use runShellCommand
to call it from your sketch as in the previous tutorial, and use grep
and awk
(like we did in the runShellCommand
here) to isolate key words you need to decide whether the link is up.
Connecting to the Right Server
In our ARTIK Cloud Actions tutorial, we put in some code for the ARTIK remote client to automatically locate the MQTT server on the network. Our code was simple and assumed that we would only find a single MQTT server on our local network.
What we would like to do is take this code out of the sketch and make it a script that runs right after boot. Moreover, we would like to assign its findings to the /etc/hosts
file so that any sketch we bring up will be able to call for the MQTT server port by name. We'll do this with a shell script.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/bin/bash ip neigh | grep 'lladdr' | grep -F '.' | awk '{ print $1 }' > ipneighbors echo "Trying:" cat ipneighbors | \ while read IPADDR; do echo $IPADDR CURLCMD="https://"$IPADDR":8883" curl -vs --connect-timeout 2 $CURLCMD 2>&1 | grep 'Connected' if [ $? = 0 ]; then echo "mqttserver assigned as " $IPADDR echo $IPADDR "marks-iot-srvr" >> /etc/hosts fi done |
How It Works
The ip neigh
command works as it did when the code was in the ARTIK Remote sketch, compiling a list of all devices on the local Wi-Fi network. Likewise, curl
attempts a connection as in that sketch, but this time looks only for secure SSL/TLS connections (note the https://
prefix and :8883
suffix).
If a match is found, the code associates the IP address with a Common Name, which you decide on to be the one shared between the MQTT broker and clients. Here we're using marks-iot-srvr
as an example of a Common Name. In our simple demonstration script, we are just appending the IP address and its Common Name to the /etc/hosts
file:
10.0.0.3 marks-iot-srvr
but in yours, you will probably want to search and replace any existing instance of the IP address or Common Name (using sed
, for example).
Note that our script code associates the first IP address it comes across that is both MQTT and SSL/TLS-secured. What if the association is a mistake? Perhaps there is a second MQTT broker using this same Wi-Fi network. Is security compromised?
Remember that to achieve an SSL/TLS-secured connection, the transmitted server certificate must:
-
Have a Common Name that matches an entry in the client
/etc/hosts
file -
Be signed by the CA certificate already stored on the client.
If another MQTT server on the network is not one authorized by you, then its certificate will not meet the above requirements, and no insecure connection can take place.
You could make this script more robust by using an openssl
command to verify the Common Name on the server certificate. You may also want to put in a test that will recover gracefully when no broker is found at all (for example, when the Wi-Fi router is unplugged).