# 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.