diff --git a/fhem/FHEM/70_LaMetric2.pm b/fhem/FHEM/70_LaMetric2.pm index 11d459dd8..d5c0f724c 100644 --- a/fhem/FHEM/70_LaMetric2.pm +++ b/fhem/FHEM/70_LaMetric2.pm @@ -57,11 +57,8 @@ # 0x0025 -> "%" # 0x00B0 -> "°" #- notification attributes auf tatsächliche funktion prüfen -#- app interaction -#- radio setter einbinden #- sticky/cycle message prüfen -#- msgSchema -#-notificationIcons may be set to "none" and then send an empty icon +#- msgSchema (überlappende Parameter wie priority) #-mehrere metric/chart/goal/msg frames des gleichen typs (derzeit gehen per msg nur 1x zusätzlich metric,chart,goal) -> reihenfolge? package main; @@ -99,6 +96,7 @@ my %LaMetric2_sets = ( chart => '', goal => '', metric => '', + app => '', on => ':noArg', off => ':noArg', toggle => ':noArg', @@ -111,17 +109,21 @@ my %LaMetric2_sets = ( brightness => ':slider,1,1,100', brightnessMode => ':auto,manual', bluetooth => ':on,off', - channelUp => ':noArg', - channelDown => ':noArg', + inputUp => ':noArg', + inputDown => ':noArg', statusRequest => ':noArg', screensaver => ':off,when_dark,time_based', ); my %LaMetric2_setsHidden = ( - msgCancel => 1, - channel => 1, - app => 1, - refresh => 1, + msgCancel => 1, + input => 1, + refresh => 1, + channelUp => 1, + channelDown => 1, + play => 1, + pause => 1, + stop => 1, ); my %LaMetric2_metrictype_icons = ( @@ -301,7 +303,7 @@ sub LaMetric2_Define($$) { $hash->{HOST} = $host; $hash->{".API_KEY"} = $apikey; - $hash->{VERSION} = "2.0.1"; + $hash->{VERSION} = "2.1.0"; $hash->{INTERVAL} = $interval && looks_like_number($interval) ? $interval : 60; $hash->{PORT} = $port && looks_like_number($port) ? $port : 4343; @@ -311,12 +313,12 @@ sub LaMetric2_Define($$) { # presets for FHEMWEB $attr{$name}{cmdIcon} = - 'muteT:rc_MUTE channelUp:rc_RIGHT channelDown:rc_LEFT'; + 'play:rc_PLAY channelDown:rc_PREVIOUS channelUp:rc_NEXT stop:rc_STOP muteT:rc_MUTE inputUp:rc_RIGHT inputDown:rc_LEFT'; $attr{$name}{devStateIcon} = 'on:rc_GREEN@green:off off:rc_STOP:on absent:rc_RED playing:rc_PLAY@green:pause paused:rc_PAUSE@green:play muted:rc_MUTE@green:muteT fast-rewind:rc_REW@green:play fast-forward:rc_FF@green:play interrupted:rc_PAUSE@yellow:play'; $attr{$name}{icon} = 'time_statistic'; $attr{$name}{stateFormat} = 'stateAV'; - $attr{$name}{webCmd} = 'volume:muteT:channelDown:channel:channelUp'; + $attr{$name}{webCmd} = 'volume:muteT:channelDown:play:stop:channelUp:inputDown:input:inputUp'; # set those to make it easier for users to see the # default values. However, deleting those will @@ -386,18 +388,25 @@ sub LaMetric2_Set($@) { if ( defined( $hash->{helper}{cancelIDs} ) && keys %{ $hash->{helper}{cancelIDs} } > 0 ); - $usage .= " channel:,"; + $usage .= " input:,"; $usage .= join( ',', - map $hash->{helper}{channels}{$_}{name}, - sort keys %{ $hash->{helper}{channels} } ) - if ( defined( $hash->{helper}{channels} ) - && keys %{ $hash->{helper}{channels} } > 0 ); + map $hash->{helper}{inputs}{$_}{name}, + sort keys %{ $hash->{helper}{inputs} } ) + if ( defined( $hash->{helper}{inputs} ) + && keys %{ $hash->{helper}{inputs} } > 0 ); + + $usage .= + " play:noArg stop:noArg channelUp:noArg channelDown:noArg" + if ( defined( $hash->{helper}{apps}{'com.lametric.radio'} ) + && keys %{ $hash->{helper}{apps}{'com.lametric.radio'} } > 0 ); return $usage; } return "Unable to set $cmd: Device is unreachable" - if ( ReadingsVal( $name, 'presence', 'absent' ) eq 'absent' ); + if ( ReadingsVal( $name, 'presence', 'absent' ) eq 'absent' + && lc($cmd) ne 'refresh' + && lc($cmd) ne 'statusrequest' ); return "Unable to set $cmd: Device is disabled" if ( IsDisabled($name) ); @@ -419,11 +428,16 @@ sub LaMetric2_Set($@) { return LaMetric2_SetBrightness( $hash, @args ) if ( $cmd eq 'brightness' || lc($cmd) eq 'brightnessmode' ); return LaMetric2_SetBluetooth( $hash, @args ) if ( $cmd eq 'bluetooth' ); - return LaMetric2_SetApp( $hash, $cmd, @args ) + return LaMetric2_SetApp( $hash, $cmd, $h, @$a ) if ( $cmd eq 'app' - || $cmd eq 'channel' || lc($cmd) eq 'channelup' - || lc($cmd) eq 'channeldown' ); + || lc($cmd) eq 'channeldown' + || $cmd eq 'input' + || lc($cmd) eq 'inputup' + || lc($cmd) eq 'inputdown' + || $cmd eq 'play' + || $cmd eq 'pause' + || $cmd eq 'stop' ); return LaMetric2_CheckState( $hash, @args ) if ( $cmd eq 'refresh' || lc($cmd) eq 'statusrequest' ); @@ -697,43 +711,54 @@ sub LaMetric2_ReceiveCommand($$$) { # API version >= 2.1.0 elsif ( $service eq "device/apps" && $method eq "GET" ) { $hash->{helper}{apps} = $response; - delete $hash->{helper}{channels} - if ( defined( $hash->{helper}{channels} ) ); + delete $hash->{helper}{inputs} + if ( defined( $hash->{helper}{inputs} ) ); foreach my $app ( sort keys %{$response} ) { - foreach - my $widget ( sort keys %{ $response->{$app}{widgets} } ) - { - my $channelName; - if ( $response->{$app}{widgets}{$widget}{settings} + # widgets + foreach + my $widgetId ( sort keys %{ $response->{$app}{widgets} } ) + { + my $inputName; + + if ( $response->{$app}{widgets}{$widgetId}{settings} {_title} ) { - $channelName .= - $response->{$app}{widgets}{$widget}{settings} + $inputName .= + $response->{$app}{widgets}{$widgetId}{settings} {_title}; } else { - $channelName .= $response->{$app}{title}; + $inputName .= $response->{$app}{title}; } - $channelName =~ s/\s/_/g; + $inputName =~ s/\s/_/g; - my $i = 1; - my $channelName2 = lc($channelName); + my $i = 1; + my $inputName2 = lc($inputName); while ( - defined( $hash->{helper}{channels}{$channelName2} ) - ) + defined( $hash->{helper}{inputs}{$inputName2} ) ) { $i++; - $channelName2 = lc( $channelName . "_" . $i ); + $inputName2 = lc( $inputName . "_" . $i ); } - $channelName .= "_" . $i if ( $i > 1 ); + $inputName .= "_" . $i if ( $i > 1 ); - $hash->{helper}{channels}{ lc($channelName) } = ( + my $vendorId; + my $appId; + + if ( $response->{$app}{package} =~ /^(.+)\.([^.]+)$/ ) { + $vendorId = $1; + $appId = $2; + } + + $hash->{helper}{inputs}{ lc($inputName) } = ( { - 'name' => $channelName, - 'package' => $response->{$app}{package}, - 'widget' => $widget, + 'name' => $inputName, + 'package_id' => $response->{$app}{package}, + 'vendor_id' => $vendorId, + 'app_id' => $appId, + 'widget_id' => $widgetId, } ); } @@ -741,9 +766,6 @@ sub LaMetric2_ReceiveCommand($$$) { } elsif ( $service =~ /^device\/apps\/.+\/widgets\/.+\/actions/ ) { - } - elsif ( $service =~ /^device\/apps\/.+\/widgets\/.+\/activate/ ) { - } # Update readings @@ -1246,37 +1268,163 @@ sub LaMetric2_SetMute { sub LaMetric2_SetApp { my $hash = shift; my $cmd = shift; + my $h = shift; my $name = $hash->{NAME}; - my ( $subCommand, $appId ) = @_; + my ( $package, $action ) = @_; + + # inject action for Radio app + if ( lc($cmd) eq "channeldown" ) { + $cmd = "app"; + $package = "com.lametric.radio"; + $action = "radio.prev"; + } + elsif ( lc($cmd) eq "channelup" ) { + $cmd = "app"; + $package = "com.lametric.radio"; + $action = "radio.next"; + } + elsif ( lc($cmd) eq "play" ) { + $cmd = "app"; + $package = "com.lametric.radio"; + $action = "radio.play"; + } + elsif ( lc($cmd) eq "stop" || lc($cmd) eq "pause" ) { + $cmd = "app"; + $package = "com.lametric.radio"; + $action = "radio.stop"; + } Log3 $name, 5, "LaMetric2 $name: called function LaMetric2_SetApp() " . $cmd . " / " - . $subCommand; + . $packageId; - if ( lc($cmd) eq "channelup" || $subCommand eq "next" ) { + if ( lc($cmd) eq "inputup" ) { LaMetric2_SendCommand( $hash, "device/apps/next", "PUT", "" ); - - return; } - elsif ( lc($cmd) eq "channeldown" || $subCommand eq "prev" ) { + elsif ( lc($cmd) eq "inputdown" ) { LaMetric2_SendCommand( $hash, "device/apps/prev", "PUT", "" ); - return; } - elsif ( $subCommand - && defined( $hash->{helper}{channels}{ lc($subCommand) } ) ) + elsif ( ( $cmd eq "app" || $cmd eq "input" ) + && $package ) { - $package = $hash->{helper}{channels}{ lc($subCommand) }{package}; - $widget = $hash->{helper}{channels}{ lc($subCommand) }{widget}; - LaMetric2_SendCommand( $hash, - "device/apps/$package/widgets/$widget/activate", - "PUT", "" ); - return; + + my $packageId; + my $widgetId; + my $vendorId; + my $appId; + my $actionId; + + # user gave widget display name as package name + if ( defined( $hash->{helper}{inputs}{ lc($package) } ) ) { + $packageId = $hash->{helper}{inputs}{ lc($package) }{package_id}; + $widgetId = $hash->{helper}{inputs}{ lc($package) }{widget_id}; + $vendorId = $hash->{helper}{inputs}{ lc($package) }{vendor_id}; + $appId = $hash->{helper}{inputs}{ lc($package) }{app_id}; + } + else { + # user gave packageId as package name + if ( defined( $hash->{helper}{apps}{$package} ) ) { + $packageId = $package; + } + + # find packageId + else { + foreach my $id ( keys %{ $hash->{helper}{apps} } ) { + if ( $hash->{helper}{apps}{$id}{package} =~ /\.$package$/ ) + { + $packageId = $hash->{helper}{apps}{$id}{package}; + last; + } + } + } + + # if we now know the packageId, find widgetId + if ($packageId) { + my %widgetlist = (); + foreach my $id ( + keys %{ $hash->{helper}{apps}{$packageId}{widgets} } ) + { + $widgetlist{ $hash->{helper}{apps}{$packageId}{widgets} + {index} } = $id; + } + + # best guess for widgetId: + # use ID with lowest index + foreach my $id ( sort keys %widgetlist ) { + $widgetId = $widgetlist{$id}; + last; + } + } + + # user gave widgetId as package name + unless ($widgetId) { + foreach my $id ( keys %{ $hash->{helper}{inputs} } ) { + if ( $hash->{helper}{inputs}{$id}{widget_id} eq $id ) { + $packageId = + $hash->{helper}{inputs}{$id}{package_id}; + $widgetId = + $hash->{helper}{inputs}{$id}{widget_id}; + last; + } + } + } + } + + # only continue if widget exists + unless ( $packageId && $widgetId ) { + return "Unable to find widget for $package"; + } + + # user gave action parameter + if ($action) { + + # get vendor and app ID + if ( $packageId && ( !$vendorId || !$appId ) ) { + if ( $packageId =~ /^(.+)\.([^.]+)$/ ) { + $vendorId = $1; + $appId = $2; + } + } + + # find actionId + if ( + defined( $hash->{helper}{apps}{$packageId}{actions}{$action} ) ) + { + $actionId = $action; + } + elsif ( + defined( + $hash->{helper}{apps}{$packageId}{actions} + { $appId . "." . $action } + ) + ) + { + $actionId = $appId . "." . $action; + } + + return "Unknown action $action" unless ($actionId); + + my %body = ( id => $actionId ); + $body{params} = $h if ($h); + + LaMetric2_SendCommand( $hash, + "device/apps/$packageId/widgets/$widgetId/actions", + "POST", encode_json( \%body ) ); + } + + # user wants to switch to widget + else { + LaMetric2_SendCommand( $hash, + "device/apps/$packageId/widgets/$widgetId/activate", + "PUT", "" ); + } } else { # There was a problem with the arguments - return "Syntax: set $name $cmd [app_name]"; + return +"Syntax: set $name $cmd [ [param1=value param2=value ...] ]"; } } @@ -2100,6 +2248,68 @@ sub LaMetric2_IsDuringTimeframe($$;$) {

+
+
+
+
+
+
+
+
+
+