APIs Can Save Your Plant's Life
Tags: mulesofthackathon
Published: 2020-11-25 20:23:06

This project grew out of a simple effort to monitor the health of a houseplant, “Karl”, several years ago (my daughter named the plant Karl after her bass guitar teacher). We would typically forget to water the plant from time to time, and so Karl was in constant danger from drying out and shrivelling up!

So I built a simple moisture sensor and configured an electronic circuit and an Arduino to monitor the moisture, and to flash a red LED when the soil became too dry. This was great, and Karl was grateful... but the system did rely on someone walking by and noticing the flashing red light. So I began to think: what if Karl could tell me by email or text when he was thirsty? Enter the Mule...

With its ability to quickly create an API that my plant could talk to, and the connectors that made email and SMS notification simple, Mule seemed to be a good way to keep Karl (and my daughter) happy. I replaced the Arduino with a Raspberry Pi to give Karl internet connectivity; and I created a Mule API running in Cloudhub that the moisture-monitoring Pi  could send a message to whenever Karl needed a drink. The Mule API would receive the message and send the appropriate email or text message.

Later on, I decided to make the Mule API more of a general purpose event-notification engine, and to allow “users” to subscribe to various event messages, and to specify their notification preferences. In this way, the API could receive messages for all kinds of events, not just dried-up houseplants. It could also route notifications to users email inboxes or cell phones based on their notification preferences. The subscriptions and preferences are stored in a SQL database (Heroku PostgreSQL in the cloud), and the Mule API uses its database connectors to retrieve the information from the database.

Here's the overall flow from Karl to my phone or email inbox:
![flow_diagram](https://dev-to-uploads.s3.amazonaws.com/i/z6phbod97o9mt9l170u9.png)

### Moisture Sensor and Raspberry Pi

The moisture sensor couldn't be simpler - just a pair of metal bolts with wires attached stuck into the plant's soil. The wires connect to the Raspberry Pi's ground and +3.3V pins so that a small electric will flow through the soil between the bolts. A resistor on this circuit keeps the current at a safe level. This turns the soil in the plant pot into a variable resistor; the drier the soil the lower the current flowing, and the wetter the soil the higher the current. With the help of an analog-digital converter chip, a Python script on the Raspberry Pi can monitor the current flowing in the circuit, and detect when the soil becomes too dry. When that happens, an HTTP request is sent to my Mule API running in the cloud, and the API takes care of routing notifications.

Here's Karl and the Raspberry Pi setup:

![DSC_0161](https://dev-to-uploads.s3.amazonaws.com/i/zbu8ji0vrulfh5753xid.jpg)

For a closer look at the electronic circuit and Rasberry Pi wiring:

![DSC_0154](https://dev-to-uploads.s3.amazonaws.com/i/zdr6ui8vhj78dk0tma1r.jpg)
  

### The Mule API

This API listens for HTTP messages about Karl's moisture-happiness, and when it receives one, it springs into action. First, it determines what type of event the incoming message is reporting (soil has become too dry or soil moisture is OK). Then it consults a subscription list, stored in a PostgresSQL database, to determine who should be notified, what their notification preferences are (SMS or Email), and the relevant contact data (phone number or email address). The API then sends the messages using the Mule Twilio connector for SMS, and the SMTP (configured for MS Outlook) connector for Email. 
![mule_flows](https://dev-to-uploads.s3.amazonaws.com/i/tzqvbmd9mnkcbifmkr52.png)
  
I developed the app using an "API-first" process. I first built the RAML in the Mulesoft cloud Design Center and published to Exchange. Next I imported the RAML into Anypoint Studio and generated the skeleton application. From there I connected the code to a new GitHub repo (see below) and started to fill in the application code.

After testing locally I created the API in API Manager and deployed the app to Cloudhub.

### Challenges

The application development was mostly straightforward, but a few minor hurdles I encountered along the way:

* While the Mule Twilio connector is a quick and easy way to use the Twilio API, any error messages sent back by Twilio aren't readily visible. Enabling HTTP-level logging in the Mule app helped me get more info about the errors and fix them (to do this I set the logging level for org.mule.service.http.impl.service.HttpMessageLogger to DEBUG).

* My first attempt at sending mail from Cloudhub by using smtp.office365.com as the SMTP server mysteriously failed. Turned out that Microsoft classified this usage as "unusual sign-in activity" and sent an email to my live.com account. Once I found this and confirmed that this was a valid usage, my app was able to send email.

### Lastly...

This was a fun project, combining a real-world situation with my interest in electronics and a Mule API.

The work was made much easier because of the useful free resources available. The Heroku Postgres SQL cloud database service, the evaluation Twilio service, Outlook email, Python libraries for the Raspberry Pi - all of these formed building blocks for my API and speeded along development.

### Reference
Mule application source code: https://github.com/sxt/plantstate-mule

Raspberry Pi application source code (Python):
https://github.com/sxt/plantstate-pi