# ESP32 Home Weather Station for Houseplants
## Introduction
*Project by: Rikard Kloth (rk222tq)*
This tutorial will explain how to setup an IoT home weather station using a Heltec ESP32 microcontroller for temperature and humidity control and webhook push notifications to Discord.
- Estimateted time of setup: 5h
## Project Objective
The main objective behind the project was to be able to measure the best weather conditions for our houseplants, in order to create the optimal environment for our plants. The IoT device will help fulfill this objective by outputting sensor data that can be acted on by increasing humidity (with a humidifier) and lower temperature (by opening adjacent windows). The idea behind the project was to react on weather conditions that were causing our houseplants to wilt and die during the summer. The device should help with insights on when and how the houseplants needs attention.
## Materials
| Hardware | Amount | Description |Retailer, Cost |
| ---------------- | ------ | ------------------------------------------ | --- |
| Heltec lora32 v2 | x1 | Microcontroller | amazon.se, ca 350:- SEK |
| Breadboard | x1 | Base for connecting circuit |electrokit.com, ca 60:- SEK |
| Jumper cable | x5 | Male to male cables for circuit connection | electrokit.com, ca 30:- SEK |
| DHT11 sensor | x1 | Digital temperature and humidity sensor |electrokit.com, ca 50:- SEK |
| Micro USB cable | x1 | For uploading code and power supply | amazon.se, ca 30:- SEK |
| USB wall adapter | x1 | For power supply | amazon.se, ca 30:- SEK |
The Heltec lora32 v2 is an affordable and versatile microcontroller development board that supports LoRa connectivity and is easy to learn for a first IoT project.
## Computer and Device Setup
For this project I used Atom IDE supported by the Pymakr plugin through which the code is uploaded. In addition to Atom and Pymakr, Node.js software needs to be installed. Circuit connection shown in image below.
*Image 1: Schematic over device circuit on breadboad*

The white wire connects to the ground, the red connects the power. The DHT11 digital sensor works with both 3.3 volts or 5 volts. For this project I went with 3.3 volts. The blue wire connects the signal pin to the Heltec board. Since im using a digital sensor, no extra resistors are needed.
## IoT Platform
I'm using Adafruit IO as a data visualization platform. Adafruit is webservice platform that can be set up for a free account with limited functionalities (which I did for this project).
## The Code
This section includes code snippets of the main parts of the code. The following libraries were used but are not shown here: time, ubinascii and micropython. Also, the snippets do not show how to set up the sensors or how to configure Adafruit IO, as these were deemed to be of lower priority to show. A dht.py library and a mqtt.py library needs to be imported as well.
#### Libraries
```python=
from network import WLAN # For operation of WiFi network
from mqtt import MQTTClient # For use of MQTT protocol to talk to Adafruit IO
from dht import DHT #importing DHT class
from machine import Pin,ADC #Pin allows for control of I/O Pins, ADC allows for analog to digital data conversion
```
#### Connection to WiFi
Setup for beeing able to connect to the internet. For this project a WiFi connection was best suited.
```python=
# WIFI
# We need to have a connection to WiFi for Internet access
wlan = WLAN(mode=WLAN.STA)
wlan.connect(WIFI_SSID, auth=(WLAN.WPA2, WIFI_PASS), timeout=5000)
while not wlan.isconnected(): # Code waits here until WiFi connects
machine.idle()
```
#### Functions
The first function helps make sure that the user gets feedback on current statuts which would lead to an improved user experience. additionaly, this could be expanded into a mobile application where users might want to recieve feedback about their plants health when on vacation. The second function helps send data to Adafruit IO.
```python=
# Function to respond to control messages from Adafruit IO
def sub_cb(topic, msg): # sub_cb means "callback subroutine"
print((topic, msg)) # Outputs the message that was received. Debugging use.
if msg == b"ON": # If message is "ON" blink once (triggered by flick of switch on Adafruit IO)
led.value(1)
time.sleep(0.2)
led.value(0)
time.sleep(0.2)
elif msg == b"OFF": # If message is "OFF" blink twice (triggered by flick of switch on Adafruit IO)
led.value(1)
time.sleep(0.2)
led.value(0)
time.sleep(0.2)
led.value(1)
time.sleep(0.2)
led.value(0)
time.sleep(0.2)
else: # If any other message is received ...
print("Unknown message") # ... do nothing but output that it happened.
# Function to send sensor data to Adafruit IO
def send_sensor_data():
global last_data_sent_ticks
global TEMPERATURE_INTERVAL
if ((time.ticks_ms() - last_data_sent_ticks) < TEMPERATURE_INTERVAL): # Check if 60 seconds have passed
return; # Too soon since last one sent.
try: #publish temp and humidity data to respective topics
client.publish(topic=AIO_TEMPERATURE_FEED, msg=str(result.temperature))
client.publish(topic=AIO_HUMIDITY_FEED, msg=str(result.humidity))
print("DONE")
except Exception as e:
print("FAILED")
finally:
last_data_sent_ticks = time.ticks_ms() #reset time since data was sent
```
#### MQTT Messaging Protocol
The messaging between the device and the Adafruit IO server is setup using the MQTT protocol.
```python=
# Use the MQTT protocol to connect to Adafruit IO
client = MQTTClient(AIO_CLIENT_ID, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY)
# Subscribed messages will be delivered to this callback
client.set_callback(sub_cb)
client.connect()
client.subscribe(AIO_TEMPERATURE_FEED)
client.subscribe(AIO_HUMIDITY_FEED)
client.subscribe(AIO_LEDS_FEED)
```
#### Check Message and Send Data - Disconnect if Needed
The second function checks recieved messages and sends the sensor data to Adagruit IO.
```python=
try: # Code between try: and finally: may cause an error
# so ensure the client disconnects the server if
# that happens.
while 1: # Repeat this loop forever
client.check_msg()# Action a message if one is received. Non-blocking.
send_sensor_data() # Send data to Adafruit IO if it's time.
finally: # If an exception is thrown ...
client.disconnect() # ... disconnect the client, dicsonnect from wifi and print a message to communicate this
client = None
wlan.disconnect()
wlan = None
print("Disconnected from Adafruit IO.")
```
## Data Transmission and Presentation
Both data on humidity and tempeture are sent once every 60 seconds. The data is sent over WiFi since the device doesn't need to move outside of the house. For this project I chose Adafruit.io as a web service for data visualization. The dashboard is made up by two line charts and the control switch for status check (Shown in image 2 bellow). The control function triggers an LED on the Heltec board. A quick blink if it is switched "ON" and two quick blinks if switched "OFF". The data is shown in Adafruit.io for the past 24 hours. Comunication between the device and Adafruit.io is based on the MQTT protocol.
*Image 2: Adafruit.io Temperature and humidity dashboard*

Two actions are set in Adafruit.io that are triggered by the data. When the humidity and/or temperature reach a certain level a notification indicationg which data and its value is sent to a discord server using the webhooks protocol (Discord notification shown in image 3 bellow).
*Image 3: Notification sent shown in Discord*

## Final Thoughts
This was a fun little project for a beginner which can serve as a great introduction both to setting up a device but also to programming in (Micro)Python :smile:.
