[AMAD2] Je nach Nutzer unterschiedliche Willkommenstexte vorlesen lassen

Begonnen von yrwyddfa, 11 April 2017, 19:50:10

Vorheriges Thema - Nächstes Thema

yrwyddfa

Hallo zusammen,

ich bin an einem kleinen Projekt dran: Ich möchte, dass mein Flurdisplay (Android-Tablet mit Automagic) beim Nachhausekommen ("An"-Schalter wird betätigt) meine Frau mit anderen Zufallstexten begrüßt als mich.

Die Einrichtung von Zufallstexten haben wir hier bereits schon besprochen und das funktioniert grandios:

Zufälliger Text vorlesen am Tablet


Meine sub sieht hierbei so aus:


sub welcomeText()

{
my @texte;
my $indexend;
my $index;


@texte = (  "Willkommen zuhause. Zufallstext",
"Willkommen zuhause. Alternativer Zufallstext",
"Willkommen zuhause. Beliebig viele weitere Zufallstexte, jeweils in Anführungszeichen und mit Kommata getrennt",
         );

$indexend = $#texte;
$index = int( rand( $indexend ) );

my $text=$texte[$index];
return $text;
}


(Danke CoolTux!)

In meiner fhem.cfg sieht das Einbinden dann wie folgt aus:



define n_willkommen notify (SchalterAnwesend:on) { my $randText = welcomeText();; fhem "set AMAD_FlurDisplay ttsMsg $randText";; }



Drücken wir unseren Anwesenheitsknopf, liest er also (leider mit etwa 15 Sekunden Verzögerung) einen zufälligen Text vor.


Das möchte ich nun zur Kunst erheben. Angedacht ist folgendes: Je nachdem, welches Handy sich via Bluetooth bei Fhem anmeldet, während der Anwesenheitsschalter gedrückt wird, soll Fhem via AMAD einen anderen Zufallsblock auslesen.
Da stellt sich mir die Frage: Wie kann ich einen zweiten solchen Block generieren? Kann ich einfach meine o.g. sub eins zu eins kopieren und neu in die myutils einfügen? also würde das hier funktionieren:


sub FrauenText()

{
my @texte;
my $indexend;
my $index;


@texte = (  "Willkommen zuhause. Zufallstext",
"Willkommen zuhause. Alternativer Frauentext",
"Willkommen zuhause. Beliebig viele weitere Frauentexte, jeweils in Anführungszeichen und mit Kommata getrennt",
         );

$indexend = $#texte;
$index = int( rand( $indexend ) );

my $text=$texte[$index];
return $text;
}
;

sub maennerText()

{
my @texte;
my $indexend;
my $index;


@texte = (  "Willkommen zuhause. Männertext",
"Willkommen zuhause. Alternativer Männertext",
"Willkommen zuhause. Beliebig viele weitere Männertexte, jeweils in Anführungszeichen und mit Kommata getrennt",
         );

$indexend = $#texte;
$index = int( rand( $indexend ) );

my $text=$texte[$index];
return $text;
}



oder "beißen" sich dann die gleichlautenden Variablen?

Ich würde hinterher gern eine Anleitung schreiben, mit der man das dann nachbauen kann, sollte bei mir dann alles funktionieren - daher würde ich mich sehr über Hilfe freuen :)

Vielen lieben Dank schon mal!
If every day has its number, Monday would be a zero division.

CoolTux

Du kannst das in mehren Subs machen, die Variablen "beißen sich auch nicht".

Du kannst das ganze aber auch in einer Sub machen und nimmst einen bestimmten Wert/index als Erkennung ob Frau oder Mann
Diesen Wert kannst Du entweder der Sub beim Aufruf übergeben (das mache ich so) oder Du versucht innerhalb der Sub zu ermitteln wer gekommen ist und steckst das Ergebnis in eine Variable die Du dann in einer Bedingung ab fragst.


sub randomTTS($) {

my ($textTyp) = @_;
        my $text;
my $indexend;
my $index;

my @texte;




if( $textTyp eq "BegruessungWeckerMorgensIsa" ) {

    @texte =    (   "Guten Morgen liebe Isa",
                    "Einen bezaubernden guten Morgen",
                    "Hallo Isa, raus aus den Federn",
                    "Zeit zum aufstehen kleine Zaubermaus",
                    "Was für ein schöner Morgen",
                    "Raus aus den Federn"
                    );
}
   

elsif( $textTyp eq "GuteNachtText" ) {
   
        @texte =    (   "Ich wünsche eine gute Nacht",
                    "Ich wünsche süße Träume",
                    "Schlaft gut",
                    "Gute Nacht bis morgen Früh",
                    );
}
   

elsif( $textTyp eq "test2" ) {

    }




$indexend = $#texte;
$index = int( rand( $indexend ) );

$text=$texte[$index];
return $text;
}


Überlege Dir also ob Du in der Sub oder im Notify rausfinden möchtest wer da nach Hause gekommen ist. Persönlich mache ich sowas im übrigen über das Residents Device. Da steht drin wer die letzte Activity gemacht hat.


Hier kannst Du auch mal schauen ob Du das schöner schreiben kannst

define n_willkommen notify (SchalterAnwesend:on) { fhem "set AMAD_FlurDisplay ttsMsg " . welcomeText();; }



Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

yrwyddfa

Ich denke, ich werde es so angehen:

Ich habe mich wegen der für mich einfacheren Verständlichkeit  für das Modul PRESENCE entschieden. Bei mir steht der Fhem-Server, der auf einem Pi 3 läuft, recht zentral in der Wohnung, daher deckt er mit seinem Bluetooth-Modul diese annähernd perfekt ab. Da wir beide durch die Freisprecheinrichtung im Auto Bluetooth eigentlich immer an haben, ist dieser Zugang perfekt. Allerdings habe ich mir noch ein Workaround mit Automagic erstellt (das Tool ist herrlich).

Weiterhin habe ich mich jetzt erst mal für eine eigene Sub-Routine pro Person entschieden, da das für mich als absoluter Perl-Noob einfacher zu individualisieren ist. So könnte ich später die Parameter und Texte pro Person anpassen, was bei einer Abfrage innerhalb einer sub für mich (nebst Knoten im Hirn) deutlich unübersichtlicher würde.

Derzeit arbeite ich mit drei Routinen: Sie kommt allein nach hause, ich komme allein nach hause, wir kommen gemeinsam nach hause. der Vorteil ist, dass sich dies später ggf. recht einfach um eine weitere sub erweitern ließe.

Ich werde die Konstellation die kommenden Tage mal testen und überprüfe mal, ob das so, wie ich es mir vorstelle, reibungslos funktioniert. Dann stell ich meine subs und die Aufrufe hier noch mal ein, ebenso mein Automagic-Workaround :)   
If every day has its number, Monday would be a zero division.

yrwyddfa

Hallo zusammen,

nach einigen Hirnknoten und Fallstricken habe ich ein für mich gut ins Konzept passende System ausgefuchst - die Komponenten habe ich ja schon erwähnt, werde hier aber - wie versprochen - nun alles Schritt für Schritt noch mal erklären. Sollte jemand Ideen haben, wie es einfacher geht, bin ich für Anregungen natürlich dankbar.

Was habe ich gemacht?

Ich habe ein Display am Eingang hängen, welches mir einen Willkommenstext vorliest, und zwar abhängig davon, ob nur ich, nur meine Frau oder aber wir beide nach Hause kommen.

Welche Komponenten verwende ich?

  • Hardware: Ein Android-Tablet, das automagic-fähig ist
  • Hardware: Bluetoothfähiger fhem-Server, z.B. Raspberry Pi 3
  • Hardware: MAX!-Eco-Taster (als "Willkommen-Schalter")
  • Software (Tablet): Automagic (auf AMAD getrimmt)
  • Software (Tablet): TTS, ich nutze derzeit Gudrun
  • Modul (fhem): PRESENCE
  • Modul (fhem): AMAD2
  • Modul (fhem): DOIF
  • (fhem): 99_myutils.pm (keine Angst, ich werde es versuchen, Schritt für Schritt anzuleiten)

Was ist zu tun?
1. Zufällige Texte pro Person als subs einrichten (damit fhem weiß, was es dem Tablet zum Reden geben soll)
2. AMAD und Automagic einrichten (damit Fhem dem Tablet sagen kann es was zu reden hat)
3. TTS einrichten (damit das Tablet reden kann)
4. Anwesenheitserkennung generieren (damit fhem weiß, wer zuhause ist)



Schritt für Schritt


1. Zufallstexte einrichten

Hierfür generieren wir pro Person, die einen zufälligen Text bekommen soll, eine eigene Sub. der Vorteil ist, dass man diese dann sehr einfach pro Person bearbeiten und auch verhältnismäßig leicht weitere Personen hinzufügen kann.

Dafür muss man die 99_myUtils.pm pro Person um folgende Sub erweitern:


# Zufallswillkommenstext für Ihn in 99_myUtils.pm

sub welcomeHim()

{
my @texte;
my $indexend;
my $index;


@texte = (  "Willkommen zuhause. Zufallstext",
"Willkommen zuhause. Alternativer Zufallstext",
"Willkommen zuhause. Beliebig viele weitere Zufallstexte, jeweils in Anführungszeichen und mit Kommata getrennt",
         );

$indexend = $#texte;
$index = int( rand( $indexend ) );
}



Dieser Text kann beliebig oft untereinander stehen, je nachdem, für wie viele Personen man individuelle Texte einrichten möchte. Bei mir sind es zwei Personen und eine weitere für den Fall, wenn alle zusammen heim kommen. Demnach sieht es bei mir in etwa so aus:

Code (CoolTux) Auswählen


# Zufallswillkommenstext für Ihn in 99_myUtils.pm

sub welcomeHim()

{
my @texte;
my $indexend;
my $index;


@texte = (  "Willkommen zuhause. Zufallstext",
"Willkommen zuhause. Alternativer Zufallstext",
"Willkommen zuhause. Beliebig viele weitere Zufallstexte, jeweils in Anführungszeichen und mit Kommata getrennt",
         );

$indexend = $#texte;
$index = int( rand( $indexend ) );
}



# Zufallswillkommenstext für Sie in 99_myUtils.pm
sub welcomeHer()

{
my @texte;
my $indexend;
my $index;


@texte = (  "Hallo schöne Frau! Willkommen zuhause. Zufallstext",
"Willkommen zuhause. Alternativer Zufallstext",
"Willkommen zuhause. Beliebig viele weitere Zufallstexte, jeweils in Anführungszeichen und mit Kommata getrennt",
         );

$indexend = $#texte;
$index = int( rand( $indexend ) );
}


# Zufallswillkommenstext für Alle in 99_myUtils.pm
sub welcomeAll()

{
my @texte;
my $indexend;
my $index;


@texte = (  "Hallo Zusammen! Willkommen zuhause. Zufallstext",
"Willkommen zuhause. Alternativer Zufallstext",
"Willkommen zuhause. Beliebig viele weitere Zufallstexte, jeweils in Anführungszeichen und mit Kommata getrennt",
         );

$indexend = $#texte;
$index = int( rand( $indexend ) );
}


Wichtig ist, dass jede sub ihren eigenen Namen bekommt, mitdem wir sie hinterher in Fhem aufrufen können. Nach dem Einfügen Speichern nicht vergessen!






2. AMAD einrichten

Hier git es eine super Beschreibung in der Commandref, dieser bitte Schritt für Schritt folgen. Etwas knifflig ist hier, die XML-Datei aus dem Fhem-Verzeichnis auf das Tablet zu bekommen. Ggf. ist es einfacher, die Datei direkt aus github herunterzuladen (Achtung! auf die richtige Version achten!), z.B. hier: https://github.com/LeonGaultier/fhem-AMAD (Achtung, Link kann veraltet sein!)






3. TTS einrichten

TTS wird je nach Tablet standardmäßig über die Google-Server geleitet. Wer das möchte, braucht hier normalerweise nichts mehr zu machen. Da mir das allerdings nicht behagt, habe ich mir Sprachsoftware aus dem Playstore heruntergeladen. die in meinen Augen bisher am saubersten formulierende App ist hierbei Gudrun, ist aber auch kostenpflichtig. Allerings kann man, wenn man sich die 1,70€ sparen will, auch auf kostenlose Stimmen (nach IVONA in Google Play suchen) umsatteln.

Nun muss man allerdings dem Tablet noch sagen, dass es standardmäßig die gewählte Engine verwenden soll. Dies macht man zumeist unter Einstellungen, bei Samsung-Geräten kann man hier nach Sprache und Eingabe --> Text-zu-Sprache suchen, bei anderen Geräten kann das abweichen. Im Zweifelsfall hilft hier Google.




4. Anwesenheitserkennung

Zuerst sollte man sich überlegen, was die sicherste Methode ist, fhem klar zu machen, dass man tatsächlich zuhause ist. Bei einem (größeren) Haus bietet sich an, die Erreichbarkeit der Handys im Netzwerk zu nutzen, da dies in der Regel eine recht stabile Erkennung bietet.
Ich selbst nutze jedoch die Bluetooth-Erkennung, da sich der FHEM-Server sehr zentral befindet und der Eingangsbereich (auf den es ja hier ankommt) in der Reichweite befindet. Ein weiterer Vorteil ist es, dass FHEM auch wirklich erst erkennt, dass wir zuhause sind, wenn wir durch die Eingangstüre sind. Der Nachteil ist, dass die Handys zwischenzeitlich durchaus von Server via Bluetooth nicht auffindbar sind.
Der Willkommenstext funktioniert auf jeden Fall mit allen Möglichkeiten.   

Für die Anwesenheitserkennung nutze ich PRESENCE und lasse ihn über mein Bluetooth vom Pi lauschen, ob unsere Handys in Reichweite sind.

Das funktioniert mit


define <Handy-Name> PRESENCE local-bluetooth xx:xx:xx:xx:xx:xx # Hier Handyname und Bluetoothadresse eintragen


Die Bluetooth-Adresse des Handys befindet sich zumeist in den Einstellungen, z.B. unter "Gerätestatus" (das variiert je nach Gerät stark, lässt sich aber ergooglen).

Wer Bluetooth eigentlich immer aus hat, wlan aber immer an, kann entweder die Anwesenheitserkennung via WLAN laufen lassen (mit der Gefahr, dass der Willkommenstext viel zu früh startet), oder aber er bedient sich eines kleinen Tricks, den ich unten erläutere.

Im Folgenden erstellen wir nun einen Dummy, der je nach Anwesenheit einen anderen Wert annimmt. Der Vorteil ist, dass man hier theoretisch beliebig viele Menschen anlegen kann:



define WerKommtHeim dummy
attr WerKommtHeim event-on-change-reading .*
attr WerKommtHeim setList 1 2 3 4 #Zahl sollte mit eventMap identisch sein
attr WerKommtHeim eventMap 1:Er 2:Sie 3:alle 4:niemand #lässt sich beliebig erweitern und mit eigenen Namen versehen



Um das Event "Nach Hause gekommen" auszulösen, habe ich an der Eingangstür einen MAX!-Eco-Taster angebracht, mit welchem ich "Abwesenheitsmodus" und "Anwesenheitsmodus definiere.

Mit dieser Grundinstallation kann man nun eine Abfrage generieren, die schaut, wer nach Hause gekommen ist. Hier bin ich über einen Fallstrick geraten, denn dadurch, dass manchmal FHEM die Handys nicht gesehen hat, wurde immer wieder sofort beim Wiederfinden ein neuer Willkommenstext ausgelöst. Das wollen wir natürlich nicht, daher bin ich den Weg über einer weiteren Dummy gegangen, der nach dem Willkommenstext wieder ausgeschaltet wird. So bleibt der Status von WerKommtHeim von der Routine unbeeinflusst:


define SchalterAnwesend dummy
#... hier habe ich Heizungssteuerung, Steckdosen etc. hinterlegt, welche abgeschaltet/runtergeregelt werden sollen, wenn SchalterAnwesend = off bzw. an- und hochgeregelt werden, wenn SchalterAnwesend = on. Um den Rahmen nicht zu sprengen, werde ich diesen Weg nicht hier mit aufnehmen, er lässt sich aber über das Forum bzw. dem Wiki gut nachvollziehen

define doif_WelcomeBack_event DOIF ([SchalterAnwesend] eq "on") (set WelcomeBack_event on) DOELSE
# Her binden wir den dummy ein, der den selben Wert wie SchalterAnwesend annehmen soll. Ihn machen wir aber hinterher wieder aus( (s.u.)

define doif_WerKommtHeim DOIF ([WelcomeBack_event] eq "on" and [HisMobile] eq "present" and [HerMobile] eq "absent") (set WerKommtHeim 1) DOELSEIF ([WelcomeBack_event] eq "on" and [HerMobile] eq "present" and [HisMobile] eq "absent") (set WerKommtHeim 2) DOELSEIF ([WelcomeBack_event] eq "on" and [HisMobile] eq "present" and [HerMobile] eq "present")(set WerKommtHeim 3) DOELSEIF ([HerMobile] eq "absent" and [HisMobile] eq "absent") (set WerKommtHeim 4) DOELSE
# Hier wird nun WerKommtHeim auf den jeweils zutreffenden Wert gesetzt - dieser Wert entscheidet dann, welche Sub (s.o.) dann ausgeführt wird


define doif_willkommen_all DOIF ([WerKommtHeim] eq "alle") ({ my $randText = welcomeAll();; fhem "set AMAD_FlurDisplay ttsMsg $randText";; })(set WelcomeBack_event off) DOELSE

