Günstig Temperatur, Luftfeuchte und Energie messen mit Raspberry Pi oder PC

Drahtloses Anbinden von Temperatursensoren und Energiemesser. Und das noch günstig. Sehr hilfreich war dieser Beitrag. Er beschreibt die Anbindung von drahtlosen Sensoren an Fhem. Fhem wollte ich jetzt (noch) nicht aufsetzen, deshalb realisierte ich meine eigene Anbindung in der die Temperaturkurven auf dem Webserver des Raspi angezeigt werden.Bildschirmfoto 2014-03-19 um 21.28.26

Zutaten: Ein Raspi (kann aber auch ein NAS, PC oder Mac sein). Ein Jeelink (arduino mit 868 MHz Sender/Empfänger auf einem USB-Stick) (Versand dauert ca. 4 Tage). Einen (oder mehrere, ich habe inzwischen 7) passende Temperatursensoren. (Gibt es auch mit Luftfeuchtemesser).

Verarbeitung: Der Jeelink muss mit dem passenden Sketch bestückt werden. Danach lauscht er nach senden Thermostationen und gibt das Ergebnis über seine serielle Schnittstelle aus. Zum Auslesen habe ich mir folgendes Perl-Script erstellt (alpha):

#!/usr/bin/perl
$|++;

# LaCrosse auslesen
# Interpretation:
# OK
# 9
# 1 Byte: addr
# 1 Byte: battery, type, channel
# 2 Byte: temperature 
# 1 Byte: battery_low, humidity

use strict;
use warnings;

use Device::SerialPort;

my $device1 = 'F0'; 
my $device2 = '68'; 
my $device3 = 'E0'; 
my $device4 = 'CC'; 
my $device5 = '58'; 
my $device6 = 'D4'; # Fensterbrett war 38
my $device7 = '54'; 
my $device8 = 'DC'; 
my $device9 = '94'; 

my $port;
my %devices = ($device1 => 'n', $device2 => 'n', $device3 => 'n', $device4 => 'n', $device5 => 'n', $device6 => 'n', $device7 => 'n', $device8 => 'n', $device9 => 'n');
	my $sec;
	my $min;
	my $hour;
	my $mday;
	my $mon;
	my $year;
	my $wday;
	my $yday;
	my $isdst;
	my @myvalues;
	my $hygro;

 sub check_output{

     my $answer;
     my $answer1;
     # my( @bytes, $channel,$cmd,$addr,$data,$power,$consumption );
     my( @bytes, $addr, $battery_new, $type, $channel, $temperature, $battery_low, $humidity ); 
      my $state;
      my $readonly;

	my @array;
	my $len;

 while(1){    
	print STDERR "wait for read\n";
    $answer1 = $port->read(255);
   	print STDERR "\n>" . $answer1 . "<-\n";

	#print "read\n";
    if ($answer1 ne "") {
    	$answer = $answer . $answer1;
    	#print "\n>" . $answer . "<\n";
		if( $answer =~ m/^OK.*\n/ ) {
			last;
		}
		$len = length($answer);    	
		if ($answer ne "" && $len > 1000){ #something went wrong
			print STDERR "---- delete length $len too long----\n";
			print STDERR ">" . $answer . "<\n";
			$answer = "";
			}
		if (length($answer) >= 2){
			if (substr($answer, 0, 2) ne "OK"){ #something went wrong
				print  STDERR  "---- delete wrong start----\n";
				$answer = "";
				}
			}

    }
    sleep(2);
}
#Falls mehrere Zeilen geliefert werden, 
@array=split(/\n/, $answer);

foreach (@array){
$answer = $_;
#  if( $answer =~ m/^OK.*\n/ ) {
  if( $answer =~ m/OK 9 \d+ \d+ \d+ \d+ \d+/ ) {
    @bytes = split( ' ', substr($answer, 5) );

 $addr = sprintf( "%02X", $bytes[0] );
$battery_new = ($bytes[1] & 0x80) >> 7;
$type = ($bytes[1] & 0x70) >> 4;
$channel = $bytes[1] & 0x0F;
$temperature = ($bytes[2]*256 + $bytes[3] - 1000)/10;
$battery_low = ($bytes[4] & 0x80) >> 7;
$humidity = $bytes[4] & 0x7f; 

 # we simply write the temperatur at the hash
	print STDERR "Adr: " . $addr;
    print STDERR " Batt_new: " . $battery_new;
    print STDERR " Type: " . $type;
    print STDERR " Chan: " . $channel;
    print STDERR " Temp: " . $temperature;
    print STDERR " Batt_low: " . $battery_low;
    print STDERR " Hum: " . $humidity . "\n";
  $devices{$addr} = $temperature;
  if ($addr eq 'E0'){
  	$hygro = $humidity;
  }

  #Wenn neue Adresse, dann hier ausgeben

    $answer ="";

} 

 }#for each
}  # sub check_output

