From b57d96e7c30bdfd9c201726d3dc3b455aa9fb090 Mon Sep 17 00:00:00 2001 From: fhemzap <> Date: Thu, 26 Nov 2015 18:23:30 +0000 Subject: [PATCH] HMCCUCHN: Client Device Channel Module git-svn-id: https://svn.fhem.de/fhem/trunk@10011 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/HMCCU/88_HMCCUCHN.pm | 414 ++++++++++++++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 fhem/contrib/HMCCU/88_HMCCUCHN.pm diff --git a/fhem/contrib/HMCCU/88_HMCCUCHN.pm b/fhem/contrib/HMCCU/88_HMCCUCHN.pm new file mode 100644 index 000000000..81e52f0c9 --- /dev/null +++ b/fhem/contrib/HMCCU/88_HMCCUCHN.pm @@ -0,0 +1,414 @@ +################################################################ +# +# 88_HMCCUCHN.pm +# +# $Id:$ +# +# Version 2.0 +# +# (c) 2015 zap (zap01 t-online de) +# +################################################################ +# +# define HMCCUCHN [readonly] +# +# set datapoint [...] +# set devstate [...] +# set +# +# get devstate +# get datapoint +# get channel +# +# attr ccureadings { 0 | 1 } +# attr statevals :[,...] +# attr substitute :[,...] +# +################################################################ +# Requires module 88_HMCCU +################################################################ + +package main; + +use strict; +use warnings; +use SetExtensions; + +sub HMCCUCHN_Define ($@); +sub HMCCUCHN_Set ($@); +sub HMCCUCHN_Get ($@); +sub HMCCUCHN_Attr ($@); +sub HMCCUCHN_SetError ($$); + +##################################### +# Initialize module +##################################### + +sub HMCCUCHN_Initialize ($) +{ + my ($hash) = @_; + + $hash->{DefFn} = "HMCCUCHN_Define"; + $hash->{SetFn} = "HMCCUCHN_Set"; + $hash->{GetFn} = "HMCCUCHN_Get"; + $hash->{AttrFn} = "HMCCUCHN_Attr"; + + $hash->{AttrList} = "IODev ccureadingformat:name,address,datapoint ccureadings:0,1 statedatapoint statevals substitute loglevel:0,1,2,3,4,5,6 ". $readingFnAttributes; +} + +##################################### +# Define device +##################################### + +sub HMCCUCHN_Define ($@) +{ + my ($hash, $def) = @_; + my $name = $hash->{NAME}; + my @a = split("[ \t][ \t]*", $def); + + return "Specifiy the CCU device name or address as parameters" if (@a < 3); + + my $devname = shift @a; + my $devtype = shift @a; + my $devspec = shift @a; + + if ($devspec =~ /^(.+)\.([A-Z]{3,3}[0-9]{7,7}:[0-9]+)$/) { + # CCU Channel address with interface + $hash->{ccuif} = $1; + $hash->{ccuaddr} = $2; + $hash->{ccuname} = HMCCU_GetDeviceName ($hash->{ccuaddr}, ''); + return "CCU device name not found for channel address $devspec" if ($hash->{ccuname} eq ''); + } + elsif ($devspec =~ /^[A-Z]{3,3}[0-9]{7,7}:[0-9]+$/) { + # CCU Channel address + $hash->{ccuaddr} = $devspec; + $hash->{ccuif} = HMCCU_GetDeviceInterface ($hash->{ccuaddr}, 'BidCos-RF'); + $hash->{ccuname} = HMCCU_GetDeviceName ($devspec, ''); + return "CCU device name not found for channel address $devspec" if ($hash->{ccuname} eq ''); + } + else { + # CCU Device name + $hash->{ccuname} = $devspec; + my ($add, $chn) = HMCCU_GetAddress ($devspec, '', ''); + return "Channel address not found for channel name $devspec" if ($add eq '' || $chn eq ''); + $hash->{ccuaddr} = $add.':'.$chn; + $hash->{ccuif} = HMCCU_GetDeviceInterface ($hash->{ccuaddr}, 'BidCos-RF'); + } + + $hash->{ccutype} = HMCCU_GetDeviceType ($hash->{ccuaddr}, ''); + $hash->{statevals} = 'devstate'; + + my $arg = shift @a; + if (defined ($arg) && $arg eq 'readonly') { + $hash->{statevals} = $arg; + } + + # Inform HMCCU device about client device + AssignIoPort ($hash); + + readingsSingleUpdate ($hash, "state", "Initialized", 1); + + return undef; +} + +##################################### +# Set attribute +##################################### + +sub HMCCUCHN_Attr ($@) +{ + my ($cmd, $name, $attrname, $attrval) = @_; + my $hash = $defs{$name}; + + if ($cmd eq "set") { + return "Missing attribute value" if (!defined ($attrval)); + if ($attrname eq 'IODev') { + $hash->{IODev} = $defs{$attrval}; + } + elsif ($attrname eq 'statevals') { + return "Device is read only" if ($hash->{statevals} eq 'readonly'); + $hash->{statevals} = "devstate"; + my @states = split /,/,$attrval; + foreach my $st (@states) { + my @statesubs = split /:/,$st; + return "value := text:substext[,...]" if (@statesubs != 2); + $hash->{statevals} .= '|'.$statesubs[0]; + } + } + } + elsif ($cmd eq "del") { + if ($attrname eq 'statevals') { + $hash->{statevals} = "devstate"; + } + } + + return undef; +} + +##################################### +# Set commands +##################################### + +sub HMCCUCHN_Set ($@) +{ + my ($hash, @a) = @_; + my $name = shift @a; + my $opt = shift @a; + + if (!defined ($hash->{IODev})) { + return HMCCUCHN_SetError ($hash, "No IO device defined"); + } + if ($hash->{statevals} eq 'readonly') { + return undef; + } + + my $statevals = AttrVal ($name, "statevals", ''); + my $statedatapoint = AttrVal ($name, "statedatapoint", 'STATE'); + + my $result = ''; + my $rc; + + if ($opt eq 'datapoint') { + my $objname = shift @a; + my $objvalue = join ('%20', @a); + + if (!defined ($objname) || !defined ($objvalue)) { + return HMCCUCHN_SetError ($hash, "Usage: set datapoint [...]"); + } + $objvalue = HMCCU_Substitute ($objvalue, $statevals); + + # Build datapoint address + $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}.'.'.$objname; + + $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); + return HMCCUCHN_SetError ($hash, $rc) if ($rc < 0); + + usleep (100000); + ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname); + return HMCCUCHN_SetError ($hash, $rc) if ($rc < 0); + + return undef; + } + elsif ($opt =~ /^($hash->{statevals})$/) { + my $cmd = $1; + my $objvalue = ($cmd ne 'devstate') ? $cmd : join ('%20', @a); + + if (!defined ($objvalue)) { + return HMCCUCHN_SetError ($hash, "Usage: set devstate "); + } + $objvalue = HMCCU_Substitute ($objvalue, $statevals); + + # Build datapoint address + my $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}.'.'.$statedatapoint; + + $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); + return HMCCUCHN_SetError ($hash, $rc) if ($rc < 0); + + usleep (100000); + ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname); + return HMCCUCHN_SetError ($hash, $rc) if ($rc < 0); + + return undef; + } + else { + my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of datapoint devstate"; + return undef if ($hash->{statevals} eq 'readonly'); + + if ($hash->{statevals} ne '') { + my @cmdlist = split /\|/,$hash->{statevals}; + shift @cmdlist; + $retmsg .= ':'.join(',',@cmdlist); + foreach my $sv (@cmdlist) { + $retmsg .= ' '.$sv.':noArg'; + } + } + + return $retmsg; + } +} + +##################################### +# Get commands +##################################### + +sub HMCCUCHN_Get ($@) +{ + my ($hash, @a) = @_; + my $name = shift @a; + my $opt = shift @a; + + if (!defined ($hash->{IODev})) { + return HMCCUCHN_SetError ($hash, "No IO device defined"); + } + + my $statedatapoint = AttrVal ($name, "statedatapoint", 'STATE'); + my $ccureadings = AttrVal ($name, "ccureadings", 1); + + my $result = ''; + my $rc; + + if ($opt eq 'devstate') { + my $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}.'.'.$statedatapoint; + ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname); + return HMCCUCHN_SetError ($hash, $rc) if ($rc < 0); + return $ccureadings ? undef : $result; + } + elsif ($opt eq 'datapoint') { + my $objname = shift @a; + return HMCCUCHN_SetError ($hash, "Usage: get datapoint ") if (!defined ($objname)); + + $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}.'.'.$objname; + ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname); + return HMCCUCHN_SetError ($hash, $rc) if ($rc < 0); + return $ccureadings ? undef : $result; + } + elsif ($opt eq 'channel') { + my $dptexpr = shift @a; + my $objname = $hash->{ccuif}.'.'.$hash->{ccuaddr}; + $objname .= '.'.$dptexpr if (defined ($dptexpr)); + my @chnlist = ($objname); + ($rc, $result) = HMCCU_GetChannel ($hash, \@chnlist); + return HMCCUCHN_SetError ($hash, $rc) if ($rc < 0); + return $ccureadings ? undef : $result; + } + else { + return "HMCCUCHN: Unknown argument $opt, choose one of devstate:noArg datapoint channel"; + } +} + +##################################### +# Set error status +##################################### + +sub HMCCUCHN_SetError ($$) +{ + my ($hash, $text) = @_; + my $name = $hash->{NAME}; + my $msg; + my %errlist = ( + -1 => 'Channel name or address invalid', + -2 => 'Execution of CCU script failed', + -3 => 'Cannot detect IO device' + ); + + if (exists ($errlist{$text})) { + $msg = $errlist{$text}; + } + else { + $msg = $text; + } + + $msg = "HMCCUCHN: ".$name." ". $msg; + readingsSingleUpdate ($hash, "state", "Error", 1); + Log 1, $msg; + return $msg; +} + +1; + +=pod +=begin html + + +

