Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/scenarios/sdsp-f3623/sdsp_heartbeat.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
The scenario executes the following sequence of steps:

### 1. Start SDSP Session
- **Step:** `Start/Stop SDSP Session (START)`
- **Step:** `Start SDSP Session`
- **Action:** Initiates a new SDSP session with a unique UUID.
- **Context:** Signals the beginning of a data provision session.

Expand All @@ -33,6 +33,6 @@ The scenario executes the following sequence of steps:
- **Context:** Provides the time window for the heartbeat verification to collect data and confirm the count.

### 5. Stop SDSP Session
- **Step:** `Start/Stop SDSP Session (STOP)`
- **Step:** `Stop SDSP Session`
- **Action:** Terminates the SDSP session.
- **Purpose:** Cleanly closes the connection.
4 changes: 2 additions & 2 deletions docs/scenarios/sdsp-f3623/sdsp_track.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
The scenario executes the following sequence of steps:

### 1. Start SDSP Session
- **Step:** `Start/Stop SDSP Session (START)`
- **Step:** `Start SDSP Session`
- **Action:** Initiates a new SDSP session with a unique UUID.
- **Context:** Signals the beginning of a data provision session.

Expand Down Expand Up @@ -40,7 +40,7 @@ The scenario executes the following sequence of steps:
- **Context:** Provides the time window for the verification logic to confirm the track count.

### 6. Stop SDSP Session
- **Step:** `Start/Stop SDSP Session (STOP)`
- **Step:** `Stop SDSP Session`
- **Action:** Terminates the SDSP session.
- **Purpose:** Cleanly closes the connection.

Expand Down
8 changes: 3 additions & 5 deletions scenarios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ steps:
- step: Generate UUID

- id: start_session
step: Start / Stop SDSP Session
step: Start SDSP Session
arguments:
action: START
session_id: ${{ steps.Generate UUID.result }}

- step: Wait X seconds
Expand All @@ -37,9 +36,8 @@ steps:
arguments:
duration: 5

- step: Start / Stop SDSP Session
- step: Stop SDSP Session
arguments:
action: STOP
session_id: ${{ steps.Generate UUID.result }}
```

Expand Down Expand Up @@ -134,7 +132,7 @@ python -m pytest tests/test_yaml_scenarios.py -q --tb=no
```

## Discovering Available Operations
The system exposes registered operations used in YAML (e.g., `Generate UUID`, `Wait X seconds`, `Start / Stop SDSP Session`). These are provided by clients and discovered at runtime. In the web editor, you can browse and insert these operations directly.
The system exposes registered operations used in YAML (e.g., `Generate UUID`, `Wait X seconds`, `Start SDSP Session`, `Stop SDSP Session`). These are provided by clients and discovered at runtime. In the web editor, you can browse and insert these operations directly.

## Tips
- Keep `id` short and unique if you plan to reference a step later.
Expand Down
6 changes: 2 additions & 4 deletions scenarios/sdsp-f3623/sdsp_heartbeat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ steps:
- step: Generate UUID

- id: start_session
step: Start / Stop SDSP Session
step: Start SDSP Session
arguments:
action: START
session_id: ${{ steps.Generate UUID.result }}

- step: Wait X seconds
Expand All @@ -25,7 +24,6 @@ steps:
arguments:
duration: 5

- step: Start / Stop SDSP Session
- step: Stop SDSP Session
arguments:
action: STOP
session_id: ${{ steps.Generate UUID.result }}
6 changes: 2 additions & 4 deletions scenarios/sdsp-f3623/sdsp_track.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ description: Runs the SDSP track scenario.
steps:
- step: Generate UUID
- id: start_sdsp_session
step: Start / Stop SDSP Session
step: Start SDSP Session
arguments:
session_id: ${{ steps.Generate UUID.result }}
action: START
- id: stream_air_traffic
step: Stream Air Traffic
arguments:
Expand All @@ -27,9 +26,8 @@ steps:
arguments:
duration: 5
- id: stop_sdsp_session
step: Start / Stop SDSP Session
step: Stop SDSP Session
arguments:
session_id: ${{ steps.Generate UUID.result }}
action: STOP
needs:
- stream_air_traffic
6 changes: 2 additions & 4 deletions scenarios/sdsp-f3623/verify_sdsp_metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ 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 / Stop SDSP Session
step: Start SDSP Session
arguments:
session_id: ${{ steps.generated_sdsp_session_id.result }}
action: START
- id: wait_10_seconds
step: Wait X seconds
arguments:
Expand All @@ -31,9 +30,8 @@ steps:
observations: ${{ steps.stream_air_traffic.result.observations }}
# session_id: ${{ steps.generated_sdsp_session_id.result }}
- id: stop_sdsp_session
step: Start / Stop SDSP Session
step: Stop SDSP Session
arguments:
session_id: ${{ steps.generated_sdsp_session_id.result }}
action: STOP
needs:
- stream_air_traffic
Original file line number Diff line number Diff line change
Expand Up @@ -1145,36 +1145,36 @@ async def list_sensor_failure_notifications(self) -> StepResult:
result=f"Retrieved {len(notifications)} sensor failure notifications",
)

