Commit Graph

261 Commits

Author SHA1 Message Date
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 227c481022 fix: update MiniMateClient to correctly handle 1F calls for event iteration and 5A arming 2026-04-06 14:37:36 -04:00
claude 33de4239f4 fix: update MiniMateClient to use browse=False for 1F in download mode to ensure correct token handling for 5A 2026-04-06 13:39:11 -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 41090a9346 fix: enhance logging for event download process in MiniMateClient 2026-04-06 12:57:24 -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 57e7225a62 fix: correct DLE-stuffing handling in build_5a_frame function and update parameter description 2026-04-06 03:02:36 -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 dfa09d2a4f fix: clarify event handling in waveform viewer 2026-04-06 00:00:06 -04:00
claude ecb1147216 fix: update Peak Vector Sum offset calculation and clarify event_count handling in device info 2026-04-05 02:48:58 -04:00
claude 1c570b083a fix: update timestamp decoding for Waveform and Continuous records in models and client 2026-04-04 00:09:55 -04:00
claude 2286d2ccf8 fix: enhance event record handling to include MonitorLog sub_code and adjust timestamp parsing logic 2026-04-03 18:58:46 -04:00
claude 755050b347 fix: ensure proper waveform context by always calling 0A before 0C and use all-zero params for event advancement 2026-04-03 18:48:04 -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 4fb1bbfe35 fix: fix token position in params and enhance event iteration logic for MiniMateClient 2026-04-03 17:30:47 -04:00
claude 3effa1aab5 feat: add detailed logging for event counting process in MiniMateClient 2026-04-03 16:47:06 -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 2cb95cd45e feat: implement reliable event counting via 1E/1F chain and update device info 2026-04-03 16:02:10 -04:00
claude 7cd8fda5e8 feat: add logging for raw event index bytes and decoded count in event count decoder 2026-04-03 15:28:51 -04:00
claude f495b91d8a feat: enhance waveform viewer with record type handling and improved empty state messaging 2026-04-03 15:22:26 -04:00
claude e4730376ad feat: enhance waveform viewer with unit info display and event selection functionality 2026-04-03 15:08:57 -04:00
claude 23e4febba6 feat: add CORS middleware to allow cross-origin requests for waveform viewer 2026-04-03 14:50:43 -04:00
claude 8941dd0aef feat: add waveform_viewer page 2026-04-03 14:26:47 -04:00
claude dfb974d658 feat: add endpoint to download full raw ADC waveform for a single event 2026-04-03 13:54:54 -04:00
claude 790e442a7a feat: implement raw ADC waveform decoding and download functionality
- Added `_decode_a5_waveform()` to parse SUB 5A frames into per-channel time-series data.
- Introduced `download_waveform(event)` method in `MiniMateClient` to fetch full waveform data.
- Updated `Event` model to include new fields: `total_samples`, `pretrig_samples`, `rectime_seconds`, and `_waveform_key`.
- Enhanced documentation in `CHANGELOG.md` and `instantel_protocol_reference.md` to reflect new features and confirmed protocol details.
2026-04-03 13:53:09 -04:00
claude 5d0f0855f2 doc: update to .0.6.0 with full working event read loop 2026-04-02 17:30:33 -04:00
claude 0f5aa7a3fc fix: adjust anchor search range in compliance config decoder for improved data handling 2026-04-02 17:22:56 -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 9b1ed1f3a8 client: update channel block layout documentation and improve validation checks for 'Tran' label 2026-04-02 15:31:09 -04:00
claude 501b5080e9 server: backfill event.project_info fields from compliance config
The 210-byte waveform record only stores "Project:" — client, operator,
sensor_location, and notes are device-level settings in SUB 1A, not
per-event fields. Backfill those into each event's project_info after
download, same pattern as the sample_rate backfill.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 14:33:33 -04:00
claude 5948c833bd client: lower Tran search floor from 1000 to 44 in channel block extraction
The channel block is in frame C data (cfg[44:1071]) not deep in a
hypothetical frame D section.  The offset-1000 assumption was wrong —
searching from 44 lets us find it while unit string validation still
prevents false positives.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 14:22:00 -04:00
claude c4a5da893c client: add WARNING-level diagnostics for Tran channel block search
Temporary: log tran_pos, surrounding bytes, and exact unit string check
results at WARNING level so we can see why trigger/alarm/max_range are
still null even with the full 2126-byte cfg.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 14:18:27 -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 6eecd0c1d1 client/models/server: wire event_count from SUB 08 event index into connect()
- DeviceInfo.event_count: Optional[int] = None  (new field in models.py)
- connect() now calls proto.read_event_index() after compliance config and
  stores the decoded count in device_info.event_count
- _serialise_device_info() exposes event_count in /device/info and /device/events
  JSON responses

