petal-user-journey-coordinator 0.1.5__py3-none-any.whl → 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- petal_user_journey_coordinator/controllers.py +83 -96
- petal_user_journey_coordinator/data_model.py +104 -24
- petal_user_journey_coordinator/plugin.py +649 -135
- {petal_user_journey_coordinator-0.1.5.dist-info → petal_user_journey_coordinator-0.1.7.dist-info}/METADATA +1 -1
- petal_user_journey_coordinator-0.1.7.dist-info/RECORD +8 -0
- petal_user_journey_coordinator-0.1.5.dist-info/RECORD +0 -8
- {petal_user_journey_coordinator-0.1.5.dist-info → petal_user_journey_coordinator-0.1.7.dist-info}/WHEEL +0 -0
- {petal_user_journey_coordinator-0.1.5.dist-info → petal_user_journey_coordinator-0.1.7.dist-info}/entry_points.txt +0 -0
|
@@ -810,22 +810,10 @@ class ESCCalibrationController(BaseTimeoutController):
|
|
|
810
810
|
self.logger.error(f"[{message_id}] Unknown throttle type: {throttle_type}")
|
|
811
811
|
return False
|
|
812
812
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
command_msg = self.mavlink_proxy.master.mav.command_long_encode(
|
|
818
|
-
1, # TODO: investigate best practice
|
|
819
|
-
1, # TODO: investigate best practice
|
|
820
|
-
mavutil.mavlink.MAV_CMD_ACTUATOR_TEST,
|
|
821
|
-
0, # confirmation
|
|
822
|
-
param1, # Motor value (0-1 or NaN)
|
|
823
|
-
timeout, # Timeout in seconds
|
|
824
|
-
0, # Reserved
|
|
825
|
-
0, # Reserved
|
|
826
|
-
param5, # Motor mapping (110x)
|
|
827
|
-
0, # Reserved
|
|
828
|
-
0 # Reserved
|
|
813
|
+
command_msg = self.mavlink_proxy.build_motor_value_command(
|
|
814
|
+
motor_idx=motor_idx,
|
|
815
|
+
motor_value=param1,
|
|
816
|
+
timeout=timeout
|
|
829
817
|
)
|
|
830
818
|
|
|
831
819
|
# Send the command
|
|
@@ -833,7 +821,7 @@ class ESCCalibrationController(BaseTimeoutController):
|
|
|
833
821
|
|
|
834
822
|
action = "maximum throttle" if throttle_type == "maximum" else \
|
|
835
823
|
"minimum throttle" if throttle_type == "minimum" else "stopped"
|
|
836
|
-
self.logger.info(f"[{message_id}] Motor {motor_idx}: {action} (
|
|
824
|
+
self.logger.info(f"[{message_id}] Motor {motor_idx}: {action} (motor value={param1}, timeout={timeout}s)")
|
|
837
825
|
|
|
838
826
|
# Small delay between motor commands
|
|
839
827
|
await asyncio.sleep(0.1)
|
|
@@ -1019,22 +1007,11 @@ class ESCForceRunAllController(BaseTimeoutController):
|
|
|
1019
1007
|
"""Send MAV_CMD_ACTUATOR_TEST command to all motors."""
|
|
1020
1008
|
try:
|
|
1021
1009
|
for motor_idx in range(1, self.motor_count + 1):
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
1, # TODO: investigate best practice
|
|
1028
|
-
1, # TODO: investigate best practice
|
|
1029
|
-
mavutil.mavlink.MAV_CMD_ACTUATOR_TEST,
|
|
1030
|
-
0, # confirmation
|
|
1031
|
-
motor_value, # Motor value (0-1 or NaN)
|
|
1032
|
-
timeout, # Timeout in seconds
|
|
1033
|
-
0, # Reserved
|
|
1034
|
-
0, # Reserved
|
|
1035
|
-
param5, # Motor mapping (110x)
|
|
1036
|
-
0, # Reserved
|
|
1037
|
-
0 # Reserved
|
|
1010
|
+
|
|
1011
|
+
command_msg = self.mavlink_proxy.build_motor_value_command(
|
|
1012
|
+
motor_idx=motor_idx,
|
|
1013
|
+
motor_value=motor_value,
|
|
1014
|
+
timeout=timeout
|
|
1038
1015
|
)
|
|
1039
1016
|
|
|
1040
1017
|
# Send the command
|
|
@@ -1056,21 +1033,11 @@ class ESCForceRunAllController(BaseTimeoutController):
|
|
|
1056
1033
|
nan_value = float('nan')
|
|
1057
1034
|
|
|
1058
1035
|
for motor_idx in range(1, self.motor_count + 1):
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
1, # TODO: investigate best practice
|
|
1065
|
-
mavutil.mavlink.MAV_CMD_ACTUATOR_TEST,
|
|
1066
|
-
0, # confirmation
|
|
1067
|
-
nan_value, # Motor value (0-1 or NaN)
|
|
1068
|
-
0.0, # Timeout in seconds
|
|
1069
|
-
0, # Reserved
|
|
1070
|
-
0, # Reserved
|
|
1071
|
-
param5, # Motor mapping (110x)
|
|
1072
|
-
0, # Reserved
|
|
1073
|
-
0 # Reserved
|
|
1036
|
+
|
|
1037
|
+
command_msg = self.mavlink_proxy.build_motor_value_command(
|
|
1038
|
+
motor_idx=motor_idx,
|
|
1039
|
+
motor_value=nan_value,
|
|
1040
|
+
timeout=0.0
|
|
1074
1041
|
)
|
|
1075
1042
|
|
|
1076
1043
|
# Send the command
|
|
@@ -1250,22 +1217,11 @@ class ESCForceRunSingleController(BaseTimeoutController):
|
|
|
1250
1217
|
async def _send_actuator_test_single_motor(self, motor_value: float, timeout: float) -> bool:
|
|
1251
1218
|
"""Send MAV_CMD_ACTUATOR_TEST command to single motor."""
|
|
1252
1219
|
try:
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
1, # TODO: investigate best practice
|
|
1259
|
-
1, # TODO: investigate best practice
|
|
1260
|
-
mavutil.mavlink.MAV_CMD_ACTUATOR_TEST,
|
|
1261
|
-
0, # confirmation
|
|
1262
|
-
motor_value, # Motor value (0-1 or NaN)
|
|
1263
|
-
timeout, # Timeout in seconds
|
|
1264
|
-
0, # Reserved
|
|
1265
|
-
0, # Reserved
|
|
1266
|
-
param5, # Motor mapping (110x)
|
|
1267
|
-
0, # Reserved
|
|
1268
|
-
0 # Reserved
|
|
1220
|
+
|
|
1221
|
+
command_msg = self.mavlink_proxy.build_motor_value_command(
|
|
1222
|
+
motor_idx=self.target_motor,
|
|
1223
|
+
motor_value=motor_value,
|
|
1224
|
+
timeout=timeout
|
|
1269
1225
|
)
|
|
1270
1226
|
|
|
1271
1227
|
# Send the command
|
|
@@ -1284,23 +1240,13 @@ class ESCForceRunSingleController(BaseTimeoutController):
|
|
|
1284
1240
|
try:
|
|
1285
1241
|
# Use NaN to stop motor
|
|
1286
1242
|
nan_value = float('nan')
|
|
1287
|
-
param5 = float(1100 + self.target_motor)
|
|
1288
1243
|
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
mavutil.mavlink.MAV_CMD_ACTUATOR_TEST,
|
|
1294
|
-
0, # confirmation
|
|
1295
|
-
nan_value, # Motor value (0-1 or NaN)
|
|
1296
|
-
0.0, # Timeout in seconds
|
|
1297
|
-
0, # Reserved
|
|
1298
|
-
0, # Reserved
|
|
1299
|
-
param5, # Motor mapping (110x)
|
|
1300
|
-
0, # Reserved
|
|
1301
|
-
0 # Reserved
|
|
1244
|
+
command_msg = self.mavlink_proxy.build_motor_value_command(
|
|
1245
|
+
motor_idx=self.target_motor,
|
|
1246
|
+
motor_value=nan_value,
|
|
1247
|
+
timeout=0.0
|
|
1302
1248
|
)
|
|
1303
|
-
|
|
1249
|
+
|
|
1304
1250
|
# Send the command
|
|
1305
1251
|
self.mavlink_proxy.send("mav", command_msg)
|
|
1306
1252
|
|
|
@@ -1447,7 +1393,15 @@ class BasePubSubController(ABC):
|
|
|
1447
1393
|
3. Stop publishing when receiving petal-user-journey-coordinator/unsubscribe_<stream_name>
|
|
1448
1394
|
"""
|
|
1449
1395
|
|
|
1450
|
-
def __init__(
|
|
1396
|
+
def __init__(
|
|
1397
|
+
self,
|
|
1398
|
+
stream_name: str,
|
|
1399
|
+
mqtt_proxy: MQTTProxy,
|
|
1400
|
+
mavlink_proxy: MavLinkExternalProxy,
|
|
1401
|
+
logger: logging.Logger,
|
|
1402
|
+
petal_name: str = "petal-user-journey-coordinator"
|
|
1403
|
+
):
|
|
1404
|
+
self.petal_name = petal_name
|
|
1451
1405
|
self.stream_name = stream_name
|
|
1452
1406
|
self.mqtt_proxy = mqtt_proxy
|
|
1453
1407
|
self.mavlink_proxy = mavlink_proxy
|
|
@@ -1544,7 +1498,7 @@ class BasePubSubController(ABC):
|
|
|
1544
1498
|
|
|
1545
1499
|
mqtt_message = {
|
|
1546
1500
|
"messageId": str(uuid.uuid4()),
|
|
1547
|
-
"command": f"/
|
|
1501
|
+
"command": f"/{self.petal_name}/publish_{self.stream_name}",
|
|
1548
1502
|
"timestamp": datetime.now().isoformat(),
|
|
1549
1503
|
"payload": publish_payload.model_dump()
|
|
1550
1504
|
}
|
|
@@ -1568,8 +1522,14 @@ class BasePubSubController(ABC):
|
|
|
1568
1522
|
class RCChannelsController(BasePubSubController):
|
|
1569
1523
|
"""Controller for streaming RC_CHANNELS MAVLink data."""
|
|
1570
1524
|
|
|
1571
|
-
def __init__(
|
|
1572
|
-
|
|
1525
|
+
def __init__(
|
|
1526
|
+
self,
|
|
1527
|
+
mqtt_proxy: MQTTProxy,
|
|
1528
|
+
mavlink_proxy: MavLinkExternalProxy,
|
|
1529
|
+
logger: logging.Logger,
|
|
1530
|
+
petal_name: str = "petal-user-journey-coordinator"
|
|
1531
|
+
):
|
|
1532
|
+
super().__init__("rc_value_stream", mqtt_proxy, mavlink_proxy, logger, petal_name=petal_name)
|
|
1573
1533
|
self._latest_sample = None
|
|
1574
1534
|
self._sample_lock = threading.Lock()
|
|
1575
1535
|
|
|
@@ -1628,9 +1588,10 @@ class PositionChannelsController(BasePubSubController):
|
|
|
1628
1588
|
corner_exclusion_radius: float,
|
|
1629
1589
|
max_matching_distance: float,
|
|
1630
1590
|
corner_points: List[Dict[str, float]],
|
|
1631
|
-
reference_trajectory: List[Dict[str, float]]
|
|
1591
|
+
reference_trajectory: List[Dict[str, float]],
|
|
1592
|
+
petal_name: str = "petal-user-journey-coordinator"
|
|
1632
1593
|
):
|
|
1633
|
-
super().__init__("real_time_pose", mqtt_proxy, mavlink_proxy, logger)
|
|
1594
|
+
super().__init__("real_time_pose", mqtt_proxy, mavlink_proxy, logger, petal_name=petal_name)
|
|
1634
1595
|
self._latest_position = None
|
|
1635
1596
|
self._latest_attitude = None
|
|
1636
1597
|
self._sample_lock = threading.Lock()
|
|
@@ -1916,8 +1877,14 @@ def _classify_kill_transition(text: str) -> Optional[bool]:
|
|
|
1916
1877
|
class KillSwitchController(BasePubSubController):
|
|
1917
1878
|
"""Controller for streaming kill switch status from PX4 STATUSTEXT messages with automatic parameter configuration."""
|
|
1918
1879
|
|
|
1919
|
-
def __init__(
|
|
1920
|
-
|
|
1880
|
+
def __init__(
|
|
1881
|
+
self,
|
|
1882
|
+
mqtt_proxy: MQTTProxy,
|
|
1883
|
+
mavlink_proxy: MavLinkExternalProxy,
|
|
1884
|
+
logger: logging.Logger,
|
|
1885
|
+
petal_name: str = "petal-user-journey-coordinator"
|
|
1886
|
+
):
|
|
1887
|
+
super().__init__("ks_status_stream", mqtt_proxy, mavlink_proxy, logger, petal_name=petal_name)
|
|
1921
1888
|
|
|
1922
1889
|
# Kill switch state tracking
|
|
1923
1890
|
self.is_killed: Optional[bool] = None # None = unknown
|
|
@@ -2007,8 +1974,14 @@ class KillSwitchController(BasePubSubController):
|
|
|
2007
1974
|
class MultiFunctionalSwitchAController(BasePubSubController):
|
|
2008
1975
|
"""Controller for streaming Multi-functional Switch A data from MAVLink messages."""
|
|
2009
1976
|
|
|
2010
|
-
def __init__(
|
|
2011
|
-
|
|
1977
|
+
def __init__(
|
|
1978
|
+
self,
|
|
1979
|
+
mqtt_proxy: MQTTProxy,
|
|
1980
|
+
mavlink_proxy: MavLinkExternalProxy,
|
|
1981
|
+
logger: logging.Logger,
|
|
1982
|
+
petal_name: str = "petal-user-journey-coordinator"
|
|
1983
|
+
):
|
|
1984
|
+
super().__init__("mfs_a_status_stream", mqtt_proxy, mavlink_proxy, logger, petal_name=petal_name)
|
|
2012
1985
|
|
|
2013
1986
|
# Multi-functional Switch A state tracking
|
|
2014
1987
|
self.latest_mfs_a_data: Optional[Dict[str, Any]] = None
|
|
@@ -2061,8 +2034,14 @@ class MultiFunctionalSwitchAController(BasePubSubController):
|
|
|
2061
2034
|
class MultiFunctionalSwitchBController(BasePubSubController):
|
|
2062
2035
|
"""Controller for streaming Multi-functional Switch B data from MAVLink messages."""
|
|
2063
2036
|
|
|
2064
|
-
def __init__(
|
|
2065
|
-
|
|
2037
|
+
def __init__(
|
|
2038
|
+
self,
|
|
2039
|
+
mqtt_proxy: MQTTProxy,
|
|
2040
|
+
mavlink_proxy: MavLinkExternalProxy,
|
|
2041
|
+
logger: logging.Logger,
|
|
2042
|
+
petal_name: str = "petal-user-journey-coordinator"
|
|
2043
|
+
):
|
|
2044
|
+
super().__init__("mfs_b_status_stream", mqtt_proxy, mavlink_proxy, logger, petal_name=petal_name)
|
|
2066
2045
|
|
|
2067
2046
|
# Multi-functional Switch B state tracking
|
|
2068
2047
|
self.latest_mfs_b_data: Optional[Dict[str, Any]] = None
|
|
@@ -2124,8 +2103,10 @@ class TrajectoryVerificationController:
|
|
|
2124
2103
|
rectangle_a: float = 2.0,
|
|
2125
2104
|
rectangle_b: float = 2.0,
|
|
2126
2105
|
points_per_edge: int = 10,
|
|
2127
|
-
corner_exclusion_radius: float = 0.2
|
|
2106
|
+
corner_exclusion_radius: float = 0.2,
|
|
2107
|
+
petal_name: str = "petal-user-journey-coordinator"
|
|
2128
2108
|
):
|
|
2109
|
+
self.petal_name = petal_name
|
|
2129
2110
|
self.mqtt_proxy = mqtt_proxy
|
|
2130
2111
|
self.logger = logger
|
|
2131
2112
|
self.is_active = False
|
|
@@ -2730,7 +2711,7 @@ class TrajectoryVerificationController:
|
|
|
2730
2711
|
|
|
2731
2712
|
mqtt_message = {
|
|
2732
2713
|
"messageId": str(uuid.uuid4()),
|
|
2733
|
-
"command": "/
|
|
2714
|
+
"command": f"/{self.petal_name}/verify_pos_yaw_directions_results",
|
|
2734
2715
|
"timestamp": datetime.now().isoformat(),
|
|
2735
2716
|
"payload": results_payload
|
|
2736
2717
|
}
|
|
@@ -2758,7 +2739,13 @@ class WifiOptitrackConnectivityController:
|
|
|
2758
2739
|
Controller for connecting to WiFi and verifying OptiTrack server connectivity.
|
|
2759
2740
|
"""
|
|
2760
2741
|
|
|
2761
|
-
def __init__(
|
|
2742
|
+
def __init__(
|
|
2743
|
+
self,
|
|
2744
|
+
mqtt_proxy: "MQTTProxy",
|
|
2745
|
+
logger: logging.Logger,
|
|
2746
|
+
petal_name: str = "petal-user-journey-coordinator"
|
|
2747
|
+
):
|
|
2748
|
+
self.petal_name = petal_name
|
|
2762
2749
|
self.mqtt_proxy = mqtt_proxy
|
|
2763
2750
|
self.logger = logger
|
|
2764
2751
|
self.is_active = False
|
|
@@ -3115,7 +3102,7 @@ class WifiOptitrackConnectivityController:
|
|
|
3115
3102
|
mqtt_message = {
|
|
3116
3103
|
"messageId": message_id,
|
|
3117
3104
|
"deviceId": getattr(self.mqtt_proxy, 'device_id', 'unknown'),
|
|
3118
|
-
"command": "
|
|
3105
|
+
"command": f"{self.petal_name}/acknowledge",
|
|
3119
3106
|
"timestamp": datetime.now().isoformat(),
|
|
3120
3107
|
"payload": response_payload.model_dump()
|
|
3121
3108
|
}
|
|
@@ -3387,7 +3374,7 @@ class WifiOptitrackConnectivityController:
|
|
|
3387
3374
|
mqtt_message = {
|
|
3388
3375
|
"messageId": message_id,
|
|
3389
3376
|
"deviceId": getattr(self.mqtt_proxy, 'device_id', 'unknown'),
|
|
3390
|
-
"command": "
|
|
3377
|
+
"command": f"{self.petal_name}/set_static_ip_address_ack",
|
|
3391
3378
|
"timestamp": datetime.now().isoformat(),
|
|
3392
3379
|
"payload": response_payload.model_dump()
|
|
3393
3380
|
}
|
|
@@ -1,57 +1,59 @@
|
|
|
1
1
|
from pydantic import BaseModel, Field, field_validator, ValidationError
|
|
2
|
-
from typing import Dict, Any, List, Union, Optional, Callable
|
|
2
|
+
from typing import Dict, Any, List, Literal, Union, Optional, Callable
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
class ParameterBaseModel(BaseModel):
|
|
7
6
|
"""Base fields for flight records"""
|
|
8
7
|
parameter_name: str = Field(..., description="Parameter name")
|
|
9
8
|
parameter_value: Union[str,int,float] = Field(..., description="Value of the parameter")
|
|
9
|
+
parameter_type: Optional[Literal['UINT8','INT8','UINT16','INT16','UINT32','INT32','UINT64','INT64','REAL32','REAL64']] = Field(default=None, description="Type of the parameter")
|
|
10
10
|
|
|
11
11
|
model_config = {
|
|
12
12
|
"json_schema_extra": {
|
|
13
13
|
"example": {
|
|
14
14
|
"parameter_name": "CA_ROTOR_COUNT",
|
|
15
|
-
"parameter_value": 4
|
|
15
|
+
"parameter_value": 4,
|
|
16
|
+
"parameter_type": "UINT8"
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
class
|
|
22
|
-
"""
|
|
23
|
-
|
|
22
|
+
class ParameterResult(BaseModel):
|
|
23
|
+
"""Individual parameter result"""
|
|
24
|
+
name: str = Field(..., description="Name of the parameter")
|
|
25
|
+
value: Optional[Union[str,int,float]] = Field(None, description="Decoded value of the parameter")
|
|
26
|
+
raw: Optional[Union[str,int,float]] = Field(None, description="Raw value of the parameter")
|
|
27
|
+
type: Optional[int] = Field(None, description="Type of the parameter")
|
|
28
|
+
count: Optional[int] = Field(None, description="Total number of parameters")
|
|
29
|
+
index: Optional[int] = Field(None, description="Index of the parameter")
|
|
30
|
+
error: Optional[str] = Field(default=None, description="Error message if setting the parameter failed")
|
|
31
|
+
success: Optional[bool] = Field(default=None, description="Whether setting the parameter was successful")
|
|
24
32
|
|
|
25
33
|
model_config = {
|
|
26
34
|
"json_schema_extra": {
|
|
27
35
|
"example": {
|
|
28
|
-
"
|
|
36
|
+
"name": "CA_ROTOR_COUNT",
|
|
37
|
+
"value": 4,
|
|
38
|
+
"raw": 4.0,
|
|
39
|
+
"type": 6,
|
|
40
|
+
"count": 1053,
|
|
41
|
+
"index": 65535,
|
|
42
|
+
"error": None,
|
|
43
|
+
"success": True
|
|
29
44
|
}
|
|
30
45
|
}
|
|
31
46
|
}
|
|
32
47
|
|
|
33
48
|
|
|
34
|
-
class
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
messageId: str = Field(..., description="Unique message ID")
|
|
38
|
-
deviceId: str = Field(..., description="Device ID")
|
|
39
|
-
command: str = Field(..., description="Command to execute")
|
|
40
|
-
timestamp: str = Field(..., description="Timestamp of the message")
|
|
41
|
-
payload: Dict[str, Any] = Field(..., description="Message payload")
|
|
49
|
+
class ParameterRequestModel(BaseModel):
|
|
50
|
+
"""Base fields for flight records"""
|
|
51
|
+
parameter_name: str = Field(..., description="Parameter name")
|
|
42
52
|
|
|
43
53
|
model_config = {
|
|
44
54
|
"json_schema_extra": {
|
|
45
55
|
"example": {
|
|
46
|
-
"
|
|
47
|
-
"messageId": "kkkss8fepn-1756665973142-bptyoj06z",
|
|
48
|
-
"deviceId": "Instance-a92c5505-ccdb-4ac7-b0fe-74f4fa5fc5b9",
|
|
49
|
-
"command": "Update",
|
|
50
|
-
"payload": {
|
|
51
|
-
"source": "web-client",
|
|
52
|
-
"app": "leaf-fc"
|
|
53
|
-
},
|
|
54
|
-
"timestamp": "2025-08-31T18:46:13.142Z"
|
|
56
|
+
"parameter_name": "CA_ROTOR_COUNT"
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
}
|
|
@@ -554,3 +556,81 @@ class SetStaticIpAddressResponse(BaseModel):
|
|
|
554
556
|
}
|
|
555
557
|
}
|
|
556
558
|
}
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
class BulkParameterSetRequest(BaseModel):
|
|
562
|
+
"""Request model for bulk parameter setting"""
|
|
563
|
+
parameters: List[ParameterBaseModel] = Field(..., description="List of parameters to set")
|
|
564
|
+
|
|
565
|
+
model_config = {
|
|
566
|
+
"json_schema_extra": {
|
|
567
|
+
"example": {
|
|
568
|
+
"parameters": [
|
|
569
|
+
{
|
|
570
|
+
"parameter_name": "CA_ROTOR_COUNT",
|
|
571
|
+
"parameter_value": 4,
|
|
572
|
+
"parameter_type": "UINT8"
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
"parameter_name": "VTO_LOITER_ALT",
|
|
576
|
+
"parameter_value": 80.0,
|
|
577
|
+
"parameter_type": "REAL32"
|
|
578
|
+
}
|
|
579
|
+
]
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
class BulkParameterGetRequest(BaseModel):
|
|
586
|
+
"""Request model for bulk parameter getting"""
|
|
587
|
+
parameter_names: List[str] = Field(..., description="List of parameter names to get")
|
|
588
|
+
|
|
589
|
+
model_config = {
|
|
590
|
+
"json_schema_extra": {
|
|
591
|
+
"example": {
|
|
592
|
+
"parameter_names": [
|
|
593
|
+
"CA_ROTOR_COUNT",
|
|
594
|
+
"VTO_LOITER_ALT"
|
|
595
|
+
]
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
class BulkParameterResponse(BaseModel):
|
|
602
|
+
"""Response model for bulk parameter setting"""
|
|
603
|
+
success: bool = Field(..., description="Whether all parameters were set successfully")
|
|
604
|
+
results: Dict[str, ParameterResult] = Field(..., description="Results for each parameter set attempt")
|
|
605
|
+
timestamp: str = Field(..., description="Timestamp of the operation")
|
|
606
|
+
|
|
607
|
+
model_config = {
|
|
608
|
+
"json_schema_extra": {
|
|
609
|
+
"example": {
|
|
610
|
+
"success": True,
|
|
611
|
+
"results": {
|
|
612
|
+
"CA_ROTOR_COUNT": {
|
|
613
|
+
"name": "CA_ROTOR_COUNT",
|
|
614
|
+
"value": 4,
|
|
615
|
+
"raw": 4.0,
|
|
616
|
+
"type": 6,
|
|
617
|
+
"count": 1053,
|
|
618
|
+
"index": 65535,
|
|
619
|
+
"error": None,
|
|
620
|
+
"success": True
|
|
621
|
+
},
|
|
622
|
+
"VTO_LOITER_ALT": {
|
|
623
|
+
"name": "VTO_LOITER_ALT",
|
|
624
|
+
"value": 80.0,
|
|
625
|
+
"raw": 80.0,
|
|
626
|
+
"type": 9,
|
|
627
|
+
"count": 1053,
|
|
628
|
+
"index": 1047,
|
|
629
|
+
"error": None,
|
|
630
|
+
"success": True
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
"timestamp": "2023-01-01T00:00:00Z"
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|