2
0
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:
zap 2019-01-04 15:48:08 +00:00
parent 78ef0f87f2
commit ba687a7d8e
6 changed files with 269 additions and 309 deletions

View File

@ -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

View File

@ -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 &lt;interval&gt;</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 &lt;value[,...]&gt;</b><br/>
Deprecated, use attribute 'rpcinterfaces' instead. Specify list of RPC ports on CCU.
Default is 2001. Valid RPC ports are:<br/><br/>

View File

@ -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 &lt;name&gt; down [&lt;value&gt;]</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 &lt;name&gt; &lt;statevalue&gt;</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 &lt;name&gt; up [&lt;value&gt;]</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/>

View File

@ -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 &lt;name&gt; down [&lt;value&gt;]</b><br/>
<a href="#HMCCUCHNset">see HMCCUCHN</a>
</li><br/>
<li><b>set &lt;name&gt; on-for-timer &lt;ontime&gt;</b><br/>
<a href="#HMCCUCHNset">see HMCCUCHN</a>
</li><br/>
@ -947,6 +921,9 @@ sub HMCCUDEV_Get ($@)
<li><b>set &lt;name&gt; toggle</b><br/>
<a href="#HMCCUCHNset">see HMCCUCHN</a>
</li><br/>
<li><b>set &lt;name&gt; up [&lt;value&gt;]</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/>

View File

@ -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 &lt;seconds&gt;</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 &lt;seconds&gt;</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 &lt;count&gt;</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 &lt;interval&gt;</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 &lt;events&gt;</b><br/>
Maximum number of events sent to FHEM per accept loop. Default is 70. If set to 0

View File

@ -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);