FHEM und Rhasspy

Begonnen von drhirn, 28 Juli 2020, 14:28:50

Vorheriges Thema - Nächstes Thema

JensS

Es sieht so aus, dass im Response-Mapping keine subs mehr aufgerufen werden - warum auch immer. Wenn ich response={return "Hallo"} schreibe, geht's.
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

drhirn

Weil die Subs im falschen Kontext aufgerufen werden. Im Log steht
Undefined subroutine &MQTT::RHASSPY::ResponseOnOff called at (eval 232) line 1.

Sollte eigentlich main::ResponseOnOff sein. Oder so.
Ich schau mir das morgen an.

drhirn

#257
Ein Quick&Dirty Work-Around wäre, wenn du die sub einfach in MQTT::RHASSPY::ResponseOnOff umbenennst.

(Nur in der 99_myUtils; das Mapping kann so bleiben)

ODER ((c) BetaUser)

Die 99_myUtils so zu lassen, und das Mapping auf response={::ResponseOnOff($DEVICE)} zu ändern.

drhirn

BetaUser hat das Problem elegant gelöst: https://forum.fhem.de/index.php/topic,118926.msg1134695.html#msg1134695

Ich hab das in der Version 0.2.0 ausgebessert.

JensS

Danke für die Weiterleitung aber ich habe mich dazu entschlossen, vorerst bei der Version aus meinem Fork zu bleiben.
Erstmal alles in die Luft zu werfen, um es dann hoffentlich richtig zusammen zu setzen ist nicht so mein Ding. Entwicklung bedeutet schrittweise vorzugehen.
Wenn das Modul in einem stabilen Zustand ist und hoffentlich noch deutsch unterstützt, teste ich gern.

Gruß Jens
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

drhirn

Naja, andererseits hätte ich ohne dich viele Fehler nicht gefunden. Außer uns beiden testet leider niemand.
Entwickeln tu ich aber sowieso mit der testing-branch. Die 0.2.0 sollte eigentlich eine "stabile Beta" sein.

Cordula

Zwei Anmerkungen zum Intent SetTimer. Hier fehlt noch für die Räume die Umlautunterstützung. Dadurch wird z.B. auch das Reading timer_raum nicht auf 0 zurückgesetzt. Als zweites ist mir aufgefallen, dass wenn ich einen Raum angebe, versucht der Timer die Ausgabe auf einer siteId, die dem Raum entspricht. Wenn diese siteId nicht existiert, läuft das Ganze ins Leere. Hier fände ich es besser, dass wenn die siteId nicht existiert, die aufrufende siteId verwendet wird mit dem Zusatz des Raumes. Aber nur ein Vorschlag.

drhirn

Kannst du mir das bitte genauer erklären? Ich weiß nicht genau, was du meinst.
Und die Sache ist die: FHEM kennt die vorhandenen siteIDs nicht.

Ich hab gerade folgenden Satz getestet: "Timer im Bad auf 5 Sekunden"
Die siteId "Bad" gibt's bei mir nicht, einen rhasspyRoom "Bad" auch nicht. Somit wurde der Timer mit der siteId des Satelliten gesetzt, der die Nachricht empfangen hat. "Wohnzimmer" in meinem Fall.

Cordula

Beispiel: Timer im Arbeitszimmer auf 30 Sekunden. rhasspyRoom Arbeitszimmer gibt es, aber keine siteId Arbeitszimmer. Timer/Reading wird gesetzt, aber keine Ausgabe am eingebenden Satellit. Hier der passende Logfileintrag: Created timer: defmod timer_Arbeitszimmer at +00:00:30 set Rhasspy speak siteId="Arbeitszimmer" text="taimer abgelaufen";;setreading Rhasspy timer_arbeitszimmer 0    mit der siteId Arbeitszimmer.
Umlaut ist klar oder soll ich das noch genauer erklären.

drhirn

Hehe, nein, Umlaut ist klar. Das ist in meiner Entwicklungsversion schon gelöst. Muss nur noch ordentlich getestet werden.

Und bezüglich siteId hab ich jetzt verstanden, um was genau es geht. Danke!

JensS

