[ghome-fhem] HowTo: Google Home/Assistant Integration

Begonnen von dominik, 27 November 2018, 21:56:29

Vorheriges Thema - Nächstes Thema

dominik

Hi Georg,

gerne kannst du das machen. Ich hatte einiges aus dem homebridge Code entfernt, um mir überhaupt mal einen Überblick zu verschaffen.
Manche Sachen sind jedoch Device spezifisch, z.B. unterstützt Google Assistant "Modes" die es meines Wissens bei Alexa noch nicht gibt. Man kann aber solche Dinge einfach im Code belassen und in der server.js werden die dann nicht verarbeitet.

Gruß
Dominik
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

gvzdus

Okay, das ist ein Wort. Dann mal gucken, dass ich den ersten Wurf eines Merge hinbekomme.

Weitere Perspektive:
Ich hatte heute mein "Heureka". Über Google Home und ngrok bin ich auf https://serveo.net/ gestoßen. Wenn man sich anguckt, wie viele Beiträge hier um "ich krieg' die Connectivity" nicht hin gehen, und sich anguckt, wie viele Verrenkungen es benötigt, um Alexa zu integrieren (bei Google ist das ja etwas einfacher), ist eigentlich da eine Lösung in Form eines Public-Skills m.E. etwas überfällig. justme-1968 hatte ja mal was angedacht - ist dann aber wohl - wie ich oft auch - nicht zur Umsetzung gekommen.

Meine Idee ist nun folgende, die würde ich gerne mal zur Diskussion stellen:

1) Der Nutzer baut den SSH-Tunnel a la serveo.net zum "Einheitsserver" mit Reverse-Tunnel auf. Bzw.: ghome-fhem macht das automatisch.
2) Der neue Key wird erkannt, der "Einheitsserver" sendet einen längeren Auth-Code (Zufallszahl) zurück, der beim OAuth2-Connect von Google und Amazon händisch eingegeben werden muss, wenn der FHEM-Smarthome-Skill installiert wird.
3) Der "Einheitsserver" kann auch OAuth. Beim Account-Linking vergibt er nach Eingabe des Auth-Codes den OAuth2-Code bzw. die Tokens.
4) Kommt nun ein HTTPS-Request vom Skill beim "Einheitsserver" an, schickt der die Requests in den anhand des Bearer-Tokens identifizierten persönlichen SSH-Tunnel mit dem zugeordneten SSH-Key, wo sie dann beim lokalen nodejs landen und zu FHEM gehen.

Der "Einheitsserver" hat also 3 Interfaces:
- SSH inbound zum "Raspberry" etc. mit Auto-Provisionierung (Authcode für Anmeldung)
- HTTPS: OAuth2, zur Vergabe Authcode -> Code für Oauth2 -> Bearer-Token
- HTTPS: Inbound als zentraler Host für Requests vom Skill, die anhand des Bearer-Tokens in den richtigen SSH-Tunnel des Nutzers geroutet werden.

Vorteile:
- Keine offenen Ports
- Simple Installation ohne Developer-Registration etc. - wie die kommerzielle Welt.
- nodejs kann und sollte auf localhost laufen.
- Deutlich schneller, weil kein SSL-Context aufgebaut werden muss.
- Den ganzen hässlichen Overhead von Correlation-ID und Bearer-Token (bei Amazon) muss man eigentlich nicht durchreichen, und die Kommunikation kann per HTTP geführt werden, weil SSH schon Security & Encryption bereitstellt.

Nachteile:
- Muss jemand machen :-) Und den "Einheitsserver" sponsern :-)
- "Die dritte Partei" im Spiel, eine Sache des Vertrauens.

Da mein DS-Light Unitymedia Anschluss zur Zeit auf IPv4-Layer sehr unzuverlässig ist, und inbound IPv4 ohnehin nicht klappt, ist meine Krücke z.Zt. der eigene Webserver beim Hosting-Partner, der dann über IPv6 zum heimischen Raspberry als Reverse-Proxy geht. Alles irgendwie krank, und auch definitiv langsamer als z.B. Hue.

