############################################################################## # # 72_TA_CMI_JSON.pm # # This file is part of Fhem. # # Fhem is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # Fhem is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Fhem. If not, see . # ############################################################################## # # TA_CMI_JSON (c) Martin Gutenbrunner / https://github.com/delmar43/FHEM # # This module queries the CMI JSON API and allows to map values to readings. # Supported devices are UVR1611, UVR16x2, RSM610, CAN-I/O45, CAN-EZ2, CAN-MTx2, # and CAN-BC2 by Technische Alternative https://www.ta.co.at/ # # Information in the Wiki: https://wiki.fhem.de/wiki/TA_CMI_UVR16x2_UVR1611 # # Discussed in FHEM Forum: # * https://forum.fhem.de/index.php/topic,92740.0.html (official) # * https://forum.fhem.de/index.php/topic,41439.0.html (previous discussions) # * https://forum.fhem.de/index.php/topic,13534.45.html (previous discussions) # # $Id$ # ############################################################################## package main; use strict; use warnings; sub TA_CMI_JSON_Initialize { my ($hash) = @_; $hash->{SetFn} = "TA_CMI_JSON::Set"; $hash->{GetFn} = "TA_CMI_JSON::Get"; $hash->{DefFn} = "TA_CMI_JSON::Define"; $hash->{UndefFn} = "TA_CMI_JSON::Undef"; $hash->{NotifyFn} = "TA_CMI_JSON::Notify"; # $hash->{FW_detailFn} = "TA_CMI_JSON::DetailFn"; # $hash->{FW_directNotify} = "TA_CMI_JSON::DirectNotify"; $hash->{AttrList} = "username password outputStatesInterval interval readingNamesInputs:textField-long ". "readingNamesOutputs:textField-long readingNamesDL-Bus:textField-long ". "readingNamesLoggingAnalog:textField-long readingNamesLoggingDigital:textField-long ". "includePrettyReadings:0,1 includeUnitReadings:0,1 prettyOutputStates:0,1 setList:textField-long ". $readingFnAttributes; Log3 '', 3, "TA_CMI_JSON - Initialize done ..."; } package TA_CMI_JSON; use strict; use warnings; use HttpUtils; use GPUtils qw(:all); my %deviceNames = ( '80' => 'UVR1611', '87' => 'UVR16x2', '88' => 'RSM610', '89' => 'CAN-I/O45', '8B' => 'CAN-EZ2', '8C' => 'CAN-MTx2', '8D' => 'CAN-BC2', '8E' => 'UVR65', '8F' => 'CAN-EZ3', '91' => 'UVR610', '92' => 'UVR67', 'A3' => 'BL_NET' ); my %versions = ( 1 => '1.25.2 2016-12-12', 2 => '1.26.1 2017-02-24', 3 => '1.28.0 2017-11-09', 4 => '1.34.2 2019-04-04', 5 => '1.35.1 2019-07-02', 6 => '1.38.1 2021-02-04' ); my %units = ( 0 => '', 1 => '°C', 2 => 'W/m²', 3 => 'l/h', 4 => 'Sek', 5 => 'Min', 6 => 'l/Imp', 7 => 'K', 8 => '%', 10 => 'kW', 11 => 'kWh', 12 => 'MWh', 13 => 'V', 14 => 'mA', 15 => 'Std', 16 => 'Tage', 17 => 'Imp', 18 => 'kΩ', 19 => 'l', 20 => 'km/h', 21 => 'Hz', 22 => 'l/min', 23 => 'bar', 24 => '', 25 => 'km', 26 => 'm', 27 => 'mm', 28 => 'm³', 35 => 'l/d', 36 => 'm/s', 37 => 'm³/min', 38 => 'm³/h', 39 => 'm³/d', 40 => 'mm/min', 41 => 'mm/h', 42 => 'mm/d', 43 => 'Aus/Ein', 44 => 'Nein/Ja', 46 => '°C', 50 => '€', 51 => '$', 52 => 'g/m³', 53 => '', 54 => '°', 56 => '°', 57 => 'Sek', 58 => '', 59 => '%', 60 => 'Uhr', 63 => 'A', 65 => 'mbar', 66 => 'Pa', 67 => 'ppm' ); my %rasStates = ( 0 => 'Time/auto', 1 => 'Standard', 2 => 'Setback', 3 => 'Standby/frost pr.' ); my %outputStates = ( 0 => 'n/a', 1 => 'Auto-Off', 3 => 'Auto-On', 5 => 'Manual-Off', 7 => 'Manual-On' ); my %fixwertTypes = ( 'fixwertAnalog' => 'D1', 'fixwertDigital' => '11', 'fixwertImpuls' => '1f' ); ## Import der FHEM Funktionen BEGIN { GP_Import(qw( readingsSingleUpdate readingsBulkUpdate readingsBulkUpdateIfChanged readingsBeginUpdate readingsEndUpdate readingsDelete Log3 HttpUtils_Close HttpUtils_NonblockingGet RemoveInternalTimer InternalTimer makeReadingName AttrVal json2nameValue gettimeofday )) }; sub Define($$) { my ( $hash, $def ) = @_; my @a = split( "[ \t][ \t]*", $def ); my $name = $a[0]; my $module = $a[1]; my $cmiUrl = $a[2]; my $nodeId = $a[3]; my $queryParams = $a[4]; if(@a != 4 && @a != 5) { my $msg = "TA_CMI_JSON ($name) - Wrong syntax: define TA_CMI_JSON CMI-URL CAN-Node-ID "; Log3 $name, 0, $msg; return $msg; } $hash->{NAME} = $name; $hash->{CMIURL} = $cmiUrl; $hash->{NODEID} = $nodeId; $hash->{QUERYPARAM} = $queryParams; my $hexNodeId = sprintf('%1x',$nodeId); $hexNodeId = "0$hexNodeId" unless length($hexNodeId) == 2; $hash->{NODEID_HEX} = $hexNodeId; Log3 $name, 3, "TA_CMI_JSON ($name) - Define ... module=$module, CMI-URL=$cmiUrl, nodeId=$nodeId"; readingsSingleUpdate($hash, 'state', 'defined', 1); SetupIntervals($hash) if ($main::init_done); return undef; } sub Notify($$) { my ($own_hash, $dev_hash) = @_; my $ownName = $own_hash->{NAME}; # own name / hash return "" if(main::IsDisabled($ownName)); # Return without any further action if the module is disabled my $devName = $dev_hash->{NAME}; # Device that created the events my $events = main::deviceEvents($dev_hash, 1); if($devName eq "global" && grep(m/^INITIALIZED|REREADCFG$/, @{$events})) { SetupIntervals($own_hash); } } sub SetupIntervals($) { my ($hash) = @_; my $name = $hash->{NAME}; my $queryParams = $hash->{QUERYPARAM}; if ( defined $queryParams ) { $hash->{INTERVAL} = AttrVal( $name, "interval", "60" ); Log3 $name, 3, "TA_CMI_JSON ($name) - queryParam interval: ".$hash->{INTERVAL}; Log3 $name, 3, "TA_CMI_JSON ($name) - queryParams=$queryParams"; } #make initial call in any case, even if queryParams not defined. because that brings us model and number of outputs GetStatus( $hash ); my $outputStatesInterval = AttrVal( $name, 'outputStatesInterval', undef); if ( defined $outputStatesInterval ) { Log3 $name, 3, "TA_CMI_JSON ($name) - Define::outputStatesInterval: $outputStatesInterval"; RequestOutputStates ( $hash ); } } sub GetStatus($) { my ( $hash ) = @_; my $name = $hash->{NAME}; PerformHttpRequest($hash); } sub Undef($$) { my ($hash, $arg) = @_; my $name = $hash->{NAME}; HttpUtils_Close($hash); RemoveInternalTimer($hash); return undef; } sub PerformHttpRequest($) { my ($hash) = @_; my $name = $hash->{NAME}; my $queryParam = $hash->{QUERYPARAM}; $queryParam = '' unless defined $queryParam; my $url = "http://$hash->{CMIURL}/INCLUDE/api.cgi?jsonnode=$hash->{NODEID}&jsonparam=$queryParam"."&_=".gettimeofday(); my $username = AttrVal($name, 'username', 'admin'); my $password = AttrVal($name, 'password', 'admin'); my $param = { url => "$url", timeout => 5, hash => $hash, method => "GET", header => "User-Agent: FHEM\r\nAccept: application/json", user => $username, pwd => $password, callback => \&ParseHttpResponse }; Log3 $name, 4, "TA_CMI_JSON ($name) - PerformHttpRequest $url"; HttpUtils_NonblockingGet($param); } sub ParseHttpResponse($$$) { my ($param, $err, $data) = @_; my $hash = $param->{hash}; my $name = $hash->{NAME}; my $return; if($err ne "") { Log3 $name, 0, "TA_CMI_JSON ($name) - error while requesting ".$param->{url}." - $err"; readingsBeginUpdate($hash); readingsBulkUpdate($hash, 'state', 'ERROR', 1); readingsBulkUpdate($hash, 'error', $err, 1); readingsEndUpdate($hash, 1); } elsif($data ne "") { my $keyValues = json2nameValue($data); my $j2nvErr = $keyValues->{json2nameValueErrorText}; if (defined $j2nvErr) { Log3 $name, 1, "TA_CMI_JSON ($name) - JSON problem: $j2nvErr. Skipping. Can be ignored if not occurring too often."; readingsBeginUpdate($hash); readingsBulkUpdate($hash, 'state', 'ERROR', 0); readingsBulkUpdate($hash, 'error', $j2nvErr, 0); readingsEndUpdate($hash, 1); return undef; } my $canDevice = extractDeviceName($keyValues->{Header_Device}); $hash->{CAN_DEVICE} = $canDevice; $hash->{model} = $canDevice; $hash->{CMI_API_VERSION} = extractVersion($keyValues->{Header_Version}); readingsDelete($hash, "error"); readingsDelete($hash, "state"); readingsBeginUpdate($hash); readingsBulkUpdateIfChanged($hash, 'state', $keyValues->{Status}, 1); if ( $keyValues->{Status} eq 'OK' ) { my $queryParams = $hash->{QUERYPARAM}; $queryParams = '' unless defined $queryParams; extractReadings($hash, $keyValues, 'Inputs', 'Inputs') if ($queryParams =~ /I/); extractReadings($hash, $keyValues, 'Outputs', 'Outputs') if ($queryParams =~ /O/); if ($queryParams =~ /D/) { if ($canDevice eq 'UVR16x2' or $canDevice eq 'RSM610' ) { extractReadings($hash, $keyValues, 'DL-Bus', 'DL-Bus'); } else { Log3 $name, 1, "TA_CMI_JSON ($name) - Reading DL-Bus input is not supported on $canDevice"; } } if ($queryParams =~ /La/) { if ($canDevice eq 'UVR16x2') { extractReadings($hash, $keyValues, 'LoggingAnalog', 'Logging_Analog'); } else { Log3 $name, 1, "TA_CMI_JSON ($name) - Reading Logging Analog data is not supported on $canDevice"; } } if ($queryParams =~ /Ld/) { if ($canDevice eq 'UVR16x2') { extractReadings($hash, $keyValues, 'LoggingDigital', 'Logging_Digital'); } else { Log3 $name, 1, "TA_CMI_JSON ($name) - Reading Logging Digital data is not supported on $canDevice"; } } } readingsEndUpdate($hash, 1); # Log3 $name, 3, "TA_CMI_JSON ($name) - Device: $keyValues->{Header_Device}"; } if ( defined $hash->{QUERYPARAM} ) { my $functionName = "TA_CMI_JSON::GetStatus"; RemoveInternalTimer($hash, $functionName); InternalTimer( gettimeofday() + $hash->{INTERVAL}, $functionName, $hash, 0 ); } return undef; } sub extractDeviceName($) { my ($input) = @_; return (defined($deviceNames{$input}) ? $deviceNames{$input} : 'unknown: ' . $input); } sub extractVersion($) { my ($input) = @_; return (defined($versions{$input}) ? $versions{$input} : 'unknown: ' . $input); } sub extractReadings($$$$) { my ( $hash, $keyValues, $id, $dataKey ) = @_; my $name = $hash->{NAME}; my $readingNames = AttrVal($name, "readingNames$id", ''); Log3 $name, 5, 'readingNames'.$id.": $readingNames"; my @readingsArray = split(/ /, $readingNames); #1:T.Kollektor 5:T.Vorlauf my $inclUnitReadings = AttrVal( $name, "includeUnitReadings", 0 ); my $inclPrettyReadings = AttrVal( $name, "includePrettyReadings", 0 ); for my $i (0 .. (@readingsArray-1)) { my ( $idx, $readingName ) = split(/\:/, $readingsArray[$i]); $readingName = makeReadingName($readingName); my $jsonKey = 'Data_'.$dataKey.'_'.$idx.'_Value_Value'; my $readingValue = $keyValues->{$jsonKey}; Log3 $name, 5, "TA_CMI_JSON ($name) - readingName: $readingName, key: $jsonKey, value: $readingValue"; readingsBulkUpdateIfChanged($hash, $readingName, $readingValue, 1); $jsonKey = 'Data_'.$dataKey.'_'.$idx.'_Value_RAS'; my $readingRas = $keyValues->{$jsonKey}; if (defined($readingRas)) { readingsBulkUpdateIfChanged($hash, $readingName . '_RAS', $readingRas, 1); if ($inclPrettyReadings) { my $ras = (defined($rasStates{$readingRas}) ? $rasStates{$readingRas} : undef); readingsBulkUpdateIfChanged($hash, $readingName . '_RAS_Pretty', $ras, 1) if ($ras); } } my $unit; if ($inclUnitReadings || $inclPrettyReadings) { $jsonKey = 'Data_'.$dataKey.'_'.$idx.'_Value_Unit'; my $readingUnit = $keyValues->{$jsonKey}; $unit = (defined($units{$readingUnit}) ? $units{$readingUnit} : 'unknown: ' . $readingUnit); Log3 $name, 5, "TA_CMI_JSON ($name) - readingName: $readingName . '_Unit', key: $jsonKey, value: $readingUnit, unit: $unit"; readingsBulkUpdateIfChanged($hash, $readingName . '_Unit', $unit, 1) if ($inclUnitReadings); } if ($inclPrettyReadings) { readingsBulkUpdateIfChanged($hash, $readingName . '_Pretty', $readingValue . ' ' . $unit, 1); } } return undef; } sub Set { my ( $hash, $name, $opt, @arg) = @_; Log3 $name, 5, "TA_CMI_JSON ($name) - Set: $name $opt ".join(' ', @arg); my ($sets, $cmdList) = getCmdHash(AttrVal($name, 'setList', '')); if ($opt eq 'fixwertAnalog' || $opt eq 'fixwertDigital' || $opt eq 'fixwertImpuls') { my $index = $arg[0]; my $value = $arg[1]; my $type = $fixwertTypes{$opt}; FixwertChangeRequest($hash, $index, $value, $type); return undef; } else { my $command = $sets->{$opt}; if (defined $command) { # Log3 $name, 5, "TA_CMI_JSON ($name) - command: $command"; my ($cmd, $index, $value) = split(' ', $command); # Log3 $name, 5, "TA_CMI_JSON ($name) - cmd: $cmd"; # Log3 $name, 5, "TA_CMI_JSON ($name) - index: $index"; # Log3 $name, 5, "TA_CMI_JSON ($name) - value: $value"; # Log3 $name, 5, "TA_CMI_JSON ($name) - arg: ".join(' ', @arg); unshift @arg, $value if (defined $value); unshift @arg, $index if (defined $index); # Log3 $name, 5, "TA_CMI_JSON ($name) - arg2: ".join(' ', @arg); return Set($hash, $name, $cmd, @arg); } } return "Unknown argument $opt, choose one of fixwertAnalog fixwertDigital fixwertImpuls $cmdList"; } # credits for this method go to MQTT2_DEVICE sub getCmdHash($) { my ($list) = @_; my (%h, @cmd); map { my ($k,$v) = split(" ",$_,2); push @cmd, $k; $k =~ s/:.*//; # potential arguments $h{$k} = $v; } grep /./, split("\n", $list); return (\%h, join(" ",@cmd)); } sub FixwertChangeRequest($$$$) { my ($hash, $index, $value, $type) = @_; my $name = $hash->{NAME}; my $nodeId = $hash->{NODEID}; my $cmiIp = $hash->{CMIURL}; my $hexNodeId = $hash->{NODEID_HEX}; $index--; #1 on the Web UI is index 0. 2 is 1, etc. my $hexIndex = sprintf('%1x',$index); $hexIndex = "0$hexIndex" unless length($hexIndex) == 2; my $referrer = "Referer: http://$cmiIp/menupagex.cgi?nodex2=".$hexNodeId."005800"; my $url = "http://$cmiIp/INCLUDE/change.cgi?changeadrx2=".$hexNodeId."00".$hexIndex."4414".$type."01&changetox2=".$value."&_=".gettimeofday(); my $username = AttrVal($name, 'username', 'admin'); my $password = AttrVal($name, 'password', 'admin'); my $param = { url => "$url", timeout => 5, hash => $hash, method => "GET", header => $referrer, user => $username, pwd => $password, callback => \&FixwertChangeRequest_Callback }; Log3 $name, 4, "TA_CMI_JSON ($name) - FixwertChangeRequest $url"; HttpUtils_NonblockingGet($param); } sub FixwertChangeRequest_Callback { my ($param, $err, $data) = @_; my $hash = $param->{hash}; my $name = $hash->{NAME}; if($err ne "") { Log3 $name, 0, "TA_CMI_JSON ($name) - error while calling ".$param->{url}." - $err"; } elsif($data ne "") { Log3 $name, 5, "TA_CMI_JSON ($name) - FixwertChangeRequest_Callback: $data"; } return undef; } sub Get($$$$) { my ( $hash, $name, $opt, $args ) = @_; if ("update" eq $opt) { PerformHttpRequest($hash); return undef; } if ("readOutputStates" eq $opt) { RequestOutputStates($hash); #unless $hash->{CAN_DEVICE} ne 'UVR1611'; return undef; } # Log3 $name, 3, "ZoneMinder ($name) - Get done ..."; return "Unknown argument $opt, choose one of update readOutputStates"; } sub RequestOutputStates($) { my ($hash) = @_; my $name = $hash->{NAME}; my $nodeId = $hash->{NODEID}; my $hexNodeId = $hash->{NODEID_HEX}; my $url = "http://$hash->{CMIURL}/INCLUDE/agx2.cgi?nodex2=$hexNodeId"."&_=".gettimeofday(); my $username = AttrVal($name, 'username', 'admin'); my $password = AttrVal($name, 'password', 'admin'); my $param = { url => "$url", timeout => 5, hash => $hash, method => "GET", header => "User-Agent: FHEM\r\nAccept: application/json", user => $username, pwd => $password, callback => \&ParseOutputStateResponse }; Log3 $name, 4, "TA_CMI_JSON ($name) - RequestOutputStates $url"; HttpUtils_NonblockingGet($param); } sub ParseOutputStateResponse($$$) { my ($param, $err, $data) = @_; my $hash = $param->{hash}; my $name = $hash->{NAME}; my $return; if($err ne "") { Log3 $name, 0, "TA_CMI_JSON ($name) - error while requesting output data ".$param->{url}." - $err"; readingsBeginUpdate($hash); readingsBulkUpdate($hash, 'state', 'ERROR', 0); readingsBulkUpdate($hash, 'error', $err, 0); readingsEndUpdate($hash, 1); } elsif($data ne "") { readingsDelete($hash, "error"); readingsDelete($hash, "state"); my @values = split(';', $data); my $nrValues = @values -2; my $prettyOutputStates = AttrVal( $name, "prettyOutputStates", '0' ); my $readingNames = AttrVal($name, "readingNamesOutputs", undef); if ( ! defined $readingNames ) { Log3 $name, 1, "TA_CMI_JSON ($name) - Unable to assign output states, please set attribute readingNamesOutputs"; return undef; } my @readingsArray = split(/ /, $readingNames); #1:T.Kollektor 5:T.Vorlauf readingsBeginUpdate($hash); foreach (@readingsArray) { my ( $readingNameIndex, $readingName ) = split(/\:/, $_); my $i = $readingNameIndex+1; $readingName = makeReadingName($readingName); my $readingValue = $values[$i]; readingsBulkUpdateIfChanged($hash, $readingName.'_State', $readingValue, 1); if ($prettyOutputStates eq '1') { my $prettyValue = (defined($outputStates{$readingValue}) ? $outputStates{$readingValue} : '?:'.$readingValue); readingsBulkUpdateIfChanged($hash, $readingName.'_State_Pretty', $prettyValue, 1); } Log3 $name, 5, "TA_CMI_JSON ($name) - readingName: $readingName, readingNameIndex: $readingNameIndex, valueIndex: $i, value: $readingValue"; } readingsEndUpdate($hash, 1); Log3 $name, 5, "TA_CMI_JSON ($name) - Output Data $nrValues: $data"; } my $outputStatesInterval = AttrVal($name, 'outputStatesInterval', undef); if ( defined $outputStatesInterval ) { Log3 $name, 5, "TA_CMI_JSON ($name) - outputStatesInterval $outputStatesInterval"; my $functionName = "TA_CMI_JSON::RequestOutputStates"; RemoveInternalTimer($hash, $functionName); InternalTimer( gettimeofday() + $outputStatesInterval, $functionName, $hash, 0 ); } return undef; } # Eval-Rückgabewert für erfolgreiches # Laden des Moduls 1; # Beginn der Commandref =pod =item [device] =item summary Reads values from the Technische Alternative CMI device =item summary_DE Werte vom CMI der Firma Technische Alternative auslesen. =begin html

