From ba687a7d8e98e174464da0f89e1485042fd9c4db Mon Sep 17 00:00:00 2001 From: zap <> Date: Fri, 4 Jan 2019 15:48:08 +0000 Subject: [PATCH] HMCCU: Fixed some bugs git-svn-id: https://svn.fhem.de/fhem/trunk@18134 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/88_HMCCU.pm | 137 +++++++++++++++++------------------ fhem/FHEM/88_HMCCUCHN.pm | 129 ++++++++++++++------------------- fhem/FHEM/88_HMCCUDEV.pm | 131 ++++++++++++++------------------- fhem/FHEM/88_HMCCURPCPROC.pm | 123 ++++++++++++++++--------------- fhem/FHEM/HMCCUConf.pm | 57 ++++++++------- 6 files changed, 269 insertions(+), 309 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 39826b8b0..9deae20dd 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: Bug fixes - change: 10_MYSENSORS_DEVICE: make OTA feature available, change battery name convention, support MySensors API 2.0 features like diff --git a/fhem/FHEM/88_HMCCU.pm b/fhem/FHEM/88_HMCCU.pm index 8d69dbf7c..320380af3 100755 --- a/fhem/FHEM/88_HMCCU.pm +++ b/fhem/FHEM/88_HMCCU.pm @@ -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 t-online de) +# (c) 2019 by zap (zap01 t-online de) # ############################################################################## # -# define HMCCU [ccunumber] [waitforccu=] -# -# set ackmessages -# set cleardefaults -# set defaults -# set delete [{ OT_VARDP | OT_DEVICE }] -# set execute -# set importdefaults -# set hmscript {|!|'['']'} [dump] [= [...]] -# set rpcregister [{all|}] -# set rpcserver {on|off|restart} -# set var [] [= [...]] -# -# get aggregation {|all} -# get configdesc {|} -# get defaults -# get deviceinfo -# get devicelist [dump] -# get devicelist create [t={chn|dev|all}] [s=] [p=] [f=] -# [defattr] [duplicates] [save] [= [...]]}] -# get dump {devtypes|datapoints} [] -# get dutycycle -# get exportdefaults {filename} [csv] [all] -# get firmware [{type-expr}|full] -# get parfile [] -# get rpcevents -# get rpcstate -# get update [ [{ State | Value }]] -# get updateccu [ [{ State | Value }]] -# get vars -# -# attr ccuaggregate -# attr ccudef-hmstatevals -# attr ccudef-readingfilter -# attr ccudef-readingname -# attr ccudef-substitute -# attr ccudefaults -# attr ccuflags { intrpc,extrpc,procrpc,dptnocheck,noagg,logEvents,noReadings,nonBlocking } -# attr ccuget { State | Value } -# attr ccuReqTimeout -# attr ccuGetVars [:] -# attr parfile -# attr rpcevtimeout -# attr rpcinterfaces { BidCos-Wired, BidCos-RF, HmIP-RF, VirtualDevices, Homegear, HVL } -# attr rpcinterval -# attr rpcport -# attr rpcqueue -# attr rpcserver { on | off } -# attr rpcserveraddr -# attr rpcserverport -# attr rpctimeout [,] -# attr stripchar -# attr stripnumber [|0|1|2}[;...] -# attr substitute -# -# filter_rule := channel-regexp!datapoint-regexp[;...] -# subst_rule := [[channel.]datapoint[,...]!]:[,...][;...] -############################################################################## # 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.
extrpc - Same as procrpc (see below)
logEvents - Write events from CCU into FHEM logfile
+ logPong - Write log message when receiving pong event if verbose level is at least 3.
noEvents - Ignore events / device updates sent by CCU. No readings will be updated!
nonBlocking - Use non blocking (asynchronous) CCU requests
noReadings - Do not create or update readings
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'
+ reconnect - Automatically reconnect to CCU when events timeout occurred. Flags intrpc, extrpc and procrpc cannot be combined.
  • ccuget {State | Value}
    @@ -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).

  • +
  • rpcPingCCU <interval>
    + Send RPC ping request to CCU every interval seconds. If interval 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. +

  • rpcport <value[,...]>
    Deprecated, use attribute 'rpcinterfaces' instead. Specify list of RPC ports on CCU. Default is 2001. Valid RPC ports are:

    diff --git a/fhem/FHEM/88_HMCCUCHN.pm b/fhem/FHEM/88_HMCCUCHN.pm index 09fd9cf05..70ad2572e 100644 --- a/fhem/FHEM/88_HMCCUCHN.pm +++ b/fhem/FHEM/88_HMCCUCHN.pm @@ -4,54 +4,12 @@ # # $Id$ # -# Version 4.3.004 +# Version 4.3.005 # # (c) 2018 zap (zap01 t-online de) # ###################################################################### -# -# define HMCCUCHN [readonly] [defaults] -# [iodev=] -# -# set config [device] = [...] -# set control -# set datapoint [...] -# set defaults -# set devstate -# set -# set on-till -# set on-for-timer -# set pct [{ | 0 } []] -# set toggle -# -# get config [device] [] -# get configdesc [device] -# get configlist [device] [] -# get datapoint -# get defaults -# get deviceinfo -# get devstate -# get update -# -# attr ccucalculate :[:][...] -# attr ccuflags { ackState, nochn0, trace } -# attr ccuget { State | Value } -# attr ccureadings { 0 | 1 } -# attr ccureadingfilter [;...] -# attr ccureadingformat { name[lc] | address[lc] | datapoint[lc] } -# attr ccureadingname :[;...] -# attr ccuSetOnChange -# attr ccuverify { 0 | 1 | 2 } -# attr controldatapoint -# attr disable { 0 | 1 } -# attr peer datapoints:condition:{hmccu:object=value|ccu:object=value|fhem:command} -# attr hmstatevals [;...] -# attr statedatapoint -# attr statevals :[,...] -# attr substexcl -# attr substitute [;...] -# -###################################################################### +# 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:
    set light_entrance devstate true

  • +
  • set <name> down [<value>]
    + Decrement value of datapoint LEVEL. This command is only available if channel contains + a datapoint LEVEL. Default for value is 10. +

  • set <name> <statevalue>
    Set state of a CCU device channel to StateValue. 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

  • +
  • set <name> up [<value>]
    + Increment value of datapoint LEVEL. This command is only available if channel contains + a datapoint LEVEL. Default for value is 10. +


  • diff --git a/fhem/FHEM/88_HMCCUDEV.pm b/fhem/FHEM/88_HMCCUDEV.pm index 7a3fbb660..49926897a 100644 --- a/fhem/FHEM/88_HMCCUDEV.pm +++ b/fhem/FHEM/88_HMCCUDEV.pm @@ -4,55 +4,12 @@ # # $Id$ # -# Version 4.3.005 +# Version 4.3.006 # # (c) 2018 zap (zap01 t-online de) # ###################################################################### -# -# define HMCCUDEV {|virtual} [] [readonly] [defaults] -# [{group={|}[,...]|groupexp=}] [iodev=] -# -# set clear [] -# set config [] = [...] -# set control -# set datapoint [.] [...] -# set defaults -# set devstate -# set on-till -# set on-for-timer -# set pct [{|0} []] -# set -# set toggle -# -# get config [] [] -# get configdesc [] -# get configlist [] -# get datapoint [.] -# get defaults -# get devstate -# get update -# -# attr ccucalculate :[:][...] -# attr ccuflags { ackState, nochn0, trace } -# attr ccuget { State | Value } -# attr ccureadings { 0 | 1 } -# attr ccureadingformat { address[lc] | name[lc] | datapoint[lc] } -# attr ccureadingfilter [,...] -# attr ccureadingname :[,...] -# attr ccuscaleval :[::][,...] -# attr ccuverify { 0 | 1 | 2} -# attr controldatapoint . -# attr disable { 0 | 1 } -# attr peer datapoints:condition:{hmccu:object=value|ccu:object=value|fhem:command} -# attr hmstatevals [;...] -# attr statechannel -# attr statedatapoint [.] -# attr statevals :[,...] -# attr substexcl -# attr substitute [;...] -# -###################################################################### +# 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 value contains string \_ it is substituted by blank.
    +
  • set <name> down [<value>]
    + see HMCCUCHN +

  • set <name> on-for-timer <ontime>
    see HMCCUCHN

  • @@ -947,6 +921,9 @@ sub HMCCUDEV_Get ($@)
  • set <name> toggle
    see HMCCUCHN

  • +
  • set <name> up [<value>]
    + see HMCCUCHN +

  • ePaper Display

    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:

    diff --git a/fhem/FHEM/88_HMCCURPCPROC.pm b/fhem/FHEM/88_HMCCURPCPROC.pm index 72e7be594..f81b29826 100755 --- a/fhem/FHEM/88_HMCCURPCPROC.pm +++ b/fhem/FHEM/88_HMCCURPCPROC.pm @@ -4,11 +4,11 @@ # # $Id$ # -# Version 1.3 +# Version 1.4 # # Subprocess based RPC Server module for HMCCU. # -# (c) 2018 by zap (zap01 t-online de) +# (c) 2019 by zap (zap01 t-online 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.
    expert - Activate expert mode
    logEvents - Events are written into FHEM logfile if verbose is 4
    - logPong - Write log message when receiving pong event if verbose level is at least 3.
    noEvents - Ignore events from CCU, do not update client device readings.
    queueEvents - Always write events into queue and send them asynchronously to FHEM. Frequency of event transmission to FHEM depends on attribute rpcConnTimeout.
    - reconnect - Try to re-register at CCU if no events received for rpcEventTimeout seconds

  • rpcAcceptTimeout <seconds>
    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.

  • rpcEventTimeout <seconds>
    - 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.

  • rpcMaxEvents <count>
    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.

  • rpcPingCCU <interval>
    - Send RPC ping request to CCU every interval seconds. If interval 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.

  • rpcQueueSend <events>
    Maximum number of events sent to FHEM per accept loop. Default is 70. If set to 0 diff --git a/fhem/FHEM/HMCCUConf.pm b/fhem/FHEM/HMCCUConf.pm index 5f70063da..ec6ae1fe6 100644 --- a/fhem/FHEM/HMCCUConf.pm +++ b/fhem/FHEM/HMCCUConf.pm @@ -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);