Micropython Based Room Sensors: Part 1

Having recently moved into a new house, I find myself with a profusion of Smart Lights (not everywhere yet, but in more locations than I have previously had). The main problem is that I currently lack a way to drive these intelligently. Right now I have a few automations that drive them based on sunset/sunrise times and media state through Home Assistant. This is mainly due to having almost no sensors deployed in the new house currently – something I’m aiming to address in this project.

I’m planning to build and deploy a set of ESP8266 based sensors across the house, with at least one in each room. The base hardware for this is the ESP8266 connected to a PIR motion sensors and DHT22 temperature and humidity sensor (so nothing ground breaking). This should give me temperature/humidity data for the whole house as well as motion events that can be used as a starting point to drive the light automation.

Why ESP8266?

I’ve gone through several options for the sensor platform on the way to settling on the ESP8266. I’ve tried out MySensors and even gone as far as building a battery powered prototype complete with PCB. Unfortunately I stuffed up the PCB design so that the radio didn’t work and never got around to working out the problem. Thinking further on this I find the software platform limiting. For example, any kind of OTA firmware update is difficult.

The main disadvantage of the ESP8266 is the power usage, but given that I now own this house and that these are permanent sensors I’m planning on powering them via a 12v supply run from the main server cabinet through the roof space to each sensor. There is more than enough power from a 12v 2A supply to provide power to all the sensors.

Also, it’s cheap and easy to work with!

Why Micropython?

I had originally looked at either writing some custom firmware using the Arduino ESP8266 core or using ESPEasy. I’ve tried out ESPEasy on my first prototype and it does what I need, but as an Embedded Software Engineer by day I felt I needed to be more adventurous.

I love Python as my go to language whenever the platforms don’t dictate something else (in the case of embedded this almost always ends up being C or C++). Recently I’ve been getting more engaged with the Python ecosystem via a couple of excellent podcasts (Talk Python and Python Bytes), so this was a good time to get back into writing some Python at home. Having played around with earlier versions of Micropython on both the ESP8266 and the ESP32 I had a good idea of its capabilities and knew it could do what I needed.

Current Status

As of right now, I have one prototype sensor running using a ‘bare’ ESP-12 module with adapter board, plus the sensors soldered on to some vero-board (photos below). Using the ‘bare’ ESP module added quite a bit of complexity since you are responsible for pulling the various lines required to program/run the chip up or down. It’s not difficult, but it’s more difficult than it should be. For that reason, after I’ve exhausted my one remaining ‘bare’ module/adapter I will be switching to Wemos D1 Mini modules.

In terms of the hardware, I encountered a couple of issues building the first prototype. Whilst the ESP8266 adapter board I used has a regulator to take 5V down to the 3V3 required for the ESP, I wanted to use 12V to reduce the voltage drop through the wires in the ceiling space. This meant I needed another regulator to go from 12V down to 5V. At first I used a spare linear regulator I had in my parts box for this. As it turns out this was a mistake, whilst it powered the ESP and sensors just fine, the whole thing got very hot (even with an extra heat sink). This also affected the reading from the temperature sensor. The solution was to order some cheap buck converter modules online, which did the trick without getting the slightest bit warm and are much more efficient.

The second issue is a weird one. Whilst re-programming the ESP from ESPEasy to Micropython, I noticed that after running the erase flash command the current going to the board would get very high (~400mA at 12V!), this would result in the ESP getting very hot. Seemingly this didn’t damage it because I did it several times and it always continued to work. In addition to this the Micropython firmware wouldn’t boot, instead just spewing incomprehensible (at any of the common baud rates) garbage to the UART. As it turns out, the chip was not being erased correctly, running an erase regions across the full extent of flash did the trick:

If anyone knows what the problem with these modules is, please get in touch in the comments. I couldn’t find any reference to this problem online and the (probably cloned) Wemos modules I have don’t have the same problem.

Anyway, here are some photos of the finished prototype:

Fully assembled prototype

Fully assembled prototype with PIR sensor connected.

Front of prototype

Front of prototype showing ESP8266 and adapter board

Back of prototype

Back of prototype, the wires in the bottom right corner are where it was re-worked after changing the power supply

The Software

The software is fairly basic, but has a few nice features. I use the boot.py script to load the configuration from the config.json file on the internal filesystem, then I connect to the wifi following the example given in the Micropython documentation. After this main.py is executed which connects to the broker and initialises the sensors. This is where things get a bit more interesting. I’ve written a minimal implementation of the Home Assistant MQTT Discovery spec, which so far supports binary sensors and standard sensors. This allows the sensors to come up in HASS without any configuration on the HASS server (except enabling MQTT discovery, which is a one time operation). Reading from the sensors themselves is fairly standard, using a pin change interrupt for the motion sensor and the standard dht module for the temperature/humidity. The use of uasyncio allows the DHT sensor to be polled at regular intervals. The code for the whole program is available via GitLab (also mirrored on GitHub). You can see a screenshot of the sensors in HASS below:

Home Assistant state card

Home Assistant state card showing the automatically added entities

In comparison to other embedded platforms/languages, writing a Micropython application is awesome. The power of Python makes you extremely productive. I wrote the whole software in a couple of hours, including the MQTT discovery implementation, using a Wemos board with no sensors connected as my development platform. When I uploaded this to the prototype board it hit a couple of exceptions in the sensor code, which previously hadn’t been exercised. The key thing here is that it hit exceptions! The resulting stack traces of course tell you where and why the exception occurred. What could have been a long and arduous debugging session turned into a few minutes of tweaking. The availability of uasyncio is also a really nice feature and allows direct knowledge transfer from CPython.

Future Work

There is still some work to do in order to finish the project, mostly on the hardware side. Obviously I need to make enough sensors to cover the house, which is just an ongoing assembly task. There is also the in ceiling wiring, assembly into cases and mounting. I’ll be sure to post an update on this as I make progress. There are also a couple of software improvements I would like to make. Firstly, I would like to add a meta sensor which makes use of the LWT feature of MQTT to report the status of the unit, but also still utilises HASS MQTT discovery. I’m also planning to spin out the current MQTT discovery implementation into it’s own Python module, which will be published to PyPI. The only other software task is to write a script to automate the deployment of the Micropython firmware, application and device specific configuration, which will be useful when programming multiple units.

Thats all for now. I’ll be posting further parts in this series as the project progresses, so subscribe to the feed, join the mailing list (above) or follow me on Twitter to keep up.

My Home Automation Setup

Welcome to this long awaited (by me at least) post about my Home Automation setup, specifically my Home Assistant configuration. It feels like I’ve been promising this post forever, so it’s great to finally deliver. Let’s get straight into it.

I’ve pushed my full Home Assistant configuration to GitLab and will be linking to various parts throughout this post. The config makes heavy use of secrets, to obscure sensitive details about my infrastructure (the sensitive files themselves are encrypted with git-crypt).

What is Home Assistant?

Home Assistant Logo

 

Unless you’ve had your head in the sand or just have no interest in home automation (why are you reading this?) you should know that Home Assistant (HASS) is an Open Source home automation server written in Python (3). What you might not know is that it has an awesome and very active set of developers, two weekly release cycle and a friendly and helpful community. At the time of writing it supports 668 different components. A component is the HASS term for an integration with an external device, tool or service. These components form the base for a device and manufactuer agnostic home automation system. Due to the sheer number of them, chances are you have several HASS compatible devices or service subscriptions, even if you are not into home automation.

I ended up trying out Home Assistant whilst looking for an alternative to OpenHAB. My reasons for switching away from OpenHAB were that I found the profusion of DSLs unweildy and the automation rules difficult to debug, so I never managed to get a satisfactorily working system. I haven’t followed the project since moving to HASS, so these issues might have improved. I would encourage anyone for whom HASS doesn’t appeal to head over and take a look.

After being initally sceptical that the YAML based configuration and automations in HASS would be flexible enough to do what I wanted, I was pleasently surprised by the level of functionality available at little effort. Things like Scenes, which had been tricky in OpenHAB, were easy in HASS! Overall Home Assistant just operates at a higher level of abstraction, which makes things simpler. Since I switched the project has gone from strength to strength and gets better with every release!

My Setup and Hardware

My Home Assistant Frontend

My Home Assistant Frontend

As previously documented Home Assistant runs in a VM on my main home server. It talks mostly to devices in an isolated subnet – so that my IoT devices are firewalled from both the main LAN and the internet at large. The firewall on this subnet blocks both incoming and outgoing traffic, preventing any of these devices from calling home without my say so. The only ports open are those required to allow the devices to speak to HASS or the MQTT server (plus DNS and DHCP to the firewall).

