Commit Graph

32 Commits

Author SHA1 Message Date
claude e712d68505 feat: add erase-all protocol and browse helpers to protocol/client layer
protocol.py:
- SUB_ERASE_ALL_BEGIN = 0xA3, SUB_ERASE_ALL_CONFIRM = 0xA2 (confirmed 4-11-26 MITM)
- SUB_CHANNEL_CONFIG (0x06) data length = 0x24 (36 bytes) in DATA_LENGTHS
- begin_erase_all()              — single frame, token=0xFE, response 0x5C
- confirm_erase_all()            — single frame, token=0xFE, response 0x5D
- read_event_storage_range()     — two-step read (probe+data), token=0xFE
  Response last 8 bytes = first/last stored event key; both 0x01110000 after erase

client.py:
- list_event_keys()              — browse-mode 1E→0A→1F walk, no waveform download;
  returns list of hex key strings; used as fast pre-check before get_events()
- get_events(skip_waveform_for_keys=set())
  — for already-seen keys: only 0A+1F(browse), skips 1E-arm/0C/POLL×3/5A entirely
- delete_all_events()            — orchestrates the confirmed erase sequence:
  0xA3 → 0x1C → 0x06 → 0xA2; logs first/last key from storage range response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 01:14:37 -04:00
claude dda5683572 fix: improve monitoring functionality with session-reset signal and payload adjustments 2026-04-08 18:29:51 -04:00
claude a41e7a9e1a feat: Add monitoring functionality to MiniMate protocol and web interface
- Introduced new SUBs for monitoring status, start, and stop commands in protocol.py.
- Implemented read_monitor_status, start_monitoring, and stop_monitoring methods in MiniMateProtocol class.
- Added new API endpoints for monitoring status retrieval and control in server.py.
- Enhanced the web application with a monitoring panel, including battery and memory status display.
- Created a new Python script to parse SUB 0x1C response frames for monitoring status.
- Documented the monitoring status response format and field locations in markdown and text files.
2026-04-08 14:34:42 -04:00
claude 7005ae766d feat: implement set_project_info functionality and add POC test script 2026-04-07 02:49:17 -04:00
claude bcc044655a feat: updates to 0.8.0 - initial write functions 2026-04-07 02:09:29 -04:00
claude 781d21f132 perf: reduce 5A chunk timeout to 10s and stop iteration at requested event index
Two improvements to eliminate the ~2-min-per-event wait and unnecessary
full-event-list download when only one event is requested:

1. protocol.py: pass timeout=10.0 to _recv_one in the 5A chunk loop.
   Device responds within ~1s per chunk; 10s gives a safe 10x buffer.
   End-of-stream detection (raw_bytes=1) now fires in 10s instead of 120s,
   cutting ~110s of dead wait per event.

2. client.py: add stop_after_index parameter to get_events(). When set,
   iteration stops immediately after the target event is collected — no
   further 0A/1E/0C/5A/1F cycles for events the caller doesn't need.

3. server.py: pass stop_after_index=index to both /device/event/{idx}
   and /device/event/{idx}/waveform endpoints so a single-event request
   only downloads that one event.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:02:01 -04:00
claude e3a5c6f07d 5A: treat partial end-of-stream byte as graceful stream termination
When the device finishes streaming waveform data, it sends a single
partial byte (raw_bytes=1) rather than a complete A5 frame, then goes
silent for the full 120s timeout.

Observed: 35 chunks succeed, chunk 36 times out with raw_bytes=1 —
identical for both events in the test run.

