FHEM Forum

FHEM => Sonstiges => Thema gestartet von: ch.eick am 06 Februar 2026, 10:58:45

Titel: FHEM goes Gemini
Beitrag von: ch.eick am 06 Februar 2026, 10:58:45
Hallo zusammen, das wird der weitergehende Thread von diesem (https://forum.fhem.de/index.php?topic=143598.0).


Dieser Post wird gerade noch bearbeitet, Rückfragen bitte später.


Was bisher geschah:

- Wir haben eine mehrstufiege abarbeitung der Anfragen beschlossen, um resourcen zu sparen und auf vom Internet etwas unabhängiger zu sein
- Gemini oder andere KI wird nur ganz am Ende eingebunden, wenn es für die normalen Module zu komplex wird

- Sprach oder Text Eingabe erfolgt über Signal mit den Handys
    Hierzu wird im Signal die Google Spracherkennung aktiviert
      Man öffnet einen Chat und tippt ins Eingabefeld => die Tastatur erscheint
      Über das Rädchen kommt man in die Tastatur Einstellungen
      Weiter unten kommt man zur Spracheingabe ( antippen )
      Dort kann man die Google-Spracheingabe aktivieren oder auch einen anderen Dienst
    Wenn man nun Text eingeben möchte hat man links unter der Tastatur ein Microphon, auf das man zur Spracherkennung einfach tippt.
    Bei Google erscheint ein großes Feld zur Aktivierung des Microphons und bei Samsung ist es direkt das kleine Microphon Symbol, was dann blau wird.

    Ich werde wohl ein altes Smartphone mit Signal für die Spracheingabe in der Wohnung verwenden, das kann man dann genau wie eine Fernbedienung immer schön suchen gehen :-)

- Mit signal-mqtt erfolgt der Empfang in einem Docker Container
- Die Einbindung ins Signal erfolgt in diesem Beispiel über die Syncronisation mit einem Master Handy, das auch der Admin für eine Gruppe ist
- Im FHEM wird mit dem Device fhem_cli per MQTT empfangen
- Über userReadings erfolgt eine Steuerung der Abarbeitungsreihenfolge
  1. Kommando Mapping im fhem_cli Device
      Hier wird bereits eine kleine Hilfe per Signal gesendet, wenn ein Kommando nicht gefunden wurde
  2. Analyse mit Babble
  3. Analyse mit Gemini_AI
