#!/usr/bin/env python3 """ Test T-Embed signature matching This script: 1. Imports T-Embed signatures into database (if not already imported) 2. Tests matching engine against the same files 3. Shows matching accuracy and confidence scores """ import sys from pathlib import Path # Add project root to path sys.path.insert(0, str(Path(__file__).parent.parent)) from src.parser.sub_parser import SubFileParser from src.matcher.strategies_orm import ( FrequencyMatcherORM, TimingMatcherORM, RAWPatternMatcherORM, ExactMatcherORM ) from src.database.connection import get_session def test_matching(): """Test signature matching with T-Embed files""" print("="*70) print("T-Embed Signature Matching Test") print("="*70) print() # Get database session session = get_session() # Initialize parser and matchers parser = SubFileParser() matchers = [ ('Exact', ExactMatcherORM(session)), ('Frequency', FrequencyMatcherORM(session, tolerance_hz=10000)), ('Timing', TimingMatcherORM(session)), ('RAW Pattern', RAWPatternMatcherORM(session, min_samples=10)) ] # Find T-Embed files tembed_dir = Path(__file__).parent.parent / 'signatures' / 't-embed-rf' sub_files = sorted(tembed_dir.glob('*.sub')) print(f"Found {len(sub_files)} .sub files\n") total_files = 0 total_matches = 0 # Test each file for sub_file in sub_files: print("-"*70) print(f"File: {sub_file.name}") # Parse file try: metadata = parser.parse(str(sub_file)) except Exception as e: print(f" ❌ Parse error: {e}\n") continue # Skip empty files if metadata.frequency == 0 or (metadata.file_format == 'RAW' and not metadata.raw_data): print(f" ⏭️ Skipped: Empty capture\n") continue total_files += 1 # Show signal info print(f"\nSignal Info:") print(f" Frequency: {metadata.frequency/1e6:.2f} MHz") print(f" Protocol: {metadata.protocol or 'RAW'}") print(f" Format: {metadata.file_format}") if metadata.raw_data: abs_timings = [abs(t) for t in metadata.raw_data] print(f" RAW Samples: {len(metadata.raw_data)}") print(f" Timing Range: {min(abs_timings)}-{max(abs_timings)} μs") print(f" Avg Timing: {sum(abs_timings)/len(abs_timings):.1f} μs") # Try each matcher print(f"\nMatching Results:") file_matched = False for matcher_name, matcher in matchers: try: matches = matcher.match(metadata) if matches: file_matched = True print(f"\n {matcher_name} Matcher: {len(matches)} match(es)") # Show top 3 matches for i, match in enumerate(matches[:3], 1): print(f" {i}. {match.device_name}") print(f" Manufacturer: {match.manufacturer}") print(f" Confidence: {match.confidence:.2%}") print(f" Method: {match.match_method}") # Show match details if match.match_details: for key, value in match.match_details.items(): if key != 'signature_id': print(f" {key}: {value}") except Exception as e: print(f" ❌ {matcher_name} error: {e}") if file_matched: total_matches += 1 print(f"\n ✅ File matched successfully!") else: print(f"\n ⚠️ No matches found") print() # Summary print("="*70) print("MATCHING SUMMARY") print("="*70) print(f"Files tested: {total_files}") print(f"Files matched: {total_matches}") if total_files > 0: match_rate = (total_matches / total_files) * 100 print(f"Match rate: {match_rate:.1f}%") if match_rate == 100: print("\n✅ Perfect! All files matched to signatures") elif match_rate >= 75: print(f"\n✅ Good! Most files matched") elif match_rate >= 50: print(f"\n⚠️ Moderate: Some files unmatched") else: print(f"\n❌ Low match rate - may need more signatures or tuning") else: print("\n⚠️ No valid files to test") print("="*70) session.close() if __name__ == '__main__': test_matching()