i8beef / HomeAutio.Mqtt.GoogleHome

MIT License
215 stars 29 forks source link

I configured everything, deployed Docker... and now what? #16

Closed GAZ082 closed 6 years ago

GAZ082 commented 6 years ago

Followed all the steps in the wiki.

How do i get this rolling?

i8beef commented 6 years ago

I made some setup instructions for registering your app with Google Actions: https://github.com/i8beef/HomeAutio.Mqtt.GoogleHome/wiki/Google-Action-Setup

Note the prerequisites at the top. You have to have setup your app to be publicly accessible behind an SSL certificate before registering with Google. For me, that meant:

  1. Getting a Dynamic DNS address that pointed at my router's public IP address, and kept itself updated. A lot of router firmwares have built in support for this now, but its router specific how to get it setup.
  2. Forward port 443 (specifically) through to your host.
  3. Setup an nginx proxy for the application so you can provide SSL transport. Note to be careful here, as if you are proxying other stuff through that, you can expose everything in the virtual host at port 443 accidentally here. I like to put a global "deny all" on this virtual host, and then selectively allow things to sub folders as necessary (i.e., something like this)
server {
  listen 443 ssl;
  ssl on;
  ssl_certificate /REDACTED/fullchain.pem;
  ssl_certificate_key /REDACTED/privkey.pem;
  ssl_verify_depth 3;
  ssl_protocols TLSv1.1 TLSv1.2;
  ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

  location / {
    allow 192.168.1.0/24;
    deny all;

    try_files $uri @proxy;
  }

  location /google/home {
    allow all;

    proxy_pass http://0.0.0.0:5000;
    proxy_set_header X-Real-IP $remote_addr;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
  }

  location @proxy {
    ....
  }
}

That allows me to make sure I'm not exposing ANYTHING publicly except the SPECIFIC things I want to (i.e., this Google Home app). I left in my SSL config there so you can see where I add that in the proxy, but redacted the certificate names / location. LetsEncrypt isn't exactly fun to get up and running, but it's your best bet for getting those certs, as they have to be REAL certs, not self signed, to satisfy Google.

GAZ082 commented 6 years ago

When trying to add the app to my google home, when the auth redirection happens i get a 502.

I checked nginx's log and i get:

2018/08/16 20:19:50 [error] 22844#22844: *858 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.1, server: mydomain.me, request: "GET /googlehome/connect/authorize?response_type=code&client_id=SOMEID-hkmn4vrkon6633dtiusi1e4icg81lton.apps.googleusercontent.com&redirect_uri=https://oauth-redirect.googleusercontent.com/r/mygoogleactionapp&scope=api+offline_access&state=*SNIP*-aHR0cHM6Ly9vYXV0aC1yZWRpcmVjdC5nb29nbGV1c2VyY29udGVudC5jb20vci9hc2lzdGVudGUtZGU4YjQqEGdhejA4MkBnbWFpbC5jb20yE2FzaXN0ZW50ZS1kZThiNF9kZXY HTTP/2.0", upstream: "http://0.0.0.0:55000/googlehome/connect/authorize?response_type=code&client_id=SOMEID-hkmn4vrkon6633dtiusi1e4icg81lton.apps.googleusercontent.com&redirect_uri=https://oauth-redirect.googleusercontent.com/r/mygoogleactionapp&scope=api+offline_access&state=*SNIP*-aHR0cHM6Ly9vYXV0aC1yZWRpcmVjdC5nb29nbGV1c2VyY29udGVudC5jb20vci9hc2lzdGVudGUtZGU4YjQqEGdhejA4MkBnbWFpbC5jb20yE2FzaXN0ZW50ZS1kZThiNF9kZXY", host: "www.mydomain.me"

192.168.1.1 is my router. It forwards from 55000 to 5000. 55000 and 5000 are open in 192.168.1.2 which is where nginx and docker is running.

Also, in your app's log, i get (in a different time frame):

