docs: handoff + decisions — Google Home TV integration live end-to-end
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 `<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.
|
||||||
@@ -37,6 +37,16 @@ Format: `YYYY-MM-DD: <decision> — <why>`
|
|||||||
immediate OFF-after-ON can fail. Retry covers it; normal case (TV already up)
|
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.
|
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
|
## Deferred / Rejected
|
||||||
- **DHCP reservation for the TV (static IP):** not done — Pi-hole doesn't run
|
- **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
|
DHCP (router does), so it's Seth's action on the router. The cached-IP probe
|
||||||
|
|||||||
Reference in New Issue
Block a user