doc: update to .0.6.0 with full working event read loop
This commit is contained in:
@@ -72,6 +72,11 @@
|
||||
| 2026-04-01 | §7.6.1 | **CORRECTED — Record time offset.** Previous doc (`+0x28` from E5 data page2 start) was correct for single-frame reads but unreliable for BE11529 due to a 1-byte DLE jitter (see §7.6.3). The `minimateplus` library now uses an anchor-based approach: search for `\x01\x2c\x00\x00\xbe\x80\x00\x00\x00\x00` in cfg[40:100]; record time float32 BE is at anchor+10. Validated at 3.0, 5.0, and 8.0 seconds. |
|
||||
| 2026-04-01 | §7.6.3 (NEW) | **NEW — Sample rate confirmed and documented.** Sample rate (Normal=1024 / Fast=2048 / Faster=4096 Sa/s) is stored as uint16 BE at anchor−2, where anchor is the 10-byte sequence `\x01\x2c\x00\x00\xbe\x80\x00\x00\x00\x00`. DLE jitter root cause: 4096 = 0x1000, so in the raw S3 frame the sample-rate bytes are sent as `10 10 00` (DLE-escaped `10`); after DLE unstuffing → `10 00` (2 bytes instead of 3 for 1024/2048), making frame C 1 byte shorter and shifting all subsequent offsets by −1. Anchor search is immune to this shift. All three modes confirmed on BE11529 firmware S338.17. |
|
||||
| 2026-04-01 | §5.1 | **CONFIRMED — `_pending_frames` buffer and `reset_parser=False` parameter.** `MiniMateProtocol._recv_one()` now supports `reset_parser=False` to preserve parser state between consecutive reads within a multi-frame sequence. A `_pending_frames: list[S3Frame]` buffer stores extra frames parsed from a single TCP chunk when multiple E5 responses arrive together. Required for reliable SUB 1A frame B/C/D sequence on BE11529. |
|
||||
| 2026-04-02 | §7.8 (NEW) | **CONFIRMED — SUB 5A frame format.** `offset_hi` byte (`0x10`) must be sent **raw, not DLE-stuffed** — standard `build_bw_frame` incorrectly stuffs it to `10 10` on the wire; device ignores the frame. BW sends it as bare `10`. Checksum is **DLE-aware**: when walking the byte sequence, `10 XX` pairs contribute only `XX` to the sum; lone bytes contribute normally. `build_5a_frame()` reproduces BW's exact wire format. |
|
||||
| 2026-04-02 | §7.8 | **CONFIRMED — SUB 5A params are 11 bytes (not 10) for chunk frames.** Extra trailing `0x00` confirmed from 1-2-26 BW wire capture. Probe frame and termination frame differ — see `bulk_waveform_params()` in `framing.py`. |
|
||||
| 2026-04-02 | §7.7.5 | **CONFIRMED — Event-time metadata source.** `Client:`, `User Name:`, and `Seis Loc:` strings are present in **A5 frame 7** of the SUB 5A bulk waveform stream — they are NOT in the 210-byte SUB 0C waveform record. They reflect the compliance setup active when the event was stored on the device (not the current setup). `get_events()` now issues SUB 5A after each 0C download. Sequence: `1E → 0A → 0C → 5A → 1F`. |
|
||||
| 2026-04-02 | §7.6.2 | **FIXED — Compliance config orphaned send bug.** An extra `self._send(SUB_COMPLIANCE / 0x2A / DATA_PARAMS)` before the B/C/D receive loop had no corresponding `recv_one()`. Every receive in the loop was consuming the previous send's response, leaving frame D's channel block unread. Bug removed. Total config bytes now ~2126 (was ~1071 due to truncation). `trigger_level_geo`, `alarm_level_geo`, `max_range_geo` are now correctly populated. |
|
||||
| 2026-04-02 | §7.6.1 | **CORRECTED — Anchor search range.** Previous doc stated anchor search range `cfg[40:100]`. With the orphaned-send bug fixed, the 44-byte header padding is gone and the anchor now appears at `cfg[11]`. Corrected to `cfg[0:150]`. |
|
||||
|
||||
---
|
||||
|
||||
@@ -495,7 +500,9 @@ Values are stored natively in **imperial units (in/s)** — unit strings `"in."`
|
||||
|
||||
Record time is stored as a **32-bit IEEE 754 float, big-endian**, located via an anchor pattern (see §7.6.3 below).
|
||||
|
||||
**Anchor-relative location:** search for the 10-byte sequence `\x01\x2c\x00\x00\xbe\x80\x00\x00\x00\x00` in cfg[40:100]. Record time float is at **anchor + 10**.
|
||||
**Anchor-relative location:** search for the 10-byte sequence `\x01\x2c\x00\x00\xbe\x80\x00\x00\x00\x00` in `cfg[0:150]`. Record time float is at **anchor + 10**.
|
||||
|
||||
> ✅ **2026-04-02 — CORRECTED:** Search range was `cfg[40:100]`. With the compliance-config orphaned-send bug fixed (§7.6.2), the 44-byte accidental header padding is gone and the anchor now appears at `cfg[11]`. Search range widened to `cfg[0:150]`.
|
||||
|
||||
| Record Time | float32 BE bytes | Decoded |
|
||||
|---|---|---|
|
||||
@@ -907,16 +914,20 @@ Near-ambient: 0x3C75C28F = 0.015 in/s (histogram event, near-zero ambient)
|
||||
|
||||
**Project strings** — ASCII label-value pairs (search for label, read null-terminated value):
|
||||
```
|
||||
"Project:" → project description (present in 0C record ✅)
|
||||
"Client:" → client name (NOT in 0C; comes from compliance config SUB 1A/E5 ❓)
|
||||
"User Name:" → operator / user (NOT confirmed in 0C ❓)
|
||||
"Seis Loc:" → sensor location (NOT confirmed in 0C ❓)
|
||||
"Extended Notes"→ notes field
|
||||
"Project:" → project description (in 0C record ✅)
|
||||
"Client:" → client name (in SUB 5A / A5 frame 7 ✅ — NOT in 0C)
|
||||
"User Name:" → operator / user (in SUB 5A / A5 frame 7 ✅ — NOT in 0C)
|
||||
"Seis Loc:" → sensor location (in SUB 5A / A5 frame 7 ✅ — NOT in 0C)
|
||||
"Extended Notes"→ notes field (in SUB 5A / A5 frame 7 ✅)
|
||||
```
|
||||
|
||||
> ❓ **Clarification needed:** Only "Project:" has been confirmed in the 210-byte 0C record.
|
||||
> "Client:", "User Name:", and "Seis Loc:" appear in the Blastware event report but their
|
||||
> source in the protocol (0C vs SUB 1A/E5 compliance config) is not yet confirmed.
|
||||
> ✅ **2026-04-02 — CONFIRMED:** `Client:`, `User Name:`, and `Seis Loc:` are sourced from
|
||||
> **SUB 5A (bulk waveform stream)**, specifically A5 frame 7 of the multi-frame response.
|
||||
> They are NOT present in the 210-byte SUB 0C waveform record. The strings reflect the
|
||||
> compliance setup that was active when the event was recorded on the device — making SUB 5A
|
||||
> the authoritative source for true event-time metadata. The `get_events()` client method
|
||||
> now issues a SUB 5A request after each 0C download (`stop_after_metadata=True`) and
|
||||
> overwrites `event.project_info` with the decoded fields.
|
||||
|
||||
---
|
||||
|
||||
@@ -948,6 +959,101 @@ return events
|
||||
|
||||
---
|
||||
|
||||
### 7.7.7 Updated Download Loop with SUB 5A Metadata
|
||||
|
||||
> ✅ **Added 2026-04-02.** Confirmed working on BE11529 over TCP/cellular.
|
||||
|
||||
```python
|
||||
key4, _ = proto.read_event_first() # SUB 1E
|
||||
if key4 == b'\x00\x00\x00\x00':
|
||||
return []
|
||||
|
||||
events = []
|
||||
is_first = True
|
||||
|
||||
while key4 != b'\x00\x00\x00\x00':
|
||||
if is_first:
|
||||
_header, rec_len = proto.read_waveform_header(key4) # SUB 0A
|
||||
is_first = False
|
||||
if rec_len < 0x30:
|
||||
key4 = proto.advance_event()
|
||||
continue
|
||||
|
||||
record = proto.read_waveform_record(key4) # SUB 0C (0xD2 bytes)
|
||||
event = decode(record)
|
||||
|
||||
a5_data = proto.read_bulk_waveform_stream( # SUB 5A → A5 frames
|
||||
key4, stop_after_metadata=True)
|
||||
client._decode_a5_metadata_into(a5_data, event) # overwrites project_info
|
||||
|
||||
events.append(event)
|
||||
key4 = proto.advance_event() # SUB 1F (token=0xFE)
|
||||
|
||||
return events
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7.8 SUB 5A — Bulk Waveform Stream (event-time metadata)
|
||||
|
||||
> ✅ **Added 2026-04-02.** Frame format confirmed by reproducing Blastware wire bytes
|
||||
> byte-for-byte from the 1-2-26 BW capture.
|
||||
|
||||
SUB 5A initiates a bulk transfer of the raw sample data for a stored event. The response is a
|
||||
sequence of A5 frames. Frame 7 (0-indexed) contains the full compliance setup as it existed
|
||||
when the event was recorded — including `Client:`, `User Name:`, `Seis Loc:`, and
|
||||
`Extended Notes` ASCII label-value pairs.
|
||||
|
||||
#### 7.8.1 Frame Format
|
||||
|
||||
SUB 5A uses a **non-standard frame layout** that differs from all other BW→S3 write commands.
|
||||
|
||||
```
|
||||
[ACK][STX][10][10][00][5A][00][offset_hi][offset_lo][params...][chk][ETX]
|
||||
41 02 10 10 00 5A 00 ^^raw^^ ^^raw^^ ^^stuffed^^
|
||||
```
|
||||
|
||||
Two critical differences from `build_bw_frame`:
|
||||
|
||||
1. **`offset_hi` is sent raw, not DLE-stuffed.** When `offset_hi = 0x10`, the wire carries
|
||||
a bare `0x10` — NOT the stuffed `10 10` that `build_bw_frame` would produce. The device
|
||||
ignores frames where this byte is incorrectly stuffed.
|
||||
|
||||
2. **DLE-aware checksum.** Walking the full frame byte sequence: when a `10 XX` pair is seen,
|
||||
only `XX` is added to the running sum; lone bytes are added normally.
|
||||
|
||||
#### 7.8.2 Request Sequence
|
||||
|
||||
| Frame | offset_word | params | Purpose |
|
||||
|---|---|---|---|
|
||||
| Probe | `0x1004` | 10 bytes (`bulk_waveform_params(0)`) | Initiate transfer |
|
||||
| Chunk 1 | `0x1004` | 11 bytes (`bulk_waveform_params(counter)`) | First data chunk |
|
||||
| Chunk 2 | `0x1004` | 11 bytes, counter += `0x0400` | Second chunk |
|
||||
| … | … | … | … |
|
||||
| Termination | `0x005A` | 11 bytes, term_counter = last+`0x0400` | End transfer |
|
||||
|
||||
The `stop_after_metadata=True` flag causes the loop to stop as soon as `b"Project:"` is
|
||||
found in the accumulated A5 frame data, typically after 7–9 chunks. A termination frame
|
||||
is always sent before returning.
|
||||
|
||||
#### 7.8.3 A5 Frame Layout
|
||||
|
||||
Each A5 response frame contains a chunk of raw bulk data. Frame 7 of the stream carries the
|
||||
compliance text block with all project-info label-value pairs. The `client` layer searches
|
||||
for ASCII labels with a null-terminated value read:
|
||||
|
||||
```
|
||||
"Project:" → null-terminated project name
|
||||
"Client:" → null-terminated client name
|
||||
"User Name:" → null-terminated operator name
|
||||
"Seis Loc:" → null-terminated sensor location
|
||||
"Extended Notes" → null-terminated notes
|
||||
```
|
||||
|
||||
All five fields reflect the **setup at event-record time**, not the current device config.
|
||||
|
||||
---
|
||||
|
||||
## 8. Timestamp Format
|
||||
|
||||
Two timestamp wire formats are used:
|
||||
|
||||
Reference in New Issue
Block a user