Tuesday, February 05, 2019

Easy IoT with Ubuntu Core and Raspberry Pi

My current job involves me mostly working in the upper layers of the desktop software stack however I started out working in what was then called embedded engineering but now would probably be know as the Internet of Things (IoT). I worked on a number of projects which normally involved taking some industrial equipment (radio infrastructure, camera control system) and adding a stripped down Linux kernel and an application.

While this was cutting edge at the time, there were a number of issues with this approach:
  • You essentially had to make your own mini-distribution to match the hardware you were using. There were some distributions available at the time but they were often not light weight enough or had a financial cost.
  • You had to build your own update system. That comes with a lot of security risks.
  • The hardware was often custom.
The above issues meant a large overhead building and maintaining the platform instead of spending that time and money on your application. If you wanted to make a hobby project it was going to be expensive.

But we live in exciting times! It's now possible to use cheap hardware and easily accessible software to make a robust IoT device. For around $USD60 you can make a highly capable device using Ubuntu Core and Raspberry Pi. I decided to make a device that showed a scrolling LED display, but there are many other sensors and output devices you could attach.

The Raspberry Pi 3 A+ is a good choice to build with. It was just recently released and is the same as the B+ variant but on a smaller board. This means you save some money and space but only lose some connectors that you can probably live without in an IoT device.



I added an SD card and for protection put it in a case. I chose an nice Ubuntu orange colour.


Next step was to connect up a display (also in Ubuntu orange). Note this didn't need the wires - it should fit flat onto the case but I spent too much time photographing the process that I accidentally soldered on the connector backwards. So don't make that mistake... 😕


Final step was to connect a USB power supply (e.g. a phone charger). The hardware is complete, now for the software...

Using Ubuntu Core 18 is as simple as downloading a file and copying it onto the SD card. Then I put the SD card into the Raspberry Pi, powered it on and all I had to do was:
  1. Select my home WiFi network.
  2. Enter my email address for my Ubuntu SSO account.
  3. Secure shell into the Raspberry Pi from my Ubuntu laptop.
The last step is magically easy. If you connect a screen to the Pi it shows you the exact ssh command to type to log into it (i.e. you don't have to work out the IP address) and it uses the SSH key you have attached to your Ubuntu SSO account - no password necessary!

$ ssh robert-ancell@192.168.1.210

Now to write my application. I decided to write it in C so it would be fast and have very few dependencies. The easiest way to quickly develop was to cross-compile it on my Ubuntu laptop, then ssh the binary over the the Pi. This just required installing the appropriate compiler:

$ sudo apt install gcc-arm-linux-gnueabihf
$ arm-linux-gnueabihf-gcc test.c -o test
$ scp test robert-ancell@192.168.1.210:
$ ssh robert-ancell@192.168.1.210 ./test

Once I was happy my application worked the next step was to package it to run on Ubuntu Core. Core doesn't use .deb packages, instead the whole system is built using Snaps.

All that is required to generate a snap is to fill out the following metadata (running snapcraft init creates the template for you):

name: little-orange-display
base: core18
version: git
summary: Demonstration app using Ubuntu Core and a Raspberry Pi
description: |
  This is a small app used to demonstrate using Ubuntu Core with a Raspberry Pi.
  It uses a Scroll pHAT HD display to show a message.

architectures:
  - build-on: all
    run-on: armhf

grade: stable
confinement: strict

apps:
  little-orange-display:
    daemon: simple
    command: display-daemon
    plugs:
      - i2c

parts:
  little-orange-display:
    plugin: make
    source: .


This describes the following:
  • Information for users to understand the app.
  • It is an armhf package that is stable and confined.
  • It should run as a daemon.
  • It needs a special access to I2C devices (the display).
  • How to build it (use the Makefile I wrote).
To test the package I built it on my laptop and installed the .snap file on the Raspberry Pi:

$ snapcraft
$ scp little-orange-display_0+git.aaa6688_armhf.snap robert-ancell@192.168.1.210:
$ ssh robert-ancell@192.168.1.210
$ snap install little-orange-display_0+git.aaa6688_armhf.snap
$ snap connect little-orange-display:i2c pi:i2c-1
$ snap start little-orange-display

And it ran!
 

The last stage was to upload it to the Snap store. This required me to register the name (little-orange-display) and upload it:

$ snapcraft register little-orange-display
$ snapcraft push little-orange-display_0+git.aaa6688_armhf.snap

And with that little-orange-display is in the store. If I wanted to make more devices I can by installing Ubuntu Core and enter the following on each device:

$ snap install little-orange-display
$ snap connect little-orange-display:i2c pi:i2c-1
$ snap start little-orange-display


And that's the end of my little project. I spent very little time installing Ubuntu Core and doing the packaging and the majority of the time writing the app, so it solved the issues I would have traditionally encountered building a project like this.

Using Ubuntu Core and Snaps this project now has following functionality available:
  • It automatically updates.
  • The application I wrote is confined, so any bugs I introduce are unlikely to break the OS or any other app that might be installed.
  • I can use Snap channels to test software easily. In their simplest usage I can have a device choose to be on the edge channel which contains a snap built directly from the git repository. When I'm happy that's working I can move it to the beta channel for wider testing and finally to the stable channel for all devices.
  • I get metrics on where my app is being used. Apparently it has one user in New Zealand currently (i.e. me). 🙂

No comments: