feat(protocol): update Blastware file format documentation and encoding details

This commit is contained in:
2026-04-22 19:16:05 -04:00
parent dfbc9f29c5
commit c47e3a3af0
5 changed files with 250 additions and 109 deletions
+79 -25
View File
@@ -2249,10 +2249,14 @@ Semantic Interpretation <- settings, events, responses
---
## Appendix D — Blastware Binary File Formats (.N00 / .MLG)
## Appendix D — Blastware Binary File Formats (.N00 / .MLG / others)
> ✅ CONFIRMED 2026-04-21 — all fields verified by binary diff of reconstructed vs reference
> files from the 4-3-26-multi_event capture (M529LIY6.N00, BE11529.MLG).
>
> ⚠️ EXTENSION MAPPING REFUTED 2026-04-21 — earlier assumption that extension encodes
> recording mode is **FALSE**. A continuous-mode event produced `.EI0`, not `.9T0`.
> Extension encoding algorithm is unknown. Do not use extension to infer recording mode.
### D.1 Common File Header (22 bytes)
@@ -2271,10 +2275,37 @@ All Blastware files (regardless of type) share an 18-byte prefix followed by a 4
| Extension | Type tag | Description |
|---|---|---|
| `.N00` | `00 12 03 00` | Single-shot waveform event |
| `.N00` | `00 12 03 00` | Waveform event (confirmed) |
| `.9T0` | `00 12 03 00` | Waveform event — same type tag as .N00 (assumed; not independently confirmed) |
| `.EI0` | `00 12 03 00` | Waveform event — same type tag (assumed; continuous-mode event observed 2026-04-21) |
| `.MLG` | `22 01 0e a0` | Monitor log |
Blastware identifies file type by extension, not by type tag alone.
**Extension encoding — new firmware (V10.72+) FULLY DECODED (confirmed 2026-04-21, further confirmed 2026-04-22):**
Format: `AB0T` (4 chars):
- `AB` = 2-char base-36 encoding of `total_seconds % 1296` where `total_seconds = (event_local_time 1985-01-01T00:00:00)` in seconds; `A = value // 36`, `B = value % 36`
- `0` = always literal digit zero (third character)
- `T` = `W` (Full Waveform) or `H` (Full Histogram)
Base-36 alphabet: `09` = 09, `AZ` = 1035.
Combined with the 4-char stem, the full filename encodes a complete second-resolution timestamp.
**Verification — 10-year production archive frequency analysis (2026-04-22):**
A 10-year archive from a long-term monitoring site showed the top 3 extensions across ~3,200 waveform files were `CE0H` (95 files), `0E0H` (93), `OE0H` (91). These are exactly the 3-day cycle of a 06:00:14 daily call-in time:
- `0E0H` → seconds = 0×36+14 = **14** (06:00:**14** — the `14` seconds appears directly)
- `OE0H` → seconds = 24×36+14 = **878** (next calendar day)
- `CE0H` → seconds = 12×36+14 = **446** (day after)
**3-day cycle property:** A unit recording at a fixed daily time cycles through exactly **3 different extensions** with a 3-day period. Each calendar day shifts `total_seconds % 1296` by 864 (since `86400 % 1296 = 864`). The cycle repeats every 3 days because `gcd(1296, 864) = 432`, giving `1296 / 432 = 3` distinct values spaced 432 seconds apart.
**B character invariance:** The second extension character `B` (= `value % 36`) **never changes** for a fixed daily recording time, because `864 = 24 × 36` — adding 864 never changes the value mod 36. Only the first character `A` cycles through 3 values. All three cycle extensions share the same `B` character (confirmed: `0E0H`, `OE0H`, `CE0H` all have `E` as second character).
**Old firmware (S338, 3-char extensions ending in `0`):** encoding unknown. Extension is NOT recording mode — a continuous-mode event produced `.EI0`, not `.9T0`. `blastware_filename()` uses `.N00` as a placeholder for old-firmware units.
**Micromate Series 4** uses a different extension format (observed: `IDFH`, `IDFW`). The `AB0T` formula does NOT apply to Micromate units.
All waveform files share the same `00 12 03 00` type tag regardless of extension. Blastware identifies file type by extension, not by type tag alone.
### D.2 Timestamp Encoding (Blastware files)
@@ -2394,38 +2425,61 @@ The footer terminates the N00 file. Its bytes come directly from the terminator
The 2-byte CRC at record[0:2] uses an unconfirmed algorithm. Tested against CRC-16/CCITT, CRC-16/IBM, CRC-32 (truncated), word sums, XOR variants, and 40+ polynomial/init combinations — none matched. The writer emits `00 00`. Blastware may reject files with incorrect CRCs (impact on import unknown — TODO: test).
### D.5 Filename Encoding ✅ CONFIRMED 2026-04-21
### D.5 Filename Encoding ✅ PARTIALLY CONFIRMED 2026-04-22
Blastware assigns waveform filenames of the form `M<serial3><stem><ext>`, where:
Blastware assigns waveform filenames of the form `<prefix_letter><serial3><stem><ext>`, where:
#### D.5.1 Serial Prefix
#### D.5.1 Serial Prefix ✅ CONFIRMED 2026-04-22
`"M"` + last 3 decimal digits of the device serial number.
Example: serial `"BE11529"` → prefix `"M529"`.
#### D.5.2 Stem — 4-character base-36 timestamp encoding
The first 4 characters of the filename encode the full device serial number:
```
stem_int = floor((event_local_time 1985-01-01T00:00:00_local) / 1296)
stem = 4-character uppercase base-36 string of stem_int
prefix_letter = chr(ord('B') + floor(serial_numeric / 1000))
serial3 = f"{serial_numeric % 1000:03d}" (last 3 digits, zero-padded)
```
- **Unit:** 1296 seconds = 36² seconds ≈ 21.6 minutes per stem increment
- **Epoch:** January 1, 1985, 00:00:00 local time (Instantel founding year)
Where `serial_numeric` is the integer after the "BE" device-type prefix.
Examples (all confirmed from archive):
| Serial | serial_numeric / 1000 | prefix_letter | serial3 | Filename prefix |
|--------|----------------------|---------------|---------|-----------------|
| BE6907 | 6 | H | 907 | H907 |
| BE7145 | 7 | I | 145 | I145 |
| BE11529 | 11 | M | 529 | M529 |
| BE14036 | 14 | P | 036 | P036 |
| BE17353 | 17 | S | 353 | S353 |
| BE18003 | 18 | T | 003 | T003 |
| BE18191 | 18 | T | 191 | T191 |
| BE18676 | 18 | T | 676 | T676 |
**Interpretation:** The prefix letter encodes the production generation (batch of 1000 units). B=generation 0 (serials 0999), C=generation 1 (10001999), etc. No units with prefix A have been observed — the earliest known units start around serial 2000+ (prefix D).
**Note:** The "BE" device-type prefix is implicit. The filename only encodes the numeric part of the serial. Other Instantel device types (Micromate, Blastmate) may use a different scheme.
#### D.5.2 Stem + Extension — full timestamp encoding ✅ FULLY CONFIRMED 2026-04-22
The stem (4 chars) and AB extension (2 chars) together form a 6-digit base-36 number encoding a complete second-resolution timestamp:
```python
total_seconds = stem_int * 1296 + ab_int
event_local_time = datetime(1985, 1, 1) + timedelta(seconds=total_seconds)
```
- **Epoch:** `1985-01-01 00:00:00` **device local time** ✅ CONFIRMED — verified against 3,248 files from a 10-year production archive; zero errors (only 2 mismatches were Micromate `IDFH`/`IDFW` files which use a completely different naming scheme)
- **Unit:** 1296 seconds = 36² ≈ 21.6 minutes per stem increment
- **Alphabet:** `"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"` (digits then uppercase letters)
- **Collision:** Events within the same 21.6-minute window share a stem; their extension distinguishes them
- **Collision:** Events within the same 21.6-minute window share a stem; extension distinguishes them
Confirmed against 6 events (April 19, 2026):
**Decoding example — `P036L318.C80H` (BE14036, Full Histogram):**
```
stem L318 = 21×36³ + 3×36² + 1×36 + 8 = 983,708
AB C8 = 12×36 + 8 = 440
total_sec = 983,708 × 1296 + 440 = 1,274,886,008
event_time = 1985-01-01 + 1,274,886,008s = 2025-05-26 15:00:08 local
```
| Stem | Event time | Epoch estimate |
|---|---|---|
| LIY6 | 2026-04-01 00:28 | 1985-01-01 00:23 local |
| LJ31 | 2026-04-03 15:20 | 1985-01-01 00:22 local |
| LJ8V | 2026-04-06 18:52 | 1985-01-01 00:25 local |
| LJDY | 2026-04-09 12:46 | 1985-01-01 00:23 local |
All 6 stems match exactly. Epoch estimates converge within ±7 minutes of midnight Jan 1 1985.
**Note on local time:** The device's onboard clock is set to the local timezone of the deployment site. The epoch and all timestamps are in that same local time — there is no UTC conversion. Files moved between timezones will decode to the original deployment timezone.
#### D.5.3 Extension taxonomy