diff --git a/src/blueapi/service/interface.py b/src/blueapi/service/interface.py index 7df474557..f4ed2aa3e 100644 --- a/src/blueapi/service/interface.py +++ b/src/blueapi/service/interface.py @@ -7,6 +7,9 @@ from typing import Any from bluesky.callbacks.tiled_writer import TiledWriter +from bluesky.protocols import Readable, Reading +from bluesky.run_engine import call_in_bluesky_event_loop +from bluesky.utils import maybe_await from bluesky_stomp.messaging import StompClient from bluesky_stomp.models import Broker, DestinationBase, MessageTopic from fastapi import status @@ -342,6 +345,18 @@ def get_python_env( return get_python_environment(config=scratch, name=name, source=source) +def read_device(addr: str) -> dict[str, Reading[Any]]: + device = context().find_device(addr) + + if not isinstance(device, Readable): + raise TypeError("Requested device is not readable") + + return call_in_bluesky_event_loop( + maybe_await(device.read()), + timeout=10.0, + ) + + @dataclass class SubHandles: worker: int diff --git a/src/blueapi/service/main.py b/src/blueapi/service/main.py index 2ba310787..a72b575ff 100644 --- a/src/blueapi/service/main.py +++ b/src/blueapi/service/main.py @@ -618,6 +618,15 @@ def get_python_environment( return runner.run(interface.get_python_env, name, source) +@secure_router_v1.get("/device-read/{device}", tags=[Tag.DEVICE]) +@start_as_current_span(TRACER) +def read_device( + runner: Annotated[WorkerDispatcher, Depends(_runner)], + device: str, +): + return runner.run(interface.read_device, device) + + @open_router.get("/healthz", status_code=status.HTTP_200_OK, tags=[Tag.META]) def health_probe() -> HealthProbeResponse: """If able to serve this, server is live and ready for requests."""