Loading noctua/api/__init__.py +7 −9 Original line number Diff line number Diff line Loading @@ -35,15 +35,13 @@ def dynamic_import(url_path): if url_path.startswith(("/blocks", "/sequencer", "/templates")): return res_class_name = ends.get(url_path, "resource") dev_name = ends.get(url_path, "device") res_class_name = ends.get(url_path, "resource") # CoolerWarmup dev_name = ends.get(url_path, "device") # cam dev_instance = getattr(devices, dev_name) # noctua.devices.stx.Camera object mod_name = dev_instance.__class__.__name__.lower() # camera # Hardware devices logic 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) module = importlib.import_module(f"noctua.api.{mod_name}") # noctua.api.camera resource_class = getattr(module, res_class_name) # noctua.api.camera.CoolerWarmup # Register dynamic route as MethodView # This automatically maps GET/POST/PUT/DELETE to class methods Loading noctua/api/camera.py +28 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ class FrameBinning(BaseResource): async def put(self): """Set a new binning for the camera.""" binning = await self.get_payload() def action(): self.dev.binning = binning Loading @@ -25,12 +26,14 @@ class Cooler(BaseResource): async def get(self): """Check wether the CCD cooler is on or off.""" raw = await self.run_blocking(lambda: self.dev.cooler) res = constants.on_off.get(raw, "N/A") return self.make_response(res, raw_data=raw) async def put(self): """Set on or off the CCD cooler.""" state = await self.get_payload() def action(): self.dev.cooler = state Loading @@ -43,6 +46,7 @@ class CoolerTemperatureSetpoint(BaseResource): async def put(self): """Set a new temperature of the CCD.""" state = await self.get_payload() def action(): self.dev.temperature = state Loading @@ -55,6 +59,7 @@ class Filters(BaseResource): async def get(self): """Retrieve the filter names.""" # Constants are not blocking res = constants.filter_number return self.make_response(res) Loading @@ -64,6 +69,7 @@ class Filter(BaseResource): async def get(self): """Retrieve the current filter.""" raw = await self.run_blocking(lambda: self.dev.filter) res = constants.filter_name.get(raw, "Undef.") return self.make_response(res, raw_data=raw) Loading @@ -73,12 +79,14 @@ class FilterMovement(BaseResource): async def get(self): """Check if the filter wheel is moving.""" raw = await self.run_blocking(lambda: self.dev.is_moving) res = constants.filter_state.get(raw, "Off") return self.make_response(res, raw_data=raw) async def post(self): """Set a new filter.""" target = await self.get_payload() def action(): self.dev.filter = target Loading @@ -91,6 +99,7 @@ class FrameCustom(BaseResource): async def put(self): """Set a custom windowing.""" new_frame = await self.get_payload() def action(): self.dev.binning = new_frame["binning"] Loading @@ -104,6 +113,7 @@ class FrameFull(BaseResource): async def put(self): """Set the ccd to full frame in current binning.""" res = await self.run_blocking(self.dev.full_frame) return self.make_response(res) Loading @@ -113,6 +123,7 @@ class FrameHalf(BaseResource): async def put(self): """Set a center ccd window spanning half the size of the full frame in the current binning.""" res = await self.run_blocking(self.dev.half_frame) return self.make_response(res) Loading @@ -122,6 +133,7 @@ class FrameSmall(BaseResource): async def put(self): """Set a center ccd window spanning 2 arcminutes on the sky.""" res = await self.run_blocking(self.dev.small_frame) return self.make_response(res) Loading @@ -130,6 +142,7 @@ class SnapshotRaw(BaseResource): async def post(self): """Start a raw image using camera interface.""" new = await self.get_payload() # exptime, type try: res = await self.run_blocking( Loading @@ -144,6 +157,7 @@ class SnapshotRaw(BaseResource): async def delete(self): """Stop the process.""" res = await self.run_blocking(self.dev.abort) return self.make_response(res) Loading @@ -152,6 +166,7 @@ class SnapshotState(BaseResource): async def get(self): """Retrieve the status of the acquisition process.""" raw = await self.run_blocking(lambda: self.dev.state) res = constants.camera_state.get(raw, "Off") return self.make_response(res, raw_data=raw) Loading @@ -161,6 +176,7 @@ class Snapshot(BaseResource): async def get(self): """Retrieve the status of the image process.""" data = { "paused": seq.tpl.paused if seq.tpl else None, "quitting": seq.tpl.aborted if seq.tpl else None, Loading @@ -176,6 +192,7 @@ class Snapshot(BaseResource): async def delete(self): """Stop the image process.""" res = await self.run_blocking(seq.tpl.abort) return self.make_response(res) Loading @@ -184,6 +201,7 @@ class SnapshotRecenter(BaseResource): async def get(self): """Retrieve the recenter status and parameters of the box.""" res = { "recenter": getattr(seq.tpl, 'recenter', None), "box": getattr(seq.tpl, 'box', None), Loading @@ -192,6 +210,7 @@ class SnapshotRecenter(BaseResource): async def put(self): """Set a given box to the recentering function""" data = await self.get_payload() if seq.tpl: seq.tpl.box = data Loading @@ -199,12 +218,14 @@ class SnapshotRecenter(BaseResource): async def post(self): """Enable the recentering function.""" if seq.tpl: seq.tpl.recenter = True return self.make_response(True) async def delete(self): """Disable the recentering function.""" if seq.tpl: seq.tpl.recenter = False return self.make_response(False) Loading @@ -214,17 +235,20 @@ class SnapshotDomeslewing(BaseResource): async def get(self): """Retrieve the domeslewing status""" res = {"domeslewing": getattr(seq.tpl, 'domeslewing', None)} return self.make_response(res) async def post(self): """Enable the domeslewing function.""" if seq.tpl: seq.tpl.domeslewing = True return self.make_response(True) async def delete(self): """Disable the domeslewing function.""" if seq.tpl: seq.tpl.domeslewing = False return self.make_response(False) Loading @@ -234,10 +258,12 @@ class CoolerWarmup(BaseResource): async def post(self): """Start the warm up the CCD.""" return self.make_response("Warmup sequence initiated") async def delete(self): """Stop the warm up of the CCD.""" return self.make_response("Warmup sequence aborted") class Connection(BaseResource): Loading @@ -245,6 +271,7 @@ class Connection(BaseResource): async def get(self): '''Check if the telescope is connected to ASCOM.''' res = await self.run_blocking(lambda: self.dev.connection) return self.make_response(res) Loading @@ -253,5 +280,6 @@ class Settings(BaseResource): async def get(self): '''Retrieve all-in-one the settings of the camera.''' res = await self.run_blocking(lambda: self.dev.all) return self.make_response(res) noctua/api/dome.py +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ class Position(BaseResource): async def get(self): '''Check the azimuth of the dome, and if this corresponds to the parking position.''' is_parked = await self.run_blocking(lambda: self.dev.is_parked) azimuth = await self.run_blocking(lambda: self.dev.azimuth) Loading @@ -32,6 +33,7 @@ class Shutter(BaseResource): async def get(self): '''Check the state of the dome shutter.''' shutter = await self.run_blocking(lambda: self.dev.shutter) return self.make_response(constants.open_state.get(shutter, "Off"), raw_data=shutter) Loading @@ -42,6 +44,7 @@ class ShutterMovement(BaseResource): async def post(self): '''Move the shutter to a new position (open or closed).''' target_state = await self.get_payload() def action(): Loading @@ -53,6 +56,7 @@ class ShutterMovement(BaseResource): async def delete(self): '''Stop the movement of the shutter.''' res = await self.run_blocking(self.dev.abort) return self.make_response(res) Loading @@ -64,12 +68,14 @@ class PositionSlaved(BaseResource): async def get(self): '''Check if the dome is slaved to the telescope or not.''' slave = await self.run_blocking(lambda: self.dev.slave) return self.make_response(constants.yes_no.get(slave, "N/A"), raw_data=slave) async def put(self): '''Make the dome slaved to the telescope or release it.''' slave_target = await self.get_payload() def action(): Loading @@ -86,6 +92,7 @@ class PositionSync(BaseResource): async def put(self): '''Tell the dome that its current position corresponds to a given azimuth.''' new_azimuth = await self.get_payload() res = await self.run_blocking(self.dev.sync, new_azimuth) return self.make_response(res) Loading @@ -96,11 +103,13 @@ class PositionMovement(BaseResource): async def get(self): '''Return if the dome is moving or not.''' is_moving = await self.run_blocking(lambda: self.dev.is_moving) return self.make_response(constants.yes_no.get(is_moving, "N/A"), raw_data=is_moving) async def delete(self): '''Stop the movement of the dome.''' res = await self.run_blocking(self.dev.abort) return self.make_response(res) Loading @@ -110,6 +119,7 @@ class PositionMovementPark(BaseResource): async def post(self): '''Park the dome.''' res = await self.run_blocking(self.dev.park) return self.make_response(res) Loading @@ -119,6 +129,7 @@ class PositionMovementAzimuth(BaseResource): async def post(self): '''Set a new dome azimuth.''' target_azimuth = await self.get_payload() def action(): Loading @@ -134,6 +145,7 @@ class Connection(BaseResource): async def get(self): '''check if the dome is connected to ASCOM.''' conn = await self.run_blocking(lambda: self.dev.connection) # Handling bool(conn) logic from original Loading @@ -142,6 +154,7 @@ class Connection(BaseResource): async def put(self): '''Connect or disconnect the telescope to ASCOM.''' conn_target = await self.get_payload() def action(): Loading noctua/api/focuser.py +5 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ class Focuser(BaseResource): async def get(self): '''Retrieve the secondary mirror position.''' res = await self.run_blocking(lambda: self.dev.position) return self.make_response(res) Loading @@ -21,11 +22,13 @@ class FocuserMovement(BaseResource): async def get(self): '''Check if the secondary mirror is moving.''' res = await self.run_blocking(lambda: self.dev.is_moving) return self.make_response(res) async def put(self): '''Update the secondary mirror position.''' target = await self.get_payload() def action(): Loading @@ -41,11 +44,13 @@ class Connection(BaseResource): async def get(self): '''Check if the focuser is connected.''' res = await self.run_blocking(lambda: self.dev.connection) return self.make_response(res) async def put(self): '''Connect or disconnect the focuser.''' connection_target = await self.get_payload() def action(): Loading noctua/api/rotator.py +5 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ class Rotator(BaseResource): async def get(self): '''Retrieve the field derotator position.''' res = await self.run_blocking(lambda: self.dev.position) return self.make_response(res) Loading @@ -21,11 +22,13 @@ class RotatorMovement(BaseResource): async def get(self): '''Check if the field derotator is moving.''' res = await self.run_blocking(lambda: self.dev.is_moving) return self.make_response(res) async def post(self): '''Set the field derotator to a new position.''' target = await self.get_payload() def action(): Loading @@ -41,11 +44,13 @@ class Connection(BaseResource): async def get(self): '''Check if the rotator is connected.''' res = await self.run_blocking(lambda: self.dev.connection) return self.make_response(res) async def put(self): '''Connect or disconnect the rotator.''' connection_target = await self.get_payload() def action(): Loading Loading
noctua/api/__init__.py +7 −9 Original line number Diff line number Diff line Loading @@ -35,15 +35,13 @@ def dynamic_import(url_path): if url_path.startswith(("/blocks", "/sequencer", "/templates")): return res_class_name = ends.get(url_path, "resource") dev_name = ends.get(url_path, "device") res_class_name = ends.get(url_path, "resource") # CoolerWarmup dev_name = ends.get(url_path, "device") # cam dev_instance = getattr(devices, dev_name) # noctua.devices.stx.Camera object mod_name = dev_instance.__class__.__name__.lower() # camera # Hardware devices logic 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) module = importlib.import_module(f"noctua.api.{mod_name}") # noctua.api.camera resource_class = getattr(module, res_class_name) # noctua.api.camera.CoolerWarmup # Register dynamic route as MethodView # This automatically maps GET/POST/PUT/DELETE to class methods Loading
noctua/api/camera.py +28 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ class FrameBinning(BaseResource): async def put(self): """Set a new binning for the camera.""" binning = await self.get_payload() def action(): self.dev.binning = binning Loading @@ -25,12 +26,14 @@ class Cooler(BaseResource): async def get(self): """Check wether the CCD cooler is on or off.""" raw = await self.run_blocking(lambda: self.dev.cooler) res = constants.on_off.get(raw, "N/A") return self.make_response(res, raw_data=raw) async def put(self): """Set on or off the CCD cooler.""" state = await self.get_payload() def action(): self.dev.cooler = state Loading @@ -43,6 +46,7 @@ class CoolerTemperatureSetpoint(BaseResource): async def put(self): """Set a new temperature of the CCD.""" state = await self.get_payload() def action(): self.dev.temperature = state Loading @@ -55,6 +59,7 @@ class Filters(BaseResource): async def get(self): """Retrieve the filter names.""" # Constants are not blocking res = constants.filter_number return self.make_response(res) Loading @@ -64,6 +69,7 @@ class Filter(BaseResource): async def get(self): """Retrieve the current filter.""" raw = await self.run_blocking(lambda: self.dev.filter) res = constants.filter_name.get(raw, "Undef.") return self.make_response(res, raw_data=raw) Loading @@ -73,12 +79,14 @@ class FilterMovement(BaseResource): async def get(self): """Check if the filter wheel is moving.""" raw = await self.run_blocking(lambda: self.dev.is_moving) res = constants.filter_state.get(raw, "Off") return self.make_response(res, raw_data=raw) async def post(self): """Set a new filter.""" target = await self.get_payload() def action(): self.dev.filter = target Loading @@ -91,6 +99,7 @@ class FrameCustom(BaseResource): async def put(self): """Set a custom windowing.""" new_frame = await self.get_payload() def action(): self.dev.binning = new_frame["binning"] Loading @@ -104,6 +113,7 @@ class FrameFull(BaseResource): async def put(self): """Set the ccd to full frame in current binning.""" res = await self.run_blocking(self.dev.full_frame) return self.make_response(res) Loading @@ -113,6 +123,7 @@ class FrameHalf(BaseResource): async def put(self): """Set a center ccd window spanning half the size of the full frame in the current binning.""" res = await self.run_blocking(self.dev.half_frame) return self.make_response(res) Loading @@ -122,6 +133,7 @@ class FrameSmall(BaseResource): async def put(self): """Set a center ccd window spanning 2 arcminutes on the sky.""" res = await self.run_blocking(self.dev.small_frame) return self.make_response(res) Loading @@ -130,6 +142,7 @@ class SnapshotRaw(BaseResource): async def post(self): """Start a raw image using camera interface.""" new = await self.get_payload() # exptime, type try: res = await self.run_blocking( Loading @@ -144,6 +157,7 @@ class SnapshotRaw(BaseResource): async def delete(self): """Stop the process.""" res = await self.run_blocking(self.dev.abort) return self.make_response(res) Loading @@ -152,6 +166,7 @@ class SnapshotState(BaseResource): async def get(self): """Retrieve the status of the acquisition process.""" raw = await self.run_blocking(lambda: self.dev.state) res = constants.camera_state.get(raw, "Off") return self.make_response(res, raw_data=raw) Loading @@ -161,6 +176,7 @@ class Snapshot(BaseResource): async def get(self): """Retrieve the status of the image process.""" data = { "paused": seq.tpl.paused if seq.tpl else None, "quitting": seq.tpl.aborted if seq.tpl else None, Loading @@ -176,6 +192,7 @@ class Snapshot(BaseResource): async def delete(self): """Stop the image process.""" res = await self.run_blocking(seq.tpl.abort) return self.make_response(res) Loading @@ -184,6 +201,7 @@ class SnapshotRecenter(BaseResource): async def get(self): """Retrieve the recenter status and parameters of the box.""" res = { "recenter": getattr(seq.tpl, 'recenter', None), "box": getattr(seq.tpl, 'box', None), Loading @@ -192,6 +210,7 @@ class SnapshotRecenter(BaseResource): async def put(self): """Set a given box to the recentering function""" data = await self.get_payload() if seq.tpl: seq.tpl.box = data Loading @@ -199,12 +218,14 @@ class SnapshotRecenter(BaseResource): async def post(self): """Enable the recentering function.""" if seq.tpl: seq.tpl.recenter = True return self.make_response(True) async def delete(self): """Disable the recentering function.""" if seq.tpl: seq.tpl.recenter = False return self.make_response(False) Loading @@ -214,17 +235,20 @@ class SnapshotDomeslewing(BaseResource): async def get(self): """Retrieve the domeslewing status""" res = {"domeslewing": getattr(seq.tpl, 'domeslewing', None)} return self.make_response(res) async def post(self): """Enable the domeslewing function.""" if seq.tpl: seq.tpl.domeslewing = True return self.make_response(True) async def delete(self): """Disable the domeslewing function.""" if seq.tpl: seq.tpl.domeslewing = False return self.make_response(False) Loading @@ -234,10 +258,12 @@ class CoolerWarmup(BaseResource): async def post(self): """Start the warm up the CCD.""" return self.make_response("Warmup sequence initiated") async def delete(self): """Stop the warm up of the CCD.""" return self.make_response("Warmup sequence aborted") class Connection(BaseResource): Loading @@ -245,6 +271,7 @@ class Connection(BaseResource): async def get(self): '''Check if the telescope is connected to ASCOM.''' res = await self.run_blocking(lambda: self.dev.connection) return self.make_response(res) Loading @@ -253,5 +280,6 @@ class Settings(BaseResource): async def get(self): '''Retrieve all-in-one the settings of the camera.''' res = await self.run_blocking(lambda: self.dev.all) return self.make_response(res)
noctua/api/dome.py +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ class Position(BaseResource): async def get(self): '''Check the azimuth of the dome, and if this corresponds to the parking position.''' is_parked = await self.run_blocking(lambda: self.dev.is_parked) azimuth = await self.run_blocking(lambda: self.dev.azimuth) Loading @@ -32,6 +33,7 @@ class Shutter(BaseResource): async def get(self): '''Check the state of the dome shutter.''' shutter = await self.run_blocking(lambda: self.dev.shutter) return self.make_response(constants.open_state.get(shutter, "Off"), raw_data=shutter) Loading @@ -42,6 +44,7 @@ class ShutterMovement(BaseResource): async def post(self): '''Move the shutter to a new position (open or closed).''' target_state = await self.get_payload() def action(): Loading @@ -53,6 +56,7 @@ class ShutterMovement(BaseResource): async def delete(self): '''Stop the movement of the shutter.''' res = await self.run_blocking(self.dev.abort) return self.make_response(res) Loading @@ -64,12 +68,14 @@ class PositionSlaved(BaseResource): async def get(self): '''Check if the dome is slaved to the telescope or not.''' slave = await self.run_blocking(lambda: self.dev.slave) return self.make_response(constants.yes_no.get(slave, "N/A"), raw_data=slave) async def put(self): '''Make the dome slaved to the telescope or release it.''' slave_target = await self.get_payload() def action(): Loading @@ -86,6 +92,7 @@ class PositionSync(BaseResource): async def put(self): '''Tell the dome that its current position corresponds to a given azimuth.''' new_azimuth = await self.get_payload() res = await self.run_blocking(self.dev.sync, new_azimuth) return self.make_response(res) Loading @@ -96,11 +103,13 @@ class PositionMovement(BaseResource): async def get(self): '''Return if the dome is moving or not.''' is_moving = await self.run_blocking(lambda: self.dev.is_moving) return self.make_response(constants.yes_no.get(is_moving, "N/A"), raw_data=is_moving) async def delete(self): '''Stop the movement of the dome.''' res = await self.run_blocking(self.dev.abort) return self.make_response(res) Loading @@ -110,6 +119,7 @@ class PositionMovementPark(BaseResource): async def post(self): '''Park the dome.''' res = await self.run_blocking(self.dev.park) return self.make_response(res) Loading @@ -119,6 +129,7 @@ class PositionMovementAzimuth(BaseResource): async def post(self): '''Set a new dome azimuth.''' target_azimuth = await self.get_payload() def action(): Loading @@ -134,6 +145,7 @@ class Connection(BaseResource): async def get(self): '''check if the dome is connected to ASCOM.''' conn = await self.run_blocking(lambda: self.dev.connection) # Handling bool(conn) logic from original Loading @@ -142,6 +154,7 @@ class Connection(BaseResource): async def put(self): '''Connect or disconnect the telescope to ASCOM.''' conn_target = await self.get_payload() def action(): Loading
noctua/api/focuser.py +5 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ class Focuser(BaseResource): async def get(self): '''Retrieve the secondary mirror position.''' res = await self.run_blocking(lambda: self.dev.position) return self.make_response(res) Loading @@ -21,11 +22,13 @@ class FocuserMovement(BaseResource): async def get(self): '''Check if the secondary mirror is moving.''' res = await self.run_blocking(lambda: self.dev.is_moving) return self.make_response(res) async def put(self): '''Update the secondary mirror position.''' target = await self.get_payload() def action(): Loading @@ -41,11 +44,13 @@ class Connection(BaseResource): async def get(self): '''Check if the focuser is connected.''' res = await self.run_blocking(lambda: self.dev.connection) return self.make_response(res) async def put(self): '''Connect or disconnect the focuser.''' connection_target = await self.get_payload() def action(): Loading
noctua/api/rotator.py +5 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ class Rotator(BaseResource): async def get(self): '''Retrieve the field derotator position.''' res = await self.run_blocking(lambda: self.dev.position) return self.make_response(res) Loading @@ -21,11 +22,13 @@ class RotatorMovement(BaseResource): async def get(self): '''Check if the field derotator is moving.''' res = await self.run_blocking(lambda: self.dev.is_moving) return self.make_response(res) async def post(self): '''Set the field derotator to a new position.''' target = await self.get_payload() def action(): Loading @@ -41,11 +44,13 @@ class Connection(BaseResource): async def get(self): '''Check if the rotator is connected.''' res = await self.run_blocking(lambda: self.dev.connection) return self.make_response(res) async def put(self): '''Connect or disconnect the rotator.''' connection_target = await self.get_payload() def action(): Loading