Building a Homekit enabled weather station using Homebridge and an ESP8266
Beware, there’s a follow up on this article.
— — — —
My wife likes to grow her own vegetables on our balcony. The problem with this however is, that one also needs to water the plants (first world problems right?)
As the tech guy I am, I was going a little bit wild last summer and build a Homekit enabled solution to water the plants. Every day at 8 in the morning and 7 in the evening, it was watering the plants for a couple of minutes.
It works great, but the system was not aware of the temperature or if it was raining, that is why it also watered the plants when it rained (and not enough if it was a really hot day)
I wanted to solve this with the minimum effort (and costs), but buying a Homekit enabled rain sensor was surprisingly expensive. The only one I found was the Netatmo Rain Sensor (~70€).
This is why I decided to build my own system.
A few key points that it should fulfill
- detecting rain and make Homekit aware of this
- measuring the temperature, creating a chart out of the historical values and make Homekit aware of the current temperature
- Using as little power as possible
- Using a battery/Powerbank to be able to move the system to any place
Parts
I’ve decided to use the ESP8266 as I can use the Arduino IDE and the support throughout the community is great. Also it consumes very little power and the number of sensors that are compatible is extremely large.
The following list contains Amazon links to make it easier to buy the parts I’ve used, however, if I were you, I’d consider buying them from Ebay or Wish, as they are way cheaper than buying on Amazon.
- ESP8266
- Rain sensor
- Temperature sensor
- Some jumper cables
- A GOOD USB-C to Micro-USB Cable (rly make sure it’s good, I’ll explain later why)
- An outdoor case for the sensors/ESP
- Some heat shrink tubes
- A Powerbank with “always on” feature (or alternatively something like this) (See Problem III)
All in all you should not spend more than max 15€, probably less…
Preparation
I’m not going to explain in detail how you setup your Arduino IDE, it’s quite simple. If you need a guide, you can follow this one.
After setting up the IDE and powering on the ESP, I wanted to start simple as everybody and get the led to blink.. This is where everything started to go sideways.
Problem I, finding the matching usb driver
I was using a MacBook with Mac OS BigSur 11.0.1. Finding the correct driver was not the biggest issue after checking the chip on the ESP (Most likely it’s a CH340 chipset), however installing the driver was a mess, as the driver was not updated for Big Sur, but Apple decided to strengthen the security for kernel extensions. The result was that I could not install the driver as I was not able to approve the kernel extension in the security settings. The only thing that helped was turning off the system integrity check, installing the driver and turning it back on..
Problem II, Mac does not detect the ESP8266
Yes I have installed the correct driver and yes I tried 4 different cables. Oh and yes, I was under the assumption, I broke the ESP and bought a new one. I was even checking the driver sources.. It turns out the ESP was totally fine, but the cable(s) were the problem. As the Macbook has only USB-C Ports while I was just having USB-A to Micro-USB cables, I was using a dongle. This one seemed to have broken the connection. Buying a new cable that was directly using USB-C fixed the problem. It took me 4 days of trying to find this out. (See parts list)
Problem III, Powerbank turning itself off after x minutes
I’m stepping ahead a little, but I feel like this is another important topic to talk about. If you want to run the ESP using a battery, you have a couple of problems to solve. Beside of the obvious fact that you need to save power where you can (Deep Sleep), you must use something, e.g. a Powerbank to run the ESP and this is where the fun starts. Nowadays, Powerbanks are build to charge smartphones and such. A Powerbank tries to save power where possible, thus 99% of them have an “auto off” mode implemented. This means if the Powerbank notice there’s little to no power consumption, it turns itself off. As the ESP is using too little power, the Powerbank will turn off. There are hacks out there how you can work around this, but all of them included consuming extra power so that the auto-off mode is disabled. Luckily, I had a very old Powerbank (an old promotional gift) which did not have the auto-off “feature”. If you don’t have this, you should consider taking a look at the parts section of this article, I’ve added an alternative which is using 4 AA batteries to usb. You can for sure build numerous different solutions, I found this the quickest and simplest one.
After I fixed those issues, I was finally able to start with the actual work.
Requirements
As Homekit is not able to show historical data, I had to come up with a little workaround. Also as I was running the ESP on battery power, I wanted to know the current status of the battery.
- Using Homebridge as the receiver of the sensor data
- Having historical data of the temperature and how much power I have left in the Powerbank
If I wouldn’t want to have historical data, things would have been simpler, the ESP would just have send the data to Homebridge and that’s it.
This is the architecture I’m using to enable both, historical data and forwarding data to Homekit.
Building
Let’s start with the building process. For the following explanation, I’m expecting you to basically copy my setup. For this to work, you need to be able to deploy a nodeJS server somewhere as an endpoint for the ESP (to store temperature and power consumption data for historical charts)
Hardware
Let’s start with the ESP and the wiring.
Software
All needed code is available at Github.
ESP8266
To flash the needed code to the ESP, you need to use the Arduino IDE. The code can be found here. After cloning the repository, you first have to rename configEXAMPLE.h to config.h and adjust the values to the ones matching your environment.
Note: If you don’t want historical data, you can simply point the urls in the config to Homebridge instead of pointing them to the server backend.
Once the code has been flashed to the ESP, it will try to read the data from the sensors and send them using your wifi every 25 minutes. In between it’s falling into a Deep Sleep.
The deep sleep basically shuts down the whole ESP (thus power consumption is extremely low). After a specific time, the ESP is being woken up (for this you need the connection between pin RST and D0). A wakeup is basically the same as if you would press the reset button, thus the setup method is executed again.
NodeJS Server
As said, I have decided to have some backend service as I’d like to have historical data. This is totally optional. The code is here. It’s a pretty simple node server, serving an api and a static page with 2 charts.
You can deploy anywhere you like, only requirement is that the ESP can send data to it and Homebridge can query it.
This is how the 2 charts looks for me.
Homebridge
Homebridge is as the name implies a (software) bridge that enables Homekit for devices, that are actually not supported. There are numerous plugins. I’m running Homebridge on my Raspberry Pi Zero WH.
The 2 plugins we need to use to this project are this for the temperature data and this for the rain detection.
Note, if you decided to not use the server, you only need the last plugin.
homebridge-http-temperature-sensor Plugin
This plugin collects temperature data from somewhere. This somewhere can be anything as long as it’s a rest-GET endpoint. Perfect for us, because we query nodeJS to get the latest temperature value. Yes, I could have also let the ESP send the data to Homebridge directly, but this would have meant another HTTP call and as I wanted to save as much power as possible, I wanted to avoid this.
homebridge-http-webhooks
This extremely powerful plugin enables webhooks in Homebridge. You need to add a new webhook so that the ESP can send the rain detection data. As I did not need historical data for this, I could send it directly to Homebridge without sending it to the server first.
In the plugin, simply create a new contact sensor, name it “rain”, copy the given url and copy it into your config.h in the ESP code.
Obviously Homekit does not support the sensor type “rain” thus a contact sensor should do the trick. If it’s open, it doesn’t rain, if it’s closed, it’s raining.
Putting it all together
After you’ve deployed the node server, configured Homebridge and flashed the ESP, it’s time to put everything together.
As the whole thing is running outside, I wanted to have it waterproof, thus I bought a waterproof case (see Parts section).
Power consumption / Powerbank
The last part, but probably one of the most important ones is the power management. As said previously, I’ve decided to work with a Powerbank as I was lucky enough to find one without the auto-off feature. If you don’t have such a device, you have 3 choices.
a) power the ESP directly using an outlet
b) Using some Lipo battery, avoiding the USB port
c) use an adapter from AA batteries to USB
If you’re not too experienced, I would advise NOT to play around with lipos as this could go horribly wrong if you don’t know what you’re doing.
As I did not find a matching waterproof box for my Powerbank, I was getting a little creative and used an old tooth-brush box and wrapped it in duck-tape. I am using 2 USB cables, one to re-charge the Powerbank, the other one to power the ESP.
It works good.. Well, there’s not much you can’t solve without duck tape..
Power consumption data
The last part which I’d like to cover here is the power consumption data, that the ESP is sending to the nodeJS server every xx minutes. This is to monitor how much power is left and when I have to re-charge the Powerbank. Unfortunately you cannot read the battery voltage Vin without external components. There is however a method to detect a discharged battery indirectly, by measuring the input voltage of ESP8266 called V3.3.
In my code, the ESP is configured to read the V3.3 voltage by placing ADC_MODE(ADC_VCC);
Then, the battery voltage in mV is read by calling ESP.getVcc();
I found that my Powerbank at full capacity produces a value of 3.929 while a nearly empty Powerbank produced 2.854. Knowing those thresholds enables me to establish alertings if desired. The problem with this solution however is that you cannot use the analog pin A0 on your ESP anymore, thus you cannot read the analog temperature data. But this compromise should be ok as you still get the digital value (it’s raining, it’s not raining).
I hope this article helps you build your own weather station. Best of luck and happy hacking :)