Update things to have thing_server_interface, and further fixes to properties

This commit is contained in:
Julian Stirling 2025-12-14 13:07:50 +00:00
parent a0b8a71477
commit 5d3aa71b4f
9 changed files with 39 additions and 17 deletions

View file

@ -175,7 +175,7 @@ class BaseCamera(lt.Thing):
lores_mjpeg_stream = lt.outputs.MJPEGStreamDescriptor()
_memory_buffer = CameraMemoryBuffer()
def __init__(self) -> None:
def __init__(self, thing_server_interface: lt.ThingServerInterface) -> None:
"""Initialise the base camera, this creates the background detectors.
This must be run by all child camera classes.
@ -183,7 +183,7 @@ class BaseCamera(lt.Thing):
To add a new background detector to the server it must be added to the
dictionary in this function. Configuration will be added at a later date.
"""
super().__init__()
super().__init__(thing_server_interface)
self.background_detectors = {
"Colour Channels (LUV)": ColourChannelDetectLUV(),
"Channel Deviations (LUV)": ChannelDeviationLUV(),

View file

@ -27,12 +27,14 @@ LOGGER = logging.getLogger(__name__)
class OpenCVCamera(BaseCamera):
"""A Thing that provides and interface to an OpenCV Camera."""
def __init__(self, camera_index: int = 0) -> None:
def __init__(
self, thing_server_interface: lt.ThingServerInterface, camera_index: int = 0
) -> None:
"""Iniatilise the thing storing the index of the camera to use.
:param camera_index: The index of the camera to use for the microscope.
"""
super().__init__()
super().__init__(thing_server_interface)
self.camera_index = camera_index
self._capture_thread: Optional[Thread] = None
self._capture_enabled = False

View file

@ -128,7 +128,12 @@ class StreamingPiCamera2(BaseCamera):
generalisation.
"""
def __init__(self, camera_num: int = 0, camera_board: str = "picamera_v2") -> None:
def __init__(
self,
thing_server_interface: lt.ThingServerInterface,
camera_num: int = 0,
camera_board: str = "picamera_v2",
) -> None:
"""Initialise the camera with the given camera number.
This makes no connection to the camera (except to get the default tuning file).
@ -138,7 +143,7 @@ class StreamingPiCamera2(BaseCamera):
:param camera_board: The camera board used. Supported options are "picamera_v2"
and "picamera_hq".
"""
super().__init__()
super().__init__(thing_server_interface)
self._setting_save_in_progress = False
self._camera_num = camera_num
self._camera_board = camera_board
@ -175,7 +180,7 @@ class StreamingPiCamera2(BaseCamera):
mjpeg_bitrate: Optional[int] = lt.property(default=100000000)
"""Bitrate for MJPEG stream (None for default)."""
stream_active: bool = lt.property(default=False, observable=True, readonly=True)
stream_active: bool = lt.property(default=False, readonly=True)
"""Whether the MJPEG stream is active."""
def save_settings(self) -> None:

View file

@ -52,6 +52,7 @@ class SimulatedCamera(BaseCamera):
def __init__(
self,
thing_server_interface: lt.ThingServerInterface,
shape: tuple[int, int, int] = (616, 820, 3),
glyph_shape: tuple[int, int, int] = (121, 121, 3),
canvas_shape: tuple[int, int, int] = (3000, 4000, 3),
@ -71,7 +72,7 @@ class SimulatedCamera(BaseCamera):
:param frame_interval: Nominally the time between frames on the MJPEG stream,
however the rate may be slower due to calculation time for focus.
"""
super().__init__()
super().__init__(thing_server_interface)
self.shape = shape
self.glyph_shape = glyph_shape
self.canvas_shape = canvas_shape

View file

@ -103,13 +103,16 @@ class SmartScanThing(lt.Thing):
past scans.
"""
def __init__(self, scans_folder: str) -> None:
def __init__(
self, thing_server_interface: lt.ThingServerInterface, scans_folder: str
) -> None:
"""Initialise a SmartScanThing saving to and loading from the input directory.
:param scans_folder: This is the path to the directory where all scans will be
saved. Any scans already in this directory will be accessible through the
HTTP interface.
"""
super().__init__(thing_server_interface)
self._scan_dir_manager = scan_directories.ScanDirectoryManager(scans_folder)
self._scan_lock = threading.Lock()

View file

@ -46,7 +46,7 @@ class BaseStage(lt.Thing):
_axis_names = ("x", "y", "z")
def __init__(self) -> None:
def __init__(self, thing_server_interface: lt.ThingServerInterface) -> None:
"""Initialise the stage.
:raises RedefinedBaseMovementError: if ``move_relative`` and/or
@ -54,6 +54,7 @@ class BaseStage(lt.Thing):
``_hardware_move_relative`` and/or ``_hardware_move_absolute`` instead so
that all code in the child class uses the hardware reference frame.
"""
super().__init__(thing_server_interface)
self._hardware_position = dict.fromkeys(self._axis_names, 0)
# This must be the last thing the function does in case it is caught in a try.
@ -78,7 +79,7 @@ class BaseStage(lt.Thing):
"""Current position of the stage."""
return self._apply_axis_direction(self._hardware_position)
moving: bool = lt.property(bool, default=False, readonly=True, observable=True)
moving: bool = lt.property(default=False, readonly=True)
"""Whether the stage is in motion."""
axis_inverted: Mapping[str, bool] = lt.setting(

View file

@ -19,7 +19,12 @@ class DummyStage(BaseStage):
hardware attached.
"""
def __init__(self, step_time: float = 0.001, **kwargs: Any) -> None:
def __init__(
self,
thing_server_interface: lt.ThingServerInterface,
step_time: float = 0.001,
**kwargs: Any,
) -> None:
"""Initialise the Dummy stage, setting the step_time to adjust the speed.
:param step_time: The time in seconds per "motor" step. The default of 0.001
@ -27,7 +32,7 @@ class DummyStage(BaseStage):
so the speed can be increased. Increasing it too far is problematic if
also doing computationally heavy tasks like simulated image blurring.
"""
super().__init__(**kwargs)
super().__init__(thing_server_interface, **kwargs)
self.step_time = step_time
self.instantaneous_position = self._hardware_position

View file

@ -33,7 +33,12 @@ class SangaboardThing(BaseStage):
functionality is accessed by directly querying the serial interface.
"""
def __init__(self, port: str = None, **kwargs: Any) -> None:
def __init__(
self,
thing_server_interface: lt.ThingServerInterface,
port: str = None,
**kwargs: Any,
) -> None:
"""Initialise SangaboardThing.
Initialise the "Thing", but do not initialise an underlying
@ -49,7 +54,7 @@ class SangaboardThing(BaseStage):
self.sangaboard_kwargs = copy(kwargs)
self.sangaboard_kwargs["port"] = port
self._sangaboard_lock = threading.RLock()
super().__init__(**kwargs)
super().__init__(thing_server_interface, **kwargs)
def __enter__(self) -> None:
"""Connect to the sangaboard when the Thing context manager is opened."""

View file

@ -138,9 +138,9 @@ class RangeofMotionThing(lt.Thing):
calibrated_range: int = lt.setting(default=None, readonly=True)
def __init__(self) -> None:
def __init__(self, thing_server_interface: lt.ThingServerInterface) -> None:
"""Initialise and create the lock."""
super().__init__()
super().__init__(thing_server_interface)
self._lock = Lock()
self._stream_resolution: Optional[tuple[int, int]] = None
self._rom_data = RomDataTracker()