dominik

Ich bin auch schon am überlegen eine offizielle Action zu bauen, um diese mühsame Einrichtung zu umgehen.

Meine aktuelle Idee:
- Auth0 als Authentication Provider
- Firebase mit Auth0 authentifizieren
- Lokaler nodejs mit Auth0 authentifizieren und Firestore Verbindung
- Cloud Function als Endpoint für Assistant welches dann über Firestore die Verbindung zum lokalen nodejs aufbaut

Ich habe jedoch noch nie mit Firestore gearbeitet, daher muss ich mich mal einlesen ob das überhaupt so gehen kann.
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

gvzdus

Schon ziemlich fette Frameworks, wenn ich das richtig gegooglet habe: Ich mag an serveo.net diesen Ansatz: "Probier doch mal das eine Kommando oben aus, und Du hast es".
Egal. Ich glaube, was auch immer jenseits von "Werde Developer bei Amazon etc" real da wäre, würde gut ankommen.

JF Mennedy

Hallo, bei mir bleibt der Dienst immer stehen... Ich habe alles nach ANleitung installiert komme aber nicht weiter. wo finde ich denn die logs, weshalb der dienst stehenbleibt?
Das sonstige Einrichten hat super geklappt...
Danke für Eure Hilfe...

pi@raspberrypi:~/.ghome $ sudo systemctl status ghome
● ghome.service - Google Assistant FHEM Connector
   Loaded: loaded (/lib/systemd/system/ghome.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Mon 2018-12-03 20:36:40 CET; 17s ago
  Process: 2778 ExecStart=/home/pi/ghome-fhem/bin/ghome (code=exited, status=1/FAILURE)
Main PID: 2778 (code=exited, status=1/FAILURE)

Dez 03 20:36:39 raspberrypi systemd[1]: ghome.service: Unit entered failed state.
Dez 03 20:36:39 raspberrypi systemd[1]: ghome.service: Failed with result 'exit-code'.
Dez 03 20:36:40 raspberrypi systemd[1]: ghome.service: Service hold-off time over, scheduling restart.
Dez 03 20:36:40 raspberrypi systemd[1]: Stopped Google Assistant FHEM Connector.
Dez 03 20:36:40 raspberrypi systemd[1]: ghome.service: Start request repeated too quickly.
Dez 03 20:36:40 raspberrypi systemd[1]: Failed to start Google Assistant FHEM Connector.
Dez 03 20:36:40 raspberrypi systemd[1]: ghome.service: Unit entered failed state.
Dez 03 20:36:40 raspberrypi systemd[1]: ghome.service: Failed with result 'exit-code'.

dominik

sudo journalctl -u ghome.service

Mit den Cursortasten kann man durch das Log navigieren.
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

JF Mennedy

ok DANKE :-) Problem gefunden war ein Fehler in der config json... Jetzt komm ich auf die seite im eigenen netz, aber noch  nicht hinter dem reverse proxy...

SouzA

#37
Zitat von: dominik am 29 November 2018, 19:34:12
Kannst du bitte mal beim SYNC im Log prüfen ob die Scenes auch wirklich nochmals an Google übertragen werden? Ich habe gerade im Code geprüft und da sollte definitiv nichts mehr übertragen werden, egal ob eine einzelne Scene weg ist oder das gesamte Device.
Hi,
ich hab mal versucht das nachzuvollziehen.
Mit
journalctl -u ghome --no-pager
kriege ich ja eigentlich alles angezeigt. Nach "synchronisiere meine Geräte" kommt erst einmal eine ganze Latte an removing's.
Darunter auch mein LightScene-Device.
Das ist aber auch das einzige mal, dass das Device im Log auftaucht. (Es ist noch im "Sync-Raum") Wie soll ich nun beurteilen, ob da noch was übergeben wird?  :o
Namensänderungen der Szenen werden aber definitiv sofort mitgenommen.

Bis denn
SouzA

Btw.
Jetzt habe ich die Scenen einmal umbenannt und wieder zurück benannt. Jetzt habe ich zwei weitere Szenen unter "Ambiente steuern" in der App. Unter Geräte taucht allerdings nur eine Szene auf(was auch richtig wäre). Scheint nen Bug in der App zu sein.
Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

SouzA

#38
Zitat von: jf.mennedy@gmail.com am 03 Dezember 2018, 21:12:53
ok DANKE :-) Problem gefunden war ein Fehler in der config json... Jetzt komm ich auf die seite im eigenen netz, aber noch  nicht hinter dem reverse proxy...

Hi,
Apache?
Wie sieht deine sites-available config aus?

Folgendes zu meiner config:
1.) Einen willkürlichen Port in den Actions bei Google eingetragen. Z.B: https://<<sub.deineSeite>>:55786  ..../oauth  ..../token
2.) Diesen Port "55786" in der FritzBox auf Port "443" des Raspi umgeleitet. Ein anderer Port hat bei mir nicht funktioniert. Unfähigkeit oder Ungeduld. Beides möglich...
3.) sites-available config:
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName <<sub.deineSeite.de>>

    ServerAdmin <<info@deineSeite.de>>
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/<<sub.deineSeite.de>>.error.log
    CustomLog ${APACHE_LOG_DIR}/<<sub.deineSeite.de>>.access.log combined

    SSLCertificateFile /etc/letsencrypt/live/<<sub.deineSeite.de>>/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/<<sub.deineSeite.de>>/privkey.pem

    Include /etc/letsencrypt/options-ssl-apache.conf

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On
    ProxyTimeout 60
    ProxyErrorOverride On

    ProxyPass / http://localhost:<<deinGhomePort>>/
    ProxyPassReverse / http://localhost:<<deinGhomePort>>/

    <Directory />
        RedirectPermanent / /
    </Directory>

</VirtualHost>
</IfModule>

Voraussetzung dafür ist natürlich ein aktuelles ssl-Zertifikat. (LetsEncrypt z.B.)
4.) Den Port <<deinGHomePort>> in der GHome config.json eintragen.

Das wars eigentlich.

Bis denn
SouzA
Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

JF Mennedy

So, vielen Dank für die Unterstützung. Habe es endlich mit einem TestDevice laufen... Allerdings nicht auf meinem Apache sondern erstmal auf einem Standalone System... Komme da irgendwie nicht so richtig weiter mit dem Reverse Proxy. Hatte es genauso konfiguriert wie beschrieben, wollte aber nicht so richtig :-( Ich bleib dran ...

JF Mennedy

Hallo nochmals... Ich bekomme es einfach nicht hin... Ich habe den Reverse Proxy für meine FHEM Instanz laufen mit folgender Konfiguration:

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName meine.url.de
    ServerAdmin abc@meine.url.de
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/meine.url.de.error.log
    CustomLog ${APACHE_LOG_DIR}/meine.url.de.access.log combined

    SSLCertificateFile /etc/letsencrypt/live/meine.url.de/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/meine.url.de/privkey.pem

    Include /etc/letsencrypt/options-ssl-apache.conf

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On
    ProxyTimeout 60
    ProxyErrorOverride On

    <Location /fhem>
        ProxyPass http://192.168.0.252:8086/fhem
        ProxyPassReverse http://192.168.0.252:8086/fhem
        AuthType Basic
        AuthName "Password for FHEM Required"
        AuthUserFile /etc/fhem-htpasswd
        Require valid-user
        Order deny,allow
        Allow from all
     </Location>

    <Location /api>
        ProxyPass http://192.168.0.252:8085/fhem
        ProxyPassReverse http://192.168.0.252:8085/fhem
        AuthUserFile /etc/fhemapi-htpasswd
    </Location>

    <Directory />
        RedirectPermanent / /fhem
    </Directory>

    <Proxy *>
        AuthType Basic
        AuthName "Password for FHEM Required"
        AuthUserFile /etc/fhem-htpasswd
        Require valid-user
        Order deny,allow
        Allow from all
    </Proxy>
</VirtualHost>
</IfModule>


Wie muss ich denn die KOnfiguration anpassen, damit ghome auch weitergeleitet wird.

Wenn ich ghome auf einem separaten Raspberry laufen habe ohne apache und direkte weiterleitung von port 443 auf den von ghome läuft alles wunderbar, aber ich würde das gerne hinter meinem apache laufen lassen...

Sorry, bin in den Angelegenheiten noch recht frisch hinter den Ohren und freue mich über jeglichen Input, der förderlich ist, solche Probleme auch mal selber gelöst zu bekommen...

Merci im Voraus :-)

