diff --git a/src/fastcs_odin/odin_controller.py b/src/fastcs_odin/odin_controller.py index 7ef29be..aadbb47 100644 --- a/src/fastcs_odin/odin_controller.py +++ b/src/fastcs_odin/odin_controller.py @@ -10,7 +10,7 @@ FrameProcessorAdapterController, FrameReceiverAdapterController, ) -from fastcs_odin.util import OdinParameter, create_odin_parameters +from fastcs_odin.util import AdapterType, OdinParameter, create_odin_parameters types = {"float": Float(), "int": Int(), "bool": Bool(), "str": String()} @@ -50,9 +50,17 @@ async def initialise(self) -> None: response = await self.connection.get( f"{self.API_PREFIX}/{adapter}", headers=REQUEST_METADATA_HEADER ) + # Extract the module name of the adapter + match response: + case {"module": {"value": str() as module}}: + pass + case _: + raise ValueError( + f"Did not find valid module name in response:\n{response}" + ) adapter_controller = self._create_adapter_controller( - self.connection, create_odin_parameters(response), adapter + self.connection, create_odin_parameters(response), adapter, module ) self.register_sub_controller(adapter.upper(), adapter_controller) await adapter_controller.initialise() @@ -64,32 +72,30 @@ def _create_adapter_controller( connection: HTTPConnection, parameters: list[OdinParameter], adapter: str, + module: str, ) -> OdinAdapterController: """Create a sub controller for an adapter in an odin control server.""" - match adapter: - # TODO: May not be called "fp", it is configurable in the server - case "fp": + match module: + case AdapterType.FRAME_PROCESSOR: return FrameProcessorAdapterController( - connection, parameters, f"{self.API_PREFIX}/fp" + connection, parameters, f"{self.API_PREFIX}/{adapter}" ) - case "fr": + case AdapterType.FRAME_RECEIVER: return FrameReceiverAdapterController( - connection, parameters, f"{self.API_PREFIX}/fr" + connection, parameters, f"{self.API_PREFIX}/{adapter}" ) - case "mw": + case AdapterType.META_WRITER: return MetaWriterAdapterController( - connection, parameters, f"{self.API_PREFIX}/mw" + connection, parameters, f"{self.API_PREFIX}/{adapter}" ) - case "ef": + case AdapterType.EIGER_FAN: return EigerFanAdapterController( - connection, parameters, f"{self.API_PREFIX}/ef" + connection, parameters, f"{self.API_PREFIX}/{adapter}" ) case _: return OdinAdapterController( - connection, - parameters, - f"{self.API_PREFIX}/{adapter}", + connection, parameters, f"{self.API_PREFIX}/{adapter}" ) async def connect(self) -> None: diff --git a/src/fastcs_odin/util.py b/src/fastcs_odin/util.py index 9e96825..310e2f1 100644 --- a/src/fastcs_odin/util.py +++ b/src/fastcs_odin/util.py @@ -1,5 +1,6 @@ from collections.abc import Callable, Iterator, Mapping from dataclasses import dataclass, field +from enum import Enum from typing import Any, TypeVar @@ -7,6 +8,13 @@ def is_metadata_object(v: Any) -> bool: return isinstance(v, dict) and "writeable" in v and "type" in v +class AdapterType(str, Enum): + FRAME_PROCESSOR = "FrameProcessorAdapter" + FRAME_RECEIVER = "FrameReceiverAdapter" + META_WRITER = "MetaListenerAdapter" + EIGER_FAN = "EigerFanAdapter" + + @dataclass class OdinParameter: uri: list[str] diff --git a/tests/test_controllers.py b/tests/test_controllers.py index 80c7677..fc78b36 100644 --- a/tests/test_controllers.py +++ b/tests/test_controllers.py @@ -3,23 +3,31 @@ import pytest from fastcs.attributes import AttrR, AttrRW +from fastcs.connections.ip_connection import IPConnectionSettings from fastcs.datatypes import Bool, Float, Int from pytest_mock import MockerFixture +from fastcs_odin.eiger_fan import EigerFanAdapterController from fastcs_odin.http_connection import HTTPConnection +from fastcs_odin.meta_writer import MetaWriterAdapterController from fastcs_odin.odin_adapter_controller import ( ConfigFanSender, ParamTreeHandler, StatusSummaryUpdater, ) -from fastcs_odin.odin_controller import OdinAdapterController +from fastcs_odin.odin_controller import ( + OdinAdapterController, + OdinController, +) from fastcs_odin.odin_data import ( + FrameProcessorAdapterController, FrameProcessorController, FrameProcessorPluginController, + FrameReceiverAdapterController, FrameReceiverController, FrameReceiverDecoderController, ) -from fastcs_odin.util import OdinParameter +from fastcs_odin.util import AdapterType, OdinParameter HERE = Path(__file__).parent @@ -66,6 +74,38 @@ def test_fp_process_parameters(): ] +@pytest.mark.asyncio +async def test_create_adapter_controller(mocker: MockerFixture): + controller = OdinController(IPConnectionSettings("", 0)) + controller.connection = mocker.AsyncMock() + parameters = [OdinParameter(["0"], metadata={})] + + ctrl = controller._create_adapter_controller( + controller.connection, parameters, "fp", AdapterType.FRAME_PROCESSOR + ) + assert isinstance(ctrl, FrameProcessorAdapterController) + + ctrl = controller._create_adapter_controller( + controller.connection, parameters, "fr", AdapterType.FRAME_RECEIVER + ) + assert isinstance(ctrl, FrameReceiverAdapterController) + + ctrl = controller._create_adapter_controller( + controller.connection, parameters, "mw", AdapterType.META_WRITER + ) + assert isinstance(ctrl, MetaWriterAdapterController) + + ctrl = controller._create_adapter_controller( + controller.connection, parameters, "ef", AdapterType.EIGER_FAN + ) + assert isinstance(ctrl, EigerFanAdapterController) + + ctrl = controller._create_adapter_controller( + controller.connection, parameters, "od", "OtherAdapter" + ) + assert isinstance(ctrl, OdinAdapterController) + + @pytest.mark.asyncio async def test_fp_create_plugin_sub_controllers(): parameters = [