@drhirn
Zur Prüfung auf eine vorhandene siteId könnte man ein "set Rhasspy fetchSiteIDs" einbauen und z.B. ein Reading für die SetTimer-Abfrage füllen.sub fetchSiteIDs(){
my $RhasspyMaster = AttrVal("Rhasspy","rhasspyMaster",'http://127.0.0.1:12101')."/api/profile";
my $ua = LWP::UserAgent->new();
my $response = $ua->get("$RhasspyMaster");
my $content = $response->content;
my $ref = JSON->new->decode($content);
my $JSONString = encode('cp-1252',$ref->{'dialogue'}{'satellite_site_ids'});
fhem("setreading Rhasspy SatellitesIDs $JSONString");
}

Gruß Jens
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

drhirn

Cool, schau ich mir an!

laberlaib

#267
Hallo drhirn,

da ich deinen Professionalisierungsthread nicht stören will, ich darin aber diesen language-Teil gelesen habe:
Einen Wunsch, keinen Ahnung ob das geht:
Die Mehrsprachigkeit zielt jetzt ja soweit ich das nachvollziehen kann nur auf die Rhasspy-Ebene ab.

Was ich toll fände, wäre wenn es Mehrsprachigkeit auch auf der FHEM-Ebene gäbe:
Zwei Rhasspy-Devices anlegen, welche sich mit zwei unterschiedlichen Rhasspy-Mastern verbinden, sollte ja kein Problem sein.
Aber das bewusste Trainieren von wenigen Wörtern , um die Schwierigkeiten der Speech2Text-Fähigkeit zu erleichtern, wird dann durch nur ein Attribut rhasspyRoom /rhasspyName aufgeweicht. Beide Master erlenen dann "Stehlampe" obwohl der Engländer damit wenig anfangen kann. "Rhasspy weiß nicht, wie man folgenden Worte ausspricht...".

Könnte man also in Abhängigkeit einer Sprachdefinition in der DEF auch unterschiedliche, mehrere Raumattribute zur Verfügung stellen?
rhasspyRoomDE, rhasspyRoomEN

(Ich hatte zu Beginn des Threads schon einmal gewünscht, konnte das aber so nicht in der Überarbeitung sehen, drum Wünsch ichs noch einmal - sonst müsste ich das Modul wohl immer forken und sozusagen ein zweites Modul jedes mal per Suchen & Ersetzen daraus generieren).

(Bei uns hat der Wechselunterricht angefangen so dass ich endlich wieder Zeit für so etwas habe).
--
Proxmox, Homematic, G-Tags, Zigbee2MQTT, Rhasspy Sprachsteuerung im Aufbau (beta)

drhirn

Hatte deinen Wunsch noch im Hinterkopf.

Du wirst um zwei 10_RHASSPY Devices nicht herum kommen.
Stört Rhasspy ja nicht, wenn da "fremdsprachige" Wörter in den Slots sind. Kennt halt die Wörter einfach nicht. Es ist nicht schön, das gebe ich zu. Dafür musst du bei den FHEM-Devices nicht mehrere Attribute befüllen.

Aber ich werde es weiter im Hinterkopf behalten, eine Lösung kann nicht das Drama sein.

JensS

#269
In einem anderen Thread taucht gerade die Frage nach Implementation von genericDeviceType auf.
Dieses Attribut nutze ich für einige eigene Intents.
99_myUtils.pmsub GetAllOff($$){
my ($Raum,$Typ) = @_;
if ( !defined $Raum || length($Raum) == 0 ) {$Raum = 'Haus'};
my $Ansprache;
if ($Typ eq "light"){$Ansprache = "Es sind alle Lampen im $Raum ausgeschaltet"}else{$Ansprache = "Es sind alle Fenster im $Raum geschlossen"};
my $Response = "";
my @Lampen = split /\n/,fhem("list .*:FILTER=genericDeviceType=$Typ");
for (my $w=0;$w<@Lampen;$w++){
if ( lc(InternalVal($Lampen[$w],'STATE','Fehler')) ne "off"
and lc(InternalVal($Lampen[$w],'STATE','Fehler')) ne "closed"
and InternalVal($Lampen[$w],'STATE','Fehler') ne "0"
and (AttrVal($Lampen[$w],'rhasspyRoom','Haus') eq $Raum or $Raum eq 'Haus')){
my $Name = (split(/,/,AttrVal($Lampen[$w],"rhasspyName","Fehler")))[0];
$Response = $Response." $Name im ".AttrVal($Lampen[$w],'rhasspyRoom','Haus')." - ";};
};
if ($Response ne "" and $Typ eq "light"){$Ansprache = "Folgende Lampen sind eingeschaltet - "}
elsif ($Response ne "" and $Typ eq "window"){$Ansprache = "Folgende Fenster sind geöffnet - "};
return $Ansprache.$Response;
}

