From e309dc99ca8110d0a12436abd627493402ff1e68 Mon Sep 17 00:00:00 2001 From: justme-1968 Date: Wed, 6 Nov 2013 14:49:20 +0000 Subject: [PATCH] new module 36_LaCrosse.pm for LaCrosse IT+ temperature and humidity sensors and JeeLink as RF modem git-svn-id: https://svn.fhem.de/fhem/trunk@4162 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 6 +- fhem/FHEM/36_JeeLink.pm | 18 +- fhem/FHEM/36_LaCrosse.pm | 241 ++++++++++++++++++ .../36_LaCrosse-LaCrosseITPlusReader.zip | Bin 0 -> 3735 bytes 4 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 fhem/FHEM/36_LaCrosse.pm create mode 100644 fhem/contrib/arduino/36_LaCrosse-LaCrosseITPlusReader.zip diff --git a/fhem/CHANGED b/fhem/CHANGED index 836ba4b20..8356478a0 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,6 +1,10 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. - SVN + - feature: new module 36_LaCrosse.pm for LaCrosse IT+ temperature and + humidity sensors with a JeeLabs JeeLink as RF modem. + The matching JeeNode sketch can be found in + .../36_LaCrosse-LaCrosseITPlusReader.zip (by ohweh&justme1968) - feature: YAMAHA_AVR: new attribute request-timeout. - bugfix: YAMAHA_AVR: fix missing greater-than sign. Use different Control-Tag name for RX-Vx75 series @@ -46,7 +50,7 @@ - feature: new modules JeeLink and PCA301 and for the ELV PCA 301 power meter with a JeeLabs JeeLink as RF modem. The matching JeeNode sketch can be found in .../contrib/36_PCA301-pcaSerial.zip - (by justme1968) + (by ohweh&justme1968) - change: PRESENCE: using ping command line utility to check presence on Windows based machines. - feature: install FHEM as Windows service by T.E., see docs/HOWTO_Windows.txt diff --git a/fhem/FHEM/36_JeeLink.pm b/fhem/FHEM/36_JeeLink.pm index 47754cb14..cbcf487f6 100644 --- a/fhem/FHEM/36_JeeLink.pm +++ b/fhem/FHEM/36_JeeLink.pm @@ -18,7 +18,7 @@ sub JeeLink_Write($$); sub JeeLink_SimpleWrite(@); -my $clientsJeeLink = ":PCA301:EC3000:RoomNode:"; +my $clientsJeeLink = ":PCA301:EC3000:RoomNode:LaCrosse:"; my %matchListPCA301 = ( "1:PCA301" => "^\\S+\\s+24", @@ -119,6 +119,13 @@ JeeLink_Shutdown($) return undef; } +sub +JeeLink_RemoveLaCrossePair($) +{ + my $hash = shift; + delete($hash->{LaCrossePair}); +} + ##################################### sub JeeLink_Set($@) @@ -130,6 +137,7 @@ JeeLink_Set($@) my $arg = join("", @a); my $list = "raw:noArg"; + $list .= " LaCrossePairForSec"; return $list if( $cmd eq '?' ); if($cmd eq "raw") { @@ -138,6 +146,11 @@ JeeLink_Set($@) Log3 $name, 4, "set $name $cmd $arg"; JeeLink_SimpleWrite($hash, $arg); + } elsif( $cmd eq "LaCrossePairForSec" ) { + return "Usage: set $name LaCrossePairForSec " if(!$arg || $arg !~ m/^\d+$/); + $hash->{LaCrossePair} = 1; + InternalTimer(gettimeofday()+$arg, "JeeLink_RemoveLaCrossePair", $hash, 1); + } else { return "Unknown argument $cmd, choose one of ".$list; } @@ -548,6 +561,9 @@ JeeLink_Attr(@)
  • raw <datar>
    send <data> as a raw message to the JeeLink to be transmitted over the RF link.

  • +
  • LaCrossePair <sec>
    + enable autocreate of new LaCrosse sensors vor <sec> seconds +
  • diff --git a/fhem/FHEM/36_LaCrosse.pm b/fhem/FHEM/36_LaCrosse.pm new file mode 100644 index 000000000..a3606036c --- /dev/null +++ b/fhem/FHEM/36_LaCrosse.pm @@ -0,0 +1,241 @@ + +# $Id$ +# +# TODO: + +package main; + +use strict; +use warnings; +use SetExtensions; + +sub LaCrosse_Parse($$); + +sub +LaCrosse_Initialize($) +{ + my ($hash) = @_; + + $hash->{Match} = "^\\S+\\s+9 "; + #$hash->{SetFn} = "LaCrosse_Set"; + #$hash->{GetFn} = "LaCrosse_Get"; + $hash->{DefFn} = "LaCrosse_Define"; + $hash->{UndefFn} = "LaCrosse_Undef"; + $hash->{FingerprintFn} = "LaCrosse_Fingerprint"; + $hash->{ParseFn} = "LaCrosse_Parse"; + #$hash->{AttrFn} = "LaCrosse_Attr"; + $hash->{AttrList} = "IODev" + ." ignore:1" + ." filterThreshold" + ." $readingFnAttributes"; +} + +sub +LaCrosse_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + if(@a != 3 ) { + my $msg = "wrong syntax: define LaCrosse "; + Log3 undef, 2, $msg; + return $msg; + } + + $a[2] =~ m/^([\da-f]{2})$/i; + return "$a[2] is not a valid LaCrosse address" if( !defined($1) ); + + my $name = $a[0]; + my $addr = $a[2]; + + #return "$addr is not a 1 byte hex value" if( $addr !~ /^[\da-f]{2}$/i ); + #return "$addr is not an allowed address" if( $addr eq "00" ); + + return "LaCrosse device $addr already used for $modules{LaCrosse}{defptr}{$addr}->{NAME}." if( $modules{LaCrosse}{defptr}{$addr} + && $modules{LaCrosse}{defptr}{$addr}->{NAME} ne $name ); + + $hash->{addr} = $addr; + + $modules{LaCrosse}{defptr}{$addr} = $hash; + + AssignIoPort($hash); + if(defined($hash->{IODev}->{NAME})) { + Log3 $name, 3, "$name: I/O device is " . $hash->{IODev}->{NAME}; + } else { + Log3 $name, 1, "$name: no I/O device"; + } + + return undef; +} + +##################################### +sub +LaCrosse_Undef($$) +{ + my ($hash, $arg) = @_; + my $name = $hash->{NAME}; + my $addr = $hash->{addr}; + + delete( $modules{LaCrosse}{defptr}{$addr} ); + + return undef; +} + + +##################################### +sub +LaCrosse_Get($@) +{ + my ($hash, $name, $cmd, @args) = @_; + + return "\"get $name\" needs at least one parameter" if(@_ < 3); + + my $list = ""; + + return "Unknown argument $cmd, choose one of $list"; +} + +sub +LaCrosse_Fingerprint($$) +{ + my ($name, $msg) = @_; + + return ( "", $msg ); +} + +sub +LaCrosse_Parse($$) +{ + my ($hash, $msg) = @_; + my $name = $hash->{NAME}; + + my( @bytes, $addr, $battery_new, $type, $channel, $temperature, $battery_low, $humidity ); + if( $msg =~ m/^OK/ ) { + @bytes = split( ' ', substr($msg, 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; + } else { + DoTrigger($name, "UNKNOWNCODE $msg"); + Log3 $name, 3, "$name: Unknown code $msg, help me!"; + return undef; + } + + my $raddr = $addr; + my $rhash = $modules{LaCrosse}{defptr}{$raddr}; + my $rname = $rhash?$rhash->{NAME}:$raddr; + + if( !$modules{LaCrosse}{defptr}{$raddr} ) { + Log3 $name, 3, "LaCrosse Unknown device $rname, please define it"; + + my $iohash = $rhash->{IODev}; + return undef if( $iohash->{LaCrossePair} ); + + return "UNDEFINED LaCrosse_$rname LaCrosse $raddr" if( $battery_new ); + return undef; + } + + $rhash->{battery_new} = $battery_new; + + my @list; + push(@list, $rname); + + $rhash->{LaCrosse_lastRcv} = TimeNow(); + + if( $type == 0x00 ) { + $channel = "" if( $channel == 1 ); + + if( defined($rhash->{"previousT$channel"}) + && abs($rhash->{"previousH$channel"} - $humidity) <= AttrVal( $rname, "filterThreshold", 10 ) + && abs($rhash->{"previousT$channel"} - $temperature) <= AttrVal( $rname, "filterThreshold", 10 ) ) { + readingsBeginUpdate($rhash); + readingsBulkUpdate($rhash, "temperature$channel", $temperature); + readingsBulkUpdate($rhash, "humidity$channel", $humidity) if( $humidity && $humidity != 99 ); + if( !$channel ) { + my $state = "T: $temperature"; + $state .= " H: $humidity" if( $humidity && $humidity != 99 ); + readingsBulkUpdate($rhash, "state", $state) if( Value($rname) ne $state ); + } + readingsBulkUpdate($rhash, "battery$channel", $battery_low?"low":"ok"); + readingsEndUpdate($rhash,1); + } + + $rhash->{"previousH$channel"} = $humidity; + $rhash->{"previousT$channel"} = $temperature; + } + + return @list; +} + +sub +LaCrosse_Attr(@) +{ + my ($cmd, $name, $attrName, $attrVal) = @_; + + return undef; +} + +1; + +=pod +=begin html + + +

    LaCrosse

    +
      + + + FHEM module for LaCrosse IT+ (and TFA 35.1111.IT and possibly Conrad WS9160-IT) Temperature and Humidity sensors.

      + + It can be integrated in to FHEM via a JeeLink as the IODevice.

      + + The JeeNode sketch required for this module can be found in .../contrib/36_LaCrosse-pcaSerial.zip.

      + + + Define +
        + define <name> LaCrosse <addr>
        +
        + addr is a 2 digit hex number to identify the LaCrosse device.

        + Note: devices are autocreated on reception of the first message with new battery flag set if LaCrossePair is active for the JeeLink IODevice device.
        +
      +
      + + + Set +
        +

      + + + Get +
        +

      + + + Readings +
        +
      • battery[] + ok or low
      • +
      • temperature[] + Notice: see the filterThreshold attribute.
      • +
      • humidity
      • +

      + + + Attributes +
        +
      • filterThreshold
        + if the difference between the current and previous temperature is greater than filterThreshold degrees + the readings for this channel are not updated. the default is 10.
      • +
      • ignore
        + 1 -> ignore this device.
      • +

      +
    + +=end html +=cut diff --git a/fhem/contrib/arduino/36_LaCrosse-LaCrosseITPlusReader.zip b/fhem/contrib/arduino/36_LaCrosse-LaCrosseITPlusReader.zip new file mode 100644 index 0000000000000000000000000000000000000000..04b58e3235320d15fc52d512583e988244074c5a GIT binary patch literal 3735 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