2018-08-16 20:42:53.120 -03:00 [Information] Connection id ""0HLG3Q7TPM819"" bad request data: ""Invalid request line: '\x16\x03\x01\x00\xC2\x01\x00\x00\xBE\x03\x03N\x9FD\xF4\xBC1\xA0o\xBB[D\x99\x1D\xB1\xD8\xC9\xFD\x88^\xEA.\x1C\x03\xCB\x83qI{\xE9\xD6$\xC8\x00\x00\x1C**\xCC\xA9\xCC\xA8\xC0+\xC0/\xC0,\xC00\xC0\x13\xC0\x14\x00\x9C\x00\x9D\x00/\x005\x00\x0A'""
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Invalid request line: '\x16\x03\x01\x00\xC2\x01\x00\x00\xBE\x03\x03N\x9FD\xF4\xBC1\xA0o\xBB[D\x99\x1D\xB1\xD8\xC9\xFD\x88^\xEA.\x1C\x03\xCB\x83qI{\xE9\xD6$\xC8\x00\x00\x1C**\xCC\xA9\xCC\xA8\xC0+\xC0/\xC0,\xC00\xC0\x13\xC0\x14\x00\x9C\x00\x9D\x00/\x005\x00\x0A'
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.RejectRequestLine(Byte* requestLine, Int32 length)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.GetUnknownMethod(Byte* data, Int32 length, Int32& methodLength)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.ParseRequestLine(TRequestHandler handler, Byte* data, Int32 length)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.ParseRequestLine(TRequestHandler handler, ReadOnlySequence`1& buffer, SequencePosition& consumed, SequencePosition& examined)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpParser<TRequestHandler>.ParseRequestLine(TRequestHandler handler, ReadOnlySequence`1& buffer, SequencePosition& consumed, SequencePosition& examined)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TakeStartLine(ReadOnlySequence`1 buffer, SequencePosition& consumed, SequencePosition& examined)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.ParseRequest(ReadOnlySequence`1 buffer, SequencePosition& consumed, SequencePosition& examined)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
2018-08-16 20:42:53.120 -03:00 [Information] Connection id ""0HLG3Q7TPM818"" bad request data: ""Invalid request line: '\x16\x03\x01\x00\xC2\x01\x00\x00\xBE\x03\x03X\xE6\x83\xB5\xFC\xD7\x14\x1F\xB5\x9F\xCF\x9FF\x8E5\xDE\x8A\xAB\xE8\x0F\xFA\xD6\x7F\x051\xF6B|}b=\x0C\x00\x00\x1C\xDA\xDA\xCC\xA9\xCC\xA8\xC0+\xC0/\xC0,\xC00\xC0\x13\xC0\x14\x00\x9C\x00\x9D\x00/\x005\x00\x0A'""
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Invalid request line: '\x16\x03\x01\x00\xC2\x01\x00\x00\xBE\x03\x03X\xE6\x83\xB5\xFC\xD7\x14\x1F\xB5\x9F\xCF\x9FF\x8E5\xDE\x8A\xAB\xE8\x0F\xFA\xD6\x7F\x051\xF6B|}b=\x0C\x00\x00\x1C\xDA\xDA\xCC\xA9\xCC\xA8\xC0+\xC0/\xC0,\xC00\xC0\x13\xC0\x14\x00\x9C\x00\x9D\x00/\x005\x00\x0A'
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.RejectRequestLine(Byte* requestLine, Int32 length)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.GetUnknownMethod(Byte* data, Int32 length, Int32& methodLength)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.ParseRequestLine(TRequestHandler handler, Byte* data, Int32 length)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.ParseRequestLine(TRequestHandler handler, ReadOnlySequence`1& buffer, SequencePosition& consumed, SequencePosition& examined)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser`1.Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpParser<TRequestHandler>.ParseRequestLine(TRequestHandler handler, ReadOnlySequence`1& buffer, SequencePosition& consumed, SequencePosition& examined)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TakeStartLine(ReadOnlySequence`1 buffer, SequencePosition& consumed, SequencePosition& examined)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.ParseRequest(ReadOnlySequence`1 buffer, SequencePosition& consumed, SequencePosition& examined)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
2018-08-16 20:43:05.212 -03:00 [Information] Request starting HTTP/1.1 GET http://192.168.1.2:5000/  
2018-08-16 20:43:08.179 -03:00 [Information] Route matched with "{action = \"Index\", controller = \"Home\"}". Executing action "IdentityServer4.Quickstart.UI.HomeController.Index (HomeAutio.Mqtt.GoogleHome)"
2018-08-16 20:43:08.500 -03:00 [Information] Executing action method "IdentityServer4.Quickstart.UI.HomeController.Index (HomeAutio.Mqtt.GoogleHome)" - Validation state: Valid
2018-08-16 20:43:08.528 -03:00 [Information] Executed action method "IdentityServer4.Quickstart.UI.HomeController.Index (HomeAutio.Mqtt.GoogleHome)", returned result "Microsoft.AspNetCore.Mvc.NotFoundResult" in 6.9666ms.
2018-08-16 20:43:08.672 -03:00 [Information] Executing HttpStatusCodeResult, setting HTTP status code 404
2018-08-16 20:43:08.730 -03:00 [Information] Executed action "IdentityServer4.Quickstart.UI.HomeController.Index (HomeAutio.Mqtt.GoogleHome)" in 514.7101ms
2018-08-16 20:43:08.852 -03:00 [Information] Request finished in 3663.5832ms 404 
i8beef commented 6 years ago

One warning, Im not sure you can use a port other than 443 with Google...

So you are forwarding port 55000 from your router to NGinx on 192.168.1.2 at 55000, which then is configured to proxy http://192.168.1.2/googlehome on port 5000 correct? One thing to try is changing the proxy_pass to the actual IP address, not 0.0.0.0... thats actually how I have mine running right now.

Also, did you start your Docker instance with the environment variable -e ASPNETCORE_PATHBASE="/googlehome"? Given that it sounds like you're proxying a specific path, you will need to let the app know what that path is via this DOCKER environment variable.

GAZ082 commented 6 years ago

The nginx was proxying to port 55000, my bad. Fixed it with 5000 and also the complete IP of the local machine. Thanks!

GAZ082 commented 6 years ago

Now I login to the app via Google Home but when I authorize everything and the embebbed webpage goes back to the Home App an Android popup fires off with a "Could not update settings, please check connection." message (or something like that, i translated from spanish) and adds nothing to the home app. Perhaps it need another port open?

The log returns no error:

S1kZThiNF9kZXY"]) - Validation state: Valid
2018-08-16 23:16:18.583 -03:00 [Information] Executed action method "IdentityServer4.Quickstart.UI.AccountController.Login (HomeAutio.Mqtt.GoogleHome)", returned result "Microsoft.AspNetCore.Mvc.ViewResult" in 7.631ms.
2018-08-16 23:16:18.585 -03:00 [Information] Executing ViewResult, running view "Login".
2018-08-16 23:16:18.595 -03:00 [Information] Executed ViewResult - view "Login" executed in 9.7248ms.
2018-08-16 23:16:18.604 -03:00 [Information] Executed action "IdentityServer4.Quickstart.UI.AccountController.Login (HomeAutio.Mqtt.GoogleHome)" in 37.8858ms
2018-08-16 23:16:18.607 -03:00 [Information] Request finished in 46.8157ms 200 text/html; charset=utf-8

A screencast I made: https://www.youtube.com/watch?v=q1x4tF7SQCY

i8beef commented 6 years ago

Ah, ok, so notice the broken images and such on the login? I'm willing to bet that when you created the docker image you did not include that environment variable I mentioned. If you looked at the source for that page, you'd see it looking for those images (and the form action target) pointing at stuff based off / rather than /googlehome. Try creating the docker container again with that -e ASPNETCORE_PATHBASE="/googlehome".

Just a tip, I tend to create a script with my docker command because I find myself making these mistakes and having to rerun the stupid thing 20 times with every new image :-P

Below is the script I run to upgrade my containers when I put out new versions. If I just need to modify the container and recreate, I just run the docker stop and docker rm containername parts manually and then run this after my modifications. Obviously if you wanted to use this you'd have to change the REPOSITORY variable to the right tag instead of latest

#!/bin/bash

REPOSITORY="i8beef/homeautio.mqtt.googlehome:latest"
IMAGENAME="homeautio.mqtt.googlehome"

docker pull $REPOSITORY

LATEST=`docker inspect --format "{{.Id}}" $REPOSITORY`
RUNNING=`docker inspect --format "{{.Image}}" $IMAGENAME`

if [ "$RUNNING" == "$LATEST" ];then
    echo "Up to date"
else
    echo "Updating $IMAGENAME"
    docker stop $IMAGENAME
    docker rm $IMAGENAME
    docker run --restart=always --name $IMAGENAME --user=1000 -dit -p 5000:5000 -e ASPNETCORE_PATHBASE="/google/home" -v /pathToMy/appsettings.Production.json:/app/appsettings.Production.json:ro -v /pathToMy/config:/app/config -v /pathToMy/logs:/app/logs -e TZ=America/New_York $REPOSITORY
fi
GAZ082 commented 6 years ago

Thanks for the script, very handy! This is my current systemd command, as you can see, i do use the ASPNETCORE_PATHBASE param.

[Service]
Type=oneshot
ExecStart=/bin/bash -c "docker run --restart=always --name homeautio.mqtt.googlehome --user=1001 -dit -p 5000:5000 -v /home/gabriel/googlehome/appsettings.Production.json:/app/appsettings.Production.json:ro -v /home/gabriel/googlehome/config:/app/config -v /home/gabriel/googlehome/logs:/app/logs -e ASPNETCORE_PATHBASE="/googlehome" -e TZ=America/Buenos_Aires i8beef/homeautio.mqtt.googlehome:1.0.0.47-arm32"

and the NGINX chunk:

location /googlehome{ <--- also tried with /googlehome/
    allow all;

    proxy_pass http://192.168.1.2:5000;
    proxy_set_header X-Real-IP $remote_addr;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
}
i8beef commented 6 years ago

Hmmm, if you go to https://yourdomain/googlehome/account/login and view source, do the links at the top in the head section all start with "/googlehome" instead of "/", like this?

<link rel="icon" type="image/x-icon" href="/googlehome/favicon.ico" />
<link rel="shortcut icon" type="image/x-icon" href="/googlehome/favicon.ico" />
<link rel="stylesheet" href="/googlehome/lib/bootstrap/css/bootstrap.css" />
<link rel="stylesheet" href="/googlehome/css/site.css" />
i8beef commented 6 years ago

Also note that if you just added that environment variable, you actually have to blow away the container with docker rm and create it again. Those are CREATION time parameters, not run time.

You can check with docker inspect homeautio.mqtt.googlehome --format='{{.Config.Env}}' and looking at what the container thinks it has for that environment variable.

GAZ082 commented 6 years ago

To the HTML, yes, it references googlehome as the root and fires off a lot of "file not found" in the chrome debugger as consequence.

To the second part:

sudo docker inspect homeautio.mqtt.googlehome --format='{{.Config.Env}}'
[ASPNETCORE_PATHBASE=/googlehome TZ=America/Buenos_Aires PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ASPNETCORE_URLS=http://+:5000 DOTNET_RUNNING_IN_CONTAINER=true ASPNETCORE_VERSION=2.1.2 ASPNETCORE_ENVIRONMENT=Production]

Looks like the env parameter you are refering to is properly configured. Don't know if you can find something wrong with the rest.

i8beef commented 6 years ago

What happens when you actually go to https://yoururl/googlehome/lib/bootstrap/css/bootstrap.css`? Does it load that file?

GAZ082 commented 6 years ago

404 not found.

i8beef commented 6 years ago

That's weird. Ill have to do some research. That environment variable is read by the code in order to handle the situation where the site is proxied like this at a URL other than /. When it builds links and templates inside of a Docker instance, it IS running at / in the container so thats how it builds any URLs it needs to reference internally... you have to TELL it that its actually being proxied at a different path, which is what that does.

Whats surprising is that you can't get this static files at that location... That sounds more like a proxy setup issue or something....

i8beef commented 6 years ago

But you CAN hit https://yourhost/googlehome/connect/authorize? Or what URL did you put into your account linking on Google for that?

And are there other nginx configurations here, or is it only doing the forwarding for this?

GAZ082 commented 6 years ago

If i hit by with my browser i get invalid request. But that's the address the google home app hits when asking for auth, right? Because the auth part is working.

image

i8beef commented 6 years ago

Sorry, try https://yoururl/googlehome/account/login

GAZ082 commented 6 years ago

image

I put my login credentials then jumps to https://yoururl/googlehome/ with 404. If i put invalid credentials the login screen tells.

i8beef commented 6 years ago

And are there other nginx configurations here, or is it only doing the forwarding for this?

Can you run a tail -f against the log file, and hit these URLs?

  1. https://yoururl/googlehome/account/login
  2. https://yoururl/googlehome/lib/bootstrap/css/bootstrap.css
  3. https://yoururl/googlehome/icon.png

You SHOULD see the requests hit in those logs. If you DON'T then I think the issue has to be in the nginx setup, and we'll need to look at your config there.

i8beef commented 6 years ago

Below is my simplified nginx config. I don't think you need the / location here, but I'm including it for something to try. You definitely don't want the /googlehome/ with the extra slash, as it has a different meaning for nginx.

server {
  listen 443 ssl;
  ssl on;
  ssl_certificate /REDACTED/fullchain.pem;
  ssl_certificate_key /REDACTED/privkey.pem;
  ssl_verify_depth 3;
  ssl_protocols TLSv1.1 TLSv1.2;
  ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

  location / {
    allow 192.168.1.0/24;
    deny all;

    try_files $uri;
  }

  location /google/home {
    allow all;

    proxy_pass http://192.168.1.2:5000;
    proxy_set_header X-Real-IP $remote_addr;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
  }
}
GAZ082 commented 6 years ago

Those files hit to my local server, not the Docker'ed. IE:

2018/08/18 17:12:58 [error] 12343#12343: *1094 open() "/var/www/KRAKEN/public/mywebsite/googlehome/lib/bootstrap/css/bootstrap.css" failed (2: No such file or directory), client: 192.168.1.1, server: mywebsite, request: "GET /googlehome/lib/bootstrap/css/bootstrap.css HTTP/2.0", host: "mywebsite"

The client show is my router's IP, dont know if that's ok.

GAZ082 commented 6 years ago

I believe the nginx config is ok, i put it here redacted for a quick look:

#server {
#    listen 80;
#   server_name mywebsite.me www.mywebsite.me;
    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
 #   return 301 https://$server_name$request_uri; #para renovar certificado creo que tenes que sacar el texto 301 nada mas.

#}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name mywebsite.me www.mywebsite.me;
    root /var/www/KRAKEN/public/mywebsite.me;
    error_log /var/www/KRAKEN/public/mywebsite.me/nginx.error.log;
    access_log /var/www/KRAKEN/public/mywebsite.me/nginx.access.log;
    ssl_certificate /xxxx/mywebsite.me/fullchain.pem;
    ssl_certificate_key /xxxx/mywebsite.me/privkey.pem;
    ssl_session_timeout 1d;
#    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;   
    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /etc/nginx/dhparam.pem;
    # modern configuration. tweak to your needs.
    ssl_protocols TLSv1.2;
    ssl_ciphers 'xxxxxxxxxxxxxxxxxxx';
    ssl_prefer_server_ciphers on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;
    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /xxxx/mywebsite.me/fullchain.pem;
    resolver 8.8.8.8 8.8.4.4;
    location /zweihander/
    {
        auth_basic "Restricted Content";
            auth_basic_user_file /etc/nginx/.htpasswd;
    }   
    location / {
    return 301 https://mywebsite.me/;

#       rewrite ^ http://xx.xxxx.com;
    }
    location /blog {
    index index.html index.htm;
}
    location /laverna {
    index index.html index.htm;
}
    location /zwei {
    index index.html index.htm;
}
    location /mqtt {
    index index.html index.htm;
}
    location /barathrum {
            error_page 404 /barathrum/templates/error.html;
    }
    location /barathrum/static {
        root /var/www/KRAKEN/public/barathrum/static/;
    }
    location /im {
        include uwsgi_params;
        uwsgi_pass unix:///run/uwsgi/im.sock;
    }

    location /im/static {
        alias /var/www/KRAKEN/public/im/static/;
    }

 location /pola {
  return 301 https://mywebsite.me:xxx/ui;
}
location /googlehome{
    allow all;

    proxy_pass http://192.168.1.2:5000;
    proxy_set_header X-Real-IP $remote_addr;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
}

location ~*  \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
    }

    location /barathrum/multimedia {
    autoindex on;
    }
    location /files {
    autoindex on;
    }
}
i8beef commented 6 years ago

