Fix device detection format and pipeline deployment compatibility

Device Detection Updates:
- Update device series detection to use product_id mapping (0x100 -> KL520, 0x720 -> KL720)
- Handle JSON dict format from kp.core.scan_devices() properly
- Extract usb_port_id correctly from device descriptors
- Support multiple device descriptor formats (dict, list, object)
- Enhanced debug output shows Product ID for verification

Pipeline Deployment Fixes:
- Remove invalid preprocessor/postprocessor parameters from MultiDongle constructor
- Add max_queue_size parameter support to MultiDongle
- Fix pipeline stage initialization to match MultiDongle constructor
- Add auto_detect parameter support for pipeline stages
- Store stage processors as instance variables for future use

Example Updates:
- Update device_detection_example.py to show Product ID in output
- Enhanced error handling and format detection

Resolves pipeline deployment error: "MultiDongle.__init__() got an unexpected keyword argument 'preprocessor'"
Now properly handles real device descriptors with correct product_id to series mapping.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Masonmason 2025-07-16 21:45:14 +08:00
parent 918b9aabd1
commit e0169cd845
3 changed files with 103 additions and 28 deletions

View File

@ -49,11 +49,15 @@ class PipelineStage:
ncpu_fw_path=config.ncpu_fw_path,
model_path=config.model_path,
upload_fw=config.upload_fw,
preprocessor=config.stage_preprocessor,
postprocessor=config.stage_postprocessor,
auto_detect=config.auto_detect if hasattr(config, 'auto_detect') else False,
max_queue_size=config.max_queue_size
)
# Store preprocessor and postprocessor for later use
self.stage_preprocessor = config.stage_preprocessor
self.stage_postprocessor = config.stage_postprocessor
self.max_queue_size = config.max_queue_size
# Inter-stage processors
self.input_preprocessor = config.input_preprocessor
self.output_postprocessor = config.output_postprocessor

View File

