From 111198bb126958d443b4b35a4e220da3627c7be9 Mon Sep 17 00:00:00 2001 From: Mortdecai Date: Sat, 6 Jun 2026 07:08:49 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20handoff=20+=20decisions=20=E2=80=94=20G?= =?UTF-8?q?oogle=20Home=20TV=20integration=20live=20end-to-end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- ...06-06-070435-google-home-tv-integration.md | 186 ++++++++++++++++++ DECISIONS.md | 10 + 2 files changed, 196 insertions(+) create mode 100644 .claude/handoffs/2026-06-06-070435-google-home-tv-integration.md diff --git a/.claude/handoffs/2026-06-06-070435-google-home-tv-integration.md b/.claude/handoffs/2026-06-06-070435-google-home-tv-integration.md new file mode 100644 index 0000000..0cceb57 --- /dev/null +++ b/.claude/handoffs/2026-06-06-070435-google-home-tv-integration.md @@ -0,0 +1,186 @@ +# Handoff: LG TV → Home Assistant → Google Home (working end-to-end) + +## Session Metadata +- Created: 2026-06-06 07:04:35 +- Project: /home/claude/bin/lgtv +- Branch: master +- Session duration: ~long (multi-hour, spanning the bridge consolidation + the full Google Home linking saga) + +### Recent Commits (for context) + - ddfb768 chore: project-id-named icon copy (seth-freiberg.png) for Google Home upload + - d07f334 feat: 144x144 transparent PNG app icon for Google Home action + - 205bc15 docs: session handoff — consolidation + fixes complete and verified + - 66b0f51 docs: record OFF-path gotchas (CWD-relative key path, freshly-woken retry) + - 8f2bd2b fix: power_off works under systemd — absolute key path + freshly-woken retry + +## Handoff Chain + +- **Continues from**: [2026-06-01-consolidate-and-fix.md](./2026-06-01-consolidate-and-fix.md) + - Previous title: LG TV Bridge — consolidated, fixed, deployed (2026-06-01) +- **Supersedes**: None + +## Current State Summary + +DONE and verified. The LG TV is controllable from **Google Home** (account +`slingshooter08@gmail.com`) via voice/app. Chain: Google Home → Google smart-home +cloud → HA `google_assistant` integration (VM HA, 192.168.0.146) → MQTT broker +(192.168.0.154) → `lgtv-mqtt.service` bridge on steel141 → WoL / WebOS power_off → +TV. Confirmed live: a Google "turn on" produced `Received command: ON` on the bridge +and GCP action logs show `syncLog status: OK` + `executionLog isSuccess`. The only +remaining work is **security cleanup** of credentials that passed through the chat. + +## Codebase Understanding + +## Architecture Overview + +- **Bridge** (`lgtv_mqtt.py` + `lgtv.sh`) runs ONLY on steel141 as systemd + `lgtv-mqtt.service` (User=seth). Single instance. pve173's old copy retired + 2026-06-01. See prior handoff for the bridge internals. +- **HA google_assistant** is the *manual* (free, non-Nabu-Casa) Cloud-to-Cloud + integration. Config lives in `/config/configuration.yaml` on the VM HA, with + `/config/SERVICE_ACCOUNT.json` for HomeGraph report_state. +- HA is publicly reachable at `https://hass.sethpc.xyz` (Caddy CT → 192.168.0.146:8123), + valid LE cert, **no auth gate** on that vhost — required so Google can reach + `/auth/authorize`, `/auth/token`, `/api/google_assistant`. + +## Critical Files + +| File | Purpose | Relevance | +|------|---------|-----------| +| `/usr/local/bin/lgtv.sh` (steel141) | TV control (WoL/power_off/status) | deployed; source in repo | +| `/usr/local/bin/lgtv_mqtt.py` (steel141) | MQTT↔HA bridge | systemd `lgtv-mqtt.service` | +| `/config/configuration.yaml` (VM HA .146) | holds the `google_assistant:` block | backed up as `.bak.pre-googleassistant` | +| `/config/SERVICE_ACCOUNT.json` (VM HA .146) | HomeGraph key (project seth-freiberg) | chmod 600 | +| `assets/seth-freiberg.png` (repo) | Google action icon (must be named `.png`) | uploaded to console | + +### Key Patterns Discovered + +- VM HA `/config` access: SSH add-on on `192.168.0.146:22`, user `seth`, **passwordless + sudo to root** (seth in `wheel`). `/config` is root-owned; write via `sudo tee`. +- HA core logs: `ssh seth@.146 'bash -lc "ha core logs"'` (needs login shell for the + supervisor token). `/config/home-assistant.log` does NOT exist on this HAOS install. +- GCP read access: minted SA access tokens via a signed-JWT OAuth assertion in + Python (`cryptography` lib) → called Logging/ServiceUsage/IAP REST APIs. + +## Work Completed + +### Tasks Finished + +- [x] Deployed HA `google_assistant:` config + SERVICE_ACCOUNT.json, validated, restarted. +- [x] Generated the 144×144 transparent PNG icon (`scripts/make_icon.py`), named it + `seth-freiberg.png` (Google requires filename == project_id). +- [x] Diagnosed and fixed the entire Google linking chain (see Decisions). +- [x] Confirmed end-to-end: Google → HA → bridge → TV ON. GCP action logs OK. +- [x] Reset the debug logging that was enabled for diagnosis. + +## Files Modified + +| File | Changes | Rationale | +|------|---------|-----------| +| repo `assets/`, `scripts/make_icon.py` | added icon + generator | Google action branding | +| VM HA `/config/configuration.yaml` | appended `google_assistant:` block | the integration | +| VM HA `/config/SERVICE_ACCOUNT.json` | created | HomeGraph report_state | + +## Decisions Made + +| Decision | Options Considered | Rationale | +|----------|-------------------|-----------| +| Manual Google Assistant integration (free) | Nabu Casa ($) | already had public HTTPS via Caddy | +| Keep using existing project `seth-freiberg` | dedicated project | it worked once linking was fixed; see gotcha | +| Account-linking scopes `email`,`name` | leave blank | blank → Google wouldn't open the login page | +| HTTP basic-auth-header checkbox **UNCHECKED** | checked | HA OAuth is secretless; checked → token exchange 401 | + +## Pending Work + +## Immediate Next Steps + +1. **SECURITY: rotate/revoke credentials that were pasted into the chat transcript** — + see "Important Context". This is the only outstanding task. +2. Optional: assign the "Big TV" device to a room in Google Home for nicer voice targeting. +3. Optional: give the action a dedicated GCP project later if `seth-freiberg` (shared + with WP Mail SMTP + Gemini keys) ever causes trouble. Not needed now. + +### Blockers/Open Questions + +- [ ] None blocking. Integration is live. + +### Deferred Items + +- DHCP reservation for the TV (not needed; cached-IP probe handles it). +- Dedicated GCP project for the action (works as-is in the shared project). + +## Context for Resuming Agent + +## Important Context + +**The integration WORKS. Do not "re-fix" it.** If re-touching, preserve these exact +settings that were hard-won: +- HA config: `project_id: seth-freiberg`, `service_account: !include SERVICE_ACCOUNT.json`, + `report_state: true`, `expose_by_default: false`, only `switch.big_tv_lg_tv` exposed. +- Google console (Cloud-to-cloud → Setup): Client ID + `https://oauth-redirect.googleusercontent.com/r/seth-freiberg`, Auth URL + `https://hass.sethpc.xyz/auth/authorize`, Token URL `…/auth/token`, Fulfillment + `…/api/google_assistant`, **Scopes `email` and `name`**, **HTTP-basic-auth-header + checkbox OFF**. +- HomeGraph API enabled in project `seth-freiberg`. + +**SECURITY — rotate these (their VALUES were exposed in the chat transcript):** +1. The GCP service-account key(s) for `claude@seth-freiberg.iam` — TWO keys were + created (04:25 + 05:26 UTC). Delete unused ones, rotate the live one. The HA copy + is `/config/SERVICE_ACCOUNT.json`; redeploy a fresh key there after rotating. +2. The HA SSH add-on password for user `seth` on 192.168.0.146:22 — change it. +3. The HA long-lived access token used for API calls — revoke it in the VM HA + (profile → Security → Long-lived tokens). +4. Remove the temporary **Logs Viewer** role granted to `claude@seth-freiberg.iam` + (added only for log diagnosis). +5. Delete the local key file `seth-freiberg-4ba9cc3a2d99.json` in the repo dir + (gitignored, but remove it now that it's deployed). +6. Address the GCP console banner about **unrestricted Gemini API keys** in this project. + +## Assumptions Made + +- steel141 stays effectively always-on (it does — hosts seth's desktop session for weeks). +- The Google Home account is `slingshooter08@gmail.com`; GCP owner is `seth@sethfreiberg.com`. + +## Potential Gotchas + +- `seth-freiberg` is a **shared** GCP project (WP Mail SMTP consent screen "wp mail", + **In production**). DO NOT flip its OAuth consent screen to Testing — it would break + WP Mail SMTP. The GCP consent screen is NOT part of smart-home linking anyway. +- HA `http.ban` logs Google's `/auth/token` posts as failed auth when the token + exchange breaks; repeated failures can ban Google's IPs → check `/config/ip_bans.yaml` + and delete Google (108.177.x / google.com) entries if linking suddenly fails instantly. +- bscpylgtv key DB is CWD-relative — `lgtv.sh` passes an absolute `key_file_path` + (prior handoff). Don't regress that. + +## Environment State + +### Tools/Services Used + +- VM HA 2026.2.3 at 192.168.0.146 (HAOS); SSH add-on on :22 (user seth, sudo root). +- MQTT broker: Mosquitto CT 301 on pve241 (192.168.0.154); user `lgtv`. +- Caddy CT: `hass.sethpc.xyz` → 192.168.0.146:8123 (no auth gate, HTTP/1.1 to backend). +- GCP project `seth-freiberg` (HomeGraph + smart-home action "LG-TV"). +- External reachability test host: `ssh rosy` (68.100.191.36). + +### Active Processes + +- `lgtv-mqtt.service` on steel141 (enabled, running). +- HA `google_assistant` integration loaded on the VM HA. + +### Environment Variables + +- `HOMELAB_PASSWORD` (used for MQTT/SSH where applicable) — name only. +- `MQTT_PASSWORD` via `/etc/lgtv/lgtv.env` on steel141 (EnvironmentFile) — name only. + +## Related Resources + +- Prior handoff: `.claude/handoffs/2026-06-01-consolidate-and-fix.md` +- `DECISIONS.md` (bridge architecture decisions) +- Repo: `git.sethpc.xyz/Seth/lgtv` +- HA manual Google Assistant docs: https://www.home-assistant.io/integrations/google_assistant/ + +--- + +**Security Reminder**: Credential VALUES were intentionally omitted from this doc; +the cleanup list above names them by location only. Rotate them. diff --git a/DECISIONS.md b/DECISIONS.md index dc25c6e..2b08db2 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -37,6 +37,16 @@ Format: `YYYY-MM-DD: ` immediate OFF-after-ON can fail. Retry covers it; normal case (TV already up) succeeds first try in ~3s. Bounded under the bridge's 60s subprocess timeout. +- **2026-06-06: Google Home via the free manual `google_assistant` integration** + (not Nabu Casa). Exposed only `switch.big_tv_lg_tv`. Linked end-to-end and verified. + Three non-obvious requirements that were each a separate failure mode: + account-linking **Scopes must include `email` + `name`** (blank → no login page); + the **"HTTP basic auth header" checkbox must be OFF** (HA OAuth is secretless → + checked = `/auth/token` 401); and the Google **Test must be activated by the same + account used in the Home app** (slingshooter08). The GCP OAuth consent screen is + *not* part of smart-home linking — don't touch it (shared project runs WP Mail SMTP). + Full detail + security-cleanup list in `.claude/handoffs/2026-06-06-*.md`. + ## Deferred / Rejected - **DHCP reservation for the TV (static IP):** not done — Pi-hole doesn't run DHCP (router does), so it's Seth's action on the router. The cached-IP probe