Ok, so there is something wrong with your nginx config then. Those should all be passing through to the Docker instance. Try commenting out the location ~* \.(jpg|...)$ one. I think that is hijacking the requests that should go to your proxy here.

Then see if your account/login page looks a little prettier.

GAZ082 commented 6 years ago

big grin it solved the issue of serving the files used in the login form but did not the fact i cannot register the app in my google home app.

GAZ082 commented 6 years ago

Couldn't update the setting. Check your connection. That would be the error in english. Looks like it's something not too uncommon with Google Home.

i8beef commented 6 years ago

Ok, cool, one issue down.

So in your log file do you see the sync attempt? It'll be a requesy to /googlehome/smarthome

Another place to look is in the Google Actions console. If you go into the "Simulator" menu item, there should be a "View logs" link on the right hand side.

GAZ082 commented 6 years ago

There is nothing in the GA Console's log.

The request to googlehome/smarthome should be logged where? NGINX? your app?

In your app there is no reference to "smarthome" (i grepped it) and on NGINX, there are no new error entries and none access entry referring to "smarthome".

i8beef commented 6 years ago

Ok, so then Google wasn't passing the auth token stage then. The next step would be a call to that endpoint to get the initial device SYNC stuff. So what IS in your log for this app after attempting to connect through the Google Home app?

