Perl - Modul 10_RHASSPY.pm "professionalisieren"

Begonnen von drhirn, 18 Februar 2021, 17:02:31

Vorheriges Thema - Nächstes Thema

drhirn

So, das war leicht.

Allerdings, wenn man einen Text in Anführungszeichen eingibt, haut's FHEM auf's Maul.

Can't use string ("set lampe2 off") as an ARRAY ref while "strict refs" in use at ./FHEM/10_RHASSPY.pm line 2290.

Das ist diese Zeile in RHASSPY_ReplaceReadingsVal
my $to_analyze = join q{ }, @{$arr};

Da habe ich keine Lösung gefunden.

Beta-User

#226
Nach etwas Rumspielen mit der response: Das funktioniert schon, wenn man es richtig macht, ist aber nicht ganz ungefährlich, wie du ja auch bemerkt hast:
SetOnOff:cmdOn=on,cmdOff=off,response=state
SetOnOff:cmdOn=on,cmdOff=off,response={"wird erledigt"}


Wie man das mit dem bareword lösen kann (abgesehen von stricture vorübergehend auszuschalten), wird ggf. noch zu klären sein, dazu muss man erst mal checken, von wo aus dieser Code-Teil überhaupt angefahren wird...


Anbei jedenfalls der Umbau:
Es gibt jetzt ein paar mehr interne Hashes, die Logik ist dann (hoffentlich) immer die: Wenn der Wert direkt verwertbar ist (z.B. {Change:up}), dann nimm' den, wenn nicht, schau, ob der (althergebrachte) englische Wert/die regex passt, und wenn auch das nicht klappt, versuch's mit den deutschen Begriffen.

Soweit ich das bisher getestet habe, funktioniert es, und der jetzt noch in der cfg verbliebene Teil ist auch relativ überschaubar und in der Struktur vereinfacht.

Dann mal wieder viel Spaß beim Testen.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Ich hab das jetzt einfach so gelöst:


sub RHASSPY_getValue { #($$$;$$)
    my $hash      = shift // return;
    my $device    = shift // return;
    my $getString = shift // return;
    my $val       = shift;
    my $siteId    = shift;
   
    # Perl Command oder in Anführungszeichen? -> Umleiten zu RHASSPY_runCmd
    if ($getString =~ m{\A\s*\{.*\}\s*\z}x || $getString =~ m/^\s*".*"\s*$/) {
        return RHASSPY_runCmd($hash, $device, $getString, $val, $siteId);
    }

    # Soll Reading von einem anderen Device gelesen werden?
    if ($getString =~ m{:}x) {
        my @replace = split m{:}x, $getString;
        $device = $replace[0];
        $getString = $replace[1] // $getString;
        return ReadingsVal($device, $getString, 0);
    }
    # If it's only a string without quotes, return string for TTS
    else {
        return $getString;
    }
}

Beta-User

#228
Klingt logisch...

Aber mach' die "else" weg. Wir sind doch schon am Ende des Codes und hören - wie es sich gehört - mit einer return-Anweisung auf ;) .

Nachtrag:
Wenn "$getstring" ein Reading-Name ist, macht es durchaus Sinn, den R-Val zurückzugeben. Also so?
sub RHASSPY_getValue { #($$$;$$)
    my $hash      = shift // return;
    my $device    = shift // return;
    my $getString = shift // return;
    my $val       = shift;
    my $siteId    = shift;
   
    # Perl Command oder in Anführungszeichen? -> Umleiten zu RHASSPY_runCmd
    if ($getString =~ m{\A\s*\{.*\}\s*\z}x || $getString =~ m/^\s*".*"\s*$/) {
        return RHASSPY_runCmd($hash, $device, $getString, $val, $siteId);
    }

    # Soll Reading von einem anderen Device gelesen werden?
    if ($getString =~ m{:}x) {
        my @replace = split m{:}x, $getString;
        $device = $replace[0];
        $getString = $replace[1] // $getString;
        return ReadingsVal($device, $getString, 0);
    }
    # If it's only a string without quotes, return string for TTS
    return ReadingsVal($device, $getString, $getString);
}
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Sehr schlau! :)

Dein
SetOnOff:cmdOn=on,cmdOff=off,response=state
wird halt nicht mehr funktionieren. Also schon, aber es wird nicht das Reading gesprochen.

Was mich daran erinnert, dass

response=[lampe1:state]

leider auch nicht funktioniert. Weiß aber noch nicht, warum nicht.

Beta-User

Zitat von: drhirn am 10 März 2021, 15:01:22
Dein
SetOnOff:cmdOn=on,cmdOff=off,response=state
wird halt nicht mehr funktionieren. Also schon, aber es wird nicht das Reading gesprochen.
Siehe meinen Nachtrag...