In terms of hardware, I currently have:

  • 3x Milight GU10 RGBW bulbs and the associated (crappy) wifi bridge (I actually have the older wifi bridge). These are located in the living room and provide the main overhead lighting as well as evening mood lighting when watching TV.
  • 2x Kankun SP3 wifi switches, for which I wrote the HASS platform integration. These are connected to some low power (500W) heaters which provide heating in the bedrooms.
  • 2x Raspberry Pis with various sensors connected (temperature/humidity and motion). These also have attached Webcams which stream to ZoneMinder via MJPG-Streamer. One of these also forms the RC-Switch gateway for the RF switches below.
  • 3x 433Mhz dumb RF switches connected to a couple of lamps and the kettle, these are actuated via an MQTT to RC-Switch bridge implemented in Node-RED running on the aforementioned RPi.
  • 2x home built sensors which publish sensor data (temperature, light and motion) from the bedrooms via MQTT.
  • 1x Cheap (and insecure) nondescript Chinese IP camera – yes, I did change the default password and this thing is well firewalled (incoming and outgoing). Again, this streams to ZoneMinder.

In addition, I have Home Assistant setup with my Kodi instance as a media player and use the DarkSky support for providing weather information. Presence detection is provided via OwnTracks and SNMP from my pfsense firewall.

For notifications, I’m using both SMTP and the native HTML5 notifications. I’m particularly pleased with the HTML5 notifications, which are a recent addition to my config. They are a bit of a pain to setup, but they finally spurred me on to getting a proper nginx reverse proxy set up for HASS and getting a proper TLS certificate with Let’s Encrypt. Once set up they a reliable, fast and look great on all our devices. I haven’t yet tried out the actions support, but it does open up some interesting possibilities for new automations.

One component which is conspiciously absent from my setup is any kind of physical control of the smart devices. Some devices (like the Kankun switches) will sync their state back to HASS when manually actuated, but most need to be directly addressed by HASS in order to prevent getting into an inconsistent state. Aside from implementing automations (detailed below), so that manual intervention isn’t required for common actions, we also use the HTTP Shortcuts app on our phones for reasonably quick switching of devices. The user experience is still not brilliant, so it would be good to have some physical switches for some things in the future.

Scripts and Automations

The ‘A’ in Home Automation is for automation. Up until now, I’ve described the infrastructure that provides me with (remote) Home Control. The real power of HASS is in its capability to act without direct user input, or to react to your behaviour (somewhat) intelligently. To this end I have several automations and scripts set up to perform various actions, based on what’s going on. In no particular order these are:

  • Execute an ‘Away Mode’ script when presence detection reports everyone has left. There is a corresponding ‘Deactivate Away Mode’ script for when someone returns home. The away mode script switches my cameras into motion detect mode (indoor cameras are also powered up, since they are powered down for privacy when we are home). It also sends a notification to tell us this has happened.
  • On weekday mornings turn on the lights if it is still dark outside and turn on the kettle (this will cause it to boil automatically if I remembered to set it up the night before). The lights get turned off a little while later. The kettle gets turned off at night, ready for the next day. This automation only executes if someone is home.
  • Switch the living room lights into Movie mode in the evening (after a certain time and if the sun has set), when pressing play in Kodi. If playback is paused or stopped the main lights come back up. I recently added transitions to these changes, which don’t work perfectly with the Milight bulbs but are better than the harsh change I had before.
  • Turn on the lights just before sunset, with an adjustment for cloud cover. Through a bit of experimentation I found that 20 mins before sunset was good for fine days and 40 mins was good for cloudy days. This automation only executes if someone is home.
  • Turn on the lights if someone comes home after sunset. This works really well with the combination presence detection via OwnTracks and SNMP – the lights are always on by the time we get in the house.
  • Send various notifications, mostly for motion detection if we are out or at certain times. Also sends me an email when HASS has an upgrade pending.
  • This isn’t really an automation, but I use the Generic Thermostat component to control the heaters in the bedrooms. This is filtered to switch off based on presence by a couple of template sensors which wrap the actual temperature sensors when someone is home and return 100°C when everyone is out, thus making sure the heaters stay off. I’m sure there is a better way to do this, but it works.
  • I also run AppDaemon, but currently only have a single app – OccuSim, which mimics our lighting patterns when we are away.

That’s pretty much it. Those automations cover most of our current use cases, but there are definately more to come and there will be much more as I add more devices to the setup.

The Future

