Raspberry Pi Temperature Monitor
Table of Contents
Introduction
I recently needed to temperature monitor, log and alert on over temperatures. I had a look in my parts bin and I found a Raspberry PI a 1-Wire HBA, a 1-Wire temperature IC and a 3G dongle.
Solution
I needed a quick way to create anImage I could throw on the Pi. I didn’t want to have to maintain it, and if the pops I want to be able to generate a replacement image easily.
In the end I created the below script. It’s not particually nice, but it works.
Method
#!/bin/bash -x
umount /dev/loop0
rm -r -f /home/thomas/rpi23-gen-image
export proxy=1.2.3.4:3128
export somemirror=debmirror
export ntpserver=1.2.3.4
export pinghost=1.2.3.4
export nhostname=logger
export smarthost=smarthost.isp.com
export http_proxy="http://$proxy/"
export https_proxy="http://$proxy/"
git clone https://github.com/drtyhlpr/rpi23-gen-image.git /home/thomas/rpi23-gen-image
sed -i 's/\(.*firmware_install\)/#\1/' /home/thomas/rpi23-gen-image/bootstrap.d/13-kernel.sh
cd /home/thomas/rpi23-gen-image
cat << EOF > bootstrap.d/80-local.sh
. ./functions.sh
sed -i 's/ftp.debian.org/$somemirror/' "\${ETC_DIR}/apt/sources.list"
echo "Europe/London" > "\${ETC_DIR}/timezone"
sed -i "s/^pool/#pool/" "\${ETC_DIR}/ntp.conf"
echo "server $ntpserver iburst\n" >> "\${ETC_DIR}/ntp.conf"
echo "Acquire::http::Proxy \"http://$proxy/\";\n" > "\${ETC_DIR}/apt/apt.conf.d/99proxy"
cat files/ferm.conf > "\${ETC_DIR}/ferm/ferm.conf"
cat files/50unattended-upgrades-local > "\${ETC_DIR}/apt/apt.conf.d/50unattended-upgrades-local"
cat files/sms-service-notification.sh > "\${ETC_DIR}/icinga2/scripts/sms-service-notification.sh"
chmod +x "\${ETC_DIR}/icinga2/scripts/sms-service-notification.sh"
cat files/check_w1retap > "\${ETC_DIR}/icinga2/scripts/check_w1retap"
chmod +x "\${ETC_DIR}/icinga2/scripts/check_w1retap"
cat files/prometheus-w1retap.sh > "\${ETC_DIR}/icinga2/scripts/prometheus-w1retap.sh"
chmod +x "\${ETC_DIR}/icinga2/scripts/prometheus-w1retap.sh"
cat files/local.conf > "\${ETC_DIR}/icinga2/conf.d/local.conf"
#sed -i 's/}//' "\${ETC_DIR}/icinga2/conf.d/apt.conf"
#echo "\ninterval = 86400\n}\n" >> "\${ETC_DIR}/icinga2/conf.d/apt.conf"
sed -i 's/vars.backup_downtime/#vars.backup_downtime/' "\${ETC_DIR}/icinga2/conf.d/services.conf"
sed -i 's/^/#/' "\${ETC_DIR}/icinga2/conf.d/users.conf"
cat files/backup.sh > "\${ETC_DIR}/cron.daily/backup.sh"
chmod +x "\${ETC_DIR}/cron.daily/backup.sh"
echo "* * * * * root ping -c 1 -n $pinghost > /dev/null" > "\${ETC_DIR}/cron.d/pinghome"
echo "0 * * * * root chmod -R o+r /var/log/icinga2/compat" > "\${ETC_DIR}/cron.d/fix-icinga-perm"
sed -i 's#^dc_eximconfig_configtype=.*#dc_eximconfig_configtype=satellite#' "\${ETC_DIR}/exim4/update-exim4.conf.conf"
sed -i 's#^dc_readhost=.*#dc_readhost=$nhostname#' "\${ETC_DIR}/exim4/update-exim4.conf.conf"
sed -i 's#^dc_smarthost=.*#dc_smarthost=$smarthost#' "\${ETC_DIR}/exim4/update-exim4.conf.conf"
sed -i 's#^dc_hide_mailname=.*#dc_hide_mailname=true#' "\${ETC_DIR}/exim4/update-exim4.conf.conf"
sed -i 's#^device = .*#device = /dev/modem00#' "\${ETC_DIR}/smsd.conf"
sed -i 's#^GROUP=.*#GROUP=\"smsd\"#' "\${ETC_DIR}/default/smstools"
echo 'ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", SYMLINK+="modem%E{ID_USB_INTERFACE_NUM}"' > "\${ETC_DIR}/udev/rules.d/99-usb-serial.rules"
sed -i 's#^log.*#log = w1sqlite=/var/lib/w1retap/w1retap.sqlite#' "\${ETC_DIR}/w1retap.conf"
echo "282BE781080000A8|DS1820|ROOM|Temperature #1|°C|||||" >> "\${ETC_DIR}/w1retap-sensors.dat"
mkdir -p "\${ETC_DIR}/systemd/system/w1retap.service.d"
echo "[Service]\nExecStart=\nExecStart=/usr/bin/w1retap -d -R -t 60\nRestart=always\n" > "\${ETC_DIR}/systemd/system/w1retap.service.d/override.conf"
mkdir -p "\${ETC_DIR}/systemd/system/paths.target.wants"
echo "[Unit]\nDescription=Read data from w1retap database when .w1retap.dat is updated\n\n[Path]\nPathChanged=/var/lib/w1retap/.w1retap.dat\n\n[Install]\nWantedBy=paths.target\n" > "\${ETC_DIR}/systemd/system/prometheus-w1retap.path"
echo "[Unit]\nDescription=Publish w1retap readings to prometheus\n\n[Service]\nType=oneshot\nExecStart=/etc/icinga2/scripts/prometheus-w1retap.sh\n" > "\${ETC_DIR}/systemd/system/prometheus-w1retap.service"
ln -s /etc/systemd/system/prometheus-w1retap.path "\${ETC_DIR}/systemd/system/paths.target.wants/prometheus-w1retap.path"
ln -s /lib/systemd/system/w1retap.service "\${ETC_DIR}/systemd/system/multi-user.target.wants/w1retap.service"
ln -s /lib/systemd/system/prometheus-node-exporter.service "\${ETC_DIR}/systemd/system/multi-user.target.wants/prometheus-node-exporter.service"
EOF
cat <<EOF > files/ferm.conf
domain (ip ip6) chain (INPUT OUTPUT FORWARD) policy DROP;
domain (ip ip6) chain (INPUT OUTPUT) {
mod conntrack ctstate INVALID DROP;
mod conntrack ctstate (ESTABLISHED RELATED) ACCEPT;
}
domain (ip ip6) chain INPUT interface lo ACCEPT;
domain (ip ip6) chain OUTPUT outerface lo ACCEPT;
domain ip chain (INPUT FORWARD OUTPUT) proto icmp ACCEPT;
domain ip6 chain (INPUT FORWARD OUTPUT) proto icmpv6 ACCEPT;
domain (ip ip6) chain INPUT {
proto tcp dport (ssh http https 9100) ACCEPT;
}
domain (ip ip6) chain OUTPUT {
proto (tcp udp) dport domain ACCEPT;
proto udp dport ntp ACCEPT;
proto tcp dport (ssh smtp http https 3128 8080) ACCEPT;
}
domain (ip ip6) chain INPUT NFLOG nflog-prefix 'INPUT';
domain (ip ip6) chain FORWARD NFLOG nflog-prefix 'FORWARD';
domain (ip ip6) chain OUTPUT NFLOG nflog-prefix 'OUTPUT';
domain ip chain (INPUT FORWARD OUTPUT) REJECT reject-with icmp-admin-prohibited;
domain ip6 chain (INPUT FORDWARD OUTPUT) REJECT reject-with icmp6-adm-prohibited;
EOF
cat <<EOF > files/50unattended-upgrades-local
Unattended-Upgrade::Origins-Pattern {
"o=Debian,a=stable";
"o=Debian,a=stable-updates";
"o=Debian,a=proposed-updates";
"o=Debian,a=stable-backports";
"origin=Debian,archive=stable,label=Debian-Security";
};
Unattended-Upgrade::Mail "root";
Unattended-Upgrade::Automatic-Reboot "false";
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
EOF
cat <<EOF > files/backup.sh
#!/bin/sh
set -eu
export OS_TOKEN="*********"
export OS_OBJECT_STORE="https://openstackapi.endpoint:port/swift/v1"
curl -k -H "X-Auth-Token: \$OS_TOKEN" -X PUT "\$OS_OBJECT_STORE/logger"
cat /var/lib/w1retap/w1retap.sqlite | gzip > /var/lib/w1retap/w1retap.sqlite.gz
curl -k -H "X-Auth-Token: \$OS_TOKEN" -X PUT -T /var/lib/w1retap/w1retap.sqlite.gz "\$OS_OBJECT_STORE/logger/w1retap.sqlite.gz"
EOF
cat <<EOF > files/sms-service-notification.sh
#!/bin/sh
template=\$(cat <<TEMPLATE
To: \$USERPAGER
\$NOTIFICATIONTYPE - \$SERVICEDISPLAYNAME is \$SERVICESTATE - \$SERVICEOUTPUT at \$LONGDATETIME
TEMPLATE
)
/usr/bin/printf "%b" "\$template" > /var/spool/sms/outgoing/\$(date +%s%N)
EOF
cat <<EOF > files/prometheus-w1retap.sh
#!/bin/bash
set -eu
dir=/var/lib/prometheus/node-exporter
if [[ ! -d \$dir ]]; then
echo 'prometheus-node-exporter not installed?' >&2
exit 0
fi
q=$'
SELECT "w1retap_temp_celsius{id=""" || value || """,type=""" || abbrv1 || """,name=""" || name1 || """} " || value
FROM readings
INNER JOIN w1sensors
ON readings.name = w1sensors.name1
WHERE date > strftime(\'%s\', \'now\') - 60
GROUP BY type,abbrv1,name1,value
;
'
(
echo "# HELP w1retap_temp_celsius Temperature in Celsius"
echo "# TYPE w1retap_temp_celsius gauge"
sqlite3 -cmd "\$q" /var/lib/w1retap/w1retap.sqlite < /dev/null
) > "\$dir/w1retap.prom.tmp"
mv "\$dir/w1retap.prom.tmp" "\$dir/w1retap.prom"
EOF
cat <<EOF > files/check_w1retap
#!/bin/bash
set -eu
sensor_name="ROM"
#warning=20
#critical=21
warning=27
critical=28
udate=\$(awk -F= '/udate=/{print \$2}' /var/lib/w1retap/.w1retap.dat)
now=\$(date +%s)
if [[ \$(( \$now - \$udate )) -ge 65 ]]; then
echo "UNKNOWN - Data out of date"
exit 3
fi
value=\$(awk -F= "/\$sensor_name=/{print \\\$2}" /var/lib/w1retap/.w1retap.dat | awk '{print \$1}')
if [[ \$( echo "\$value > \$critical" | bc -l) -eq 1 ]]; then
echo "CRITICAL - w1retap temperature \$value C"
exit 2
elif [[ \$( echo "\$value > \$warning" | bc -l) -eq 1 ]]; then
echo "WARNING - w1retap temperature \$value C"
exit 1
else
echo "OK - w1retap temperature \$value C"
exit 0
fi
EOF
cat <<EOF > files/local.conf
apply Service "w1retap" {
import "generic-service"
check_command = "w1retap"
assign where host.name == NodeName
check_interval = 15s
retry_interval = 15s
}
object UserGroup "icingaadmins" {
display_name = "Icinga 2 Admin Group"
}
object User "thomas" {
import "generic-user"
display_name = "thomas"
groups = [ "icingaadmins" ]
email = "thomas@stewarts.org.uk"
pager = "447987654321"
}
object CheckCommand "w1retap" {
command = [ "/etc/icinga2/scripts/check_w1retap" ]
}
object NotificationCommand "sms-service-notification" {
command = [ "/etc/icinga2/scripts/sms-service-notification.sh" ]
env = {
NOTIFICATIONTYPE = "\$notification.type$"
SERVICEDESC = "\$service.name$"
HOSTALIAS = "\$host.display_name$"
HOSTADDRESS = "\$address$"
SERVICESTATE = "\$service.state$"
LONGDATETIME = "\$icinga.long_date_time$"
SERVICEOUTPUT = "\$service.output$"
NOTIFICATIONAUTHORNAME = "\$notification.author$"
NOTIFICATIONCOMMENT = "\$notification.comment$"
HOSTDISPLAYNAME = "\$host.display_name$"
SERVICEDISPLAYNAME = "\$service.display_name$"
USERPAGER = "\$user.pager$"
}
}
apply Notification "sms-icingaadmin" to Service {
import "mail-service-notification"
command = "sms-service-notification"
user_groups = host.vars.notification.mail.groups
users = host.vars.notification.mail.users
assign where host.vars.notification.mail
}
object ScheduledDowntime "weeklytest-downtime" {
host_name = "logger"
service_name = "w1retap"
author = "icingaadmin"
comment = "Scheduled downtime for weekly test"
ranges = {
"friday" = "13:30-13:32"
}
}
EOF
#TODO
#check email setup re root email
#root resize seems to fail
# in notification:
# if (service.vars.notification_interval) {
# interval = service.vars.notification_interval
# }
# in service:
# vars.notification_interval = 43200
#root@logger:~# cat /etc/cron.d/check
#* * * * * root /root/check.sh
#root@logger:~# grep . /root/check.sh
##!/bin/bash
#set -eu
#files="$(find /var/spool/sms/incoming -type f)"
#for file in $files; do
# if [ "$(tail -1 $file | grep temp | wc -l)" -eq 1 ]; then
# from="$(grep "From:" $file | awk '{print $2}')"
# hist="$(sqlite3 -cmd "SELECT date, value FROM readings ORDER BY date DESC LIMIT 10;" /var/lib/w1retap/w1retap.sqlite < /dev/null | sed 's/|/ /' | while read line; do d=$(echo $line | awk '{print $1}'); d=$(date -d @$d --iso-8601=minutes | sed 's/:00//'); v=$(echo $line | awk '{print $2}'); echo "$d $v"; done)"
# echo -en "To: $from\n\n$(cat /var/lib/w1retap/.w1retap.dat | grep -v udate | xargs)\n$hist" \
# > /var/spool/sms/outgoing/$(date +%s%N)
# sed -i 's/temp/TEMP/' $file
# fi
#done
#root@logger:~#
#INFO
#send test txt: echo -en "To: 447987654321\n\ntest\n" > /var/spool/sms/outgoing/test
#FIRST BOOT
# sudo passwd user
# sudo dpkg-reconfigure tzdata
# echo "exim4-config exim4/dc_postmaster string thomas@stewarts.org.uk" | sudo debconf-set-selections
# sudo update-exim4.conf
# echo "root: thomas@stewarts.org.uk" | sudo tee -a /etc/aliases
# sudo usermod -a -G smsd nagios
# sudo htpasswd /etc/icinga2-classicui/htpasswd.users icingaadmin
# sudo -u w1retap sqlite3 /var/lib/w1retap/w1retap.sqlite < /usr/share/doc/w1retap-doc/mksens.sql
# sudo w1find DS2490-1 | w1sensors | sed 's/NULL,NULL,//' | sed 's/TMP_1/ROOM/' | sudo -u w1retap sqlite3 /var/lib/w1retap/w1retap.sqlite
# sudo systemctl reboot
export proxy="http://$proxy/"
cat <<EOF > templates/logger
export http_proxy="$proxy"
export https_proxy="$proxy"
export no_proxy="$mirror"
export APT_PROXY="$proxy"
export APT_SERVER="$mirror"
export APT_INCLUDES="aptitude,atop,bash-completion,bc,bind9-host,busybox,curl,debian-goodies,debsums,dnsutils,dstat,etckeeper,fake-hwclock,ferm,file,firmware-linux-free,git,htop,less,mtr,netcat-openbsd,nmap,ntp,ntpdate,parted,psmisc,psutils,pv,resolvconf,rsync,screen,tcpdump,telnet,ulogd2,unattended-upgrades,usbutils,vim,vnstat,w1retap,w1retap-sqlite,w1retap-doc,smstools,prometheus-node-exporter,icinga2,sqlite3,apache2,icinga2-classicui,monitoring-plugins-basic,exim4-daemon-light,dphys-swapfile,strace,mailutils"
export RPI_MODEL=2
export RELEASE="stretch"
export HOSTNAME="$hostname"
export USER_PASSWORD="password"
export DEFLOCAL="en_GB.UTF-8"
export TIMEZONE="Europe/London"
export EXPANDROOT=true
export ENABLE_DHCP=true
export ENABLE_CONSOLE=true
export ENABLE_NONFREE=true
export ENABLE_SOUND=false
export ENABLE_MINGPU=false
export ENABLE_USER=true
export USER_NAME=user
export BUILD_KERNEL=false
export ENABLE_HARDNET=true
export NET_NTP_1="$ntpserver"
EOF
CONFIG_TEMPLATE=logger ./rpi23-gen-image.sh
exit
#sudo bmaptool copy /home/thomas/rpi23-gen-image/images/stretch/*.img /dev/mmcblk0