Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add endpoint for stream configs #645

Closed
wants to merge 1 commit into from
Closed
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
20 changes: 20 additions & 0 deletions src/isar/apis/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from pydantic import AnyHttpUrl

from isar.apis.models.models import ControlMissionResponse, StartMissionResponse
from isar.apis.robot_control.robot_controller import RobotController
from isar.apis.schedule.scheduling_controller import SchedulingController
from isar.apis.security.authentication import Authenticator
from isar.config.configuration_error import ConfigurationError
Expand All @@ -34,12 +35,14 @@ def __init__(
self,
authenticator: Authenticator,
scheduling_controller: SchedulingController,
robot_controller: RobotController,
keyvault_client: Keyvault,
port: int = settings.API_PORT,
azure_ai_logging_enabled: bool = settings.LOG_HANDLER_APPLICATION_INSIGHTS_ENABLED,
) -> None:
self.authenticator: Authenticator = authenticator
self.scheduling_controller: SchedulingController = scheduling_controller
self.robot_controller: RobotController = robot_controller
self.keyvault_client: Keyvault = keyvault_client
self.host: str = "0.0.0.0" # Locking uvicorn to use 0.0.0.0
self.port: int = port
Expand Down Expand Up @@ -98,6 +101,8 @@ def _create_app(self) -> FastAPI:

app.include_router(router=self._create_info_router())

app.include_router(router=self._create_media_control_router())

return app

def _create_scheduler_router(self) -> APIRouter:
Expand Down Expand Up @@ -284,6 +289,21 @@ def _create_info_router(self) -> APIRouter:
)

return router

def _create_media_control_router(self) -> APIRouter:
router: APIRouter = APIRouter(tags=["Media"])

authentication_dependency: Security = Security(self.authenticator.get_scheme())

router.add_api_route(
path="/media/media-stream-config",
endpoint=self.robot_controller.generate_media_stream_config,
methods=["GET"],
dependencies=[authentication_dependency],
summary="Generates a media stream connection config",
)

return router

def _log_startup_message(self) -> None:
address_format = "%s://%s:%d/docs"
Expand Down
41 changes: 41 additions & 0 deletions src/isar/apis/robot_control/robot_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import logging
from typing import List

from injector import inject

from isar.apis.models.models import (
RobotInfoResponse,
TaskResponse,
)
from isar.config.settings import robot_settings, settings
from isar.services.utilities.robot_utilities import RobotUtilities
from robot_interface.models.mission.task import Task


class RobotController:
@inject
def __init__(
self,
robot_utilities: RobotUtilities,
):
self.robot_utilities: RobotUtilities = robot_utilities
self.logger = logging.getLogger("api")

def generate_media_stream_config(self):
return self.robot_utilities.generate_robot_media_config()
andchiind marked this conversation as resolved.
Show resolved Hide resolved

def get_info(self):
andchiind marked this conversation as resolved.
Show resolved Hide resolved
return RobotInfoResponse(
robot_package=settings.ROBOT_PACKAGE,
isar_id=settings.ISAR_ID,
robot_name=settings.ROBOT_NAME,
robot_map_name=settings.DEFAULT_MAP,
robot_capabilities=robot_settings.CAPABILITIES,
)

def _task_api_response(self, task: Task) -> TaskResponse:
andchiind marked this conversation as resolved.
Show resolved Hide resolved
steps: List[dict] = []
for step in task.steps:
steps.append({"id": step.id, "type": step.__class__.__name__})

return TaskResponse(id=task.id, tag_id=task.tag_id, steps=steps)
21 changes: 20 additions & 1 deletion src/isar/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from isar.apis.api import API
from isar.apis.schedule.scheduling_controller import SchedulingController
from isar.apis.robot_control.robot_controller import RobotController
from isar.apis.security.authentication import Authenticator
from isar.config.keyvault.keyvault_service import Keyvault
from isar.config.settings import settings
Expand All @@ -18,6 +19,7 @@
from isar.models.communication.queues.queues import Queues
from isar.services.service_connections.request_handler import RequestHandler
from isar.services.utilities.scheduling_utilities import SchedulingUtilities
from isar.services.utilities.robot_utilities import RobotUtilities
from isar.state_machine.state_machine import StateMachine
from isar.storage.blob_storage import BlobStorage
from isar.storage.local_storage import LocalStorage
Expand All @@ -35,9 +37,10 @@ def provide_api(
self,
authenticator: Authenticator,
scheduling_controller: SchedulingController,
robot_controller: RobotController,
keyvault: Keyvault,
) -> API:
return API(authenticator, scheduling_controller, keyvault)
return API(authenticator, scheduling_controller, robot_controller, keyvault)

@provider
@singleton
Expand All @@ -46,6 +49,14 @@ def provide_scheduling_controller(
scheduling_utilities: SchedulingUtilities,
) -> SchedulingController:
return SchedulingController(scheduling_utilities)

@provider
@singleton
def provide_robot_controller(
self,
robot_utilities: RobotUtilities,
) -> SchedulingController:
return RobotController(robot_utilities)


class AuthenticationModule(Module):
Expand Down Expand Up @@ -150,6 +161,13 @@ def provide_scheduling_utilities(
) -> SchedulingUtilities:
return SchedulingUtilities(queues, mission_planner)

class RobotUtilitiesModule(Module):
andchiind marked this conversation as resolved.
Show resolved Hide resolved
@provider
@singleton
def provide_robot_utilities(
self, robot: RobotInterface
) -> RobotUtilities:
return RobotUtilities(robot)

class ServiceModule(Module):
@provider
Expand Down Expand Up @@ -194,6 +212,7 @@ def provide_task_selector(self) -> TaskSelectorInterface:
"storage_slimm": (SlimmStorageModule, settings.STORAGE_SLIMM_ENABLED),
"mqtt": (MqttModule, "required"),
"utilities": (UtilitiesModule, "required"),
"robot_utilities": (RobotUtilitiesModule, "required"),
}


Expand Down
27 changes: 27 additions & 0 deletions src/isar/services/utilities/robot_utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import logging

from injector import inject

from isar.config.settings import settings

from isar.config.settings import settings

from robot_interface.robot_interface import RobotInterface


class RobotUtilities:
"""
Contains utility functions for scheduling missions from the API. The class handles
required thread communication through queues to the state machine.
andchiind marked this conversation as resolved.
Show resolved Hide resolved
"""

@inject
def __init__(
self,
robot: RobotInterface,
):
self.robot: RobotInterface = robot
self.logger = logging.getLogger("api")

def generate_robot_media_config(self) -> str:
return self.robot.generate_media_config(settings.ISAR_ID, settings.ROBOT_NAME)
13 changes: 13 additions & 0 deletions src/robot_interface/robot_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,19 @@ def initialize(self, params: InitializeParams) -> None:

"""
raise NotImplementedError

@abstractmethod
def generate_media_config(self, isar_id: str, robot_name: str) -> str:
"""
Generate a JSON containing the url and token needed to establish a media stream
connection to a robot.

Returns
-------
str
JSON string containing the connection information for a media stream connection
"""
raise NotImplementedError

@abstractmethod
def get_telemetry_publishers(
Expand Down
Loading