Also, side note, I just pushed up a new version that will have two changes that would be relevant to you:

  1. googleDevices.json not being present shouldn't throw an error anymore, it'll just start empty. Your empty one should be fine too, its essentially the same thing, but since you hit that I changed it so others don't hit it.
  2. I moved appsettings.Production.json to the config directory. This will let you drop one of the volume mounts on the Docker command (one less thing for people to worry about setting up). So next time you upgrade, just remember to move that file, and change your Docker command to remove that volume mount for the individual file.
GAZ082 commented 6 years ago

This is the log after a re-initialization (old version) and trying to register the app in Google Home.

Will be deleted in a day: https://pastebin.com/raw/t9QF5csc

i8beef commented 6 years ago
2018-08-18 19:47:18.661 -03:00 [Error] Client secret validation failed for client: "66330018166-hkmn4vrkon6633dtiusi1e4icg81lton.apps.googleusercontent.com".

By chance in your config file do you have a client with the clientId? And does the client secret there match whats in the Google Actions console for account linking?

Another thought, you DO have a tokens.json file in your config directory after this right? Just making sure the tokens file is getting persisted correctly.

GAZ082 commented 6 years ago

Okey, i had wrong the secret. Looks like now it throws the SYNC thingie:

http://termbin.com/vp9b

