Initial commit: Phase 1 & Phase 2 infrastructure complete

This commit is contained in:
2026-01-12 11:21:17 -08:00
commit eb225771bc
53 changed files with 13645 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
"""
Main signature matching engine
"""
from dataclasses import dataclass
from typing import List, Optional, Dict, Any
from loguru import logger
from ..parser.metadata import SignalMetadata
@dataclass
class MatchResult:
"""Result of a signature match"""
device_id: int
device_name: str
manufacturer: str
confidence: float # 0.0 to 1.0
match_method: str # 'exact', 'partial', 'pattern', 'timing'
match_details: Dict[str, Any]
def to_dict(self) -> Dict:
"""Convert to dictionary"""
return {
'device_id': self.device_id,
'device_name': self.device_name,
'manufacturer': self.manufacturer,
'confidence': self.confidence,
'match_method': self.match_method,
'match_details': self.match_details
}
class SignatureMatcher:
"""
Main signature matching engine
Coordinates multiple matching strategies to identify devices
from RF signal metadata
"""
def __init__(self, database):
"""
Initialize matcher with database connection
Args:
database: Database connection for signature queries
"""
self.db = database
self.strategies = []
def add_strategy(self, strategy):
"""Add a matching strategy"""
self.strategies.append(strategy)
def match(self, metadata: SignalMetadata, max_results: int = 10) -> List[MatchResult]:
"""
Match signal metadata against signature database
Args:
metadata: Parsed signal metadata
max_results: Maximum number of results to return
Returns:
List of MatchResult objects sorted by confidence
"""
all_matches = []
# Run all matching strategies
for strategy in self.strategies:
try:
matches = strategy.match(metadata, self.db)
all_matches.extend(matches)
except Exception as e:
logger.error(f"Strategy {strategy.__class__.__name__} failed: {e}")
# Deduplicate and sort
unique_matches = self._deduplicate_matches(all_matches)
sorted_matches = sorted(unique_matches, key=lambda x: x.confidence, reverse=True)
return sorted_matches[:max_results]
def _deduplicate_matches(self, matches: List[MatchResult]) -> List[MatchResult]:
"""
Deduplicate matches, keeping highest confidence for each device
Args:
matches: List of match results
Returns:
Deduplicated list
"""
device_map = {}
for match in matches:
if match.device_id not in device_map:
device_map[match.device_id] = match
else:
# Keep higher confidence match
if match.confidence > device_map[match.device_id].confidence:
device_map[match.device_id] = match
return list(device_map.values())
class MatchStrategy:
"""Base class for matching strategies"""
def match(self, metadata: SignalMetadata, db) -> List[MatchResult]:
"""
Match metadata against database
Args:
metadata: Signal metadata
db: Database connection
Returns:
List of MatchResult objects
"""
raise NotImplementedError