Are you working on a project involving connected devices and the Internet of Things, aka IoT? The number of fielded devices varies wildly among projects, so a particular project could encompass anything from a handful to millions of devices. Connected devices can be things like smart TVs, smart watches, home voice controllers, connected cameras, smart light bulbs and thermostats. You get the idea.
I want to discuss fielded devices connected to a central server – in this case, the AWS IoT Core service. For every IoT project, these fielded devices need to run software to connect to IoT Core. There are two ways to achieve this: A) write your own or B) use the Device Client.
Naturally, each approach brings its own benefits and drawbacks. In this blog, I’ll discuss both approaches, as well as share some important lessons I learned when attempting to follow AWS’ own instructions for installing and using the Device Client.
Connecting to IoT Core
Approach A: Write Your Own Software
But – you knew there was a but – that would require a significant time commitment, the right kind of knowledge, and the need to deal with devices on a lower level. While this approach makes sense for microcontrollers, not so much for devices fitted with processors. This option only really makes sense for projects that require a great level of control.
What if you don’t want to build from scratch? You could try a hybrid approach.
Approach B: Use the Device Client
The Device Client is a ready-made reference implementation of the software needed to interface with IoT Core, written by AWS itself with best practices baked in. It's a piece of software for Linux, therefore for devices with processors. It's also open source – Apache 2.0 license – and written in C++.
(Here's a brief overview of the Device Client.)
Being open source, you can modify it to your heart's content. This is the hybrid approach I mentioned earlier: pick the parts that implement the core functionality, and then customize on top of that. Or use it as is. Up to you!
If your devices have processors, using the Device Client makes sense for most use cases. Some of the features that ship with the Device Client include first connect, secure certificate provisioning, MQTT messaging, device state commands from a desktop or mobile client, remotely run scripts or reboot, secure SSH tunneling for maintenance, logging, and telemetry.
AWS Online Workshop
To help people install and use the Device Client, AWS published an online workshop. While informative, the workshop is not without its flaws. For instance, some of its instructions are faulty or incomplete, leaving the reader with problems that may disable important features or make them unusable – or prevent installation altogether.
I went through the whole process outlined in the workshop so you don't have to! I’ll share some of the important quirks and pitfalls I encountered along the way – as well as the solutions, of course.
To set the stage: the computing environment is an EC2 64-bit x86 t2.micro virtual machine, with Ubuntu Server 22.04. This is the device. I picked all the defaults when setting up the machine. (If you go this route, make sure to give it a public IP.)
Here’s what I learned.
Lesson #1: Some key info is missing.
Three of the dependencies aren't listed. Those are cmake, the libraries build-essential and libssl-dev. Without these the Device Client obviously won't install. So simply install these dependencies using the commands appropriate to your Linux distro, and you're good to go.
Lesson #2: The Device Client is finicky about permissions.
There are several points in the workshop at which you have to create directories and files. At these points, the workshop will tell you what permissions are needed. Follow these to the letter because the Device Client will check for the exact permissions on startup. Even if you give the user and the group more generous permissions, the Device Client won't start as a service and will instead log an error.
You can see all the permissions listed together in easy-to-read table format in the project's documentation on Github. You can find permissions here.
Lesson #3: The provided shell scripts don't deal well with relative paths.
The workshop provides two scripts, "build_execute.sh" and "quick_setup.sh". These scripts do exactly what their names imply: build the Device Client from source and walk you through quick configuration shell prompts. The scripts are provided so you can install the Device Client easily, without writing your own script or issuing shell commands.
Here’s the concern. The workshop suggests that you create resources under the directory "/home/ubuntu/workshop_dc/". If you decide to change this directory name, you'll have to inspect the files "build_execute.sh" and "quick_setup.sh" for the original directory "/home/ubuntu/workshop_dc/" and replace it with your chosen name everywhere you find it. When putting in your chosen directory name, make sure to use absolute paths. If you use relative paths, you'll get cryptic error messages that are difficult to debug.
Lesson #4: The config file must go in its rightful directory.
The script "quick_setup.sh" will place the config file in "/root/.aws-iot-device-client/aws-iot-device-client.conf". This will make your life more difficult when trying to inspect or write to the file, because it'll be under a directory owned by root. Instead, I suggest you run "quick_setup.sh" normally to completion (i.e. until you have the Device Client running as service) and then move the config file to the usual "/etc/.aws-iot-device-client/aws-iot-device-client.conf".
Don't forget to tell the Device Client where the config file is by running the command:
"aws-iot-device-client --config-file /etc/.aws-iot-device-client/aws-iot-device-client.conf"
Then restart the service with the command:
"sudo systemd restart aws-iot-device-client"
Lesson #5: Commands to control your devices are simpler than you think.
This is not in the workshop, but it is important. At some point you'll undoubtedly want to issue commands to your remote devices. Perhaps you want to control the color of a device’s LED using your mobile phone. The feature that makes this possible is called the device shadow. You issue commands by publishing a simple JSON message to your device's shadow-relevant topic.
I assume most people will, at first, tend to include more information in the message than is necessary. I know I did. This will create convoluted device states that are difficult to understand and difficult to trace. The way the IoT Core servers are set up are really lean in that regard, so stick to simplicity. A command message should be simply:
Pretty neat, right?
In summary, I’ll leave you with this. The Device Client works quite well and is chock full of IoT features. The project is alive and kicking on Github, with improvements and fixes being added regularly. It is an easy way to implement device-side IoT functionality – either take it as is, or customize to suit your needs.
For more on AWS, read my series Securing the Cloud with AWS.