GAZ082 commented 6 years ago

OH JESUS! IT'S SYNCED NOW!

GAZ082 commented 6 years ago

Okey, so, i believe this is the final step. I have configured a lamp for testing, this is my googleDevices.json file:

{
  "google/home/switch": {
    "id": "pola/living/lampara",
    "type": "action.devices.types.SWITCH",
    "willReportState": false,
    "roomHint": "Some Room",
    "name": {
      "defaultNames": [],
      "name": "lampara",
      "nicknames": []
    },
    "deviceInfo": {
      "manufacturer": "Some Company",
      "model": "Some Model",
      "hwVersion": "1.0",
      "swVersion": "1.0"
    },
    "traits": [
      {
        "trait": "action.devices.traits.OnOff",
        "commands": {
          "action.devices.commands.OnOff": {
            "on": "pola/living/lampara/cmnd/POWER"
          }
        },
        "state": {
          "on": {
            "topic": "pola/living/lampara/estado",
            "googleType": "bool",
            "valueMap": [
              {
                "mqtt": "on",
                "type": "value",
                "google": true
              },
              {
                "mqtt": "off",
                "type": "value",
                "google": false
              }
            ]
          }
        }
      }
    ]
  }

Now i say "ok google, turn on lamara", does nothing for 3-4 seconds and the girl says "oh, i could not connect to the device My app name and the log is:

2018-08-18 20:28:27.144 -03:00 [Information] Request starting HTTP/1.1 POST http://192.168.1.2:5000/googlehome/smarthome application/json;charset=UTF-8 229
2018-08-18 20:28:29.886 -03:00 [Information] Route matched with "{action = \"Post\", controller = \"GoogleHome\"}". Executing action "HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post (HomeAutio.Mqtt.GoogleHome)"
2018-08-18 20:28:32.021 -03:00 [Information] Request starting HTTP/1.1 GET http://192.168.1.2:5000/googlehome/.well-known/openid-configuration  
2018-08-18 20:28:32.307 -03:00 [Information] Invoking IdentityServer endpoint: "IdentityServer4.Endpoints.DiscoveryEndpoint" for "/.well-known/openid-configuration"
2018-08-18 20:28:33.433 -03:00 [Information] Request finished in 1362.9896ms 200 application/json; charset=UTF-8
2018-08-18 20:28:33.783 -03:00 [Information] Request starting HTTP/1.1 GET http://192.168.1.2:5000/googlehome/.well-known/openid-configuration/jwks  
2018-08-18 20:28:33.788 -03:00 [Information] Invoking IdentityServer endpoint: "IdentityServer4.Endpoints.DiscoveryKeyEndpoint" for "/.well-known/openid-configuration/jwks"
2018-08-18 20:28:33.985 -03:00 [Information] Request finished in 201.9882ms 200 application/json; charset=UTF-8
2018-08-18 20:28:34.509 -03:00 [Information] Successfully validated the token.
2018-08-18 20:28:34.691 -03:00 [Information] Authorization was successful.
2018-08-18 20:28:35.949 -03:00 [Information] Executing action method "HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post (HomeAutio.Mqtt.GoogleHome)" with arguments (["HomeAutio.Mqtt.GoogleHome.Models.Request.Request"]) - Validation state: Valid
2018-08-18 20:28:36.021 -03:00 [Information] Received EXECUTE intent for commands: action.devices.commands.OnOff
2018-08-18 20:28:36.113 -03:00 [Information] Executed action method "HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post (HomeAutio.Mqtt.GoogleHome)", returned result "Microsoft.AspNetCore.Mvc.OkObjectResult" in 101.3607ms.
2018-08-18 20:28:44.519 -03:00 [Warning] Using an in-memory repository. Keys will not be persisted to storage.
2018-08-18 20:28:44.830 -03:00 [Warning] Neither user profile nor HKLM registry available. Using an ephemeral key repository. Protected data will be unavailable when application exits.
2018-08-18 20:28:45.006 -03:00 [Information] Creating key {49fb84a0-194d-47cb-bf80-64b5f22ed859} with creation date 2018-08-18 23:28:44Z, activation date 2018-08-18 23:28:44Z, and expiration date 2018-11-16 23:28:44Z.
2018-08-18 20:28:45.142 -03:00 [Warning] No XML encryptor configured. Key {49fb84a0-194d-47cb-bf80-64b5f22ed859} may be persisted to storage in unencrypted form.
2018-08-18 20:28:49.432 -03:00 [Information] Service start initiated
2018-08-18 20:28:49.462 -03:00 [Information] MQTT subscribing to the following topics: google/home/#, pola/living/lampara/estado
2018-08-18 20:28:49.534 -03:00 [Information] Started
2018-08-18 20:28:49.559 -03:00 [Information] Service started successfully
2018-08-18 20:28:50.008 -03:00 [Information] MQTT Connection established
2018-08-18 20:28:50.012 -03:00 [Information] Connected.
2018-08-18 20:28:50.059 -03:00 [Information] ManagedMqttClient
2018-08-18 20:28:50.218 -03:00 [Information] MQTT message received for topic pola/living/lampara/estado: false

BTW; dont know why its subscribin to google/home/#

i8beef commented 6 years ago

Woot! I've updated the documentation a bit as we've gone here. Ill probably use your experience here to write up a "Things that can go wrong" doc.

The google/home/# subscription is for the app itself. It actually publishes a google/home/connected message when it connects so you can monitor that and know if it goes up or down (0 on down, 2 on up). It also monitors google/home/REQUEST_SYNC which will trigger a REQUEST_SYNC from MQTT, but I haven't documented that behavior yet.

i8beef commented 6 years ago

In the googleDevices.json file, the KEY for each object should match the id:

{
  "pola/living/lampara": {
    "id": "pola/living/lampara",
i8beef commented 6 years ago

Also just a warning, I broke something on the appsettings.Production.json file in that build, Im in process of fixing it so it reads it again

GAZ082 commented 6 years ago

YAY! that was it, had to match the KEY to the ID.

Are all the fields required by Google? IE, manufacturer and such.

I'll be happy to colaborate in anything i can, so far i can test it under Pi3 which will be the platform most likely this will be run on.

BTW, can you do a "latest" version for arm32?

i8beef commented 6 years ago

latest-arm32 should be available now. But hold off on updating a little bit, because I need to figure out the arcane details of getting this to load a config file from another directory... if I can't figure that out I'll revert that, but I thought it'd be nice...

Google doesn't require everything, I just expose everything for you to supply. If you look at their docs it'll tell you some of whats optional. I supply those just for completeness, but you don't have to supply the manufacturer info for instance.

GAZ082 commented 6 years ago

Okey, so I guess this is a closed issue! I leave you the honors!

GAZ082 commented 6 years ago

BTW, when I add a new device i have to restart the Docker instance?

i8beef commented 6 years ago

To rescan the googleDevices.json, yes. You can just do a docker restart homeautio.mqtt.googlehome or whatever you called the container. Ill note that in the documentation.