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)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user