diff --git a/fhem/FHEM/00_HMLAN.pm b/fhem/FHEM/00_HMLAN.pm index 4628b9b40..ad6edda91 100755 --- a/fhem/FHEM/00_HMLAN.pm +++ b/fhem/FHEM/00_HMLAN.pm @@ -15,7 +15,7 @@ sub HMLAN_secSince2000(); sub HMLAN_SimpleWrite(@); -my $debug = 0; # set 1 for better log readability +my $debug = 1; # set 1 for better log readability my %sets = ( "hmPairForSec" => "HomeMatic", "hmPairSerial" => "HomeMatic", diff --git a/fhem/FHEM/10_CUL_HM.pm b/fhem/FHEM/10_CUL_HM.pm index 79a9c1a93..6e390db2d 100755 --- a/fhem/FHEM/10_CUL_HM.pm +++ b/fhem/FHEM/10_CUL_HM.pm @@ -9,46 +9,7 @@ package main; use strict; use warnings; -sub CUL_HM_Initialize($); -sub CUL_HM_Define($$); -sub CUL_HM_Undef($$); -sub CUL_HM_Parse($$); -sub CUL_HM_Get($@); -sub CUL_HM_fltCvT($); -sub CUL_HM_Set($@); -sub CUL_HM_infoUpdtDevData($$$); -sub CUL_HM_Pair(@); -sub CUL_HM_getConfig($$$$$); -sub CUL_HM_SndCmd($$); -sub CUL_HM_responseSetup($$); -sub CUL_HM_eventP($$); -sub CUL_HM_respPendRm($); -sub CUL_HM_respPendTout($); -sub CUL_HM_PushCmdStack($$); -sub CUL_HM_ProcessCmdStack($); -sub CUL_HM_Resend($); -sub CUL_HM_Id($); -sub CUL_HM_name2Hash($); -sub CUL_HM_name2Id(@); -sub CUL_HM_id2Name($); -sub CUL_HM_getDeviceHash($); -sub CUL_HM_DumpProtocol($$@); -sub CUL_HM_parseCommon(@); -sub CUL_HM_encodeTime8($); -sub CUL_HM_decodeTime8($); -sub CUL_HM_encodeTime16($); -sub CUL_HM_convTemp($); -sub CUL_HM_updtRegDisp($$$); -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 $K_actDetID = '000000'; # id of actionDetector #my %culHmDevProps=( @@ -225,6 +186,749 @@ my %culHmModel=( #263 167 HM Smoke Detector Schueco ); + +##----------definitions for register settings----------------- + # definition of Register for all devices + # a: address, incl bits 13.4 4th bit in reg 13 + # s: size 2.0 = 2 byte, 0.5 = 5 bit. Max is 4.0!! + # l: list number. List0 will be for channel 0 + # List 1 will set peer to 00000000 + # list 3 will need the input of a peer! + # min: minimal input value + # max: maximal input value + # c: conversion, will point to a routine for calculation + # f: factor to be used if c = 'factor' + # u: unit for description + # t: txt description + # lit: if the command is a literal options will be entered here + # d: if '1' the register will appear in Readings + # +my %culHmRegDefShLg = (# register that are available for short AND long button press. Will be merged to rgister list at init +#blindActuator mainly + ActionType =>{a=> 10.0,s=>0.2,l=>3,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{off=>0,jmpToTarget=>1,toggleToCnt=>2,toggleToCntInv=>3}}, + OffTimeMode =>{a=> 10.6,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"off time mode",lit=>{absolut=>0,minimal=>1}}, + OnTimeMode =>{a=> 10.7,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"on time mode" ,lit=>{absolut=>0,minimal=>1}}, + MaxTimeF =>{a=> 29.0,s=>1.0,l=>3,min=>0 ,max=>25.4 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>0,t=>"max time first direction"}, + DriveMode =>{a=> 31.0,s=>1.0,l=>3,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{direct=>0,viaUpperEnd=>1,viaLowerEnd=>2,viaNextEnd=>3}}, +#dimmer mainly + OnDly =>{a=> 6.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"on delay "}, + OnTime =>{a=> 7.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"on time"}, + OffDly =>{a=> 8.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"off delay"}, + OffTime =>{a=> 9.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"off time"}, + + ActionTypeDim =>{a=> 10.0,s=>0.4,l=>3,min=>0 ,max=>8 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{off=>0,jmpToTarget=>1,toggleToCnt=>2,toggleToCntInv=>3,upDim=>4,downDim=>5,toggelDim=>6,toggelDimToCnt=>7,toggelDimToCntInv=>8}}, + OffDlyBlink =>{a=> 14.5,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{off=>0,on=>1}}, + OnLvlPrio =>{a=> 14.6,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{high=>0,low=>1}}, + OnDlyMode =>{a=> 14.7,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{setToOff=>0,NoChange=>1}}, + OffLevel =>{a=> 15.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"PowerLevel Off"}, + OnMinLevel =>{a=> 16.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"minimum PowerLevel"}, + OnLevel =>{a=> 17.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>1,t=>"PowerLevel on"}, + + OffLevelKm =>{a=> 15.0,s=>1.0,l=>3,min=>0 ,max=>127.5 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"OnLevel 127.5=locked"}, + OnLevelKm =>{a=> 17.0,s=>1.0,l=>3,min=>0 ,max=>127.5 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"OnLevel 127.5=locked"}, + OnRampOnSp =>{a=> 34.0,s=>1.0,l=>3,min=>0 ,max=>1 ,c=>'factor' ,f=>200 ,u=>'s' ,d=>0,t=>"Ramp On speed"}, + OnRampOffSp =>{a=> 35.0,s=>1.0,l=>3,min=>0 ,max=>1 ,c=>'factor' ,f=>200 ,u=>'s' ,d=>0,t=>"Ramp Off speed"}, + + RampSstep =>{a=> 18.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"rampStartStep"}, + RampOnTime =>{a=> 19.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"rampOnTime"}, + RampOffTime =>{a=> 20.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"rampOffTime"}, + DimMinLvl =>{a=> 21.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"dimMinLevel"}, + DimMaxLvl =>{a=> 22.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"dimMaxLevel"}, + DimStep =>{a=> 23.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"dimStep"}, + + OffDlyNewTime =>{a=> 25.0,s=>1.0,l=>3,min=>0.1,max=>25.6 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>0,t=>"off delay new time"}, + OffDlyNewTime =>{a=> 26.0,s=>1.0,l=>3,min=>0.1,max=>25.6 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>0,t=>"off delay old time"}, + DimElsOffTimeMd =>{a=> 38.6,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{absolut=>0,minimal=>1}}, + DimElsOnTimeMd =>{a=> 38.7,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{absolut=>0,minimal=>1}}, + DimElsActionType=>{a=> 38.0,s=>0.4,l=>3,min=>0 ,max=>8 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{off=>0,jmpToTarget=>1,toggleToCnt=>2,toggleToCntInv=>3,upDim=>4,downDim=>5,toggelDim=>6,toggelDimToCnt=>7,toggelDimToCntInv=>8}}, +#output Unit + ActType =>{a=> 36 ,s=>1 ,l=>3,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Action type(LED or Tone)"}, + ActNum =>{a=> 37 ,s=>1 ,l=>3,min=>1 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Action Number"}, + Intense =>{a=> 43 ,s=>1 ,l=>3,min=>10 ,max=>255 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Volume",lit=>{vol_0=>255,vol_1=>250,vol_2=>246,vol_3=>240,vol_4=>234,vol_5=>227,vol_6=>218,vol_7=>207,vol_8=>190,vol_9=>162,vol_00=>10}}, +# statemachines + BlJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from On" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, + BlJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, + BlJtDlyOn =>{a=> 12.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOn" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, + BlJtDlyOff =>{a=> 12.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOff",lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, + BlJtRampOn =>{a=> 13.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from rampOn" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, + BlJtRampOff =>{a=> 13.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from rampOff" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, + BlJtRefOn =>{a=> 28.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from refOn" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, + BlJtRefOff =>{a=> 28.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from refOff" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, + + DimJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from On" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimJtDlyOn =>{a=> 12.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOn" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimJtDlyOff =>{a=> 12.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOff",lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimJtRampOn =>{a=> 13.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from rampOn" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimJtRampOff =>{a=> 13.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from rampOff" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + + DimElsJtOn =>{a=> 39.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from On" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimElsJtOff =>{a=> 39.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from Off" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimElsJtDlyOn =>{a=> 40.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from delayOn" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimElsJtDlyOff =>{a=> 40.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from delayOff",lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimElsJtRampOn =>{a=> 41.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from rampOn" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + DimElsJtRampOff =>{a=> 41.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from rampOff" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + + SwJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from On" ,lit=>{no=>0,dlyOn=>1,on=>3,dlyOff=>4,off=>6}}, + SwJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,dlyOn=>1,on=>3,dlyOff=>4,off=>6}}, + SwJtDlyOn =>{a=> 12.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOn" ,lit=>{no=>0,dlyOn=>1,on=>3,dlyOff=>4,off=>6}}, + SwJtDlyOff =>{a=> 12.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOff",lit=>{no=>0,dlyOn=>1,on=>3,dlyOff=>4,off=>6}}, + + KeyJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>7 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from On" ,lit=>{no=>0,dlyUnlock=>1,rampUnlock=>2,lock=>3,dlyLock=>4,rampLock=>5,lock=>6,open=>8}}, + KeyJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>7 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,dlyUnlock=>1,rampUnlock=>2,lock=>3,dlyLock=>4,rampLock=>5,lock=>6,open=>8}}, + + WinJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,rampOnDly=>1,rampOn=>2,on=>3,ramoOffDly=>4,rampOff=>5,Off=>6,rampOnFast=>8,rampOffFast=>9}}, + WinJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,rampOnDly=>1,rampOn=>2,on=>3,ramoOffDly=>4,rampOff=>5,Off=>6,rampOnFast=>8,rampOffFast=>9}}, + WinJtRampOn =>{a=> 13.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,rampOnDly=>1,rampOn=>2,on=>3,ramoOffDly=>4,rampOff=>5,Off=>6,rampOnFast=>8,rampOffFast=>9}}, + WinJtRampOff =>{a=> 13.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,rampOnDly=>1,rampOn=>2,on=>3,ramoOffDly=>4,rampOff=>5,Off=>6,rampOnFast=>8,rampOffFast=>9}}, + + CtRampOn =>{a=> 1.0,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from rampOn" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, + CtRampOff =>{a=> 1.4,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from rampOff" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, + CtDlyOn =>{a=> 2.0,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from delayOn" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, + CtDlyOff =>{a=> 2.4,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from delayOff" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, + CtOn =>{a=> 3.0,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from On" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, + CtOff =>{a=> 3.4,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from Off" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, + CtValLo =>{a=> 4.0,s=>1 ,l=>3,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Condition value low for CT table" }, + CtValHi =>{a=> 5.0,s=>1 ,l=>3,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Condition value high for CT table" }, + CtRefOn =>{a=> 28.0,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from refOn" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, + CtRefOff =>{a=> 28.4,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from refOff" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, +); + +my %culHmRegDefine = ( + intKeyVisib =>{a=> 2.7,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>'visibility of internal channel',lit=>{invisib=>0,visib=>1}}, + pairCentral =>{a=> 10.0,s=>3.0,l=>0,min=>0 ,max=>16777215,c=>'hex' ,f=>'' ,u=>'' ,d=>1,t=>'pairing to central'}, +#blindActuator mainly + lgMultiExec =>{a=>138.5,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"multiple execution per repeat of long trigger" ,lit=>{off=>0,on=>1}}, + driveDown =>{a=> 11.0,s=>2.0,l=>1,min=>0 ,max=>6000.0 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>1,t=>"drive time up"}, + driveUp =>{a=> 13.0,s=>2.0,l=>1,min=>0 ,max=>6000.0 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>1,t=>"drive time up"}, + driveTurn =>{a=> 15.0,s=>1.0,l=>1,min=>0 ,max=>6000.0 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>1,t=>"fliptime up <=>down"}, + refRunCounter =>{a=> 16.0,s=>1.0,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"reference run counter"}, + +#repeater + compMode =>{a=> 23.0,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"compatibility moden" ,lit=>{off=>0,on=>1}}, +#remote mainly + language =>{a=> 7.0,s=>1.0,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Language" ,lit=>{English=>0,German=>1}}, + backAtKey =>{a=> 13.7,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight at keystroke",lit=>{off=>0,on=>1}}, + backAtMotion =>{a=> 13.6,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight at motion" ,lit=>{off=>0,on=>1}}, + backAtCharge =>{a=> 13.5,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight at Charge" ,lit=>{off=>0,on=>1}}, + stbyTime =>{a=> 14.0,s=>1.0,l=>0,min=>1 ,max=>99 ,c=>'' ,f=>'' ,u=>'s' ,d=>1,t=>"Standby Time"}, + backOnTime =>{a=> 14.0,s=>1.0,l=>0,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'s' ,d=>1,t=>"Backlight On Time"}, + + longPress =>{a=> 4.4,s=>0.4,l=>1,min=>0.3,max=>1.8 ,c=>'m10s3' ,f=>'' ,u=>'s' ,d=>0,t=>"time to detect key long press"}, + dblPress =>{a=> 9.0,s=>0.4,l=>1,min=>0 ,max=>1.5 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>0,t=>"time to detect double press"}, + msgShowTime =>{a=> 45.0,s=>1.0,l=>1,min=>0.0,max=>120 ,c=>'factor' ,f=>2 ,u=>'s' ,d=>1,t=>"Message show time(RC19). 0=always on"}, + beepAtAlarm =>{a=> 46.0,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Beep Alarm" ,lit=>{none=>0,tone1=>1,tone2=>2,tone3=>3}}, + beepAtService =>{a=> 46.2,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Beep Service" ,lit=>{none=>0,tone1=>1,tone2=>2,tone3=>3}}, + beepAtInfo =>{a=> 46.4,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Beep Info" ,lit=>{none=>0,tone1=>1,tone2=>2,tone3=>3}}, + backlAtAlarm =>{a=> 47.0,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight Alarm" ,lit=>{off=>0,on=>1,blinkSlow=>2,blinkFast=>3}}, + backlAtService =>{a=> 47.2,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight Service" ,lit=>{off=>0,on=>1,blinkSlow=>2,blinkFast=>3}}, + backlAtInfo =>{a=> 47.4,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight Info" ,lit=>{off=>0,on=>1,blinkSlow=>2,blinkFast=>3}}, + + peerNeedsBurst =>{a=> 1.0,s=>0.1,l=>4,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"peer expects burst",lit=>{off=>0,on=>1}}, + expectAES =>{a=> 1.7,s=>0.1,l=>4,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"expect AES" ,lit=>{off=>0,on=>1}}, + lcdSymb =>{a=> 2.0,s=>0.1,l=>4,min=>0 ,max=>255 ,c=>'hex' ,f=>'' ,u=>'' ,d=>0,t=>"bitmask which symbol to display on message"}, + lcdLvlInterp =>{a=> 3.0,s=>0.1,l=>4,min=>0 ,max=>255 ,c=>'hex' ,f=>'' ,u=>'' ,d=>0,t=>"bitmask fro symbols"}, +#dimmer mainly + loadErrCalib =>{a=> 18.0,s=>1.0,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>"" ,d=>0,t=>"Load Error Calibration"}, + transmitTryMax =>{a=> 48.0,s=>1.0,l=>1,min=>1 ,max=>10 ,c=>'' ,f=>'' ,u=>"" ,d=>0,t=>"max message re-transmit"}, + loadAppearBehav =>{a=> 49.0,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>"" ,d=>1,t=>"behavior on load appearence at restart",lit=>{off=>0,last=>1,btnPress=>2,btnPressIfWasOn=>3}}, + ovrTempLvl =>{a=> 50.0,s=>1.0,l=>1,min=>30 ,max=>100 ,c=>'' ,f=>'' ,u=>"C" ,d=>0,t=>"overtemperatur level"}, + fuseDelay =>{a=> 51.0,s=>1.0,l=>1,min=>0 ,max=>2.55 ,c=>'factor' ,f=>100 ,u=>"s" ,d=>0,t=>"fuse delay"}, + redTempLvl =>{a=> 52.0,s=>1.0,l=>1,min=>30 ,max=>100 ,c=>'' ,f=>'' ,u=>"C" ,d=>0,t=>"reduced temperatur recover"}, + redLvl =>{a=> 53.0,s=>1.0,l=>1,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>"%" ,d=>0,t=>"reduced power level"}, + powerUpAction =>{a=> 86.0,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>"" ,d=>1,t=>"behavior on power up" ,lit=>{off=>0,on=>1}}, + statusInfoMinDly=>{a=> 87.0,s=>0.5,l=>1,min=>0.5,max=>15.5 ,c=>'factor' ,f=>2 ,u=>"s" ,d=>0,t=>"status message min delay"}, + statusInfoRandom=>{a=> 87.5,s=>0.3,l=>1,min=>0 ,max=>7 ,c=>'' ,f=>'' ,u=>"s" ,d=>0,t=>"status message random delay"}, + characteristic =>{a=> 88.0,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>"" ,d=>1,t=>"" ,lit=>{linear=>0,square=>1}}, + logicCombination=>{a=> 89.0,s=>0.5,l=>1,min=>0 ,max=>16 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{inactive=>0,or=>1,and=>2,xor=>3,nor=>4,nand=>5,orinv=>6,andinv=>7,plus=>8,minus=>9,mul=>10,plusinv=>11,minusinv=>12,mulinv=>13,invPlus=>14,invMinus=>15,invMul=>16}}, +# logicCombination=>{a=> 89.0,s=>0.5,l=>1,min=>0 ,max=>16 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"". +# "inactive=>unused\n". +# "or =>max(state,chan)\n". +# "and =>min(state,chan)\n". +# "xor =>0 if both are != 0, else max\n". +# "nor =>100-max(state,chan)\n". +# "nand =>100-min(state,chan)\n". +# "orinv =>max((100-chn),state)\n". +# "andinv =>min((100-chn),state)\n". +# "plus =>state + chan\n". +# "minus =>state - chan\n". +# "mul =>state * chan\n". +# "plusinv =>state + 100 - chan\n". +# "minusinv=>state - 100 + chan\n". +# "mulinv =>state * (100 - chan)\n". +# "invPlus =>100 - state - chan\n". +# "invMinus=>100 - state + chan\n". +# "invMul =>100 - state * chan\n",lit=>{inactive=>0,or=>1,and=>2,xor=>3,nor=>4,nand=>5,orinv=>6,andinv=>7,plus=>8,minus=>9,mul=>10,plusinv=>11,minusinv=>12,mulinv=>13,invPlus=>14,invMinus=>15,invMul=>16}}, +# +# +#CC-TC + backlOnTime =>{a=> 5.0,s=>0.6,l=>0,min=>1 ,max=>25 ,c=>"" ,f=>'' ,u=>'s' ,d=>0,t=>"Backlight ontime"}, + backlOnMode =>{a=> 5.6,s=>0.2,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Backlight mode" ,lit=>{off=>0,auto=>1}}, + btnLock =>{a=> 15 ,s=>1 ,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Button Lock" ,lit=>{unlock=>0,lock=>1}}, + + dispTempHum =>{a=> 1.0,s=>0.1,l=>5,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{temp=>0,tempHumidity=>1}}, + dispTempInfo =>{a=> 1.1,s=>0.1,l=>5,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{actual=>0,setPoint=>1}}, + dispTempUnit =>{a=> 1.2,s=>0.1,l=>5,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{Celsius=>0,Fahrenheit=>1}}, + mdTempReg =>{a=> 1.3,s=>0.2,l=>5,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{manual=>0,auto=>1,central=>2,party=>3}}, + decalDay =>{a=> 1.5,s=>0.3,l=>5,min=>0 ,max=>7 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Decalc weekday" ,lit=>{sat=>0,sun=>1,mon=>2,tue=>3,wed=>4,thu=>5,fri=>6}}, + mdTempValve =>{a=> 2.6,s=>0.2,l=>5,min=>0 ,max=>2 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{auto=>0,close=>1,open=>2}}, + tempComfort =>{a=> 3 ,s=>0.6,l=>5,min=>6 ,max=>30 ,c=>'factor' ,f=>2 ,u=>'C' ,d=>1,t=>"comfort temp value"}, + tempLower =>{a=> 4 ,s=>0.6,l=>5,min=>6 ,max=>30 ,c=>'factor' ,f=>2 ,u=>'C' ,d=>1,t=>"comfort temp value"}, + tempWinOpen =>{a=> 5 ,s=>0.6,l=>5,min=>6 ,max=>30 ,c=>'factor' ,f=>2 ,u=>'C' ,d=>1,t=>"Temperature for Win open !chan 3 only!"}, + tempParty =>{a=> 6 ,s=>0.6,l=>5,min=>6 ,max=>30 ,c=>'factor' ,f=>2 ,u=>'C' ,d=>1,t=>"Temperature for Party"}, + decalMin =>{a=> 8 ,s=>0.3,l=>5,min=>0 ,max=>50 ,c=>'factor' ,f=>0.1 ,u=>'min' ,d=>1,t=>"Decalc min"}, + decalHr =>{a=> 8.3,s=>0.5,l=>5,min=>0 ,max=>23 ,c=>'' ,f=>'' ,u=>'h' ,d=>1,t=>"Decalc hour"}, + partyEndHr =>{a=> 97 ,s=>0.6,l=>6,min=>0 ,max=>23 ,c=>'' ,f=>'' ,u=>'h' ,d=>1,t=>"Party end Hour"}, + partyEndMin =>{a=> 97.7,s=>0.1,l=>6,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'min' ,d=>1,t=>"Party end min",lit=>{"00"=>0,"30"=>1}}, + partyEndDay =>{a=> 98 ,s=>1 ,l=>6,min=>0 ,max=>200 ,c=>'' ,f=>'' ,u=>'d' ,d=>1,t=>"Party end Day"}, +#Thermal-cc-VD + valveOffset =>{a=> 9 ,s=>0.5,l=>5,min=>0 ,max=>25 ,c=>'' ,f=>'' ,u=>'%' ,d=>1,t=>"Valve offset"}, # size actually 0.5 + valveError =>{a=> 10 ,s=>1 ,l=>5,min=>0 ,max=>99 ,c=>'' ,f=>'' ,u=>'%' ,d=>1,t=>"Valve position when error"},# size actually 0.7 +#SCD + msgScdPosA =>{a=> 32.6,s=>0.2,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position A",lit=>{noMsg=>0,lvlNormal=>1}}, + msgScdPosB =>{a=> 32.4,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position B",lit=>{noMsg=>0,lvlNormal=>1,lvlAddStrong=>2,lvlAdd=>3}}, + msgScdPosC =>{a=> 32.2,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position C",lit=>{noMsg=>0,lvlNormal=>1,lvlAddStrong=>2,lvlAdd=>3}}, + msgScdPosD =>{a=> 32.0,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position D",lit=>{noMsg=>0,lvlNormal=>1,lvlAddStrong=>2,lvlAdd=>3}}, + evtFltrTime =>{a=> 35.0,s=>1 ,l=>1,min=>600,max=>1200 ,c=>'' ,f=>1.6 ,u=>'s' ,d=>0,t=>"Event filter time",},#todo check calculation +#rhs - different literals + msgRhsPosA =>{a=> 32.6,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position A",lit=>{noMsg=>0,closed=>1,open=>2,tilted=>3}}, + msgRhsPosB =>{a=> 32.4,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position B",lit=>{noMsg=>0,closed=>1,open=>2,tilted=>3}}, + msgRhsPosC =>{a=> 32.2,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position C",lit=>{noMsg=>0,closed=>1,open=>2,tilted=>3}}, + evtDly =>{a=> 33 ,s=>1 ,l=>1,min=>0 ,max=>7620 ,c=>'factor' ,f=>1.6 ,u=>'s' ,d=>0,t=>"Event delay time",},#todo check calculation +# keymatic/winmatic secific register + signal =>{a=> 3.4,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Confirmation beep" ,lit=>{off=>0,on=>1}}, + signalTone =>{a=> 3.6,s=>0.2,l=>0,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{low=>0,mid=>1,high=>2,veryHigh=>3}}, + keypressSignal =>{a=> 3.0,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Keypress beep" ,lit=>{off=>0,on=>1}}, + holdTime =>{a=> 20 ,s=>1, l=>1,min=>0 ,max=>8.16 ,c=>'factor' ,f=>31.25 ,u=>'s' ,d=>0,t=>"Holdtime for door opening"}, + holdPWM =>{a=> 21 ,s=>1, l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Holdtime pulse wide modulation"}, + setupDir =>{a=> 22 ,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Rotation direction for locking",lit=>{right=>0,left=>1}}, + setupPosition =>{a=> 23 ,s=>1 ,l=>1,min=>0 ,max=>3000 ,c=>'factor' ,f=>0.06666 ,u=>'deg' ,d=>1,t=>"Rotation angle neutral position"}, + angelOpen =>{a=> 24 ,s=>1 ,l=>1,min=>0 ,max=>3000 ,c=>'factor' ,f=>0.06666 ,u=>'deg' ,d=>1,t=>"Door opening angle"}, + angelMax =>{a=> 25 ,s=>1 ,l=>1,min=>0 ,max=>3000 ,c=>'factor' ,f=>0.06666 ,u=>'deg' ,d=>1,t=>"Angle maximum"}, + angelLocked =>{a=> 26 ,s=>1 ,l=>1,min=>0 ,max=>3000 ,c=>'factor' ,f=>0.06666 ,u=>'deg' ,d=>1,t=>"Angle Locked position"}, + pullForce =>{a=> 28 ,s=>1 ,l=>1,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>1,t=>"pull force level"}, + pushForce =>{a=> 29 ,s=>1 ,l=>1,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>1,t=>"push force level"}, + tiltMax =>{a=> 30 ,s=>1 ,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"maximum tilt level"}, + ledFlashUnlocked=>{a=> 31.3,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"LED blinks when not locked",lit=>{off=>0,on=>1}}, + ledFlashLocked =>{a=> 31.6,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"LED blinks when locked" ,lit=>{off=>0,on=>1}}, +# sec_mdir + cyclicInfoMsg =>{a=> 9 ,s=>1 ,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"cyclic message",lit=>{off=>0,on=>1}}, + sabotageMsg =>{a=> 16.0,s=>1 ,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"enable sabotage message" ,lit=>{off=>0,on=>1}}, + lowBatLimit =>{a=> 18.0,s=>1 ,l=>0,min=>10 ,max=>12 ,c=>'factor' ,f=>10 ,u=>'V' ,d=>1,t=>"low batterie limit"}, + batDefectLimit =>{a=> 19.0,s=>1 ,l=>0,min=>0.1,max=>2 ,c=>'factor' ,f=>100 ,u=>'Ohm' ,d=>1,t=>"batterie defect detection"}, + transmDevTryMax =>{a=> 20.0,s=>1.0,l=>0,min=>1 ,max=>10 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"max message re-transmit"}, + localResDis =>{a=> 24.0,s=>1.0,l=>0,min=>1 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"local reset disable" ,lit=>{off=>0,on=>1}}, + + waterUppThr =>{a=> 6.0,s=>1 ,l=>1,min=>0 ,max=>256 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"water upper threshold"}, + waterlowThr =>{a=> 7.0,s=>1 ,l=>1,min=>0 ,max=>256 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"water lower threshold"}, + caseDesign =>{a=> 90.0,s=>1 ,l=>1,min=>1 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"case desing" ,lit=>{verticalBarrel=>1,horizBarrel=>2,rectangle=>3}}, + caseHigh =>{a=> 94.0,s=>2 ,l=>1,min=>100,max=>10000 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>"case hight"}, + fillLevel =>{a=> 98.0,s=>2 ,l=>1,min=>100,max=>300 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>"fill level"}, + caseWidth =>{a=>102.0,s=>2 ,l=>1,min=>100,max=>10000 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>"case width"}, + caseLength =>{a=>106.0,s=>2 ,l=>1,min=>100,max=>10000 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>"case length"}, + meaLength =>{a=>108.0,s=>2 ,l=>1,min=>110,max=>310 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>""}, + useCustom =>{a=>110.0,s=>1 ,l=>1,min=>110,max=>310 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"use custom" ,lit=>{off=>0,on=>1}}, + + fillLvlUpThr =>{a=> 4.0,s=>1 ,l=>4,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"fill level upper threshold"}, + fillLvlLoThr =>{a=> 5.0,s=>1 ,l=>4,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"fill level lower threshold"}, + + evtFltrPeriod =>{a=> 1.0,s=>0.4,l=>1,min=>0.5,max=>7.5 ,c=>'factor' ,f=>2 ,u=>'s' ,d=>1,t=>"event filter period"}, + evtFltrNum =>{a=> 1.4,s=>0.4,l=>1,min=>1 ,max=>15 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"sensitivity - read sach n-th puls"}, + minInterval =>{a=> 2.0,s=>0.3,l=>1,min=>0 ,max=>4 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"minimum interval in sec" ,lit=>{15=>0,30=>1,60=>2,120=>3,240=>4}}, + captInInterval =>{a=> 2.3,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"capture within interval" ,lit=>{off=>0,on=>1}}, + brightFilter =>{a=> 2.4,s=>0.4,l=>1,min=>0 ,max=>7 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"brightness filter - ignore light at night"}, + msgScPosA =>{a=> 32.6,s=>0.2,l=>1,min=>0 ,max=>2 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position A",lit=>{noMsg=>0,closed=>1,open=>2}}, + msgScPosB =>{a=> 32.4,s=>0.2,l=>1,min=>0 ,max=>2 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position B",lit=>{noMsg=>0,closed=>1,open=>2}}, + eventDlyTime =>{a=> 33 ,s=>1 ,l=>1,min=>0 ,max=>7620 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>1,t=>"event delay time"}, + ledOnTime =>{a=> 34 ,s=>1 ,l=>1,min=>0 ,max=>1.275 ,c=>'factor' ,f=>200 ,u=>'s' ,d=>0,t=>"LED ontime"}, + eventFilterTime =>{a=> 35 ,s=>1 ,l=>1,min=>0 ,max=>7620 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"evetn filter time"}, + +# weather units + stormUpThresh =>{a=> 6 ,s=>1 ,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"Storm upper threshold"}, + stormLowThresh =>{a=> 7 ,s=>1 ,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"Storm lower threshold"}, +# others + localResetDis =>{a=> 7 ,s=>1 ,l=>1,min=>0 ,max=>255 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"LocalReset disable",lit=>{off=>0,on=>1}}, + ); + +my %culHmRegGeneral = ( + intKeyVisib=>1,pairCentral=>1, + ); +my %culHmRegType = ( + remote =>{expectAES =>1,peerNeedsBurst =>1,dblPress =>1,longPress =>1}, + blindActuator =>{driveUp =>1,driveDown =>1,driveTurn =>1,refRunCounter =>1, + transmitTryMax =>1,statusInfoMinDly=>1,statusInfoRandom=>1, # nt present in all files + MaxTimeF =>1, + OnDly =>1,OnTime =>1,OffDly =>1,OffTime =>1, + OffLevel =>1,OnLevel =>1, + ActionType =>1,OnTimeMode =>1,OffTimeMode =>1,DriveMode =>1, + BlJtOn =>1,BlJtOff =>1,BlJtDlyOn =>1,BlJtDlyOff =>1, + BlJtRampOn =>1,BlJtRampOff =>1,BlJtRefOn =>1,BlJtRefOff =>1, + CtValLo =>1,CtValHi =>1, + CtOn =>1,CtDlyOn =>1,CtRampOn =>1,CtRefOn =>1, + CtOff =>1,CtDlyOff =>1,CtRampOff =>1,CtRefOff =>1, + lgMultiExec =>1, + }, + dimmer =>{transmitTryMax =>1,statusInfoMinDly=>1,statusInfoRandom=>1,powerUpAction =>1, + ovrTempLvl =>1,redTempLvl =>1,redLvl =>1,fuseDelay =>1,#not dim.L + OnDly =>1,OnTime =>1,OffDly =>1,OffTime =>1, + OffDlyBlink =>1,OnLvlPrio =>1,OnDlyMode =>1, + ActionTypeDim =>1,OnTimeMode =>1,OffTimeMode =>1, + OffLevel =>1,OnMinLevel =>1,OnLevel =>1, + RampSstep =>1,RampOnTime =>1,RampOffTime =>1, + DimMinLvl =>1,DimMaxLvl =>1,DimStep =>1, + DimJtOn =>1,DimJtOff =>1,DimJtDlyOn =>1, + DimJtDlyOff =>1,DimJtRampOn =>1,DimJtRampOff =>1, + CtValLo =>1,CtValHi =>1, + CtOn =>1,CtDlyOn =>1,CtRampOn =>1, + CtOff =>1,CtDlyOff =>1,CtRampOff =>1, + OffDlyNewTime =>1,OffDlyNewTime =>1, + DimElsOffTimeMd =>1,DimElsOnTimeMd =>1, + DimElsActionType=>1, + DimElsJtOn =>1,DimElsJtOff =>1,DimElsJtDlyOn =>1, + DimElsJtDlyOff =>1,DimElsJtRampOn =>1,DimElsJtRampOff =>1, + lgMultiExec =>1, + logicCombination=>1, + }, + switch =>{OnTime =>1,OffTime =>1,OnDly =>1,OffDly =>1, + SwJtOn =>1,SwJtOff =>1,SwJtDlyOn =>1,SwJtDlyOff =>1, + CtValLo =>1,CtValHi =>1, + CtOn =>1,CtDlyOn =>1,CtOff =>1,CtDlyOff =>1, + ActionType =>1,OnTimeMode =>1,OffTimeMode =>1, + lgMultiExec =>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, + captInInterval=>1,brightFilter =>1,ledOnTime =>1, + }, +); + +my %culHmRegModel = ( + "HM-RC-12" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1}, + "HM-RC-12-B" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1}, + "HM-RC-12-SW" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1}, + + "HM-RC-19" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1,backAtCharge =>1,language =>1,}, + "HM-RC-19-B" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1,backAtCharge =>1,language =>1,}, + "HM-RC-19-SW" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1,backAtCharge =>1,language =>1,}, + + "HM-LC-Dim1PWM-CV"=>{characteristic =>1}, + "HM-LC-Dim1L-P" =>{loadAppearBehav =>1,loadErrCalib =>1}, + "HM-LC-Dim1L-CV" =>{loadAppearBehav =>1,loadErrCalib =>1}, + "HM-LC-Dim2L-SM" =>{loadAppearBehav =>1,loadErrCalib =>1}, + + "HM-CC-VD" =>{valveOffset =>1,valveError =>1}, + "HM-PB-4DIS-WM" =>{peerNeedsBurst =>1,expectAES =>1,language =>1,stbyTime =>1}, + "HM-WDS100-C6-O" =>{stormUpThresh =>1,stormLowThresh =>1}, + "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, + 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, + transmitTryMax =>1,evtFltrTime =>1, + msgScdPosA =>1,msgScdPosB =>1,msgScdPosC =>1,msgScdPosD =>1,}, + "HM-SEC-RHS" =>{peerNeedsBurst =>1,expectAES =>1, + cyclicInfoMsg =>1, transmDevTryMax =>1, + msgRhsPosA =>1,msgRhsPosB =>1,msgRhsPosC =>1, + evtDly =>1,ledOnTime =>1,transmitTryMax =>1,}, + "HM-SEC-SC" =>{cyclicInfoMsg =>1,sabotageMsg =>1,transmDevTryMax =>1, + msgScPosA =>1,msgScPosB =>1, + ledOnTime =>1,transmitTryMax =>1,eventDlyTime =>1, + peerNeedsBurst =>1,expectAES =>1,}, + "HM-SCI-3-FM" =>{cyclicInfoMsg =>1 ,transmDevTryMax =>1, + msgScPosA =>1,msgScPosB =>1, + transmitTryMax =>1,eventDlyTime =>1, + peerNeedsBurst =>1,expectAES =>1,}, + "HM-SEC-TIS" =>{cyclicInfoMsg =>1,sabotageMsg =>1,transmDevTryMax =>1, + msgScPosA =>1,msgScPosB =>1, + ledOnTime =>1,transmitTryMax =>1,eventFilterTime =>1, + peerNeedsBurst =>1,expectAES =>1,}, + "HM-SEC-SFA-SM" =>{cyclicInfoMsg =>1,sabotageMsg =>1,transmDevTryMax =>1, + lowBatLimit =>1,batDefectLimit =>1, + transmitTryMax =>1,}, + "HM-Sys-sRP-Pl" =>{compMode =>1,}, + "KFM-Display" =>{CtDlyOn =>1,CtDlyOff =>1, + CtOn =>1,CtOff =>1,CtRampOn =>1,CtRampOff =>1, + CtValLo =>1,CtValHi =>1, + ActionType =>1,OffTimeMode =>1,OnTimeMode =>1, + DimJtOn =>1,DimJtOff =>1,DimJtDlyOn =>1,DimJtDlyOff =>1, + DimJtRampOn =>1,DimJtRampOff =>1, + lgMultiExec =>1, + }, + "HM-Sen-Wa-Od" =>{cyclicInfoMsg =>1, transmDevTryMax =>1, + localResDis =>1,ledOnTime =>1,transmitTryMax =>1, + waterUppThr =>1,waterlowThr =>1,caseDesign =>1,caseHigh =>1, + fillLevel =>1,caseWidth =>1,caseLength =>1,meaLength =>1, + useCustom =>1, + fillLvlUpThr =>1,fillLvlLoThr =>1, + expectAES =>1,peerNeedsBurst =>1,}, + ); +my %culHmRegChan = (# if channelspecific then enter them here + "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, + }, + "HM-CC-TC03" =>{tempWinOpen =>1, }, #window channel + "HM-RC-1912" =>{msgShowTime =>1, beepAtAlarm =>1, beepAtService =>1,beepAtInfo =>1, + backlAtAlarm =>1, backlAtService =>1, backlAtInfo =>1, + lcdSymb =>1, lcdLvlInterp =>1}, + "HM-RC-19-B12" =>{msgShowTime =>1, beepAtAlarm =>1, beepAtService =>1,beepAtInfo =>1, + backlAtAlarm =>1, backlAtService =>1, backlAtInfo =>1, + lcdSymb =>1, lcdLvlInterp =>1}, + "HM-RC-19-SW12" =>{msgShowTime =>1, beepAtAlarm =>1, beepAtService =>1,beepAtInfo =>1, + backlAtAlarm =>1, backlAtService =>1, backlAtInfo =>1, + lcdSymb =>1, lcdLvlInterp =>1}, + "HM-OU-CFM-PL02" =>{Intense=>1}, + "HM-SEC-WIN01" =>{setupDir =>1,pullForce =>1,pushForce =>1,tiltMax =>1, + CtValLo =>1,CtValHi =>1, + CtOn =>1,CtOff =>1,CtRampOn =>1,CtRampOff =>1, + WinJtOn =>1,WinJtOff =>1,WinJtRampOn =>1,WinJtRampOff =>1, + OnTime =>1,OffTime =>1,OffLevelKm =>1, + OnLevelKm =>1,OnRampOnSp =>1,OnRampOffSp =>1 + } + ); +# RC send BCAST to specific address. Is the meaning understood? +my @culHmCmdFlags = ("WAKEUP", "WAKEMEUP", "CFG", "Bit3", + "BURST", "BIDI", "RPTED", "RPTEN"); + #RPTEN 0x80: set in every message. Meaning? + #RPTED 0x40: repeated (repeater operation) + #BIDI 0x20: response is expected + #Burst 0x10: set if burst is required by device + #Bit3 0x08: + #CFG 0x04: Device in Config mode + #WAKEMEUP 0x02: awake - hurry up to send messages + #WAKEUP 0x01: send initially to keep the device awake + +##--------------- Conversion routines for register settings + + +#define gets - try use same names as for set +my %culHmGlobalGets = ( + param => "", + reg => " ... ", + regList => "", + saveConfig => "", +); +my %culHmSubTypeGets = ( + none4Type =>{ "test"=>"" }, +); +my %culHmModelGets = ( + none4Mod =>{ "none"=>"" }, +); + +################################### +my %culHmGlobalSetsDevice = ( + raw => "data ...", + reset => "", + pair => "", + unpair => "", + getpair => "", + virtual =>"", +); +my %culHmGlobalSets = ( + sign => "[on|off]", + regBulk => ": ...", + peerBulk => "", + statusRequest => "", + getdevicepair => "", + getRegRaw =>"[List0|List1|List2|List3|List4|List5|List6] ... ", + getConfig => "", + regSet =>" ... ", + clear =>"[readings|msgEvents]", +); +my %culHmSubTypeSets = ( + switch =>{ "on-for-timer"=>"sec", "on-till"=>"time", + on=>"", off=>"", toggle=>"", + press => "[long|short] [on|off] ..."}, + dimmer =>{ "on-for-timer"=>"sec", "on-till"=>"time", + on=>"", off=>"", toggle=>"", pct=>"", stop=>"", + press => "[long|short] [on|off] ...", + up => "[] [ontime] [ramptime]...", + down => "[] [ontime] [ramptime]..." + }, + blindActuator =>{ on=>"", off=>"", toggle=>"", pct=>"", stop=>"", + press => "[long|short] [on|off] ...", + up => "[] [ontime] [ramptime]...", + down => "[] [ontime] [ramptime]..." + }, + remote =>{ devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]",}, + pushButton =>{ devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]",}, + threeStateSensor =>{ devicepair => " device ... single [set|unset] [actor|remote|both]",}, + motionDetector =>{ devicepair => " device ... single [set|unset] [actor|remote|both]",}, + virtual =>{ raw => "data ...", + devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]", + press => "[long|short]...", + valvePos => "position",#acting as TC + virtual =>"",}, #redef necessary for virtual + smokeDetector =>{ test => "", alarmOn=>"", alarmOff=>"", + devicepair => " device ... single [set|unset] actor",}, + winMatic =>{ matic => "", + keydef => " ", + create => "" }, + keyMatic =>{ lock =>"", + unlock =>"[sec] ...", + open =>"[sec] ...", + inhibit =>"[on|off]"}, +); +my %culHmModelSets = ( + "HM-CC-VD"=>{ + valvePos => "position"}, + "HM-RC-19"=> { + service => "", + alarm => "", + display => " [comma,no] [unit] [off|1|2|3] [off|on|slow|fast] "}, + "HM-RC-19-B"=> { + service => "", + alarm => "", + display => " [comma,no] [unit] [off|1|2|3] [off|on|slow|fast] "}, + "HM-RC-19-SW"=> { + service => "", + alarm => "", + display => " [comma,no] [unit] [off|1|2|3] [off|on|slow|fast] "}, + "HM-PB-4DIS-WM"=>{ + text => " [on|off] "}, + "HM-OU-LED16" =>{ + led =>"[off|red|green|orange]" , + ilum =>"[0-15] [0-127]" }, + "HM-OU-CFM-PL"=>{ + led => "[,..]", + playTone => "[,..]"}, + "HM-Sys-sRP-Pl"=>{ + setRepeat => "[no1..36] [bdcast-yes|no]"}, +); + +my %culHmChanSets = ( + "HM-CC-TC00"=>{ + devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]", + "day-temp" => "[on,off,6.0..30.0]", + "night-temp" => "[on,off,6.0..30.0]", + "party-temp" => "[on,off,6.0..30.0]", + "desired-temp" => "[on,off,6.0..30.0]", + tempListSat => "HH:MM temp ...", + tempListSun => "HH:MM temp ...", + tempListMon => "HH:MM temp ...", + tempListTue => "HH:MM temp ...", + tempListThu => "HH:MM temp ...", + tempListWed => "HH:MM temp ...", + tempListFri => "HH:MM temp ...", + displayMode => "[temp-only|temp-hum]", + displayTemp => "[actual|setpoint]", + displayTempUnit => "[celsius|fahrenheit]", + controlMode => "[manual|auto|central|party]", + decalcDay => "day", }, + "HM-CC-TC02"=>{ + devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]", + "day-temp" => "[on,off,6.0..30.0]", + "night-temp" => "[on,off,6.0..30.0]", + "party-temp" => "[on,off,6.0..30.0]", + "desired-temp" => "[on,off,6.0..30.0]", + tempListSat => "HH:MM temp ...", + tempListSun => "HH:MM temp ...", + tempListMon => "HH:MM temp ...", + tempListTue => "HH:MM temp ...", + tempListThu => "HH:MM temp ...", + tempListWed => "HH:MM temp ...", + tempListFri => "HH:MM temp ...", + displayMode => "[temp-only|temp-hum]", + displayTemp => "[actual|setpoint]", + displayTempUnit => "[celsius|fahrenheit]", + controlMode => "[manual|auto|central|party]", + decalcDay => "day", }, + "HM-SEC-WIN01"=>{ stop =>"", + level =>" ..."}, +); + +############################# +my %culHmBits = ( + "00" => { txt => "DEVICE_INFO", params => { + FIRMWARE => '00,2', + TYPE => "02,4", + SERIALNO => '06,20,$val=pack("H*",$val)', + CLASS => "26,2", + PEER_CHANNEL_A => "28,2", + PEER_CHANNEL_B => "30,2", + UNKNOWN => "32,2", }}, + + "01;p11=01" => { txt => "CONFIG_PEER_ADD", params => { + CHANNEL => "00,2", + PEER_ADDRESS => "04,6", + PEER_CHANNEL_A => "10,2", + PEER_CHANNEL_B => "12,2", }}, + "01;p11=02" => { txt => "CONFIG_PEER_REMOVE", params => { + CHANNEL => "00,2", + PEER_ADDRESS => '04,6,$val=CUL_HM_id2Name($val)', + PEER_CHANNEL_A => "10,2", + PEER_CHANNEL_B => "12,2", } }, + "01;p11=03" => { txt => "CONFIG_PEER_LIST_REQ", params => { + CHANNEL => "0,2", },}, + "01;p11=04" => { txt => "CONFIG_PARAM_REQ", params => { + CHANNEL => "00,2", + PEER_ADDRESS => "04,6", + PEER_CHANNEL => "10,2", + PARAM_LIST => "12,2", },}, + "01;p11=05" => { txt => "CONFIG_START", params => { + CHANNEL => "00,2", + PEER_ADDRESS => "04,6", + PEER_CHANNEL => "10,2", + PARAM_LIST => "12,2", } }, + "01;p11=06" => { txt => "CONFIG_END", params => { + CHANNEL => "0,2", } }, + "01;p11=08" => { txt => "CONFIG_WRITE_INDEX", params => { + CHANNEL => "0,2", + DATA => '4,,$val =~ s/(..)(..)/ $1:$2/g', } }, + "01;p11=0A" => { txt => "PAIR_SERIAL", params => { + SERIALNO => '04,,$val=pack("H*",$val)', } }, + "01;p11=0E" => { txt => "CONFIG_STATUS_REQUEST", params => { + CHANNEL => "0,2", } }, + + "02;p01=00" => { txt => "ACK"}, + "02;p01=01" => { txt => "ACK_STATUS", params => { + CHANNEL => "02,2", + STATUS => "04,2", + DOWN => '06,02,$val=(hex($val)&0x20)?1:0', + UP => '06,02,$val=(hex($val)&0x10)?1:0', + LOWBAT => '06,02,$val=(hex($val)&0x80)?1:0', + RSSI => '08,02,$val=(-1)*(hex($val))', }}, + "02;p01=02" => { txt => "ACK2"}, # smokeDetector pairing only? + "02;p01=04" => { txt => "ACK-proc", params => { + Para1 => "02,4", + Para2 => "06,4", + Para3 => "10,4", + Para4 => "14,2",}}, # remote? + "02;p01=80" => { txt => "NACK"}, + "02;p01=84" => { txt => "NACK_TARGET_INVALID"}, + "02" => { txt => "ACK/NACK_UNKNOWN "}, + + "02" => { txt => "Request AES", params => { #todo check data + DATA => "0," } }, + + "03" => { txt => "AES reply", params => { + DATA => "0," } }, + + "10;p01=01" => { txt => "INFO_PEER_LIST", params => { + PEER1 => '02,8,$val=CUL_HM_id2Name($val)', + PEER2 => '10,8,$val=CUL_HM_id2Name($val)', + PEER3 => '18,8,$val=CUL_HM_id2Name($val)', + PEER4 => '26,8,$val=CUL_HM_id2Name($val)'},}, + "10;p01=02" => { txt => "INFO_PARAM_RESPONSE_PAIRS", params => { + DATA => "2,", },}, + "10;p01=03" => { txt => "INFO_PARAM_RESPONSE_SEQ", params => { + OFFSET => "2,2", + DATA => "4,", },}, + "10;p01=04" => { txt => "INFO_PARAMETER_CHANGE", params => { + CHANNEL => "2,2", + PEER => '4,8,$val=CUL_HM_id2Name($val)', + PARAM_LIST => "12,2", + DATA => '14,,$val =~ s/(..)(..)/ $1:$2/g', } }, + "10;p01=06" => { txt => "INFO_ACTUATOR_STATUS", params => { + CHANNEL => "2,2", + STATUS => '4,2', + UNKNOWN => "6,2", + RSSI => '08,02,$val=(-1)*(hex($val))' } }, + "11;p02=0400" => { txt => "RESET" }, + "11;p01=02" => { txt => "SET" , params => { + CHANNEL => "02,2", + VALUE => "04,2", + RAMPTIME => '06,4,$val=CUL_HM_decodeTime16($val)', + DURATION => '10,4,$val=CUL_HM_decodeTime16($val)', } }, + "11;p01=80" => { txt => "LED" , params => { + CHANNEL => "02,2", + COLOR => "04,2", } }, + "11;p01=81" => { txt => "LEDall" , params => { + Led1To16 => '04,8,$val= join(":",sprintf("%b",hex($val))=~ /(.{2})/g)', + } }, + "12" => { txt => "HAVE_DATA"}, + "3E" => { txt => "SWITCH", params => { + DST => "00,6", + UNKNOWN => "06,2", + CHANNEL => "08,2", + COUNTER => "10,2", } }, + "3F" => { txt => "TimeStamp", params => { + UNKNOWN => "00,4", + TIME => "04,2", } }, + "40" => { txt => "REMOTE", params => { + BUTTON => '00,2,$val=(hex($val)&0x3F)', + LONG => '00,2,$val=(hex($val)&0x40)?1:0', + LOWBAT => '00,2,$val=(hex($val)&0x80)?1:0', + COUNTER => "02,2", } }, + "41" => { txt => "Sensor_event", params => { + BUTTON => '00,2,$val=(hex($val)&0x3F)', + LONG => '00,2,$val=(hex($val)&0x40)?1:0', + LOWBAT => '00,2,$val=(hex($val)&0x80)?1:0', + VALUE => '02,2,$val=(hex($val))', + NEXT => '04,2,$val=(hex($val))',} }, + "53" => { txt => "WaterSensor", params => { + CMD => "00,2", + SEQ => '02,2,$val=(hex($val))-64', + V1 => '08,2,$val=(hex($val))', + V2 => '10,2,$val=(hex($val))', + V3 => '12,2,$val=(hex($val))'} }, + "58" => { txt => "ClimateEvent", params => { + CMD => "00,2", + ValvePos => '02,2,$val=(hex($val))', } }, + "70" => { txt => "WeatherEvent", params => { + TEMP => '00,4,$val=((hex($val)&0x3FFF)/10)*((hex($val)&0x4000)?-1:1)', + HUM => '04,2,$val=(hex($val))', } }, + +); +############################################################ + +sub CUL_HM_Initialize($); +sub CUL_HM_Define($$); +sub CUL_HM_Undef($$); +sub CUL_HM_Parse($$); +sub CUL_HM_Get($@); +sub CUL_HM_fltCvT($); +sub CUL_HM_Set($@); +sub CUL_HM_infoUpdtDevData($$$); +sub CUL_HM_Pair(@); +sub CUL_HM_getConfig($$$$$); +sub CUL_HM_SndCmd($$); +sub CUL_HM_responseSetup($$); +sub CUL_HM_eventP($$); +sub CUL_HM_respPendRm($); +sub CUL_HM_respPendTout($); +sub CUL_HM_PushCmdStack($$); +sub CUL_HM_ProcessCmdStack($); +sub CUL_HM_Resend($); +sub CUL_HM_Id($); +sub CUL_HM_name2Hash($); +sub CUL_HM_name2Id(@); +sub CUL_HM_id2Name($); +sub CUL_HM_getDeviceHash($); +sub CUL_HM_DumpProtocol($$@); +sub CUL_HM_parseCommon(@); +sub CUL_HM_encodeTime8($); +sub CUL_HM_decodeTime8($); +sub CUL_HM_encodeTime16($); +sub CUL_HM_convTemp($); +sub CUL_HM_updtRegDisp($$$); +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 +#+++++++++++++++++ startup, init, definition+++++++++++++++++++++++++++++++++++ sub CUL_HM_Initialize($) { my ($hash) = @_; @@ -346,8 +1050,8 @@ sub CUL_HM_updateConfig($){ $hash->{channel_01} && $st ne "virtual" && $st ne "thermostat" ){$webCmd="getConfig"; - }elsif($st eq "blindActuator"){$webCmd="toggle:on:off:stop:statusRequest"; - }elsif($st eq "dimmer" ){$webCmd="toggle:on:off:statusRequest"; + }elsif($st eq "blindActuator"){$webCmd="toggle:on:off:up:down:stop:statusRequest"; + }elsif($st eq "dimmer" ){$webCmd="toggle:on:off:up:down: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"; @@ -371,7 +1075,7 @@ sub CUL_HM_updateConfig($){ $modules{CUL_HM}{helper}{updtCfgLst} = \@getConfList; CUL_HM_autoReadConfig("updateConfig"); } -sub CUL_HM_Define($$) {############################# +sub CUL_HM_Define($$) {############################## my ($hash, $def) = @_; my @a = split("[ \t][ \t]*", $def); my $HMid = uc($a[2]); @@ -411,7 +1115,7 @@ sub CUL_HM_Define($$) {############################# 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}; @@ -447,7 +1151,77 @@ sub CUL_HM_Rename($$$) {############################# } return; } +sub CUL_HM_Attr(@) {############################# + my ($cmd,$name, $attrName,$attrVal) = @_; + my @hashL; + if ($attrName eq "expert"){#[0,1,2] + $attr{$name}{expert} = $attrVal; + my $eHash = CUL_HM_name2Hash($name); + foreach my $chId (CUL_HM_getAssChnIds($name)){ + my $cHash = CUL_HM_id2Hash($chId); + push(@hashL,$cHash) if ($eHash ne $cHash); + } + push(@hashL,$eHash); + foreach my $hash (@hashL){ + my $exLvl = CUL_HM_getExpertMode($hash); + if ($exLvl eq "0"){# off + foreach my $rdEntry (keys %{$hash->{READINGS}}){ + my $rdEntryNew; + $rdEntryNew = ".".$rdEntry if ($rdEntry =~m /^RegL_/); + if ($rdEntry =~m /^R-/){ + my $reg = $rdEntry; + $reg =~ s/.*-//; + $rdEntryNew = ".".$rdEntry if($culHmRegDefine{$reg}{d} eq '0' ); + } + next if (!defined($rdEntryNew)); # no change necessary + delete $hash->{READINGS}{$rdEntryNew}; + $hash->{READINGS}{$rdEntryNew} = $hash->{READINGS}{$rdEntry}; + delete $hash->{READINGS}{$rdEntry}; + } + } + elsif ($exLvl eq "1"){# on: Only register values, no raw data + # move register to visible if available + foreach my $rdEntry (keys %{$hash->{READINGS}}){ + my $rdEntryNew; + $rdEntryNew = substr($rdEntry,1) if ($rdEntry =~m /^\.R-/); + $rdEntryNew = ".".$rdEntry if ($rdEntry =~m /^RegL_/); + next if (!$rdEntryNew); # no change necessary + delete $hash->{READINGS}{$rdEntryNew}; + $hash->{READINGS}{$rdEntryNew} = $hash->{READINGS}{$rdEntry}; + delete $hash->{READINGS}{$rdEntry}; + } + } + elsif ($exLvl eq "2"){# full - incl raw data + foreach my $rdEntry (keys %{$hash->{READINGS}}){ + my $rdEntryNew; + $rdEntryNew = substr($rdEntry,1) if (($rdEntry =~m /^\.RegL_/) || + ($rdEntry =~m /^\.R-/)); + next if (!$rdEntryNew); # no change necessary + delete $hash->{READINGS}{$rdEntryNew}; + $hash->{READINGS}{$rdEntryNew} = $hash->{READINGS}{$rdEntry}; + delete $hash->{READINGS}{$rdEntry}; + } + } + else{; + } + } + } + elsif($attrName eq "actCycle"){#"000:00" or 'off' + return if (CUL_HM_name2Id($name) eq $K_actDetID); + # Add to ActionDetector. Wait a little - config might not be finished + my @arr; + if(!$modules{CUL_HM}{helper}{updtCfgLst}){ + $modules{CUL_HM}{helper}{updtCfgLst} = \@arr; + } + push(@{$modules{CUL_HM}{helper}{updtCfgLst}}, $name); + RemoveInternalTimer("updateConfig"); + InternalTimer(gettimeofday()+5,"CUL_HM_updateConfig", "updateConfig", 0); + } + return; +} + +#+++++++++++++++++ msg receive, parsing++++++++++++++++++++++++++++++++++++++++ sub CUL_HM_Parse($$) {############################# my ($iohash, $msg) = @_; my $id = CUL_HM_Id($iohash); @@ -598,15 +1372,15 @@ sub CUL_HM_Parse($$) {############################# ( $1, hex($2)); $vp = int($vp/2.56+0.5); # valve position in % my $chnHash = $modules{CUL_HM}{defptr}{$src.$chn}; - if($chnHash){ - push @entities, - CUL_HM_UpdtReadSingle($chnHash,"state","$vp %",1); - } + push @entities,CUL_HM_UpdtReadSingle($chnHash,"state","$vp %",1) + if($chnHash); push @event, "actuator:$vp %"; # Set the valve state too, without an extra trigger - push @entities, - CUL_HM_UpdtReadSingle($dhash,"state","set_$vp %",1) if($dhash); + push @entities,CUL_HM_UpdtReadBulk($dhash,1, + "state:set_$vp %", + "ValveDesired:$vp %") + if($dhash); } elsif(($msgType eq '02' &&$sType eq '01')|| # ackStatus ($msgType eq '10' &&$sType eq '06')){ # infoStatus @@ -747,8 +1521,6 @@ sub CUL_HM_Parse($$) {############################# } } elsif($model eq "HM-CC-VD") { ############################################### - # CMD:8202 SRC:13F251 DST:15B50D 010100002A - # status ACK to controlling HM-CC-TC if($msgType eq "02" && $p =~ m/^(..)(..)(..)(..)/) {#subtype+chn+value+err my ($chn,$vp, $err) = (hex($2),hex($3), hex($4)); $chn = sprintf("%02X",$chn&0x3f); @@ -758,9 +1530,7 @@ sub CUL_HM_Parse($$) {############################# $shash = $modules{CUL_HM}{defptr}{"$src$chn"} if($modules{CUL_HM}{defptr}{"$src$chn"}); - # Status-Byte Auswertung - - my $stErr = ($err >>1) & 0x7; + my $stErr = ($err >>1) & 0x7; # Status-Byte Evaluation push @event,"battery:".(($stErr == 4)?"critical":($err&0x80?"low":"ok")); if (!$stErr){#remove both conditions push @event, "motorErr:ok"; @@ -774,10 +1544,20 @@ sub CUL_HM_Parse($$) {############################# push @event, "motor:opening" if(($err&0x30) == 0x10); push @event, "motor:closing" if(($err&0x30) == 0x20); push @event, "motor:stop" if(($err&0x30) == 0x00); - push @event, ""; # just in case - mark message as confirmed + + #VD hang detection + my $des = ReadingsVal($name, "ValveDesired", ""); + $des =~ s/ .*//; # remove unit + if (defined $des && $des != $vp && ($err&0x30) == 0x00){ + push @event, "operState:errorTargetNotMet"; + push @event, "operStateErrCnt:". + (ReadingsVal($name,"ValveStateErrCnt","0")+1); + } + else{ + push @event, "operState:".((($err&0x30) == 0x00)?"onTarget":"adjusting"); + } } - # CMD:A010 SRC:13F251 DST:5D24C9 0401 00000000 05 09:00 0A:07 00:00 # status change report to paired central unit #read List5 reg 09 (offset) and 0A (err-pos) @@ -1348,642 +2128,228 @@ sub CUL_HM_Parse($$) {############################# } return $name ;#general notification to the device } - -##----------definitions for register settings----------------- - # definition of Register for all devices - # a: address, incl bits 13.4 4th bit in reg 13 - # s: size 2.0 = 2 byte, 0.5 = 5 bit. Max is 4.0!! - # l: list number. List0 will be for channel 0 - # List 1 will set peer to 00000000 - # list 3 will need the input of a peer! - # min: minimal input value - # max: maximal input value - # c: conversion, will point to a routine for calculation - # f: factor to be used if c = 'factor' - # u: unit for description - # t: txt description - # lit: if the command is a literal options will be entered here - # d: if '1' the register will appear in Readings - # -my %culHmRegDefShLg = (# register that are available for short AND long button press. Will be merged to rgister list at init -#blindActuator mainly - ActionType =>{a=> 10.0,s=>0.2,l=>3,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{off=>0,jmpToTarget=>1,toggleToCnt=>2,toggleToCntInv=>3}}, - OffTimeMode =>{a=> 10.6,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"off time mode",lit=>{absolut=>0,minimal=>1}}, - OnTimeMode =>{a=> 10.7,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"on time mode" ,lit=>{absolut=>0,minimal=>1}}, - MaxTimeF =>{a=> 29.0,s=>1.0,l=>3,min=>0 ,max=>25.4 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>0,t=>"max time first direction"}, - DriveMode =>{a=> 31.0,s=>1.0,l=>3,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{direct=>0,viaUpperEnd=>1,viaLowerEnd=>2,viaNextEnd=>3}}, -#dimmer mainly - OnDly =>{a=> 6.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"on delay "}, - OnTime =>{a=> 7.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"on time"}, - OffDly =>{a=> 8.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"off delay"}, - OffTime =>{a=> 9.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"off time"}, - - ActionTypeDim =>{a=> 10.0,s=>0.4,l=>3,min=>0 ,max=>8 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{off=>0,jmpToTarget=>1,toggleToCnt=>2,toggleToCntInv=>3,upDim=>4,downDim=>5,toggelDim=>6,toggelDimToCnt=>7,toggelDimToCntInv=>8}}, - OffDlyBlink =>{a=> 14.5,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{off=>0,on=>1}}, - OnLvlPrio =>{a=> 14.6,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{high=>0,low=>1}}, - OnDlyMode =>{a=> 14.7,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{setToOff=>0,NoChange=>1}}, - OffLevel =>{a=> 15.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"PowerLevel Off"}, - OnMinLevel =>{a=> 16.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"minimum PowerLevel"}, - OnLevel =>{a=> 17.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>1,t=>"PowerLevel on"}, - - OffLevelKm =>{a=> 15.0,s=>1.0,l=>3,min=>0 ,max=>127.5 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"OnLevel 127.5=locked"}, - OnLevelKm =>{a=> 17.0,s=>1.0,l=>3,min=>0 ,max=>127.5 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"OnLevel 127.5=locked"}, - OnRampOnSp =>{a=> 34.0,s=>1.0,l=>3,min=>0 ,max=>1 ,c=>'factor' ,f=>200 ,u=>'s' ,d=>0,t=>"Ramp On speed"}, - OnRampOffSp =>{a=> 35.0,s=>1.0,l=>3,min=>0 ,max=>1 ,c=>'factor' ,f=>200 ,u=>'s' ,d=>0,t=>"Ramp Off speed"}, - - RampSstep =>{a=> 18.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"rampStartStep"}, - RampOnTime =>{a=> 19.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"rampOnTime"}, - RampOffTime =>{a=> 20.0,s=>1.0,l=>3,min=>0 ,max=>111600 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"rampOffTime"}, - DimMinLvl =>{a=> 21.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"dimMinLevel"}, - DimMaxLvl =>{a=> 22.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"dimMaxLevel"}, - DimStep =>{a=> 23.0,s=>1.0,l=>3,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>0,t=>"dimStep"}, - - OffDlyNewTime =>{a=> 25.0,s=>1.0,l=>3,min=>0.1,max=>25.6 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>0,t=>"off delay new time"}, - OffDlyNewTime =>{a=> 26.0,s=>1.0,l=>3,min=>0.1,max=>25.6 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>0,t=>"off delay old time"}, - DimElsOffTimeMd =>{a=> 38.6,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{absolut=>0,minimal=>1}}, - DimElsOnTimeMd =>{a=> 38.7,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{absolut=>0,minimal=>1}}, - DimElsActionType=>{a=> 38.0,s=>0.4,l=>3,min=>0 ,max=>8 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{off=>0,jmpToTarget=>1,toggleToCnt=>2,toggleToCntInv=>3,upDim=>4,downDim=>5,toggelDim=>6,toggelDimToCnt=>7,toggelDimToCntInv=>8}}, -#output Unit - ActType =>{a=> 36 ,s=>1 ,l=>3,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Action type(LED or Tone)"}, - ActNum =>{a=> 37 ,s=>1 ,l=>3,min=>1 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Action Number"}, - Intense =>{a=> 43 ,s=>1 ,l=>3,min=>10 ,max=>255 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Volume",lit=>{vol_0=>255,vol_1=>250,vol_2=>246,vol_3=>240,vol_4=>234,vol_5=>227,vol_6=>218,vol_7=>207,vol_8=>190,vol_9=>162,vol_00=>10}}, -# statemachines - BlJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from On" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, - BlJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, - BlJtDlyOn =>{a=> 12.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOn" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, - BlJtDlyOff =>{a=> 12.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOff",lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, - BlJtRampOn =>{a=> 13.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from rampOn" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, - BlJtRampOff =>{a=> 13.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from rampOff" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, - BlJtRefOn =>{a=> 28.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from refOn" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, - BlJtRefOff =>{a=> 28.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from refOff" ,lit=>{no=>0,dlyOn=>1,refOn=>2,on=>3,dlyOff=>4,refOff=>5,off=>6,rampOn=>8,rampOff=>9}}, +sub CUL_HM_parseCommon(@){##################################################### + # parsing commands that are device independant + my ($msgId,$msgFlag,$msgType,$src,$dst,$p) = @_; + my $shash = $modules{CUL_HM}{defptr}{$src}; + my $dhash = $modules{CUL_HM}{defptr}{$dst}; + return "" if(!$shash->{DEF});# this should be from ourself - DimJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from On" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimJtDlyOn =>{a=> 12.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOn" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimJtDlyOff =>{a=> 12.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOff",lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimJtRampOn =>{a=> 13.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from rampOn" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimJtRampOff =>{a=> 13.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from rampOff" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - - DimElsJtOn =>{a=> 39.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from On" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimElsJtOff =>{a=> 39.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from Off" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimElsJtDlyOn =>{a=> 40.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from delayOn" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimElsJtDlyOff =>{a=> 40.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from delayOff",lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimElsJtRampOn =>{a=> 41.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from rampOn" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, - DimElsJtRampOff =>{a=> 41.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"else Jump from rampOff" ,lit=>{no=>0,dlyOn=>1,rampOn=>2,on=>3,dlyOff=>4,rampOff=>5,Off=>6}}, + my $pendType = $shash->{helper}{respWait}{Pending}? + $shash->{helper}{respWait}{Pending}:""; + #------------ parse message flag for start processing command Stack + # TC wakes up with 8270, not with A258 + # VD wakes up with 8202 + if( $shash->{cmdStack} && + ((hex($msgFlag) & 0xA2) == 0x82) && + (CUL_HM_getRxType($shash) & 0x08)){ #wakeup ##### + #send wakeup and process command stack + CUL_HM_SndCmd($shash, '++A112'.CUL_HM_IOid($shash).$src); + CUL_HM_ProcessCmdStack($shash); + } - SwJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from On" ,lit=>{no=>0,dlyOn=>1,on=>3,dlyOff=>4,off=>6}}, - SwJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,dlyOn=>1,on=>3,dlyOff=>4,off=>6}}, - SwJtDlyOn =>{a=> 12.0,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOn" ,lit=>{no=>0,dlyOn=>1,on=>3,dlyOff=>4,off=>6}}, - SwJtDlyOff =>{a=> 12.4,s=>0.4,l=>3,min=>0 ,max=>6 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from delayOff",lit=>{no=>0,dlyOn=>1,on=>3,dlyOff=>4,off=>6}}, - - KeyJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>7 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from On" ,lit=>{no=>0,dlyUnlock=>1,rampUnlock=>2,lock=>3,dlyLock=>4,rampLock=>5,lock=>6,open=>8}}, - KeyJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>7 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,dlyUnlock=>1,rampUnlock=>2,lock=>3,dlyLock=>4,rampLock=>5,lock=>6,open=>8}}, - - WinJtOn =>{a=> 11.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,rampOnDly=>1,rampOn=>2,on=>3,ramoOffDly=>4,rampOff=>5,Off=>6,rampOnFast=>8,rampOffFast=>9}}, - WinJtOff =>{a=> 11.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,rampOnDly=>1,rampOn=>2,on=>3,ramoOffDly=>4,rampOff=>5,Off=>6,rampOnFast=>8,rampOffFast=>9}}, - WinJtRampOn =>{a=> 13.0,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,rampOnDly=>1,rampOn=>2,on=>3,ramoOffDly=>4,rampOff=>5,Off=>6,rampOnFast=>8,rampOffFast=>9}}, - WinJtRampOff =>{a=> 13.4,s=>0.4,l=>3,min=>0 ,max=>9 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jump from Off" ,lit=>{no=>0,rampOnDly=>1,rampOn=>2,on=>3,ramoOffDly=>4,rampOff=>5,Off=>6,rampOnFast=>8,rampOffFast=>9}}, - - CtRampOn =>{a=> 1.0,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from rampOn" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, - CtRampOff =>{a=> 1.4,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from rampOff" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, - CtDlyOn =>{a=> 2.0,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from delayOn" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, - CtDlyOff =>{a=> 2.4,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from delayOff" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, - CtOn =>{a=> 3.0,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from On" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, - CtOff =>{a=> 3.4,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from Off" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, - CtValLo =>{a=> 4.0,s=>1 ,l=>3,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Condition value low for CT table" }, - CtValHi =>{a=> 5.0,s=>1 ,l=>3,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Condition value high for CT table" }, - CtRefOn =>{a=> 28.0,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from refOn" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, - CtRefOff =>{a=> 28.4,s=>0.4,l=>3,min=>0 ,max=>5 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Jmp on condition from refOff" ,lit=>{geLo=>0,geHi=>1,ltLo=>2,ltHi=>3,between=>4,outside=>5}}, -); - -my %culHmRegDefine = ( - intKeyVisib =>{a=> 2.7,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>'visibility of internal channel',lit=>{invisib=>0,visib=>1}}, - pairCentral =>{a=> 10.0,s=>3.0,l=>0,min=>0 ,max=>16777215,c=>'hex' ,f=>'' ,u=>'' ,d=>1,t=>'pairing to central'}, -#blindActuator mainly - lgMultiExec =>{a=>138.5,s=>0.1,l=>3,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"multiple execution per repeat of long trigger" ,lit=>{off=>0,on=>1}}, - driveDown =>{a=> 11.0,s=>2.0,l=>1,min=>0 ,max=>6000.0 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>1,t=>"drive time up"}, - driveUp =>{a=> 13.0,s=>2.0,l=>1,min=>0 ,max=>6000.0 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>1,t=>"drive time up"}, - driveTurn =>{a=> 15.0,s=>1.0,l=>1,min=>0 ,max=>6000.0 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>1,t=>"fliptime up <=>down"}, - refRunCounter =>{a=> 16.0,s=>1.0,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"reference run counter"}, - -#repeater - compMode =>{a=> 23.0,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"compatibility moden" ,lit=>{off=>0,on=>1}}, -#remote mainly - language =>{a=> 7.0,s=>1.0,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Language" ,lit=>{English=>0,German=>1}}, - backAtKey =>{a=> 13.7,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight at keystroke",lit=>{off=>0,on=>1}}, - backAtMotion =>{a=> 13.6,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight at motion" ,lit=>{off=>0,on=>1}}, - backAtCharge =>{a=> 13.5,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight at Charge" ,lit=>{off=>0,on=>1}}, - stbyTime =>{a=> 14.0,s=>1.0,l=>0,min=>1 ,max=>99 ,c=>'' ,f=>'' ,u=>'s' ,d=>1,t=>"Standby Time"}, - backOnTime =>{a=> 14.0,s=>1.0,l=>0,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'s' ,d=>1,t=>"Backlight On Time"}, - - longPress =>{a=> 4.4,s=>0.4,l=>1,min=>0.3,max=>1.8 ,c=>'m10s3' ,f=>'' ,u=>'s' ,d=>0,t=>"time to detect key long press"}, - dblPress =>{a=> 9.0,s=>0.4,l=>1,min=>0 ,max=>1.5 ,c=>'factor' ,f=>10 ,u=>'s' ,d=>0,t=>"time to detect double press"}, - msgShowTime =>{a=> 45.0,s=>1.0,l=>1,min=>0.0,max=>120 ,c=>'factor' ,f=>2 ,u=>'s' ,d=>1,t=>"Message show time(RC19). 0=always on"}, - beepAtAlarm =>{a=> 46.0,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Beep Alarm" ,lit=>{none=>0,tone1=>1,tone2=>2,tone3=>3}}, - beepAtService =>{a=> 46.2,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Beep Service" ,lit=>{none=>0,tone1=>1,tone2=>2,tone3=>3}}, - beepAtInfo =>{a=> 46.4,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Beep Info" ,lit=>{none=>0,tone1=>1,tone2=>2,tone3=>3}}, - backlAtAlarm =>{a=> 47.0,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight Alarm" ,lit=>{off=>0,on=>1,blinkSlow=>2,blinkFast=>3}}, - backlAtService =>{a=> 47.2,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight Service" ,lit=>{off=>0,on=>1,blinkSlow=>2,blinkFast=>3}}, - backlAtInfo =>{a=> 47.4,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Backlight Info" ,lit=>{off=>0,on=>1,blinkSlow=>2,blinkFast=>3}}, - - peerNeedsBurst =>{a=> 1.0,s=>0.1,l=>4,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"peer expects burst",lit=>{off=>0,on=>1}}, - expectAES =>{a=> 1.7,s=>0.1,l=>4,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"expect AES" ,lit=>{off=>0,on=>1}}, - lcdSymb =>{a=> 2.0,s=>0.1,l=>4,min=>0 ,max=>255 ,c=>'hex' ,f=>'' ,u=>'' ,d=>0,t=>"bitmask which symbol to display on message"}, - lcdLvlInterp =>{a=> 3.0,s=>0.1,l=>4,min=>0 ,max=>255 ,c=>'hex' ,f=>'' ,u=>'' ,d=>0,t=>"bitmask fro symbols"}, -#dimmer mainly - loadErrCalib =>{a=> 18.0,s=>1.0,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>"" ,d=>0,t=>"Load Error Calibration"}, - transmitTryMax =>{a=> 48.0,s=>1.0,l=>1,min=>1 ,max=>10 ,c=>'' ,f=>'' ,u=>"" ,d=>0,t=>"max message re-transmit"}, - loadAppearBehav =>{a=> 49.0,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>"" ,d=>1,t=>"behavior on load appearence at restart",lit=>{off=>0,last=>1,btnPress=>2,btnPressIfWasOn=>3}}, - ovrTempLvl =>{a=> 50.0,s=>1.0,l=>1,min=>30 ,max=>100 ,c=>'' ,f=>'' ,u=>"C" ,d=>0,t=>"overtemperatur level"}, - fuseDelay =>{a=> 51.0,s=>1.0,l=>1,min=>0 ,max=>2.55 ,c=>'factor' ,f=>100 ,u=>"s" ,d=>0,t=>"fuse delay"}, - redTempLvl =>{a=> 52.0,s=>1.0,l=>1,min=>30 ,max=>100 ,c=>'' ,f=>'' ,u=>"C" ,d=>0,t=>"reduced temperatur recover"}, - redLvl =>{a=> 53.0,s=>1.0,l=>1,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>"%" ,d=>0,t=>"reduced power level"}, - powerUpAction =>{a=> 86.0,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>"" ,d=>1,t=>"behavior on power up" ,lit=>{off=>0,on=>1}}, - statusInfoMinDly=>{a=> 87.0,s=>0.5,l=>1,min=>0.5,max=>15.5 ,c=>'factor' ,f=>2 ,u=>"s" ,d=>0,t=>"status message min delay"}, - statusInfoRandom=>{a=> 87.5,s=>0.3,l=>1,min=>0 ,max=>7 ,c=>'' ,f=>'' ,u=>"s" ,d=>0,t=>"status message random delay"}, - characteristic =>{a=> 88.0,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>"" ,d=>1,t=>"" ,lit=>{linear=>0,square=>1}}, - logicCombination=>{a=> 89.0,s=>0.5,l=>1,min=>0 ,max=>16 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{inactive=>0,or=>1,and=>2,xor=>3,nor=>4,nand=>5,orinv=>6,andinv=>7,plus=>8,minus=>9,mul=>10,plusinv=>11,minusinv=>12,mulinv=>13,invPlus=>14,invMinus=>15,invMul=>16}}, -# logicCombination=>{a=> 89.0,s=>0.5,l=>1,min=>0 ,max=>16 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"". -# "inactive=>unused\n". -# "or =>max(state,chan)\n". -# "and =>min(state,chan)\n". -# "xor =>0 if both are != 0, else max\n". -# "nor =>100-max(state,chan)\n". -# "nand =>100-min(state,chan)\n". -# "orinv =>max((100-chn),state)\n". -# "andinv =>min((100-chn),state)\n". -# "plus =>state + chan\n". -# "minus =>state - chan\n". -# "mul =>state * chan\n". -# "plusinv =>state + 100 - chan\n". -# "minusinv=>state - 100 + chan\n". -# "mulinv =>state * (100 - chan)\n". -# "invPlus =>100 - state - chan\n". -# "invMinus=>100 - state + chan\n". -# "invMul =>100 - state * chan\n",lit=>{inactive=>0,or=>1,and=>2,xor=>3,nor=>4,nand=>5,orinv=>6,andinv=>7,plus=>8,minus=>9,mul=>10,plusinv=>11,minusinv=>12,mulinv=>13,invPlus=>14,invMinus=>15,invMul=>16}}, -# -# -#CC-TC - backlOnTime =>{a=> 5.0,s=>0.6,l=>0,min=>1 ,max=>25 ,c=>"" ,f=>'' ,u=>'s' ,d=>0,t=>"Backlight ontime"}, - backlOnMode =>{a=> 5.6,s=>0.2,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Backlight mode" ,lit=>{off=>0,auto=>1}}, - btnLock =>{a=> 15 ,s=>1 ,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Button Lock" ,lit=>{unlock=>0,lock=>1}}, - - dispTempHum =>{a=> 1.0,s=>0.1,l=>5,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{temp=>0,tempHumidity=>1}}, - dispTempInfo =>{a=> 1.1,s=>0.1,l=>5,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{actual=>0,setPoint=>1}}, - dispTempUnit =>{a=> 1.2,s=>0.1,l=>5,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{Celsius=>0,Fahrenheit=>1}}, - mdTempReg =>{a=> 1.3,s=>0.2,l=>5,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{manual=>0,auto=>1,central=>2,party=>3}}, - decalDay =>{a=> 1.5,s=>0.3,l=>5,min=>0 ,max=>7 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"Decalc weekday" ,lit=>{sat=>0,sun=>1,mon=>2,tue=>3,wed=>4,thu=>5,fri=>6}}, - mdTempValve =>{a=> 2.6,s=>0.2,l=>5,min=>0 ,max=>2 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"" ,lit=>{auto=>0,close=>1,open=>2}}, - tempComfort =>{a=> 3 ,s=>0.6,l=>5,min=>6 ,max=>30 ,c=>'factor' ,f=>2 ,u=>'C' ,d=>1,t=>"comfort temp value"}, - tempLower =>{a=> 4 ,s=>0.6,l=>5,min=>6 ,max=>30 ,c=>'factor' ,f=>2 ,u=>'C' ,d=>1,t=>"comfort temp value"}, - tempWinOpen =>{a=> 5 ,s=>0.6,l=>5,min=>6 ,max=>30 ,c=>'factor' ,f=>2 ,u=>'C' ,d=>1,t=>"Temperature for Win open !chan 3 only!"}, - tempParty =>{a=> 6 ,s=>0.6,l=>5,min=>6 ,max=>30 ,c=>'factor' ,f=>2 ,u=>'C' ,d=>1,t=>"Temperature for Party"}, - decalMin =>{a=> 8 ,s=>0.3,l=>5,min=>0 ,max=>50 ,c=>'factor' ,f=>0.1 ,u=>'min' ,d=>1,t=>"Decalc min"}, - decalHr =>{a=> 8.3,s=>0.5,l=>5,min=>0 ,max=>23 ,c=>'' ,f=>'' ,u=>'h' ,d=>1,t=>"Decalc hour"}, - partyEndHr =>{a=> 97 ,s=>0.6,l=>6,min=>0 ,max=>23 ,c=>'' ,f=>'' ,u=>'h' ,d=>1,t=>"Party end Hour"}, - partyEndMin =>{a=> 97.7,s=>0.1,l=>6,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'min' ,d=>1,t=>"Party end min",lit=>{"00"=>0,"30"=>1}}, - partyEndDay =>{a=> 98 ,s=>1 ,l=>6,min=>0 ,max=>200 ,c=>'' ,f=>'' ,u=>'d' ,d=>1,t=>"Party end Day"}, -#Thermal-cc-VD - valveOffset =>{a=> 9 ,s=>0.5,l=>5,min=>0 ,max=>25 ,c=>'' ,f=>'' ,u=>'%' ,d=>1,t=>"Valve offset"}, # size actually 0.5 - valveError =>{a=> 10 ,s=>1 ,l=>5,min=>0 ,max=>99 ,c=>'' ,f=>'' ,u=>'%' ,d=>1,t=>"Valve position when error"},# size actually 0.7 -#SCD - msgScdPosA =>{a=> 32.6,s=>0.2,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position A",lit=>{noMsg=>0,lvlNormal=>1}}, - msgScdPosB =>{a=> 32.4,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position B",lit=>{noMsg=>0,lvlNormal=>1,lvlAddStrong=>2,lvlAdd=>3}}, - msgScdPosC =>{a=> 32.2,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position C",lit=>{noMsg=>0,lvlNormal=>1,lvlAddStrong=>2,lvlAdd=>3}}, - msgScdPosD =>{a=> 32.0,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position D",lit=>{noMsg=>0,lvlNormal=>1,lvlAddStrong=>2,lvlAdd=>3}}, - evtFltrTime =>{a=> 35.0,s=>1 ,l=>1,min=>600,max=>1200 ,c=>'' ,f=>1.6 ,u=>'s' ,d=>0,t=>"Event filter time",},#todo check calculation -#rhs - different literals - msgRhsPosA =>{a=> 32.6,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position A",lit=>{noMsg=>0,closed=>1,open=>2,tilted=>3}}, - msgRhsPosB =>{a=> 32.4,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position B",lit=>{noMsg=>0,closed=>1,open=>2,tilted=>3}}, - msgRhsPosC =>{a=> 32.2,s=>0.2,l=>1,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position C",lit=>{noMsg=>0,closed=>1,open=>2,tilted=>3}}, - evtDly =>{a=> 33 ,s=>1 ,l=>1,min=>0 ,max=>7620 ,c=>'factor' ,f=>1.6 ,u=>'s' ,d=>0,t=>"Event delay time",},#todo check calculation -# keymatic/winmatic secific register - signal =>{a=> 3.4,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Confirmation beep" ,lit=>{off=>0,on=>1}}, - signalTone =>{a=> 3.6,s=>0.2,l=>0,min=>0 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"" ,lit=>{low=>0,mid=>1,high=>2,veryHigh=>3}}, - keypressSignal =>{a=> 3.0,s=>0.1,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Keypress beep" ,lit=>{off=>0,on=>1}}, - holdTime =>{a=> 20 ,s=>1, l=>1,min=>0 ,max=>8.16 ,c=>'factor' ,f=>31.25 ,u=>'s' ,d=>0,t=>"Holdtime for door opening"}, - holdPWM =>{a=> 21 ,s=>1, l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"Holdtime pulse wide modulation"}, - setupDir =>{a=> 22 ,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Rotation direction for locking",lit=>{right=>0,left=>1}}, - setupPosition =>{a=> 23 ,s=>1 ,l=>1,min=>0 ,max=>3000 ,c=>'factor' ,f=>0.06666 ,u=>'deg' ,d=>1,t=>"Rotation angle neutral position"}, - angelOpen =>{a=> 24 ,s=>1 ,l=>1,min=>0 ,max=>3000 ,c=>'factor' ,f=>0.06666 ,u=>'deg' ,d=>1,t=>"Door opening angle"}, - angelMax =>{a=> 25 ,s=>1 ,l=>1,min=>0 ,max=>3000 ,c=>'factor' ,f=>0.06666 ,u=>'deg' ,d=>1,t=>"Angle maximum"}, - angelLocked =>{a=> 26 ,s=>1 ,l=>1,min=>0 ,max=>3000 ,c=>'factor' ,f=>0.06666 ,u=>'deg' ,d=>1,t=>"Angle Locked position"}, - pullForce =>{a=> 28 ,s=>1 ,l=>1,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>1,t=>"pull force level"}, - pushForce =>{a=> 29 ,s=>1 ,l=>1,min=>0 ,max=>100 ,c=>'factor' ,f=>2 ,u=>'%' ,d=>1,t=>"push force level"}, - tiltMax =>{a=> 30 ,s=>1 ,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"maximum tilt level"}, - ledFlashUnlocked=>{a=> 31.3,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"LED blinks when not locked",lit=>{off=>0,on=>1}}, - ledFlashLocked =>{a=> 31.6,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"LED blinks when locked" ,lit=>{off=>0,on=>1}}, -# sec_mdir - cyclicInfoMsg =>{a=> 9 ,s=>1 ,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"cyclic message",lit=>{off=>0,on=>1}}, - sabotageMsg =>{a=> 16.0,s=>1 ,l=>0,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"enable sabotage message" ,lit=>{off=>0,on=>1}}, - lowBatLimit =>{a=> 18.0,s=>1 ,l=>0,min=>10 ,max=>12 ,c=>'factor' ,f=>10 ,u=>'V' ,d=>1,t=>"low batterie limit"}, - batDefectLimit =>{a=> 19.0,s=>1 ,l=>0,min=>0.1,max=>2 ,c=>'factor' ,f=>100 ,u=>'Ohm' ,d=>1,t=>"batterie defect detection"}, - transmDevTryMax =>{a=> 20.0,s=>1.0,l=>0,min=>1 ,max=>10 ,c=>'' ,f=>'' ,u=>'' ,d=>0,t=>"max message re-transmit"}, - localResDis =>{a=> 24.0,s=>1.0,l=>0,min=>1 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"local reset disable" ,lit=>{off=>0,on=>1}}, - - waterUppThr =>{a=> 6.0,s=>1 ,l=>1,min=>0 ,max=>256 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"water upper threshold"}, - waterlowThr =>{a=> 7.0,s=>1 ,l=>1,min=>0 ,max=>256 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"water lower threshold"}, - caseDesign =>{a=> 90.0,s=>1 ,l=>1,min=>1 ,max=>3 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"case desing" ,lit=>{verticalBarrel=>1,horizBarrel=>2,rectangle=>3}}, - caseHigh =>{a=> 94.0,s=>2 ,l=>1,min=>100,max=>10000 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>"case hight"}, - fillLevel =>{a=> 98.0,s=>2 ,l=>1,min=>100,max=>300 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>"fill level"}, - caseWidth =>{a=>102.0,s=>2 ,l=>1,min=>100,max=>10000 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>"case width"}, - caseLength =>{a=>106.0,s=>2 ,l=>1,min=>100,max=>10000 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>"case length"}, - meaLength =>{a=>108.0,s=>2 ,l=>1,min=>110,max=>310 ,c=>'' ,f=>'' ,u=>'cm' ,d=>1,t=>""}, - useCustom =>{a=>110.0,s=>1 ,l=>1,min=>110,max=>310 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"use custom" ,lit=>{off=>0,on=>1}}, - - fillLvlUpThr =>{a=> 4.0,s=>1 ,l=>4,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"fill level upper threshold"}, - fillLvlLoThr =>{a=> 5.0,s=>1 ,l=>4,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"fill level lower threshold"}, - - evtFltrPeriod =>{a=> 1.0,s=>0.4,l=>1,min=>0.5,max=>7.5 ,c=>'factor' ,f=>2 ,u=>'s' ,d=>1,t=>"event filter period"}, - evtFltrNum =>{a=> 1.4,s=>0.4,l=>1,min=>1 ,max=>15 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"sensitivity - read sach n-th puls"}, - minInterval =>{a=> 2.0,s=>0.3,l=>1,min=>0 ,max=>4 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"minimum interval in sec" ,lit=>{15=>0,30=>1,60=>2,120=>3,240=>4}}, - captInInterval =>{a=> 2.3,s=>0.1,l=>1,min=>0 ,max=>1 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"capture within interval" ,lit=>{off=>0,on=>1}}, - brightFilter =>{a=> 2.4,s=>0.4,l=>1,min=>0 ,max=>7 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"brightness filter - ignore light at night"}, - msgScPosA =>{a=> 32.6,s=>0.2,l=>1,min=>0 ,max=>2 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position A",lit=>{noMsg=>0,closed=>1,open=>2}}, - msgScPosB =>{a=> 32.4,s=>0.2,l=>1,min=>0 ,max=>2 ,c=>'lit' ,f=>'' ,u=>'' ,d=>0,t=>"Message for position B",lit=>{noMsg=>0,closed=>1,open=>2}}, - eventDlyTime =>{a=> 33 ,s=>1 ,l=>1,min=>0 ,max=>7620 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>1,t=>"event delay time"}, - ledOnTime =>{a=> 34 ,s=>1 ,l=>1,min=>0 ,max=>1.275 ,c=>'factor' ,f=>200 ,u=>'s' ,d=>0,t=>"LED ontime"}, - eventFilterTime =>{a=> 35 ,s=>1 ,l=>1,min=>0 ,max=>7620 ,c=>'fltCvT' ,f=>'' ,u=>'s' ,d=>0,t=>"evetn filter time"}, - -# weather units - stormUpThresh =>{a=> 6 ,s=>1 ,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"Storm upper threshold"}, - stormLowThresh =>{a=> 7 ,s=>1 ,l=>1,min=>0 ,max=>255 ,c=>'' ,f=>'' ,u=>'' ,d=>1,t=>"Storm lower threshold"}, -# others - localResetDis =>{a=> 7 ,s=>1 ,l=>1,min=>0 ,max=>255 ,c=>'lit' ,f=>'' ,u=>'' ,d=>1,t=>"LocalReset disable",lit=>{off=>0,on=>1}}, - ); - -my %culHmRegGeneral = ( - intKeyVisib=>1,pairCentral=>1, - ); -my %culHmRegType = ( - remote =>{expectAES =>1,peerNeedsBurst =>1,dblPress =>1,longPress =>1}, - blindActuator =>{driveUp =>1,driveDown =>1,driveTurn =>1,refRunCounter =>1, - transmitTryMax =>1,statusInfoMinDly=>1,statusInfoRandom=>1, # nt present in all files - MaxTimeF =>1, - OnDly =>1,OnTime =>1,OffDly =>1,OffTime =>1, - OffLevel =>1,OnLevel =>1, - ActionType =>1,OnTimeMode =>1,OffTimeMode =>1,DriveMode =>1, - BlJtOn =>1,BlJtOff =>1,BlJtDlyOn =>1,BlJtDlyOff =>1, - BlJtRampOn =>1,BlJtRampOff =>1,BlJtRefOn =>1,BlJtRefOff =>1, - CtValLo =>1,CtValHi =>1, - CtOn =>1,CtDlyOn =>1,CtRampOn =>1,CtRefOn =>1, - CtOff =>1,CtDlyOff =>1,CtRampOff =>1,CtRefOff =>1, - lgMultiExec =>1, - }, - dimmer =>{transmitTryMax =>1,statusInfoMinDly=>1,statusInfoRandom=>1,powerUpAction =>1, - ovrTempLvl =>1,redTempLvl =>1,redLvl =>1,fuseDelay =>1,#not dim.L - OnDly =>1,OnTime =>1,OffDly =>1,OffTime =>1, - OffDlyBlink =>1,OnLvlPrio =>1,OnDlyMode =>1, - ActionTypeDim =>1,OnTimeMode =>1,OffTimeMode =>1, - OffLevel =>1,OnMinLevel =>1,OnLevel =>1, - RampSstep =>1,RampOnTime =>1,RampOffTime =>1, - DimMinLvl =>1,DimMaxLvl =>1,DimStep =>1, - DimJtOn =>1,DimJtOff =>1,DimJtDlyOn =>1, - DimJtDlyOff =>1,DimJtRampOn =>1,DimJtRampOff =>1, - CtValLo =>1,CtValHi =>1, - CtOn =>1,CtDlyOn =>1,CtRampOn =>1, - CtOff =>1,CtDlyOff =>1,CtRampOff =>1, - OffDlyNewTime =>1,OffDlyNewTime =>1, - DimElsOffTimeMd =>1,DimElsOnTimeMd =>1, - DimElsActionType=>1, - DimElsJtOn =>1,DimElsJtOff =>1,DimElsJtDlyOn =>1, - DimElsJtDlyOff =>1,DimElsJtRampOn =>1,DimElsJtRampOff =>1, - lgMultiExec =>1, - logicCombination=>1, - }, - switch =>{OnTime =>1,OffTime =>1,OnDly =>1,OffDly =>1, - SwJtOn =>1,SwJtOff =>1,SwJtDlyOn =>1,SwJtDlyOff =>1, - CtValLo =>1,CtValHi =>1, - CtOn =>1,CtDlyOn =>1,CtOff =>1,CtDlyOff =>1, - ActionType =>1,OnTimeMode =>1,OffTimeMode =>1, - lgMultiExec =>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, - captInInterval=>1,brightFilter =>1,ledOnTime =>1, - }, -); - -my %culHmRegModel = ( - "HM-RC-12" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1}, - "HM-RC-12-B" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1}, - "HM-RC-12-SW" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1}, - - "HM-RC-19" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1,backAtCharge =>1,language =>1,}, - "HM-RC-19-B" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1,backAtCharge =>1,language =>1,}, - "HM-RC-19-SW" =>{backAtKey =>1, backAtMotion =>1, backOnTime =>1,backAtCharge =>1,language =>1,}, - - "HM-LC-Dim1PWM-CV"=>{characteristic =>1}, - "HM-LC-Dim1L-P" =>{loadAppearBehav =>1,loadErrCalib =>1}, - "HM-LC-Dim1L-CV" =>{loadAppearBehav =>1,loadErrCalib =>1}, - "HM-LC-Dim2L-SM" =>{loadAppearBehav =>1,loadErrCalib =>1}, - - "HM-CC-VD" =>{valveOffset =>1,valveError =>1}, - "HM-PB-4DIS-WM" =>{peerNeedsBurst =>1,expectAES =>1,language =>1,stbyTime =>1}, - "HM-WDS100-C6-O" =>{stormUpThresh =>1,stormLowThresh =>1}, - "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, - 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, - transmitTryMax =>1,evtFltrTime =>1, - msgScdPosA =>1,msgScdPosB =>1,msgScdPosC =>1,msgScdPosD =>1,}, - "HM-SEC-RHS" =>{peerNeedsBurst =>1,expectAES =>1, - cyclicInfoMsg =>1, transmDevTryMax =>1, - msgRhsPosA =>1,msgRhsPosB =>1,msgRhsPosC =>1, - evtDly =>1,ledOnTime =>1,transmitTryMax =>1,}, - "HM-SEC-SC" =>{cyclicInfoMsg =>1,sabotageMsg =>1,transmDevTryMax =>1, - msgScPosA =>1,msgScPosB =>1, - ledOnTime =>1,transmitTryMax =>1,eventDlyTime =>1, - peerNeedsBurst =>1,expectAES =>1,}, - "HM-SCI-3-FM" =>{cyclicInfoMsg =>1 ,transmDevTryMax =>1, - msgScPosA =>1,msgScPosB =>1, - transmitTryMax =>1,eventDlyTime =>1, - peerNeedsBurst =>1,expectAES =>1,}, - "HM-SEC-TIS" =>{cyclicInfoMsg =>1,sabotageMsg =>1,transmDevTryMax =>1, - msgScPosA =>1,msgScPosB =>1, - ledOnTime =>1,transmitTryMax =>1,eventFilterTime =>1, - peerNeedsBurst =>1,expectAES =>1,}, - "HM-SEC-SFA-SM" =>{cyclicInfoMsg =>1,sabotageMsg =>1,transmDevTryMax =>1, - lowBatLimit =>1,batDefectLimit =>1, - transmitTryMax =>1,}, - "HM-Sys-sRP-Pl" =>{compMode =>1,}, - "KFM-Display" =>{CtDlyOn =>1,CtDlyOff =>1, - CtOn =>1,CtOff =>1,CtRampOn =>1,CtRampOff =>1, - CtValLo =>1,CtValHi =>1, - ActionType =>1,OffTimeMode =>1,OnTimeMode =>1, - DimJtOn =>1,DimJtOff =>1,DimJtDlyOn =>1,DimJtDlyOff =>1, - DimJtRampOn =>1,DimJtRampOff =>1, - lgMultiExec =>1, - }, - "HM-Sen-Wa-Od" =>{cyclicInfoMsg =>1, transmDevTryMax =>1, - localResDis =>1,ledOnTime =>1,transmitTryMax =>1, - waterUppThr =>1,waterlowThr =>1,caseDesign =>1,caseHigh =>1, - fillLevel =>1,caseWidth =>1,caseLength =>1,meaLength =>1, - useCustom =>1, - fillLvlUpThr =>1,fillLvlLoThr =>1, - expectAES =>1,peerNeedsBurst =>1,}, - ); -my %culHmRegChan = (# if channelspecific then enter them here - "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, - }, - "HM-CC-TC03" =>{tempWinOpen =>1, }, #window channel - "HM-RC-1912" =>{msgShowTime =>1, beepAtAlarm =>1, beepAtService =>1,beepAtInfo =>1, - backlAtAlarm =>1, backlAtService =>1, backlAtInfo =>1, - lcdSymb =>1, lcdLvlInterp =>1}, - "HM-RC-19-B12" =>{msgShowTime =>1, beepAtAlarm =>1, beepAtService =>1,beepAtInfo =>1, - backlAtAlarm =>1, backlAtService =>1, backlAtInfo =>1, - lcdSymb =>1, lcdLvlInterp =>1}, - "HM-RC-19-SW12" =>{msgShowTime =>1, beepAtAlarm =>1, beepAtService =>1,beepAtInfo =>1, - backlAtAlarm =>1, backlAtService =>1, backlAtInfo =>1, - lcdSymb =>1, lcdLvlInterp =>1}, - "HM-OU-CFM-PL02" =>{Intense=>1}, - "HM-SEC-WIN01" =>{setupDir =>1,pullForce =>1,pushForce =>1,tiltMax =>1, - CtValLo =>1,CtValHi =>1, - CtOn =>1,CtOff =>1,CtRampOn =>1,CtRampOff =>1, - WinJtOn =>1,WinJtOff =>1,WinJtRampOn =>1,WinJtRampOff =>1, - OnTime =>1,OffTime =>1,OffLevelKm =>1, - OnLevelKm =>1,OnRampOnSp =>1,OnRampOffSp =>1 - } - ); - -##--------------- Conversion routines for register settings -my %fltCvT = (0.1=>3.1,1=>31,5=>155,10=>310,60=>1860,300=>9300, - 600=>18600,3600=>111600); -sub CUL_HM_Attr(@) {############################# - my ($cmd,$name, $attrName,$attrVal) = @_; - my @hashL; - if ($attrName eq "expert"){#[0,1,2] - $attr{$name}{expert} = $attrVal; - my $eHash = CUL_HM_name2Hash($name); - foreach my $chId (CUL_HM_getAssChnIds($name)){ - my $cHash = CUL_HM_id2Hash($chId); - push(@hashL,$cHash) if ($eHash ne $cHash); + if ($msgType eq "02"){# Ack/Nack ############################# + if ($shash->{helper}{respWait}{msgId} && + $shash->{helper}{respWait}{msgId} eq $msgId ){ + #ack we waited for - stop Waiting + CUL_HM_respPendRm($shash); } - push(@hashL,$eHash); - foreach my $hash (@hashL){ - my $exLvl = CUL_HM_getExpertMode($hash); - if ($exLvl eq "0"){# off - foreach my $rdEntry (keys %{$hash->{READINGS}}){ - my $rdEntryNew; - $rdEntryNew = ".".$rdEntry if ($rdEntry =~m /^RegL_/); - if ($rdEntry =~m /^R-/){ - my $reg = $rdEntry; - $reg =~ s/.*-//; - $rdEntryNew = ".".$rdEntry if($culHmRegDefine{$reg}{d} eq '0' ); - } - next if (!defined($rdEntryNew)); # no change necessary - delete $hash->{READINGS}{$rdEntryNew}; - $hash->{READINGS}{$rdEntryNew} = $hash->{READINGS}{$rdEntry}; - delete $hash->{READINGS}{$rdEntry}; - } - } - elsif ($exLvl eq "1"){# on: Only register values, no raw data - # move register to visible if available - foreach my $rdEntry (keys %{$hash->{READINGS}}){ - my $rdEntryNew; - $rdEntryNew = substr($rdEntry,1) if ($rdEntry =~m /^\.R-/); - $rdEntryNew = ".".$rdEntry if ($rdEntry =~m /^RegL_/); - next if (!$rdEntryNew); # no change necessary - delete $hash->{READINGS}{$rdEntryNew}; - $hash->{READINGS}{$rdEntryNew} = $hash->{READINGS}{$rdEntry}; - delete $hash->{READINGS}{$rdEntry}; - } - } - elsif ($exLvl eq "2"){# full - incl raw data - foreach my $rdEntry (keys %{$hash->{READINGS}}){ - my $rdEntryNew; - $rdEntryNew = substr($rdEntry,1) if (($rdEntry =~m /^\.RegL_/) || - ($rdEntry =~m /^\.R-/)); - next if (!$rdEntryNew); # no change necessary - delete $hash->{READINGS}{$rdEntryNew}; - $hash->{READINGS}{$rdEntryNew} = $hash->{READINGS}{$rdEntry}; - delete $hash->{READINGS}{$rdEntry}; - } - } - else{; - } - } - } - elsif($attrName eq "actCycle"){#"000:00" or 'off' - return if (CUL_HM_name2Id($name) eq $K_actDetID); - # Add to ActionDetector. Wait a little - config might not be finished - my @arr; - if(!$modules{CUL_HM}{helper}{updtCfgLst}){ - $modules{CUL_HM}{helper}{updtCfgLst} = \@arr; - } - push(@{$modules{CUL_HM}{helper}{updtCfgLst}}, $name); + if ($pendType eq "StatusReq"){#possible answer for status request + my $chnSrc = $src.$shash->{helper}{respWait}{forChn}; + my $chnhash = $modules{CUL_HM}{defptr}{$chnSrc}; + $chnhash = $shash if (!$chnhash); + CUL_HM_respPendRm($shash); + } - RemoveInternalTimer("updateConfig"); - InternalTimer(gettimeofday()+5,"CUL_HM_updateConfig", "updateConfig", 0); - } - return; -} -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}}; - $culHmRegDefine{"lg".$reg}{a} +=0x80; - } - foreach my $type(sort(keys %culHmRegType)){ #update references to register - foreach my $reg (sort(keys %{$culHmRegType{$type}})){ - if ($culHmRegDefShLg{$reg}){ - delete $culHmRegType{$type}{$reg}; - $culHmRegType{$type}{"sh".$reg} = 1; - $culHmRegType{$type}{"lg".$reg} = 1; - } - } - } - foreach my $type(sort(keys %culHmRegModel)){ #update references to register - foreach my $reg (sort(keys %{$culHmRegModel{$type}})){ - if ($culHmRegDefShLg{$reg}){ - delete $culHmRegModel{$type}{$reg}; - $culHmRegModel{$type}{"sh".$reg} = 1; - $culHmRegModel{$type}{"lg".$reg} = 1; - } - } - } - foreach my $type(sort(keys %culHmRegChan)){ #update references to register - foreach my $reg (sort(keys %{$culHmRegChan{$type}})){ - if ($culHmRegDefShLg{$reg}){ - delete $culHmRegChan{$type}{$reg}; - $culHmRegChan{$type}{"sh".$reg} = 1; - $culHmRegChan{$type}{"lg".$reg} = 1; - } - } - } -} -sub CUL_HM_fltCvT($) { # float -> config time - my ($inValue) = @_; - my $exp = 0; - my $div2; - foreach my $div(sort{$a <=> $b} keys %fltCvT){ - $div2 = $div; - last if ($inValue < $fltCvT{$div}); - $exp++; - } - return ($exp << 5)+int($inValue/$div2); -} -sub CUL_HM_CvTflt($) { # config time -> float - my ($inValue) = @_; - return ($inValue & 0x1f)*((sort {$a <=> $b} keys(%fltCvT))[$inValue >> 5]); -} + #see if the channel is defined separate - otherwise go for chief + my $subType = substr($p,0,2); + my $chn = sprintf("%02X",hex(substr($p,2,2))&0x3f); + #mark timing on the channel, not the device + my $HMid = $chn?$src.$chn:$src; + my $chnhash = $modules{CUL_HM}{defptr}{$HMid}; + $chnhash = $shash if(!$chnhash); + + my $reply; + my $success; + if ($subType =~ m/^8/){ #NACK + $success = "no"; + CUL_HM_eventP($shash,"Nack"); + delete($shash->{cmdStack}); + delete($shash->{protCmdPend}); + CUL_HM_respPendRm($shash); + $reply = "NACK"; + } + elsif($subType eq "01"){ #ACKinfo################# + $success = "yes"; + my $rssi = substr($p,8,2);# --calculate RSSI + CUL_HM_storeRssi(CUL_HM_hash2Name($shash), + ($dhash?CUL_HM_hash2Name($dhash):$shash->{IODev}{NAME}), + (-1)*(hex($rssi))) + if ($rssi && $rssi ne '00' && $rssi ne'80'); + $reply = "ACKStatus"; + } + else{ #ACK + $success = "yes"; + $reply = "ACK"; + } + readingsSingleUpdate($chnhash,"CommandAccepted",$success,1); + CUL_HM_ProcessCmdStack($shash) + if($dhash->{DEF} && (CUL_HM_IOid($shash) eq $dhash->{DEF})); + return $reply; + } + elsif($msgType eq "00"){###################################### + if ($pendType eq "PairSerial"){ + if($shash->{helper}{respWait}{forChn} = substr($p,6,20)){ + CUL_HM_respPendRm($shash); + } + } + } + elsif($msgType eq "10"){###################################### + my $subType = substr($p,0,2); + if($subType eq "01"){ #storePeerList################# + if ($pendType eq "PeerList"){ + my $chn = $shash->{helper}{respWait}{forChn}; + my $chnhash = $modules{CUL_HM}{defptr}{$src.$chn}; + $chnhash = $shash if (!$chnhash); + my $chnNname = $chnhash->{NAME}; + my @peers = substr($p,2,) =~ /(.{8})/g; + $chnhash->{helper}{peerIDsRaw}.= ",".join",",@peers; + + foreach my $peer(@peers){ + CUL_HM_ID2PeerList ($chnNname,$peer,1); + } + if ($p =~ m/000000..$/) {# last entry, peerList is complete + CUL_HM_respPendRm($shash); + # check for request to get List3 data + my $reqPeer = $chnhash->{helper}{getCfgList}; + if ($reqPeer){ + my $flag = CUL_HM_getFlag($shash); + my $id = CUL_HM_IOid($shash); + my $listNo = "0".$chnhash->{helper}{getCfgListNo}; + my @peerID = split(",", AttrVal($chnNname,"peerIDs","")); + foreach my $peer (@peerID){ + next if ($peer eq '00000000');# ignore termination + $peer .="01" if (length($peer) == 6); # add the default + if ($peer &&($peer eq $reqPeer || $reqPeer eq "all")){ + CUL_HM_PushCmdStack($shash,sprintf("++%s01%s%s%s04%s%s", + $flag,$id,$src,$chn,$peer,$listNo));# List3 or 4 + } + } + } + delete $chnhash->{helper}{getCfgList}; + delete $chnhash->{helper}{getCfgListNo}; + } + else{ + CUL_HM_respPendToutProlong($shash);#wasn't last - reschedule timer + } + return "done"; + } + } + elsif($subType eq "02" ||$subType eq "03"){ #ParamResp================== + if ($pendType eq "RegisterRead"){ + my $chnSrc = $src.$shash->{helper}{respWait}{forChn}; + my $chnHash = $modules{CUL_HM}{defptr}{$chnSrc}; + $chnHash = $shash if (!$chnHash); + my $chnName = $chnHash->{NAME}; + my ($format,$data) = ($1,$2) if ($p =~ m/^(..)(.*)/); + my $list = $shash->{helper}{respWait}{forList}; + $list = "00" if (!$list); #use the default + if ($format eq "02"){ # list 2: format aa:dd aa:dd ... + $data =~ s/(..)(..)/ $1:$2/g; + } + elsif ($format eq "03"){ # list 3: format aa:dddd + my $addr; + my @dataList; + ($addr,$data) = (hex($1),$2) if ($data =~ m/(..)(.*)/); + if ($addr == 0){ + $data = "00:00"; + } + else{ + $data =~s/(..)/$1:/g; + foreach my $d1 (split(":",$data)){ + push (@dataList,sprintf("%02X:%s",$addr++,$d1)); + } + $data = join(" ",@dataList); + } + } + my $peer = $shash->{helper}{respWait}{forPeer}; + my $regLN = ((CUL_HM_getExpertMode($chnHash) eq "2")?"":".")."RegL_".$list.":".$peer; + readingsSingleUpdate($chnHash,$regLN, + ReadingsVal($chnName,$regLN,"")." ".$data,0); + if ($data =~m/00:00$/){ # this was the last message in the block + if($list eq "00"){ + my $name = CUL_HM_id2Name($src); + readingsSingleUpdate($shash,"PairedTo", + CUL_HM_getRegFromStore($name,"pairCentral",0,"00000000"),0); + } + CUL_HM_respPendRm($shash); + delete $chnHash->{helper}{shadowReg}{$regLN};#remove shadowhash + # peer Channel name from/for user entry. + CUL_HM_updtRegDisp($chnHash,$list, + CUL_HM_peerChId($peer, + substr(CUL_HM_hash2Id($chnHash),0,6),"00000000")); + } + else{ + CUL_HM_respPendToutProlong($shash);#wasn't last - reschedule timer + } + return "done"; + } + } + elsif($subType eq "04"){ #ParamChange=================================== + my($chn,$peerID,$list,$data) = ($1,$2,$3,$4) if($p =~ m/^04(..)(........)(..)(.*)/); + my $chnHash = $modules{CUL_HM}{defptr}{$src.$chn}; + $chnHash = $shash if(!$chnHash); # will add param to dev if no chan + my $regLN = ((CUL_HM_getExpertMode($chnHash) eq "2")?"":".")."RegL_".$list.":".CUL_HM_id2Name($peerID); + $regLN =~ s/broadcast//; + $regLN =~ s/ /_/g; #remove blanks -#define gets - try use same names as for set -my %culHmGlobalGets = ( - param => "", - reg => " ... ", - regList => "", - saveConfig => "", -); -my %culHmSubTypeGets = ( - none4Type =>{ "test"=>"" }, -); -my %culHmModelGets = ( - none4Mod =>{ "none"=>"" }, -); -sub CUL_HM_TCtempReadings($) { - my ($hash)=@_; - my $name = $hash->{NAME}; - my $regLN = ((CUL_HM_getExpertMode($hash) eq "2")?"":".")."RegL_"; - my $reg5 = ReadingsVal($name,$regLN."05:" ,""); - my $reg6 = ReadingsVal($name,$regLN."06:" ,""); - my @days = ("Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"); - $reg5 =~ s/.* 0B://; #remove register up to addr 11 from list 5 - my $tempRegs = $reg5.$reg6; #one row - $tempRegs =~ s/ 00:00/ /g; #remove regline termination - $tempRegs =~ s/ ..:/,/g; #remove addr Info - $tempRegs =~ s/ //g; #blank - my @Tregs = split(",",$tempRegs); - my @time = @Tregs[grep !($_ % 2), 0..$#Tregs]; # even-index =time - my @temp = @Tregs[grep $_ % 2, 0..$#Tregs]; # odd-index =data - return "reglist incomplete\n" if (scalar( @time )<168); - foreach (@time){$_=hex($_)*10}; - foreach (@temp){$_=hex($_)/2}; - my $setting; - my @changedRead; - push (@changedRead,"tempList_State:". - (($hash->{helper}{shadowReg}{$regLN."05:"} || - $hash->{helper}{shadowReg}{$regLN."06:"} )?"set":"verified")); - for (my $day = 0;$day<7;$day++){ - my $tSpan = 0; - my $dayRead = ""; - for (my $entry = 0;$entry<24;$entry++){ - my $reg = $day *24 + $entry; - last if ($tSpan > 1430); - $tSpan = $time[$reg]; - my $entry = sprintf("%02d:%02d %3.01f",($tSpan/60),($tSpan%60),$temp[$reg]); - $setting .= "Temp set: ".$days[$day]." ".$entry." C\n"; - $dayRead .= " ".$entry; - $tSpan = $time[$reg]; - } - push (@changedRead,"tempList".$days[$day].":".$dayRead); + $data =~ s/(..)(..)/ $1:$2/g; + + my $lN = ReadingsVal($chnHash->{NAME},$regLN,""); + my $shdwReg = $chnHash->{helper}{shadowReg}{$regLN}; + foreach my $entry(split(' ',$data)){ + my ($a,$d) = split(":",$entry); + last if ($a eq "00"); + if ($lN =~m/$a:/){$lN =~ s/$a:../$a:$d/; + }else{ $lN .= " ".$entry;} + $shdwReg =~ s/ $a:..// if ($shdwReg);# confirmed: remove from shadow + } + $chnHash->{helper}{shadowReg}{$regLN} = $shdwReg; + $lN = join(' ',sort(split(' ',$lN)));# re-order + if ($lN =~ s/00:00//){$lN .= " 00:00"}; + readingsSingleUpdate($chnHash,$regLN,$lN,0); + CUL_HM_updtRegDisp($chnHash,$list,$peerID); + } + elsif($subType eq "06"){ #reply to status request======================= + my $rssi = substr($p,8,2);# --calculate RSSI + CUL_HM_storeRssi(CUL_HM_hash2Name($shash), + ($dhash?CUL_HM_hash2Name($dhash):$shash->{IODev}{NAME}), + (-1)*(hex($rssi))) + if ($rssi && $rssi ne '00' && $rssi ne'80'); + #todo = what is the answer to a status request + if ($pendType eq "StatusReq"){#it is the answer to our request + my $chnSrc = $src.$shash->{helper}{respWait}{forChn}; + my $chnhash = $modules{CUL_HM}{defptr}{$chnSrc}; + $chnhash = $shash if (!$chnhash); + CUL_HM_respPendRm($shash); + return "STATresp"; + } + else{ + my ($chn) = ($1) if($p =~ m/^..(..)/); + return "powerOn" if ($chn eq "00");# check dst eq "000000" as well? + } + } } - CUL_HM_UpdtReadBulk($hash,1,@changedRead) if (@changedRead); - return $setting; -} -sub CUL_HM_repReadings($) { - my ($hash)=@_; - my %pCnt; - foreach my$pId(split',',$hash->{helper}{peerIDsRaw}){ - next if (!$pId || $pId eq "00000000"); - $pCnt{$pId}{cnt}++; + elsif($msgType eq "70"){ #Time to trigger TC################## + #send wakeup and process command stack +# CUL_HM_SndCmd($shash, '++A112'.CUL_HM_IOid($shash).$src); +# CUL_HM_ProcessCmdStack($shash); } - my $ret; - foreach my$pId(sort keys %pCnt){ - my ($pdID,$bdcst) = ($1,$2) if ($pId =~ m/(......)(..)/); - $ret .= "source ".$pCnt{$pId}{cnt}." entry for: ".CUL_HM_id2Name($pdID) - .($bdcst eq "01"?" broadcast enabled":"")."\n"; - } - return $ret; -} -sub CUL_HM_dimLog($) { - my ($hash)=@_; - my $lComb = CUL_HM_Get($hash,$hash->{NAME},"reg","logicCombination"); - return if (!$lComb); - my %logicComb=( - inactive=>{calc=>'$val=$val' ,txt=>'unused'}, - or =>{calc=>'$val=$in>$val?$in:$val' ,txt=>'max(state,chan)'}, - and =>{calc=>'$val=$in<$val?$in:$val' ,txt=>'min(state,chan)'}, - xor =>{calc=>'$val=!($in!=0&&$val!=0)?($in>$val?$in:$val): 0' ,txt=>'0 if both are != 0, else max'}, - nor =>{calc=>'$val=100-($in>$val?$in : $val)' ,txt=>'100-max(state,chan)'}, - nand =>{calc=>'$val=100-($in<$val?$in : $val)' ,txt=>'100-min(state,chan)'}, - orinv =>{calc=>'$val=(100-$in)>$val?(100-$in) : $val' ,txt=>'max((100-chn),state)'}, - andinv =>{calc=>'$val=(100-$in)<$val?(100-$in) : $val' ,txt=>'min((100-chn),state)'}, - plus =>{calc=>'$val=($in + $val)<100?($in + $val) : 100' ,txt=>'state + chan'}, - minus =>{calc=>'$val=($in - $val)>0?($in + $val) : 0' ,txt=>'state - chan'}, - mul =>{calc=>'$val=($in * $val)<100?($in + $val) : 100' ,txt=>'state * chan'}, - plusinv =>{calc=>'$val=($val+100-$in)<100?($val+100-$in) : 100' ,txt=>'state + 100 - chan'}, - minusinv=>{calc=>'$val=($val-100+$in)>0?($val-100+$in) : 0' ,txt=>'state - 100 + chan'}, - mulinv =>{calc=>'$val=((100-$in)*$val)<100?(100-$in)*$val) : 100',txt=>'state * (100 - chan)'}, - invPlus =>{calc=>'$val=(100-$val-$in)>0?(100-$val-$in) : 0' ,txt=>'100 - state - chan'}, - invMinus=>{calc=>'$val=(100-$val+$in)<100?(100-$val-$in) : 100' ,txt=>'100 - state + chan'}, - invMul =>{calc=>'$val=(100-$val*$in)>0?(100-$val*$in) : 0' ,txt=>'100 - state * chan'}, - ); - readingsSingleUpdate($hash,"R-logicCombTxt" ,$logicComb{$lComb}{txt},0); - readingsSingleUpdate($hash,"R-logicCombCalc",$logicComb{$lComb}{calc},0); return ""; } -################################### + +#+++++++++++++++++ get command+++++++++++++++++++++++++++++++++++++++++++++++++ sub CUL_HM_Get($@) { my ($hash, @a) = @_; return "no get value specified" if(@a < 2); @@ -2160,170 +2526,11 @@ sub CUL_HM_Get($@) { CUL_HM_ProcessCmdStack($devHash) if ($rxType & 0x03);#burst/all return ""; } -################################### -my %culHmGlobalSetsDevice = ( - raw => "data ...", - reset => "", - pair => "", - unpair => "", - getpair => "", - virtual =>"", -); -my %culHmGlobalSets = ( - sign => "[on|off]", - regBulk => ": ...", - peerBulk => "", - statusRequest => "", - getdevicepair => "", - getRegRaw =>"[List0|List1|List2|List3|List4|List5|List6] ... ", - getConfig => "", - regSet =>" ... ", - clear =>"[readings|msgEvents]", -); -my %culHmSubTypeSets = ( - switch =>{ "on-for-timer"=>"sec", "on-till"=>"time", - on=>"", off=>"", toggle=>"", - press => "[long|short] [on|off] ..."}, - dimmer =>{ "on-for-timer"=>"sec", "on-till"=>"time", - on=>"", off=>"", toggle=>"", pct=>"", stop=>"", - press => "[long|short] [on|off] ..."}, - blindActuator =>{ on=>"", off=>"", toggle=>"", pct=>"", stop=>"", - press => "[long|short] [on|off] ..."}, - remote =>{ devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]",}, - pushButton =>{ devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]",}, - threeStateSensor =>{ devicepair => " device ... single [set|unset] [actor|remote|both]",}, - motionDetector =>{ devicepair => " device ... single [set|unset] [actor|remote|both]",}, - virtual =>{ raw => "data ...", - devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]", - press => "[long|short]...", - valvePos => "position",#acting as TC - virtual =>"",}, #redef necessary for virtual - smokeDetector =>{ test => "", alarmOn=>"", alarmOff=>"", - devicepair => " device ... single [set|unset] actor",}, - winMatic =>{ matic => "", - keydef => " ", - create => "" }, - keyMatic =>{ lock =>"", - unlock =>"[sec] ...", - open =>"[sec] ...", - inhibit =>"[on|off]"}, -); -my %culHmModelSets = ( - "HM-CC-VD"=>{ - valvePos => "position"}, - "HM-RC-19"=> { - service => "", - alarm => "", - display => " [comma,no] [unit] [off|1|2|3] [off|on|slow|fast] "}, - "HM-RC-19-B"=> { - service => "", - alarm => "", - display => " [comma,no] [unit] [off|1|2|3] [off|on|slow|fast] "}, - "HM-RC-19-SW"=> { - service => "", - alarm => "", - display => " [comma,no] [unit] [off|1|2|3] [off|on|slow|fast] "}, - "HM-PB-4DIS-WM"=>{ - text => " [on|off] "}, - "HM-OU-LED16" =>{ - led =>"[off|red|green|orange]" , - ilum =>"[0-15] [0-127]" }, - "HM-OU-CFM-PL"=>{ - led => "[,..]", - playTone => "[,..]"}, - "HM-Sys-sRP-Pl"=>{ - setRepeat => "[no1..36] [bdcast-yes|no]"}, -); -my %culHmChanSets = ( - "HM-CC-TC00"=>{ - devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]", - "day-temp" => "[on,off,6.0..30.0]", - "night-temp" => "[on,off,6.0..30.0]", - "party-temp" => "[on,off,6.0..30.0]", - "desired-temp" => "[on,off,6.0..30.0]", - tempListSat => "HH:MM temp ...", - tempListSun => "HH:MM temp ...", - tempListMon => "HH:MM temp ...", - tempListTue => "HH:MM temp ...", - tempListThu => "HH:MM temp ...", - tempListWed => "HH:MM temp ...", - tempListFri => "HH:MM temp ...", - displayMode => "[temp-only|temp-hum]", - displayTemp => "[actual|setpoint]", - displayTempUnit => "[celsius|fahrenheit]", - controlMode => "[manual|auto|central|party]", - decalcDay => "day", }, - "HM-CC-TC02"=>{ - devicepair => " device ... [single|dual] [set|unset] [actor|remote|both]", - "day-temp" => "[on,off,6.0..30.0]", - "night-temp" => "[on,off,6.0..30.0]", - "party-temp" => "[on,off,6.0..30.0]", - "desired-temp" => "[on,off,6.0..30.0]", - tempListSat => "HH:MM temp ...", - tempListSun => "HH:MM temp ...", - tempListMon => "HH:MM temp ...", - tempListTue => "HH:MM temp ...", - tempListThu => "HH:MM temp ...", - tempListWed => "HH:MM temp ...", - tempListFri => "HH:MM temp ...", - displayMode => "[temp-only|temp-hum]", - displayTemp => "[actual|setpoint]", - displayTempUnit => "[celsius|fahrenheit]", - controlMode => "[manual|auto|central|party]", - decalcDay => "day", }, - "HM-SEC-WIN01"=>{ stop =>"", - level =>" ..."}, -); - -############################################## -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); - my $mId = $hash->{helper}{mId}; - if (!$mId){ - my $model = AttrVal($hash->{NAME}, "model", ""); - foreach my $mIdKey(keys%culHmModel){ - next if (!$culHmModel{$mIdKey}{name} || $culHmModel{$mIdKey}{name} ne $model); - $mId = $hash->{helper}{mId} = $mIdKey ; - return $mIdKey; - } - return ""; - } - return $mId; -} -############################################## -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); - no warnings; #convert regardless of content - my $rxtEntity = int($hash->{helper}{rxType}); - use warnings; - if (!$rxtEntity){ #at least one bit must be set - my $MId = CUL_HM_getMId($hash); - my $rxtOfModel = $culHmModel{$MId}{rxt} if ($MId && $culHmModel{$MId}{rxt}); - if ($rxtOfModel){ - $rxtEntity |= ($rxtOfModel =~ m/b/)?0x02:0;#burst - $rxtEntity |= ($rxtOfModel =~ m/c/)?0x04:0;#config - $rxtEntity |= ($rxtOfModel =~ m/w/)?0x08:0;#wakeup - } - $rxtEntity = 1 if (!$rxtEntity);#always - $hash->{helper}{rxType} = $rxtEntity; - } - return $rxtEntity; -} -############################################## -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 -} +#+++++++++++++++++ set command+++++++++++++++++++++++++++++++++++++++++++++++++ sub CUL_HM_Set($@) { my ($hash, @a) = @_; my ($ret, $tval, $rval); #added rval for ramptime by unimatrix - return "no set value specified" if(@a < 2); my $name = $hash->{NAME}; @@ -2691,6 +2898,20 @@ sub CUL_HM_Set($@) { CUL_HM_PushCmdStack($hash, sprintf("++%s11%s%s02%s%02X%s%s",$flag,$id,$dst,$chn,$a[1]*2,$rval,$tval)); } + elsif($cmd =~ m/^(up|down)$/) { ############################################# +# elsif($cmd eq "up" || $cmd eq "down") { ############################################# + #dim [|up|down] ... [ontime] [ramptime] + my $lvl = (defined $a[2])?$a[2]:10; + $lvl = -1*$lvl if ($a[0] eq "down"); + my $curVal = ReadingsVal($name,"state",0); + $curVal = ($curVal eq "on")?100:(($curVal eq "off")?0:$curVal); + $lvl += $curVal; + $lvl = ($lvl > 100)?100:(($lvl < 0)?0:$lvl); + $tval = CUL_HM_encodeTime16(((@a > 2)&&$a[3]!=0)?$a[3]:6709248);# onTime 0.0..6709248, 0=forever + $rval = CUL_HM_encodeTime16((@a > 3)?$a[3]:2.5); # rampTime 0.0..6709248, 0=immediate + CUL_HM_PushCmdStack($hash, + sprintf("++%s11%s%s02%s%02X%s%s",$flag,$id,$dst,$chn,$lvl*2,$rval,$tval)); + } elsif($cmd eq "stop") { ##################################################### CUL_HM_PushCmdStack($hash,'++'.$flag.'11'.$id.$dst.'03'.$chn); } @@ -3011,9 +3232,9 @@ sub CUL_HM_Set($@) { my $pChn = $chn; # simple device, only one button per channel $pChn = (($vChn && $vChn eq "off")?-1:0) + $chn*2 if($st ne 'switch'); CUL_HM_PushCmdStack($hash, sprintf("++%s3E%s%s%s40%02X%02X",$flag, - $id,$dst,$dst, + $id,$dst,$dst, $pChn+(($mode && $mode eq "long")?64:0), - $pressCnt)); + $pressCnt)); } } elsif($cmd eq "devicepair") { ############################################### @@ -3098,10 +3319,9 @@ sub CUL_HM_Set($@) { return ("",1);# no not generate trigger outof command } -################################### +#+++++++++++++++++ set/get support subroutines+++++++++++++++++++++++++++++++++ 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); @@ -3248,7 +3468,8 @@ sub CUL_HM_getConfig($$$$$){ } } } -###################-------send related --------################ + + #+++++++++++++++++ Protocol stack, sending, repeat+++++++++++++++++++++++++++++ sub CUL_HM_SndCmd($$) { my ($hash, $cmd) = @_; $hash = CUL_HM_getDeviceHash($hash); @@ -3463,6 +3684,49 @@ sub CUL_HM_ProcessCmdStack($) { } return $sent; } +sub CUL_HM_pushConfig($$$$$$$$) {#generate messages to cnfig data to register + my ($hash,$src,$dst,$chn,$peerAddr,$peerChn,$list,$content) = @_; + my $flag = CUL_HM_getFlag($hash); + my $tl = length($content); + $chn = sprintf("%02X",$chn); + $peerChn = sprintf("%02X",$peerChn); + $list = sprintf("%02X",$list); + + # --store pending changes in shadow to handle bit manipulations cululativ-- + $peerAddr = "000000" if(!$peerAddr); + my $peerN = ($peerAddr ne "000000")?CUL_HM_id2Name($peerAddr.$peerChn):""; + $peerN =~ s/broadcast//; + $peerN =~ s/ /_/g;#remote blanks + my $regLN = ((CUL_HM_getExpertMode($hash) eq "2")?"":"."). + "RegL_".$list.":".$peerN; + #--- copy data from readings to shadow + my $chnhash = $modules{CUL_HM}{defptr}{$dst.$chn}; + $chnhash = $hash if (!$chnhash); + if (!$chnhash->{helper}{shadowReg} || + !$chnhash->{helper}{shadowReg}{$regLN}){ + $chnhash->{helper}{shadowReg}{$regLN} = + ReadingsVal($chnhash->{NAME},$regLN,""); + } + #--- update with ne value + my $regs = $chnhash->{helper}{shadowReg}{$regLN}; + for(my $l = 0; $l < $tl; $l+=4) { #substitute changed bytes in shadow + my $addr = substr($content,$l,2); + my $data = substr($content,$l+2,2); + if(!$regs || !($regs =~ s/$addr:../$addr:$data/)){ + $regs .= " ".$addr.":".$data; + } + } + $chnhash->{helper}{shadowReg}{$regLN} = $regs; + CUL_HM_updtRegDisp($hash,$list,$peerAddr.$peerChn); + CUL_HM_PushCmdStack($hash, "++".$flag.'01'.$src.$dst.$chn.'05'. + $peerAddr.$peerChn.$list); + for(my $l = 0; $l < $tl; $l+=28) { + my $ml = $tl-$l < 28 ? $tl-$l : 28; + CUL_HM_PushCmdStack($hash, "++A001".$src.$dst.$chn."08". + substr($content,$l,$ml)); + } + CUL_HM_PushCmdStack($hash,"++A001".$src.$dst.$chn."06"); +} sub CUL_HM_Resend($) {#resend a message if there is no answer my $hash = shift; my $name = $hash->{NAME}; @@ -3486,6 +3750,7 @@ sub CUL_HM_Resend($) {#resend a message if there is no answer InternalTimer(gettimeofday()+rand(40)/10+1, "CUL_HM_Resend", $hash, 0); } } + ###################-----------helper and shortcuts--------################ ################### Peer Handling ################ sub CUL_HM_ID2PeerList ($$$) { @@ -3517,15 +3782,63 @@ sub CUL_HM_ID2PeerList ($$$) { delete $hash->{READINGS}{peerList}; } } -################### Conversions ################ -sub CUL_HM_getExpertMode($) { # get expert level for the entity. - # if expert level is not set try to get it for device +sub CUL_HM_peerChId($$$) {# in: , out:channelID + 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'); + return $iId.sprintf("%02X",'0'.substr($pId,4)) if ($pSc eq 'fhem'); + return "all" if ($pId eq 'all');#used by getRegList + my $repID = CUL_HM_name2Id($pId); + $repID .= '01' if (length( $repID) == 6);# add default 01 if this is a device + return $repID; +} +sub CUL_HM_peerChName($$$) {#in: , out:name + 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_getMId($) {#in: hash(chn or dev) out:model key (key for %culHmModel) + # Will store result in device helper my ($hash) = @_; - my $expLvl = AttrVal($hash->{NAME},"expert",""); - my $dHash = CUL_HM_getDeviceHash($hash); - $expLvl = AttrVal($dHash->{NAME},"expert","0") - if ($expLvl eq ""); - return substr($expLvl,0,1); + $hash = CUL_HM_getDeviceHash($hash); + my $mId = $hash->{helper}{mId}; + if (!$mId){ + my $model = AttrVal($hash->{NAME}, "model", ""); + foreach my $mIdKey(keys%culHmModel){ + next if (!$culHmModel{$mIdKey}{name} || $culHmModel{$mIdKey}{name} ne $model); + $mId = $hash->{helper}{mId} = $mIdKey ; + return $mIdKey; + } + return ""; + } + return $mId; +} +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); + no warnings; #convert regardless of content + my $rxtEntity = int($hash->{helper}{rxType}); + use warnings; + if (!$rxtEntity){ #at least one bit must be set + my $MId = CUL_HM_getMId($hash); + my $rxtOfModel = $culHmModel{$MId}{rxt} if ($MId && $culHmModel{$MId}{rxt}); + if ($rxtOfModel){ + $rxtEntity |= ($rxtOfModel =~ m/b/)?0x02:0;#burst + $rxtEntity |= ($rxtOfModel =~ m/c/)?0x04:0;#config + $rxtEntity |= ($rxtOfModel =~ m/w/)?0x08:0;#wakeup + } + $rxtEntity = 1 if (!$rxtEntity);#always + $hash->{helper}{rxType} = $rxtEntity; + } + return $rxtEntity; +} +sub CUL_HM_getFlag($) {#msgFlag 'A0' or 'B0' for burst/normal 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_getAssChnIds($) { #in: name out:ID list of assotiated channels # if it is a channel only return itself @@ -3543,6 +3856,17 @@ sub CUL_HM_getAssChnIds($) { #in: name out:ID list of assotiated channels push @chnIdList,$dId if (length($dId) == 8); return sort(@chnIdList); } +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",""); + my $dHash = CUL_HM_getDeviceHash($hash); + $expLvl = AttrVal($dHash->{NAME},"expert","0") + if ($expLvl eq ""); + return substr($expLvl,0,1); +} + +#+++++++++++++++++ Conversions names, hashes, ids++++++++++++++++++++++++++++++ sub CUL_HM_Id($) {#in: ioHash out: ioHMid my ($io) = @_; my $fhtid = defined($io->{FHTID}) ? $io->{FHTID} : "0000"; @@ -3602,24 +3926,7 @@ sub CUL_HM_id2Hash($) {#in: id, out:hash 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_peerChId($$$) {# peer Channel name from/for user entry. - 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'); - return $iId.sprintf("%02X",'0'.substr($pId,4)) if ($pSc eq 'fhem'); - return "all" if ($pId eq 'all');#used by getRegList - my $repID = CUL_HM_name2Id($pId); - $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. - 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_getDeviceHash($) {#in: hash (chn or dev) out: hash of the device (used e.g. for send messages) +sub CUL_HM_getDeviceHash($) {#in: hash out: devicehash my ($hash) = @_; return $hash if(!$hash->{DEF}); my $devHash = $modules{CUL_HM}{defptr}{substr($hash->{DEF},0,6)}; @@ -3627,150 +3934,7 @@ sub CUL_HM_getDeviceHash($) {#in: hash (chn or dev) out: hash of the device (use } -############################# -my %culHmBits = ( - "00" => { txt => "DEVICE_INFO", params => { - FIRMWARE => '00,2', - TYPE => "02,4", - SERIALNO => '06,20,$val=pack("H*",$val)', - CLASS => "26,2", - PEER_CHANNEL_A => "28,2", - PEER_CHANNEL_B => "30,2", - UNKNOWN => "32,2", }}, - - "01;p11=01" => { txt => "CONFIG_PEER_ADD", params => { - CHANNEL => "00,2", - PEER_ADDRESS => "04,6", - PEER_CHANNEL_A => "10,2", - PEER_CHANNEL_B => "12,2", }}, - "01;p11=02" => { txt => "CONFIG_PEER_REMOVE", params => { - CHANNEL => "00,2", - PEER_ADDRESS => '04,6,$val=CUL_HM_id2Name($val)', - PEER_CHANNEL_A => "10,2", - PEER_CHANNEL_B => "12,2", } }, - "01;p11=03" => { txt => "CONFIG_PEER_LIST_REQ", params => { - CHANNEL => "0,2", },}, - "01;p11=04" => { txt => "CONFIG_PARAM_REQ", params => { - CHANNEL => "00,2", - PEER_ADDRESS => "04,6", - PEER_CHANNEL => "10,2", - PARAM_LIST => "12,2", },}, - "01;p11=05" => { txt => "CONFIG_START", params => { - CHANNEL => "00,2", - PEER_ADDRESS => "04,6", - PEER_CHANNEL => "10,2", - PARAM_LIST => "12,2", } }, - "01;p11=06" => { txt => "CONFIG_END", params => { - CHANNEL => "0,2", } }, - "01;p11=08" => { txt => "CONFIG_WRITE_INDEX", params => { - CHANNEL => "0,2", - DATA => '4,,$val =~ s/(..)(..)/ $1:$2/g', } }, - "01;p11=0A" => { txt => "PAIR_SERIAL", params => { - SERIALNO => '04,,$val=pack("H*",$val)', } }, - "01;p11=0E" => { txt => "CONFIG_STATUS_REQUEST", params => { - CHANNEL => "0,2", } }, - - "02;p01=00" => { txt => "ACK"}, - "02;p01=01" => { txt => "ACK_STATUS", params => { - CHANNEL => "02,2", - STATUS => "04,2", - DOWN => '06,02,$val=(hex($val)&0x20)?1:0', - UP => '06,02,$val=(hex($val)&0x10)?1:0', - LOWBAT => '06,02,$val=(hex($val)&0x80)?1:0', - RSSI => '08,02,$val=(-1)*(hex($val))', }}, - "02;p01=02" => { txt => "ACK2"}, # smokeDetector pairing only? - "02;p01=04" => { txt => "ACK-proc", params => { - Para1 => "02,4", - Para2 => "06,4", - Para3 => "10,4", - Para4 => "14,2",}}, # remote? - "02;p01=80" => { txt => "NACK"}, - "02;p01=84" => { txt => "NACK_TARGET_INVALID"}, - "02" => { txt => "ACK/NACK_UNKNOWN "}, - - "02" => { txt => "Request AES", params => { #todo check data - DATA => "0," } }, - - "03" => { txt => "AES reply", params => { - DATA => "0," } }, - - "10;p01=01" => { txt => "INFO_PEER_LIST", params => { - PEER1 => '02,8,$val=CUL_HM_id2Name($val)', - PEER2 => '10,8,$val=CUL_HM_id2Name($val)', - PEER3 => '18,8,$val=CUL_HM_id2Name($val)', - PEER4 => '26,8,$val=CUL_HM_id2Name($val)'},}, - "10;p01=02" => { txt => "INFO_PARAM_RESPONSE_PAIRS", params => { - DATA => "2,", },}, - "10;p01=03" => { txt => "INFO_PARAM_RESPONSE_SEQ", params => { - OFFSET => "2,2", - DATA => "4,", },}, - "10;p01=04" => { txt => "INFO_PARAMETER_CHANGE", params => { - CHANNEL => "2,2", - PEER => '4,8,$val=CUL_HM_id2Name($val)', - PARAM_LIST => "12,2", - DATA => '14,,$val =~ s/(..)(..)/ $1:$2/g', } }, - "10;p01=06" => { txt => "INFO_ACTUATOR_STATUS", params => { - CHANNEL => "2,2", - STATUS => '4,2', - UNKNOWN => "6,2", - RSSI => '08,02,$val=(-1)*(hex($val))' } }, - "11;p02=0400" => { txt => "RESET" }, - "11;p01=02" => { txt => "SET" , params => { - CHANNEL => "02,2", - VALUE => "04,2", - RAMPTIME => '06,4,$val=CUL_HM_decodeTime16($val)', - DURATION => '10,4,$val=CUL_HM_decodeTime16($val)', } }, - "11;p01=80" => { txt => "LED" , params => { - CHANNEL => "02,2", - COLOR => "04,2", } }, - "11;p01=81" => { txt => "LEDall" , params => { - Led1To16 => '04,8,$val= join(":",sprintf("%b",hex($val))=~ /(.{2})/g)', - } }, - "12" => { txt => "HAVE_DATA"}, - "3E" => { txt => "SWITCH", params => { - DST => "00,6", - UNKNOWN => "06,2", - CHANNEL => "08,2", - COUNTER => "10,2", } }, - "3F" => { txt => "TimeStamp", params => { - UNKNOWN => "00,4", - TIME => "04,2", } }, - "40" => { txt => "REMOTE", params => { - BUTTON => '00,2,$val=(hex($val)&0x3F)', - LONG => '00,2,$val=(hex($val)&0x40)?1:0', - LOWBAT => '00,2,$val=(hex($val)&0x80)?1:0', - COUNTER => "02,2", } }, - "41" => { txt => "Sensor_event", params => { - BUTTON => '00,2,$val=(hex($val)&0x3F)', - LONG => '00,2,$val=(hex($val)&0x40)?1:0', - LOWBAT => '00,2,$val=(hex($val)&0x80)?1:0', - VALUE => '02,2,$val=(hex($val))', - NEXT => '04,2,$val=(hex($val))',} }, - "53" => { txt => "WaterSensor", params => { - CMD => "00,2", - SEQ => '02,2,$val=(hex($val))-64', - V1 => '08,2,$val=(hex($val))', - V2 => '10,2,$val=(hex($val))', - V3 => '12,2,$val=(hex($val))'} }, - "58" => { txt => "ClimateEvent", params => { - CMD => "00,2", - ValvePos => '02,2,$val=(hex($val))', } }, - "70" => { txt => "WeatherEvent", params => { - TEMP => '00,4,$val=((hex($val)&0x3FFF)/10)*((hex($val)&0x4000)?-1:1)', - HUM => '04,2,$val=(hex($val))', } }, - -); -# RC send BCAST to specific address. Is the meaning understood? -my @culHmCmdFlags = ("WAKEUP", "WAKEMEUP", "CFG", "Bit3", - "BURST", "BIDI", "RPTED", "RPTEN"); - #RPTEN 0x80: set in every message. Meaning? - #RPTED 0x40: repeated (repeater operation) - #BIDI 0x20: response is expected - #Burst 0x10: set if burst is required by device - #Bit3 0x08: - #CFG 0x04: Device in Config mode - #WAKEMEUP 0x02: awake - hurry up to send messages - #WAKEUP 0x01: send initially to keep the device awake +#+++++++++++++++++ debug ++++++++++++++++++++++++++++++++++++++++++++++++++++++ sub CUL_HM_DumpProtocol($$@) { my ($prefix, $iohash, $len,$cnt,$msgFlags,$msgType,$src,$dst,$p) = @_; my $iname = $iohash->{NAME}; @@ -3816,227 +3980,8 @@ sub CUL_HM_DumpProtocol($$@) { Log GetLogLevel($iname, 4), $msg; DoTrigger($iname, $msg) if($hmProtocolEvents > 2); } -sub CUL_HM_parseCommon(@){############################# - # parsing commands that are device independant - my ($msgId,$msgFlag,$msgType,$src,$dst,$p) = @_; - my $shash = $modules{CUL_HM}{defptr}{$src}; - my $dhash = $modules{CUL_HM}{defptr}{$dst}; - return "" if(!$shash->{DEF});# this should be from ourself - - my $pendType = $shash->{helper}{respWait}{Pending}? - $shash->{helper}{respWait}{Pending}:""; - #------------ parse message flag for start processing command Stack - # TC wakes up with 8270, not with A258 - # VD wakes up with 8202 - if( $shash->{cmdStack} && - ((hex($msgFlag) & 0xA2) == 0x82) && - (CUL_HM_getRxType($shash) & 0x08)){ #wakeup ##### - #send wakeup and process command stack - CUL_HM_SndCmd($shash, '++A112'.CUL_HM_IOid($shash).$src); - CUL_HM_ProcessCmdStack($shash); - } - - if ($msgType eq "02"){# Ack/Nack ####################################### - if ($shash->{helper}{respWait}{msgId} && - $shash->{helper}{respWait}{msgId} eq $msgId ){ - #ack we waited for - stop Waiting - CUL_HM_respPendRm($shash); - } - if ($pendType eq "StatusReq"){#possible answer for status request - my $chnSrc = $src.$shash->{helper}{respWait}{forChn}; - my $chnhash = $modules{CUL_HM}{defptr}{$chnSrc}; - $chnhash = $shash if (!$chnhash); - CUL_HM_respPendRm($shash); - } - #see if the channel is defined separate - otherwise go for chief - my $subType = substr($p,0,2); - my $chn = substr($p,2,2); - #mark timing on the channel, not the device - my $HMid = $chn?$src.$chn:$src; - my $chnhash = $modules{CUL_HM}{defptr}{$HMid}; - $chnhash = $shash if(!$chnhash); - - my $reply; - my $success; - - if ($subType =~ m/^8/){ #NACK - $success = "no"; - CUL_HM_eventP($shash,"Nack"); - delete($shash->{cmdStack}); - delete($shash->{protCmdPend}); - CUL_HM_respPendRm($shash); - $reply = "NACK"; - } - elsif($subType eq "01"){ #ACKinfo################# - - my $rssi = substr($p,8,2);# --calculate RSSI - CUL_HM_storeRssi(CUL_HM_hash2Name($shash), - ($dhash?CUL_HM_hash2Name($dhash):$shash->{IODev}{NAME}), - (-1)*(hex($rssi))) - if ($rssi && $rssi ne '00' && $rssi ne'80'); - $reply = "ACKStatus"; - } - else{ #ACK - $reply = "ACK"; - $success = "yes"; - } - readingsSingleUpdate($chnhash,"CommandAccepted",$success,1); - CUL_HM_ProcessCmdStack($shash) - if($dhash->{DEF} && (CUL_HM_IOid($shash) eq $dhash->{DEF})); - return $reply; - } - elsif($msgType eq "00"){ - if ($pendType eq "PairSerial"){ - if($shash->{helper}{respWait}{forChn} = substr($p,6,20)){ - CUL_HM_respPendRm($shash); - } - } - } - elsif($msgType eq "10"){ - my $subType = substr($p,0,2); - if($subType eq "01"){ #storePeerList################# - if ($pendType eq "PeerList"){ - my $chn = $shash->{helper}{respWait}{forChn}; - my $chnhash = $modules{CUL_HM}{defptr}{$src.$chn}; - $chnhash = $shash if (!$chnhash); - my $chnNname = $chnhash->{NAME}; - my @peers = substr($p,2,) =~ /(.{8})/g; - $chnhash->{helper}{peerIDsRaw}.= ",".join",",@peers; - - foreach my $peer(@peers){ - CUL_HM_ID2PeerList ($chnNname,$peer,1); - } - if ($p =~ m/000000..$/) {# last entry, peerList is complete - CUL_HM_respPendRm($shash); - # check for request to get List3 data - my $reqPeer = $chnhash->{helper}{getCfgList}; - if ($reqPeer){ - my $flag = CUL_HM_getFlag($shash); - my $id = CUL_HM_IOid($shash); - my $listNo = "0".$chnhash->{helper}{getCfgListNo}; - my @peerID = split(",", AttrVal($chnNname,"peerIDs","")); - foreach my $peer (@peerID){ - next if ($peer eq '00000000');# ignore termination - $peer .="01" if (length($peer) == 6); # add the default - if ($peer &&($peer eq $reqPeer || $reqPeer eq "all")){ - CUL_HM_PushCmdStack($shash,sprintf("++%s01%s%s%s04%s%s", - $flag,$id,$src,$chn,$peer,$listNo));# List3 or 4 - } - } - } - delete $chnhash->{helper}{getCfgList}; - delete $chnhash->{helper}{getCfgListNo}; - } - else{ - CUL_HM_respPendToutProlong($shash);#wasn't last - reschedule timer - } - return "done"; - } - } - elsif($subType eq "02" ||$subType eq "03"){ #ParamResp================== - if ($pendType eq "RegisterRead"){ - my $chnSrc = $src.$shash->{helper}{respWait}{forChn}; - my $chnHash = $modules{CUL_HM}{defptr}{$chnSrc}; - $chnHash = $shash if (!$chnHash); - my $chnName = $chnHash->{NAME}; - my ($format,$data) = ($1,$2) if ($p =~ m/^(..)(.*)/); - my $list = $shash->{helper}{respWait}{forList}; - $list = "00" if (!$list); #use the default - if ($format eq "02"){ # list 2: format aa:dd aa:dd ... - $data =~ s/(..)(..)/ $1:$2/g; - } - elsif ($format eq "03"){ # list 3: format aa:dddd - my $addr; - my @dataList; - ($addr,$data) = (hex($1),$2) if ($data =~ m/(..)(.*)/); - if ($addr == 0){ - $data = "00:00"; - } - else{ - $data =~s/(..)/$1:/g; - foreach my $d1 (split(":",$data)){ - push (@dataList,sprintf("%02X:%s",$addr++,$d1)); - } - $data = join(" ",@dataList); - } - } - my $peer = $shash->{helper}{respWait}{forPeer}; - my $regLN = ((CUL_HM_getExpertMode($chnHash) eq "2")?"":".")."RegL_".$list.":".$peer; - readingsSingleUpdate($chnHash,$regLN, - ReadingsVal($chnName,$regLN,"")." ".$data,0); - if ($data =~m/00:00$/){ # this was the last message in the block - if($list eq "00"){ - my $name = CUL_HM_id2Name($src); - readingsSingleUpdate($shash,"PairedTo", - CUL_HM_getRegFromStore($name,"pairCentral",0,"00000000"),0); - } - CUL_HM_respPendRm($shash); - delete $chnHash->{helper}{shadowReg}{$regLN};#remove shadowhash - # peer Channel name from/for user entry. - CUL_HM_updtRegDisp($chnHash,$list, - CUL_HM_peerChId($peer, - substr(CUL_HM_hash2Id($chnHash),0,6),"00000000")); - } - else{ - CUL_HM_respPendToutProlong($shash);#wasn't last - reschedule timer - } - return "done"; - } - } - elsif($subType eq "04"){ #ParamChange=================================== - my($chn,$peerID,$list,$data) = ($1,$2,$3,$4) if($p =~ m/^04(..)(........)(..)(.*)/); - my $chnHash = $modules{CUL_HM}{defptr}{$src.$chn}; - $chnHash = $shash if(!$chnHash); # will add param to dev if no chan - my $regLN = ((CUL_HM_getExpertMode($chnHash) eq "2")?"":".")."RegL_".$list.":".CUL_HM_id2Name($peerID); - $regLN =~ s/broadcast//; - $regLN =~ s/ /_/g; #remove blanks - - $data =~ s/(..)(..)/ $1:$2/g; - - my $lN = ReadingsVal($chnHash->{NAME},$regLN,""); - my $shdwReg = $chnHash->{helper}{shadowReg}{$regLN}; - foreach my $entry(split(' ',$data)){ - my ($a,$d) = split(":",$entry); - last if ($a eq "00"); - if ($lN =~m/$a:/){$lN =~ s/$a:../$a:$d/; - }else{ $lN .= " ".$entry;} - $shdwReg =~ s/ $a:..// if ($shdwReg);# confirmed: remove from shadow - } - $chnHash->{helper}{shadowReg}{$regLN} = $shdwReg; - $lN = join(' ',sort(split(' ',$lN)));# re-order - if ($lN =~ s/00:00//){$lN .= " 00:00"}; - readingsSingleUpdate($chnHash,$regLN,$lN,0); - CUL_HM_updtRegDisp($chnHash,$list,$peerID); - } - elsif($subType eq "06"){ #reply to status request======================= - my $rssi = substr($p,8,2);# --calculate RSSI - CUL_HM_storeRssi(CUL_HM_hash2Name($shash), - ($dhash?CUL_HM_hash2Name($dhash):$shash->{IODev}{NAME}), - (-1)*(hex($rssi))) - if ($rssi && $rssi ne '00' && $rssi ne'80'); - #todo = what is the answer to a status request - if ($pendType eq "StatusReq"){#it is the answer to our request - my $chnSrc = $src.$shash->{helper}{respWait}{forChn}; - my $chnhash = $modules{CUL_HM}{defptr}{$chnSrc}; - $chnhash = $shash if (!$chnhash); - CUL_HM_respPendRm($shash); - return "STATresp"; - } - else{ - my ($chn) = ($1) if($p =~ m/^..(..)/); - return "powerOn" if ($chn eq "00");# check dst eq "000000" as well? - } - } - } - elsif($msgType eq "70"){ #Time to trigger TC################## - #send wakeup and process command stack -# CUL_HM_SndCmd($shash, '++A112'.CUL_HM_IOid($shash).$src); -# CUL_HM_ProcessCmdStack($shash); - } - return ""; -} -############################# +#+++++++++++++++++ handling register updates ++++++++++++++++++++++++++++++++++ sub CUL_HM_getRegFromStore($$$$) {#read a register from backup data my($name,$regName,$list,$peerId)=@_; my $hash = CUL_HM_name2Hash($name); @@ -4140,7 +4085,10 @@ sub CUL_HM_updtRegDisp($$$) { CUL_HM_UpdtReadBulk($hash,1,@changedRead) if (@changedRead); } ############################# +#+++++++++++++++++ parameter cacculations +++++++++++++++++++++++++++++++++++++ my @culHmTimes8 = ( 0.1, 1, 5, 10, 60, 300, 600, 3600 ); +my %fltCvT = (0.1=>3.1,1=>31,5=>155,10=>310,60=>1860,300=>9300, + 600=>18600,3600=>111600); sub CUL_HM_encodeTime8($) { my $v = shift; return "00" if($v < 0.1); @@ -4198,51 +4146,7 @@ sub CUL_HM_decodeTime16($) {############################# my $mul = 0.1; return 2^$e*$m*0.1; } -############################# -sub CUL_HM_pushConfig($$$$$$$$) {#routine will generate messages to write cnfig data to register - my ($hash,$src,$dst,$chn,$peerAddr,$peerChn,$list,$content) = @_; - my $flag = CUL_HM_getFlag($hash); - my $tl = length($content); - $chn = sprintf("%02X",$chn); - $peerChn = sprintf("%02X",$peerChn); - $list = sprintf("%02X",$list); - - # --store pending changes in shadow to handle bit manipulations cululativ-- - $peerAddr = "000000" if(!$peerAddr); - my $peerN = ($peerAddr ne "000000")?CUL_HM_id2Name($peerAddr.$peerChn):""; - $peerN =~ s/broadcast//; - $peerN =~ s/ /_/g;#remote blanks - my $regLN = ((CUL_HM_getExpertMode($hash) eq "2")?"":"."). - "RegL_".$list.":".$peerN; - #--- copy data from readings to shadow - my $chnhash = $modules{CUL_HM}{defptr}{$dst.$chn}; - $chnhash = $hash if (!$chnhash); - if (!$chnhash->{helper}{shadowReg} || - !$chnhash->{helper}{shadowReg}{$regLN}){ - $chnhash->{helper}{shadowReg}{$regLN} = - ReadingsVal($chnhash->{NAME},$regLN,""); - } - #--- update with ne value - my $regs = $chnhash->{helper}{shadowReg}{$regLN}; - for(my $l = 0; $l < $tl; $l+=4) { #substitute changed bytes in shadow - my $addr = substr($content,$l,2); - my $data = substr($content,$l+2,2); - if(!$regs || !($regs =~ s/$addr:../$addr:$data/)){ - $regs .= " ".$addr.":".$data; - } - } - $chnhash->{helper}{shadowReg}{$regLN} = $regs; - CUL_HM_updtRegDisp($hash,$list,$peerAddr.$peerChn); - CUL_HM_PushCmdStack($hash, "++".$flag.'01'.$src.$dst.$chn.'05'. - $peerAddr.$peerChn.$list); - for(my $l = 0; $l < $tl; $l+=28) { - my $ml = $tl-$l < 28 ? $tl-$l : 28; - CUL_HM_PushCmdStack($hash, "++A001".$src.$dst.$chn."08". - substr($content,$l,$ml)); - } - CUL_HM_PushCmdStack($hash,"++A001".$src.$dst.$chn."06"); -} -sub CUL_HM_secSince2000() { +sub CUL_HM_secSince2000() {############################# # Calculate the local time in seconds from 2000. my $t = time(); my @l = localtime($t); @@ -4253,12 +4157,146 @@ sub CUL_HM_secSince2000() { - 7200; # HM Special return $t; } -############### Activity supervision section ################ + +#--------------- Conversion routines for register settings--------------------- +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}}; + $culHmRegDefine{"lg".$reg}{a} +=0x80; + } + foreach my $type(sort(keys %culHmRegType)){ #update references to register + foreach my $reg (sort(keys %{$culHmRegType{$type}})){ + if ($culHmRegDefShLg{$reg}){ + delete $culHmRegType{$type}{$reg}; + $culHmRegType{$type}{"sh".$reg} = 1; + $culHmRegType{$type}{"lg".$reg} = 1; + } + } + } + foreach my $type(sort(keys %culHmRegModel)){ #update references to register + foreach my $reg (sort(keys %{$culHmRegModel{$type}})){ + if ($culHmRegDefShLg{$reg}){ + delete $culHmRegModel{$type}{$reg}; + $culHmRegModel{$type}{"sh".$reg} = 1; + $culHmRegModel{$type}{"lg".$reg} = 1; + } + } + } + foreach my $type(sort(keys %culHmRegChan)){ #update references to register + foreach my $reg (sort(keys %{$culHmRegChan{$type}})){ + if ($culHmRegDefShLg{$reg}){ + delete $culHmRegChan{$type}{$reg}; + $culHmRegChan{$type}{"sh".$reg} = 1; + $culHmRegChan{$type}{"lg".$reg} = 1; + } + } + } +} +sub CUL_HM_fltCvT($) { # float -> config time + my ($inValue) = @_; + my $exp = 0; + my $div2; + foreach my $div(sort{$a <=> $b} keys %fltCvT){ + $div2 = $div; + last if ($inValue < $fltCvT{$div}); + $exp++; + } + return ($exp << 5)+int($inValue/$div2); +} +sub CUL_HM_CvTflt($) { # config time -> float + my ($inValue) = @_; + return ($inValue & 0x1f)*((sort {$a <=> $b} keys(%fltCvT))[$inValue >> 5]); +} +sub CUL_HM_TCtempReadings($) {# parse TC readings + my ($hash)=@_; + my $name = $hash->{NAME}; + my $regLN = ((CUL_HM_getExpertMode($hash) eq "2")?"":".")."RegL_"; + my $reg5 = ReadingsVal($name,$regLN."05:" ,""); + my $reg6 = ReadingsVal($name,$regLN."06:" ,""); + my @days = ("Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"); + $reg5 =~ s/.* 0B://; #remove register up to addr 11 from list 5 + my $tempRegs = $reg5.$reg6; #one row + $tempRegs =~ s/ 00:00/ /g; #remove regline termination + $tempRegs =~ s/ ..:/,/g; #remove addr Info + $tempRegs =~ s/ //g; #blank + my @Tregs = split(",",$tempRegs); + my @time = @Tregs[grep !($_ % 2), 0..$#Tregs]; # even-index =time + my @temp = @Tregs[grep $_ % 2, 0..$#Tregs]; # odd-index =data + return "reglist incomplete\n" if (scalar( @time )<168); + foreach (@time){$_=hex($_)*10}; + foreach (@temp){$_=hex($_)/2}; + my $setting; + my @changedRead; + push (@changedRead,"tempList_State:". + (($hash->{helper}{shadowReg}{$regLN."05:"} || + $hash->{helper}{shadowReg}{$regLN."06:"} )?"set":"verified")); + for (my $day = 0;$day<7;$day++){ + my $tSpan = 0; + my $dayRead = ""; + for (my $entry = 0;$entry<24;$entry++){ + my $reg = $day *24 + $entry; + last if ($tSpan > 1430); + $tSpan = $time[$reg]; + my $entry = sprintf("%02d:%02d %3.01f",($tSpan/60),($tSpan%60),$temp[$reg]); + $setting .= "Temp set: ".$days[$day]." ".$entry." C\n"; + $dayRead .= " ".$entry; + $tSpan = $time[$reg]; + } + push (@changedRead,"tempList".$days[$day].":".$dayRead); + } + CUL_HM_UpdtReadBulk($hash,1,@changedRead) if (@changedRead); + return $setting; +} +sub CUL_HM_repReadings($) {# for repeater in:hash, out: string with peers + my ($hash)=@_; + my %pCnt; + foreach my$pId(split',',$hash->{helper}{peerIDsRaw}){ + next if (!$pId || $pId eq "00000000"); + $pCnt{$pId}{cnt}++; + } + my $ret; + foreach my$pId(sort keys %pCnt){ + my ($pdID,$bdcst) = ($1,$2) if ($pId =~ m/(......)(..)/); + $ret .= "source ".$pCnt{$pId}{cnt}." entry for: ".CUL_HM_id2Name($pdID) + .($bdcst eq "01"?" broadcast enabled":"")."\n"; + } + return $ret; +} +sub CUL_HM_dimLog($) {# dimmer readings - support virtual chan - unused so far + my ($hash)=@_; + my $lComb = CUL_HM_Get($hash,$hash->{NAME},"reg","logicCombination"); + return if (!$lComb); + my %logicComb=( + inactive=>{calc=>'$val=$val' ,txt=>'unused'}, + or =>{calc=>'$val=$in>$val?$in:$val' ,txt=>'max(state,chan)'}, + and =>{calc=>'$val=$in<$val?$in:$val' ,txt=>'min(state,chan)'}, + xor =>{calc=>'$val=!($in!=0&&$val!=0)?($in>$val?$in:$val): 0' ,txt=>'0 if both are != 0, else max'}, + nor =>{calc=>'$val=100-($in>$val?$in : $val)' ,txt=>'100-max(state,chan)'}, + nand =>{calc=>'$val=100-($in<$val?$in : $val)' ,txt=>'100-min(state,chan)'}, + orinv =>{calc=>'$val=(100-$in)>$val?(100-$in) : $val' ,txt=>'max((100-chn),state)'}, + andinv =>{calc=>'$val=(100-$in)<$val?(100-$in) : $val' ,txt=>'min((100-chn),state)'}, + plus =>{calc=>'$val=($in + $val)<100?($in + $val) : 100' ,txt=>'state + chan'}, + minus =>{calc=>'$val=($in - $val)>0?($in + $val) : 0' ,txt=>'state - chan'}, + mul =>{calc=>'$val=($in * $val)<100?($in + $val) : 100' ,txt=>'state * chan'}, + plusinv =>{calc=>'$val=($val+100-$in)<100?($val+100-$in) : 100' ,txt=>'state + 100 - chan'}, + minusinv=>{calc=>'$val=($val-100+$in)>0?($val-100+$in) : 0' ,txt=>'state - 100 + chan'}, + mulinv =>{calc=>'$val=((100-$in)*$val)<100?(100-$in)*$val) : 100',txt=>'state * (100 - chan)'}, + invPlus =>{calc=>'$val=(100-$val-$in)>0?(100-$val-$in) : 0' ,txt=>'100 - state - chan'}, + invMinus=>{calc=>'$val=(100-$val+$in)<100?(100-$val-$in) : 100' ,txt=>'100 - state + chan'}, + invMul =>{calc=>'$val=(100-$val*$in)>0?(100-$val*$in) : 0' ,txt=>'100 - state * chan'}, + ); + readingsSingleUpdate($hash,"R-logicCombTxt" ,$logicComb{$lComb}{txt},0); + readingsSingleUpdate($hash,"R-logicCombCalc",$logicComb{$lComb}{calc},0); + return ""; +} + +#+++++++++++++++++ Action Detector ++++++++++++++++++++++++++++++++++++++++++++ # 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 # that period. # ActionDetector will use the fixed HMid 000000 -sub CUL_HM_ActGetCreateHash() {# return hash of ActionDetector - create one if not existant +sub CUL_HM_ActGetCreateHash() {# get ActionDetector - create if necessary if (!$modules{CUL_HM}{defptr}{"000000"}){ DoTrigger("global", "UNDEFINED ActionDetector CUL_HM 000000"); $attr{ActionDetector}{actCycle} = 600; @@ -4428,6 +4466,7 @@ sub CUL_HM_ActCheck() {# perform supervision "CUL_HM_ActCheck", "ActionDetector", 0); } +#+++++++++++++++++ helper +++++++++++++++++++++++++++++++++++++++++++++++++++++ sub CUL_HM_UpdtReadBulk(@) { #update a bunch of readings and trigger the events my ($hash,$doTrg,@readings) = @_; return if (!@readings); @@ -4441,7 +4480,7 @@ sub CUL_HM_UpdtReadBulk(@) { #update a bunch of readings and trigger the events readingsEndUpdate($hash,$doTrg); return $hash->{NAME}; } -sub CUL_HM_UpdtReadSingle(@) { #update a bunch of readings and trigger the events +sub CUL_HM_UpdtReadSingle(@) { #update single reading and trigger the event my ($hash,$rName,$val,$updt) = @_; readingsSingleUpdate($hash,$rName,$val,$updt); return $hash->{NAME}; @@ -4453,10 +4492,6 @@ sub CUL_HM_setAttrIfCh($$$$) { $attr{$name}{$att} = $val; } } -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 @_; @@ -4488,12 +4523,18 @@ sub CUL_HM_storeRssi(@){ $hash->{"rssi_".$peerName} = $rssi; return ; } -sub CUL_HM_stateUpdat($){ +sub CUL_HM_stateUpdat($){#in:name, send status-request my $name = shift; (undef,$name)=split":",$name,2; CUL_HM_Set(CUL_HM_name2Hash($name),$name,"statusRequest") if ($name); } +#+++++++++++++++++ external use +++++++++++++++++++++++++++++++++++++++++++++++ +sub CUL_HM_putHash($) {# provide data for HMinfo + my ($info) = @_; + return %culHmModel if ($info eq "culHmModel"); +} + 1; =pod @@ -4709,13 +4750,17 @@ sub CUL_HM_stateUpdat($){
  • pair
    - Pair the device again with its known serialNumber (e.g. after a device - reset) to the CUL. If paired, devices will report status information to - the CUL. If not paired, the device wont respond to requests, and + Pair the device with a known serialNumber (e.g. after a device reset) + to FHEM Central unit. FHEM Central is usualy represented by CUL/CUNO, + HMLAN,... + If paired, devices will report status information to + FHEM. If not paired, the device won't respond to some requests, and certain status information is also not reported. Paring is on device - level and is common for all channels. See also getPair and unpair.
  • + level. Channels cannot be paired to central separate from the device. + See also getPair and + unpair.
    + Don't confuse pair (to a central) with peer (channel to channel) with + devicepair.
  • peerBulk
    peerBulk will add peer channels to the channel. All channels in the list will be added. This includes that the parameter and behavior @@ -4855,6 +4900,8 @@ sub CUL_HM_stateUpdat($){
  • on-for-timer <sec> - Dimmer only!
  • on-till <time> - Dimmer only!
  • stop - stop motion or dim ramp
  • +
  • up [changeValue] [ontime] [ramptime] dim up one step
  • +
  • down [changeValue] [ontime] [ramptime] dim up one step

  • @@ -4868,7 +4915,7 @@ sub CUL_HM_stateUpdat($){
  • devicepair <btn_no> <hmDevice> [single|dual] [set|unset] [actor|remote]
    - Pair/unpair will establish a connection between a sender-channel and + Devicepair will establish a connection between a sender-channel and an actuator-channel called link in HM nomenclatur. Trigger from sender-channel, e.g. button press, will be processed by the actuator-channel without CCU interaction. Sender-channel waits for an @@ -5321,6 +5368,9 @@ sub CUL_HM_stateUpdat($){ ValvePosition:$vp %
    ValveErrorPosition:$vep %
    ValveOffset:$of %
    + ValveDesired:$vp % # set by TC
    + operState:[errorTargetNotMet|onTarget|adjusting] # operational condition
    + operStateErrCnt:$cnt # number of failed settings
  • KFM100:
    $v