Moved status routes to instrument/state
This commit is contained in:
parent
e9e2419fe4
commit
9b4bf4c8fc
16 changed files with 52 additions and 64 deletions
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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 *
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"])
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue