Phase 1 & 2: Cleanup redundant code and integrate pattern decoder
## Phase 1: Code Cleanup (~1,859 lines removed) **Deleted Redundant Matchers:** - ❌ strategies_orm.py (356 lines) - Old ORM-based strategies - ❌ simple_matcher.py (351 lines) - Replaced by strategies.py - ❌ rtl433_matcher.py (352 lines) - Replaced by strategies.py **Archived Old Scripts:** - Moved 11 one-time analysis/import scripts to scripts/archive/ - Scripts: analyze_flipper_signatures, analyze_tembed_files, identify_tembed_devices, import_flipper_sqlite, import_tembed_signatures, match_tembed_with_db, match_with_flipper_db, rematch_captures, test_gps_extraction, test_tembed_matching, test_wardriving_import **Consolidated API:** - Renamed main.py → main_orm_legacy.py (archived old ORM-based API) - main_simple.py is now the primary production API ## Phase 2: Pattern Decoder Integration ✅ **CRITICAL FIX: Pattern decoder now integrated into production API!** **Changes:** 1. Updated main_simple.py to use unified SignatureMatcher 2. Added 6 strategies to matcher pipeline: - ExactMatcher (protocol + frequency) - FrequencyMatcher (frequency-based) - BitPatternMatcher (data patterns) - TimingMatcher (timing-based) - RTL433DecoderStrategy (RTL_433 decoder) - PatternBasedStrategy (NEW! Pattern decoder for short captures) 3. Created MockDB class for simplified mode (no real database) 4. Replaced old get_matcher() with get_matcher_engine() 5. Updated upload handler to use MatchResult format 6. All matches now include confidence scores and match methods **Result:** - Pattern decoder is NOW ACTIVE in production 🎉 - Unified matching pipeline with 6 strategies - Cleaner codebase (-1,859 lines) - Single source of truth for matching logic 🎉 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+156
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Analyze Flipper Zero signature database
|
||||
|
||||
Parses all Flipper Zero .sub files and creates a comprehensive device signature database
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from collections import defaultdict
|
||||
from typing import Dict, List
|
||||
|
||||
# Add project root to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from src.parser.sub_parser import SubFileParser
|
||||
|
||||
|
||||
def analyze_flipper_database(flipper_dir: Path):
|
||||
"""Analyze all Flipper Zero .sub files"""
|
||||
|
||||
print("="*80)
|
||||
print("FLIPPER ZERO SIGNATURE DATABASE ANALYSIS")
|
||||
print("="*80)
|
||||
print()
|
||||
|
||||
parser = SubFileParser()
|
||||
|
||||
# Find all .sub files
|
||||
sub_files = list(flipper_dir.glob('**/*.sub'))
|
||||
print(f"Found {len(sub_files)} Flipper Zero .sub files\n")
|
||||
|
||||
# Parse all files
|
||||
signatures = []
|
||||
parse_errors = []
|
||||
|
||||
for sub_file in sub_files:
|
||||
try:
|
||||
metadata = parser.parse(str(sub_file))
|
||||
|
||||
# Extract device name from path
|
||||
device_name = sub_file.stem
|
||||
|
||||
signatures.append({
|
||||
'filename': sub_file.name,
|
||||
'device_name': device_name,
|
||||
'path': str(sub_file.relative_to(flipper_dir)),
|
||||
'frequency': metadata.frequency,
|
||||
'protocol': metadata.protocol,
|
||||
'file_format': metadata.file_format,
|
||||
'modulation': metadata.modulation,
|
||||
'bit_length': metadata.bit_length,
|
||||
'has_raw_data': bool(metadata.raw_data),
|
||||
'raw_samples': len(metadata.raw_data) if metadata.raw_data else 0
|
||||
})
|
||||
except Exception as e:
|
||||
parse_errors.append((sub_file.name, str(e)))
|
||||
|
||||
print(f"Successfully parsed: {len(signatures)} files")
|
||||
print(f"Parse errors: {len(parse_errors)} files\n")
|
||||
|
||||
# Analyze by frequency
|
||||
print("-"*80)
|
||||
print("FREQUENCY DISTRIBUTION")
|
||||
print("-"*80)
|
||||
|
||||
freq_groups = defaultdict(list)
|
||||
for sig in signatures:
|
||||
freq_mhz = sig['frequency'] / 1e6 if sig['frequency'] else 0
|
||||
freq_groups[freq_mhz].append(sig)
|
||||
|
||||
for freq in sorted(freq_groups.keys()):
|
||||
if freq > 0:
|
||||
count = len(freq_groups[freq])
|
||||
print(f"{freq:8.2f} MHz: {count:3d} devices")
|
||||
|
||||
# Analyze by protocol
|
||||
print(f"\n{'-'*80}")
|
||||
print("PROTOCOL DISTRIBUTION")
|
||||
print("-"*80)
|
||||
|
||||
protocol_groups = defaultdict(list)
|
||||
for sig in signatures:
|
||||
proto = sig['protocol'] or 'RAW'
|
||||
protocol_groups[proto].append(sig)
|
||||
|
||||
for proto in sorted(protocol_groups.keys(), key=lambda x: len(protocol_groups[x]), reverse=True)[:15]:
|
||||
count = len(protocol_groups[proto])
|
||||
print(f"{proto:30s}: {count:3d} devices")
|
||||
|
||||
# Analyze by format
|
||||
print(f"\n{'-'*80}")
|
||||
print("FILE FORMAT DISTRIBUTION")
|
||||
print("-"*80)
|
||||
|
||||
format_groups = defaultdict(list)
|
||||
for sig in signatures:
|
||||
format_groups[sig['file_format']].append(sig)
|
||||
|
||||
for fmt in sorted(format_groups.keys()):
|
||||
count = len(format_groups[fmt])
|
||||
print(f"{fmt:10s}: {count:3d} files")
|
||||
|
||||
# Show sample devices by frequency band
|
||||
print(f"\n{'-'*80}")
|
||||
print("SAMPLE DEVICES BY FREQUENCY BAND")
|
||||
print("-"*80)
|
||||
|
||||
# Group into common RF bands
|
||||
bands = {
|
||||
'300-350 MHz (Garage/Gate)': (300, 350),
|
||||
'400-450 MHz (Key Fobs/Remotes)': (400, 450),
|
||||
'800-900 MHz (Sensors/Utility)': (800, 900),
|
||||
'900-930 MHz (ISM Band - US)': (900, 930)
|
||||
}
|
||||
|
||||
for band_name, (min_freq, max_freq) in bands.items():
|
||||
matching = [s for s in signatures
|
||||
if min_freq <= (s['frequency']/1e6) <= max_freq]
|
||||
|
||||
print(f"\n{band_name}: {len(matching)} devices")
|
||||
|
||||
# Show first 10
|
||||
for sig in matching[:10]:
|
||||
print(f" - {sig['device_name']:40s} {sig['frequency']/1e6:7.2f} MHz {sig['protocol'] or 'RAW'}")
|
||||
|
||||
return signatures, parse_errors
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point"""
|
||||
|
||||
flipper_dir = Path(__file__).parent.parent / 'signatures' / 'flipperzero-firmware'
|
||||
|
||||
if not flipper_dir.exists():
|
||||
print(f"❌ Flipper Zero directory not found: {flipper_dir}")
|
||||
print("Run: git clone https://github.com/flipperdevices/flipperzero-firmware.git")
|
||||
return 1
|
||||
|
||||
signatures, errors = analyze_flipper_database(flipper_dir)
|
||||
|
||||
# Summary
|
||||
print(f"\n{'='*80}")
|
||||
print("SUMMARY")
|
||||
print(f"{'='*80}")
|
||||
print(f"Total signatures: {len(signatures)}")
|
||||
print(f"Parse errors: {len(errors)}")
|
||||
print(f"\nThese signatures can now be imported into GigLez database")
|
||||
print(f"for device matching against wardriving captures.")
|
||||
print("="*80)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user