Fix: on TimeoutError, if bytes_fed > 0 and we already have collected
frames, treat it as natural end-of-stream and break to the termination
step rather than propagating the exception.  True transport failures
(raw_bytes=0, no prior frames) still raise.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 17:41:29 -04:00
claude 1397f8486f diag: per-chunk WARNING logging in 5A bulk stream loop
Wraps each recv_one call in a try/except TimeoutError, logging:
- On timeout: chunk_num, counter, raw bytes_fed (distinguishes "device
  silent" from "device sent unparseable bytes")
- On success: chunk_num, page_key, data_len, contains_Project flag

Parser is explicitly reset before each chunk recv so bytes_fed is
accurate per-chunk rather than cumulative. Helps identify exactly which
chunk fails and whether the device is responding at all.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 17:32:49 -04:00
claude 5b3e8af1e3 fix: remove special case chunk counter, all chunks use chunk_num * 0x0400 2026-04-06 17:03:09 -04:00
claude ad1c9e48b0 fix: update MiniMateClient and protocol to ensure correct handling of 1F calls and improve event download sequence 2026-04-06 15:58:03 -04:00
claude d0d5a18d5c fix: update event handling in MiniMateClient and protocol to ensure correct sequence for waveform downloads 2026-04-06 13:19:51 -04:00
claude d87e02fab2 fix: update event handling in MiniMateClient and protocol to address 5A timeout issue 2026-04-06 12:41:27 -04:00
claude 5d43acd827 fix: clarify bulk counter step handling and improve comments for waveform chunk processing 2026-04-06 01:35:09 -04:00
claude 6adf8b6078 Fix: advance_event(browse=True) now sends token_params(0) — all zeros — matching the confirmed BW browse sequence. 2026-04-03 18:15:42 -04:00
claude 95f2becf21 feat: update event iteration logic to use null sentinel for end-of-events detection 2026-04-03 16:29:10 -04:00
claude 3b04d4683b fix: update compliance config read logic to handle buffered responses on slow links 2026-04-02 17:18:48 -04:00
claude 0363425d83 fix: add addition recv after loop to make up for modem TCP/IP lag 2026-04-02 17:13:12 -04:00
claude 66967e036c fix: match BW's 5A frame probe to parse event-time metadata. 2026-04-02 16:57:12 -04:00
claude 9bf20803c2 feat: fetch event-time metadata from SUB 5A bulk waveform stream
Add read_bulk_waveform_stream() to MiniMateProtocol and wire it into
get_events() so each event gets authoritative client/operator/sensor_location
from the A5 frames recorded at event-time, not the current compliance config.

- framing.py: bulk_waveform_params() and bulk_waveform_term_params() helpers
  (probe/chunk params and termination params for SUB 5A, confirmed from
  1-2-26 BW TX capture)
- protocol.py: read_bulk_waveform_stream(key4, stop_after_metadata=True) —
  probe + chunk loop (counter += 0x0400), early stop when b"Project:" found
  (A5[7] of 9), then sends termination at offset=0x005A
- client.py: _decode_a5_metadata_into() needle-searches concatenated A5 frame
  data for Project/Client/User Name/Seis Loc/Extended Notes; get_events() now
  calls SUB 5A after each SUB 0C, overwriting project_info with event-time values

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 16:08:21 -04:00
claude 638e60532c protocol: tighten compliance config dedup to exact byte content
Old key was (page_key, chunk_len) which would incorrectly drop a second
config section that has the same length as the first (e.g. current-config
vs event-time-config when settings haven't changed).

New key is the full chunk bytes — only truly byte-identical chunks are
dropped.  Different data that happens to share page_key and length now
comes through correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 03:36:25 -04:00
claude ce44852383 protocol: add read_event_index() for SUB 08/F7
Two-step probe+fetch for SUB 08 (EVENT_INDEX), returning the raw 88-byte
(0x58) index block.  SUB_EVENT_INDEX and DATA_LENGTHS[0x08]=0x58 were
already registered — this just wires the method that calls them.

Docstring notes the partially-decoded layout (event count at +3 as uint32 BE,
timestamps at +7) pending live device confirmation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 01:59:48 -04:00
claude 114cbb4679 protocol: skip duplicate E5 chunks in read_compliance_config
BE11529 sometimes returns frame D with page_key=0x0000 (44 bytes),
identical to the frame B response, inflating cfg to ~1115 bytes and
mis-aligning all field offsets.  Track (page_key, chunk_size) pairs
and drop any repeat before appending to the running config buffer.
2026-04-01 15:39:56 -04:00
claude eee1e36a1b protocol: send 3-step data requests for full compliance config (SUB 1A)
Reverse-engineered the full Blastware 4-frame sequence for SUB 1A:
  A (probe):      offset=0x0000, params[7]=0x64
  B (data req 1): offset=0x0400, params[2]=0x00, params[7]=0x64  → bytes 0..1023
  C (data req 2): offset=0x0400, params[2]=0x04, params[7]=0x64  → bytes 1024..2047
  D (data req 3): offset=0x002A, params[2]=0x08, params[7]=0x64  → bytes 2048..2089

We were only sending A+D and getting 44 bytes (the last chunk).
Now sends B, C, D in sequence; each E5 response has 11-byte echo header
stripped, and chunks are concatenated.  Devices that return all data in
one frame (BE18189 style) are handled — timeouts on B/C are skipped
gracefully and data from D still accumulates.

Total expected: 0x0400 + 0x0400 + 0x002A = 0x082A = 2090 bytes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:08:50 -04:00
claude a5069c302d protocol: accumulate multiple E5 frames for chunked compliance config
BE11529 sends the compliance config (SUB 1A / E5 response) as a stream
of small frames (~44 bytes each) rather than one large frame like BE18189.

Changes:
- read_compliance_config(): loop calling _recv_one() until 0x082A bytes
  accumulated or 2s inter-frame gap; first frame strips 11-byte echo header,
  subsequent frames logged in full for structure analysis
- _recv_one(): add reset_parser=False option to preserve parser state and
  _pending_frames buffer between consecutive reads from one device response;
  also stash any extra frames parsed in a single TCP chunk so they are not lost

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 14:54:16 -04:00
claude 6e0b83efa5 fix: update compliance config reading to handle variable payload sizes and improve logging 2026-04-01 14:31:03 -04:00
claude d4b1b834a7 fix: refine SUB 1A compliance config read parameters and logging 2026-04-01 14:20:12 -04:00
claude 32b9d3050c feat: implement SUB 1A (compliance config) read
Adds full support for reading device compliance configuration (2090-byte E5
response) containing record time, trigger/alarm levels, and project strings.

protocol.py:
- Implement read_compliance_config() two-step read (SUB 1A → E5)
- Fixed length 0x082A (2090 bytes)

models.py:
- Add ComplianceConfig dataclass with fields: record_time, sample_rate,
  trigger_level_geo, alarm_level_geo, max_range_geo, project strings
- Add compliance_config field to DeviceInfo

client.py:
- Implement _decode_compliance_config_into() to extract:
  * Record time float at offset +0x28 
  * Trigger/alarm levels per-channel (heuristic parsing) 🔶
  * Project/setup strings from E5 payload
  * Placeholder for sample_rate (location TBD )
- Update connect() to read SUB 1A after SUB 01, cache in device_info
- Add ComplianceConfig to imports

sfm/server.py:
- Add _serialise_compliance_config() JSON encoder
- Include compliance_config in /device/info response
- Updated _serialise_device_info() to output compliance config

Both record_time (at fixed offset 0x28) and project strings are  CONFIRMED
from protocol reference §7.6. Trigger/alarm extraction uses heuristics
pending more detailed field mapping from captured data.

Sample rate remains undiscovered in the E5 payload — likely in the
mystery flags at offset +0x12 or requires a "fast mode" capture.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 12:08:43 -04:00
claude 9f52745bb4 feat: add full event download pipeline 2026-03-31 20:48:03 -04:00
claude 8074bf0fee bump timeout to 30s to deal with modem slowness. 2026-03-31 12:12:36 -04:00
claude 3f142ce1c0 fix: stop raising on S3 checksum mismatches 2026-03-31 00:15:07 -04:00
claude 8e985154a7 bumps timeout up 2026-03-30 23:46:34 -04:00
claude f8f590b19b sfm first build 2026-03-30 23:23:29 -04:00