#!/usr/bin/env python3 """ Match T-Embed captures against Flipper Zero signature database Demonstrates device identification using expanded signature knowledge base """ import sys from pathlib import Path from typing import List, Dict # Add project root to path sys.path.insert(0, str(Path(__file__).parent.parent)) from src.parser.sub_parser import SubFileParser def load_flipper_signatures(flipper_dir: Path) -> List[Dict]: """Load all Flipper Zero signatures""" parser = SubFileParser() signatures = [] for sub_file in flipper_dir.glob('**/*.sub'): try: metadata = parser.parse(str(sub_file)) signatures.append({ 'device_name': sub_file.stem, 'filename': sub_file.name, 'frequency': metadata.frequency, 'protocol': metadata.protocol or 'RAW', 'file_format': metadata.file_format, 'bit_length': metadata.bit_length, 'has_raw': bool(metadata.raw_data), 'raw_samples': len(metadata.raw_data) if metadata.raw_data else 0 }) except: pass return signatures def match_by_frequency(target_freq: int, signatures: List[Dict], tolerance_hz: int = 10000) -> List[Dict]: """Match by frequency with tolerance""" matches = [] for sig in signatures: freq_diff = abs(sig['frequency'] - target_freq) if freq_diff <= tolerance_hz: confidence = 1.0 - (freq_diff / tolerance_hz) confidence = max(0.5, confidence) matches.append({ 'signature': sig, 'confidence': confidence, 'freq_diff_hz': freq_diff, 'match_method': 'frequency' }) return sorted(matches, key=lambda x: x['confidence'], reverse=True) def main(): """Main entry point""" print("="*80) print("DEVICE MATCHING: T-Embed vs Flipper Zero Database") print("="*80) print() # Load Flipper signatures flipper_dir = Path(__file__).parent.parent / 'signatures' / 'flipperzero-firmware' if not flipper_dir.exists(): print("❌ Flipper Zero database not found") return 1 print("Loading Flipper Zero signature database...") signatures = load_flipper_signatures(flipper_dir) print(f"✅ Loaded {len(signatures)} signatures\n") # Load T-Embed capture tembed_dir = Path(__file__).parent.parent / 'signatures' / 't-embed-rf' parser = SubFileParser() tembed_file = tembed_dir / 'raw_7.sub' print(f"Analyzing T-Embed capture: {tembed_file.name}") print("-"*80) metadata = parser.parse(str(tembed_file)) print(f"Frequency: {metadata.frequency/1e6:.2f} MHz") print(f"Protocol: {metadata.protocol or 'RAW (undecoded)'}") print(f"Format: {metadata.file_format}") if metadata.raw_data: print(f"RAW Samples: {len(metadata.raw_data)}") print(f"\n{'='*80}") print("MATCHING AGAINST FLIPPER ZERO DATABASE") print(f"{'='*80}\n") # Match by frequency (±10 kHz tolerance) matches = match_by_frequency(metadata.frequency, signatures, tolerance_hz=10000) if matches: print(f"Found {len(matches)} potential matches:\n") for i, match in enumerate(matches[:10], 1): sig = match['signature'] print(f"{i}. {sig['device_name']}") print(f" Frequency: {sig['frequency']/1e6:.3f} MHz (diff: {match['freq_diff_hz']/1000:.1f} kHz)") print(f" Protocol: {sig['protocol']}") print(f" Format: {sig['file_format']}") print(f" Confidence: {match['confidence']:.1%}") print() # Best match best = matches[0] print(f"{'='*80}") print(f"BEST MATCH: {best['signature']['device_name']}") print(f"Confidence: {best['confidence']:.1%}") print(f"Method: Frequency matching ({best['freq_diff_hz']/1000:.1f} kHz difference)") print(f"{'='*80}") else: print("❌ No matches found in Flipper Zero database") print("\nThis device is at 915 MHz (ISM band)") print("Flipper Zero database contains mostly 433 MHz devices") print("\nTo improve matching:") print("- Import RTL_433 database (has 915 MHz devices)") print("- Add more T-Embed captures from wardriving") print("- Import community-contributed 915 MHz signatures") print(f"\n{'='*80}") print("DATABASE COVERAGE ANALYSIS") print(f"{'='*80}\n") # Analyze frequency coverage freq_groups = {} for sig in signatures: freq_mhz = sig['frequency'] / 1e6 freq_band = f"{int(freq_mhz/100)*100}-{int(freq_mhz/100)*100+100}" if freq_band not in freq_groups: freq_groups[freq_band] = 0 freq_groups[freq_band] += 1 print("Frequency Band Coverage:") for band in sorted(freq_groups.keys()): print(f" {band} MHz: {freq_groups[band]} devices") # Check if 915 MHz covered target_freq = metadata.frequency / 1e6 target_band = f"{int(target_freq/100)*100}-{int(target_freq/100)*100+100}" print(f"\nTarget device: {target_freq:.2f} MHz ({target_band} MHz band)") if target_band in freq_groups: print(f"✅ Coverage: {freq_groups[target_band]} devices in target band") else: print(f"❌ No coverage: Target band not in Flipper database") print("\n" + "="*80) return 0 if __name__ == '__main__': sys.exit(main())