feat: Sens'it v2 decoder + auto-detection v2/v3

Sens'it v2 has a totally different payload layout than Discovery v3:
- Bit order LSB→MSB (was MSB→LSB in v3)
- Mode in bits 0-2 (was bits 7-3 in v3)
- Battery split across bytes 0 & 1 (was 5 contiguous bits in v3)
- Temperature always sent (in T° MSB byte 1) even outside temp mode

Auto-detection uses byte 0 reserved bits: 0b110 = v3, otherwise = v2.
Frontend updated to render new fields: move_events, reed_events, fw_major/minor.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 18:02:44 +02:00
parent 2e24415224
commit 1549d4a73e
2 changed files with 118 additions and 60 deletions
+6
View File
@@ -67,8 +67,11 @@ const modeIcon = mode => ({
'Light': '💡',
'Door': '🚪',
'Vibration': '📳',
'Move': '📳',
'Magnet': '🧲',
'Reed Switch': '🧲',
'Standby / Button': '⏸️',
'Button': '🔘',
}[mode] || '❓');
function summaryLine(d) {
@@ -81,6 +84,9 @@ function summaryLine(d) {
if ('vibration_status' in d) parts.push(`vibration: ${d.vibration_status}`);
if ('magnet_status' in d) parts.push(`aimant: ${d.magnet_status}`);
if ('event_count' in d && d.mode_id > 2) parts.push(`events: ${d.event_count}`);
if ('move_events' in d) parts.push(`move: ${d.move_events}`);
if ('reed_events' in d) parts.push(`reed: ${d.reed_events}`);
if ('fw_major' in d) parts.push(`fw v${d.fw_major}.${d.fw_minor}`);
if (parts.length === 0) parts.push('heartbeat');
return parts.join(' · ');
}