[Heads-up: This is a work in progress, I’m adding to it as I go.]
I want to monitor the temperature in all the rooms in my house.
Why? I like comfort and efficiency. If I know the temperature of each room in my house, with periodic measurements twenty four hours a day, I can tune the heating system to be comfortable and energy efficient. Because I’m a bit of a geek, this is classed as ‘fun’ which means I don’t need to offset the cost of the project against my heating bill.
What? I want a way to have a log of the temperature in each room of my house at regular intervals without having to be there in person, or - for that matter - be awake.
How? Well, that’s the question, isn’t it? My starting assumption is that I need a sensor in every room. This rules out a single smart thermostat which might learn my habits, but would be woefully under-informed about the temperatures across my house.
Contents:
Priorities
I’ve had lots of recommendations for good approaches. There are trade-offs to be made for each:
- Battery vs mains
- Portability
- Low maintenance
Some applications need the freedom to put the sensors anywhere. My preference is to have a system that I maintain (in person) about once a year. I’m happy to give up a power socket per room to get that, and have the sensor within reach of that power socket.
- Wifi vs bluetooth vs Z-Wave vs Zigbee vs ethernet
- Dedicated device vs DIY mashup
- Arduino vs Raspberry Pi
- Affinity to my skills
I’ve done my time writing assembler and embedded C (for now, at least). I learnt both at university, and applied those skills in my first job after my degree. I’ve helped write I2C libraries and (different job) an X10 module in Python. I think I’ve got the aptitude to use any of those options. But do I want to?
- Alignment to my areas of interest
I’m working in the wonderful world of DevOps, where Python and Ansible and Prometheus are regularly in the spotlight. I’m a manager in my day-job, so I don’t actually get to play with the toys (except spreadsheets). It’d be cool to have a solution that uses those.
- Price per unit: Cheaper is better, as long as the fun-factor is maintained.
- Development time: Quicker is better. There aren’t many fun-project-hours in a given month.
- Availability of equipment: If it needs a lathe, a 3D printer or an underground network of tunnels, it’s out.
Arduino approach
Cost | Thing |
---|---|
£20 | Arduino uno / £6 Arduino nano |
£5 | Real time clock board/Data logging shield |
£6 | Temperature sensor |
£8 | Bluetooth module?? |
Total: £39 per unit. I reckon that component list wouldn’t work - the nano and uno have different form factors, the bluetooth has to talk to … something, but it gives me a place to start. I’ve heard I get a WiFi-enabled-Arduino-compatible board from China for cheaps. So that’s an option.
Raspberry Pi approach
Cost | Thing |
---|---|
£10 | Raspberry Pi Zero W |
£4 | DS18B20 temperature sensor |
£0 | 4.7kohm resistor - free with sensor |
£1 | 40 pin header |
£6 | USB PSU |
£3 | Case |
£3 | Shipping |
Total: £27 per unit
Blocker: I can order only one Raspberry Pi Zero W per customer? What madness is this?
I’m going to give the Raspberry Pi route a try. It hits a lot of the sweet spots, and it’ll be fun - even if I can’t source 10 RPi Zero Ws because of the bizarre sales limits.
Purchases
Here’s what I’m starting out with.
Central control server:
- Raspberry Pi 4
- microSD card
- Case
- Pi 4 official power supply
Temperature sensor pi:
- Waterproof DS18B20 Digital temperature sensor + extras
- Raspberry Pi Zero W
- microSD card
- Case
- Micro-USB power supply
microSD OS image
The first order of business is to get a process for bootstrapping the Raspberry Pi Zeros.
Install the official Raspberry Pi Imager
…from https://www.raspberrypi.org/software/.
(You could use this zsh script I wrote to do that, but honestly it seems like a lot of trouble to go to.)
IMAGER="/Applications/Raspberry Pi Imager.app"
# Install RPi imager software if it's not already available
if [[ ! -a $IMAGER ]]; then
IMAGER_DOWNLOAD="https://downloads.raspberrypi.org/imager/imager_1.5.dmg"
wget $IMAGER_DOWNLOAD
DISKIMAGE=$(hdiutil attach ./imager_1.5.dmg | grep 'Raspberry' | cut -f1)
cp -R "/Volumes/Raspberry Pi Imager/Raspberry Pi Imager.app" /Applications/
hdiutil detach $DISKIMAGE
fi
Transfer the OS image to the microSD card
- Open Raspberry Pi Imager
- Plug in microSD card
- Choose
Raspberry Pi OS Lite (32-bit)
- Choose microSD card
- CHoose Write
- MacOS is likely to ask you for various permissions for the imager
- The imaging unmounts the SD card, so unplug it and plug it in again
Prepare the OS image for first boot
The first boot will be headless (no keyboard/monitor) and wireless (i.e. I want it to connect to my Wifi with no further configuration nesessary). The Pi OS image checks for a few additional files in the /boot directory on first boot. That enables me to enable SSH and WiFi.
From a terminal, with the microSD card plugged back in…
cd /Volumes/boot
Enable SSH:
touch ssh
Enable and configure WiFi:
cat << EOF > wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
network={
ssid="YOUR_SSID"
psk="YOUR_WIFI_PASSWORD"
key_mgmt=WPA-PSK
}
EOF
Eject the microSD card safely using Finder, and unplug it.
#First boot
- Assemble the Raspberry Pi Zero in the case
- Insert the microSD card
- Run
arp -a
to list the devices connected to your network - Plug the power supply into the wall and plug the lead into the microUSB connector (it’s the one closest to the corner of the board).
- Wait a minute or two for the Pi to boot
- Run
arp -a
and spot the difference. The host name for me israspberrypi.myhomedomain
Configure with Ansible
There are a number of bootstrap tasks to perform that will let me connect to the Pi with Ansible in a consistent way.
- Create SSH keys
- Create a new user
- Enable SSH access for that user with that key and remove its password
- Enable passwordless sudo for that user
- Set the hostname
- Clean up (delete) the default user
Ideally, I’d like to complete those tasks automatically with Ansible too, but I don’t know how yet, so in the interim:
Create pubic-private keypair
$ ssh-keygen -t rsa -f ./rpi-key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./rpi-key.
Your public key has been saved in ./rpi-key.pub.
The key fingerprint is:
SHA256:JRdQyqJfuDglJ4r+SqsdFXIF8FlXSi9QAE3ZY2nHXnU ak@Ashpool
The key's randomart image is:
+---[RSA 3072]----+
| ..o=*==*+ .. E|
| . +o=*+o.. . |
| . = .o*++. |
| o o o =. |
| = + S |
| . o B o |
|..o o o |
|o... . |
|o++. |
+----[SHA256]-----+
$ ls rpi-key*
rpi-key rpi-key.pub
Log in using SSH
$ ssh [email protected]
The authenticity of host 'raspberrypi.myhomedomain (172.80.43.99)' can't be established.
ECDSA key fingerprint is SHA256:6ryJBtgVc6k1liVATfBBXnapErFLAArbhVhwoFu7aw0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'raspberrypi.myhomedomain,172.80.43.99' (ECDSA) to the list of known hosts.
[email protected]'s password:
Linux raspberrypi 5.4.83+ #1379 Mon Dec 14 13:06:05 GMT 2020 armv6l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.
pi@raspberrypi:~ $
Create a new user
pi@raspberrypi:~ $ sudo adduser robot
Adding user `robot' ...
Adding new group `robot' (1001) ...
Adding new user `robot' (1001) with group `robot' ...
Creating home directory `/home/robot' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for robot
Enter the new value, or press ENTER for the default
Full Name []: Ansible Robot
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] y
pi@raspberrypi:~ $
Give that user passwordless sudo access
pi@raspberrypi:~ $ sudo adduser robot sudo
Adding user `robot' to group `sudo' ...
Adding user robot to group sudo
Done.
pi@raspberrypi:~ $
sudo visudo /etc/sudoers.d/010_robot-nopasswd
Enter robot ALL=(ALL) NOPASSWD: ALL
Save and quit the editor
Test:
pi@raspberrypi:~ $ logout
Connection to raspberrypi.myhomedomain closed.
$ ssh robot@raspberrypi
robot@raspberrypi:~ $ sudo whoami
root
Give robot user same groups as pi
sudo cat /etc/group | grep pi
sudo usermod -G adm,dialout,cdrom,audio,video,plugdev,games,users,input,netdev robot
Authorise public key for that user
From my dev laptop:
$ ssh-copy-id -i ./rpi-key.pub [email protected]
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "./rpi-key.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '[email protected]'"
and check to make sure that only the key(s) you wanted were added.
$ ssh [email protected] -i ./rpi-key
Linux raspberrypi 5.4.83+ #1379 Mon Dec 14 13:06:05 GMT 2020 armv6l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
robot@raspberrypi:~ $
Remove password for user
robot@raspberrypi:~ $ sudo passwd robot -d
passwd: password expiry information changed.
robot@raspberrypi:~ $
Remove default user ‘pi’
robot@raspberrypi:~ $ sudo deluser --remove-home pi
Looking for files to backup/remove ...
Removing files ...
Removing user `pi' ...
Warning: group `pi' has no more members.
Done.
robot@raspberrypi:~ $
Set hostname
robot@raspberrypi:~ $ echo "mon-livingroom" | sudo tee /etc/hostname
mon-livingroom
robot@raspberrypi:~ $ sudo sed -i 's/raspberrypi/mon-livingroom/g' /etc/hosts
robot@raspberrypi:~ $ sudo reboot
$ ssh [email protected] -i ./rpi-key
The authenticity of host 'mon-livingroom.myhomedomain (172.80.43.99)' can't be established.
ECDSA key fingerprint is SHA256:6ryJBtgVc3k1liVATeBBXnapErFLAArbhVhwoFu7aw0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'mon-livingroom.myhomedomain' (ECDSA) to the list of known hosts.
Linux mon-livingroom 5.4.83+ #1379 Mon Dec 14 13:06:05 GMT 2020 armv6l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Mar 26 22:05:57 2021 from 172.80.41.127
robot@mon-livingroom:~ $
Ansible bit
This is what I want set up on my Raspberry Pi:
- Daily automatic security updates
- Reboots as needed (or weekly)
Services to set up:
- Prometheus
Application metrics to collect:
- Hostname/location
- Temperature
System metrics to collect:
To be continued…