Files
POS-Automation/.claude/handoffs/2026-06-11-045021-pos-google-home-button.md
T
Mortdecai 1dfe8dadc2 docs: session handoff — Google Home print button (complete)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 04:52:17 -04:00

12 KiB
Raw Blame History

Handoff: POS Briefing — Google Home on-demand print button (COMPLETE)

Session Metadata

  • Created: 2026-06-11 04:50:21
  • Project: /home/claude/bin/POS-Automation
  • Branch: master
  • Session duration: long (multi-day: 2026-06-07 build + deploy, 2026-06-10/11 verify/simplify)

Recent Commits (for context)

  • 93f6c33 feat: simplify Google switch to on-only (state push restored)
  • 6607367 docs: Google Home button confirmed working (switch tile); SA key regenerated
  • 5c8f2d7 chore: gitignore service-account key files
  • b540d5e docs: expose POS briefing as a switch tile (scenes don't tile in Google Home)
  • 2691dc4 docs: record HA deployment details + access method in DECISIONS

Handoff Chain

  • Continues from: None (fresh start)
  • Supersedes: None

Current State Summary

DONE and verified end-to-end. The POS daily briefing now prints on demand from a Google Home button (no cron). Tapping "Print Daily Briefing" in the Google Home app (account slingshooter08) → HA switch.print_daily_briefingbutton.press → MQTT → pos-briefing-mqtt.service on steel141 → pos_briefing.py → printer (resolved by MAC) → Epson TM-m30. Confirmed live: a real Google tap produced a printed receipt. State push to Google is working (HomeGraph SA key was regenerated). Nothing is in-progress; remaining items are optional polish (see Deferred).

The original report was "the automation is not firing" — root causes were (1) no cron was ever installed (a prior commit only edited SESSION.md), and (2) yfinance was missing on steel141 post-migration. Seth then redirected the whole approach to a Google Home button, which is what got built.

Codebase Understanding

Architecture Overview

Mirrors the lgtv project pattern (steel141 systemd MQTT bridge + HA MQTT discovery + the free manual google_assistant integration).

Google Home tap → google_assistant integration (VM HA 192.168.0.146, acct slingshooter08)
  → HA switch.print_daily_briefing (template switch, always-off, on-tap only)
  → button.press on button.pos_briefing_print_daily_briefing (MQTT-discovery button)
  → MQTT posbriefing/button/press on broker CT 301 (192.168.0.154)
  → pos-briefing-mqtt.service on steel141 (systemd, User=claude)
  → subprocess: /usr/bin/python3 pos_briefing.py
  → discover_printer() resolves IP by MAC 50:57:9c:eb:0f:07 → ESC/POS over TCP :9100
  → status/availability published back to MQTT

Critical Files

File Purpose Relevance
pos_briefing.py Main script: fetch FreshRSS, select+summarize, dashboard, build+print receipt Has discover_printer() (MAC-based), gemma4 summary + fast-model selection
pos_briefing_mqtt.py MQTT bridge → /usr/local/bin/pos_briefing_mqtt.py (deployed) systemd pos-briefing-mqtt.service, User=claude
pos-briefing-mqtt.service systemd unit (repo copy) EnvironmentFile=/etc/pos-briefing/pos-briefing.env
install.sh Deploys bridge+unit+env, enable Re-run to redeploy bridge changes
scripts/dryrun.py Full pipeline, print suppressed Use to test without printing/marking-read
tests/test_printer_discovery.py 5 unit tests for discovery python3 -m pytest tests/test_printer_discovery.py
tests/pytest.ini Pins pytest rootdir to tests/ Works around dead /root/bin symlinks that crash collection
docs/ha-setup.md The HA/Google deployment (as-built) Read first for the Google side
DECISIONS.md All decisions w/ rationale Read first for the why
config.json (gitignored) Live config incl. real creds Has printer_mac, ollama_model, ollama_select_model

Key Patterns Discovered

  • paho-mqtt 2.1.0 is installed for claude; bridge pins CallbackAPIVersion.VERSION1 (matches lgtv; one harmless deprecation warning at startup).
  • HA scripts/scenes expose to Google as the Scene trait, which Google Home does NOT render as a tappable tile (voice/Routine only). A switch tiles. This was the key fix — the briefing is exposed as a template switch, not a script/scene.
  • HA on VM 192.168.0.146 (HAOS 2026.2.3): access via ssh seth@192.168.0.146 (key auth), bash -lc "ha core check|restart|logs", and call core services via the supervisor token: curl -H "Authorization: Bearer $SUPERVISOR_TOKEN" http://supervisor/core/api/.... /config is root-owned (write via sudo tee); back up to /config/.backup/ first.
  • The manual google_assistant integration has a local fulfillment webhook that answers SYNC/EXECUTE without Google auth — great for diagnosing what HA reports to Google: curl -X POST http://127.0.0.1:8123/api/webhook/<local_webhook_id> -d '{"inputs":[{"intent":"action.devices.SYNC"}],"requestId":"x"}' (webhook id is in /config/.storage/google_assistant).

Work Completed

Tasks Finished

  • Diagnosed "not firing" (no cron + missing yfinance); installed yfinance on steel141.
  • Verified pipeline runs on steel141 (scripts/dryrun.py).
  • Committed the in-tree hourly-weather rewrite.
  • Summaries → gemma4:26b (prompt converged via ask_gemma4 MCP); selection stays on qwen2.5:1.5b (gemma4 broke Phase-1 JSON under format:json).
  • Printer discovery by MAC (cache + /24 sweep); 5 unit tests; wired into print_receipt.
  • MQTT bridge + systemd unit + env template + installer; broker user posbriefing on CT 301.
  • Deployed HA side on VM HA: switch + google_assistant exposure; verified via local SYNC.
  • Regenerated the HomeGraph SA key (old one was invalid); state push now works.
  • Simplified switch to on-only (turn_off no-op) after state push confirmed.
  • Confirmed end-to-end: real Google Home tap printed a receipt.

Files Modified

File Changes Rationale
pos_briefing.py discovery, gemma4 summaries, fast-model selection, hourly weather core feature work
pos_briefing_mqtt.py (new) MQTT bridge the trigger
pos-briefing-mqtt.service, install.sh, pos-briefing.env.example (new) deploy systemd install
tests/test_printer_discovery.py, tests/pytest.ini (new) tests discovery coverage
config.json/config.example.json printer_mac, printer_subnet, ollama_select_model, gemma4 model config
docs/ha-setup.md, DECISIONS.md, CONTEXT.md (new/edited) docs record the build
VM HA /config/configuration.yaml added template switch + google_assistant exposure HA side
VM HA /config/scripts.yaml print_daily_briefing script (alt trigger) HA side
VM HA /config/SERVICE_ACCOUNT.json replaced with valid key fix HomeGraph

Decisions Made

See DECISIONS.md (2026-06-07 entries) for the full list with rationale. Highlights: SWITCH-tile exposure (scenes don't tile); MAC-based printer discovery (DHCP IP churn); gemma4:26b summaries + fast selection model; on-demand MQTT trigger (no cron).

Pending Work

Immediate Next Steps

The feature is complete. No required next steps. Optional follow-ups only (see Deferred).

Blockers/Open Questions

  • None. Working end-to-end.

Deferred Items

  • Print latency ~12 min (gemma4:26b summarization + yfinance). The button returns immediately; posbriefing/status tracks printingok. Optimize later if it annoys (model keep-alive, fewer/shorter summaries, smaller model).
  • Router DHCP reservation for the printer (Seth's router action). MAC discovery makes it optional; a reservation would let us drop the /24 sweep fallback.
  • Dashboard fields zfs/reddit/grafana return None on steel141 (it's not the tank host; cannot open 'tank'). Out of scope; the receipt prints everything else fine.
  • SA key value passed through this session's transcript when Seth shared the file. It's the live key; rotate once more out-of-band later if desired (then redeploy to HA).

Context for Resuming Agent

Important Context

  • Don't reintroduce cron. Trigger is on-demand via Google Home → MQTT only.
  • Expose to Google as a SWITCH, never a script/scene — scenes don't render as tappable tiles in Google Home.
  • The printer IP is DHCP-mobile — always resolve via discover_printer() (MAC 50:57:9c:eb:0f:07); current IP was 192.168.0.184 but expect it to change.
  • A manually admin-triggered google_assistant.request_sync logs a harmless 404 — it sends the unlinked owner-context id 2c22820…; HA's automatic reporting uses the linked f948247… and succeeds. Do NOT chase that 404; it is not a real failure.
  • gemma4 under format:json returns reasoning objects ({"thought": ...}), which is why Phase-1 selection uses qwen2.5:1.5b, not gemma4. Don't point selection at gemma4.
  • lgtv project is the reference for the HA/Google/MQTT pattern; its .claude/handoffs/ (2026-06-06) documents the google_assistant linking invariants — do not "re-fix" them.

Assumptions Made

  • steel141 stays effectively always-on (hosts seth's desktop for weeks).
  • Broker CT 301 (192.168.0.154) and HA VM (192.168.0.146) stay put.
  • The TM-m30 keeps the same MAC (it will; only its DHCP IP moves).

Potential Gotchas

  • pytest crashes on collection from the repo root unless tests/pytest.ini pins rootdir (dead CREATE_PROJECT.md/GITEA_API.md symlinks → inaccessible /root/bin → PermissionError). Run python3 -m pytest tests/test_printer_discovery.py.
  • The bridge runs pos_briefing.py from the repo path /home/claude/bin/POS-Automation/; editing that file takes effect immediately. The bridge itself is the copy at /usr/local/bin/pos_briefing_mqtt.py — re-run ./install.sh (or sudo install) + restart after editing pos_briefing_mqtt.py.
  • google_assistant config reload needs a full ha core restart (no targeted reload).
  • Editing /config/* on HA requires sudo tee (root-owned); always back up to /config/.backup/.

Environment State

Tools/Services Used

  • pos-briefing-mqtt.service on steel141 (systemd, enabled+active, User=claude).
  • MQTT broker: Mosquitto CT 301 on pve241 (192.168.0.154); user posbriefing.
  • VM HA 2026.2.3 at 192.168.0.146 (HAOS); SSH add-on (user seth, key auth, sudo root).
  • steel141 Ollama (192.168.0.141:11434): gemma4:26b (summaries), qwen2.5:1.5b (selection).
  • Printer: Epson TM-m30, MAC 50:57:9c:eb:0f:07, port 9100 (DHCP IP, was .184).
  • GCP project seth-freiberg (HomeGraph; SA claude@seth-freiberg.iam, key id 8e3e812b6913…).

Active Processes

  • pos-briefing-mqtt.service (steel141) — running.
  • HA google_assistant integration (VM HA) — loaded; state push working.

Environment Variables

  • MQTT_PASSWORD via /etc/pos-briefing/pos-briefing.env (EnvironmentFile, 0600) — name only.
  • HOMELAB_PASSWORD — name only.
  • $SUPERVISOR_TOKEN (inside HA SSH add-on login shell) — used for HA core API calls.

Quick health check

sudo systemctl is-active pos-briefing-mqtt.service
sudo bash -c 'set -a; . /etc/pos-briefing/pos-briefing.env; set +a; mosquitto_sub -h "$MQTT_HOST" -p "$MQTT_PORT" -u "$MQTT_USER" -P "$MQTT_PASSWORD" -t posbriefing/status -C 1'
python3 -c "import pos_briefing as pb; print(pb.discover_printer())"   # current printer IP
  • docs/ha-setup.md — HA/Google deployment (as-built, read first for the Google side).
  • docs/superpowers/specs/2026-06-07-ha-google-home-trigger-design.md — design.
  • docs/superpowers/plans/2026-06-07-ha-google-home-trigger.md — implementation plan.
  • DECISIONS.md — all decisions with rationale.
  • ../lgtv/ + its .claude/handoffs/2026-06-06-*.md — the reference pattern + Google linking invariants.
  • Repo: git.sethpc.xyz/Seth/POS-Automation.

Security Reminder: No secret values included — credentials referenced by location/name only.