TA_CMI_JSON

Define
    define <name> TA_CMI_JSON <IP> <CAN-Node-Id> <Query-Params>

    Defines a device that receives values from the CMI at the given IP for the CAN-device with the given CAN-Node-Id.
    Query-Param defines, which values you want to read. Allowed values are I,O,D.
    Example:
      defmod cmi TA_CMI_JSON 192.168.4.250 1 <I,O,D>

    It's mandatory to define which values should be mapped to readings.
    Only mapped values will not be written to readings. (see Attributes for details)


Set
  • fixwertAnalog
    Set Fixwert to an analog value. Example:
      set cmiNode fixwertAnalog <index> <value>
      set cmiNode fixwertAnalog 3 64.0
      will set Fixwert 3 to 64.0
  • fixwertDigital
    Set Fixwert to a digital value. Also works for impulse values. Example:
      set cmiNode fixwertDigital <index> <value>
      set cmiNode fixwertDigital 2 1
      will set Fixwert 2 to On/Yes.
  • fixwertImpuls
    Trigger an impulse to Fixwert. Example:
      set cmiNode fixwertImpuls <index> <value>
      set cmiNode fixwertImpuls 3 1
      will send an On-impulse to Fixwert 3.
Get
  • update
    Triggers querying of values from the CMI. Please note that the request rate is limited to one query per minute.
  • readOutputStates
    Reads Output states (eg Manual-On, Auto-Off) per defined output. Can be automated by setting outputStatesInterval.


