Monitoring Plants with AWS IoT and Home Assistant

Craig Huber
6 min readMay 11, 2018

--

I’ve been using Home Assistant on a Raspberry Pi 3 to automate all the lights, sensors, music and media devices in my apartment for several months now. I cant say enough good things about it, so if you are even remotely interested in home automation I highly suggest looking into it. With it, I’ve even managed to monitor the moisture and conductivity of my plants. I bought a Xiaomi Plant Monitor which Home Assistant supports out of the box so its easy to check the status of my plants while I’m at home. But there was still something missing..

My Palm with Mi Flora Sensor

When I’m on the road I sometimes wonder if my beloved Dracena’s and Cateracterum’s are dying a slow and painful arid death without my care. It would be nice to be able to check in on them once in a while remotely, so I built my own solution using open source tools and the cloud. While Home Assistant does a good job of connecting via Bluetooth to the Mi Flora device and grabbing it’s status, it doesn’t publish those metrics out to the Internet.

Plant moisture in Home Assistant

I started investigating AWS IoT and tried to figure out if I could publish Home Assistant metrics to AWS IoT for further analysis. It turns out this is relatively easy using MQTT. The solution I came up uses the following components:

  • Mi Flora Sensor
  • Raspberry Pi3
  • Home Assistant
  • AWS IoT
  • AWS DynamoDb

The end result is I have all my plant metrics such as moisture, temperature and conductivity stored in a DynamoDB database which I can query and create a beautiful visualizations using ChartJS like this:

The finished product: Plant Moisture

Home Assistant

Home Assistant is the ultimate home automation hub. It connects to over 1000 devices, platforms and services to all you to stitch them all together and create automations like you never imaged. Best of all its open source, written in Python and configured through YAML files. To add my plant sensor all I needed was 3 lines in my config file

- platform: miflora  name: plant  mac: ‘C1:2C:3D:42:A5:AB’
Home Assistant showing my plant metrics

MQTT

MQTT is a lightweight TCP telemetry protocol for machine to machine Internet of Things devices. MQTT uses a publish and subscribe model so we can publish messages from Home Assistant and AWS IoT can subscribe to retrieve them. Between the Home Assistant and AWS IoT we’ll use a MQTT Bridge (Gateway). The communication will look something like this:

Plant ←Bluetooth → Home Assistant ← MQTT Bridge → AWS IoT → DynamoDB←Rest API →Internet

AWS IoT

AWS IoT Core essentially lets your Internet connected devices communicate securely to the cloud over MQTT, WebSockets and HTTP. It can do other fancy things like run actions when messages are received which I’ll leverage to store data in DynamoDB (or potentially SNS alerts). If you think about trying to build a platform to accomplish the same thing you’ll realize why IoT core is valuable.

In this scenario I’ll use AWS IoT to allow Home Assistant to publish metrics to. To set this up the first we will create is “Thing” in AWS IoT. This will represent the Raspberry Pi running Home Assistant

Create a Thing

Give your Thing a name like HomeAssistant.

Call it HomeAssistant

You can have the certificates created for your automatically, but in this example I created thing without a certificate. I’ll create a certificate using the command line next.

Skip certificate creation

Create the IAM policy, certificates, attach the policy to your certificate. and attach the certificate to the thing.

# Create an IAM policy for the bridgeaws iot create-policy --policy-name HomeAssistant --policy-document '{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": "iot:*","Resource": "*"}]}'

# Place yourself in Mosquitto directory
# And create certificates and keys, note the certificate ARN
cd /etc/mosquitto/certs/
sudo aws iot create-keys-and-certificate --set-as-active --certificate-pem-outfile cert.crt --private-key-outfile private.key --public-key-outfile public.key --region eu-central-1

# List the certificate and copy the ARN in the form of
# arn:aws:iot:us-east-1:0123456789:cert/xyzxyz
aws iot list-certificates

# Attach the policy to your certificate
aws iot attach-principal-policy --policy-name HomeAssistant --principal <ARN_OF_CERTIFICATE>

# Add read permissions to private key and client cert
sudo chmod 644 private.key
sudo chmod 644 cert.crt

# Download root CA certificate
sudo wget https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem -O rootCA.pem
# Attach the certificate ARN from above to the thing
attach-thing-principal --thing-name HomeAssistant --principal arn:aws:iot:us-east-1:0123456789:cert/xyzxyz

Next let’s create some actions for when data comes in to the topic. We can run a SQL query for all messages coming into the topic localgateway_to_awsiot/plant. In this situation we will want to store messages in DynamoDB

SQL query your MQTT messages

Select an action to split incoming messages into multiple columns of a database table. This will allow each new message from Home Assistant arrive in a new row in the database

Split messages into DynamoDB

I have already created a database in DynamoDB called homeassistant. So this will be the destination for message

Choose your DB table

Home Assistant Configuration

All thats left now is to tell Home Assistant to use our AWS Iot Core Thing as a broker. Once, thats complete we can use the mqtt.publish action in our automations

mqtt:  certificate: /etc/mosquitto/certs/rootCA.pem
client_key: /etc/mosquitto/certs/private.key
client_cert: /etc/mosquitto/certs/cert.crt
broker: XXXXXXX.iot.us-east-1.amazonaws.com
port: 8883
tls_version: '1.2'
tls_insecure: false

Notice the certs are the ones we created earlier in setting up the IoT Thing. Now, I want an automation to publish the state of my plant to the MQTT broker every 12 hours. Included in the payload I want a timestamp, conductivity, temperature and moisture.

- alias: Send Plant Data to IoT
trigger:
- platform: time
hours: '/12'
minutes: 00
seconds: 00
action:
- service: mqtt.publish
data:
topic: "localgateway_to_awsiot/plant"
payload_template: '{"topic": "localgateway_to_awsiot/plant", "timestamp": "{{ as_timestamp(now()) }}", "conductivity": "{{ states.sensor.plant_conductivity.state }}", "temperature": "{{ states.sensor.plant_temperature.state }}", "problem": "{{states.plant.palm.attributes.problem}}", "moisture": "{{ states.sensor.plant_moisture.state }}", "friendly_name": "palm" }'

If I query my DynamoDB table, I now see data flowing in containing all the metrics I care about. Great success.

With all the data being stored in DynamoDB, I now have a central location outside of my RaspberryPi where I can query my data. I created an REST API that I query to get all this information in JSON format like so:

[
{
"conductivity": "353",
"friendly_name": "palm",
"moisture": "28",
"problem": "none",
"temperature": "22.3",
"timestamp": "1525968000.265589",
"topic": "localgateway_to_awsiot/plant"
},
{
"conductivity": "371",
"friendly_name": "palm",
"moisture": "29",
"problem": "none",
"temperature": "22.3",
"timestamp": "1525924800.268653",
"topic": "localgateway_to_awsiot/plant"
},
]

Fin

Using a combination of AWS tools and Home Assistant I’m now able to store, query and analyze all the metrics being received by Home Assistant. With AWS IoT Core Actions, any metric being received could be sent not only to DynamoDb, but to other things like SNS for Alerting, Firehose for realtime analytics or Lambda for processing. Hopefully this guide gives you a few ideas of whats possible and further improves your home automation.

Automate all the things.

--

--

Craig Huber

Craig Huber is a Senior Devops Engineer where he focuses on building cloud infrastructure, automation, containers and helping teams deploy their applications