docs: session handoff — Google Home print button (complete)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
# 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_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 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
|
||||
|
||||
- [x] Diagnosed "not firing" (no cron + missing yfinance); installed yfinance on steel141.
|
||||
- [x] Verified pipeline runs on steel141 (scripts/dryrun.py).
|
||||
- [x] Committed the in-tree hourly-weather rewrite.
|
||||
- [x] Summaries → gemma4:26b (prompt converged via ask_gemma4 MCP); selection stays on
|
||||
qwen2.5:1.5b (gemma4 broke Phase-1 JSON under format:json).
|
||||
- [x] Printer discovery by MAC (cache + /24 sweep); 5 unit tests; wired into print_receipt.
|
||||
- [x] MQTT bridge + systemd unit + env template + installer; broker user `posbriefing` on CT 301.
|
||||
- [x] Deployed HA side on VM HA: switch + google_assistant exposure; verified via local SYNC.
|
||||
- [x] Regenerated the HomeGraph SA key (old one was invalid); state push now works.
|
||||
- [x] Simplified switch to on-only (turn_off no-op) after state push confirmed.
|
||||
- [x] 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/status` tracks `printing`→`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`/`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
|
||||
|
||||
```bash
|
||||
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.
|
||||
Reference in New Issue
Block a user