Skip to content

Commit

Permalink
Move SensorAPI to API package under dev version
Browse files Browse the repository at this point in the history
  • Loading branch information
Flix6x committed Apr 22, 2021
1 parent 9bd99f9 commit 65122e4
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 68 deletions.
2 changes: 2 additions & 0 deletions flexmeasures/api/__init__.py
Expand Up @@ -105,9 +105,11 @@ def register_at(app: Flask):
from flexmeasures.api.v1_2 import register_at as v1_2_register_at
from flexmeasures.api.v1_3 import register_at as v1_3_register_at
from flexmeasures.api.v2_0 import register_at as v2_0_register_at
from flexmeasures.api.dev import register_at as dev_register_at

v1_register_at(app)
v1_1_register_at(app)
v1_2_register_at(app)
v1_3_register_at(app)
v2_0_register_at(app)
dev_register_at(app)
9 changes: 9 additions & 0 deletions flexmeasures/api/dev/__init__.py
@@ -0,0 +1,9 @@
from flask import Flask


def register_at(app: Flask):
"""This can be used to register FlaskViews."""

from flexmeasures.api.dev.sensors import SensorAPI

SensorAPI.register(app, route_prefix="/api/dev")
73 changes: 73 additions & 0 deletions flexmeasures/api/dev/sensors.py
@@ -0,0 +1,73 @@
from flask_classful import FlaskView, route
from flask_login import login_required
from flask_security import roles_required
from marshmallow import fields
from webargs.flaskparser import use_kwargs
from werkzeug.exceptions import abort

from flexmeasures.api.common.schemas.times import AwareDateTimeField
from flexmeasures.data.models.time_series import Sensor


class SensorAPI(FlaskView):
"""
This view exposes sensor attributes through API endpoints under development.
These endpoints are not yet part of our official API, but support the FlexMeasures UI.
"""

route_base = "/sensor"

@login_required
@roles_required("admin") # todo: remove after we check for sensor ownership
@route("/<id>/chart/")
@use_kwargs(
{
"event_starts_after": AwareDateTimeField(format="iso", required=False),
"event_ends_before": AwareDateTimeField(format="iso", required=False),
"beliefs_after": AwareDateTimeField(format="iso", required=False),
"beliefs_before": AwareDateTimeField(format="iso", required=False),
"include_data": fields.Boolean(required=False),
"as_html": fields.Boolean(required=False),
"dataset_name": fields.Str(required=False),
},
location="query",
)
def get_chart(self, id, **kwargs):
"""GET from /sensor/<id>/chart"""
sensor = get_sensor_or_abort(id)
return sensor.chart(**kwargs)

@login_required
@roles_required("admin") # todo: remove after we check for sensor ownership
@route("/<id>/chart_data/")
@use_kwargs(
{
"event_starts_after": AwareDateTimeField(format="iso", required=False),
"event_ends_before": AwareDateTimeField(format="iso", required=False),
"beliefs_after": AwareDateTimeField(format="iso", required=False),
"beliefs_before": AwareDateTimeField(format="iso", required=False),
},
location="query",
)
def get_chart_data(self, id, **kwargs):
"""GET from /sensor/<id>/chart_data
Data for use in charts (in case you have the chart specs already).
"""
sensor = get_sensor_or_abort(id)
return sensor.search_beliefs(as_json=True, **kwargs)

@login_required
@roles_required("admin") # todo: remove after we check for sensor ownership
def get(self, id: int):
"""GET from /sensor/<id>"""
sensor = get_sensor_or_abort(id)
attributes = ["name", "timezone", "timerange"]
return {attr: getattr(sensor, attr) for attr in attributes}


def get_sensor_or_abort(id: int) -> Sensor:
sensor = Sensor.query.filter(Sensor.id == id).one_or_none()
if sensor is None:
raise abort(404, f"Sensor {id} not found")
return sensor
3 changes: 1 addition & 2 deletions flexmeasures/ui/__init__.py
Expand Up @@ -33,12 +33,11 @@ def register_at(app: Flask):

from flexmeasures.ui.crud.assets import AssetCrudUI
from flexmeasures.ui.crud.users import UserCrudUI
from flexmeasures.ui.views.sensors import SensorUI, SensorAPI
from flexmeasures.ui.views.sensors import SensorUI

AssetCrudUI.register(app)
UserCrudUI.register(app)
SensorUI.register(app)
SensorAPI.register(app)

import flexmeasures.ui.views # noqa: F401 this is necessary to load the views

Expand Down
67 changes: 1 addition & 66 deletions flexmeasures/ui/views/sensors.py
@@ -1,11 +1,10 @@
from flask import abort
from flask_classful import FlaskView, route
from flask_security import login_required, roles_required
from marshmallow import fields
from webargs.flaskparser import use_kwargs

from flexmeasures.api.common.schemas.times import AwareDateTimeField
from flexmeasures.data.models.time_series import Sensor
from flexmeasures.api.dev.sensors import SensorAPI
from flexmeasures.ui.utils.view_utils import render_flexmeasures_template


Expand Down Expand Up @@ -44,67 +43,3 @@ def get(self, id: int):
sensor_id=id,
msg="",
)


class SensorAPI(FlaskView):
"""
This view exposes sensor attributes through API endpoints under development.
These endpoints are not yet part of our official API, but support the FlexMeasures UI.
"""

route_base = "/sensor"

@login_required
@roles_required("admin") # todo: remove after we check for sensor ownership
@route("/<id>/chart/")
@use_kwargs(
{
"event_starts_after": AwareDateTimeField(format="iso", required=False),
"event_ends_before": AwareDateTimeField(format="iso", required=False),
"beliefs_after": AwareDateTimeField(format="iso", required=False),
"beliefs_before": AwareDateTimeField(format="iso", required=False),
"include_data": fields.Boolean(required=False),
"as_html": fields.Boolean(required=False),
"dataset_name": fields.Str(required=False),
},
location="query",
)
def get_chart(self, id, **kwargs):
"""GET from /sensor/<id>/chart"""
sensor = get_sensor_or_abort(id)
return sensor.chart(**kwargs)

@login_required
@roles_required("admin") # todo: remove after we check for sensor ownership
@route("/<id>/chart_data/")
@use_kwargs(
{
"event_starts_after": AwareDateTimeField(format="iso", required=False),
"event_ends_before": AwareDateTimeField(format="iso", required=False),
"beliefs_after": AwareDateTimeField(format="iso", required=False),
"beliefs_before": AwareDateTimeField(format="iso", required=False),
},
location="query",
)
def get_chart_data(self, id, **kwargs):
"""GET from /sensor/<id>/chart_data
Data for use in charts (in case you have the chart specs already).
"""
sensor = get_sensor_or_abort(id)
return sensor.search_beliefs(as_json=True, **kwargs)

@login_required
@roles_required("admin") # todo: remove after we check for sensor ownership
def get(self, id: int):
"""GET from /sensor/<id>"""
sensor = get_sensor_or_abort(id)
attributes = ["name", "timezone", "timerange"]
return {attr: getattr(sensor, attr) for attr in attributes}


def get_sensor_or_abort(id: int) -> Sensor:
sensor = Sensor.query.filter(Sensor.id == id).one_or_none()
if sensor is None:
raise abort(404, f"Sensor {id} not found")
return sensor

0 comments on commit 65122e4

Please sign in to comment.