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.
This commit is contained in:
2026-04-08 14:34:42 -04:00
parent 8545daac04
commit a41e7a9e1a
9 changed files with 1121 additions and 10 deletions
+225
View File
@@ -0,0 +1,225 @@
SUB 0x1C MONITORING STATUS RESPONSE — FINAL FIELD LOCATIONS
============================================================
Source: raw_s3_20260408_015927.bin (2ndtry capture)
Frames analyzed:
- IDLE (OFF): Frame 90 at file offset 4115 (58-byte response)
- MONITORING (ON): Frame 106 at file offset 4922 (12-byte response)
================================================================================
IDLE/OFF RESPONSE (58 bytes) — COMPLETE FIELD MAP
================================================================================
HEX DUMP:
00: 2c 00 00 00 00 00 00 00 00 00 00 00 00 08 10 04
10: 07 ea 00 01 3b 2d 00 00 00 00 00 00 01 01 07 cb
20: 00 06 00 00 01 01 07 cb 00 15 00 00 00 00 10 02
30: a8 00 0e ff f2 00 0e 9e 52 ef
CONFIRMED FIELDS:
─────────────────────────────────────────────────────────────────
[00] MONITOR_MODE
Value: 0x2c (44 decimal)
Meaning: Device is IDLE (not monitoring)
When ON: 0x00
[0d] DAY
Value: 0x08 (8 decimal)
Range: 131
Date: 8th
[0e] HOUR
Value: 0x10 (16 decimal)
Range: 023
Interpretation: 4:00 PM (16:00)
[0f] MONTH
Value: 0x04 (4 decimal)
Range: 112
Meaning: April
[10:12] YEAR (uint16 BE)
Value: 0x07ea
Decimal: 2026
Full date: 2026-04-08
[12] MINUTE
Value: 0x00 (0 decimal)
Range: 059
Note: May have different encoding in other captures
[13] SECOND
Value: 0x01 (1 decimal)
Range: 059
Note: Unusually low; likely indicates sampling at minute turn-over
[2f:31] BATTERY_VOLTAGE (uint16 BE, ÷100)
Raw bytes: 0x02a8
Raw decimal: 680
Voltage: 680 ÷ 100 = 6.80 V
✓ CONFIRMED: Expected ~6.8V
Alternative encodings tested and ruled out:
- BE/1000: 0.68V (too low)
- BE/10: 68V (too high)
- float32 BE/LE: no match
- Fixed-point variations: no match
[31:35] MEMORY_TOTAL (uint32 BE, in bytes)
Raw bytes: 0x000efff2
Decimal: 983,026 bytes
Kilobytes: 983,026 ÷ 1024 = 960.0 KB
✓ CONFIRMED: Expected ~960 KB
[35:39] MEMORY_FREE (uint32 BE, in bytes)
Raw bytes: 0x000e9e52
Decimal: 958,034 bytes
Kilobytes: 958,034 ÷ 1024 = 935.6 KB
✓ CONFIRMED: Expected ~936 KB
Sanity check: 935.6 / 960.0 = 97.5% (plausible)
UNIDENTIFIED REGIONS:
─────────────────────────────────────────────────────────────────
[01:0d] PADDING/RESERVED (12 bytes)
All zeros: 00 00 00 00 00 00 00 00 00 00 00 00
[14:16] UNKNOWN (2 bytes)
Value: 0x3b2d (59, 45)
Possibly event countdown or state field
[16:2f] CONFIGURATION SNAPSHOT (25 bytes)
Contains repeating patterns suggesting sub-structures:
- Possibly trigger levels
- Possibly calibration data
- Possibly alarm settings
[39] TRAILER (1 byte)
Value: 0xef (239)
Purpose unknown
================================================================================
MONITORING/ON RESPONSE (12 bytes) — CONDENSED FORMAT
================================================================================
HEX DUMP:
00: 00 00 00 00 2c 00 00 00 00 00 00 1f
INTERPRETATION:
─────────────────────────────────────────────────────────────────
When the unit is actively monitoring, the response shrinks to 12 bytes.
Response layout appears different from idle format.
[04] POSSIBLE MONITOR_MODE (shifted position?)
Value: 0x2c
Note: In idle response this was at [00]
[0b] TRAILER (1 byte)
Value: 0x1f (31 decimal)
Different from idle trailer (0xef at [39])
All other bytes: 0x00 padding
HYPOTHESIS:
When monitoring, the device suppresses detailed fields and returns only:
- Monitor mode status (position may shift)
- A condensed state indicator
================================================================================
TIME FIELD SUMMARY (3 INTERPRETATIONS)
================================================================================
OBSERVED BYTES:
[0d] = 0x08 (day)
[0e] = 0x10 (hour)
[0f] = 0x04 (month)
[10:12] = 0x07ea (year)
[12] = 0x00 (minute)
[13] = 0x01 (second)
INTERPRETATION #1 (MOST LIKELY):
2026-04-08 16:00:01
INTERPRETATION #2 (IF BYTES ARE SWAPPED):
Could be 2026-04-08 04:10:?? (but less likely)
INTERPRETATION #3 (IF TIME IS ELSEWHERE):
Bytes at [14:16] = 0x3b2d could indicate 59 seconds, 45 ???
But structure is unclear
CONFIDENCE: MEDIUM
The date part (day/month/year) is confirmed at 2026-04-08.
The hour=16 (4 PM) seems reasonable.
Minute=00 and second=01 seem offset but may reflect the sample time.
================================================================================
VOLTAGE ENCODING VERIFICATION
================================================================================
Test: uint16 BE ÷ 100
Raw bytes: 0x02a8
As BE uint16: 680
After ÷100: 6.80 V
Expected: ~6.8V ✓ MATCH
Eliminated alternatives:
÷1000: 0.68V ✗ (too low)
÷10: 68V ✗ (too high)
float32 BE: no 6.8V match ✗
float32 LE: no 6.8V match ✗
Fixed-point 8.8: no match ✗
Fixed-point 16.0: no match ✗
CONCLUSION: uint16 BE ÷ 100 is correct encoding.
================================================================================
MEMORY ENCODING VERIFICATION
================================================================================
Test: uint32 BE (bytes), convert to KB
Memory Total:
Raw bytes: 0x000efff2
As BE uint32: 983,026
In KB: 983,026 ÷ 1024 = 960.0 KB
Spec: ~960 KB ✓ MATCH
Memory Free:
Raw bytes: 0x000e9e52
As BE uint32: 958,034
In KB: 958,034 ÷ 1024 = 935.6 KB
Spec: ~936 KB ✓ MATCH
Sanity check: free (935.6) < total (960.0) ✓
Usage: (960.0 - 935.6) / 960.0 = 2.5% (plausible)
CONCLUSION: uint32 BE (in bytes), divide by 1024 for KB.
================================================================================
PYTHON PARSING REFERENCE
================================================================================
from struct import unpack
data = bytes.fromhex("2c00000000000000000000000008100407ea00013b2d...")
monitor_mode = data[0x00]
day = data[0x0d]
hour = data[0x0e]
month = data[0x0f]
year = unpack('>H', data[0x10:0x12])[0]
minute = data[0x12]
second = data[0x13]
voltage_v = unpack('>H', data[0x2f:0x31])[0] / 100.0
memory_total_kb = unpack('>I', data[0x31:0x35])[0] / 1024.0
memory_free_kb = unpack('>I', data[0x35:0x39])[0] / 1024.0
print(f"Monitor: {['ON', 'OFF'][monitor_mode == 0x2c]}")
print(f"Date: {year:04d}-{month:02d}-{day:02d}")
print(f"Time: {hour:02d}:{minute:02d}:{second:02d}")
print(f"Battery: {voltage_v:.2f} V")
print(f"Memory: {memory_total_kb:.1f} KB total, {memory_free_kb:.1f} KB free")
================================================================================