Attributes

  • readingNamesDL-Bus {index:reading-name}
    This maps received values from the DL-Bus to readings. eg 1:Flowrate_Solar 2:T.Solar_Backflow
  • readingNamesInputs {index:reading-name}
    This maps received values from the Inputs to readings. eg 1:Flowrate_Solar 2:T.Solar_Backflow
  • readingNamesOutputs {index:reading-name}
    This maps received values from the Outputs to readings. eg 1:Flowrate_Solar 2:T.Solar_Backflow
  • readingNamesLoggingAnalog {index:reading-name}
    This maps received values from Analog Logging to readings. zB eg 1:Flowrate_Solar 2:T.Solar_Backflow
  • readingNamesLoggingDigital {index:reading-name}
    This maps received values from Digital Logging to readings. zB eg 1:Flowrate_Solar 2:T.Solar_Backflow
  • includeUnitReadings [0:1]
    Adds another reading per value, which just contains the according unit of that reading.
  • includePrettyReadings [0:1]
    Adds another reading per value, which contains value plus unit of that reading.
  • interval
    Query interval in seconds. Minimum query interval is 60 seconds.
  • outputStatesInterval
    Request interval in seconds for getting output states.
  • prettyOutputStates [0:1]
    If set, generates a reading _State_Pretty for output states (eg Auto-On, Manual-Off)
  • setList
    Used to define Set shortcuts for fixwertAnalog, Digital, and Impuls. eg Light_on:noArg fixwertImpuls 3 1
    The second parameter (for the value) can be left out and directly read from the input field. eg Water_Temperature fixwertAnalog 7
    can be used like set cmiNode Water_Temperature 55.0.
  • username
    Username for querying the JSON-API. Needs to be either admin or user privilege.
  • password
    Password for querying the JSON-API.


