feat: Add Upload Firmware checkbox to Model Node properties panel

- Add upload_fw property with enhanced UI checkbox styling
- Connect checkbox to inference pipeline process
- Enable/disable firmware upload based on user selection
- Add visual feedback and logging for firmware upload status

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
HuangMason320 2025-07-31 01:13:49 +08:00
parent b8e95f56cb
commit 77bd8324ab
4 changed files with 70 additions and 17 deletions

View File

@ -17,7 +17,7 @@ class StageConfig:
scpu_fw_path: str scpu_fw_path: str
ncpu_fw_path: str ncpu_fw_path: str
model_path: str model_path: str
upload_fw: bool = False upload_fw: bool
max_queue_size: int = 50 max_queue_size: int = 50
# Inter-stage processing # Inter-stage processing
input_preprocessor: Optional[PreProcessor] = None # Before this stage input_preprocessor: Optional[PreProcessor] = None # Before this stage

View File

@ -293,16 +293,16 @@ class MultiDongle:
print('[Set Device Timeout]') print('[Set Device Timeout]')
print(' - Skipped (prevents camera connection crashes)') print(' - Skipped (prevents camera connection crashes)')
# if self.upload_fw: if self.upload_fw:
try: try:
print('[Upload Firmware]') print('[Upload Firmware]')
kp.core.load_firmware_from_file(device_group=self.device_group, kp.core.load_firmware_from_file(device_group=self.device_group,
scpu_fw_path=self.scpu_fw_path, scpu_fw_path=self.scpu_fw_path,
ncpu_fw_path=self.ncpu_fw_path) ncpu_fw_path=self.ncpu_fw_path)
print(' - Success') print(' - Success')
except kp.ApiKPException as exception: except kp.ApiKPException as exception:
print('Error: upload firmware failed, error = \'{}\''.format(str(exception))) print('Error: upload firmware failed, error = \'{}\''.format(str(exception)))
sys.exit(1) sys.exit(1)
# upload model to device # upload model to device
try: try:

View File

@ -122,7 +122,8 @@ class ExactModelNode(BaseNode):
'model_path': {'type': 'file_path', 'filter': 'NEF Model files (*.nef)'}, 'model_path': {'type': 'file_path', 'filter': 'NEF Model files (*.nef)'},
'scpu_fw_path': {'type': 'file_path', 'filter': 'SCPU Firmware files (*.bin)'}, 'scpu_fw_path': {'type': 'file_path', 'filter': 'SCPU Firmware files (*.bin)'},
'ncpu_fw_path': {'type': 'file_path', 'filter': 'NCPU Firmware files (*.bin)'}, 'ncpu_fw_path': {'type': 'file_path', 'filter': 'NCPU Firmware files (*.bin)'},
'port_id': {'placeholder': 'e.g., 8080 or auto'} 'port_id': {'placeholder': 'e.g., 8080 or auto'},
'upload_fw': {'type': 'bool', 'default': True, 'description': 'Upload firmware to dongle if needed'}
} }
# Create custom properties dictionary for UI compatibility # Create custom properties dictionary for UI compatibility

View File

@ -1170,7 +1170,7 @@ class IntegratedPipelineDashboard(QMainWindow):
'fps': node.get_property('fps') if hasattr(node, 'get_property') else 30 'fps': node.get_property('fps') if hasattr(node, 'get_property') else 30
} }
elif 'Model' in node_type: elif 'Model' in node_type:
# Exact ModelNode properties from original # Exact ModelNode properties from original - including upload_fw checkbox
properties = { properties = {
'model_path': node.get_property('model_path') if hasattr(node, 'get_property') else '', 'model_path': node.get_property('model_path') if hasattr(node, 'get_property') else '',
'scpu_fw_path': node.get_property('scpu_fw_path') if hasattr(node, 'get_property') else '', 'scpu_fw_path': node.get_property('scpu_fw_path') if hasattr(node, 'get_property') else '',
@ -1211,9 +1211,13 @@ class IntegratedPipelineDashboard(QMainWindow):
# Create widget based on property type and name # Create widget based on property type and name
widget = self.create_property_widget_enhanced(node, prop_name, prop_value) widget = self.create_property_widget_enhanced(node, prop_name, prop_value)
# Add to form # Add to form with appropriate labels
label = prop_name.replace('_', ' ').title() if prop_name == 'upload_fw':
form_layout.addRow(f"{label}:", widget) # For upload_fw, don't show a separate label since the checkbox has its own text
form_layout.addRow(widget)
else:
label = prop_name.replace('_', ' ').title()
form_layout.addRow(f"{label}:", widget)
else: else:
# Show available properties for debugging # Show available properties for debugging
info_text = f"Node type: {node.__class__.__name__}\n" info_text = f"Node type: {node.__class__.__name__}\n"
@ -1338,13 +1342,61 @@ class IntegratedPipelineDashboard(QMainWindow):
widget.currentTextChanged.connect(on_change) widget.currentTextChanged.connect(on_change)
elif isinstance(prop_value, bool): elif isinstance(prop_value, bool):
# Boolean property # Boolean property (like upload_fw checkbox)
widget = QCheckBox() widget = QCheckBox()
widget.setChecked(prop_value) widget.setChecked(prop_value)
# Add special styling for upload_fw checkbox
if prop_name == 'upload_fw':
widget.setText("Upload Firmware to Device")
widget.setStyleSheet("""
QCheckBox {
color: #cdd6f4;
font-size: 11px;
padding: 2px;
}
QCheckBox::indicator {
width: 16px;
height: 16px;
border-radius: 3px;
border: 2px solid #45475a;
background-color: #313244;
}
QCheckBox::indicator:checked {
background-color: #89b4fa;
border-color: #89b4fa;
}
QCheckBox::indicator:hover {
border-color: #74c7ec;
}
""")
else:
widget.setStyleSheet("""
QCheckBox {
color: #cdd6f4;
font-size: 11px;
padding: 2px;
}
QCheckBox::indicator {
width: 14px;
height: 14px;
border-radius: 2px;
border: 1px solid #45475a;
background-color: #313244;
}
QCheckBox::indicator:checked {
background-color: #a6e3a1;
border-color: #a6e3a1;
}
""")
def on_change(state): def on_change(state):
if hasattr(node, 'set_property'): if hasattr(node, 'set_property'):
node.set_property(prop_name, state == 2) node.set_property(prop_name, state == 2)
# For upload_fw, also print confirmation
if prop_name == 'upload_fw':
status = "enabled" if state == 2 else "disabled"
print(f"Upload Firmware {status} for {node.name()}")
widget.stateChanged.connect(on_change) widget.stateChanged.connect(on_change)