diff --git a/scenarios/README.md b/scenarios/README.md index 6809e487..db3a03f9 100644 --- a/scenarios/README.md +++ b/scenarios/README.md @@ -19,7 +19,8 @@ steps: - id: start_session step: Start SDSP Session arguments: - session_id: ${{ steps.Generate UUID.result }} + action: START + surveillance_session_id: ${{ steps.Generate UUID.result }} - step: Wait X seconds arguments: @@ -27,7 +28,7 @@ steps: - step: Verify SDSP Heartbeat arguments: - session_id: ${{ steps.Generate UUID.result }} + surveillance_session_id: ${{ steps.Generate UUID.result }} expected_heartbeat_interval_seconds: 1 expected_heartbeat_count: 3 @@ -38,7 +39,8 @@ steps: - step: Stop SDSP Session arguments: - session_id: ${{ steps.Generate UUID.result }} + action: STOP + surveillance_session_id: ${{ steps.Generate UUID.result }} ``` ## Step Groups (Reusable Step Collections) diff --git a/scenarios/sdsp-f3623/sdsp_heartbeat.yaml b/scenarios/sdsp-f3623/sdsp_heartbeat.yaml index a72ecb48..43028bb4 100644 --- a/scenarios/sdsp-f3623/sdsp_heartbeat.yaml +++ b/scenarios/sdsp-f3623/sdsp_heartbeat.yaml @@ -5,9 +5,10 @@ steps: - step: Generate UUID - id: start_session - step: Start SDSP Session + step: Start / Stop SDSP Session arguments: - session_id: ${{ steps.Generate UUID.result }} + action: START + surveillance_session_id: ${{ steps.Generate UUID.result }} - step: Wait X seconds arguments: @@ -15,7 +16,7 @@ steps: - step: Verify SDSP Heartbeat arguments: - session_id: ${{ steps.Generate UUID.result }} + surveillance_session_id: ${{ steps.Generate UUID.result }} expected_heartbeat_interval_seconds: 1 expected_heartbeat_count: 3 @@ -24,6 +25,7 @@ steps: arguments: duration: 5 - - step: Stop SDSP Session + - step: Start / Stop SDSP Session arguments: - session_id: ${{ steps.Generate UUID.result }} + action: STOP + surveillance_session_id: ${{ steps.Generate UUID.result }} diff --git a/scenarios/sdsp-f3623/sdsp_track.yaml b/scenarios/sdsp-f3623/sdsp_track.yaml index 652466b3..9e5e69ab 100644 --- a/scenarios/sdsp-f3623/sdsp_track.yaml +++ b/scenarios/sdsp-f3623/sdsp_track.yaml @@ -3,9 +3,10 @@ description: Runs the SDSP track scenario. steps: - step: Generate UUID - id: start_sdsp_session - step: Start SDSP Session + step: Start / Stop SDSP Session arguments: - session_id: ${{ steps.Generate UUID.result }} + surveillance_session_id: ${{ steps.Generate UUID.result }} + action: START - id: stream_air_traffic step: Stream Air Traffic arguments: @@ -20,14 +21,15 @@ steps: arguments: expected_track_interval_seconds: 1 expected_track_count: 3 - session_id: ${{ steps.Generate UUID.result }} + surveillance_session_id: ${{ steps.Generate UUID.result }} - id: wait_5_seconds step: Wait X seconds arguments: duration: 5 - id: stop_sdsp_session - step: Stop SDSP Session + step: Start / Stop SDSP Session arguments: - session_id: ${{ steps.Generate UUID.result }} + surveillance_session_id: ${{ steps.Generate UUID.result }} + action: STOP needs: - stream_air_traffic diff --git a/scenarios/sdsp-f3623/verify_sdsp_metrics.yaml b/scenarios/sdsp-f3623/verify_sdsp_metrics.yaml index e41b96dc..64de850e 100644 --- a/scenarios/sdsp-f3623/verify_sdsp_metrics.yaml +++ b/scenarios/sdsp-f3623/verify_sdsp_metrics.yaml @@ -16,9 +16,10 @@ steps: description: Generate a unique session ID for this test run, this is used to create a SDSP session, the default.yaml config step: Generate UUID - id: start_sdsp_session - step: Start SDSP Session + step: Start / Stop SDSP Session arguments: - session_id: ${{ steps.generated_sdsp_session_id.result }} + surveillance_session_id: ${{ steps.generated_sdsp_session_id.result }} + action: START - id: wait_10_seconds step: Wait X seconds arguments: @@ -30,8 +31,9 @@ steps: observations: ${{ steps.stream_air_traffic.result.observations }} # session_id: ${{ steps.generated_sdsp_session_id.result }} - id: stop_sdsp_session - step: Stop SDSP Session + step: Start / Stop SDSP Session arguments: - session_id: ${{ steps.generated_sdsp_session_id.result }} + surveillance_session_id: ${{ steps.generated_sdsp_session_id.result }} + action: STOP needs: - stream_air_traffic diff --git a/src/openutm_verification/core/clients/flight_blender/flight_blender_client.py b/src/openutm_verification/core/clients/flight_blender/flight_blender_client.py index a9250bf1..0aa692dd 100644 --- a/src/openutm_verification/core/clients/flight_blender/flight_blender_client.py +++ b/src/openutm_verification/core/clients/flight_blender/flight_blender_client.py @@ -1145,43 +1145,43 @@ async def list_sensor_failure_notifications(self) -> StepResult: result=f"Retrieved {len(notifications)} sensor failure notifications", ) - async def _sdsp_session_action(self, session_id: str, action: SDSPSessionAction) -> str: - endpoint = f"/surveillance_monitoring_ops/start_stop_surveillance_heartbeat_track/{session_id}" - payload = {"action": action.value} - response = await self.put(endpoint, json=payload) - logger.info(f"SDSP session {session_id} action {action.value} response: {response.status_code}") - if response.status_code == 200: - logger.info(f"SDSP session {session_id} action {action.value} completed successfully.") - return f"{action.value} Heartbeat Track message received for {session_id}" - else: - logger.error(f"Failed to perform action {action.value} on SDSP session {session_id}. Response: {response.text}") - raise FlightBlenderError(f"{action.value} Heartbeat Track message not received for {session_id}") - - @scenario_step("Start SDSP Session", phase=FlightPhase.PRE_FLIGHT) - async def start_sdsp_session(self, session_id: str) -> str: - """Starts an SDSP (Strategic Deconfliction Service Provider) session. - + @scenario_step("Start / Stop SDSP Session") + async def start_stop_sdsp_session(self, surveillance_session_id: str, action: SDSPSessionAction) -> str: + """ + Starts or stops an SDSP (Strategic Deconfliction Service Provider) session based on the specified action. + This method interacts with the Flight Blender service to manage the lifecycle of an SDSP session. + It can be used to initiate a new session or terminate an existing one. Args: - session_id: The unique identifier of the SDSP session to start. + session_id (str): The unique identifier of the SDSP session to start or stop. + action (SDSPSessionAction): The action to perform on the session, such as START or STOP. + Returns: + bool: True if the action was successfully performed, False otherwise. + Raises: + ValueError: If the session_id is invalid or the action is not supported. + ConnectionError: If there is an issue communicating with the Flight Blender service. + FlightBlenderError: If the action fails due to service errors. """ - return await self._sdsp_session_action(session_id, SDSPSessionAction.START) - @scenario_step("Stop SDSP Session", phase=FlightPhase.POST_FLIGHT) - async def stop_sdsp_session(self, session_id: str) -> str: - """Stops an SDSP (Strategic Deconfliction Service Provider) session. + endpoint = f"/surveillance_monitoring_ops/start_stop_surveillance_heartbeat_track/{surveillance_session_id}" - Args: - session_id: The unique identifier of the SDSP session to stop. - """ - return await self._sdsp_session_action(session_id, SDSPSessionAction.STOP) + payload = {"action": action.value} + response = await self.put(endpoint, json=payload) + logger.info(f"SDSP session {surveillance_session_id} action {action.value} response: {response.status_code}") + if response.status_code == 200: + logger.info(f"SDSP session {surveillance_session_id} action {action.value} completed successfully.") + return f"{action.value} Heartbeat Track message received for {surveillance_session_id}" + + else: + logger.error(f"Failed to perform action {action.value} on SDSP session {surveillance_session_id}. Response: {response.text}") + raise FlightBlenderError(f"{action.value} Heartbeat Track message not received for {surveillance_session_id}") - async def initialize_heartbeat_websocket_connection(self, session_id: str) -> ClientConnection: - endpoint = f"/ws/surveillance/heartbeat/{session_id}" + async def initialize_heartbeat_websocket_connection(self, surveillance_session_id: str) -> ClientConnection: + endpoint = f"/ws/surveillance/heartbeat/{surveillance_session_id}" ws = await self.create_websocket_connection(endpoint=endpoint) return ws - async def initialize_track_websocket_connection(self, session_id: str) -> ClientConnection: - endpoint = f"/ws/surveillance/track/{session_id}" + async def initialize_track_websocket_connection(self, surveillance_session_id: str) -> ClientConnection: + endpoint = f"/ws/surveillance/track/{surveillance_session_id}" ws = await self.create_websocket_connection(endpoint=endpoint) return ws @@ -1190,9 +1190,9 @@ async def initialize_verify_sdsp_track( self, expected_track_interval_seconds: int, expected_track_count: int, - session_id: str, + surveillance_session_id: str, ) -> StepResult: - ws_connection = await self.initialize_track_websocket_connection(session_id=session_id) + ws_connection = await self.initialize_track_websocket_connection(surveillance_session_id=surveillance_session_id) start_time = time.time() all_received_messages = [] @@ -1252,9 +1252,9 @@ async def initialize_verify_sdsp_heartbeat( self, expected_heartbeat_interval_seconds: int, expected_heartbeat_count: int, - session_id: str, + surveillance_session_id: str, ) -> StepResult: - ws_connection = await self.initialize_heartbeat_websocket_connection(session_id=session_id) + ws_connection = await self.initialize_heartbeat_websocket_connection(surveillance_session_id=surveillance_session_id) start_time = time.time() all_received_messages = [] diff --git a/tests/test_client_steps.py b/tests/test_client_steps.py index 46662d0e..68a69758 100644 --- a/tests/test_client_steps.py +++ b/tests/test_client_steps.py @@ -12,7 +12,7 @@ from openutm_verification.core.clients.flight_blender.flight_blender_client import FlightBlenderClient from openutm_verification.core.clients.opensky.opensky_client import OpenSkyClient from openutm_verification.core.reporting.reporting_models import Status -from openutm_verification.models import OperationState +from openutm_verification.models import OperationState, SDSPSessionAction from openutm_verification.simulator.models.flight_data_types import FlightObservationSchema @@ -272,7 +272,7 @@ async def test_start_sdsp_session(fb_client): mock_response.status_code = 200 fb_client.put.return_value = mock_response - result = await fb_client.start_sdsp_session(session_id="sess_123") + result = await fb_client.start_stop_sdsp_session(surveillance_session_id="sess_123", action=SDSPSessionAction.START) assert "start Heartbeat Track message received" in result.result fb_client.put.assert_called_once() @@ -283,7 +283,7 @@ async def test_stop_sdsp_session(fb_client): mock_response.status_code = 200 fb_client.put.return_value = mock_response - result = await fb_client.stop_sdsp_session(session_id="sess_123") + result = await fb_client.start_stop_sdsp_session(surveillance_session_id="sess_123", action=SDSPSessionAction.STOP) assert "stop Heartbeat Track message received" in result.result fb_client.put.assert_called_once() @@ -330,7 +330,7 @@ async def test_initialize_verify_sdsp_track(fb_client): except Exception: pass # Expected to fail due to complex mocking needs, but we verified the call - fb_client.initialize_track_websocket_connection.assert_called_with(session_id="sess_123") + fb_client.initialize_track_websocket_connection.assert_called_with(surveillance_session_id="sess_123") async def test_submit_simulated_air_traffic(fb_client): @@ -495,7 +495,7 @@ async def test_initialize_verify_sdsp_heartbeat(fb_client): except Exception: # noqa: E722 pass - fb_client.initialize_heartbeat_websocket_connection.assert_called_with(session_id="sess_123") + fb_client.initialize_heartbeat_websocket_connection.assert_called_with(surveillance_session_id="sess_123") async def test_setup_flight_declaration(fb_client):