(#22) Amazon's Internet of Things Play
Navigating the waters (avoiding the piranhas)
I've been making half-hearted attempts at some Cloud players in the IoT space. The two worth a blogpost are Microsoft's and Amazon's. I'll hold off on Microsoft Azure for awhile, but suffice to say after a few days in URL-hell, after fighting their makefiles, I bailed.
I'll come back to Azure, but I couldn't see any reason to continue the fight. They had their expectations and those weren't mine. Also 30 days of a "probably" free trial run on Azure wasn't anywhere close to sufficient. So I said "See ya' later -- maybe." to Azure.
Enter Amazon's AWS IoT play. Well documented, free, an SDK, free, a port to the Raspberry Pi and free. Did I mention it's free? Twelve months of free? And this is not free as in free beer, but free as in beer that costs $0.00.
While well documented, I bumped my head a few times. Perhaps this post will help you avoid whacking your head on the same obstacles.
Recapping my setup
- I'm predominately a consumer of IoT data. I'm not a maker -- I produce IoT events (as MQTT messages) under duress. I only create events because I need them to satisfy my needs for consuming them.
- As a consumer, I'll probably take a number of shortcuts (aka hacks) in these posts on AWS IoT. Again, I'm trying to get my equipment to send IoT events as quickly and as painlessly as possible.
- I'm developing on Ubuntu 14.04 64bit, and as of this post, it's April 2016.
- I develop typically in C, Java and Python for IoT projects
Getting Started
Like everyone else, start with Amazon's IoT Developer's Guide. But pay attention to these details (that I glossed over).
Do not install the AWS CLI Debian package, instead use PIP to get the latest:
$ sudo apt-get install python-pip
$ pip install awscli
Make sure the IoT commands are present by trying:
$ aws iot help
Next, make sure your user/role has the proper permissions. To get going quickly, I opened myself up completely and added the AWSIoTFullAccess policy. Use the AWS Console and IAM to attach a policy:
Follow the developer guide to create a thing. Note that the DG glosses over the Thing's attributes. Reading ahead, it looks like these attributes (three and at most three?) associated with the Thing are additonal identifiers of the Thing itself.
For example, three attributes could be: the vendor, the version and the serial number of the Thing. The documentation lists this as an example:
$ aws iot
describe-thing --thing-name "MyDevice3"
{
"thingName": "
MyDevice3",
"defaultClientId":
"MyDevice3",
"attributes": {
"Manufacturer":
"Amazon",
"Type": "IoT Device
A",
"Serial Number":
"10293847562912"
}
}
So, for my Weather Station Thing I could do something like:
$ aws iot
describe-thing --thing-name "WS2308"
{
"thingName": "WS2308",
"defaultClientId":
"WS2308",
"attributes": {
"Manufacturer":
"LaCrosse",
"Type": "WS2308-AL",
"Serial Number":
"00000001"
}
}
But setting the Thing Attributes aren't necessary to make progress. So we move on to creating the X.509 Certificates.
AWS IoT X.509 Cert Creation
I hit a couple of bumps in the documentation, but probably because of my gross unfamiliarity with certificates. Said another way, you're probably smarter and won't have the same issues.
Nota Bene #1 would be to choose more descriptive certificate file names in the first create command. The DG shows this:
$ aws iot
create-keys-and-certificate --set-as-active --certificate-pem-outfile cert.pem --public-key-outfile
publicKey.pem --private-key-outfile privateKey.pem
Three files will be created:
1. cert.pem - which will be referred to as the "device certificate" by other documentation and the sample code. Name the file "cert.pem" if you wish, or name it "myThingCert.pem".
2. The public key cert, as of this point in my exploration, goes unused.
3. The private key cert is properly named, privateKey.pem, and you'll need this one later
Don't Forget the Root Cert
Finally note that we'll need a third Certificate to make things work and it's not created like the other two. It's downloaded. And it's a short, small mention in the guide so don't miss it. It's in this section of the Developer Guide.
First paragraph:
MQTT clients require a root CA certificate to authenticate with AWS IoT.
Download the root CA certificate file from root certificate.
Download it now, call it awsIoTRootCert.pem or something equally descriptive.
The AWS IoT SDK Sample code will suck in the complete path and filenames for these three certs so plunk them someplace useful.
Make a Note of the Certificate ARN
When the create-keys-and-certificate command completes, there will be some output similar to:
{
"certificateArn": "arn:aws:iot:us-east-1:634:cert/cd----x-x-x-x-x-x--x-x-x8d153d02801c",
"certificatePem":
"-----BEGIN CERTIFICATE-----
Make a note of the certificate ARN (shown in red) as you'll need it later.
Don't change the Version on the Policy
Several steps later, you're asked to create a policy file. This JSON formatted file as a Version attribute. Don't change it. It needs to be set to "2012-10-17" or things won't work.
$ pconroy@pconroy-VirtualBox:~/Dropbox/Amazon/IoT$
more policy.json {
"Version":
"2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action":["iot:*"],
"Resource": ["*"]
}]
MQTT.fx
The Developer's Guide uses a GUI java based tool called MQTT.fx to test the MQTT connectivity. I tried the Debian based package first and it wouldn't start, so I downloaded the JAR file and ran it that way.
When it comes to the step of entering the full Certificate paths and filenames, take note that MQTT.fx again uses different terms.
The root certificate filename goes in the "CA File" text box. The device certificate filename (called 'cert.pem' in the DG) goes in the "Client Certificate File" text box and the private key cert goes in the Client Key File text box. The fourth text box, Client Key Password, remains blank.
MQTT.fx - Did you get a Connection Error?
I did. I kept getting this one:
2016-03-30
15:21:19,130 ERROR --- MqttFX ClientModel : Error when connecting
org.eclipse.paho.client.mqttv3.MqttException:
Connection lost
at
org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146)
~[org.eclipse.paho.client.mqttv3-1.0.2.jar:?]
at java.lang.Thread.run(Thread.java:745)
[?:1.8.0_77]
Caused by:
java.io.EOFException
at
java.io.DataInputStream.readByte(DataInputStream.java:267) ~[?:1.8.0_77]
at
org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65)
~[org.eclipse.paho.client.mqttv3-1.0.2.jar:?]
at
org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107)
~[org.eclipse.paho.client.mqttv3-1.0.2.jar:?]
... 1 more
2016-03-30
15:21:19,154 INFO ---
ScriptsController : Clear
console.
2016-03-30
15:21:19,156 ERROR --- BrokerConnectService : MqttException: Connection lost
A little Googling showed that I wasn't alone; others were getting the same error. But it wasn't common, it seemed to be rare. A there wasn't much in the way of guidance on making the error go away.
After poking at it for a couple of hours, I started over from the Certificate creation steps - and redid everything. Tried it again and -- it worked. No errors.
I have no cure just a suggestion that if you too hit a Connection Error, just back up and recreate all of the certs, policies and attachments.
AWS IoT SDK for C
That's about all it took for me to work through the Quickstart Section of the Developer's Guide. At this point, I decided to start in on their SDK and port my existing Home Automation Devices over to using their SDK. That's the topic of my next post.