Readings

Readings will appear according to the mappings defined in Attributes. =end html =begin html_DE

TA_CMI_JSON

Weitere Informationen zu diesem Modul im FHEM-Wiki. Define
    define <name> TA_CMI_JSON <IP> <CAN-Node-Id> <Query-Params>

    Liest Werte vom CMI mit der angegebenen IP für das CAN-Gerät mit der angegebenen Node-Id.
    Query-Param definiert, welche Werte ausgelesen werden sollen. Erlaubt sind I,O,D.
    Beispiel:
      defmod cmi TA_CMI_JSON 192.168.4.250 1 <I,O,D>

    Daneben muss auch noch das mapping angegeben werden, welche Werte in welches Reading geschrieben werden sollen.
    Nur gemappte Werte werden in Readings geschrieben. (siehe Attributes)


Set
  • fixwertAnalog
    Setzt einen Fixwert auf einen analogen Wert. Beispiel:
      set cmiNode fixwertAnalog <index> <value>
      set cmiNode fixwertAnalog 3 64.0
      setzt Fixwert 3 auf 64.0
  • fixwertDigital
    Setzt einen Fixwert auf einen digitalen Wert. Funktioniert auch für Impulse. Beispiel:
      set cmiNode fixwertDigital <index> <value>
      set cmiNode fixwertDigital 2 1
      setzt Fixwert 2 auf Ein/Ja
  • fixwertImpuls
    Sendet einen Impuls an den Fixwert. Beispiel:
      set cmiNode fixwertImpuls <index> <value>
      set cmiNode fixwertImpuls 3 1
      sendet einen Ein-Impuls nach Fixwert 3.