sub SetAllOff($$){
my ($Raum,$Typ) = @_;
if ( !defined $Raum || length($Raum) == 0 ) {$Raum = 'Haus'};
my $Ansprache;
if ($Typ eq "light"){$Ansprache = "Es sind bereits alle Lampen im $Raum ausgeschaltet"}else{$Ansprache = "Es sind bereits alle Rollos im $Raum geschlossen"};
my $Response = "";
my @Lampen = split /\n/,fhem("list .*:FILTER=genericDeviceType=$Typ");
for (my $w=0;$w<@Lampen;$w++){
if ( lc(InternalVal($Lampen[$w],'STATE','Fehler')) ne "off"
and lc(InternalVal($Lampen[$w],'STATE','Fehler')) ne "closed"
and InternalVal($Lampen[$w],'STATE','Fehler') ne "0"
and (AttrVal($Lampen[$w],'rhasspyRoom','Haus') eq $Raum or $Raum eq 'Haus')){
my $Name = (split(/,/,AttrVal($Lampen[$w],"rhasspyName","Fehler")))[0];
$Response = $Response." $Name im ".AttrVal($Lampen[$w],'rhasspyRoom','Haus')." - ";
fhem("set $Lampen[$w] off") if $Typ eq "light";
fhem("set $Lampen[$w] closed") if $Typ eq "blind";
};
};
if ($Response ne "" and $Typ eq "light"){$Ansprache = "Folgende Lampen wurden ausgeschaltet - "}
elsif ($Response ne "" and $Typ eq "window"){$Ansprache = "Folgende werden geschlossen - "};
return $Ansprache.$Response;
}

sub SetAllOn($$){
my ($Raum,$Typ) = @_;
if ( !defined $Raum || length($Raum) == 0 ) {$Raum = 'Haus'};
my $Ansprache;
if ($Typ eq "light"){$Ansprache = "Es sind bereits alle Lampen im $Raum eingeschaltet"}else{$Ansprache = "Es sind bereits alle Rollos im $Raum geöffnet"};
my $Response = "";
my @Lampen = split /\n/,fhem("list .*:FILTER=genericDeviceType=$Typ");
for (my $w=0;$w<@Lampen;$w++){
if ( lc(InternalVal($Lampen[$w],'STATE','Fehler')) ne "on"
and lc(InternalVal($Lampen[$w],'STATE','Fehler')) ne "open"
and InternalVal($Lampen[$w],'STATE','Fehler') ne "1"
and (AttrVal($Lampen[$w],'rhasspyRoom','Haus') eq $Raum or $Raum eq 'Haus')){
my $Name = (split(/,/,AttrVal($Lampen[$w],"rhasspyName","Fehler")))[0];
$Response = $Response." $Name im ".AttrVal($Lampen[$w],'rhasspyRoom','Haus')." - ";
fhem("set $Lampen[$w] on") if $Typ eq "light";
fhem("set $Lampen[$w] open") if $Typ eq "blind";
};
};
if ($Response ne "" and $Typ eq "light"){$Ansprache = "Folgende Lampen wurden eingeschaltet - "}
elsif ($Response ne "" and $Typ eq "window"){$Ansprache = "Folgende werden geöffnet - "};
return $Ansprache.$Response;
}

sentences.ini:[de.fhem:GetAllOff]
sind alle ((Lichter|Lampen){Type:light}|(Fenster){Type:window}) [im (Haus | $de.fhem.Room){Room}] (gelöscht|aus|an|zu|geschlossen)

[de.fhem:SetAllOff]
(schließe|lösche) alle ((Lichter|Lampen){Type:light}|(Rollos){Type:blind}) [im (Haus | $de.fhem.Room){Room}]

[de.fhem:SetAllOn]
(schalte|öffne) alle ((Lichter|Lampen){Type:light}|(Rollos){Type:blind}) [im (Haus | $de.fhem.Room){Room}] [an]

rhasspyIntents:GetAllOff=GetAllOff(Room,Type)
SetAllOff=SetAllOff(Room,Type)
SetAllOn=SetAllOn(Room,Type)
Gruß Jens

p.s. list .*:FILTER=genericDeviceType=$Typ hat den Nachteil, dass ich mindestens zwei Devices des jeweiligen Types brauche aber ist halt mal wieder "quick & dirty".
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.