Merge branch 'master' of https://gitlab.com/openflexure/openflexure-microscope-server
This commit is contained in:
commit
e1e553c1cd
20 changed files with 64 additions and 99 deletions
|
|
@ -14,6 +14,12 @@ This includes installing the server in a mode better suited for active developme
|
||||||
* `poetry install`
|
* `poetry install`
|
||||||
* `poetry run build_static`
|
* `poetry run build_static`
|
||||||
|
|
||||||
|
### Node installation
|
||||||
|
* Note, building the static interface will require a valid Node.js installation
|
||||||
|
* To build on a Raspberry Pi:
|
||||||
|
* `curl -sL https://deb.nodesource.com/setup_10.x | sudo bash -`
|
||||||
|
* `sudo apt install nodejs`
|
||||||
|
|
||||||
### Distributing
|
### Distributing
|
||||||
* `mkdir -p dist`
|
* `mkdir -p dist`
|
||||||
* `tar -c --exclude-vcs --exclude-from .tarignore -vzf dist/openflexure-microscope-server.tar.gz .`
|
* `tar -c --exclude-vcs --exclude-from .tarignore -vzf dist/openflexure-microscope-server.tar.gz .`
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,11 @@ Thing Actions "invoke a function of the Thing, which manipulates state (e.g., to
|
||||||
|
|
||||||
Actions should be *triggered* with POST requests *only*. Ideally, a view corresponding to an action should only support POST requests.
|
Actions should be *triggered* with POST requests *only*. Ideally, a view corresponding to an action should only support POST requests.
|
||||||
|
|
||||||
Like properties, we use a class decorator to identify a view as an action: ``@ThingAction``. For example, a view to perform a "quick-capture" action may look like:
|
Like properties, we use a special view class to identify a view as an action: ``ActionView``. For example, a view to perform a "quick-capture" action may look like:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ThingAction
|
class QuickCaptureAPI(ActionView):
|
||||||
class QuickCaptureAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Take an image capture and return it without saving
|
Take an image capture and return it without saving
|
||||||
"""
|
"""
|
||||||
|
|
@ -44,8 +43,6 @@ Like properties, we use a class decorator to identify a view as an action: ``@Th
|
||||||
|
|
||||||
In this example, we are also making use of the ``@doc_response`` decorator, to document that our successful response (HTTP code 200) will return data with a mimetype ``image/jpeg``, as well as ``@use_args`` to accept optional parameters with POST requests.
|
In this example, we are also making use of the ``@doc_response`` decorator, to document that our successful response (HTTP code 200) will return data with a mimetype ``image/jpeg``, as well as ``@use_args`` to accept optional parameters with POST requests.
|
||||||
|
|
||||||
Again like properties, the ``@ThingAction`` decorator serves only to add documentation.
|
|
||||||
|
|
||||||
Complete example
|
Complete example
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, PropertyView
|
||||||
|
|
||||||
from labthings.server.decorators import (
|
from labthings.server.decorators import (
|
||||||
use_args,
|
use_args,
|
||||||
|
|
@ -36,8 +36,7 @@ def rename(microscope, new_name):
|
||||||
## Extension views
|
## Extension views
|
||||||
|
|
||||||
# Since we only have a GET method here, it'll register as a read-only property
|
# Since we only have a GET method here, it'll register as a read-only property
|
||||||
@ThingProperty
|
class ExampleIdentifyView(PropertyView):
|
||||||
class ExampleIdentifyView(View):
|
|
||||||
# Format our returned object using MicroscopeIdentifySchema
|
# Format our returned object using MicroscopeIdentifySchema
|
||||||
@marshal_with(MicroscopeIdentifySchema())
|
@marshal_with(MicroscopeIdentifySchema())
|
||||||
def get(self):
|
def get(self):
|
||||||
|
|
@ -52,11 +51,10 @@ class ExampleIdentifyView(View):
|
||||||
return microscope
|
return microscope
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
|
||||||
# We can use a single schema for all methods if the input and output will be formatted identically
|
# We can use a single schema for all methods if the input and output will be formatted identically
|
||||||
# Eg. Here, we will always expect a "name" string argument, and always return a "name" string attribute
|
# Eg. Here, we will always expect a "name" string argument, and always return a "name" string attribute
|
||||||
@PropertySchema({"name": fields.String(required=True, example="My Example Microscope")})
|
@PropertySchema({"name": fields.String(required=True, example="My Example Microscope")})
|
||||||
class ExampleRenameView(View):
|
class ExampleRenameView(PropertyView):
|
||||||
def get(self):
|
def get(self):
|
||||||
"""
|
"""
|
||||||
Show the current microscope name
|
Show the current microscope name
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView, PropertyView
|
||||||
|
|
||||||
from labthings.server.decorators import (
|
from labthings.server.decorators import (
|
||||||
use_args,
|
use_args,
|
||||||
|
|
@ -41,8 +41,7 @@ def rename(microscope, new_name):
|
||||||
## Extension views
|
## Extension views
|
||||||
|
|
||||||
# Since we only have a GET method here, it'll register as a read-only property
|
# Since we only have a GET method here, it'll register as a read-only property
|
||||||
@ThingProperty
|
class ExampleIdentifyView(PropertyView):
|
||||||
class ExampleIdentifyView(View):
|
|
||||||
# Format our returned object using MicroscopeIdentifySchema
|
# Format our returned object using MicroscopeIdentifySchema
|
||||||
@marshal_with(MicroscopeIdentifySchema())
|
@marshal_with(MicroscopeIdentifySchema())
|
||||||
def get(self):
|
def get(self):
|
||||||
|
|
@ -57,11 +56,10 @@ class ExampleIdentifyView(View):
|
||||||
return microscope
|
return microscope
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
|
||||||
# We can use a single schema for all methods if the input and output will be formatted identically
|
# We can use a single schema for all methods if the input and output will be formatted identically
|
||||||
# Eg. Here, we will always expect a "name" string argument, and always return a "name" string attribute
|
# Eg. Here, we will always expect a "name" string argument, and always return a "name" string attribute
|
||||||
@PropertySchema({"name": fields.String(required=True, example="My Example Microscope")})
|
@PropertySchema({"name": fields.String(required=True, example="My Example Microscope")})
|
||||||
class ExampleRenameView(View):
|
class ExampleRenameView(PropertyView):
|
||||||
def get(self):
|
def get(self):
|
||||||
"""
|
"""
|
||||||
Show the current microscope name
|
Show the current microscope name
|
||||||
|
|
@ -89,8 +87,7 @@ class ExampleRenameView(View):
|
||||||
return microscope
|
return microscope
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class QuickCaptureAPI(ActionView):
|
||||||
class QuickCaptureAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Take an image capture and return it without saving
|
Take an image capture and return it without saving
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView
|
||||||
|
|
||||||
from labthings.server.decorators import (
|
from labthings.server.decorators import (
|
||||||
use_args,
|
use_args,
|
||||||
|
|
@ -66,8 +66,7 @@ def timelapse(microscope, n_images, t_between):
|
||||||
## Extension views
|
## Extension views
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class TimelapseAPI(ActionView):
|
||||||
class TimelapseAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Take a series of images in a timelapse
|
Take a series of images in a timelapse
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView
|
||||||
|
|
||||||
from labthings.server.decorators import (
|
from labthings.server.decorators import (
|
||||||
use_args,
|
use_args,
|
||||||
|
|
@ -68,8 +68,7 @@ def timelapse(microscope, n_images, t_between):
|
||||||
## Extension views
|
## Extension views
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class TimelapseAPI(ActionView):
|
||||||
class TimelapseAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Take a series of images in a timelapse, running as a background task
|
Take a series of images in a timelapse, running as a background task
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,12 @@ The property description for a view will be generated automatically from your av
|
||||||
Defining Thing Properties
|
Defining Thing Properties
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
In order to register a view as a Thing property, we use the ``@ThingProperty`` decorator, like so:
|
In order to register a view as a Thing property, we use the ``PropertyView`` class, like so:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# Since we only have a GET method here, it'll register as a read-only property
|
# Since we only have a GET method here, it'll register as a read-only property
|
||||||
@ThingProperty
|
class ExampleIdentifyView(PropertyView):
|
||||||
class ExampleIdentifyView(View):
|
|
||||||
# Format our returned object using MicroscopeIdentifySchema
|
# Format our returned object using MicroscopeIdentifySchema
|
||||||
@marshal_with(MicroscopeIdentifySchema())
|
@marshal_with(MicroscopeIdentifySchema())
|
||||||
def get(self):
|
def get(self):
|
||||||
|
|
@ -78,11 +77,10 @@ We will implement the ``@PropertySchema`` decorator in our ``ExampleRenameView``
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ThingProperty
|
|
||||||
# We can use a single schema for all methods if the input and output will be formatted identically
|
# We can use a single schema for all methods if the input and output will be formatted identically
|
||||||
# Eg. Here, we will always expect a "name" string argument, and always return a "name" string attribute
|
# Eg. Here, we will always expect a "name" string argument, and always return a "name" string attribute
|
||||||
@PropertySchema({"name": fields.String(required=True, example="My Example Microscope")})
|
@PropertySchema({"name": fields.String(required=True, example="My Example Microscope")})
|
||||||
class ExampleRenameView(View):
|
class ExampleRenameView(PropertyView):
|
||||||
def get(self):
|
def get(self):
|
||||||
"""
|
"""
|
||||||
Show the current microscope name
|
Show the current microscope name
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ We get around these issues by making use of background tasks, and component lock
|
||||||
Background tasks
|
Background tasks
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Tasks are introduced to manage long-running functions in a way that does not block HTTP requests. Any API Action will automatically run as a background task (that is, any View that subclasses `ActionView`, or uses the `@ThingAction` decorator).
|
Tasks are introduced to manage long-running functions in a way that does not block HTTP requests. Any API Action will automatically run as a background task (that is, any View that subclasses `ActionView`).
|
||||||
|
|
||||||
Internally, the ``tasks`` submodule stores a list of all requested tasks, and their states. This state stores the running status of the task (if itis idle, running, error, or success), information about the start and end times, a unique task ID, and, upon completion, the return value of the long-running function.
|
Internally, the ``tasks`` submodule stores a list of all requested tasks, and their states. This state stores the running status of the task (if itis idle, running, error, or success), information about the start and end times, a unique task ID, and, upon completion, the return value of the long-running function.
|
||||||
|
|
||||||
|
|
@ -30,11 +30,9 @@ An example of a long running task may look like:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
...
|
...
|
||||||
from labthings.tasks import taskify
|
from labthings.server.view import ActionView
|
||||||
from labthings.server.decorators import ThingAction
|
|
||||||
|
|
||||||
@ThingAction
|
class SlowAPI(ActionView):
|
||||||
class SlowAPI(View):
|
|
||||||
def post(self):
|
def post(self):
|
||||||
# Return the task object.
|
# Return the task object.
|
||||||
return long_running_function(function_argument_1, function_argument_2)
|
return long_running_function(function_argument_1, function_argument_2)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView, PropertyView
|
||||||
from labthings.server.decorators import ThingAction, ThingProperty
|
from labthings.server.decorators import ThingAction, ThingProperty
|
||||||
|
|
||||||
from openflexure_microscope.devel import JsonResponse, request, abort
|
from openflexure_microscope.devel import JsonResponse, request, abort
|
||||||
|
|
@ -332,8 +332,7 @@ class MeasureSharpnessAPI(View):
|
||||||
return {"sharpness": measure_sharpness(microscope)}
|
return {"sharpness": measure_sharpness(microscope)}
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class AutofocusAPI(ActionView):
|
||||||
class AutofocusAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Run a standard autofocus
|
Run a standard autofocus
|
||||||
"""
|
"""
|
||||||
|
|
@ -357,8 +356,7 @@ class AutofocusAPI(View):
|
||||||
abort(503, "No stage connected. Unable to autofocus.")
|
abort(503, "No stage connected. Unable to autofocus.")
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class FastAutofocusAPI(ActionView):
|
||||||
class FastAutofocusAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Run a fast autofocus
|
Run a fast autofocus
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, PropertyView
|
||||||
from labthings.server.decorators import ThingProperty, PropertySchema, use_args
|
from labthings.server.decorators import ThingProperty, PropertySchema, use_args
|
||||||
from labthings.server import fields
|
from labthings.server import fields
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
|
|
@ -190,8 +190,7 @@ class AutostorageExtension(BaseExtension):
|
||||||
autostorage_extension_v2 = AutostorageExtension()
|
autostorage_extension_v2 = AutostorageExtension()
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
class GetLocationsView(PropertyView):
|
||||||
class GetLocationsView(View):
|
|
||||||
def get(self):
|
def get(self):
|
||||||
global autostorage_extension_v2
|
global autostorage_extension_v2
|
||||||
|
|
||||||
|
|
@ -199,9 +198,8 @@ class GetLocationsView(View):
|
||||||
return autostorage_extension_v2.get_locations()
|
return autostorage_extension_v2.get_locations()
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
|
||||||
@PropertySchema(fields.String(required=True, example="Default"))
|
@PropertySchema(fields.String(required=True, example="Default"))
|
||||||
class PreferredLocationView(View):
|
class PreferredLocationView(PropertyView):
|
||||||
def get(self):
|
def get(self):
|
||||||
global autostorage_extension_v2
|
global autostorage_extension_v2
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ API extension for stage calibration
|
||||||
|
|
||||||
This file contains the HTTP API for camera/stage calibration.
|
This file contains the HTTP API for camera/stage calibration.
|
||||||
"""
|
"""
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView, PropertyView
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
from labthings.server.decorators import (
|
from labthings.server.decorators import (
|
||||||
|
|
@ -139,8 +139,7 @@ class CSMExtension(BaseExtension):
|
||||||
csm_extension = CSMExtension()
|
csm_extension = CSMExtension()
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class Calibrate1DView(ActionView):
|
||||||
class Calibrate1DView(View):
|
|
||||||
@use_args(
|
@use_args(
|
||||||
{"direction": fields.List(fields.Float(), required=True, example=[1, 0, 0])}
|
{"direction": fields.List(fields.Float(), required=True, example=[1, 0, 0])}
|
||||||
)
|
)
|
||||||
|
|
@ -155,8 +154,7 @@ class Calibrate1DView(View):
|
||||||
csm_extension.add_view(Calibrate1DView, "/calibrate_1d", endpoint="calibrate_1d")
|
csm_extension.add_view(Calibrate1DView, "/calibrate_1d", endpoint="calibrate_1d")
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class CalibrateXYView(ActionView):
|
||||||
class CalibrateXYView(View):
|
|
||||||
def post(self):
|
def post(self):
|
||||||
"""Calibrate both axes of the microscope stage against the camera."""
|
"""Calibrate both axes of the microscope stage against the camera."""
|
||||||
return csm_extension.calibrate_xy()
|
return csm_extension.calibrate_xy()
|
||||||
|
|
@ -165,8 +163,7 @@ class CalibrateXYView(View):
|
||||||
csm_extension.add_view(CalibrateXYView, "/calibrate_xy", endpoint="calibrate_xy")
|
csm_extension.add_view(CalibrateXYView, "/calibrate_xy", endpoint="calibrate_xy")
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class MoveInImageCoordinatesView(ActionView):
|
||||||
class MoveInImageCoordinatesView(View):
|
|
||||||
@use_args(
|
@use_args(
|
||||||
{
|
{
|
||||||
"x": fields.Float(
|
"x": fields.Float(
|
||||||
|
|
@ -194,8 +191,7 @@ class MoveInImageCoordinatesView(View):
|
||||||
csm_extension.add_view(MoveInImageCoordinatesView, "/move_in_image_coordinates", endpoint="move_in_image_coordinates")
|
csm_extension.add_view(MoveInImageCoordinatesView, "/move_in_image_coordinates", endpoint="move_in_image_coordinates")
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
class GetCalibrationFile(PropertyView):
|
||||||
class GetCalibrationFile(View):
|
|
||||||
def get(self):
|
def get(self):
|
||||||
"""Get the calibration data in JSON format."""
|
"""Get the calibration data in JSON format."""
|
||||||
datafile_name = CSM_DATAFILE_NAME
|
datafile_name = CSM_DATAFILE_NAME
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
from labthings.server.decorators import ThingAction
|
from labthings.server.decorators import ThingAction
|
||||||
|
|
@ -58,8 +58,7 @@ def recalibrate(microscope):
|
||||||
microscope.save_settings()
|
microscope.save_settings()
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class RecalibrateView(ActionView):
|
||||||
class RecalibrateView(View):
|
|
||||||
def post(self):
|
def post(self):
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
|
|
||||||
|
|
@ -71,8 +70,7 @@ class RecalibrateView(View):
|
||||||
return recalibrate(microscope)
|
return recalibrate(microscope)
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class FlattenLSTView(ActionView):
|
||||||
class FlattenLSTView(View):
|
|
||||||
def post(self):
|
def post(self):
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
|
|
||||||
|
|
@ -95,8 +93,7 @@ class FlattenLSTView(View):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class DeleteLSTView(ActionView):
|
||||||
class DeleteLSTView(View):
|
|
||||||
def post(self):
|
def post(self):
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import tempfile
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView, PropertyView
|
||||||
from labthings.server.schema import Schema
|
from labthings.server.schema import Schema
|
||||||
from labthings.server import fields
|
from labthings.server import fields
|
||||||
from labthings.server.extensions import BaseExtension
|
from labthings.server.extensions import BaseExtension
|
||||||
|
|
@ -138,8 +138,7 @@ class ZipManager:
|
||||||
default_zip_manager = ZipManager()
|
default_zip_manager = ZipManager()
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class ZipBuilderAPIView(ActionView):
|
||||||
class ZipBuilderAPIView(View):
|
|
||||||
def post(self):
|
def post(self):
|
||||||
|
|
||||||
ids = list(JsonResponse(request).json)
|
ids = list(JsonResponse(request).json)
|
||||||
|
|
@ -151,8 +150,7 @@ class ZipBuilderAPIView(View):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
class ZipListAPIView(PropertyView):
|
||||||
class ZipListAPIView(View):
|
|
||||||
@marshal_with(ZipObjectSchema(many=True))
|
@marshal_with(ZipObjectSchema(many=True))
|
||||||
def get(self):
|
def get(self):
|
||||||
return default_zip_manager.session_zips.values()
|
return default_zip_manager.session_zips.values()
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4a482f3e0f1f1e1774ec559a28a8c6a85c5a4977
|
Subproject commit c32bca436c2b17837e73097e9977d077a14305ab
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from openflexure_microscope.api.utilities import get_bool, JsonResponse
|
from openflexure_microscope.api.utilities import get_bool, JsonResponse
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.decorators import (
|
from labthings.server.decorators import (
|
||||||
use_args,
|
use_args,
|
||||||
|
|
@ -20,8 +20,7 @@ import io
|
||||||
from flask import request, abort, url_for, redirect, send_file
|
from flask import request, abort, url_for, redirect, send_file
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class CaptureAPI(ActionView):
|
||||||
class CaptureAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Create a new image capture.
|
Create a new image capture.
|
||||||
"""
|
"""
|
||||||
|
|
@ -75,8 +74,7 @@ class CaptureAPI(View):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class RAMCaptureAPI(ActionView):
|
||||||
class RAMCaptureAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Take a non-persistant image capture.
|
Take a non-persistant image capture.
|
||||||
"""
|
"""
|
||||||
|
|
@ -124,8 +122,7 @@ class RAMCaptureAPI(View):
|
||||||
return send_file(io.BytesIO(stream.getbuffer()), mimetype="image/jpeg")
|
return send_file(io.BytesIO(stream.getbuffer()), mimetype="image/jpeg")
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class GPUPreviewStartAPI(ActionView):
|
||||||
class GPUPreviewStartAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Start the onboard GPU preview.
|
Start the onboard GPU preview.
|
||||||
Optional "window" parameter can be passed to control the position and size of the preview window,
|
Optional "window" parameter can be passed to control the position and size of the preview window,
|
||||||
|
|
@ -157,8 +154,7 @@ class GPUPreviewStartAPI(View):
|
||||||
return microscope.state
|
return microscope.state
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class GPUPreviewStopAPI(ActionView):
|
||||||
class GPUPreviewStopAPI(View):
|
|
||||||
def post(self):
|
def post(self):
|
||||||
"""
|
"""
|
||||||
Stop the onboard GPU preview.
|
Stop the onboard GPU preview.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from openflexure_microscope.api.utilities import JsonResponse
|
from openflexure_microscope.api.utilities import JsonResponse
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.decorators import use_args, marshal_with, doc, ThingAction
|
from labthings.server.decorators import use_args, marshal_with, doc, ThingAction
|
||||||
from labthings.server import fields
|
from labthings.server import fields
|
||||||
|
|
@ -11,8 +11,7 @@ from flask import Blueprint, request
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class MoveStageAPI(ActionView):
|
||||||
class MoveStageAPI(View):
|
|
||||||
@use_args(
|
@use_args(
|
||||||
{
|
{
|
||||||
"absolute": fields.Boolean(
|
"absolute": fields.Boolean(
|
||||||
|
|
@ -56,8 +55,7 @@ class MoveStageAPI(View):
|
||||||
return microscope.state["stage"]["position"]
|
return microscope.state["stage"]["position"]
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class ZeroStageAPI(ActionView):
|
||||||
class ZeroStageAPI(View):
|
|
||||||
def post(self):
|
def post(self):
|
||||||
"""
|
"""
|
||||||
Zero the stage coordinates.
|
Zero the stage coordinates.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, ActionView
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
from sys import platform
|
from sys import platform
|
||||||
|
|
@ -14,8 +14,7 @@ def is_raspberrypi(raise_on_errors=False):
|
||||||
return os.path.exists("/usr/bin/raspi-config")
|
return os.path.exists("/usr/bin/raspi-config")
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class ShutdownAPI(ActionView):
|
||||||
class ShutdownAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Attempt to shutdown the device
|
Attempt to shutdown the device
|
||||||
"""
|
"""
|
||||||
|
|
@ -35,8 +34,7 @@ class ShutdownAPI(View):
|
||||||
return {"out": out, "err": err}, 201
|
return {"out": out, "err": err}, 201
|
||||||
|
|
||||||
|
|
||||||
@ThingAction
|
class RebootAPI(ActionView):
|
||||||
class RebootAPI(View):
|
|
||||||
"""
|
"""
|
||||||
Attempt to reboot the device
|
Attempt to reboot the device
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from openflexure_microscope.api.utilities import get_bool, JsonResponse
|
||||||
|
|
||||||
from labthings.server.schema import Schema
|
from labthings.server.schema import Schema
|
||||||
from labthings.server import fields
|
from labthings.server import fields
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, PropertyView
|
||||||
from labthings.server.utilities import description_from_view
|
from labthings.server.utilities import description_from_view
|
||||||
from labthings.server.decorators import marshal_with, doc_response, Tag, ThingProperty
|
from labthings.server.decorators import marshal_with, doc_response, Tag, ThingProperty
|
||||||
|
|
||||||
|
|
@ -91,9 +91,8 @@ capture_list_schema = CaptureSchema(many=True)
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
|
||||||
@Tag("captures")
|
@Tag("captures")
|
||||||
class CaptureList(View):
|
class CaptureList(PropertyView):
|
||||||
@marshal_with(CaptureSchema(many=True))
|
@marshal_with(CaptureSchema(many=True))
|
||||||
def get(self):
|
def get(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from openflexure_microscope.api.utilities import JsonResponse
|
||||||
from labthings.core.utilities import get_by_path, set_by_path, create_from_path
|
from labthings.core.utilities import get_by_path, set_by_path, create_from_path
|
||||||
|
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, PropertyView
|
||||||
|
|
||||||
from labthings.server.decorators import ThingProperty, Tag, doc_response
|
from labthings.server.decorators import ThingProperty, Tag, doc_response
|
||||||
|
|
||||||
|
|
@ -11,8 +11,7 @@ from flask import request, abort
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
class SettingsProperty(PropertyView):
|
||||||
class SettingsProperty(View):
|
|
||||||
def get(self):
|
def get(self):
|
||||||
"""
|
"""
|
||||||
Current microscope settings, including camera and stage
|
Current microscope settings, including camera and stage
|
||||||
|
|
@ -71,8 +70,7 @@ class NestedSettingsProperty(View):
|
||||||
return self.get(route)
|
return self.get(route)
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
class StateProperty(PropertyView):
|
||||||
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
|
||||||
|
|
@ -99,8 +97,7 @@ class NestedStateProperty(View):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
class ConfigurationProperty(PropertyView):
|
||||||
class ConfigurationProperty(View):
|
|
||||||
def get(self):
|
def get(self):
|
||||||
"""
|
"""
|
||||||
Show current read-only state of the microscope
|
Show current read-only state of the microscope
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,13 @@ from openflexure_microscope.api.utilities import gen, JsonResponse
|
||||||
from labthings.core.utilities import get_by_path, set_by_path, create_from_path
|
from labthings.core.utilities import get_by_path, set_by_path, create_from_path
|
||||||
|
|
||||||
from labthings.server.find import find_component
|
from labthings.server.find import find_component
|
||||||
from labthings.server.view import View
|
from labthings.server.view import View, PropertyView
|
||||||
from labthings.server.decorators import doc_response, ThingProperty
|
from labthings.server.decorators import doc_response, ThingProperty
|
||||||
|
|
||||||
from flask import Response
|
from flask import Response
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
class MjpegStream(PropertyView):
|
||||||
class MjpegStream(View):
|
|
||||||
"""
|
"""
|
||||||
Real-time MJPEG stream from the microscope camera
|
Real-time MJPEG stream from the microscope camera
|
||||||
"""
|
"""
|
||||||
|
|
@ -38,8 +37,7 @@ class MjpegStream(View):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ThingProperty
|
class SnapshotStream(PropertyView):
|
||||||
class SnapshotStream(View):
|
|
||||||
"""
|
"""
|
||||||
Single JPEG snapshot from the camera stream
|
Single JPEG snapshot from the camera stream
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue