You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add OFF event for deterministic .alog linking via roastUUID
Sentinel now reads the newest .alog when Artisan sends an OFF event,
extracting roastUUID and roastbatchnr for deterministic matching
with coffee-roasting analysis. Falls back to date/time if OFF is
not configured.
- artisan_sync: add OFF to ROAST_EVENTS and ARTISAN_EVENT_MAP
- sentinel: add _link_alog() method, triggered on OFF event
- sentinel: include roast_uuid and batch_nr in saved JSON
- Update CLAUDE.md and README.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DROP's action slot is used by Hottop safety commands. COOL END is configured to send DROP instead.
222
+
DROP's action slot is used by Hottop safety commands. COOL END is configured to send DROP instead. OFF triggers sentinel to scan for the newest .alog and extract roast identifiers for deterministic log matching.
215
223
216
224
### Message formats (`artisan_sync.py`)
217
225
218
226
- Button events: `{"event": "CHARGE"}`
219
227
- Native events: `{"message": "chargeEvent"}` (mapped via `ARTISAN_EVENT_MAP`)
220
228
- Data polling: `{"command": "getData", "id": N}` (responded with dummy BT/ET data)
OFF is not a roast phase event — it signals that Artisan has saved the `.alog` file (autosave on OFF button). The sentinel uses this to link the session log to the `.alog` before pushing.
237
+
238
+
### Phase mapping (`artisan_sync.py:74-82`)
223
239
224
240
| Event | Phase |
225
241
|-------|-------|
@@ -228,14 +244,45 @@ DROP's action slot is used by Hottop safety commands. COOL END is configured to
228
244
| FCs/FCe/SCs/SCe | development |
229
245
| DROP | cooling |
230
246
247
+
## Sentinel Session — Key Methods
248
+
249
+
### `SentinelSession` instance vars (`sentinel.py:47-61`)
250
+
251
+
| Var | Type | Description |
252
+
|-----|------|-------------|
253
+
|`bean_name`| str | Bean name for the session |
254
+
|`session_id`| str |`YYYY-MM-DD_HHMM` timestamp |
255
+
|`observations`| list | Vision observation dicts |
256
+
|`roast_uuid`| str/None | From `.alog``roastUUID`, set by `_link_alog()`|
257
+
|`batch_nr`| int/None | From `.alog``roastbatchnr`, set by `_link_alog()`|
258
+
259
+
### `_link_alog()` (`sentinel.py:163-193`)
260
+
261
+
Called when the OFF event is received. Scans `ARTISAN_SAVE_DIR` (env var, default `~/coffee-roasts`) for the newest `.alog` file, parses it with `ast.literal_eval()`, and extracts `roastUUID` and `roastbatchnr`. These are saved into the sentinel JSON for deterministic matching by `coffee-roasting/sentinel_loader.py`.
262
+
263
+
### `_on_artisan_event()` (`sentinel.py:75-90`)
264
+
265
+
Handles roast events from Artisan. Key behaviors:
266
+
- Events in `CAPTURE_EVENTS` set → flag immediate capture
267
+
-`DROP` → sets `self.running = False` to end session
268
+
-`OFF` → calls `_link_alog()` to extract roast identifiers
269
+
270
+
### `_save_log()` (`sentinel.py:214-231`)
271
+
272
+
Writes session JSON including `roast_uuid` and `batch_nr` fields.
273
+
274
+
### `_push_log()` (`sentinel.py:195-212`)
275
+
276
+
Rsyncs the session log to the dev machine. Uses `SENTINEL_RSYNC_DEST` env var.
277
+
231
278
## Sentinel Capture Logic
232
279
233
280
Two triggers run simultaneously:
234
281
235
282
1.**Event-triggered** — immediate capture on CHARGE, DRY, FCs, FCe, SCs, SCe, DROP
Camera opens on Artisan connect (ON/START), before CHARGE. Capture loop starts at CHARGE. Session ends on DROP or Ctrl+C. Partial logs are saved on interrupt.
285
+
Camera opens on Artisan connect (ON/START), before CHARGE. Capture loop starts at CHARGE. Session ends on DROP or Ctrl+C. OFF (after DROP) triggers `.alog` linking but no capture. Partial logs are saved on interrupt.
239
286
240
287
## Session Log Schema
241
288
@@ -245,6 +292,8 @@ Saved to `captures/sentinel_YYYY-MM-DD_HHMM.json`:
@@ -260,6 +309,8 @@ Saved to `captures/sentinel_YYYY-MM-DD_HHMM.json`:
260
309
}
261
310
```
262
311
312
+
`roast_uuid` and `batch_nr` are populated by `_link_alog()` when the OFF event is received. They default to `""` and `0` respectively if OFF was not received or the `.alog` could not be parsed.
313
+
263
314
Development score scale (1-10): green → pale yellow → tan → cinnamon → city → full city → dark → Vienna → French → Italian. Defined in `vision_client.py:149-160`.
Configure button WebSocket Command actions for ON, START, CHARGE, DRY, FCs, FCe, and COOL END (sends DROP). See [CLAUDE.md](CLAUDE.md) for the full button mapping.
98
+
Configure button WebSocket Command actions for ON, START, CHARGE, DRY, FCs, FCe, COOL END (sends DROP), and OFF (triggers .alog linking). See [CLAUDE.md](CLAUDE.md) for the full button mapping.
The `roast_uuid` and `batch_nr` fields are extracted from the `.alog` file when Artisan's OFF button is pressed. These enable deterministic matching between sentinel logs and roast logs in the analysis pipeline.
140
+
137
141
For code-level details, SDK API notes, and tuning parameters, see [CLAUDE.md](CLAUDE.md).
0 commit comments