Commit f2af359b authored by Joel Collins's avatar Joel Collins
Browse files

Added basic thing description to root

parent d5245384
Loading
Loading
Loading
Loading
+31 −29
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ import logging
import sys
import os

from flask import Flask, jsonify, send_file
from flask import Flask, jsonify, send_file, url_for

from serial import SerialException
from datetime import datetime
@@ -79,7 +79,7 @@ CORS(app, resources=r"*")
handler = JSONExceptionHandler(app)

# Attach lab devices
labthing = LabThing(app, prefix="/api/v2b")
labthing = LabThing(app, prefix="/api/v2")
labthing.description = "Test LabThing-based API for OpenFlexure Microscope"

labthing.register_device(api_microscope, "openflexure_microscope")
@@ -88,41 +88,23 @@ for _plugin in find_plugins(USER_PLUGINS_PATH):
    labthing.register_plugin(_plugin)

from openflexure_microscope.api.v2.views.captures import add_captures_to_labthing
add_captures_to_labthing(labthing, prefix="")

# WEBAPP ROUTES

### V2
# Root routes
v2_root_blueprint = v2.blueprints.root.construct_blueprint(api_microscope)
app.register_blueprint(v2_root_blueprint, url_prefix=uri("/", "v2"))
add_captures_to_labthing(labthing, prefix="")
from openflexure_microscope.api.v2.views.state import add_states_to_labthing

v2_streams_blueprint = v2.blueprints.streams.construct_blueprint(api_microscope)
app.register_blueprint(v2_streams_blueprint, url_prefix=uri("/streams", "v2"))
add_states_to_labthing(labthing, prefix="")

# Captures routes
v2_captures_blueprint = v2.blueprints.captures.construct_blueprint(api_microscope)
app.register_blueprint(v2_captures_blueprint, url_prefix=uri("/captures", "v2"))
from openflexure_microscope.api.v2.views.tasks import add_tasks_to_labthing

# Settings routes
v2_settings_blueprint = v2.blueprints.settings.construct_blueprint(api_microscope)
app.register_blueprint(v2_settings_blueprint, url_prefix=uri("/settings", "v2"))
add_tasks_to_labthing(labthing, prefix="")

# Status routes
v2_status_blueprint = v2.blueprints.status.construct_blueprint(api_microscope)
app.register_blueprint(v2_status_blueprint, url_prefix=uri("/status", "v2"))
from openflexure_microscope.api.v2.views.streams import add_streams_to_labthing

# Plugins routes
# v2_plugin_blueprint = v2.blueprints.plugins.construct_blueprint(api_microscope)
# app.register_blueprint(v2_plugin_blueprint, url_prefix=uri("/plugins", "v2"))
add_streams_to_labthing(labthing, prefix="")

# Tasks routes
v2_tasks_blueprint = v2.blueprints.tasks.construct_blueprint(api_microscope)
app.register_blueprint(v2_tasks_blueprint, url_prefix=uri("/tasks", "v2"))
from openflexure_microscope.api.v2.views.actions import add_actions_to_labthing

# Actions routes
v2_actions_blueprint = v2.blueprints.actions.construct_blueprint(api_microscope)
app.register_blueprint(v2_actions_blueprint, url_prefix=uri("/actions", "v2"))
add_actions_to_labthing(labthing)


@app.route("/routes")
@@ -139,6 +121,26 @@ def routes():
    return jsonify(list_routes(app))


@app.route("/props")
def props():
    p = {}
    for key, prop in labthing.properties.items():
        p[key] = {}
        p[key]["view"] = prop
        p[key]["url"] = labthing.url_for(prop, _external=True)
    return jsonify(p)


@app.route("/ac")
def actions():
    p = {}
    for key, prop in labthing.actions.items():
        p[key] = {}
        p[key]["view"] = prop
        p[key]["url"] = labthing.url_for(prop, _external=True)
    return jsonify(p)


