From 6606767d30ab8f61d318580f12029d1a518402a2 Mon Sep 17 00:00:00 2001 From: justme-1968 Date: Wed, 26 Jan 2022 21:51:14 +0000 Subject: [PATCH] 30_HUEBridge.pm: added v2effect and v2json command 31_HUEDevice.pm: added v2effect command git-svn-id: https://svn.fhem.de/fhem/trunk@25566 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/30_HUEBridge.pm | 67 ++++++++++++++++++++++++++++++++++++--- fhem/FHEM/31_HUEDevice.pm | 30 +++++++++++++++--- 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 451fce555..573a6d659 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 31_HUEDevice: added v2effect command - bugfix: 14_Hideki.pm: fix match regex - forum:#125679 - bugfix: 66_EseraOneWire: fix match list - change: 49_SSCAM: module ready for SVS 9.0.0 forum:#125646 diff --git a/fhem/FHEM/30_HUEBridge.pm b/fhem/FHEM/30_HUEBridge.pm index 821cb6f44..7e07880ed 100644 --- a/fhem/FHEM/30_HUEBridge.pm +++ b/fhem/FHEM/30_HUEBridge.pm @@ -1124,7 +1124,9 @@ HUEBridge_Set($@) readingsSingleUpdate($hash, 'state', 'inactive', 1 ); return undef; - } elsif($cmd eq 'v2effect' ) { + } elsif($cmd eq 'v2json' ) { + return "usage: $cmd " if( !@params ); + my $params = { url => "https://$hash->{host}/clip/v2/resource/light/$arg", method => 'PUT', @@ -1133,9 +1135,44 @@ HUEBridge_Set($@) type => $cmd, hash => $hash, callback => \&HUEBridge_dispatch, - #data => '{"on":{"on": true}}', - data => '{"effect":{"effect": "candle"}}', - #data => '{"effect":{"effect": "breathe"}}', + data => join( ' ', @params ), + }; + + my($err,$data) = HttpUtils_BlockingGet( $params ); + + if( !$data ) { + Log3 $name, 2, "$name: empty answer received for $cmd"; + return undef; + } elsif( $data =~ m'HTTP/1.1 200 OK' ) { + Log3 $name, 4, "$name: empty answer received for $cmd"; + return undef; + } elsif( $data !~ m/^[\[{].*[\]}]$/ ) { + #Log3 $name, 2, "$name: invalid json detected for $cmd: $data"; + #return undef; + } + + Log3 $name, 4, "$name: got: $data"; + + my $json = eval { JSON->new->utf8(0)->decode($data) }; + Log3 $name, 2, "$name: json error: $@ in $data" if( $@ ); + return undef if( !$json ); + + Log3 $name, 1, "$name: error: ". Dumper $json->{errors} if( scalar @{$json->{errors}} ); + return Dumper $json if( scalar @{$json->{errors}} ); + + return; + + } elsif($cmd eq 'v2effect' ) { + return "usage: $cmd " if( !@params ); + my $params = { + url => "https://$hash->{host}/clip/v2/resource/light/$arg", + method => 'PUT', + timeout => 5, + header => { 'HUE-Application-Key' => $attr{$name}{key}, }, + type => $cmd, + hash => $hash, + callback => \&HUEBridge_dispatch, + data => '{"effects": {"effect": "'. $params[0] .'"}, "on": {"on": true}}', }; my($err,$data) = HttpUtils_BlockingGet( $params ); @@ -1235,6 +1272,22 @@ HUEBridge_Set($@) } } +sub +HUEBridge_V2IdOfV1Id($$$) +{ + my ($hash, $type, $id) = @_; + my $name = $hash->{NAME}; + return "undef" if( !$hash->{has_v2_api} ); + + foreach my $entry ( values %{$hash->{helper}{resource}{by_id}} ) { + next if( $entry->{id_v1} ne $id ); + next if( $entry->{type} ne $type ); + + return $entry->{id}; + } + + return undef; +} sub HUEBridge_nameOfResource($$) { @@ -2490,6 +2543,10 @@ HUEBridge_dispatch($$$;$) $obj->{state}{ct} = $data->{color_temperature}{mirek}; } + if( defined($data->{effects}) ) { + $obj->{state}{v2effect} = $data->{effects}{status} if( $data->{effects}{status} ); + } + if( defined($data->{dynamics}) ) { $obj->{state}{dynamics_speed} = $data->{dynamics}{speed} if( $data->{dynamics}{speed_valid} ); $obj->{state}{dynamics_status} = $data->{dynamics}{status}; @@ -2526,7 +2583,7 @@ HUEBridge_dispatch($$$;$) } elsif( $event->{type} eq 'delete' ) { Log3 $name, 4, "$name: EventStream: got $event->{type} event"; - } else { + } else { #handle type error Log3 $name, 3, "$name: EventStream: unknown event type $event->{type}: $data"; } diff --git a/fhem/FHEM/31_HUEDevice.pm b/fhem/FHEM/31_HUEDevice.pm index 31b014b70..01a030189 100644 --- a/fhem/FHEM/31_HUEDevice.pm +++ b/fhem/FHEM/31_HUEDevice.pm @@ -274,10 +274,12 @@ HUEDevice_devStateIcon($) return ".*:$s:toggle" if( $subtype eq "dimmer" ); return ".*:$s:toggle" if( $subtype eq "switch" ); - return ".*:light_toggle@#".CommandGet("","$name RGB").":toggle" if( ReadingsVal($name, 'dynamics_status', 'none') eq 'dynamic_palette' - && $pct < 100 && AttrVal($name, "color-icons", 0) == 2 ); - return ".*:light_toggle:toggle" if( ReadingsVal($name, 'dynamics_status', 'none') eq 'dynamic_palette' - && AttrVal($name, "color-icons", 0) != 0 ); + my $effect = ReadingsVal($name, 'effect', 'none') ne 'none' + || ReadingsVal($name, 'v2effect', 'no_effect') ne 'no_effect' + || ReadingsVal($name, 'dynamics_status', 'none') ne 'none'; # eq 'dynamic_palette' ? + + return ".*:light_toggle@#".CommandGet("","$name RGB").":toggle" if( $effect && $pct < 100 && AttrVal($name, "color-icons", 0) == 2 ); + return ".*:light_toggle:toggle" if( $effect && AttrVal($name, "color-icons", 0) != 0 ); return ".*:$s@#".CommandGet("","$name RGB").":toggle" if( $pct < 100 && AttrVal($name, "color-icons", 0) == 2 ); return ".*:on@#".CommandGet("","$name rgb").":toggle" if( AttrVal($name, "color-icons", 0) != 0 ); @@ -458,6 +460,8 @@ HUEDevice_Define($$) { $hash->{helper}{xy} = ''; $hash->{helper}{alert} = ''; $hash->{helper}{effect} = ''; + $hash->{helper}{v2effect} = ''; + $hash->{helper}{dynamics_status} = ''; $hash->{helper}{pct} = -1; $hash->{helper}{rgb} = ""; @@ -793,7 +797,17 @@ HUEDevice_SetParam($$@) $value='' if( !$value ); HUEDevice_AddJson( $name, $obj, "$cmd$value ".join( ' ', @aa) ); + } elsif( $cmd eq 'v2effect' ) { + my $hash = $defs{$name}; + my $shash = $hash->{IODev}; + my $id = HUEBridge_V2IdOfV1Id( $shash, 'light', "/lights/$hash->{ID}" ); + + HUEBridge_Set( $shash, $shash->{NAME}, $cmd, $id, $value ); + + $obj->{'on'} = JSON::true; + } else { + return 0; } @@ -1144,6 +1158,12 @@ HUEDevice_Set($@) if( $hash->{helper}->{devtype} eq 'G' ) { $list .= " savescene deletescene"; } + + if( $hash->{IODev}{has_v2_api} ) { + my $id = HUEBridge_V2IdOfV1Id( $hash->{IODev}, 'light', "/lights/$hash->{ID}" ); + + $list .= eval { " v2effect:". join(',', @{$hash->{IODev}{helper}{resource}{by_id}{$id}{effects}{effect_values}} ) } if( $id ); + } } if( $hash->{IODev} && $hash->{IODev}{is_deCONZ} ) { @@ -1944,6 +1964,7 @@ HUEDevice_Parse($$) $lastseen = $result->{lastseen} if( defined($result->{lastseen}) ); + $readings{v2effect} = $state->{v2effect}; $readings{dynamics_speed} = $state->{dynamics_speed}; $readings{dynamics_status} = $state->{dynamics_status}; @@ -2006,6 +2027,7 @@ HUEDevice_Parse($$) } $readings{dynamics_status} = 'none' if( !$on && defined($hash->{helper}{dynamics_status}) && !defined($readings{dynamics_status}) ); + $readings{v2effect} = 'none' if( !$on && defined($hash->{helper}{v2effect}) && !defined($readings{v2effect}) ); if( $pct != $hash->{helper}{pct} ) {readingsBulkUpdate($hash,"pct", $pct);} #if( $pct != $hash->{helper}{pct} ) {readingsBulkUpdate($hash,"level", $pct . ' %');}