mirror of
https://github.com/fhem/fhem-mirror.git
synced 2024-11-22 09:49:50 +00:00
4d00e2c973
git-svn-id: https://svn.fhem.de/fhem/trunk@26359 2b470e98-0d58-463d-a4d8-8e2adae1ed80
648 lines
21 KiB
Perl
648 lines
21 KiB
Perl
##############################################################################
|
|
#
|
|
# 98_dev_proxy.pm
|
|
# Copyright by A. Schulz
|
|
# e-mail:
|
|
#
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
#
|
|
##############################################################################
|
|
# $Id: $
|
|
package main;
|
|
|
|
use strict;
|
|
use warnings;
|
|
#use List::Util qw[min max];
|
|
use Data::Dumper;
|
|
|
|
#####################################
|
|
sub dev_proxy_setDefaultObservedReadings($);
|
|
sub dev_proxy_setObservedReading($@);
|
|
sub dev_proxy_addDevice($$);
|
|
sub dev_proxy_updateReadings($$);
|
|
sub dev_proxy_computeCombReading($$);
|
|
sub dev_proxy_mapDeviceReadingValueDefultMap($$$$$);
|
|
sub dev_proxy_mapDeviceReadingValue($$$$$);
|
|
sub dev_proxy_mapValue($$$);
|
|
sub dev_proxy_eval_map_readings($$);
|
|
sub dev_proxy_remap_reading($$$);
|
|
sub dev_proxy_cleanup_readings($);
|
|
#####################################
|
|
sub dev_proxy_Initialize($) {
|
|
my ($hash) = @_;
|
|
|
|
$hash->{DefFn} = "dev_proxy_Define";
|
|
$hash->{UndefFn} = "dev_proxy_Undef";
|
|
$hash->{NotifyFn} = "dev_proxy_Notify";
|
|
$hash->{SetFn} = "dev_proxy_Set";
|
|
$hash->{AttrFn} = "dev_proxy_Attr";
|
|
$hash->{AttrList} = "observedReadings setList:textField-long mapValues:textField-long mapReadings:textField-long ". "disable disabledForIntervals useSetExtensions ". $readingFnAttributes;
|
|
|
|
}
|
|
|
|
sub dev_proxy_Define($$) {
|
|
my ($hash, $def) = @_;
|
|
my @a = split("[ \t][ \t]*", $def);
|
|
|
|
my $u = "wrong syntax: define <name> dev_proxy [device ...]*";
|
|
return $u if(int(@a) < 3);
|
|
|
|
my $devname = shift(@a);
|
|
my $modname = shift(@a);
|
|
|
|
$hash->{CHANGEDCNT} = 0;
|
|
my $or = AttrVal($devname, "observedReadings", undef);
|
|
if(defined($or)) {
|
|
dev_proxy_setObservedReading($or);
|
|
} else {
|
|
dev_proxy_setDefaultObservedReadings($hash);
|
|
}
|
|
|
|
my %list;
|
|
$hash->{CONTENT} = \%list;
|
|
foreach my $a (@a) {
|
|
foreach my $d (devspec2array($a)) {
|
|
dev_proxy_addDevice($hash, $d);
|
|
}
|
|
}
|
|
|
|
my $valuesMap = AttrVal($devname,'mapValues',undef);
|
|
if (defined $valuesMap) {
|
|
$hash->{DEV_READING_VALUE_MAP} = eval($valuesMap);
|
|
} else {
|
|
$hash->{DEV_READING_VALUE_MAP} = undef;
|
|
}
|
|
dev_proxy_eval_map_readings($hash, AttrVal($devname,'mapReadings',undef));
|
|
dev_proxy_updateReadings($hash, undef);
|
|
|
|
return undef;
|
|
}
|
|
|
|
sub dev_proxy_setDefaultObservedReadings($) {
|
|
my ($hash) = @_;
|
|
#$hash->{OBSERVED_READINGS} = ["state","dim", "position"];
|
|
$hash->{OBSERVED_READINGS} = {};
|
|
$hash->{OBSERVED_READINGS} ->{"state"}=1;
|
|
$hash->{OBSERVED_READINGS} ->{"dim"}=1;
|
|
$hash->{OBSERVED_READINGS} ->{"position"}=1;
|
|
}
|
|
|
|
sub dev_proxy_setObservedReading($@) {
|
|
my ($hash, @list) = @_;
|
|
|
|
$hash->{OBSERVED_READINGS} = {};
|
|
foreach my $a (@list) {
|
|
$hash->{OBSERVED_READINGS} -> {$a} = 1;
|
|
}
|
|
}
|
|
|
|
sub dev_proxy_addDevice($$) {
|
|
my ($hash, $d) = @_;
|
|
if($defs{$d}) {
|
|
$hash->{CONTENT}{$d} = 1;
|
|
}
|
|
}
|
|
|
|
sub dev_proxy_Undef($$) {
|
|
my ($hash, $def) = @_;
|
|
return undef;
|
|
}
|
|
|
|
sub dev_proxy_Notify($$) {
|
|
my ($hash, $dev) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
if( $dev->{NAME} eq "global" ) {
|
|
my $max = int(@{$dev->{CHANGED}});
|
|
for (my $i = 0; $i < $max; $i++) {
|
|
my $s = $dev->{CHANGED}[$i];
|
|
$s = "" if(!defined($s));
|
|
if($s =~ m/^RENAMED ([^ ]*) ([^ ]*)$/) {
|
|
my ($old, $new) = ($1, $2);
|
|
if( exists($hash->{CONTENT}{$old}) ) {
|
|
|
|
$hash->{DEF} =~ s/(\s+)$old(\s*)/$1$new$2/;
|
|
|
|
delete( $hash->{CONTENT}{$old} );
|
|
$hash->{CONTENT}{$new} = 1;
|
|
}
|
|
} elsif($s =~ m/^DELETED ([^ ]*)$/) {
|
|
my ($name) = ($1);
|
|
|
|
if( exists($hash->{CONTENT}{$name}) ) {
|
|
|
|
$hash->{DEF} =~ s/(\s+)$name(\s*)/ /;
|
|
$hash->{DEF} =~ s/^ //;
|
|
$hash->{DEF} =~ s/ $//;
|
|
|
|
delete $hash->{CONTENT}{$name};
|
|
delete $hash->{".cachedHelp"};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return "" if(IsDisabled($name));
|
|
|
|
# pruefen ob Devices welches das notify ausgeloest hat Mitglied dieser Gruppe ist
|
|
return "" if (! exists $hash->{CONTENT}->{$dev->{NAME}});
|
|
|
|
dev_proxy_updateReadings($hash, $dev);
|
|
|
|
readingsSingleUpdate($hash, "LastDevice", $dev->{NAME}, 0);
|
|
|
|
return undef;
|
|
}
|
|
|
|
sub dev_proxy_updateReadings($$) {
|
|
my ($hash,$dev) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
if($hash->{INNTFY}) {
|
|
Log3 $name, 1, "ERROR: endless loop detected in composite_Notify $name";
|
|
return "";
|
|
}
|
|
$hash->{INNTFY} = 1;
|
|
|
|
# my $nrmap;
|
|
# foreach my $or (keys %{ $hash->{OBSERVED_READINGS}} ) {
|
|
# my $map;
|
|
# foreach my $d (keys %{ $hash->{CONTENT}} ) {
|
|
# next if(!$defs{$d});
|
|
# my $or_mapped = dev_proxy_remap_reading($hash, $d, $or);
|
|
# my $devReadings = ReadingsVal($d,$or_mapped,undef);
|
|
# if(defined($devReadings)) {
|
|
# ($devReadings) = dev_proxy_mapDeviceReadingValueDefultMap($hash,$d,$or,$devReadings,1);
|
|
# $map->{$d}=$devReadings;
|
|
# }
|
|
# }
|
|
# my $newReading = dev_proxy_computeCombReading($or, $map);
|
|
# if(defined($newReading)) {
|
|
# $nrmap->{$or}=$newReading;
|
|
# }
|
|
# }
|
|
|
|
my $map;
|
|
foreach my $or (keys %{ $hash->{OBSERVED_READINGS}} ) {
|
|
foreach my $d (keys %{ $hash->{CONTENT}} ) {
|
|
next if(!$defs{$d});
|
|
my $or_mapped = dev_proxy_remap_reading($hash, $d, $or);
|
|
my $devReadings = ReadingsVal($d,$or_mapped,undef);
|
|
if(defined($devReadings)) {
|
|
my $nReading;
|
|
($devReadings, $nReading) = dev_proxy_mapDeviceReadingValueDefultMap($hash,$d,$or,$devReadings,1);
|
|
# Nur wenn nicht ueberschrieben wurde
|
|
if(!defined($map->{$or}->{$d})) {
|
|
$map->{$or}->{$d}=$devReadings;
|
|
}
|
|
# falls umgemappt werden soll, den neuen Wert auch aufnehmen (ueberschreibt den eigentlichen Wert für das andere Reading)
|
|
if($or ne $nReading) {
|
|
$map->{$nReading}->{$d}=$devReadings;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# jetzt gesammelten Werte kombinieren / zusammenrechnen
|
|
my $nrmap;
|
|
foreach my $or (keys %{ $map } ) {
|
|
my $newReading = dev_proxy_computeCombReading($or, $map->{$or});
|
|
if(defined($newReading)) {
|
|
$nrmap->{$or}=$newReading;
|
|
}
|
|
}
|
|
|
|
readingsBeginUpdate($hash);
|
|
foreach my $d (sort keys %{ $nrmap }) {
|
|
my $newState = $nrmap->{$d};
|
|
my $dd = defined($dev)?" because device $dev->{NAME} has changed":"";
|
|
Log3 ($name, 5, "Update composite '$name' reading $d to $newState $dd");
|
|
readingsBulkUpdate($hash, $d, $newState);
|
|
}
|
|
readingsEndUpdate($hash, 1);
|
|
|
|
$hash->{CHANGEDCNT}++;
|
|
delete($hash->{INNTFY});
|
|
|
|
dev_proxy_cleanup_readings($hash);
|
|
}
|
|
|
|
sub dev_proxy_computeCombReading($$) {
|
|
my ($rName, $map) = @_;
|
|
my $size = keys %{$map};
|
|
if($size<1) {
|
|
return undef;
|
|
}
|
|
|
|
my @values = values %{$map};
|
|
|
|
if($rName eq 'state') {
|
|
my $tm;
|
|
foreach my $d (@values) {
|
|
$tm->{$d}=1;
|
|
}
|
|
return join(" ", keys %{ $tm });
|
|
}
|
|
|
|
my $maxV = List::Util::max(@values);
|
|
my $minV = List::Util::min(@values);
|
|
#if($maxV-$minV<10) {
|
|
return $minV+($maxV-$minV)/2;
|
|
#}
|
|
|
|
return $maxV;
|
|
|
|
return undef;
|
|
}
|
|
|
|
sub dev_proxy_mapDeviceReadingValueDefultMap($$$$$) {
|
|
my ($hash, $dev, $reading, $val, $incoming) = @_;
|
|
return dev_proxy_mapDeviceReadingValue($hash->{DEV_READING_VALUE_MAP}, $dev, $reading, $val,$incoming);
|
|
}
|
|
|
|
# Definition: map {'dev:reading'=>{'val'=>'valnew',.},..}
|
|
# Priority: zuerst richtungsspezifische (in/out):
|
|
# in:dev:reading, in:dev:*, in:*:reading, in:*:* (or in:*),
|
|
# dann Standard: dev:reading, dev:*, *:reading, *:* (or *)
|
|
# Nur bei out-Richtung (also set) relevant:
|
|
# Moeglichkeit, Zielreading umzudefinieren.
|
|
# Dafuer soll der Zielwert in Form WERT:NEWREADINGNAME geliefert werden:
|
|
# ...{'val'=>'valnew:newreading',..}...
|
|
sub dev_proxy_mapDeviceReadingValue($$$$$) {
|
|
my ($map, $dev, $reading, $val, $incoming) = @_;
|
|
|
|
return ($val, $reading) unless defined $map;
|
|
my $nval;
|
|
my $selectedMap;
|
|
# zuerst richtungsspeziefische Map (in/out) ausprobieren
|
|
my $prefix = $incoming ? 'in:' : 'out:';
|
|
$selectedMap = $map->{$prefix.$dev.':'.$reading};
|
|
$selectedMap = $map->{$prefix.$dev.':*'} unless defined $selectedMap;
|
|
$selectedMap = $map->{$prefix.'*:'.$reading} unless defined $selectedMap;
|
|
$selectedMap = $map->{$prefix.'*:*'} unless defined $selectedMap;
|
|
$selectedMap = $map->{$prefix.'*'} unless defined $selectedMap;
|
|
# falls keine passende Map vorhanden ist, oder sie keine passende Regel
|
|
# enthaelt, dann Standardmap verwenden
|
|
if(defined $selectedMap) {
|
|
$nval = dev_proxy_mapValue($selectedMap, $val, $incoming);
|
|
if(defined $nval) {
|
|
my ($nval, @areading) = split(/:/, $nval);
|
|
my $nreading = @areading ? join(':',@areading) : $reading;
|
|
return ($nval, $nreading);
|
|
}
|
|
}
|
|
|
|
$selectedMap = $map->{$dev.':'.$reading};
|
|
$selectedMap = $map->{$dev.':*'} unless defined $selectedMap;
|
|
$selectedMap = $map->{'*:'.$reading} unless defined $selectedMap;
|
|
$selectedMap = $map->{'*:*'} unless defined $selectedMap;
|
|
$selectedMap = $map->{'*'} unless defined $selectedMap;
|
|
# Originalwert, falls kein passendes Map
|
|
return ($val, $reading) unless defined $selectedMap;
|
|
|
|
$nval = dev_proxy_mapValue($selectedMap, $val, $incoming);
|
|
return ($nval, $reading) if defined $nval;
|
|
# Originalwert, falls keine Entsprechung im Map
|
|
return ($val, $reading);
|
|
}
|
|
|
|
sub dev_proxy_mapValue($$$) {
|
|
my ($map, $val, $incoming) = @_;
|
|
|
|
my $nv=$map->{$val};
|
|
if(!defined($nv)) {
|
|
$nv=$map->{'*'};
|
|
}
|
|
|
|
return undef unless(defined($nv)) ;
|
|
|
|
if($nv=~/^{/) {
|
|
$nv = eval($nv);
|
|
}
|
|
|
|
return $nv;
|
|
}
|
|
|
|
sub dev_proxy_Set($@){
|
|
my ($hash,$name,$command,@values) = @_;
|
|
|
|
return "no set value specified" if(!defined($command));
|
|
|
|
if ($command eq '?') {
|
|
my $setList = AttrVal($name, "setList", undef);
|
|
if(!defined $setList) {
|
|
$setList = "";
|
|
foreach my $n (sort keys %{ $hash->{READINGS} }) {
|
|
next if($n eq 'LastDevice' || $n eq 'state');
|
|
$setList.=$n;
|
|
if($n eq 'position' || $n eq 'dim' ) {
|
|
$setList.=":slider,0,1,100";
|
|
}
|
|
$setList.=" ";
|
|
}
|
|
}
|
|
$setList =~ s/\n/ /g;
|
|
if(AttrVal($name,"useSetExtensions",undef)) {
|
|
return SetExtensions($hash, $setList, $name, $command, @values);
|
|
} else {
|
|
return "Unknown argument $command, choose one of $setList";
|
|
}
|
|
}
|
|
|
|
if (AttrVal($name,"useSetExtensions",undef)) {
|
|
if ($command =~ m/^(blink|intervals|(off-|on-)(for-timer|till)|toggle)/) {
|
|
Log3($hash->{NAME},5,"calling SetExtensions(...) for $command");
|
|
my $setList = AttrVal($name, "setList", undef);
|
|
return SetExtensions($hash, $setList, $name, $command, @values);
|
|
}
|
|
}
|
|
|
|
if(int(@values)>0 && !defined($hash->{READINGS}->{$command})) {
|
|
if(AttrVal($name,"useSetExtensions",undef)) {
|
|
my $setList = AttrVal($name, "setList", undef);
|
|
return SetExtensions($hash, $setList, $name, $command, @values);
|
|
} else {
|
|
return "Unknown reading $command";
|
|
}
|
|
}
|
|
|
|
SetExtensionsCancel($hash);
|
|
|
|
my $ret;
|
|
my @devList = keys %{$hash->{CONTENT}};
|
|
foreach my $d (@devList) {
|
|
my $val;
|
|
if(int(@values)<1) {
|
|
# state
|
|
my $cmd = "state";
|
|
($val, $cmd) = dev_proxy_mapDeviceReadingValueDefultMap($hash, $d, "state", $command,0);
|
|
$cmd = dev_proxy_remap_reading($hash, $d, $cmd);
|
|
my $cmdstr;
|
|
if($cmd ne "state") {
|
|
$cmdstr = join(" ", ($d, $cmd, $val));
|
|
} else {
|
|
$cmdstr = join(" ", ($d, $val));
|
|
}
|
|
#Log3 $hash, 1, "SET: >>> ".$cmdstr;
|
|
$ret .= CommandSet(undef, $cmdstr);
|
|
} else {
|
|
# benannte readings
|
|
my $cmd = $command;
|
|
($val, $cmd) = dev_proxy_mapDeviceReadingValueDefultMap($hash, $d, $command, join(" ", @values),0);
|
|
$cmd = dev_proxy_remap_reading($hash, $d, $cmd);
|
|
my $cmdstr;
|
|
if($cmd ne "state") {
|
|
$cmdstr = join(" ", ($d, $cmd, $val));
|
|
} else {
|
|
$cmdstr = join(" ", ($d, $val));
|
|
}
|
|
#Log3 $hash, 1, "SET: >>> ".$cmdstr;
|
|
$ret .= CommandSet(undef, $cmdstr);
|
|
}
|
|
}
|
|
Log3 $hash, 5, "SET: $ret" if($ret);
|
|
|
|
|
|
return undef;
|
|
}
|
|
|
|
sub dev_proxy_Attr($@){
|
|
my ($type, $name, $attrName, $attrVal) = @_;
|
|
my %ignore = (
|
|
alias=>1,
|
|
devStateIcon=>1,
|
|
disable=>1,
|
|
disabledForIntervals=>1,
|
|
group=>1,
|
|
icon=>1,
|
|
room=>1,
|
|
stateFormat=>1,
|
|
webCmd=>1,
|
|
userattr=>1
|
|
);
|
|
|
|
return undef if($ignore{$attrName});
|
|
|
|
my $hash = $defs{$name};
|
|
|
|
if($attrName eq "observedReadings") {
|
|
if($type eq "del") {
|
|
dev_proxy_setDefaultObservedReadings($hash);
|
|
} else {
|
|
my @a=split("[ \t][ \t]*",$attrVal);
|
|
dev_proxy_setObservedReading($hash, @a);
|
|
}
|
|
} elsif($attrName eq "mapValues") {
|
|
if($type ne "del") {
|
|
$hash->{DEV_READING_VALUE_MAP} = eval($attrVal);
|
|
} else {
|
|
$hash->{DEV_READING_VALUE_MAP} = undef;
|
|
}
|
|
} elsif($attrName eq "mapReadings") {
|
|
if($type ne "del") {
|
|
dev_proxy_eval_map_readings($hash, $attrVal);
|
|
} else {
|
|
$hash->{READING_NAME_MAP} = undef;
|
|
}
|
|
}
|
|
|
|
dev_proxy_updateReadings($hash, undef);
|
|
|
|
Log3 $name, 4, "dev_proxy attr $type";
|
|
return undef;
|
|
}
|
|
|
|
sub dev_proxy_eval_map_readings($$) {
|
|
my ($hash, $attrVal) = @_;
|
|
$hash->{READING_NAME_MAP} = undef unless defined $attrVal;
|
|
my $map;
|
|
if(defined $attrVal) {
|
|
my @list = split("[ \t][ \t]*", $attrVal);
|
|
foreach (@list) {
|
|
my($devName, $devReading, $newReading) = split(/:/, $_);
|
|
$map->{$devName} -> {$newReading} = $devReading;
|
|
}
|
|
}
|
|
$hash->{READING_NAME_MAP} = $map;
|
|
}
|
|
|
|
# Readings remappen, die von hier in die Richtung anderen Devices gesendet werden
|
|
sub dev_proxy_remap_reading($$$) {
|
|
my ($hash, $devName, $readingName) = @_;
|
|
my $map = $hash->{READING_NAME_MAP};
|
|
return $readingName unless defined $map;
|
|
|
|
my $t = $map->{$devName};
|
|
$t = $map->{"*"} unless defined $t;
|
|
my $newReadingName = $t->{$readingName} if defined $t;
|
|
|
|
return $readingName unless defined $newReadingName;
|
|
return $newReadingName;
|
|
}
|
|
|
|
sub dev_proxy_cleanup_readings($) {
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
|
|
my $map = $hash->{OBSERVED_READINGS};
|
|
return unless defined $map;
|
|
|
|
foreach my $aName (keys %{$defs{$name}{READINGS}}) {
|
|
if(!defined $map->{$aName} && ($aName ne "LastDevice") && ($aName ne "state")) {
|
|
delete $defs{$name}{READINGS}{$aName};
|
|
}
|
|
}
|
|
}
|
|
|
|
1;
|
|
|
|
=pod
|
|
=item helper
|
|
=item summary organize devices and readings, remap / rename readings
|
|
=item summary_DE mehrere Geräte zu einem zusammenfassen, Readings umbenennen / umrechnen
|
|
=begin html
|
|
|
|
<a name="dev_proxy"></a>
|
|
<h3>dev_proxy</h3>
|
|
|
|
=end html
|
|
=begin html_DE
|
|
|
|
<a name="dev_proxy"></a>
|
|
<h3>dev_proxy</h3>
|
|
<ul>
|
|
<br>
|
|
<a name="dev_proxydefine"></a>
|
|
<b>Define</b>
|
|
<ul>
|
|
<code>define <name> dev_proxy <dev1> <dev2> ...</code> <br><br>
|
|
|
|
Mit diesem virtuellem Gerät können ausgewählte Readings eines anderen oder mehreren Geräte
|
|
an einer Stelle zusammengefasst werden. Diese können dabei ggf. umbenannt
|
|
und / oder umgerechnet werden.
|
|
<br>Beispiel:<br>
|
|
<code>defmod testdev_proxy dev_proxy MQ_DG_WZ_O_Rollo1 MQ_DG_WZ_O_Rollo2</code>
|
|
</ul>
|
|
|
|
<br>
|
|
<a name="dev_proxyset"></a>
|
|
<b>Set</b>
|
|
<ul>
|
|
Die hier angegebenen Werte werden an die Originalgeräte weitergeleitet.
|
|
Definierte Umbenennungen und Umrechnungen werden berücksichtigt.
|
|
</ul>
|
|
|
|
<br>
|
|
<a name="dev_proxyget"></a>
|
|
<b>Get</b>
|
|
<ul>
|
|
N/A
|
|
</ul>
|
|
|
|
<br>
|
|
<a name="dev_proxyattr"></a>
|
|
<b>Attributes</b>
|
|
<ul>
|
|
<li>
|
|
observedReadings: bestimmt zu überwachende Readings (durch Leerzeichen separierte liste)<br>
|
|
(wenn dieses Attrubut nicht angegeben wird, werden 'state', 'dim'und 'position' überwacht)
|
|
<br>Beispiel: <br>
|
|
<code>attr <name> observedReadings state level</code>
|
|
<br>
|
|
</li><br>
|
|
<li>
|
|
setList: Durch Leerzeichen getrennte Liste der Werte für Set-Befehl.<br>
|
|
Diese Liste wird bei "set name ?" ausgegeben.
|
|
Damit kann das FHEMWEB-Frontend Auswahl-Menüs oder Schalter erzeugen.
|
|
<br>Die gesetzten Werte werden an die entsprechende Readings der Geräte weitergereicht.
|
|
Dabei wird im mapReadings definierte Umsetzungsregel beachtet.
|
|
<br>Es wird jedoch nicht geprüfft, ob angegebene Reading in observed_reading vorhanden ist.
|
|
Ggf. wird einfach 'blind' weitergereicht.<br>
|
|
Beispiel: <br>
|
|
<code>attr <name> setList opens:noArg closes:noArg stop:noArg up:noArg down:noArg position:slider,0,1,100</code>
|
|
<br>
|
|
</li><br>
|
|
<li>
|
|
mapValues: Erlaubt Änderungen/Umrechnungen an den Werten der Readings
|
|
ggf. abhängig von den jeweiligen Device- und Readingsnamen.
|
|
Umrechnungstabellen können je nach Richtung ('in' aus Notify oder 'out' für set) getrennt definiert werden.
|
|
Falls die Definition mit dem Richtungsprefix nicht existiert oder kein Ergebnis liefert,
|
|
werden Standartdefinitionen (die parallel angegeben werden können) verwendet.
|
|
Für ausgehende Werte kann die Ziel-Reading auch umdefiniert werden, dieser wird im Zielwert nach dem ':' angegeben.
|
|
Die Angabe ist auch bei 'in:' möglich, dann wird dieser Wert den Wert der angegebenen Reading (bei dem selben Device) ersetzen.
|
|
Das kann nützlich sein, um spezielle Werte an andere Readings umzuleiten.
|
|
<br>
|
|
Die Werte müssen in als eine Hash-Map angegeben werden.
|
|
<STATE> soll als state angesprochen werden.<br>
|
|
Form: <code>{'<device>:<reading>'=>{'<value>'=>'new value',..},..}</code><br>
|
|
Oder mit Richtungsprefix: <code>{'out:<device>:<reading>'=>{'<value>'=>'new value[:new reading]',..},..}</code><br>
|
|
<device>, <reading> und <value> können auch mit * angegeben werden.
|
|
Diese Angabe wird als 'Default' verwendet, wenn keine andere gepasst haben.<br>
|
|
Prioritätenreihenfolge für die <device>:<reading>-Paaren: <device>:<reading>, <device>:*, *:<reading>, *:* (oder auch *).<br>
|
|
Für die Umrechnung steht das Originalvalue als $val-Variable zur Verfügung.
|
|
Falls Richtung (von Original-Gerät (bei Notify) oder zu dem Original-Gerät (bei set))
|
|
wichtig ist, kann diese durch Abfrage der Variable $incoming
|
|
(jeweils 1 oder 0) abgefragt werden.
|
|
<br>Beispiel: <br>
|
|
<code>attr <name> mapValues {'*:position'=>{'*'=>'{100-$val}','down'=>'100', 'closed'=>'100', 'up'=>'0', 'open'=>'0', 'open_ack'=>'0', 'off'=>'0', 'on'=>'100'}}</code>
|
|
<br>
|
|
</li><br>
|
|
<li>
|
|
mapReadings: Erlaubt Geräte-Readings unter anderem Namen verwenden.
|
|
* kann als Default anstatt Gerätenamen verwendet werden. <STATE> soll als state angesprochen werden.
|
|
<br>
|
|
<code>attr <name> mapReadings <device>:<original reading>:<hier zu verwendende reading> ...</code>
|
|
<br>
|
|
Beispiel: <br>
|
|
<code>attr <name> mapReadings Rollo1:pct:position Rollo2:pct:position</code>
|
|
</li><br>
|
|
<li>
|
|
useSetExtensions: bestimmt, ob <a href="#setExtensions">set extensions</a> unterstützt werden. Mögliche Werte: 0,1
|
|
<br>Beispiel: <br>
|
|
<p><code>attr <name> useSetExtensions <flags></code><br/>
|
|
</li>
|
|
</ul>
|
|
<br>
|
|
<b>Beispiele:</b>
|
|
<ul>
|
|
<li>
|
|
Zusammenfassung zweier Rollläden, Steuerung über die Reading 'position', Umkehrung der Prozentwerte.
|
|
<br>
|
|
<code>
|
|
defmod test1 dev_proxy Rollo1 Rollo2 <br>
|
|
attr test1 mapValues {'*:position'=>{'*'=>'{100-$val}','down'=>'100', 'closed'=>'100', 'up'=>'0', 'open'=>'0', 'open_ack'=>'0', 'off'=>'0', 'on'=>'100'}} <br>
|
|
attr test1 setList opens:noArg closes:noArg stop:noArg up:noArg down:noArg position:slider,0,1,100 <br>
|
|
attr test1 webCmd opens:closes:stop:position <br>
|
|
</code>
|
|
</li><br>
|
|
<li>
|
|
Abbildung für ein Rollladen, Umbenennung der Original-Reading 'position' in 'pos', Umkehrung der Prozentwerte.
|
|
<br>
|
|
<code>
|
|
defmod test2 dev_proxy Rollo1 <br>
|
|
attr test2 observed_readings pos state <br>
|
|
attr test2 mapValues {'*:pos'=>{'*'=>'{100-$val}','down'=>'100', 'closed'=>'100', 'up'=>'0', 'open'=>'0', 'open_ack'=>'0', 'off'=>'0', 'on'=>'100'}} <br>
|
|
attr test2 setList opens:noArg closes:noArg stop:noArg up:noArg down:noArg pos:slider,0,1,100 <br>
|
|
attr test2 mapReadings *:position:pos <br>
|
|
attr test2 webCmd up:down:stop:pos <br>
|
|
</code>
|
|
</li>
|
|
</ul>
|
|
|
|
</ul>
|
|
=end html_DE
|
|
=cut
|