Moved status routes to instrument/state

This commit is contained in:
Joel Collins 2020-01-29 17:43:52 +00:00
parent e9e2419fe4
commit 9b4bf4c8fc
16 changed files with 52 additions and 64 deletions

View file

@ -14,7 +14,7 @@ from labthings.server import fields
class MicroscopeIdentifySchema(Schema): class MicroscopeIdentifySchema(Schema):
name = fields.String() # Microscopes name name = fields.String() # Microscopes name
id = fields.UUID() # Microscopes unique ID id = fields.UUID() # Microscopes unique ID
status = fields.Dict() # Status dictionary state = fields.Dict() # Status dictionary
camera = fields.String() # Camera object (represented as a string) camera = fields.String() # Camera object (represented as a string)
stage = fields.String() # Stage object (represented as a string) stage = fields.String() # Stage object (represented as a string)

View file

@ -19,7 +19,7 @@ from labthings.server import fields
class MicroscopeIdentifySchema(Schema): class MicroscopeIdentifySchema(Schema):
name = fields.String() # Microscopes name name = fields.String() # Microscopes name
id = fields.UUID() # Microscopes unique ID id = fields.UUID() # Microscopes unique ID
status = fields.Dict() # Status dictionary state = fields.Dict() # Status dictionary
camera = fields.String() # Camera object (represented as a string) camera = fields.String() # Camera object (represented as a string)
stage = fields.String() # Stage object (represented as a string) stage = fields.String() # Stage object (represented as a string)

View file

@ -24,7 +24,7 @@ import io # Used in our capture action
class MicroscopeIdentifySchema(Schema): class MicroscopeIdentifySchema(Schema):
name = fields.String() # Microscopes name name = fields.String() # Microscopes name
id = fields.UUID() # Microscopes unique ID id = fields.UUID() # Microscopes unique ID
status = fields.Dict() # Status dictionary state = fields.Dict() # Status dictionary
camera = fields.String() # Camera object (represented as a string) camera = fields.String() # Camera object (represented as a string)
stage = fields.String() # Stage object (represented as a string) stage = fields.String() # Stage object (represented as a string)

View file

