Commit Graph

12 Commits

Author SHA1 Message Date
Brian Harrison
824322597a fix: validate offset size in build_bw_frame and adjust payload construction 2026-04-01 13:28:00 -04:00
Brian Harrison
7e501620fc fix: skip trigger/alarm extraction pending offset confirmation
The heuristic offsets for trigger/alarm levels were causing struct unpack
errors. These fields require detailed field mapping from actual E5 captures
to determine exact byte positions relative to channel labels.

For now, skip extraction and leave trigger_level_geo/alarm_level_geo as None.
This prevents the '500 Device error: bytes must be in range(0, 256)' error.

Once we capture an E5 response and map the exact float positions, we can
re-enable this section with correct offsets.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-01 13:07:04 -04:00
Brian Harrison
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
Brian Harrison
4944974f6e feat: decode waveform record timestamp, record type, and Peak Vector Sum
Confirmed 2026-04-01 against Blastware event report for BE11529 thump
event ("00:28:12 April 1, 2026", PVS 3.906 in/s).

models.py:
- Timestamp.from_waveform_record(): decode 9-byte format from 0C record
  bytes[0-8]: [day][sub_code][month][year:2BE][?][hour][min][sec]
- Timestamp: add hour/minute/second optional fields; __str__ includes
  time when available
- PeakValues: add peak_vector_sum field (confirmed fixed offset 87)

client.py:
- _decode_waveform_record_into: add timestamp decode from bytes[0:9]
- _extract_record_type: decode byte[1] (sub_code), not ASCII string
  search; 0x10 → "Waveform", histogram TBD
- _extract_peak_floats: add PVS from offset 87 (IEEE 754 BE float32)
  = √(T²+V²+L²) at max instantaneous vector moment

sfm/server.py:
- _serialise_timestamp: add hour/minute/second/day fields to JSON
- _serialise_peak_values: add peak_vector_sum to JSON

docs: update §7.7.5 and §8 with confirmed 9-byte timestamp layout,
PVS field, and byte[1] record type encoding; update command table;
close resolved open questions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 00:53:34 -04:00
Brian Harrison
f74992f4e5 fix: serial decode offset, PPV label scan, debug mode for waveform records
- _decode_serial_number: read from data[11:] not data[:8] — was returning
  the LENGTH_ECHO byte (0x0A = '\n') instead of the serial string
- _extract_peak_floats: search for channel label strings ("Tran" etc) and
  read float at label+6; old step-4 aligned scan was reading trigger levels
  instead of PPV values
- get_events: add debug=False param; stashes raw 210-byte record on
  Event._raw_record when True for field-layout inspection
- server /device/events: add ?debug=true query param; includes
  raw_record_hex + raw_record_len in response when set
- models: add Event._raw_record optional bytes field
2026-03-31 23:46:07 -04:00
Brian Harrison
9f52745bb4 feat: add full event download pipeline 2026-03-31 20:48:03 -04:00
Brian Harrison
8074bf0fee bump timeout to 30s to deal with modem slowness. 2026-03-31 12:12:36 -04:00
Brian Harrison
51d1aa917a Add TCP/modem transport (Sierra Wireless RV55/RX55 field units)
- minimateplus/transport.py: add TcpTransport — stdlib socket-based transport
  with same interface as SerialTransport. Overrides read_until_idle() with
  idle_gap=1.5s to absorb the modem's 1-second serial data forwarding buffer.
- minimateplus/client.py: make `port` param optional (default "") so
  MiniMateClient works cleanly when a pre-built transport is injected.
- minimateplus/__init__.py: export SerialTransport and TcpTransport.
- sfm/server.py: add `host` / `tcp_port` query params to all device endpoints.
  New _build_client() helper selects TCP or serial transport automatically.
  OSError (connection refused, timeout) now returns HTTP 502.
- docs/instantel_protocol_reference.md: add changelog entry and full §14
  (TCP/Modem Transport) documenting confirmed transparent passthrough, no ENQ
  on connect, modem forwarding delay, call-up vs ACH modes, and hardware note
  deprecating Raven X in favour of RV55/RX55.

Usage: GET /device/info?host=<modem_ip>&tcp_port=12345
2026-03-31 00:44:50 -04:00
Brian Harrison
3f142ce1c0 fix: stop raising on S3 checksum mismatches 2026-03-31 00:15:07 -04:00
serversdwn
88adcbcb81 fix: s3parser now looks for bare ETX, not DLE+ETX. 2026-03-31 00:10:13 -04:00
serversdwn
8e985154a7 bumps timeout up 2026-03-30 23:46:34 -04:00
serversdwn
f8f590b19b sfm first build 2026-03-30 23:23:29 -04:00