ryan-williams / sensors

Home temperature + humidity metrics: custom sensors and dashboards
0 stars 0 forks source link

sensors

Scratch repo with work I've done to monitor the temperature and humidity in my apartment: 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, I bought 1, then 2, then 4 small-ish Honeywell HCM350W humidifiers, before realizing I needed something heavier and adding an Aircare MA1201. 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 sensors one winter, but they required proactively pulling data with my phone via Bluetooth. I bought their $100 wifi bridge 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 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:

Hardware

The basic setup for one sensor is currently:

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

A Pi 3 B also runs [InfluxDB] collecting metrics from the sensors and a [Grafana] server serving dashboards.

Software

A "temps" service runs 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/