Get
  • update
    Hiermit kann sofort eine Abfrage der API ausgeführt werden. Das Limit von einer Anfrage pro Minute besteht trotzdem.
  • readOutputStates
    Liest Ausgangs-Stati, zB Auto-Ein, Hand-Aus. Kann mittels outputStatesInterval automatisch ausgeführt werden. Das Zeitlimit von 60 Sekunden trifft hier nicht zu.


Attributes

  • readingNamesDL-Bus {index:reading-name}
    Hiermit werden erhaltene Werte vom DL-Bus einem Reading zugewiesen. zB 1:Durchfluss_Solar 2:T.Solar_RL
  • readingNamesInput {index:reading-name}
    Hiermit werden erhaltene Werte der Eingänge einem Reading zugewiesen. zB 1:Durchfluss_Solar 2:T.Solar_RL
  • readingNamesDL-Bus {index:reading-name}
    Hiermit werden erhaltene Werte der Ausgänge einem Reading zugewiesen. zB 1:Durchfluss_Solar 2:T.Solar_RL
  • readingNamesLoggingAnalog {index:reading-name}
    Hiermit werden erhaltene Werte vom Analog Logging einem Reading zugewiesen. zB 1:Durchfluss_Solar 2:T.Solar_RL
  • readingNamesLoggingDigital {index:reading-name}
    Hiermit werden erhaltene Werte vom Digital Logging einem Reading zugewiesen. zB 1:Durchfluss_Solar 2:T.Solar_RL
  • includeUnitReadings [0:1]
    Definiert, ob zu jedem Reading ein zusätzliches Reading _Name geschrieben werden soll, welches die Einheit enthält.
  • includePrettyReadings [0:1]
    Definiert, ob zu jedem Reading zusätzlich ein Reading, welches Wert und Einheit enthält, geschrieben werden soll.
  • interval
    Abfrage-Intervall in Sekunden. Muss mindestens 60 sein.
  • outputStatesInterval
    Abfrage-Intervall für Ausgangs-Stati in Sekunden.
  • prettyOutputStates [0:1]
    Definiert, ob zu einem Ausgangs-Status ein zusätzliches Reading _State_Pretty geschrieben werden soll (liefert zB Auto-On, Manual-Off)
  • setList
    Dienst zum Anlegen direkter Set Befehle für fixwertAnalog, Digital, und Impuls. zB Licht_ein:noArg fixwertImpuls 3 1
    Wird der zweite Parameter (der Wert) weggelassen, kann dieser direkt aus dem Textfeld übernommen werden. zB Wasser_Temperatur fixwertAnalog 7
    könnte dann mit set cmiNode Wasser_Temperatur 55.0 verwendet werden.
  • username
    Username zur Abfrage der JSON-API. Muss die Berechtigungsstufe admin oder user haben.
  • password
    Passwort zur Abfrage der JSON-API.


Readings

Readings werden entsprechend der Definition in den Attributen angelegt. =end html_DE # Ende der Commandref =cut