define doif_willkommen_him DOIF ([WerKommtHeim] eq "Er") ({ my $randText = welcomeHim();; fhem "set AMAD_FlurDisplay ttsMsg $randText";; }) (set WelcomeBack_event off) DOELSE

define doif_willkommen_her DOIF ([WerKommtHeim] eq "Sie") ({ my $randText = welcomeHer();; fhem "set AMAD_FlurDisplay ttsMsg $randText";; }) (set WelcomeBack_event off) DOELSE
# Je nach WerKommtHeim-Zustand wird nun eine andere Sub geladen, dann wird WelcomeBack_event wieder auf "off" gesetzt,  damit die Statusabfrage nicht immer und immer wieder einen Willkommenstext auslöst.






Jetzt kann man sich schon ans Testen wagen. Viel Erfolg!
Ach ja: wenn man testen will, ist es sinnvoll, die Aktoren (Thermostate, Steckdosen,...), die man alle runterfahren will, wenn man das Haus verlässt, erstmal auszukoppeln (z.B. mit einer # auskommentieren) - sonst erreicht man schnell die 1%-Hürde und Fhem lässt sich viiiiel Zeit mit dem Reagieren auf einen neuen Taster-Druck.







Bluetooth nur vorübergehend anschalten

Wie versprochen kommt hier nun noch ein kleiner Trick, den ich nutze, damit das Handy auch immer Bluetooth an hat, wenn ich nach Hause komme. Bei uns ist WLAN am Handy immer angeschaltet, demnach gibt es, wenn wir nach Hause kommen, immer ein Event, dass sich unser Handy ins WLAN einwählt.
Da wir ja nun Automagic besitzen, können wir es auch auf unserem Handy installieren (ohne Mehrkosten bei gleichem Account). Hier lässt sich ein einfacher Flow hinterlegen, der folgende Grundstruktur hat:


           Trigger                                                     
[Login Heim-WLAN (SSID angeben!)] -------------------------------> [ist Bluetooth an?]            Condition
                                                                        |
                                                                        | Nein
                                                                        |
                                                              [Schalte Bluetooth an]      Action
                                                                        |
                                                              [Pause (z.B. 5 Minuten)]    Action
                                                                        |
                                                              [Schalte Bluetooth aus]     Action


Dieser "Flow" überprüft beim Einloggen ins Heim-WLAN ob Bluetooth am Handy an ist. Wenn ja, macht er nichts, wenn nicht, schaltet er es für 5 Minuten an und macht es danach wieder aus. Diese Zeit reicht für die Anwesenheitskontrolle locker, allerdings weiß nach dem Ausschalten FHEM nicht mehr, dass man zuhause ist. Ggf. sollte man also die letzten beiden Actions weg lassen, denn dann lässt er Bluetooth an.
Ähnliche Flows lassen sich natürlich auch direkt für die Einwahl ins WLAN erstellen, hier kann man ggf. auch mit ortsgebundenen Flows arbeiten ( bin ich im Umkreis von XY, schalte WLAN/Bluetooth an,...)


So, ich hoffe, ich konnte Euch hiermit einen kleinen Gefallen tun. Ich bin weder Programmierer noch langjähriger FHEM-Nutzer, bin daher natürlich offen für Verbesserungsvorschläge und Vereinfachungen. Wenn jemand Fragen hat, versuche ich im Rahmen meiner Möglichkeiten gern zu helfen, kann aber nichts versprechen ;)

Viel Spaß mit eurem "Willkommen zuhause" :)

yw
If every day has its number, Monday would be a zero division.

floxx

Danke für deine Anleitung @yrwyddfa

Ich habe alles soweit auf mein System angepasst und die Sprachausgabe klappt auch nur leider gibt mein Tablet nur "0" oder "1" sprachtechnisch aus. Ändere ich in der doif $randText auf Hallo höre ich auch ein Hallo. Mein Problem ist also die random Textermittlung. Hat sich dies bezüglich etwas geändert?

Im Eventmonitor hab ich leider keine eindeutige Meldung, Danke

yrwyddfa

Hallo Floxx,

sorry für die späte Rückantwort, irgendwie wurde ich nicht über deinen Beitrag informiert (mich hat die SPAM-Welle nun wohl auch erfasst -.- )

Ist die Problematik denn noch aktuell? Wie lautet deine sub? Und wie deine doif?
If every day has its number, Monday would be a zero division.