Monitoring Plants with AWS IoT and Home Assistant

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..

Image for post
Image for post
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.

Image for post
Image for post
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:

Image for post
Image for post
The finished product: Plant Moisture

Home Assistant

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


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


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

Image for post
Image for post
Create a Thing

Give your Thing a name like HomeAssistant.

Image for post
Image for post
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.

Image for post
Image for post
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

Image for post
Image for post
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

Image for post
Image for post
Split messages into DynamoDB

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

Image for post
Image for post
Choose your DB table

Home Assistant Configuration

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
- platform: time
hours: '/12'
minutes: 00
seconds: 00
- service: mqtt.publish
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.

Image for post
Image for post

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"


Automate all the things.

Written by

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

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store