2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-14 05:46:35 +00:00

10_RHASSPY: add Get key to SetScenes

git-svn-id: https://svn.fhem.de/fhem/trunk@25899 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Beta-User 2022-03-31 04:16:26 +00:00
parent 3cba270070
commit 6f65699a41
2 changed files with 128 additions and 58 deletions

View File

@ -106,6 +106,7 @@ my $languagevars = {
'DefaultChangeIntentRequestRawInput' => 'change command to $rawInput', 'DefaultChangeIntentRequestRawInput' => 'change command to $rawInput',
'RequestChoiceDevice' => 'there are several possible devices, choose between $first_items and $last_item', 'RequestChoiceDevice' => 'there are several possible devices, choose between $first_items and $last_item',
'RequestChoiceRoom' => 'more than one possible device, please choose one of the following rooms $first_items and $last_item', 'RequestChoiceRoom' => 'more than one possible device, please choose one of the following rooms $first_items and $last_item',
'RequestChoiceGeneric' => 'there are several options, choose between $options',
'DefaultChoiceNoOutstanding' => "no choice expected", 'DefaultChoiceNoOutstanding' => "no choice expected",
'NoMinConfidence' => 'minimum confidence not given, level is $confidence', 'NoMinConfidence' => 'minimum confidence not given, level is $confidence',
'timerSet' => { 'timerSet' => {
@ -243,7 +244,7 @@ BEGIN {
Log3 Log3
defs attr cmds modules L defs attr cmds modules L
DAYSECONDS HOURSECONDS MINUTESECONDS DAYSECONDS HOURSECONDS MINUTESECONDS
init_done init_done fhem_started
InternalTimer InternalTimer
RemoveInternalTimer RemoveInternalTimer
AssignIoPort AssignIoPort
@ -334,7 +335,7 @@ sub Define {
$hash->{defaultRoom} = $defaultRoom; $hash->{defaultRoom} = $defaultRoom;
my $language = $h->{language} // shift @{$anon} // lc AttrVal('global','language','en'); my $language = $h->{language} // shift @{$anon} // lc AttrVal('global','language','en');
$hash->{MODULE_VERSION} = '0.5.25'; $hash->{MODULE_VERSION} = '0.5.26a';
$hash->{baseUrl} = $Rhasspy; $hash->{baseUrl} = $Rhasspy;
initialize_Language($hash, $language) if !defined $hash->{LANGUAGE} || $hash->{LANGUAGE} ne $language; initialize_Language($hash, $language) if !defined $hash->{LANGUAGE} || $hash->{LANGUAGE} ne $language;
$hash->{LANGUAGE} = $language; $hash->{LANGUAGE} = $language;
@ -875,7 +876,7 @@ sub initialize_rhasspyTweaks {
sub configure_DialogManager { sub configure_DialogManager {
my $hash = shift // return; my $hash = shift // return;
my $siteId = shift // 'null'; #ReadingsVal( $hash->{NAME}, 'siteIds', 'default' ) // return; my $siteId = shift // 'null'; #ReadingsVal( $hash->{NAME}, 'siteIds', 'default' ) // return;
my $toDisable = shift // [qw(ConfirmAction CancelAction ChoiceRoom ChoiceDevice)]; my $toDisable = shift // [qw(ConfirmAction CancelAction Choice ChoiceRoom ChoiceDevice)];
my $enable = shift // q{false}; my $enable = shift // q{false};
my $timer = shift; my $timer = shift;
my $retArr = shift; my $retArr = shift;
@ -989,7 +990,7 @@ sub init_custom_intents {
sub initialize_devicemap { sub initialize_devicemap {
my $hash = shift // return; my $hash = shift // return;
Log3($hash->{NAME}, 5, "initialize_devicemap called");
my $devspec = $hash->{devspec}; my $devspec = $hash->{devspec};
delete $hash->{helper}{devicemap}; delete $hash->{helper}{devicemap};
@ -1002,6 +1003,7 @@ sub initialize_devicemap {
_analyze_genDevType($hash, $_) if $hash->{useGenericAttrs}; _analyze_genDevType($hash, $_) if $hash->{useGenericAttrs};
_analyze_rhassypAttr($hash, $_); _analyze_rhassypAttr($hash, $_);
} }
InternalTimer(time+125, \&initialize_devicemap, $hash ) if $fhem_started + 90 > time;
return; return;
} }
@ -1326,11 +1328,16 @@ sub _analyze_genDevType {
} }
if ( $gdt eq 'info' ) { if ( $gdt eq 'info' ) {
my $r = $defs{$device}{READINGS};
$currentMapping->{GetState}->{$gdt} = {currentVal => 'STATE', type => 'STATE' }; $currentMapping->{GetState}->{$gdt} = {currentVal => 'STATE', type => 'STATE' };
$currentMapping = _analyze_genDevType_setter( $hash, $device, $allset, $currentMapping ); $currentMapping = _analyze_genDevType_setter( $hash, $device, $allset, $currentMapping );
$hash->{helper}{devicemap}{devices}{$device}{intents} = $currentMapping; $hash->{helper}{devicemap}{devices}{$device}{intents} = $currentMapping;
} }
if ( $gdt eq 'scene' ) {
$currentMapping = _analyze_genDevType_setter( $hash, $device, $allset, $currentMapping );
$hash->{helper}{devicemap}{devices}{$device}{intents} = $currentMapping;
}
return; return;
} }
@ -1376,6 +1383,8 @@ sub _analyze_genDevType_setter {
cmdPlay => 'play', cmdPause => 'pause' ,cmdStop => 'stop', cmdBack => 'previous', cmdFwd => 'next', chanUp => 'channelUp', chanDown => 'channelDown' }, cmdPlay => 'play', cmdPause => 'pause' ,cmdStop => 'stop', cmdBack => 'previous', cmdFwd => 'next', chanUp => 'channelUp', chanDown => 'channelDown' },
GetState => { GetState => {
update => 'reread|update|reload' }, update => 'reread|update|reload' },
SetScene => {
cmdBack => 'previousScene', cmdFwd => 'nextScene' }
}; };
for my $okey ( keys %{$allValMappings} ) { for my $okey ( keys %{$allValMappings} ) {
my $ikey = $allValMappings->{$okey}; my $ikey = $allValMappings->{$okey};
@ -1420,7 +1429,6 @@ sub _analyze_genDevType_setter {
my $clscene = $scname; my $clscene = $scname;
# cleanup HUE scenes # cleanup HUE scenes
if ($clscene =~ m{[#]}xms) { if ($clscene =~ m{[#]}xms) {
#next if $clscene =~ m{[#]\[id}xms;
$clscene = (split m{[#]\[id}xms, $clscene)[0] if $clscene =~ m{[#]\[id}xms; $clscene = (split m{[#]\[id}xms, $clscene)[0] if $clscene =~ m{[#]\[id}xms;
$clscene =~ s{[#]}{ }gxm; $clscene =~ s{[#]}{ }gxm;
$scname =~ s{.*[#]\[(id=.+)]}{$1}xms if $scname =~ m{[#]\[id}xms; $scname =~ s{.*[#]\[(id=.+)]}{$1}xms if $scname =~ m{[#]\[id}xms;
@ -1914,7 +1922,7 @@ sub getAllRhasspyScenes {
push @names, split m{,}x, $hash->{helper}{devicemap}{devices}{$device}->{names}; push @names, split m{,}x, $hash->{helper}{devicemap}{devices}{$device}->{names};
my $scenes = $hash->{helper}{devicemap}{devices}{$device}{intents}{SetScene}->{SetScene}; my $scenes = $hash->{helper}{devicemap}{devices}{$device}{intents}{SetScene}->{SetScene};
for (keys %{$scenes}) { for (keys %{$scenes}) {
push @sentences, qq{( $scenes->{$_} ){Scene:$_}}; push @sentences, qq{( $scenes->{$_} ){Scene:$_}} if $_ ne 'cmdBack' && $_ ne 'cmdFwd' ;
} }
} }
@ -2773,10 +2781,13 @@ my $dispatchFns = {
GetTime => \&handleIntentGetTime, GetTime => \&handleIntentGetTime,
GetDate => \&handleIntentGetDate, GetDate => \&handleIntentGetDate,
SetTimer => \&handleIntentSetTimer, SetTimer => \&handleIntentSetTimer,
GetTimer => \&handleIntentGetTimer,
Timer => \&handleIntentSetTimer,
ConfirmAction => \&handleIntentConfirmAction, ConfirmAction => \&handleIntentConfirmAction,
CancelAction => \&handleIntentCancelAction, CancelAction => \&handleIntentCancelAction,
ChoiceRoom => \&handleIntentChoiceRoom, ChoiceRoom => \&handleIntentChoiceRoom,
ChoiceDevice => \&handleIntentChoiceDevice, ChoiceDevice => \&handleIntentChoiceDevice,
Choice => \&handleIntentChoice,
MsgDialog => \&handleIntentMsgDialog, MsgDialog => \&handleIntentMsgDialog,
ReSpeak => \&handleIntentReSpeak ReSpeak => \&handleIntentReSpeak
}; };
@ -3379,7 +3390,7 @@ sub respond {
} elsif ( $delay ) { } elsif ( $delay ) {
$sendData->{text} = $response; $sendData->{text} = $response;
$topic = 'continueSession'; $topic = 'continueSession';
my @ca_strings = configure_DialogManager($hash,$data->{siteId}, [qw(ConfirmAction ChoiceRoom ChoiceDevice)], 'false', undef, 1 ); my @ca_strings = configure_DialogManager($hash,$data->{siteId}, [qw(ConfirmAction Choice ChoiceRoom ChoiceDevice)], 'false', undef, 1 );
$sendData->{intentFilter} = [@ca_strings]; $sendData->{intentFilter} = [@ca_strings];
} else { } else {
$sendData->{text} = $response; $sendData->{text} = $response;
@ -3472,13 +3483,13 @@ sub sendSpeakCommand {
}; };
if (ref $cmd eq 'HASH') { if (ref $cmd eq 'HASH') {
return 'speak with explicite params needs siteId and text as arguments!' if !defined $cmd->{siteId} || !defined $cmd->{text}; return 'speak with explicite params needs siteId and text as arguments!' if !defined $cmd->{siteId} || !defined $cmd->{text};
$sendData->{siteId} = $cmd->{siteId}; $sendData->{siteId} = _getSiteIdbyRoom($hash, $cmd->{siteId});
$sendData->{init}->{text} = $cmd->{text}; $sendData->{init}->{text} = $cmd->{text};
} else { } else {
my($unnamedParams, $namedParams) = parseParams($cmd); my($unnamedParams, $namedParams) = parseParams($cmd);
if (defined $namedParams->{siteId} && defined $namedParams->{text}) { if (defined $namedParams->{siteId} && defined $namedParams->{text}) {
$sendData->{siteId} = $namedParams->{siteId}; $sendData->{siteId} = _getSiteIdbyRoom($hash, $namedParams->{siteId});
$sendData->{init}->{text} = $namedParams->{text}; $sendData->{init}->{text} = $namedParams->{text};
} else { } else {
return 'speak needs siteId and text as arguments!'; return 'speak needs siteId and text as arguments!';
@ -3488,12 +3499,25 @@ sub sendSpeakCommand {
return IOWrite($hash, 'publish', qq{hermes/dialogueManager/startSession $json}); return IOWrite($hash, 'publish', qq{hermes/dialogueManager/startSession $json});
} }
sub _getSiteIdbyRoom {
my $hash = shift // return;
my $siteId = shift // return;
my $siteIdList = ReadingsVal($hash->{NAME}, 'siteIds', $siteId);
my $siteId2 = ReadingsVal($hash->{NAME}, "room2siteId_$siteId", $siteId);
for my $id ($siteId2, $siteId) {
return $1 if $siteIdList =~ m{\b($id)(?:[,]|\Z)}xmsi;
return $1 if $siteIdList =~ m{\b($id[^,]+)(?:[,]|\Z)}xmsi;
}
return $siteId;
}
# start intent recognition by Rhasspy service, see https://rhasspy.readthedocs.io/en/latest/reference/#nlu_query # start intent recognition by Rhasspy service, see https://rhasspy.readthedocs.io/en/latest/reference/#nlu_query
sub msgDialog { sub msgDialog {
my $hash = shift; my $hash = shift;
my $cmd = shift; my $cmd = shift;
readingsSingleUpdate($hash,"enableMsgDialog", $cmd eq 'enable' ? 1 : 0 ,1); readingsSingleUpdate($hash,'enableMsgDialog', $cmd eq 'enable' ? 1 : 0 ,1);
return initialize_msgDialog($hash) if $cmd eq 'enable'; return initialize_msgDialog($hash) if $cmd eq 'enable';
return disable_msgDialog($hash); return disable_msgDialog($hash);
@ -4416,7 +4440,7 @@ sub handleIntentSetNumeric {
my $all = $device->[2]; my $all = $device->[2];
my $choice = $device->[3]; my $choice = $device->[3];
$data->{customData} = $all; $data->{customData} = $all;
my $toActivate = $choice eq 'RequestChoiceDevice' ? [qw(ChoiceDevice CancelAction)] : [qw(ChoiceRoom CancelAction)]; my $toActivate = $choice eq 'RequestChoiceDevice' ? [qw(ChoiceDevice Choice CancelAction)] : [qw(ChoiceRoom Choice CancelAction)];
$device = $first; $device = $first;
Log3($hash->{NAME}, 5, "More than one device possible, response is $response, first is $first, all are $all, type is $choice"); Log3($hash->{NAME}, 5, "More than one device possible, response is $response, first is $first, all are $all, type is $choice");
return setDialogTimeout($hash, $data, _getDialogueTimeout($hash), $response, $toActivate); return setDialogTimeout($hash, $data, _getDialogueTimeout($hash), $response, $toActivate);
@ -4575,7 +4599,7 @@ sub handleIntentGetNumeric {
my $all = $device->[2]; my $all = $device->[2];
my $choice = $device->[3]; my $choice = $device->[3];
$data->{customData} = $all; $data->{customData} = $all;
my $toActivate = $choice eq 'RequestChoiceDevice' ? [qw(ChoiceDevice CancelAction)] : [qw(ChoiceRoom CancelAction)]; my $toActivate = $choice eq 'RequestChoiceDevice' ? [qw(ChoiceDevice Choice CancelAction)] : [qw(ChoiceRoom Choice CancelAction)];
$device = $first; $device = $first;
Log3($hash->{NAME}, 5, "More than one device possible, response is $response, first is $first, all are $all, type is $choice"); Log3($hash->{NAME}, 5, "More than one device possible, response is $response, first is $first, all are $all, type is $choice");
return setDialogTimeout($hash, $data, _getDialogueTimeout($hash), $response, $toActivate); return setDialogTimeout($hash, $data, _getDialogueTimeout($hash), $response, $toActivate);
@ -4655,6 +4679,7 @@ sub handleIntentGetState {
my $room = getRoomName($hash, $data); my $room = getRoomName($hash, $data);
my $type = $data->{Type} // $data->{type}; my $type = $data->{Type} // $data->{type};
my @scenes; my $deviceNames; my $sceneNames;
if ($device eq 'RHASSPY') { if ($device eq 'RHASSPY') {
$type //= 'generic'; $type //= 'generic';
return respond( $hash, $data, getResponse($hash, 'NoValidData')) if $type !~ m{\Ageneric|control|info|scenes|rooms\z}; return respond( $hash, $data, getResponse($hash, 'NoValidData')) if $type !~ m{\Ageneric|control|info|scenes|rooms\z};
@ -4663,11 +4688,12 @@ sub handleIntentGetState {
if ( $type eq 'rooms' ) { if ( $type eq 'rooms' ) {
my @rooms = getAllRhasspyMainRooms($hash); my @rooms = getAllRhasspyMainRooms($hash);
$roomNames = _array2andString( $hash, \@rooms); $roomNames = _array2andString( $hash, \@rooms);
$response =~ s{(\$\w+)}{$1}eegx;
return respond( $hash, $data, $response);
} }
my @names; my @scenes; my @names;
my @intents = qw(SetNumeric SetOnOff GetNumeric GetOnOff MediaControls GetState SetScene); my @intents = qw(SetNumeric SetOnOff GetNumeric GetOnOff MediaControls GetState SetScene);
@intents = [] if $type eq 'rooms';
@intents = qw(GetState GetNumeric) if $type eq 'info'; @intents = qw(GetState GetNumeric) if $type eq 'info';
@intents = qw(SetScene) if $type eq 'scenes'; @intents = qw(SetScene) if $type eq 'scenes';
@ -4690,8 +4716,9 @@ sub handleIntentGetState {
@names = uniq(@names); @names = uniq(@names);
@scenes = uniq(@scenes) if @scenes; @scenes = uniq(@scenes) if @scenes;
my $deviceNames = _array2andString( $hash, \@names ); $deviceNames = _array2andString( $hash, \@names );
my $sceneNames = !@scenes ? '' : _array2andString( $hash, \@scenes ); $sceneNames = !@scenes ? '' : _array2andString( $hash, \@scenes );
$response =~ s{(\$\w+)}{$1}eegx; $response =~ s{(\$\w+)}{$1}eegx;
return respond( $hash, $data, $response); return respond( $hash, $data, $response);
} }
@ -4699,7 +4726,18 @@ sub handleIntentGetState {
my $deviceName = $device; my $deviceName = $device;
my $intent = 'GetState'; my $intent = 'GetState';
$device = getDeviceByName($hash, $room, $device); $device = getDeviceByName($hash, $room, $device) // return respond( $hash, $data, getResponse($hash, 'NoDeviceFound') );
if ( $type eq 'scenes' ) {
$response = getResponse( $hash, 'getRHASSPYOptions', $type );
@scenes = values %{$hash->{helper}{devicemap}{devices}{$device}{intents}{SetScene}->{SetScene}};
@scenes = uniq(@scenes) if @scenes;
$sceneNames = !@scenes ? '' : _array2andString( $hash, \@scenes );
$deviceNames = $deviceName;
$response =~ s{(\$\w+)}{$1}eegx;
return respond( $hash, $data, $response);
}
$type //= 'GetState'; $type //= 'GetState';
my $mapping = getMapping($hash, $device, 'GetState', $type) // return respond( $hash, $data, getResponse($hash, 'NoMappingFound') ); my $mapping = getMapping($hash, $device, 'GetState', $type) // return respond( $hash, $data, getResponse($hash, 'NoMappingFound') );
@ -4712,7 +4750,7 @@ sub handleIntentGetState {
} elsif ( defined $mapping->{response} ) { } elsif ( defined $mapping->{response} ) {
$response = _getValue($hash, $device, _shuffle_answer($mapping->{response}), undef, $room); $response = _getValue($hash, $device, _shuffle_answer($mapping->{response}), undef, $room);
$response = _ReplaceReadingsVal($hash, _shuffle_answer($mapping->{response})) if !$response; #Beta-User: case: plain Text with [device:reading] $response = _ReplaceReadingsVal($hash, _shuffle_answer($mapping->{response})) if !$response; #Beta-User: case: plain Text with [device:reading]
} elsif ( defined $data->{type} || $data->{Type} ) { } elsif ( defined $data->{type} || defined $data->{Type} ) {
my $reading = $data->{Reading} // 'STATE'; my $reading = $data->{Reading} // 'STATE';
$response = getResponse( $hash, 'getStateResponses', $type ) // getResponse( $hash, 'NoValidIntentResponse') ; $response = getResponse( $hash, 'getStateResponses', $type ) // getResponse( $hash, 'NoValidIntentResponse') ;
$response =~ s{(\$\w+)}{$1}eegx; $response =~ s{(\$\w+)}{$1}eegx;
@ -4777,7 +4815,7 @@ sub handleIntentSetScene{
my $data = shift // return; my $data = shift // return;
Log3($hash->{NAME}, 5, "handleIntentSetScene called"); Log3($hash->{NAME}, 5, "handleIntentSetScene called");
return respond( $hash, $data, getResponse( $hash, 'NoValidData' ) ) if !defined $data->{Scene}; return respond( $hash, $data, getResponse( $hash, 'NoValidData' ) ) if !defined $data->{Scene} && (!defined $data->{Get} || $data->{Get} ne 'scenes');
# Device AND Scene are optimum exist # Device AND Scene are optimum exist
@ -4787,6 +4825,22 @@ sub handleIntentSetScene{
my $scene = $data->{Scene}; my $scene = $data->{Scene};
my $device = getDeviceByName($hash, $room, $data->{Device}); my $device = getDeviceByName($hash, $room, $data->{Device});
my $mapping = getMapping($hash, $device, 'SetScene'); my $mapping = getMapping($hash, $device, 'SetScene');
#Welche (Szenen | Szenarien | Einstellungen){Get:scenes} (kennt|kann) [(der | die | das)] $de.fhem.Device-scene{Device}
if ( defined $data->{Get} && $data->{Get} eq 'scenes' ) {
delete $data->{Get};
my $response = getResponse( $hash, 'RequestChoiceGeneric' );
my @scenes = values %{$hash->{helper}{devicemap}{devices}{$device}{intents}{SetScene}->{SetScene}};
@scenes = uniq(@scenes) if @scenes;
my $options = !@scenes ? '' : _array2andString( $hash, \@scenes );
$response =~ s{(\$\w+)}{$1}eegx;
#until now: only extended test code
$data->{customData} = join q{,}, @scenes;
my $toActivate = [qw(Choice CancelAction)];
return setDialogTimeout($hash, $data, _getDialogueTimeout($hash), $response, $toActivate);
}
# restore HUE scenes # restore HUE scenes
$scene = qq([$scene]) if $scene =~ m{id=.+}xms; $scene = qq([$scene]) if $scene =~ m{id=.+}xms;
@ -4797,6 +4851,7 @@ sub handleIntentSetScene{
return $hash->{NAME} if !$data->{Confirmation} && getNeedsConfirmation( $hash, $data, 'SetScene' ); return $hash->{NAME} if !$data->{Confirmation} && getNeedsConfirmation( $hash, $data, 'SetScene' );
my $cmd = qq(scene $scene); my $cmd = qq(scene $scene);
$cmd = $scene if $scene eq 'cmdBack' || $scene eq 'cmdFwd';
# execute Cmd # execute Cmd
analyzeAndRunCmd($hash, $device, $cmd); analyzeAndRunCmd($hash, $device, $cmd);
@ -5123,8 +5178,8 @@ sub handleIntentSetColorGroup {
# Handle incoming SetTimer intents # Handle incoming Timer, SetTimer and GetTimer intents
sub handleIntentSetTimer { sub handleIntentTimer {
my $hash = shift; my $hash = shift;
my $data = shift // return; my $data = shift // return;
my $siteId = $data->{siteId} // return; my $siteId = $data->{siteId} // return;
@ -5256,6 +5311,23 @@ sub handleIntentSetTimer {
return $name; return $name;
} }
sub handleIntentGetTimer {
my $hash = shift;
my $data = shift // return;
my $siteId = $data->{siteId} // return;
$data->{GetTimer} = 'redirected from intent GetTimer';
return handleIntentTimer($hash, $data);
}
sub handleIntentSetTimer {
my $hash = shift;
my $data = shift // return;
my $siteId = $data->{siteId} // return;
$data->{'.remark'} = 'redirected from intent SetTimer';
return handleIntentTimer($hash, $data);
}
sub handleIntentNotRecognized { sub handleIntentNotRecognized {
my $hash = shift // return; my $hash = shift // return;
@ -5381,11 +5453,11 @@ sub handleIntentConfirmAction {
return $device; return $device;
} }
sub handleIntentChoiceRoom { sub handleIntentChoice {
my $hash = shift // return; my $hash = shift // return;
my $data = shift // return; my $data = shift // return;
Log3($hash->{NAME}, 5, 'handleIntentChoiceRoom called'); Log3($hash->{NAME}, 5, 'handleIntentChoice called');
my $identity = qq($data->{sessionId}); my $identity = qq($data->{sessionId});
my $data_old = $hash->{helper}{'.delayed'}->{$identity}; my $data_old = $hash->{helper}{'.delayed'}->{$identity};
@ -5394,10 +5466,9 @@ sub handleIntentChoiceRoom {
return respond( $hash, $data, getResponse( $hash, 'DefaultChoiceNoOutstanding' ) ) if !defined $data_old; return respond( $hash, $data, getResponse( $hash, 'DefaultChoiceNoOutstanding' ) ) if !defined $data_old;
$data_old->{siteId} = $data->{siteId}; for ( qw( siteId sessionId requestType Room Device Scene ) ) {
$data_old->{sessionId} = $data->{sessionId}; $data_old->{$_} = $data->{$_} if defined $data->{$_};
$data_old->{requestType} = $data->{requestType}; }
$data_old->{Room} = $data->{Room};
my $intent = $data_old->{intent}; my $intent = $data_old->{intent};
my $device = $hash->{NAME}; my $device = $hash->{NAME};
@ -5410,34 +5481,23 @@ sub handleIntentChoiceRoom {
return $device; return $device;
} }
sub handleIntentChoiceRoom {
my $hash = shift // return;
my $data = shift // return;
Log3($hash->{NAME}, 5, 'handleIntentChoiceRoom called');
return handleIntentChoice($hash, $data);
}
sub handleIntentChoiceDevice { sub handleIntentChoiceDevice {
my $hash = shift // return; my $hash = shift // return;
my $data = shift // return; my $data = shift // return;
Log3($hash->{NAME}, 5, 'handleIntentChoiceDevice called'); Log3($hash->{NAME}, 5, 'handleIntentChoiceDevice called');
#my $data_old = $data->{customData}; return handleIntentChoice($hash, $data);
my $identity = qq($data->{sessionId});
my $data_old = $hash->{helper}{'.delayed'}->{$identity};
delete $hash->{helper}{'.delayed'}{$identity};
deleteSingleRegIntTimer($identity, $hash);
return respond( $hash, $data, getResponse( $hash, 'DefaultChoiceNoOutstanding' ) ) if ! defined $data_old;
$data_old->{siteId} = $data->{siteId};
$data_old->{sessionId} = $data->{sessionId};
$data_old->{requestType} = $data->{requestType};
$data_old->{Device} = $data->{Device};
my $intent = $data_old->{intent};
my $device = $hash->{NAME};
# Passenden Intent-Handler aufrufen
if (ref $dispatchFns->{$intent} eq 'CODE') {
$device = $dispatchFns->{$intent}->($hash, $data_old);
}
return $device;
} }
@ -5463,7 +5523,7 @@ sub setPlayWav {
return 'playWav needs siteId and path to file as parameters!' if !defined $cmd->{siteId} || !defined $cmd->{path}; return 'playWav needs siteId and path to file as parameters!' if !defined $cmd->{siteId} || !defined $cmd->{path};
my $siteId = $cmd->{siteId}; my $siteId = _getSiteIdbyRoom($hash, $cmd->{siteId});
my $filename = $cmd->{path}; my $filename = $cmd->{path};
my $repeats = $cmd->{repeats}; my $repeats = $cmd->{repeats};
my $encoding = q{:raw :bytes}; my $encoding = q{:raw :bytes};
@ -5708,7 +5768,12 @@ So all parameters in define should be provided in the <i>key=value</i> form. In
<li><b>prefix</b>: May be used to distinguishe between different instances of RHASSPY on the FHEM-internal side.<br> <li><b>prefix</b>: May be used to distinguishe between different instances of RHASSPY on the FHEM-internal side.<br>
Might be usefull, if you have several instances of RHASSPY in one FHEM running and want e.g. to use different identifier for groups and rooms (e.g. a different language). Not recommended to be set if just one RHASSPY device is defined.</li> Might be usefull, if you have several instances of RHASSPY in one FHEM running and want e.g. to use different identifier for groups and rooms (e.g. a different language). Not recommended to be set if just one RHASSPY device is defined.</li>
<a id="RHASSPY-genericDeviceType"></a> <a id="RHASSPY-genericDeviceType"></a>
<li><b>useGenericAttrs</b>: Formerly, RHASSPY only used it's own attributes (see list below) to identifiy options for the subordinated devices you want to control. Today, it is capable to deal with a couple of commonly used <code>genericDeviceType</code> (<i>switch</i>, <i>light</i>, <i>thermostat</i>, <i>thermometer</i>, <i>blind</i> and <i>media</i>), so it will add <code>genericDeviceType</code> to the global attribute list and activate RHASSPY's feature to estimate appropriate settings - similar to rhasspyMapping. <code>useGenericAttrs=0</code> will deactivate this. (do not set this unless you know what you are doing!). Note: <code>homebridgeMapping</code> atm. is not used as source for appropriate mappings in RHASSPY.</li> <li><b>useGenericAttrs</b>: Formerly, RHASSPY only used it's own attributes (see list below) to identifiy options for the subordinated devices you want to control. Today, it is capable to deal with a couple of commonly used <code>genericDeviceType</code> (<i>switch</i>, <i>light</i>, <i>thermostat</i>, <i>thermometer</i>, <i>blind</i>, <i>media</i>, <i>scene</i> and <i>info</i>), so it will add <code>genericDeviceType</code> to the global attribute list and activate RHASSPY's feature to estimate appropriate settings - similar to rhasspyMapping. <code>useGenericAttrs=0</code> will deactivate this. (do not set this unless you know what you are doing!). Notes:
<ul>
<li>As some devices may not directly provide all their setter infos at startup time, RHASSPY will do a second automatic devicemap update 2 minutes after each FHEM start. In the meantime not all commands may work.</li>
<li><code>homebridgeMapping</code> atm. is not used as source for appropriate mappings in RHASSPY.</li>
</ul>
</li>
<li><b>handleHotword</b>: Trigger Reading <i>hotword</i> in case of a hotword is detected. See attribute <a href="#RHASSPY-attr-rhasspyHotwords">rhasspyHotwords</a> for further reference.</li> <li><b>handleHotword</b>: Trigger Reading <i>hotword</i> in case of a hotword is detected. See attribute <a href="#RHASSPY-attr-rhasspyHotwords">rhasspyHotwords</a> for further reference.</li>
<li><b>Babble</b>: <a href="#RHASSPY-experimental"><b>experimental!</b></a> Points to a <a href="#Babble ">Babble</a> device. Atm. only used in case if text input from an <a href="#AMADCommBridge">AMADCommBridge</a> is processed, see <a href="#RHASSPY-attr-rhasspySTT">rhasspySTT</a> for details.</li> <li><b>Babble</b>: <a href="#RHASSPY-experimental"><b>experimental!</b></a> Points to a <a href="#Babble ">Babble</a> device. Atm. only used in case if text input from an <a href="#AMADCommBridge">AMADCommBridge</a> is processed, see <a href="#RHASSPY-attr-rhasspySTT">rhasspySTT</a> for details.</li>
<li><b>encoding</b>: <b>most likely deprecated!</b> May be helpfull in case you experience problems in conversion between RHASSPY (module) and Rhasspy (service). Example: <code>encoding=cp-1252</code>. Do not set this unless you experience encoding problems!</li> <li><b>encoding</b>: <b>most likely deprecated!</b> May be helpfull in case you experience problems in conversion between RHASSPY (module) and Rhasspy (service). Example: <code>encoding=cp-1252</code>. Do not set this unless you experience encoding problems!</li>
@ -6284,14 +6349,17 @@ yellow=rgb FFFF00</code></p>
<li>SetColor</li> <li>SetColor</li>
{Device} and one Color option are mandatory, {Room} is optional. Color options are {Hue} (0-360), {Colortemp} (0-100), {Saturation} (as understood by your device) or {Rgb} (hex value from 000000 to FFFFFF) {Device} and one Color option are mandatory, {Room} is optional. Color options are {Hue} (0-360), {Colortemp} (0-100), {Saturation} (as understood by your device) or {Rgb} (hex value from 000000 to FFFFFF)
<li>SetColorGroup</li> (as SetColor, except for {Group} instead of {Device}). <li>SetColorGroup</li> (as SetColor, except for {Group} instead of {Device}).
<li>SetScene</li> {Device} and {Scene} (it's recommended to use the $lng.fhemId.Scenes slot to get that generated automatically!). <li>SetScene</li> {Device} and {Scene} (it's recommended to use the $lng.fhemId.Scenes slot to get that generated automatically!), {Room} is optional, {Get} with value <i>scenes</i> may be used to request all possible scenes for a device prior to make a choice.
<li>GetTime</li> <li>GetTime</li>
<li>GetDate</li> <li>GetDate</li>
<li>SetTimer</li> Timer info as described in SetTimedOnOff is mandatory, {Room} and/or {Label} are optional to distinguish between different timers. {CancelTimer} key will force RHASSPY to try to remove a running timer (using optional {Room} and/or {Label} key to identify the respective timer). <li>Timer</li> Timer info as described in <i>SetTimedOnOff</i> is mandatory, {Room} and/or {Label} are optional to distinguish between different timers. {CancelTimer} key will force RHASSPY to try to remove a running timer (using optional {Room} and/or {Label} key to identify the respective timer), {GetTimer} key will be treated as request if there's a timer running (optionally also identified by {Room} and/or {Label} keys).
Required tags to set a timer: at least one of {Hour}, {Hourabs}, {Min} or {Sec}. {Label} and {Room} are optional to distinguish between different timers. If {Hourabs} is provided, all timer info will be regarded as absolute time of day info, otherwise everything is calculated using a "from now" logic. Required tags to set a timer: at least one of {Hour}, {Hourabs}, {Min} or {Sec}. {Label} and {Room} are optional to distinguish between different timers. If {Hourabs} is provided, all timer info will be regarded as absolute time of day info, otherwise everything is calculated using a "from now" logic.
<li>SetTimer</li> Set a timer, required info as mentionned in <i>Timer</i>
<li>GetTimer</li> Get timer info as mentionned in <i>Timer</i>, key {GetTimer} is not explicitely required.
<li>ConfirmAction</li> <li>ConfirmAction</li>
{Mode} with value 'OK'. All other calls will be interpreted as CancelAction intent call. {Mode} with value 'OK'. All other calls will be interpreted as CancelAction intent call.
<li>CancelAction</li>{Mode} is recommended. <li>CancelAction</li>{Mode} is recommended.
<li>Choice</li>One or more of {Room}, {Device} or {Scene}
<li>ChoiceRoom</li>{Room} <li>ChoiceRoom</li>{Room}
<li>ChoiceDevice</li>{Device} <li>ChoiceDevice</li>{Device}
<li>ReSpeak</li> <li>ReSpeak</li>
@ -6304,6 +6372,7 @@ yellow=rgb FFFF00</code></p>
<li>siteId2room_&lt;siteId&gt;</li> <li>siteId2room_&lt;siteId&gt;</li>
Typically, RHASSPY derives room info from the name of the siteId. So naming a satellite <i>bedroom</i> will let RHASSPY assign this satellite to the same room, using the group sheme is also supported, e.g. <i>kitchen.front</i> will refer to <i>kitchen</i> as room (if not explicitly given). <br> Typically, RHASSPY derives room info from the name of the siteId. So naming a satellite <i>bedroom</i> will let RHASSPY assign this satellite to the same room, using the group sheme is also supported, e.g. <i>kitchen.front</i> will refer to <i>kitchen</i> as room (if not explicitly given). <br>
You may overwrite that behaviour by setting values to siteId2room readings: <code>setreading siteId2room_mobile_phone1 kitchen</code> will force RHASSPY to link your satellite <i>phone1 kitchen</i> to kitchen as room. You may overwrite that behaviour by setting values to siteId2room readings: <code>setreading siteId2room_mobile_phone1 kitchen</code> will force RHASSPY to link your satellite <i>phone1 kitchen</i> to kitchen as room.
<li>room2siteId_&lt;room&gt;</li> Used to identify the satellite to speak messages addressed to a room (same for playing sound files). Should deliver exactly one possible siteId, e.g. &lt;lingingroom.04&gt;
<li>siteId2doubleSpeak_&lt;siteId&gt;</li> <li>siteId2doubleSpeak_&lt;siteId&gt;</li>
RHASSPY will always respond via the satellite where the dialogue was initiated from. In some cases, you may want additional output to other satellites - e.g. if they don't have (always on) sound output options. Setting this type of reading will lead to (additional!) responses to the given second satellite; naming scheme is the same as for site2room. RHASSPY will always respond via the satellite where the dialogue was initiated from. In some cases, you may want additional output to other satellites - e.g. if they don't have (always on) sound output options. Setting this type of reading will lead to (additional!) responses to the given second satellite; naming scheme is the same as for site2room.
<li>sessionTimeout_&lt;siteId&gt;</li> <li>sessionTimeout_&lt;siteId&gt;</li>

View File

@ -54,6 +54,7 @@
"DefaultChangeIntentRequestRawInput": "Wechseln zu $rawInput", "DefaultChangeIntentRequestRawInput": "Wechseln zu $rawInput",
"RequestChoiceDevice": "Es kommen mehrere Geräte in Frage, bitte wähle zwischen $first_items oder $last_item", "RequestChoiceDevice": "Es kommen mehrere Geräte in Frage, bitte wähle zwischen $first_items oder $last_item",
"RequestChoiceRoom": "Es kommen mehrere Geräte in verschiedenen Räumen in Frage, wähle zwischen $first_items oder $last_item", "RequestChoiceRoom": "Es kommen mehrere Geräte in verschiedenen Räumen in Frage, wähle zwischen $first_items oder $last_item",
"RequestChoiceGeneric": "Es gibt diese Möglichkeiten, unter denen du wählen kannst: $options",
"DefaultError": "Da ist leider etwas schief gegangen", "DefaultError": "Da ist leider etwas schief gegangen",
"NoValidData": "Ich habe leider zu wenig Daten um den Vorgang auszuführen", "NoValidData": "Ich habe leider zu wenig Daten um den Vorgang auszuführen",
"NoDeviceFound": "Tut mir leid, ich konnte kein passendes Gerät finden", "NoDeviceFound": "Tut mir leid, ich konnte kein passendes Gerät finden",