mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-01 06:28:32 +00:00
HMCCU: Fixed some bugs
git-svn-id: https://svn.fhem.de/fhem/trunk@18134 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
78ef0f87f2
commit
ba687a7d8e
@ -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: Bug fixes
|
||||
- change: 10_MYSENSORS_DEVICE: make OTA feature available,
|
||||
change battery name convention,
|
||||
support MySensors API 2.0 features like
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.3.008
|
||||
# Version 4.3.009
|
||||
#
|
||||
# Module for communication between FHEM and Homematic CCU2/3.
|
||||
#
|
||||
@ -12,74 +12,17 @@
|
||||
# CCU group devices, HomeGear, CUxD, Osram Lightify, Homematic Virtual Layer
|
||||
# and Philips Hue (not tested)
|
||||
#
|
||||
# (c) 2018 by zap (zap01 <at> t-online <dot> de)
|
||||
# (c) 2019 by zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
##############################################################################
|
||||
#
|
||||
# define <name> HMCCU <hostname_or_ip_of_ccu> [ccunumber] [waitforccu=<seconds>]
|
||||
#
|
||||
# set <name> ackmessages
|
||||
# set <name> cleardefaults
|
||||
# set <name> defaults
|
||||
# set <name> delete <name> [{ OT_VARDP | OT_DEVICE }]
|
||||
# set <name> execute <ccu_program>
|
||||
# set <name> importdefaults <filename>
|
||||
# set <name> hmscript {<scriptfile>|!<function>|'['<code>']'} [dump] [<parname>=<value> [...]]
|
||||
# set <name> rpcregister [{all|<interface>}]
|
||||
# set <name> rpcserver {on|off|restart}
|
||||
# set <name> var [<type>] <name> <value> [<parameter>=<value> [...]]
|
||||
#
|
||||
# get <name> aggregation {<rule>|all}
|
||||
# get <name> configdesc {<device>|<channel>}
|
||||
# get <name> defaults
|
||||
# get <name> deviceinfo <device>
|
||||
# get <name> devicelist [dump]
|
||||
# get <name> devicelist create <devexp> [t={chn|dev|all}] [s=<suffix>] [p=<prefix>] [f=<format>]
|
||||
# [defattr] [duplicates] [save] [<attr>=<val> [...]]}]
|
||||
# get <name> dump {devtypes|datapoints} [<filter>]
|
||||
# get <name> dutycycle
|
||||
# get <name> exportdefaults {filename} [csv] [all]
|
||||
# get <name> firmware [{type-expr}|full]
|
||||
# get <name> parfile [<parfile>]
|
||||
# get <name> rpcevents
|
||||
# get <name> rpcstate
|
||||
# get <name> update [<fhemdevexp> [{ State | Value }]]
|
||||
# get <name> updateccu [<devexp> [{ State | Value }]]
|
||||
# get <name> vars <regexp>
|
||||
#
|
||||
# attr <name> ccuaggregate <rules>
|
||||
# attr <name> ccudef-hmstatevals <subst_rules>
|
||||
# attr <name> ccudef-readingfilter <filter_rule>
|
||||
# attr <name> ccudef-readingname <rules>
|
||||
# attr <name> ccudef-substitute <subst_rule>
|
||||
# attr <name> ccudefaults <filename>
|
||||
# attr <name> ccuflags { intrpc,extrpc,procrpc,dptnocheck,noagg,logEvents,noReadings,nonBlocking }
|
||||
# attr <name> ccuget { State | Value }
|
||||
# attr <name> ccuReqTimeout <seconds>
|
||||
# attr <name> ccuGetVars <seconds>[:<pattern>]
|
||||
# attr <name> parfile <parfile>
|
||||
# attr <name> rpcevtimeout <seconds>
|
||||
# attr <name> rpcinterfaces { BidCos-Wired, BidCos-RF, HmIP-RF, VirtualDevices, Homegear, HVL }
|
||||
# attr <name> rpcinterval <seconds>
|
||||
# attr <name> rpcport <ccu_rpc_port>
|
||||
# attr <name> rpcqueue <file>
|
||||
# attr <name> rpcserver { on | off }
|
||||
# attr <name> rpcserveraddr <ip-or-name>
|
||||
# attr <name> rpcserverport <base_port>
|
||||
# attr <name> rpctimeout <read>[,<write>]
|
||||
# attr <name> stripchar <character>
|
||||
# attr <name> stripnumber [<datapoint-expr!]{-<digits>|0|1|2}[;...]
|
||||
# attr <name> substitute <subst_rule>
|
||||
#
|
||||
# filter_rule := channel-regexp!datapoint-regexp[;...]
|
||||
# subst_rule := [[channel.]datapoint[,...]!]<regexp>:<subtext>[,...][;...]
|
||||
##############################################################################
|
||||
# Verbose levels:
|
||||
#
|
||||
# 0 = Log start/stop and initialization messages
|
||||
# 1 = Log errors
|
||||
# 2 = Log counters and warnings
|
||||
# 3 = Log events and runtime information
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
package main;
|
||||
@ -108,7 +51,7 @@ my %HMCCU_CUST_CHN_DEFAULTS;
|
||||
my %HMCCU_CUST_DEV_DEFAULTS;
|
||||
|
||||
# HMCCU version
|
||||
my $HMCCU_VERSION = '4.3.008';
|
||||
my $HMCCU_VERSION = '4.3.009';
|
||||
|
||||
# Default RPC port (BidCos-RF)
|
||||
my $HMCCU_RPC_PORT_DEFAULT = 2001;
|
||||
@ -119,6 +62,10 @@ my $HMCCU_MAX_IOERRORS = 100;
|
||||
my $HMCCU_MAX_QUEUESIZE = 500;
|
||||
my $HMCCU_TIME_WAIT = 100000;
|
||||
my $HMCCU_TIME_TRIGGER = 10;
|
||||
|
||||
# RPC ping interval for interface BidCos-RF, should be smaller than HMCCU_TIMEOUT_EVENT
|
||||
my $HMCCU_TIME_PING = 300;
|
||||
|
||||
my $HMCCU_TIMEOUT_CONNECTION = 10;
|
||||
my $HMCCU_TIMEOUT_WRITE = 0.001;
|
||||
my $HMCCU_TIMEOUT_ACCEPT = 1;
|
||||
@ -280,6 +227,7 @@ sub HMCCU_UpdateSingleDatapoint ($$$$);
|
||||
sub HMCCU_UpdateSingleDevice ($$$$);
|
||||
|
||||
# RPC functions
|
||||
sub HMCCU_EventsTimedOut ($);
|
||||
sub HMCCU_GetRPCCallbackURL ($$$$$);
|
||||
sub HMCCU_GetRPCDevice ($$$);
|
||||
sub HMCCU_GetRPCInterfaceList ($);
|
||||
@ -424,8 +372,9 @@ sub HMCCU_Initialize ($)
|
||||
" ccudef-hmstatevals:textField-long ccudef-substitute:textField-long".
|
||||
" ccudef-readingname:textField-long ccudef-readingfilter:textField-long".
|
||||
" ccudef-readingformat:name,namelc,address,addresslc,datapoint,datapointlc".
|
||||
" ccuflags:multiple-strict,extrpc,intrpc,procrpc,dptnocheck,noagg,nohmstate,logEvents,noEvents,noReadings,nonBlocking".
|
||||
" ccuReqTimeout ccuGetVars rpcinterval:2,3,5,7,10 rpcqueue".
|
||||
" ccuflags:multiple-strict,extrpc,intrpc,procrpc,dptnocheck,noagg,nohmstate,".
|
||||
"logEvents,noEvents,noReadings,nonBlocking,reconnect,logPong,trace".
|
||||
" ccuReqTimeout ccuGetVars rpcinterval:2,3,5,7,10 rpcqueue rpcPingCCU".
|
||||
" rpcport:multiple-strict,".join(',',sort keys %HMCCU_RPC_NUMPORT).
|
||||
" rpcserver:on,off rpcserveraddr rpcserverport rpctimeout rpcevtimeout parfile substitute".
|
||||
" ccuget:Value,State ".
|
||||
@ -1431,7 +1380,7 @@ sub HMCCU_Set ($@)
|
||||
my @ifList = HMCCU_GetRPCInterfaceList ($hash);
|
||||
if (scalar (@ifList) > 0) {
|
||||
my $ifStr = join (',', @ifList);
|
||||
$options =~ s/register:all/rpcregister:all,$ifStr/;
|
||||
$options =~ s/rpcregister:all/rpcregister:all,$ifStr/;
|
||||
}
|
||||
my $usage = "HMCCU: Unknown argument $opt, choose one of $options";
|
||||
my $host = $hash->{host};
|
||||
@ -1498,13 +1447,14 @@ sub HMCCU_Set ($@)
|
||||
}
|
||||
elsif ($opt eq 'execute') {
|
||||
my $program = shift @$a;
|
||||
$program .= ' '.join(' ', @$a) if (scalar (@$a) > 0);
|
||||
my $response;
|
||||
$usage = "Usage: set $name $opt program-name";
|
||||
|
||||
return HMCCU_SetError ($hash, $usage) if (!defined ($program));
|
||||
|
||||
my $cmd = qq(dom.GetObject("$program").ProgramExecute());
|
||||
my $value = HMCCU_HMCommand ($hash, $cmd, 0);
|
||||
my $value = HMCCU_HMCommand ($hash, $cmd, 1);
|
||||
|
||||
return HMCCU_SetState ($hash, "OK") if (defined ($value));
|
||||
return HMCCU_SetError ($hash, "Program execution error");
|
||||
@ -3510,6 +3460,48 @@ sub HMCCU_GetRPCPortList ($)
|
||||
return @ports;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Called by HMCCURPCPROC device of interface BidCos-RF when no events
|
||||
# from CCU were received for a specified time span.
|
||||
# Return 1 if all RPC servers have been registered successfully.
|
||||
# Return 0 if at least one RPC server failed to register or the
|
||||
# corresponding HMCCURPCPROC device was not found.
|
||||
######################################################################
|
||||
|
||||
sub HMCCU_EventsTimedOut ($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
return 1 if (!HMCCU_IsFlag ($name, 'reconnect'));
|
||||
|
||||
HMCCU_Log ($hash, 2, "Reconnecting to CCU", 0);
|
||||
|
||||
# Register callback for each interface
|
||||
my $rc = 1;
|
||||
my @iflist = HMCCU_GetRPCInterfaceList ($hash);
|
||||
foreach my $ifname (@iflist) {
|
||||
my ($rpcdev, $save) = HMCCU_GetRPCDevice ($hash, 0, $ifname);
|
||||
if ($rpcdev eq '') {
|
||||
HMCCU_Log ($hash, 0, "Can't find RPC device for interface $ifname", 0);
|
||||
$rc = 0;
|
||||
next;
|
||||
}
|
||||
my $cl_hash = $defs{$rpcdev};
|
||||
# Check if CCU interface is reachable before registering callback
|
||||
my ($nrc, $msg) = HMCCURPCPROC_RegisterCallback ($cl_hash, 2);
|
||||
$rc &= $nrc;
|
||||
if ($nrc) {
|
||||
$cl_hash->{ccustate} = 'active';
|
||||
}
|
||||
else {
|
||||
HMCCU_Log ($cl_hash, 1, $msg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Build RPC callback URL
|
||||
# Parameter hash might be a HMCCU or a HMCCURPC hash.
|
||||
@ -4409,7 +4401,7 @@ sub HMCCU_GetDeviceList ($)
|
||||
######################################################################
|
||||
# Read list of datapoints for all or one CCU device type(s).
|
||||
# Function must not be called before GetDeviceList.
|
||||
# Return number of datapoints.
|
||||
# Return number of datapoints read.
|
||||
######################################################################
|
||||
|
||||
sub HMCCU_GetDatapointList ($$$)
|
||||
@ -5170,10 +5162,6 @@ 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 '');
|
||||
@ -6011,7 +5999,7 @@ sub HMCCU_BulkUpdate ($$$$)
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Get datapoint value from CCU and update reading.
|
||||
# Get datapoint value from CCU and optionally update reading.
|
||||
# If parameter noupd is defined and > 0 no readings will be updated.
|
||||
######################################################################
|
||||
|
||||
@ -8049,12 +8037,14 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
|
||||
intrpc - Use internal RPC server. This is the default.<br/>
|
||||
extrpc - Same as procrpc (see below)<br/>
|
||||
logEvents - Write events from CCU into FHEM logfile<br/>
|
||||
logPong - Write log message when receiving pong event if verbose level is at least 3.<br/>
|
||||
noEvents - Ignore events / device updates sent by CCU. No readings will be updated!<br/>
|
||||
nonBlocking - Use non blocking (asynchronous) CCU requests<br/>
|
||||
noReadings - Do not create or update readings<br/>
|
||||
procrpc - Use external RPC server provided by module HMCCPRPCPROC. During first RPC
|
||||
server start HMCCU will create a HMCCURPCPROC device for each interface confiugured
|
||||
in attribute 'rpcinterface'<br/>
|
||||
reconnect - Automatically reconnect to CCU when events timeout occurred.
|
||||
Flags intrpc, extrpc and procrpc cannot be combined.
|
||||
</li><br/>
|
||||
<li><b>ccuget {State | <u>Value</u>}</b><br/>
|
||||
@ -8097,6 +8087,11 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
|
||||
Specifiy how often RPC queue is read. Default is 5 seconds. Only relevant if internal
|
||||
RPC server is used (deprecated).
|
||||
</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
|
||||
ping requests are disabled. Default value is 300 seconds. If attribut ccuflags is set
|
||||
to logPong a log message with level 3 is created when receiving a pong event.
|
||||
</li><br/>
|
||||
<li><b>rpcport <value[,...]></b><br/>
|
||||
Deprecated, use attribute 'rpcinterfaces' instead. Specify list of RPC ports on CCU.
|
||||
Default is 2001. Valid RPC ports are:<br/><br/>
|
||||
|
@ -4,54 +4,12 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.3.004
|
||||
# Version 4.3.005
|
||||
#
|
||||
# (c) 2018 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
######################################################################
|
||||
#
|
||||
# define <name> HMCCUCHN <ccudev> [readonly] [defaults]
|
||||
# [iodev=<iodevname>]
|
||||
#
|
||||
# set <name> config [device] <parameter>=<value> [...]
|
||||
# set <name> control <value>
|
||||
# set <name> datapoint <datapoint> <value> [...]
|
||||
# set <name> defaults
|
||||
# set <name> devstate <value>
|
||||
# set <name> <stateval_cmds>
|
||||
# set <name> on-till <timestamp>
|
||||
# set <name> on-for-timer <ontime>
|
||||
# set <name> pct <level> [{ <ontime> | 0 } [<ramptime>]]
|
||||
# set <name> toggle
|
||||
#
|
||||
# get <name> config [device] [<filter-expr>]
|
||||
# get <name> configdesc [device]
|
||||
# get <name> configlist [device] [<filtet-expr>]
|
||||
# get <name> datapoint <datapoint>
|
||||
# get <name> defaults
|
||||
# get <name> deviceinfo
|
||||
# get <name> devstate
|
||||
# get <name> update
|
||||
#
|
||||
# attr <name> ccucalculate <value>:<reading>[:<dp-list>][...]
|
||||
# attr <name> ccuflags { ackState, nochn0, trace }
|
||||
# attr <name> ccuget { State | Value }
|
||||
# attr <name> ccureadings { 0 | 1 }
|
||||
# attr <name> ccureadingfilter <filter-rule>[;...]
|
||||
# attr <name> ccureadingformat { name[lc] | address[lc] | datapoint[lc] }
|
||||
# attr <name> ccureadingname <oldname>:<newname>[;...]
|
||||
# attr <name> ccuSetOnChange <expr>
|
||||
# attr <name> ccuverify { 0 | 1 | 2 }
|
||||
# attr <name> controldatapoint <datapoint>
|
||||
# attr <name> disable { 0 | 1 }
|
||||
# attr <name> peer datapoints:condition:{hmccu:object=value|ccu:object=value|fhem:command}
|
||||
# attr <name> hmstatevals <subst-rule>[;...]
|
||||
# attr <name> statedatapoint <datapoint>
|
||||
# attr <name> statevals <text1>:<subtext1>[,...]
|
||||
# attr <name> substexcl <reading-expr>
|
||||
# attr <name> substitute <subst-rule>[;...]
|
||||
#
|
||||
######################################################################
|
||||
# Client device for Homematic channels.
|
||||
# Requires modules 88_HMCCU.pm, HMCCUConf.pm
|
||||
######################################################################
|
||||
|
||||
@ -61,8 +19,6 @@ use strict;
|
||||
use warnings;
|
||||
use SetExtensions;
|
||||
|
||||
# use Time::HiRes qw( gettimeofday usleep );
|
||||
|
||||
sub HMCCUCHN_Initialize ($);
|
||||
sub HMCCUCHN_Define ($@);
|
||||
sub HMCCUCHN_InitDevice ($$);
|
||||
@ -239,9 +195,9 @@ sub HMCCUCHN_Attr ($@)
|
||||
return undef;
|
||||
}
|
||||
|
||||
#####################################
|
||||
######################################################################
|
||||
# Set commands
|
||||
#####################################
|
||||
######################################################################
|
||||
|
||||
sub HMCCUCHN_Set ($@)
|
||||
{
|
||||
@ -369,38 +325,53 @@ sub HMCCUCHN_Set ($@)
|
||||
|
||||
return HMCCU_SetState ($hash, "OK");
|
||||
}
|
||||
elsif ($opt eq 'pct') {
|
||||
elsif ($opt eq 'pct' || $opt eq 'up' || $opt eq 'down') {
|
||||
return HMCCU_SetError ($hash, "Can't find LEVEL datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "LEVEL", 2));
|
||||
|
||||
my $objname = '';
|
||||
my $objvalue = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Usage: set $name pct {value} [{ontime} [{ramptime}]]")
|
||||
if (!defined ($objvalue));
|
||||
|
||||
my $timespec = shift @$a;
|
||||
my $ramptime = shift @$a;
|
||||
my %dpval;
|
||||
if ($opt eq 'pct') {
|
||||
my $objname = '';
|
||||
my $objvalue = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Usage: set $name pct {value} [{ontime} [{ramptime}]]")
|
||||
if (!defined ($objvalue));
|
||||
|
||||
my $timespec = shift @$a;
|
||||
my $ramptime = shift @$a;
|
||||
my %dpval;
|
||||
|
||||
# Set on time
|
||||
if (defined ($timespec)) {
|
||||
return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "ON_TIME", 2));
|
||||
if ($timespec =~ /^[0-9]{2}:[0-9]{2}/) {
|
||||
$timespec = HMCCU_GetTimeSpec ($timespec);
|
||||
return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM[:SS]") if ($timespec < 0);
|
||||
# Set on time
|
||||
if (defined ($timespec)) {
|
||||
return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "ON_TIME", 2));
|
||||
if ($timespec =~ /^[0-9]{2}:[0-9]{2}/) {
|
||||
$timespec = HMCCU_GetTimeSpec ($timespec);
|
||||
return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM[:SS]") if ($timespec < 0);
|
||||
}
|
||||
$dpval{"001.$ccuif.$ccuaddr.ON_TIME"} = $timespec if ($timespec > 0);
|
||||
}
|
||||
$dpval{"001.$ccuif.$ccuaddr.ON_TIME"} = $timespec if ($timespec > 0);
|
||||
|
||||
# Set ramp time
|
||||
$dpval{"002.$ccuif.$ccuaddr.RAMP_TIME"} = $ramptime if (defined ($ramptime));
|
||||
|
||||
# Set level
|
||||
$dpval{"003.$ccuif.$ccuaddr.LEVEL"} = $objvalue;
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
|
||||
}
|
||||
else {
|
||||
my $delta = shift @$a;
|
||||
$delta = 10 if (!defined ($delta));
|
||||
$delta = -$delta if ($opt eq 'down');
|
||||
my $objname = "$ccuif.$ccuaddr.LEVEL";
|
||||
|
||||
# Set ramp time
|
||||
$dpval{"002.$ccuif.$ccuaddr.RAMP_TIME"} = $ramptime if (defined ($ramptime));
|
||||
|
||||
# Set level
|
||||
$dpval{"003.$ccuif.$ccuaddr.LEVEL"} = $objvalue;
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 1);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
|
||||
# Set level
|
||||
my $objvalue = min(max($result+$delta,0),100);
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, { "001.$objname" => $objvalue });
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetState ($hash, "OK");
|
||||
}
|
||||
elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
|
||||
@ -471,7 +442,7 @@ sub HMCCUCHN_Set ($@)
|
||||
$retmsg .= " toggle:noArg";
|
||||
$retmsg .= " on-for-timer on-till"
|
||||
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $ccuaddr, "ON_TIME", 2));
|
||||
$retmsg .= " pct"
|
||||
$retmsg .= " pct up down"
|
||||
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $ccuaddr, "LEVEL", 2));
|
||||
}
|
||||
|
||||
@ -479,9 +450,9 @@ sub HMCCUCHN_Set ($@)
|
||||
}
|
||||
}
|
||||
|
||||
#####################################
|
||||
######################################################################
|
||||
# Get commands
|
||||
#####################################
|
||||
######################################################################
|
||||
|
||||
sub HMCCUCHN_Get ($@)
|
||||
{
|
||||
@ -679,6 +650,10 @@ sub HMCCUCHN_Get ($@)
|
||||
Example:<br/>
|
||||
<code>set light_entrance devstate true</code>
|
||||
</li><br/>
|
||||
<li><b>set <name> down [<value>]</b><br/>
|
||||
Decrement value of datapoint LEVEL. This command is only available if channel contains
|
||||
a datapoint LEVEL. Default for <i>value</i> is 10.
|
||||
</li><br/>
|
||||
<li><b>set <name> <statevalue></b><br/>
|
||||
Set state of a CCU device channel to <i>StateValue</i>. The state datapoint of a channel
|
||||
must be defined by setting attribute 'statedatapoint'. The available state values must
|
||||
@ -736,6 +711,10 @@ sub HMCCUCHN_Get ($@)
|
||||
set myswitch pct 100 600 10
|
||||
</code>
|
||||
</li><br/>
|
||||
<li><b>set <name> up [<value>]</b><br/>
|
||||
Increment value of datapoint LEVEL. This command is only available if channel contains
|
||||
a datapoint LEVEL. Default for <i>value</i> is 10.
|
||||
</li><br/>
|
||||
</ul>
|
||||
<br/>
|
||||
|
||||
|
@ -4,55 +4,12 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.3.005
|
||||
# Version 4.3.006
|
||||
#
|
||||
# (c) 2018 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
######################################################################
|
||||
#
|
||||
# define <name> HMCCUDEV {<ccudev>|virtual} [<statechannel>] [readonly] [defaults]
|
||||
# [{group={<device>|<channel>}[,...]|groupexp=<regexp>}] [iodev=<iodevname>]
|
||||
#
|
||||
# set <name> clear [<regexp>]
|
||||
# set <name> config [<channel-number>] <parameter>=<value> [...]
|
||||
# set <name> control <value>
|
||||
# set <name> datapoint [<channel-number>.]<datapoint> <value> [...]
|
||||
# set <name> defaults
|
||||
# set <name> devstate <value>
|
||||
# set <name> on-till <timestamp>
|
||||
# set <name> on-for-timer <ontime>
|
||||
# set <name> pct <level> [{<ontime>|0} [<ramptime>]]
|
||||
# set <name> <stateval_cmds>
|
||||
# set <name> toggle
|
||||
#
|
||||
# get <name> config [<channel-number>] [<filter-expr>]
|
||||
# get <name> configdesc [<channel-number>]
|
||||
# get <name> configlist [<channel-number>]
|
||||
# get <name> datapoint [<channel-number>.]<datapoint>
|
||||
# get <name> defaults
|
||||
# get <name> devstate
|
||||
# get <name> update
|
||||
#
|
||||
# attr <name> ccucalculate <value>:<reading>[:<dp-list>][...]
|
||||
# attr <name> ccuflags { ackState, nochn0, trace }
|
||||
# attr <name> ccuget { State | Value }
|
||||
# attr <name> ccureadings { 0 | 1 }
|
||||
# attr <name> ccureadingformat { address[lc] | name[lc] | datapoint[lc] }
|
||||
# attr <name> ccureadingfilter <filter-rule>[,...]
|
||||
# attr <name> ccureadingname <oldname>:<newname>[,...]
|
||||
# attr <name> ccuscaleval <datapoint>:<factor>[:<min>:<max>][,...]
|
||||
# attr <name> ccuverify { 0 | 1 | 2}
|
||||
# attr <name> controldatapoint <channel-number>.<datapoint>
|
||||
# attr <name> disable { 0 | 1 }
|
||||
# attr <name> peer datapoints:condition:{hmccu:object=value|ccu:object=value|fhem:command}
|
||||
# attr <name> hmstatevals <subst-rule>[;...]
|
||||
# attr <name> statechannel <channel>
|
||||
# attr <name> statedatapoint [<channel-number>.]<datapoint>
|
||||
# attr <name> statevals <text1>:<subtext1>[,...]
|
||||
# attr <name> substexcl <reading-expr>
|
||||
# attr <name> substitute <subst-rule>[;...]
|
||||
#
|
||||
######################################################################
|
||||
# Client device for Homematic devices.
|
||||
# Requires modules 88_HMCCU.pm, HMCCUConf.pm
|
||||
######################################################################
|
||||
|
||||
@ -61,9 +18,6 @@ package main;
|
||||
use strict;
|
||||
use warnings;
|
||||
use SetExtensions;
|
||||
# use Data::Dumper;
|
||||
|
||||
# use Time::HiRes qw( gettimeofday usleep );
|
||||
|
||||
sub HMCCUDEV_Initialize ($);
|
||||
sub HMCCUDEV_Define ($@);
|
||||
@ -73,9 +27,9 @@ sub HMCCUDEV_Set ($@);
|
||||
sub HMCCUDEV_Get ($@);
|
||||
sub HMCCUDEV_Attr ($@);
|
||||
|
||||
#####################################
|
||||
######################################################################
|
||||
# Initialize module
|
||||
#####################################
|
||||
######################################################################
|
||||
|
||||
sub HMCCUDEV_Initialize ($)
|
||||
{
|
||||
@ -98,9 +52,9 @@ sub HMCCUDEV_Initialize ($)
|
||||
$readingFnAttributes;
|
||||
}
|
||||
|
||||
#####################################
|
||||
######################################################################
|
||||
# Define device
|
||||
#####################################
|
||||
######################################################################
|
||||
|
||||
sub HMCCUDEV_Define ($@)
|
||||
{
|
||||
@ -537,7 +491,7 @@ sub HMCCUDEV_Set ($@)
|
||||
|
||||
return HMCCU_SetState ($hash, "OK");
|
||||
}
|
||||
elsif ($opt eq 'pct') {
|
||||
elsif ($opt eq 'pct' || $opt eq 'up' || $opt eq 'down') {
|
||||
return HMCCU_SetError ($hash, -11) if ($sc eq '' && $cc eq '');
|
||||
my $chn;
|
||||
if (HMCCU_IsValidDatapoint ($hash, $ccutype, $cc, "LEVEL", 2)) {
|
||||
@ -550,35 +504,52 @@ sub HMCCUDEV_Set ($@)
|
||||
return HMCCU_SetError ($hash, "Can't find LEVEL datapoint for device type $ccutype")
|
||||
}
|
||||
|
||||
my $objname = '';
|
||||
my $objvalue = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Usage: set $name pct {value} [{ontime} [{ramptime}]]")
|
||||
if (!defined ($objvalue));
|
||||
if ($opt eq 'pct') {
|
||||
my $objname = '';
|
||||
my $objvalue = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Usage: set $name pct {value} [{ontime} [{ramptime}]]")
|
||||
if (!defined ($objvalue));
|
||||
|
||||
my $timespec = shift @$a;
|
||||
my $ramptime = shift @$a;
|
||||
my %dpval;
|
||||
my $timespec = shift @$a;
|
||||
my $ramptime = shift @$a;
|
||||
my %dpval;
|
||||
|
||||
# Set on time
|
||||
if (defined ($timespec)) {
|
||||
return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $chn, "ON_TIME", 2));
|
||||
# Set on time
|
||||
if (defined ($timespec)) {
|
||||
return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $chn, "ON_TIME", 2));
|
||||
|
||||
if ($timespec =~ /^[0-9]{2}:[0-9]{2}/) {
|
||||
$timespec = HMCCU_GetTimeSpec ($timespec);
|
||||
return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM[:SS]") if ($timespec < 0);
|
||||
if ($timespec =~ /^[0-9]{2}:[0-9]{2}/) {
|
||||
$timespec = HMCCU_GetTimeSpec ($timespec);
|
||||
return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM[:SS]") if ($timespec < 0);
|
||||
}
|
||||
$dpval{"001.$ccuif.$ccuaddr:$chn.ON_TIME"} = $timespec if ($timespec > 0);
|
||||
}
|
||||
$dpval{"001.$ccuif.$ccuaddr:$chn.ON_TIME"} = $timespec if ($timespec > 0);
|
||||
}
|
||||
|
||||
# Set ramp time
|
||||
$dpval{"002.$ccuif.$ccuaddr:$chn.RAMP_TIME"} = $ramptime if (defined ($ramptime));
|
||||
|
||||
# Set level
|
||||
$dpval{"003.$ccuif.$ccuaddr:$chn.LEVEL"} = $objvalue;
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
|
||||
# Set ramp time
|
||||
$dpval{"002.$ccuif.$ccuaddr:$chn.RAMP_TIME"} = $ramptime if (defined ($ramptime));
|
||||
|
||||
# Set level
|
||||
$dpval{"003.$ccuif.$ccuaddr:$chn.LEVEL"} = $objvalue;
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
|
||||
}
|
||||
else {
|
||||
my $delta = shift @$a;
|
||||
$delta = 10 if (!defined ($delta));
|
||||
$delta = -$delta if ($opt eq 'down');
|
||||
my $objname = "$ccuif.$ccuaddr:$chn.LEVEL";
|
||||
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 1);
|
||||
Log3 $name, 2, "HMCCU: set $opt: GetDatapoint returned $rc, $result"
|
||||
if ($ccuflags =~ /trace/);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
|
||||
# Set level
|
||||
my $objvalue = min(max($result+$delta,0),100);
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, { "001.$objname" => $objvalue });
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
|
||||
return HMCCU_SetState ($hash, "OK");
|
||||
}
|
||||
elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
|
||||
@ -653,7 +624,7 @@ sub HMCCUDEV_Set ($@)
|
||||
$retmsg .= " toggle:noArg";
|
||||
$retmsg .= " on-for-timer on-till"
|
||||
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $sc, "ON_TIME", 2));
|
||||
$retmsg .= " pct"
|
||||
$retmsg .= " pct up down"
|
||||
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $sc, "LEVEL", 2) ||
|
||||
HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $cc, "LEVEL", 2));
|
||||
}
|
||||
@ -923,6 +894,9 @@ sub HMCCUDEV_Get ($@)
|
||||
Set state of a CCU device channel. Channel and state datapoint must be defined as
|
||||
attribute 'statedatapoint'. If <i>value</i> contains string \_ it is substituted by blank.
|
||||
</li><br/>
|
||||
<li><b>set <name> down [<value>]</b><br/>
|
||||
<a href="#HMCCUCHNset">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
<li><b>set <name> on-for-timer <ontime></b><br/>
|
||||
<a href="#HMCCUCHNset">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
@ -947,6 +921,9 @@ sub HMCCUDEV_Get ($@)
|
||||
<li><b>set <name> toggle</b><br/>
|
||||
<a href="#HMCCUCHNset">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
<li><b>set <name> up [<value>]</b><br/>
|
||||
<a href="#HMCCUCHNset">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
<li><b>ePaper Display</b><br/><br/>
|
||||
This display has 5 text lines. The lines 1,2 and 4,5 are accessible via config parameters
|
||||
TEXTLINE_1 and TEXTLINE_2 in channels 1 and 2. Example:<br/><br/>
|
||||
|
@ -4,11 +4,11 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 1.3
|
||||
# Version 1.4
|
||||
#
|
||||
# Subprocess based RPC Server module for HMCCU.
|
||||
#
|
||||
# (c) 2018 by zap (zap01 <at> t-online <dot> de)
|
||||
# (c) 2019 by zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
##############################################################################
|
||||
#
|
||||
@ -35,7 +35,7 @@ use SetExtensions;
|
||||
######################################################################
|
||||
|
||||
# HMCCURPC version
|
||||
my $HMCCURPCPROC_VERSION = '1.3';
|
||||
my $HMCCURPCPROC_VERSION = '1.4';
|
||||
|
||||
# Maximum number of events processed per call of Read()
|
||||
my $HMCCURPCPROC_MAX_EVENTS = 100;
|
||||
@ -52,6 +52,9 @@ my $HMCCURPCPROC_MAX_QUEUESEND = 70;
|
||||
# Time to wait after data processing loop in microseconds
|
||||
my $HMCCURPCPROC_TIME_WAIT = 100000;
|
||||
|
||||
# RPC ping interval for interface BidCos-RF, should be smaller than HMCCURPCPROC_TIMEOUT_EVENT
|
||||
my $HMCCURPCPROC_TIME_PING = 300;
|
||||
|
||||
# Timeout for established CCU connection in seconds
|
||||
my $HMCCURPCPROC_TIMEOUT_CONNECTION = 1;
|
||||
|
||||
@ -61,8 +64,8 @@ my $HMCCURPCPROC_TIMEOUT_WRITE = 0.001;
|
||||
# Timeout for accepting incoming connections in seconds (0 = default)
|
||||
my $HMCCURPCPROC_TIMEOUT_ACCEPT = 1;
|
||||
|
||||
# Timeout for incoming CCU events in seconds
|
||||
my $HMCCURPCPROC_TIMEOUT_EVENT = 600;
|
||||
# Timeout for incoming CCU events in seconds (0 = ignore timeout)
|
||||
my $HMCCURPCPROC_TIMEOUT_EVENT = 0;
|
||||
|
||||
# Send statistic information after specified amount of events
|
||||
my $HMCCURPCPROC_STATISTICS = 500;
|
||||
@ -200,7 +203,7 @@ sub HMCCURPCPROC_Initialize ($)
|
||||
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = "ccuflags:multiple-strict,expert,reconnect,logEvents,ccuInit,queueEvents,noEvents,logPong".
|
||||
$hash->{AttrList} = "ccuflags:multiple-strict,expert,logEvents,ccuInit,queueEvents,noEvents".
|
||||
" rpcMaxEvents rpcQueueSend rpcQueueSize rpcMaxIOErrors".
|
||||
" rpcServerAddr rpcServerPort rpcWriteTimeout rpcAcceptTimeout".
|
||||
" rpcConnTimeout rpcStatistics rpcEventTimeout rpcPingCCU ".
|
||||
@ -356,11 +359,10 @@ sub HMCCURPCPROC_InitDevice ($$) {
|
||||
|
||||
Log3 $name, 1, "HMCCURPCPROC: [$name] Initialized version $HMCCURPCPROC_VERSION for interface $ifname with I/O device $ioname";
|
||||
|
||||
# Set some attributes and start CCU ping
|
||||
# Set some attributes
|
||||
if ($init_done) {
|
||||
$attr{$name}{stateFormat} = "rpcstate/state";
|
||||
$attr{$name}{verbose} = 2;+
|
||||
HMCCURPCPROC_RPCPing ($dev_hash);
|
||||
$attr{$name}{verbose} = 2;
|
||||
}
|
||||
|
||||
HMCCURPCPROC_ResetRPCState ($dev_hash);
|
||||
@ -424,26 +426,19 @@ sub HMCCURPCPROC_Attr ($@)
|
||||
$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");
|
||||
}
|
||||
Log3 $name, 1, "HMCCURPCPROC: [$name] Attribute rpcPingCCU ignored. Please set it in I/O device"
|
||||
}
|
||||
elsif ($attrname eq 'ccuflags' && $attrval =~ /reconnect/) {
|
||||
Log3 $name, 1, "HMCCURPCPROC: [$name] Flag reconnect ignored. Please set it in I/O device"
|
||||
}
|
||||
elsif ($attrname eq 'ccuflags' && $attrval =~ /logPong/) {
|
||||
Log3 $name, 1, "HMCCURPCPROC: [$name] Flag logPong ignored. Please set it in I/O device"
|
||||
}
|
||||
}
|
||||
elsif ($cmd eq 'del') {
|
||||
if ($attrname eq 'rpcServerAddr') {
|
||||
$hash->{hmccu}{localaddr} = $hash->{hmccu}{defaultaddr};
|
||||
}
|
||||
elsif ($attrname eq 'rpcPingCCU') {
|
||||
RemoveInternalTimer ($hash, "HMCCURPCPROC_RPCPing");
|
||||
}
|
||||
}
|
||||
|
||||
return undef;
|
||||
@ -799,9 +794,10 @@ sub HMCCURPCPROC_ProcessEvent ($$)
|
||||
);
|
||||
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
my $evttimeout = HMCCURPCPROC_GetAttribute ($hash, 'rpcEventTimeout', 'rpcevtimeout',
|
||||
$HMCCURPCPROC_TIMEOUT_EVENT);
|
||||
|
||||
my $ping = AttrVal ($hmccu_hash->{NAME}, 'rpcPingCCU', $HMCCURPCPROC_TIME_PING);
|
||||
my $evttimeout = ($ping > 0 && $hash->{rpcinterface} eq 'BidCos-RF') ? $ping*2 :
|
||||
HMCCURPCPROC_GetAttribute ($hash, 'rpcEventTimeout', 'rpcevtimeout', $HMCCURPCPROC_TIMEOUT_EVENT);
|
||||
|
||||
return undef if (!defined ($event) || $event eq '');
|
||||
|
||||
# Log event
|
||||
@ -853,7 +849,7 @@ sub HMCCURPCPROC_ProcessEvent ($$)
|
||||
$rh->{avgdelay} = $rh->{sumdelay}/$rh->{rec}{$et};
|
||||
$hash->{ccustate} = 'active' if ($hash->{ccustate} ne 'active');
|
||||
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/);
|
||||
if ($t[1] eq 'CENTRAL' && $t[3] eq $rpcname && HMCCU_IsFlag ($hmccu_hash->{NAME}, 'logPong'));
|
||||
my ($add, $chn) = split (/:/, $t[1]);
|
||||
return defined ($chn) ? ($et, $clkey, $add, $chn, $t[2], $t[3]) : undef;
|
||||
}
|
||||
@ -953,21 +949,15 @@ sub HMCCURPCPROC_ProcessEvent ($$)
|
||||
elsif ($et eq 'TO') {
|
||||
#
|
||||
# Event timeout
|
||||
# Input: TO|clkey|Time
|
||||
# Output: TO, clkey, Port, Time
|
||||
# Input: TO|clkey|DiffTime
|
||||
# Output: TO, clkey, Port, DiffTime
|
||||
#
|
||||
if ($evttimeout > 0 && $evttimeout >= $t[0]) {
|
||||
if ($evttimeout > 0 && $t[0] > $evttimeout) {
|
||||
Log3 $name, 2, "HMCCURPCPROC: [$name] Received no events from interface $clkey for ".$t[0]." seconds";
|
||||
$hash->{ccustate} = 'timeout';
|
||||
if ($hash->{RPCState} eq 'running' && $ccuflags =~ /reconnect/) {
|
||||
Log3 $name, 2, "HMCCURPCPROC: [$name] Reconnecting to CCU interface ".$hash->{rpcinterface};
|
||||
my ($rc, $rcmsg) = HMCCURPCPROC_RegisterCallback ($hash, 2);
|
||||
if ($rc) {
|
||||
$hash->{ccustate} = 'active';
|
||||
}
|
||||
else {
|
||||
Log3 $name, 1, "HMCCURPCPROC: [$name] $rcmsg";
|
||||
}
|
||||
if ($hash->{RPCState} eq 'running' && $hash->{rpcport} == 2001) {
|
||||
# If interface is BidCos-RF inform IO device about timeout
|
||||
HMCCU_EventsTimedOut ($hmccu_hash)
|
||||
}
|
||||
DoTrigger ($name, "No events from interface $clkey for ".$t[0]." seconds");
|
||||
}
|
||||
@ -1227,10 +1217,12 @@ sub HMCCURPCPROC_StartRPCServer ($)
|
||||
return (0, "RPC server already running") if (HMCCURPCPROC_CheckProcessState ($hash, 'running'));
|
||||
|
||||
# Get parameters and attributes
|
||||
my %procpar;
|
||||
my $ping = AttrVal ($hmccu_hash->{NAME}, 'rpcPingCCU', $HMCCURPCPROC_TIME_PING);
|
||||
my $localaddr = HMCCURPCPROC_GetAttribute ($hash, undef, 'rpcserveraddr', $hash->{hmccu}{localaddr});
|
||||
my $rpcserverport = HMCCURPCPROC_GetAttribute ($hash, 'rpcServerPort', 'rpcserverport', $HMCCURPCPROC_SERVER_PORT);
|
||||
my $evttimeout = HMCCURPCPROC_GetAttribute ($hash, 'rpcEventTimeout', 'rpcevtimeout', $HMCCURPCPROC_TIMEOUT_EVENT);
|
||||
my $evttimeout = ($ping > 0 && $hash->{rpcinterface} eq 'BidCos-RF') ?
|
||||
$ping*2 :
|
||||
HMCCURPCPROC_GetAttribute ($hash, 'rpcEventTimeout', 'rpcevtimeout', $HMCCURPCPROC_TIMEOUT_EVENT);
|
||||
my $ccunum = $hash->{CCUNum};
|
||||
my $rpcport = $hash->{rpcport};
|
||||
my $serveraddr = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'host');
|
||||
@ -1239,16 +1231,16 @@ sub HMCCURPCPROC_StartRPCServer ($)
|
||||
$hash->{hmccu}{localaddr} = $localaddr;
|
||||
|
||||
# Store parameters for child process
|
||||
my %procpar;
|
||||
$procpar{socktimeout} = AttrVal ($name, 'rpcWriteTimeout', $HMCCURPCPROC_TIMEOUT_WRITE);
|
||||
$procpar{conntimeout} = AttrVal ($name, 'rpcConnTimeout', $HMCCURPCPROC_TIMEOUT_CONNECTION);
|
||||
$procpar{acctimeout} = AttrVal ($name, 'rpcAcceptTimeout', $HMCCURPCPROC_TIMEOUT_ACCEPT);
|
||||
$procpar{evttimeout} = AttrVal ($name, 'rpcEventTimeout', $HMCCURPCPROC_TIMEOUT_EVENT);
|
||||
$procpar{queuesize} = AttrVal ($name, 'rpcQueueSize', $HMCCURPCPROC_MAX_QUEUESIZE);
|
||||
$procpar{queuesend} = AttrVal ($name, 'rpcQueueSend', $HMCCURPCPROC_MAX_QUEUESEND);
|
||||
$procpar{statistics} = AttrVal ($name, 'rpcStatistics', $HMCCURPCPROC_STATISTICS);
|
||||
$procpar{maxioerrors} = AttrVal ($name, 'rpcMaxIOErrors', $HMCCURPCPROC_MAX_IOERRORS);
|
||||
$procpar{evttimeout} = AttrVal ($name, 'rpcEventTimeout', $HMCCURPCPROC_TIMEOUT_EVENT);
|
||||
$procpar{ccuflags} = AttrVal ($name, 'ccuflags', 'null');
|
||||
$procpar{evttimeout} = $evttimeout;
|
||||
$procpar{interface} = $interface;
|
||||
$procpar{flags} = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'flags');
|
||||
$procpar{type} = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'type');
|
||||
@ -1290,7 +1282,8 @@ sub HMCCURPCPROC_StartRPCServer ($)
|
||||
if (!$rpcpid) {
|
||||
# Child process, only needs parent socket
|
||||
HMCCURPCPROC_HandleConnection ($rpcport, $callbackport, $sockparent, \%procpar);
|
||||
# Exit child process
|
||||
|
||||
# Connection loop ended. Close sockets and exit child process
|
||||
close ($sockparent);
|
||||
close ($sockchild);
|
||||
exit (0);
|
||||
@ -1338,18 +1331,28 @@ sub HMCCURPCPROC_RPCServerStarted ($)
|
||||
my $hmccu_hash = $hash->{IODev};
|
||||
my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
|
||||
my $ifname = $hash->{rpcinterface};
|
||||
my $ping = AttrVal ($hmccu_hash->{NAME}, 'rpcPingCCU', $HMCCURPCPROC_TIME_PING);
|
||||
|
||||
# Check if RPC servers are running. Set overall status
|
||||
if (HMCCURPCPROC_CheckProcessState ($hash, 'running')) {
|
||||
$hash->{hmccu}{rpcstarttime} = time ();
|
||||
HMCCURPCPROC_SetState ($hash, "OK");
|
||||
|
||||
# Update client devices if interface is managed by HMCCURPCPROC device.
|
||||
# Normally interfaces are managed by HMCCU device.
|
||||
if ($hmccu_hash->{hmccu}{interfaces}{$ifname}{manager} eq 'HMCCURPCPROC') {
|
||||
my ($c_ok, $c_err) = HMCCU_UpdateClients ($hmccu_hash, '.*', 'Attr', 0, $ifname);
|
||||
Log3 $name, 2, "HMCCURPCPROC: [$name] Updated devices. Success=$c_ok Failed=$c_err";
|
||||
}
|
||||
|
||||
RemoveInternalTimer ($hash, "HMCCURPCPROC_IsRPCServerRunning");
|
||||
|
||||
# Activate heartbeat if interface is BidCos-RF and rpcPingCCU > 0
|
||||
if ($ping > 0 && $ifname eq "BidCos-RF") {
|
||||
Log3 $name, 1, "HMCCURPCPROC: [$name] Scheduled CCU ping every $ping seconds";
|
||||
InternalTimer (gettimeofday()+$ping, "HMCCURPCPROC_RPCPing", $hash, 0);
|
||||
}
|
||||
|
||||
RemoveInternalTimer ($hash);
|
||||
DoTrigger ($name, "RPC server $clkey running");
|
||||
return 1;
|
||||
}
|
||||
@ -1649,14 +1652,20 @@ sub HMCCURPCPROC_RPCPing ($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $hmccu_hash = $hash->{IODev};
|
||||
my $ping = AttrVal ($hmccu_hash->{NAME}, 'rpcPingCCU', $HMCCURPCPROC_TIME_PING);
|
||||
|
||||
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);
|
||||
if ($hash->{rpcinterface} eq 'BidCos-RF') {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
Log3 $name, 1, "HMCCURPCPROC: [$name] CCU ping disabled";
|
||||
}
|
||||
InternalTimer (gettimeofday()+$ping, "HMCCURPCPROC_RPCPing", $hash, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2732,11 +2741,9 @@ 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/>
|
||||
reconnect - Try to re-register at CCU if no events received for rpcEventTimeout seconds<br/>
|
||||
</li><br/>
|
||||
<li><b>rpcAcceptTimeout <seconds></b><br/>
|
||||
Specify timeout for accepting incoming connections. Default is 1 second. Increase this
|
||||
@ -2746,9 +2753,9 @@ sub HMCCURPCPROC_DecodeResponse ($)
|
||||
Specify timeout of incoming CCU connections. Default is 1 second. Value must be greater than 0.
|
||||
</li><br/>
|
||||
<li><b>rpcEventTimeout <seconds></b><br/>
|
||||
Specify timeout for CCU events. Default is 600 seconds. If timeout occurs an event
|
||||
is triggered. If set to 0 the timeout is ignored. If ccuflag reconnect is set the
|
||||
RPC device tries to establish a new connection to the CCU.
|
||||
Specify timeout for CCU events. Default is 0, timeout is ignored. If timeout occurs an event
|
||||
is triggered. If ccuflag reconnect is set in I/O device the RPC device tries to establish a new
|
||||
connection to the CCU.
|
||||
</li><br/>
|
||||
<li><b>rpcMaxEvents <count></b><br/>
|
||||
Specify maximum number of events read by FHEM during one I/O loop. If FHEM performance
|
||||
@ -2761,9 +2768,7 @@ sub HMCCURPCPROC_DecodeResponse ($)
|
||||
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.
|
||||
Ignored. Should be set in I/O device.
|
||||
</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
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.4
|
||||
# Version 4.5
|
||||
#
|
||||
# Configuration parameters for HomeMatic devices.
|
||||
#
|
||||
@ -765,7 +765,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
webCmd => "control:Auto:Manu:Boost:on:off",
|
||||
widgetOverride => "control:slider,4.5,0.5,30.5,1"
|
||||
},
|
||||
"HmIP-eTRV|HmIP-eTRV-2" => {
|
||||
"HmIP-eTRV|HmIP-eTRV-2|HmIP-eTRV-B1" => {
|
||||
_description => "Heizkoerperthermostat HM-IP",
|
||||
ccureadingfilter => "^ACTUAL_TEMPERATURE|^BOOST_MODE|^SET_POINT_MODE|^SET_POINT_TEMPERATURE|^LEVEL|^WINDOW_STATE",
|
||||
ccureadingname => "1.LEVEL:valve_position",
|
||||
@ -782,6 +782,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
},
|
||||
"HmIP-WTH|HmIP-WTH-2|HmIP-BWTH" => {
|
||||
_description => "Wandthermostat HM-IP",
|
||||
ccureadingfilter => ".*",
|
||||
controldatapoint => "1.SET_POINT_TEMPERATURE",
|
||||
eventMap => "/datapoint 1.BOOST_MODE true:Boost/datapoint 1.CONTROL_MODE 0:Auto/datapoint 1.CONTROL_MODE 1:Manual/datapoint 1.CONTROL_MODE 2:Holiday/datapoint 1.SET_POINT_TEMPERATURE 4.5:off/datapoint 1.SET_POINT_TEMPERATURE 30.5:on/",
|
||||
genericDeviceType => "thermostat",
|
||||
@ -1002,7 +1003,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
syntax => "name, mode",
|
||||
parameters => 2,
|
||||
code => qq(
|
||||
object oPR = dom.GetObject("\$name");
|
||||
object oPR = (dom.GetObject(ID_PROGRAMS)).Get("\$name");
|
||||
if (oPR) {
|
||||
oPR.Active(\$mode);
|
||||
}
|
||||
@ -1026,7 +1027,7 @@ if (!oSV) {
|
||||
oSV.State("\$init");
|
||||
oSV.Internal(false);
|
||||
oSV.Visible(true);
|
||||
dom.RTUpdate(false);
|
||||
dom.RTUpdate(0);
|
||||
}
|
||||
else {
|
||||
oSV.State("\$init");
|
||||
@ -1053,7 +1054,7 @@ if (!oSV) {
|
||||
oSV.State("\$init");
|
||||
oSV.Internal(false);
|
||||
oSV.Visible(true);
|
||||
dom.RTUpdate(false);
|
||||
dom.RTUpdate(0);
|
||||
}
|
||||
else {
|
||||
oSV.State("\$init");
|
||||
@ -1078,7 +1079,7 @@ if (!oSV) {
|
||||
oSV.DPInfo("\$desc");
|
||||
oSV.ValueUnit("\$unit");
|
||||
oSV.State("\$init");
|
||||
dom.RTUpdate(false);
|
||||
dom.RTUpdate(0);
|
||||
}
|
||||
else {
|
||||
oSV.State("\$init");
|
||||
@ -1102,7 +1103,7 @@ if (!oSV){
|
||||
oSV.DPInfo("\$desc");
|
||||
oSV.ValueUnit("\$unit");
|
||||
oSV.State("\$init");
|
||||
dom.RTUpdate(false);
|
||||
dom.RTUpdate(0);
|
||||
}
|
||||
else {
|
||||
oSV.State("\$init");
|
||||
@ -1129,16 +1130,16 @@ if (oSV) {
|
||||
code => qq(
|
||||
object osysvar;
|
||||
string ssysvarid;
|
||||
foreach (ssysvarid, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()) {
|
||||
osysvar = dom.GetObject(ssysvarid);
|
||||
Write(osysvar.Name());
|
||||
if(osysvar.ValueSubType() == 6) {
|
||||
Write ("=" # osysvar.AlType());
|
||||
}
|
||||
else {
|
||||
Write ("=" # osysvar.Variable());
|
||||
}
|
||||
WriteLine ("=" # osysvar.Value());
|
||||
foreach (ssysvarid, (dom.GetObject(ID_SYSTEM_VARIABLES)).EnumUsedIDs()) {
|
||||
osysvar = dom.GetObject(ssysvarid);
|
||||
Write(osysvar.Name());
|
||||
if(osysvar.ValueSubType() == 6) {
|
||||
Write ("=" # osysvar.AlType());
|
||||
}
|
||||
else {
|
||||
Write ("=" # osysvar.Variable());
|
||||
}
|
||||
WriteLine ("=" # osysvar.Value());
|
||||
}
|
||||
)
|
||||
},
|
||||
@ -1148,7 +1149,7 @@ foreach (ssysvarid, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()) {
|
||||
parameters => 0,
|
||||
code => qq(
|
||||
string sSysVarId;
|
||||
foreach (sSysVarId, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()) {
|
||||
foreach (sSysVarId, (dom.GetObject(ID_SYSTEM_VARIABLES)).EnumUsedIDs()) {
|
||||
object oSysVar = dom.GetObject(sSysVarId);
|
||||
Write(oSysVar.Name());
|
||||
if (oSysVar.ValueSubType() == 6) {
|
||||
@ -1181,7 +1182,7 @@ foreach (sSysVarId, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()) {
|
||||
code => qq(
|
||||
string chnid;
|
||||
string sDPId;
|
||||
object odev = dom.GetObject ("\$devname");
|
||||
object odev = (dom.GetObject(ID_DEVICES)).Get("\$devname");
|
||||
if (odev) {
|
||||
foreach (chnid, odev.Channels()) {
|
||||
object ochn = dom.GetObject(chnid);
|
||||
@ -1210,13 +1211,15 @@ else {
|
||||
syntax => "name",
|
||||
parameters => 1,
|
||||
code => qq(
|
||||
object odev=dom.GetObject("\$name");
|
||||
if (odev) {
|
||||
if (odev.IsTypeOf (OT_CHANNEL)) {
|
||||
string devid = odev.Device();
|
||||
object odev = (dom.GetObject(ID_DEVICES)).Get("\$name");
|
||||
if (!odev) {
|
||||
object ochn = (dom.GetObject(ID_CHANNELS)).Get("\$name");
|
||||
if(ochn) {
|
||||
string devid = ochn.Device();
|
||||
odev = dom.GetObject (devid);
|
||||
}
|
||||
|
||||
}
|
||||
if(odev) {
|
||||
string intid=odev.Interface();
|
||||
string intna=dom.GetObject(intid).Name();
|
||||
string chnid;
|
||||
@ -1313,7 +1316,7 @@ string sDevName;
|
||||
string sDevList = "\$list";
|
||||
integer c = 0;
|
||||
foreach (sDevName, sDevList.Split(",")) {
|
||||
object odev = dom.GetObject (sDevName);
|
||||
object odev = (dom.GetObject(ID_DEVICES)).Get(sDevName);
|
||||
if (odev) {
|
||||
foreach (chnid, odev.Channels()) {
|
||||
object ochn = dom.GetObject(chnid);
|
||||
@ -1349,7 +1352,7 @@ string sDPId;
|
||||
string sDevice;
|
||||
string sDevList = "\$list";
|
||||
foreach (sDevice, sDevList.Split(",")) {
|
||||
object odev = dom.GetObject (sDevice);
|
||||
object odev = (dom.GetObject(ID_DEVICES)).Get(sDevice);
|
||||
if (odev) {
|
||||
string intid = odev.Interface();
|
||||
string intna = dom.GetObject(intid).Name();
|
||||
@ -1384,7 +1387,7 @@ string sDPId;
|
||||
string sChannel;
|
||||
string sChnList = "\$list";
|
||||
foreach (sChannel, sChnList.Split(",")) {
|
||||
object oChannel = dom.GetObject (sChannel);
|
||||
object oChannel = (dom.GetObject(ID_CHANNELS)).Get(sChannel);
|
||||
if (oChannel) {
|
||||
foreach(sDPId, oChannel.DPs()) {
|
||||
object oDP = dom.GetObject(sDPId);
|
||||
|
Loading…
x
Reference in New Issue
Block a user