48fcb00241
Major Achievements: - ✅ Full web interface (1,520+ lines of frontend code) - ✅ Interactive Leaflet.js map with marker clustering - ✅ Drag-and-drop upload system with GPS input - ✅ Search & filter UI with multi-criteria - ✅ Statistics dashboard with Chart.js - ✅ Responsive mobile-friendly design Backend: - ✅ FastAPI static file serving - ✅ Simplified server mode (main_simple.py) - ✅ Improved startup script with port auto-selection - ✅ PostgreSQL schema ready (requires setup) Database: - ✅ SQLite populated with 85 Flipper Zero signatures - ✅ Device matching system operational - ✅ Frequency-based search working Documentation: - ✅ PHASE_3_COMPLETE.md - Technical summary - ✅ WEB_INTERFACE_README.md - User guide - ✅ WEBAPP_STARTUP_GUIDE.md - Troubleshooting - ✅ POSTGRESQL_SETUP_EXPLANATION.md - DB setup guide - ✅ DATABASE_POPULATION_SUCCESS.md - Import report - ✅ DEVICE_IDENTIFICATION_REPORT.md - Matching analysis Files Created: - templates/index.html (260 lines) - static/css/main.css (500 lines) - static/js/*.js (760 lines total) - src/api/main_simple.py (simplified server) - start_web.sh (auto port selection) Status: Production MVP Ready Next: Phase 4 - API & Integration 🛰️ Generated with Claude Code https://claude.com/claude-code Co-Authored-By: Claude <noreply@anthropic.com>
154 lines
4.5 KiB
Python
Executable File
154 lines
4.5 KiB
Python
Executable File
#!/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()
|