diff --git a/fhem/CHANGED b/fhem/CHANGED index 8bf1bc8c5..7ad3927bd 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - bugfix: 88_HMCCU: Some minor bugs fixed - bugfix: 42_XiaomiBTLESens: bugfix humidity reading - feature: 42_AptToDate: add new get command getDistribution to fetch distribution info diff --git a/fhem/FHEM/88_HMCCU.pm b/fhem/FHEM/88_HMCCU.pm index 8370b834c..8d69dbf7c 100755 --- a/fhem/FHEM/88_HMCCU.pm +++ b/fhem/FHEM/88_HMCCU.pm @@ -4,7 +4,7 @@ # # $Id$ # -# Version 4.3.007 +# Version 4.3.008 # # Module for communication between FHEM and Homematic CCU2/3. # @@ -108,7 +108,7 @@ my %HMCCU_CUST_CHN_DEFAULTS; my %HMCCU_CUST_DEV_DEFAULTS; # HMCCU version -my $HMCCU_VERSION = '4.3.007'; +my $HMCCU_VERSION = '4.3.008'; # Default RPC port (BidCos-RF) my $HMCCU_RPC_PORT_DEFAULT = 2001; @@ -2883,7 +2883,7 @@ sub HMCCU_CreateDevice ($$$$$) if (!defined ($sourceAddr)) { # Search for type in device table return 1 if (!defined ($newType)); - for my $da (keys %{$hash->{hmccu}{dev}}) { + foreach my $da (keys %{$hash->{hmccu}{dev}}) { if ($hash->{hmccu}{dev}{$da}{type} eq $newType) { $sourceAddr = $da; last; @@ -4038,7 +4038,7 @@ sub HMCCU_GetDeviceInfo ($$$) $ccuget = HMCCU_GetAttribute ($hmccu_hash, $hash, 'ccuget', 'Value') if ($ccuget eq 'Attr'); - for my $dev (@devlist) { + foreach my $dev (@devlist) { my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $dev, 0); if ($flags == $HMCCU_FLAG_ADDRESS) { $devname = HMCCU_GetDeviceName ($hmccu_hash, $add, ''); @@ -5078,12 +5078,12 @@ sub HMCCU_FindClientDevices ($$$$) } ###################################################################### -# Get name of assigned client device of type HMCCURPC or HMCCURPCPROC. -# Create a RPC device of type HMCCURPC or HMCCURPCPROC if none is -# found and parameter create is set to 1. +# Get name of assigned client device of type HMCCURPCPROC. +# Create a RPC device of type HMCCURPCPROC if none is found and +# parameter create is set to 1. # Return (devname, create). # Return empty string for devname if RPC device cannot be identified -# or created. Return create = 1 if device has been created and +# or created. Return (devname,1) if device has been created and # configuration should be saved. ###################################################################### @@ -5170,6 +5170,10 @@ sub HMCCU_GetRPCDevice ($$$) my %rpcdevattr = ('room' => 'copy', 'group' => 'copy', 'icon' => 'copy', 'stateFormat' => 'rpcstate/state', 'eventMap' => '/rpcserver on:on/rpcserver off:off/', 'verbose' => 2, 'alias' => $alias ); + if ($ifname eq 'BidCos-RF') { + $rpcdevattr{'rpcPingCCU'} = 300; + $rpcdevattr{'ccuflags'} = 'reconnect'; + } foreach my $a (keys %rpcdevattr) { my $v = $rpcdevattr{$a} eq 'copy' ? AttrVal ($name, $a, '') : $rpcdevattr{$a}; CommandAttr (undef, "$rpcdevname $a $v") if ($v ne ''); @@ -6215,7 +6219,7 @@ sub HMCCU_SetDatapoint ($$$) } if ($type eq 'HMCCUDEV' && $hash->{ccuif} eq 'fhem' && $hash->{ccutype} ne 'n/a' && exists ($hash->{ccugroup})) { - for my $gaddr (split (',', $hash->{ccugroup})) { + foreach my $gaddr (split (',', $hash->{ccugroup})) { $cmd .= '(datapoints.Get("'.$int.'.'.$gaddr.':'.$chn.'.'.$dpt.'")).State('.$value.");\n"; } } @@ -7110,13 +7114,20 @@ sub HMCCU_CalculateReading ($$) elsif ($vt eq 'avg') { # Average value next if ($pc < 1); - my $newval = shift @pars; - my $cnt = ReadingsVal ($name, $rn."_cnt", 0); - my $sum = ReadingsVal ($name, $rn."_sum", 0); - $cnt++; - $sum += $newval; - my $curval = $sum/$cnt; - push (@result, $rn."_cnt", $cnt, $rn."_sum", $sum, $rn, $curval); + if ($pc == 1) { + my $newval = shift @pars; + my $cnt = ReadingsVal ($name, $rn."_cnt", 0); + my $sum = ReadingsVal ($name, $rn."_sum", 0); + $cnt++; + $sum += $newval; + my $curval = $sum/$cnt; + push (@result, $rn."_cnt", $cnt, $rn."_sum", $sum, $rn, $curval); + } + else { + my $sum = 0; + foreach my $p (@pars) { $sum += $p; } + push (@result, $rn, $sum/scalar(@pars)); + } } elsif ($vt eq 'sum') { # Sum of values @@ -7632,7 +7643,7 @@ sub HMCCU_CCURPC_NewDevicesCB ($$$) my $msg = ''; Log3 $name, 2, "CCURPC: $cb NewDevice received $devcount device specifications"; - for my $dev (@$a) { + foreach my $dev (@$a) { my $msg = ''; if ($dev->{ADDRESS} =~ /:[0-9]{1,2}$/) { $msg = "C|".$dev->{ADDRESS}."|".$dev->{TYPE}."|".$dev->{VERSION}."|null|null"; @@ -7660,7 +7671,7 @@ sub HMCCU_CCURPC_DeleteDevicesCB ($$$) my $devcount = scalar (@$a); Log3 $name, 2, "CCURPC: $cb DeleteDevice received $devcount device addresses"; - for my $dev (@$a) { + foreach my $dev (@$a) { HMCCU_CCURPC_Write ("DD", $dev); } @@ -7704,7 +7715,7 @@ sub HMCCU_CCURPC_ReaddDevicesCB ($$$) my $devcount = scalar (@$a); Log3 $name, 2, "CCURPC: $cb ReaddDevice received $devcount device addresses"; - for my $dev (@$a) { + foreach my $dev (@$a) { HMCCU_CCURPC_Write ("RA", $dev); } diff --git a/fhem/FHEM/88_HMCCUCHN.pm b/fhem/FHEM/88_HMCCUCHN.pm index f6ea62992..09fd9cf05 100644 --- a/fhem/FHEM/88_HMCCUCHN.pm +++ b/fhem/FHEM/88_HMCCUCHN.pm @@ -4,7 +4,7 @@ # # $Id$ # -# Version 4.3.003 +# Version 4.3.004 # # (c) 2018 zap (zap01 <at> t-online <dot> de) # @@ -788,7 +788,7 @@ sub HMCCUCHN_Get ($@) <i>dp-list</i>. The result is stored in <i>reading</i>. For datapoints in <i>dp-list</i> also variable notation is supported (for more information on variables see documentation of attribute 'peer').<br/> - The following <i>values</i> are supported:<br/> + The following <i>value-types</i> are supported:<br/> dewpoint = calculate dewpoint, <i>dp-list</i> = <temperature>,<humidity><br/> abshumidity = calculate absolute humidity, <i>dp-list</i> = <temperature>,<humidity><br/> equ = compare datapoint values. Result is "n/a" if values are not equal.<br/> diff --git a/fhem/FHEM/88_HMCCURPCPROC.pm b/fhem/FHEM/88_HMCCURPCPROC.pm index 532673b02..72e7be594 100755 --- a/fhem/FHEM/88_HMCCURPCPROC.pm +++ b/fhem/FHEM/88_HMCCURPCPROC.pm @@ -4,7 +4,7 @@ # # $Id$ # -# Version 1.2 +# Version 1.3 # # Subprocess based RPC Server module for HMCCU. # @@ -35,7 +35,7 @@ use SetExtensions; ###################################################################### # HMCCURPC version -my $HMCCURPCPROC_VERSION = '1.2'; +my $HMCCURPCPROC_VERSION = '1.3'; # Maximum number of events processed per call of Read() my $HMCCURPCPROC_MAX_EVENTS = 100; @@ -52,16 +52,16 @@ my $HMCCURPCPROC_MAX_QUEUESEND = 70; # Time to wait after data processing loop in microseconds my $HMCCURPCPROC_TIME_WAIT = 100000; -# Timeout for established CCU connection +# Timeout for established CCU connection in seconds my $HMCCURPCPROC_TIMEOUT_CONNECTION = 1; -# Timeout for TriggerIO() +# Timeout for TriggerIO() in seconds my $HMCCURPCPROC_TIMEOUT_WRITE = 0.001; -# Timeout for accepting incoming connections (0 = default) +# Timeout for accepting incoming connections in seconds (0 = default) my $HMCCURPCPROC_TIMEOUT_ACCEPT = 1; -# Timeout for incoming CCU events +# Timeout for incoming CCU events in seconds my $HMCCURPCPROC_TIMEOUT_EVENT = 600; # Send statistic information after specified amount of events @@ -73,13 +73,13 @@ my $HMCCURPCPROC_RPC_PORT_DEFAULT = 2001; # Default RPC server base port my $HMCCURPCPROC_SERVER_PORT = 5400; -# Delay for RPC server start after FHEM is initialized +# Delay for RPC server start after FHEM is initialized in seconds my $HMCCURPCPROC_INIT_INTERVAL0 = 12; -# Delay for RPC server cleanup after stop +# Delay for RPC server cleanup after stop in seconds my $HMCCURPCPROC_INIT_INTERVAL2 = 30; -# Delay for RPC server functionality check after start +# Delay for RPC server functionality check after start in seconds my $HMCCURPCPROC_INIT_INTERVAL3 = 25; # BinRPC data types @@ -117,24 +117,25 @@ sub HMCCURPCPROC_SetState ($$); sub HMCCURPCPROC_ProcessEvent ($$); # RPC server control functions -sub HMCCURPCPROC_GetRPCServerID ($$); -sub HMCCURPCPROC_RegisterCallback ($$); +sub HMCCURPCPROC_CheckProcessState ($$); +sub HMCCURPCPROC_CleanupIO ($); +sub HMCCURPCPROC_CleanupProcess ($); sub HMCCURPCPROC_DeRegisterCallback ($$); +sub HMCCURPCPROC_GetRPCServerID ($$); +sub HMCCURPCPROC_Housekeeping ($); sub HMCCURPCPROC_InitRPCServer ($$$$); -sub HMCCURPCPROC_StartRPCServer ($); +sub HMCCURPCPROC_IsRPCServerRunning ($); +sub HMCCURPCPROC_IsRPCStateBlocking ($); +sub HMCCURPCPROC_RegisterCallback ($$); +sub HMCCURPCPROC_ResetRPCState ($); +sub HMCCURPCPROC_RPCPing ($); sub HMCCURPCPROC_RPCServerStarted ($); sub HMCCURPCPROC_RPCServerStopped ($); -sub HMCCURPCPROC_CleanupProcess ($); -sub HMCCURPCPROC_CleanupIO ($); -sub HMCCURPCPROC_TerminateProcess ($); -sub HMCCURPCPROC_CheckProcessState ($$); -sub HMCCURPCPROC_IsRPCServerRunning ($); -sub HMCCURPCPROC_Housekeeping ($); -sub HMCCURPCPROC_StopRPCServer ($); sub HMCCURPCPROC_SendRequest ($@); sub HMCCURPCPROC_SetRPCState ($$$$); -sub HMCCURPCPROC_ResetRPCState ($); -sub HMCCURPCPROC_IsRPCStateBlocking ($); +sub HMCCURPCPROC_StartRPCServer ($); +sub HMCCURPCPROC_StopRPCServer ($); +sub HMCCURPCPROC_TerminateProcess ($); # Helper functions sub HMCCURPCPROC_GetAttribute ($$$$); @@ -199,10 +200,10 @@ sub HMCCURPCPROC_Initialize ($) $hash->{parseParams} = 1; - $hash->{AttrList} = "ccuflags:multiple-strict,expert,reconnect,logEvents,ccuInit,queueEvents,noEvents". + $hash->{AttrList} = "ccuflags:multiple-strict,expert,reconnect,logEvents,ccuInit,queueEvents,noEvents,logPong". " rpcMaxEvents rpcQueueSend rpcQueueSize rpcMaxIOErrors". " rpcServerAddr rpcServerPort rpcWriteTimeout rpcAcceptTimeout". - " rpcConnTimeout rpcStatistics rpcEventTimeout ". + " rpcConnTimeout rpcStatistics rpcEventTimeout rpcPingCCU ". $readingFnAttributes; } @@ -245,7 +246,7 @@ sub HMCCURPCPROC_Define ($$) $rpcip = HMCCU_ResolveName ($hash->{host}, 'N/A'); # Find IO device - for my $d (keys %defs) { + foreach my $d (keys %defs) { my $dh = $defs{$d}; next if (!exists ($dh->{TYPE}) || !exists ($dh->{NAME})); next if ($dh->{TYPE} ne 'HMCCU'); @@ -299,7 +300,8 @@ sub HMCCURPCPROC_Define ($$) ###################################################################### # Initialization of FHEM device. -# Called during Define() or by HMCCU after CCU ready. +# Called during Define() or by HMCCU during delayed initialization +# after CCU ready. # Return 0 on successful initialization or >0 on error: # 1 = Invalid port or interface # 2 = Cannot assign IO device @@ -319,7 +321,7 @@ sub HMCCURPCPROC_InitDevice ($$) { return 1 if (!defined ($ifname) || !defined ($ifport)); # Check if RPC device with same interface already exists - for my $d (keys %defs) { + foreach my $d (keys %defs) { my $dh = $defs{$d}; next if (!exists ($dh->{TYPE}) || !exists ($dh->{NAME})); if ($dh->{TYPE} eq 'HMCCURPCPROC' && $dh->{NAME} ne $name && IsDisabled ($dh->{NAME}) != 1) { @@ -354,10 +356,11 @@ sub HMCCURPCPROC_InitDevice ($$) { Log3 $name, 1, "HMCCURPCPROC: [$name] Initialized version $HMCCURPCPROC_VERSION for interface $ifname with I/O device $ioname"; - # Set some attributes + # Set some attributes and start CCU ping if ($init_done) { $attr{$name}{stateFormat} = "rpcstate/state"; - $attr{$name}{verbose} = 2; + $attr{$name}{verbose} = 2;+ + HMCCURPCPROC_RPCPing ($dev_hash); } HMCCURPCPROC_ResetRPCState ($dev_hash); @@ -420,11 +423,27 @@ sub HMCCURPCPROC_Attr ($@) elsif ($attrname eq 'rpcServerAddr') { $hash->{hmccu}{localaddr} = $attrval; } + elsif ($attrname eq 'rpcPingCCU') { + if ($attrval > 0) { + if ($hash->{rpcinterface} =~ /^(BidCos-RF|BidCos-Wired|HmIP-RF)$/) { + InternalTimer (gettimeofday()+$attrval, "HMCCURPCPROC_RPCPing", $hash, 0); + } + else { + return "HMCCURPCPROC: [$name] RPC Ping not supported by interface ".$hash->{rpcinterface}; + } + } + else { + RemoveInternalTimer ($hash, "HMCCURPCPROC_RPCPing"); + } + } } elsif ($cmd eq 'del') { if ($attrname eq 'rpcServerAddr') { $hash->{hmccu}{localaddr} = $hash->{hmccu}{defaultaddr}; } + elsif ($attrname eq 'rpcPingCCU') { + RemoveInternalTimer ($hash, "HMCCURPCPROC_RPCPing"); + } } return undef; @@ -442,7 +461,8 @@ sub HMCCURPCPROC_Set ($@) my $opt = shift @$a; my $ccuflags = AttrVal ($name, 'ccuflags', 'null'); - my $options = $ccuflags =~ /expert/ ? "cleanup:noArg deregister:noArg register:noArg rpcrequest rpcserver:on,off" : ""; + my $options = $ccuflags =~ /expert/ ? + "cleanup:noArg deregister:noArg register:noArg rpcrequest rpcserver:on,off" : ""; my $busyoptions = $ccuflags =~ /expert/ ? "rpcserver:off" : ""; return "HMCCURPCPROC: CCU busy, choose one of $busyoptions" @@ -782,22 +802,18 @@ sub HMCCURPCPROC_ProcessEvent ($$) my $evttimeout = HMCCURPCPROC_GetAttribute ($hash, 'rpcEventTimeout', 'rpcevtimeout', $HMCCURPCPROC_TIMEOUT_EVENT); - # Parse event return undef if (!defined ($event) || $event eq ''); - my @t = split (/\|/, $event); - my $et = shift @t; - my $clkey = shift @t; - my $tc = scalar (@t); # Log event Log3 $name, 2, "HMCCURPCPROC: [$name] CCUEvent = $event" if ($ccuflags =~ /logEvents/); - # Check event data - if (!defined ($clkey)) { - Log3 $name, 2, "HMCCURPCPROC: [$name] Syntax error in RPC event data"; + # Detect event type and clkey + my ($et, $clkey, $evdata) = split (/\|/, $event, 3); + if (!defined ($evdata)) { + Log3 $name, 2, "HMCCURPCPROC: [$name] Syntax error in RPC event data $event"; return undef; } - + # Check for valid server if ($clkey ne $rpcname) { Log3 $name, 2, "HMCCURPCPROC: [$name] Received $et event for unknown RPC server $clkey"; @@ -810,10 +826,14 @@ sub HMCCURPCPROC_ProcessEvent ($$) Log3 $name, 2, "HMCCURPCPROC: [$name] Received unknown event from CCU: ".$et; return undef; } + + # Parse event + my @t = split (/\|/, $evdata, $rpceventargs{$et}); + my $tc = scalar (@t); # Check event parameters if ($tc != $rpceventargs{$et}) { - Log3 $name, 2, "HMCCURPCPROC: [$name] Wrong number of parameters in event $event. Expected ". + Log3 $name, 2, "HMCCURPCPROC: [$name] Wrong number of $tc parameters in event $event. Expected ". $rpceventargs{$et}; return undef; } @@ -832,7 +852,8 @@ sub HMCCURPCPROC_ProcessEvent ($$) $rh->{sumdelay} += $delay; $rh->{avgdelay} = $rh->{sumdelay}/$rh->{rec}{$et}; $hash->{ccustate} = 'active' if ($hash->{ccustate} ne 'active'); - Log3 $name, 3, "HMCCURPCPROC: [$name] Received CENTRAL event. ".$t[2]."=".$t[3] if ($t[1] eq 'CENTRAL'); + Log3 $name, 3, "HMCCURPCPROC: [$name] Received CENTRAL event from $clkey. ".$t[2]."=".$t[3] + if ($t[1] eq 'CENTRAL' && $t[3] eq $rpcname && $ccuflags =~ /logPong/); my ($add, $chn) = split (/:/, $t[1]); return defined ($chn) ? ($et, $clkey, $add, $chn, $t[2], $t[3]) : undef; } @@ -1474,7 +1495,7 @@ sub HMCCURPCPROC_CheckProcessState ($$) sub HMCCURPCPROC_IsRPCServerRunning ($) { - my ($hash, $cleanup) = @_; + my ($hash) = @_; my $name = $hash->{NAME}; Log3 $name, 2, "HMCCURPCPROC: [$name] Checking if RPC server process is running"; @@ -1562,6 +1583,7 @@ sub HMCCURPCPROC_SendRequest ($@) my $rc; if (HMCCU_IsRPCType ($hmccu_hash, $port, 'A')) { + # Use XMLRPC my $clurl = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'url'); return HMCCU_Log ($hash, 2, "Can't get client URL for port $port", undef) if (!defined ($clurl)); @@ -1572,6 +1594,7 @@ sub HMCCURPCPROC_SendRequest ($@) Log3 $name, 2, "HMCCURPCPROC: [$name] RPC request error ".$RPC::XML::ERROR if (!defined ($rc)); } elsif (HMCCU_IsRPCType ($hmccu_hash, $port, 'B')) { + # Use BINRPC my $serveraddr = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'host'); return HMCCU_Log ($hash, 2, "Can't get server address for port $port", undef) if (!defined ($serveraddr)); @@ -1618,6 +1641,25 @@ sub HMCCURPCPROC_SendRequest ($@) return $rc; } +###################################################################### +# Timer function for RPC Ping +###################################################################### + +sub HMCCURPCPROC_RPCPing ($) +{ + my ($hash) = @_; + my $name = $hash->{NAME}; + + my $ping = AttrVal ($name, 'rpcPingCCU', 0); + if ($ping > 0) { + if ($init_done && HMCCURPCPROC_CheckProcessState ($hash, 'running')) { + my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid}; + HMCCURPCPROC_SendRequest ($hash, "ping", $clkey); + } + InternalTimer (gettimeofday()+$ping, "HMCCURPCPROC_RPCPing", $hash, 0); + } +} + ###################################################################### # Process binary RPC request ###################################################################### @@ -2690,6 +2732,7 @@ sub HMCCURPCPROC_DecodeResponse ($) This flag is not supported by interfaces CUxD and HVL.<br/> expert - Activate expert mode<br/> logEvents - Events are written into FHEM logfile if verbose is 4<br/> + logPong - Write log message when receiving pong event if verbose level is at least 3.<br/> noEvents - Ignore events from CCU, do not update client device readings.<br/> queueEvents - Always write events into queue and send them asynchronously to FHEM. Frequency of event transmission to FHEM depends on attribute rpcConnTimeout.<br/> @@ -2717,6 +2760,11 @@ sub HMCCURPCPROC_DecodeResponse ($) message is written into FHEM log file. Default value is 100. Set this attribute to 0 to disable error counting. </li><br/> + <li><b>rpcPingCCU <interval></b><br/> + Send RPC ping request to CCU every <i>interval</i> seconds. If <i>interval</i> is 0 + sending ping requests is disabled. If attribut ccuflags is set to logPong a log message + with level 3 is created when receiving a pong event. + </li><br/> <li><b>rpcQueueSend <events></b><br/> Maximum number of events sent to FHEM per accept loop. Default is 70. If set to 0 all events in queue are sent to FHEM. Transmission is stopped when an I/O error occurrs diff --git a/fhem/FHEM/HMCCUConf.pm b/fhem/FHEM/HMCCUConf.pm index 2d1789e6b..5f70063da 100644 --- a/fhem/FHEM/HMCCUConf.pm +++ b/fhem/FHEM/HMCCUConf.pm @@ -4,7 +4,7 @@ # # $Id$ # -# Version 4.3 +# Version 4.4 # # Configuration parameters for HomeMatic devices. # @@ -58,6 +58,20 @@ use vars qw(%HMCCU_SCRIPTS); statedatapoint => "STATE", substitute => "STATE!0:closed,1:tilted,2:open;ERROR!0:no,1:sabotage" }, + "HmIP-SRH" => { + _description => "Fenster Drehgriffkontakt", + _channels => "1", + ccureadingfilter => "STATE", + statedatapoint => "STATE", + substitute => "STATE!0:closed,1:tilted,2:open" + }, + "HmIP-SAM" => { + _description => "Beschleunigungssensor", + _channels => "1", + ccureadingfilter => "MOTION", + statedatapoint => "MOTION", + substitute => "MOTION!(0|false):no,(1|true):yes" + }, "HM-Sec-Key|HM-Sec-Key-S|HM-Sec-Key-O|HM-Sec-Key-Generic" => { _description => "Funk-Tuerschlossantrieb KeyMatic", _channels => "1", @@ -89,7 +103,7 @@ use vars qw(%HMCCU_SCRIPTS); webCmd => "devstate", widgetOverride => "devstate:uzsuToggle,off,on" }, - "HMIP-PS" => { + "HmIP-PS" => { _description => "Steckdose", _channels => "3", ccureadingfilter => "STATE", @@ -468,6 +482,18 @@ use vars qw(%HMCCU_SCRIPTS); statedatapoint => "1.STATE", substitute => "STATE!0:closed,1:tilted,2:open;ERROR!0:no,1:sabotage" }, + "HMIP-SRH" => { + _description => "Fenster Drehgriffkontakt", + ccureadingfilter => "STATE", + statedatapoint => "1.STATE", + substitute => "STATE!0:closed,1:tilted,2:open" + }, + "HmIP-SAM" => { + _description => "Beschleunigungssensor", + ccureadingfilter => "1.MOTION", + statedatapoint => "1.MOTION", + substitute => "MOTION!(0|false):no,(1|true):yes" + }, "HM-Sec-Key|HM-Sec-Key-S|HM-Sec-Key-O|HM-Sec-Key-Generic" => { _description => "Funk-Tuerschlossantrieb KeyMatic", ccureadingfilter => "(STATE|INHIBIT)", @@ -606,6 +632,14 @@ use vars qw(%HMCCU_SCRIPTS); ccureadingfilter => "PRESS", substitute => "PRESS_SHORT,PRESS_LONG!(1|true):pressed,(0|false):released" }, + "HmIP-BSL" => { + _description => "Schaltaktor mit Signalleuchte", + ccureadingfilter => "(LEVEL|STATE|COLOR|PRESS)", + ccuscaleval => "LEVEL:0:1:0:100", + statedatapoint => "4.STATE", + statevals => "on:true,off:false", + substitute => "STATE!(0|false):off,(1|true):on;COLOR!0:black,1:blue,2:green,3:turquoise,4:red,5:purple,6:yellow,7:white" + }, "HM-SwI-3-FM" => { _description => "Funk-Schalterschnittstelle", ccureadingfilter => "PRESS", @@ -980,7 +1014,7 @@ if (oPR) { parameters => 4, code => qq( object oSV = dom.GetObject("\$name"); -if (!oSV){ +if (!oSV) { object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES); oSV = dom.CreateObject(OT_VARDP); oSysVars.Add(oSV.ID()); @@ -1005,7 +1039,7 @@ else { parameters => 6, code => qq( object oSV = dom.GetObject("\$name"); -if (!oSV){ +if (!oSV) { object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES); oSV = dom.CreateObject(OT_VARDP); oSysVars.Add(oSV.ID()); @@ -1032,7 +1066,7 @@ else { parameters => 6, code => qq( object oSV = dom.GetObject("\$name"); -if (!oSV){ +if (!oSV) { object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES); oSV = dom.CreateObject(OT_VARDP); oSysVars.Add(oSV.ID()); @@ -1095,10 +1129,48 @@ if (oSV) { code => qq( object osysvar; string ssysvarid; -foreach (ssysvarid, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()) -{ +foreach (ssysvarid, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()) { osysvar = dom.GetObject(ssysvarid); - WriteLine (osysvar.Name() # "=" # osysvar.Variable() # "=" # osysvar.Value()); + Write(osysvar.Name()); + if(osysvar.ValueSubType() == 6) { + Write ("=" # osysvar.AlType()); + } + else { + Write ("=" # osysvar.Variable()); + } + WriteLine ("=" # osysvar.Value()); +} + ) + }, + "GetVariablesExt" => { + description => "Query system variables", + syntax => "", + parameters => 0, + code => qq( +string sSysVarId; +foreach (sSysVarId, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()) { + object oSysVar = dom.GetObject(sSysVarId); + Write(oSysVar.Name()); + if (oSysVar.ValueSubType() == 6) { + Write(";" # oSysVar.AlType()); + } else { + Write(";" # oSysVar.Variable()); + } + Write(";" # oSysVar.Value() # ";"); + if (oSysVar.ValueType() == 16) { + Write(oSysVar.ValueList()); + } + Write(";" # oSysVar.ValueMin() # ";" # oSysVar.ValueMax()); + Write(";" # oSysVar.ValueUnit() # ";" # oSysVar.ValueType() # ";" # oSysVar.ValueSubType()); + Write(";" # oSysVar.DPArchive() # ";" # oSysVar.Visible()); + Write(";" # oSysVar.Timestamp().ToInteger()); + if (oSysVar.ValueType() == 2) { + Write(";" # oSysVar.ValueName0()); + } + if (oSysVar.ValueType() == 2) { + Write(";" # oSysVar.ValueName1()); + } + WriteLine(""); } ) }, @@ -1382,6 +1454,147 @@ if(lResult == 0) { WriteLine(lGetOut); } ) + }, + "GetServiceMessages" => { + description => "Read list of CCU service messages", + syntax => "", + parameters => 0, + code => qq( +integer c = 0; +object oTmpArray = dom.GetObject(ID_SERVICES); +if(oTmpArray) { + string sTmp; + string sdesc; + string stest; + foreach(sTmp, oTmpArray.EnumIDs()) { + object oTmp = dom.GetObject(sTmp); + if (oTmp) { + if(oTmp.IsTypeOf(OT_ALARMDP) && (oTmp.AlState() == asOncoming)) { + boolean collect = true; + object trigDP = dom.GetObject(oTmp.AlTriggerDP()); + object och = dom.GetObject((trigDP.Channel())); + object odev = dom.GetObject((och.Device())); + var ival = trigDP.Value(); + time sftime = oTmp.AlOccurrenceTime(); + time sltime = oTmp.LastTriggerTime(); + var sdesc = trigDP.HSSID(); + var sserial = odev.Address(); + string sAlarmMessage = web.webKeyFromStringTable(sdesc.Name()); + if(!sAlarmMessage.Length()) { + sAlarmMessage = sdesc; + } + c = c+1; + WriteLine(sftime # ";" # sltime # ";" # sAlarmMessage # ";" # sserial); + } + } + } +} +Write(c); + ) + }, + "GetAlarms" => { + description => "Read list of CCU alarm messages", + syntax => "", + parameters => 0, + code => qq( +integer c = 0; +object oTmpArray = dom.GetObject( ID_SYSTEM_VARIABLES ); +if(oTmpArray) { + string sTmp; + foreach(sTmp,oTmpArray.EnumIDs()) { + object oTmp = dom.GetObject(sTmp); + if(oTmp) { + if(oTmp.IsTypeOf(OT_ALARMDP) && (oTmp.AlState() == asOncoming)) { + c = c+1; + object oSV = oTmp; + Write(oSV.AlOccurrenceTime()); + Write(";" # oSV.Timestamp()); + object oDestDP = dom.GetObject( oSV.AlDestMapDP() ); + string sDestDPName = ""; + if(oDestDP) { + sDestDPName = oDestDP.Name(); + } + else { + sDestDPName = "none"; + } + Write(";" # sDestDPName); + + string sAlarmName = oSV.Name(); + if(!sAlarmName.Length()) { + sAlarmName = "none"; + } + Write(";" # sAlarmName); + + string sAlarmDescription = oSV.DPInfo(); + if(!sAlarmDescription.Length()) { + sAlarmDescription = "none"; + } + Write(";" # sAlarmDescription); + + string sRooms = ""; + string sLastTriggerName = ""; + string sLastTriggerMessage = ""; + string sLastTriggerKey = ""; + integer iTmpTriggerID = oSV.LastTriggerID(); + if(iTmpTriggerID == ID_ERROR) { + iTmpTriggerID = oSV.AlTriggerDP(); + } + + string sAlarmMessage = ""; + string sChannelName = "none"; + object oLastTrigger = dom.GetObject(iTmpTriggerID); + if(oLastTrigger) { + object oLastTriggerChannel = dom.GetObject(oLastTrigger.Channel()); + if(oLastTriggerChannel) { + sChannelName = oLastTriggerChannel.Name(); + string sLastTriggerName = sChannelName; + string sRID; + foreach(sRID, oLastTriggerChannel.ChnRoom()) { + object oRoom = dom.GetObject(sRID); + if(oRoom) { + sRooms = sRooms # "," # oRoom.Name(); + } + } + + if(oLastTrigger.IsTypeOf(OT_HSSDP)) { + string sLongKey = oLastTriggerChannel.ChnLabel()#"|"#oLastTrigger.HSSID(); + string sShortKey = oLastTrigger.HSSID(); + if((oLastTrigger.ValueType() == ivtInteger) && (oLastTrigger.ValueSubType() == istEnum)) { + sLongKey = sLongKey#"="#web.webGetValueFromList( oLastTrigger.ValueList(), oSV.Value() ); + sShortKey = sShortKey#"="#web.webGetValueFromList( oLastTrigger.ValueList(), oSV.Value() ); + } + sAlarmMessage = web.webKeyFromStringTable(sLongKey); + if(!sAlarmMessage.Length()) { + sAlarmMessage = web.webKeyFromStringTable(sShortKey); + if(!sAlarmMessage.Length()) { + sAlarmMessage = sShortKey; + } + } + } + } + } + else { + if (oSV.IsTypeOf(OT_ALARMDP)) { + if ((oSV.Value() == false) || (oSV.Value() == "")) { + sAlarmMessage = oSV.ValueName0(); + } + else { + sAlarmMessage = oSV.ValueName1(); + } + } + } + if(sRooms == "") { + sRooms = "none"; + } + + Write(";" # sAlarmMessage # ";" # sRooms # ";" # sChannelName); + WriteLine(""); + } + } + } +} +Write(c); + ) } );