Solar-Powered Outdoor Thermometer with Multiple DS18B20 Sensors

I’ve been pretty happy with how my ESP8266-powered outdoor thermometers turned out.  One of these has two sensors — one to measure ambient temperature, and one to measure the temperature of a hot tub.  It’s solar-powered (with an 18650 Li-Ion battery), uses a single GPIO pin, and never needs charging!

DS18B20 Temperature Sensor

DS18B20s* are great digital thermometers for DIY projects.  They’re about the same price as the more popular DHT11*, and while they don’t measure humidity, they have a really cool advantage: you can use multiple sensors on the same data pin!  They also support a parasitic power mode, which drops their standby power draw to close to 0.

Diagram showing how to set up DS18B20s in parasite power mode. Image from tweaking4all.

Firmware

I updated the ESP8266 firmware I’ve been using to support multiple sensors, and added a nice web UI:

This allows me to push readings from multiple sensors connected to the same GPIO pin to different MQTT topics.  You can also push readings to an HTTP server.

The finished setup

In deep sleep mode, this project is suitable for battery life.  My outdoor thermometer uses an 18650 cell with a 5v solar panel and battery protection circuit.  I’ve never needed to charge it.  It’s been running for months.

Tips on power efficiency:

  1. Use an efficient voltage regulator.  Many dev boards use an AMS1117, which has a very high quiescent current.  You’re probably best off with a buck converter*, but an HT7333 or similar would be a lot better too.
  2. Use parasitic power mode!  Just wire Gnd and Vin on the DS18B20 to Gnd, and add a 4.7 KΩ pullup resistor to the data line.
  3. Disable any LEDs that are on for long periods of time.  I just used a pair of pliers to break the power LED.

I use a 3.5mm aux cable soldered to the probe wires to connect the DS18B20 probe to the ESP8266 circuit:

This is nice because it’s easy to add length with an extension cable or split the line with a standard aux splitter:

Here is a sloppy circuit in Fritzing.

Links

  1. GitHub page for firmware
  2. DS18B20 datasheet

Components Used*

  1. 5V battery protection circuit for 18650 cells
  2. 5V 180mA solar panel (mine is actually 160mA, but can’t find the product link anymore)
  3. 18650 Li-Ion Battery (recommend getting Samsung or Panasonic)
  4. ESP8266-07 and Breakout Board (soldering required. Wemos D1 Mini works if you want to avoid soldering).
  5. Waterproof DS18B20 Temperature Sensor
  6. Buck Converter (not necessary if using Wemos D1 Mini)
  7. Optional: 3.5mm extension cable (cut in half, solder one end to ESP8266 board, other to DS18B20)

* Contains Amazon affiliate link

Using a Milight remote with HomeAssistant

Milight sells 2.4 GHz remotes* for quite cheap (~$12) which can be used to control Milight bulbs*. They also make in-wall panels* that do the same thing. These work quite well, but if you’re using something like HASS, you’ll end up with stale state. For example, if you turn lights on with the remote, that change won’t be reflected in HASS.

I recently released v1.4.0 of esp8266_milight_hub which allows you to use Milight remotes in conjunction with HomeAssistant, or any other platform that works with MQTT. Here’s some footage of it in action:

The ESP8266 is passively listening for packets sent by the remote, and forwards the data to an MQTT topic. HASS reacts by sending commands to a different MQTT topic which instructs the ESP8266 to turn bulbs on. You could just as easily have HASS do something completely different, like control a non-Milight bulb.

If you’re interested in setting this up yourself, instructions are available GitHub project wiki.

* Contains Amazon affiliate link

Securing HomeAssistant with client certificates (works with Safari/iOS)

I recently moved from SmartThings to HomeAssistant. One of the things I didn’t have to think about too much with SmartThings was how to authenticate all of my connected devices (laptops, phones, tablets, etc.) with my HA platform. I wanted to find a good balance between security and convenience with HomeAssistant.

HomeAssistant makes it easy to secure your install with a password. Coupled with TLS, this is pretty solid. But there’s just something about the idea of a publically facing page that anyone on the Internet can get to, protected with nothing but a password that made me feel uneasy.