HMCCUCHN

+
+
    + The module implements client devices for HMCCU. A HMCCU device must exist + before a client device can be defined. +

    + + Define +
      +
      + define <name> HMCCUCHN {<channel-name>|<channel-address>} [readonly] +

      + If readonly parameter is specified no set command will be available. +

      + Examples:
      + define window_living HMCCUCHN WIN-LIV-1 readonly
      + define temp_control HMCCUCHN BidCos-RF.LEQ1234567:1 +
      +
    +
    + + + Set
    +
      +
      +
    • set <name> devstate <value> [...] +
      + Set state of a CCU device channel. Channel datapoint must be defined + by setting attribute 'statedatapoint'. +

      + Example:
      + set light_entrance devstate on +

    • +
    • set <name> <statevalue> +
      + State of a CCU device channel is set to StateValue. State datapoint + must be defined as attribute statedatapoint. State values can be replaced + by setting attribute statevals. +

      + Example:
      + + attr myswitch statedatapoint TEST
      + attr myswitch statevals on:true,off:false
      + set myswitch on +
      +

    • +
    • set <name> datapoint <datapoint> <value> [...] +
      + Set value of a datapoint of a CCU device channel. +

      + Example:
      + set temp_control datapoint SET_TEMPERATURE 21 +
    • +
    +
    + + + Get
    +
      +
      +
    • get <name> devstate +
      + Get state of CCU device. Default datapoint STATE can be changed by setting + attribute 'statedatapoint'. +

    • +
    • get <name> datapoint <datapoint> +
      + Get value of a CCU device datapoint. +
    • +
    +
    + + + Attributes
    +
    +
      +
    • ccureadings <0 | 1> +
      + If set to 1 values read from CCU will be stored as readings. +

    • +
    • statedatapoint <datapoint> +
      + Set datapoint for devstate commands. +

    • +
    • statevals <text>:<text>[,...] +
      + 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>:<subststr>[,...] +
      + Define substitions for reading values. +
    • +
    +
+
+ +=end html +=cut +