petal-user-journey-coordinator 0.1.5__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.
@@ -0,0 +1,556 @@
1
+ from pydantic import BaseModel, Field, field_validator, ValidationError
2
+ from typing import Dict, Any, List, Union, Optional, Callable
3
+ from datetime import datetime
4
+
5
+
6
+ class ParameterBaseModel(BaseModel):
7
+ """Base fields for flight records"""
8
+ parameter_name: str = Field(..., description="Parameter name")
9
+ parameter_value: Union[str,int,float] = Field(..., description="Value of the parameter")
10
+
11
+ model_config = {
12
+ "json_schema_extra": {
13
+ "example": {
14
+ "parameter_name": "CA_ROTOR_COUNT",
15
+ "parameter_value": 4
16
+ }
17
+ }
18
+ }
19
+
20
+
21
+ class ParameterRequestModel(BaseModel):
22
+ """Base fields for flight records"""
23
+ parameter_name: str = Field(..., description="Parameter name")
24
+
25
+ model_config = {
26
+ "json_schema_extra": {
27
+ "example": {
28
+ "parameter_name": "CA_ROTOR_COUNT"
29
+ }
30
+ }
31
+ }
32
+
33
+
34
+ class MQTTMessage(BaseModel):
35
+ """MQTT message model"""
36
+ waitResponse: bool = Field(..., description="Whether to wait for a response")
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")
42
+
43
+ model_config = {
44
+ "json_schema_extra": {
45
+ "example": {
46
+ "waitResponse": True,
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"
55
+ }
56
+ }
57
+ }
58
+
59
+
60
+ class RotorCountParameter(BaseModel):
61
+ """Flight record input model"""
62
+ # File paths and IDs
63
+ rotor_count: int = Field(..., description="Value of the parameter")
64
+
65
+ model_config = {
66
+ "json_schema_extra": {
67
+ "example": {
68
+ "rotor_count": 4
69
+ }
70
+ }
71
+ }
72
+
73
+
74
+ class ESCCalibrationRequest(BaseModel):
75
+ """ESC calibration request model"""
76
+ motor_number: int = Field(..., description="Motor number (1-based)")
77
+ calibration_value: float = Field(..., description="Calibration value [-1..1]")
78
+ safety_timeout_s: float = Field(default=3.0, description="Safety timeout in seconds (<=3)")
79
+ period: float = Field(default=1.0, description="Period between commands in seconds")
80
+ repetitions: Optional[int] = Field(default=None, description="Number of repetitions (None for infinite)")
81
+
82
+ model_config = {
83
+ "json_schema_extra": {
84
+ "example": {
85
+ "motor_number": 1,
86
+ "calibration_value": 0.2,
87
+ "safety_timeout_s": 2.5,
88
+ "period": 1.0,
89
+ "repetitions": 10
90
+ }
91
+ }
92
+ }
93
+
94
+
95
+ class ESCCalibrationResponse(BaseModel):
96
+ """ESC calibration response model"""
97
+ motor_number: int = Field(..., description="Motor number")
98
+ status: str = Field(..., description="Calibration status")
99
+ message: str = Field(..., description="Status message")
100
+ timestamp: datetime = Field(..., description="Timestamp")
101
+
102
+ model_config = {
103
+ "json_schema_extra": {
104
+ "example": {
105
+ "motor_number": 1,
106
+ "status": "started",
107
+ "message": "ESC calibration started for motor 1",
108
+ "timestamp": "2023-01-01T00:00:00Z"
109
+ }
110
+ }
111
+ }
112
+
113
+
114
+ class ESCCalibrationStop(BaseModel):
115
+ """ESC calibration stop request model"""
116
+ motor_number: Optional[int] = Field(default=None, description="Motor number to stop (None for all)")
117
+ force_stop: bool = Field(default=True, description="Force stop calibration")
118
+
119
+ model_config = {
120
+ "json_schema_extra": {
121
+ "example": {
122
+ "motor_number": 1,
123
+ "force_stop": True
124
+ }
125
+ }
126
+ }
127
+
128
+
129
+ class ESCCalibrationPayload(BaseModel):
130
+ """ESC calibration MQTT payload model"""
131
+ is_calibration_started: bool = Field(..., description="Whether calibration is started")
132
+ safety_timeout_s: float = Field(..., ge=0, le=3, description="Safety timeout in seconds (0-3)")
133
+ force_cancel_calibration: bool = Field(default=False, description="Force cancel calibration")
134
+ throttle: Optional[str] = Field(default=None, description="Throttle command: 'maximum' or 'minimum'")
135
+ esc_interface_signal_type: Optional[str] = Field(default="PWM", description="ESC signal interface type (PWM, OneShot125, DShot, etc.)")
136
+ ca_rotor_count: Optional[int] = Field(default=None, description="Number of rotors/motors")
137
+ safe_stop_calibration: Optional[bool] = Field(default=False, description="Whether to perform a safe stop of the calibration process")
138
+
139
+ model_config = {
140
+ "json_schema_extra": {
141
+ "example": {
142
+ "is_calibration_started": True,
143
+ "safety_timeout_s": 2.5,
144
+ "force_cancel_calibration": False,
145
+ "throttle": "maximum",
146
+ "esc_interface_signal_type": "PWM",
147
+ "ca_rotor_count": 4,
148
+ "safe_stop_calibration": True
149
+ }
150
+ }
151
+ }
152
+
153
+
154
+ class ESCCalibrationLimitsPayload(BaseModel):
155
+ """ESC calibration limits update payload model"""
156
+ motors_common_max_pwm: int = Field(..., ge=1000, le=2000, description="Common maximum PWM value for all motors (1000-2000)")
157
+ motors_common_min_pwm: int = Field(..., ge=1000, le=2000, description="Common minimum PWM value for all motors (1000-2000)")
158
+
159
+ model_config = {
160
+ "json_schema_extra": {
161
+ "example": {
162
+ "motors_common_max_pwm": 2000,
163
+ "motors_common_min_pwm": 1000
164
+ }
165
+ }
166
+ }
167
+
168
+
169
+ class ESCForceRunAllPayload(BaseModel):
170
+ """ESC force run all motors MQTT payload model"""
171
+ motors_common_command: float = Field(..., ge=1000, le=1200, description="Common command value for all motors [1000..1200]")
172
+ safety_timeout_s: float = Field(..., ge=0, le=3, description="Safety timeout in seconds (0-3)")
173
+ force_cancel: bool = Field(default=False, description="Force cancel operation")
174
+
175
+ model_config = {
176
+ "json_schema_extra": {
177
+ "example": {
178
+ "motors_common_command": 1000,
179
+ "safety_timeout_s": 2.0,
180
+ "force_cancel": False
181
+ }
182
+ }
183
+ }
184
+
185
+
186
+ class ESCForceRunSinglePayload(BaseModel):
187
+ """ESC force run single motor MQTT payload model"""
188
+ motor_idx: int = Field(..., ge=1, description="Motor index (1-based)")
189
+ motor_command: float = Field(..., ge=1000, le=2000, description="Motor command value [1000..2000]")
190
+ safety_timeout_s: float = Field(..., ge=0, le=3, description="Safety timeout in seconds (0-3)")
191
+ force_cancel: bool = Field(default=False, description="Force cancel operation")
192
+
193
+ model_config = {
194
+ "json_schema_extra": {
195
+ "example": {
196
+ "motor_idx": 1,
197
+ "motor_command": 1000,
198
+ "safety_timeout_s": 2.5,
199
+ "force_cancel": False
200
+ }
201
+ }
202
+ }
203
+
204
+
205
+ class GPSModulePayload(BaseModel):
206
+ """GPS module configuration payload"""
207
+ gps_module: str = Field(..., description="GPS module type")
208
+
209
+ model_config = {
210
+ "json_schema_extra": {
211
+ "example": {
212
+ "gps_module": "Mosaic-H RTX"
213
+ }
214
+ }
215
+ }
216
+
217
+
218
+ class DistanceModulePayload(BaseModel):
219
+ """Distance module configuration payload"""
220
+ dist_module: str = Field(..., description="Distance module type")
221
+
222
+ model_config = {
223
+ "json_schema_extra": {
224
+ "example": {
225
+ "dist_module": "LiDAR Lite v3"
226
+ }
227
+ }
228
+ }
229
+
230
+
231
+ class OpticalFlowModulePayload(BaseModel):
232
+ """Optical flow module configuration payload"""
233
+ oflow_module: str = Field(..., description="Optical flow module type")
234
+
235
+ model_config = {
236
+ "json_schema_extra": {
237
+ "example": {
238
+ "oflow_module": "ARK Flow"
239
+ }
240
+ }
241
+ }
242
+
243
+
244
+ class GPSSpatialOffsetPayload(BaseModel):
245
+ """GPS spatial offset configuration payload"""
246
+ gps_module_spatial_offset_x_m: float = Field(..., description="GPS X offset in meters")
247
+ gps_module_spatial_offset_y_m: float = Field(..., description="GPS Y offset in meters")
248
+ gps_module_spatial_offset_z_m: float = Field(..., description="GPS Z offset in meters")
249
+
250
+ model_config = {
251
+ "json_schema_extra": {
252
+ "example": {
253
+ "gps_module_spatial_offset_x_m": 0.1,
254
+ "gps_module_spatial_offset_y_m": 0.0,
255
+ "gps_module_spatial_offset_z_m": -0.05
256
+ }
257
+ }
258
+ }
259
+
260
+
261
+ class DistanceSpatialOffsetPayload(BaseModel):
262
+ """Distance sensor spatial offset configuration payload"""
263
+ dist_module_spatial_offset_x_m: float = Field(..., description="Distance sensor X offset in meters")
264
+ dist_module_spatial_offset_y_m: float = Field(..., description="Distance sensor Y offset in meters")
265
+ dist_module_spatial_offset_z_m: float = Field(..., description="Distance sensor Z offset in meters")
266
+
267
+ model_config = {
268
+ "json_schema_extra": {
269
+ "example": {
270
+ "dist_module_spatial_offset_x_m": 0.05,
271
+ "dist_module_spatial_offset_y_m": 0.0,
272
+ "dist_module_spatial_offset_z_m": -0.1,
273
+ }
274
+ }
275
+ }
276
+
277
+
278
+ class OpticalFlowSpatialOffsetPayload(BaseModel):
279
+ """Optical flow spatial offset configuration payload"""
280
+ oflow_module_spatial_offset_x_m: float = Field(..., description="Optical flow X offset in meters")
281
+ oflow_module_spatial_offset_y_m: float = Field(..., description="Optical flow Y offset in meters")
282
+ oflow_module_spatial_offset_z_m: float = Field(..., description="Optical flow Z offset in meters")
283
+
284
+ model_config = {
285
+ "json_schema_extra": {
286
+ "example": {
287
+ "oflow_module_spatial_offset_x_m": 0.0,
288
+ "oflow_module_spatial_offset_y_m": 0.0,
289
+ "oflow_module_spatial_offset_z_m": -0.02
290
+ }
291
+ }
292
+ }
293
+
294
+
295
+ class ParameterResponseModel(BaseModel):
296
+ """Response model for parameter requests"""
297
+ parameter_name: str = Field(..., description="Name of the parameter")
298
+ parameter_value: Union[int,str,float] = Field(..., description="Value of the parameter")
299
+ timestamp: datetime = Field(..., description="Timestamp of the parameter value")
300
+
301
+ model_config = {
302
+ "json_schema_extra": {
303
+ "example": {
304
+ "parameter_name": "CA_ROTOR_COUNT",
305
+ "parameter_value": 4,
306
+ "timestamp": "2023-01-01T00:00:00Z"
307
+ }
308
+ }
309
+ }
310
+
311
+
312
+ class MavlinkParameterData(BaseModel):
313
+
314
+ """Response model for mavlink parameter requests"""
315
+ value: Union[str, int, float, None] = Field(None, description="Parameter value (nullable, optional)")
316
+ raw: Union[str, int, float, None] = Field(None, description="Raw parameter value (nullable, optional)")
317
+ type: int = Field(..., description="Parameter type")
318
+ count: int = Field(..., description="Parameter count")
319
+ index: int = Field(..., description="Parameter index")
320
+
321
+ model_config = {
322
+ "json_schema_extra": {
323
+ "example": {
324
+ "value": 4,
325
+ "raw": 4.0,
326
+ "type": 6,
327
+ "count": 1053,
328
+ "index": 65535
329
+ }
330
+ }
331
+ }
332
+
333
+
334
+ class MavlinkParametersResponseModel(BaseModel):
335
+
336
+ parameters: Dict[str,MavlinkParameterData] = Field(..., description="List of MAVLink parameters")
337
+ timestamp: datetime = Field(..., description="Timestamp of the parameter values")
338
+
339
+ model_config = {
340
+ "json_schema_extra": {
341
+ "example": {
342
+ "parameters": {
343
+ "CA_ROTOR_COUNT": {
344
+ "value": 4,
345
+ "raw": 4.0,
346
+ "type": 6,
347
+ "count": 1053,
348
+ "index": 65535
349
+ },
350
+ "VTO_LOITER_ALT": {
351
+ "value": 80.0,
352
+ "raw": 80.0,
353
+ "type": 9,
354
+ "index": 1047,
355
+ "count": 1053
356
+ }
357
+ },
358
+ "timestamp": "2023-01-01T00:00:00Z"
359
+ }
360
+ }
361
+ }
362
+
363
+
364
+ class MavlinkNamedParameterData(BaseModel):
365
+
366
+ """Response model for mavlink parameter requests"""
367
+ name: str = Field(..., description="Parameter name")
368
+ value: Union[str, int, float] = Field(..., description="Parameter value")
369
+ raw: Union[str, int, float] = Field(..., description="Raw parameter value")
370
+ type: int = Field(..., description="Parameter type")
371
+ count: int = Field(..., description="Parameter count")
372
+ index: int = Field(..., description="Parameter index")
373
+
374
+ model_config = {
375
+ "json_schema_extra": {
376
+ "example": {
377
+ "name": "CA_ROTOR_COUNT",
378
+ "value": 4,
379
+ "raw": 4.0,
380
+ "type": 6,
381
+ "count": 1053,
382
+ "index": 65535
383
+ }
384
+ }
385
+ }
386
+
387
+
388
+ class MavlinkParameterResponseModel(BaseModel):
389
+ """Response model for parameter requests"""
390
+ parameter_name: str = Field(..., description="Name of the parameter")
391
+ parameter_value: MavlinkNamedParameterData = Field(..., description="Value of the parameter")
392
+ timestamp: datetime = Field(..., description="Timestamp of the parameter value")
393
+
394
+ model_config = {
395
+ "json_schema_extra": {
396
+ "example": {
397
+ "parameter_name": "CA_ROTOR_COUNT",
398
+ "parameter_value": {
399
+ "name": "CA_ROTOR_COUNT",
400
+ "value": 4,
401
+ "raw": 4.0,
402
+ "type": 6,
403
+ "count": 1053,
404
+ "index": 65535
405
+ },
406
+ "timestamp": "2023-01-01T00:00:00Z"
407
+ }
408
+ }
409
+ }
410
+
411
+
412
+ class SubscribePayload(BaseModel):
413
+ """Payload for subscription messages"""
414
+ subscribed_stream_id: str = Field(..., description="Unique identifier for the stream")
415
+ data_rate_hz: float = Field(..., ge=0.1, le=100.0, description="Data rate in Hz (0.1-100)")
416
+
417
+ model_config = {
418
+ "json_schema_extra": {
419
+ "example": {
420
+ "subscribed_stream_id": "px4_rc_raw",
421
+ "data_rate_hz": 10.0
422
+ }
423
+ }
424
+ }
425
+
426
+
427
+ class PublishPayload(BaseModel):
428
+ """Payload for publish messages"""
429
+ published_stream_id: str = Field(..., description="Unique identifier for the stream")
430
+ stream_payload: Dict[str, Any] = Field(..., description="The actual data payload")
431
+
432
+ model_config = {
433
+ "json_schema_extra": {
434
+ "example": {
435
+ "published_stream_id": "px4_rc_raw",
436
+ "stream_payload": {
437
+ "time_boot_ms": 12345,
438
+ "chancount": 8,
439
+ "chan1_raw": 1500,
440
+ "chan2_raw": 1600,
441
+ "rssi": 255
442
+ }
443
+ }
444
+ }
445
+ }
446
+
447
+
448
+ class UnsubscribePayload(BaseModel):
449
+ """Payload for unsubscribe messages"""
450
+ unsubscribed_stream_id: str = Field(..., description="Unique identifier for the stream to stop")
451
+
452
+ model_config = {
453
+ "json_schema_extra": {
454
+ "example": {
455
+ "unsubscribed_stream_id": "px4_rc_raw"
456
+ }
457
+ }
458
+ }
459
+
460
+
461
+ class VerifyPosYawDirectionsPayload(BaseModel):
462
+ """Payload for position and yaw verification start"""
463
+ start: bool = Field(..., description="Start verification process")
464
+
465
+ model_config = {
466
+ "json_schema_extra": {
467
+ "example": {
468
+ "start": True
469
+ }
470
+ }
471
+ }
472
+
473
+
474
+ class VerifyPosYawDirectionsResultsPayload(BaseModel):
475
+ """Payload for position and yaw verification results"""
476
+ was_successful: bool = Field(..., description="Whether verification was successful")
477
+ results_text: str = Field(..., description="Detailed results text")
478
+
479
+ model_config = {
480
+ "json_schema_extra": {
481
+ "example": {
482
+ "was_successful": True,
483
+ "results_text": "Position error: 0.15m, Yaw error: 2.3°. Verification passed."
484
+ }
485
+ }
486
+ }
487
+
488
+
489
+ class ConnectToWifiAndVerifyOptitrackPayload(BaseModel):
490
+ """Payload for connecting to WiFi and verifying OptiTrack connectivity"""
491
+ positioning_system_network_wifi_ssid: str = Field(..., description="WiFi SSID to connect to")
492
+ positioning_system_network_wifi_pass: str = Field(..., description="WiFi password")
493
+ positioning_system_network_wifi_subnet: str = Field(..., description="Expected subnet (e.g., '192.168.1.0/24')")
494
+ positioning_system_network_server_ip_address: str = Field(..., description="OptiTrack server IP address to ping")
495
+ positioning_system_network_server_multicast_address: str = Field(..., description="Multicast address for OptiTrack")
496
+ positioning_system_network_server_data_port: str = Field(..., description="Data port for OptiTrack communication")
497
+
498
+ model_config = {
499
+ "json_schema_extra": {
500
+ "example": {
501
+ "positioning_system_network_wifi_ssid": "OptiTrack_Network",
502
+ "positioning_system_network_wifi_pass": "password123",
503
+ "positioning_system_network_wifi_subnet": "192.168.1.0/24",
504
+ "positioning_system_network_server_ip_address": "192.168.1.100",
505
+ "positioning_system_network_server_multicast_address": "239.255.42.99",
506
+ "positioning_system_network_server_data_port": "1511"
507
+ }
508
+ }
509
+ }
510
+
511
+
512
+ class WifiOptitrackConnectionResponse(BaseModel):
513
+ """Response payload for WiFi and OptiTrack connection attempt"""
514
+ was_successful: bool = Field(..., description="Whether the connection was successful")
515
+ status_message: str = Field(..., description="Detailed status message")
516
+ assigned_ip_address: str = Field(default="", description="Assigned IP address if successful")
517
+
518
+ model_config = {
519
+ "json_schema_extra": {
520
+ "example": {
521
+ "was_successful": True,
522
+ "status_message": "Successfully connected to WiFi and verified OptiTrack server connectivity",
523
+ "assigned_ip_address": "192.168.1.45"
524
+ }
525
+ }
526
+ }
527
+
528
+
529
+ class SetStaticIpAddressPayload(BaseModel):
530
+ """Payload for setting static IP address within OptiTrack network"""
531
+ positioning_system_network_wifi_subnet: str = Field(..., description="Subnet mask (e.g., '255.255.255.0' or '10.0.0.0/24')")
532
+ positioning_system_network_server_ip_address: str = Field(..., description="OptiTrack server IP address for gateway calculation")
533
+
534
+ model_config = {
535
+ "json_schema_extra": {
536
+ "example": {
537
+ "positioning_system_network_wifi_subnet": "255.255.255.0",
538
+ "positioning_system_network_server_ip_address": "10.0.0.27"
539
+ }
540
+ }
541
+ }
542
+
543
+
544
+ class SetStaticIpAddressResponse(BaseModel):
545
+ """Response payload for static IP address configuration"""
546
+ assigned_static_ip: str = Field(default="", description="The static IP address that was assigned")
547
+ was_successful: bool = Field(..., description="Whether the static IP configuration was successful")
548
+
549
+ model_config = {
550
+ "json_schema_extra": {
551
+ "example": {
552
+ "assigned_static_ip": "10.0.0.25",
553
+ "was_successful": True
554
+ }
555
+ }
556
+ }