or, bumbling your way into IoT
The Internet of Things is currently on everyone’s lips. It’s the facilitator par excellence, the solver of all problems, the liquidator of all costs and the divine messenger of communications to and from devices.
Or, it is an extra sinkhole of money and effort, yet another tool that takes more than it gives, another trinket in the long list of things that were to save the world. In essence, snake oil in binary.
The truth lies somewhere in between.
Here at Haaga-Helia University of Applied Sciences, we are putting together an IoT Proto Lab. Slightly before I learned of that effort and was brought to the team, I had designed a Moai statue that was able to take input from Arduino’s serial monitor, and turn that into Morse code. It was both beeped on a buzzer as well as blinked on a pair of LEDs, and displayed in cleartext on a LCD display. I thought it was rather cool.
Being locally clever is nice of course, but soon I was thinking of how to bring this little statue to the Internet of Things. Arduino is handy for many purposes, if you use the Uno model. To get a Uno to be Internet aware only means adding a WLAN shield, or if you have access to a wired LAN, an Ethernet shield. If you use Nano, the tiny brother of the Uno, you’re looking at a soldering job.
This also got me thinking about selecting a different System on a Chip (SoC) platform. ESP32 is an inexpensive but powerful option when you need connectivity without add-ons. I bought five of those for 28 euros, but since only four worked, I had a unit price of seven euros. It comes with everything you could ask for and then some.
This Internet issue brought up another thing. Arduinos are programmed in C, which isn’t really the language of champions when you want to discuss over the Internet. C is a very device-oriented language, whereas the Web is as device-independent environment as possible. So, it was a good time to move on from C to Python, another fine and open source programming language.
As I have shown in the three previous posts here, and here, and here, going Python is not a walk in the park, but it’s entirely doable. In fact, as you go past the hurdles, you begin to savor the feeling of frustration when the device obstinately refuses to answer your beckoning. And when you finally see the >>> that signals MicroPython is ready and willing to work for you, coffee will taste better than in a long while.
So, now I am assuming you have read the previous posts, as I now go into what it takes to get your Moai to converse across vast distances instead of a USB cable.
The full code will soon be available in GitHub under my account, but for now let’s just see the main points. I won’t address the conversion from C to Python regarding the local Moai, instead I will talk about the Python settings for entering the Web.
The function that takes you into the Internet is called connectWifi (there’s some code to control the LCD too, so don’t mind that bit):
def connectWifi(ssid,passwd): #function to connect to the Web
global wlan #declare a WLAN object
lcd.move_to(0, 0) #move LCD cursor to top left corner
lcd.putstr("Connecting to WLAN") #write the string to the LCD
wlan=network.WLAN(network.STA_IF) #create a wlan object
wlan.active(True) #Activate the network interface
wlan.disconnect()#Disconnect the last connected WiFi
wlan.connect(ssid,passwd) #connect wifi
while(wlan.ifconfig()[0]=='0.0.0.0'): #wait for connection
sleep_ms(1)
sleep_ms(1000) #hold on for 1 second
lcd.move_to(0, 0) #move cursor to top left corner
lcd.putstr("Connected to WLAN ") #write the string to LCD,
sleep_ms(1000) #hold on for 1 second
lcd.clear() #clear the LCD screen
return True
After this is done, you have a connection to the Internet.
To read something off the Web, you need to have a server to read from. I have one at the Sabulo site, so I could set up a little piece of text that the Moai can access with this function:
def getURLMessage():
try:
response = urequests.get(url)
if len(response.content) > 3:
lcd.putstr("Getting message\nfrom server\nstay tuned!")
sleep_ms(2000)
lcd.clear()
myRawNetMsg = response.content.decode('utf-8', 'ignore')
#lcd.putstr(myRawNetMsg)
#sleep_ms(5000)
myFinalMsg = myRawNetMsg.split('\n')
return(myFinalMsg)
else:
lcd.putstr("No server message -\nso I will advertise\nthe 3D and Robo Lab")
sleep_ms(2000)
myFinalMsg=""
lcd.clear()
return(myFinalMsg)
except Exception as e:
print(e)
sleep_ms(100)
In this function, you will first see the ingenious device called Try in Python. Any code inside a Try – Except pair is executed, but if something goes wrong, it will enter the Except code and do whatever is coded there. This means your device may crash, but the Except bit can be made to handle any eventualities, including a reboot.
The actual data is lifted from the server via the urequests object. The URL is passed to the function, and it gets the content of the file into the variable response. If the length of that variable is 4 or less, we know there is no message, because the file contents then is just three newline characters. Otherwise, the response is then parsed into another string object, called myRawNetMsg, which in turn is processed into the final product, myFinalMsg. All this is necessary because the content type passed from the Web doesn’t match that on the ESP32.
That message is then passed through the rest of the Moai much in the same way it happened in the local version. What’s new is the ability to talk back. I have set up the system so that whenever it gets triggered, it writes an entry in a log file on the same server where the message manager sits. You need some code on the server too, but it is written in PHP, not Python. I’ll show that after the Python.
The code you need to send something is actually rather simple. Here you will see how I write information on the boot-up of the device. Whenever you want to send some data back to the website you run, it only takes this much code:
url = "insert_your_url_here"
headers = {'content-type': 'application/json'}
data = {'message': 'Boot sequence','crash': 'LatestMoaiUpload.py'}
jsonObj = json.dumps(data)
resp = urequests.post(url, data=jsonObj, headers=headers)
The URL points to your PHP file. Headers contain some auxiliary data for the transfer to work. Data is the actual beef here – the ‘message’ key now contains the data ‘Boot sequence’, and the ‘crash’ key contains the data on the version of the software that is currrently in use. The jsonObj is the object that uses the well-known JSON structures to prepare the message for transfer, and finally, the urequests object’s post method sends it out.
I use the crash key for two purposes, so it probably could be called something a little less dramatic. But anyway, all that you have to pay attention to is that your keys in the ESP32 message match those that the receiving PHP file is expecting to see. This is how the PHP looks:
$_POST = json_decode(file_get_contents('php://input'), true);
$message = $_POST["message"];
$crash = $_POST["crash"];
$myYear = date("Y-m-d");
$myHour = date("H:i:s");
$myFile = "place_your_file_name_here";
$fh = fopen($myFile, 'a') or die("can't open file");
fwrite($fh, $message);
fwrite($fh, "\t");
fwrite($fh, $myYear);
fwrite($fh, "\t");
fwrite($fh, $myHour);
fwrite($fh, "\t");
fwrite($fh, $crash);
fwrite($fh, "\n");
fclose($fh);
The variable $_POST contains the input stream. From it, the data is parsed for the message and the crash, placed in their own variables. Time and date can be acquired from the server as shown, so we don’t need to use the real time clock on the ESP32. The rest of the script is a simple file write operation. This is what collects into the text file on the server
WLAN connected 2018-11-07 11:12:12
Boot sequence 2018-11-07 11:12:13 LatestMoaiUpload.py
Trigger server 2018-11-07 11:12:17
Trigger server 2018-11-07 11:29:46
Trigger server 2018-11-07 12:28:44
So, in essence, Internet of Things is nothing special. It’s just a regular device that has been given a way of communicating with a server. And given the vast array of sensors available today, for really small money, there’s no reason not to try this, if you have a need for such systems. The SoC devices are available and reasonably priced, the integrated development environments contain everything you need, and all it really takes is the idea. And it’s a good idea to remember LoRa, which is a handy long-range WLAN system for devices that aren’t right next to an access point.
As it happens, we at Haaga-Helia IoT Proto Labs will soon be working with real clients, developing proof of concept systems for their Internet of Things needs. With our 3D printers for making housings and other auxiliary parts, we can deliver the entire system for you to try out IoT for very little cost.
Let’s be in touch!