diff --git a/fhem/FHEM/00_SIGNALduino.pm b/fhem/FHEM/00_SIGNALduino.pm
index 348940f02..ba3aae876 100644
--- a/fhem/FHEM/00_SIGNALduino.pm
+++ b/fhem/FHEM/00_SIGNALduino.pm
@@ -1,7 +1,7 @@
##############################################
# $Id$
#
-# v3.3.1 (release 3.3)
+# v3.3.1 (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
@@ -10,7 +10,6 @@
# N. Butzek, S. Butzek, 2014-2015
# S.Butzek,Ralf9 2016-2017
-
package main;
use strict;
@@ -25,7 +24,7 @@ no warnings 'portable';
use constant {
- SDUINO_VERSION => "v3.3.1",
+ SDUINO_VERSION => "v3.3.2",
SDUINO_INIT_WAIT_XQ => 1.5, # wait disable device
SDUINO_INIT_WAIT => 2,
SDUINO_INIT_MAXRETRY => 3,
@@ -34,6 +33,8 @@ use constant {
SDUINO_KEEPALIVE_MAXRETRY => 3,
SDUINO_WRITEQUEUE_NEXT => 0.3,
SDUINO_WRITEQUEUE_TIMEOUT => 2,
+
+ SDUINO_DISPATCH_VERBOSE => 5, # default 5
};
@@ -55,10 +56,13 @@ my %gets = ( # Name, Data to send to the SIGNALduino, Regexp for the answer
"raw" => ["", '.*'],
"uptime" => ["t", '^[0-9]+' ],
"cmds" => ["?", '.*Use one of[ 0-9A-Za-z]+[\r\n]*$' ],
- "ITParms" => ["ip",'.*'],
+# "ITParms" => ["ip",'.*'],
"ping" => ["P",'^OK$'],
"config" => ["CG",'^MS.*MU.*MC.*'],
"protocolIDs" => ["none",'none'],
+ "ccconf" => ["C0DnF", 'C0Dn11.*'],
+ "ccreg" => ["C", '^C.* = .*'],
+ "ccpatable" => ["C3E", '^C3E = .*'],
# "ITClock" => ["ic", '\d+'],
# "FAParms" => ["fp", '.*' ],
# "TCParms" => ["dp", '.*' ],
@@ -72,19 +76,49 @@ my %sets = (
"reset" => 'noArg',
"close" => 'noArg',
#"disablereceiver" => "",
- "ITClock" => 'slider,100,20,700',
+ #"ITClock" => 'slider,100,20,700',
"enableMessagetype" => 'syncedMS,unsyncedMU,manchesterMC',
"disableMessagetype" => 'syncedMS,unsyncedMU,manchesterMC',
- 'sendMsg' => "",
+ "sendMsg" => "",
+ "cc1101_freq" => '',
+ "cc1101_bWidth" => '',
+ "cc1101_rAmpl" => '',
+ "cc1101_sens" => '',
+ "cc1101_patable_433" => '-10_dBm,-5_dBm,0_dBm,5_dBm,7_dBm,10_dBm',
+ "cc1101_patable_868" => '-10_dBm,-5_dBm,0_dBm,5_dBm,7_dBm,10_dBm',
);
+my %patable = (
+ "433" =>
+ {
+ "-10_dBm" => '34',
+ "-5_dBm" => '68',
+ "0_dBm" => '60',
+ "5_dBm" => '84',
+ "7_dBm" => 'C8',
+ "10_dBm" => 'C0',
+ },
+ "868" =>
+ {
+ "-10_dBm" => '27',
+ "-5_dBm" => '67',
+ "0_dBm" => '50',
+ "5_dBm" => '81',
+ "7_dBm" => 'CB',
+ "10_dBm" => 'C2',
+ },
+);
+
+
+my @ampllist = (24, 27, 30, 33, 36, 38, 40, 42); # rAmpl(dB)
+
## Supported Clients per default
my $clientsSIGNALduino = ":IT:"
."CUL_TCM97001:"
-# ."SIGNALduino_RSL:"
+ ."SD_RSL:"
."OREGON:"
."CUL_TX:"
-# ."SD_AS:"
+ ."SD_AS:"
."Hideki:"
."SD_WS07:"
."SD_WS09:"
@@ -93,8 +127,17 @@ my $clientsSIGNALduino = ":IT:"
."RFXX10REC:"
."Dooya:"
."SOMFY:"
-# ."SD_UT:" ## BELL 201.2 TXA
+ ."SD_UT:" ## BELL 201.2 TXA
."SD_WS_Maverick:"
+ ."FLAMINGO:"
+ ."CUL_WS:"
+ ."Revolt:"
+ ." :" # Zeilenumbruch
+ ."FS10:"
+ ."CUL_FHTTK:"
+ ."Siro:"
+ ."FHT:"
+ ."FS20:"
."SIGNALduino_un:"
;
@@ -102,20 +145,28 @@ my $clientsSIGNALduino = ":IT:"
my %matchListSIGNALduino = (
"1:IT" => "^i......", # Intertechno Format
"2:CUL_TCM97001" => "^s[A-Fa-f0-9]+", # Any hex string beginning with s
-# "3:SIGNALduino_RSL" => "^r[A-Fa-f0-9]+", # Any hex string beginning with r
+ "3:SD_RSL" => "^P1#[A-Fa-f0-9]{8}",
"5:CUL_TX" => "^TX..........", # Need TX to avoid FHTTK
-# "6:SD_AS" => "^P2#[A-Fa-f0-9]{7,8}", # Arduino based Sensors, should not be default
+ "6:SD_AS" => "^P2#[A-Fa-f0-9]{7,8}", # Arduino based Sensors, should not be default
"4:OREGON" => "^(3[8-9A-F]|[4-6][0-9A-F]|7[0-8]).*",
"7:Hideki" => "^P12#75[A-F0-9]+",
- "10:SD_WS07" => "^P7#[A-Fa-f0-9]{6}F[A-Fa-f0-9]{2}",
- "11:SD_WS09" => "^P9#[A-Fa-f0-9]+",
+ "9:CUL_FHTTK" => "^T[A-F0-9]{8}",
+ "10:SD_WS07" => "^P7#[A-Fa-f0-9]{6}F[A-Fa-f0-9]{2}(#R[A-F0-9][A-F0-9]){0,1}\$",
+ "11:SD_WS09" => "^P9#F[A-Fa-f0-9]+",
"12:SD_WS" => '^W\d+x{0,1}#.*',
"13:RFXX10REC" => '^(20|29)[A-Fa-f0-9]+',
"14:Dooya" => '^P16#[A-Fa-f0-9]+',
- "15:SOMFY" => '^YsA[0-9A-F]+',
+ "15:SOMFY" => '^Ys[0-9A-F]+',
"16:SD_WS_Maverick" => '^P47#[A-Fa-f0-9]+',
-# "17:SD_UT" => '^u30#.*', ## BELL 201.2 TXA
- "X:SIGNALduino_un" => '^[uP]\d+#.*',
+ "17:SD_UT" => '^u30#.*', ## BELL 201.2 TXA
+ "18:FLAMINGO" => '^P13#[A-Fa-f0-9]+', ## Flamingo Smoke
+ "19:CUL_WS" => '^K[A-Fa-f0-9]{5,}',
+ "20:Revolt" => '^r[A-Fa-f0-9]{22}',
+ "21:FS10" => '^P61#[A-F0-9]+',
+ "22:Siro" => '^P72#[A-Fa-f0-9]+',
+ "23:FHT" => "^81..(04|09|0d)..(0909a001|83098301|c409c401)..",
+ "24:FS20" => "^81..(04|0c)..0101a001",
+ "X:SIGNALduino_un" => '^[u]\d+#.*',
);
@@ -135,7 +186,7 @@ my %ProtocolListSIGNALduino = (
clientmodule => 'CUL_TCM97001', # not used now
#modulematch => '^s[A-Fa-f0-9]+', # not used now
length_min => '24',
- length_max => '40',
+ length_max => '42',
paddingbits => '8', # pad up to 8 bits, default is 4
},
"1" =>
@@ -147,20 +198,21 @@ my %ProtocolListSIGNALduino = (
sync => [1,-11],
clockabs => '560', # not used now
format => 'twostate', # not used now
- preamble => 'r', # prepend to converted message
+ preamble => 'P1#', # prepend to converted message
postamble => '', # Append to converted message
- clientmodule => 'SIGNALduino_RSL', # not used now
- modulematch => '^r[A-Fa-f0-9]+', # not used now
- length_min => '23',
- length_max => '24',
+ clientmodule => 'SD_RSL', # not used now
+ modulematch => '^P1#[A-Fa-f0-9]{8}', # not used now
+ length_min => '20', # 23
+ length_max => '40', # 24
},
"2" =>
{
- name => 'AS', # Self build arduino sensor
- comment => 'Self build arduino sensor',
+ name => 'AS, Self build arduino sensor',
+ comment => 'developModule. SD_AS module is only in github available',
+ developId => 'm',
id => '2',
one => [1,-2],
zero => [1,-1],
@@ -191,6 +243,24 @@ my %ProtocolListSIGNALduino = (
length_min => '24',
#length_max => '800', # Don't know maximal lenth of a valid message
+ },
+ "3.1" =>
+ {
+ name => 'itv1_sync40',
+ comment => 'IT remote Control PAR 1000',
+ id => '3',
+ 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',
+ clientmodule => 'IT', # not used now
+ modulematch => '^i......', # not used now
+ length_min => '24',
+ #length_max => '800', # Don't know maximal lenth of a valid message
+
},
"4" =>
{
@@ -277,8 +347,8 @@ my %ProtocolListSIGNALduino = (
},
"9" => ## Funk Wetterstation CTW600
{
- name => 'CTW 600',
- comment => 'Funk Wetterstation CTW600',
+ name => 'CTW 600',
+ comment => 'FunkWS WH1080/WH3080/CTW600',
id => '9',
zero => [3,-2],
one => [1,-2],
@@ -289,7 +359,7 @@ my %ProtocolListSIGNALduino = (
preamble => 'P9#', # prepend to converted message
clientmodule => 'SD_WS09', # not used now
#modulematch => '^u9#.....', # not used now
- length_min => '70',
+ length_min => '60',
length_max => '120',
},
@@ -328,27 +398,59 @@ my %ProtocolListSIGNALduino = (
preamble => 'P12#', # prepend to converted message
clientmodule => 'hideki', # not used now
modulematch => '^P12#75.+', # not used now
- length_min => '72',
- length_max => '104',
+ length_min => '71',
+ length_max => '128',
method => \&SIGNALduino_Hideki, # Call to process this message
polarity => 'invert',
},
- "13" => ## FA21RF
+ "12.1" => ## hideki
{
- name => '21RF',
+ name => 'Hideki protocol not invert',
+ comment => 'only for test of the firmware dev-r33_fixmc',
+ id => '12',
+ clockrange => [420,510], # min, max better for Bresser Sensors, OK for hideki/Hideki/TFA too
+ format => 'manchester',
+ preamble => 'P12#', # prepend to converted message
+ clientmodule => 'hideki', # not used now
+ modulematch => '^P12#75.+', # not used now
+ length_min => '71',
+ length_max => '128',
+ method => \&SIGNALduino_Hideki, # Call to process this message
+ #polarity => 'invert',
+
+ },
+ "13" => ## FLAMINGO FA 21
+ {
+ name => 'FLAMINGO FA21',
id => '13',
one => [1,-2],
zero => [1,-4],
- sync => [10,-1],
+ sync => [1,-20,10,-1],
clockabs => 800,
format => 'twostate',
- preamble => 'u13#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '20',
- length_max => '40',
+ preamble => 'P13#', # prepend to converted message
+ clientmodule => 'FLAMINGO', # not used now
+ #modulematch => 'P13#.*', # not used now
+ length_min => '24',
+ length_max => '26',
},
+ "13.1" => ## FLAMINGO FA20
+ {
+ name => 'FLAMINGO FA21 b',
+ id => '13',
+ one => [1,-2],
+ zero => [1,-4],
+ start => [20,-1],
+ clockabs => 800,
+ format => 'twostate',
+ preamble => 'P13#', # prepend to converted message
+ clientmodule => 'FLAMINGO', # not used now
+ #modulematch => 'P13#.*', # not used now
+ length_min => '24',
+ length_max => '24',
+ },
+
"14" => ## Heidemann HX
{
name => 'Heidemann HX',
@@ -421,14 +523,15 @@ my %ProtocolListSIGNALduino = (
{
name => 'OSV1',
id => '18',
- clockrange => [1550,1650], # min , max
+ clockrange => [1400,1500], # min , max
format => 'manchester', # tristate can't be migrated from bin into hex!
- #preamble => '', # prepend to converted message
- #clientmodule => 'to be written', # not used now
- modulematch => '^(3[8-9A-F]|[4-6][0-9A-F]|7[0-8]).*',
- length_min => '8',
- length_max => '8',
- method => \&SIGNALduino_OSV1 # Call to process this message
+ preamble => '',
+ clientmodule => 'OREGON',
+ modulematch => '^[0-9A-F].*',
+ length_min => '31',
+ length_max => '32',
+ polarity => 'invert', # invert bits
+ method => \&SIGNALduino_OSV1 # Call to process this message
},
#"19" => # nothing knowing about this 2015-09-28 01:25:40-MS;P0=-8916;P1=-19904;P2=390;P3=-535;P4=-1020;P5=12846;P6=1371;D=2120232323232324242423232323232323232320239;CP=2;SP=1;
#
@@ -609,7 +712,9 @@ my %ProtocolListSIGNALduino = (
"30" => # a unitec remote door reed switch
{
name => 'unitec47031',
+ comment => 'developModule. SD_UT module is only in github available',
id => '30',
+ developId => 'm',
one => [-1,2],
zero => [-2,1],
start => [-33,1], # Message is not provided as MS, worakround is start
@@ -668,22 +773,22 @@ my %ProtocolListSIGNALduino = (
length_min => '42',
length_max => '44',
},
- "34" =>
- {
- name => 'unknown34',
- id => '34',
- one => [2,-1],
- zero => [1,-2],
- start => [3,-3,3,-3,3,-3,3,-3],
- clockabs => '240',
- format => 'twostate', # not used now
- preamble => 'u34#', # prepend to converted message
- postamble => '', # Append to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '40',
- length_max => '40',
- },
+# "34" => # replaced by 37
+# {
+# name => 'unknown34',
+# id => '34',
+# one => [2,-1],
+# zero => [1,-2],
+# start => [3,-3,3,-3,3,-3,3,-3],
+# clockabs => '240',
+# format => 'twostate', # not used now
+# preamble => 'u34#', # prepend to converted message
+# postamble => '', # Append to converted message
+# #clientmodule => '', # not used now
+# #modulematch => '', # not used now
+# length_min => '40',
+# length_max => '40',
+ # },
"35" =>
{
name => 'socket35',
@@ -716,21 +821,24 @@ my %ProtocolListSIGNALduino = (
length_min => '24',
length_max => '24',
},
- "37" =>
+ "37" => ## Bresser 7009994
+ # MU;P0=729;P1=-736;P2=483;P3=-251;P4=238;P5=-491;D=010101012323452323454523454545234523234545234523232345454545232345454545452323232345232340;CP=4;
+ # MU;P0=-790;P1=-255;P2=474;P4=226;P6=722;P7=-510;D=721060606060474747472121212147472121472147212121214747212147474721214747212147214721212147214060606060474747472121212140;CP=4;R=216;
+ # short pulse of 250 us followed by a 500 us gap is a 0 bit
+ # long pulse of 500 us followed by a 250 us gap is a 1 bit
+ # sync preamble of pulse, gap, 750 us each, repeated 4 times
{
- name => 'weather37',
+ name => 'Bresser 7009994',
id => '37',
one => [2,-1],
zero => [1,-2],
start => [3,-3,3,-3],
- clockabs => '230',
+ clockabs => '250',
format => 'twostate', # not used now
preamble => 'W37#', # prepend to converted message
- postamble => '', # Append to converted message
- clientmodule => 'SD_WS', # not used now
- #modulematch => '', # not used now
+ clientmodule => 'SD_WS',
length_min => '40',
- length_max => '44',
+ length_max => '40',
},
"38" =>
{
@@ -755,13 +863,13 @@ my %ProtocolListSIGNALduino = (
id => '39',
one => [1,-3],
zero => [1,-1],
- start => [16,-4],
- clockabs => 650,
+ start => [17,-7],
+ clockabs => 560,
format => 'twostate',
preamble => '', # prepend to converted message
clientmodule => 'RFXX10REC', # not used now
#modulematch => '^TX......', # not used now
- length_min => '38',
+ length_min => '32',
length_max => '44',
paddingbits => '8',
postDemodulation => \&SIGNALduino_lengtnPrefix,
@@ -781,6 +889,8 @@ my %ProtocolListSIGNALduino = (
#clientmodule => '', # not used now
#modulematch => '', # not used now
length_min => '10',
+ length_min => '12',
+
},
"41" => ## Elro (Smartwares) Doorbell DB200
{
@@ -795,39 +905,40 @@ my %ProtocolListSIGNALduino = (
#clientmodule => '', # not used now
#modulematch => '', # not used now
length_min => '20',
- },
- "42" => ## MKT Multi Kon Trade
- {
- name => 'MKT motionsensor',
- id => '42',
- zero => [1,-3],
- one => [3,-1],
- start => [-28],
- clockabs => 550,
- preamble => 'u42#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '',
- length_min => '24',
- },
+ },
+ #"42" => ## MKT Multi Kon Trade // Sollte eigentlich als MS ITv1 erkannt werden
+ # {
+ # name => 'MKT motionsensor',
+ # id => '42',
+ # zero => [1,-3],
+ # one => [3,-1],
+ # sync => [-28],
+ # clockabs => 550,
+ # preamble => 'u42#', # prepend to converted message
+ # #clientmodule => '', # not used now
+ # #modulematch => '',
+ # length_min => '24',
+ # },
"43" => ## Somfy RTS
{
name => 'Somfy RTS',
id => '43',
- clockrange => [610,670], # min , max
+ clockrange => [610,680], # min , max
format => 'manchester',
preamble => 'Ys',
clientmodule => 'SOMFY', # not used now
- modulematch => '^YsA[0-9A-F]{13}',
+ modulematch => '^Ys[0-9A-F]{14}',
length_min => '56',
- length_max => '56',
+ length_max => '57',
method => \&SIGNALduino_SomfyRTS, # Call to process this message
msgIntro => 'SR;P0=-2560;P1=2560;P3=-640;D=10101010101010113;',
#msgOutro => 'SR;P0=-30415;D=0;',
+ frequency => '10AB85550A',
},
"44" => ## Bresser Temeo Trend
{
name => 'BresserTemeo',
- id => '44',
+ id => '44',
clockabs => 500,
zero => [4,-4],
one => [4,-8],
@@ -838,10 +949,10 @@ my %ProtocolListSIGNALduino = (
length_min => '64',
length_max => '72',
},
- "51" => ## Bresser Temeo Trend
+ "44.1" => ## Bresser Temeo Trend
{
name => 'BresserTemeo',
- id => '44x',
+ id => '44',
clockabs => 500,
zero => [4,-4],
one => [4,-8],
@@ -853,21 +964,22 @@ my %ProtocolListSIGNALduino = (
length_max => '72',
},
- "45" =>
- {
- name => 'revolt',
- id => '45',
- one => [3,-1],
- zero => [1,-3],
- #float => [-1,3], # not full supported now later use
- sync => [1,-24],
- clockabs => -1, # -1=auto
- format => 'twostate', # not used now
- preamble => 'i',
- clientmodule => 'IT', # not used now
- modulematch => '^i......', # not used now
- length_min => '24',
- },
+ "45" => # Revolt
+ # MU;P0=-8320;P1=9972;P2=-376;P3=117;P4=-251;P5=232;D=012345434345434345454545434345454545454543454343434343434343434343434543434345434343434545434345434343434343454343454545454345434343454345434343434343434345454543434343434345434345454543454343434543454345434545;CP=3;R=2
+ {
+ name => 'Revolt',
+ id => '45',
+ one => [2,-2],
+ zero => [1,-2],
+ start => [83,-3],
+ clockabs => 120,
+ preamble => 'r', # prepend to converted message
+ clientmodule => 'Revolt',
+ modulematch => '^r[A-Fa-f0-9]{22}',
+ length_min => '84',
+ length_max => '120',
+ postDemodulation => sub { my ($name, @bit_msg) = @_; my @new_bitmsg = splice @bit_msg, 0,88; return 1,@new_bitmsg; },
+ },
"46" =>
{
name => 'EKX1BE',
@@ -928,7 +1040,7 @@ my %ProtocolListSIGNALduino = (
},
"50" => ## Opus XT300
{
- name => 'optus_XT300',
+ name => 'optus_XT300',
id => '50',
clockabs => 500,
zero => [3,-2],
@@ -936,11 +1048,450 @@ my %ProtocolListSIGNALduino = (
# start => [1,-25], # Wenn das startsignal empfangen wird, fehlt das 1 bit
format => 'twostate',
preamble => 'W50#', # prepend to converted message
- clientmodule => 'SD_WS', # not used now
+ clientmodule => 'SD_WS', # not used now
modulematch => '^W50#.*', # not used now
length_min => '47',
length_max => '48',
+ },
+ "51" =>
+ {
+ name => 'weather51', # Logilink, NC, WS, TCM97001 etc.
+ comment => 'IAN 275901 Wetterstation Lidl',
+ id => '51',
+ one => [1,-8],
+ zero => [1,-4],
+ sync => [1,-13],
+ clockabs => '560', # not used now
+ format => 'twostate', # not used now
+ preamble => 'W51#', # prepend to converted message
+ postamble => '', # Append to converted message
+ clientmodule => 'SD_WS',
+ modulematch => '^W51#.*',
+ length_min => '40',
+ length_max => '40',
+ },
+ "52" => ## Oregon PIR Protocol
+ {
+ name => 'OS_PIR',
+ id => '52',
+ clockrange => [470,640], # min , max
+ format => 'manchester', # tristate can't be migrated from bin into hex!
+ clientmodule => 'OREGON',
+ modulematch => '^u52#F{3}|0{3}.*',
+ preamble => 'u52#',
+ length_min => '30',
+ length_max => '30',
+ method => \&SIGNALduino_OSPIR, # Call to process this message
+ polarity => 'invert',
+ },
+
+ "55" => ##quigg gt1000
+ {
+ name => 'quigg_gt1000',
+ id => '55',
+ clockabs => 300,
+ zero => [1,-4],
+ one => [4,-2],
+ sync => [1,-8],
+ format => 'twostate',
+ preamble => 'i', # prepend to converted message
+ clientmodule => 'IT', # not used now
+ modulematch => '^i.*', # not used now
+ length_min => '24',
+ length_max => '24',
+ },
+ "56" => ## Celexon
+ {
+ name => 'Celexon',
+ id => '56',
+ clockabs => 200,
+ zero => [1,-3],
+ one => [3,-1],
+ start => [25,-3],
+ format => 'twostate',
+ preamble => 'u56#', # prepend to converted message
+ #clientmodule => '' , # not used now
+ modulematch => '', # not used now
+ length_min => '56',
+ length_max => '68',
+ },
+ "57" => ## m-e doorbell
+ {
+ name => 'm-e',
+ id => '57',
+ clockrange => [300,360], # min , max
+ format => 'manchester', # tristate can't be migrated from bin into hex!
+ clientmodule => '',
+ modulematch => '^u57*',
+ preamble => 'u57#',
+ length_min => '21',
+ length_max => '24',
+ method => \&SIGNALduino_MCRAW, # Call to process this message
+ polarity => 'invert',
+ },
+ "58" => ## tfa 30.3208.0
+ {
+ name => 'tfa 30.3208.0 ',
+ id => '58',
+ clockrange => [460,520], # min , max
+ format => 'manchester', # tristate can't be migrated from bin into hex!
+ clientmodule => '',
+ modulematch => '^W58*',
+ preamble => 'W58#',
+ length_min => '54',
+ length_max => '136',
+ method => \&SIGNALduino_MCTFA, # Call to process this message
+ polarity => 'invert',
+ },
+ "59" => ## AK-HD-4 remote
+ {
+ name => 'AK-HD-4',
+ id => '59',
+ clockabs => 230,
+ zero => [-4,1],
+ one => [-1,4],
+ start => [-1,37],
+ format => 'twostate', # tristate can't be migrated from bin into hex!
+ preamble => 'u59#', # Append to converted message
+ postamble => '', # Append to converted message
+ #clientmodule => '', # not used now
+ modulematch => '', # not used now
+ length_min => '24',
+ length_max => '24',
+ },
+ "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,
+ # 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
+ # ___ _
+ # | |_ | |___
+ # Bit 0 Bit 1
+ # kurz 366 µSek / lang 854 µSek / gesamt 1220 µSek - Sollzeiten
+ name => 'WS2000',
+ id => '60',
+ one => [3,-7],
+ zero => [7,-3],
+ clockabs => 122,
+ preamble => 'K', # prepend to converted message
+ postamble => '', # Append to converted message
+ clientmodule => 'CUL_WS',
+ length_min => '44', # eigentlich 46
+ length_max => '82', # eigentlich 81
+ postDemodulation => \&SIGNALduino_postDemo_WS2000,
+ },
+
+ "61" => ## ELV FS10
+ # tested transmitter: FS10-S8, FS10-S4, FS10-ZE
+ # tested receiver: FS10-ST, FS10-MS, WS3000-TV, PC-Wettersensor-Empfaenger
+ # das letzte Bit 1 und 1 x 0 Preambel fehlt immer
+ {
+ name => 'FS10',
+ id => '61',
+ one => [1,-2],
+ zero => [1,-1],
+ clockabs => 400,
+ format => 'twostate',
+ preamble => 'P61#', # prepend to converted message
+ postamble => '', # Append to converted message
+ clientmodule => 'FS10',
+ #modulematch => '',
+ length_min => '38', # eigentlich 41 oder 46 (Pruefsumme nicht bei allen)
+ length_max => '48', # eigentlich 46
+
},
+ "62" => ## Clarus_Switch
+ { #MU;P0=-5893;P4=-634;P5=498;P6=-257;P7=116;D=45656567474747474745656707456747474747456745674567456565674747474747456567074567474747474567456745674565656747474747474565670745674747474745674567456745656567474747474745656707456747474747456745674567456565674747474747456567074567474747474567456745674567;CP=7;O;
+ name => 'Clarus_Switch',
+ id => '62',
+ one => [3,-1],
+ zero => [1,-3],
+ start => [1,-35], # ca 30-40
+ clockabs => 189,
+ preamble => 'i', # prepend to converted message
+ clientmodule => 'IT',
+ #modulematch => '',
+ length_min => '24',
+ length_max => '24',
+ },
+ "63" => ## Warema MU
+ { #MU;P0=-2988;P1=1762;P2=-1781;P3=-902;P4=871;P5=6762;P6=5012;D=0121342434343434352434313434243521342134343436;
+ name => 'Warema',
+ comment => 'developId, is still experimental',
+ id => '63',
+ developId => 'y',
+ one => [1],
+ zero => [0],
+ clockabs => 800,
+ syncabs => '6700',# Special field for filterMC function
+ preamble => 'u63', # prepend to converted message
+ #clientmodule => '',
+ #modulematch => '',
+ length_min => '24',
+ filterfunc => 'SIGNALduino_filterMC',
+ },
+ "64" => ## WH2 #############################################################################
+ {
+ # MU;P0=-32001;P1=457;P2=-1064;P3=1438;D=0123232323212121232123232321212121212121212323212121232321;CP=1;R=63;
+ # MU;P0=-32001;P1=473;P2=-1058;P3=1454;D=0123232323212121232123232121212121212121212121232321212321;CP=1;R=51;
+ #MU;P0=134;P1=-113;P3=412;P4=-1062;P5=1379;D=01010101013434343434343454345454345454545454345454545454343434545434345454345454545454543454543454345454545434545454345;CP=3;
+
+ name => 'WH2',
+ id => '64',
+ one => [1,-2],
+ zero => [3,-2],
+ clockabs => 490,
+ clientmodule => 'SD_WS',
+ modulematch => '^W64*',
+ preamble => 'W64#', # prepend to converted message
+ postamble => '', # Append to converted message
+ #clientmodule => '',
+ length_min => '48',
+ length_max => '54',
+ },
+ "65" => ## Homeeasy
+ {
+ name => 'Homeeasy',
+ id => '65',
+ one => [1,-5],
+ zero => [1,-1],
+ start => [1,-40],
+ clockabs => 250,
+ format => 'twostate', # not used now
+ preamble => 'U65#',
+ length_min => '50',
+ #msgOutro => 'SR;P0=275;P1=-7150;D=01;',
+ postDemodulation => \&SIGNALduino_HE,
+ },
+ "66" => ## TX2 Protocol (Remote Temp Transmitter & Remote Thermo Model 7035)
+ # MU;P0=13312;P1=-2785;P2=4985;P3=1124;P4=-6442;P5=3181;P6=-31980;D=0121345434545454545434545454543454545434343454543434545434545454545454343434545434343434545621213454345454545454345454545434545454343434545434345454345454545454543434345454343434345456212134543454545454543454545454345454543434345454343454543454545454545;CP=3;R=73;O;
+ {
+ name => 'WS7035',
+ id => '66',
+ one => [10,-52],
+ zero => [27,-52],
+ start => [-21,42,-21],
+ clockabs => 122,
+ format => 'pwm', # not used now
+ preamble => 'TX',
+ clientmodule => 'CUL_TX',
+ modulematch => '^TX......',
+ length_min => '43',
+ length_max => '44',
+ postDemodulation => \&SIGNALduino_postDemo_WS7035,
+ },
+ "67" => ## TX2 Protocol (Remote Datalink & Remote Thermo Model 7053)
+ # MU;P0=3381;P1=-672;P2=-4628;P3=1142;P4=-30768;D=0102320232020202020232020232020202320232323202323202020202020202020401023202320202020202320202320202023202323232023232020202020202020200;CP=0;R=45;
+ # MU;P0=1148;P1=3421;P6=-664;P7=-4631;D=16170717071717171717071717071717171717070707170717171717070717171710;CP=1;R=29;
+ # MU;P0=3389;P3=2560;P4=-720;P5=1149;P7=-4616;D=345407570757070707070757070757070707070757570707075707070707570757575;CP=5;R=253;
+ # __ ____
+ # ________| | ________| |
+ # Bit 1 Bit 0
+ # 4630 1220 4630 3420 µSek - mit Oszi gemessene Zeiten
+ {
+ name => 'WS7053',
+ id => '67',
+ one => [-38,10],
+ zero => [-38,28],
+ clockabs => 122,
+ preamble => 'TX', # prepend to converted message
+ clientmodule => 'CUL_TX',
+ modulematch => '^TX......',
+ length_min => '32',
+ length_max => '34',
+ postDemodulation => \&SIGNALduino_postDemo_WS7053,
+ },
+ "68" => ## PFR-130 ###########################################################################
+ {
+ # MS;P0=-3890;P1=386;P2=-2191;P3=-8184;D=1312121212121012121212121012121212101012101010121012121210121210101210101012;CP=1;SP=3;R=20;O;
+ # MS;P0=-2189;P1=371;P2=-3901;P3=-8158;D=1310101010101210101010101210101010121210121212101210101012101012121012121210;CP=1;SP=3;R=20;O;
+ name => 'PFR-130',
+ id => '68',
+ one => [1,-10],
+ zero => [1,-5],
+ sync => [1,-21],
+ clockabs => 380, # not used now
+ preamble => 's', # prepend to converted message
+ postamble => '00', # Append to converted message
+ clientmodule => 'CUL_TCM97001', # not used now
+ length_min => '24',
+ length_max => '42',
+ paddingbits => '8', # pad up to 8 bits, default is 4
+ },
+ "69" => ## Hoermann
+ # MU;P0=-508;P1=1029;P2=503;P3=-1023;P4=12388;D=01010232323232310104010101010101010102323231010232310231023232323231023101023101010231010101010232323232310104010101010101010102323231010232310231023232323231023101023101010231010101010232323232310104010101010101010102323231010232310231023232323231023101;CP=2;R=37;O;
+ {
+ name => 'Hoermann',
+ id => '69',
+ zero => [2,-1],
+ one => [1,-2],
+ start => [24,-1],
+ clockabs => 510,
+ format => 'twostate', # not used now
+ #clientmodule => '',
+ #modulematch => '^U69*',
+ preamble => 'U69#',
+ length_min => '40',
+ #length_max => '90',
+ postDemodulation => \&SIGNALduino_postDemo_Hoermann, # Call to process this message
+ },
+ "70" => ## FHT80TF (Funk-Tuer-Fenster-Melder FHT 80TF und FHT 80TF-2)
+ # closed MU;P0=-24396;P1=417;P2=-376;P3=610;P4=-582;D=012121212121212121212121234123434121234341212343434121234123434343412343434121234341212121212341212341234341234123434;CP=1;R=35;
+ # open MU;P0=-21652;P1=429;P2=-367;P4=634;P5=-555;D=012121212121212121212121245124545121245451212454545121245124545454512454545121245451212121212124512451245451245121212;CP=1;R=38;
+ {
+ name => 'FHT80TF',
+ comment => 'Door/Window switch (868Mhz)',
+ id => '70',
+ one => [1.5,-1.5], # 600
+ zero => [1,-1], # 400
+ clockabs => 400,
+ format => 'twostate', # not used now
+ clientmodule => 'CUL_FHTTK',
+ preamble => 'T',
+ length_min => '50',
+ length_max => '58',
+ postDemodulation => \&SIGNALduino_postDemo_FHT80TF,
+ },
+ "71" => ## PV-8644 infactory Poolthermometer
+ # MU;P0=1735;P1=-1160;P2=591;P3=-876;D=0123012323010101230101232301230123010101010123012301012323232323232301232323232323232323012301012;CP=2;R=97;
+ {
+ name => 'PV-8644',
+ comment => 'infactory Poolthermometer',
+ id => '71',
+ clockabs => 580,
+ zero => [3,-2],
+ one => [1,-1.5],
+ format => 'twostate',
+ preamble => 'W71#', # prepend to converted message
+ clientmodule => 'SD_WS',
+ #modulematch => '^W71#.*'
+ length_min => '48',
+ length_max => '48',
+ },
+ # MU;P0=-760;P1=334;P2=693;P3=-399;P4=-8942;P5=4796;P6=-1540;D=01010102310232310101010102310232323101010102310101010101023102323102323102323102310101010102310232323101010102310101010101023102310231023102456102310232310232310231010101010231023232310101010231010101010102310231023102310245610231023231023231023101010101;CP=1;R=45;O;
+ # MU;P0=-8848;P1=4804;P2=-1512;P3=336;P4=-757;P5=695;P6=-402;D=0123456345656345656345634343434345634565656343434345634343434343456345634563456345;CP=3;R=49;
+
+ "72" => # Siro blinds MU @Dr. Smag
+ {
+ 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
+ start => [14,-4.4], # 4800,-1520
+ clockabs => 340,
+ format => 'twostate',
+ preamble => 'P72#', # prepend to converted message
+ clientmodule => 'Siro',
+ #modulematch => '',
+ length_min => '39',
+ length_max => '40',
+ msgOutro => 'SR;P0=-8500;D=0;',
+ },
+
+ # MS;P0=4803;P1=-1522;P2=333;P3=-769;P4=699;P5=-393;P6=-9190;D=2601234523454523454523452323232323452345454523232323452323232323234523232345454545;CP=2;SP=6;R=61;
+ "72.1" => # Siro blinds MS @Dr. Smag
+ {
+ 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
+ sync => [14,-4.4], # 4800,-1520
+ clockabs => 340,
+ format => 'twostate',
+ preamble => 'P72#', # prepend to converted message
+ clientmodule => 'Siro',
+ #modulematch => '',
+ length_min => '39',
+ length_max => '40',
+ #msgOutro => 'SR;P0=-8500;D=0;',
+ },
+ "73" => ## FHT80 - Raumthermostat (868Mhz), @HomeAutoUser
+ {
+ name => 'FHT80',
+ comment => 'Roomthermostat (868Mhz only receive)',
+ id => '73',
+ developId => 'y',
+ one => [1.5,-1.5], # 600
+ zero => [1,-1], # 400
+ clockabs => 400,
+ format => 'twostate', # not used now
+ clientmodule => 'FHT',
+ preamble => '810c04xx0909a001',
+ length_min => '59',
+ length_max => '67',
+ postDemodulation => \&SIGNALduino_postDemo_FHT80,
+ },
+ "74" => ## FS20 - 'Remote Control (868Mhz), @HomeAutoUser
+ {
+ name => 'FS20',
+ comment => 'Remote Control (868Mhz only receive)',
+ id => '74',
+ developId => 'y',
+ one => [1.5,-1.5], # 600
+ zero => [1,-1], # 400
+ clockabs => 400,
+ format => 'twostate', # not used now
+ clientmodule => 'FS20',
+ preamble => '810b04f70101a001',
+ length_min => '50',
+ length_max => '67',
+ postDemodulation => \&SIGNALduino_postDemo_FS20,
+ },
+ "75" => ## ConradRSL2 @litronics https://github.com/RFD-FHEM/SIGNALDuino/issues/69
+ # MU;P0=-1365;P1=477;P2=1145;P3=-734;P4=-6332;D=01023202310102323102423102323102323101023232323101010232323231023102323102310102323102423102323102323101023232323101010232323231023102323102310102323102;CP=1;R=12;
+ {
+ name => 'ConradRSL2',
+ id => '75',
+ one => [3,-1],
+ zero => [1,-3],
+ clockabs => 500,
+ format => 'twostate',
+ clientmodule => 'SD_RSL',
+ preamble => 'P1#',
+ modulematch => '^P1#[A-Fa-f0-9]{8}',
+ length_min => '32',
+ length_max => '40',
+ },
+ "76" => ## Kabellose LED-Weihnachtskerzen XM21-0
+ {
+ name => 'xm21',
+ comment => 'reserviert, LED Lichtrekette on',
+ id => '76',
+ developId => 'p',
+ one => [1.2,-2], # 120,-200
+ zero => [], # existiert nicht
+ start => [4.5,-2], # 450,-200 Starsequenz
+ clockabs => 100,
+ format => 'twostate', # not used now
+ clientmodule => '',
+ preamble => 'P76',
+ length_min => 64,
+ length_max => 64,
+ },
+ "76.1" => ## Kabellose LED-Weihnachtskerzen XM21-0
+ {
+ name => 'xm21',
+ comment => 'reserviert, LED Lichtrekette off',
+ id => '76.1',
+ developId => 'p',
+ one => [1.2,-2], # 120,-200
+ zero => [], # existiert nicht
+ start => [4.5,-2], # 450,-200 Starsequenz
+ clockabs => 100,
+ format => 'twostate', # not used now
+ clientmodule => '',
+ preamble => 'P76',
+ length_min => 58,
+ length_max => 58,
+ },
+
);
@@ -971,17 +1522,28 @@ SIGNALduino_Initialize($)
." hexFile"
." initCommands"
." flashCommand"
- ." hardware:nano328,uno,promini328"
+ ." hardware:nano328,uno,promini328,nanoCC1101"
." debug:0,1"
." longids"
." minsecs"
." whitelist_IDs"
- ." WS09_WSModel:undef,WH1080,CTW600"
- ." WS09_CRCAUS:0,1"
+ ." blacklist_IDs"
+ ." WS09_CRCAUS:0,1,2"
+ ." addvaltrigger"
+ ." rawmsgEvent:1,0"
+ ." cc1101_frequency"
+ ." doubleMsgCheck_IDs"
+ ." suppressDeviceRawmsg:1,0"
+ ." development"
+ ." noMsgVerbose:0,1,2,3,4,5"
." $readingFnAttributes";
$hash->{ShutdownFn} = "SIGNALduino_Shutdown";
-
+
+ $hash->{msIdList} = ();
+ $hash->{muIdList} = ();
+ $hash->{mcIdList} = ();
+
}
sub
@@ -1047,14 +1609,14 @@ SIGNALduino_Define($$)
if( !defined( $attr{$name}{flashCommand} ) ) {
# $attr{$name}{flashCommand} = "avrdude -p atmega328P -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2>[LOGFILE]"
- $attr{$name}{flashCommand} = "avrdude -c arduino -b 57600 -P [PORT] -p atmega328p -vv -U flash:w:[HEXFILE] 2>[LOGFILE]"
+ $attr{$name}{flashCommand} = "avrdude -c arduino -b [BAUDRATE] -P [PORT] -p atmega328p -vv -U flash:w:[HEXFILE] 2>[LOGFILE]";
+
}
$hash->{DeviceName} = $dev;
my $ret=undef;
-
- my $whitelistIDs = AttrVal($name,"whitelist_IDs","");
- SIGNALduino_IdList($hash ,$name, $whitelistIDs);
+
+ InternalTimer(gettimeofday(), 'SIGNALduino_IdList',"sduino_IdList:$name",0); # verzoegern bis alle Attribute eingelesen sind
if($dev ne "none") {
$ret = DevIo_OpenDev($hash, 0, "SIGNALduino_DoInit", 'SIGNALduino_Connect');
@@ -1064,6 +1626,7 @@ SIGNALduino_Define($$)
}
$hash->{DMSG}="nothing";
+ $hash->{LASTDMSG} = "nothing";
$hash->{TIME}=time();
@@ -1091,6 +1654,9 @@ SIGNALduino_Undef($$)
{
my ($hash, $arg) = @_;
my $name = $hash->{NAME};
+
+
+
foreach my $d (sort keys %defs) {
if(defined($defs{$d}) &&
@@ -1129,9 +1695,27 @@ SIGNALduino_Set($@)
my ($hash, @a) = @_;
return "\"set SIGNALduino\" needs at least one parameter" if(@a < 2);
+
+ #Log3 $hash, 3, "SIGNALduino_Set called with params @a";
+
+
+ my $hasCC1101 = 0;
+ my $CC1101Frequency;
+ if ($hash->{version} && $hash->{version} =~ m/cc1101/) {
+ $hasCC1101 = 1;
+ if (!defined($hash->{cc1101_frequency})) {
+ $CC1101Frequency = "433";
+ } else {
+ $CC1101Frequency = $hash->{cc1101_frequency};
+ }
+ }
if (!defined($sets{$a[1]})) {
my $arguments = ' ';
foreach my $arg (sort keys %sets) {
+ next if ($arg =~ m/cc1101/ && $hasCC1101 == 0);
+ if ($arg =~ m/patable/) {
+ next if (substr($arg, -3) ne $CC1101Frequency);
+ }
$arguments.= $arg . ($sets{$arg} ? (':' . $sets{$arg}) : '') . ' ';
}
#Log3 $hash, 3, "set arg = $arguments";
@@ -1142,8 +1726,16 @@ SIGNALduino_Set($@)
my $cmd = shift @a;
my $arg = join(" ", @a);
+ if ($cmd =~ m/cc1101/ && $hasCC1101 == 0) {
+ return "This command is only available with a cc1101 receiver";
+ }
+
return "$name is not active, may firmware is not suppoted, please flash or reset" if ($cmd ne 'reset' && $cmd ne 'flash' && exists($hash->{DevState}) && $hash->{DevState} ne 'initialized');
+ if ($cmd =~ m/^cc1101_/) {
+ $cmd = substr($cmd,7);
+ }
+
if($cmd eq "raw") {
Log3 $name, 4, "set $name $cmd $arg";
#SIGNALduino_SimpleWrite($hash, $arg);
@@ -1155,7 +1747,7 @@ SIGNALduino_Set($@)
my @deviceName = split('@', $hash->{DeviceName});
my $port = $deviceName[0];
my $hardware=AttrVal($name,"hardware","nano328");
-
+ my $baudrate=$hardware eq "uno" ? 115200 : 57600;
my $defaultHexFile = "./FHEM/firmware/$hash->{TYPE}_$hardware.hex";
my $logFile = AttrVal("global", "logdir", "./log/") . "$hash->{TYPE}-Flash.log";
@@ -1165,10 +1757,23 @@ SIGNALduino_Set($@)
$hexFile = $defaultHexFile;
}
}
- else {
+ elsif ($args[0] =~ m/^https?:\/\// ) {
+ my $http_param = {
+ url => $args[0],
+ timeout => 5,
+ hash => $hash, # Muss gesetzt werden, damit die Callback funktion wieder $hash hat
+ method => "GET", # Lesen von Inhalten
+ callback => \&SIGNALduino_ParseHttpResponse, # Diese Funktion soll das Ergebnis dieser HTTP Anfrage bearbeiten
+ command => 'flash',
+ };
+
+ HttpUtils_NonblockingGet($http_param);
+ return;
+ } else {
$hexFile = $args[0];
}
-
+ Log3 $name, 3, "$name: filename $hexFile provided, trying to flash";
+
return "Usage: set $name flash [filename]\n\nor use the hexFile attribute" if($hexFile !~ m/^(\w|\/|.)+$/);
$log .= "flashing Arduino $name\n";
@@ -1189,6 +1794,7 @@ SIGNALduino_Set($@)
my $avrdude = $flashCommand;
$avrdude =~ s/\Q[PORT]\E/$port/g;
+ $avrdude =~ s/\Q[BAUDRATE]\E/$baudrate/g;
$avrdude =~ s/\Q[HEXFILE]\E/$hexFile/g;
$avrdude =~ s/\Q[LOGFILE]\E/$logFile/g;
@@ -1224,17 +1830,6 @@ SIGNALduino_Set($@)
} elsif( $cmd eq "close" ) {
$hash->{DevState} = 'closed';
return SIGNALduino_CloseDevice($hash);
- } elsif( $cmd eq "ITClock" ) {
- Log3 $name, 4, "set $name $cmd $arg";
- my $clock = shift @a;
-
- $clock=250 if ($clock eq "" );
- return "argument $arg is not numeric" if($clock !~ /^\d+$/);
- Log3 $name, 3, "$name: Setting ITClock to $clock (sending $arg)";
- $arg="ic$clock";
- #SIGNALduino_SimpleWrite($hash, $arg);
- SIGNALduino_AddSendQueue($hash,$arg);
- $hash->{$cmd}=$clock;
} elsif( $cmd eq "disableMessagetype" ) {
my $argm = 'CD' . substr($arg,-1,1);
#SIGNALduino_SimpleWrite($hash, $argm);
@@ -1245,12 +1840,70 @@ SIGNALduino_Set($@)
#SIGNALduino_SimpleWrite($hash, $argm);
SIGNALduino_AddSendQueue($hash,$argm);
Log3 $name, 4, "set $name $cmd $arg $argm";
+ } elsif( $cmd eq "freq" ) {
+ if ($arg eq "") {
+ $arg = AttrVal($name,"cc1101_frequency", 433.92);
+ }
+ my $f = $arg/26*65536;
+ my $f2 = sprintf("%02x", $f / 65536);
+ my $f1 = sprintf("%02x", int($f % 65536) / 256);
+ my $f0 = sprintf("%02x", $f % 256);
+ $arg = sprintf("%.3f", (hex($f2)*65536+hex($f1)*256+hex($f0))/65536*26);
+ Log3 $name, 3, "$name: Setting FREQ2..0 (0D,0E,0F) to $f2 $f1 $f0 = $arg MHz";
+ SIGNALduino_AddSendQueue($hash,"W0F$f2");
+ SIGNALduino_AddSendQueue($hash,"W10$f1");
+ SIGNALduino_AddSendQueue($hash,"W11$f0");
+ SIGNALduino_WriteInit($hash);
+ } elsif( $cmd eq "bWidth" ) {
+ SIGNALduino_AddSendQueue($hash,"C10");
+ $hash->{getcmd}->{cmd} = "bWidth";
+ $hash->{getcmd}->{arg} = $arg;
+ } elsif( $cmd eq "rAmpl" ) {
+ return "a numerical value between 24 and 42 is expected" if($arg !~ m/^\d+$/ || $arg < 24 || $arg > 42);
+ my ($v, $w);
+ for($v = 0; $v < @ampllist; $v++) {
+ last if($ampllist[$v] > $arg);
+ }
+ $v = sprintf("%02d", $v-1);
+ $w = $ampllist[$v];
+ Log3 $name, 3, "$name: Setting AGCCTRL2 (1B) to $v / $w dB";
+ SIGNALduino_AddSendQueue($hash,"W1D$v");
+ SIGNALduino_WriteInit($hash);
+ } elsif( $cmd eq "sens" ) {
+ return "a numerical value between 4 and 16 is expected" if($arg !~ m/^\d+$/ || $arg < 4 || $arg > 16);
+ my $w = int($arg/4)*4;
+ my $v = sprintf("9%d",$arg/4-1);
+ Log3 $name, 3, "$name: Setting AGCCTRL0 (1D) to $v / $w dB";
+ SIGNALduino_AddSendQueue($hash,"W1F$v");
+ SIGNALduino_WriteInit($hash);
+ } elsif( substr($cmd,0,7) eq "patable" ) {
+ my $paFreq = substr($cmd,8);
+ my $pa = "x" . $patable{$paFreq}{$arg};
+ Log3 $name, 3, "$name: Setting patable $paFreq $arg $pa";
+ SIGNALduino_AddSendQueue($hash,$pa);
+ SIGNALduino_WriteInit($hash);
} elsif( $cmd eq "sendMsg" ) {
- my ($protocol,$data,$repeats,$clock) = split("#",$arg);
+ Log3 $name, 5, "$name: sendmsg msg=$arg";
+ my ($protocol,$data,$repeats,$clock,$frequency) = split("#",$arg);
$protocol=~ s/[Pp](\d+)/$1/; # extract protocol num
$repeats=~ s/[rR](\d+)/$1/; # extract repeat num
- $clock=~ s/[Cc](\d+)/$1/ if (defined($clock)); # extract ITClock num
$repeats=1 if (!defined($repeats));
+ if (defined($clock) && substr($clock,0,1) eq "F") { # wenn es kein clock gibt, pruefen ob im clock eine frequency ist
+ $clock=~ s/[F]([0-9a-fA-F]+$)/$1/;
+ $frequency = $clock;
+ $clock = undef;
+ } else {
+ $clock=~ s/[Cc](\d+)/$1/ if (defined($clock)); # extract ITClock num
+ $frequency=~ s/[Ff]([0-9a-fA-F]+$)/$1/ if (defined($frequency));
+ }
+ if (exists($ProtocolListSIGNALduino{$protocol}{frequency}) && $hasCC1101 && !defined($frequency)) {
+ $frequency = $ProtocolListSIGNALduino{$protocol}{frequency};
+ }
+ if (defined($frequency) && $hasCC1101) {
+ $frequency="F=$frequency;";
+ } else {
+ $frequency="";
+ }
return "$name: sendmsg, unknown protocol: $protocol" if (!exists($ProtocolListSIGNALduino{$protocol}));
@@ -1262,8 +1915,6 @@ SIGNALduino_Set($@)
my %patternHash;
my $pattern="";
my $cnt=0;
-
-
my $sendData;
if ($ProtocolListSIGNALduino{$protocol}{format} eq 'manchester')
@@ -1288,7 +1939,7 @@ SIGNALduino_Set($@)
$repeats = 0;
}
- $sendData = $intro . "SM;" . ($repeats > 0 ? "R=$repeats;" : "") . "C=$clock;D=$data;" . $outro; # SM;R=2;C=400;D=AFAFAF;
+ $sendData = $intro . "SM;" . ($repeats > 0 ? "R=$repeats;" : "") . "C=$clock;D=$data;" . $outro . $frequency; # SM;R=2;C=400;D=AFAFAF;
Log3 $name, 5, "$name: sendmsg Preparing manchester protocol=$protocol, repeats=$repeats, clock=$clock data=$data";
} else {
if ($protocol == 3 || substr($data,0,2) eq "is") {
@@ -1337,7 +1988,7 @@ SIGNALduino_Set($@)
#Log3 $name, 5, "encoding $bit";
$SignalData.=$signalHash{$bitconv{$bit}}; ## Add the signal to our data string
}
- $sendData = "SR;R=$repeats;$pattern$SignalData;";
+ $sendData = "SR;R=$repeats;$pattern$SignalData;$frequency";
}
@@ -1367,13 +2018,17 @@ SIGNALduino_Get($@)
Log3 $name, 5, "\"get $type\" needs at least one parameter" if(@a < 2);
return "\"get $type\" needs at least one parameter" if(@a < 2);
if(!defined($gets{$a[1]})) {
- my @cList = map { $_ =~ m/^(file|raw)$/ ? $_ : "$_:noArg" } sort keys %gets;
+ my @cList = map { $_ =~ m/^(file|raw|ccreg)$/ ? $_ : "$_:noArg" } sort keys %gets;
return "Unknown argument $a[1], choose one of " . join(" ", @cList);
}
my $arg = ($a[2] ? $a[2] : "");
return "no command to send, get aborted." if (length($gets{$a[1]}[0]) == 0 && length($arg) == 0);
+ if (($a[1] eq "ccconf" || $a[1] eq "ccreg" || $a[1] eq "ccpatable") && $hash->{version} && $hash->{version} !~ m/cc1101/) {
+ return "This command is only available with a cc1101 receiver";
+ }
+
my ($msg, $err);
if (IsDummy($name))
@@ -1518,9 +2173,10 @@ SIGNALduino_Get($@)
$ret .= "\n";
}
- $moduleId =~ s/,$//;
+ #$moduleId =~ s/,$//;
- return "$a[1]: \n\n$ret\nIds with modules: $moduleId";
+ return "$a[1]: \n\n$ret\n";
+ #return "$a[1]: \n\n$ret\nIds with modules: $moduleId";
}
#SIGNALduino_SimpleWrite($hash, $gets{$a[1]}[0] . $arg);
@@ -1551,8 +2207,73 @@ sub SIGNALduino_parseResponse($$$)
{ # decode it
#$msg = hex($msg); # /125; only for col or coc
$msg = sprintf("%d %02d:%02d:%02d", $msg/86400, ($msg%86400)/3600, ($msg%3600)/60, $msg%60);
- }
-
+ }
+ elsif($cmd eq "ccregAll")
+ {
+ $msg =~ s/ /\n/g;
+ $msg = "\n\n" . $msg
+ }
+ elsif($cmd eq "ccconf")
+ {
+ my (undef,$str) = split('=', $msg);
+ my $var;
+ my %r = ( "0D"=>1,"0E"=>1,"0F"=>1,"10"=>1,"11"=>1,"1B"=>1,"1D"=>1 );
+ $msg = "";
+ foreach my $a (sort keys %r) {
+ $var = substr($str,(hex($a)-13)*2, 2);
+ $r{$a} = hex($var);
+ }
+ $msg = sprintf("freq:%.3fMHz bWidth:%dKHz rAmpl:%ddB sens:%ddB (DataRate:%.2fBaud)",
+ 26*(($r{"0D"}*256+$r{"0E"})*256+$r{"0F"})/65536, #Freq
+ 26000/(8 * (4+(($r{"10"}>>4)&3)) * (1 << (($r{"10"}>>6)&3))), #Bw
+ $ampllist[$r{"1B"}&7], #rAmpl
+ 4+4*($r{"1D"}&3), #Sens
+ ((256+$r{"11"})*(2**($r{"10"} & 15 )))*26000000/(2**28) #DataRate
+ );
+ }
+ elsif($cmd eq "bWidth") {
+ my $val = hex(substr($msg,6));
+ my $arg = $hash->{getcmd}->{arg};
+ my $ob = $val & 0x0f;
+
+ my ($bits, $bw) = (0,0);
+ OUTERLOOP:
+ for (my $e = 0; $e < 4; $e++) {
+ for (my $m = 0; $m < 4; $m++) {
+ $bits = ($e<<6)+($m<<4);
+ $bw = int(26000/(8 * (4+$m) * (1 << $e))); # KHz
+ last OUTERLOOP if($arg >= $bw);
+ }
+ }
+
+ $ob = sprintf("%02x", $ob+$bits);
+ $msg = "Setting MDMCFG4 (10) to $ob = $bw KHz";
+ Log3 $name, 3, "$name/msg parseResponse bWidth: Setting MDMCFG4 (10) to $ob = $bw KHz";
+ delete($hash->{getcmd});
+ SIGNALduino_AddSendQueue($hash,"W12$ob");
+ SIGNALduino_WriteInit($hash);
+ }
+ elsif($cmd eq "ccpatable") {
+ my $CC1101Frequency = "433";
+ if (defined($hash->{cc1101_frequency})) {
+ $CC1101Frequency = $hash->{cc1101_frequency};
+ }
+ my $dBn = substr($msg,9,2);
+ Log3 $name, 3, "$name/msg parseResponse patable: $dBn";
+ foreach my $dB (keys %{ $patable{$CC1101Frequency} }) {
+ if ($dBn eq $patable{$CC1101Frequency}{$dB}) {
+ Log3 $name, 5, "$name/msg parseResponse patable: $dB";
+ $msg .= " => $dB";
+ last;
+ }
+ }
+ # $msg .= "\n\n$CC1101Frequency MHz\n\n";
+ # foreach my $dB (keys $patable{$CC1101Frequency})
+ # {
+ # $msg .= "$patable{$CC1101Frequency}{$dB} $dB\n";
+ # }
+ }
+
return $msg;
}
@@ -1603,7 +2324,10 @@ SIGNALduino_DoInit($)
RemoveInternalTimer("HandleWriteQueue:$name");
@{$hash->{QUEUE}} = ();
- if (($hash->{DEF} !~ m/\@DirectIO/) and ($hash->{DEF} !~ m/none/) )
+ $hash->{sendworking} = 0;
+
+ # if (($hash->{DEF} !~ m/\@DirectIO/) and ($hash->{DEF} !~ m/none/) )
+ if (($hash->{DEF} !~ m/\@directio/) and ($hash->{DEF} !~ m/none/) )
{
Log3 $hash, 1, "$name/init: ".$hash->{DEF};
$hash->{initretry} = 0;
@@ -1618,7 +2342,7 @@ SIGNALduino_DoInit($)
delete($hash->{XMIT_TIME});
delete($hash->{NR_CMD_LAST_H});
return;
- #return undef;
+ return undef;
}
# Disable receiver
@@ -1773,13 +2497,12 @@ sub SIGNALduino_AddSendQueue($$)
my ($hash, $msg) = @_;
my $name = $hash->{NAME};
- #Log3 $hash, 3,"AddSendQueue: " . $hash->{NAME} . ": $msg";
-
push(@{$hash->{QUEUE}}, $msg);
#Log3 $hash , 5, Dumper($hash->{QUEUE});
- InternalTimer(gettimeofday() + 0.1, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name") if (@{$hash->{QUEUE}} == 1);
+ Log3 $hash, 5,"AddSendQueue: " . $hash->{NAME} . ": $msg (" . @{$hash->{QUEUE}} . ")";
+ InternalTimer(gettimeofday() + 0.1, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name") if (@{$hash->{QUEUE}} == 1 && $hash->{sendworking} == 0);
}
@@ -1792,10 +2515,14 @@ SIGNALduino_SendFromQueue($$)
if($msg ne "") {
SIGNALduino_XmitLimitCheck($hash,$msg);
#DevIo_SimpleWrite($hash, $msg . "\n", 2);
+ $hash->{sendworking} = 1;
SIGNALduino_SimpleWrite($hash,$msg);
if ($msg =~ m/^S(R|C|M);/) {
$hash->{getcmd}->{cmd} = 'sendraw';
- Log3 $hash, 4, "$name SendFromQueue: msg=$msg"; # zu testen der Queue, kann wenn es funktioniert auskommentiert werden
+ Log3 $hash, 4, "$name SendrawFromQueue: msg=$msg"; # zu testen der Queue, kann wenn es funktioniert auskommentiert werden
+ }
+ elsif ($msg eq "C99") {
+ $hash->{getcmd}->{cmd} = 'ccregAll';
}
}
@@ -1820,6 +2547,8 @@ SIGNALduino_HandleWriteQueue($)
#my @arr = @{$hash->{QUEUE}};
+ $hash->{sendworking} = 0; # es wurde gesendet
+
if (defined($hash->{getcmd}->{cmd}) && $hash->{getcmd}->{cmd} eq 'sendraw') {
Log3 $name, 4, "$name/HandleWriteQueue: sendraw no answer (timeout)";
delete($hash->{getcmd});
@@ -1859,13 +2588,90 @@ SIGNALduino_Read($)
my $rmsg;
($rmsg,$SIGNALduinodata) = split("\n", $SIGNALduinodata, 2);
$rmsg =~ s/\r//;
- Log3 $name, 4, "$name/msg READ: $rmsg";
+
+ if ($rmsg =~ m/^\002(M(s|u);.*;)\003/) {
+ $rmsg =~ s/^\002//; # \002 am Anfang entfernen
+ my @msg_parts = split(";",$rmsg);
+ my $m0;
+ my $mnr0;
+ my $m1;
+ my $mL;
+ my $mH;
+ my $part = "";
+ my $partD;
+
+ foreach my $msgPart (@msg_parts) {
+ $m0 = substr($msgPart,0,1);
+ $mnr0 = ord($m0);
+ $m1 = substr($msgPart,1);
+ if ($m0 eq "M") {
+ $part .= "M" . uc($m1) . ";";
+ }
+ elsif ($mnr0 > 127) {
+ $part .= "P" . sprintf("%u", ($mnr0 & 7)) . "=";
+ if (length($m1) == 2) {
+ $mL = ord(substr($m1,0,1)) & 127; # Pattern low
+ $mH = ord(substr($m1,1,1)) & 127; # Pattern high
+ if (($mnr0 & 0b00100000) != 0) { # Vorzeichen 0b00100000 = 32
+ $part .= "-";
+ }
+ if ($mnr0 & 0b00010000) { # Bit 7 von Pattern low
+ $mL += 128;
+ }
+ $part .= ($mH * 256) + $mL;
+ }
+ $part .= ";";
+ }
+ elsif (($m0 eq "D" || $m0 eq "d") && length($m1) > 0) {
+ my @arrayD = split(//, $m1);
+ $part .= "D=";
+ $partD = "";
+ foreach my $D (@arrayD) {
+ $mH = ord($D) >> 4;
+ $mL = ord($D) & 7;
+ $partD .= "$mH$mL";
+ }
+ #Log3 $name, 3, "$name/msg READredu1$m0: $partD";
+ if ($m0 eq "d") {
+ $partD =~ s/.$//; # letzte Ziffer entfernen wenn Anzahl der Ziffern ungerade
+ }
+ $partD =~ s/^8//; # 8 am Anfang entfernen
+ #Log3 $name, 3, "$name/msg READredu2$m0: $partD";
+ $part = $part . $partD . ';';
+ }
+ elsif (($m0 eq "C" || $m0 eq "S") && length($m1) == 1) {
+ $part .= "$m0" . "P=$m1;";
+ }
+ elsif ($m1 =~ m/^[0-9A-Z]{1,2}$/) { # bei 1 oder 2 Hex Ziffern nach Dez wandeln
+ $part .= "$m0=" . hex($m1) . ";";
+ }
+ elsif ($m0 =~m/[0-9a-zA-Z]/) {
+ $part .= "$m0";
+ if ($m1 ne "") {
+ $part .= "=$m1";
+ }
+ $part .= ";";
+ }
+ }
+ Log3 $name, 4, "$name/msg READredu: $part";
+ $rmsg = "\002$part\003";
+ }
+ else {
+ Log3 $name, 4, "$name/msg READ: $rmsg";
+ }
+
if ( $rmsg && !SIGNALduino_Parse($hash, $hash, $name, $rmsg) && defined($hash->{getcmd}) && defined($hash->{getcmd}->{cmd}))
{
my $regexp;
if ($hash->{getcmd}->{cmd} eq 'sendraw') {
$regexp = '^S(R|C|M);';
}
+ elsif ($hash->{getcmd}->{cmd} eq 'ccregAll') {
+ $regexp = '^ccreg 00:';
+ }
+ elsif ($hash->{getcmd}->{cmd} eq 'bWidth') {
+ $regexp = '^C.* = .*';
+ }
else {
$regexp = $gets{$hash->{getcmd}->{cmd}}[1];
}
@@ -1897,7 +2703,9 @@ SIGNALduino_Read($)
}
else {
$rmsg = SIGNALduino_parseResponse($hash,$hash->{getcmd}->{cmd},$rmsg);
- readingsSingleUpdate($hash, $hash->{getcmd}->{cmd}, $rmsg, 0);
+ if (defined($hash->{getcmd}) && $hash->{getcmd}->{cmd} ne 'ccregAll') {
+ readingsSingleUpdate($hash, $hash->{getcmd}->{cmd}, $rmsg, 0);
+ }
if (defined($hash->{getcmd}->{asyncOut})) {
#Log3 $name, 4, "$name/msg READ: asyncOutput";
my $ao = asyncOutput( $hash->{getcmd}->{asyncOut}, $hash->{getcmd}->{cmd}.": " . $rmsg );
@@ -1920,24 +2728,30 @@ sub SIGNALduino_KeepAlive($){
return if ($hash->{DevState} eq 'disconnected');
- Log3 $name,4 , "$name/KeepAliveOk: " . $hash->{keepalive}{ok};
+ #Log3 $name,4 , "$name/KeepAliveOk: " . $hash->{keepalive}{ok};
if (!$hash->{keepalive}{ok}) {
delete($hash->{getcmd});
if ($hash->{keepalive}{retry} >= SDUINO_KEEPALIVE_MAXRETRY) {
- Log3 $name,4 , "$name/keepalive retry count reached. Reset";
+ Log3 $name,3 , "$name/keepalive not ok, retry count reached. Reset";
$hash->{DevState} = 'INACTIVE';
SIGNALduino_ResetDevice($hash);
return;
}
else {
+ my $logLevel = 3;
$hash->{keepalive}{retry} ++;
- Log3 $name,3 , "$name/KeepAliveOk: " . $hash->{keepalive}{ok} . " retry = " . $hash->{keepalive}{retry} . " -> get ping";
+ if ($hash->{keepalive}{retry} == 1) {
+ $logLevel = 4;
+ }
+ Log3 $name, $logLevel, "$name/KeepAlive not ok, retry = " . $hash->{keepalive}{retry} . " -> get ping";
$hash->{getcmd}->{cmd} = "ping";
SIGNALduino_AddSendQueue($hash, "P");
#SIGNALduino_SimpleWrite($hash, "P");
}
}
- Log3 $name,4 , "$name/keepalive retry = " . $hash->{keepalive}{retry};
+ else {
+ Log3 $name,4 , "$name/keepalive ok, retry = " . $hash->{keepalive}{retry};
+ }
$hash->{keepalive}{ok} = 0;
InternalTimer(gettimeofday() + SDUINO_KEEPALIVE_TIMEOUT, "SIGNALduino_KeepAlive", $hash);
@@ -1946,6 +2760,55 @@ sub SIGNALduino_KeepAlive($){
### Helper Subs >>>
+
+## Parses a HTTP Response for example for flash via http download
+sub SIGNALduino_ParseHttpResponse
+{
+
+ my ($param, $err, $data) = @_;
+ my $hash = $param->{hash};
+ my $name = $hash->{NAME};
+
+ if($err ne "") # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
+ {
+ Log3 $name, 3, "error while requesting ".$param->{url}." - $err"; # Eintrag fürs Log
+ }
+ elsif($param->{code} eq "200" && $data ne "") # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes)
+ {
+
+ Log3 $name, 3, "url ".$param->{url}." returned: ".length($data)." bytes Data"; # Eintrag fürs Log
+
+ if ($param->{command} eq "flash")
+ {
+ my $filename;
+
+ if ($param->{httpheader} =~ /Content-Disposition: attachment;filename=\"?([-+.\w]+)?\"/)
+ {
+ $filename = $1;
+ } else { # Filename via path if not specifyied via Content-Disposition
+ ($filename = $param->{path}) =~s/.*\///;
+ }
+
+ Log3 $name, 3, "$name: Downloaded $filename firmware from ".$param->{host};
+ Log3 $name, 5, "$name: Header = ".$param->{httpheader};
+
+
+ $filename = "FHEM/firmware/" . $filename;
+ open(my $file, ">", $filename) or die $!;
+ print $file $data;
+ close $file;
+
+ # Den Flash Befehl mit der soebene heruntergeladenen Datei ausführen
+ #Log3 $name, 3, "calling set ".$param->{command}." $filename"; # Eintrag fürs Log
+
+ SIGNALduino_Set($hash,$name,$param->{command},$filename); # $hash->{SetFn}
+
+ }
+ } else {
+ Log3 $name, 3, "undefined error while requesting ".$param->{url}." - $err - code=".$param->{code}; # Eintrag fürs Log
+ }
+}
+
sub SIGNALduino_splitMsg
{
my $txt = shift;
@@ -1980,6 +2843,8 @@ sub SIGNALduino_PatternExists
#Debug "plist: ".Dumper($patternList) if($debug);
#Debug "searchlist: ".Dumper($search) if($debug);
+
+
my $searchpattern;
my $valid=1;
my @pstr;
@@ -2129,6 +2994,7 @@ sub SIGNALduino_Split_Message($$)
my $rawData;
my $clockabs;
my $mcbitnum;
+ my $rssi;
my @msg_parts = SIGNALduino_splitMsg($rmsg,';'); ## Split message parts by ";"
my %ret;
@@ -2188,6 +3054,13 @@ sub SIGNALduino_Split_Message($$)
$clockabs = $_ ;
Debug "$name: extracted absolute clock $clockabs \n" if ($debug);
$ret{clockabs} = $clockabs;
+ }
+ elsif($_ =~ m/^R=\d+/) ### RSSI ###
+ {
+ $_ =~ s/R=//;
+ $rssi = $_ ;
+ Debug "$name: extracted RSSI $rssi \n" if ($debug);
+ $ret{rssi} = $rssi;
} else {
Debug "$name: unknown Message part $_" if ($debug);;
}
@@ -2200,36 +3073,66 @@ sub SIGNALduino_Split_Message($$)
# Function which dispatches a message if needed.
-sub SIGNALduno_Dispatch($$$)
+sub SIGNALduno_Dispatch($$$$$)
{
- my ($hash, $rmsg, $dmsg) = @_;
+ my ($hash, $rmsg, $dmsg, $rssi, $id) = @_;
my $name = $hash->{NAME};
if (!defined($dmsg))
{
- Log3 $name, 5, "$name: (SIGNALduno_Dispatch) dmsg is undef. Skipping dispatch call";
+ Log3 $name, 5, "$name Dispatch: dmsg is undef. Skipping dispatch call";
return;
}
- Log3 $name, 5, "$name: converted Data to ($dmsg)";
+ #Log3 $name, 5, "$name: Dispatch DMSG: $dmsg";
+
+ my $DMSGgleich = 1;
+ if ($dmsg eq $hash->{LASTDMSG}) {
+ Log3 $name, SDUINO_DISPATCH_VERBOSE, "$name Dispatch: $dmsg, test gleich";
+ } else {
+ if (defined($hash->{DoubleMsgIDs}{$id})) {
+ $DMSGgleich = 0;
+ Log3 $name, SDUINO_DISPATCH_VERBOSE, "$name Dispatch: $dmsg, test ungleich";
+ }
+ else {
+ Log3 $name, SDUINO_DISPATCH_VERBOSE, "$name Dispatch: $dmsg, test ungleich: disabled";
+ }
+ $hash->{LASTDMSG} = $dmsg;
+ }
- #Dispatch only if $dmsg is different from last $dmsg, or if 2 seconds are between transmits
- if ( ($hash->{DMSG} ne $dmsg) || ($hash->{TIME}+1 < time()) ) {
+ if ($DMSGgleich) {
+ #Dispatch if dispatchequals is provided in protocol definition or only if $dmsg is different from last $dmsg, or if 2 seconds are between transmits
+ if ( (SIGNALduino_getProtoProp($id,'dispatchequals',0) eq 'true') || ($hash->{DMSG} ne $dmsg) || ($hash->{TIME}+2 < time() ) ) {
$hash->{MSGCNT}++;
$hash->{TIME} = time();
$hash->{DMSG} = $dmsg;
- my $event = 0;
- if (substr($dmsg,0,1) eq 'u') {
- $event = 1;
+ #my $event = 0;
+ if (substr(ucfirst($dmsg),0,1) eq 'U') {
+ #$event = 1;
+ DoTrigger($name, "DMSG " . $dmsg);
}
- readingsSingleUpdate($hash, "state", $hash->{READINGS}{state}{VAL}, $event);
+ #readingsSingleUpdate($hash, "state", $hash->{READINGS}{state}{VAL}, $event);
+
$hash->{RAWMSG} = $rmsg;
- my %addvals = (RAWMSG => $rmsg, DMSG => $dmsg);
+ my %addvals = (DMSG => $dmsg);
+ if (AttrVal($name,"suppressDeviceRawmsg",0) == 0) {
+ $addvals{RAWMSG} = $rmsg
+ }
+ if(defined($rssi)) {
+ $hash->{RSSI} = $rssi;
+ $addvals{RSSI} = $rssi;
+ $rssi .= " dB,"
+ }
+ else {
+ $rssi = "";
+ }
+ Log3 $name, SDUINO_DISPATCH_VERBOSE, "$name Dispatch: $dmsg, $rssi dispatch";
Dispatch($hash, $dmsg, \%addvals); ## Dispatch to other Modules
} else {
- Log3 $name, 4, "$name: Dropped ($dmsg) due to short time or equal msg";
- }
+ Log3 $name, 4, "$name Dispatch: $dmsg, Dropped due to short time or equal msg";
+ }
+ }
}
sub
@@ -2240,9 +3143,14 @@ SIGNALduino_Parse_MS($$$$%)
my $protocolid;
my $syncidx=$msg_parts{syncidx};
my $clockidx=$msg_parts{clockidx};
+ my $rawRssi=$msg_parts{rssi};
my $protocol=undef;
my $rawData=$msg_parts{rawData};
my %patternList;
+ my $rssi;
+ if (defined($rawRssi)) {
+ $rssi = ($rawRssi>=128 ? (($rawRssi-256)/2-74) : ($rawRssi/2-74)); # todo: passt dies so? habe ich vom 00_cul.pm
+ }
#$patternList{$_} = $msg_parts{rawData}{$_] for keys %msg_parts{rawData};
#$patternList = \%msg_parts{pattern};
@@ -2294,8 +3202,8 @@ SIGNALduino_Parse_MS($$$$%)
#Check calculated max length
$valid = $valid && $ProtocolListSIGNALduino{$id}{length_max} >= $bit_length if (exists $ProtocolListSIGNALduino{$id}{length_max});
+ Debug "expecting $bit_length bits in signal" if ($debug);
next if (!$valid) ;
- Debug "expecting $bit_length bits in signal" if ($debug && $valid);
#Debug Dumper(@{$ProtocolListSIGNALduino{$id}{sync}});
Debug "Searching in patternList: ".Dumper(\%patternList) if($debug);
@@ -2366,7 +3274,7 @@ SIGNALduino_Parse_MS($$$$%)
Debug "$name: decoded message raw (@bit_msg), ".@bit_msg." bits\n" if ($debug);;
my ($rcode,@retvalue) = SIGNALduino_callsub('postDemodulation',$ProtocolListSIGNALduino{$id}{postDemodulation},$name,@bit_msg);
- next if (!$rcode);
+ next if ($rcode < 1 );
#Log3 $name, 5, "$name: postdemodulation value @retvalue";
@bit_msg = @retvalue;
@@ -2391,25 +3299,43 @@ SIGNALduino_Parse_MS($$$$%)
#my $dmsg = sprintf "%02x", oct "0b" . join "", @bit_msg; ## Array -> String -> bin -> hex
my $dmsg = SIGNALduino_b2h(join "", @bit_msg);
- $dmsg = "$dmsg"."$ProtocolListSIGNALduino{$id}{postamble}" if (defined($ProtocolListSIGNALduino{$id}{postamble}));
+ my $postamble = $ProtocolListSIGNALduino{$id}{postamble};
+ #if (defined($rawRssi)) {
+ #if (defined($ProtocolListSIGNALduino{$id}{preamble}) && $ProtocolListSIGNALduino{$id}{preamble} eq "s") {
+ # $postamble = sprintf("%02X", $rawRssi);
+ #} elsif ($id eq "7") {
+ # $postamble = "#R" . sprintf("%02X", $rawRssi);
+ #}
+ #}
+ $dmsg = "$dmsg".$postamble if (defined($postamble));
$dmsg = "$ProtocolListSIGNALduino{$id}{preamble}"."$dmsg" if (defined($ProtocolListSIGNALduino{$id}{preamble}));
- Log3 $name, 4, "$name: Decoded MS Protocol id $id dmsg $dmsg length " . scalar @bit_msg;
-
+ if (defined($rssi)) {
+ Log3 $name, 4, "$name: Decoded MS Protocol id $id dmsg $dmsg length " . scalar @bit_msg . " RSSI = $rssi";
+ } else {
+ Log3 $name, 4, "$name: Decoded MS Protocol id $id dmsg $dmsg length " . scalar @bit_msg;
+ }
#my ($rcode,@retvalue) = SIGNALduino_callsub('preDispatchfunc',$ProtocolListSIGNALduino{$id}{preDispatchfunc},$name,$dmsg);
#next if (!$rcode);
#$dmsg = @retvalue;
#undef(@retvalue); undef($rcode);
-
- my $modulematch;
+ my $modulematch = undef;
if (defined($ProtocolListSIGNALduino{$id}{modulematch})) {
$modulematch = $ProtocolListSIGNALduino{$id}{modulematch};
}
if (!defined($modulematch) || $dmsg =~ m/$modulematch/) {
Debug "$name: dispatching now msg: $dmsg" if ($debug);
- SIGNALduno_Dispatch($hash,$rmsg,$dmsg);
+ if (defined($ProtocolListSIGNALduino{$id}{developId}) && substr($ProtocolListSIGNALduino{$id}{developId},0,1) eq "m") {
+ my $devid = "m$id";
+ my $develop = lc(AttrVal($name,"development",""));
+ if ($develop !~ m/$devid/) { # kein dispatch wenn die Id nicht im Attribut development steht
+ Log3 $name, 3, "$name: ID=$devid skiped dispatch (developId=m). To use, please add m$id to the attr development";
+ next;
+ }
+ }
+ SIGNALduno_Dispatch($hash,$rmsg,$dmsg,$rssi,$id);
$message_dispatched=1;
}
}
@@ -2437,18 +3363,21 @@ sub SIGNALduino_padbits(\@$)
# - - - - - - - - - - - -
#=item SIGNALduino_getProtoProp()
-#This functons, will return a value from the Protocolist and check if it is defined
+#This functons, will return a value from the Protocolist and check if it is defined optional you can specify a optional default value that will be reurned
#
# returns "" if the var is not defined
# =cut
# $id, $propertyname,
-sub SIGNALduino_getProtoProp($$)
+sub SIGNALduino_getProtoProp
{
- my $id = shift;
- my $propNameLst = shift;
+ my ($id,$propNameLst,$default) = @_;
+
+ #my $id = shift;
+ #my $propNameLst = shift;
return $ProtocolListSIGNALduino{$id}{$propNameLst} if defined($ProtocolListSIGNALduino{$id}{$propNameLst});
- return undef;
+ return $default; # Will return undef if $default is not provided
+ #return undef;
}
sub SIGNALduino_Parse_MU($$$$@)
@@ -2456,17 +3385,21 @@ sub SIGNALduino_Parse_MU($$$$@)
my ($hash, $iohash, $name, $rmsg,%msg_parts) = @_;
my $protocolid;
- my $clockidx=$msg_parts{clockidx};
+ my $clockidx=$msg_parts{clockidx};
+ my $rssi=$msg_parts{rssi};
my $protocol=undef;
my $rawData;
my %patternListRaw;
my $message_dispatched=0;
-
my $debug = AttrVal($iohash->{NAME},"debug",0);
+ if (defined($rssi)) {
+ $rssi = ($rssi>=128 ? (($rssi-256)/2-74) : ($rssi/2-74)); # todo: passt dies so? habe ich vom 00_cul.pm
+ }
+
Debug "$name: processing unsynced message\n" if ($debug);
- #my $clockabs; #Clock will be fetched from Protocol
+ my $clockabs = 1; #Clock will be fetched from Protocol if possible
#$patternListRaw{$_} = floor($msg_parts{pattern}{$_}/$clockabs) for keys $msg_parts{pattern};
$patternListRaw{$_} = $msg_parts{pattern}{$_} for keys %{$msg_parts{pattern}};
@@ -2482,7 +3415,7 @@ sub SIGNALduino_Parse_MU($$$$@)
foreach $id (@{$hash->{muIdList}}) {
my $valid=1;
- my $clockabs= $ProtocolListSIGNALduino{$id}{clockabs};
+ $clockabs= $ProtocolListSIGNALduino{$id}{clockabs};
my %patternList;
$rawData=$msg_parts{rawData};
if (exists($ProtocolListSIGNALduino{$id}{filterfunc}))
@@ -2540,17 +3473,18 @@ sub SIGNALduino_Parse_MU($$$$@)
my $pstr="";
$valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{one}},\%patternList,\$rawData)) >=0;
Debug "Found matched one" if ($debug && $valid);
-
-
my $oneStr=$pstr if ($valid);
$patternLookupHash{$pstr}="1" if ($valid); ## Append one to our lookuptable
Debug "added $pstr " if ($debug && $valid);
- $valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{zero}},\%patternList,\$rawData)) >=0;
- Debug "Found matched zero" if ($debug && $valid);
- my $zeroStr=$pstr if ($valid);
- $patternLookupHash{$pstr}="0" if ($valid); ## Append zero to our lookuptable
- Debug "added $pstr " if ($debug && $valid);
+ my $zeroStr ="";
+ if (scalar @{$ProtocolListSIGNALduino{$id}{zero}} >0) {
+ $valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{zero}},\%patternList,\$rawData)) >=0;
+ Debug "Found matched zero" if ($debug && $valid);
+ $zeroStr=$pstr if ($valid);
+ $patternLookupHash{$pstr}="0" if ($valid); ## Append zero to our lookuptable
+ Debug "added $pstr " if ($debug && $valid);
+ }
if (defined($ProtocolListSIGNALduino{$id}{float}))
{
@@ -2583,17 +3517,21 @@ sub SIGNALduino_Parse_MU($$$$@)
if (@msgStartLst = SIGNALduino_getProtoProp($id,"start"))
{
Debug "msgStartLst: ".Dumper(@msgStartLst) if ($debug);
-
- if ( ($startStr=SIGNALduino_PatternExists($hash,@msgStartLst,\%patternList,\$rawData)) eq -1)
- {
- Log3 $name, 5, "$name: start pattern for MU Protocol id $id -> $ProtocolListSIGNALduino{$id}{name} mismatches, aborting" ;
- $valid=0;
- next;
- };
- }
- $start_regex="$startStr($oneStr|$zeroStr)";
- Debug "Regex is: $start_regex" if ($debug);
+ if ( ($startStr=SIGNALduino_PatternExists($hash,@msgStartLst,\%patternList,\$rawData)) eq -1)
+ {
+ Log3 $name, 5, "$name: start pattern for MU Protocol id $id -> $ProtocolListSIGNALduino{$id}{name} mismatches, aborting" ;
+ $valid=0;
+ next;
+ };
+ }
+
+
+ if (length ($zeroStr) > 0 ){ $start_regex = "$startStr\($oneStr\|$zeroStr\)";}
+ else {$start_regex = $startStr.$oneStr; }
+
+ Debug "Regex is: $start_regex" if ($debug);
+
$rawData =~ /$start_regex/;
if (defined($-[0] && $-[0] > 0)) {
$message_start=$-[0]+ length($startStr);
@@ -2639,7 +3577,8 @@ sub SIGNALduino_Parse_MU($$$$@)
if ($valid) {
my ($rcode,@retvalue) = SIGNALduino_callsub('postDemodulation',$ProtocolListSIGNALduino{$id}{postDemodulation},$name,@bit_msg);
- next if (!$rcode);
+ next if ($rcode < 1 );
+
#Log3 $name, 5, "$name: postdemodulation value @retvalue";
@bit_msg = @retvalue;
@@ -2658,7 +3597,11 @@ sub SIGNALduino_Parse_MU($$$$@)
$dmsg = "$dmsg"."$ProtocolListSIGNALduino{$id}{postamble}" if (defined($ProtocolListSIGNALduino{$id}{postamble}));
$dmsg = "$ProtocolListSIGNALduino{$id}{preamble}"."$dmsg" if (defined($ProtocolListSIGNALduino{$id}{preamble}));
- Log3 $name, 4, "$name: decoded matched MU Protocol id $id dmsg $dmsg length " . scalar @bit_msg;
+ if (defined($rssi)) {
+ Log3 $name, 4, "$name: decoded matched MU Protocol id $id dmsg $dmsg length " . scalar @bit_msg . " RSSI = $rssi";
+ } else {
+ Log3 $name, 4, "$name: decoded matched MU Protocol id $id dmsg $dmsg length " . scalar @bit_msg;
+ }
my $modulematch;
if (defined($ProtocolListSIGNALduino{$id}{modulematch})) {
@@ -2666,7 +3609,16 @@ sub SIGNALduino_Parse_MU($$$$@)
}
if (!defined($modulematch) || $dmsg =~ m/$modulematch/) {
Debug "$name: dispatching now msg: $dmsg" if ($debug);
- SIGNALduno_Dispatch($hash,$rmsg,$dmsg);
+ if (defined($ProtocolListSIGNALduino{$id}{developId}) && substr($ProtocolListSIGNALduino{$id}{developId},0,1) eq "m") {
+ my $devid = "m$id";
+ my $develop = lc(AttrVal($name,"development",""));
+ if ($develop !~ m/$devid/) { # kein dispatch wenn die Id nicht im Attribut development steht
+ Log3 $name, 3, "$name: ID=$devid skiped dispatch (developId=m). To use, please add m$id to the attr development";
+ next;
+ }
+ }
+
+ SIGNALduno_Dispatch($hash,$rmsg,$dmsg,$rssi,$id);
$message_dispatched=1;
}
} else {
@@ -2691,7 +3643,6 @@ sub SIGNALduino_Parse_MU($$$$@)
if (defined($-[0]) && ($-[0] > 0)) {
#$i=$-[0]+ $i+ length($startStr);
$i=$-[0]+ $i;
-
$i=$i-$signal_width if ($i>0 && length($startStr) == 0); #Todo:
Debug "$name: found restart at Position $i ($regex)\n" if ($debug);
} else {
@@ -2728,10 +3679,15 @@ SIGNALduino_Parse_MC($$$$@)
my ($hash, $iohash, $name, $rmsg,%msg_parts) = @_;
my $clock=$msg_parts{clockabs}; ## absolute clock
my $rawData=$msg_parts{rawData};
+ my $rssi=$msg_parts{rssi};
+ my $mcbitnum=$msg_parts{mcbitnum};
my $bitData;
my $dmsg;
my $message_dispatched=0;
my $debug = AttrVal($iohash->{NAME},"debug",0);
+ if (defined($rssi)) {
+ $rssi = ($rssi>=128 ? (($rssi-256)/2-74) : ($rssi/2-74)); # todo: passt dies so? habe ich vom 00_cul.pm
+ }
return undef if (!$clock);
#my $protocol=undef;
@@ -2740,7 +3696,12 @@ SIGNALduino_Parse_MC($$$$@)
Debug "$name: processing manchester messag len:".length($rawData) if ($debug);
my $hlen = length($rawData);
- my $blen = $hlen * 4;
+ my $blen;
+ #if (defined($mcbitnum)) {
+ # $blen = $mcbitnum;
+ #} else {
+ $blen = $hlen * 4;
+ #}
my $id;
my $rawDataInverted;
@@ -2748,12 +3709,17 @@ SIGNALduino_Parse_MC($$$$@)
foreach $id (@{$hash->{mcIdList}}) {
-
+ #next if ($blen < $ProtocolListSIGNALduino{$id}{length_min} || $blen > $ProtocolListSIGNALduino{$id}{length_max});
+ #if ( $clock >$ProtocolListSIGNALduino{$id}{clockrange}[0] and $clock <$ProtocolListSIGNALduino{$id}{clockrange}[1]);
if ( $clock >$ProtocolListSIGNALduino{$id}{clockrange}[0] and $clock <$ProtocolListSIGNALduino{$id}{clockrange}[1] and length($rawData)*4 >= $ProtocolListSIGNALduino{$id}{length_min} )
{
Debug "clock and min length matched" if ($debug);
- Log3 $name, 4, "$name: Found manchester Protocol id $id clock $clock -> $ProtocolListSIGNALduino{$id}{name}";
+ if (defined($rssi)) {
+ Log3 $name, 4, "$name: Found manchester Protocol id $id clock $clock RSSI $rssi -> $ProtocolListSIGNALduino{$id}{name}";
+ } else {
+ Log3 $name, 4, "$name: Found manchester Protocol id $id clock $clock -> $ProtocolListSIGNALduino{$id}{name}";
+ }
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
@@ -2770,7 +3736,7 @@ SIGNALduino_Parse_MC($$$$@)
{
Log3 $name, 5, "$name: Error: Unknown function=$method. Please define it in file $0";
} else {
- my ($rcode,$res) = $method->($name,$bitData,$id);
+ my ($rcode,$res) = $method->($name,$bitData,$id,$mcbitnum);
if ($rcode != -1) {
$dmsg = $res;
$dmsg=$ProtocolListSIGNALduino{$id}{preamble}.$dmsg if (defined($ProtocolListSIGNALduino{$id}{preamble}));
@@ -2779,11 +3745,20 @@ SIGNALduino_Parse_MC($$$$@)
$modulematch = $ProtocolListSIGNALduino{$id}{modulematch};
}
if (!defined($modulematch) || $dmsg =~ m/$modulematch/) {
- SIGNALduno_Dispatch($hash,$rmsg,$dmsg);
+ if (defined($ProtocolListSIGNALduino{$id}{developId}) && substr($ProtocolListSIGNALduino{$id}{developId},0,1) eq "m") {
+ my $devid = "m$id";
+ my $develop = lc(AttrVal($name,"development",""));
+ if ($develop !~ m/$devid/) { # kein dispatch wenn die Id nicht im Attribut development steht
+ Log3 $name, 3, "$name: ID=$devid skiped dispatch (developId=m). To use, please add m$id to the attr development";
+ next;
+ }
+ }
+ SIGNALduno_Dispatch($hash,$rmsg,$dmsg,$rssi,$id);
$message_dispatched=1;
}
} else {
- Log3 $name, 5, "$name: protocol does not match return from method: ($res)" if ($debug);
+ $res="undef" if (!defined($res));
+ Log3 $name, 5, "$name: protocol does not match return from method: ($res)" ;
}
}
@@ -2801,9 +3776,14 @@ SIGNALduino_Parse($$$$@)
my ($hash, $iohash, $name, $rmsg, $initstr) = @_;
#print Dumper(\%ProtocolListSIGNALduino);
+
- return undef if !($rmsg=~ s/^\002(M.;.*;)\003/$1/); ## Check if a Data Message arrived and if it's complete (start & end control char are received)
- # cut off start end end character from message for further processing they are not needed
+ if (!($rmsg=~ s/^\002(M.;.*;)\003/$1/)) # Check if a Data Message arrived and if it's complete (start & end control char are received)
+ { # cut off start end end character from message for further processing they are not needed
+ Log3 $name, AttrVal($name,"noMsgVerbose",5), "$name/noMsg Parse: $rmsg";
+ return undef;
+ }
+
if (defined($hash->{keepalive})) {
$hash->{keepalive}{ok} = 1;
$hash->{keepalive}{retry} = 0;
@@ -2814,6 +3794,10 @@ SIGNALduino_Parse($$$$@)
Debug "$name: incomming message: ($rmsg)\n" if ($debug);
+ if (AttrVal($name, "rawmsgEvent", 0)) {
+ DoTrigger($name, "RAWMSG " . $rmsg);
+ }
+
my %signal_parts=SIGNALduino_Split_Message($rmsg,$name); ## Split message and save anything in an hash %signal_parts
#Debug "raw data ". $signal_parts{rawData};
@@ -2882,6 +3866,17 @@ SIGNALduino_Ready($)
return ($InBytes && $InBytes>0);
}
+
+sub
+SIGNALduino_WriteInit($)
+{
+ my ($hash) = @_;
+
+ # todo: ist dies so ausreichend, damit die Aenderungen uebernommen werden?
+ SIGNALduino_AddSendQueue($hash,"WS36"); # SIDLE, Exit RX / TX, turn off frequency synthesizer
+ SIGNALduino_AddSendQueue($hash,"WS34"); # SRX, Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
+}
+
########################
sub
SIGNALduino_SimpleWrite(@)
@@ -2949,27 +3944,95 @@ SIGNALduino_Attr(@)
}
elsif ($aName eq "whitelist_IDs")
{
- SIGNALduino_IdList($hash, $name, $aVal);
+ Log3 $name, 3, "$name Attr: whitelist_IDs";
+ if ($init_done) { # beim fhem Start wird das SIGNALduino_IdList nicht aufgerufen, da es beim define aufgerufen wird
+ SIGNALduino_IdList("x:$name",$aVal);
+ }
+ }
+ elsif ($aName eq "blacklist_IDs")
+ {
+ Log3 $name, 3, "$name Attr: blacklist_IDs";
+ if ($init_done) { # beim fhem Start wird das SIGNALduino_IdList nicht aufgerufen, da es beim define aufgerufen wird
+ SIGNALduino_IdList("x:$name",undef,$aVal);
+ }
+ }
+ elsif ($aName eq "development")
+ {
+ Log3 $name, 3, "$name Attr: development";
+ if ($init_done) { # beim fhem Start wird das SIGNALduino_IdList nicht aufgerufen, da es beim define aufgerufen wird
+ SIGNALduino_IdList("x:$name",undef,undef,$aVal);
+ }
+ }
+ elsif ($aName eq "doubleMsgCheck_IDs")
+ {
+ if (defined($aVal)) {
+ if (length($aVal)>0) {
+ if (substr($aVal,0 ,1) eq '#') {
+ Log3 $name, 3, "$name Attr: doubleMsgCheck_IDs disabled: $aVal";
+ delete $hash->{DoubleMsgIDs};
+ }
+ else {
+ Log3 $name, 3, "$name Attr: doubleMsgCheck_IDs enabled: $aVal";
+ my %DoubleMsgiD = map { $_ => 1 } split(",", $aVal);
+ $hash->{DoubleMsgIDs} = \%DoubleMsgiD;
+ #print Dumper $hash->{DoubleMsgIDs};
+ }
+ }
+ else {
+ Log3 $name, 3, "$name delete Attr: doubleMsgCheck_IDs";
+ delete $hash->{DoubleMsgIDs};
+ }
+ }
+ }
+ elsif ($aName eq "cc1101_frequency")
+ {
+ if ($aVal eq "" || $aVal < 800) {
+ Log3 $name, 3, "$name: delete cc1101_frequeny";
+ delete ($hash->{cc1101_frequency}) if (defined($hash->{cc1101_frequency}));
+ } else {
+ Log3 $name, 3, "$name: setting cc1101_frequency to 868";
+ $hash->{cc1101_frequency} = 868;
+ }
}
return undef;
}
-sub SIGNALduino_IdList($$$)
+sub SIGNALduino_IdList($@)
{
- my ($hash, $name, $aVal) = @_;
+ my ($param, $aVal, $blacklist, $develop) = @_;
+ my (undef,$name) = split(':', $param);
+ my $hash = $defs{$name};
my @msIdList = ();
my @muIdList = ();
my @mcIdList = ();
+ if (!defined($aVal)) {
+ $aVal = AttrVal($name,"whitelist_IDs","");
+ }
+ Log3 $name, 3, "$name sduinoIdList: whitelistIds=$aVal";
+
+ if (!defined($blacklist)) {
+ $blacklist = AttrVal($name,"blacklist_IDs","");
+ }
+ Log3 $name, 3, "$name sduinoIdList: blacklistIds=$blacklist";
+
+ if (!defined($develop)) {
+ $develop = AttrVal($name,"development","");
+ }
+ $develop = lc($develop);
+ Log3 $name, 3, "$name sduinoIdList: development=$develop";
+
my %WhitelistIDs;
- my $wflag = 0;
+ my %BlacklistIDs;
+ my $wflag = 0; # whitelist flag, 0=disabled
+ my $bflag = 0; # blacklist flag, 0=disabled
if (defined($aVal) && length($aVal)>0)
{
if (substr($aVal,0 ,1) eq '#') {
- Log3 $name, 3, "Attr whitelist deaktiviert: $aVal";
+ Log3 $name, 3, "$name Attr whitelist disabled: $aVal";
}
else {
%WhitelistIDs = map { $_ => 1 } split(",", $aVal);
@@ -2978,6 +4041,15 @@ sub SIGNALduino_IdList($$$)
$wflag = 1;
}
}
+ if ($wflag == 0) { # whitelist disabled
+ if (defined($blacklist) && length($blacklist)>0) {
+ %BlacklistIDs = map { $_ => 1 } split(",", $blacklist);
+ my $w = join ', ' => map "$_" => keys %BlacklistIDs;
+ Log3 $name, 3, "$name Attr blacklist $w";
+ $bflag = 1;
+ }
+ }
+
my $id;
foreach $id (keys %ProtocolListSIGNALduino)
{
@@ -2985,8 +4057,28 @@ sub SIGNALduino_IdList($$$)
if ($wflag == 1 && !defined($WhitelistIDs{$id}))
{
#Log3 $name, 3, "skip ID $id";
- next;
- }
+ next;
+ }
+ if ($bflag == 1 && defined($BlacklistIDs{$id}))
+ {
+ Log3 $name, 3, "$name skip Blacklist ID $id";
+ next;
+ }
+
+ if (defined($ProtocolListSIGNALduino{$id}{developId}) && substr($ProtocolListSIGNALduino{$id}{developId},0,1) eq "p") {
+ my $devid = "p$id";
+ if ($develop !~ m/$devid/) { # skip wenn die Id nicht im Attribut development steht
+ Log3 $name, 3, "$name: ID=$devid skiped (developId=p)";
+ next;
+ }
+ }
+
+ if (defined($ProtocolListSIGNALduino{$id}{developId}) && substr($ProtocolListSIGNALduino{$id}{developId},0,1) eq "y") {
+ if ($develop !~ m/y/) { # skip wenn y nicht im Attribut development steht
+ Log3 $name, 3, "$name: ID=$id skiped (developId=y)";
+ next;
+ }
+ }
if (exists ($ProtocolListSIGNALduino{$id}{format}) && $ProtocolListSIGNALduino{$id}{format} eq "manchester")
{
@@ -3026,13 +4118,14 @@ sub SIGNALduino_callsub
if ( defined $method && defined &$method )
{
- Log3 $name, 5, "$name: applying $funcname method $method";
+ #my $subname = @{[eval {&$method}, $@ =~ /.*/]};
+ Log3 $name, 5, "$name: applying $funcname"; # method $subname";
#Log3 $name, 5, "$name: value bevore $funcname: @args";
- my @returnvalues = $method->(@args) ;
+ my ($rcode, @returnvalues) = $method->($name, @args) ;
Log3 $name, 5, "$name: modified value after $funcname: @returnvalues";
- return (1,@returnvalues);
+ return ($rcode, @returnvalues);
} elsif (defined $method ) {
Log3 $name, 5, "$name: Error: Unknown method $funcname Please check definition";
return (0,undef);
@@ -3046,23 +4139,26 @@ sub SIGNALduino_callsub
# output = @list
sub SIGNALduino_lengtnPrefix
{
- my $msg = join("",@_);
+ my ($name, @bit_msg) = @_;
+
+ my $msg = join("",@bit_msg);
#$msg = unpack("B8", pack("N", length($msg))).$msg;
$msg=sprintf('%08b', length($msg)).$msg;
- return split("",$msg);
+ return (1,split("",$msg));
}
sub SIGNALduino_bit2Arctec
{
- my $msg = join("",@_);
+ my ($name, @bit_msg) = @_;
+ my $msg = join("",@bit_msg);
# Convert 0 -> 01 1 -> 10 to be compatible with IT Module
$msg =~ s/0/z/g;
$msg =~ s/1/10/g;
$msg =~ s/z/01/g;
- return split("",$msg);
+ return (1,split("",$msg));
}
@@ -3075,13 +4171,427 @@ sub SIGNALduino_ITV1_tristateToBit($)
$msg =~ s/F/01/g;
$msg =~ s/D/10/g;
- return $msg;
+ return (1,$msg);
+}
+
+sub SIGNALduino_HE($@) {
+ my ($name, @bit_msg) = @_;
+ my $msg = join("",@bit_msg);
+
+ #Log3 $name, 4, "$name HE: $msg";
+ Log3 $name, 4, "$name HE: " . substr($msg,0,11) ." ". substr($msg,11,32) ." ". substr($msg,43,4) ." ". substr($msg,47,2) ." ". substr($msg,49,2) ." ". substr($msg,51);
+
+ return (1,split("",$msg));
+}
+
+sub SIGNALduino_postDemo_Hoermann($@) {
+ my ($name, @bit_msg) = @_;
+ my $msg = join("",@bit_msg);
+
+ if (substr($msg,0,9) ne "000000001") { # check ident
+ Log3 $name, 4, "$name: Hoermann ERROR - Ident not 000000001";
+ return 0, undef;
+ } else {
+ Log3 $name, 5, "$name: Hoermann $msg";
+ $msg = substr($msg,9);
+ return (1,split("",$msg));
+ }
+}
+
+sub SIGNALduino_postDemo_FS20($@) {
+ my ($name, @bit_msg) = @_;
+ my $datastart = 0;
+ my $protolength = scalar @bit_msg;
+ 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, 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) { ### 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[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, 3, "$name: FS20 ERROR - Parity not even";
+ return 0, undef;
+ }
+ } # parity ok
+ for(my $b = 44; $b > 0; $b -= 9) { # delete 5 parity bits
+ splice(@bit_msg, $b, 1);
+ }
+ 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;
+}
+
+sub SIGNALduino_postDemo_FHT80($@) {
+ my ($name, @bit_msg) = @_;
+ my $datastart = 0;
+ my $protolength = scalar @bit_msg;
+ 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, 3, "$name: FHT80 - 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 == 54) { ### FHT80 fixed length
+ 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 + 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, 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);
+ }
+ if ($bit_msg[26] != 1) { # Bit 5 Byte 3 must 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
+ Log3 $name, 4, "$name: FHT80 - roomthermostat protolength $protolength";
+ return (1, @bit_msg); ## FHT80 ok
+ }
+ }
+ return 0, undef;
+}
+
+sub SIGNALduino_postDemo_FHT80TF($@) {
+ my ($name, @bit_msg) = @_;
+ my $datastart = 0;
+ my $protolength = scalar @bit_msg;
+ my $sum = 0;
+ my $b = 0;
+ if ($protolength < 46) { # min 5 bytes + 6 bits
+ 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, 3, "$name: FHTTF or 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) { ### FHT80TF fixed length
+ 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[36 .. 43])); # Checksum Byte 5
+ 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
+ splice(@bit_msg, $b, 1);
+ }
+ if ($bit_msg[26] != 0) { # Bit 5 Byte 3 must 0
+ Log3 $name, 3, "$name: FHT80 ERROR - byte 3 bit 5 not 0";
+ return 0, undef;
+ }
+ splice(@bit_msg, 32, 8); # delete checksum
+ Log3 $name, 4, "$name: FHT80TF - door/window switch protolength $protolength";
+ return (1, @bit_msg); ## FHT80TF ok
+ }
+ }
+ return 0, undef;
+}
+
+sub SIGNALduino_postDemo_WS7035($@) {
+ my ($name, @bit_msg) = @_;
+ my $msg = join("",@bit_msg);
+ my $parity = 0; # Parity even
+
+ Log3 $name, 4, "$name: WS7035 $msg";
+ if (substr($msg,0,8) ne "10100000") { # check ident
+ 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, 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);
+ substr($msg, 27, 4, ''); # delete nibble 8
+ return (1,split("",$msg));
+ }
+ }
+}
+
+sub SIGNALduino_postDemo_WS2000($@) {
+ my ($name, @bit_msg) = @_;
+ my $debug = AttrVal($name,"debug",0);
+ my @new_bit_msg = "";
+ my $protolength = scalar @bit_msg;
+ my @datalenghtws = (35,50,35,50,70,40,40,85);
+ my $datastart = 0;
+ my $datalength = 0;
+ my $datalength1 = 0;
+ my $index = 0;
+ my $data = 0;
+ my $dataindex = 0;
+ my $error = 0;
+ my $check = 0;
+ my $sum = 5;
+ my $typ = 0;
+ my $adr = 0;
+ my @sensors = (
+ "Thermo",
+ "Thermo/Hygro",
+ "Rain",
+ "Wind",
+ "Thermo/Hygro/Baro",
+ "Brightness",
+ "Pyrano",
+ "Kombi"
+ );
+
+ 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, 3, "$name: WS2000 - ERROR message all bit are zeros";
+ return 0, undef;
+ }
+ $datalength = $protolength - $datastart;
+ $datalength1 = $datalength - ($datalength % 5); # modulo 5
+ Log3 $name, 5, "$name: WS2000 protolength: $protolength, datastart: $datastart, datalength $datalength";
+ $typ = oct( "0b".(join "", reverse @bit_msg[$datastart + 1.. $datastart + 4])); # Sensortyp
+ if ($typ > 7) {
+ Log3 $name, 4, "$name: WS2000 Sensortyp $typ - ERROR typ to big";
+ return 0, undef;
+ }
+ if ($typ == 1 && ($datalength == 45 || $datalength == 46)) {$datalength1 += 5;} # Typ 1 ohne Summe
+ if ($datalenghtws[$typ] != $datalength1) { # check lenght of message
+ Log3 $name, 4, "$name: WS2000 Sensortyp $typ - ERROR lenght of message $datalength1 ($datalenghtws[$typ])";
+ return 0, undef;
+ } elsif ($datastart > 10) { # max 10 Bit preamble
+ Log3 $name, 4, "$name: WS2000 ERROR preamble > 10 ($datastart)";
+ return 0, undef;
+ } else {
+ do {
+ $error += !$bit_msg[$index + $datastart]; # jedes 5. Bit muss 1 sein
+ $dataindex = $index + $datastart + 1;
+ $data = oct( "0b".(join "", reverse @bit_msg[$dataindex .. $dataindex + 3]));
+ if ($index == 5) {$adr = ($data & 0x07)} # Sensoradresse
+ if ($datalength == 45 || $datalength == 46) { # Typ 1 ohne Summe
+ if ($index <= $datalength - 5) {
+ $check = $check ^ $data; # Check - Typ XOR Adresse XOR bis XOR Check muss 0 ergeben
+ }
+ } else {
+ if ($index <= $datalength - 10) {
+ $check = $check ^ $data; # Check - Typ XOR Adresse XOR bis XOR Check muss 0 ergeben
+ $sum += $data;
+ }
+ }
+ $index += 5;
+ } until ($index >= $datalength);
+ }
+ if ($error != 0) {
+ Log3 $name, 4, "$name: WS2000 Sensortyp $typ Adr $adr - ERROR examination bit";
+ return (0, undef);
+ } elsif ($check != 0) {
+ Log3 $name, 4, "$name: WS2000 Sensortyp $typ Adr $adr - ERROR check XOR";
+ return (0, undef);
+ } else {
+ if ($datalength < 45 || $datalength > 46) { # Summe prüfen, außer Typ 1 ohne Summe
+ $data = oct( "0b".(join "", reverse @bit_msg[$dataindex .. $dataindex + 3]));
+ if ($data != ($sum & 0x0F)) {
+ Log3 $name, 4, "$name: WS2000 Sensortyp $typ Adr $adr - ERROR sum";
+ return (0, undef);
+ }
+ }
+ Log3 $name, 4, "$name: WS2000 Sensortyp $typ Adr $adr - $sensors[$typ]";
+ $datastart += 1; # [x] - 14_CUL_WS
+ @new_bit_msg[4 .. 7] = reverse @bit_msg[$datastart .. $datastart+3]; # [2] Sensortyp
+ @new_bit_msg[0 .. 3] = reverse @bit_msg[$datastart+5 .. $datastart+8]; # [1] Sensoradresse
+ @new_bit_msg[12 .. 15] = reverse @bit_msg[$datastart+10 .. $datastart+13]; # [4] T 0.1, R LSN, Wi 0.1, B 1, Py 1
+ @new_bit_msg[8 .. 11] = reverse @bit_msg[$datastart+15 .. $datastart+18]; # [3] T 1, R MID, Wi 1, B 10, Py 10
+ if ($typ == 0 || $typ == 2) { # Thermo (AS3), Rain (S2000R, WS7000-16)
+ @new_bit_msg[16 .. 19] = reverse @bit_msg[$datastart+20 .. $datastart+23]; # [5] T 10, R MSN
+ } else {
+ @new_bit_msg[20 .. 23] = reverse @bit_msg[$datastart+20 .. $datastart+23]; # [6] T 10, Wi 10, B 100, Py 100
+ @new_bit_msg[16 .. 19] = reverse @bit_msg[$datastart+25 .. $datastart+28]; # [5] H 0.1, Wr 1, B Fak, Py Fak
+ if ($typ == 1 || $typ == 3 || $typ == 4 || $typ == 7) { # Thermo/Hygro, Wind, Thermo/Hygro/Baro, Kombi
+ @new_bit_msg[28 .. 31] = reverse @bit_msg[$datastart+30 .. $datastart+33]; # [8] H 1, Wr 10
+ @new_bit_msg[24 .. 27] = reverse @bit_msg[$datastart+35 .. $datastart+38]; # [7] H 10, Wr 100
+ if ($typ == 4) { # Thermo/Hygro/Baro (S2001I, S2001ID)
+ @new_bit_msg[36 .. 39] = reverse @bit_msg[$datastart+40 .. $datastart+43]; # [10] P 1
+ @new_bit_msg[32 .. 35] = reverse @bit_msg[$datastart+45 .. $datastart+48]; # [9] P 10
+ @new_bit_msg[44 .. 47] = reverse @bit_msg[$datastart+50 .. $datastart+53]; # [12] P 100
+ @new_bit_msg[40 .. 43] = reverse @bit_msg[$datastart+55 .. $datastart+58]; # [11] P Null
+ }
+ }
+ }
+ return (1, @new_bit_msg);
+ }
+
+}
+
+
+sub SIGNALduino_postDemo_WS7053($@) {
+ my ($name, @bit_msg) = @_;
+ my $msg = join("",@bit_msg);
+ my $new_msg ="";
+ my $parity = 0; # Parity even
+ if (length($msg) > 32) { # start not correct
+ $msg = substr($msg,1)
+ }
+ Log3 $name, 4, "$name: WS7053 MSG = $msg";
+ if (substr($msg,0,8) ne "10100000") { # check ident
+ Log3 $name, 3, "$name: WS7053 ERROR - Ident not 1010 0000 - " . substr($msg,0,8);
+ 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, 3, "$name: WS7053 ERROR - Parity not even";
+ return 0, undef;
+ } else {
+ Log3 $name, 5, "$name: WS7053 before: " . 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);
+ # Format from 7053: Bit 0-7 Ident, Bit 8-15 Rolling Code/Parity, Bit 16-27 Temperature (12.3), Bit 28-31 Zero
+ $new_msg = substr($msg,0,28) . substr($msg,16,8) . substr($msg,28,4);
+ # Format for CUL_TX: Bit 0-7 Ident, Bit 8-15 Rolling Code/Parity, Bit 16-27 Temperature (12.3), Bit 28 - 35 Temperature (12), Bit 36-39 Zero
+ Log3 $name, 5, "$name: WS7053 after: " . substr($new_msg,0,4) ." ". substr($new_msg,4,4) ." ". substr($new_msg,8,4) ." ". substr($new_msg,12,4) ." ". substr($new_msg,16,4) ." ". substr($new_msg,20,4) ." ". substr($new_msg,24,4) ." ". substr($new_msg,28,4) ." ". substr($new_msg,32,4) ." ". substr($new_msg,36,4);
+ return (1,split("",$new_msg));
+ }
+ }
+}
+
+
+# manchester method
+
+sub SIGNALduino_MCTFA
+{
+ my ($name,$bitData,$id,$mcbitnum) = @_;
+
+ my $preamble_pos;
+ my $message_end;
+ my $message_length;
+
+ #if ($bitData =~ m/^.?(1){16,24}0101/) {
+ if ($bitData =~ m/(1{10}101)/ )
+ {
+ $preamble_pos=$+[1];
+ Log3 $name, 4, "$name: TFA 30.3208.0 preamble_pos = $preamble_pos";
+ return return (-1," sync not found") if ($preamble_pos <=0);
+ my @messages;
+
+ do
+ {
+ $message_end = index($bitData,"1111111111101",$preamble_pos);
+ if ($message_end < $preamble_pos)
+ {
+ $message_end=length($bitData);
+ }
+ $message_length = ($message_end - $preamble_pos);
+
+ my $part_str=substr($bitData,$preamble_pos,$message_length);
+ $part_str = substr($part_str,0,52) if (length($part_str)) > 52;
+
+ Log3 $name, 4, "$name: TFA message start=$preamble_pos end=$message_end with length".$message_length;
+ Log3 $name, 5, "$name: part $part_str";
+ my $hex=SIGNALduino_b2h($part_str);
+ push (@messages,$hex);
+ Log3 $name, 4, "$name: ".$hex;
+ $preamble_pos=index($bitData,"1101",$message_end)+4;
+ } while ( $message_end < length($bitData) );
+
+ my %seen;
+ my @dupmessages = map { 1==$seen{$_}++ ? $_ : () } @messages;
+
+ if (scalar(@dupmessages) > 0 ) {
+ Log3 $name, 4, "$name: repeated hex ".$dupmessages[0]." found ".$seen{$dupmessages[0]}." times";
+ return (1,$dupmessages[0]);
+ } else {
+ return (-1," no duplicate found");
+ }
+ }
+ return (-1,undef);
+
}
sub SIGNALduino_OSV2()
{
- my ($name,$bitData,$id) = @_;
+ my ($name,$bitData,$id,$mcbitnum) = @_;
my $preamble_pos;
my $message_end;
@@ -3211,26 +4721,66 @@ sub SIGNALduino_OSV2()
sub SIGNALduino_OSV1()
{
- my ($name,$bitData,$rawData) = @_;
+ my ($name,$bitData,$id,$mcbitnum) = @_;
- my $idx=0;
+ 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 $osv1hex ;# ~hex('0x'.$rawData);
- #my $osv1bit = $bitData =~ tr/10/01/r;
- my $osv1bit;
- ($osv1bit = $bitData) =~ tr/10/01/;
- #Log3 $name, 5, "$name: OSV1 protocol converted from ($bitData) to bit: ($osv1bit)" ;
- $osv1hex=sprintf("%02X", length($rawData)*4, $osv1hex).SIGNALduino_b2h($osv1bit);
+
+ 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");
+ } 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 = ($checksum - 0xa) & 0xff;
+ $newBitData .= sprintf("%08b",$checksum); # Byte 8: new Checksum
+ $newBitData .= "00000000"; # Byte 9: immer 0000 0000
-
- Log3 $name, 5, "$name: OSV1 protocol converted to hex: ($osv1hex) with length (".(length($rawData)*4).") bits \n";
+ 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()
{
- my ($name,$bitData,$id) = @_;
+ my ($name,$bitData,$id,$mcbitnum) = @_;
my $debug = AttrVal($name,"debug",0);
if(index($bitData,"1100",16) >= 0) # $rawData =~ m/^A{2,3}/)
@@ -3258,7 +4808,7 @@ sub SIGNALduino_AS()
sub SIGNALduino_Hideki()
{
- my ($name,$bitData,$id) = @_;
+ my ($name,$bitData,$id,$mcbitnum) = @_;
my $debug = AttrVal($name,"debug",0);
Debug "$name: search in $bitData \n" if ($debug);
@@ -3294,13 +4844,13 @@ sub SIGNALduino_Hideki()
return (1,$hidekihex); ## Return only the original bits, include length
}
- return (-1,"");
+ return (-1,"Start pattern (10101110) not found");
}
sub SIGNALduino_Maverick()
{
- my ($name,$bitData,$id) = @_;
+ my ($name,$bitData,$id,$mcbitnum) = @_;
my $debug = AttrVal($name,"debug",0);
@@ -3318,17 +4868,127 @@ sub SIGNALduino_Maverick()
}
}
+sub SIGNALduino_OSPIR()
+{
+ my ($name,$bitData,$id,$mcbitnum) = @_;
+ my $debug = AttrVal($name,"debug",0);
+
+
+ if ($bitData =~ m/^.*(1{14}|0{14}).*/)
+ { # Valid Oregon PIR detected
+ my $header_pos=$+[1];
+
+ Log3 $name, 4, "$name: Oregon PIR protocol detected: header_pos = $header_pos";
+
+ my $hex=SIGNALduino_b2h($bitData);
+
+ return (1,$hex); ## Return the bits unchanged in hex
+ } else {
+ return return (-1," header not found");
+ }
+}
+sub SIGNALduino_MCRAW()
+{
+ my ($name,$bitData,$id,$mcbitnum) = @_;
+ my $debug = AttrVal($name,"debug",0);
+
+
+ my $hex=SIGNALduino_b2h($bitData);
+ return (1,$hex); ## Return the bits unchanged in hex
+}
+
+
+
sub SIGNALduino_SomfyRTS()
{
- my ($name, $bitData, $rawData) = @_;
+ my ($name, $bitData,$id,$mcbitnum) = @_;
#(my $negBits = $bitData) =~ tr/10/01/; # Todo: eventuell auf pack umstellen
+
+ if (defined($mcbitnum)) {
+ Log3 $name, 4, "$name: Somfy bitdata: $bitData ($mcbitnum)";
+ if ($mcbitnum == 57) {
+ $bitData = substr($bitData, 1, 56);
+ Log3 $name, 4, "$name: Somfy bitdata: _$bitData (" . length($bitData) . "). Bit am Anfang entfernt";
+ }
+ }
my $encData = SIGNALduino_b2h($bitData);
#Log3 $name, 4, "$name: Somfy RTS protocol enc: $encData";
return (1, $encData);
}
+# - - - - - - - - - - - -
+#=item SIGNALduino_filterMC()
+#This functons, will act as a filter function. It will decode MU data via Manchester encoding
+#
+# Will return $count of ???, modified $rawData , modified %patternListRaw,
+# =cut
+
+
+sub SIGNALduino_filterMC($$$%)
+{
+
+ ## Warema Implementierung : Todo variabel gestalten
+ my ($name,$id,$rawData,%patternListRaw) = @_;
+ my $debug = AttrVal($name,"debug",0);
+
+ my ($ht, $hasbit, $value) = 0;
+ $value=1 if (!$debug);
+ my @bitData;
+ my @sigData = split "",$rawData;
+
+ foreach my $pulse (@sigData)
+ {
+ next if (!defined($patternListRaw{$pulse}));
+ #Log3 $name, 4, "$name: pulese: ".$patternListRaw{$pulse};
+
+ if (SIGNALduino_inTol($ProtocolListSIGNALduino{$id}{clockabs},abs($patternListRaw{$pulse}),$ProtocolListSIGNALduino{$id}{clockabs}*0.5))
+ {
+ # Short
+ $hasbit=$ht;
+ $ht = $ht ^ 0b00000001;
+ $value='S' if($debug);
+ #Log3 $name, 4, "$name: filter S ";
+ } elsif ( SIGNALduino_inTol($ProtocolListSIGNALduino{$id}{clockabs}*2,abs($patternListRaw{$pulse}),$ProtocolListSIGNALduino{$id}{clockabs}*0.5)) {
+ # Long
+ $hasbit=1;
+ $ht=1;
+ $value='L' if($debug);
+ #Log3 $name, 4, "$name: filter L ";
+ } elsif ( SIGNALduino_inTol($ProtocolListSIGNALduino{$id}{syncabs}+(2*$ProtocolListSIGNALduino{$id}{clockabs}),abs($patternListRaw{$pulse}),$ProtocolListSIGNALduino{$id}{clockabs}*0.5)) {
+ $hasbit=1;
+ $ht=1;
+ $value='L' if($debug);
+ #Log3 $name, 4, "$name: sync L ";
+
+ } else {
+ # No Manchester Data
+ $ht=0;
+ $hasbit=0;
+ #Log3 $name, 4, "$name: filter n ";
+ }
+
+ if ($hasbit && $value) {
+ $value = lc($value) if($debug && $patternListRaw{$pulse} < 0);
+ my $bit=$patternListRaw{$pulse} > 0 ? 1 : 0;
+ #Log3 $name, 5, "$name: adding value: ".$bit;
+
+ push @bitData, $bit ;
+ }
+ }
+
+ my %patternListRawFilter;
+
+ $patternListRawFilter{0} = 0;
+ $patternListRawFilter{1} = $ProtocolListSIGNALduino{$id}{clockabs};
+
+ #Log3 $name, 5, "$name: filterbits: ".@bitData;
+ $rawData = join "", @bitData;
+ return (undef ,$rawData, %patternListRawFilter);
+
+}
+
# - - - - - - - - - - - -
#=item SIGNALduino_filterSign()
#This functons, will act as a filter function. It will remove the sign from the pattern, and compress message and pattern
@@ -3345,7 +5005,7 @@ sub SIGNALduino_filterSign($$$%)
my %buckets;
# Remove Sign
- %patternListRaw = map { $_ => abs($patternListRaw{$_})} keys %patternListRaw; ## remove sing from all
+ %patternListRaw = map { $_ => abs($patternListRaw{$_})} keys %patternListRaw; ## remove sign from all
my $intol=0;
my $cnt=0;
@@ -3503,8 +5163,9 @@ sub SIGNALduino_compPattern($$$%)
Wireless switches
- ITv1 & ITv3/Elro and other brands using pt2263 or arctech protocol--> uses IT.pm
+ ITv1 & ITv3/Elro and other brands using pt2263 or arctech protocol--> uses IT.pm
+ In the ITv1 protocol is used to sent a default ITclock from 250 and it may be necessary in the IT-Modul to define the attribute ITclock
Temperatur / humidity senso
define <name> SIGNALduino <device>