Commit 4521837c authored by Joel Collins's avatar Joel Collins
Browse files

Property to read and write capture storage path (by location key)

parent 201da43f
Loading
Loading
Loading
Loading
+100 −9
Original line number Diff line number Diff line
from labthings.server.extensions import BaseExtension
from labthings.server.view import View
from labthings.server.decorators import ThingProperty, PropertySchema
from labthings.server import fields
from labthings.server.find import find_component

from openflexure_microscope.paths import settings_file_path, check_rw
from openflexure_microscope.config import OpenflexureSettingsFile
from openflexure_microscope.camera.base import BASE_CAPTURE_PATH

from flask import abort
import logging
import os
import psutil
@@ -32,12 +38,18 @@ def get_current_location(camera):
    return camera.paths.get("default")


def set_current_location(camera, location: str):
    if not os.path.isdir(location):
        os.makedirs(location)
    return camera.paths.update({"default": location})


def get_default_location():
    return BASE_CAPTURE_PATH


def get_all_locations(camera):
    locations = {"System": get_current_location(camera)}
def get_all_locations():
    locations = {}
    # If default is not already listed (e.g. if it's currently set)
    if get_default_location() not in locations.values():
        locations["Default"] = get_default_location()
@@ -73,30 +85,109 @@ class AutostorageExtension(BaseExtension):
            description="Handle switching capture storage devices",
        )

        self.settings = OpenflexureSettingsFile(
            AS_SETTINGS_PATH, defaults={"preferred": None}
        )

        # We'll store a reference to a camera object, who's capture paths will be modified
        self.camera = None

        self.initial_location = get_default_location()

        # Register the on_microscope function to run when the microscope is attached
        self.on_component("org.openflexure.microscope", self.on_microscope)

    @property
    def preferred(self):
        return self._preferred

    @preferred.setter
    def preferred(self, new_path_key: str):
        if not new_path_key in self.get_locations().keys():
            raise KeyError(f"No location named {new_path_key}")
        self._preferred = new_path_key

    def on_microscope(self, microscope_obj):
        """Function to automatically call when the parent LabThing has a microscope attached."""
        logging.debug(f"Autostorage extension found microscope {microscope_obj}")
        if hasattr(microscope_obj, "camera"):
            self.camera = microscope_obj.camera
            logging.debug(f"Autostorage extension bound to camera {self.camera}")

            # Store a reference to the camera
            self.camera = microscope_obj.camera
            # Store the initial storage location
            self.initial_location = get_current_location(self.camera)

            # If preferred path does not exist, or cannot be written to
            if not (
                os.path.isdir(self.initial_location) and check_rw(self.initial_location)
            ):
                logging.error(
                    f"Preferred capture path {self.initial_location} is missing or cannot be written to. Restoring defaults."
                )
                # Reset the storage location to default
                set_current_location(self.camera, get_default_location())

            logging.debug(self.get_locations())

    def get_locations(self):
        if self.camera:
            return get_all_locations(self.camera)
            locations = get_all_locations()

            current_location = get_current_location(self.camera)
            if current_location not in locations.values():
                locations.update({"Custom": current_location})
            # Add location from the cameras settings file
            return locations
        else:
            return []
            return {}

    def get_preferred_key(self):
        current = get_current_location(self.camera)
        locations = self.get_locations()

        matches = [k for k, v in locations.items() if v == current]

        if len(matches) > 1:
            logging.warning(
                "Multiple path matches found. Weird, but carrying on using zeroth."
            )

        return matches[0]

    def set_preferred_key(self, new_path_key: str):
        if not new_path_key in self.get_locations().keys():
            raise KeyError(f"No location named {new_path_key}")

        location = self.get_locations().get(new_path_key)
        set_current_location(self.camera, location)


autostorage_extension_v2 = AutostorageExtension()


@ThingProperty
class GetLocationsView(View):
    def get(self):
        global autostorage_extension_v2

        return autostorage_extension_v2.get_locations()


@ThingProperty
@PropertySchema(fields.String(required=True, example="Default"))
class PreferredLocationView(View):
    def get(self):
        global autostorage_extension_v2

        return autostorage_extension_v2.get_preferred_key()

    def post(self, new_path_key):
        global autostorage_extension_v2
        microscope = find_component("org.openflexure.microscope")

        if not microscope:
            abort(503, "No microscope connected. Unable to autofocus.")

        autostorage_extension_v2.set_preferred_key(new_path_key)
        microscope.save_settings()


autostorage_extension_v2.add_view(GetLocationsView, "list-locations")
autostorage_extension_v2.add_view(PreferredLocationView, "location")