@scenario_step("Start / Stop SDSP Session")
async def start_stop_sdsp_session(self, 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 (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.
"""

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.

Args:
session_id: The unique identifier of the SDSP session to start.
"""
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:
Comment thread
atti92 marked this conversation as resolved.
"""Stops an SDSP (Strategic Deconfliction Service Provider) session.

Args:
session_id: The unique identifier of the SDSP session to stop.
"""
return await self._sdsp_session_action(session_id, SDSPSessionAction.STOP)

async def initialize_heartbeat_websocket_connection(self, session_id: str) -> ClientConnection:
endpoint = f"/ws/surveillance/heartbeat/{session_id}"
ws = await self.create_websocket_connection(endpoint=endpoint)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
FlightBlenderClient,
)
from openutm_verification.core.reporting.reporting_models import StepResult
from openutm_verification.models import SDSPSessionAction
from openutm_verification.scenarios.registry import register_scenario


Expand All @@ -23,8 +22,7 @@ async def sdsp_track_with_bluesky_sim(
session_id = str(uuid.uuid4())
logger.info(f"Starting SDSP track scenario with session ID: {session_id}")

await fb_client.start_stop_sdsp_session(
action=SDSPSessionAction.START,
await fb_client.start_sdsp_session(
session_id=session_id,
)

Expand All @@ -47,8 +45,7 @@ async def sdsp_track_with_bluesky_sim(

await asyncio.sleep(5)

await fb_client.start_stop_sdsp_session(
action=SDSPSessionAction.STOP,
await fb_client.stop_sdsp_session(
session_id=session_id,
)

Expand Down
17 changes: 14 additions & 3 deletions tests/test_client_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, SDSPSessionAction
from openutm_verification.models import OperationState
from openutm_verification.simulator.models.flight_data_types import FlightObservationSchema


Expand Down Expand Up @@ -267,17 +267,28 @@ async def test_submit_air_traffic(fb_client):
fb_client.post.assert_called_once()


async def test_start_stop_sdsp_session(fb_client):
async def test_start_sdsp_session(fb_client):
mock_response = MagicMock()
mock_response.status_code = 200
fb_client.put.return_value = mock_response

result = await fb_client.start_stop_sdsp_session(session_id="sess_123", action=SDSPSessionAction.START)
result = await fb_client.start_sdsp_session(session_id="sess_123")

assert "start Heartbeat Track message received" in result.result
fb_client.put.assert_called_once()


async def test_stop_sdsp_session(fb_client):
mock_response = MagicMock()
mock_response.status_code = 200
fb_client.put.return_value = mock_response

result = await fb_client.stop_sdsp_session(session_id="sess_123")

assert "stop Heartbeat Track message received" in result.result
fb_client.put.assert_called_once()


async def test_initialize_verify_sdsp_track(fb_client):
mock_ws = MagicMock()
# Simulate messages: 2 initial + 3 valid tracks
Expand Down
3 changes: 2 additions & 1 deletion tests/test_yaml_scenarios.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def mock_clients():
# Mock methods that return values used in other steps
fb_client.upload_geo_fence.return_value = {"id": "geo_fence_123"}
fb_client.upload_flight_declaration.return_value = {"id": "flight_decl_123", "is_approved": True}
fb_client.start_stop_sdsp_session.return_value = "Session Started"
fb_client.start_sdsp_session.return_value = "Session Started"
fb_client.stop_sdsp_session.return_value = "Session Stopped"

# Mock methods that return objects with attributes accessed in YAML
# e.g. ${{ steps.stream_air_traffic.result.observations }}
Expand Down
Loading