Commit 608c8b36 authored by vertighel's avatar vertighel
Browse files

Started web page. Implemented part of Init page. Implemented status page with bare monitoring

parent fcdfd3cf
Loading
Loading
Loading
Loading
Loading
+9 −12
Original line number Diff line number Diff line
@@ -26,8 +26,8 @@ api_blueprint.register_blueprint(blocks_api, url_prefix='/blocks')
api_blueprint.register_blueprint(defaults_api, url_prefix='/templates')
api_blueprint.register_blueprint(sequencer_api, url_prefix='/sequencer')

# This will store { "/telescope/power": <Instance of State>, ... }
resource_registry = {}
# # Uncomment to test dependecy errors
# resource_registry = {}

api_blueprint = Blueprint('api', __name__)

@@ -40,23 +40,20 @@ def dynamic_import(url_path):
        if url_path.startswith(("/blocks", "/sequencer")):
            return

        res_class_name = ends.get(url_path, "resource")
        dev_name = ends.get(url_path, "device")
        
        dev_instance = getattr(devices, dev_name)
        mod_name = dev_instance.__class__.__name__.lower()

        module = importlib.import_module(f"noctua.api.{mod_name}")
        resource_class = getattr(module, res_class_name)
        dev = getattr(devices, ends.get(url_path,"device"))             # devices.light instance
        cls = dev.__class__.__name__                                    # string "Switch"
        mod_name = cls.lower()                                          # string "switch"
        module = importlib.import_module(f"noctua.api.{mod_name}")      # module noctua.api.switch
        resource_class = getattr(module, ends.get(url_path,"resource")) # class noctua.api.switch.State
        
        # Identify supported HTTP methods by checking for lowercase method names in the class
        methods = [m for m in ["GET", "POST", "PUT", "DELETE"] if hasattr(resource_class, m.lower())]
        
        # Populate internal registry
        resource_registry[url_path] = resource_class(dev=dev_instance)
        resource_registry[url_path] = resource_class(dev=dev)

        # Register route
        view = resource_class.as_view(url_path, dev=dev_instance)
        view = resource_class.as_view(url_path, dev=dev)
        api_blueprint.add_url_rule(url_path, view_func=view)
        
        # Improved debug print with methods list
+27 −2
Original line number Diff line number Diff line
@@ -23,6 +23,10 @@ class Position(BaseResource):
        res = await self.run_blocking(action)
        return self.make_response(res)

    async def delete(self):
        """Check if the stage is currently moving."""
        res = await self.run_blocking(lambda: self.dev.abort)
        return self.make_response(res)

class Named(BaseResource):
    """Manage named positions (e.g., 'imaging', 'spectroscopy')."""
@@ -35,9 +39,15 @@ class Named(BaseResource):
    async def put(self):
        """Move the stage to a named position."""
        target_name = await self.get_payload() # expected string
        named_positions = self.dev.named_positions
        def action():
            if target_name in self.dev.named_positions:
                self.dev.named = target_name
                return self.dev.named
            else:
                return self.make_response(None,
                                          errors=[f"Not in: {named_positions}"],
                                          status_code=500)                
        
        try:
            res = await self.run_blocking(action)
@@ -45,6 +55,11 @@ class Named(BaseResource):
        except KeyError as e:
            return self.make_response(None, errors=[str(e)], status_code=400)

    async def delete(self):
        """Check if the stage is currently moving."""
        res = await self.run_blocking(lambda: self.dev.abort)
        return self.make_response(res)


class Initialization(BaseResource):
    """Handle stage homing and status."""
@@ -60,6 +75,11 @@ class Initialization(BaseResource):
        res = await self.run_blocking(lambda: self.dev.is_init)
        return self.make_response(res)

    async def delete(self):
        """Check if the stage is currently moving."""
        res = await self.run_blocking(lambda: self.dev.abort)
        return self.make_response(res)


class Movement(BaseResource):
    """Monitor stage motion status."""
@@ -69,6 +89,11 @@ class Movement(BaseResource):
        res = await self.run_blocking(lambda: self.dev.is_moving)
        return self.make_response(res)

    async def delete(self):
        """Check if the stage is currently moving."""
        res = await self.run_blocking(lambda: self.dev.abort)
        return self.make_response(res)


class Limits(BaseResource):
    """Manage software movement limits."""
+13 −6
Original line number Diff line number Diff line
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Third-party modules
import uvicorn
from quart import Quart
from quart_cors import cors

# Custom modules
from noctua.api import api_blueprint
#from noctua.web import web_blueprint
from noctua.api.baseresource import register_error_handlers
from noctua.web import web_blueprint


app = Quart(__name__)
app = cors(app)

# Centralized error handling (400, 404, 405, 500)
register_error_handlers(app)

# API blueprint in api/__init__.py
app.register_blueprint(api_blueprint, url_prefix='/api')
#app.register_blueprint(web_blueprint, url_prefix='/web')
app.register_blueprint(web_blueprint, url_prefix='/web')  # Added Web Blueprint


def run():
    """Server run using uvicorn"""
    """
    Server run using uvicorn.
    """

    try:
        uvicorn.run(app, host="0.0.0.0", port=5533)
@@ -27,5 +32,7 @@ def run():
        print(f"Shutting down: {e}")
        pass


if __name__ == "__main__":
    run()
+4 −4
Original line number Diff line number Diff line
@@ -232,10 +232,10 @@ resource = CoolerWarmup
device = cam
depends-on = /camera/power

[/camera/filters]
resource = Filters
device = cam
depends-on = /camera/power
# [/camera/filters]
# resource = Filters
# device = cam
# depends-on = /camera/power

[/camera/filter]
resource = Filter
+7 −7
Original line number Diff line number Diff line
@@ -66,13 +66,13 @@ filter_state = {

filter_name = {
    0: "Undef.",
    1: "U",
    2: "B",
    3: "V",
    4: "R",
    5: "I",
    6: "Halpha",
    7: "Free",
    1: "SDSS g",
    2: "SDSS r",
    3: "SDSS i",
    4: "SDSS z",
    5: "SDSS y",
    6: "FREE",
    7: "SDSS u",
    15: "Filter_error",
    None: "Off",
}
Loading