rithvikvibhu / ghlocalapi Goto Github PK
View Code? Open in Web Editor NEW(Unofficial) Google Home local API documentation.
Home Page: https://rithvikvibhu.github.io/GHLocalApi
License: MIT License
(Unofficial) Google Home local API documentation.
Home Page: https://rithvikvibhu.github.io/GHLocalApi
License: MIT License
I was just goofing around trying out API calls that seemed plausible, and hit on this one which I assume requires a POST request.
You can very easily obtain the authorization token on Zolo Mojo audio speakers in the following way. Without any HomeGraph ))))
http://192.168.x.x:8008/setup/offer
I'm trying to check if I can make this works but I found a minor issue and a bigger one looking at the example https://rithvikvibhu.github.io/GHLocalApi/#section/Google-Home-Local-API/Example
The minor one is that isn't reported jq
as a prerequisite.
The bigger one is that I can't find any info about the content of /path/to/protos
in
./grpcurl -H 'authorization: Bearer ya29.a0Af****' \
-import-path /path/to/protos \
-proto /path/to/protos/google/internal/home/foyer/v1.proto \
googlehomefoyer-pa.googleapis.com:443 \
google.internal.home.foyer.v1.StructuresService/GetHomeGraph | jq '.home.devices[] | {deviceName, localAuthToken}'
I was lucky enought to find #39 (comment)
I don't know why the protos aren't available or mentioned elsewere (that I can found) but it was pretty hard to figure it out as I never user grpcurl
I think that the instruction should be updated. Let me know if I can work on a PR
https://rithvikvibhu.github.io/GHLocalApi/#tag/Wifi
the "connect_wifi" does not require the BSSID nor the signal_level.
The password is encrypted using:
let cleartext = "PassWord";
let publicKey = "PUBLICKEY_FROM_EUREKA_INFO";
publicKey = "-----BEGIN RSA PUBLIC KEY-----\n"+publicKey+"\n-----END RSA PUBLIC KEY-----"
const encryptedData = crypto.publicEncrypt({
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PADDING,
oaepHash: "sha256",
}, Buffer.from(cleartext));
console.log(encryptedData.toString("base64"));```
Is there any method to programmatically mute the microphones? I can appreciate the security concerns for an un-muting capability, but a mute trigger doesn't seem like a risk that a malicious actor could exploit.
From a log dump of the Blaupunkt PMR100 speaker I have found references to a number of endpoints:
This is a device that also has support for Bluetooth and an aux cable, so I assume some of them are to do with this.
I also found the three endpoints already covered by #24.
It now returns a different JSON:
{"bssid":"bssid","build_version":"130671","cast_build_revision":"1.34.130671","closed_caption":{},"connected":true,"ethernet_connected":false,"has_update":false,"hotspot_bssid":"hotspot_bssid","ip_address":"x.x.x.x","locale":"es","location":{"country_code":"ES","latitude":0.0,"longitude":0.0},"mac_address":"mac_address","name":"name","noise_level":-95,"opt_in":{"crash":true,"opencast":false,"stats":true},"public_key":"key","release_track":"preview-joining-stable-channel","setup_state":60,"setup_stats":{"historically_succeeded":true,"num_check_connectivity":0,"num_connect_wifi":0,"num_connected_wifi_not_saved":0,"num_initial_eureka_info":0,"num_obtain_ip":0},"signal_level":-53,"ssdp_udn":"ssdp_udn","ssid":"ssid","time_format":2,"timezone":"Europe/Madrid","tos_accepted":true,"uma_client_id":"uma_client_id","uptime":72490.36,"version":9,"wpa_configured":true,"wpa_id":0,"wpa_state":10}
I'm not sure what exactly triggers this; currently I'm playing music from Spotify and I allowed the Android Home app to sleep, and this seems to trigger on wake each time. Not sure if Spotify is necessary or related in that regard. Also, the phone I'm using does not currently have its account linked to the Home.
Headers
Content-Type:application/json
Body
{
"play_ready_message":false,
"user_id":"?????????????????????"
}
"user_id" is a 21 digit decimal number, I'm not sure if it's something I should post publicly, so I won't. Anyway, here's the HTTP response to the above POST:
HTTP/1.1 200 OK
Access-Control-Allow-Headers: Content-Type
Cache-Control: no-cache
Access-Control-Allow-Origin: https://www.google.com
Content-Length: 108
Content-Type: application/json
{"can_enroll":true,"enrollment_state":0,"error":"NOT_LINKED","error_code":0,"ready":false,"retryable":false}
Anyway, if you set "play_ready_message"
to true
, Assistant gives the following (verbal) response:
Hi, I'm your Google Assistant. I'm here to help. To learn a few things you can do, continue in the Google Home app.
And the response:
{"can_enroll":true,"enrollment_state":0,"error_code":0,"ready":true}
Using + Parameters
and + Attributes
Found this endpoint on this webpage about sniffing traffic on a Chromecast. It works on the Home, too. On that page it's documented as "scan for available wifi" but the result I get from the request only shows one AP, the one the device is currently connected to (there are others in range). I'm not sure what to make of this.
I think everything else on that page is either already documented or doesn't work on Homes.
Hi, @rithvikvibhu. Thanks for doing such an amazing job at documenting these endpoints!
I was wondering if the broadcast feature with Google Home is a private, local network API similar to what you've documented. I'd like to be able to tap into that for a hobby project on my own network. I'm hoping I can trigger a broadcast via an internal API.
Thanks!
JT
It looks like google have changed the api as I'm getting 403 Forbidden for anything other than /setup/eureka_info and that now return a public_key
Does anyone here know the endpoint that the Google Home App calls when you broadcast from your phone? I've tried listening on the app traffic through Charles but have not been able to find any API calls.
Hi,
Thanks for this super useful repo !
I found additional parameters for https://rithvikvibhu.github.io/GHLocalApi/#connectivity-connect-disconnect-bluetooth-device-post : if you use {mac_address:"X:Y:Z", profile:2, connect:true}
, then it will define the default Bluetooth device for the Google Home.
The {connect:true/false}
only will just connect/disconnect from the default device defined before.
Hi. Does anything in particular need to be done for gpsoauth to be able to successfully return a master token? I keep getting this error against a 2FA enabled account.
from gpsoauth import perform_master_login, perform_oauth
res = perform_master_login('<mygmail', 'mygmailpwrd', 'myandroidid')
print (res)
[] Getting master token...
{'Error': 'BadAuthentication'}
[!] Could not get master token.
[] Master token: None
@SoulEater45 (I think) sent a message on Twitter, but I can't reply there, probably their privacy settings.
...getting information from the homegraph api, where you used the tool grpcurl. Is there a reason you didn't implement that also in python
This is possible, but I just wanted to get it working as soon as possible and gpgcurl just made debugging very easy. Now that the request and the proto file are known to work, it should be easy to use it and generate a regular python (or any other lang) sdk with gRPC.
https://grpc.io/docs/languages/python/quickstart/
I'm currently not free to build this, but if someone does it, please post it here. I'll be happy to link to their guide/sdk.
Found in this Chromecast support thread. Sorry, I have zero idea what should be POST
ed to it or what it's actually for beyond what can be guessed from the name. Attempting a GET
results in Error 405: Method Not Allowed
, but an empty or invalid POST
just results in 404 Not Found
. Perhaps it's neither GET
nor POST
?
EDIT: Based on this page which I do not understand at all as a lay user, it seems to have something to do with sending crash logs to Google? And perhaps it's triggered by POST
ing your UUID to that endpoint? From what I can tell, end users are not supposed to know their UUIDs, so I'm not sure how you'd find that info, assuming I'm even remotely in the ballpark of what this is all about. Quoting from that page in case it dies:
d.getAllResponseHeaders=function(){return this.ea&&this.Ty()?this.ea.getAllResponseHeaders():""};d.gH=function(){return r(this.Nh)?this.Nh:String(this.Nh)};d.pg=function(a){return a+" ["+this.vJ+" "+this.lp+" "+this.Sa()+"]"};var Bf=function(a,b,c){this.source=a;this.type=b;this.message=c};var Cf=x("mr.DongleUtils"),Df=function(a){return"https://crash.corp.google.com/samples?stbtiq="+a},Ef=function(a,b,c){var e=new tf;e.dO("text");e.Mu(3E5);Xc(e,"complete",function(a){a=a.target;var e,f;a.ie()?(e="ok",f=Df(b)):(e="error",f="Unable to retrieve "+a.ws()+", error = "+a.gH());c(e,f);a.Ya()});e.send("http://"+a+":8008/setup/send_log_report","POST",JSON.stringify({uuid:b}),{"Content-Type":"application/json"});return Df(b)},Ff=null,Gf=function(a){if(!r(a))return Promise.resolve();if(Ff&&Ff.ip==
In the alarms and timers section you have
For alarms: status: 1 for set up and 2 for currently ringing.
For alarms: status: 1 for set up and 3 for currently ringing.
I assume that at least one of these is supposed to be timers?
Gets a token which can presumably be used to get offers online. Not used anywhere locally.
Any hunch or evidence of what the offer token provided by /setup/offer
is actually used for? I'm doing some security research around this undocumented Google Home API and that screams red flag. I'd really like to know what this token can be used for.
Great work by the way. Your efforts in documenting this API are amazing. Really appreciated 😸.
Migrated from this gist comment https://gist.github.com/rithvikvibhu/952f83ea656c6782fbd0f1645059055d#gistcomment-3586276
I am requested to log in (using a browser) first. When I copy & paste the URL to a browser window, I can provide my credentials, but then I am stuck on a "One moment please..." page which does not reload. Does anybody else have this kind of problem?
Not sure what you mean @cicero200272. Which URL did you copy? This script doesn't need any browser or a website to visit at all.
name, locale, timezone can be changed by:
curl -X POST -H "Content-Type: application/json" -d '{"name": "myChromecast","settings":{"timezone":"Europe\/Madrid","time_format":2,"locale":"es"},"opt_in":{"stats":false}}' http://10.10.0.10:8008/setup/set_eureka_info
how to get device list that connect Google home (light, door, camera etc)
In the file ghapi.apib it says:
the base url for these endpoints is:
http://<google-home-ip>:8080
But I believe that 8080
should be 8008
.
I have a Google Home Mini in which I'm doing some testing, and I found out that it doesn't match the format specified at GHLocalApi device_info.capabilities
. The values I'm getting are:
{
'aogh_supported': True,
'assistant_supported': True,
'audio_hdr_supported': False,
'audio_surround_mode_supported': False,
'ble_supported': True,
'bluetooth_audio_sink_supported': True,
'bluetooth_audio_source_supported': True,
'bluetooth_supported': True,
'cloudcast_supported': True,
'content_filters_supported': True,
'disable_google_dns_supported': True,
'display_supported': False,
'fdr_supported': False,
'hdmi_prefer_50hz_supported': False,
'hdmi_prefer_high_fps_supported': False,
'hotspot_supported': True,
'https_setup_supported': True,
'input_management_supported': True,
'keep_hotspot_until_connected_supported': True,
'multi_user_supported': True,
'multichannel_group_supported': True,
'multizone_supported': True,
'night_mode_supported': True,
'night_mode_supported_v2': True,
'opencast_supported': False,
'preview_channel_supported': True,
'reboot_supported': True,
'remote_ducking_supported': True,
'renaming_supported': True,
'setup_supported': True,
'sleep_mode_supported': True,
'stats_supported': True,
'system_sound_effects_supported': False,
'ui_flipping_supported': True,
'user_eq_supported': True,
'wifi_auto_save_supported': True,
'wifi_supported': True,
}
Currently, this repo uses Travis CI to generate the website from aglio.
Later, I realized that GitHub has a neat integration with Apiary.
Also, it has better formatting, works with the same API Blueprint files, and supports the latest apib specs.
What do you think?
Hi @rithvikvibhu,
Your work on this has been excellent and very insightful. In my attempts to understand how to connect and use the chromecast/ google home API I created a docker image to install prereqs and work through your examples. The repo may be obtained here: https://github.com/advanced-data-machines/chromeblast. Per your excellent work, I am able to successfully obtain the Master token then use this to get the Access Token, then (if the device is registered) use the Access Token to get the Local-Auth-Token (required by all of the POST actions).
Even with the Local-Auth-Token set as the value for "cast-local-authentication-token" I remain unable to issue successful queries to any rest methods that require the "cast-local-authorization-token" in the header? I suspect I am missing something obvious but not sure what else to try. Any help would be greatly appreciated.
After I run this command line script for get local auth token:
grpcurl -H "authorization: Bearer ya29.**" -import-path /user/google/ -proto /user/google/internal/home/foyer/v1.proto googlehomefoyer-pa.googleapis.com:443 google.internal.home.foyer.v1.StructuresService/GetHomeGraph | jq ".home.devices[] | {deviceName, localAuthToken}"
The script output is an error because, if I run the script without jq | etc. I get an huge list but there aren't deviceName and localAuthToken.
How can I get localAuthToken by this script and then using to make request with
curl -H "cast-local-authorization-token: LOCAL_AUTH_TOKEN" --verbose --insecure https://192.168.0.18:8443/setup/bluetooth/status
Thanks
Ubuntu 20.04.2 LTS. Value returned by getmac() is rejected:
$ python ./get_tokens.py
Traceback (most recent call last):
File "./get_tokens.py", line 70, in <module>
device_id = _get_android_id()
File "./get_tokens.py", line 49, in _get_android_id
raise OSError("a valid MAC could not be determined."
OSError: a valid MAC could not be determined. Provide an android_id (and be sure to provide the same one on future runs).
Returned value is 113320225457236.
/setup/get_app_device_id
this call gets the certificate which is then used to talk to the device on port 8009
i.e. GET /setup/eureka_info?options=detail¶ms=audio
Response on my end is {"audio":{"digital":false}}
Seems like somehow ¶ms=
has become ¶ms=
, because that's a paragraph marker ¶
: ¶
I'm new to nodejs, so I might ask a stupid question, but I'm getting an error while building the site.
Ubuntu Server 20.04 LTS
nodejs v10.19.0
npm 6.14.4
root@server1:/home/server1/GHLocalApi# npm run build
[email protected] build /home/server1/GHLocalApi
redoc-cli bundle --ssr --title 'Google Home Local API' --output dist/index.htm >l GoogleHome.openapi3.jsonsh: 1: redoc-cli: not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh
npm ERR! errno ENOENT
npm ERR! [email protected] build:redoc-cli bundle --ssr --title 'Google Home Lo >cal API' --output dist/index.html GoogleHome.openapi3.json
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional log >ging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to in >stall?npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-08-04T16_45_21_305Z-debug.log
https://github.com/rithvikvibhu/GHLocalApi/blob/master/all.apib#L34
The GET parameter is described as param
. Should be params
. I almost gave up until I noticed that the Postman Collection had it listed as params
.
Hello,
By testing the request from the cmd:
curl --header "Content-Type: application/json" --request POST --data "{"params": "now"}' http://192.168.1.52:8008/setup/reboot
Google Home does not react.
Yet the request:
curl -s http://192.168.1.52:8008/setup/eureka_info
Works well:/
Can you help me? Thank you very much.
PS: With windows and I am French
Sample Request
POST /setup/test_internet_download_speed
Content-Type: application/json
{
"url": "https://storage.googleapis.com/reliability-speedtest/random.txt"
}
Sample Response
HTTP/1.1 200
Access-Control-Allow-Headers: Content-Type
Content-Type: application/json
{
"bytes_received": 31457280,
"response_code": 200,
"time_for_data_fetch": 9554,
"time_for_http_response": 130
}
This is used by the Chromecast backdrop (probably very old version of it), and it tests the internet speed, if not obvious by the endpoint url.
This is not an issue but a reference for the ones who would like to set the volume and would search for it here.
It's possible to do it using the Chromecast protocol, for example: thibauts/node-castv2-client#72
I assume it takes a POST request of an SSID to connect to, or something similar.
It could be that things are coming more official ... at least to include local devices as controllable devices ...
https://developers.google.com/actions/smarthome/concepts/local
Trying to post to /setup/assistant/alarms/delete but I keep getting
{
"error": "JSON with ids required!"
}
Has the JSON body format changed? I'm trying with:
{
"ids":"alarm\/xxxxxxxxxxxxx"
}
Escaping the / has no effect on the error message though.
Found in this forum post.
This seems to be for managing multiple devices, like when you have Google Homes all through the house and want them all to play the same music so you can hear it wherever you go. I only have one Home and no Chromecasts currently, so unfortunately, I really have no way of testing this.
The poster in the above thread gives the following info on the two endpoints:
/setup/multizone/disband_group - POSTed and needs json with uuid of group to disband
/setup/multizone/join_group - - POSTed and needs json wit data to create group
EDIT: Not from that thread but seemed logical, so I tried it and there is also:
POST /setup/multizone/leave_group
grpcurl -H 'authorization: Lorenzo aas_et.***' -import-path /Go/google/ -proto /Go/google/internal/home/foyer/v1.proto googlehomefoyer-pa.googleapis.com:443 google.internal.home.foyer.v1.StructuresService/GetHomeGraph | jq '.home.devices[] | {deviceName, localAuthToken}'
When I run this command it returns to me:
"{localAuthToken}' and {deviceName}" are not recognized as external or internal command.
I've already installed jq.
Thank you for answers.
This library (https://github.com/horihiro/esp8266-google-home-notifier) permits you to play custom mp3s to your Google home local device. I think it would be great to add this feature also in this local API!
Running: curl -vvv -H "Content-Type: application/json" http://192.168.xx.xx:8008/setup/scan_results
responds in a 403, not sure if I'm missing something here?
* Trying 192.168.xx.xx...
* TCP_NODELAY set
* Connected to home.hub (192.168.xx.xx) port 8008 (#0)
> GET /setup/scan_results HTTP/1.1
> Host: home.hub:8008
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: application/json
>
< HTTP/1.1 403 Forbidden
< Content-Length:0
<
* Connection #0 to host 192.168.xx.xx left intact
I'm new to this and was trying your get_tokens.py to get the tokens to access the setup/reboot route to force my chromecast for "foreground ota" because its stuck at a 1.42 firmware.
I filled in my google accountdata (mail & pw) in the script but it always says "could not get access token".
Maybe I missed a few steps?
Would be nice if you can add these in the documentation.
Thanks a lot.
I have been struggling for a few days to extract the local auth token.
(Following https://rithvikvibhu.github.io/GHLocalApi/#section/Google-Home-Local-API/Authentication)
I am able to get Master and Access tokens
However, when I attempt to get the local auth token, I get the Device name, but an empty token.
I suspect either an issue with the protocol files, or there is no local auth token assigned.
(The device in question is refusing to come out of 'configuration', using the "google home" app. So, maybe - perhaps - the issue is indeed at the server end, that for some reason, the google account isn't recording a local auth token ?)
Any hints or tips most welcome !
Hello,
I'm looking to turn off automatic sleep mode on the Nest Hubs. When I Cast a web page on a Nest Hub with Jeedom, my Nest Hubs put the time on top after 10 minutes. it didn't do me before. It is with an update from Google that this watch appeared.
and recently, with Fuchsia OS, sleep mode is 30 seconds. So I really want to deactivate this automatic standby which is just annoying!
Do any of you know the option in the GHlocal API?
Thank you
Nest Hub on latest Fuchsia build:
Nmap scan report for 10.10.10.12
Host is up (0.0071s latency).
Not shown: 65527 closed ports
PORT STATE SERVICE
22/tcp filtered ssh
8008/tcp open http
8009/tcp open ajp13
8012/tcp open unknown
8443/tcp filtered https-alt
9000/tcp open cslistener
10001/tcp open scp-config
10101/tcp open ezmeeting-2
MAC Address: 1C:F2:9A:33:0E:9C (Google)
after downgrading to stable build:
Nmap scan report for 10.10.10.12
Host is up (0.0074s latency).
Not shown: 65527 closed ports
PORT STATE SERVICE
22/tcp filtered ssh
8008/tcp open http
8009/tcp open ajp13
8012/tcp open unknown
8443/tcp open https-alt
9000/tcp open cslistener
10001/tcp open scp-config
10101/tcp open ezmeeting-2
MAC Address: 1C:F2:9A:33:0E:9C (Google)
For both master
and gh-pages
branches
Hi,
First of all, thank you @rithvikvibhu for your work.
I would like to know if you or anyone else has made any progress regarding the "enc_passwd" parameter.
We have built a solution around the chromecast and to speed up the configuration, my company is willing to reward 750€ the person who can successfully connect a chromecast to a WPA2 network using the /connect_wifi endpoint or any workaround. There will also be an additionnal reward if you can connect the chromecast to a Google account and change the screen saver settings (hide weather, hide time, change background screen through Google photos)
You can contact us at [email protected]
Regards,
Hah, this is what happens when you hit the "Open source licenses" button in Device settings in the Home app.
The response is apparently a gzipped web page, and is just the open source licenses, which are read by the Home app directly off the Home device. That's fun.
EDIT: Mildly interesting/dangerous: looking at the page's source, it pulls some Javascript off of gc.kis.v2.scr.kaspersky-labs.com over HTTP. Compromise DNS, inject your own Javascript into the Google Home app, ????, profit?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.