/BirdhouseDay /BirdhouseWeek |
Temperature Measurement
Contents
|
The target was to collect weather data via radio sensors, display them via web interface and monitor the inside temperature for a specified minimum and maximum threshold. In case of leaving the allowed bandwidth, an email will be send for an alarm.
The resulting temperature and humidity graphs are made over a time span of a day and week, please see the links at the top right of this page.
Components
The used computer should be a low cost Linux capable device with network connection and USB interface. Actually a Seagate Freeagent Dockstar box is used, please see CategoryDockStar. A Raspberry Pi may also be usable.
The computer network port must be connected to a router, in order to allow Internet access.
The web interface is realized with the wiki software http://moinmo.in.
The radio sensors for temperature and humidity are named S300TH, please see here for reference.
The radio receiver with USB port is the module WDE1 (Wetter Daten Empfänger 1 = weather data receiver 1) from company ELV, please see here for reference.
Software
The software should be build with available modules, as much as possible. What was collected:
Bash shell script wde1_read.sh for data read in, started from crontab.
Database rrdtool for collecting the data in weather.rrd.
Shell script rrd_graph_all.sh for updating the graphs every 15 minutes via cron.
Python program temp_alarm.py to check regularly the temperature limit and sending an email alarm.
Wiki software moinmoin for web interface.
Database setup
If not already done install package rrdtool.
# for example: $ sudo apt-get install rrdtool
Before collecting data, the RRD (Round Robin database) must be setup first. This is done with the script file rrd_create_wde1.sh:
#!/bin/sh rrdtool create weather.rrd --step 300 \ DS:temps1:GAUGE:1200:-40:50 \ DS:temps2:GAUGE:1200:-40:50 \ DS:temps3:GAUGE:1200:-40:50 \ DS:temps4:GAUGE:1200:-40:50 \ DS:temps5:GAUGE:1200:-40:50 \ DS:temps6:GAUGE:1200:-40:50 \ DS:temps7:GAUGE:1200:-40:50 \ DS:temps8:GAUGE:1200:-40:50 \ DS:hums1:GAUGE:1200:0:100 \ DS:hums2:GAUGE:1200:0:100 \ DS:hums3:GAUGE:1200:0:100 \ DS:hums4:GAUGE:1200:0:100 \ DS:hums5:GAUGE:1200:0:100 \ DS:hums6:GAUGE:1200:0:100 \ DS:hums7:GAUGE:1200:0:100 \ DS:hums8:GAUGE:1200:0:100 \ DS:temps9:GAUGE:1200:-40:50 \ DS:hums9:GAUGE:1200:0:100 \ DS:winds9:GAUGE:1200:0:200 \ DS:rains9:DERIVE:1200:0:U \ DS:israins9:GAUGE:1200:0:1 \ RRA:AVERAGE:0.5:1:4032 \ RRA:MIN:0.5:96:3600 \ RRA:MAX:0.5:96:3600 \ RRA:AVERAGE:0.5:96:7300 # Datensatz alle 5 min: step 300 # 14 Tage Einzelwerte: 12 x 24 x 14 = AVERAGE 4032 # 20 Jahre Mittelwerte: 365 x 20 = AVERAGE 7300
WDE1 data read, crontab
Start method: by crontab line
In order to access device /dev/ttyUSB0 you have to be a member of the group dialout, if not, you will get a permission problem, please see TempMess#Test_WDE1_Data_Reception .
The WDE1 weather data are read in via shell script wde1_read.sh.
#!/bin/bash # File: wde1_read.sh # Receive remote weather data from USB-WDE1 and store into RRD database # Start with crontab # Adopted from: http://www.kompf.de/weather/technik.html # 2013-01-08 RudolfReuter cd $HOME/Install/rrdtool # Read data from USB-WDE1 # Setup serial port parameters stty -F /dev/ttyUSB0 cstopb -ixon raw speed 9600 > /dev/null read line < /dev/ttyUSB0 # Check for header = "$1" if [[ "${line%%;*}" == '$1' ]] ; then #echo $line > wde1_raw.dat # remove trailing "0", stop character line=`echo "${line%?}"` # format data, remove prefix "$1;1;", replace ";," by ":." tmp=`echo "${line#?1;1;}" | tr ';,' ':.'` # 1. add prefix "N" (date stamp), remove trailing 0 # 2. substitude all (g=global) strings "::" by ":U:" # 3. again point 2., why? data=`echo "N${tmp%%0}" | sed 's/::/:U:/g' | sed 's/::/:U:/g'` # remove trailing ":" data=${data%%:} # save last data values echo $data > rrd_data.dat # update rrdmc rrdtool update weather.rrd $data # save last indoor temperature for alarm compare cut -d ":" -f 6 rrd_data.dat > temp5.dat fi
Note: The bash shell must be used, in order to work properly.
The shell script is started with crontab:
$ crontab -e # append # read every 5 minutes the temp. and hum. values from WDE1 */5 * * * * $HOME/Install/rrdtool/wde1_read.sh > /dev/null # check with $ crontab -l # for a manual test do $ ./wde1_read.sh
Note: In case of an error in the crontab call, you will get a system mail, announced at the next RETURN on the command line. Then check your system mail for the error message:
# Announcement of a system mail Sie haben Post in /var/mail/user. $ ls -ls # check system mail $ mail "/var/mail/user": 40 messages 2 new 5 unread ... N 40 Cron Daemon Wed Jan 9 06:11 19/705 Cron <user@rudiswiki> $HOME/Install/rrdtool/wde1_read.sh > # Read mail ? RETURN ... ERROR: weather.rrd: found extra data on update argument: 0 # delete mail ? d # next mail ? n ... At EOF # Quit mail program ? q
Sensor channels
The WDE1 receiver does have the capacity for 8 different sensors.
Channel 5 is used for Indoor temperature and humitdity.
Channel 6 is used for Outdoor temperature and humitdity.
Generate data graphs
Now you have some data in the database, next you will see in a graph how the trend is.
For me it was the easiest method to update all useful graphs every 15 minutes and display them in a web interface (wiki moinmoin). This is done with the script rrd_graph_all.sh:
#!/bin/sh # file: rrd_graph_all.sh # exec all rrd_graph* files at once, for cron # 2013-01-07 RudolfReuter cd $HOME/Install/rrdtool/ ./rrd_graph_h1d.sh ./rrd_graph_h1w.sh ./rrd_graph_t1d.sh ./rrd_graph_t1w.sh
The crontab entry was setup with:
$ crontab -e # append the following lines: # run every 15 minutes, but with offset of 3 minutes */3,18,33,48 * * * * $HOME/Install/rrdtool/rrd_graph_all.sh > /dev/null # check with: $ crontab -l
The single graphs are defined with the following 4 files.
#!/bin/sh # File: rrd_graph_h1d.sh rrdtool graph hum1d.png --end now --start end-1d --height 125 \ DEF:hums5=weather.rrd:hums5:AVERAGE \ LINE2:hums5#000000:Raum. \ DEF:min=weather.rrd:hums5:MIN \ DEF:max=weather.rrd:hums5:MAX \ VDEF:First=hums5,FIRST \ GPRINT:hums5:MIN:"Humidity %% Min %3.0lf" \ GPRINT:hums5:AVERAGE:"Avg %3.0lf" \ GPRINT:hums5:MAX:"Max %3.0lf" \ GPRINT:First:"from %Y-%m-%d\\n":strftime \ DEF:hums6=weather.rrd:hums6:AVERAGE \ LINE2:hums6#FF0000:Außen \ DEF:min2=weather.rrd:hums6:MIN \ DEF:max2=weather.rrd:hums6:MAX \ GPRINT:hums6:MIN:"Humidity %% Min %3.0lf" \ GPRINT:hums6:AVERAGE:"Avg %3.0lf" \ GPRINT:hums6:MAX:"Max %3.0lf" \ COMMENT:"\\n"
#!/bin/sh # File: rrd_graph_h1w.sh rrdtool graph hum1w.png --end now --start end-1w --height 125 \ DEF:hums5=weather.rrd:hums5:AVERAGE \ LINE2:hums5#000000:Raum. \ DEF:min=weather.rrd:hums5:MIN \ DEF:max=weather.rrd:hums5:MAX \ VDEF:First=hums5,FIRST \ GPRINT:hums5:MIN:"Humidity %% Min %3.0lf" \ GPRINT:hums5:AVERAGE:"Avg %3.0lf" \ GPRINT:hums5:MAX:"Max %3.0lf" \ GPRINT:First:"from %Y-%m-%d\\n":strftime \ DEF:hums6=weather.rrd:hums6:AVERAGE \ LINE2:hums6#FF0000:Außen \ DEF:min2=weather.rrd:hums6:MIN \ DEF:max2=weather.rrd:hums6:MAX \ GPRINT:hums6:MIN:"Humidity %% Min %3.0lf" \ GPRINT:hums6:AVERAGE:"Avg %3.0lf" \ GPRINT:hums6:MAX:"Max %3.0lf" \ COMMENT:"\\n"
#!/bin/sh # File: rrd_graph_t1d.sh rrdtool graph temp1d.png --end now --start end-1d --height 125 \ DEF:temps5=weather.rrd:temps5:AVERAGE \ LINE2:temps5#000000:Raum. \ DEF:min=weather.rrd:temps5:MIN \ DEF:max=weather.rrd:temps5:MAX \ VDEF:First=temps5,FIRST \ GPRINT:temps5:MIN:"Temp. Min %5.1lf" \ GPRINT:temps5:AVERAGE:"Avg %5.1lf" \ GPRINT:temps5:MAX:"Max %5.1lf" \ GPRINT:First:"from %Y-%m-%d\\n":strftime \ DEF:temps6=weather.rrd:temps6:AVERAGE \ LINE2:temps6#FF0000:Außen \ DEF:min2=weather.rrd:temps6:MIN \ DEF:max2=weather.rrd:temps6:MAX \ GPRINT:temps6:MIN:"Temp. Min %5.1lf" \ GPRINT:temps6:AVERAGE:"Avg %5.1lf" \ GPRINT:temps6:MAX:"Max %5.1lf" \ HRULE:0#0000ff \ COMMENT:"\\n"
#!/bin/sh # File: rrd_graph_t1w.sh rrdtool graph temp1w.png --end now --start end-1w --height 125 \ DEF:temps5=weather.rrd:temps5:AVERAGE \ LINE2:temps5#000000:Raum. \ DEF:min=weather.rrd:temps5:MIN \ DEF:max=weather.rrd:temps5:MAX \ VDEF:First=temps5,FIRST \ GPRINT:temps5:MIN:"Temp. Min %5.1lf" \ GPRINT:temps5:AVERAGE:"Avg %5.1lf" \ GPRINT:temps5:MAX:"Max %5.1lf" \ GPRINT:First:"from %Y-%m-%d\\n":strftime \ DEF:temps6=weather.rrd:temps6:AVERAGE \ LINE2:temps6#FF0000:Außen \ DEF:min2=weather.rrd:temps6:MIN \ DEF:max2=weather.rrd:temps6:MAX \ GPRINT:temps6:MIN:"Temp. Min %5.1lf" \ GPRINT:temps6:AVERAGE:"Avg %5.1lf" \ GPRINT:temps6:MAX:"Max %5.1lf" \ HRULE:0#0000ff \ COMMENT:"\\n"
Check for Alarm
Start method: by crontab line
If not already done install package python-rrdtool.
# for example: $ sudo apt-get install python-rrdtool
The indoor temperature check for exceeding the thresholds is done with a Python program temp_alarm.py.
In case of a transition from a temperature value inside the bandwidth to outside, an alert email is send. In order to avoid unnecessary alert emails, a hysteresis is used.
All parameters are stored in a configuration file temp_alarm.cfg.
The state of the alert is written in file temp_alarm.dat.
The crontab entry was setup with:
$ crontab -e # append the following lines: # # run every 15 minutes, but with offset of 4 minutes */4,19,34,49 * * * * $HOME/Install/rrdtool/temp_alarm.py > /dev/null # check with: $ crontab -l
The program is not so long, therefore it is listed here:
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # File: temp_alarm.py
4 # Author: RudolfReuter
5 # Copyright: GPL2
6 # Source: http://www.rudiswiki.de
7 # Version: 2012-01-09
8 # Features:
9 # - computer: Dockstar-Debian
10 # - Email and Text Alerts for High and Low Temperatures
11 # - Data Logging and Analysis using RRDTool
12 # - Custom Configuration parameter
13 #------------------------------------------
14 # Import Libaries
15 import datetime
16 from smtplib import SMTP
17 import time
18 import ConfigParser # to read cfg file
19 from email.MIMEText import MIMEText
20 import sys # for exit
21 import os # for file delete, cd
22
23 #----- Functions -------------------
24
25 def email_alert(subject, message):
26 msg = MIMEText(message)
27 msg['From'] = myEmailFrom
28 msg['To'] = myEmailTo
29 msg['Subject'] = subject
30 server = SMTP(myEmailSMTPsrv)
31 server.login(myEmailFrom, myEmailPwd)
32 try:
33 print "EmailAlert"
34 server.sendmail(myEmailFrom, myEmailTo, msg.as_string())
35 finally:
36 server.quit()
37 try:
38 fpw = open("temp_alert.dat","w")
39 except:
40 print ("Error: File open AlertSend.dat failed")
41 sys.exit(0)
42 fpw.write(message)
43 fpw.close()
44
45 # Begin main program --------------------
46
47 # If called from crontab, change directory is needed.
48 try:
49 home = os.environ['HOME']
50 os.chdir(home + "/Install/rrdtool")
51 print(os.getcwd())
52 except:
53 print ("Error: cd HOME does not work")
54 sys.exit(0)
55
56 # Read in configuration file using Config Parser
57 aConfig = ConfigParser.RawConfigParser()
58 aConfig.read('temp_alarm.cfg')
59
60 myAlertLabel = aConfig.get('cfg', 'alertlabel')
61
62 # Alert level for Temperature
63 alertHighTemp = aConfig.getfloat('cfg', 'alerthightemp')
64 alertLowTemp = aConfig.getfloat('cfg', 'alertlowtemp')
65 alertHyst = aConfig.getfloat('cfg', 'alerthyst')
66
67 # Email parameters
68 myEmailFrom = aConfig.get('cfg', 'emailfrom')
69 myEmailPwd = aConfig.get('cfg', 'emailpwd')
70 myEmailSMTPsrv = aConfig.get('cfg', 'emailsmtpsrv')
71 myEmailTo = aConfig.get('cfg', 'emailto')
72
73 DateNow = time.strftime('%Y-%m-%d %H:%M:%S', (time.localtime(time.time())))
74
75 # Read the actual indoor temperature
76 try:
77 fpr = open("temp5.dat")
78 except:
79 print ("Error at open temp5.dat")
80 sys.exit(0)
81 temp5 = fpr.readline()
82 fpr.close()
83 print("Temperature: " + temp5)
84
85 # Check for Alert recovery
86 try:
87 fp = open("temp_alert.dat")
88 # Check for temperature recovery with hysteris
89 if float(temp5) > (alertLowTemp + alertHyst):
90 if float(temp5) < (alertHighTemp - alertHyst):
91 try:
92 os.remove("temp_alert.dat")
93 except:
94 print("Error: File AlertSend.dat delete failed")
95 sys.exit(0)
96 except:
97 # Alerts checking for high and low temp
98 if float(temp5) < 50.0:
99 if float(temp5) < alertLowTemp:
100 print(DateNow + " Alert: Low Temp °C " + temp5)
101 email_alert(myAlertLabel, DateNow + " Low Temperature: " + temp5)
102 if float(temp5) > alertHighTemp:
103 print(DateNow + " Alert: High Temp °C " + temp5)
104 email_alert(myAlertLabel, DateNow + " High Temperature: " + temp5)
The configuration file is used to change quickly parameters, with no need to touch the program.
[cfg] alertlabel = Temperatur Alarm Vogelhaus alerthightemp = 30.0 alertlowtemp = 15.0 alerthyst = 1.0 emailto = reuterx@xxxx.de emailfrom = reuterx@xxxx.de emailpwd = xxx emailsmtpsrv = mail.xxx.de
Web Interface
The web interface is realized with the wiki software moinmoin, see MoinSetup.
Test WDE1 Data Reception
Connect the WDE1 to the USB plug and check if it is recognized:
# see if the USB device is seen $ ls -ls /dev/ttyU* 0 crw-rw---- 1 root dialout 188, 0 Dez 26 2012 /dev/ttyUSB0 # check if your user is in the group "dialout" $ groups # if the user is not in the group "dialout", add it $ sudo adduser user dialout # logout and login to have the group attached to the user $ groups
Check if you have reception of the sensors:
# if utility "socat" is not installed, do so $ sudo apt-get install socat # check for the data telegram # 2 sensors at address 5 and 6 $ socat /dev/ttyUSB0,b9600 stdout $1;1;;;;;;20,5;6,8;;;;;;;57;84;;;;;;;;0 # inside temperature = 20,5 °C, outside temperature = 6,8 °C # inside humidity = 57 %, outside humidity = 84 % # some times I will receive also a foreign "Kombi sensor" from the neighborhood: $1;1;;;;;;20,4;7,3;;;;;;;57;84;;;6,1;73;0,0;550;0;0 # Kombi Temperature = 6,1 °C, Kombi Humidity = 73 % # Kombi Wind speed 0.0 kmph, Kombi Rain volume = 550 rocker beats # Kombi Rain = 0 = no
Troubleshooting WDE1
If the USB device WDE1 is not seen:
# check for needed kernel modules $ lsmod ... cp210x 17514 0 usbserial 37173 1 cp210x ... # check for USB device $ lsusb ... Bus 002 Device 004: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x Composite Device
Start methods at boot
The start of the bash script wde1_read2.sh at boot time, running in an endless loop was not reliable. But I will describe two easy methods to start the script at boot time, just for reference. The start|stop method in /etc/init.d was too much effort for this job.
Start method: by /etc/rc.local
The shell script is started at boot time with a line in file /etc/rc.local:
start-stop-daemon --background --chuid user:group --start --exec /home/user/Install/rrdtool/wde1_read2.sh --chdir /home/user/Install/rrdtool # for a manual start do $ sudo /etc/rc.local
Note: The shell script should be started with user rights (--chuid) in a specified folder (--chdir) and must run in the background (--background).
Start method: by crontab
$ crontab -e # append # start once at boot time @reboot $HOME/Install/rrdtool/wde1_read2.sh > /dev/null
Note: Take care to make a change directory in the script to the working directory, or use an absolute path.
Links
Bash parameter examples - good examples
List of pages in this category:
-- RudolfReuter 2013-01-06 18:55:50
Go back to CategoryDockStar or FrontPage ; KontaktEmail (ContactEmail)