189 lines
6.6 KiB
Python
Executable File
189 lines
6.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Test script for the custom IR protocol decoder
|
|
Tests the decoder against captured signal data
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import os
|
|
from custom_ir_protocol import CustomIRProtocol
|
|
|
|
def test_decoder_with_captured_data():
|
|
"""Test the custom decoder with captured signal data"""
|
|
|
|
# Load captured signals
|
|
try:
|
|
with open("ir_analysis_20250927_190536.json", 'r') as f:
|
|
signals = json.load(f)
|
|
except FileNotFoundError:
|
|
print("Error: ir_analysis_20250927_190536.json not found!")
|
|
return False
|
|
|
|
# Create custom protocol decoder
|
|
protocol = CustomIRProtocol("TEST_CUSTOM")
|
|
|
|
print("Testing Custom IR Protocol Decoder")
|
|
print("=" * 50)
|
|
print(f"Loaded {len(signals)} captured signals")
|
|
print()
|
|
|
|
# Test signals with 71 pulses (most common)
|
|
successful_decodes = 0
|
|
failed_decodes = 0
|
|
decoded_commands = {}
|
|
|
|
for i, signal_data in enumerate(signals):
|
|
pulse_count = signal_data['pulse_count']
|
|
pulses = signal_data['pulses']
|
|
|
|
# Convert to the format expected by the decoder
|
|
# (is_pulse, duration_in_seconds)
|
|
formatted_pulses = []
|
|
for j, duration_us in enumerate(pulses):
|
|
is_pulse = (j % 2 == 0) # Alternating pulse/space
|
|
duration_seconds = duration_us / 1000000.0
|
|
formatted_pulses.append((is_pulse, duration_seconds))
|
|
|
|
# Try to decode
|
|
command = protocol.decode(formatted_pulses)
|
|
|
|
if command:
|
|
successful_decodes += 1
|
|
if command not in decoded_commands:
|
|
decoded_commands[command] = 0
|
|
decoded_commands[command] += 1
|
|
|
|
print(f"Signal {i+1:2d} ({pulse_count:2d} pulses): {command}")
|
|
else:
|
|
failed_decodes += 1
|
|
if pulse_count == 71: # Only show failed 71-pulse signals
|
|
print(f"Signal {i+1:2d} ({pulse_count:2d} pulses): FAILED TO DECODE")
|
|
|
|
print()
|
|
print("=" * 50)
|
|
print("DECODING RESULTS")
|
|
print("=" * 50)
|
|
print(f"Successful decodes: {successful_decodes}")
|
|
print(f"Failed decodes: {failed_decodes}")
|
|
print(f"Success rate: {successful_decodes/(successful_decodes+failed_decodes)*100:.1f}%")
|
|
print()
|
|
|
|
if decoded_commands:
|
|
print("Decoded commands:")
|
|
for command, count in sorted(decoded_commands.items()):
|
|
print(f" {command}: {count} occurrences")
|
|
print()
|
|
|
|
# Analyze timing patterns for failed decodes
|
|
print("Analyzing timing patterns...")
|
|
analyze_timing_patterns(signals, protocol)
|
|
|
|
return successful_decodes > 0
|
|
|
|
def analyze_timing_patterns(signals, protocol):
|
|
"""Analyze timing patterns to help debug the decoder"""
|
|
|
|
print("\nTiming analysis for 71-pulse signals:")
|
|
print("-" * 40)
|
|
|
|
for signal_data in signals:
|
|
if signal_data['pulse_count'] == 71:
|
|
pulses = signal_data['pulses']
|
|
|
|
# Check header
|
|
if len(pulses) >= 2:
|
|
header_pulse = pulses[0]
|
|
header_space = pulses[1]
|
|
|
|
print(f"Header: {header_pulse:.0f}μs pulse, {header_space:.0f}μs space")
|
|
|
|
# Check if header matches expected timing
|
|
pulse_match = protocol._is_timing_match(header_pulse, protocol.HEADER_PULSE)
|
|
space_match = protocol._is_timing_match(header_space, protocol.HEADER_SPACE)
|
|
|
|
print(f" Header pulse match: {pulse_match}")
|
|
print(f" Header space match: {space_match}")
|
|
|
|
# Analyze first few data bits
|
|
if len(pulses) >= 6:
|
|
print(" First data bits:")
|
|
for i in range(2, min(8, len(pulses)), 2):
|
|
if i + 1 < len(pulses):
|
|
pulse_time = pulses[i]
|
|
space_time = pulses[i + 1]
|
|
|
|
pulse_match = protocol._is_timing_match(pulse_time, protocol.BIT_PULSE)
|
|
space_0_match = protocol._is_timing_match(space_time, protocol.BIT_0_SPACE)
|
|
space_1_match = protocol._is_timing_match(space_time, protocol.BIT_1_SPACE)
|
|
|
|
bit_value = "?"
|
|
if space_0_match:
|
|
bit_value = "0"
|
|
elif space_1_match:
|
|
bit_value = "1"
|
|
|
|
print(f" Bit {(i-2)//2}: {pulse_time:.0f}μs pulse, {space_time:.0f}μs space -> {bit_value}")
|
|
|
|
break # Only analyze first 71-pulse signal
|
|
|
|
def create_mapping_file():
|
|
"""Create a mapping file for the decoded commands"""
|
|
|
|
# Example mapping based on common IR remote patterns
|
|
mapping = {
|
|
"CUSTOM_0000_0001": {
|
|
"command": "power_toggle",
|
|
"description": "Power on/off",
|
|
"repeatable": True
|
|
},
|
|
"CUSTOM_0000_0002": {
|
|
"command": "channel_1",
|
|
"description": "Channel 1",
|
|
"repeatable": False
|
|
},
|
|
"CUSTOM_0000_0003": {
|
|
"command": "channel_2",
|
|
"description": "Channel 2",
|
|
"repeatable": False
|
|
},
|
|
"CUSTOM_0000_0004": {
|
|
"command": "channel_3",
|
|
"description": "Channel 3",
|
|
"repeatable": False
|
|
},
|
|
"CUSTOM_0000_0005": {
|
|
"command": "volume_up",
|
|
"description": "Volume up",
|
|
"repeatable": True
|
|
},
|
|
"CUSTOM_0000_0006": {
|
|
"command": "volume_down",
|
|
"description": "Volume down",
|
|
"repeatable": True
|
|
},
|
|
"REPEAT": {
|
|
"command": "repeat_last",
|
|
"description": "Repeat last command",
|
|
"repeatable": False
|
|
}
|
|
}
|
|
|
|
with open("custom_ir_mapping.json", "w") as f:
|
|
json.dump(mapping, f, indent=2)
|
|
|
|
print("Created custom_ir_mapping.json with example mappings")
|
|
|
|
if __name__ == "__main__":
|
|
success = test_decoder_with_captured_data()
|
|
|
|
if success:
|
|
print("\nDecoder test completed successfully!")
|
|
print("You can now integrate the custom protocol into your IR system.")
|
|
create_mapping_file()
|
|
else:
|
|
print("\nDecoder test failed. Check the timing constants and protocol structure.")
|
|
print("You may need to adjust the timing values in custom_ir_protocol.py")
|
|
|
|
sys.exit(0 if success else 1)
|