Zitat
Was mich daran erinnert, dass

response=[lampe1:state]

leider auch nicht funktioniert. Weiß aber noch nicht, warum nicht.
Na ja, die eckigen Klammern sollte man dann nach "if ($getString =~ m{:}x) {" und vor dem split entfernen, falls die da sind. Diese "set magic"-Syntax ist aber bisher nicht als funktionierend dokumentiert...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

#231
Bei SetNumeric wird immer in Prozent gerechnet. Weil der Code davon ausgehen, dass das so sein soll, wenn im Mapping "percent" vorkommt.

my $forcePercent = (defined $mapping->{map} && lc($mapping->{map}) eq 'percent') ? 1 : 0;

Das stimmt nicht, es soll nur in Prozent gerechnet werden, wenn die Unit "percent" ist.

Mein Fehler. Das soll wirklich so sein.

drhirn

Aber, wie sollen diese beiden Sätze jetzt "richtig" aussehen?


\[stell|stelle|mach|mache|schalt|schalte] $de.fhem.Device{Device} [$de.fhem.Device{Room}] [auf|um] [(0..100){Value}] [(prozent|grad|dezibel){Unit}] [(heller|dunkler|wärmer|kälter){Change}]
\[mach] $de.fhem.Device{Device} lauter{Change:upward}

Beta-User

Hm, (hinsichtlich der Klammersetzung) vermutlich etwa so:
\[stell|stelle|mach|mache|schalt|schalte] $de.fhem.Device{Device} [$de.fhem.Device{Room}] [auf|um] [(0..100){Value}] [(prozent{Unit:percent}|grad{Unit:degree}|dezibel{Unit:decibel})] [((heller|wärmer){Change:up}|(dunkler|kälter){Change:down})]
\[mach] $de.fhem.Device{Device} lauter{Change:up}

Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Also, ich weiß jetzt nicht, ob das an mir oder am Code liegt. Aber irgendwie wird immer das erste gefundene Mapping verwendet.

Payload:
Msg: hermes/intent/de.fhem_SetNumeric => {"input": "stell radio um 5 decibel up", "intent": {"intentName": "de.fhem:SetNumeric", "confidenceScore": 1.0}, "siteId": "wohnzimmer", "id": null, "slots": [{"entity": "de.fhem.Device", "value": {"kind": "Unknown", "value": "radio"}, "slotName": "Device", "rawValue": "radio", "confidence": 1.0, "range": {"start": 6, "end": 11, "rawStart": 6, "rawEnd": 11}}, {"entity": "rhasspy/number", "value": {"kind": "Number", "value": 5}, "slotName": "Value", "rawValue": "fünf", "confidence": 1.0, "range": {"start": 15, "end": 16, "rawStart": 15, "rawEnd": 19}}, {"entity": "Unit", "value": {"kind": "Unknown", "value": "decibel"}, "slotName": "Unit", "rawValue": "dezibel", "confidence": 1.0, "range": {"start": 17, "end": 24, "rawStart": 20, "rawEnd": 27}}, {"entity": "Change", "value": {"kind": "Unknown", "value": "up"}, "slotName": "Change", "rawValue": "lauter", "confidence": 1.0, "range": {"start": 25, "end": 27, "rawStart": 28, "rawEnd": 34}}], "sessionId": "wohnzimmer-snowboy-ca7b4bf6-5649-492a-ac8a-7bfb85b597c3", "customData": null, "asrTokens": [[{"value": "stell", "confidence": 1.0, "rangeStart": 0, "rangeEnd": 5, "time": null}, {"value": "radio", "confidence": 1.0, "rangeStart": 6, "rangeEnd": 11, "time": null}, {"value": "um", "confidence": 1.0, "rangeStart": 12, "rangeEnd": 14, "time": null}, {"value": "5", "confidence": 1.0, "rangeStart": 15, "rangeEnd": 16, "time": null}, {"value": "decibel", "confidence": 1.0, "rangeStart": 17, "rangeEnd": 24, "time": null}, {"value": "up", "confidence": 1.0, "rangeStart": 25, "rangeEnd": 27, "time": null}]], "asrConfidence": null, "rawInput": "stell radio um fünf dezibel lauter", "wakewordId": "snowboy", "lang": null}

(wildes) Device:

defmod lampe2 dummy
attr lampe2 readingList pct temperature volume
attr lampe2 rhasspyMapping SetOnOff:cmdOn=on,cmdOff=off\
GetOnOff:currentVal=state,valueOff=off\
GetNumeric:currentVal=temperature,type=Temperatur\
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next\
SetNumeric:currentVal=pct,minVal=0,maxVal=255,cmd=pct,step=1,type=Helligkeit\
SetNumeric:currentVal=temperature,minVal=0,maxVal=255,cmd=temperature,step=1,type=Temperatur\
SetNumeric:currentVal=volume,minVal=-40,maxVal=20,cmd=volume,step=0.5,type=Lautstärke
attr lampe2 rhasspyName lampe,radio,licht
attr lampe2 rhasspyRoom wohnzimmer,schlafzimmer
attr lampe2 room Rhasspy
attr lampe2 setList pct temperature toggle on off play stop pause next previous volume


Log:

RHASSPY: [Rhasspy] Parse (IO: rhasspyMQTT2): Msg: hermes/intent/de.fhem_SetNumeric => {"input": "
Parsed value: up for key: Change
Parsed value: 1 for key: probability
Parsed value: wohnzimmer-snowboy-ca7b4bf6-5649-492a-ac8a-7bfb85b597c3 for key: sessionId
Parsed value: 5 for key: Value
Parsed value: SetNumeric for key: intent
Parsed value: stell radio um 5 decibel up for key: input
Parsed value: decibel for key: Unit
Parsed value: radio for key: Device
Parsed value: stell radio um fünf dezibel lauter for key: rawInput
Parsed value: wohnzimmer for key: siteId
handleIntentSetNumeric called
Device selected: lampe2
rhasspyMapping selected: currentVal=pct,minVal=0,maxVal=255,cmd=pct,step=1,type=Helligkeit
runCmd called with command: pct
lampe2 pct 171 is a normal command
RHASSPY: [Rhasspy] Parse (IO: rhasspyMQTT2): Msg: hermes/dialogueManager/sessionEnded => {"termin

Beta-User

Hmm, da steige ich auf die Schnelle auch nicht durch, aber was ich mir notiert hatte war:
muss auf lauter/leiser begrenzt werden? Was ist mit Kleinschreibung? (Letzteres muss/kann ggf. vorher erledigt werden?

ABER:
Und etwas weiter hinten wird dann noch nach dem Type sortiert. Den sollten wir dann auch mitgeben. Geht sowas:
\[stell|stelle|mach|mache|schalt|schalte] $de.fhem.Device{Device} [$de.fhem.Device{Room}] [auf|um] [(0..100){Value}] [(prozent{Unit:percent}|grad{Unit:degree}|dezibel{Unit:decibel}{Type:volume})] [(heller{Change:up}{Type:brightness}|dunkler{Change:down}{Type:brightness}|wärmer{Change:up}{Type:temperature}|kälter{Change:down}{Type:temperature}|lauter{Change:up}{Type:volume}|leiser{Change:down}{Type:volume}
)]
\[mach] $de.fhem.Device{Device} lauter{Change:up}{Type:volume}

(Ich habe aber noch keine Idee, ob der interne JSON-Parser das sauber auseinanderfieselt...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

Nachtrag: vermutlich ist es einfacher, über das zu gehen, was grade "changeType" heißt. (nicht sicher, ob der Name und die Keywords da drin "gut" sind, vermutlich verbesserungsfähig nach (z.B.) "changeRel",  "volUp", "tempDown" etc...)
\[stell|stelle|mach|mache|schalt|schalte] $de.fhem.Device{Device} [$de.fhem.Device{Room}] [auf|um] [(0..100){Value}] [(prozent{Unit:percent}|grad{Unit:degree}|dezibel{Unit:decibel})] [(heller{changeType:brighter}|dunkler{changeType:darker}|wärmer{changeType:warmer}|kälter{changeType:cooler}|lauter{{changeType:louder}|leiser{changeType:lower})]
\[mach] $de.fhem.Device{Device} lauter{Change:up}{Type:volume}
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Das wird jetzt dann sehr kompliziert :D

Ursprünglich konnten wir ja anhand von "type" im Mapping unterscheiden. Das war aber halt so eine sprachabhängige Lösung.

Der zweite Satz geht auf keinen Fall.

Wir müssen uns also auf Begriffe einigen und danach dann im Code entscheiden. "volUp", "volDown", etc. finde ich ganz gut.

Können wir mit sowas umgehen:

$de.fhem.Device{Device} [0..10]{Value} [dezibel]{Unit:decibel}(lauter|rauf){Change:volUp}
$de.fhem.Device{Device} [0..10]{Value} [grad]{Unit:decibel}(leiser|runter){Change:volDown}
$de.fhem.Device{Device} [0..10]{Value} [grad]{Unit:degree} (kälter|runter){Change:tempDown}
...

Beta-User

Gefällt mir und sollte machbar sein!
Kannst du dazu MSG/payload generieren?
Dann schaue ich bei Gelegenheit, wie man das hinbiegen kann.Vorerst wäre wichtig, dass die alte Syntax noch geht, aber das müsste eigentlich der Fall sein...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Msg: hermes/intent/de.fhem_SetNumeric => {"input": "Musik bad 10 decibel volUp", "intent": {"intentName": "de.fhem:SetNumeric", "confidenceScore": 1.0}, "siteId": "wohnzimmer", "id": null, "slots": [{"entity": "de.fhem.Device", "value": {"kind": "Unknown", "value": "Musik"}, "slotName": "Device", "rawValue": "musik", "confidence": 1.0, "range": {"start": 0, "end": 5, "rawStart": 0, "rawEnd": 5}}, {"entity": "de.fhem.Room", "value": {"kind": "Unknown", "value": "bad"}, "slotName": "Room", "rawValue": "bad", "confidence": 1.0, "range": {"start": 6, "end": 9, "rawStart": 6, "rawEnd": 9}}, {"entity": "rhasspy/number", "value": {"kind": "Number", "value": 10}, "slotName": "Value", "rawValue": "zehn", "confidence": 1.0, "range": {"start": 10, "end": 12, "rawStart": 10, "rawEnd": 14}}, {"entity": "Unit", "value": {"kind": "Unknown", "value": "decibel"}, "slotName": "Unit", "rawValue": "dezibel", "confidence": 1.0, "range": {"start": 13, "end": 20, "rawStart": 15, "rawEnd": 22}}, {"entity": "Change", "value": {"kind": "Unknown", "value": "volUp"}, "slotName": "Change", "rawValue": "lauter", "confidence": 1.0, "range": {"start": 21, "end": 26, "rawStart": 23, "rawEnd": 29}}], "sessionId": "wohnzimmer-snowboy-26e76002-22ab-47dd-9f55-ca64e5a49019", "customData": null, "asrTokens": [[{"value": "Musik", "confidence": 1.0, "rangeStart": 0, "rangeEnd": 5, "time": null}, {"value": "bad", "confidence": 1.0, "rangeStart": 6, "rangeEnd": 9, "time": null}, {"value": "10", "confidence": 1.0, "rangeStart": 10, "rangeEnd": 12, "time": null}, {"value": "decibel", "confidence": 1.0, "rangeStart": 13, "rangeEnd": 20, "time": null}, {"value": "volUp", "confidence": 1.0, "rangeStart": 21, "rangeEnd": 26, "time": null}]], "asrConfidence": null, "rawInput": "musik bad zehn dezibel lauter", "wakewordId": "snowboy", "lang": null}

Msg: hermes/intent/de.fhem_SetNumeric => {"input": "Musik bad decibel volUp", "intent": {"intentName": "de.fhem:SetNumeric", "confidenceScore": 1.0}, "siteId": "wohnzimmer", "id": null, "slots": [{"entity": "de.fhem.Device", "value": {"kind": "Unknown", "value": "Musik"}, "slotName": "Device", "rawValue": "musik", "confidence": 1.0, "range": {"start": 0, "end": 5, "rawStart": 0, "rawEnd": 5}}, {"entity": "de.fhem.Room", "value": {"kind": "Unknown", "value": "bad"}, "slotName": "Room", "rawValue": "bad", "confidence": 1.0, "range": {"start": 6, "end": 9, "rawStart": 6, "rawEnd": 9}}, {"entity": "Value", "value": {"kind": "Unknown", "value": ""}, "slotName": "Value", "rawValue": "", "confidence": 1.0, "range": {"start": 10, "end": 9, "rawStart": 10, "rawEnd": 9}}, {"entity": "Unit", "value": {"kind": "Unknown", "value": "decibel"}, "slotName": "Unit", "rawValue": "", "confidence": 1.0, "range": {"start": 10, "end": 17, "rawStart": 10, "rawEnd": 9}}, {"entity": "Change", "value": {"kind": "Unknown", "value": "volUp"}, "slotName": "Change", "rawValue": "lauter", "confidence": 1.0, "range": {"start": 18, "end": 23, "rawStart": 10, "rawEnd": 16}}], "sessionId": "wohnzimmer-snowboy-13933d03-8d48-4d58-95a5-d6fb588516a2", "customData": null, "asrTokens": [[{"value": "Musik", "confidence": 1.0, "rangeStart": 0, "rangeEnd": 5, "time": null}, {"value": "bad", "confidence": 1.0, "rangeStart": 6, "rangeEnd": 9, "time": null}, {"value": "decibel", "confidence": 1.0, "rangeStart": 10, "rangeEnd": 17, "time": null}, {"value": "volUp", "confidence": 1.0, "rangeStart": 18, "rangeEnd": 23, "time": null}]], "asrConfidence": null, "rawInput": "musik bad lauter", "wakewordId": "snowboy", "lang": null}