Files
lgtv/.claude/handoffs/2026-06-06-070435-google-home-tv-integration.md
T
2026-06-06 07:08:49 -04:00

187 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 `<project_id>.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.