diff --git a/.vscode/launch.json b/.vscode/launch.json index 78d0876..72a40ed 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": "Debug temp controller", + "name": "TempController Sim", "type": "python", "request": "launch", "module": "tickit", @@ -25,6 +25,23 @@ "PYTEST_ADDOPTS": "--no-cov" }, }, + { + "name": "TempController IOC", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/src/demo_fast_cs/demo.py", + "justMyCode": false, + "purpose": [ + "debug-test" + ], + "console": "integratedTerminal", + "env": { + // The default config in pyproject.toml's "[tool.pytest.ini_options]" adds coverage. + // Cannot have coverage and debugging at the same time. + // https://github.com/microsoft/vscode-python/issues/693 + "PYTEST_ADDOPTS": "--no-cov" + }, + }, { "name": "Debug Unit Test", "type": "python", diff --git a/src/demo_fast_cs/controllers.py b/src/demo_fast_cs/controllers.py index 30a4c28..977c5ab 100755 --- a/src/demo_fast_cs/controllers.py +++ b/src/demo_fast_cs/controllers.py @@ -1,5 +1,6 @@ from __future__ import annotations +import asyncio from dataclasses import dataclass from typing import Any @@ -41,6 +42,7 @@ async def update( response = await controller.conn.send_query( f"{self.name}{controller.suffix}?\r\n" ) + if attr.dtype is bool: await attr.set(int(response)) else: @@ -48,7 +50,7 @@ async def update( class TempController(Controller): - ramp_rate = AttrRW(Float(), handler=TempControllerHandler("R")) + ramp_rate = AttrRW(Float(), handler=TempControllerHandler("R"), group="Config") def __init__(self, settings: TempControllerSettings) -> None: super().__init__() @@ -63,10 +65,12 @@ def __init__(self, settings: TempControllerSettings) -> None: self._ramp_controllers.append(controller) self.register_sub_controller(controller) - @command + @command() async def cancel_all(self) -> None: for rc in self._ramp_controllers: await rc.enabled.process(False) + # TODO: The requests all get concatenated if they are sent too quickly? + await asyncio.sleep(0.1) async def connect(self) -> None: await self.conn.connect(self._settings.ip_settings) @@ -76,12 +80,12 @@ async def close(self) -> None: class TempRampController(SubController): - start = AttrRW(Int(), handler=TempControllerHandler("S")) - end = AttrRW(Int(), handler=TempControllerHandler("E")) - current = AttrR(Float(prec=3), handler=TempControllerHandler("T")) + start = AttrRW(Int(), handler=TempControllerHandler("S"), group="Config") + end = AttrRW(Int(), handler=TempControllerHandler("E"), group="Config") + current = AttrR(Float(prec=3), handler=TempControllerHandler("T"), group="Status") enabled = AttrRW(Bool(znam="Off", onam="On"), handler=TempControllerHandler("N")) def __init__(self, index: int, conn: IPConnection) -> None: self.suffix = f"{index:02d}" - super().__init__(f"ramp{self.suffix}") + super().__init__(f"Ramp{self.suffix}") self.conn = conn diff --git a/src/demo_fast_cs/demo.py b/src/demo_fast_cs/demo.py index ca08040..77dba8e 100644 --- a/src/demo_fast_cs/demo.py +++ b/src/demo_fast_cs/demo.py @@ -80,3 +80,7 @@ def main() -> None: # test_asyncio_backend() create_gui() test_ioc() + + +if __name__ == "__main__": + main() diff --git a/src/demo_fast_cs/simulation/device.py b/src/demo_fast_cs/simulation/device.py index df8fc8d..62cec2e 100755 --- a/src/demo_fast_cs/simulation/device.py +++ b/src/demo_fast_cs/simulation/device.py @@ -1,19 +1,19 @@ import logging import traceback -from dataclasses import dataclass from os import _exit import numpy as np import numpy.typing as npt -from tickit.adapters.composed import ComposedAdapter -from tickit.adapters.interpreters.command import CommandInterpreter -from tickit.adapters.interpreters.command.regex_command import RegexCommand -from tickit.adapters.interpreters.wrappers import SplittingInterpreter -from tickit.adapters.servers.tcp import ByteFormat, TcpServer +import pydantic.v1.dataclasses +from tickit.adapters.io import TcpIo +from tickit.adapters.specifications.regex_command import RegexCommand +from tickit.adapters.tcp import CommandAdapter +from tickit.core.adapter import AdapterContainer from tickit.core.components.component import Component, ComponentConfig -from tickit.core.components.device_simulation import DeviceSimulation +from tickit.core.components.device_component import DeviceComponent from tickit.core.device import Device, DeviceUpdate from tickit.core.typedefs import SimTime +from tickit.utils.byte_format import ByteFormat from typing_extensions import TypedDict @@ -35,8 +35,11 @@ def wrapped_func(*args, **kwargs): class TempControllerDevice(Device): - Inputs: type = TypedDict("Inputs", {"flux": float}) - Outputs: type = TypedDict("Outputs", {"flux": float}) + class Inputs(TypedDict): + flux: float + + class Outputs(TypedDict): + flux: float def __init__( self, @@ -105,19 +108,13 @@ def update(self, time: SimTime, inputs: Inputs) -> DeviceUpdate[Outputs]: return DeviceUpdate(TempControllerDevice.Outputs(flux=inputs["flux"]), call_at) -class TempControllerAdapter(ComposedAdapter): +class TempControllerAdapter(CommandAdapter): device: TempControllerDevice + _byte_format: ByteFormat = ByteFormat(b"%b\r\n") - def __init__( - self, - host: str = "localhost", - port: int = 25565, - ) -> None: - super().__init__( - TcpServer(host, port, ByteFormat(b"%b\r\n")), - SplittingInterpreter(CommandInterpreter(), message_delimiter=b"\n"), - # CommandInterpreter(), - ) + def __init__(self, device: TempControllerDevice) -> None: + super().__init__() + self.device = device def _validate_index(self, index: str) -> int: int_index = int(index) - 1 @@ -172,7 +169,7 @@ async def ignore_whitespace(self) -> None: pass -@dataclass +@pydantic.v1.dataclasses.dataclass class TempController(ComponentConfig): num_ramp_controllers: int default_start: float = 0 @@ -181,12 +178,18 @@ class TempController(ComponentConfig): port: int = 25565 def __call__(self) -> Component: - return DeviceSimulation( + device = TempControllerDevice( + num_ramp_controllers=self.num_ramp_controllers, + default_start=self.default_start, + default_end=self.default_end, + ) + return DeviceComponent( name=self.name, - device=TempControllerDevice( - num_ramp_controllers=self.num_ramp_controllers, - default_start=self.default_start, - default_end=self.default_end, - ), - adapters=[TempControllerAdapter(host=self.host, port=self.port)], + device=device, + adapters=[ + AdapterContainer( + TempControllerAdapter(device), + TcpIo(self.host, self.port), + ) + ], ) diff --git a/src/demo_fast_cs/simulation/temp_controller.yaml b/src/demo_fast_cs/simulation/temp_controller.yaml index 5d88ecd..34562a9 100644 --- a/src/demo_fast_cs/simulation/temp_controller.yaml +++ b/src/demo_fast_cs/simulation/temp_controller.yaml @@ -1,15 +1,21 @@ -- tickit.devices.source.Source: - name: source - inputs: {} - value: 42.0 -- demo_fast_cs.simulation.device.TempController: - name: tempcont - inputs: - flux: source:value - num_ramp_controllers: 4 - default_start: 10 - default_end: 50 -- tickit.devices.sink.Sink: - name: sink - inputs: - flux: tempcont:flux \ No newline at end of file +- type: tickit.devices.source.Source + name: source + inputs: {} + value: 42.0 + +- type: demo_fast_cs.simulation.device.TempController + name: tempcont + inputs: + flux: + component: source + port: value + num_ramp_controllers: 4 + default_start: 10 + default_end: 50 + +- type: tickit.devices.sink.Sink + name: sink + inputs: + flux: + component: tempcont + port: flux