diff --git a/fhem/FHEM/00_SIGNALduino.pm b/fhem/FHEM/00_SIGNALduino.pm index d2139ccf5..abc89e945 100644 --- a/fhem/FHEM/00_SIGNALduino.pm +++ b/fhem/FHEM/00_SIGNALduino.pm @@ -1,7 +1,7 @@ ############################################## # $Id$ # -# v3.3.2 (release 3.3) +# v3.3.2 (stable release 3.3) # The module is inspired by the FHEMduino project and modified in serval ways for processing the incomming messages # see http://www.fhemwiki.de/wiki/SIGNALDuino # It was modified also to provide support for raw message handling which can be send from the SIGNALduino @@ -25,7 +25,7 @@ no warnings 'portable'; use constant { - SDUINO_VERSION => "v3.3.2ralf", + SDUINO_VERSION => "v3.3.2", SDUINO_INIT_WAIT_XQ => 1.5, # wait disable device SDUINO_INIT_WAIT => 2, SDUINO_INIT_MAXRETRY => 3, @@ -35,9 +35,7 @@ use constant { SDUINO_WRITEQUEUE_NEXT => 0.3, SDUINO_WRITEQUEUE_TIMEOUT => 2, - SDUINO_DISPATCH_VERBOSE => 5, # default 5 - SDUINO_MC_DISPATCH_VERBOSE => 3, # wenn kleiner 5, z.B. 3 dann wird vor dem dispatch mit loglevel 3 die ID und rmsg ausgegeben - SDUINO_MC_DISPATCH_LOG_ID => '12.1' # die o.g. Ausgabe erfolgt nur wenn der Wert mit der ID übereinstimmt + SDUINO_DISPATCH_VERBOSE => 5, # default 5 }; @@ -190,7 +188,7 @@ my %ProtocolListSIGNALduino = ( clientmodule => 'CUL_TCM97001', # not used now #modulematch => '^s[A-Fa-f0-9]+', # not used now length_min => '24', - length_max => '42', + length_max => '46', paddingbits => '8', # pad up to 8 bits, default is 4 }, "1" => @@ -248,16 +246,15 @@ my %ProtocolListSIGNALduino = ( #length_max => '800', # Don't know maximal lenth of a valid message }, - "3.1" => # MS;P0=-11440;P1=-1121;P2=-416;P5=309;P6=1017;D=150516251515162516251625162516251515151516251625151;CP=5;SP=0;R=66; - # MS;P1=309;P2=-1130;P3=1011;P4=-429;P5=-11466;D=15123412121234123412141214121412141212123412341234;CP=1;SP=5;R=38; Gruppentaste + "3.1" => { name => 'itv1_sync40', - comment => 'IT remote Control PAR 1000, ITS-150', + comment => 'IT remote Control PAR 1000', id => '3', - one => [3.5,-1], - zero => [1,-3.8], - float => [1,-1], # fuer Gruppentaste (nur bei ITS-150,ITR-3500 und ITR-300), siehe Kommentar in sub SIGNALduino_bit2itv1 - sync => [1,-44], + one => [3,-1], + zero => [1,-3], + #float => [-1,3], # not full supported now later use + sync => [1,-40], clockabs => -1, # -1=auto format => 'twostate', # not used now preamble => 'i', @@ -265,7 +262,7 @@ my %ProtocolListSIGNALduino = ( modulematch => '^i......', # not used now length_min => '24', #length_max => '800', # Don't know maximal lenth of a valid message - postDemodulation => \&SIGNALduino_bit2itv1, + }, "4" => { @@ -294,7 +291,7 @@ my %ProtocolListSIGNALduino = ( zero => [1,-3], clockabs => 500, # -1 = auto format => 'twostate', # tristate can't be migrated from bin into hex! - preamble => 'i', # Append to converted message + preamble => 'p5#', # Append to converted message clientmodule => 'IT', # not used now modulematch => '^i......', # not used now length_min => '24', @@ -328,7 +325,7 @@ my %ProtocolListSIGNALduino = ( format => 'twostate', preamble => 'P7#', # prepend to converted message clientmodule => 'SD_WS07', # not used now - modulematch => '^P7#.{6}F.{2}$', # not used now + modulematch => '^P7#.{6}F.{2}', # not used now length_min => '35', length_max => '40', @@ -367,7 +364,7 @@ my %ProtocolListSIGNALduino = ( length_min => '60', length_max => '120', - }, + }, "10" => ## Oregon Scientific 2 { name => 'OSV2o3', @@ -425,16 +422,13 @@ my %ProtocolListSIGNALduino = ( length_min => '24', length_max => '26', }, - # MU;P0=-1384;P1=815;P2=-2725;P3=-20001;P4=8159;P5=-891;D=01010121212121010101210101345101210101210101212101010101012121212101010121010134510121010121010121210101010101212121210101012101013451012101012101012121010101010121212121010101210101345101210101210101212101010101012121212101010121010134510121010121010121;CP=1;O; - # MU;P0=-17201;P1=112;P2=-1419;P3=-28056;P4=8092;P5=-942;P6=777;P7=-2755;D=12134567676762626762626762626767676762626762626267626260456767676262676262676262676767676262676262626762626045676767626267626267626267676767626267626262676262604567676762626762626762626767676762626762626267626260456767676262676262676262676767676262676262;CP=6;O; - # MU;P0=-4284;P1=865;P2=-1403;P3=-2706;P4=-20914;P5=8132;P6=-932;D=01213121312121212121213121212121312121312131312131456121312131212121212121312121212131212131213131213141;CP=1;R=252; "13.1" => ## FLAMINGO FA20 { name => 'FLAMINGO FA21 b', id => '13', - one => [1,-1.8], - zero => [1,-3.5], - start => [-23.5,10,-1], + one => [1,-2], + zero => [1,-4], + start => [20,-1], clockabs => 800, format => 'twostate', preamble => 'P13#', # prepend to converted message @@ -501,7 +495,6 @@ my %ProtocolListSIGNALduino = ( #zero => [1,-1], sync => [1,-10], float => [1,-1,1,-1], - end => [1,-40], clockabs => -1, # -1 = auto format => 'twostate', # tristate can't be migrated from bin into hex! preamble => 'i', # Append to converted message @@ -868,7 +861,9 @@ my %ProtocolListSIGNALduino = ( paddingbits => '8', postDemodulation => \&SIGNALduino_lengtnPrefix, filterfunc => 'SIGNALduino_compPattern', - }, + + + }, "40" => ## Romotec { name => 'romotec', @@ -1154,8 +1149,7 @@ my %ProtocolListSIGNALduino = ( }, "60" => ## ELV, LA CROSSE (WS2000/WS7000) { - # MU;P0=32001;P1=-381;P2=835;P3=354;P4=-857;D=01212121212121212121343421212134342121213434342121343421212134213421213421212121342121212134212121213421212121343421343430;CP=2;R=53; - # tested sensors: WS-7000-20, AS2000, ASH2000, S2000, S2000I, S2001A, S2001IA, + # MU;P0=32001;P1=-381;P2=835;P3=354;P4=-857;D=01212121212121212121343421212134342121213434342121343421212134213421213421212121342121212134212121213421212121343421343430;CP=2;R=53; # tested sensors: WS-7000-20, AS2000, ASH2000, S2000, S2000I, S2001A, S2001IA, # ASH2200, S300IA, S2001I, S2000ID, S2001ID, S2500H # not tested: AS3, S2000W, S2000R, WS7000-15, WS7000-16, WS2500-19, S300TH, S555TH # das letzte Bit 1 und 1 x 0 Preambel fehlt meistens @@ -1185,7 +1179,6 @@ my %ProtocolListSIGNALduino = ( id => '61', one => [1,-2], zero => [1,-1], - pause => [-25], clockabs => 400, format => 'twostate', preamble => 'P61#', # prepend to converted message @@ -1393,6 +1386,7 @@ my %ProtocolListSIGNALduino = ( name => 'Siro shutter', comment => 'developModule. Siro is not in github or SVN available', id => '72', + developId => 'm', dispatchequals => 'true', one => [2,-1.2], # 680, -400 zero => [1,-2.2], # 340, -750 @@ -1485,66 +1479,7 @@ my %ProtocolListSIGNALduino = ( length_min => 58, length_max => 58, }, - #.MU;P0=102;P1=236;P2=-2192;P3=971;P6=-21542;D=01230303030103010303030303010103010303010303010101030301030103030303010101030301030303010163030303010301030303030301010301030301030301010103030103010303030301010103030103030301016303030301030103030303030101030103030103030101010303010301030303030101010303;CP=0;O;. - #.MU;P0=-1483;P1=239;P2=970;P3=-21544;D=01020202010132020202010201020202020201010201020201020201010102020102010202020201010102020102020201013202020201020102020202020101020102020102020101010202010201020202020101010202010202020101;CP=1;. - #.MU;P0=-168;P1=420;P2=-416;P3=968;P4=-1491;P5=242;P6=-21536;D=01234343434543454343434343454543454345434543454345434343434343434343454345434343434345454363434343454345434343434345454345434543454345434543434343434343434345434543434343434545436343434345434543434343434545434543454345434543454343434343434343434543454343;CP=3;O;. - #.MU;P0=-1483;P1=969;P2=236;P3=-21542;D=01010102020131010101020102010101010102020102010201020102010201010101010101010102010201010101010202013101010102010201010101010202010201020102010201020101010101010101010201020101010101020201;CP=1;. - #.MU;P0=-32001;P1=112;P2=-8408;P3=968;P4=-1490;P5=239;P6=-21542;D=01234343434543454343434343454543454345454343454345434343434343434343454345434343434345454563434343454345434343434345454345434545434345434543434343434343434345434543434343434545456343434345434543434343434545434543454543434543454343434343434343434543454343;CP=3;O;. - #.MU;P0=-1483;P1=968;P2=240;P3=-21542;D=01010102020231010101020102010101010102020102010202010102010201010101010101010102010201010101010202023101010102010201010101010202010201020201010201020101010101010101010201020101010101020202;CP=1;. - #.MU;P0=-32001;P1=969;P2=-1483;P3=237;P4=-21542;D=01212121232123212121212123232123232121232123212321212121212121212123212321212121232123214121212123212321212121212323212323212123212321232121212121212121212321232121212123212321412121212321232121212121232321232321212321232123212121212121212121232123212121;CP=1;O;. - #.MU;P0=-1485;P1=967;P2=236;P3=-21536;D=010201020131010101020102010101010102020102020101020102010201010101010101010102010201010101020102013101010102010201010101010202010202010102010201020101010101010101010201020101010102010201;CP=1;. - "77" => ## https://github.com/juergs/NANO_DS1820_4Fach - { - name => 'NANO_DS1820_4Fach', - comment => 'Selbstbau Sensor', - id => '77', - zero => [4,-6], # - one => [1,-6], # - clockabs => 250, # - format => 'pwm', # - preamble => 'TX', # prepend to converted message - clientmodule => 'CUL_TX', # not used now - modulematch => '^TX......', # not used now - length_min => '43', - length_max => '44', - remove_zero => 1, # Removes leading zeros from output - }, - "78" => # MU;P0=313;P1=1212;P2=-309;P4=-2024;P5=-16091;P6=2014;D=01204040562620404626204040404040462046204040562620404626204040404040462046204040562620404626204040404040462046204040562620404626204040404040462046204040;CP=0;R=236;) - # https://forum.fhem.de/index.php/topic,39153.0.html - { - name => 'geiger', - comment => 'geiger blind motors', - id => '78', - developId => 'y', - zero => [1,-6.6], - one => [6.6,-1], - start => [-53], - clockabs => 300, - format => 'twostate', - preamble => 'u78#', # prepend to converted message - clientmodule => 'SIGNALduino_un', - #modulematch => '^TX......', - length_min => '14', - #length_max => '18', - paddingbits => '2' # pad 1 bit, default is 4 - }, - "79" => ## MU;P0=656;P1=-656;P2=335;P3=-326;P4=-5024;D=01230121230123030303012423012301212301230303030124230123012123012303030301242301230121230123030303012423012301212301230303030124230123012123012303030301242301230121230123030303012423012301212301230303030124230123012123012303030301242301230121230123030303;CP=2;O; - # https://github.com/RFD-FHEM/SIGNALDuino/issues/84 - { - name => 'VTX-BELL_Funkklingel', - #comment => '', - id => '79', - zero => [-2,1], # - one => [-1,2], # - start => [-15,1], # - clockabs => 330, - format => 'twostate', # - preamble => 'U79#', # prepend to converted message - #clientmodule => '', # not used now - #modulematch => '^TX......', # not used now - length_min => '12', - #length_max => '44', - }, + ); @@ -1581,7 +1516,6 @@ SIGNALduino_Initialize($) ." minsecs" ." whitelist_IDs" ." blacklist_IDs" - ." WS09_WSModel:WH3080,WH1080,CTW600" ." WS09_CRCAUS:0,1,2" ." addvaltrigger" ." rawmsgEvent:1,0" @@ -1682,7 +1616,8 @@ SIGNALduino_Define($$) $hash->{DMSG}="nothing"; $hash->{LASTDMSG} = "nothing"; $hash->{TIME}=time(); - $hash->{versionmodul} = SDUINO_VERSION; + + Log3 $name, 3, "$name: Firmwareversion: ".$hash->{READINGS}{version}{VAL} if ($hash->{READINGS}{version}{VAL}); @@ -2000,11 +1935,7 @@ SIGNALduino_Set($@) if (substr($data,0,2) eq "is") { $data = substr($data,2); # is am Anfang entfernen } - if ($protocol == 3) { - $data = SIGNALduino_ITV1_tristateToBit($data); - } else { - $data = SIGNALduino_ITV1_31_tristateToBit($data); # $protocolId 3.1 - } + $data = SIGNALduino_ITV1_tristateToBit($data); Log3 $name, 5, "$name: sendmsg IT V1 convertet tristate to bits=$data"; } if (!defined($clock)) { @@ -2014,7 +1945,7 @@ SIGNALduino_Set($@) Log3 $name, 5, "$name: sendmsg Preparing rawsend command for protocol=$protocol, repeats=$repeats, clock=$clock bits=$data"; - foreach my $item (qw(sync start one zero float pause end)) + foreach my $item (qw(sync start one zero float)) { #print ("item= $item \n"); next if (!exists($ProtocolListSIGNALduino{$protocol}{$item})); @@ -2035,7 +1966,7 @@ SIGNALduino_Set($@) } my @bits = split("", $data); - my %bitconv = (1=>"one", 0=>"zero", 'D'=> "float", 'P'=> "pause"); + my %bitconv = (1=>"one", 0=>"zero", 'D'=> "float"); my $SignalData="D="; $SignalData.=$signalHash{sync} if (exists($signalHash{sync})); @@ -2046,7 +1977,6 @@ SIGNALduino_Set($@) #Log3 $name, 5, "encoding $bit"; $SignalData.=$signalHash{$bitconv{$bit}}; ## Add the signal to our data string } - $SignalData.=$signalHash{end} if (exists($signalHash{end})); $sendData = "SR;R=$repeats;$pattern$SignalData;$frequency"; } @@ -2092,7 +2022,7 @@ SIGNALduino_Get($@) if (IsDummy($name)) { - if ($arg =~ /^M[CcSU];.*/) + if ($arg =~ /^M[CSU];.*/) { $arg="\002$arg\003"; ## Add start end end marker if not already there Log3 $name, 5, "$name/msg adding start and endmarker to message"; @@ -2660,7 +2590,6 @@ SIGNALduino_Read($) my $partD; foreach my $msgPart (@msg_parts) { - next if (length($msgPart) le 1 ); $m0 = substr($msgPart,0,1); $mnr0 = ord($m0); $m1 = substr($msgPart,1); @@ -2859,7 +2788,7 @@ sub SIGNALduino_ParseHttpResponse close $file; # Den Flash Befehl mit der soebene heruntergeladenen Datei ausführen - Log3 $name, 3, "calling set ".$param->{command}." $filename"; # Eintrag fürs Log + #Log3 $name, 3, "calling set ".$param->{command}." $filename"; # Eintrag fürs Log SIGNALduino_Set($hash,$name,$param->{command},$filename); # $hash->{SetFn} @@ -3064,8 +2993,7 @@ sub SIGNALduino_Split_Message($$) { #Debug "$name: checking msg part:( $_ )" if ($debug); - #if ($_ =~ m/^MS/ or $_ =~ m/^MC/ or $_ =~ m/^Mc/ or $_ =~ m/^MU/) #### Synced Message start - if ($_ =~ m/^M./) + if ($_ =~ m/^MS/ or $_ =~ m/^MC/ or $_ =~ m/^MU/) #### Synced Message start { $ret{messagetype} = $_; } @@ -3168,10 +3096,9 @@ sub SIGNALduno_Dispatch($$$$$) $hash->{TIME} = time(); $hash->{DMSG} = $dmsg; #my $event = 0; - if (substr($dmsg,0,1) eq 'U') { + if (substr(ucfirst($dmsg),0,1) eq 'U') { #$event = 1; DoTrigger($name, "DMSG " . $dmsg); - return; # Fuer $dmsg die mit U anfangen ist kein Dispatch notwendig, da es dafuer kein Modul gibt } #readingsSingleUpdate($hash, "state", $hash->{READINGS}{state}{VAL}, $event); @@ -3264,8 +3191,8 @@ SIGNALduino_Parse_MS($$$$%) #Check calculated max length $valid = $valid && $ProtocolListSIGNALduino{$id}{length_max} >= $bit_length if (exists $ProtocolListSIGNALduino{$id}{length_max}); - #Log3 $name, 5, "$name: ID $id MS expecting $bit_length bits in signal, length_rawData=$signal_length"; - next if (!$valid); + Debug "expecting $bit_length bits in signal" if ($debug); + next if (!$valid) ; #Debug Dumper(@{$ProtocolListSIGNALduino{$id}{sync}}); Debug "Searching in patternList: ".Dumper(\%patternList) if($debug); @@ -3297,14 +3224,7 @@ SIGNALduino_Parse_MS($$$$%) Debug "Found matched zero with indexes: ($pstr)" if ($debug && $valid); $patternLookupHash{$pstr}="0" if ($valid); ## Append Sync to our lookuptable Debug "zero pattern not found" if ($debug && !$valid); - - if (defined($ProtocolListSIGNALduino{$id}{float})) - { - my $floatValid = ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{float}},\%patternList,\$rawData)) >=0; - Debug "Found matched float with indexes: ($pstr)" if ($debug && $floatValid); - $patternLookupHash{$pstr}="F" if ($floatValid); ## Append Sync to our lookuptable - Debug "float pattern not found" if ($debug && !$floatValid); - } + #Debug "added $pstr " if ($debug && $valid); next if (!$valid) ; @@ -3314,7 +3234,7 @@ SIGNALduino_Parse_MS($$$$%) #Anything seems to be valid, we can start decoding this. - Log3 $name, 4, "$name: Matched MS Protocol id $id -> $ProtocolListSIGNALduino{$id}{name}, bitLen=$bit_length" if ($valid); + Log3 $name, 4, "$name: Matched MS Protocol id $id -> $ProtocolListSIGNALduino{$id}{name}" if ($valid); my $signal_width= @{$ProtocolListSIGNALduino{$id}{one}}; #Debug $signal_width; @@ -3750,7 +3670,6 @@ SIGNALduino_Parse_MC($$$$@) my $rawData=$msg_parts{rawData}; my $rssi=$msg_parts{rssi}; my $mcbitnum=$msg_parts{mcbitnum}; - my $messagetype=$msg_parts{messagetype}; my $bitData; my $dmsg; my $message_dispatched=0; @@ -3791,16 +3710,8 @@ SIGNALduino_Parse_MC($$$$@) Log3 $name, 4, "$name: Found manchester Protocol id $id clock $clock -> $ProtocolListSIGNALduino{$id}{name}"; } - my $polarityInvert = 0; - if (exists($ProtocolListSIGNALduino{$id}{polarity}) && ($ProtocolListSIGNALduino{$id}{polarity} eq 'invert')) - { - $polarityInvert = 1; - } - if ($messagetype eq 'Mc' || (defined($hash->{version}) && substr($hash->{version},0,6) eq 'V 3.2.')) - { - $polarityInvert = $polarityInvert ^ 1; - } - if ($polarityInvert == 1) + if (exists($ProtocolListSIGNALduino{$id}{polarity}) && ($ProtocolListSIGNALduino{$id}{polarity} eq 'invert') && (!defined($hash->{version}) || substr($hash->{version},0,6) ne 'V 3.2.')) + # todo && substr($hash->{version},0,6) ne 'V 3.2.') # bei version V 3.2. nicht invertieren { $bitData= unpack("B$blen", pack("H$hlen", $rawDataInverted)); } else { @@ -3831,15 +3742,6 @@ SIGNALduino_Parse_MC($$$$@) next; } } - if (SDUINO_MC_DISPATCH_VERBOSE < 5 && (SDUINO_MC_DISPATCH_LOG_ID eq '' || SDUINO_MC_DISPATCH_LOG_ID eq $id)) - { - if (defined($rssi)) { - Log3 $name, SDUINO_MC_DISPATCH_VERBOSE, "$name $id, $rmsg RSSI=$rssi"; - } else - { - Log3 $name, SDUINO_MC_DISPATCH_VERBOSE, "$name $id, $rmsg"; - } - } SIGNALduno_Dispatch($hash,$rmsg,$dmsg,$rssi,$id); $message_dispatched=1; } @@ -3902,7 +3804,7 @@ SIGNALduino_Parse($$$$@) $dispatched= SIGNALduino_Parse_MU($hash, $iohash, $name, $rmsg,%signal_parts); } # Manchester encoded Data -> MC - elsif (@{$hash->{mcIdList}} && $rmsg=~ m/^M[cC];.*;/) + elsif (@{$hash->{mcIdList}} && $rmsg=~ m/^MC;.*;/) { $dispatched= SIGNALduino_Parse_MC($hash, $iohash, $name, $rmsg,%signal_parts); } @@ -4206,7 +4108,8 @@ sub SIGNALduino_callsub if ( defined $method && defined &$method ) { #my $subname = @{[eval {&$method}, $@ =~ /.*/]}; - Log3 $name, 5, "$name: applying $funcname, value before: @args"; # method $subname"; + Log3 $name, 5, "$name: applying $funcname"; # method $subname"; + #Log3 $name, 5, "$name: value bevore $funcname: @args"; my ($rcode, @returnvalues) = $method->($name, @args) ; @@ -4251,20 +4154,6 @@ sub SIGNALduino_bit2Arctec return (1,split("",$msg)); } -sub SIGNALduino_bit2itv1 -{ - my ($name, @bit_msg) = @_; - my $msg = join("",@bit_msg); - -# $msg =~ s/0F/01/g; # Convert 0F -> 01 (F) to be compatible with CUL - $msg =~ s/0F/11/g; # Convert 0F -> 11 (1) float - if (index($msg,'F') == -1) { - return (1,split("",$msg)); - } else { - return (0,0); - } -} - sub SIGNALduino_ITV1_tristateToBit($) { @@ -4278,17 +4167,6 @@ sub SIGNALduino_ITV1_tristateToBit($) return (1,$msg); } -sub SIGNALduino_ITV1_31_tristateToBit($) # ID 3.1 -{ - my ($msg) = @_; - # Convert 0 -> 00 1 -> 0D F => 01 to be compatible with IT Module - $msg =~ s/0/00/g; - $msg =~ s/1/0D/g; - $msg =~ s/F/01/g; - - return (1,$msg); -} - sub SIGNALduino_HE($@) { my ($name, @bit_msg) = @_; my $msg = join("",@bit_msg); @@ -4317,48 +4195,69 @@ sub SIGNALduino_postDemo_FS20($@) { my ($name, @bit_msg) = @_; my $datastart = 0; my $protolength = scalar @bit_msg; - my $sum = 6; + my $sum = 0; my $b = 0; my $i = 0; for ($datastart = 0; $datastart < $protolength; $datastart++) { # Start bei erstem Bit mit Wert 1 suchen last if $bit_msg[$datastart] eq "1"; } if ($datastart == $protolength) { # all bits are 0 - Log3 $name, 4, "$name: FS20 - ERROR message all bit are zeros"; + Log3 $name, 3, "$name: FS20 - ERROR message all bit are zeros"; return 0, undef; } splice(@bit_msg, 0, $datastart + 1); # delete preamble + 1 bit $protolength = scalar @bit_msg; - if ($protolength == 45 || $protolength == 54) { ### FS20 length 45 or 54 - for(my $b = 0; $b < $protolength - 9; $b += 9) { # build sum over first 4 or 5 bytes + + if ($protolength == 45) { ### FS20 length 45 or 54 + for(my $b = 0; $b < 36; $b += 9) { # build sum over first 4 bytes $sum += oct( "0b".(join "", @bit_msg[$b .. $b + 7])); } - my $checksum = oct( "0b".(join "", @bit_msg[$protolength - 9 .. $protolength - 2])); # Checksum Byte 5 or 6 - if (($sum & 0xFF) == $checksum) { ## FH20 remote control - for(my $b = 0; $b < $protolength; $b += 9) { # check parity over 5 or 6 bytes + my $checksum = oct( "0b".(join "", @bit_msg[36 .. 43])); # Checksum Byte 5 + if (((($sum + 6) & 0xFF) - $checksum) == 0) { ## FHT80TF Tuer-/Fensterkontakt + for(my $b = 0; $b < 45; $b += 9) { # check parity over 5 byte my $parity = 0; # Parity even for(my $i = $b; $i < $b + 9; $i++) { # Parity over 1 byte + 1 bit $parity += $bit_msg[$i]; } if ($parity % 2 != 0) { - Log3 $name, 4, "$name: FS20 ERROR - Parity not even"; + Log3 $name, 3, "$name: FS20 ERROR - Parity not even"; return 0, undef; } } # parity ok - for(my $b = $protolength - 1; $b > 0; $b -= 9) { # delete 5 or 6 parity bits + for(my $b = 44; $b > 0; $b -= 9) { # delete 5 parity bits splice(@bit_msg, $b, 1); } - if ($protolength == 45) { ### FS20 length 45 - splice(@bit_msg, 32, 8); # delete checksum - splice(@bit_msg, 24, 0, (0,0,0,0,0,0,0,0)); # insert Byte 3 - } else { ### FS20 length 54 - splice(@bit_msg, 40, 8); # delete checksum - } - my $dmsg = SIGNALduino_b2h(join "", @bit_msg); - Log3 $name, 4, "$name: FS20 - remote control post demodulation $dmsg length $protolength"; + splice(@bit_msg, 32, 8); # delete checksum + splice(@bit_msg, 24, 0, (0,0,0,0,0,0,0,0)); # insert Byte 3 + Log3 $name, 4, "$name: FS20 - remote control protolength $protolength"; return (1, @bit_msg); ## FHT80TF ok } } + + if ($protolength == 54) { ### FS20 length 45 or 54 + for($b = 0; $b < 45; $b += 9) { # build sum over first 5 bytes + $sum += oct( "0b".(join "", @bit_msg[$b .. $b + 7])); + } + my $checksum = oct( "0b".(join "", @bit_msg[45 .. 52])); # Checksum Byte 6 + if (((($sum + 6) & 0xFF) - $checksum) == 0) { ## FHT80 Raumthermostat + for($b = 0; $b < 55; $b += 9) { # check parity over 6 byte + my $parity = 0; # Parity even + for($i = $b; $i < $b + 9; $i++) { # Parity over 1 byte + 1 bit + $parity += $bit_msg[$i]; + } + if ($parity % 2 != 0) { + Log3 $name, 3, "$name: FHT80 ERROR - Parity not even"; + return 0, undef; + } + } # parity ok + for($b = 53; $b > 0; $b -= 9) { # delete 6 parity bits + splice(@bit_msg, $b, 1); + } + splice(@bit_msg, 40, 8); # delete checksum + Log3 $name, 4, "$name: FS20 - remote control protolength $protolength"; + return (1, @bit_msg); ## FHT80 ok + } + } return 0, undef; } @@ -4366,14 +4265,18 @@ sub SIGNALduino_postDemo_FHT80($@) { my ($name, @bit_msg) = @_; my $datastart = 0; my $protolength = scalar @bit_msg; - my $sum = 12; + my $sum = 0; my $b = 0; my $i = 0; + # if ($protolength < 66) { # min 6 bytes + 6 bits + # Log3 $name, 3, "$name: FHT80 - ERROR lenght of message < 66"; + # return 0, undef; + # } for ($datastart = 0; $datastart < $protolength; $datastart++) { # Start bei erstem Bit mit Wert 1 suchen last if $bit_msg[$datastart] eq "1"; } if ($datastart == $protolength) { # all bits are 0 - Log3 $name, 4, "$name: FHT80 - ERROR message all bit are zeros"; + Log3 $name, 3, "$name: FHT80 - ERROR message all bit are zeros"; return 0, undef; } splice(@bit_msg, 0, $datastart + 1); # delete preamble + 1 bit @@ -4383,11 +4286,14 @@ sub SIGNALduino_postDemo_FHT80($@) { $sum += oct( "0b".(join "", @bit_msg[$b .. $b + 7])); } my $checksum = oct( "0b".(join "", @bit_msg[45 .. 52])); # Checksum Byte 6 - if (($sum & 0xFF) == $checksum) { ## FHT80 Raumthermostat - for($b = 0; $b < 54; $b += 9) { # check parity over 6 byte + if (((($sum + 12) & 0xFF) - $checksum) == 0) { ## FHT80 Raumthermostat + for($b = 0; $b < 55; $b += 9) { # check parity over 6 byte my $parity = 0; # Parity even + for($i = $b; $i < $b + 9; $i++) { # Parity over 1 byte + 1 bit + $parity += $bit_msg[$i]; + } if ($parity % 2 != 0) { - Log3 $name, 4, "$name: FHT80 ERROR - Parity not even"; + Log3 $name, 3, "$name: FHT80 ERROR - Parity not even"; return 0, undef; } } # parity ok @@ -4395,13 +4301,12 @@ sub SIGNALduino_postDemo_FHT80($@) { splice(@bit_msg, $b, 1); } if ($bit_msg[26] != 1) { # Bit 5 Byte 3 must 1 - Log3 $name, 4, "$name: FHT80 ERROR - byte 3 bit 5 not 1"; + Log3 $name, 3, "$name: FHT80 ERROR - byte 3 bit 5 not 1"; return 0, undef; } splice(@bit_msg, 40, 8); # delete checksum - splice(@bit_msg, 24, 0, (0,0,0,0,0,0,0,0));# insert Byte 3 - my $dmsg = SIGNALduino_b2h(join "", @bit_msg); - Log3 $name, 4, "$name: FHT80 - roomthermostat post demodulation $dmsg"; + splice(@bit_msg, 24, 0, (0,0,0,0,0,0,0,0)); # insert Byte 3 + Log3 $name, 4, "$name: FHT80 - roomthermostat protolength $protolength"; return (1, @bit_msg); ## FHT80 ok } } @@ -4412,17 +4317,17 @@ sub SIGNALduino_postDemo_FHT80TF($@) { my ($name, @bit_msg) = @_; my $datastart = 0; my $protolength = scalar @bit_msg; - my $sum = 12; + my $sum = 0; my $b = 0; if ($protolength < 46) { # min 5 bytes + 6 bits - Log3 $name, 4, "$name: FHT80TF - ERROR lenght of message < 46"; + Log3 $name, 4, "$name: FHT80TF or FS20 - ERROR lenght of message < 46"; return 0, undef; } for ($datastart = 0; $datastart < $protolength; $datastart++) { # Start bei erstem Bit mit Wert 1 suchen last if $bit_msg[$datastart] eq "1"; } if ($datastart == $protolength) { # all bits are 0 - Log3 $name, 4, "$name: FHTTF - ERROR message all bit are zeros"; + Log3 $name, 3, "$name: FHTTF or FS20 - ERROR message all bit are zeros"; return 0, undef; } splice(@bit_msg, 0, $datastart + 1); # delete preamble + 1 bit @@ -4432,27 +4337,26 @@ sub SIGNALduino_postDemo_FHT80TF($@) { $sum += oct( "0b".(join "", @bit_msg[$b .. $b + 7])); } my $checksum = oct( "0b".(join "", @bit_msg[36 .. 43])); # Checksum Byte 5 - if (($sum & 0xFF) == $checksum) { ## FHT80TF Tuer-/Fensterkontakt - for(my $b = 0; $b < 45; $b += 9) { # check parity over 5 byte - my $parity = 0; # Parity even - for(my $i = $b; $i < $b + 9; $i++) { # Parity over 1 byte + 1 bit + if (((($sum + 12) & 0xFF) - $checksum) == 0) { ## FHT80TF Tuer-/Fensterkontakt + for(my $b = 0; $b < 45; $b += 9) { # check parity over 5 byte + my $parity = 0; # Parity even + for(my $i = $b; $i < $b + 9; $i++) { # Parity over 1 byte + 1 bit $parity += $bit_msg[$i]; } if ($parity % 2 != 0) { Log3 $name, 4, "$name: FHT80TF ERROR - Parity not even"; return 0, undef; } - } # parity ok - for(my $b = 44; $b > 0; $b -= 9) { # delete 5 parity bits + } # parity ok + for(my $b = 44; $b > 0; $b -= 9) { # delete 5 parity bits splice(@bit_msg, $b, 1); } if ($bit_msg[26] != 0) { # Bit 5 Byte 3 must 0 - Log3 $name, 4, "$name: FHT80TF ERROR - byte 3 bit 5 not 0"; + Log3 $name, 3, "$name: FHT80 ERROR - byte 3 bit 5 not 0"; return 0, undef; } - splice(@bit_msg, 32, 8); # delete checksum - my $dmsg = SIGNALduino_b2h(join "", @bit_msg); - Log3 $name, 4, "$name: FHT80 - roomthermostat post demodulation $dmsg"; + splice(@bit_msg, 32, 8); # delete checksum + Log3 $name, 4, "$name: FHT80TF - door/window switch protolength $protolength"; return (1, @bit_msg); ## FHT80TF ok } } @@ -4466,14 +4370,14 @@ sub SIGNALduino_postDemo_WS7035($@) { Log3 $name, 4, "$name: WS7035 $msg"; if (substr($msg,0,8) ne "10100000") { # check ident - Log3 $name, 4, "$name: WS7035 ERROR - Ident not 1010 0000"; + Log3 $name, 3, "$name: WS7035 ERROR - Ident not 1010 0000"; return 0, undef; } else { for(my $i = 15; $i < 28; $i++) { # Parity over bit 15 and 12 bit temperature $parity += substr($msg, $i, 1); } if ($parity % 2 != 0) { - Log3 $name, 4, "$name: WS7035 ERROR - Parity not even"; + Log3 $name, 3, "$name: WS7035 ERROR - Parity not even"; return 0, undef; } else { Log3 $name, 4, "$name: WS7035 " . substr($msg,0,4) ." ". substr($msg,4,4) ." ". substr($msg,8,4) ." ". substr($msg,12,4) ." ". substr($msg,16,4) ." ". substr($msg,20,4) ." ". substr($msg,24,4) ." ". substr($msg,28,4) ." ". substr($msg,32,4) ." ". substr($msg,36,4) ." ". substr($msg,40); @@ -4515,7 +4419,7 @@ sub SIGNALduino_postDemo_WS2000($@) { last if $bit_msg[$datastart] eq "1"; } if ($datastart == $protolength) { # all bits are 0 - Log3 $name, 4, "$name: WS2000 - ERROR message all bit are zeros"; + Log3 $name, 3, "$name: WS2000 - ERROR message all bit are zeros"; return 0, undef; } $datalength = $protolength - $datastart; @@ -4687,14 +4591,13 @@ sub SIGNALduino_OSV2() my $message_length; #$bitData =~ tr/10/01/; - #if ($bitData =~ m/^.?(01){12,17}.?10011001/) - if ($bitData =~ m/^.?(01){8,17}.?10011001/) + if ($bitData =~ m/^.?(01){12,17}.?10011001/) { # Valid OSV2 detected! #$preamble_pos=index($bitData,"10011001",24); $preamble_pos=$+[1]; Log3 $name, 4, "$name: OSV2 protocol detected: preamble_pos = $preamble_pos"; - return return (-1," sync not found") if ($preamble_pos <=18); + return return (-1," sync not found") if ($preamble_pos <=24); $message_end=$-[1] if ($bitData =~ m/^.{44,}(01){16,17}.?10011001/); #Todo regex .{44,} 44 should be calculated from $preamble_pos+ min message lengh (44) if (!defined($message_end) || $message_end < $preamble_pos) { @@ -4809,59 +4712,63 @@ sub SIGNALduino_OSV2() return (-1,undef); } -sub SIGNALduino_OSV1() { +sub SIGNALduino_OSV1() +{ my ($name,$bitData,$id,$mcbitnum) = @_; + return (-1," message is to short") if (defined($ProtocolListSIGNALduino{$id}{length_min}) && $mcbitnum < $ProtocolListSIGNALduino{$id}{length_min} ); return (-1," message is to long") if (defined($ProtocolListSIGNALduino{$id}{length_max}) && $mcbitnum > $ProtocolListSIGNALduino{$id}{length_max} ); + + my $calcsum = oct( "0b" . reverse substr($bitData,0,8)); $calcsum += oct( "0b" . reverse substr($bitData,8,8)); $calcsum += oct( "0b" . reverse substr($bitData,16,8)); $calcsum = ($calcsum & 0xFF) + ($calcsum >> 8); my $checksum = oct( "0b" . reverse substr($bitData,24,8)); - if ($calcsum != $checksum) { # Checksum return (-1,"OSV1 - ERROR checksum not equal: $calcsum != $checksum"); - } - #if (substr($bitData,20,1) == 0) { - # $bitData =~ tr/01/10/; # invert message and check if it is possible to deocde now - #} - - Log3 $name, 4, "$name: OSV1 input data: $bitData"; - my $newBitData = "00001010"; # Byte 0: Id1 = 0x0A - $newBitData .= "01001101"; # Byte 1: Id2 = 0x4D - my $channel = substr($bitData,6,2); # Byte 2 h: Channel - if ($channel == "00") { # in 0 LSB first - $newBitData .= "0001"; # out 1 MSB first - } elsif ($channel == "10") { # in 4 LSB first - $newBitData .= "0010"; # out 2 MSB first - } elsif ($channel == "01") { # in 4 LSB first - $newBitData .= "0011"; # out 3 MSB first - } else { # in 8 LSB first - return (-1,"$name: OSV1 - ERROR channel not valid: $channel"); - } - $newBitData .= "0000"; # Byte 2 l: ???? - $newBitData .= "0000"; # Byte 3 h: address - $newBitData .= reverse substr($bitData,0,4); # Byte 3 l: address (Rolling Code) - $newBitData .= reverse substr($bitData,8,4); # Byte 4 h: T 0,1 - $newBitData .= "0" . substr($bitData,23,1) . "00"; # Byte 4 l: Bit 2 - Batterie 0=ok, 1=low (< 2,5 Volt) - $newBitData .= reverse substr($bitData,16,4); # Byte 5 h: T 10 - $newBitData .= reverse substr($bitData,12,4); # Byte 5 l: T 1 - $newBitData .= "0000"; # Byte 6 h: immer 0000 - $newBitData .= substr($bitData,21,1) . "000"; # Byte 6 l: Bit 3 - Temperatur 0=pos | 1=neg, Rest 0 - $newBitData .= "00000000"; # Byte 7: immer 0000 0000 - # calculate new checksum over first 16 nibbles + } else { + Log3 $name, 4, "$name: OSV1 input data: $bitData"; + my $newBitData = "00001010"; # Byte 0: Id1 = 0x0A + $newBitData .= "01001101"; # Byte 1: Id2 = 0x4D + # Todo: Sensortyp automtisch erkennen und Premable damit setzen. + + # preamble => '50B208', # THR128 ohne Checksumme + # 50 - Length + # B2 - Byte 0: Id1 + # 08 - Byte 1: Id2 + my $channel = substr($bitData,6,2); # Byte 2 h: Channel + if ($channel == "00") { # in 0 LSB first + $newBitData .= "0001"; # out 1 MSB first + } elsif ($channel == "10") { # in 4 LSB first + $newBitData .= "0010"; # out 2 MSB first + } else { # in 8 LSB first + $newBitData .= "0100"; # out 4 MSB first + } + $newBitData .= "0000"; # Byte 2 l: ???? + $newBitData .= "0000"; # Byte 3 h: address + $newBitData .= reverse substr($bitData,0,4); # Byte 3 l: address (Rolling Code) + $newBitData .= reverse substr($bitData,8,4); # Byte 4 h: T 0,1 + $newBitData .= "0" . substr($bitData,23,1) . "00"; # Byte 4 l: Bit 2 - Batterie 0=ok, 1=low (< 2,5 Volt) + $newBitData .= reverse substr($bitData,16,4); # Byte 5 h: T 10 + $newBitData .= reverse substr($bitData,12,4); # Byte 5 l: T 1 + $newBitData .= "0000"; # Byte 6 h: immer 0000 + $newBitData .= substr($bitData,21,1) . "000"; # Byte 6 l: Bit 3 - Temperatur 0=pos | 1=neg, Rest 0 + $newBitData .= "00000000"; # Byte 7: immer 0000 0000 + # calculate new checksum over first 16 nibbles $checksum = 0; for (my $i = 0; $i < 64; $i = $i + 4) { - $checksum += oct( "0b" . substr($newBitData, $i, 4)); + $checksum += oct( "0b" . substr($newBitData, $i, 4)); } $checksum = ($checksum - 0xa) & 0xff; - $newBitData .= sprintf("%08b",$checksum); # Byte 8: new Checksum + $newBitData .= sprintf("%08b",$checksum); # Byte 8: new Checksum $newBitData .= "00000000"; # Byte 9: immer 0000 0000 - my $osv1hex = "50" . SIGNALduino_b2h($newBitData); # output with length before - Log3 $name, 4, "$name: OSV1 protocol id $id translated to RFXSensor format"; - Log3 $name, 4, "$name: converted to hex: $osv1hex"; - return (1,$osv1hex); - + + my $osv1hex = "50" . SIGNALduino_b2h($newBitData); # output with length before #todo: Länge berechnen + Log3 $name, 4, "$name: OSV1 protocol id ($id) translated to RFXSensor format"; + Log3 $name, 4, "$name: converted to hex: ($osv1hex)"; + return (1,$osv1hex); +} } sub SIGNALduino_AS() @@ -4897,12 +4804,6 @@ sub SIGNALduino_Hideki() my ($name,$bitData,$id,$mcbitnum) = @_; my $debug = AttrVal($name,"debug",0); - if ($mcbitnum == 89) { - my $bit0 = substr($bitData,0,1); - $bit0 = $bit0 ^ 1; - Log3 $name, 4, "$name hideki: L=$mcbitnum add bit $bit0 at begin $bitData"; - $bitData = $bit0 . $bitData; - } Debug "$name: search in $bitData \n" if ($debug); my $message_start = index($bitData,"10101110"); my $invert = 0; @@ -5578,261 +5479,4 @@ With a # at the beginnging whitelistIDs can be deactivated. =end html -=begin html_DE - - -
- Der SIGNALduino ist basierend auf eine Idee von "mdorenka" und veröffentlicht im FHEM Forum. - - Mit der OpenSource-Firmware (hier der Link) ist dieser fähig - für den Empfang und zum Senden verschiedener Protokolle von diversen Medien. Derzeit sind 433Mhz / 868Mhz Protokolle implementiert. - - - Folgende Geräteunterstützung sind ist derzeit verfügbar: - - - Funk-Schalter - ITv1 & ITv3/Elro und andere Marken mit dem pt2263-Chip oder welche das arctech Protokoll nutzen --> IT.pm - - Das ITv1 Protokoll benutzt einen Standard ITclock von 250 und es kann vorkommen, in dem IT-Modul das Attribut "ITclock" zu setzen. - - Temperatur / Feuchtigkeits Sensoren: -
- - Es ist möglich, mehr als ein Gerät anzuschließen, um beispielsweise besseren Empfang zu erhalten. FHEM wird doppelte Nachrichten herausfiltern. - - Hinweis: Dieses Modul erfordert das Device::SerialPort oder Win32::SerialPort - Modul. Es kann derzeit nur über USB angeschlossen werden. - |
-
define <name> SIGNALduino <device>
cdc_acm
Kernel_Modul dafür verantwortlich und es wird ein /dev/ttyACM0
oder /dev/ttyUSB0
Gerät angelegt. Wenn deine Distribution kein cdc_acm
Module besitzt, kannst du usbserial nutzen um den SIGNALduino zu betreiben mit folgenden Kommandos:
- /dev/ttyUSB0
./dev/ttyACM0@57600
/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0@57600
/dev/ttyACM0@directio
), dann benutzt das Perl Modul nicht Device::SerialPort und FHEM öffnet das Gerät mit einem file io. Dies kann funktionieren, wenn das Betriebssystem die Standardwerte für die seriellen Parameter verwendet. Bsp: einige Linux Distributionen und
- OSX. avrdude -p atmega328P -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2>[LOGFILE]
set SIGNALduino flash
als erstes Argument übergebenflash
. Hier sollten Sie angeben, welche Hardware Sie mit dem usbport verbunden haben. Andernfalls kann es zu Fehlfunktionen des Geräts kommen.MS=1;MU=1;MC=1;Mred=0
freq
, legt sowohl die Empfangsfrequenz als auch die Übertragungsfrequenz fest.bWidth
, kann auf Werte zwischen 58 kHz und 812 kHz eingestellt werden. Große Werte sind störanfällig, ermöglichen jedoch den Empfang von ungenau kalibrierten Sendern. Es wirkt sich auch auf die Übertragung aus. Standard ist 325 kHz.patable
, Änderung der PA-Tabelle (Leistungsverstärkung für HF-Senden)rAmpl
, ist die Empfängerverstärkung mit Werten zwischen 24 und 42 dB. Größere Werte erlauben den Empfang schwacher Signale. Der Standardwert ist 42.sens
, ist die Entscheidungsgrenze zwischen den Ein- und Aus-Werten und beträgt 4, 8, 12 oder 16 dB. Kleinere Werte erlauben den Empfang von weniger klaren Signalen. Standard ist 4 dB.avrdude
muss auf dem Host installiert sein. Auf einem Raspberry PI kann dies getan werden mit: sudo apt-get install avrdude
set sduino raw SR;R=3;P0=500;P1=-9000;P2=-4000;P3=-2000;D=0302030
, sendet die Daten im Raw-Modus dreimal wiederholtset sduino raw SM;R=3;P0=500;C=250;D=A4F7FDDE
, sendet die Daten Manchester codiert mit einem clock von 250µSset sduino raw SC;R=3;SR;P0=5000;SM;P0=500;C=250;D=A4F7FDDE
, sendet eine kombinierte Nachricht von Raw und Manchester codiert 3 mal wiederholt