Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
12 KiB
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)
93f6c33feat: simplify Google switch to on-only (state push restored)6607367docs: Google Home button confirmed working (switch tile); SA key regenerated5c8f2d7chore: gitignore service-account key filesb540d5edocs: expose POS briefing as a switch tile (scenes don't tile in Google Home)2691dc4docs: 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_briefing → button.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 pinsCallbackAPIVersion.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 viassh 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/..../configis root-owned (write viasudo 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
posbriefingon 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 ~1–2 min (gemma4:26b summarization + yfinance). The button returns
immediately;
posbriefing/statustracksprinting→ok. 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/grafanareturn 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()(MAC50:57:9c:eb:0f:07); current IP was 192.168.0.184 but expect it to change. - A manually admin-triggered
google_assistant.request_synclogs a harmless 404 — it sends the unlinked owner-context id2c22820…; HA's automatic reporting uses the linkedf948247…and succeeds. Do NOT chase that 404; it is not a real failure. - gemma4 under
format:jsonreturns reasoning objects ({"thought": ...}), which is why Phase-1 selection usesqwen2.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
pytestcrashes on collection from the repo root unlesstests/pytest.inipins rootdir (deadCREATE_PROJECT.md/GITEA_API.mdsymlinks → inaccessible /root/bin → PermissionError). Runpython3 -m pytest tests/test_printer_discovery.py.- The bridge runs
pos_briefing.pyfrom 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(orsudo install) + restart after editingpos_briefing_mqtt.py. - google_assistant config reload needs a full
ha core restart(no targeted reload). - Editing
/config/*on HA requiressudo tee(root-owned); always back up to/config/.backup/.
Environment State
Tools/Services Used
pos-briefing-mqtt.serviceon 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_assistantintegration (VM HA) — loaded; state push working.
Environment Variables
MQTT_PASSWORDvia/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
Related Resources
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.