The Internet of Things (IoT) is enabling the observation, analysis, and transmission of information in new and exciting ways. Low-cost connected devices that interact with cloud applications extend our reach into what is observable, learned, and actionable in the world.
Nowhere is this more evident than in agriculture, where IoT and data-driven approaches are making farming more efficient and sustainable. Beekeeping and hive management provide an important use case for IoT in agriculture. In the last ten years, scientists have observed distress and unexplained die-offs in honey bees (Apis mellifera). Although the cause of their decline is unknown, many experts suspect a confluence of issues, including Varroa destructor, a parasitic mite that attacks honey bee colonies, neonicotinoid pesticide poisoning, and even climate change.[i] The resulting shifts in habitat have contributed to bee colony distress. Gaining insight into honey bee health is important when you consider that in the United States, bee pollination is responsible for $15 billion in crop value each year. That’s one out of every three bites of food.[ii]
AWS IoT is a managed cloud platform that allows you to easily build systems in which billions of devices exchange trillions of messages. AWS IoT can reliably and securely process and route these messages to AWS endpoints and other devices. This whitepaper will demonstrate how to use AWS IoT and low-cost, internet-connected sensors to monitor the hives in a honey bee apiary. More broadly, this paper shows how any IoT system can deliver similar insights with different inputs.
Readers of this paper should be tech-savvy. Some Linux experience is helpful, but a desire to learn more about AWS IoT (and perhaps a passion for beekeeping and saving the world) is all that’s required. Although learning how to become a beekeeper is recommended (unless you are allergic to honey bees, of course), it is beyond the scope of this paper.
The steps that follow show how AWS IoT can be used to establish secure hive telemetry communications between IoT devices in honey bee colonies and the AWS IoT message broker. The analytical data we receive from these messages can alert us when measurements fall outside of normal, healthy ranges.
The AWS IoT message broker supports MQTT, a lightweight connectivity protocol that uses TCP as a transport protocol.
Secure-MQTT uses X.509 certificates as keys in the same way as other mutually authenticated TLS applications. In this use case, the client (a honey beehive) must be able to authenticate the server (AWS IoT), and the server must be able to authenticate the client.
To establish a Secure-MQTT connection to AWS IoT, the client must have:
- A root CA certificate (stored in a file named ca.pem). The AWS IoT service root CA is provided by Symantec. You can download it from here.
- The client’s private key (stored in a file named private-key.pem).
- A client certificate generated by AWS IoT (stored in a file named certificate.pem).
The root CA is used by the client device to verify the identity of the AWS IoT service. The private key and client certificate represent the identity of the client device and are used to authenticate to AWS IoT.
Create a Private Key
In this paper, you will use OpenSSL to create a key pair (public and private key). Alternatively, you can have AWS IoT create a private key for you, or you can use private keys from third-party certificate providers.
openssl genrsa 2048 > private-key.pem
Request a Client Certificate from AWS IoT
AWS IoT must create a client certificate for the devices. You must first create a certificate signing request (CSR), and then sign it with the private key you just created.
A CSR contains information that will be included in the certificate to identify who you are, such as organization name, common name (domain name), city, and country. The CSR also contains the public key that will be included in your certificate.
You can use the following command to create the CSR.
openssl req -new -key private-key.pem -out csr.pem
OpenSSL will interactively prompt for these inputs:
- Country Name: The two-letter country code (for example, US, CA).
- State or Province: The unabbreviated state or province name (for example, Washington, British Columbia).
- Locality or City: The city or town name (for example, Seattle, Vancouver).
- Company: The company or department name.
- Organizational Unit (Optional): The name of the department or organizational unit. To skip this field, press Enter.
- Common Name: This is the domain name (for example, example.com).
Note: You do not need to provide an email address or other attributes when prompted.
The interaction with OpenSSL will look like this:
openssl req -new -key private-key.pem -out csr.pem
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:Washington
Locality Name (eg, city) [Default City]:Seattle
Organization Name (eg, company) [Default Company Ltd]:Example Company
Organizational Unit Name (eg, section) []:IT Department
Common Name (eg, your name or your server's hostname) []:example.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
An optional company name []:
Alternatively, you can create a CSR by providing all of the information on the command line with the –subj option.
openssl req -new -key private-key.pem -out csr.pem -subj "/C=US/ST=Washington/L=Seattle/O=Example Company/OU=IT Department/CN=example.com"
The preceding commands create a csr.pem file that contains the CSR. The newly created and signed CSR is now sent to AWS IoT to request a client certificate that will be stored in certificate.pem.
Note: Instructions for installing AWS command-line interface tools (CLI) are here. After you install the CLI tools, you will need to configure credentials.
aws iot create-certificate-from-csr --certificate-signing-request file://csr.pem
If you need to download the client certificate again later, you can use the AWS IoT console or the AWS CLI with the following command.
Note: The output of the following command displays the results on your screen. The contents of the certificatePem attribute contains your certificate, in PEM format.
aws iot describe-certificate --certificate-id <your_certificate_id>
You now have the three items required for an IoT device to establish a Secure-MQTT TSL connection to AWS IoT: ca.pem, private-key.pem, and certificate.pem.
This IoT beehive implementation uses Raspberry Pi A+ client devices running the Raspbian Jessie operating system. At the time of this writing, the most current version is Raspbian Jessie (based on Debian Jessie) dated 3/18/2016. You can download it here.
The Raspberry Pi A+ does not have a wired Ethernet connector, so it may be more convenient to use an Ethernet USB cable or a Raspberry Pi device with a wired Ethernet connector (for example, B or B+), at least until you have configured wireless access for the operating system.
Update Base Raspbian Operating System Configuration
sudo apt-get update
sudo apt-get upgrade
First, install the Mosquitto MQTT client software. This is the client software that will be used to communicate with AWS IoT.
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
cd /etc/apt/sources.list.d/
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list
sudo apt-get update
sudo apt-get install mosquitto-clients
You need Mosquitto version 1.4 or later. Use the following command to check your version:
mosquitto_pub --help | grep "mosquitto_pub version"
The output should be something similar to:
mosquitto_pub version 1.4.8 running on libmosquitto 1.4.8.
Because this IoT implementation will be using an application written in Python, install the Paho Python client from Eclipse:
sudo pip install paho-mqtt
You now have all of the base software configured for the Raspberry device image.
The Raspberry Pi A+ was introduced in November 2014. It retails in individual quantities for around $20. Here are the specifications:
- 700MHz processor
- 256MB RAM
- HDMI and USB port
- Micro-SD slot for the Raspbian operating system
Typically, an inexpensive USB Wi-Fi dongle is added to provide wireless internet connectivity. The A+ is more than adequate for this AWS IoT beehive application. It also includes a 40-pin extended GPIO for wiring sensors.
Wire DS18B20 Thermometers
You will use two DS18B20 thermometers with long cables to collect temperature readings. The long cables make it easy to route one thermometer to the best location inside the hive for an internal hive temperature and the other outside the hive for an ambient temperature.
You will use a small wiring breadboard to connect the thermometer sensors to the Raspberry Pi. A Tupperware container can serve as an inexpensive case.
There is a lot of information on the internet about how to wire DS18B20 thermometers to the Raspberry Pi.
Add Kernel Modules
Two kernel modules must be loaded in order to access the temperatures reported by the w1-gpio and w1-therm sensors. To do this at boot, edit the /etc/modules file and add them to the end of the file.
w1-gpio
w1-therm
Although this was not required in earlier versions, on Raspbian Jessie, in order for devices to report their temperature through GPIO4, you must add the following to the end of the /boot/config.txt file:
dtoverlay=w1-gpio,gpiopin=4
Reboot the Raspberry Pi for the changes to take effect.
Validate Wiring and Operating System Configuration
Use the following commands to see if your sensors are reporting to the operating system:
cd /sys/bus/w1/devices
ls (you should see two directory links beginning with ’28-‘)
cd 28-xxxx (change this to match the serial numbers of your sensors)
cat w1_slave
Your output will look similar to this:
pi@raspberrypi /sys/bus/w1/devices $ ls -l
total 0
lrwxrwxrwx 1 root root 0 Mar 26 21:42 28-031574549fff -> ../../../devices/w1_bus_master1/28-031574549fff
lrwxrwxrwx 1 root root 0 Mar 26 21:42 28-031574610dff -> ../../../devices/w1_bus_master1/28-031574610dff
lrwxrwxrwx 1 root root 0 Mar 26 21:42 w1_bus_master1 -> ../../../devices/w1_bus_master1
Then change to the directory for either thermometer and view the contents of the w1_slave file:
pi@raspberrypi /sys/bus/w1/devices $ cd 28-031574549fff
pi@raspberrypi /sys/bus/w1/devices/28-031574549fff $ cat w1_slave
85 01 4b 01 7f ff 0c 10 89 : crc=89 YES
85 01 4b 01 7f ff 0c 10 89 t=24312
In this example, the temperature was 24.312 °C or 75.76 °F.
AWS IoT maintains a list of client devices in a thing registry. The thing registry allows you to keep a record of all things connected to AWS IoT.
Create a Thing
You can use the create-thing CLI command or the AWS IoT console to create a thing.
The following example shows how to create a thing for a honey beehive client device, beehive-1:
aws iot create-thing --thing-name "beehive-1"
{
"thingArn":"arn:aws:iot:us-west-2:123456789012:thing/beehive-1",
"thingName":"beehive-1"
}
Create and Attach an IoT Policy to the Certificate
AWS IoT provides support for AWS Identity and Access Management (IAM) to maintain a security access model of least privilege. A policy is used to restrict the behavior of devices that connect with the associated certificate.
First, create the policy (in this case, by using the Nano text editor and providing the policy in JSON format), and then attach it to the client certificate created by AWS IoT. The policy governs which AWS IoT operations the authenticated certificate owner can perform.
nano allow-iot-operations.json
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action":[
"iot:*"
],
"Resource":[
"*"
]
}
]
}
aws iot create-policy --policy-name "AllowIotOperationsPolicy" --policy-document file://allow-iot-operations.json
{
"policyName":"AllowIotOperationsPolicy",
"policyArn":"arn:aws:iot:us-west-2:123456789012:policy/AllowIotOperationsPolicy",
"policyDocument":"{\n \"Version\": \"2012-10-17\",\n \"Statement\": [{\n \"Effect\": \"Allow\",\n \"Action\":[\"iot:*\"],\n \"Resource\": [\"*\"]\n }]\n}\n\n",
"policyVersionId":"1"
}
aws iot attach-principal-policy --principal "<certificate ARN>" --policy-name "AllowIotOperationsPolicy"
Note: You can use the AWS IoT console or the list-certificates CLI command to get the certificate ARN.
AWS IoT allows you to enable and disable certificates. You can use the following CLI command to specifically enable a certificate. Alternatively, if the certificate was created with the create-certificate-from-csr or the create-keys-and-certificate CLI commands, you can pass the --set-as-active switch.
aws iot update-certificate --new-status ACTIVE --certificate-id <your_certificate_id>
Up to this point, you have created a certificate and associated your policy with the certificate. You have also created a new thing in the AWS IoT thing registry. Now, attach your certificate with its policy to your thing.
aws iot attach-thing-principal --thing-name "beehive-1" --principal "<your_certificate_ARN>"
Clients establish a secure connection to AWS IoT through an AWS account-specific custom endpoint. You can use the AWS IoT console or the AWS CLI to retrieve your endpoint address.
aws iot describe-endpoint
{
"endpointAddress": "ABCDEFGHIJKLM.iot.us-west-2.amazonaws.com"
}
Now you are ready to test connectivity from your client device to the AWS IoT service. Use SSH to connect to the Raspberry Pi for beehive-1, and then run the mosquitto_pub command:
mosquitto_pub --cafile ca.pem --cert c80e3b1c03-certificate.pem.crt --key private-key.pem -h ABCDEFGHIJKLM.iot.us-west-2.amazonaws.com -p 8883 -q 1 -d -t topic1 -i beehive-1 -m "Hello, World"
As your beekeeping business grows, you may eventually have millions of beehives reporting observational data to AWS IoT. When messages arrive from your beehive sensors, you can use AWS IoT rules and actions to place this data into an Amazon DynamoDB table.
First, you will create a DynamoDB table with a hash key and a primary sort key (formerly known as a range key). The hash key will be the client device ID (for example, beehive-1) and the sort key will be a timestamp of when the observation occurred. AWS IoT requires that both the hash key and the primary sort key are of type String.
The following CLI command creates a DynamoDB table with the appropriate keys.
aws dynamodb create-table --table-name IOT-HiveData --attribute-definitions AttributeName=key,AttributeType=S AttributeName=timestamp,AttributeType=S --key-schema AttributeName=key,KeyType=HASH AttributeName=timestamp,KeyType=RANGE --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
Now you need to create an IAM role. AWS IoT will assume this role in order to process messages and place them in the DynamoDB database.
iot-hivedata-actions-role.txt
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"",
"Effect":"Allow",
"Principal":{
"Service":"iot.amazonaws.com"
},
"Action":"sts:AssumeRole"
}
]
}
aws iam create-role --role-name "iot-hivedata-actions-role" --assume-role-policy-document file://iot-hivedata-actions-role.txt
Now you need to create a policy and attach it to the role. Following the model of least-privilege (a best practice), create a policy that has only the permissions required to insert items into the DynamoDB table. Then, attach this policy to the newly created role.
iot-hivedata-ddb-insert-policy.txt
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:*"
],
"Resource": [
"arn:aws:dynamodb:us-west-2:123456789012:table/IOT-HiveData"
]
}
]
}
aws iam create-policy --policy-name "iot-hivedata-ddb-insert-policy" --policy-document file://iot-hivedata-ddb-insert-policy.txt
aws iam attach-role-policy --role-name "iot-hivedata-actions-role" --policy-arn "arn:aws:iam::123456789012:policy/iot-hivedata-ddb-insert-policy"
Build a Topic Rule
You can trigger actions that will take place when messages are received by AWS IoT based on the MQTT topic string sent from the client. Topic strings are organized hierarchically and use the forward slash (/) to distinguish subtopics.
The topic arriving from the IoT beehive for temperature data will look like this: topic/hivedata/temperature. Later, you can add the following topics:
- humidity: topic/hivedata/humidity
- hive weight: topic/hivedata/weight
- number of bees leaving the hive: topic/hivedata/egress
- number of bees returning to the hive: topic/hivedata/ingress
AWS IoT allows you to perform specific actions based on these topic strings. You can perform multiple actions on the same topic string.
Here is the rule to create a new item in the DynamoDB table. Rules are specified in JSON using a SQL-like syntax.
iot-hivedata-topic-ddb-insert-rule.txt
{
"sql":"SELECT * FROM 'topic/hivedata/temperature'",
"ruleDisabled":false,
"actions":[
{
"dynamoDB":{
"tableName":"IOT-HiveData",
"hashKeyField":"key",
"hashKeyValue":"${clientId()}",
"rangeKeyField":"timestamp",
"rangeKeyValue":"${timestamp()}",
"roleArn":"arn:aws:iam::123456789012:role/iot-hivedata-actions-role"
}
}
]
}
aws iot create-topic-rule --rule-name "iot_hivedata_topic_ddb_insert_rule" --topic-rule-payload file://iot-hivedata-topic-ddb-insert-rule.txt
Debug Rules and Actions
You may need to debug your IoT configuration in order to get everything operating correctly. You can choose to have messages from your devices that pass through the IoT message broker appear in CloudWatch logs. This information can be very helpful when diagnosing permission errors. The supported reporting levels are DEBUG, INFO, ERROR, or DISABLED.
First, create an AWS IoT logging role:
iot-logging-role.txt
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"",
"Effect":"Allow",
"Principal":{
"Service":"iot.amazonaws.com"
},
"Action":"sts:AssumeRole"
}
]
}
aws iam create-role --role-name "iot-logging-role" --assume-role-policy-document file://iot-logging-role.txt
Then, create a logging policy and attach it to the role:
iot-logging-policy.txt
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:PutMetricFilter",
"logs:PutRetentionPolicy",
"logs:GetLogEvents",
"logs:DeleteLogStream"
],
"Resource": [
"*"
]
}
]
}
aws iam create-policy --policy-name "iot-logging-policy" --policy-document file://iot-logging-policy.txt
aws iam attach-role-policy --role-name "iot-logging-role" --policy-arn "arn:aws:iam::123456789012:policy/iot-logging-policy"
You can toggle logging on and off, as needed. To turn on logging, set the logLevel to INFO.
aws iot set-logging-options --logging-options-payload roleArn="arn:aws:iam::123456789012:role/iot-logging-role",logLevel="INFO"
To turn off logging, set the logLevel to DISABLED.
aws iot set-logging-options --logging-options-payload roleArn="arn:aws:iam::123456789012:role/iot-logging-role",logLevel="DISABLED"
Now, from the command line of your Raspberry Pi client, perform your first end-end test.
Test with Mosquitto
Use SSH to connect to the Raspberry Pi for beehive-1 and issue a mosquito_pub command using the account-specific IoT endpoint and topic/hivedata/temperature topic string.
The message payload contains simulated JSON data representing the temperatures inside and outside the hive as measured by the two DS18B20 thermometers.
mosquitto_pub --cafile ca.pem --cert 3f12ecfb51-certificate.pem.crt --key private-key.pem -h ABCDEFGHIJKLM.iot.us-west-2.amazonaws.com -p 8883 -q 1 -d -t "topic/hivedata/temperature" -i beehive-1 -m "{\"InsideTemperature\": \"85.23\", \"OutsideTemperature\": \"49.78\"}"
The output from the mosquitto_pub command will look like this:
Client beehive-1 sending CONNECT
Client beehive-1 received CONNACK
Client beehive-1 sending PUBLISH (d0, q1, r0, m1, 'topic/hivedata/temperature', ... (62 bytes))
Client beehive-1 received PUBACK (Mid: 1)
Client beehive-1 sending DISCONNECT
If everything is configured correctly, you should see the first item has been inserted into the DynamoDB table:
The Python Application
The mosquito_pub command sent a message to AWS IoT with simulated data. Now you will write a Python application and use the Paho MQTT client to read real data from the two DS18B20 thermometers every 60 seconds.
You can run this Python program at boot by modifying the /etc/rc.local file on the Raspberry Pi.
import json
import datetime
import time
import threading
import paho.mqtt.client as mqtt
import ssl
####################################################
client_id = 'beehive-1'
aws_endpoint = 'ABCDEFGHIJKLM.iot.us-west-2.amazonaws.com'
ca_filename = 'ca.pem'
cert_filename = '3f12ecfb51-certificate.pem.crt'
private_key_filename = 'private-key.pem'
in_temp_file = '/sys/bus/w1/devices/28-031574610dff/w1_slave'
out_temp_file = '/sys/bus/w1/devices/28-031574549fff/w1_slave'
mqtt_topic = 'topic/hivedata/temperature'
####################################################
def onDisconnect(client, userdata, rc):
print("Disconnected from AWS IoT")
def on_connect(client, userdata, flags, rc):
print("Connected to AWS IoT with result code " + str(rc))
####################################################
def getTemp(fname):
tfile = open(fname)
text = tfile.read()
tfile.close()
secondline = text.split("\n")[1]
temperaturedata = secondline.split(" ")[9]
temperature = float(temperaturedata[2:])
temperature = (temperature / 1000) * 9 / 5 + 32
return str(round(temperature, 2))
####################################################
def getNow():
localtime = time.localtime()
return (time.strftime("%Y%m%d %H%M%S", localtime))
####################################################
client = mqtt.Client(client_id=client_id)
client.tls_set(
ca_filename,
certfile=cert_filename,
keyfile=private_key_filename,
tls_version=ssl.PROTOCOL_TLSv1_2)
client.on_connect = on_connect
client.on_disconnect = onDisconnect
client.connect(aws_endpoint, 8883, 70)
client.loop_start()
while True:
now = getNow()
intemp = getTemp(in_temp_file)
outtemp = getTemp(out_temp_file)
payload = json.dumps(
dict(
InsideTemperature=str(intemp),
OutsideTemperature=str(outtemp)))
client.publish(mqtt_topic, payload)
time.sleep(60) # sleep for 60 seconds
The following chart shows the data collected from beehive-1 during a spring day in the Pacific Northwest. Honey bees become dormant in cold temperatures. They are not hibernating, but are far less active than during the summer.
As you can see from the chart, the ambient temperature was near 40 °F in the morning, but in the hive, the temperature was a comfortable ~80 - 90 °F. Bees form a tight cluster in the hive and regulate its temperature by activating their flight muscles to generate heat.
Add an action to trigger an Amazon Simple Notification Service (Amazon SNS) message if the internal temperature of the hive falls below 70 °F.
Run the following command to create an SNS topic:
aws sns create-topic --name iot-hivedata-inside-temperature
Create a policy that only allows publishing to the SNS topic, and then attach it to the iot-hivedata-actions-role you created earlier.
iot-hivedata-publish-sns-policy.txt
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1448390963000",
"Effect": "Allow",
"Action": [
"sns:publish"
],
"Resource": [
"arn:aws:sns:us-west-2:123456789012:iot-hivedata-inside-temperature"
]
}
]
}
aws iam create-policy --policy-name "iot-hivedata-publish-sns-policy" --policy-document file://iot-hivedata-publish-sns-policy.txt
aws iam attach-role-policy --role-name "iot-hivedata-actions-role" --policy-arn "arn:aws:iam::123456789012:policy/iot-hivedata-publish-sns-policy"
Now create a rule that publishes to this topic when the InsideTemperature < 70.
iot-hivedata-topic-sns-inside-temperature-rule.txt
{
"sql":"SELECT * FROM 'topic/hivedata/temperature' WHERE InsideTemperature < 70",
"ruleDisabled":false,
"actions":[
{
"sns":{
"targetArn":"arn:aws:sns:us-west-2:123456789012:iot-hivedata-inside-temperature",
"roleArn":"arn:aws:iam::123456789012:role/iot-hivedata-actions-role"
}
}
]
}
aws iot create-topic-rule --rule-name "iot_hivedata_topic_sns_inside_temperature_rule" --topic-rule-payload file://iot-hivedata-topic-sns-inside-temperature-rule.txt
The use of AWS IoT in this whitepaper demonstrates the collection, processing, and analysis of IoT data without having to manage any infrastructure. AWS IoT is a fully managed service that can scale to support billions of devices and trillions of messages, if required. Its low-cost pricing model is based solely on the number of messages published to and delivered by the service.
[i] Le Conte, Yves, and Maria Navajas. "Climate Change: Impact on Honey Bee Populations and Diseases." Revue Scientifique et Technique (International Office of Epizootics) 27.2 (2008): 499-510. 27 Nov. 2015.
[ii] Barriounuevo, Alexei. "Honeybees Vanish, Leaving Keepers in Peril." New York Times 27 Feb. 2007: A1. 27 Nov. 2015 <
http://www.nytimes.com/2007/02/27/business/27bees.html?pagewanted=all&_r=2&
>.
This document is provided for informational purposes only. It represents AWS’s current product offerings and practices as of the date of issue of this document, which are subject to change without notice. Customers are responsible for making their own independent assessment of the information in this document and any use of AWS’s products or services, each of which is provided “as is” without warranty of any kind, whether express or implied. This document does not create any warranties, representations, contractual commitments, conditions or assurances from AWS, its affiliates, suppliers or licensors. The responsibilities and liabilities of AWS to its customers are controlled by AWS agreements, and this document is not part of, nor does it modify, any agreement between AWS and its customers.
Comments