Client certificates are a very robust authentication mechanism that involves installing a digital certificate on each device you wish to grant access to. Each certificate is signed by the server certificate, which is how the server knows that the client is valid.

This feels nicer than HomeAssistant’s built-in security measures to me for a few reasons:

  1. Individual client certificates can be revoked. You don’t have to configure authentication on every device you own if someone loses their phone.
  2. While I highly doubt there are any issues with HomeAssistant, I feel more confident in nginx and openssl.
  3. Unless you add a passphrase to the client certificates (I didn’t), the whole thing is passwordless and still manages to be pretty darn secure.
  4. If I ever became truly paranoid, I could turn on HomeAssistant’s password protection and my HA dashboard would essentially need two authentication factors (the SSL cert + the password).

While I did find this approach more appealing, there are several drawbacks:

  1. It’s way harder to set up. You need to run a bunch of openssl commands, and install a certificate on each device you want to grant access to.
  2. The HomeAssistant web UI requires WebSockets, which seem to not play nicely in combination with client certificates on Safari or iOS devices. My household has iOS users, so this was something I needed to figure out.

I think I managed to get this working. The only disadvantage is that clients are granted access for an hour after successfully authenticating once. The basic approach is to tag authenticated browsers with an access token that’s good for a short period of time, long enough for them to establish a WebSocket connection. I’ll go through the steps in setting this up.

What you need

  1. Install packages:  sudo apt-get install nginx nginx-extras lua5.1 liblua5.1-dev
  2. openssl
  3. luacrypto module, which exposes openssl bindings in lua.

luacrypto was kind of a pain to install. Here’s what I did to get it working with my nginx install. It involved patching configure.ac (thanks to this very helpful StackOverflow post for the tip):

Setting up a Certificate Authority

There are already good guides on doing this. I recommend this one. In this guide, I’m using the default_CA parameters pre-filled by openssl on my system.

Generate client certificates

I put a script in /usr/local/bin  to make this easier:

You then run this for each device you want to grant access to:

Make sure to supply an export password. Generated certificate files will be placed in /etc/ssl/ca/certs/users .

Get the certificates on the devices

The .p12 file is the one you want. Make sure to not compromise the certificates in the process.

I rsynced the files to my laptop and attached them to a LastPass note, which I could access on my devices. On most devices, you should be able to just open the .p12 file and it’ll do what you want.

On iOS devices, I needed to serve the certificates over HTTPS on a trusted network because they needed to be “opened” by Safari in order to be recognized.

Configure nginx

Here’s my nginx config. You’ll need to substitute your domain and SSL certificate parameters:

If this all worked, you should be able to access my-homeassistant-install.mydomain.com from a device with a client certificate installed, but not otherwise. Unfortunately if you’re using iOS or Safari, you’ll probably notice that the page loads, but you get a forever spinny wheel. If you look in the debugger console, you might see messages that look like this:

This is because the browser isn’t sending the client certificate information when trying to connect to the WebSocket and is therefore failing.

Fixing compatibility with iOS/Safari

Safari does actually send client cert info along with the initial request. Nginx has a really cool module that allows you to insert all sorts of fancy logic with lua scripts. I added one that tags browsers supplying a valid client certificate with a cookie granting access for about an hour. This worked really well. Since this is all over HTTPS, and the access tokens are short-lived, I felt pretty comfortable.

The easiest way I could think of to create a cookie that was valid for a limited time was to use an HMAC. Basically I “sign” a hash of the client’s certificate along with an expiry timestamp. The certificate hash, expiration timestamp, and HMAC are all stored in cookies. Nginx can then validate that the expiration timestamp is in the future, and that the HMAC signature matches what’s expected.

You’ll notice the commented-out line in the nginx config above. Uncomment it:

And add the script:

 

Update (August, 2019)

After upgrading to Ubuntu 18.04, the nginx LUA module stopped working, and every combination of fixes I tried didn’t work.

Fortunately, OpenResty worked out of the box. After adding their PPA and installing it, all of my existing scripts worked. I just copied over my entire nginx config.