@app.route("/log")
def err_log():
    """
+1 −1
Original line number Diff line number Diff line
from . import root, captures, settings, status, tasks, streams, plugins, actions
from . import root, captures, settings, status, tasks, streams, actions
+0 −114
Original line number Diff line number Diff line
"""
Top-level representation of attached and enabled plugins
"""

from openflexure_microscope.api.views import MicroscopeViewPlugin
from openflexure_microscope.utilities import get_docstring, description_from_view
from openflexure_microscope.api.utilities import blueprint_for_module

from openflexure_microscope.common.labthings.plugins import find_plugins
from openflexure_microscope.config import USER_PLUGINS_PATH

from flask import Blueprint, jsonify, url_for
from openflexure_microscope.api.views import MicroscopeView

import copy
import logging
import warnings

_plugins = find_plugins(USER_PLUGINS_PATH)
print(_plugins)


def plugins_representation(plugin_list):
    """
    Generate a dictionary representation of all plugins, including Flask route URLs

    Args:
        plugin_loader_object (:py:class:`openflexure_microscope.plugins.PluginLoader`): Microscope plugin loader

    Returns:
        dict: Dictionary representation of all plugins
    """
    plugins = {}

    for plugin in plugin_list:
        logging.debug(f"Representing plugin {plugin._name}")
        d = {
            "python_name": plugin._name_python_safe,
            "plugin": str(plugin),
            "views": {},
            "gui": plugin.gui,
            "description": get_docstring(plugin),
        }

        for view_id, view_data in plugin.views.items():
            logging.debug(f"Representing view {view_id}")
            uri = url_for(f"v2_plugins_blueprint.plugins") + view_data["rule"][1:]
            # uri = view_data["rule"]
            # Make links dictionary if it doesn't yet exist
            view_d = {"links": {"self": uri}}

            view_d.update(description_from_view(view_data["view"]))

            d["views"][view_id] = view_d

        plugins[plugin._name] = d

    return plugins


class PluginFormAPI(MicroscopeView):
    def get(self):
        """
        Return the current plugin forms

        .. :quickref: Plugin; Get forms

        Returns an array of present plugin forms (describing plugin user interfaces.)
        Please note, this is *not* a list of all enabled plugins, only those with associated
        user interface forms.

        A complete list of enabled plugins can be found in the microscope state.

        """
        global _plugins
        return jsonify(plugins_representation(_plugins))


def construct_blueprint(microscope_obj):

    blueprint = blueprint_for_module(__name__)

    for plugin_obj in _plugins:
        for plugin_view_id, plugin_view in plugin_obj.views.items():
            # Add route to the plugins blueprint
            blueprint.add_url_rule(
                plugin_view["rule"],
                view_func=plugin_view["view"].as_view(
                    f"{plugin_obj._name_python_safe}_{plugin_view_id}"
                ),
                **plugin_view["kwargs"],
            )

    # Create a base route to return plugin API forms, if any exist
    blueprint.add_url_rule(
        "/", view_func=PluginFormAPI.as_view("plugins", microscope=microscope_obj)
    )

    # For each plugin attached to the microscope object
    for plugin in microscope_obj.plugins.active:

        for plugin_view_id, plugin_view in plugin.views.items():
            # Add route to the plugins blueprint
            blueprint.add_url_rule(
                plugin_view["rule"],
                view_func=plugin_view["view"].as_view(
                    f"{plugin._name_python_safe}_{plugin_view_id}",
                    microscope=microscope_obj,
                    plugin=plugin,
                ),
                **plugin_view["kwargs"],
            )

    return blueprint
+0 −1
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@ from openflexure_microscope.api.utilities import blueprint_name_for_module
from openflexure_microscope.api.v2.blueprints import (
    settings,
    status,
    plugins,
    captures,
    actions,
    streams,
+65 −0
Original line number Diff line number Diff line
"""
Top-level representation of enabled actions
"""

from flask import Blueprint, url_for, jsonify

from openflexure_microscope.api.utilities import blueprint_for_module
from openflexure_microscope.utilities import get_docstring, description_from_view
from openflexure_microscope.api.views import MicroscopeView

from . import camera, stage, system

_actions = {
    "capture": {
        "rule": "/camera/capture/",
        "view_class": camera.CaptureAPI,
        "conditions": True,
    },
    "previewStart": {
        "rule": "/camera/preview/start",
        "view_class": camera.GPUPreviewStartAPI,
        "conditions": True,
    },
    "previewStop": {
        "rule": "/camera/preview/stop",
        "view_class": camera.GPUPreviewStopAPI,
        "conditions": True,
    },
    "move": {
        "rule": "/stage/move/",
        "view_class": stage.MoveStageAPI,
        "conditions": True,
    },
    "zeroStage": {
        "rule": "/stage/zero/",
        "view_class": stage.ZeroStageAPI,
        "conditions": True,
    },
    "shutdown": {
        "rule": "/system/shutdown/",
        "view_class": system.ShutdownAPI,
        "conditions": system.is_raspberrypi(),
    },
    "reboot": {
        "rule": "/system/reboot/",
        "view_class": system.RebootAPI,
        "conditions": system.is_raspberrypi(),
    },
}


def enabled_actions():
    global _actions
    return {k: v for k, v in _actions.items() if v["conditions"]}


def add_actions_to_labthing(labthing, prefix=""):
    """
    Add all capture resources to a labthing
    """
    for name, action in enabled_actions().items():
        view_class = action["view_class"]
        rule = action["rule"]
        labthing.add_resource(view_class, f"{prefix}/actions{rule}")
        labthing.register_action(view_class)
Loading