@ -107,7 +107,7 @@ We start by creating a schema to describe how to serialise a :py:class:`openflex
class MicroscopeIdentifySchema(Schema): class MicroscopeIdentifySchema(Schema):
name = fields.String() # Microscopes name name = fields.String() # Microscopes name
id = fields.UUID() # Microscopes unique ID id = fields.UUID() # Microscopes unique ID
status = fields.Dict() # Status dictionary state = fields.Dict() # Status dictionary
camera = fields.String() # Camera object (represented as a string) camera = fields.String() # Camera object (represented as a string)
stage = fields.String() # Stage object (represented as a string) stage = fields.String() # Stage object (represented as a string)

View file

@ -94,16 +94,18 @@ labthing.add_view(views.CaptureDownload, f"/captures/<id>/download/<filename>")
labthing.add_view(views.CaptureTags, f"/captures/<id>/tags") labthing.add_view(views.CaptureTags, f"/captures/<id>/tags")
labthing.add_view(views.CaptureAnnotations, f"/captures/<id>/annotations") labthing.add_view(views.CaptureAnnotations, f"/captures/<id>/annotations")
# Attach settings and status resources # Attach settings and state resources
labthing.add_view(views.SettingsProperty, f"/settings") labthing.add_view(views.SettingsProperty, f"/instrument/settings")
labthing.add_root_link(views.SettingsProperty, "settings") labthing.add_root_link(views.SettingsProperty, "instrumentSettings")
labthing.add_view(views.NestedSettingsProperty, "/settings/<path:route>") labthing.add_view(views.NestedSettingsProperty, "/instrument/settings/<path:route>")
labthing.add_view(views.StatusProperty, "/status") labthing.add_view(views.StateProperty, "/instrument/state")
labthing.add_view(views.NestedStatusProperty, "/status/<path:route>") labthing.add_view(views.NestedStateProperty, "/instrument/state/<path:route>")
labthing.add_root_link(views.StatusProperty, "status") labthing.add_root_link(views.StateProperty, "instrumentState")
labthing.add_view(views.ConfigurationProperty, "/configuration") labthing.add_view(views.ConfigurationProperty, "/instrument/configuration")
labthing.add_view(views.NestedConfigurationProperty, "/configuration/<path:route>") labthing.add_view(
labthing.add_root_link(views.ConfigurationProperty, "configuration") views.NestedConfigurationProperty, "/instrument/configuration/<path:route>"
)
labthing.add_root_link(views.ConfigurationProperty, "instrumentConfiguration")
# Attach streams resources # Attach streams resources

View file

@ -73,17 +73,15 @@ class ZipManager:
# Update task progress # Update task progress
update_task_progress(int((index / n_files) * 100)) update_task_progress(int((index / n_files) * 100))
session_id = uuid.uuid4() session_id = str(uuid.uuid4())
session_key = str(session_id) self.session_zips[session_id] = {
# self.session_zips[session_id] = fp
self.session_zips[session_key] = {
"id": session_id, "id": session_id,
"fp": fp, "fp": fp,
"data_size": data_size_megabytes, "data_size": data_size_megabytes,
"zip_size": os.path.getsize(fp.name) * 1e-6, "zip_size": os.path.getsize(fp.name) * 1e-6,
} }
return self.session_zips[session_key] return self.session_zips[session_id]
def zip_from_id(self, session_id): def zip_from_id(self, session_id):
return self.session_zips[session_id]["fp"] return self.session_zips[session_id]["fp"]
@ -103,13 +101,13 @@ class ZipBuilderAPIView(View):
task = taskify(default_zip_manager.build_zip_from_capture_ids)(microscope, ids) task = taskify(default_zip_manager.build_zip_from_capture_ids)(microscope, ids)
# Return a handle on the autofocus task # Return a handle on the autofocus task
return jsonify(task.state), 201 return task.state, 201
@ThingProperty @ThingProperty
class ZipListAPIView(View): class ZipListAPIView(View):
def get(self): def get(self):
return jsonify(default_zip_manager.session_zips) return default_zip_manager.session_zips
class ZipGetterAPIView(View): class ZipGetterAPIView(View):
@ -141,7 +139,7 @@ class ZipGetterAPIView(View):
del default_zip_manager.session_zips[session_id] del default_zip_manager.session_zips[session_id]
return jsonify({"return": session_id}) return {"return": session_id}
zip_extension_v2 = BaseExtension("org.openflexure.zipbuilder", version="2.0.0-beta.1") zip_extension_v2 = BaseExtension("org.openflexure.zipbuilder", version="2.0.0-beta.1")

View file

@ -1,4 +1,4 @@
from .actions import enabled_root_actions from .actions import enabled_root_actions
from .captures import * from .captures import *
from .state import * from .instrument import *
from .streams import * from .streams import *

View file

@ -163,8 +163,8 @@ class GPUPreviewStartAPI(View):
microscope.camera.start_preview(fullscreen=fullscreen, window=window) microscope.camera.start_preview(fullscreen=fullscreen, window=window)
# TODO: Make schema for microscope status # TODO: Make schema for microscope state
return jsonify(microscope.status) return jsonify(microscope.state)
@ThingAction @ThingAction
@ -175,5 +175,5 @@ class GPUPreviewStopAPI(View):
""" """
microscope = find_component("org.openflexure.microscope") microscope = find_component("org.openflexure.microscope")
microscope.camera.stop_preview() microscope.camera.stop_preview()
# TODO: Make schema for microscope status # TODO: Make schema for microscope state
return jsonify(microscope.status) return jsonify(microscope.state)

View file

@ -52,7 +52,7 @@ class MoveStageAPI(View):
else: else:
logging.warning("Unable to move. No stage found.") logging.warning("Unable to move. No stage found.")
# TODO: Make schema for microscope status # TODO: Make schema for microscope state
return jsonify(microscope.state["stage"]["position"]) return jsonify(microscope.state["stage"]["position"])
@ -66,5 +66,5 @@ class ZeroStageAPI(View):
microscope = find_component("org.openflexure.microscope") microscope = find_component("org.openflexure.microscope")
microscope.stage.zero_position() microscope.stage.zero_position()
# TODO: Make schema for microscope status # TODO: Make schema for microscope state
return jsonify(microscope.status["stage"]) return jsonify(microscope.state["stage"])

View file

@ -72,7 +72,7 @@ class NestedSettingsProperty(View):
@ThingProperty @ThingProperty
class StatusProperty(View): class StateProperty(View):
def get(self): def get(self):
""" """
Show current read-only state of the microscope Show current read-only state of the microscope
@ -82,7 +82,7 @@ class StatusProperty(View):
@Tag("properties") @Tag("properties")
class NestedStatusProperty(View): class NestedStateProperty(View):
@doc_response(404, description="Status key cannot be found") @doc_response(404, description="Status key cannot be found")
def get(self, route): def get(self, route):
""" """

View file

@ -91,20 +91,6 @@ class CameraEvent(object):
class BaseCamera(metaclass=ABCMeta): class BaseCamera(metaclass=ABCMeta):
""" """
Base implementation of StreamingCamera. Base implementation of StreamingCamera.
Attributes:
thread: Background thread reading frames from camera
camera: Camera object
lock (:py:class:`labthings.lock.StrictLock`): Strict lock controlling thread
access to stage hardware
frame (bytes): Current frame is stored here by background thread
last_access (time): Time of last client access to the camera
stream_timeout (int): Number of inactive seconds before timing out the stream
stream_timeout_enabled (bool): Enable or disable timing out the stream
status (dict): Dictionary for capture state
paths (dict): Dictionary of capture paths
images (list): List of image capture objects
videos (list): List of video capture objects
""" """
def __init__(self): def __init__(self):

View file

@ -85,7 +85,7 @@ class PiCameraStreamer(BaseCamera):
picamera.PiCamera() picamera.PiCamera()
) #: :py:class:`picamera.PiCamera`: Picamera object ) #: :py:class:`picamera.PiCamera`: Picamera object
# Store status of PiCameraStreamer # Store state of PiCameraStreamer
self.preview_active = False self.preview_active = False
# Reset variable states # Reset variable states
@ -157,7 +157,7 @@ class PiCameraStreamer(BaseCamera):
"picamera_lst_path": self.picamera_lst_path "picamera_lst_path": self.picamera_lst_path
if os.path.isfile(self.picamera_lst_path) if os.path.isfile(self.picamera_lst_path)
else None, else None,
"picamera_settings": {}, "picamera": {},
} }
) )
@ -166,7 +166,7 @@ class PiCameraStreamer(BaseCamera):
try: try:
value = getattr(self.camera, key) value = getattr(self.camera, key)
logging.debug("Reading PiCamera().{}: {}".format(key, value)) logging.debug("Reading PiCamera().{}: {}".format(key, value))
conf_dict["picamera_settings"][key] = value conf_dict["picamera"][key] = value
except AttributeError: except AttributeError:
logging.debug("Unable to read PiCamera attribute {}".format(key)) logging.debug("Unable to read PiCamera attribute {}".format(key))
@ -204,14 +204,14 @@ class PiCameraStreamer(BaseCamera):
paused_stream = True # Remember to unpause stream when done paused_stream = True # Remember to unpause stream when done
# PiCamera parameters # PiCamera parameters
if "picamera_settings" in config: # If new settings are given if "picamera" in config: # If new settings are given
self.apply_picamera_settings( self.apply_picamera_settings(
config["picamera_settings"], pause_for_effect=True config["picamera"], pause_for_effect=True
) )
# PiCameraStreamer parameters # PiCameraStreamer parameters
for key, value in config.items(): # For each provided setting for key, value in config.items(): # For each provided setting
if (key != "picamera_settings") and hasattr(self, key): if (key != "picamera") and hasattr(self, key):
setattr(self, key, value) setattr(self, key, value)
# Handle lens shading if camera supports it # Handle lens shading if camera supports it
@ -412,7 +412,7 @@ class PiCameraStreamer(BaseCamera):
quality=quality, quality=quality,
) )
# Update status dictionary # Update state
self.record_active = True self.record_active = True
return output return output
@ -432,7 +432,7 @@ class PiCameraStreamer(BaseCamera):
self.camera.stop_recording(splitter_port=2) self.camera.stop_recording(splitter_port=2)
logging.info("Recording stopped") logging.info("Recording stopped")
# Update status dictionary # Update state
self.record_active = False self.record_active = False
def stop_stream_recording( def stop_stream_recording(
@ -681,7 +681,6 @@ class PiCameraStreamer(BaseCamera):
# Start stream recording (and set resolution) # Start stream recording (and set resolution)
self.start_stream_recording() self.start_stream_recording()
# Update status
logging.debug("STREAM ACTIVE") logging.debug("STREAM ACTIVE")
# While the iterator is not closed # While the iterator is not closed

View file

@ -94,11 +94,14 @@ class JSONEncoder(flask.json.JSONEncoder):
# Numpy arrays # Numpy arrays
elif isinstance(o, np.ndarray): elif isinstance(o, np.ndarray):
return o.tolist() return o.tolist()
# UUIDs
elif isinstance(o, UUID):
return str(o)
else: else:
# call base class implementation which takes care of # call base class implementation which takes care of
# raising exceptions for unsupported types # raising exceptions for unsupported types
try: try:
return json.JSONEncoder.default(self, o) return flask.json.JSONEncoder.default(self, o)
# if it's some mystery object, just return a string representation # if it's some mystery object, just return a string representation
except TypeError: except TypeError:
return str(o) return str(o)

View file

@ -120,13 +120,13 @@ class Microscope:
else: else:
return False return False
# Create unified status # Create unified state
@property @property
def state(self): def state(self):
"""Dictionary of the basic microscope status. """Dictionary of the basic microscope state.
Return: Return:
dict: Dictionary containing complete microscope status dict: Dictionary containing complete microscope state
""" """
state = {"camera": self.camera.state, "stage": self.stage.state} state = {"camera": self.camera.state, "stage": self.stage.state}
return state return state
@ -216,7 +216,7 @@ class Microscope:
initial_configuration = self.configuration_file.load() initial_configuration = self.configuration_file.load()
current_configuration = { current_configuration = {
"@application": { "application": {
"name": "openflexure_microscope", "name": "openflexure_microscope",
"version": pkg_resources.get_distribution( "version": pkg_resources.get_distribution(
"openflexure_microscope" "openflexure_microscope"

View file

@ -18,9 +18,9 @@ class MissingStage(BaseStage):
@property @property
def state(self): def state(self):
"""The general status dictionary of the board.""" """The general state dictionary of the board."""
status = {"position": self.position_map} state = {"position": self.position_map}
return status return state
@property @property
def configuration(self): def configuration(self):

View file

@ -33,7 +33,7 @@ class SangaStage(BaseStage):
@property @property
def state(self): def state(self):
"""The general status dictionary of the board.""" """The general state dictionary of the board."""
return {"position": self.position_map} return {"position": self.position_map}
@property @property