event_count is decoded from uint32 BE at offset +3 of the 88-byte F7 payload
(🔶 inferred — needs live device confirmation against a multi-event device).
Any ProtocolError from the index read is caught and logged; event_count stays
None rather than failing the whole connect().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 02:00:37 -04:00
claude 870a10365e server: fill ev.sample_rate from compliance config for /device/events
sample_rate is a device-level setting stored in the compliance config,
not per-event in the waveform record.  After downloading events, backfill
ev.sample_rate from info.compliance_config.sample_rate for any event
that didn't get it from the waveform record decode path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 02:00:00 -04:00
claude b2d10fd689 client: wire trigger_level_geo, alarm_level_geo, max_range_geo from channel block
The channel block is only present in the full ~2126-byte cfg (when frame D
delivers correctly rather than duplicating frame B's page).  Layout per §7.6:
  [00 00][max_range f32][00 00][trigger f32]["in.\0"][alarm f32]["/s\0\0"][00 01][label]

Relative offsets from the "Tran" label position (label-24/label-18/label-10)
are validated by checking the unit strings "in.\0" at label-14 and "/s\0\0"
at label-6 before reading the floats.  Guard against "Tran2" false-match.

When frame D duplicates, cfg is ~1071 bytes and tran_pos search returns a hit
without the unit string sentinels — we log the miss and leave fields None.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 01:59:56 -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 6a42facf02 docs: update protocol reference for SUB 1A compliance config read
New/corrected sections:

§7.6.1 Record Time — corrected: anchor+10 supersedes the +0x28 absolute
offset.  Added 3 s, 5 s, 8 s confirmations alongside existing 7/10/13.
Warning added: do NOT use fixed offset for BE11529.

§7.6.2 (NEW) SUB 1A Multi-Frame Read Protocol — 4-frame A/B/C/D
sequence documented (reverse-engineered from raw_bw capture).  E5
page_key field explained.  BE11529 duplicate-page behaviour and
(page_key, chunk_len) dedup strategy documented.

§7.6.3 (NEW) Sample Rate and DLE Jitter — Normal/Fast/Faster = 1024/
2048/4096 Sa/s confirmed.  Root cause of ±1 byte cfg jitter explained:
4096 = 0x1000 → `10 10 00` in raw frame → `10 00` after DLE unstuffing
= 1 byte shorter than 04 00/08 00.  Anchor search requirement explained.

Changelog — 5 new entries covering the 4-frame sequence, duplicate-page
detection, record_time anchor correction, sample_rate confirmation, and
_pending_frames / reset_parser=False implementation notes.

Quick Reference — Record Time and Sample Rate rows updated with correct
locations, types, and confirmed values.

Open Questions — SUB 1A item updated to "substantially resolved".
Record time item updated. Sample rate added as resolved.
2026-04-01 16:54:51 -04:00
claude 4b703811d9 client: remove _cfg_diagnostic now that all compliance fields are confirmed
record_time (float32_BE) and sample_rate (uint16_BE) both validated
against live device across normal / fast / faster modes and multiple
record time settings.  Diagnostic scaffolding no longer needed.
2026-04-01 16:49:37 -04:00
claude ea4475c9ad client: use anchor-relative offsets for record_time and sample_rate
Fixed a 1-byte offset jitter that produced garbage values when the
device was set to "faster" (4096 Sa/s) mode.

Root cause: 4096 = 0x1000, so the sample_rate bytes in the raw S3
frame are `10 10 00` (DLE-escaped).  After DLE unstuffing → `10 00`
(2 bytes vs 3 for 1024/2048), making frame C 1 byte shorter and
shifting all subsequent field offsets by -1.

Fix: locate the stable 10-byte anchor `01 2c 00 00 be 80 00 00 00 00`
(max-record-limit constant + first two alarm-level floats) and read:
  sample_rate  = uint16_BE at anchor - 2
  record_time  = float32_BE at anchor + 10

Offline-validated against all five logged hex dumps (1071 and 1070
byte cfg, record times 3/5/8 s, sample rates 1024 and 4096):
  all five: correct values with anchor approach.
2026-04-01 16:45:40 -04:00
claude df51fe0668 client: wire record_time (cfg[64] f32_BE) and sample_rate (cfg[52] u16_BE)
Both offsets identified from _cfg_diagnostic scan on BE11529:
  cfg[64] float32_BE = 3.0  → record_time in seconds
  cfg[52] uint16_BE  = 1024 → sample_rate in Sa/s

Values are plausible but NOT yet validated by changing device settings
and re-reading.  Marked as  candidate in docstring — confirm and
remove the ⚠️ note once a device-side change is observed here.
2026-04-01 15:40:35 -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 58a5f15ed5 client: fix setup_name; add diagnostic scan for record_time/sample_rate
- setup_name was broken: _find_string_after(b"Standard Recording Setup")
  returned what comes AFTER the string (i.e. "Project:"), not the name
  itself.  Fixed by searching for the first long (>=8 char) ASCII string
  in cfg[40:250] with _find_first_string().

- record_time offset 0x28 was wrong (that location holds "(L)", a unit
  label string).  Disabled for now to avoid returning garbage; correct
  offset will be determined from _cfg_diagnostic() output.

- Added _cfg_diagnostic(): logs all strings and all plausible float32/uint16
  values across the full cfg so record_time and sample_rate offsets can be
  pinpointed from a single device run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:18:41 -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