- Gemini_AI ist in der kostenlosen Variante auf 20 Abfragen limitiert
    Man kann sich jedoch über zwei Google Konten auch zwei Keys generieren. Das Limit gilt auch nicht pro Projekt, sondern pro Account :-(

  - Man legt sich eine zweite Mail Adresse an, wenn man noch keine hat
  - Meldet das als google Konto an und durchläuft die Verifizierung
  - Dann meldet man sich mit dem neuen Accout an und wechselt zu aistudio
  - Man kann den default Key verwenden oder sich ein eigenes Projekt anlegen.
   
    Somit kann man jetzt bei rollierender Verwendung 2x20 Anfrage stellen, was erstmal ausreichen sollte.


Was bereits funktioniert:

fhem_cli Device (signal-mqtt)
defmod fhem_cli MQTT2_DEVICE signal/in/method/receive/#
attr fhem_cli userattr in_commands
attr fhem_cli DbLogExclude .*
attr fhem_cli autocreate 0
attr fhem_cli devicetopic signal_receiver
attr fhem_cli event-on-change-reading in_...._message.*
attr fhem_cli event-on-update-reading in_...._analyse.*, in_sync_.*
attr fhem_cli in_commands 'wallbox sofort laden'=>'setreading WB_1_lp_1 ui_command_1 SofortLaden',  'wallbox nur pv'=>'setreading WB_1_lp_1 ui_command_1 NurPV',  'wallbox stop'=>'setreading WB_1_lp_1 ui_command_1 Stop',  'whirlpool an'=>'setreading Pool_PV_Perl 01_2_Eigenverbrauch_manuell_An',  'whirlpool aus'=>'setreading Pool_PV_Perl 01_3_Eigenverbrauch_manuell_Aus',  'media an'=>'setreading Wohnzimmer_Standby Standby_Steckdose_ein',  'media aus'=>'setreading Wohnzimmer_Standby Standby_Steckdose_aus',  'küche licht an'=>'set KU_Licht ON',  'küche licht aus'=>'set KU_Licht OFF',  'zirkulation'=>'set Zirkulation on',  'spülwasser'=>'set Zirkulation on',  'wohnzimmer lichterkette an'=>'set shellyswitch25_E0980695962A_CH2 on',  'wohnzimmer lichterkette aus'=>'set shellyswitch25_E0980695962A_CH2 off',  'terrasse lichterkette an'=>'set shellyplus2pm_b0a73246a024_CH2 on',  'terrasse lichterkette aus'=>'set shellyplus2pm_b0a73246a024_CH2 off'
attr fhem_cli jsonMap params_envelope_syncMessage_sentMessage_message:in_analyse
attr fhem_cli readingList $DEVICETOPIC:signal/in:.* { my $j = json2nameValue($EVENT);;my $key = "params_envelope_syncMessage_sentMessage_destination";; return if(!exists $j->{$key});; my $ret = defined $j->{$key} ? $j->{$key}: "null";; return if($ret ne "null");; return {in_sync_message_sent => $j->{params_envelope_syncMessage_sentMessage_message}, in_sync_sourceUuid => $j->{params_envelope_sourceUuid}, in_sync_sourceNumber => $j->{params_envelope_sourceNumber}, in_sync_sourceName => $j->{params_envelope_sourceName}, in_sync_signal_json=> $EVENT};; }\
\
\
##$DEVICETOPIC:signal/in:.* { my $j = json2nameValue($EVENT);; my $key = "params_envelope_syncMessage_sentMessage_groupInfo_groupId";; return if(!exists $j->{$key});; my $ret = defined $j->{$key} ? $j->{$key}: "null";; return if($ret eq "null");; return {in_data_message_sent => $j->{params_envelope_dataMessage_message},in_data_sourceUuid => $j->{params_envelope_sourceUuid},in_data_sourceNumber => $j->{params_envelope_sourceNumber},in_data_sourceName => $j->{params_envelope_sourceName}};; }\
\
$DEVICETOPIC:signal/in:.* { my $j = json2nameValue($EVENT);; my $ret = $j->{params_envelope_dataMessage_message};; return if(!$ret);; return {in_data_signal_json=> $EVENT};; }\
\
\
$DEVICETOPIC:signal/in:.* { {in_conf_groupName=>json2nameValue($EVENT)->{params_envelope_syncMessage_sentMessage_groupInfo_groupName} } }\
$DEVICETOPIC:signal/in/method/receive/source_number/\x252B49<Telefonnummer vom Master>:.* in_conf_0049<Telefonnummer vom Master>
attr fhem_cli room MQTT2_DEVICE,babbleRoom
attr fhem_cli setList FHEM_group signal/out {"jsonrpc":"2.0","method": "send","params": {"groupId":"ik32NK0yzzzzzzzzzzzzereJc=","sourceName": "SmartHome","message": "$EVENT" } }\

attr fhem_cli userReadings in_data_analyse_mapping:in_data_message_sent.* {\
  my $in_source = ReadingsVal("$NAME","in_sync_sourceUuid","null");;\
  Log3($name,3,sprintf("%-20s ur_02 : ", $name)."in_sync_sourceUuid   : $in_source");;\
  my $in_analyse = lc(ReadingsVal("$NAME","in_sync_message_sent","null"));;\
       $in_analyse =~ s/^\s+|\s+$//g ;;                            # leerzeichen abschneiden\
       $in_analyse =~ s/\s+/ /g;;                                     # immer nur ein Leerzeichen zwischen den Worten\
  Log3($name,3,sprintf("%-20s ur_02 : ", $name)."in_sync_message_sent : $in_analyse ");;\
  if (   $in_source eq "984fayyyyyyyyyy76239" ) {\
    my $in_command = "null";;\
    if ( $in_analyse ne "null") {\
      my %h=eval "(".(AttrVal("$NAME","in_commands","n/a")).")";;\
      $in_command = $h{$in_analyse} if defined $h{$in_analyse};;\
      if ($in_command ne "null") {\
        fhem("$in_command");;\
        Log3($name,3,sprintf("%-20s ur_02 : ", $name)."in_sync_command      : $in_command");;\
      } else {\
        Log3($name,3,sprintf("%-20s ur_02 : ", $name)."in_sync_command      : Not found");;\
      }\
      return $in_command;;\
    }\
  }\
  return "null";;\
},\
\
in_sync_analyse_mapping:in_sync_message_sent.* {\
  my $in_source = ReadingsVal("$NAME","in_sync_sourceUuid","null");;\
  Log3($name,3,sprintf("%-20s ur_02 : ", $name)."in_sync_sourceUuid   : $in_source");;\
  my $in_analyse = lc(ReadingsVal("$NAME","in_sync_message_sent","null"));;\
       $in_analyse =~ s/^\s+|\s+$//g ;;                            # leerzeichen abschneiden\
       $in_analyse =~ s/\s+/ /g;;                                     # immer nur ein Leerzeichen zwischen den Worten\
  Log3($name,3,sprintf("%-20s ur_02 : ", $name)."in_sync_message_sent : $in_analyse ");;\
  if (   $in_source eq "9258xxxxxxxxx78bd" ) {\
    my $in_command = "null";;\
    if ( $in_analyse ne "null") {\
      my %h=eval "(".(AttrVal("$NAME","in_commands","n/a")).")";;\
      $in_command = $h{$in_analyse} if defined $h{$in_analyse};;\
      if ($in_command ne "null") {\
        fhem("$in_command");;\
        Log3($name,3,sprintf("%-20s ur_02 : ", $name)."in_sync_command      : $in_command");;\
      } else {\
        Log3($name,3,sprintf("%-20s ur_02 : ", $name)."in_sync_command      : Not found");;\
      }\
      return $in_command;;\
    }\
  }\
  return "null";;\
},\
\
in_sync_analyse_babble:in_sync_analyse_mapping.* {\
  my $in_command;;\
  my $in_source = ReadingsVal("$NAME","in_sync_sourceUuid","null");;\
  Log3($name,4,sprintf("%-20s ur_02 : ", $name)."in_sync_sourceUuid   : $in_source");;\
  my $in_analyse = lc(ReadingsVal("$NAME","in_sync_message_sent","null"));;\
       $in_analyse =~ s/^\s+|\s+$//g ;;                            # leerzeichen abschneiden\
       $in_analyse =~ s/\s+/ /g;;                                     # immer nur ein Leerzeichen zwischen den Worten\
  Log3($name,4,sprintf("%-20s ur_02 : ", $name)."in_sync_message_sent : $in_analyse ");;\
  if (   $in_source eq "9258xxxxxxxxx78bd" ) {                     ## "+491728447553"\
    $in_command = Babble_DoIt("Babble",$in_analyse,"testit",0);;\
    $in_command = "null" if ( $in_command eq "Es tut mir leid, das habe ich nicht verstanden" );;\
  }\
  return $in_command;;\
},\
\
in_sync_analyse_Gemini:in_sync_analyse_babble.* {\
  my $in_command = "null";;\
  if ( ReadingsVal("$NAME","in_sync_analyse_babble","null") eq "null" ) {\
    my $in_source = ReadingsVal("$NAME","in_sync_sourceUuid","null");;\
    Log3($name,4,sprintf("%-20s ur_02 : ", $name)."in_sync_sourceUuid   : $in_source");;\
    my $in_analyse = ReadingsVal("$NAME","in_sync_message_sent","null");;\
         $in_analyse =~ s/^\s+|\s+$//g ;;                            # leerzeichen abschneiden\
         $in_analyse =~ s/\s+/ /g;;                                     # immer nur ein Leerzeichen zwischen den Worten\
    Log3($name,4,sprintf("%-20s ur_02 : ", $name)."in_sync_message_sent : $in_analyse ");;\
    if ( $in_source eq "9258xxxxxxxxx78bd" ) {\
      fhem("set Gemini_AI 02_FHEM_CMD $in_analyse");;\
      $in_command = "waiting";;\
    }\
  } else {\
    $in_command = "Not needed";;\
  }\
  return $in_command;;\
},\
\
help:in_sync_analyse_mapping.*  {\
  my $message;;\
  my $in_help = ReadingsVal("$NAME","in_sync_analyse_mapping","n/a");;\
  Log3($name,4,sprintf("%-20s ur_03 : ", $name)."in_help              : $in_help");;\
  if ( $in_help eq "null" ) {\
    Log3($name,4,sprintf("%-20s ur_03 : ", $name)."Es stehen folgende Kurzbefehle zur Verfügung");;\
    $message = "Es stehen folgende Kurzbefehle zur Verfügung\n";;\
    $in_help = AttrVal("$NAME","in_commands","n/a");;\
    while ($in_help =~ /'([^']+)'\s*=>/g) {\
      Log3($name,4,sprintf("%-20s ur_03 : ", $name)."$1");;\
      $message .= "$1\n";;\
    }\
    # an/aus-Zeilen zusammenfassen\
    $message =~ s/^(.*)\s+(an|aus)\n\1\s+(aus|an)$/$1 an\/aus/gm;;\
    # Newlines escapen\
    $message =~ s/\n/\\n/g;;\
    fhem("set $NAME FHEM_group $message");;\
  }\
  return;;\
}
attr fhem_cli verbose 3



Hier mal einige readings mit einem Beispiel
Das Mapping und Babble haben hier nichts gefunden und Gemini wurde bereits auf mein Umfeld für die Rollos trainiert.
in_sync_analyse_Gemini set WZ_O_Rollo open;set WZ_W_Rollo open;set KU_S_Rollo open;set SC_W_Rollo open;set BA_N_Rollo open;set AZ_O_Rollo position 40
in_sync_analyse_babble null
in_sync_analyse_mapping null
in_sync_message_sent Generiere mir alle vorhandenen Rollo Namen mit einem 'set' davor und 'open' dahinter. Für das Arbeitszimmer soll es auf 40 gesetzt werden.



Babble Device (momentan die im FHEM mitgelieferte Version)
Hier müssen natürlich die Attribute auf die eigene Umgebung angepasst werden
defmod Babble Babble
attr Babble babbleArticles der die das den des dem zur
attr Babble babbleDevices Licht:KU_Licht Zirkulation:Zirkulation Media:Media Lichterkette:Lichterkette
attr Babble babbleNotPlaces 1_Manuell 2_PV_Steuerung Abrechnung EnOcean FhemNative FritzBox Heizung->Info Heizung->System Informationen->Anrufliste Informationen->Kalender Informationen->Wetter JEL MQTT2_DEVICE MieleAtHome Multimedia->DLNA Multimedia->Radio Multimedia->Sonos Multimedia->TV Neu Residents Rollos Shelly Strom->Boerse Strom->Info Strom->Photovoltaik Strom->Wallbox System Wasser
attr Babble babblePlaces Arbeitszimmer Wohnzimmer Esszimmer Küche Schlafzimmer Bad Flur Terrasse Stellplatz Garage Garageneinfahrt Garten Keller
attr Babble babblePreSubs zirkulation\san:zirkulation\sküche\seinschalten
attr Babble babblePrepos von vom des der in im auf bei am
attr Babble babbleQuests wie wo wann
attr Babble babbleStatus Status Wert Wetter Zeit
attr Babble babbleTimes heute morgen übermorgen nacht
attr Babble babbleVerbParts zu auf ent wider ein an aus ab um
attr Babble babbleVerbs schalt,schalte:schalten sagt,sage:sagen
attr Babble babbleWrites setzen ändern löschen
attr Babble comment 2026-02-06 13:00
attr Babble room babbleRoom



Gemini_AI Device
Hier müssen natürlich die Attribute auf die eigene Umgebung angepasst werden
defmod Gemini_AI HTTPMOD none 0
attr Gemini_AI userattr KI_CMD00 KI_CMD01 KI_CMD02 KI_CMD03 KI_CMD04 KI_CMD05 KI_CMD06 KI_CMD07 KI_CMD08 KI_CMD09 KI_CMD10 KI_Instr00 KI_Instr01 KI_Instr02 KI_Instr03 KI_Instr04 KI_Instr05 KI_Instr06 KI_Instr07 KI_Instr08 KI_Instr09 KI_Instr10
attr Gemini_AI KI_CMD00 BEISPIELE:
attr Gemini_AI KI_CMD01 'Es ist dunkel in der Küche' -> set MQTT2_zigbee_Ku_Licht ON  'Licht aus in der Küche' -> set MQTT2_zigbee_Ku_Licht OFF
attr Gemini_AI KI_Instr00 Du bist die Smart-Home-KI für FHEM. Antworte NUR mit dem FHEM-Befehl.
attr Gemini_AI KI_Instr01 Mehrere Befehle trenne mit ;;;;
attr Gemini_AI KI_Instr02 Deine GERÄTE-LISTE: - Das Hauptlicht heißt: Küche
attr Gemini_AI KI_Instr03 Es gibt Rollos in allen Räumen. Wohnzimmer -> WZ;; Küche -> KU;; Schlafzimmer -> SC;; Bad -> BA;; Arbeitszimmer -> AR;;
attr Gemini_AI KI_Instr04 WZ hat je 1 Ost und West, KU 1 Süd, SC 1 West, BA 1 Nord und AZ 1 Ost Rollo. Es gibt Kommandos open, close und position mit 0 bis 100.
attr Gemini_AI KI_Instr05 Die Gerätenamen entsprechen folgendem Syntax mit _ als Trennzeichen: 'Kurzname des Raums' 'Kurzname der Himmelsrichtung' 'Rollo'
attr Gemini_AI KI_Instr06 Die Himmelsrichtungen werden mit dem ersten Buchstaben abgekürzt.
attr Gemini_AI comment 2026-02-06 13:00\
\
Zuerst den Key holen: https://aistudio.google.com/api-keys\
\
Dann im FHEM ablegen\
{KeyValue("store","Gemini_AI_Key_0","DEIN_API_KEY_HIER")}\
Verwendet man zwei Keys ist dieses reading anzulegen: setreading Gemini_AI Gemini_AI_Key 0\
{KeyValue("store","Gemini_AI_Key_1","DEIN_ZWEITER_API_KEY_HIER")}\
\
Nutzerfrage: Mach ma Küche hell und dann wieder aus.\
responce: set MQTT2_zigbee_Ku_Licht ON;;;; set MQTT2_zigbee_Ku_Licht OFF\
\
Nutzerfrage: Küche dunkel\
responce: set MQTT2_zigbee_Ku_Licht OFF\
\
Nutzerfrage: Küche an\
responce: set MQTT2_zigbee_Ku_Licht ON\
\
Nutzerfrage: Küche is echt grell\
responce: set MQTT2_zigbee_Ku_Licht OFF\
\
Nutzerfrage: Generiere mir alle vorhandenen Rollo Namen mit einem 'set' davor und 'open' dahinter. Für das Arbeitszimmer soll es auf 40 gesetzt werden.\
response: set WZ_O_Rollo open;;;;set WZ_W_Rollo open;;;;set KU_S_Rollo open;;;;set SC_W_Rollo open;;;;set BA_N_Rollo open;;;;set AR_O_Rollo position 40
attr Gemini_AI get02AutoNumLen 3
attr Gemini_AI get02ExtractAllJSON 1
attr Gemini_AI get02Header01 Content-Type: application/json
attr Gemini_AI get02Name 05_ListModels
attr Gemini_AI get02URL https://generativelanguage.googleapis.com/v1/models?key=%%KEY%%
attr Gemini_AI reading01DeleteIfUnmatched 1
attr Gemini_AI reading01JSON error_message
attr Gemini_AI reading01Name error_message
attr Gemini_AI reading02DeleteIfUnmatched 1
attr Gemini_AI reading02JSON error_status
attr Gemini_AI reading02Name error_status
attr Gemini_AI reading03DeleteIfUnmatched 1
attr Gemini_AI reading03JSON error_code
attr Gemini_AI reading03Name error_code
attr Gemini_AI reading05DeleteIfUnmatched 1
attr Gemini_AI reading05JSON candidates_01_content_parts
attr Gemini_AI reading05Name response
attr Gemini_AI replacement01Mode expression
attr Gemini_AI replacement01Regex %%KEY%%
attr Gemini_AI replacement01Value { my $key = ReadingsVal($name,"Gemini_AI_Key","null");;\
  my $j;;\
  if ( $key eq "null" ) { \
    $j = 0;;\
  } else {\
    for (my $i=int($key);;$i<=1;;$i++) {\
      $j = $i;;\
      if ($i < 1) { fhem("setreading $name Gemini_AI_Key ".($i+1));;last;;}\
      else { fhem("setreading $name Gemini_AI_Key 0");;}\
    }\
  }\
  my $tmp = KeyValue("read","Gemini_AI_Key_".$j);;\
  return defined($tmp) ? $tmp : undef;;\
}\

attr Gemini_AI replacement05Mode expression
attr Gemini_AI replacement05Regex %%KI_Instructions%%
attr Gemini_AI replacement05Value { my $tmp = "";; my $KI_Instr = "";;\
  for (my $j=0;;$j<=99;;$j++){\
    $tmp = AttrVal($name,sprintf("KI_Instr%02d",$j),"null");;\
    if ( $tmp ne "null" ) { $KI_Instr .= $tmp."\n" } else { last };;\
  }\
  for (my $j=0;;$j<=99;;$j++){\
    $tmp = AttrVal($name,sprintf("KI_CMD%02d",$j),"null");;\
    if ( $tmp ne "null" ) { $KI_Instr .= $tmp."\n" } else { last };;\
  }\
  return $KI_Instr;;\
}
attr Gemini_AI room babbleRoom
attr Gemini_AI set01Data {"contents": [{"parts":[{"text": "$val"}]}]}
attr Gemini_AI set01ExtractAllJSON 0
attr Gemini_AI set01Header01 Content-Type: application/json
attr Gemini_AI set01Header02 x-goog-api-key: %%KEY%%
attr Gemini_AI set01Method POST
attr Gemini_AI set01Name 01_ask
attr Gemini_AI set01ParseResponse 1
attr Gemini_AI set01TextArg 1
attr Gemini_AI set01URL https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent
attr Gemini_AI set05Data {"contents": [{"role": "user", "parts": [{"text": "INSTRUKTION: %%KI_Instructions%% NUTZERFRAGE: $val"}]}]}
attr Gemini_AI set05ExtractAllJSON 0
attr Gemini_AI set05Header01 Content-Type: application/json
attr Gemini_AI set05Header02 x-goog-api-key: %%KEY%%
attr Gemini_AI set05Method POST
attr Gemini_AI set05Name 02_FHEM_CMD
attr Gemini_AI set05ParseResponse 1
attr Gemini_AI set05TextArg 1
attr Gemini_AI set05URL https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent
attr Gemini_AI showBody 1
attr Gemini_AI showError 0
attr Gemini_AI timeout 15
attr Gemini_AI userReadings fhem_cli:response.* {\
  my $in_command = ReadingsVal("$NAME","response","null");;\
  fhem("setreading fhem_cli in_sync_analyse_Gemini $in_command");;\
  return "Sent to device fhem_cli";;\
}
attr Gemini_AI verbose 3


Gemini_AI Attribute (als Wiederholung)
# Ich habe folgende SystemInstruction definiert, die die Umgebung beschreiben und mit der die KI zusätzlich lernt

# 1.
attr Gemini_AI KI_Instr00 Du bist die Smart-Home-KI für FHEM. Antworte NUR mit dem FHEM-Befehl.
attr Gemini_AI KI_Instr01 Mehrere Befehle trenne mit ;;;;
attr Gemini_AI KI_Instr02 Deine GERÄTE-LISTE: - Das Hauptlicht heißt: Küche

# 2.  Das beschreibt meine Rollo Installation, ohne die Device Namen direkt anzugeben
# 2.1 Wie heißen die Räume und welche Kurznamen sollen verwendet werden
attr Gemini_AI KI_Instr03 Es gibt Rollos in allen Räumen. Wohnzimmer -> WZ;; Küche -> KU;; Schlafzimmer -> SC;; Bad -> BA;; Arbeitszimmer -> AR;;
# 2.2 Wie sind die Aurichtungen der Rollos in den Räumen
#     Man kann auch mehrere Beschreibungen in eine Zeile schreiben, die Zeilen sollen es nur lesbarer machen.
#     Welche Kommandos können für Rollos verwendet werden?
attr Gemini_AI KI_Instr04 WZ hat je 1 Ost und West, KU 1 Süd, SC 1 West, BA 1 Nord und AZ 1 Ost Rollo. Es gibt Kommandos open, close und position mit 0 bis 100.
# 2.3 Das beschreibt meinen Namensstandard für die Rollos
attr Gemini_AI KI_Instr05 Die Gerätenamen entsprechen folgendem Syntax mit _ als Trennzeichen: 'Kurzname des Raums' 'Kurzname der Himmelsrichtung' 'Rollo'
# 2.3 Hier lernt die KI noch, dass die Himmelsrichtungen abgekürzt werden.
attr Gemini_AI KI_Instr06 Die Himmelsrichtungen werden mit dem ersten Buchstaben abgekürzt.

# 3. Für direkte Kommandos und Aussagen gibt man Beispiele. Dies ist sinnvoll, wenn es keinen guten Namensstandard gibt, oder das Kommando komplexer ist.
attr Gemini_AI KI_CMD00 BEISPIELE:
attr Gemini_AI KI_CMD01 'Es ist dunkel in der Küche' -> set MQTT2_zigbee_Ku_Licht ON  'Licht aus in der Küche' -> set MQTT2_zigbee_Ku_Licht OFF

In den Tests sieht man, dass die KI auch aus anderen Aussagen durchaus das richtige Kommando findet.
Bei den Attributen ist die Möglichkeit von 00-99 eingerichtet, die man jedoch noch im userattr fortlaufend ergänzen muss. Es dürfen bei der Nummerierung keine Lücken entstehen.

In den bisherigen Devices werden nur fhem_cli und Babble Kommandos ausgeführt. Die KI Rückmeldungen werden zur Zeit nicht im FHEM ausgeführt.
Den Verlauf der Analyse sieht man im fhem_cli Device.


VG  Christian


Titel: Aw: FHEM goes Gemini
Beitrag von: Prof. Dr. Peter Henning am 06 Februar 2026, 13:06:12
OK, ich binde mich mit ein.

LG

pah
Titel: Aw: FHEM goes Gemini
Beitrag von: ch.eick am 06 Februar 2026, 14:11:23
Zitat von: Prof. Dr. Peter Henning am 06 Februar 2026, 13:06:12OK, ich binde mich mit ein.
Danke, da fühle ich mich geehrt.
Bei Babble brauche ich sicherlich noch Hilfe.