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:

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.

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.

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:

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.

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:

Individual client certificates can be revoked. You don’t have to configure authentication on every device you own if someone loses their phone.

While I highly doubt there are any issues with HomeAssistant, I feel more confident in nginx and openssl.

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.

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:

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.

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.

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: