petal-user-journey-coordinator 0.1.8__py3-none-any.whl → 0.1.9__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/data_model.py +23 -0
- petal_user_journey_coordinator/plugin.py +124 -36
- {petal_user_journey_coordinator-0.1.8.dist-info → petal_user_journey_coordinator-0.1.9.dist-info}/METADATA +1 -1
- petal_user_journey_coordinator-0.1.9.dist-info/RECORD +8 -0
- {petal_user_journey_coordinator-0.1.8.dist-info → petal_user_journey_coordinator-0.1.9.dist-info}/WHEEL +1 -1
- petal_user_journey_coordinator-0.1.8.dist-info/RECORD +0 -8
- {petal_user_journey_coordinator-0.1.8.dist-info → petal_user_journey_coordinator-0.1.9.dist-info}/entry_points.txt +0 -0
|
@@ -633,4 +633,27 @@ class BulkParameterResponse(BaseModel):
|
|
|
633
633
|
"timestamp": "2023-01-01T00:00:00Z"
|
|
634
634
|
}
|
|
635
635
|
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
class RebootPX4StatusPayload(BaseModel):
|
|
640
|
+
"""Payload for PX4 reboot status published via MQTT after reboot completes."""
|
|
641
|
+
reboot_initiated: bool = Field(..., description="Whether the reboot command was initiated")
|
|
642
|
+
reboot_success: Optional[bool] = Field(default=None, description="Whether the reboot completed successfully")
|
|
643
|
+
status: Literal["success", "failed"] = Field(..., description="Reboot status")
|
|
644
|
+
message: str = Field(..., description="Human-readable status message")
|
|
645
|
+
error_code: Optional[str] = Field(default=None, description="Error code if reboot failed")
|
|
646
|
+
timestamp: datetime = Field(..., description="Timestamp of the status update")
|
|
647
|
+
|
|
648
|
+
model_config = {
|
|
649
|
+
"json_schema_extra": {
|
|
650
|
+
"example": {
|
|
651
|
+
"reboot_initiated": True,
|
|
652
|
+
"reboot_success": True,
|
|
653
|
+
"status": "success",
|
|
654
|
+
"message": "PX4 reboot completed successfully",
|
|
655
|
+
"error_code": None,
|
|
656
|
+
"timestamp": "2026-01-07T12:00:00Z"
|
|
657
|
+
}
|
|
658
|
+
}
|
|
636
659
|
}
|
|
@@ -93,7 +93,10 @@ from .data_model import (
|
|
|
93
93
|
OpticalFlowModulePayload,
|
|
94
94
|
BulkParameterSetRequest,
|
|
95
95
|
BulkParameterGetRequest,
|
|
96
|
-
BulkParameterResponse
|
|
96
|
+
BulkParameterResponse,
|
|
97
|
+
|
|
98
|
+
# Reboot status payload
|
|
99
|
+
RebootPX4StatusPayload
|
|
97
100
|
)
|
|
98
101
|
|
|
99
102
|
from petal_app_manager.models.mavlink import (
|
|
@@ -1940,13 +1943,22 @@ class PetalUserJourneyCoordinator(Petal):
|
|
|
1940
1943
|
|
|
1941
1944
|
@http_action(method="POST", path="/mqtt/reboot_px4")
|
|
1942
1945
|
async def _reboot_px4_message_handler(self, topic: str, message: Dict[str, Any]):
|
|
1943
|
-
"""
|
|
1946
|
+
"""
|
|
1947
|
+
Handle reboot PX4 MQTT messages.
|
|
1948
|
+
|
|
1949
|
+
Flow:
|
|
1950
|
+
1. Validate message and check for active operations
|
|
1951
|
+
2. Immediately send_command_response to acknowledge command received
|
|
1952
|
+
3. Await reboot_autopilot to execute the reboot
|
|
1953
|
+
4. Publish reboot status via MQTT publish_message
|
|
1954
|
+
"""
|
|
1955
|
+
mqtt_msg = None
|
|
1944
1956
|
try:
|
|
1945
|
-
# Parse
|
|
1957
|
+
# Parse and validate MQTT message
|
|
1946
1958
|
mqtt_msg = MQTTMessage(**message)
|
|
1947
1959
|
message_id = mqtt_msg.messageId
|
|
1948
1960
|
|
|
1949
|
-
# Check if controller
|
|
1961
|
+
# Check if any controller has an active operation
|
|
1950
1962
|
for controller in self._active_controllers.values():
|
|
1951
1963
|
if controller is not None and controller.is_active:
|
|
1952
1964
|
error_msg = "PX4 reboot blocked - Active operation in progress"
|
|
@@ -1960,61 +1972,137 @@ class PetalUserJourneyCoordinator(Petal):
|
|
|
1960
1972
|
"error_code": "OPERATION_ACTIVE"
|
|
1961
1973
|
}
|
|
1962
1974
|
)
|
|
1963
|
-
|
|
1964
1975
|
return
|
|
1965
|
-
|
|
1966
|
-
logger.info(f"Restarting PX4 for {self.name} petal")
|
|
1967
|
-
reboot_response = await self._mavlink_proxy.reboot_autopilot(
|
|
1968
|
-
reboot_onboard_computer=False,
|
|
1969
|
-
timeout=5.0
|
|
1970
|
-
)
|
|
1971
|
-
|
|
1972
|
-
if not reboot_response.success:
|
|
1973
|
-
error_msg = "PX4 reboot command failed or timed out"
|
|
1974
|
-
logger.error(f"[{message_id}] {error_msg}")
|
|
1975
|
-
if mqtt_msg.waitResponse:
|
|
1976
|
-
await self._mqtt_proxy.send_command_response(
|
|
1977
|
-
message_id=message_id,
|
|
1978
|
-
response_data={
|
|
1979
|
-
"status": "error",
|
|
1980
|
-
"message": error_msg,
|
|
1981
|
-
"error_code": "REBOOT_FAILED",
|
|
1982
|
-
"data": _json_safe(reboot_response.model_dump())
|
|
1983
|
-
}
|
|
1984
|
-
)
|
|
1985
|
-
return
|
|
1986
|
-
|
|
1987
|
-
logger.info(f"[{message_id}] PX4 reboot command successful")
|
|
1988
1976
|
|
|
1977
|
+
# Step 1: Immediately respond to acknowledge command received
|
|
1978
|
+
logger.info(f"[{message_id}] PX4 reboot command received, sending acknowledgement")
|
|
1989
1979
|
if mqtt_msg.waitResponse:
|
|
1990
1980
|
await self._mqtt_proxy.send_command_response(
|
|
1991
1981
|
message_id=message_id,
|
|
1992
1982
|
response_data={
|
|
1993
1983
|
"status": "success",
|
|
1994
|
-
"message": "PX4 reboot command
|
|
1995
|
-
"data":
|
|
1984
|
+
"message": "PX4 reboot command initiated",
|
|
1985
|
+
"data": {
|
|
1986
|
+
"reboot_initiated": True,
|
|
1987
|
+
"message": "Reboot in progress, status will be published to command/web"
|
|
1988
|
+
}
|
|
1996
1989
|
}
|
|
1997
1990
|
)
|
|
1991
|
+
|
|
1998
1992
|
except ValidationError as ve:
|
|
1999
|
-
error_msg = f"Invalid PX4 reboot
|
|
1993
|
+
error_msg = f"Invalid PX4 reboot message: {ve}"
|
|
2000
1994
|
logger.error(f"PX4 reboot validation error: {error_msg}")
|
|
2001
|
-
if mqtt_msg.waitResponse:
|
|
1995
|
+
if mqtt_msg and mqtt_msg.waitResponse:
|
|
2002
1996
|
await self._mqtt_proxy.send_command_response(
|
|
2003
|
-
message_id=
|
|
1997
|
+
message_id=mqtt_msg.messageId,
|
|
2004
1998
|
response_data={
|
|
2005
1999
|
"status": "error",
|
|
2006
2000
|
"message": error_msg,
|
|
2007
2001
|
"error_code": "VALIDATION_ERROR"
|
|
2008
2002
|
}
|
|
2009
2003
|
)
|
|
2004
|
+
return
|
|
2010
2005
|
except Exception as e:
|
|
2011
|
-
|
|
2006
|
+
error_msg = f"PX4 reboot message handler error: {str(e)}"
|
|
2007
|
+
logger.error(f"Unexpected PX4 reboot error: {error_msg}")
|
|
2012
2008
|
if mqtt_msg and mqtt_msg.waitResponse:
|
|
2013
2009
|
await self._mqtt_proxy.send_command_response(
|
|
2014
2010
|
message_id=mqtt_msg.messageId,
|
|
2015
|
-
response_data={
|
|
2011
|
+
response_data={
|
|
2012
|
+
"status": "error",
|
|
2013
|
+
"message": error_msg,
|
|
2014
|
+
"error_code": "HANDLER_ERROR"
|
|
2015
|
+
}
|
|
2016
2016
|
)
|
|
2017
|
-
|
|
2017
|
+
return
|
|
2018
|
+
|
|
2019
|
+
try:
|
|
2020
|
+
# Step 2: Await the actual reboot operation
|
|
2021
|
+
logger.info(f"[{message_id}] Executing PX4 reboot for {self.name} petal")
|
|
2022
|
+
reboot_response: RebootAutopilotResponse = await self._mavlink_proxy.reboot_autopilot(
|
|
2023
|
+
reboot_onboard_computer=False,
|
|
2024
|
+
timeout=5.0
|
|
2025
|
+
)
|
|
2026
|
+
|
|
2027
|
+
# Step 3: Build and publish reboot status via MQTT
|
|
2028
|
+
if reboot_response.success:
|
|
2029
|
+
logger.info(f"[{message_id}] PX4 reboot successful: {reboot_response.reason}")
|
|
2030
|
+
status_payload = RebootPX4StatusPayload(
|
|
2031
|
+
reboot_initiated=True,
|
|
2032
|
+
reboot_success=True,
|
|
2033
|
+
status="success",
|
|
2034
|
+
message=reboot_response.reason,
|
|
2035
|
+
error_code=None,
|
|
2036
|
+
timestamp=datetime.now(timezone.utc)
|
|
2037
|
+
)
|
|
2038
|
+
else:
|
|
2039
|
+
logger.error(f"[{message_id}] PX4 reboot failed: {reboot_response.reason}")
|
|
2040
|
+
status_payload = RebootPX4StatusPayload(
|
|
2041
|
+
reboot_initiated=True,
|
|
2042
|
+
reboot_success=False,
|
|
2043
|
+
status="failed",
|
|
2044
|
+
message=reboot_response.reason,
|
|
2045
|
+
error_code=reboot_response.status_code.value,
|
|
2046
|
+
timestamp=datetime.now(timezone.utc)
|
|
2047
|
+
)
|
|
2048
|
+
|
|
2049
|
+
# Publish reboot status via MQTT
|
|
2050
|
+
mqtt_message = {
|
|
2051
|
+
"messageId": message_id,
|
|
2052
|
+
"command": f"/{self.name}/reboot_px4_status",
|
|
2053
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
2054
|
+
"payload": status_payload.model_dump(mode="json")
|
|
2055
|
+
}
|
|
2056
|
+
await self._mqtt_proxy.publish_message(payload=mqtt_message)
|
|
2057
|
+
logger.info(f"[{message_id}] Published reboot status to command/web")
|
|
2058
|
+
|
|
2059
|
+
except ValidationError as ve:
|
|
2060
|
+
error_msg = f"PX4 reboot status payload validation error: {ve}"
|
|
2061
|
+
logger.error(f"[{mqtt_msg.messageId if mqtt_msg else 'unknown'}] {error_msg}")
|
|
2062
|
+
# Try to publish error status if we got past validation
|
|
2063
|
+
if mqtt_msg:
|
|
2064
|
+
try:
|
|
2065
|
+
error_payload = RebootPX4StatusPayload(
|
|
2066
|
+
reboot_initiated=True,
|
|
2067
|
+
reboot_success=False,
|
|
2068
|
+
status="failed",
|
|
2069
|
+
message=error_msg,
|
|
2070
|
+
error_code="PAYLOAD_VALIDATION_ERROR",
|
|
2071
|
+
timestamp=datetime.now(timezone.utc)
|
|
2072
|
+
)
|
|
2073
|
+
mqtt_message = {
|
|
2074
|
+
"messageId": mqtt_msg.messageId,
|
|
2075
|
+
"command": f"/{self.name}/reboot_px4_status",
|
|
2076
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
2077
|
+
"payload": error_payload.model_dump(mode="json")
|
|
2078
|
+
}
|
|
2079
|
+
await self._mqtt_proxy.publish_message(payload=mqtt_message)
|
|
2080
|
+
except Exception as publish_error:
|
|
2081
|
+
logger.error(f"[{mqtt_msg.messageId}] Failed to publish error status: {publish_error}")
|
|
2082
|
+
|
|
2083
|
+
except Exception as e:
|
|
2084
|
+
error_msg = f"PX4 reboot error: {str(e)}"
|
|
2085
|
+
logger.error(f"[{mqtt_msg.messageId if mqtt_msg else 'unknown'}] {error_msg}")
|
|
2086
|
+
# Try to publish error status if we got past validation
|
|
2087
|
+
if mqtt_msg:
|
|
2088
|
+
try:
|
|
2089
|
+
error_payload = RebootPX4StatusPayload(
|
|
2090
|
+
reboot_initiated=True,
|
|
2091
|
+
reboot_success=False,
|
|
2092
|
+
status="failed",
|
|
2093
|
+
message=error_msg,
|
|
2094
|
+
error_code="EXECUTION_ERROR",
|
|
2095
|
+
timestamp=datetime.now(timezone.utc)
|
|
2096
|
+
)
|
|
2097
|
+
mqtt_message = {
|
|
2098
|
+
"messageId": mqtt_msg.messageId,
|
|
2099
|
+
"command": f"/{self.name}/reboot_px4_status",
|
|
2100
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
2101
|
+
"payload": error_payload.model_dump(mode="json")
|
|
2102
|
+
}
|
|
2103
|
+
await self._mqtt_proxy.publish_message(payload=mqtt_message)
|
|
2104
|
+
except Exception as publish_error:
|
|
2105
|
+
logger.error(f"[{mqtt_msg.messageId}] Failed to publish error status: {publish_error}")
|
|
2018
2106
|
|
|
2019
2107
|
def _create_parameter_message_handler(self, handler_key: str, config_type: str):
|
|
2020
2108
|
"""
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
petal_user_journey_coordinator-0.1.9.dist-info/METADATA,sha256=eHStRH5q2V1WJYWyFIEc7ROKS5ZVZQ03BuwwoWu7_IE,1635
|
|
2
|
+
petal_user_journey_coordinator-0.1.9.dist-info/WHEEL,sha256=Wb0ASbVj8JvWHpOiIpPi7ucfIgJeCi__PzivviEAQFc,90
|
|
3
|
+
petal_user_journey_coordinator-0.1.9.dist-info/entry_points.txt,sha256=KQ6R6_Hkhmre4_ecl2Ri7PKsAk3M-eEZIoTEhSigAQo,150
|
|
4
|
+
petal_user_journey_coordinator/__init__.py,sha256=2SZkPYkJXjCsy_74o2EnFj-N-bTqHzIQXHjOZkIqdo4,598
|
|
5
|
+
petal_user_journey_coordinator/controllers.py,sha256=I32JoHVopkQ_Cqmk0RRRJN-ZG3VnrGninQsVx_ojQ-I,150306
|
|
6
|
+
petal_user_journey_coordinator/data_model.py,sha256=gLEuTFI6iX-5DzT1EYFIRAF1IgwBYUh6yQlf5Z2wqRo,23818
|
|
7
|
+
petal_user_journey_coordinator/plugin.py,sha256=LWKSk0KsyG45xAZjAW92RVLb7Omt3BmNg0DXz_HRXPk,131018
|
|
8
|
+
petal_user_journey_coordinator-0.1.9.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
petal_user_journey_coordinator-0.1.8.dist-info/METADATA,sha256=76Qk_KywapLpDnxOwVq2keZEridQGwVNqPl9E3E2KBA,1635
|
|
2
|
-
petal_user_journey_coordinator-0.1.8.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
|
|
3
|
-
petal_user_journey_coordinator-0.1.8.dist-info/entry_points.txt,sha256=KQ6R6_Hkhmre4_ecl2Ri7PKsAk3M-eEZIoTEhSigAQo,150
|
|
4
|
-
petal_user_journey_coordinator/__init__.py,sha256=2SZkPYkJXjCsy_74o2EnFj-N-bTqHzIQXHjOZkIqdo4,598
|
|
5
|
-
petal_user_journey_coordinator/controllers.py,sha256=I32JoHVopkQ_Cqmk0RRRJN-ZG3VnrGninQsVx_ojQ-I,150306
|
|
6
|
-
petal_user_journey_coordinator/data_model.py,sha256=xITvKjjyRM-PoI3UUAuAmCuInjBUBSKlT5VIYCDpcR4,22763
|
|
7
|
-
petal_user_journey_coordinator/plugin.py,sha256=ik2FfCSnVvbTaKI6vCnWOZwBPofVeFAaXTrrMsGNK5s,126717
|
|
8
|
-
petal_user_journey_coordinator-0.1.8.dist-info/RECORD,,
|
|
File without changes
|