There’s lots to add in future. In addition to solving the manual input problems, I’m very interested in replacing the unreliable RC-Switches with some Sonoff modules (running custom firmware) and adding some more for other appliances. I’m also interested in upgrading my Milight gateway to a homebuilt one based on the ESP8266/NRF24L01 modules. I also like the look off the Yeelight bulbs as a better alternative to Milight. In addition I’ll soon be moving my Kodi install to a Raspberry Pi which will allow me to play with some HDMI-CEC stuff. I also need to improve the design of my frontend pages in HASS.

I’ve looked into many of the available components within HASS for devices which may be applicable to my setup, including Z-Wave and the Zigbee based platforms (Hue, IKEA Tradfri, etc.). Many of these platforms either don’t meet my requirements in terms of security (most Z-Wave devices don’t appear to use encryption [not that Milight or RC-Switch are secure either, but at least they are only switching low power LEDs]), are too expensive (looking at you Hue) or have limited availability here in NZ (Z-Wave devices using the AU/NZ spectrum are limited in number and I can’t find anywhere shipping the Tradfri devices to NZ [for the record Tradfri fits my security requirements]). For these reasons, I’ve been working on more custom devices based on Arduino/MySensors (for battery powered devices) and ESP8266/Homie for mains powered devices. The key here will be building something reliable and getting the physical design right so it is robust and not unsightly. Some of the new Z-Wave Plus devices also look promising due to their encryption support (particularly the Aeotec devices e.g. this).

For all of the above, I’ll try to do write ups here when I can. It’s a pretty long list and should keep me going for quite some time!

I hope you’ve enjoyed reading this high level view of my home automation setup. I’ll happily receive suggestions for improvements in the comments, or field questions. You can follow me on Twitter if you are that way inclined or subscribe to the RSS or email updates (see sidebar). Thanks again for reading.

Monthly Update: April 2017

So I don’t actually have very much to say this month. Although I’ve done quite a lot, I don’t yet have much to show for it. All going well that should change soon.

I’ve now ‘completed’ my Home Assistant configuration and am currently working on the long awaited blog post. I put completed in air quotes there, because it will never really be finished. It is however in a state where I’m happy to share it, will all the known issues fixed.

The other project that I’ve been working on is the previously mentioned ESP8266 project, which is also nearing completion. Once it’s completed I will share the code and mention it here, but it’s unlikely to reach the stage of a full blog post, since I didn’t really document the electronics well enough as I went along!

That’s all for now, let’s see what happens in May.

Monthly Update: March 2017

It’s been another busy month, but mostly with non-tech stuff, so this will be a short post. I’m nearing completion of a Home Assistant config that I’m happy to publish. The new config is now deployed on my live HASS system and I’m just ironing out a few bugs and making slight improvements here and there. Then I just need to find time to write it up. I’m probably being really precious about keeping it to myself until my inner perfectionist is happy, but I want something that I can point to when people ask me about Home Assistant or home automation in general as an example of what you can do.

Probably the reason I haven’t managed to quite finish this off this month is that I decided to take a detour into Arch Linux again, which is always a fun way to spend time (if your idea of fun involves kernel panics and chroots that is). Suffice to say I now have a nice MATE based Arch setup on my laptop, which so far hasn’t broken (except when I decided to set up Plymouth) and is blindingly fast compared to Ubuntu MATE on the same machine.

I’ve also been playing around with one of my ESP8266s and Homie, but so far didn’t get much done. That will be a story for another day.

That’s it for this update. Looks like April is shaping up to be a quieter month, so with a bit of luck there might be a bit more to see around here in the next month or so.

Monthly Update: February 2017

Hello again. It’s been a busy (and short) month so I don’t have much to update on. Most of my work this month has gone into refactoring my Home Assistant configuration into something which is publicly sharable. This has mostly involved splitting the configuration into more logical chunks than the few monolithic files I had previously and extracting secrets out into a file protected by git-crypt. I’ve also been updating and improving aspects of my config as I go, particularly the automations. I’m not quite ready to share this since I still have a couple of things to clean up and also need to actually deploy and test the new configuration. Hopefully this will be posted on gitlab during March, with an accompanying blog post here.

I’ve also been working on another Home Assistant related task, which was to get AppDaemon working. This was specifically so I could run Occusim, which provides occupancy simulation (turns things on and off when you’re not there) for Home Assistant. It didn’t take me long to get this up and running, but my first live test of Occusim it didn’t work, due to me not removing the test command properly. Now that I’ve fixed that issue, it works great.

I think that’s pretty much it for now. Hopefully there will be more to share next month.