..

Temperature Measurement

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:

graphviz-SomeGraph-ea319bef754f3470a394796cc41a5e3b8763e4db.png

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

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.

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

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.

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).

$ 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.

List of pages in this category:

-- RudolfReuter 2013-01-06 18:55:50


Go back to CategoryDockStar or FrontPage ; KontaktEmail (ContactEmail)

TempMess (last edited 2013-01-12 05:48:24 by dslb-084-058-178-181)