feat: Phase 0 accuracy fix - category routing + confidence calibration

Adds a rules-based device category router that classifies a signal by
frequency band + timing ratio + pulse count BEFORE the per-protocol
scoring loop, restricting the candidate set. This fixes the "everything
matches a weather sensor with 69-76% false confidence" problem.

- src/matcher/category_router.py: frequency-band + timing routing
- pattern_decoder.py: category filter, category-mismatch penalty,
  post-match spread penalty (surfaces low-discrimination cases)
- protocol_database.py: garage door / doorbell / fan controller entries
- scripts/benchmark_phase0.py: real-world-shaped benchmark

Benchmark gate: top-3 accuracy 0% -> 67% (target >=30%). 52/52 unit
tests pass. NOTE: benchmark .sub files are synthetic-from-DB-params,
so 67% is an upper bound pending real Flipper capture validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
leetcrypt
2026-07-18 13:09:43 -07:00
parent 422a1e1d2e
commit 1b9b33fa3f
4 changed files with 1105 additions and 40 deletions
+314 -4
View File
@@ -182,7 +182,7 @@ GARAGE_DOOR_OPENERS = [
typical_pulse_count=60,
),
ProtocolSignature(
name="Chamberlain/LiftMaster",
name="Chamberlain/LiftMaster 315MHz",
category="Garage Door Opener",
manufacturer="Chamberlain",
short_pulse_us=300,
@@ -191,7 +191,36 @@ GARAGE_DOOR_OPENERS = [
min_bits=32,
max_bits=40,
typical_pulse_count=80,
frequency=315000000, # 315 MHz
frequency=315000000,
),
ProtocolSignature(
name="LiftMaster 433MHz",
category="Garage Door Opener",
manufacturer="LiftMaster",
# Fixed-code LiftMaster (pre-Security+) at 433 MHz
# Uses ~350µs SHORT, ~1050µs LONG (3:1 ratio like Princeton but 40-bit)
short_pulse_us=350,
long_pulse_us=1050,
encoding=Encoding.PWM,
min_bits=32,
max_bits=40,
typical_pulse_count=90,
frequency=433920000,
),
ProtocolSignature(
name="LiftMaster Security+ 2.0",
category="Garage Door Opener",
manufacturer="LiftMaster",
# Security+ 2.0 uses rolling code — we can only detect the family by
# its distinctive 390 MHz carrier and ~300µs pulse width
short_pulse_us=300,
long_pulse_us=600,
encoding=Encoding.PWM,
min_bits=40,
max_bits=66,
typical_pulse_count=100,
frequency=390000000,
frequency_tolerance=2000000,
),
ProtocolSignature(
name="Linear MegaCode",
@@ -203,7 +232,67 @@ GARAGE_DOOR_OPENERS = [
min_bits=32,
max_bits=32,
typical_pulse_count=70,
frequency=318000000, # 318 MHz
frequency=318000000,
),
ProtocolSignature(
name="Marantec D302 / D304",
category="Garage Door Opener",
manufacturer="Marantec",
short_pulse_us=1000,
long_pulse_us=2000,
encoding=Encoding.PWM,
min_bits=12,
max_bits=16,
typical_pulse_count=35,
frequency=433920000,
),
ProtocolSignature(
name="FAAC XT2 / XT4",
category="Garage Door Opener",
manufacturer="FAAC",
short_pulse_us=500,
long_pulse_us=1500,
encoding=Encoding.PWM,
min_bits=40,
max_bits=64,
typical_pulse_count=110,
frequency=433920000,
),
ProtocolSignature(
name="Came TOP432 / BRC802",
category="Garage Door Opener",
manufacturer="Came",
short_pulse_us=500,
long_pulse_us=1000,
encoding=Encoding.PWM,
min_bits=12,
max_bits=24,
typical_pulse_count=55,
frequency=433920000,
),
ProtocolSignature(
name="BFT Mitto Rolling Code",
category="Garage Door Opener",
manufacturer="BFT",
short_pulse_us=500,
long_pulse_us=1500,
encoding=Encoding.PWM,
min_bits=52,
max_bits=64,
typical_pulse_count=125,
frequency=433920000,
),
ProtocolSignature(
name="CAME-АТЛАС Gate Remote",
category="Garage Door Opener",
manufacturer="Came",
short_pulse_us=320,
long_pulse_us=960,
encoding=Encoding.PWM,
min_bits=24,
max_bits=24,
typical_pulse_count=55,
frequency=433920000,
),
]
@@ -219,6 +308,71 @@ DOORBELLS = [
max_bits=48,
typical_pulse_count=100,
),
ProtocolSignature(
name="Byron Doorbell",
category="Doorbell",
manufacturer="Byron",
# Byron WE-series: Princeton-like OOK, 300-400us SHORT, 3:1 ratio
short_pulse_us=350,
long_pulse_us=1050,
encoding=Encoding.PWM,
preamble_pattern="1" * 4,
sync_pattern="10000", # Long sync gap
min_bits=24,
max_bits=32,
typical_pulse_count=60,
frequency=433920000,
),
ProtocolSignature(
name="GE Doorbell",
category="Doorbell",
manufacturer="GE",
# GE wireless doorbell 433 MHz, ~250us SHORT, 2:1 ratio
short_pulse_us=250,
long_pulse_us=500,
encoding=Encoding.PWM,
min_bits=24,
max_bits=48,
typical_pulse_count=80,
frequency=433920000,
),
ProtocolSignature(
name="Heidemann Doorbell",
category="Doorbell",
manufacturer="Heidemann",
short_pulse_us=400,
long_pulse_us=1200,
encoding=Encoding.PWM,
min_bits=12,
max_bits=24,
typical_pulse_count=40,
frequency=433920000,
),
ProtocolSignature(
name="Elro DB286A Doorbell",
category="Doorbell",
manufacturer="Elro",
short_pulse_us=300,
long_pulse_us=900,
encoding=Encoding.PWM,
preamble_pattern="1" * 4,
min_bits=24,
max_bits=24,
typical_pulse_count=50,
frequency=433920000,
),
ProtocolSignature(
name="Blyss Doorbell",
category="Doorbell",
manufacturer="Blyss",
short_pulse_us=500,
long_pulse_us=1500,
encoding=Encoding.PWM,
min_bits=32,
max_bits=40,
typical_pulse_count=80,
frequency=433920000,
),
]
TIRE_PRESSURE = [
@@ -299,7 +453,19 @@ REMOTE_CONTROLS = [
typical_pulse_count=50,
),
ProtocolSignature(
name="HCS301",
name="Generic Remote SC226x EV1527",
category="Remote Control",
manufacturer=None,
short_pulse_us=320,
long_pulse_us=960,
encoding=Encoding.PWM,
min_bits=24,
max_bits=24,
typical_pulse_count=52,
frequency=433920000,
),
ProtocolSignature(
name="HCS301 Rolling Code",
category="Remote Control",
manufacturer="Microchip",
short_pulse_us=400,
@@ -309,6 +475,149 @@ REMOTE_CONTROLS = [
max_bits=66,
typical_pulse_count=140,
),
ProtocolSignature(
name="RGB LED Remote Controller",
category="Remote Control",
manufacturer=None,
# Most 433 MHz RGB LED remotes use EV1527-like encoding
short_pulse_us=300,
long_pulse_us=900,
encoding=Encoding.PWM,
min_bits=24,
max_bits=24,
typical_pulse_count=52,
frequency=433920000,
),
ProtocolSignature(
name="Nice Flor-S Rolling Code",
category="Remote Control",
manufacturer="Nice",
short_pulse_us=500,
long_pulse_us=1000,
encoding=Encoding.PWM,
min_bits=52,
max_bits=56,
typical_pulse_count=115,
frequency=433920000,
),
ProtocolSignature(
name="FAAC SLH Rolling Code",
category="Remote Control",
manufacturer="FAAC",
short_pulse_us=500,
long_pulse_us=1500,
encoding=Encoding.PWM,
min_bits=40,
max_bits=64,
typical_pulse_count=110,
frequency=433920000,
),
ProtocolSignature(
name="Somfy RTS",
category="Remote Control",
manufacturer="Somfy",
# Somfy RTS uses Manchester at 433.42 MHz
short_pulse_us=604,
long_pulse_us=1208,
encoding=Encoding.MANCHESTER,
min_bits=56,
max_bits=56,
typical_pulse_count=120,
frequency=433420000,
frequency_tolerance=50000,
),
ProtocolSignature(
name="Holtek HT12X Remote",
category="Remote Control",
manufacturer="Holtek",
short_pulse_us=300,
long_pulse_us=900,
encoding=Encoding.PWM,
preamble_pattern="1" * 36, # Long burst sync
min_bits=12,
max_bits=12,
typical_pulse_count=52,
frequency=433920000,
),
]
FAN_CONTROLLERS = [
ProtocolSignature(
name="Hampton Bay Ceiling Fan Remote",
category="Fan Controller",
manufacturer="Hampton Bay",
# Most common: 303 MHz or 433 MHz, OOK, 12-bit dip-switch code
short_pulse_us=300,
long_pulse_us=900,
encoding=Encoding.PWM,
min_bits=12,
max_bits=24,
typical_pulse_count=45,
frequency=303900000,
frequency_tolerance=200000,
),
ProtocolSignature(
name="Hampton Bay Ceiling Fan Remote 433MHz",
category="Fan Controller",
manufacturer="Hampton Bay",
short_pulse_us=320,
long_pulse_us=960,
encoding=Encoding.PWM,
min_bits=12,
max_bits=24,
typical_pulse_count=45,
frequency=433920000,
),
ProtocolSignature(
name="Hunter Fan Remote",
category="Fan Controller",
manufacturer="Hunter",
short_pulse_us=250,
long_pulse_us=750,
encoding=Encoding.PWM,
min_bits=16,
max_bits=32,
typical_pulse_count=55,
frequency=433920000,
),
ProtocolSignature(
name="Harbor Breeze Ceiling Fan Remote",
category="Fan Controller",
manufacturer="Harbor Breeze",
short_pulse_us=300,
long_pulse_us=900,
encoding=Encoding.PWM,
min_bits=12,
max_bits=24,
typical_pulse_count=50,
frequency=433920000,
),
ProtocolSignature(
name="Westinghouse Fan Remote",
category="Fan Controller",
manufacturer="Westinghouse",
short_pulse_us=330,
long_pulse_us=990,
encoding=Encoding.PWM,
min_bits=16,
max_bits=24,
typical_pulse_count=48,
frequency=303900000,
frequency_tolerance=200000,
),
ProtocolSignature(
name="Generic Ceiling Fan Remote (EV1527)",
category="Fan Controller",
manufacturer=None,
# Many cheap ceiling fans use EV1527 at 433 MHz
short_pulse_us=300,
long_pulse_us=900,
encoding=Encoding.PWM,
min_bits=24,
max_bits=24,
typical_pulse_count=52,
frequency=433920000,
),
]
@@ -327,6 +636,7 @@ ALL_PROTOCOLS = (
TIRE_PRESSURE +
SECURITY_SENSORS +
REMOTE_CONTROLS +
FAN_CONTROLLERS +
RTL433_PROTOCOLS # Imported from RTL_433 database
)