Skip to content
Commits on Source (110)
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
*# *#
.#* .#*
__pycache__ __pycache__
web/static/js9/
ob/*json ob/*json
data/fits/20* data/fits/20*
data/log/OARPAF* data/log/OARPAF*
\ No newline at end of file
...@@ -2,24 +2,11 @@ ...@@ -2,24 +2,11 @@
OARPAF Instrument Control Software OARPAF Instrument Control Software
## git configuration on observatory pc # System dependencies:
To push directly on observatory pc (for people without access to INAF repo)
```
# on obseravatory pc
git config receive.denyCurrentBranch updateInstead
# on local machine
git remote add machine user@machine:software-di-controllo
git push machine main
```
## System dependencies:
Maybe I'll trop these:
``` ```
sudo apt install gnuplot gnupot-x11 sudo apt install gnuplot gnupot-x11
sudo /home/zap/MBB/mbb -w 9000 -i 22000 -l /home/zap/MBB/mbb.log 10.185.119.248
``` ```
## Python dependencies: ## Python dependencies:
...@@ -29,13 +16,38 @@ sudo /home/zap/MBB/mbb -w 9000 -i 22000 -l /home/zap/MBB/mbb.log 10.185.119.248 ...@@ -29,13 +16,38 @@ sudo /home/zap/MBB/mbb -w 9000 -i 22000 -l /home/zap/MBB/mbb.log 10.185.119.248
pip3 install requests loguru astropy pip3 install requests loguru astropy
pip3 install gnuplotlib pyvantagepro # maybe I'll drop these. pip3 install gnuplotlib pyvantagepro # maybe I'll drop these.
# For the API and the web interface: # For the API interface:
pip3 install flask flask-restx flask-httpauth flask-apscheduler werkzeug pip3 install flask flask-restx flask-cors
pip3 install requests ping3 # maybe I'll drop these. It's just in home page.
# Tested with flask==3.0.2 flask-restx==1.3.0 flask-httpauth==4.8.0 flask-apscheduler==1.13.1 werkzeug-3.0.1 # Tested with flask==3.0.2 flask-restx==1.3.0 flask-httpauth==4.8.0 flask-apscheduler==1.13.1 werkzeug-3.0.1
./app.py --noweb
./app.py --noweb port hostname_or_ip
# http://server:port/api
# for the web pages:
pip3 install flask flask-socketio flask-httpauth
./app.py
./app.py port hostname_or_ip
# http://server:port/api
# http://server:port/web
``` ```
# Dome board: ## git configuration on observatory pc
To push directly on observatory pc (for people without access to INAF repo)
```
# on obseravatory pc
git config receive.denyCurrentBranch updateInstead
# on local machine
git remote add machine user@machine:software-di-controllo
git push machine main
```
## Dome board:
``` ```
sudo apt-get install python-dev libusb-dev swig libwxgtk3.0-gtk3-dev sudo apt-get install python-dev libusb-dev swig libwxgtk3.0-gtk3-dev
...@@ -57,11 +69,20 @@ sudo make pyinstall guiinstall ...@@ -57,11 +69,20 @@ sudo make pyinstall guiinstall
git clone https://github.com/lfini/SW-OPC-2.git git clone https://github.com/lfini/SW-OPC-2.git
``` ```
## Siemens modbus interface
```
sudo apt install gnuplot gnupot-x11
sudo /home/zap/MBB/mbb -w 9000 -i 22000 -l /home/zap/MBB/mbb.log 10.185.119.248
```
# Branches: # Branches:
- main - main
- dev - dev
[![Latest Release](https://www.ict.inaf.it/gitlab/davide.ricci/software-di-controllo/-/badges/release.svg)](https://www.ict.inaf.it/gitlab/davide.ricci/software-di-controllo/-/releases) <!-- [![Latest Release](https://www.ict.inaf.it/gitlab/davide.ricci/software-di-controllo/-/badges/release.svg)](https://www.ict.inaf.it/gitlab/davide.ricci/software-di-controllo/-/releases) -->
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
############################ '''Automatic REST APIs'''
# REST API
############################ # System modules
import configparser
import importlib
import sys
# Third-party modules # Third-party modules
from flask import Blueprint from flask import Blueprint
from flask_httpauth import HTTPBasicAuth from flask_restx import Api, Namespace, Resource
from flask_restx import Api, reqparse
# Custom modules
import devices
from utils.url_stuff import build_url
from .blocks import api as blocks_api from .blocks import api as blocks_api
from .camera import api as camera_api
from .dome import api as dome_api
from .environment import api as environment_api from .environment import api as environment_api
from .home import api as home_api
from .other import api as other_api
from .telescope import api as telescope_api
from .templates import api as templates_api from .templates import api as templates_api
from .webcam import api as webcam_api from .testfulvio import api as testfulvio_api
from .display import api as display_api
from .testfulvio import api as fulvio_api
api_blueprint = Blueprint('api', __name__) api_blueprint = Blueprint('api', __name__)
api = Api(api_blueprint, api = Api(api_blueprint,
title='OARPAF APIs for observatory control', title='Generic APIs for observatory control',
version='1.0', version='1.0',
description='A description', description=['A description']
) )
api.add_namespace(home_api) base = "api." # this module
api.add_namespace(blocks_api)
api.add_namespace(templates_api)
api.add_namespace(other_api)
api.add_namespace(dome_api) ends = configparser.ConfigParser()
api.add_namespace(telescope_api) ends.read('./config/api.ini')
api.add_namespace(camera_api)
api.add_namespace(webcam_api)
api.add_namespace(display_api)
api.add_namespace(environment_api)
api.add_namespace(fulvio_api)
def dynamic_import(url):
"""Dynamically import into this module api.ini files.
"""
############################ parts = url.split('/') # /dome/shutter/movement
# WEB VIEW namespace = parts[1] # dome
############################ end = '/' + '/'.join(parts[2:]) # /shutter/movement
# System modules
import json # for users
# Third-party modules dev_api = Namespace(namespace) # adding namespace /dome. Endpoint will be added
from .blocks import web as blocks_web
from .control import web as control_web
from .environment import web as environment_web
from .home import web as home_web
from .init import web as init_web
from .other import web as other_web
from .templates import web as templates_web
from .webcam import web as webcam_web
from .display import web as display_web
from .testfulvio import web as fulvio_web
auth = HTTPBasicAuth()
users_file = 'users.json' dev = getattr(devices, ends.get(url,"device")) # devices.light instance
cls = dev.__class__.__name__ # string "Switch"
mod_name = cls.lower() # string "switch"
module = importlib.import_module(base + mod_name ) # module api.switch
module_class = getattr(module, ends.get(url,"resource")) # class api.switch.State
try: # Assigning endpoint to api.ShutterMovement
with open(users_file) as json_file: dev_api.add_resource(module_class, end , resource_class_kwargs={"dev": dev})
users = json.load(json_file) api.add_namespace(dev_api) # Adding to /dome: /shutter/movement
except FileNotFoundError as e:
print(f"{users_file} containing user:pass not found")
exit(0)
for end in ends.sections():
dynamic_import(end)
@auth.verify_password # Apart, what is not in the api.ini.
def verify(username, password):
if not (username and password):
return False
return users.get(username) == password
api.add_namespace(environment_api)
web_blueprint = Blueprint('web', __name__) api.add_namespace(blocks_api)
api.add_namespace(templates_api)
web = Api(web_blueprint,
title='OARPAF Web view for observatory control',
version='1.0',
description='A description',
decorators=[auth.login_required], # on every page.
)
web.add_namespace(home_web) api.add_namespace(testfulvio_api)
web.add_namespace(blocks_web)
web.add_namespace(templates_web)
web.add_namespace(webcam_web)
web.add_namespace(display_web)
web.add_namespace(environment_web)
web.add_namespace(other_web)
web.add_namespace(control_web)
web.add_namespace(init_web)
web.add_namespace(fulvio_web)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''Estension of flask_restx Resource to pass the device in the constructor'''
# System modules
from datetime import datetime
# Third-party modules
from flask_restx import Resource
class ResourceDev(Resource):
'''Add the device to the constructor of the Resource class.
So other resources will inherit from this,
without always passing it to the constructor'''
def __init__(self, *args, **kwargs):
'''Constructor.'''
super().__init__(self, *args, **kwargs)
self.dev = kwargs["dev"]
@property
def timestamp(self):
"""Generate a iso timestamp"""
clock = datetime.utcnow().isoformat()
return clock
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
'''REST API to edit Observation Blocks'''
# Third-party modules # Third-party modules
from flask import make_response, render_template, request
from flask_restx import Namespace, Resource from flask_restx import Namespace, Resource
from .data_access_object import ObservationBlockObject as DAO # Custom modules
from .data_access_object import guess from utils.data_access_object import ObservationBlockObject as DAO
from utils.data_access_object import guess
dao = DAO("ob") dao = DAO("ob")
tpl = DAO("defaults") tpl = DAO("defaults")
############################
# REST API
############################
api = Namespace('blocks', description='Observation blocks') api = Namespace('blocks', description='Observation blocks')
@api.route("/") @api.route("/")
class BlockList(Resource): class BlockList(Resource):
"""Show and create OBs""" """Show and create OBs"""
...@@ -38,7 +35,6 @@ class BlockList(Resource): ...@@ -38,7 +35,6 @@ class BlockList(Resource):
dao.delete(name) dao.delete(name)
return "", 204 return "", 204
@api.route("/<string:name>") @api.route("/<string:name>")
@api.param("name", "The uniqe name of the OB") @api.param("name", "The uniqe name of the OB")
class Block(Resource): class Block(Resource):
...@@ -53,9 +49,9 @@ class Block(Resource): ...@@ -53,9 +49,9 @@ class Block(Resource):
def put(self, name): def put(self, name):
"""Update the OB""" """Update the OB"""
data = api.payload data = api.payload
for d in data: for datum in data:
for key, val in d["params"].items(): for key, val in datum["params"].items():
d["params"][key] = guess(val) datum["params"][key] = guess(val)
dao.update(name, data) dao.update(name, data)
return "", 204 return "", 204
...@@ -74,50 +70,3 @@ class Block(Resource): ...@@ -74,50 +70,3 @@ class Block(Resource):
data.pop(instance - 1) # jinjia loop starts from 1 in html data.pop(instance - 1) # jinjia loop starts from 1 in html
dao.update(name, data) dao.update(name, data)
return "", 204 return "", 204
############################
# WEB VIEW
############################
web = Namespace('blocks', description='OB generator')
@web.route("/")
class BlockListWeb(Resource):
"""Show and create OBs"""
def get(self):
"""Show all observation OB files"""
data = dao.todos
return make_response(render_template("blocks.html", data=data, tpl=tpl.todos))
@web.route("/<string:name>")
@web.param("name", "The uniqe name of the OB")
class BlockWeb(Resource):
"""Show a selected OB, update it, or add a new
template in it.
"""
def get(self, name):
"""Show a specific OB"""
included = request.args.get("included") or False
data = dao.show(name)
#data = block.get(name)
return make_response(render_template("block.html",
data=data, tpl=tpl.todos,
included=included))
@web.route("/<string:name>/<int:instance>")
@web.param("name", "The uniqe name of the OB")
@web.param("instance", "The template instance in the selected OB")
class BlockInstanceWeb(Resource):
def get(self, name, instance):
"""Show a specific template instance of the selected OB"""
data = dao.show(name)
data["content"] = [data["content"][instance]]
return make_response(render_template("block.html", data=data))
# return [data]
This diff is collapsed.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''REST API for fits files'''
# System modules
import time
# Third-party modules
from astropy.time import Time
from flask import Response, make_response, render_template, request
from flask_restx import Namespace, Resource, fields
# Custom modules
# import devices
############################
# REST API
############################
api = Namespace('display', description='Fits files related operations')
# @api.route("/position")
# class Pointing(Resource):
# """Position of the webcam."""
# def get(self):
# """Retrieve the alt az coordinates of the webcam."""
# res = {
# "response": devices.ipcam.altaz,
# "error": devices.ipcam.error,
# }
# return res
# def put(self):
# """Set new alt az coordinates of the webcam."""
# target = api.payload
# devices.ipcam.altaz = target
# res = {
# "response": devices.ipcam.altaz,
# "error": devices.ipcam.error,
# }
# return res
# @api.route("/test2")
# class Pointing(Resource):
# """test."""
# def get(self):
# """BSON test"""
# res = {
# "response": (1.234*1+np.zeros((100,100))).tolist(),
# "error": (1.234*1+np.zeros((100,100))).tolist(),
# }
# # Convert JSON to binary
# b = msgpack.packb(res)
# #json.dumps(res).encode('utf-8')
# response = make_response(b)
# response.headers['Content-Type'] = 'application/octet-stream'
# return response
# def put(self):
# """Set new alt az coordinates of the webcam."""
# target = api.payload
# res = {
# "response": devices.ipcam.altaz,
# "error": devices.ipcam.error,
# }
# return res
# @api.route("/snapshot")
# class Snapshot(Resource):
# """Image from the webcam."""
# def __init__(self, *args, **kwargs):
# '''Constructor.'''
# super().__init__(self)
# self.last = None
# def get(self):
# """Retrieve a raw base/64 image from the webcam."""
# img = devices.ipcam.image
# if not img:
# code = 401
# elif devices.ipcam.error:
# code = 501
# else:
# code = 200
# res = {
# "response": img.decode("ISO-8859-1") if img else img,
# "error": devices.ipcam.error,
# }
# self.last = img
# return res, code
############################
# WEB VIEW
############################
web = Namespace('display', description='Display fits file interface')
@web.route("/")
class Init(Resource):
def get(self):
data = {}
return make_response(render_template("display.html", data=data))
...@@ -4,268 +4,197 @@ ...@@ -4,268 +4,197 @@
'''REST API for Dome related operations''' '''REST API for Dome related operations'''
# Third-party modules # Third-party modules
from flask_restx import Namespace, Resource, fields from flask import request
# Custom modules # Custom modules
import devices from config import constants
from .baseresource import ResourceDev
api = Namespace('dome', description='Dome related operations')
model_generic = api.model('Generic', { # @api.route("/position")
'error': fields.List(fields.String), class Position(ResourceDev):
})
model_bool = api.clone('Boolean', model_generic, {
'response': fields.Boolean,
})
model_int = api.clone('Integer', model_generic, {
'response': fields.Integer,
})
model_float = api.clone('Float', model_generic, {
'response': fields.Float,
})
sub_model_position = api.model('SubPosition', {
"azimuth": fields.Float,
"parked": fields.Boolean,
})
model_position = api.clone('Position', model_generic, {
'response': fields.Nested(sub_model_position),
})
@api.route("/light")
class Light(Resource):
'''Manage the dome illumination.'''
@api.marshal_with(model_bool, 200)
def get(self, **kwargs):
'''Check if the dome illumination is on or off.'''
res = {
"response": devices.light.state,
"error": devices.light.error,
}
return res
@api.marshal_with(model_bool, 200)
def put(self):
'''Switch on or off the dome illumination.'''
state = api.payload
devices.light.state = state
res = {
"response": devices.light.state,
"error": devices.light.error,
}
return res
@api.route("/position")
class Position(Resource):
'''Get the position of the dome.''' '''Get the position of the dome.'''
@api.marshal_with(model_position, 200)
def get(self): def get(self):
'''Check the azimuth of the dome, and if '''Check the azimuth of the dome, and if
this corresponds to the parking position.''' this corresponds to the parking position.'''
res = { res = {
"raw": self.dev.is_parked,
"response": { "response": {
"azimuth": devices.dom.azimuth, "azimuth": self.dev.azimuth,
"parked": devices.dom.is_parked, "parked": constants.yes_no[self.dev.is_parked],
}, },
"error": devices.dom.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/shutter") # @api.route("/shutter")
class Shutter(Resource): class Shutter(ResourceDev):
'''Dome Shutter''' '''Dome Shutter'''
@api.marshal_with(model_int, 200)
def get(self): def get(self):
'''Check the state of the dome shutter.''' '''Check the state of the dome shutter.'''
res = { res = {
"response": devices.dom.shutter, "raw": self.dev.shutter,
"error": devices.dom.error, "response": constants.open_state[self.dev.shutter],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
# @api.route("/shutter/movement")
@api.route("/shutter/movement") class ShutterMovement(ResourceDev):
class ShutterMovement(Resource):
'''Manage the movement of the dome shutter.''' '''Manage the movement of the dome shutter.'''
def post(self): def post(self):
'''Move the shutter to a new position '''Move the shutter to a new position
(open or closed).''' (open or closed).'''
target = api.payload target = request.json
devices.dom.open = target self.dev.open = target
res = { res = {
"response": devices.dom.open, "raw": self.dev.open,
"error": devices.dom.error, "response": constants.open_state[self.open],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
def delete(self): def delete(self):
'''Stop the movement of the shutter.''' '''Stop the movement of the shutter.'''
res = { res = {
"response": devices.dom.abort(), "response": self.dev.abort(),
"error": devices.dom.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/position/slaved") # @api.route("/position/slaved")
class PositionSlaved(Resource): class PositionSlaved(ResourceDev):
'''Manage the minioning of the shutter '''Manage the minioning of the shutter
to the telescope.''' to the telescope.'''
@api.marshal_with(model_bool, 200)
def get(self): def get(self):
'''Check if the dome is slaved '''Check if the dome is slaved
to the telescope or not.''' to the telescope or not.'''
res = { res = {
"response": devices.dom.slave, "raw": self.dev.slave,
"error": devices.dom.error, "response": constants.yes_no[self.dev.slave],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.marshal_with(model_bool, 200)
def put(self): def put(self):
'''Make the dome slaved to the telescope '''Make the dome slaved to the telescope
or release it.''' or release it.'''
slaved = api.payload slaved = request.json
devices.dom.slave = slaved self.dev.slave = slaved
res = { res = {
"response": devices.dom.slave, "raw": self.dev.slave,
"error": devices.dom.error, "response": constants.yes_no[self.dev.slave],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/position/sync") # @api.route("/position/sync")
class PositionSync(Resource): class PositionSync(ResourceDev):
'''Manage the reference azimuth of the dome''' '''Manage the reference azimuth of the dome'''
@api.marshal_with(model_float, 200)
def put(self): def put(self):
'''Tell the dome that its current position '''Tell the dome that its current position
corresponds to a given azimuth.''' corresponds to a given azimuth.'''
new_azimuth = api.payload new_azimuth = request.json
res = { res = {
"response": devices.dom.sync(new_azimuth), "response": self.dev.sync(new_azimuth),
"error": devices.dom.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/position/movement") # @api.route("/position/movement")
class PositionMovement(Resource): class PositionMovement(ResourceDev):
'''Manage the movement of the dome.''' '''Manage the movement of the dome.'''
@api.marshal_with(model_bool, 200) # @api.marshal_with(model_bool, 200)
def get(self): def get(self):
'''Return if the dome is moving or not.''' '''Return if the dome is moving or not.'''
res = { res = {
"response": devices.dom.is_moving, "raw": self.dev.is_moving,
"error": devices.dom.error, "response": constants.yes_no[self.dev.is_moving],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
def delete(self): def delete(self):
'''Stop the movement of the dome.''' '''Stop the movement of the dome.'''
res = { res = {
"response": devices.dom.abort(), "response": self.dev.abort(),
"error": devices.dom.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/position/movement/park") # @api.route("/position/movement/park")
class PositionMovementPark(Resource): class PositionMovementPark(ResourceDev):
'''Manage the dome parking.''' '''Manage the dome parking.'''
def post(self): def post(self):
'''Park the dome.''' '''Park the dome.'''
res = { res = {
"response": devices.dom.park(), "response": self.dev.park(),
"error": devices.dom.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/position/movement/azimuth") # @api.route("/position/movement/azimuth")
class PositionMovementAzimuth(Resource): class PositionMovementAzimuth(ResourceDev):
'''Manage the position of the dome.''' '''Manage the position of the dome.'''
@api.marshal_with(model_float, 200)
def post(self): def post(self):
'''Set a new dome azimuth.''' '''Set a new dome azimuth.'''
azimuth = api.payload azimuth = request.json
devices.dom.azimuth = azimuth self.dev.azimuth = azimuth
res = { res = {
"response": devices.dom.azimuth, "response": self.dev.azimuth,
"error": devices.dom.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/connection") # @api.route("/connection")
class Connection(Resource): class Connection(ResourceDev):
'''Manage the connection to ASCOM.''' '''Manage the connection to ASCOM.'''
def get(self): def get(self):
'''Check if the dome is connected to ASCOM.''' '''check if the dome is connected to ASCOM.'''
conn = self.dev.connection
res = { res = {
"response": devices.dom.connection, "raw": conn,
"error": devices.dom.error, "response": constants.yes_no[conn] if bool(conn) else False,
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.response(200, 'Success', fields.Boolean())
def put(self): def put(self):
'''Connect or disconnect the telescope to ASCOM.''' '''Connect or disconnect the telescope to ASCOM.'''
connection = api.payload connection = request.json
devices.dom.connection = connection self.dev.connection = connection
res = { res = {
"response": devices.dom.connection, "raw": self.dev.connection,
"error": devices.dom.error, "response": constants.yes_no[self.dev.connection],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/status")
class Status(Resource):
'''General dome status.'''
def __init__(self, *args, **kwargs):
'''Constructor.'''
super().__init__(self)
self.last = None
def get(self):
'''Retrieve the status of each compoent.'''
connection = Connection().get()
if connection["response"]:
res = {
"connection": connection,
"light": Light().get(),
"position": Position().get(),
"moving": PositionMovement().get(),
"shutter": Shutter().get(),
"slaved": PositionSlaved().get(),
}
else:
res = {
"connection": connection,
"light": Light().get(),
}
self.last = res
return res
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
'''REST API to get Meteo data'''
# Third-party modules # Third-party modules
from astropy.time import Time from flask_restx import Namespace, Resource
from flask import Response, make_response, render_template, request
from flask_restx import Model, Namespace, Resource, fields
# Custom modules # Custom modules
import devices import devices
...@@ -14,7 +13,6 @@ import devices ...@@ -14,7 +13,6 @@ import devices
# REST API # REST API
############################ ############################
api = Namespace( api = Namespace(
'environment', description='Environment data from multiple devices') 'environment', description='Environment data from multiple devices')
...@@ -23,11 +21,6 @@ api = Namespace( ...@@ -23,11 +21,6 @@ api = Namespace(
class Status(Resource): class Status(Resource):
"""Asks all the environment data""" """Asks all the environment data"""
def __init__(self, *args, **kwargs):
'''Constructor.'''
super().__init__(self)
self.last = None
def get(self): def get(self):
"""Downloads all the environment values available """ """Downloads all the environment values available """
meteo = Meteo().get() meteo = Meteo().get()
...@@ -35,7 +28,6 @@ class Status(Resource): ...@@ -35,7 +28,6 @@ class Status(Resource):
# meteo.update(internal) # meteo.update(internal)
res = {"external": meteo, "internal": internal} res = {"external": meteo, "internal": internal}
self.last = res
return res return res
...@@ -73,19 +65,19 @@ class Internal(Resource): ...@@ -73,19 +65,19 @@ class Internal(Resource):
"""Downloads the current meteo station values""" """Downloads the current meteo station values"""
try: try:
telescope_temperatures = devices.tel.temperature telescope_temperatures = devices.tel_temp.temperature
if not telescope_temperatures: if not telescope_temperatures:
print("telescope_temperatures device error!") print("telescope_temperatures device error!")
telescope_temperatures = [None, None, None] telescope_temperatures = [None, None, None]
except Exception as e: except Exception as e:
print("telescope_temperatures exception error:") print("telescope_temperatures exception error:")
print(e) print(e)
telescope_temperatures = [None, None, None] telescope_temperatures = [None, None, None]
# try: # try:
# if devices.sof.state: # if devices.sof.state:
# camera_ambient = devices.cam.ambient # camera_ambient = devices.cam.ambient
# camera_ambient = None # camera_ambient = None
# except Exception as e: # except Exception as e:
# log.debug(f"Environment camera_ambient error: {e}") # log.debug(f"Environment camera_ambient error: {e}")
# camera_ambient = None # camera_ambient = None
...@@ -111,27 +103,3 @@ class Internal(Resource): ...@@ -111,27 +103,3 @@ class Internal(Resource):
} }
return res return res
############################
# WEB VIEW
############################
web = Namespace('environment', description='Meteo Weather page')
@web.route("/")
class EnvironmentWeb(Resource):
""" Weatherpage """
def get(self):
""" Display the meteo """
data = Status().get()
exclude = ["Barometric_trend", "Battery_status", "Battery_volts",
"ET_day", "ET_month", "ET_year",
"Storm_start_date", "Forecast_rule_number", "Forecast_icon"
]
for e in exclude:
data["external"].pop(e, None)
return make_response(render_template("meteo.html", data=data))
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''REST API for Focuser related operations'''
# Third-party modules
from flask import request
from .baseresource import ResourceDev
# @api.route("/focuser")
class Focuser(ResourceDev):
'''Secondary mirror position.'''
def get(self):
'''Retrieve the secondary mirror position.'''
res = {
"response": self.dev.position,
"error": self.dev.error,
}
return res
# @api.route("/focuser/movement")
class FocuserMovement(ResourceDev):
'''Manage the secondary mirror position.'''
def get(self):
'''Check if the secondary mirror is moving.'''
res = {
"response": self.dev.is_moving,
"error": self.dev.error,
}
return res
def put(self):
'''Update the secondary mirror position.'''
target = request.json
self.dev.position = target
res = {
"response": self.dev.position,
"error": self.dev.error,
}
return res
# def delete(self):
# '''Stop the movement.'''
# return
# @api.route("/connection")
class Connection(ResourceDev):
'''Manage the connection to ASCOM.'''
def get(self):
'''Check if the focuser is connected.'''
res = {
"response": self.dev.connection,
"error": self.dev.error,
}
return res
def put(self):
'''Connect or disconnect the focuser.'''
connection = request.json
self.dev.connection = connection
res = {
"response": self.dev.connection,
"error": self.dev.error,
}
return res
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Third-party modules
from flask import make_response, render_template
from flask_restx import Namespace, Resource, fields
from .data_access_object import TemplateObject as DAO
# defaults_folder = "defaults"
# api = Namespace('defaults', description='Defaults template parameters')
web = Namespace('templates', description='Defaults template parameters')
dao = DAO()
@web.route("/")
class TemplateList(Resource):
def get(self):
data = dao.todos
return make_response(render_template("ob_controls.html", data=data))
@web.route("/<string:name>")
class Template(Resource):
def get(self,name):
data = dao.show(name)
data["content"] = [data["content"]]
return make_response(render_template("ob.html", data=data))
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# System modules
import json
# adjusted flask_logger
import time
# Third-party modules
from astropy.time import Time
from flask import (Response, make_response, render_template, request,
stream_with_context)
from flask_restx import Namespace, Resource
from loguru import logger
from .data_access_object import ObservationBlockObject as DAO
from .data_access_object import guess
dao = DAO("ob")
tpl = DAO("defaults")
############################
# REST API
############################
api = Namespace('logger', description='Logger')
@api.route("/")
class Logger(Resource):
"""Show and create OBs"""
def get(self):
return make_response(render_template("per-orso.html"))
# return "ppp"
# def generate():
# while True:
# content = Time.now().isot
# yield str(content)
# time.sleep(1)
# return Response(stream_with_context(generate()))
############################
# WEB VIEW
############################
web = Namespace('logger', description='OB generator')
@web.route("/")
class Logger(Resource):
"""Show and create OBs"""
def get(self):
return make_response(render_template("per-orso.html"))
# @web.route("/")
# class BlockListWeb(Resource):
# """Show and create OBs"""
# def get(self):
# """Show all observation OB files"""
# data = dao.todos
# return make_response(render_template("ob_list.html", data=data, tpl=tpl.todos))
# def post(self):
# """Create a new OB file based on name"""
# name = api.payload
# dao.create(name)
# return "", 204
# def delete(self):
# """Delete an OB file based on name"""
# name = api.payload
# dao.delete(name)
# return "", 204
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Third-party modules
from flask import make_response, render_template
from flask_restx import Namespace, Resource, fields
from .data_access_object import ObservationBlockObject as DAO
# @web.route("/")
# class (Resource):
# def get(self):
# data = dao.todos
# return make_response(render_template("defaults.html", data=data))
# @web.route("/list")
# class TodoListWeb(Resource):
# def get(self):
# data = dao.todos
# return make_response(render_template("defaults-list.html", data=data))
# @web.route("/<string:id>")
# class TodoWeb(Resource):
# def get(self,id):
# data = [dao.read(id)]
# return make_response(render_template("defaults.html", data=data))
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''REST API for Rotator related operations'''
# Third-party modules
from flask import request
from .baseresource import ResourceDev
# @api.route("/rotator")
class Rotator(ResourceDev):
'''Field derotator position.'''
def get(self):
'''Retrieve the field derotator position.'''
res = {
"response": self.dev.position,
"error": self.dev.error,
}
return res
# @api.route("/rotator/movement")
class RotatorMovement(ResourceDev):
'''Manage the field derotator position.'''
def get(self):
'''Check if the field derotator is moving.'''
res = {
"response": self.dev.is_moving,
"error": self.dev.error,
}
return res
def post(self):
'''Set the field derotator to a new position.'''
target = request.json
self.dev.position = target
res = {
"response": self.dev.position,
"error": self.dev.error,
}
return res
# @api.route("/connection")
class Connection(ResourceDev):
'''Manage the connection to ASCOM.'''
def get(self):
'''Check if the rotator is connected.'''
res = {
"response": self.dev.connection,
"error": self.dev.error,
}
return res
def put(self):
'''Connect or disconnect the rotator.'''
connection = request.json
self.dev.connection = connection
res = {
"response": self.dev.connection,
"error": self.dev.error,
}
return res
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''Unique sequencer instance for all APIs'''
# Custom modules
from sequencer import Sequencer
seq = Sequencer()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''REST API for Switch related operations'''
# System modules
# Third-party modules
from flask import request
# Custom modules
from config import constants
from .baseresource import ResourceDev
# @api.route("/dome/light")
# @api.route("/telescope/lamp")
# @api.route("/camera/power")
class State(ResourceDev):
'''Manage a switch state.'''
def __init__(self, *args, **kwargs):
'''Constructor.'''
super().__init__(self, *args, **kwargs)
self.dev = kwargs["dev"]
def get(self):
'''Check if the switch on or off.'''
res = {
"raw": self.dev.state,
"response": constants.on_off[self.dev.state],
"error": self.dev.error,
"timestamp": self.timestamp,
}
return res
def put(self):
'''Switch on or off.'''
state = request.json
self.dev.state = state
res = {
"raw": self.dev.state,
"response": constants.on_off[self.dev.state],
"error": self.dev.error,
"timestamp": self.timestamp,
}
return res
...@@ -3,156 +3,49 @@ ...@@ -3,156 +3,49 @@
'''REST API for Telescope related operations''' '''REST API for Telescope related operations'''
# System modules
from datetime import datetime
# Third-party modules # Third-party modules
from astropy.time import Time from flask import request
from flask_restx import Namespace, Resource, fields
# Custom modules # Custom modules
import devices from config import constants
from utils.coordinates import to_hms, to_hms_dms, to_radec from utils.coordinates import to_hms, to_hms_dms, to_radec
from .baseresource import ResourceDev
api = Namespace('telescope', description='Telescope related operations')
@api.route("/lamp")
class Lamp(Resource):
'''Manage the flat field lamp.'''
@api.response(200, 'Success', fields.Boolean())
def get(self):
'''Check if the flat field lamp is on or off.'''
res = {
"response": devices.lamp.state,
"error": devices.lamp.error,
}
return res
@api.response(200, 'Success', fields.Boolean())
# @api.expect(model)
def put(self):
'''Switch on or off the flat field lamp.'''
state = api.payload
devices.lamp.state = state
res = {
"response": devices.lamp.state,
"error": devices.lamp.error,
}
return res
@api.route("/focuser")
class Focuser(Resource):
'''Secondary mirror position.'''
@api.response(200, 'Success', fields.Float())
def get(self):
'''Retrieve the secondary mirror position.'''
res = {
"response": devices.foc.position,
"error": devices.foc.error,
}
return res
@api.route("/focuser/movement")
class FocuserMovement(Resource):
'''Manage the secondary mirror position.'''
@api.response(200, 'Success', fields.Boolean())
def get(self):
'''Check if the secondary mirror is moving.'''
res = {
"response": devices.foc.is_moving,
"error": devices.foc.error,
}
return res
@api.response(200, 'Success', fields.Float())
def put(self):
'''Update the secondary mirror position.'''
target = api.payload
devices.foc.position = target
res = {
"response": devices.foc.position,
"error": devices.foc.error,
}
return res
# def delete(self):
# '''Stop the movement.'''
# return
@api.route("/rotator")
class Rotator(Resource):
'''Field derotator position.'''
@api.response(200, 'Success', fields.Float())
def get(self):
'''Retrieve the field derotator position.'''
res = {
"response": devices.rot.position,
"error": devices.rot.error,
}
return res
@api.route("/rotator/movement")
class RotatorMovement(Resource):
'''Manage the field derotator position.'''
@api.response(200, 'Success', fields.Boolean())
def get(self):
'''Check if the field derotator is moving.'''
res = {
"response": devices.rot.is_moving,
"error": devices.rot.error,
}
return res
@api.response(200, 'Success', fields.Float())
def post(self):
'''Set the field derotator to a new position.'''
target = api.payload
devices.rot.position = target
res = {
"response": devices.rot.position,
"error": devices.rot.error,
}
return res
@api.route("/cover") # @api.route("/cover")
class Cover(Resource): class Cover(ResourceDev):
'''Petals covering the primary mirror.''' '''Petals covering the primary mirror.'''
@api.response(200, 'Success', fields.Float())
def get(self): def get(self):
'''Retrieve the petals position.''' '''Retrieve the petals position.'''
res = { res = {
"response": devices.tel.cover, "response": self.dev.cover,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/cover/movement") # @api.route("/cover/movement")
class CoverMovement(Resource): class CoverMovement(ResourceDev):
'''Manage the primary mirror cover petals.''' '''Manage the primary mirror cover petals.'''
# def get(self): # def get(self):
# '''Check if petals are moving.''' # '''Check if petals are moving.'''
# return # return
@api.response(200, 'Success', fields.Boolean())
def post(self): def post(self):
'''Set a new position for cover petals '''Set a new position for cover petals
(open or closed).''' (open or closed).'''
target = api.payload target = request.json # api.payload
devices.tel.open = target self.dev.open = target
res = { res = {
"response": devices.tel.open, "response": self.dev.open,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
...@@ -161,343 +54,281 @@ class CoverMovement(Resource): ...@@ -161,343 +54,281 @@ class CoverMovement(Resource):
# return # return
@api.route("/error") # @api.route("/error")
class Error(Resource): class Error(ResourceDev):
'''Manage the cabinet errors.''' '''Manage the cabinet errors.'''
@api.response(200, 'Success', fields.String())
def get(self): def get(self):
'''Check if there are errors.''' '''Check if there are errors.'''
res = { res = {
"response": devices.tel.state, # state is global "response": self.dev.state, # state is global
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.response(200, 'Success', fields.Integer())
def delete(self): def delete(self):
'''Try to clean the errors.''' '''Try to clean the errors.'''
error_number = api.payload error_number = request.json
res = { res = {
"response": devices.tel.clear(error_number), "response": self.dev.clear(error_number),
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/error/details") # @api.route("/error/details")
class ErrorDetails(Resource): class ErrorDetails(ResourceDev):
'''Get the global status to have more info.''' '''Get the global status to have more info.'''
@api.response(200, 'Success', fields.String())
def get(self): def get(self):
'''Check if there are errors.''' '''Check if there are errors.'''
res = { res = {
"response": devices.tel.status, # state is global "response": self.dev.status, # state is global
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/clock") # @api.route("/clock")
class Clock(Resource): class Clock(ResourceDev):
'''Telescope time from GPS.''' '''Telescope time from GPS.'''
def get(self): def get(self):
'''Get the telescope time from GPS.''' '''Get the telescope time from GPS.'''
res = { res = {
"response": devices.tel.clock, "response": self.dev.clock,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates") # @api.route("/coordinates")
class Coordinates(Resource): class Coordinates(ResourceDev):
'''Telescope coordinates.''' '''Telescope coordinates.'''
def get(self): def get(self):
'''Get the telescope coordinates.''' '''Get the telescope coordinates.'''
coor = self.dev.coordinates
lst = coor["lst"]
ra = coor["radec"][0]
coor["ha"] = to_hms(lst-ra)
coor["radec"] = to_hms_dms(coor["radec"])
coor["lst"] = to_hms(coor["lst"])
utc = coor["utc"]
coor["utc"] = datetime.fromtimestamp(utc).isoformat()
res = { res = {
"response": devices.tel.coordinates, "response": coor,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates/movement") # @api.route("/coordinates/movement")
class CoordinatesMovement(Resource): class CoordinatesMovement(ResourceDev):
'''Manage the pointing of the telescope.''' '''Manage the pointing of the telescope.'''
def get(self): def get(self):
'''Check the status of the telescope movement.''' '''Check the status of the telescope movement.'''
res = { res = {
"response": devices.tel.is_moving, "response": self.dev.is_moving,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
def delete(self): def delete(self):
'''Stop the telescope movement.''' '''Stop the telescope movement.'''
res = { res = {
"response": devices.tel.abort(), "response": self.dev.abort(),
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates/movement/radec") # @api.route("/coordinates/movement/radec")
class CoordinatesMovementRadec(Resource): class CoordinatesMovementRadec(ResourceDev):
'''Point the telescope in Ra, Dec.''' '''Point the telescope in Ra, Dec.'''
def post(self): def post(self):
'''Set new Ra and Dec coordinates.''' '''Set new Ra and Dec coordinates.'''
target = api.payload target = request.json
radec = to_radec(target) radec = to_radec(target)
print(radec) print(radec)
devices.tel.radec = radec self.dev.radec = radec
res = { res = {
"response": devices.tel.radec, "response": self.dev.radec,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates/movement/altaz") # @api.route("/coordinates/movement/altaz")
class CoordinatesMovementAltaz(Resource): class CoordinatesMovementAltaz(ResourceDev):
'''Point the telescope in Alt, Az.''' '''Point the telescope in Alt, Az.'''
def post(self): def post(self):
'''Set new Alt and Az coordinates.''' '''Set new Alt and Az coordinates.'''
target = api.payload target = request.json
devices.tel.altaz = target self.dev.altaz = target
res = { res = {
"response": devices.tel.altaz, "response": self.dev.altaz,
"error": devices.tel.error "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates/movement/atpark") # @api.route("/coordinates/movement/atpark")
class CoordinatesMovementAtpark(Resource): class CoordinatesMovementAtpark(ResourceDev):
'''Park the telescope.''' '''Park the telescope.'''
def get(self): def get(self):
'''Send the telescope to park position.''' '''Send the telescope to park position.'''
devices.tel.park parked = self.dev.park
res = { res = {
"response": devices.tel.park, "raw": parked,
"error": devices.tel.error, "response": constants.yes_no[parked],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates/movement/park") # @api.route("/coordinates/movement/park")
class CoordinatesMovementPark(Resource): class CoordinatesMovementPark(ResourceDev):
'''Park the telescope.''' '''Park the telescope.'''
def post(self): def post(self):
'''Send the telescope to park position.''' '''Send the telescope to park position.'''
devices.tel.park = True self.dev.park = True
res = { res = {
"response": devices.tel.park, "response": self.dev.park,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates/movement/unpark") # @api.route("/coordinates/movement/unpark")
class CoordinatesMovementUnpark(Resource): class CoordinatesMovementUnpark(ResourceDev):
'''Unpark the telescope.''' '''Unpark the telescope.'''
def post(self): def post(self):
'''Remove the telescope from park position.''' '''Remove the telescope from park position.'''
devices.tel.park = False self.dev.park = False
res = {"response": devices.tel.park, res = {
"error": devices.tel.error, "response": self.dev.park,
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates/offset") # @api.route("/coordinates/offset")
class CoordinatesOffset(Resource): class CoordinatesOffset(ResourceDev):
'''Manage the coordinates offset.''' '''Manage the coordinates offset.'''
def get(self): def get(self):
'''Retrieve the telescope offset in Zdist, Az.''' '''Retrieve the telescope offset in Zdist, Az.'''
res = { res = {
"response": devices.tel.offset, "response": self.dev.offset,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
def put(self): def put(self):
'''Apply to the telescope new offsets in degrees.''' '''Apply to the telescope new offsets in degrees.'''
offset = api.payload offset = request.json
devices.tel.offset = offset self.dev.offset = offset
res = { res = {
"response": devices.tel.offset, "response": self.dev.offset,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/coordinates/tracking") # @api.route("/coordinates/tracking")
class CoordinatesTracking(Resource): class CoordinatesTracking(ResourceDev):
'''Enable or disable the telescope tracking.''' '''Enable or disable the telescope tracking.'''
def get(self): def get(self):
'''Check if the telescope is tracking or not.''' '''Check if the telescope is tracking or not.'''
res = { res = {
"response": devices.tel.tracking, "raw": self.dev.tracking,
"error": devices.tel.error, "response": constants.yes_no[self.dev.tracking],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.response(200, 'Success', fields.Boolean())
def put(self): def put(self):
'''Set the telescope in tracking mode or not''' '''Set the telescope in tracking mode or not'''
tracking = api.payload tracking = request.json
devices.tel.tracking = tracking self.dev.tracking = tracking
res = { res = {
"response": devices.tel.tracking, "response": self.dev.tracking,
"error": devices.tel.error, "error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/power") # @api.route("/connection")
class Power(Resource): class Connection(ResourceDev):
'''Manage the cabinet power.'''
def get(self):
'''Check if the telescope cabinet is on or off.'''
res = {
"response": devices.cab.state,
"error": devices.cab.error,
}
return res
@api.response(200, 'Success', fields.Boolean())
def put(self):
'''Switch on or off the telescope cabinet.'''
power = api.payload
devices.cab.state = power
res = {
"response": devices.cab.state,
"error": devices.cab.error,
}
return res
@api.route("/connection")
class Connection(Resource):
'''Manage the connection to ASCOM.''' '''Manage the connection to ASCOM.'''
def get(self): def get(self):
'''Check if the telescope is connected to ASCOM.''' '''Check if the telescope is connected to ASCOM.'''
res = { res = {
"response": devices.tel.connection, "raw": self.dev.connection,
"error": devices.tel.error, "response": constants.yes_no[self.dev.connection],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.response(200, 'Success', fields.Boolean())
def put(self): def put(self):
'''Connect or disconnect the telescope to ASCOM.''' '''Connect or disconnect the telescope to ASCOM.'''
connection = api.payload connection = request.json
devices.tel.connection = connection self.dev.connection = connection
res = { res = {
"response": devices.tel.connection, "raw": self.dev.connection,
"error": devices.tel.error, "response": constants.yes_no[self.dev.connection],
"error": self.dev.error,
"timestamp": self.timestamp,
} }
return res return res
@api.route("/status") # clock = Clock(dev=self.dev).get()
class Status(Resource): # if clock["response"] and type(clock["response"]) != str:
'''General telescope status.'''
def __init__(self, *args, **kwargs): # # 2) astelOS has data from the GPS
'''Constructor.'''
super().__init__(self)
self.last = None
def get(self): # connection = Connection(dev=self.dev).get()
'''Retrieve the status of each compoent.''' # if connection["response"]:
power = Power().get() # cab # # 3) Telescope manually connected to ASCOM
if power["response"]:
# 1) Powered cabinet # else:
clock = Clock().get() # # 3) No telescope ASCOM connection
if clock["response"] and type(clock["response"]) != str:
# 2) astelOS has data from the GPS # else:
# # 2) AstelOS not ready
coor = Coordinates().get()
lst = coor["response"]["lst"] # return res
ra = coor["response"]["radec"][0]
coor["response"]["ha"] = to_hms(lst-ra)
coor["response"]["radec"] = to_hms_dms(
coor["response"]["radec"])
coor["response"]["lst"] = to_hms(coor["response"]["lst"])
coor["response"]["utc"] = Time(
coor["response"]["utc"], format="unix").isot
connection = Connection().get()
if connection["response"]:
# 3) Telescope manually connected to ASCOM
res = {
"power": power, # cab
"connection": connection,
"parked": CoordinatesMovementAtpark().get(),
"lamp": Lamp().get(),
"focuser": Focuser().get(),
"focuser-movement": FocuserMovement().get(),
"rotator": Rotator().get(),
"rotator-movement": RotatorMovement().get(),
"coordinates-movement": CoordinatesMovement().get(),
"coordinates-tracking": CoordinatesTracking().get(),
"clock": clock, # ast
"cover": Cover().get(), # ast
"offset": CoordinatesOffset().get(), # ast
"error": Error().get(), # ast
"error-details": ErrorDetails().get(), # ast
"coordinates": coor, # ast
}
else:
# 3) No telescope ASCOM connection
res = {
"power": power, # cab
"connection": connection,
#"clock": clock, # ast
"cover": Cover().get(), # ast
"offset": CoordinatesOffset().get(), # ast
"error": Error().get(), # ast
"coordinates": coor, # ast
}
else:
# 2) AstelOS not ready
res = {
"power": power, # cab
#"clock": clock, # ast
}
else:
# 1) Cabinet powered off
res = {
"power": power, # cab
}
self.last = res
return res
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
'''REST API to launch observation blocks'''
# System modules # System modules
# Third-party modules # Third-party modules
from flask import Response, make_response, render_template, request
from flask_restx import Namespace, Resource, fields from flask_restx import Namespace, Resource, fields
import json
# Custom modules # Custom modules
from sequencer import Sequencer from api.sequencer_instance import seq
from utils.data_access_object import ObservationBlockObject as DAO
from .data_access_object import ObservationBlockObject as DAO
dao = DAO("ob") dao = DAO("ob")
seq = Sequencer()
############################ ############################
# REST API # REST API
...@@ -68,27 +67,26 @@ class BobRun(Resource): ...@@ -68,27 +67,26 @@ class BobRun(Resource):
'''Constructor.''' '''Constructor.'''
super().__init__(self) super().__init__(self)
self.seq = seq self.seq = seq
self.last = None
def get(self): def get(self):
"""Show the sequencer status""" """Show the sequencer status"""
if self.seq.tpl: if self.seq.tpl:
res = { res = {
"response": { "response": {
"name": self.seq.tpl.name, "name": self.seq.tpl.name,
"paused": self.seq.tpl.paused, "paused": self.seq.tpl.paused,
"quitting": self.seq.tpl.aborted, "quitting": self.seq.tpl.aborted,
"output": self.seq.tpl.output, "output": self.seq.tpl.output,
"error": self.seq.tpl.error, "error": self.seq.tpl.error,
"filename": self.seq.tpl.filename, "filename": self.seq.tpl.filename,
}, },
"error": self.seq.error, "error": self.seq.error,
} }
else: else:
res = { res = {
"response": { "response": {
"name": None, "name": None,
...@@ -100,8 +98,7 @@ class BobRun(Resource): ...@@ -100,8 +98,7 @@ class BobRun(Resource):
}, },
"error": "No tpl object", "error": "No tpl object",
} }
self.last = res
return res return res
def put(self): def put(self):
...@@ -110,7 +107,7 @@ class BobRun(Resource): ...@@ -110,7 +107,7 @@ class BobRun(Resource):
PUT /sequencer/run true: resume, PUT /sequencer/run true: resume,
PUT /sequencer/run false: pause PUT /sequencer/run false: pause
""" """
in_execution = api.payload in_execution = api.payload
self.seq.resume() if in_execution else self.seq.pause() self.seq.resume() if in_execution else self.seq.pause()
res = { res = {
...@@ -163,23 +160,9 @@ class BobRun(Resource): ...@@ -163,23 +160,9 @@ class BobRun(Resource):
"""Stop the sequencer""" """Stop the sequencer"""
self.seq.quit() self.seq.quit()
#res = "None" #res = "None"
if ob in self.seq and self.seq.ob: if getattr(self.seq, "ob", False) and self.seq.ob:
res = { res = {
"response": self.seq.ob if self.seq.ob else None, "response": self.seq.ob if self.seq.ob else None,
"error": self.seq.error, "error": self.seq.error,
} }
return res return res
############################
# WEB VIEW
############################
web = Namespace('sequencer', description='Web Sequencer interface')
@web.route("/")
class BobWeb(Resource):
def get(self):
data = dao.todos
return make_response(render_template("sequencer.html", data=data))
...@@ -4,10 +4,8 @@ ...@@ -4,10 +4,8 @@
'''REST API test for Fulvio''' '''REST API test for Fulvio'''
# Third-party modules # Third-party modules
from flask import Response, make_response, render_template, request from flask_restx import Namespace, Resource
from flask_restx import Namespace, Resource, fields
# Custom modules
# import devices # import devices
############################ ############################
...@@ -16,7 +14,6 @@ from flask_restx import Namespace, Resource, fields ...@@ -16,7 +14,6 @@ from flask_restx import Namespace, Resource, fields
api = Namespace('fulvio', description='Fulvio test') api = Namespace('fulvio', description='Fulvio test')
@api.route("/test") @api.route("/test")
class TestApi(Resource): class TestApi(Resource):
"""First get/post test of Fulvio.""" """First get/post test of Fulvio."""
...@@ -36,27 +33,10 @@ class TestApi(Resource): ...@@ -36,27 +33,10 @@ class TestApi(Resource):
if target != "bbb": if target != "bbb":
err = "Non va bene, scrivi bbb" err = "Non va bene, scrivi bbb"
else: else:
err = "nessun errore" err = "nessun errore"
res = { res = {
"response": target, "response": target,
"error": err, "error": err,
} }
return res return res
############################
# WEB VIEW
############################
web = Namespace('fulvio', description='Web fulvio test pages')
@web.route("/test")
class TestWeb(Resource):
"""First get/post test web page of Fulvio."""
def get(self):
"""GET fulvio test web page."""
data = {}
return make_response(render_template("other/fulvio.html", data=data))