Commit 3b28f8c4 authored by Joel Collins's avatar Joel Collins
Browse files

Microscope now only attaches to hardware once an API request is made.

parent ad5ec793
Loading
Loading
Loading
Loading
+24 −8
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ import numpy as np
from importlib import import_module
import time
import datetime
import os

from flask import (
    Flask, render_template, Response,
@@ -29,11 +30,6 @@ import logging, sys

logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)

# Create the microscope object globally (common to all spawned server threads)
api_microscope = Microscope(
    StreamingCamera(), 
    OpenFlexureStage("/dev/ttyUSB0")
)

# Create flask app
app = Flask(__name__)
@@ -45,9 +41,29 @@ def not_found(error):

# Some useful functions
# TODO: Maybe auto-generate API URI base from module name
def uri(suffix, base='/api/v1'):
    return base + suffix

def uri(suffix, base=None):
    if not base:
        api_ver = os.path.splitext(os.path.basename(__file__))[0]
        base = "/api/{}".format(api_ver)
    uri = base + suffix
    logging.debug("Created app route: {}".format(uri))
    return uri

# Create a dummy microscope object, with no hardware attachments
api_microscope = Microscope(None, None)
logging.debug("Created an empty microscope in global.")

# After app starts, but before first request, attach hardware to global microscope
@app.before_first_request
def attach_microscope():
    # Create the microscope object globally (common to all spawned server threads)
    global api_microscope
    logging.debug("First request made. Populating microscope with hardware...")
    api_microscope.attach(
        StreamingCamera(),
        OpenFlexureStage("/dev/ttyUSB0")
    )
    logging.debug("Microscope successfully attached!")

##### WEBAPP ROUTES ######

+23 −6
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
"""
Defines a microscope object, binding a camera and stage with basic functionality.
"""

import logging
import numpy as np

from openflexure_stage import OpenFlexureStage
@@ -20,11 +20,7 @@ class Microscope(object):
        microscope (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object
    """
    def __init__(self, camera: StreamingCamera, stage: OpenFlexureStage):
        print("Assigning camera")
        self.camera = camera  #: :py:class:`openflexure_microscope.camera.pi.StreamingCamera`: Picamera object
        print("Assigning stage")
        self.stage = stage  #: :py:class:`openflexure_stage.stage.OpenFlexureStage`: OpenFlexure stage object
        self.stage.backlash = np.zeros(3, dtype=np.int)
        self.attach(camera, stage)

    def __enter__(self):
        """Create microscope on context enter."""
@@ -39,6 +35,27 @@ class Microscope(object):
        self.camera.close()
        self.stage.close()
    
    def attach(self, camera: StreamingCamera, stage: OpenFlexureStage):
        """
        Retroactively attaches a camera and stage to the microscope object.

        Allows the microscope to be created as a "dummy", with hardware communications
        opened at a later time.

        Args:
            camera (:py:class:`openflexure_microscope.camera.pi.StreamingCamera`): camera object
            microscope (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object
        """

        self.camera = camera  #: :py:class:`openflexure_microscope.camera.pi.StreamingCamera`: Picamera object
        if isinstance(camera, StreamingCamera):
            logging.info("Attached camera {}".format(camera))

        self.stage = stage  #: :py:class:`openflexure_stage.stage.OpenFlexureStage`: OpenFlexure stage object
        if isinstance(self.stage, OpenFlexureStage):  # If a stage object has been attached
            logging.info("Attached stage {}".format(stage))
            self.stage.backlash = np.zeros(3, dtype=np.int)

    # Create unified state
    @property
    def state(self):