fix: v3 payload byte 1 layout — 10-bit sensor data, button on bit 2
Sens'it Discovery v3 byte 1 layout per official spec: bits 7-3: mode bit 2 : special / button alert bits 1-0: MSB (2 bits) of sensor data Previous decoder had button on bit 0 and used only bit 2 as data MSB (9-bit values). Real payloads confirmed 10-bit: e.g. b609a861 was decoded as -4°C but correctly resolves to 28°C with the fixed layout. Fixes applied consistently to all v3 modes: - Temperature: 10-bit temp with formula (raw - 200) / 8 - Light: 10-bit brightness with formula raw / 96 - Door/Vibration/Magnet: 2-bit status from bits 1-0 Existing DB entries re-decoded in place.
This commit is contained in:
@@ -18,8 +18,13 @@ V3_MODES = {
|
|||||||
|
|
||||||
|
|
||||||
def _decode_v3(b0: int, b1: int, b2: int, b3: int) -> dict:
|
def _decode_v3(b0: int, b1: int, b2: int, b3: int) -> dict:
|
||||||
|
# byte 1 layout per Sens'it Discovery v3 spec:
|
||||||
|
# bits 7-3: mode
|
||||||
|
# bit 2 : special / button alert
|
||||||
|
# bits 1-0: 2 MSB bits of sensor data (giving 10-bit values with b2)
|
||||||
battery_raw = (b0 >> 3) & 0x1F
|
battery_raw = (b0 >> 3) & 0x1F
|
||||||
mode = (b1 >> 3) & 0x1F
|
mode = (b1 >> 3) & 0x1F
|
||||||
|
data_msb = b1 & 0x03
|
||||||
result = {
|
result = {
|
||||||
"format": "sensit_v3",
|
"format": "sensit_v3",
|
||||||
"battery": round(battery_raw * 0.05 + 2.7, 2),
|
"battery": round(battery_raw * 0.05 + 2.7, 2),
|
||||||
@@ -27,24 +32,24 @@ def _decode_v3(b0: int, b1: int, b2: int, b3: int) -> dict:
|
|||||||
"reserved_ok": True,
|
"reserved_ok": True,
|
||||||
"mode": V3_MODES.get(mode, f"Unknown ({mode})"),
|
"mode": V3_MODES.get(mode, f"Unknown ({mode})"),
|
||||||
"mode_id": mode,
|
"mode_id": mode,
|
||||||
"button_alert": bool(b1 & 0x01),
|
"button_alert": bool((b1 >> 2) & 0x01),
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode == 1: # Temperature + Humidity
|
if mode == 1: # Temperature + Humidity (10-bit temp)
|
||||||
temp_raw = (((b1 >> 2) & 0x01) << 8) | b2
|
temp_raw = (data_msb << 8) | b2
|
||||||
result["temperature_c"] = round((temp_raw - 200) / 8, 2)
|
result["temperature_c"] = round((temp_raw - 200) / 8, 2)
|
||||||
result["humidity_pct"] = round(b3 / 2, 1)
|
result["humidity_pct"] = round(b3 / 2, 1)
|
||||||
elif mode == 2: # Light
|
elif mode == 2: # Light (10-bit brightness)
|
||||||
brightness_raw = (((b1 >> 2) & 0x01) << 8) | b2
|
brightness_raw = (data_msb << 8) | b2
|
||||||
result["brightness_lux"] = round(brightness_raw / 96, 2)
|
result["brightness_lux"] = round(brightness_raw / 96, 2)
|
||||||
elif mode == 3:
|
elif mode == 3:
|
||||||
result["door_status"] = {0: "closed", 1: "opened", 2: "opening_alert", 3: "closing_alert"}.get((b1 >> 1) & 0x03, "unknown")
|
result["door_status"] = {0: "closed", 1: "opened", 2: "opening_alert", 3: "closing_alert"}.get(data_msb, "unknown")
|
||||||
result["event_count"] = (b2 << 8) | b3
|
result["event_count"] = (b2 << 8) | b3
|
||||||
elif mode == 4:
|
elif mode == 4:
|
||||||
result["vibration_status"] = {0: "no_vibration", 1: "vibration_detected"}.get((b1 >> 1) & 0x03, "unknown")
|
result["vibration_status"] = {0: "no_vibration", 1: "vibration_detected"}.get(data_msb, "unknown")
|
||||||
result["event_count"] = (b2 << 8) | b3
|
result["event_count"] = (b2 << 8) | b3
|
||||||
elif mode == 5:
|
elif mode == 5:
|
||||||
result["magnet_status"] = {0: "no_magnet", 1: "magnet_detected"}.get((b1 >> 1) & 0x03, "unknown")
|
result["magnet_status"] = {0: "no_magnet", 1: "magnet_detected"}.get(data_msb, "unknown")
|
||||||
result["event_count"] = (b2 << 8) | b3
|
result["event_count"] = (b2 << 8) | b3
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user