# -------------
# Hauptprogramm

    # Set up the serial port
    #print "Start\n";

    $port = Device::SerialPort->new("/dev/ttyUSB0");
#    $port = Device::SerialPort->new("/dev/tty.usbserial-AM01YRW0");

    # 19200, 81N on the USB ftdi driver
    $port->baudrate(57600); # you may change this value
    $port->databits(8); # but not this and the two following
    $port->parity("none");
    $port->stopbits(1);
    $port-> write_settings;
    $port-> lookclear;
     #print "start";

my $i;
$i = 7;        
while($i > 0){    

print STDERR "Durchlauf Nr: $i \n";

$port-> lookclear;
sleep(4);
check_output();

$i = $i -1;

#sleep(900);
#exit;

#debug

 # output block; put at the end
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
    $mon = $mon +1;
    $mon = sprintf("%02d", $mon);
    $mday = sprintf("%02d", $mday);
    $hour = sprintf("%02d", $hour);
    $min = sprintf("%02d", $min);
    $sec = sprintf("%02d", $sec);
    $year = $year + 1900;
	#@myvalues = values %devices;

# ToDo Aufräumen, muss auch weiterlaufen wenn bei einem Gerät die Batterie leer ist	
if  ($devices{$device1} eq "n") {
 print STDERR "na 1  $device1 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device2} eq "n") {
 print STDERR "na 2  $device2 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device3} eq "n") {
 print STDERR "na 3  $device3 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device4} eq "n") {
 print STDERR "na 4  $device4 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device5} eq "n") {
 print STDERR "na 5  $device5 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device6} eq "n") {
 print STDERR "na 6  $device6 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device7} eq "n") {
 print STDERR "na 7 $device7 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device7} eq "n") {
 print STDERR "na 8 $device8 nicht gefunden\n";
 sleep(4);
 next;
}
if  ($devices{$device9} eq "n") {
 print STDERR "na 9 $device9 nicht gefunden\n";
 sleep(4);
 next;
}
	print "$year-$mon-$mday" . "_" . "$hour:$min:$sec";
	print " $devices{$device1}";
	print " $devices{$device2}";
	print " $devices{$device3}";
	print " $hygro";
	print " $devices{$device4}";
	print " $devices{$device5}";
	print " $devices{$device6}";
	print " $devices{$device7}";
	print " $devices{$device8}";
	print " $devices{$device9}";
	print "\n";
 # output block; put at the end

 #nochmal alle aufzaehlen
 print STDERR "Alle erfolgreich gefunden\n";

exit;

$i = $i -1;
sleep(58);
     #print "slept";

 }
    print STDERR "Abbruch nicht genug gefunden\n";
 	print "$year-$mon-$mday" . "_" . "$hour:$min:$sec";
	print " $devices{$device1}";
	print " $devices{$device2}";
	print " $devices{$device3}";
	print " $hygro";
	print " $devices{$device4}";
	print " $devices{$device5}";
	print " $devices{$device6}";
	print " $devices{$device7}";
	print " $devices{$device8}";
	print " $devices{$device9}";
	print "\n";

Dazu noch einen cronjob, der die ausgabe des Perl-scripts parst durch gnuplot schickt und die entstandene Grafikdatei auf den Webserver schiebt. – Fertig.

 

Wie verbindet man den Jeelink mit dem Raspberry PI: link