def process_hour_value(self, hour): day = DayModel.find_by_id(hour.day_id) after_datetime = (datetime.fromtimestamp(day.date_timestamp) + timedelta(hours=hour.hour)) before_datetime = (datetime.fromtimestamp(day.date_timestamp) + timedelta(hours=hour.hour + 1)) events = EventModel.filter(data_type=DataTypeEnum.WATER_USAGE.value, after_timestamp=after_datetime.timestamp(), before_timestamp=before_datetime.timestamp(), graph_id=2) total_water_usage = None if len(events) != 0 or datetime.now() > before_datetime: total_water_usage = 0 for event in events: usage = UsageModel.find_by_id(event.usage_id) if usage.consumption_type.is_water_per_hour(): if event.data == 'True': # @todo: This now ignores the fact that a usage can be spread out over multiple hours and # just adds it to the hour at wich the usage was initiated start = event.timestamp end = EventModel.find_next_false(event).timestamp duration_in_seconds = end - start duration_in_hours = duration_in_seconds / (60 * 60) total_water_usage += duration_in_hours * int(usage.consumption_amount) elif usage.consumption_type.is_water_per_usage(): total_water_usage += int(usage.consumption_amount) # is_final_value = before_datetime.timestamp() < datetime.now().timestamp() is_final_value = False if total_water_usage is not None: hour.update(total_water_usage, is_final_value)
def patch(self, usage_id, new_value): usage = UsageModel.find_by_id(usage_id) new_value = float(new_value) if usage.min_value > new_value or usage.max_value < new_value: return { "errors": Error( "New value does not fall within the expected range. ({} - {})" .format(usage.min_value, usage.max_value), "{} is outside of ({} - {})".format( new_value, usage.min_value, usage.max_value), 422, "").to_json() }, 422 print("url is: " + "{}/{}/{}".format( app.config['HOMELYNK_URI'], usage.external_item_id, new_value)) response = requests.get( url="{}/{}/{}".format(app.config['HOMELYNK_URI'], usage.external_item_id, int(new_value))) home_response = response.json() item = ItemModel.find_by_id(usage.item_id) item_in_json = item.to_json() fake_event = { 'last_use_timestamp': datetime.now().timestamp(), 'data_type': usage.unit.value, 'data': float(home_response["current_value"]), 'usage_id': usage.id } item_in_json['last_use'] = fake_event return item_in_json, 200
def get(self, item_id, usage_id): errors = validate(item_id=item_id, usage_id=usage_id) if len(errors) > 0: return {errors: [error.to_json() for error in errors]}, 404 usage = UsageModel.find_by_id(usage_id) return {"usage": usage.to_json()}, 200
def find_by_id(cls, item_id): item = cls.query.filter_by(id=item_id).first() if not item: return item item.usages = UsageModel.find_all_by_item_id(item.id) item.groups = ItemGroup.ItemGroupModel.find_groups_by_item_id(item.id) item.fill_status() return item
def find_all(cls): items = cls.query.all() for item in items: item.usages = UsageModel.find_all_by_item_id(item.id) item.groups = ItemGroup.ItemGroupModel.find_groups_by_item_id( item.id) item.fill_status() return items
def set_value(self, value): usage = UsageModel.find_by_id(self.usage_id) if value < usage.min_value or value > usage.max_value: return 'Given usage value does not fall without range ({} - {}). ({} given.)' \ .format(usage.min_value, usage.max_value, value), 500 else: self.value = value return self.to_json(), 200
def post(self, item_id): min_value = None max_value = None if 'external_item_id' in request.form.keys(): external_item_id = request.form['external_item_id'] consumption_type = request.form['consumption_type'] consumption_amount = int(request.form['consumption_amount']) address = request.form['address'] unit = request.form['unit'] if 'min_value' in request.form.keys(): min_value = request.form['min_value'] if 'max_value' in request.form.keys(): max_value = request.form['max_value'] else: request_data = json.loads(request.data) external_item_id = request_data['external_item_id'] consumption_type = request_data['consumption_type'] consumption_amount = int(request_data['consumption_amount']) address = request_data['address'] unit = request_data['unit'] if 'min_value' in request_data.keys(): min_value = request_data['min_value'] if 'max_value' in request_data.keys(): max_value = request_data['max_value'] errors = validate(item_id=item_id, usage_consumption_type=consumption_type, usage_consumption_amount=consumption_amount, usage_address=address, usage_unit=unit, usage_min_value=min_value, usage_max_value=max_value) if len(errors) > 0: return {"errors": [error.to_json() for error in errors]}, 422 consumption_type = UsageTypeEnum(consumption_type) unit = UnitEnum(unit) usage = UsageModel(item_id, external_item_id, consumption_type, consumption_amount, address, unit, min_value, max_value) usage.save_to_db() return usage.to_json(), 201
def patch(self, group_id, preset_id): errors = validate(group_id=group_id, preset_id=preset_id) if len(errors) > 0: return {"errors": [error.to_json for error in errors]}, 404 preset = PresetModel.find_by_id(preset_id) responses = [] for preset_action in preset.preset_actions: usage = UsageModel.find_by_id(preset_action.usage_id) response = requests.get(url="{}alias={}&value={}".format( app.config['HOMELYNK_URI'], usage.address, preset_action.value)) responses.append(response) print(responses) return "Request has been accepted.", 202
def put(self, item_id, usage_id): min_value = None max_value = None if 'external_item_id' in request.form.keys(): external_item_id = request.form['external_item_id'] consumption_type = request.form['consumption_type'] consumption_amount = int(request.form['consumption_amount']) address = request.form['address'] unit = request.form['unit'] if 'min_value' in request.form.keys(): min_value = request.form['min_value'] if 'max_value' in request.form.keys(): max_value = request.form['max_value'] else: request_data = json.loads(request.data) external_item_id = request_data['external_item_id'] consumption_type = request_data['consumption_type'] consumption_amount = int(request_data['consumption_amount']) address = request_data['address'] unit = request_data['unit'] if 'min_value' in request_data.keys(): min_value = request_data['min_value'] if 'max_value' in request_data.keys(): max_value = request_data['max_value'] errors = validate(item_id=item_id, usage_id=usage_id, usage_consumption_amount=consumption_amount, usage_consumption_type=consumption_type, usage_address=address, usage_unit=unit, usage_min_value=min_value, usage_max_value=max_value) if len(errors) > 0: return {"errors": [error.to_json() for error in errors]}, 404 usage = UsageModel.find_by_id(usage_id) usage = usage.update(external_item_id=external_item_id, consumption_type=consumption_type, consumption_amount=consumption_amount, address=address, unit=unit, min_value=min_value, max_value=max_value) return usage.to_json(), 202
def fill_status(self): last_event = None for usage in self.usages: event = EventModel.find_latest_by_usage_id(usage.id) if event is None: pass elif last_event is None: last_event = event elif last_event.timestamp > event: last_event = event if last_event is not None: usage = UsageModel.find_by_id(last_event.usage_id) self.last_use = { 'last_use_timestamp': last_event.timestamp, 'data_type': usage.unit.value, 'data': float(last_event.data), 'usage_id': last_event.usage_id }
def post(self): errors = [] if 'usage_id' in request.form.keys(): usage_id = request.form['usage_id'] data_type = request.form['data_type'] data = request.form['data'] else: request_data = json.loads(request.data) usage_id = request_data['usage_id'] data_type = request_data['data_type'] data = request_data['data'] usage = UsageModel.find_by_id(usage_id) if usage is None: errors.append( Error( "Cannot find usage with id: {}".format(usage_id), "UsageModel.find_by_id({}) returns None".format(usage_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) if UnitEnum.has_value(data_type): data_type = UnitEnum(data_type) else: errors.append( Error( '"{}" is not a valid unit type.'.format(data_type), "UnitEnum.has_value({}) returned False".format(data_type), 400, "https://en.wikipedia.org/wiki/HTTP_400")) if len(errors) > 0: all_errors_in_json = [error.to_json() for error in errors] return {"errors": all_errors_in_json}, 422 if usage.unit != data_type: error = Error( 'The unit type of the usage with id "{}" does not match the given "{}".' .format(usage_id, data_type), "usage.unit does not equal data_type.", 422, "https://en.wikipedia.org/wiki/HTTP_422") return {"errors": error.to_json()}, 422 event = EventModel(usage_id, data, round(datetime.now().timestamp())) event.save_to_db() return event.to_json(), 201
def delete(self, item_id, usage_id): errors = validate(item_id=item_id, usage_id=usage_id) if len(errors) > 0: return {"errors": [error.to_json() for error in errors]}, 422 usage = UsageModel.find_by_id(usage_id) usage.delete_from_db()
def test_usage_resource(): print("#################### TESTING USAGE RESOURCE ####################") # GETTING ALL USAGES print("TEST_1 --- GETTING ALL USAGES") uri = "usages" expected_result = { "usages": [] } expected_status = 200 test_get(uri, expected_result, expected_status) # POSTING ONE USAGE print("TEST_2 --- POSTING ONE USAGE") item_1 = send_get('items/1') usage_1_item_id = item_1['id'] usage_1_external_item_id = 1 usage_1_consumption_type = UsageTypeEnum.KILOWATT usage_1_consumption_amount = 5 usage_1_address = "http://127.0.0.1:5000/usages/1" usage_1_unit = UnitEnum.TOGGLE usage_1_min_value = 0 usage_1_max_value = 1 usage_1 = UsageModel(usage_1_item_id, usage_1_external_item_id, usage_1_consumption_type, usage_1_consumption_amount, usage_1_address, usage_1_unit, usage_1_min_value, usage_1_max_value) body = { "item_id": usage_1_item_id, "external_item_id": usage_1_external_item_id, "consumption_type": usage_1_consumption_type.value, "consumption_amount": usage_1_consumption_amount, "address": usage_1_address, "unit": "TOGGLE", "min_value": usage_1_min_value, "max_value": usage_1_max_value } usage_1_json = usage_1.to_json() usage_1_json['id'] = 1 usage_1_json['url'] = "127.0.0.1:5000/api/v1/usages/1" expected_result = usage_1_json expected_status = 201 uri = "usages" test_post(uri, body, expected_result, expected_status) # GETTING ALL USAGES print("TEST_3 --- GETTING ALL USAGES") uri = "usages" expected_result = { "usages": [usage_1_json] } expected_status = 200 test_get(uri, expected_result, expected_status) # GETTING ONE USAGE print("TEST_4 --- GETTING ONE USAGE") uri = "usages/1" expected_result = usage_1_json expected_status = 200 test_get(uri, expected_result, expected_status) # UPDATING ONE USAGE print("TEST_5 --- UPDATING ONE USAGE") uri = 'usages/1' expected_result = usage_1_json expected_result['address'] = '127.0.0.1:5000/api/usages/7' body = expected_result expected_status = 200 test_put(uri, body, expected_result, expected_status) usage_1_json['address'] = '127.0.0.1:5000/api/usages/7' # GETTING ONE USAGE print("TEST_6 --- GETTING ONE USAGE") uri = "usages/1" expected_result = usage_1_json expected_status = 200 test_get(uri, expected_result, expected_status) # POSTING ONE USAGE - BAD REQUEST print("TEST_7 --- POSTING ONE USAGE - BAD REQUEST") item_1 = send_get('items/1') usage_1_item_id = item_1['id'] usage_1_external_item_id = item_1['id'] usage_1_consumption_type = UsageTypeEnum.KILOWATT usage_1_consumption_amount = 5 usage_1_address = "http://127.0.0.1:5000/usage/1" usage_1_min_value = 0 usage_1_max_value = 1 body = { "item_id": usage_1_item_id, "external_item_id": usage_1_external_item_id, "consumption_type": usage_1_consumption_type.value, "consumption_amount": usage_1_consumption_amount, "address": usage_1_address, "unit": "FOGGLE", "min_value": usage_1_min_value, "max_value": usage_1_max_value } expected_result = {"errors": [Error( "{} is not a valid unit option.".format("FOGGLE"), "UnitEnum.has_value({}) returned False".format("FOGGLE"), 422, "https://en.wikipedia.org/wiki/HTTP_422").to_json()]} expected_status = 422 uri = "usages" test_post(uri, body, expected_result, expected_status) # POSTING ONE USAGE - BAD REQUEST print("TEST_8 --- POSTING ONE USAGE - BAD REQUEST") body['unit'] = usage_1_unit.value body['consumption_type'] = 'KILO WHAT?' expected_result = {"errors": [Error( "{} is not a valid consumption type.".format("KILO WHAT?"), "UsageTypeEnum.has_value({}) returned False".format("KILO WHAT?"), 422, "https://en.wikipedia.org/wiki/HTTP_422").to_json()]} expected_status = 422 uri = "usages" test_post(uri, body, expected_result, expected_status) # POSTING ONE USAGE - BAD REQUEST print("TEST_9 --- POSTING ONE USAGE - BAD REQUEST") body['consumption_type'] = usage_1_consumption_type.value body['address'] = '12' expected_result = {"errors": [Error( "Address must be at least 4 characters long.", "address was {} characters long".format(len(body['address'])), 422, "https://en.wikipedia.org/wiki/HTTP_422").to_json()]} expected_status = 422 uri = "usages" test_post(uri, body, expected_result, expected_status) # POSTING ONE USAGE - BAD REQUEST print("TEST_10 --- POSTING ONE USAGE - BAD REQUEST") body['address'] = "________________________________________________________________________________________" \ "________________________________________________________________________________________" \ "________________________________________________________________________________________" \ "________________________________________________________________________________________" \ "________________________________________________________________________________________" \ "________________________________________________________________________________________" \ "________________________________________________________________________________________" expected_result = {"errors": [Error( "Address cannot be longer than 255 characters.", "address was {} characters long".format(len(body['address'])), 422, "https://en.wikipedia.org/wiki/HTTP_422").to_json()]} expected_status = 422 uri = "usages" test_post(uri, body, expected_result, expected_status) # POSTING ONE USAGE - BAD REQUEST print("TEST_11 --- POSTING ONE USAGE - BAD REQUEST") body['address'] = usage_1_address body['consumption_amount'] = -1 expected_result = {"errors": [Error( "Consumption amount cannot be below 0.", "{} is below 0".format(-1), 422, "https://en.wikipedia.org/wiki/HTTP_422").to_json()]} expected_status = 422 uri = "usages" test_post(uri, body, expected_result, expected_status) # POSTING ONE USAGE - BAD REQUEST print("TEST_12 --- POSTING ONE USAGE - BAD REQUEST") body['consumption_amount'] = usage_1_consumption_amount body['min_value'] = None expected_result = {"errors": [Error( "If either min or max value is given, both should be given.", "Either min or max was None while the other was not.", 422, "https://en.wikipedia.org/wiki/HTTP_422").to_json()]} expected_status = 422 uri = "usages" test_post(uri, body, expected_result, expected_status) # POSTING ONE USAGE - BAD REQUEST print("TEST_13 --- POSTING ONE USAGE - BAD REQUEST") body['min_value'] = usage_1_min_value body['max_value'] = None expected_result = {"errors": [Error( "If either min or max value is given, both should be given.", "Either min or max was None while the other was not.", 422, "https://en.wikipedia.org/wiki/HTTP_422").to_json()]} expected_status = 422 uri = "usages" test_post(uri, body, expected_result, expected_status) # EXECUTING COMMAND - BAD REQUEST print("TEST 14 --- POSTING COMMAND - BAD REQUEST") body = {} uri = "usages/1/command/2" expected_result = {"errors": Error( "New value does not fall within the expected range. ({} - {})" .format(usage_1_json["min_value"], usage_1_json['max_value']), "{} is outside of ({} - {})".format(2, usage_1_json["min_value"], usage_1_json['max_value']), 422, "" ).to_json()} expected_status = 422 test_patch(uri, body, expected_result, expected_status) # POSTING ONE USAGE print("TEST_15 --- POSTING ONE USAGE") item_2 = send_get('items/2') usage_2_item_id = item_2['id'] usage_2_external_item_id = 1 usage_2_consumption_type = UsageTypeEnum.KILOWATT usage_2_consumption_amount = 5 usage_2_address = "http://127.0.0.1:5000/usages/2" usage_2_unit = UnitEnum.TOGGLE usage_2_min_value = 0 usage_2_max_value = 1 usage_2 = UsageModel(usage_2_item_id, usage_2_external_item_id, usage_2_consumption_type, usage_2_consumption_amount, usage_2_address, usage_2_unit, usage_2_min_value, usage_2_max_value) body = { "item_id": usage_2_item_id, "external_item_id": usage_2_external_item_id, "consumption_type": usage_2_consumption_type.value, "consumption_amount": usage_2_consumption_amount, "address": usage_2_address, "unit": "TOGGLE", "min_value": usage_2_min_value, "max_value": usage_2_max_value } usage_2_json = usage_2.to_json() usage_2_json['id'] = 2 usage_2_json['url'] = "127.0.0.1:5000/api/v1/usages/2" expected_result = usage_2_json expected_status = 201 uri = "usages" test_post(uri, body, expected_result, expected_status)
def find_by_id_without_groups(cls, item_id): item = cls.query.filter_by(id=item_id).first() item.usages = UsageModel.find_all_by_item_id(item_id) item.fill_status() return item
def seed_test_data(): # @todo this doesn't work yet print('Seeding...') if not ItemModel.find_by_id(1): items = [] # START CREATING ITEMS print('Creating items...') items.append(ItemModel('Heating', 'comment')) items.append(UsageModel(1, UsageTypeEnum.KILOWATT, 5, '127.0.0.1:5000/item/1', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('staande_lamp_1', 'staande lamp = beste lamp')) items.append(UsageModel(2, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/2', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('staande_lamp_2', 'staande lamp = beste lamp')) items.append(UsageModel(3, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/3', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('slaapkamer_verlichting', 'verlichting in de slaapkamer')) items.append(UsageModel(4, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/4', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('lamp_nachtkastje', 'lamp op nachtkastje')) items.append(UsageModel(5, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/5', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('toilet', 'toilet in badkamer')) items.append(UsageModel(6, UsageTypeEnum.WATER_PER_USAGE, 9, '127.0.0.1:5000/item/6', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('douche', 'douche')) items.append(UsageModel(7, UsageTypeEnum.WATER_PER_HOUR, 9, '127.0.0.1:5000/item/7', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('vaatwasser', '')) items.append(UsageModel(8, UsageTypeEnum.WATER_PER_USAGE, 10, '127.0.0.1:5000/item/8', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('wasmachine', '')) items.append(UsageModel(9, UsageTypeEnum.WATER_PER_USAGE, 13, '127.0.0.1:5000/item/9', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('droger', '')) items.append(UsageModel(10, UsageTypeEnum.KILOWATT, 9, '127.0.0.1:5000/item/10', UnitEnum(UnitEnum.TOGGLE), 0, 1)) items.append(ItemModel('badkamer verlichting', '')) items.append(UsageModel(11, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/11', UnitEnum(UnitEnum.TOGGLE), 0, 1)) # START CREATING GROUPS print('Creating groups...') items.append(GroupModel('Huiskamer', True)) items.append(GroupModel('Slaapkamer', True)) items.append(GroupModel('Badkamer', True)) items.append(GroupModel('Verlichting', False)) # START ADDING ITEMS TO GROUPS print('Assigning items to groups...') items.append(ItemGroupModel(2, 1)) items.append(ItemGroupModel(3, 1)) items.append(ItemGroupModel(8, 1)) items.append(ItemGroupModel(4, 2)) items.append(ItemGroupModel(5, 2)) items.append(ItemGroupModel(6, 3)) items.append(ItemGroupModel(7, 3)) items.append(ItemGroupModel(9, 3)) items.append(ItemGroupModel(10, 3)) items.append(ItemGroupModel(11, 3)) items.append(ItemGroupModel(2, 4)) items.append(ItemGroupModel(3, 4)) items.append(ItemGroupModel(4, 4)) items.append(ItemGroupModel(5, 4)) items.append(ItemGroupModel(11, 4)) items.append(GraphModel('AVERAGE_TEMPERATURE', DataTypeEnum(DataTypeEnum.TEMPERATURE))) items.append(GraphModel('AVERAGE_WATER_USAGE', DataTypeEnum(DataTypeEnum.WATER_USAGE))) print('inserting data into db, this may take a while...') current = 1 total = len(items) for item in items: print('{} out of {}'.format(current, total)) current += 1 item.save_to_db()
def get(self): all_usages = UsageModel.find_all() or [] all_in_json = [usage.to_json() for usage in all_usages] return {"usages": all_in_json}, 200
def __init__(self, name, comment): self.name = name self.comment = comment self.usages = UsageModel.find_all_by_item_id(self.id) self.fill_status() self.groups = ItemGroup.ItemGroupModel.find_groups_by_item_id(self.id)
def validate(**kwargs): errors = [] item = None usage = None group = None preset = None schedule = None scheduled_usage = None method = None if "method" in kwargs: method = kwargs.pop('method') # ITEM if "item_id" in kwargs: item_id = kwargs.pop("item_id") item = ItemModel.find_by_id(item_id) if item is None: errors.append( Error("Could not find item with id: {}".format(item_id), "ItemMode.find_by_id({}) returned None".format(item_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) if "item_name" in kwargs: item_name = kwargs.pop("item_name") if len(item_name) < 3: errors.append( Error("Name must be at least 3 characters long.", "Name parameter must be at least 3 characters long.", 400, "https://en.wikipedia.org/wiki/HTTP_400")) elif len(item_name) > 255: errors.append( Error("Name cannot be longer than 255 characters.", "Name parameter cannot be longer than 255 characters.", 400, "https://en.wikipedia.org/wiki/HTTP_400")) if "item_comment" in kwargs: item_comment = kwargs.pop('item_comment') if len(item_comment) > 255: errors.append( Error("Comment cannot be longer than 255 characters.", "Name parameter cannot be longer than 255 characters.", 400, "https://en.wikipedia.org/wiki/HTTP_400")) # USAGE if "usage_id" in kwargs: usage_id = kwargs.pop('usage_id') usage = UsageModel.find_by_id(usage_id) if usage is None: errors.append( Error( "Could not find usage with id: {}".format(usage_id), "UsageModel.find_by_id({}) returned None".format(usage_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) elif item is not None: if not item.has_usage(usage_id): errors.append( Error( "Item with id {} does not have usage with id: {}". format(item.id, usage_id), "UsageModel.find_by_id({}) returned None".format( usage_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) if "usage_value" in kwargs: usage_value = kwargs.pop("usage_value") if usage is None: pass elif usage_value < usage.min_value or usage_value > usage.max_value: errors.append( Error( "Given value is not in range of Usage values. ({} - {}) ({} given)" .format(usage.min_value, usage.max_value, usage_value), "value is not within range. ({} - {}) ({} given)".format( usage.min_value, usage.max_value, usage_value), 422, "https://en.wikipedia.org/wiki/HTTP_404")) if "usage_consumption_type" in kwargs: usage_consumption_type = kwargs.pop('usage_consumption_type') if not UsageTypeEnum.has_value(usage_consumption_type): errors.append( Error( "{} is not a valid consumption type.".format( usage_consumption_type), "UsageTypeEnum.has_value({}) returned False".format( usage_consumption_type), 422, "https://en.wikipedia.org/wiki/HTTP_422")) if "usage_unit" in kwargs: usage_unit = kwargs.pop('usage_unit') if not UnitEnum.has_value(usage_unit): errors.append( Error( "{} is not a valid unit option.".format(usage_unit), "UnitEnum.has_value({}) returned False".format(usage_unit), 422, "https://en.wikipedia.org/wiki/HTTP_422")) if "usage_address" in kwargs: usage_address = kwargs.pop('usage_address') if len(usage_address) < 3: errors.append( Error( "Address must be at least 4 characters long.", "address was {} characters long".format( len(usage_address)), 422, "https://en.wikipedia.org/wiki/HTTP_422")) if len(usage_address) > 255: errors.append( Error( "Address cannot be longer than 255 characters.", "address was {} characters long".format( len(usage_address)), 422, "https://en.wikipedia.org/wiki/HTTP_422")) if "usage_consumption_amount" in kwargs: usage_consumption_amount = kwargs.pop("usage_consumption_amount") if usage_consumption_amount < 0: errors.append( Error("Consumption amount cannot be below 0.", "{} is below 0".format(usage_consumption_amount), 422, "https://en.wikipedia.org/wiki/HTTP_422")) usage_min_value = None if "usage_min_value" in kwargs: usage_min_value = kwargs.pop("usage_min_value") usage_max_value = None if "usage_max_value" in kwargs: usage_max_value = kwargs.pop("usage_max_value") if (usage_min_value is None and usage_max_value is not None) or \ (usage_min_value is not None and usage_max_value is None): errors.append( Error("If either min or max value is given, both should be given.", "Either min or max was None while the other was not.", 422, "https://en.wikipedia.org/wiki/HTTP_422")) elif usage_min_value is not None and usage_max_value is not None: if usage_min_value > usage_max_value: errors.append( Error("Min value should be lower than max value", "min_value is higher than max_value", 422, "https://en.wikipedia.org/wiki/HTTP_422")) # GROUP if "group_id" in kwargs: group_id = kwargs.pop("group_id") group = GroupModel.find_by_id(group_id) if group is None: errors.append( Error( "Could not find group with id: {}".format(group_id), "GroupModel.find_by_id({}) returned None".format(group_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) if "group_name" in kwargs: group_name = kwargs.pop("group_name") if len(group_name) < 3: errors.append( Error("Name must be at least 3 characters long.", "Name parameter must be at least 3 characters long.", 400, "https://en.wikipedia.org/wiki/HTTP_400")) elif len(group_name) > 255: errors.append( Error("Name cannot be longer than 255 characters.", "Name parameter cannot be longer than 255 characters.", 400, "https://en.wikipedia.org/wiki/HTTP_400")) # PRESET if "preset_id" in kwargs: preset_id = kwargs.pop("preset_id") preset = PresetModel.find_by_id(preset_id) if preset is None: errors.append( Error( "Could not find preset with id: {}".format(preset_id), "PresetModel.find_by_id({}) returned None".format( preset_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) elif preset.group_id != group.id: errors.append( Error("The given group id did not match the presets group id", "preset.group_id != group.id", 422, "https://en.wikipedia.org/wiki/HTTP_422")) if "preset_name" in kwargs: preset_name = kwargs.pop("preset_name") if len(preset_name) < 3: errors.append( Error("Name must be at least 3 characters long.", "len(preset_name) < 3 returned True", 422, "https://en.wikipedia.org/wiki/HTTP_422")) if len(preset_name) > 30: errors.append( Error("Name cannot be longer than 30 characters.", "len(preset_name) > 30 returned True", 422, "https://en.wikipedia.org/wiki/HTTP_422")) # PRESET_ACTION if "preset_action_id" in kwargs: preset_action_id = kwargs.pop("preset_action_id") preset_action = PresetActionModel.find_by_id(preset_action_id) if preset_action is None: errors.append( Error( "Could not find preset action with id: {}".format( preset_action_id), "PresetActionModel.find_by_id({}) returned None".format( preset_action_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) elif preset is not None: if preset_action.preset_id != preset.id: errors.append( Error( "The given preset id did not match the presets actions preset id", "preset_action.preset_id != preset.id", 422, "https://en.wikipedia.org/wiki/HTTP_422")) # SCHEDULE if "schedule_id" in kwargs: schedule_id = kwargs.pop("schedule_id") schedule = ScheduleModel.find_by_id(schedule_id) if schedule is None: errors.append( Error( "Could not find schedule with id: ".format(schedule_id), "ScheduleModel.find_by_id({}) returned None".format( schedule_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) if "schedule_time" in kwargs: schedule_time = kwargs.pop("schedule_time") if len(schedule_time) != 8 or not datetime.strptime( schedule_time, "%H:%M:%S"): errors.append( Error( "Invalid time format given, expected format is: '12:00:00'", "Invalid time format, expected format is: '%H:%M:%S'", 422, "https://en.wikipedia.org/wiki/HTTP_422")) if "schedule_days" in kwargs: schedule_days = kwargs.pop("schedule_days") if len(schedule_days) < 1: errors.append( Error("No schedule days given.", "Expecting array of days", 422, "https://en.wikipedia.org/wiki/HTTP_422")) else: seen_values = [] for schedule_day in schedule_days: if int(schedule_day) < 0 or int(schedule_day) > 6: errors.append( Error( "day should be in range 0 - 6, {} given".format( int(schedule_day)), "day should be in range 0 - 6, {} given".format( int(schedule_day)), 422, "https://en.wikipedia.org/wiki/HTTP_422")) if schedule_day in seen_values: errors.append( Error("Duplicate day entry. {}".format(schedule_day), "Duplicate day entry. {}".format(schedule_day), 422, "https://en.wikipedia.org/wiki/HTTP_422")) seen_values.append(schedule_day) if "schedule_usages" in kwargs: schedule_usages = kwargs.pop("schedule_usages") if len(schedule_usages) < 1: errors.append( Error("No schedule usages given.", "Expecting array of usages", 422, "https://en.wikipedia.org/wiki/HTTP_422")) seen_values = [] for scheduled_usage in schedule_usages: if scheduled_usage['usage_id'] is None: errors.append( Error("Missing usage_id for a scheduled usage.", "Missing usage_id for a scheduled usage.", 422, "https://en.wikipedia.org/wiki/HTTP_422")) else: _usage = UsageModel.find_by_id(scheduled_usage['usage_id']) if _usage is None: errors.append( Error( "Could not find item with id: ".format(usage_id), "UsageModel.find_by_id({}) returned None".format( usage_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) else: scheduled_usage_value = scheduled_usage['value'] if scheduled_usage_value < _usage.min_value or scheduled_usage_value > _usage.max_value: errors.append( Error( "Given value is not in range of Usage values. ({} - {}) ({} given}" .format(_usage.min_value, _usage.max_value, scheduled_usage_value), "value is not within range. ({} - {}) ({} given}" .format(_usage.min_value, _usage.max_value, scheduled_usage_value), 422, "https://en.wikipedia.org/wiki/HTTP_404")) if scheduled_usage['usage_id'] in seen_values: errors.append( Error( "Duplicate usage entry. {}".format( scheduled_usage['usage_id']), "Duplicate usage entry. {}".format( scheduled_usage['usage_id']), 422, "https://en.wikipedia.org/wiki/HTTP_422")) seen_values.append(scheduled_usage['usage_id']) if "schedule_day_number" in kwargs: schedule_day_number = kwargs.pop("schedule_day_number") if schedule is None: pass else: for schedule_day in schedule.schedule_days: if schedule_day.day == schedule_day_number: errors.append( Error( "Given day ({}) is already being used by this schedule." .format(schedule_day_number), "Given day ({}) is already being used by this schedule." .format(schedule_day_number), 422, "https://en.wikipedia.org/wiki/HTTP_404")) if "schedule_day_id" in kwargs: schedule_day_id = kwargs.pop("schedule_day_id") schedule_day = ScheduleDayModel.find_by_id(schedule_day_id) if schedule_day is None: errors.append( Error( "Could not find schedule day with id: ".format( schedule_day_id), "ScheduleDayModel.find_by_id({}) returned None".format( schedule_day_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) if schedule is None: pass elif schedule.id != schedule_day.schedule_id: errors.append( Error( "The given schedule id did not match the days schedule id", "schedule.id != schedule_day.schedule_id", 422, "https://en.wikipedia.org/wiki/HTTP_422")) # SCHEDULED USAGE if "scheduled_usage_id" in kwargs: scheduled_usage_id = kwargs.pop("scheduled_usage_id") scheduled_usage = ScheduledUsageModel.find_by_id(scheduled_usage_id) if scheduled_usage is None: errors.append( Error( "Could not find scheduled usage with id: ".format( scheduled_usage_id), "ScheduledUsageModel.find_by_id({}) returned None".format( scheduled_usage_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) elif scheduled_usage.schedule_id != schedule.id: errors.append( Error( "The given schedule id did not match the scheduled usage schedule id", "scheduled_usage.schedule_id != schedule.id", 422, "https://en.wikipedia.org/wiki/HTTP_422")) if "scheduled_usage_value" in kwargs: scheduled_usage_value = kwargs.pop("scheduled_usage_value") if scheduled_usage is not None: _usage = UsageModel.find_by_id(scheduled_usage.usage_id) if _usage.min_value > scheduled_usage_value or _usage.max_value < scheduled_usage_value: errors.append( Error( "Given value is not in range of Usage values. ({} - {}) ({} given}" .format(_usage.min_value, _usage.max_value, scheduled_usage_value), "value is not within range. ({} - {}) ({} given}". format(_usage.min_value, _usage.max_value, scheduled_usage_value), 422, "https://en.wikipedia.org/wiki/HTTP_404")) # METHOD SPECIFIC if method == "GroupItemResource.get": if item is None or group is None: pass elif not item.is_in_this_group(group.id): errors.append( Error( "Item with id {} is not in group with id {}".format( item.id, group.id), "item.is_in_this_group({}) returned False".format( group.id), 422, "https://en.wikipedia.org/wiki/HTTP_422")) elif method == "GroupItemsResource.post": if item is None or group is None: pass elif item.is_in_this_group(group.id): errors.append( Error( "Item with id {} is already in group with id {}".format( item.id, group.id), "item is already in this group", 422, "https://en.wikipedia.org/wiki/HTTP_422")) elif group.is_module is True: if item.is_in_module(): errors.append( Error("Item cannot be in two different modules", "item.is_in_module() returned True", 422, "https://en.wikipedia.org/wiki/HTTP_422")) elif method == "GroupItemResource.delete": if item is None or group is None: pass elif not item.is_in_this_group(group.id): errors.append( Error( "Item with id {} is not in group with id {}".format( item.id, group.id), "item.is_in_this_group({}) returned False".format( group.id), 400, "https://en.wikipedia.org/wiki/HTTP_400")) elif method == "PresetActionsResource.post": if (group is not None) and (usage is not None): usage_is_in_group = False for item in group.items: if item.id == usage.item_id: usage_is_in_group = True if not usage_is_in_group: errors.append( Error( "The item that usage with id {} is attached to does not belong to group with id {}." .format(usage.id, group.id), "Usage is not in this group", 422, "https://en.wikipedia.org/wiki/HTTP_422")) elif method == "ScheduledUsagesResource.post": if schedule is None or usage is None: pass else: for scheduled_usage in schedule.scheduled_usages: if scheduled_usage.usage_id == usage.id: errors.append( Error( "Given usage id is already being used by this schedule", "usage id already in schedule", 422, "https://en.wikipedia.org/wiki/HTTP_422")) assert len(kwargs) == 0, kwargs return errors
def seed(): print('Seeding...') db.init_app(app) if not ItemModel.find_by_id(1): items = [] # START CREATING ITEMS print('Creating items...') items.append(ItemModel('Heating', 'comment')) items.append( UsageModel(1, 1, UsageTypeEnum.KILOWATT, 5, '127.0.0.1:5000/item/1', 'PERCENTAGE', 0, 1)) items.append(ItemModel('staande_lamp_1', 'staande lamp = beste lamp')) items.append( UsageModel(2, 2, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/5', 'TOGGLE', 0, 1)) items.append(ItemModel('staande_lamp_2', 'staande lamp = beste lamp')) items.append( UsageModel(3, 3, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/3', 'TOGGLE', 0, 1)) items.append( ItemModel('slaapkamer_verlichting', 'verlichting in de slaapkamer')) items.append( UsageModel(4, 4, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/4', 'TOGGLE', 0, 1)) items.append(ItemModel('lamp_nachtkastje', 'lamp op nachtkastje')) items.append( UsageModel(5, 5, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/5', 'TOGGLE', 0, 1)) items.append(ItemModel('toilet', 'toilet in badkamer')) items.append( UsageModel(6, 6, UsageTypeEnum.WATER_PER_USAGE, 9, '127.0.0.1:5000/item/6', 'TOGGLE', 0, 1)) items.append(ItemModel('douche', 'douche')) items.append( UsageModel(7, 7, UsageTypeEnum.WATER_PER_HOUR, 9, '127.0.0.1:5000/item/7', 'TOGGLE', 0, 1)) items.append(ItemModel('vaatwasser', '')) items.append( UsageModel(8, 8, UsageTypeEnum.WATER_PER_USAGE, 10, '127.0.0.1:5000/item/8', 'TOGGLE', 0, 1)) items.append(ItemModel('wasmachine', '')) items.append( UsageModel(9, 9, UsageTypeEnum.WATER_PER_USAGE, 13, '127.0.0.1:5000/item/9', 'TOGGLE', 0, 1)) items.append(ItemModel('droger', '')) items.append( UsageModel(10, 10, UsageTypeEnum.KILOWATT, 9, '127.0.0.1:5000/item/10', 'TOGGLE', 0, 1)) items.append(ItemModel('badkamer verlichting', '')) items.append( UsageModel(11, 11, UsageTypeEnum.KILOWATT, 1, '127.0.0.1:5000/item/11', 'TOGGLE', 0, 1)) # START CREATING GROUPS print('Creating groups...') items.append(GroupModel('Huiskamer', True)) items.append(GroupModel('Slaapkamer', True)) items.append(GroupModel('Badkamer', True)) items.append(GroupModel('Verlichting', False)) # START ADDING ITEMS TO GROUPS print('Assigning items to groups...') items.append(ItemGroupModel(2, 1)) items.append(ItemGroupModel(3, 1)) items.append(ItemGroupModel(8, 1)) items.append(ItemGroupModel(4, 2)) items.append(ItemGroupModel(5, 2)) items.append(ItemGroupModel(6, 3)) items.append(ItemGroupModel(7, 3)) items.append(ItemGroupModel(9, 3)) items.append(ItemGroupModel(10, 3)) items.append(ItemGroupModel(11, 3)) items.append(ItemGroupModel(2, 4)) items.append(ItemGroupModel(3, 4)) items.append(ItemGroupModel(4, 4)) items.append(ItemGroupModel(5, 4)) items.append(ItemGroupModel(11, 4)) # START CREATING GRAPHS items.append( GraphModel('AVERAGE_TEMPERATURE', DataTypeEnum.TEMPERATURE)) items.append( GraphModel('AVERAGE_WATER_USAGE', DataTypeEnum.WATER_USAGE)) # START CREATING EVENTS print('Creating events') till_date = datetime.now().timestamp() about_one_month = (60 * 60 * 24 * 30) from_date = till_date - about_one_month # make sure the timestamps are never in the future limit_time = lambda timestamp: timestamp if timestamp < till_date else till_date keep_going = True while keep_going: for i in range(0, random.randint(1, 4)): toilet_break_timestamp = ( datetime.fromtimestamp(from_date) + timedelta(hours=random.randint(5, 12), minutes=random.randint(0, 60), seconds=random.randint(0, 60))).timestamp() items.append( EventModel(6, 'True', limit_time(toilet_break_timestamp), 2)) for i in range(0, 4): daily_shower_start_timestamp = ( datetime.fromtimestamp(from_date) + timedelta(hours=random.randint(5, 12), minutes=random.randint(0, 60), seconds=random.randint(0, 60))).timestamp() items.append( EventModel(7, 'True', limit_time(daily_shower_start_timestamp), 2)) daily_shower_end_timestamp = ( datetime.fromtimestamp(daily_shower_start_timestamp) + timedelta(minutes=random.randint(5, 15), seconds=random.randint(0, 60))).timestamp() items.append( EventModel(7, 'False', limit_time(daily_shower_end_timestamp), 2)) for i in range(0, 24): if not keep_going: break for y in range(0, 10): if from_date > till_date: keep_going = False break temp = 0 if i in [1, 2, 3, 4, 5, 15]: temp = 15 elif i in [0, 14]: temp = 16 elif i in [6, 12, 24, 13]: temp = 18 elif i in [7, 8, 9, 17, 18, 19, 20, 21, 22]: temp = 21 elif i in [10, 23]: temp = 20 elif i in [11, 16]: temp = 19 items.append( EventModel(1, temp * random.uniform(0.9, 1.1), from_date, 1)) from_date += 6 * 60 print('inserting data into db, this may take a while...') current = 1 total = len(items) # one last flush of the toilet at the current timestamp items.append(EventModel(6, 'True', till_date, 2)) for item in items: print('{} out of {}'.format(current, total)) item.save_to_db() current += 1