2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-19 00:26:03 +00:00

actiondetect repair, some code cleanup

git-svn-id: https://svn.fhem.de/fhem/trunk@2711 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
martinp876 2013-02-12 19:02:27 +00:00
parent cdaf33575a
commit 25ce6bffab

View File

@ -43,30 +43,33 @@ sub CUL_HM_decodeTime16($);
sub CUL_HM_pushConfig($$$$$$$$);
sub CUL_HM_maticFn($$$$$);
sub CUL_HM_secSince2000();
sub CUL_HM_noDup(@); #return list with no duplicates
sub CUL_HM_noDupInString($);#return string with no duplicates, comma separated
# ----------------modul globals-----------------------
my $respRemoved; # used to control trigger of stach processing
# need to take care that ACK is first
my %culHmDevProps=(
"01" => { st => "AlarmControl", cl => " " }, # by peterp
"12" => { st => "outputUnit", cl => "receiver" }, # Test Pending
"10" => { st => "switch", cl => "receiver" }, # Parse,Set
"20" => { st => "dimmer", cl => "receiver" }, # Parse,Set
"30" => { st => "blindActuator", cl => "receiver" }, # Parse,Set
"39" => { st => "ClimateControl", cl => "sender" },
"40" => { st => "remote", cl => "sender" }, # Parse
"41" => { st => "sensor", cl => "sender" },
"42" => { st => "swi", cl => "sender" }, # e.g. HM-SwI-3-FM
"43" => { st => "pushButton", cl => "sender" },
"58" => { st => "thermostat", cl => "receiver" },
"60" => { st => "KFM100", cl => "sender" }, # Parse,unfinished
"70" => { st => "THSensor", cl => "sender" }, # Parse,unfinished
"80" => { st => "threeStateSensor",cl => "sender" }, # e.g.HM-SEC-RHS
"81" => { st => "motionDetector", cl => "sender" },
"C0" => { st => "keyMatic", cl => "receiver" },
"C1" => { st => "winMatic", cl => "receiver" },
"CD" => { st => "smokeDetector", cl => "receiver" }, # Parse,set unfinished
);
#my %culHmDevProps=(
# "01" => { st => "AlarmControl", cl => " " }, # by peterp
# "12" => { st => "outputUnit", cl => "receiver" }, # Test Pending
# "10" => { st => "switch", cl => "receiver" }, # Parse,Set
# "20" => { st => "dimmer", cl => "receiver" }, # Parse,Set
# "30" => { st => "blindActuator", cl => "receiver" }, # Parse,Set
# "39" => { st => "ClimateControl", cl => "sender" },
# "40" => { st => "remote", cl => "sender" }, # Parse
# "41" => { st => "sensor", cl => "sender" },
# "42" => { st => "swi", cl => "sender" }, # e.g. HM-SwI-3-FM
# "43" => { st => "pushButton", cl => "sender" },
# "58" => { st => "thermostat", cl => "receiver" },
# "60" => { st => "KFM100", cl => "sender" }, # Parse,unfinished
# "70" => { st => "THSensor", cl => "sender" }, # Parse,unfinished
# "80" => { st => "threeStateSensor",cl => "sender" }, # e.g.HM-SEC-RHS
# "81" => { st => "motionDetector", cl => "sender" },
# "C0" => { st => "keyMatic", cl => "receiver" },
# "C1" => { st => "winMatic", cl => "receiver" },
# "CD" => { st => "smokeDetector", cl => "receiver" }, # Parse,set unfinished
#);
# chan supports autocreate of channels for the device
# Syntax <chnName>:<chnNoStart>:<chnNoEnd>
# chn=>{btn:1:3,disp:4,aux:5:7} wil create
@ -141,14 +144,14 @@ my %culHmModel=(
"0044" => {name=>"HM-SEN-EP" ,st=>'sensor' ,cyc=>'' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",},
"0045" => {name=>"HM-SEC-WDS" ,st=>'threeStateSensor' ,cyc=>'28:00' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",},
"0046" => {name=>"HM-SWI-3-FM" ,st=>'swi' ,cyc=>'' ,rxt=>'c' ,lst=>'4' ,chn=>"Sw:1:3",},
"0047" => {name=>"KFM-Sensor" ,st=>'sensor' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",},
"0047" => {name=>"KFM-Sensor" ,st=>'KFM100' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",},
"0048" => {name=>"IS-WDS-TH-OD-S-R3" ,st=>'' ,cyc=>'' ,rxt=>'c:w' ,lst=>'1,3' ,chn=>"",},
"0049" => {name=>"KFM-Display" ,st=>'outputUnit' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",},
"004A" => {name=>"HM-SEC-MDIR" ,st=>'motionDetector' ,cyc=>'00:10' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",},
"004B" => {name=>"HM-Sec-Cen" ,st=>'AlarmControl' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",},
"004C" => {name=>"HM-RC-12-SW" ,st=>'remote' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"Btn:1:12",},
"004D" => {name=>"HM-RC-19-SW" ,st=>'remote' ,cyc=>'' ,rxt=>'c:b' ,lst=>'1,4' ,chn=>"Btn:1:17,Disp:18:18",},
"004E" => {name=>"HM-LC-DDC1-PCB" ,st=>'' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, # door drive controller 1-channel (PCB)
"004E" => {name=>"HM-LC-DDC1-PCB" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, # door drive controller 1-channel (PCB)
"004F" => {name=>"HM-SEN-MDIR-SM" ,st=>'motionDetector' ,cyc=>'' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",},
"0050" => {name=>"HM-SEC-SFA-SM" ,st=>'threeStateSensor' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Siren:1:1,Flash:2:2",},
"0051" => {name=>"HM-LC-SW1-PB-FM" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"",},
@ -160,10 +163,10 @@ my %culHmModel=(
"0058" => {name=>"HM-LC-DIM1T-CV" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",},
"0059" => {name=>"HM-LC-DIM1T-FM" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",},
"005A" => {name=>"HM-LC-DIM2T-SM" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:2",},
"005C" => {name=>"HM-OU-CF-PL" ,st=>'outputUnit' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"Led:1:1,Sound:2:2",},
"005C" => {name=>"HM-OU-CF-PL" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"Led:1:1,Sound:2:2",},
"005D" => {name=>"HM-Sen-MDIR-O" ,st=>'motionDetector' ,cyc=>'00:10' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",},
"005F" => {name=>"HM-SCI-3-FM" ,st=>'threeStateSensor' ,cyc=>'28:00' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"Sw:1:3",},
"0060" => {name=>"HM-PB-4DIS-WM" ,st=>'' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"Btn:1:20",},
"0060" => {name=>"HM-PB-4DIS-WM" ,st=>'pushButton' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"Btn:1:20",},
"0061" => {name=>"HM-LC-SW4-DR" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"Sw:1:4",},
"0062" => {name=>"HM-LC-SW2-DR" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:2",},
"0064" => {name=>"DORMA_atent" ,st=>'' ,cyc=>'' ,rxt=>'c' ,lst=>'1,3' ,chn=>"",}, # DORMA Remote 3 buttons
@ -185,14 +188,14 @@ my %culHmModel=(
"0074" => {name=>"HM-LC-Dim2T-SM" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:2",},
"0075" => {name=>"HM-OU-CFM-PL" ,st=>'outputUnit' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"Led:1:1,Mp3:2:2",},
"0076" => {name=>"HM-Sys-sRP-Pl" ,st=>'repeater' ,cyc=>'' ,rxt=>'' ,lst=>'2' ,chn=>"",}, # repeater
"0078" => {name=>"HM-Dis-TD-T" ,st=>'' ,cyc=>'' ,rxt=>'b' ,lst=>'3' ,chn=>"",}, #
"0078" => {name=>"HM-Dis-TD-T" ,st=>'switch' ,cyc=>'' ,rxt=>'b' ,lst=>'3' ,chn=>"",}, #
"0079" => {name=>"ROTO_ZEL-STG-RM-FWT" ,st=>'' ,cyc=>'' ,rxt=>'c:w' ,lst=>'1,3' ,chn=>"",}, #
"0x7A" => {name=>"ROTO_ZEL-STG-RM-FSA" ,st=>'' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, #
"007A" => {name=>"ROTO_ZEL-STG-RM-FSA" ,st=>'' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, #
"007B" => {name=>"ROTO_ZEL-STG-RM-FEP-230V",st=>'blindActuator' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, # radio-controlled blind actuator 1-channel (flush-mount)
"007C" => {name=>"ROTO_ZEL-STG-RM-FZS" ,st=>'remote' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, # radio-controlled socket adapter switch actuator 1-channel
"007D" => {name=>"ROTO_ZEL-STG-RM-WT-2" ,st=>'remote' ,cyc=>'' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",}, # HM Push Button 2
"007D" => {name=>"ROTO_ZEL-STG-RM-WT-2" ,st=>'pushButton' ,cyc=>'' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",}, # HM Push Button 2
"007E" => {name=>"ROTO_ZEL-STG-RM-DWT-10" ,st=>'remote' ,cyc=>'00:10' ,rxt=>'c' ,lst=>'1,4' ,chn=>"",}, # HM Remote Display 4 buttons Roto
"007F" => {name=>"ROTO_ZEL-STG-RM-FST-UP4" ,st=>'remote' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"",}, # HM Push Button Interface
"007F" => {name=>"ROTO_ZEL-STG-RM-FST-UP4" ,st=>'pushButton' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"",}, # HM Push Button Interface
"0080" => {name=>"ROTO_ZEL-STG-RM-HS-4" ,st=>'remote' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"",}, # HM Remote 4 buttons
"0081" => {name=>"ROTO_ZEL-STG-RM-FDK" ,st=>'threeStateSensor' ,cyc=>'28:00' ,rxt=>'c:w' ,lst=>'1,3' ,chn=>"",}, # HM Rotary Handle Sensor
"0082" => {name=>"Roto_ZEL-STG-RM-FFK" ,st=>'threeStateSensor' ,cyc=>'28:00' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",}, # HM Shutter Contact
@ -205,23 +208,22 @@ my %culHmModel=(
"008A" => {name=>"Schueco_263-133" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, # 1 channel dimmer TPBU (flush mount)
"008B" => {name=>"Schueco_263-130" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, # radio-controlled switch actuator 1-channel (flush-mount)
"008C" => {name=>"Schueco_263-131" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, # radio-controlled switch actuator 1-channel (flush-mount)
"008D" => {name=>"Schueco_263-135" ,st=>'remote' ,cyc=>'' ,rxt=>'c:w' ,lst=>'1,3' ,chn=>"",}, # HM Push Button 2
"008D" => {name=>"Schueco_263-135" ,st=>'pushButton' ,cyc=>'' ,rxt=>'c:w' ,lst=>'1,3' ,chn=>"",}, # HM Push Button 2
"008E" => {name=>"Schueco_263-155" ,st=>'remote' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"",}, # HM Remote Display 4 buttons
"008F" => {name=>"Schueco_263-145" ,st=>'remote' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"",}, # HM Push Button Interface
"008F" => {name=>"Schueco_263-145" ,st=>'pushButton' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"",}, # HM Push Button Interface
"0090" => {name=>"Schueco_263-162" ,st=>'motionDetector' ,cyc=>'00:30' ,rxt=>'c:w' ,lst=>'1,3' ,chn=>"",}, # HM radio-controlled motion detector
"0092" => {name=>"Schueco_263-144" ,st=>'switch' ,cyc=>'' ,rxt=>'c' ,lst=>'4' ,chn=>"",}, # HM Switch Interface 3 switches
"0093" => {name=>"Schueco_263-158" ,st=>'' ,cyc=>'' ,rxt=>'c:w' ,lst=>'' ,chn=>"",}, #
"0093" => {name=>"Schueco_263-158" ,st=>'switch' ,cyc=>'' ,rxt=>'c:w' ,lst=>'' ,chn=>"",}, #
"0094" => {name=>"Schueco_263-157" ,st=>'' ,cyc=>'' ,rxt=>'c:w' ,lst=>'' ,chn=>"",}, #
"00A1" => {name=>"HM-LC-SW1-PL2" ,st=>'' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"",}, #
"00A2" => {name=>"ROTO_ZEL-STG-RM-FZS-2" ,st=>'' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, #radio-controlled socket adapter switch actuator 1-channel
"00A1" => {name=>"HM-LC-SW1-PL2" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"",}, #
"00A2" => {name=>"ROTO_ZEL-STG-RM-FZS-2" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",}, #radio-controlled socket adapter switch actuator 1-channel
"00A3" => {name=>"HM-LC-Dim1L-Pl-2" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",},
"00A4" => {name=>"HM-LC-Dim1T-Pl-2" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"",},
"00A7" => {name=>"HM-Sen-RD-O" ,st=>'' ,cyc=>'' ,rxt=>'' ,lst=>'1:1,4:1' ,chn=>"Rain:1:1,Sw:2:2",},
#263 167 HM Smoke Detector Schueco
);
sub
CUL_HM_Initialize($)
{
sub CUL_HM_Initialize($) {
my ($hash) = @_;
$hash->{Match} = "^A....................";
@ -234,24 +236,25 @@ CUL_HM_Initialize($)
$hash->{AttrFn} = "CUL_HM_Attr";
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:1,0 dummy:1,0 ".
"showtime:1,0 loglevel:0,1,2,3,4,5,6 ".
"hmClass:receiver,sender serialNr firmware devInfo ".
"rawToReadable unit ".
"serialNr firmware ".
"rawToReadable unit ".#"KFM-Sensor" only
"peerIDs ".
"actCycle actStatus autoReadReg:1,0 ".
"expert:0_off,1_on,2_full ".
"hmClass:obsolete devInfo:obsolete ". #unused
".stc .devInfo ".
$readingFnAttributes;
my @modellist;
foreach my $model (keys %culHmModel){
push @modellist,$culHmModel{$model}{name};
}
$hash->{AttrList} .= " model:" .join(",", sort @modellist);
$hash->{AttrList} .= " subType:".join(",", sort
map { $culHmDevProps{$_}{st} } keys %culHmDevProps);
$hash->{AttrList} .= " subType:".join(",",
CUL_HM_noDup(map { $culHmModel{$_}{st} } keys %culHmModel));
CUL_HM_initRegHash();
}
sub
CUL_HM_autoReadConfig($){
sub CUL_HM_autoReadConfig($){
# will trigger a getConfig and statusrequest for each device assigned.
#
while(@{$modules{CUL_HM}{helper}{updtCfgLst}}){
@ -266,8 +269,7 @@ CUL_HM_autoReadConfig($){
}
}
}
sub
CUL_HM_updateConfig($){
sub CUL_HM_updateConfig($){
# this routine is called 5 sec after the last define of a restart
# this gives FHEM sufficient time to fill in attributes
# it will also be called after each manual definition
@ -276,25 +278,28 @@ CUL_HM_updateConfig($){
while(@{$modules{CUL_HM}{helper}{updtCfgLst}}){
my $name = shift(@{$modules{CUL_HM}{helper}{updtCfgLst}});
my $hash = CUL_HM_name2Hash($name);
if (CUL_HM_hash2Id($hash) ne "000000"){# if not action detector
CUL_HM_ID2PeerList($name,"",1); # update peerList out of peerIDs
if ($name ne "ActionDetector"){ # need to start actiondetector?
my $actCycle = AttrVal($name,"actCycle",undef);
CUL_HM_Set($hash,$name,"actiondetect",$actCycle) if ($actCycle);
}
# convert variables, delete obsolete, move to hidden level
$attr{$name}{".devInfo"} = $attr{$name}{devInfo} if ($attr{$name}{devInfo});
delete $attr{$name}{devInfo};
delete $attr{$name}{hmClass};
# add default web-commands
my $webCmd;
my $st = AttrVal(($hash->{device}?$hash->{device}:$name), "subType", "");
$webCmd = AttrVal($name,"webCmd","");
if (!$webCmd){
if((length (CUL_HM_hash2Id($hash)) == 6)&&
$hash->{channel_01} &&
$st ne "thermostat" ){$webCmd="getConfig";
}elsif($st eq "blindActuator"){$webCmd="on:off:stop:statusRequest";
}elsif($st eq "dimmer" ){$webCmd="on:off:toggle:statusRequest";
}elsif($st eq "switch" ){$webCmd="on:off:toggle:statusRequest";
}elsif($st eq "blindActuator"){$webCmd="toggle:on:off:stop:statusRequest";
}elsif($st eq "dimmer" ){$webCmd="toggle:on:off:statusRequest";
}elsif($st eq "switch" ){$webCmd="toggle:on:off:statusRequest";
}elsif($st eq "virtual" ){$webCmd="press short:press long";
}elsif($st eq "smokeDetector"){$webCmd="test:alarmOn:alarmOff";
}elsif($st eq "keyMatic" ){$webCmd="lock:inhibit on:inhibit off";
@ -311,7 +316,6 @@ CUL_HM_updateConfig($){
}
}
}
#eventMap on:auf off:zu
$attr{$name}{webCmd} = $webCmd if ($webCmd);
push @getConfList,$name if (1 == AttrVal($name,"autoReadReg","0"));
}
@ -319,41 +323,37 @@ CUL_HM_updateConfig($){
CUL_HM_autoReadConfig("updateConfig");
}
#############################
sub
CUL_HM_Define($$)
{
sub CUL_HM_Define($$) {
my ($hash, $def) = @_;
my @a = split("[ \t][ \t]*", $def);
my $name = $hash->{NAME};
return "wrong syntax: define <name> CUL_HM 6-digit-hex-code [Raw-Message]"
if(!(int(@a)==3 || int(@a)==4) || $a[2] !~ m/^[A-F0-9]{6,8}$/i);
my $HMid = uc($a[2]);
return "wrong syntax: define <name> CUL_HM 6-digit-hex-code [Raw-Message]"
if(!(int(@a)==3 || int(@a)==4) || $HMid !~ m/^[A-F0-9]{6,8}$/i);
return "HMid DEF already used by " . CUL_HM_id2Name($HMid)
if ($modules{CUL_HM}{defptr}{$HMid});
if(length($a[2]) == 8) {# define a channel
my $devHmId = uc(substr($a[2], 0, 6));
my $chn = substr($a[2], 6, 2);
my $name = $hash->{NAME};
if(length($HMid) == 8) {# define a channel
my $devHmId = substr($HMid, 0, 6);
my $chn = substr($HMid, 6, 2);
my $devHash = $modules{CUL_HM}{defptr}{$devHmId};
return "please define a device with hmId:".$devHmId." first" if(!$devHash);
$modules{CUL_HM}{defptr}{$HMid} = $hash;
AssignIoPort($hash);
#AssignIoPort($hash);#General - remove IOport from channel
my $devName = $devHash->{NAME};
$hash->{device} = $devName;
$hash->{chanNo} = $chn;
$attr{$name}{model} = $attr{$devName}{model} if ($attr{$devName}{model});
$devHash->{"channel_$chn"} = $name;
$hash->{device} = $devName; #readable ref to device name
$hash->{chanNo} = $chn; #readable ref to Channel
$devHash->{"channel_$chn"} = $name; #reference in device as well
$attr{$name}{model} = AttrVal($devName, "model", undef);
}
else{# define a device
$modules{CUL_HM}{defptr}{$HMid} = $hash;
AssignIoPort($hash);
}
$modules{CUL_HM}{defptr}{$HMid} = $hash;
#- - - - create auto-update - - - - - -
CUL_HM_ActGetCreateHash() if($HMid eq '000000');#startTimer
if(int(@a) == 4) {
$hash->{DEF} = $a[2];
CUL_HM_Parse($hash, $a[3]);
}
$hash->{DEF} = $HMid;
CUL_HM_Parse($hash, $a[3]) if(int(@a) == 4);
RemoveInternalTimer("updateConfig");
InternalTimer(gettimeofday()+5,"CUL_HM_updateConfig", "updateConfig", 0);
@ -362,13 +362,10 @@ CUL_HM_Define($$)
$modules{CUL_HM}{helper}{updtCfgLst} = \@arr;
}
push(@{$modules{CUL_HM}{helper}{updtCfgLst}}, $name);
return undef;
}
#############################
sub
CUL_HM_Undef($$)
{
sub CUL_HM_Undef($$) {
my ($hash, $name) = @_;
my $devName = $hash->{device};
my $HMid = $hash->{DEF};
@ -387,17 +384,15 @@ CUL_HM_Undef($$)
return undef;
}
#############################
sub
CUL_HM_Rename($$$)
{
sub CUL_HM_Rename($$$) {
my ($name, $oldName) = @_;
my $HMid = CUL_HM_name2Id($name);
my $hash = CUL_HM_name2Hash($name);
if (length($HMid) == 8){# we are channel, inform the device
$hash->{chanNo} = substr($HMid,6,2);
my $device = $hash->{device}?$hash->{device}:"";
my $devHash = CUL_HM_name2Hash($device);
$devHash->{"channel_".$hash->{chanNo}} = $name if ($device);
my $devHash = CUL_HM_id2Hash(substr($HMid,0,6));
$hash->{device} = CUL_HM_hash2Name($devHash);
$devHash->{"channel_".$hash->{chanNo}} = $name;
}
else{# we are a device - inform channels if exist
for (my$chn = 1; $chn <25;$chn++){
@ -409,9 +404,7 @@ CUL_HM_Rename($$$)
return;
}
#############################
sub
CUL_HM_Parse($$)
{
sub CUL_HM_Parse($$) {
my ($iohash, $msg) = @_;
my $id = CUL_HM_Id($iohash);
# Msg format: Allnnffttssssssddddddpp...
@ -437,18 +430,12 @@ CUL_HM_Parse($$)
if(!$shash) { # Unknown source
# Generate an UNKNOWN event for pairing requests, ignore everything else
if($msgType eq "00") {
my $sname = "CUL_HM_$src";
# prefer subType over model to make autocreate easier
# model names are quite cryptic anyway
my $model = substr($p, 2, 4);
my $stc = substr($p, 26, 2); # subTypeCode
if($culHmDevProps{$stc}) {
$sname = "CUL_HM_".$culHmDevProps{$stc}{st} . "_" . $src;
}
elsif($culHmModel{$model}{name}) {
$sname = "CUL_HM_".$culHmModel{$model}{name} . "_" . $src;
$model = $culHmModel{$model}{name} ?
$culHmModel{$model}{name} :
"ID_".$model;
my $sname = "CUL_HM_".$model."_$src";
$sname =~ s/-/_/g;
}
Log 3, "CUL_HM Unknown device $sname, please define it";
return "UNDEFINED $sname CUL_HM $src $msg";
}
@ -757,7 +744,6 @@ CUL_HM_Parse($$)
}
}
elsif($st eq "KFM100" && $model eq "KFM-Sensor") { ##########################
if($p =~ m/.14(.)0200(..)(..)(..)/) {# todo very risky - no start...
my ($k_cnt, $k_v1, $k_v2, $k_v3) = ($1,$2,$3,$4);
my $v = 128-hex($k_v2); # FIXME: calibrate
@ -786,7 +772,6 @@ CUL_HM_Parse($$)
push @event, "state:$v";
}
}
}
elsif($st eq "switch" || ####################################################
$st eq "dimmer" ||
@ -1152,8 +1137,8 @@ CUL_HM_Parse($$)
$error = 'motor aborted' if ($stErr == 2);
$error = 'clutch failure' if ($stErr == 1);
$error = 'none' if ($stErr == 0);
my %dir = (0=>"none",1=>"up",2=>"down",3=>"undef");
push @event, "unknown:40" if($err&0x40);
push @event, "battery:" .(($err&0x80) ? "low":"ok");
push @event, "uncertain:" .(($err&0x30) ? "yes":"no");
@ -1531,20 +1516,17 @@ my %culHmRegType = (
ActionType =>1,OnTimeMode =>1,OffTimeMode =>1,
lgMultiExec =>1,
},
winMatic=>{
signal =>1,signalTone =>1,keypressSignal =>1,
},
keyMatic=>{
signal =>1,signalTone =>1,keypressSignal =>1,
winMatic =>{signal =>1,signalTone =>1,keypressSignal =>1},
keyMatic =>{signal =>1,signalTone =>1,keypressSignal =>1,
holdTime =>1,holdPWM =>1,setupDir =>1,setupPosition =>1,
angelOpen =>1,angelMax =>1,angelLocked =>1,
ledFlashUnlocked=>1,ledFlashLocked =>1,
CtValLo =>1,CtValHi =>1,
CtOn =>1,CtOff =>1,
KeyJtOn =>1,KeyJtOff =>1,
OnTime =>1,
},
motionDetector=>{
evtFltrPeriod =>1,evtFltrNum =>1,minInterval =>1,
motionDetector =>{evtFltrPeriod =>1,evtFltrNum =>1,minInterval =>1,
captInInterval=>1,brightFilter =>1,ledOnTime =>1,
},
);
@ -1569,11 +1551,11 @@ my %culHmRegModel = (
"KS550" =>{stormUpThresh =>1,stormLowThresh =>1},
"HM-OU-CFM-PL" =>{localResetDis =>1,
OnTime =>1,OffTime =>1,OnDly =>1,OffDly =>1,
OnTimeMode =>1,OffTimeMode =>1,
SwJtOn =>1,SwJtOff =>1,SwJtDlyOn =>1,SwJtDlyOff =>1,
CtValLo =>1,CtValHi =>1,
CtOn =>1,CtDlyOn =>1,CtOff =>1,CtDlyOff =>1,
OnTimeMode =>1,OffTimeMode =>1,
ActType =>1,ActNum =>1},
ActType =>1,ActNum =>1,lgMultiExec =>1},
"HM-SEC-MDIR" =>{ sabotageMsg =>1,},
"HM-CC-TC" =>{backlOnTime =>1,backlOnMode =>1,btnLock =>1},
"HM-CC-SCD" =>{peerNeedsBurst =>1,expectAES =>1,
@ -1601,8 +1583,7 @@ my %culHmRegModel = (
"HM-Sys-sRP-Pl" =>{compMode =>1,},
);
my %culHmRegChan = (# if channelspecific then enter them here
"HM-CC-TC02" => {
dispTempHum =>1,dispTempInfo =>1,dispTempUnit =>1,mdTempReg =>1,
"HM-CC-TC02" =>{dispTempHum =>1,dispTempInfo =>1,dispTempUnit =>1,mdTempReg =>1,
mdTempValve =>1,tempComfort =>1,tempLower =>1,partyEndDay =>1,
partyEndMin =>1,partyEndHr =>1,tempParty =>1,decalDay =>1,
decalHr =>1,decalMin =>1,
@ -1631,9 +1612,7 @@ my %culHmRegChan = (# if channelspecific then enter them here
my %fltCvT = (0.1=>3.1,1=>31,5=>155,10=>310,60=>1860,300=>9300,
600=>18600,3600=>111600);
#############################
sub
CUL_HM_Attr($$$)
{
sub CUL_HM_Attr($$$) {
my ($cmd,$name, $attrName,$attrVal) = @_;
my @hashL;
if ($attrName eq "expert"){
@ -1690,10 +1669,7 @@ CUL_HM_Attr($$$)
}
return;
}
sub
CUL_HM_initRegHash()
{ #duplicate short and long press register
sub CUL_HM_initRegHash() { #duplicate short and long press register
foreach my $reg (keys %culHmRegDefShLg){ #update register list
%{$culHmRegDefine{"sh".$reg}} = %{$culHmRegDefShLg{$reg}};
%{$culHmRegDefine{"lg".$reg}} = %{$culHmRegDefShLg{$reg}};
@ -1727,10 +1703,7 @@ CUL_HM_initRegHash()
}
}
}
sub
CUL_HM_fltCvT($) # float -> config time
{
sub CUL_HM_fltCvT($) { # float -> config time
my ($inValue) = @_;
my $exp = 0;
my $div2;
@ -1741,9 +1714,7 @@ CUL_HM_fltCvT($) # float -> config time
}
return ($exp << 5)+int($inValue/$div2);
}
sub
CUL_HM_CvTflt($) # config time -> float
{
sub CUL_HM_CvTflt($) { # config time -> float
my ($inValue) = @_;
return ($inValue & 0x1f)*((sort {$a <=> $b} keys(%fltCvT))[$inValue >> 5]);
}
@ -1757,17 +1728,12 @@ my %culHmGlobalGets = (
saveConfig => "<filename>",
);
my %culHmSubTypeGets = (
none4Type =>
{ "test"=>"" },
none4Type =>{ "test"=>"" },
);
my %culHmModelGets = (
none4Mod=>
{ "none" => "",
},
none4Mod =>{ "none"=>"" },
);
sub
CUL_HM_TCtempReadings($)
{
sub CUL_HM_TCtempReadings($) {
my ($hash)=@_;
my $name = $hash->{NAME};
my $regLN = ((CUL_HM_getExpertMode($hash) eq "2")?"":".")."RegL_";
@ -1807,9 +1773,7 @@ CUL_HM_TCtempReadings($)
CUL_HM_UpdtReadBulk($hash,1,@changedRead) if (@changedRead);
return $setting;
}
sub
CUL_HM_repReadings($)
{
sub CUL_HM_repReadings($) {
my ($hash)=@_;
my $name = $hash->{NAME};
my $regLN = ((CUL_HM_getExpertMode($hash) eq "2")?"":".")."RegL_";
@ -1831,9 +1795,7 @@ CUL_HM_repReadings($)
return $ret;
}
###################################
sub
CUL_HM_Get($@)
{
sub CUL_HM_Get($@) {
my ($hash, @a) = @_;
return "no get value specified" if(@a < 2);
@ -1850,7 +1812,6 @@ CUL_HM_Get($@)
my $chn = ($isChannel)?substr($dst,6,2):"01";
$dst = substr($dst,0,6);
my $devHash = CUL_HM_getDeviceHash($hash);
my $h = $culHmGlobalGets{$cmd};
$h = $culHmSubTypeGets{$st}{$cmd} if(!defined($h) && $culHmSubTypeGets{$st});
$h = $culHmModelGets{$md}{$cmd} if(!defined($h) && $culHmModelGets{$md});
@ -1870,7 +1831,8 @@ CUL_HM_Get($@)
} elsif($h !~ m/\.\.\./ && @h != @a-2) {
return "$cmd requires parameter: $h";
}
my $id = CUL_HM_Id($hash->{IODev});
my $devHash = CUL_HM_getDeviceHash($hash);
my $id = CUL_HM_IOid($hash);
#----------- now start processing --------------
if($cmd eq "param") { ######################################################
@ -1917,7 +1879,7 @@ CUL_HM_Get($@)
if ($regVal ne 'invalid');
}
}
my $addInfo = ""; #todo - find a generic way to handle special devices
my $addInfo = "";
$addInfo = CUL_HM_TCtempReadings($hash)
if ($md eq "HM-CC-TC" && $chn eq "02");
@ -2123,9 +2085,7 @@ my %culHmChanSets = (
);
##############################################
sub
CUL_HM_getMId($)
{#in: hash(chn or dev) out:model key (key for %culHmModel).
sub CUL_HM_getMId($) {#in: hash(chn or dev) out:model key (key for %culHmModel).
# Will store result in device helper
my ($hash) = @_;
$hash = CUL_HM_getDeviceHash($hash);
@ -2142,9 +2102,7 @@ CUL_HM_getMId($)
return $mId;
}
##############################################
sub
CUL_HM_getRxType($)
{ #in:hash(chn or dev) out:binary coded Rx type
sub CUL_HM_getRxType($) { #in:hash(chn or dev) out:binary coded Rx type
# Will store result in device helper
my ($hash) = @_;
$hash = CUL_HM_getDeviceHash($hash);
@ -2165,17 +2123,12 @@ CUL_HM_getRxType($)
return $rxtEntity;
}
##############################################
sub
CUL_HM_getFlag($)
{#msgFlag set to 'A0' for normal and 'B0' for burst devices
sub CUL_HM_getFlag($) {#msgFlag set to 'A0' for normal and 'B0' for burst devices
# currently not supported is the wakeupflag since it is hardly used
my ($hash) = @_;
return (CUL_HM_getRxType($hash) & 0x02)?"B0":"A0"; #set burst flag
}
sub
CUL_HM_Set($@)
{
sub CUL_HM_Set($@) {
my ($hash, @a) = @_;
my ($ret, $tval, $rval); #added rval for ramptime by unimatrix
@ -2185,7 +2138,6 @@ CUL_HM_Set($@)
my $devName = $hash->{device}?$hash->{device}:$name;
my $st = AttrVal($devName, "subType", "");
my $md = AttrVal($devName, "model" , "");
my $class = AttrVal($devName, "hmClass", "");#relevant is the device
my $rxType = CUL_HM_getRxType($hash);
my $flag = CUL_HM_getFlag($hash); #set burst flag
@ -2194,7 +2146,6 @@ CUL_HM_Set($@)
my $isChannel = (length($dst) == 8)?"true":"";
my $chn = ($isChannel)?substr($dst,6,2):"01";
$dst = substr($dst,0,6);
my $devHash = CUL_HM_getDeviceHash($hash);
my $mdCh = $md.($isChannel?$chn:"00"); # chan specific commands?
my $h = $culHmGlobalSets{$cmd} if($st ne "virtual");
@ -2237,7 +2188,8 @@ CUL_HM_Set($@)
return "$cmd requires parameter: $h";
}
my $id = CUL_HM_Id($hash->{IODev});
my $devHash = CUL_HM_getDeviceHash($hash);
my $id = CUL_HM_IOid($hash);
my $state = "set_".join(" ", @a[1..(int(@a)-1)]);
if($cmd eq "raw") { ########################################################
@ -2274,9 +2226,6 @@ CUL_HM_Set($@)
}
elsif($cmd eq "pair") { #####################################################
$state = "";
return "pair is not enabled for this type of device, ".
"use set <IODev> hmPairForSec"
if($class eq "sender");
my $serialNr = AttrVal($name, "serialNr", undef);
return "serialNr is not set" if(!$serialNr);
CUL_HM_PushCmdStack($hash,"++A401".$id."000000010A".unpack("H*",$serialNr));
@ -2831,7 +2780,6 @@ CUL_HM_Set($@)
return $name." already defines as ".$attr{$name}{subType}
if ($attr{$name}{subType} && $attr{$name}{subType} ne "virtual");
$attr{$name}{subType} = "virtual";
$attr{$name}{hmClass} = "sender";
$attr{$name}{model} = "virtual_".$maxBtnNo;
my $devId = $hash->{DEF};
for (my $btn=1;$btn <= $maxBtnNo;$btn++){
@ -2966,9 +2914,7 @@ CUL_HM_Set($@)
###################################
my $updtValveCnt = 0;
sub
CUL_HM_valvePosUpdt(@)
{# update valve position periodically to please valve
sub CUL_HM_valvePosUpdt(@) {# update valve position periodically to please valve
my($in ) = @_;
my(undef,$vId) = split(':',$in);
my $hash = CUL_HM_id2Hash($vId);
@ -2994,20 +2940,19 @@ CUL_HM_valvePosUpdt(@)
CUL_HM_ProcessCmdStack($hash);
InternalTimer(gettimeofday()+$nextTimer,"CUL_HM_valvePosUpdt","valvePos:$vId",0);
}
sub
CUL_HM_infoUpdtDevData($$$){
sub CUL_HM_infoUpdtDevData($$$) {#autoread config
my($name,$hash,$p) = @_;
my($fw,$mId,$serNo,$stc,$devInfo) = ($1,$2,$3,$4,$5)
if($p =~ m/(..)(.{4})(.{20})(.{2})(.*)/);
my $model = $culHmModel{$mId}{name} ? $culHmModel{$mId}{name}:"unknown";
$attr{$name}{model} = $model;
my $dp = $culHmDevProps{$stc};
$attr{$name}{subType} = $dp ? $dp->{st} : "unknown";
$attr{$name}{hmClass} = $dp ? $dp->{cl} : "unknown";
$attr{$name}{subType} = $culHmModel{$mId}{st};
$attr{$name}{serialNr} = pack('H*',$serNo);
#expert level attributes
$attr{$name}{firmware} =
sprintf("%d.%d", hex(substr($p,0,1)),hex(substr($p,1,1)));
$attr{$name}{devInfo} = $devInfo;
$attr{$name}{".devInfo"} = $devInfo;
$attr{$name}{".stc"} = $stc;
delete $hash->{helper}{rxType};
CUL_HM_getRxType($hash); #will update rxType
@ -3036,17 +2981,13 @@ CUL_HM_infoUpdtDevData($$$){
}
}
sub #---------------------------------
CUL_HM_infoUpdtChanData(@)
{# delay this to ensure the device is already available
sub CUL_HM_infoUpdtChanData(@) {# verify attributes after reboot
my($in ) = @_;
my($chnName,$chnId,$model ) = split(',',$in);
DoTrigger("global", 'UNDEFINED '.$chnName.' CUL_HM '.$chnId);
$attr{CUL_HM_id2Name($chnId)}{model} = $model;
}
sub #---------------------------------
CUL_HM_Pair(@)
{
sub CUL_HM_Pair(@) {
my ($name, $hash,$cmd,$src,$dst,$p) = @_;
my $iohash = $hash->{IODev};
my $id = CUL_HM_Id($iohash);
@ -3078,7 +3019,6 @@ CUL_HM_Pair(@)
$idstr =~ s/(..)/sprintf("%02X%s",$s++,$1)/ge;
CUL_HM_pushConfig($hash, $id, $src,0,0,0,0, "0201$idstr");
CUL_HM_ProcessCmdStack($hash); # start processing immediately
return "";
}
sub CUL_HM_getConfig($$$$$){
@ -3215,13 +3155,11 @@ sub CUL_HM_responseSetup($$) {#store all we need to handle the response
}
if (($msgFlag & 0x20) && ($dst ne '000000')){
my $iohash = $hash->{IODev};
$hash->{helper}{respWait}{cmd} = $cmd;
$hash->{helper}{respWait}{msgId} = $msgId; #msgId we wait to ack
$hash->{helper}{respWait}{reSent} = 1;
my $off = 2;
#$off += 0.15*int(@{$iohash->{QUEUE}}) if($iohash->{QUEUE});
InternalTimer(gettimeofday()+$off, "CUL_HM_Resend", $hash, 0);
}
}
@ -3385,9 +3323,7 @@ sub CUL_HM_ID2PeerList ($$$) {
readingsSingleUpdate($hash,"peerList",$peerNames,0);
}
################### Conversions ################
sub #---------------------------------
CUL_HM_getExpertMode($)
{ # get expert level for the entity.
sub CUL_HM_getExpertMode($) { # get expert level for the entity.
# if expert level is not set try to get it for device
my ($hash) = @_;
my $expLvl = AttrVal($hash->{NAME},"expert","");
@ -3396,9 +3332,7 @@ CUL_HM_getExpertMode($)
if ($expLvl eq "");
return substr($expLvl,0,1);
}
sub #---------------------------------
CUL_HM_getAssChnIds($)
{ # will return the list of assotiated channel of a device
sub CUL_HM_getAssChnIds($) { # will return the list of assotiated channel of a device
# if it is a channel only return itself
# if device and no channel
my ($name) = @_;
@ -3415,35 +3349,32 @@ CUL_HM_getAssChnIds($)
push @chnIdList,$dId if (length($dId) == 8);
return sort(@chnIdList);
}
sub #---------------------------------
CUL_HM_Id($)
{#in ioHash out ioHMid
sub CUL_HM_Id($) {#in: ioHash out: ioHMid
my ($io) = @_;
my $fhtid = defined($io->{FHTID}) ? $io->{FHTID} : "0000";
return AttrVal($io->{NAME}, "hmId", "F1$fhtid");
}
sub #---------------------------------
CUL_HM_hash2Id($)
{# in: id, out:hash
sub CUL_HM_IOid($) {#in: hash out: id of IO device
my ($hash) = @_;
my $dHash = CUL_HM_getDeviceHash($hash);
my $ioHash = $dHash->{IODev};
my $fhtid = defined($ioHash->{FHTID}) ? $ioHash->{FHTID} : "0000";
return AttrVal($ioHash->{NAME}, "hmId", "F1$fhtid");
}
sub CUL_HM_hash2Id($) {#in: id, out:hash
my ($hash) = @_;
return $hash->{DEF};
}
sub #---------------------------------
CUL_HM_id2Hash($)
{# in: id, out:hash
sub CUL_HM_id2Hash($) {#in: id, out:hash
my ($id) = @_;
return $modules{CUL_HM}{defptr}{$id} if ($modules{CUL_HM}{defptr}{$id});
return $modules{CUL_HM}{defptr}{substr($id,0,6)}; # could be chn 01 of dev
}
sub #---------------------------------
CUL_HM_name2Hash($)
{# in: name, out:hash
sub CUL_HM_name2Hash($) {#in: name, out:hash
my ($name) = @_;
return $defs{$name};
}
sub #---------------------------------
CUL_HM_name2Id(@)
{ # in: name or HMid ==>out: HMid, "" if no match
sub CUL_HM_name2Id(@) { #in: name or HMid ==>out: HMid, "" if no match
my ($name,$idHash) = @_;
my $hash = $defs{$name};
return $hash->{DEF} if ($hash); #name is entity
@ -3454,9 +3385,7 @@ CUL_HM_name2Id(@)
if($idHash && ($name =~ m/self(.*)/));
return "";
}
sub #---------------------------------
CUL_HM_peerChId($$$)
{# peer Channel name from/for user entry. <IDorName> <deviceID> <ioID>
sub CUL_HM_peerChId($$$) {# peer Channel name from/for user entry. <IDorName> <deviceID> <ioID>
my($pId,$dId,$iId)=@_;
my $pSc = substr($pId,0,4); #helper for shortcut spread
return $dId.sprintf("%02X",'0'.substr($pId,4)) if ($pSc eq 'self');
@ -3466,18 +3395,14 @@ CUL_HM_peerChId($$$)
$repID .= '01' if (length( $repID) == 6);# add default 01 if this is a device
return $repID;
}
sub #---------------------------------
CUL_HM_peerChName($$$)
{# peer Channel ID to user entry. <peerChId> <deviceID> <ioID>
sub CUL_HM_peerChName($$$) {# peer Channel ID to user entry. <peerChId> <deviceID> <ioID>
my($pId,$dId,$iId)=@_;
my($pDev,$pChn) = ($1,$2) if ($pId =~ m/(......)(..)/);
return 'self'.$pChn if ($pDev eq $dId);
return 'fhem'.$pChn if ($pDev eq $iId);
return CUL_HM_id2Name($pId);
}
sub #---------------------------------
CUL_HM_id2Name($)
{ # in: name or HMid out: name
sub CUL_HM_id2Name($) { #in: name or HMid out: name
my ($p) = @_;
return $p if($attr{$p}); # is already name
return $p if ($p =~ m/_chn:/);
@ -3496,9 +3421,7 @@ CUL_HM_id2Name($)
if( $chnId && $defPtr->{$devId});#device, add chn
return $devId. ($chn ? ("_chn:".$chn):""); #not defined, return ID only
}
sub #---------------------------------
CUL_HM_getDeviceHash($)
{#in: hash (chn or dev) out: hash of the device (used e.g. for send messages)
sub CUL_HM_getDeviceHash($) {#in: hash (chn or dev) out: hash of the device (used e.g. for send messages)
my ($hash) = @_;
return $hash if(!$hash->{DEF});
my $devHash = $modules{CUL_HM}{defptr}{substr($hash->{DEF},0,6)};
@ -3644,7 +3567,6 @@ my @culHmCmdFlags = ("WAKEUP", "WAKEMEUP", "CFG", "Bit3",
#CFG 0x04: Device in Config mode
#WAKEMEUP 0x02: awake - hurry up to send messages
#WAKEUP 0x01: send initially to keep the device awake
sub CUL_HM_DumpProtocol($$@) {
my ($prefix, $iohash, $len,$cnt,$msgFlags,$msgType,$src,$dst,$p) = @_;
my $iname = $iohash->{NAME};
@ -3707,7 +3629,7 @@ sub CUL_HM_parseCommon(@){
((hex($msgFlag) & 0xA2) == 0x82) &&
(CUL_HM_getRxType($shash) & 0x08)){ #wakeup #####
#send wakeup and process command stack
CUL_HM_SndCmd($shash, '++A112'.CUL_HM_Id($shash->{IODev}).$src);
CUL_HM_SndCmd($shash, '++A112'.CUL_HM_IOid($shash).$src);
CUL_HM_ProcessCmdStack($shash);
}
@ -3749,7 +3671,7 @@ sub CUL_HM_parseCommon(@){
}
readingsSingleUpdate($chnhash,"CommandAccepted",$success,1);
CUL_HM_ProcessCmdStack($shash)
if($dhash->{DEF} && (CUL_HM_Id($shash->{IODev}) eq $dhash->{DEF}));
if($dhash->{DEF} && (CUL_HM_IOid($shash) eq $dhash->{DEF}));
return $reply;
}
elsif($msgType eq "00"){
@ -3778,7 +3700,7 @@ sub CUL_HM_parseCommon(@){
my $reqPeer = $chnhash->{helper}{getCfgList};
if ($reqPeer){
my $flag = CUL_HM_getFlag($shash);
my $id = CUL_HM_Id($shash->{IODev});
my $id = CUL_HM_IOid($shash);
my $listNo = "0".$chnhash->{helper}{getCfgListNo};
my @peerID = split(",", AttrVal($chnNname,"peerIDs",""));
foreach my $peer (@peerID){
@ -3891,7 +3813,7 @@ sub CUL_HM_parseCommon(@){
}
elsif($msgType eq "70"){ #Time to trigger TC##################
#send wakeup and process command stack
# CUL_HM_SndCmd($shash, '++A112'.CUL_HM_Id($shash->{IODev}).$src);
# CUL_HM_SndCmd($shash, '++A112'.CUL_HM_IOid($shash).$src);
# CUL_HM_ProcessCmdStack($shash);
}
return "";
@ -3903,7 +3825,7 @@ sub CUL_HM_getRegFromStore($$$$) {#read a register from backup data
my ($size,$pos,$conversion,$factor,$unit) = (8,0,"",1,""); # default
my $addr = $regName;
my $dId = substr(CUL_HM_name2Id($name),0,6);#id of device
my $iId = CUL_HM_Id($hash->{IODev}); #id of IO device
my $iId = CUL_HM_IOid($hash); #id of IO device
my $reg = $culHmRegDefine{$regName};
if ($reg) { # get the register's information
$addr = $reg->{a};
@ -3998,7 +3920,6 @@ sub CUL_HM_updtRegDisp($$$) {
CUL_HM_UpdtReadBulk($hash,1,@changedRead) if (@changedRead);
}
#############################
my @culHmTimes8 = ( 0.1, 1, 5, 10, 60, 300, 600, 3600 );
sub CUL_HM_encodeTime8($) {
@ -4116,7 +4037,6 @@ sub CUL_HM_secSince2000() {
- 7200; # HM Special
return $t;
}
############### Activity supervision section ################
# verify that devices are seen in a certain period of time
# It will generate events if no message is seen sourced by the device during
@ -4181,10 +4101,8 @@ sub CUL_HM_ActAdd($$) {# add an HMid to list for activity supervision
CUL_HM_setAttrIfCh($devName,"actStatus","unknown","Activity");
my $actHash = CUL_HM_ActGetCreateHash();
my $actName = $actHash->{NAME}; # could have been renamed
my $peerIDs = AttrVal($actName,"peerIDs","");
$peerIDs .= $devId."," if($peerIDs !~ m/$devId,/);#add if not in
$attr{$actName}{peerIDs} = $peerIDs;
$attr{$actName}{peerIDs} = CUL_HM_noDupInString($peerIDs.",$devId");
my $tn = TimeNow();
$actHash->{helper}{$devId}{start} = $tn;
readingsSingleUpdate($actHash,"status_".$devName,"unknown",1);
@ -4193,7 +4111,6 @@ sub CUL_HM_ActAdd($$) {# add an HMid to list for activity supervision
}
sub CUL_HM_ActDel($) {# delete HMid for activity supervision
my ($devId) = @_;
return $devId." is not an HM device - action detection cannot be added"
if (length($devId) != 6);
@ -4201,13 +4118,14 @@ sub CUL_HM_ActDel($) {# delete HMid for activity supervision
delete ($attr{$devName}{actCycle});
CUL_HM_setAttrIfCh($devName,"actStatus","deleted","Activity");#post trigger
delete ($attr{$devName}{actStatus});
my $acthash = CUL_HM_ActGetCreateHash();
my $actName = $acthash->{NAME};
delete ($acthash->{helper}{$devId});
$attr{$actName}{peerIDs} = "" if (!defined($attr{$actName}{peerIDs}));
$attr{$actName}{peerIDs} =~ s/$devId,//g;
my $peerIDs = AttrVal($actName,"peerIDs","");
$peerIDs =~ s/$devId//g;
$attr{$actName}{peerIDs} = CUL_HM_noDupInString($peerIDs);
Log GetLogLevel($actName,3),"Device ".$devName." removed from ActionDetector";
}
sub CUL_HM_ActCheck() {# perform supervision
@ -4215,48 +4133,59 @@ sub CUL_HM_ActCheck() {# perform supervision
my $tod = int(gettimeofday());
my $actName = $actHash->{NAME};
my $peerIDs = AttrVal($actName,"peerIDs","none");
# delete ($actHash->{READINGS}); #cleansweep
delete ($actHash->{READINGS}); #cleansweep
my @event;
my ($noUnkn,$noAlive,$noDead,$noOff) =(0,0,0,0);
foreach my $devId (split(",",$peerIDs)){
$noUnkn++;
next if (!$devId);
my $devName = CUL_HM_id2Name($devId);
if(!$devName || !defined($attr{$devName}{actCycle})){
CUL_HM_ActDel($devId);
next;
}
$noUnkn++;
my $devHash = CUL_HM_name2Hash($devName);
my $rdName = "status_".$devName;
my $state;
my $oldState = AttrVal($devName,"actStatus","unset");
my (undef,$tSec)=CUL_HM_time2sec($attr{$devName}{actCycle});
if ($tSec == 0){# detection switched off
$noOff++;$noUnkn--;
$state = "switchedOff";
}
else{
my $devHash = CUL_HM_name2Hash($devName);
my $tLast = $devHash->{"protLastRcv"};
my @t = localtime($tod - $tSec); #time since when a trigger is expected
my $tSince = sprintf("%04d-%02d-%02d %02d:%02d:%02d",
$t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]);
if ((!$tLast || $tSince gt $tLast)){ #no message received in timeframe
if ($tSince gt $actHash->{helper}{$devId}{start}){
if ($tSince gt $actHash->{helper}{$devId}{start}){# we are dead
$noDead++;$noUnkn--;
$state = "dead";
};
}else{
}
else{# no change, update counter only
if ($oldState eq "dead"){
$noDead++;$noUnkn--;
$state = "dead";
}
else{# must be unknown, no action
$state = "unknown";
}
}
}
else{
$noAlive++;$noUnkn--;
$state = "alive";
}
}
if ($state && $attr{$devName}{actStatus} ne $state){
DoTrigger($devName,"Activity:".$state);
if ($oldState ne $state){
readingsSingleUpdate($devHash,"Activity:",$state,1);
$attr{$devName}{actStatus} = $state;
push @event, $rdName.":".$state;
Log GetLogLevel($actName,4),"Device ".$devName." is ".$state;
}
push @event, $rdName.":".$state;
}
push @event, "state:"."alive:".$noAlive
." dead:".$noDead
@ -4293,6 +4222,17 @@ sub CUL_HM_putHash($) {# provide data to HMinfo
my ($info) = @_;
return %culHmModel if ($info eq "culHmModel");
}
sub CUL_HM_noDup(@) {#return list with no duplicates
my %all;
$all{$_}=0 for @_;
delete $all{""}; #remove empties if present
return (sort keys %all);
}
sub CUL_HM_noDupInString($) {#return string with no duplicates, comma separated
my ($str) = @_;
return join ",",CUL_HM_noDup(split ",",$str);
}
1;
=pod
@ -4362,8 +4302,6 @@ sub CUL_HM_putHash($) {# provide data to HMinfo
It is the unique, hardcoded device-address and cannot be changed (no,
you cannot choose it arbitrarily like for FS20 devices). You may
detect it by inspecting the fhem log.</li>
<li>the hmClass attribute<br>
which is either sender or receiver. It is not used in fhem</li>
<li>the subType attribute<br>
which is one of switch dimmer blindActuator remote sensor swi
pushButton threeStateSensor motionDetector keyMatic winMatic
@ -5022,8 +4960,7 @@ sub CUL_HM_putHash($) {# provide data to HMinfo
extert takes benefit of the implementation.
Nevertheless - by definition - showInternalValues overrules expert.
</li>
<li><a name="hmClass">hmClass</a>,
<a name="model">model</a>,
<li><a name="model">model</a>,
<a name="subType">subType</a><br>
These attributes are set automatically after a successful pairing.
They are not supposed to be set by hand, and are necessary in order to