Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ryan-williams/sensors

Home temperature + humidity metrics: custom sensors and dashboards
https://github.com/ryan-williams/sensors

Last synced: about 2 months ago
JSON representation

Home temperature + humidity metrics: custom sensors and dashboards

Awesome Lists containing this project

README

        

# sensors

Scratch repo with work I've done to monitor the temperature and humidity in my apartment: https://boodoir.runsascoded.com

[![](https://cl.ly/77642052ea2c/Screen%20Shot%202018-11-21%20at%202.14.24%20PM.png)](https://boodoir.runsascoded.com)

The sawteeth are where the heater turned on / ran. Can you see where someone took a shower? πŸ˜‚

## Background

Most people don't understand that warmer air is less humid, even if it has the same amount of water in it; warmer air can hold more water, so it is "thirstier", and more prone to stealing water from e.g. your skin.

This shook me a few years ago: heated indoor spaces during an NYC winter are often extremely dry (β‰ˆ10% humidity) though the cold outside air is reasonably humid (β‰ˆ40%); I visited Miami and realized I felt much better in 60-80% humidity that exists year-round there, and began humidifying my apartment.

On [the wirecutter's recommendation](https://thewirecutter.com/reviews/the-best-humidifier/), I bought 1, then 2, then 4 small-ish [Honeywell HCM350W humidifiers](https://www.amazon.com/dp/B002QAYJPO), before realizing I needed something heavier and adding an [Aircare MA1201](https://www.amazon.com/gp/product/B004S34ISA). I've run all 5 through 2 NYC winters and generally kept my apt at 50-60% humidity, β‰ˆ40% higher than it would have been otherwise, and noticeably more comfortable.

### Sensors

While determining whether my humidifiers were having an impact, I experimented with several humidity sensors.

#### SensorPush

I used 4 [SensorPush](https://www.amazon.com/gp/product/B01AEQ9X9I) sensors one winter, but they required proactively pulling data with my phone via Bluetooth. I bought [their $100 wifi bridge](https://www.amazon.com/gp/product/B01N17RWWV) and that improved the UX, but it refused to switch to a new wifi router when my apt did. The sensors have unreplaceable batteries, meaning 4x$50 for new ones every 6mos or so, which felt predatory; monitoring each one's battery and replacing individually was also annoying.

#### EngBird

I briefly used [this "InkBird" model](https://www.amazon.com/gp/product/B01G8H6KHA) that runs on a CR2032 "coin cell" battery, which was nice at β‰ˆhalf the price, and with a cheap, replaceable battery. However again, pulling from phone over bluetooth manually is very painful and finicky, and the batteries had to be replaced about every month, so I quickly gave up on them.

#### Homebrewed

I decided I would make my own sensors that:

- run on USB power
- report data automatically+constantly
- over wifi
- to nice dashboards "in the cloud"

## Hardware

The basic setup for one sensor is currently:
- [Raspberry Pi Zero W](https://www.adafruit.com/product/3708) ([plus case](https://www.adafruit.com/product/3252))
- [HTU21D humidity sensor](https://www.adafruit.com/product/3515)
- [16GB micro SD card](https://www.amazon.com/gp/product/B013TMN4GW)

This runs about $50 (like a SensorPush), but should run forever and provide a better analytics UX.

A [Pi 3 B](https://www.adafruit.com/product/3055) also runs [InfluxDB] collecting metrics from the sensors and a [Grafana] server serving dashboards.

## Software

A "temps" service runs [`read.py`](./read.py) on each sensor, with one thread polling temperature+humidity data each second, and another sending them to InfluxDB (buffering and retrying as necessary).

### Sensor setup

Below are some steps I use to initialize a new sensor:

0. set env vars

These env vars will be used at various points:

- `RPI`: new rpi hostname / ssh alias
- `RPI_IP`: local WLAN IP of the new rpi, once its booted + connected to wifi (see step **2.**)
- `SSH_PUBKEY`: basename (within `~/.ssh`) of ssh public key
- `SSID`: wifi ssid
- `PSWD`: wifi password
- `DEVICE`: alias for device in influx db

1. set up OS image on SD card (laptop)

- [Download + unzip raspbian `.zip`](https://www.raspberrypi.org/downloads/raspbian/); I've been using "RASPBIAN STRETCH WITH DESKTOP AND RECOMMENDED SOFTWARE" but will try "RASPBIAN STRETCH LITE" next
- Burn unzipped `.img` onto SD card; I've used [Etcher](https://www.balena.io/etcher/) for OSX
- Configure SSH, wifi (2.4GHz networks only, for Pi Zero W!), and I2C and UART interfaces:

```bash

cd /Volumes/boot

# enable sshd on boot
touch ssh

SSID= # your wifi SSID; 2.4GHz only!
PSWD= # your wifi password

# enable uart, i2c interfaces
cat >> config.txt < wpa_supplicant.conf <

2. power on raspberry pi; set $RPI_IP to local WLAN IP address

Once it's booted:
- find its IP address and store it in `$RPI_IP` for what follows.
- (you can get this from e.g. your wifi router (which it will connect to on boot), or via a serial interface)
- also set `$RPI`: a hostname/alias you will address this RPi as

3. configure passwordless SSH, `temps.service` (laptop)

```bash
# create ssh alias
cat >> ~/.ssh/config <> .ssh/authorized_keys'

# (passwordless!) copy over source file from this repo
scp read.py requirements.txt $RPI:

# set hostname, locale
cat >setup < /etc/hostname
perl -pi -e "s/raspberrypi/$RPI/" /etc/hosts
echo "LC_ALL=en_US.UTF-8" >> /etc/environment
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
locale-gen en_US.UTF-8
EOF
chmod a+x setup
scp setup $RPI: && rm -f setup
ssh $RPI "sudo ./setup && rm -f setup"

# passwordless!
ssh $RPI
```

4. configure rpi

```bash
# set new password for 'pi' user
sudo passwd pi

# remove obsolete local hostname alias
sudo perl -pi -e "s/raspberrypi/$HOSTNAME/" /etc/hosts

# disable password login via SSH; require key that was installed above
sudo bash -c "echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config"

sudo apt-get install i2c-tools
sudo echo i2c-dev >> /etc/modules

# install necessary python deps
sudo pip3 install -r requirements.txt

# set this var to be the device you want to report metrics to InfluxDB as
DEVICE=$HOSTNAME
# set this to the hostname (and optionally port) of the InfluxDB server
SERVER=

# write "temps.service" file
sudo bash -c "cat >/lib/systemd/system/temps.service" </etc/temps/config.json" <

### Server setup

InfluxDB

[From the Influx docs](https://docs.influxdata.com/influxdb/v1.7/introduction/installation/):

```bash
curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add -
source /etc/os-release
echo "deb https://repos.influxdata.com/debian stretch stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
sudo apt-get update && sudo apt-get install influxdb influxdb-client
sudo service influxdb start
```

Grafana



…is [a little trickier](https://grafana.com/grafana/download?platform=arm):

```bash
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_5.4.0_armhf.deb
sudo dpkg -i grafana_5.4.0_armhf.deb
```

*The version you get from a vanilla `sudo apt-get install grafana` is really old! Don't try to use it!*

#### Enable anonymous access

In `/etc/grafana/grafana.ini`:

```
[auth.anonymous]
# enable anonymous access
;enabled = true

# specify organization name that should be used for unauthenticated users
;org_name =

# specify role for unauthenticated users
;org_role = Viewer
```

## Roadmap

[The issue tracker](https://github.com/ryan-williams/sensors/issues) points to a lot of future work.

[InfluxDB]: https://github.com/influxdata/influxdb
[Grafana]: https://grafana.com/