2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

fhem.pl: add map to json2nameValue (Forum #94629)

git-svn-id: https://svn.fhem.de/fhem/trunk@18003 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2018-12-19 10:45:16 +00:00
parent 34e744ea76
commit 82f5fa2123
2 changed files with 69 additions and 24 deletions

View File

@ -28,6 +28,7 @@ MQTT2_DEVICE_Initialize($)
disable:0,1 disable:0,1
disabledForIntervals disabledForIntervals
getList:textField-long getList:textField-long
jsonMap:textField-long
model model
readingList:textField-long readingList:textField-long
setList:textField-long setList:textField-long
@ -112,7 +113,8 @@ MQTT2_DEVICE_Parse($$)
if($code =~ m/^{.*}$/s) { if($code =~ m/^{.*}$/s) {
$code = EvalSpecials($code, ("%TOPIC"=>$topic, "%EVENT"=>$value, $code = EvalSpecials($code, ("%TOPIC"=>$topic, "%EVENT"=>$value,
"%DEVICETOPIC"=>$hash->{DEVICETOPIC}, "%NAME"=>$hash->{NAME})); "%DEVICETOPIC"=>$hash->{DEVICETOPIC}, "%NAME"=>$hash->{NAME},
"%JSONMAP","\$defs{$dev}{JSONMAP}"));
my $ret = AnalyzePerlCommand(undef, $code); my $ret = AnalyzePerlCommand(undef, $code);
if($ret && ref $ret eq "HASH") { if($ret && ref $ret eq "HASH") {
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
@ -165,7 +167,7 @@ MQTT2_DEVICE_Parse($$)
if(keys %{$ret}) { if(keys %{$ret}) {
$topic =~ m,.*/([^/]+),; $topic =~ m,.*/([^/]+),;
my $prefix = ($1 && $1 !~m/^0x[0-9a-f]+$/i) ? "${1}_" : ""; # 91394 my $prefix = ($1 && $1 !~m/^0x[0-9a-f]+$/i) ? "${1}_" : ""; # 91394
$add = "{ json2nameValue(\$EVENT, '$prefix') }"; $add = "{ json2nameValue(\$EVENT, '$prefix', \$JSONMAP) }";
} }
} }
if(!$add) { if(!$add) {
@ -345,7 +347,8 @@ MQTT2_DEVICE_Attr($$)
if($par2 =~ m/^{.*}$/) { if($par2 =~ m/^{.*}$/) {
my $ret = perlSyntaxCheck($par2, my $ret = perlSyntaxCheck($par2,
("%TOPIC"=>1, "%EVENT"=>"0 1 2 3 4 5 6 7 8 9", ("%TOPIC"=>1, "%EVENT"=>"0 1 2 3 4 5 6 7 8 9",
"%NAME"=>$dev, "%DEVICETOPIC"=>$hash->{DEVICETOPIC})); "%NAME"=>$dev, "%DEVICETOPIC"=>$hash->{DEVICETOPIC},
"%JSONMAP"=>""));
return $ret if($ret); return $ret if($ret);
} else { } else {
return "unsupported character in readingname $par2" return "unsupported character in readingname $par2"
@ -385,6 +388,17 @@ MQTT2_DEVICE_Attr($$)
} }
} }
if($attrName eq "jsonMap") {
if($type eq "set") {
my @ret = split(/[: \r\n]/, $param);
return "jsonMap: Odd number of elements" if(int(@ret) % 2);
my %ret = @ret;
$hash->{JSONMAP} = \%ret;
} else {
delete $hash->{JSONMAP};
}
}
return undef; return undef;
} }
@ -577,6 +591,21 @@ zigbee2mqtt_devStateIcon255($)
</li><br> </li><br>
<a name="jsonMap"></a>
<li>jsonMap oldReading1:newReading1 oldReading2:newReading2...<br>
space or newline separated list of oldReading:newReading pairs.<br>
Used in the automatically generated readingList json2nameValue function
to map the generated reading name to a better one. E.g.
<ul><code>
attr m2d jsonMap SENSOR_AM2301_Humidity:Humidity<br>
attr m2d readingList tele/sonoff/SENSOR:.* { json2nameValue($EVENT, 'SENSOR_', $JSONMAP) }
</code></ul>
The special newReading value of 0 will prevent creating a reading for
oldReading.
<br>
</li><br>
<a name="readingList"></a> <a name="readingList"></a>
<li>readingList &lt;regexp&gt; [readingName|perl-Expression] ... <li>readingList &lt;regexp&gt; [readingName|perl-Expression] ...
<br> <br>
@ -596,9 +625,9 @@ zigbee2mqtt_devStateIcon255($)
Notes: Notes:
<ul> <ul>
<li>in the perl expression the variables $TOPIC, $NAME, $DEVICETOPIC <li>in the perl expression the variables $TOPIC, $NAME, $DEVICETOPIC
and $EVENT are available (the letter containing the whole message), $JSONMAP and $EVENT are available (the letter containing the whole
as well as $EVTPART0, $EVTPART1, ... each containing a single word of message), as well as $EVTPART0, $EVTPART1, ... each containing a
the message.</li> single word of the message.</li>
<li>the helper function json2nameValue($EVENT) can be used to parse a <li>the helper function json2nameValue($EVENT) can be used to parse a
json encoded value. Importing all values from a Sonoff device with a json encoded value. Importing all values from a Sonoff device with a
Tasmota firmware can be done with: Tasmota firmware can be done with:

View File

@ -132,7 +132,8 @@ sub getAllGets($;$);
sub getAllSets($;$); sub getAllSets($;$);
sub getPawList($); sub getPawList($);
sub getUniqueId(); sub getUniqueId();
sub json2nameValue($;$); sub json2nameValue($;$$);
sub json2reading($$;$$);
sub latin1ToUtf8($); sub latin1ToUtf8($);
sub myrename($$$); sub myrename($$$);
sub notifyRegexpChanged($$); sub notifyRegexpChanged($$);
@ -4918,13 +4919,15 @@ toJSON($)
} }
############################# #############################
# will return a hash of name:value pairs. # will return a hash of name:value pairs. in is a json_string, prefix will be
# Note: doesnt know arrays, just objects and simple types # prepended to each name, map is a hash for mapping the names
sub sub
json2nameValue($;$) json2nameValue($;$$)
{ {
my ($in,$prefix) = @_; my ($in, $prefix, $map) = @_;
$prefix = "" if(!defined($prefix)); $prefix = "" if(!defined($prefix));
$map = eval $map if($map && !ref($map)); # passing hash through AnalyzeCommand
$map = {} if(!$map);
my %ret; my %ret;
sub sub
@ -4974,22 +4977,34 @@ json2nameValue($;$)
return ($t, ""); # error return ($t, ""); # error
} }
sub eObj($$$$$);
sub sub
eObj($$$$$) setVal($$$$$)
{ {
my ($ret,$name,$val,$in,$prefix) = @_; my ($ret,$map,$prefix,$name,$val) = @_;
$name = "$prefix$name";
if(defined($map->{$name})) {
return if(!$map->{$name});
$name = $map->{$name};
}
$ret->{$name} = $val;
};
sub eObj($$$$$$);
sub
eObj($$$$$$)
{
my ($ret,$map,$name,$val,$in,$prefix) = @_;
if($val =~ m/^"/) { if($val =~ m/^"/) {
($val, $in) = lStr($val); ($val, $in) = lStr($val);
$val =~ s/\\u([0-9A-F]{4})/chr(hex($1))/gsie; # toJSON reverse $val =~ s/\\u([0-9A-F]{4})/chr(hex($1))/gsie; # toJSON reverse
$ret->{"$prefix$name"} = $val; setVal($ret, $map, $prefix, $name, $val);
} elsif($val =~ m/^{/) { # } } elsif($val =~ m/^{/) { # }
($val, $in) = lObj($val, '{', '}'); ($val, $in) = lObj($val, '{', '}');
my $r2 = json2nameValue($val); my $r2 = json2nameValue($val);
foreach my $k (keys %{$r2}) { foreach my $k (keys %{$r2}) {
$ret->{"$prefix${name}_$k"} = $r2->{$k}; setVal($ret, $map, $prefix, "${name}_$k", $r2->{$k});
} }
} elsif($val =~ m/^\[/) { } elsif($val =~ m/^\[/) {
@ -4997,21 +5012,22 @@ json2nameValue($;$)
my $idx = 1; my $idx = 1;
$val =~ s/^\s*//; $val =~ s/^\s*//;
while($val) { while($val) {
$val = eObj($ret, $name."_$idx", $val, $val, $prefix); $val = eObj($ret, $map, $name."_$idx", $val, $val, $prefix);
$val =~ s/^\s*,\s*//; $val =~ s/^\s*,\s*//;
$val =~ s/\s*$//; $val =~ s/\s*$//;
$idx++; $idx++;
} }
} elsif($val =~ m/^([0-9.-]+)(.*)$/s) { } elsif($val =~ m/^([0-9.-]+)(.*)$/s) {
$ret->{"$prefix$name"} = $1; setVal($ret, $map, $prefix, $name, $1);
$in = $2; $in = $2;
} elsif($val =~ m/^(true|false)(.*)$/s) { } elsif($val =~ m/^(true|false)(.*)$/s) {
$ret->{"$prefix$name"} = $1; setVal($ret, $map, $prefix, $name, $1);
$in = $2; $in = $2;
} elsif($val =~ m/^(null)(.*)$/s) { } elsif($val =~ m/^(null)(.*)$/s) {
$ret->{"$prefix$name"} = undef; setVal($ret, $map, $prefix, $name, undef);
$in = $2; $in = $2;
} else { } else {
@ -5026,7 +5042,7 @@ json2nameValue($;$)
while($in =~ m/^\s*"([^"]+)"\s*:\s*(.*)$/s) { while($in =~ m/^\s*"([^"]+)"\s*:\s*(.*)$/s) {
my ($name,$val) = ($1,$2); my ($name,$val) = ($1,$2);
$name =~ s/[^a-z0-9._\-\/]/_/gsi; $name =~ s/[^a-z0-9._\-\/]/_/gsi;
$in = eObj(\%ret, $name, $val, $in, $prefix); $in = eObj(\%ret, $map, $name, $val, $in, $prefix);
$in =~ s/^\s*,\s*//; $in =~ s/^\s*,\s*//;
} }
return \%ret; return \%ret;
@ -5034,15 +5050,15 @@ json2nameValue($;$)
# generate readings from the json string (parsed by json2reading) for $hash # generate readings from the json string (parsed by json2reading) for $hash
sub sub
json2reading($$) json2reading($$;$$)
{ {
my ($hash, $json) = @_; my ($hash, $json, $prefix, $map) = @_;
$hash = $defs{$hash} if(ref($hash) ne "HASH"); $hash = $defs{$hash} if(ref($hash) ne "HASH");
return "json2reading: first arg is not a FHEM device" return "json2reading: first arg is not a FHEM device"
if(!$hash || ref $hash ne "HASH" || !$hash->{TYPE}); if(!$hash || ref $hash ne "HASH" || !$hash->{TYPE});
my $ret = json2nameValue($json); my $ret = json2nameValue($json, $prefix, $map);
if($ret && ref $ret eq "HASH") { if($ret && ref $ret eq "HASH") {
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
foreach my $k (keys %{$ret}) { foreach my $k (keys %{$ret}) {