@ -95,12 +95,40 @@ class MultiDongle:
return []
devices_info = []
# Handle both dict and object formats
if isinstance(device_descriptors, dict):
# Handle JSON dict format: {"0": {...}, "1": {...}}
print(f' - Found {len(device_descriptors)} device(s):')
for key, device_desc in device_descriptors.items():
# Get device series using product_id
series = MultiDongle._get_device_series(device_desc)
# Use usb_port_id from the device descriptor
port_id = device_desc.get('usb_port_id', 0)
device_info = {
'port_id': port_id,
'series': series,
'device_descriptor': device_desc
}
devices_info.append(device_info)
print(f' [{int(key)+1}] Port ID: {port_id}, Series: {series}, Product ID: {device_desc.get("product_id", "Unknown")}')
elif isinstance(device_descriptors, (list, tuple)):
# Handle list/array format
print(f' - Found {len(device_descriptors)} device(s):')
for i, device_desc in enumerate(device_descriptors):
# Get device series (e.g., KL520, KL720, etc.)
# Get device series
series = MultiDongle._get_device_series(device_desc)
port_id = device_desc.port_id
# Extract port_id based on format
if isinstance(device_desc, dict):
port_id = device_desc.get('usb_port_id', device_desc.get('port_id', 0))
else:
port_id = getattr(device_desc, 'usb_port_id', getattr(device_desc, 'port_id', 0))
device_info = {
'port_id': port_id,
@ -110,6 +138,24 @@ class MultiDongle:
devices_info.append(device_info)
print(f' [{i+1}] Port ID: {port_id}, Series: {series}')
else:
# Handle single device or other formats
print(' - Found 1 device:')
series = MultiDongle._get_device_series(device_descriptors)
if isinstance(device_descriptors, dict):
port_id = device_descriptors.get('usb_port_id', device_descriptors.get('port_id', 0))
else:
port_id = getattr(device_descriptors, 'usb_port_id', getattr(device_descriptors, 'port_id', 0))
device_info = {
'port_id': port_id,
'series': series,
'device_descriptor': device_descriptors
}
devices_info.append(device_info)
print(f' [1] Port ID: {port_id}, Series: {series}')
return devices_info
@ -120,16 +166,42 @@ class MultiDongle:
@staticmethod
def _get_device_series(device_descriptor):
"""
Extract device series from device descriptor.
Extract device series from device descriptor using product_id.
Args:
device_descriptor: Device descriptor from scan_devices()
device_descriptor: Device descriptor from scan_devices() - can be dict or object
Returns:
str: Device series (e.g., 'KL520', 'KL720', etc.)
"""
try:
# Try to get the chip from device descriptor
# Product ID to device series mapping
product_id_mapping = {
'0x100': 'KL520',
'0x720': 'KL720',
'0x630': 'KL630',
'0x730': 'KL730',
'0x540': 'KL540',
# Add more mappings as needed
}
# Handle dict format (from JSON)
if isinstance(device_descriptor, dict):
product_id = device_descriptor.get('product_id', '')
if product_id in product_id_mapping:
return product_id_mapping[product_id]
return f'Unknown ({product_id})'
# Handle object format (from SDK)
if hasattr(device_descriptor, 'product_id'):
product_id = device_descriptor.product_id
if isinstance(product_id, int):
product_id = hex(product_id)
if product_id in product_id_mapping:
return product_id_mapping[product_id]
return f'Unknown ({product_id})'
# Legacy chip-based detection (fallback)
if hasattr(device_descriptor, 'chip'):
chip = device_descriptor.chip
if chip == kp.ModelNefDescriptor.KP_CHIP_KL520:
@ -142,17 +214,8 @@ class MultiDongle:
return 'KL730'
elif chip == kp.ModelNefDescriptor.KP_CHIP_KL540:
return 'KL540'
elif chip == kp.ModelNefDescriptor.KP_CHIP_KL630_LEGACY:
return 'KL630_LEGACY'
elif chip == kp.ModelNefDescriptor.KP_CHIP_KL720_LEGACY:
return 'KL720_LEGACY'
elif chip == kp.ModelNefDescriptor.KP_CHIP_KL520_LEGACY:
return 'KL520_LEGACY'
# Fallback: try to get from device descriptor attributes
if hasattr(device_descriptor, 'product_name'):
return device_descriptor.product_name
# Final fallback
return 'Unknown'
except Exception as e:
@ -195,7 +258,7 @@ class MultiDongle:
except kp.ApiKPException as exception:
raise Exception(f'Failed to connect devices: {str(exception)}')
def __init__(self, port_id: list = None, scpu_fw_path: str = None, ncpu_fw_path: str = None, model_path: str = None, upload_fw: bool = False, auto_detect: bool = False):
def __init__(self, port_id: list = None, scpu_fw_path: str = None, ncpu_fw_path: str = None, model_path: str = None, upload_fw: bool = False, auto_detect: bool = False, max_queue_size: int = 0):
"""
Initialize the MultiDongle class.
:param port_id: List of USB port IDs for the same layer's devices. If None and auto_detect=True, will auto-detect devices.
@ -204,6 +267,7 @@ class MultiDongle:
:param model_path: Path to the model file.
:param upload_fw: Flag to indicate whether to upload firmware.
:param auto_detect: Flag to auto-detect and connect to available devices.
:param max_queue_size: Maximum size for internal queues. If 0, unlimited queues are used.
"""
self.auto_detect = auto_detect
self.connected_devices_info = []
@ -234,8 +298,11 @@ class MultiDongle:
self.generic_inference_input_descriptor = None
# Queues for data
# Input queue for images to be sent
if max_queue_size > 0:
self._input_queue = queue.Queue(maxsize=max_queue_size)
self._output_queue = queue.Queue(maxsize=max_queue_size)
else:
self._input_queue = queue.Queue()
# Output queue for received results
self._output_queue = queue.Queue()
# Threading attributes

View File

@ -28,7 +28,9 @@ def example_device_scan():
print(f"Found {len(devices)} device(s):")
for i, device in enumerate(devices):
print(f" [{i+1}] Port ID: {device['port_id']}, Series: {device['series']}")
desc = device['device_descriptor']
product_id = desc.get('product_id', 'Unknown') if isinstance(desc, dict) else 'Unknown'
print(f" [{i+1}] Port ID: {device['port_id']}, Series: {device['series']}, Product ID: {product_id}")
except Exception as e:
print(f"Error during device scan: {str(e)}")
@ -47,7 +49,9 @@ def example_auto_connect():
print(f"Successfully connected to {len(connected_devices)} device(s):")
for i, device in enumerate(connected_devices):
print(f" [{i+1}] Port ID: {device['port_id']}, Series: {device['series']}")
desc = device['device_descriptor']
product_id = desc.get('product_id', 'Unknown') if isinstance(desc, dict) else 'Unknown'
print(f" [{i+1}] Port ID: {device['port_id']}, Series: {device['series']}, Product ID: {product_id}")
# Disconnect devices
import kp