-
-
Save interfect/5f68381d55658d334e2bc4619d796476 to your computer and use it in GitHub Desktop.
| #!/usr/bin/env bash | |
| # castanet.sh: Script to connect a chromecast to a WiFi network. | |
| # | |
| # Allows you to put your Chromecast on WiFi and do Chromecast initial setup | |
| # without using the Google Home app at all, just using a normal Linux computer. | |
| # | |
| # You do need your Chromecast to be on Ethernet, or (untested) to join its setup WiFi | |
| # network with your PC, and you also need to find out its IP yourself with e.g. | |
| # Wireshark. | |
| set -e | |
| if [[ -z "${CHROMECAST_IP}" || -z "${WIFI_SSID}" || -z "${WIFI_PASSWORD}" ]] ; then | |
| echo 1>&2 "Usage: CHROMECAST_IP=\"XXX\" WIFI_SSID=\"XXX\" WIFI_PASSWORD=\"XXX\" ${0}" | |
| exit 1 | |
| fi | |
| if ! which curl >/dev/null 2>/dev/null ; then | |
| echo 1>&2 "Install curl to use this script!" | |
| exit 1 | |
| fi | |
| if ! which jq >/dev/null 2>/dev/null ; then | |
| echo 1>&2 "Install jq to use this script!" | |
| exit 1 | |
| fi | |
| if ! which nodejs >/dev/null 2>/dev/null ; then | |
| echo 1>&2 "Install nodejs to use this script!" | |
| exit 1 | |
| fi | |
| # Set VERBOSITY=-vvv to see Curl traffic happening | |
| if [[ -z "${VERBOSITY}" ]] ; then | |
| VERBOSITY=-s | |
| fi | |
| echo "Connecting ${CHROMECAST_IP} to ${WIFI_SSID} with password ${WIFI_PASSWORD}" | |
| # Get the device's public key | |
| INFO_JSON="$(curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 https://${CHROMECAST_IP}:8443/setup/eureka_info)" | |
| CHROMECAST_PUBKEY="$(echo "${INFO_JSON}" | jq -r '.public_key')" | |
| # Scan for and find the network we want to get the encryption parameters | |
| curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 -X POST https://${CHROMECAST_IP}:8443/setup/scan_wifi | |
| sleep 20 | |
| WIFI_JSON="$(curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 https://${CHROMECAST_IP}:8443/setup/scan_results)" | |
| WIFI_NETWORK_JSON="$(echo "${WIFI_JSON}" | jq ".[] | select(.ssid == \"${WIFI_SSID}\")")" | |
| WIFI_AUTH_NUMBER="$(echo "${WIFI_NETWORK_JSON}" | jq -r '.wpa_auth')" | |
| WIFI_CIPHER_NUMBER="$(echo "${WIFI_NETWORK_JSON}" | jq -r '.wpa_cipher')" | |
| echo "${WIFI_NETWORK_JSON}" | |
| # Encrypt the password to the device | |
| # Encryption kernel by @thorleifjaocbsen | |
| # See <https://github.com/rithvikvibhu/GHLocalApi/issues/68#issue-766300901> | |
| ENCRYPTED_KEY="$(nodejs <<EOF | |
| let crypto = require('crypto'); | |
| let cleartext = "${WIFI_PASSWORD}"; | |
| let publicKey = "${CHROMECAST_PUBKEY}"; | |
| publicKey = "-----BEGIN RSA PUBLIC KEY-----\n"+publicKey+"\n-----END RSA PUBLIC KEY-----" | |
| const encryptedData = crypto.publicEncrypt({ | |
| key: publicKey, | |
| padding: crypto.constants.RSA_PKCS1_PADDING, | |
| // This was in the original thorleifjaocbsen code but seems nonsensical/unneeded and upsest some Nodes | |
| //oaepHash: "sha256", | |
| }, Buffer.from(cleartext)); | |
| console.log(encryptedData.toString("base64")); | |
| EOF | |
| )" | |
| # Generate the command to connect. | |
| CONNECT_COMMAND="{\"ssid\": \"${WIFI_SSID}\", \"wpa_auth\": ${WIFI_AUTH_NUMBER}, \"wpa_cipher\": ${WIFI_CIPHER_NUMBER}, \"enc_passwd\": \"${ENCRYPTED_KEY}\"}" | |
| # And the command to save the connection. | |
| # Include keep_hotspot_until_connected in case we are on the Chromecast's setup hotspot and not Ethernet. | |
| # See <https://github.com/rithvikvibhu/GHLocalApi/issues/88#issuecomment-860538447> | |
| SAVE_COMMAND="{\"keep_hotspot_until_connected\": true}" | |
| # Send the commands | |
| curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 -H "content-type: application/json" -d "${CONNECT_COMMAND}" https://${CHROMECAST_IP}:8443/setup/connect_wifi | |
| # Hope this one gets there before it can actually disconnect if we're using the setup hotspot? | |
| # Otherwise we have to use Ethernet or jump over to the target network and find the device again. | |
| # See <http://blog.brokennetwork.ca/2019/05/setting-up-google-chromecast-without.html?m=1> for a script that knows how to swap wifi networks but needs to be ported to use the current API. | |
| curl ${VERBOSITY} --insecure --tlsv1.2 --tls-max 1.2 -H "content-type: application/json" -d "${SAVE_COMMAND}" https://${CHROMECAST_IP}:8443/setup/save_wifi | |
| # To see it working, if you aren't kicked off the hotspot (or if you set the new CHROMECAST_IP in your shell): | |
| # | |
| # curl --insecure --tlsv1.2 --tls-max 1.2 https://${CHROMECAST_IP}:8443/setup/eureka_info | jq . | |
| # | |
| # To list known networks: | |
| # | |
| # curl --insecure --tlsv1.2 --tls-max 1.2 https://${CHROMECAST_IP}:8443/setup/configured_networks | jq . | |
| # | |
| # To forget a newtwork: | |
| # | |
| # curl --insecure --tlsv1.2 --tls-max 1.2 -H "content-type: application/json" -d '{"wpa_id": 0}' https://${CHROMECAST_IP}:8443/setup/forget_wifi | |
| # | |
| # If you leave Ethernet plugged in, the Chromecast will ARP for its WiFi IP on | |
| # Etherenet and drop the WiFi connection! Unplug the Chromecast, and plug it in | |
| # again with no Ethernet, to get it to keep the WiFi connection up! | |
| # | |
| # Set Name and opt out of things: | |
| # | |
| # curl --insecure --tlsv1.2 --tls-max 1.2 -H "content-type: application/json" -d '{"name": "NovakCast5000", "opt_in": {"crash": false, "stats": false, "opencast": false}}' https://${CHROMECAST_IP}:8443/setup/set_eureka_info | |
May be someone will be intersing with GUI https://github.com/magicse/homecastanet/
Thanks @interfect and good info @circuits-of-time. I'll add some of what I learned to my approach:
https://github.com/rbrisita/Chromecast_H2G2-42
It's an all-in-one approach using native tools. I will update as I face edge cases along the way but the beta versions work seamlessly. Feel free to create issues.
Yay! Thanks a lot! After a not too long lasting crash course in how to use a shellscript and get this all sorted I managed to get my beloved Chromsecast 2nd Generation connected again and it's safe to go to the landfill. stoopid Google...works totally fine in my '2011 based environment'
Thanks a lot!
Made my day!
I don't have anything substantive to add, but since my Github account has been around for a while and has a lot of activity I figured I should post a comment to add another anecdote to this thread in case others (like me!) were a little unsure of whether it's too good to be true: I have a Chromecast (gen 3) that had been working for months until I switched ISPs and the chromecast refused to let me set it up again after a factory reset (basically an exact duplicate of this). This script worked perfectly for me and my Chromecast is back to working normally again :)
Is there a way to rename the Chromecast with the script??? is there anything in the API for renaming???
Hi, I'm having some trouble getting this to work with my "Chromecast with Google TV" and a Linux PC. So I connected the PC with the Chromecast hotspot and provided the correct SSID and password to the script but it kept complaining about the public key format, so I've debugged it a little bit, and figured that the response I get from
https://CHROMECAST_IP:8443/setup/eureka_infois always:As you can see, it's missing the public key. Did this script stopped working or did I do something wrong?
I've also tried this python version, but as it calls the same URL, it didn't work either...