diff --git a/app/config/development.default.py b/app/config/development.default.py index 3df45beeefde3e3939cddd8e0a05e5eb64fedf8c..ae446d6a5ee4881aab16150f007dbc20bd6b1e1f 100644 --- a/app/config/development.default.py +++ b/app/config/development.default.py @@ -3,6 +3,7 @@ import os SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_DATABASE_URI = os.environ['DBURI'] +REDSHIFT_DATABASE_URI = os.environ['REDSHIFT_DATABASE_URI'] REDIS_URI = os.environ['REDISURI'] @@ -32,11 +33,6 @@ AUTH0_CLAIMS_NAMESPACE = os.environ['AUTH0_CLAIMS_NAMESPACE'] AUTH0_CLIENT_ID = os.environ['AUTH0_CLIENT_ID'] AUTH0_CLIENT_SECRET = os.environ['AUTH0_CLIENT_SECRET'] -REDSHIFT_DB_NAME = os.environ['REDSHIFT_DB_NAME'] -REDSHIFT_USER = os.environ['REDSHIFT_USER'] -REDSHIFT_PASSWORD = os.environ['REDSHIFT_PASSWORD'] -REDSHIFT_HOST = os.environ['REDSHIFT_HOST'] - # Blocpower auth information. HEADER_AUTH_KEY = 'x-blocpower-auth-key' HEADER_AUTH_TOKEN = 'x-blocpower-auth-token' diff --git a/app/config/local.default.py b/app/config/local.default.py index 5c175ce7cc8060247c36a0e8929a451172940e23..9272f39873c69f39ac5cfac8854fbc8eaa4a6bca 100644 --- a/app/config/local.default.py +++ b/app/config/local.default.py @@ -1,5 +1,6 @@ SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_DATABASE_URI = 'sqlite://' +REDSHIFT_DATABASE_URI = 'redshift://' REDIS_URI = 'redis://127.0.0.1:6379/' @@ -29,11 +30,6 @@ AUTH0_CLAIMS_NAMESPACE = '$AUTH0_CLAIMS_NAMESPACE' AUTH0_CLIENT_ID = '$AUTH0_CLIENT_ID' AUTH0_CLIENT_SECRET = '$AUTH0_CLIENT_SECRET' -REDSHIFT_DB_NAME = '$REDSHIFT_DB_NAME' -REDSHIFT_USER = '$REDSHIFT_USER' -REDSHIFT_PASSWORD = '$REDSHIFT_PASSWORD' -REDSHIFT_HOST = '$REDSHIFT_HOST' - # Blocpower auth information. HEADER_AUTH_KEY = 'x-blocpower-auth-key' HEADER_AUTH_TOKEN = 'x-blocpower-auth-token' diff --git a/app/config/production.default.py b/app/config/production.default.py index a1d8c8773548b3b1e22c77e155ec960edbbdad2e..b0beed63fe87bd864dd968c8fdf8b9697bf4fc9d 100644 --- a/app/config/production.default.py +++ b/app/config/production.default.py @@ -3,6 +3,7 @@ import os SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_DATABASE_URI = os.environ['DBURI'] +REDSHIFT_DATABASE_URI = os.environ['REDSHIFT_DATABASE_URI'] REDIS_URI = os.environ['REDISURI'] @@ -32,11 +33,6 @@ AUTH0_CLAIMS_NAMESPACE = os.environ['AUTH0_CLAIMS_NAMESPACE'] AUTH0_CLIENT_ID = os.environ['AUTH0_CLIENT_ID'] AUTH0_CLIENT_SECRET = os.environ['AUTH0_CLIENT_SECRET'] -REDSHIFT_DB_NAME = os.environ['REDSHIFT_DB_NAME'] -REDSHIFT_USER = os.environ['REDSHIFT_USER'] -REDSHIFT_PASSWORD = os.environ['REDSHIFT_PASSWORD'] -REDSHIFT_HOST = os.environ['REDSHIFT_HOST'] - # Blocpower auth information. HEADER_AUTH_KEY = 'x-blocpower-auth-key' HEADER_AUTH_TOKEN = 'x-blocpower-auth-token' diff --git a/app/config/staging.default.py b/app/config/staging.default.py index 86482c6404f5f332ecb4cecc57d9ae74477461e4..1e5d971a59f6d493faf565d30fd63e02490bbe34 100644 --- a/app/config/staging.default.py +++ b/app/config/staging.default.py @@ -3,6 +3,7 @@ import os SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_DATABASE_URI = os.environ['DBURI'] +REDSHIFT_DATABASE_URI = os.environ['REDSHIFT_DATABASE_URI'] REDIS_URI = os.environ['REDISURI'] @@ -32,11 +33,6 @@ AUTH0_CLAIMS_NAMESPACE = os.environ['AUTH0_CLAIMS_NAMESPACE'] AUTH0_CLIENT_ID = os.environ['AUTH0_CLIENT_ID'] AUTH0_CLIENT_SECRET = os.environ['AUTH0_CLIENT_SECRET'] -REDSHIFT_DB_NAME = os.environ['REDSHIFT_DB_NAME'] -REDSHIFT_USER = os.environ['REDSHIFT_USER'] -REDSHIFT_PASSWORD = os.environ['REDSHIFT_PASSWORD'] -REDSHIFT_HOST = os.environ['REDSHIFT_HOST'] - # Blocpower auth information. HEADER_AUTH_KEY = 'x-blocpower-auth-key' HEADER_AUTH_TOKEN = 'x-blocpower-auth-token' diff --git a/app/controllers/apartment_node.py b/app/controllers/apartment_node.py deleted file mode 100644 index 84404b4e2dc17f13014f278d64d4dc0a51011358..0000000000000000000000000000000000000000 --- a/app/controllers/apartment_node.py +++ /dev/null @@ -1,14 +0,0 @@ -from .base import RestController -from ..forms.apartment_node import ApartmentNodeForm -from ..models.apartment_node import ApartmentNode - -class ApartmentNodeController(RestController): - """An apartment node controller.""" - Model = ApartmentNode - filters = { - 'parent_id': lambda d: ApartmentNode.parent_id == d['parent_id'], - } - - def get_form(self, filter_data): - """Return the apartment node form.""" - return ApartmentNodeForm diff --git a/app/controllers/boiler_node.py b/app/controllers/boiler_node.py deleted file mode 100644 index f1c87df8ab29bab60fbfb1e980021eb7a1c4c409..0000000000000000000000000000000000000000 --- a/app/controllers/boiler_node.py +++ /dev/null @@ -1,14 +0,0 @@ -from .base import RestController -from ..forms.boiler_node import BoilerNodeForm -from ..models.boiler_node import BoilerNode - -class BoilerNodeController(RestController): - """A boiler node controller.""" - Model = BoilerNode - filters = { - 'parent_id': lambda d: BoilerNode.parent_id == d['parent_id'], - } - - def get_form(self, filter_data): - """Return the boiler node form.""" - return BoilerNodeForm diff --git a/app/controllers/data.py b/app/controllers/data.py index 04ad7bf70d84a8283e36df09683f1c4de12aeb1e..5b9c6cc2f89a817244ada3e931e18a057082ff8a 100644 --- a/app/controllers/data.py +++ b/app/controllers/data.py @@ -29,7 +29,7 @@ class DataController(RestController): where_tuple = where_tuple + (node_module_number,) where_statement = where_statement[:-4] + ')' - sql = "SELECT * FROM data {}".format(where_statement) + sql = "SELECT ts, value, unit, unit_id, name, sn, mod FROM data {} ORDER BY ts".format(where_statement) cur = self.redshift.db.cursor(cursor_factory=psycopg2.extras.DictCursor) try: cur.execute(sql, where_tuple) diff --git a/app/controllers/gateway.py b/app/controllers/gateway.py index f668e1bb9d877280d49970fa597d4c9827ad9df4..f1e706cb004db665c4008b5292060ec720da7b31 100644 --- a/app/controllers/gateway.py +++ b/app/controllers/gateway.py @@ -2,6 +2,7 @@ from .base import RestController from ..forms.gateway import GatewayForm from ..models.gateway import Gateway from ..controllers.data import DataController +from ..controllers.senseware_node import SensewareNodeController import datetime import json import psycopg2 @@ -25,24 +26,37 @@ class GatewayController(RestController): """ result = super().index(filter_data) # If the user is also requesting data, get data - if 'data' in filter_data and 'from' in filter_data and result: - date = filter_data.get('from') - args = [('gateway_serial[]', gateway['gateway_serial']) for gateway in result] - args.append(('from', date)) - multi_dict_args = MultiDict(args) - data_result = DataController().index(multi_dict_args) - - # Map data to gateway serial numbers - data_mapping = {} - for record in data_result: - if record['sn'] not in data_mapping: - data_mapping[record['sn']] = [] - data_mapping[record['sn']].append(record) - # Add the data to the gateways + if 'nodes' in filter_data and result: + node_ids = [] for gateway in result: - if gateway['gateway_serial'] in data_mapping: - gateway['data'] = data_mapping[gateway['gateway_serial']] - else: - gateway['data'] = [] + multi_dict_args = MultiDict([('gateway_id', gateway['id'])]) + node_result = SensewareNodeController().index(multi_dict_args) + for node in node_result: + if (node['node_id']): + node_ids.append(node['node_id']) + gateway['nodes'] = node_result + + if 'data' in filter_data and 'from' in filter_data and result: + date = filter_data.get('from') + args = [('node_id[]', node_id) for node_id in node_ids] + data_mapping = {} + # Continue if any of the gateways have serials + if args: + args.append(('from', date)) + multi_dict_args = MultiDict(args) + data_result = DataController().index(multi_dict_args) + # Map data to gateway serial numbers + for record in data_result: + key = str(record['mod']) + if key not in data_mapping: + data_mapping[key] = [] + data_mapping[key].append(record) + # Add the data to the nodes + for gateway in result: + for node in gateway['nodes']: + if node['node_id'] in data_mapping: + node['data'] = data_mapping[node['node_id']] + else: + node['data'] = [] return result diff --git a/app/controllers/repeater_node.py b/app/controllers/repeater_node.py deleted file mode 100644 index 8cd4825d26c864108a6e6247b44475ff381d6010..0000000000000000000000000000000000000000 --- a/app/controllers/repeater_node.py +++ /dev/null @@ -1,14 +0,0 @@ -from .base import RestController -from ..forms.repeater_node import RepeaterNodeForm -from ..models.repeater_node import RepeaterNode - -class RepeaterNodeController(RestController): - """A repeater node controller.""" - Model = RepeaterNode - filters = { - 'parent_id': lambda d: RepeaterNode.parent_id == d['parent_id'], - } - - def get_form(self, filter_data): - """Return the repeater node form.""" - return RepeaterNodeForm diff --git a/app/controllers/senseware_node.py b/app/controllers/senseware_node.py new file mode 100644 index 0000000000000000000000000000000000000000..4257ce3980e8dd7aa86c9d53acc09fcfc9a30b36 --- /dev/null +++ b/app/controllers/senseware_node.py @@ -0,0 +1,14 @@ +from .base import RestController +from ..forms.senseware_node import SensewareNodeForm +from ..models.senseware_node import SensewareNode + +class SensewareNodeController(RestController): + """A senseware node controller.""" + Model = SensewareNode + filters = { + 'gateway_id': lambda d: SensewareNode.gateway_id == d['gateway_id'], + } + + def get_form(self, filter_data): + """Return the senseware node form.""" + return SensewareNodeForm diff --git a/app/forms/apartment_node.py b/app/forms/apartment_node.py deleted file mode 100644 index ca61f8450d6db9af3d718522f97d4d6cb6653756..0000000000000000000000000000000000000000 --- a/app/forms/apartment_node.py +++ /dev/null @@ -1,45 +0,0 @@ -import wtforms as wtf -from .base import Form, UserForm - -class ApartmentNodeForm(Form, UserForm): - """ A form for validating apartment node requests.""" - - id = wtf.IntegerField( - validators=[wtf.validators.Optional()] - ) - parent_id = wtf.IntegerField( - validators=[wtf.validators.Required()] - ) - node_id = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - node_location = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - apartment_number = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - apartment_floor = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - number_of_bedrooms = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - tenant_name = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - tenant_contact = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - apartment_orientation = wtf.IntegerField( - validators=[wtf.validators.Optional()] - ) - node_wall_type = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - tenant_heating_issue = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - notes = wtf.StringField( - validators=[wtf.validators.Optional()] - ) diff --git a/app/forms/boiler_node.py b/app/forms/boiler_node.py deleted file mode 100644 index 8350a897af00ea81879e193b4ead3ec4bbe1dea7..0000000000000000000000000000000000000000 --- a/app/forms/boiler_node.py +++ /dev/null @@ -1,33 +0,0 @@ -import wtforms as wtf -from .base import Form, UserForm - -class BoilerNodeForm(Form, UserForm): - """ A form for validating boiler node requests.""" - - id = wtf.IntegerField( - validators=[wtf.validators.Optional()] - ) - parent_id = wtf.IntegerField( - validators=[wtf.validators.Required()] - ) - node_id = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - node_location = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - temperature_probe_1 = wtf.IntegerField( - validators=[wtf.validators.Optional()] - ) - temperature_probe_2 = wtf.IntegerField( - validators=[wtf.validators.Optional()] - ) - temperature_probe_3 = wtf.IntegerField( - validators=[wtf.validators.Optional()] - ) - temperature_probe_4 = wtf.IntegerField( - validators=[wtf.validators.Optional()] - ) - notes = wtf.StringField( - validators=[wtf.validators.Optional()] - ) diff --git a/app/forms/repeater_node.py b/app/forms/repeater_node.py deleted file mode 100644 index d3c7835c1b79a791177956df63cec858569f25b3..0000000000000000000000000000000000000000 --- a/app/forms/repeater_node.py +++ /dev/null @@ -1,24 +0,0 @@ -import wtforms as wtf -from .base import Form, UserForm - -class RepeaterNodeForm(Form, UserForm): - """ A form for validating repeater node requests.""" - - id = wtf.IntegerField( - validators=[wtf.validators.Optional()] - ) - parent_id = wtf.IntegerField( - validators=[wtf.validators.Required()] - ) - node_id = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - node_location = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - apartment_floor = wtf.StringField( - validators=[wtf.validators.Optional()] - ) - notes = wtf.StringField( - validators=[wtf.validators.Optional()] - ) diff --git a/app/forms/senseware_node.py b/app/forms/senseware_node.py new file mode 100644 index 0000000000000000000000000000000000000000..98b278e67566aeb5b52685c4fd0d0ced2c406110 --- /dev/null +++ b/app/forms/senseware_node.py @@ -0,0 +1,56 @@ +import wtforms as wtf +from .base import Form, UserForm + +class NullableIntegerField(wtf.IntegerField): + """ + An IntegerField where the field can be null if the input data is an empty + string. + """ + + def process_formdata(self, valuelist): + if valuelist: + if valuelist[0] == '' or valuelist[0] is None: + self.data = None + else: + try: + self.data = int(valuelist[0]) + except ValueError: + self.data = None + raise ValueError(self.gettext('Not a valid integer value')) + +class SensewareNodeForm(Form, UserForm): + """ A form for validating senseware node requests.""" + + id = wtf.IntegerField( + validators=[wtf.validators.Optional()] + ) + gateway_id = wtf.IntegerField( + validators=[wtf.validators.Required()] + ) + node_id = wtf.StringField( + validators=[wtf.validators.Optional()] + ) + space_id = NullableIntegerField( + validators=[wtf.validators.Optional()] + ) + repeater = wtf.BooleanField( + validators=[wtf.validators.Optional()] + ) + surface_type = wtf.StringField( + validators=[wtf.validators.Optional()] + ) + temperature_probe_1 = NullableIntegerField( + validators=[wtf.validators.Optional()] + ) + temperature_probe_2 = NullableIntegerField( + validators=[wtf.validators.Optional()] + ) + temperature_probe_3 = NullableIntegerField( + validators=[wtf.validators.Optional()] + ) + temperature_probe_4 = NullableIntegerField( + validators=[wtf.validators.Optional()] + ) + notes = wtf.StringField( + validators=[wtf.validators.Optional()] + ) diff --git a/app/lib/redshift_database.py b/app/lib/redshift_database.py index f118c19e804169618c3cb5c308d67e66ed77d7dd..d5409f240ecfd8c0c3cc0576c91c95fb17880a4d 100644 --- a/app/lib/redshift_database.py +++ b/app/lib/redshift_database.py @@ -1,26 +1,24 @@ +from urllib.parse import urlparse import psycopg2 + class RedshiftWrapper(object): """A wrapper for Redshift.""" db = None def init_app(self, app): """Stores information about the redis database from the URI.""" - REDSHIFT_DB_NAME = app.config.get('REDSHIFT_DB_NAME') - REDSHIFT_USER = app.config.get('REDSHIFT_USER') - REDSHIFT_PASSWORD = app.config.get('REDSHIFT_PASSWORD') - REDSHIFT_HOST = app.config.get('REDSHIFT_HOST') - conn_string = """ - dbname='{}' - port='5439' - user='{}' - password='{}' - host='{}' - """.format(REDSHIFT_DB_NAME, REDSHIFT_USER, REDSHIFT_PASSWORD, REDSHIFT_HOST) - self.db = psycopg2.connect(conn_string) + uri = urlparse(app.config.get('REDSHIFT_DATABASE_URI')) + + self.db = psycopg2.connect( + user=uri.username, + password=uri.password, + host=uri.hostname, + port=5439, + dbname=uri.path[1:] + ) redshift = RedshiftWrapper() def register(app): redshift.init_app(app) - diff --git a/app/models/apartment_node.py b/app/models/apartment_node.py deleted file mode 100644 index 7c134b4f4a62f9d26583534b040438c5f4479c25..0000000000000000000000000000000000000000 --- a/app/models/apartment_node.py +++ /dev/null @@ -1,25 +0,0 @@ -from .base import Model, Tracked, User -from ..lib.database import db - -from sqlalchemy.ext.declarative import declared_attr - -class ApartmentNode(Model, Tracked, User, db.Model): - - @declared_attr - def __tablename__(cls): - return "apartment_node" - - __table_args__ = {"schema": "sensor"} - - parent_id = db.Column(db.Integer) - node_id = db.Column(db.Integer) - node_location = db.Column(db.Unicode(100)) - apartment_number = db.Column(db.Unicode(10)) - apartment_floor = db.Column(db.Unicode(10)) - number_of_bedrooms = db.Column(db.Unicode(10)) - tenant_name = db.Column(db.Unicode(50)) - tenant_contact = db.Column(db.Unicode(100)) - apartment_orientation = db.Column(db.Integer) - node_wall_type = db.Column(db.Unicode(50)) - tenant_heating_issue = db.Column(db.Unicode(50)) - notes = db.Column(db.Unicode(500)) diff --git a/app/models/repeater_node.py b/app/models/repeater_node.py deleted file mode 100644 index 301180afa23b167f702e9597d54194b1e35c47d0..0000000000000000000000000000000000000000 --- a/app/models/repeater_node.py +++ /dev/null @@ -1,18 +0,0 @@ -from .base import Model, Tracked, User -from ..lib.database import db - -from sqlalchemy.ext.declarative import declared_attr - -class RepeaterNode(Model, User, Tracked, db.Model): - - @declared_attr - def __tablename__(cls): - return "repeater_node" - - __table_args__ = {"schema": "sensor"} - - parent_id = db.Column(db.Integer) - node_id = db.Column(db.Unicode(30)) - node_location = db.Column(db.Unicode(100)) - apartment_floor = db.Column(db.Unicode(100)) - notes = db.Column(db.Unicode(500)) diff --git a/app/models/boiler_node.py b/app/models/senseware_node.py similarity index 66% rename from app/models/boiler_node.py rename to app/models/senseware_node.py index dd76224aaab99c9f111d677256012070771ff1e9..95e7f48189e6a7e1e389c0b52405c8d8d0bbf5bf 100644 --- a/app/models/boiler_node.py +++ b/app/models/senseware_node.py @@ -3,17 +3,19 @@ from ..lib.database import db from sqlalchemy.ext.declarative import declared_attr -class BoilerNode(Model, User, Tracked, db.Model): +class SensewareNode(Model, User, Tracked, db.Model): @declared_attr def __tablename__(cls): - return "boiler_node" + return "senseware_node" __table_args__ = {"schema": "sensor"} - parent_id = db.Column(db.Integer) + gateway_id = db.Column(db.Integer) node_id = db.Column(db.Unicode(30)) - node_location = db.Column(db.Unicode(100)) + space_id = db.Column(db.Integer) + repeater = db.Column(db.Boolean()) + surface_type = db.Column(db.Unicode(50)) temperature_probe_1 = db.Column(db.Integer) temperature_probe_2 = db.Column(db.Integer) temperature_probe_3 = db.Column(db.Integer) diff --git a/app/views/__init__.py b/app/views/__init__.py index 80bafc5409aeddb378daec69936ef467bcaac340..31c75ccf513996cd379523fe9f2745b4e83e7be2 100644 --- a/app/views/__init__.py +++ b/app/views/__init__.py @@ -1,11 +1,9 @@ """Flask-classy views for the flask application.""" from . import ( gateway, - boiler_node, - apartment_node, - repeater_node, - sensor_image, + senseware_node, data, + sensor_image, ) def register(app): @@ -16,8 +14,6 @@ def register(app): in the application. """ gateway.GatewayView.register(app) - boiler_node.BoilerNodeView.register(app) - apartment_node.ApartmentNodeView.register(app) - repeater_node.RepeaterNodeView.register(app) - sensor_image.SensorImageView.register(app) + senseware_node.SensewareNodeView.register(app) data.DataView.register(app) + sensor_image.SensorImageView.register(app) diff --git a/app/views/apartment_node.py b/app/views/apartment_node.py deleted file mode 100644 index fa2466bbf524d69bb269cf638a0f5751c758201b..0000000000000000000000000000000000000000 --- a/app/views/apartment_node.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Views for working with accounts.""" -from .base import RestView -from ..controllers.apartment_node import ApartmentNodeController - -from flask import request - -class ApartmentNodeView(RestView): - """The apartment node view.""" - - def get_controller(self): - """Return an instance of the apartment node controller.""" - return ApartmentNodeController() diff --git a/app/views/boiler_node.py b/app/views/boiler_node.py deleted file mode 100644 index 1ac2aa105db38e96ffdc039ba42ed7fe6d559a30..0000000000000000000000000000000000000000 --- a/app/views/boiler_node.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Views for working with accounts.""" -from .base import RestView -from ..controllers.boiler_node import BoilerNodeController - -from flask import request - -class BoilerNodeView(RestView): - """The boiler node view.""" - - def get_controller(self): - """Return an instance of the boiler node controller.""" - return BoilerNodeController() diff --git a/app/views/repeater_node.py b/app/views/repeater_node.py deleted file mode 100644 index a491af4ed5cc4ab8163c17edb1dea19ba75fc9b9..0000000000000000000000000000000000000000 --- a/app/views/repeater_node.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Views for working with accounts.""" -from .base import RestView -from ..controllers.repeater_node import RepeaterNodeController - -from flask import request - -class RepeaterNodeView(RestView): - """The repeater node view.""" - - def get_controller(self): - """Return an instance of the repeater node controller.""" - return RepeaterNodeController() diff --git a/app/views/senseware_node.py b/app/views/senseware_node.py new file mode 100644 index 0000000000000000000000000000000000000000..972d32bc71a6cab305d29b923ba44928ec5d88ae --- /dev/null +++ b/app/views/senseware_node.py @@ -0,0 +1,12 @@ +"""Views for working with accounts.""" +from .base import RestView +from ..controllers.senseware_node import SensewareNodeController + +from flask import request + +class SensewareNodeView(RestView): + """The senseware node view.""" + + def get_controller(self): + """Return an instance of the senseware node controller.""" + return SensewareNodeController() diff --git a/requirements.txt b/requirements.txt index 7f1e1df547049b722a635b9af764ebe097680c24..29029e307451aa1b208f206a90e30fbeb7ef5a32 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ arrow==0.7.0 blessed==1.9.5 botocore==1.5.48 -git+ssh://git@github.com/Blocp/bpvalve.git@v1.3.0 +git+ssh://git@github.com/Blocp/bpvalve.git@v1.3.1 cement==2.4.0 colorama==0.3.3 docker-py==1.1.0