From 6f06a5e031d398deff8c3ecaa79b00c02a2e8a7d Mon Sep 17 00:00:00 2001 From: Beta-User <> Date: Wed, 2 Mar 2022 17:33:38 +0000 Subject: [PATCH] mqtt2.template: add some OMG templates git-svn-id: https://svn.fhem.de/fhem/trunk@25763 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/lib/AttrTemplate/mqtt2.template | 46 ++++++++- fhem/contrib/RHASSPY/10_RHASSPY.pm | 108 ++++++++++------------ 2 files changed, 95 insertions(+), 59 deletions(-) diff --git a/fhem/FHEM/lib/AttrTemplate/mqtt2.template b/fhem/FHEM/lib/AttrTemplate/mqtt2.template index 20048d483..57df5bff9 100644 --- a/fhem/FHEM/lib/AttrTemplate/mqtt2.template +++ b/fhem/FHEM/lib/AttrTemplate/mqtt2.template @@ -4479,7 +4479,6 @@ desc:use this with an OpenMQTTGateway for temp/hum sensors like LYWSD03MMC and L order:X_02d par:BT_ID;Pls. enter your bluetooth device ID; {undef} par:BASE_ID;BASE_ID typically is home;{ AttrVal("DEVICE","readingList","") =~ m,([^:]+)[/]O[^/]*M[^/]*G[^/]*[/].*:, ? $1 : undef } -#par:READINGLISTOLD;copy readingList to new device for later resolving parameters;{ AttrVal("DEVICE","readingList","")} par:NEWDEVROOM;Room of the calling device; {AttrVal("DEVICE","room","MQTT2_\DEVICE" )} defmod OMG_BT_ID MQTT2_\DEVICE BT_ID deletereading -q OMG_BT_ID (?!associatedWith|IODev).* @@ -4497,6 +4496,51 @@ attr OMG_BT_ID model OpenMQTTGateway_BT_temp_hum_sensor set DEVICE attrTemplate set_IODev_in_channels SUBCHANNELS=OMG_BT_ID setreading OMG_BT_ID attrTemplateVersion 20220220 +name:OpenMQTTGateway_BT_scale +prereq:{my @devices=devspec2array("model=OpenMQTTGateway_MCU");return 1 if $devices[0];return 0} +filter:TYPE=MQTT2_DEVICE:FILTER=readingList=.*/O[^/]*M[^/]*G[^/]*/.* +desc:use this with an OpenMQTTGateway for scales like Xiaomi Mi Scale. For further details visit https://github.com/1technophile/OpenMQTTGateway/wiki
Recommended structure of the topic pattern home/OpenMQTTGateway/.*.
NOTE: You'll be asked to provide the HEX address of your scale. Best start with looking at what "OpenMQTTGateway_BT_scanner" povides, e.g. if you have a reading name like "6C697244245E_id", "6C697244245E" (without quotes) is what you want to enter...
NOTE: this will create a new device! +order:X_02e +par:BT_ID;Pls. enter your bluetooth device ID; {undef} +par:BASE_ID;BASE_ID typically is home;{ AttrVal('DEVICE','readingList','') =~ m,([^:]+)[/]O[^/]*M[^/]*G[^/]*[/].*:, ? $1 : undef } +par:NEWDEVROOM;Room of the calling device; {AttrVal('DEVICE','room','MQTT2_\DEVICE')} +defmod OMG_BT_ID MQTT2_\DEVICE BT_ID +deletereading -q OMG_BT_ID (?!associatedWith|IODev).* +attr OMG_BT_ID autocreate 0 +attr OMG_BT_ID readingList\ + BASE_ID/O[^/]*M[^/]*G[^/]*/BTtoMQTT/BT_ID:.* { json2nameValue($EVENT,'',$JSONMAP) } +attr OMG_BT_ID event-min-interval batteryPercent:7200,weight:1800 +attr OMG_BT_ID event-on-change-reading batteryPercent,weight:0.1,distance:5,impedance +attr OMG_BT_ID icon message_medicine +attr OMG_BT_ID jsonMap batt:batteryPercent tempc:temperature tem:0 tempf:0 hum:humidity servicedatauuid:0 servicedata:0 +attr OMG_BT_ID stateFormat weight kg +attr OMG_BT_ID room NEWDEVROOM +{ fhem "trigger $FW_wname JS:location.href='$FW_ME?detail=OMG_BT_ID'" if($cl && $cl->{TYPE} eq "FHEMWEB") } +attr OMG_BT_ID model OpenMQTTGateway_BT_temp_hum_sensor +set DEVICE attrTemplate set_IODev_in_channels SUBCHANNELS=OMG_BT_ID +setreading OMG_BT_ID attrTemplateVersion 20220302 + +name:OpenMQTTGateway_BT_unknown_gadget +prereq:{my @devices=devspec2array("model=OpenMQTTGateway_MCU");return 1 if $devices[0];return 0} +filter:TYPE=MQTT2_DEVICE:FILTER=readingList=.*/O[^/]*M[^/]*G[^/]*/.* +desc:use this with an OpenMQTTGateway to get an "empty" device for further adoptions to your needs. For further details visit https://github.com/1technophile/OpenMQTTGateway/wiki
NOTE: You'll be asked to provide the HEX address of your gadget. Best start with looking at what "OpenMQTTGateway_BT_scanner" povides, e.g. if you have a reading name like "6C697244245E_id", "6C697244245E" (without quotes) is what you want to enter...
NOTE: this will create a new device! +order:X_02x +par:BT_ID;Pls. enter your bluetooth device ID; {undef} +par:BASE_ID;BASE_ID typically is home;{ AttrVal('DEVICE','readingList','') =~ m,([^:]+)[/]O[^/]*M[^/]*G[^/]*[/].*:, ? $1 : undef } +par:NEWDEVROOM;Room of the calling device; {AttrVal('DEVICE','room','MQTT2_\DEVICE')} +defmod OMG_BT_ID MQTT2_\DEVICE BT_ID +deletereading -q OMG_BT_ID (?!associatedWith|IODev).* +attr OMG_BT_ID autocreate 0 +attr OMG_BT_ID readingList\ + BASE_ID/O[^/]*M[^/]*G[^/]*/BTtoMQTT/BT_ID:.* { json2nameValue($EVENT,'',$JSONMAP) } +attr OMG_BT_ID icon bluetooth +attr OMG_BT_ID jsonMap batt:batteryPercent tempc:temperature tem:0 tempf:0 hum:humidity servicedatauuid:0 servicedata:0 +attr OMG_BT_ID room NEWDEVROOM +{ fhem "trigger $FW_wname JS:location.href='$FW_ME?detail=OMG_BT_ID'" if($cl && $cl->{TYPE} eq "FHEMWEB") } +attr OMG_BT_ID model OpenMQTTGateway_BT_temp_hum_sensor +set DEVICE attrTemplate set_IODev_in_channels SUBCHANNELS=OMG_BT_ID +setreading OMG_BT_ID attrTemplateVersion 20220302 + ############### #OwnTracks diff --git a/fhem/contrib/RHASSPY/10_RHASSPY.pm b/fhem/contrib/RHASSPY/10_RHASSPY.pm index 95e4df262..13b66e564 100644 --- a/fhem/contrib/RHASSPY/10_RHASSPY.pm +++ b/fhem/contrib/RHASSPY/10_RHASSPY.pm @@ -320,7 +320,7 @@ sub Define { $hash->{defaultRoom} = $defaultRoom; my $language = $h->{language} // shift @{$anon} // lc AttrVal('global','language','en'); - $hash->{MODULE_VERSION} = '0.5.16'; + $hash->{MODULE_VERSION} = '0.5.18'; $hash->{baseUrl} = $Rhasspy; initialize_Language($hash, $language) if !defined $hash->{LANGUAGE} || $hash->{LANGUAGE} ne $language; $hash->{LANGUAGE} = $language; @@ -473,39 +473,10 @@ sub Undefine { sub Delete { my $hash = shift // return; - #my $prefix = $hash->{prefix} // return; deleteAllRegIntTimer($hash); RemoveInternalTimer($hash); -# DELETE POD AFTER TESTS ARE COMPLETED -#Beta-User: Most likely removing attributes isn't a good idea; additionally: if, then attributes should be removed from global -=begin comment - - #Beta-User: globale Attribute löschen - for (devspec2array("${prefix}Mapping=.+")) { - delFromDevAttrList($_,"${prefix}Mapping:textField-long"); - } - for (devspec2array("${prefix}Name=.+")) { - delFromDevAttrList($_,"${prefix}Name"); - } - for (devspec2array("${prefix}Room=.+")) { - delFromDevAttrList($_,"${prefix}Room"); - } - for (devspec2array("${prefix}Channels=.+")) { - delFromDevAttrList($_,"${prefix}Channels"); - } - for (devspec2array("${prefix}Colors=.+")) { - delFromDevAttrList($_,"${prefix}Colors"); - } - for (devspec2array("${prefix}Specials=.+")) { - delFromDevAttrList($_,"${prefix}Specials"); - } - for (devspec2array("${prefix}Group=.+")) { - delFromDevAttrList($_,"${prefix}Group"); - } -=end comment -=cut return; } @@ -846,8 +817,6 @@ hermes/dialogueManager/configure (JSON) https://rhasspy-hermes-app.readthedocs.io/en/latest/usage.html#continuing-a-session =cut - my $sId = $siteId eq 'null' ? 'null' : qq("$siteId"); - my @disabled; my $matches = join q{|}, @{$toDisable}; for (@intents) { @@ -905,7 +874,6 @@ sub init_custom_intents { my $err = perlSyntaxCheck( $perlcommand ); return "$err in $line" if $err && $init_done; - #$hash->{helper}{custom}{$+{intent}}{perl} = $perlcommand; #Beta-User: delete after testing! $hash->{helper}{custom}{$intent}{function} = $function; my $args = trim($+{arg}); @@ -916,7 +884,7 @@ sub init_custom_intents { push @params, $ar; } - $hash->{helper}{custom}{$+{intent}}{args} = \@params; + $hash->{helper}{custom}{$intent}{args} = \@params; } return; } @@ -1519,9 +1487,9 @@ sub initialize_msgDialog { sub disable_msgDialog { my $hash = shift // return; my $enable = shift // 0; - my $fromSST = shift; - readingsSingleUpdate($hash,'enableMsgDialog',$enable,1) if !$fromSST; - return initialize_msgDialog($hash) if $enable && !$fromSST; + my $fromSTT = shift; + readingsSingleUpdate($hash,'enableMsgDialog',$enable,1) if !$fromSTT; + return initialize_msgDialog($hash) if $enable && !$fromSTT; my $devsp; if ( defined $hash->{helper}->{STT} @@ -2555,7 +2523,7 @@ sub notifySTT { return AnalyzePerlCommand( undef, Babble_DoIt($hash->{Babble},$msgtext) ) if $msgtext !~ m{\A[\b]*$tocheck[\b]*\z}i; $msgtext =~ s{\A[\b]*$tocheck}{}i; } - return msgDialog_open($hash, $client, $msgtext); + return ttsDialog_open($hash, $client, $msgtext); } return; @@ -2678,7 +2646,7 @@ sub msgDialog_progress { #This is the place to add additional logics and decission making... #my $data = $hash->{helper}->{msgDialog}->{$device}->{data}; # // msgDialog_close($hash, $device); Log3($hash, 5, "msgDialog_progress called with $device and text $msgtext"); - Log3($hash, 5, 'msgDialog_progress called without DATA') if !defined $data; + #Log3($hash, 5, 'msgDialog_progress called without DATA') if !defined $data; return if !defined $data; @@ -2740,7 +2708,7 @@ sub handleTtsMsgDialog { && defined $hash->{helper}->{msgDialog}->{$recipient} ) { msgDialog_respond($hash,$recipient,$message); sayFinished($hash, $data->{id}, $hash->{siteId}); - } elsif (defined $hash->{helper}->{STT} + } elsif ( defined $hash->{helper}->{STT} && defined $hash->{helper}->{STT}->{config}->{$recipient} ) { ttsDialog_respond($hash,$recipient,$message,0); sayFinished($hash, $data->{id}, $hash->{siteId}); #Beta-User: may be moved to response logic later with timeout...? @@ -2777,6 +2745,7 @@ sub ttsDialog_close { Log3($hash, 5, "ttsDialog_close called with $device"); deleteSingleRegIntTimer($device, $hash); + readingsSingleUpdate($defs{$device}, 'rhasspy_dialogue', 'closed', 1); delete $hash->{helper}{ttsDialog}->{$device}; return; @@ -2797,7 +2766,8 @@ sub ttsDialog_open { customData => $device }; - setTtsDialogTimeout($hash, $sendData, $hash->{helper}->{TTS}->{config}->{$device}->{sessionTimeout}); + my $tout = $hash->{helper}->{TTS}->{config}->{$device}->{sessionTimeout} // $hash->{sessionTimeout}; + setTtsDialogTimeout($hash, $sendData, $tout); return ttsDialog_progress($hash, $device, $msgtext, $sendData); } @@ -2832,20 +2802,32 @@ sub ttsDialog_progress { sub ttsDialog_respond { my $hash = shift // return; - my $DEVICE = shift // return; + my $device = shift // return; my $message = shift // return; my $keepopen = shift // 1; - Log3($hash, 5, "ttsDialog_respond called with $DEVICE and text $message"); + Log3($hash, 5, "ttsDialog_respond called with $device and text $message"); trim($message); return if !$message; # empty? - my $msgCommand = $hash->{helper}->{TTS}->{config}->{$DEVICE}->{ttsCommand} // return; - $msgCommand =~ s{\\[\@]}{@}x; - $msgCommand =~ s{(\$\w+)}{$1}eegx; - AnalyzeCommand($hash, $msgCommand); - resetRegIntTimer( $DEVICE, time + $hash->{helper}->{TTS}->{config}->{$DEVICE}->{sessionTimeout}, \&RHASSPY_msgDialogTimeout, $hash, 0) if $keepopen; - return $DEVICE; + my $msgCommand = $hash->{helper}->{TTS}->{config}->{$device}->{ttsCommand} // return; + my %specials = ( + '$DEVICE' => $device, + '$message' => $message, + '$NAME' => $hash->{NAME} + ); + $msgCommand = EvalSpecials($msgCommand, %specials); + AnalyzeCommandChain($hash, $msgCommand); + if ( $keepopen ) { + my $tout = $hash->{helper}->{TTS}->{config}->{$device}->{sessionTimeout} // $hash->{sessionTimeout}; + resetRegIntTimer( $device, time + $tout, \&RHASSPY_ttsDialogTimeout, $hash, 0); + readingsSingleUpdate($defs{$device}, 'rhasspy_dialogue', 'open', 1); + } else { + deleteSingleRegIntTimer($device, $hash); + delete $hash->{helper}->{ttsDialog}->{$device}; + readingsSingleUpdate($defs{$device}, 'rhasspy_dialogue', 'closed', 1); + } + return $device; } # Update the readings lastIntentPayload and lastIntentTopic @@ -3083,12 +3065,23 @@ sub respond { readingsEndUpdate($hash,1); Log3($hash->{NAME}, 5, "Response is: $response"); - #check for msgDialog session - my $identity = (split m{_$hash->{siteId}_}, $data->{sessionId},3)[0]; + #check for msgDialog or ttsDialog sessions + my $identity = (split m{_$hash->{siteId}_}xms, $data->{sessionId},3)[0]; if ( defined $hash->{helper}->{msgDialog} && defined $hash->{helper}->{msgDialog}->{$identity} ){ Log3($hash, 5, "respond deviated to msgDialog_respond for $identity."); return msgDialog_respond($hash, $identity, $response); + } elsif (defined $hash->{helper}->{TTS} + && defined $hash->{helper}->{TTS}->{config}->{$identity} ) { + Log3($hash, 5, "respond deviated to ttsDialog_respond for $identity."); + $hash->{helper}->{ttsDialog}->{$identity}->{data} = $data if $topic eq 'continueSession'; + return ttsDialog_respond($hash,$identity,$response,$topic eq 'continueSession'); + } elsif (defined $hash->{helper}->{TTS} + && defined $hash->{helper}->{TTS}->{$identity} ) { + $identity = $hash->{helper}->{TTS}->{$identity}; + Log3($hash, 5, "respond deviated to ttsDialog_respond for $identity by siteId."); + $hash->{helper}->{ttsDialog}->{$identity}->{data} = $data if $topic eq 'continueSession'; + return ttsDialog_respond($hash,$identity,$response,$topic eq 'continueSession'); } IOWrite($hash, 'publish', qq{hermes/dialogueManager/$topic $json}); @@ -3096,13 +3089,12 @@ sub respond { #setDialogTimeout( $hash, $data, $delay, getResponse( $hash, 'SilentCancelConfirmation' ) ) if $delay; #no audio output in msgDialog session - return if defined $hash->{helper}->{msgDialog} - && defined $hash->{helper}->{msgDialog}->{(split m{_$hash->{siteId}_}, $data->{sessionId},3)[0]}; - my $secondAudio = ReadingsVal($hash->{NAME}, "siteId2doubleSpeak_$data->{siteId}",0); + #return if defined $hash->{helper}->{msgDialog} + # && defined $hash->{helper}->{msgDialog}->{(split m{_$hash->{siteId}_}, $data->{sessionId},3)[0]}; + my $secondAudio = ReadingsVal($hash->{NAME}, "siteId2doubleSpeak_$data->{siteId}",undef) // return; sendSpeakCommand( $hash, { siteId => $secondAudio, - text => $response} ) - if $secondAudio; + text => $response} ); return; } @@ -5614,7 +5606,7 @@ i="i am hungry" f="set Stove on" d="Stove" c="would you like roast pork"<
  • rhasspyHotwords

    Define custom reactions as soon as a specific hotword is detected (or with "global": a toggle command is detected). This does not require any specific configuration on any other FHEM device.
    - One hotword per line, syntax is either a simple and an extended version. The "hotword" global will be treated specially and can be used to also execute custom commands when a event is indicated.

    + One hotword per line, syntax is either a simple and an extended version. The "hotword" global will be treated specially and can be used to also execute custom commands when a toggle event is indicated.

    Examples:

    bumblebee_linux = set amplifier2 mute on
    porcupine_linux = livingroom="set amplifier mute on" default={Log3($DEVICE,3,"device $DEVICE - room $ROOM - value $VALUE")}
    @@ -5662,7 +5654,7 @@ i="i am hungry" f="set Stove on" d="Stove" c="would you like roast pork"
    <

  • rhasspyTTS experimental! -

    In addition to rhasspySTT, this attributes adds some options to manipulate the text-to-speech processing. Any AMADDevice to be adressed for own TTS processing has to be listed here with it's link to it's siteId. If RHASSPY detects a link between a siteId and an AMADDevice type FHEM device, it will not forward any text to be spoken to Rhasspy but use other synthetisation methods instead (defaulting to set <AMADDevice> ttsMsg $message). +

    In addition to rhasspySTT, this attributes adds some options to manipulate the text-to-speech processing. Any AMADDevice to be adressed for own TTS processing has to be listed here with it's link to it's siteId (development remark: this is missleading atm!). If RHASSPY detects a link between a siteId and an AMADDevice type FHEM device, it will not forward any text to be spoken to Rhasspy but use other synthetisation methods instead (defaulting to set <AMADDevice> ttsMsg $message). Example:

    AMADDev_A=siteId=android_livingroom ttsCommand={fhem("set $DEVICE ttsMsg $message")}
    Notes: