Skip to content

Commit

Permalink
Add CLI function to create new sensor (#83)
Browse files Browse the repository at this point in the history
* Add CLI function to create new sensor

* Adjustments to CLI print statements

* Register Sensor as a structure table for db-ops

* Changelog entry

* flake8 on merge

Co-authored-by: F.N. Claessen <felix@seita.nl>
  • Loading branch information
Flix6x and Flix6x committed Apr 2, 2021
1 parent 717466b commit 3f9abbf
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 10 deletions.
4 changes: 4 additions & 0 deletions documentation/changelog.rst
Expand Up @@ -6,6 +6,10 @@ FlexMeasures Changelog
v0.2.5 | April XX, 2021
===========================

New features
-----------
* Add sensors with CLI command [see `PR #83 <https://github.com/SeitaBV/flexmeasures/pull/83>`_]

Infrastructure / Support
----------------------
* Updated dependencies, including Flask-Security-Too [see `PR #82 <http://www.github.com/SeitaBV/flexmeasures/pull/82>`_]
Expand Down
4 changes: 2 additions & 2 deletions flexmeasures/data/models/assets.py
Expand Up @@ -7,7 +7,7 @@

from flexmeasures.data.config import db
from flexmeasures.data import ma
from flexmeasures.data.models.time_series import Sensor, SensorSchema, TimedValue
from flexmeasures.data.models.time_series import Sensor, SensorSchemaMixin, TimedValue
from flexmeasures.data.models.markets import Market
from flexmeasures.data.models.user import User
from flexmeasures.utils.entity_address_utils import build_entity_address
Expand Down Expand Up @@ -179,7 +179,7 @@ def __repr__(self):
)


class AssetSchema(SensorSchema, ma.SQLAlchemySchema):
class AssetSchema(SensorSchemaMixin, ma.SQLAlchemySchema):
"""
Asset schema, with validations.
"""
Expand Down
11 changes: 10 additions & 1 deletion flexmeasures/data/models/time_series.py
Expand Up @@ -22,7 +22,7 @@ class Sensor(db.Model, tb.SensorDBMixin):
"""A sensor measures events. """


class SensorSchema(Schema):
class SensorSchemaMixin(Schema):
"""
Base sensor schema.
Expand All @@ -42,6 +42,15 @@ class Meta:
event_resolution = fields.TimeDelta(required=True, precision="minutes")


class SensorSchema(SensorSchemaMixin, ma.SQLAlchemySchema):
"""
Sensor schema, with validations.
"""

class Meta:
model = Sensor


class TimedValue(object):
"""
A mixin of all tables that store time series data, either forecasts or measurements.
Expand Down
4 changes: 2 additions & 2 deletions flexmeasures/data/models/weather.py
Expand Up @@ -11,7 +11,7 @@
from flexmeasures.data.config import db

from flexmeasures.data import ma
from flexmeasures.data.models.time_series import Sensor, SensorSchema, TimedValue
from flexmeasures.data.models.time_series import Sensor, SensorSchemaMixin, TimedValue
from flexmeasures.utils.geo_utils import parse_lat_lng
from flexmeasures.utils.flexmeasures_inflection import humanize

Expand Down Expand Up @@ -171,7 +171,7 @@ def to_dict(self) -> Dict[str, str]:
return dict(name=self.name, sensor_type=self.weather_sensor_type_name)


class WeatherSensorSchema(SensorSchema, ma.SQLAlchemySchema):
class WeatherSensorSchema(SensorSchemaMixin, ma.SQLAlchemySchema):
"""
WeatherSensor schema, with validations.
"""
Expand Down
37 changes: 33 additions & 4 deletions flexmeasures/data/scripts/cli_tasks/data_add.py
Expand Up @@ -13,6 +13,7 @@

from flexmeasures.data.services.forecasting import create_forecasting_jobs
from flexmeasures.data.services.users import create_user
from flexmeasures.data.models.time_series import Sensor, SensorSchema
from flexmeasures.data.models.assets import Asset, AssetSchema
from flexmeasures.data.models.markets import Market
from flexmeasures.data.models.weather import WeatherSensor, WeatherSensorSchema
Expand Down Expand Up @@ -62,6 +63,34 @@ def new_user(username: str, email: str, roles: List[str], timezone: str):
print(f"Successfully created user {created_user}")


@fm_add_data.command("sensor")
@with_appcontext
@click.option("--name", required=True)
@click.option("--unit", required=True, help="e.g. °C, m/s, kW/m²")
@click.option(
"--event-resolution",
required=True,
type=int,
help="Expected resolution of the data in minutes",
)
@click.option(
"--timezone",
required=True,
help="timezone as string, e.g. 'UTC' or 'Europe/Amsterdam'",
)
def add_sensor(**args):
"""Add a sensor."""
check_timezone(args["timezone"])
check_errors(SensorSchema().validate(args))
args["event_resolution"] = timedelta(minutes=args["event_resolution"])
sensor = Sensor(**args)
app.db.session.add(sensor)
app.db.session.commit()
print(f"Successfully created sensor with ID {sensor.id}")
# TODO: uncomment when #66 has landed
# print(f"You can access it at its entity address {sensor.entity_address}")


@fm_add_data.command("asset")
@with_appcontext
@click.option("--name", required=True)
Expand Down Expand Up @@ -118,8 +147,8 @@ def new_asset(**args):
asset = Asset(**args)
app.db.session.add(asset)
app.db.session.commit()
print(f"Successfully created asset with ID:{asset.id}.")
print(f" You can access it at its entity address {asset.entity_address}")
print(f"Successfully created asset with ID {asset.id}")
print(f"You can access it at its entity address {asset.entity_address}")


@fm_add_data.command("weather-sensor")
Expand Down Expand Up @@ -158,9 +187,9 @@ def add_weather_sensor(**args):
sensor = WeatherSensor(**args)
app.db.session.add(sensor)
app.db.session.commit()
print(f"Successfully created sensor with ID:{sensor.id}.")
print(f"Successfully created sensor with ID {sensor.id}")
# TODO: uncomment when #66 has landed
# print(f" You can access it at its entity address {sensor.entity_address}")
# print(f"You can access it at its entity address {sensor.entity_address}")


@fm_add_data.command("structure")
Expand Down
2 changes: 1 addition & 1 deletion flexmeasures/data/scripts/data_gen.py
Expand Up @@ -18,8 +18,8 @@
from humanize import naturaldelta
import inflect

from flexmeasures.data.models.markets import MarketType, Market, Price
from flexmeasures.data.models.time_series import Sensor
from flexmeasures.data.models.markets import MarketType, Market, Price
from flexmeasures.data.models.assets import AssetType, Asset, Power
from flexmeasures.data.models.data_sources import DataSource
from flexmeasures.data.models.weather import WeatherSensorType, WeatherSensor, Weather
Expand Down

0 comments on commit 3f9abbf

Please sign in to comment.