|
| 1 | +# Plugin Architecture |
| 2 | + |
| 3 | +This document describes the plugin architecture of the ArduPilot Methodic Configurator, |
| 4 | +which allows extending the application with modular components for UI enhancements and workflow automation. |
| 5 | + |
| 6 | +## Overview |
| 7 | + |
| 8 | +The plugin system enables developers to add new functionality to the application without modifying the core codebase. |
| 9 | +There are two types of plugins: |
| 10 | + |
| 11 | +1. **UI Plugins**: Provide persistent user interface components (e.g., motor test panels) |
| 12 | +2. **Workflow Plugins**: Execute triggered actions (e.g., IMU temperature calibration workflows) |
| 13 | + |
| 14 | +## Architecture Principles |
| 15 | + |
| 16 | +### Separation of Concerns |
| 17 | + |
| 18 | +- **Business Logic**: Encapsulated in data models with no UI dependencies |
| 19 | +- **UI Coordination**: Handled by coordinators that orchestrate user interactions |
| 20 | +- **Dependency Injection**: UI callbacks injected into business logic for testability |
| 21 | + |
| 22 | +### Plugin Lifecycle |
| 23 | + |
| 24 | +- **Registration**: Plugins register themselves with factories during application startup |
| 25 | +- **Discovery**: The system discovers available plugins through factory queries |
| 26 | +- **Instantiation**: Plugins are created on-demand with appropriate context |
| 27 | +- **Execution**: UI plugins remain active; workflow plugins execute once and complete |
| 28 | + |
| 29 | +## UI Plugin System |
| 30 | + |
| 31 | +### UI Components |
| 32 | + |
| 33 | +#### Plugin Factory UI (`plugin_factory_ui.py`) |
| 34 | + |
| 35 | +- Manages registration and creation of UI plugins |
| 36 | +- Provides a registry of plugin creators |
| 37 | +- Ensures unique plugin names |
| 38 | + |
| 39 | +#### Plugin Constants (`plugin_constants.py`) |
| 40 | + |
| 41 | +- Defines string constants for plugin identifiers |
| 42 | +- Centralizes plugin naming for consistency |
| 43 | + |
| 44 | +#### Registration (`__main__.py`) |
| 45 | + |
| 46 | +- Plugins register their creators during application initialization |
| 47 | +- Ensures plugins are available when needed |
| 48 | + |
| 49 | +### UI Implementation Pattern |
| 50 | + |
| 51 | +```python |
| 52 | +# 1. Define plugin constant |
| 53 | +PLUGIN_MOTOR_TEST = "motor_test" |
| 54 | + |
| 55 | +# 2. Create plugin view class |
| 56 | +class MotorTestView: |
| 57 | + def __init__(self, parent, model, base_window): |
| 58 | + # Implementation |
| 59 | + |
| 60 | +# 3. Create factory function |
| 61 | +def create_motor_test_view(parent, model, base_window): |
| 62 | + return MotorTestView(parent, model, base_window) |
| 63 | + |
| 64 | +# 4. Register plugin |
| 65 | +plugin_factory_ui.register(PLUGIN_MOTOR_TEST, create_motor_test_view) |
| 66 | +``` |
| 67 | + |
| 68 | +### UI usage in Parameter Editor |
| 69 | + |
| 70 | +- UI plugins are instantiated when a parameter file with plugin configuration is selected |
| 71 | +- Plugins receive parent frame, data model, and base window references |
| 72 | +- Plugins manage their own lifecycle and cleanup |
| 73 | + |
| 74 | +## Workflow Plugin System |
| 75 | + |
| 76 | +### Workflow Components |
| 77 | + |
| 78 | +#### Plugin Factory Workflow (`plugin_factory_workflow.py`) |
| 79 | + |
| 80 | +- Manages registration and creation of workflow plugins |
| 81 | +- Symmetric API to UI plugin factory |
| 82 | +- Handles one-time execution workflows |
| 83 | + |
| 84 | +#### Data Models |
| 85 | + |
| 86 | +- Contain business logic with no UI dependencies |
| 87 | +- Use dependency injection for user interactions |
| 88 | +- Implement callback-based interfaces for testability |
| 89 | + |
| 90 | +#### Workflow Coordinators |
| 91 | + |
| 92 | +- Handle UI orchestration for workflows |
| 93 | +- Manage progress indicators and user feedback |
| 94 | +- Ensure proper cleanup after execution |
| 95 | + |
| 96 | +### Workflow Implementation Pattern |
| 97 | + |
| 98 | +```python |
| 99 | +# 1. Define plugin constant |
| 100 | +PLUGIN_TEMPCAL_IMU = "tempcal_imu" |
| 101 | + |
| 102 | +# 2. Create data model class |
| 103 | +class TempCalIMUDataModel: |
| 104 | + def __init__(self, config_manager, step_filename, callbacks...): |
| 105 | + # Business logic only |
| 106 | + |
| 107 | + def run_calibration(self) -> bool: |
| 108 | + # Orchestrate workflow using injected callbacks |
| 109 | + |
| 110 | +# 3. Create workflow coordinator class |
| 111 | +class TempCalIMUWorkflow: |
| 112 | + def __init__(self, root_window, data_model): |
| 113 | + # UI coordination |
| 114 | + |
| 115 | + def run_workflow(self) -> bool: |
| 116 | + # Execute workflow with UI feedback |
| 117 | + |
| 118 | +# 4. Create factory function |
| 119 | +def create_tempcal_imu_workflow(root_window, data_model): |
| 120 | + return TempCalIMUWorkflow(root_window, data_model) |
| 121 | + |
| 122 | +# 5. Register plugin |
| 123 | +plugin_factory_workflow.register(PLUGIN_TEMPCAL_IMU, create_tempcal_imu_workflow) |
| 124 | +``` |
| 125 | + |
| 126 | +### Workflow usage in Parameter Editor |
| 127 | + |
| 128 | +- Workflow plugins are triggered when specific parameter files are selected |
| 129 | +- Configuration manager creates data models with injected UI callbacks |
| 130 | +- Workflow coordinators handle execution and provide user feedback |
| 131 | +- Cleanup ensures resources are released after completion |
| 132 | + |
| 133 | +## Configuration Integration |
| 134 | + |
| 135 | +### JSON Schema Updates |
| 136 | + |
| 137 | +The configuration schema supports plugin definitions: |
| 138 | + |
| 139 | +```json |
| 140 | +{ |
| 141 | + "plugin": { |
| 142 | + "name": "tempcal_imu", |
| 143 | + "placement": "workflow" |
| 144 | + } |
| 145 | +} |
| 146 | +``` |
| 147 | + |
| 148 | +### Supported Placements |
| 149 | + |
| 150 | +- `"left"`: Plugin appears left of scrollable content |
| 151 | +- `"top"`: Plugin appears above content |
| 152 | +- `"workflow"`: Plugin executes as a triggered workflow |
| 153 | + |
| 154 | +## Testing Strategy |
| 155 | + |
| 156 | +### Unit Testing |
| 157 | + |
| 158 | +- Business logic tested in isolation with mocked callbacks |
| 159 | +- Plugin factories tested for registration and creation |
| 160 | +- Data models tested for all execution paths |
| 161 | + |
| 162 | +### Integration Testing |
| 163 | + |
| 164 | +- End-to-end plugin execution workflows |
| 165 | +- UI interaction verification |
| 166 | +- Configuration loading and plugin discovery |
| 167 | + |
| 168 | +## Implementation Notes |
| 169 | + |
| 170 | +### Error Handling |
| 171 | + |
| 172 | +- Plugin loading failures don't prevent application startup |
| 173 | +- Individual plugin errors are logged and isolated |
| 174 | +- Graceful degradation when plugins are unavailable |
| 175 | + |
| 176 | +### Performance Considerations |
| 177 | + |
| 178 | +- Lazy loading prevents startup delays |
| 179 | +- Plugin instantiation on-demand reduces memory usage |
| 180 | +- Callback-based design minimizes coupling overhead |
0 commit comments