Files
lgtv/.claude/handoffs/2026-06-06-075038-projector-google-home-and-dhcp-fix.md
T
Mortdecai 66c341b4e9 docs: handoff — projector added to Google Home + DHCP-reservation durable fix
Continues from the Google Home TV integration handoff. Diagnosed that projector
PJLink control was broken (HA host .156 stale; projector drifted to .149), fixed
HA + exposed media_player.mitsubishi_projector to Google Home, and pinned the IP
via an Omada DHCP reservation. New helper pushed to Seth/network-tools.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:52:31 -04:00

11 KiB

Handoff: Mitsubishi Projector → Google Home + DHCP-reservation durable fix

Session Metadata

  • Created: 2026-06-06 07:50:38
  • Project: /home/claude/bin/lgtv
  • Branch: master
  • Session duration: ~1 hour (continuation of the Google Home work)

Recent Commits (for context)

  • 111198b docs: handoff + decisions — Google Home TV integration live end-to-end
  • 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)

(Note: this session's only committed artifact landed in the new network-tools repo, not lgtv — see Files Modified. The lgtv repo itself was not changed.)

Handoff Chain

Review the previous handoff for full context before filling this one (HA google_assistant setup, the hard-won console settings, and the outstanding TV-side security cleanup).

Current State Summary

DONE and verified. Seth asked to add the Mitsubishi projector (already in HA via PJLink) to the existing Google Home integration. While doing so I checked whether the projector control actually worked — it did not: HA's PJLink media_player was hard-coded to host: 192.168.0.156, but the projector had DHCP-drifted to 192.168.0.149 (.156 is now a different device). The entity had been silently unavailable. Fixed the IP in HA, exposed the projector to Google Home, then applied the durable fix: an Omada DHCP reservation pinning the projector MAC to .149 so it can't drift again. Wrote a reusable Omada reservation helper, committed + pushed it to a new private Gitea repo network-tools. Updated network_inventory.md and ROUTER.md. The only user action left is a one-time Google "sync my devices".

Codebase Understanding

Architecture Overview

  • Projector control path: Google Home → Google smart-home cloud → HA google_assistant (VM HA 192.168.0.146) → HA media_player.mitsubishi_projector (PJLink platform, YAML) → TCP PJLink :4352 on the projector (192.168.0.149).
  • PJLink is auth-required (greeting PJLINK 1 <salt>); HA authenticates with password: MITSUBISHI (MD5 digest of salt+password). Verified directly: a power query returned %1POWR=0 (standby) with no ERRA, i.e. auth OK.
  • Projector keeps its NIC + PJLink alive in standby (answered PJLink while POWR=0). So turn-ON via PJLink works — unlike the LG TV, no Wake-on-LAN needed. (This corrects a wrong caveat I gave mid-session.)
  • DHCP is served by the router (ER707-M2, 192.168.0.1), managed by the Omada controller (CT 104 on pve197, https://192.168.0.10:8043). Reservations are per-client "Use Fixed IP" bindings, settable only via the internal /api/v2 API (the partner OpenAPI doesn't expose them).

Critical Files

File Purpose Relevance
/config/configuration.yaml (VM HA .146) media_player: pjlink host: 192.168.0.149 + google_assistant.entity_config backed up to /config/.backup/configuration.yaml.1780745129
~/bin/network-tools/omada_reserve_ip.py Omada DHCP reservation helper (explore/reserve/show) committed + pushed to Gitea
~/bin/network-tools/.omada.env Omada creds for the helper (gitignored, chmod 600) NOT in git
~/bin/network_inventory.md corrected projector .156→.149, Epson XP-7100 marked offline NOT under git (plain file in ~/bin)
~/bin/ROUTER.md new "DHCP Reservations" section (helper ref + netId) NOT under git

Key Patterns Discovered

  • Omada internal API for reservations: login POST /{omadacId}/api/v2/login (admin / Omada pw) → Csrf-Token header + session cookie; then PATCH /{omadacId}/api/v2/sites/{siteId}/clients/{MAC} with {"clientMac": MAC, "ipSetting": {"useFixedAddr": true, "netId": <LAN id>, "ip": <ip>}}. Field is useFixedAddr (not useFixedIp). Site 69c1cacc701bf5355840cde0, Default-LAN netId 69c1cacd701bf5355840cdeb (subnet 192.168.0.1/24).
  • HA YAML platform entities (pjlink media_player) don't appear in .storage/core.entity_registry; entity_id is the slugified name:media_player.mitsubishi_projector.
  • Verify HA entity state without a long-lived token: from the SSH add-on shell, curl -H "Authorization: Bearer $SUPERVISOR_TOKEN" http://supervisor/core/api/states/<entity>.

Work Completed

Tasks Finished

  • Diagnosed projector control as broken (stale IP .156; actual .149, MAC 00:20:4a:a5:d0:b6).
  • Verified PJLink works at .149 (greeting, MD5 auth, %1POWR=0).
  • Fixed HA host: .156 → .149; ha core check passed; restarted; entity now available (off, supported_features 2440 = on/off/source/mute).
  • Exposed projector to Google Home: added media_player.mitsubishi_projector (name "Projector", alias "Mitsubishi Projector", no room per Seth) to google_assistant.entity_config.
  • Durable fix: Omada DHCP reservation MAC→.149, verified persisted (useFixedAddr:true, serverType gateway).
  • Wrote omada_reserve_ip.py, externalized creds to gitignored .omada.env, committed; created private Gitea repo network-tools and pushed.
  • Updated network_inventory.md + ROUTER.md.

Files Modified

File Changes Rationale
VM HA /config/configuration.yaml pjlink host .156→.149; added projector to entity_config; comment updated fix control + expose to Google
~/bin/network-tools/omada_reserve_ip.py (new) Omada reservation helper reusable, first use = projector
~/bin/network-tools/.gitignore (new) ignore .omada.env, __pycache__/, .backup/ keep secrets/noise out of git
~/bin/network_inventory.md projector .156→.149 reserved; Epson XP-7100 → offline; reservation note accuracy
~/bin/ROUTER.md new "DHCP Reservations" section discoverability

Decisions Made

Decision Options Considered Rationale
Reserve .149 (current IP) revert to documented .156 .156 now held by another device; .149 is the projector's live IP — no conflict
Fix at DHCP layer (reservation) just edit HA IP again editing HA only resets the drift clock; reservation pins MAC→IP at the router
New private Gitea repo for network-tools leave local-only / move script to lgtv Seth chose "create private Gitea repo"; only 2 clean files pushed
Creds in gitignored .omada.env hardcode in script detect-secrets pre-commit hook blocked hardcoded creds; env file is the right fix (no --no-verify)
Projector exposed with no Google room Living Room / Media Room Seth chose "No room"

Pending Work

Immediate Next Steps

  1. Seth says "Hey Google, sync my devices" then tests "turn on/off the projector". The auto requestSync 400s on the free integration (known), but the voice SYNC path works (same path the TV uses). Until synced, the projector won't appear in the app.
  2. (Carried over from prior handoff, still outstanding) TV-side security cleanup — rotate the GCP SA key(s), HA SSH add-on password, HA long-lived token; remove temp Logs Viewer role; delete seth-freiberg-4ba9cc3a2d99.json. See previous handoff §SECURITY.

Blockers/Open Questions

  • None blocking. Projector is controllable from HA now; Google needs the one sync.

Deferred Items

  • Adding network-tools' other (untracked, credential-bearing) scripts to the new repo — left untracked deliberately; clean them before tracking.
  • DHCP reservation for the LG TV (TV uses a cached-IP probe instead; not needed).

Context for Resuming Agent

Important Context

  • Do not "re-fix" the Google Home TV integration — see prior handoff; the console settings are hard-won (scopes email+name, HTTP-basic-auth checkbox OFF, project_id seth-freiberg). This session only ADDED the projector entity alongside the TV switch.
  • The projector lives at 192.168.0.149, DHCP-reserved. If it ever seems unreachable, confirm the reservation with ~/bin/network-tools/omada_reserve_ip.py show 00:20:4a:a5:d0:b6 and that HA's host: still matches.
  • requestSync 400 is expected on this free integration and is NOT a regression — report_state to the same HomeGraph endpoint succeeds, proving SA auth is healthy.

Assumptions Made

  • The Epson XP-7100 printer (MAC 38:9d:92:b4:64:f1) was the stale .149 holder; it's currently offline (no ARP entry, no Omada client record) and had no reservation, so reserving .149 for the projector creates no active conflict — it'll get a new dynamic IP next boot.
  • steel141 / VM HA / Omada controller all stay effectively always-on.

Potential Gotchas

  • PROCESS MISS this session: I edited network_inventory.md and ROUTER.md WITHOUT backing them up first (violated the pre-edit backup rule). They're not under git, so no pre-edit copy exists. Edits were small/corrective. Back these up before future edits.
  • Credential sprawl: the Omada admin password now exists in ROUTER.md (plaintext, already flagged H4 in GITEA_SECURITY_REPORT.md) AND ~/bin/network-tools/.omada.env. If rotating, update both.
  • network-tools repo has ~15 untracked scripts that likely contain switch/router creds — do NOT git add . blindly; they were intentionally left untracked.
  • HA http.ban can ban Google IPs if /auth/token posts fail repeatedly — check /config/ip_bans.yaml if Google linking ever breaks instantly (from prior handoff).

Environment State

Tools/Services Used

  • VM HA 2026.2.x at 192.168.0.146 (HAOS); SSH add-on :22 (user seth, passwordless sudo).
  • Omada controller CT 104 on pve197, https://192.168.0.10:8043 (internal /api/v2 + OpenAPI).
  • Router ER707-M2 (192.168.0.1) = DHCP server (serverMac 40-ED-00-DA-2D-BA).
  • Projector: Mitsubishi PJLink at 192.168.0.149:4352 (MAC 00:20:4a:a5:d0:b6), on switch port 1/0/3.
  • New repo: https://git.sethpc.xyz/Seth/network-tools (private).

Active Processes

  • HA google_assistant integration loaded; projector + TV exposed.
  • lgtv-mqtt.service on steel141 (TV bridge; unchanged this session).

Environment Variables

  • OMADA_HOST, OMADA_CID, OMADA_SITE, OMADA_USER, OMADA_PASS — consumed by omada_reserve_ip.py from gitignored .omada.env (names only; values not here).
  • SUPERVISOR_TOKEN — available in the HA SSH add-on shell for core API queries.
  • Prior handoff: .claude/handoffs/2026-06-06-070435-google-home-tv-integration.md
  • ~/bin/ROUTER.md (Omada/DHCP), ~/bin/network_inventory.md (IP/MAC table)
  • ~/bin/network-tools/omada_reserve_ip.py + Gitea Seth/network-tools
  • HA Google Assistant docs: https://www.home-assistant.io/integrations/google_assistant/

Security Reminder: Credential VALUES are omitted here; names/locations only. Omada password lives in ROUTER.md and .omada.env — rotate both if needed.