Jan

gvzdus

Moin, ich bin z.Zt. einigermaßen aktiv z.Zt. am Code.

Ein Bug:
In handleControlSetTargetTemperature wird die humidity (sinnlos) abgefragt. Da MAX-Thermostate das nicht haben, fällt ghome-fhem da auf die Nase. Kann man einfach löschen.

SouzA

Zitat von: jf.mennedy@gmail.com am 04 Dezember 2018, 20:50:48
Hallo nochmals... Ich bekomme es einfach nicht hin... Ich habe den Reverse Proxy für meine FHEM Instanz laufen mit folgender Konfiguration:

....

Wie muss ich denn die KOnfiguration anpassen, damit ghome auch weitergeleitet wird.

Wenn ich ghome auf einem separaten Raspberry laufen habe ohne apache und direkte weiterleitung von port 443 auf den von ghome läuft alles wunderbar, aber ich würde das gerne hinter meinem apache laufen lassen...

Sorry, bin in den Angelegenheiten noch recht frisch hinter den Ohren und freue mich über jeglichen Input, der förderlich ist, solche Probleme auch mal selber gelöst zu bekommen...

Merci im Voraus :-)

Jan

Hi,
du musst ja im Reverse Proxy nicht auf FHEM verweisen, sondern auf GHome. In der Config von GHome gibst du ja den User für FHEM und den entsprechenden Port IN FHEM an. Das hat nix mit dem Reverse Proxy zu tun.
Unter welchem Port läuft denn dein GHome?
Imom sehe ich nur Anbindungen an FHEM bzw. entsprechende Zugriffe von außen auf deine FHEM-Installation per PW geschützt. Die Weiterleitung an GHome ist da ja noch gar nicht drin... oder?

Bis denn
SouzA
Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

SouzA

Zitat von: gvzdus am 04 Dezember 2018, 21:49:11
Moin, ich bin z.Zt. einigermaßen aktiv z.Zt. am Code.

Ein Bug:
In handleControlSetTargetTemperature wird die humidity (sinnlos) abgefragt. Da MAX-Thermostate das nicht haben, fällt ghome-fhem da auf die Nase. Kann man einfach löschen.

Hi,
wenn du von MAX-Thermostaten ausgehst vielleicht. Meine haben (noch) das Reading humidity.
Nachdem Dominik es fertig gebracht hatte Thermometer inkl. humidity in Google abzubilden, habe ich mich dennoch dazu entschlossen, die Readings in den Thermostaten zu belassen. Aus dem einfachen Grund, dass man nicht Unmengen an Devices in Google hat.
Je nach Installation sind das echt viel. Und wenn man dann doch nochmal 6 Thermometer sparen kann, warum nicht?

Also für mich ist das nicht sinnlos. Und ich denke, dass es noch andere Hersteller gibt, wo humidity ebenfalls vorhanden ist.

Bis denn
SouzA
Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

gvzdus

Häh? Vielleicht habe ich mich unklar ausgedrückt:

In der Routine, um die Temperatur zu setzen, wird die Humidity abgefragt.
Und dann gibt es zwei Möglichkeiten:
a) Das Gerät unterstützt es, dann wird der Wert weggeworfen.
b) Das Gerät unterstützt es nicht, dann knallt eine Exception im Code, und die Temperatur wird nicht gesetzt.

Ich denke, da gibt es schon ein "Richtig" versus "Falsch".