diff --git a/fhem/contrib/HMCCU/88_HMCCUDEV.pm b/fhem/contrib/HMCCU/88_HMCCUDEV.pm index 16a47ff04..28098e655 100644 --- a/fhem/contrib/HMCCU/88_HMCCUDEV.pm +++ b/fhem/contrib/HMCCU/88_HMCCUDEV.pm @@ -4,7 +4,7 @@ # # $Id:$ # -# Version 1.1 +# Version 1.9 # # (c) 2015 zap (zap01 t-online de) # @@ -22,7 +22,7 @@ # # attr ccureadings { 0 | 1 } # attr statechannel -# attr stateval :[,...] +# attr statevals :[,...] # attr substitute :[,...] # ################################################################ @@ -54,7 +54,7 @@ sub HMCCUDEV_Initialize ($) $hash->{GetFn} = "HMCCUDEV_Get"; $hash->{AttrFn} = "HMCCUDEV_Attr"; - $hash->{AttrList} = "IODev ccureadings:0,1 stateval substitute statechannel:0,1,2,3 loglevel:0,1,2,3,4,5,6 ". $readingFnAttributes; + $hash->{AttrList} = "IODev ccureadingformat:name,address,datapoint ccureadings:0,1 statevals substitute statechannel loglevel:0,1,2,3,4,5,6 ". $readingFnAttributes; } ##################################### @@ -67,20 +67,45 @@ sub HMCCUDEV_Define ($$) my $name = $hash->{NAME}; my @a = split("[ \t][ \t]*", $def); - return "Specifiy the CCU device name as parameters" if(@a < 3); - return "Channel or datapoint not allowed in CCU device name" if ($a[2] =~ /^(.*):/); + return "Specifiy the CCU device name or address as parameters" if (@a < 3); - $attr{$name}{ccureadings} = 1; - - # Keep name of CCU device - $hash->{ccudev} = $a[2]; + my $devname = shift @a; + my $devtype = shift @a; + my $devspec = shift @a; - # Set commands / values - if (defined ($a[3]) && $a[3] eq 'readonly') { - $hash->{statevals} = $a[3]; + if ($devspec =~ /^[A-Z]{3,3}[0-9]{7,7}$/) { + # CCU Device address + $hash->{ccuaddr} = $devspec; + $hash->{ccuname} = HMCCU_GetDeviceName ($devspec, ''); + } + elsif ($devspec =~ /^(.*):/ || $devspec =~ /\..+$/) { + # Channel and/or datapoint specified + return "Channel or datapoint not allowed in CCU device name"; } else { - $hash->{statevals} = 'devstate'; + # CCU Device name + $hash->{ccuname} = $devspec; + $hash->{ccuaddr} = HMCCU_GetAddress ($devspec, '', 1); + } + + return "CCU device address not found" if ($hash->{ccuaddr} eq ''); + return "CCU device name not found" if ($hash->{ccuname} eq ''); + + $hash->{ccutype} = HMCCU_GetDeviceType ($hash->{ccuaddr}, ''); + $hash->{ccuif} = HMCCU_GetDeviceInterface ($hash->{ccuaddr}, ''); + $hash->{statevals} = 'devstate'; + $hash->{statechannel} = ''; + + my $arg = shift @a; + while (defined ($arg)) { + if ($arg eq 'readonly') { + $hash->{statevals} = $arg; + } + else { + return "State channel must be numeric" if ($arg !~ /^[0-9]+$/); + $hash->{statechannel} = $arg; + } + $arg = shift @a; } # Inform HMCCU device about client device @@ -103,7 +128,7 @@ sub HMCCUDEV_Attr ($@) if ($attrname eq "IODev") { $defs{$name}{IODev} = $defs{$attrval}; } - elsif ($attrname eq "stateval") { + elsif ($attrname eq "statevals") { $defs{$name}{statevals} = "devstate"; my @states = split /,/,$attrval; foreach my $st (@states) { @@ -112,6 +137,9 @@ sub HMCCUDEV_Attr ($@) $defs{$name}{statevals} .= '|'.$statesubs[0]; } } + elsif ($attrname eq "statechannel") { + $defs{$name}{statechannel} = $attrval; + } } return undef; @@ -134,51 +162,48 @@ sub HMCCUDEV_Set ($@) return undef; } - my $statechannel = AttrVal ($name, "statechannel", ''); - my $stateval = AttrVal ($name, "stateval", ''); + # my $statechannel = AttrVal ($name, "statechannel", ''); + my $statechannel = $hash->{statechannel}; + my $statevals = AttrVal ($name, "statevals", ''); my $substitute = AttrVal ($name, "substitute", ''); my $hmccu_hash = $hash->{IODev}; my $hmccu_name = $hash->{IODev}->{NAME}; - my $ccudev = $hash->{ccudev}; # process set command par1 ... if ($opt eq 'datapoint') { my $objname = shift @a; my $objvalue = join ('%20', @a); - if (!defined ($objname) || $objname !~ /^[0-9]+\..*$/ || !defined ($objvalue)) { - return HMCCUDEV_SetError ($hash, "Usage: set datapoint . "); + if (!defined ($objname) || $objname !~ /^[0-9]+\..+$/ || !defined ($objvalue)) { + return HMCCUDEV_SetError ($hash, "Usage: set datapoint . [...]"); } - - $objname = $ccudev.':'.$objname; - - my ($dev, $chn, $dpt, $flags) = HMCCU_ParseCCUDev ($objname); - if ($flags != 7) { - return HMCCUDEV_SetError ($hash, "Format for objname is channel.datapoint"); - } - $objvalue = HMCCU_Substitute ($objvalue, $substitute); + + # Build datapoint address + $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}.':'.$objname; + HMCCU_Set ($hmccu_hash, $hmccu_name, 'datapoint', $objname, $objvalue); usleep (100000); HMCCU_Get ($hmccu_hash, $hmccu_name, 'datapoint', $objname); return undef; } - elsif ($opt =~ /($hash->{statevals})/) { + elsif ($opt =~ /^($hash->{statevals})$/) { my $cmd = $1; my $objvalue = ($cmd ne 'devstate') ? $cmd : join ('%20', @a); if ($statechannel eq '') { - return undef; -# return HMCCUDEV_SetError ($hash, "No STATE channel specified"); + return HMCCUDEV_SetError ($hash, "No STATE channel specified"); } if (!defined ($objvalue)) { return HMCCUDEV_SetError ($hash, "Usage: set devstate "); } + $objvalue = HMCCU_Substitute ($objvalue, $statevals); + + # Build datapoint address + my $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}.':'.$statechannel.'.STATE'; - my $objname = $ccudev.':'.$statechannel.'.STATE'; - $objvalue = HMCCU_Substitute ($objvalue, $stateval); HMCCU_Set ($hmccu_hash, $hmccu_name, 'datapoint', $objname, $objvalue); usleep (100000); HMCCU_Get ($hmccu_hash, $hmccu_name, 'datapoint', $objname); @@ -189,7 +214,7 @@ sub HMCCUDEV_Set ($@) my $retmsg = "HMCCUDEV: Unknown argument $opt, choose one of datapoint devstate"; return undef if ($hash->{statevals} eq 'readonly'); - if ($stateval ne '') { + if ($statevals ne '') { my @cmdlist = split /\|/,$hash->{statevals}; shift @cmdlist; $retmsg .= ':'.join(',',@cmdlist); @@ -218,16 +243,18 @@ sub HMCCUDEV_Get ($@) my $hmccu_hash = $hash->{IODev}; my $hmccu_name = $hash->{IODev}->{NAME}; - my $ccudev = $hash->{ccudev}; if ($opt eq 'devstate') { - my $statechannel = AttrVal ($name, 'statechannel', ''); - if ($statechannel ne '') { - my $objname = $ccudev.':'.$statechannel; - - HMCCU_Get ($hmccu_hash, $hmccu_name, 'devstate', $objname); + # my $statechannel = AttrVal ($name, 'statechannel', ''); + my $statechannel = $hash->{statechannel}; + if ($statechannel eq '') { + return HMCCUDEV_SetError ($hash, "No STATE channel specified"); } + # Build datapoint address + my $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}.':'.$statechannel; + HMCCU_Get ($hmccu_hash, $hmccu_name, 'devstate', $objname); + return undef; } elsif ($opt eq 'datapoint') { @@ -236,11 +263,8 @@ sub HMCCUDEV_Get ($@) return HMCCUDEV_SetError ($hash, "Usage: get datapoint ."); } - $objname = $ccudev.':'.$objname; - my ($dev, $chn, $dpt, $flags) = HMCCU_ParseCCUDev ($objname); - if ($flags != 7) { - return HMCCUDEV_SetError ($hash, "Format for objname is channel.datapoint"); - } + # Build datapoint address + $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}.':'.$objname; HMCCU_Get ($hmccu_hash, $hmccu_name, 'datapoint', $objname); @@ -248,7 +272,7 @@ sub HMCCUDEV_Get ($@) } elsif ($opt eq 'update') { foreach my $r (keys %{$hash->{READINGS}}) { - if ($r =~ /^$ccudev:[0-9]\..+/) { + if ($r =~ /^.+:[0-9]+\..+/) { HMCCU_Get ($hmccu_hash, $hmccu_name, 'datapoint', $r); } } @@ -318,12 +342,12 @@ sub HMCCUDEV_SetError ($$)
State of a CCU device channel is set to StateValue. Channel must be defined as attribute statechannel. State values can be replaced - by setting attribute stateval. + by setting attribute statevals.

Example:
attr myswitch statechannel 1
- attr myswitch stateval on:true,off:false
+ attr myswitch statevals on:true,off:false
set myswitch on

@@ -364,15 +388,18 @@ sub HMCCUDEV_SetError ($$)
If set to 1 values read from CCU will be stored as readings.
-
  • statechannel <Channel> +
  • statechannel <channel-number>
    Channel for setting device state by devstate command.

  • -
  • stateval <text:text[,...]> +
  • statevals <text>:<text>[,...]
    - Define substitution for set commands values. + Define substitution for set commands values. The parameters <text> + are available as set commands. Example:
    + attr my_switch statevals on:true,off:false
    + set my_switch on

  • -
  • substitude <expression:string[,...]> +
  • substitude <expression>:<subststr>[,...]
    Define substitions for reading values. Substitutions for parfile values must be specified in parfiles.