diff --git a/Makefile b/Makefile index b3fcde44..461e40a6 100755 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ COMPOSE=docker compose -f dev/docker-compose.dev.yaml +COMPOSE_TEST=docker compose -f dev/docker-compose.test.yaml .DEFAULT_GOAL := wizard ## Run wizard @@ -17,6 +18,12 @@ run: $(COMPOSE) rm -f myelectricaldata_import python3 main.py action=run +## Connect to EnedisGateway container : DEV +run-test: + $(COMPOSE_TEST) stop myelectricaldata_import + $(COMPOSE_TEST) rm -f myelectricaldata_import + python3 main.py action=run env=test + ## Connect to EnedisGateway container : DEV run-production: $(COMPOSE) stop myelectricaldata_import diff --git a/app/VERSION b/app/VERSION index 7fdd8c2e..5c5455e5 100755 --- a/app/VERSION +++ b/app/VERSION @@ -1 +1 @@ -0.8.12-beta2 \ No newline at end of file +0.8.13-beta3 \ No newline at end of file diff --git a/app/main.py b/app/main.py index 4bd71936..74754793 100755 --- a/app/main.py +++ b/app/main.py @@ -165,6 +165,11 @@ def lock(): def gateway_status(): return Ajax().gateway_status() + @APP.route("/datatable//", methods=['GET']) + @APP.route("/datatable///", methods=['GET']) + def datatable(usage_point_id, measurement_direction): + return Ajax(usage_point_id).datatable(measurement_direction, request.args) + @APP.route("/configuration/", methods=['POST']) @APP.route("/configuration//", methods=['POST']) @@ -201,6 +206,11 @@ def import_data(usage_point_id, target): def reset_all_data(usage_point_id): return Ajax(usage_point_id).reset_all_data() + @APP.route("/delete/", methods=['GET']) + @APP.route("/delete//", methods=['GET']) + def delete_all_data(usage_point_id): + return Ajax(usage_point_id).delete_all_data() + @APP.route("/reset_gateway/", methods=['GET']) @APP.route("/reset_gateway//", methods=['GET']) diff --git a/app/models/ajax.py b/app/models/ajax.py index 8fbd33d5..0e184504 100755 --- a/app/models/ajax.py +++ b/app/models/ajax.py @@ -1,12 +1,16 @@ import __main__ as app -from dependencies import reformat_json -from models.jobs import Job +from datetime import datetime + +import pytz from models.config import get_version +from models.jobs import Job +from models.query_cache import Cache from models.query_daily import Daily -from models.query_power import Power from models.query_detail import Detail +from models.query_power import Power from models.query_status import Status -from models.query_cache import Cache + +utc = pytz.UTC class Ajax: @@ -15,6 +19,8 @@ def __init__(self, usage_point_id=None): self.db = app.DB self.application_path = app.APPLICATION_PATH self.usage_point_id = usage_point_id + self.date_format = "%Y-%m-%d" + self.date_format_detail = "%Y-%m-%d %H:%M:%S" if self.usage_point_id is not None: self.usage_point_config = self.db.get_usage_point(self.usage_point_id) if hasattr(self.usage_point_config, "token"): @@ -73,9 +79,42 @@ def reset_all_data(self): "notif": "Toutes les données ont été supprimées.", } + def delete_all_data(self): + app.LOG.title(f"[{self.usage_point_id}] Suppression de la consommation journalière.") + Daily( + headers=self.headers, + usage_point_id=self.usage_point_id, + ).delete() + app.LOG.title(f"[{self.usage_point_id}] Suppression de la puissance maximum journalière.") + Power( + headers=self.headers, + usage_point_id=self.usage_point_id, + ).delete() + app.LOG.title(f"[{self.usage_point_id}] Suppression de la consommation détaillée.") + Detail( + headers=self.headers, + usage_point_id=self.usage_point_id, + ).delete() + app.LOG.title(f"[{self.usage_point_id}] Suppression de la production journalière.") + Daily( + headers=self.headers, + usage_point_id=self.usage_point_id, + measure_type="production" + ).delete() + app.LOG.title(f"[{self.usage_point_id}] Suppression de la production détaillée.") + Detail( + headers=self.headers, + usage_point_id=self.usage_point_id, + measure_type="production" + ).delete() + return { + "error": "false", + "notif": "Toutes les données ont été supprimées.", + } + def reset_gateway(self): app.LOG.title(f"[{self.usage_point_id}] Reset du cache de la passerelle.") - return Cache(self.usage_point_id).reset() + return Cache(headers=self.headers, usage_point_id=self.usage_point_id).reset() def reset_data(self, target, date): result = {} @@ -86,11 +125,13 @@ def reset_data(self, target, date): usage_point_id=self.usage_point_id ).reset(date) elif target == "consumption_detail": + # date = date.replace("---", " ") + # date = date.replace("--", ":") app.LOG.title(f"[{self.usage_point_id}] Reset de la consommation détaillée du {date}:") result["consumption_detail"] = Detail( headers=self.headers, usage_point_id=self.usage_point_id - ).reset(date) + ).reset_daily(date) elif target == "consumption_max_power": app.LOG.title(f"[{self.usage_point_id}] Reset de la puissance maximum du {date}:") result["consumption_max_power"] = Power( @@ -105,12 +146,14 @@ def reset_data(self, target, date): measure_type="production" ).reset(date) elif target == "production_detail": + # date = date.replace("---", " ") + # date = date.replace("--", ":") app.LOG.title(f"[{self.usage_point_id}] Reset de la production détaillée du {date}:") result["production_detail"] = Detail( headers=self.headers, usage_point_id=self.usage_point_id, measure_type="production" - ).reset(date) + ).reset_daily(date) else: return { "error": "true", @@ -120,7 +163,7 @@ def reset_data(self, target, date): if result[target]: return { "error": "false", - "notif": f"Reset de la {target} journalière du {date}", + "notif": f'Reset de la "{target}" du {date}', "result": result[target] } else: @@ -147,6 +190,8 @@ def fetch(self, target, date): usage_point_id=self.usage_point_id, ).fetch(date) elif target == "consumption_detail": + # date = date.replace("---", " ") + # date = date.replace("--", ":") if hasattr(self.usage_point_config, "consumption_detail") and self.usage_point_config.consumption_detail: app.LOG.title(f"[{self.usage_point_id}] Importation de la consommation détaillée du {date}:") result["consumption_detail"] = Detail( @@ -162,6 +207,8 @@ def fetch(self, target, date): measure_type="production" ).fetch(date) elif target == "production_detail": + # date = date.replace("---", " ") + # date = date.replace("--", ":") if hasattr(self.usage_point_config, "production_detail") and self.usage_point_config.production_detail: app.LOG.title(f"[{self.usage_point_id}] Importation de la production détaillée du {date}:") result["production_detail"] = Detail( @@ -189,21 +236,31 @@ def fetch(self, target, date): data["result"]["event_date"] = result[target]["event_date"] return data else: - data = { - "error": "false", - "notif": f"Importation de la {target} journalière du {date}", - "result": { - "value": result[target]["value"], - "date": result[target]["date"], - "fail_count": 0 + if target in result and "value" in result[target]: + data = { + "error": "false", + "notif": f"Importation de la {target} journalière du {date}", + "result": { + "value": result[target]["value"], + "date": result[target]["date"], + "fail_count": 0 + } + } + if "event_date" in result[target]: + data["result"]["event_date"] = result[target]["event_date"] + else: + data = { + "error": "false", + "notif": f'Importation de la "{target}" du {date}', + "result": { + "value": 0, + "date": 0, + "fail_count": 0 + } } - } - if "event_date" in result[target]: - data["result"]["event_date"] = result[target]["event_date"] return data def blacklist(self, target, date): - # print(target) result = {} if target == "consumption": if hasattr(self.usage_point_config, "consumption") and self.usage_point_config.consumption: @@ -213,7 +270,8 @@ def blacklist(self, target, date): usage_point_id=self.usage_point_id, ).blacklist(date, True) elif target == "consumption_max_power": - if hasattr(self.usage_point_config, "consumption_max_power") and self.usage_point_config.consumption_max_power: + if hasattr(self.usage_point_config, + "consumption_max_power") and self.usage_point_config.consumption_max_power: app.LOG.title(f"[{self.usage_point_id}] Blacklist de la puissance maximum du {date}:") result["consumption_max_power"] = Power( headers=self.headers, @@ -271,7 +329,8 @@ def whitelist(self, target, date): usage_point_id=self.usage_point_id, ).blacklist(date, False) elif target == "consumption_max_power": - if hasattr(self.usage_point_config, "consumption_max_power") and self.usage_point_config.consumption_max_power: + if hasattr(self.usage_point_config, + "consumption_max_power") and self.usage_point_config.consumption_max_power: app.LOG.title(f"[{self.usage_point_id}] Whitelist de la puissance maximale journalière du {date}:") result["consumption_max_power"] = Power( headers=self.headers, @@ -359,3 +418,277 @@ def configuration(self, configs): app.CONFIG.set_usage_point_config(self.usage_point_id, key, value) app.DB.set_usage_point(self.usage_point_id, output) return output + + def datatable(self, measurement_direction, args): + recordsTotal = 0 + draw = int(args.get("draw")) + length = int(args.get("length")) + search = args.get("search[value]") + start_index = int(args.get("start")) + end_index = start_index + length + order_column = int(args.get("order[0][column]")) + order_dir = args.get("order[0][dir]") + all_data = [] + data = [] + if measurement_direction == "consumption": + recordsTotal = app.DB.get_daily_count(usage_point_id=self.usage_point_id, + measurement_direction="consumption") + col_spec = { + 0: "date", + 1: "value", + 2: "value", + 3: "fail_count", + 4: "cache", + 5: "import_clean", + 6: "blacklist", + } + all_data = app.DB.get_daily_datatable( + usage_point_id=self.usage_point_id, + order_column=col_spec[order_column], + order_dir=order_dir, + search=search, + measurement_direction="consumption") + data = self.datatable_daily(all_data, start_index, end_index, measurement_direction) + + elif measurement_direction == "consumption_detail": + recordsTotal = app.DB.get_detail_count(usage_point_id=self.usage_point_id, + measurement_direction="consumption") + col_spec = { + 0: "date", + 1: "date", + 2: "value", + 3: "value", + 4: "fail_count", + 5: "cache", + 6: "import_clean", + 7: "blacklist", + } + all_data = app.DB.get_detail_datatable( + usage_point_id=self.usage_point_id, + order_column=col_spec[order_column], + order_dir=order_dir, + search=search, + measurement_direction="consumption") + data = self.datatable_detail(all_data, start_index, end_index, measurement_direction) + + elif measurement_direction == "production": + recordsTotal = app.DB.get_daily_count(usage_point_id=self.usage_point_id, + measurement_direction="production") + col_spec = { + 0: "date", + 1: "value", + 2: "value", + 3: "fail_count", + 4: "cache", + 5: "import_clean", + 6: "blacklist", + } + all_data = app.DB.get_daily_datatable( + usage_point_id=self.usage_point_id, + order_column=col_spec[order_column], + order_dir=order_dir, + search=search, + measurement_direction="production") + data = self.datatable_daily(all_data, start_index, end_index, measurement_direction) + elif measurement_direction == "production_detail": + recordsTotal = app.DB.get_detail_count(usage_point_id=self.usage_point_id, + measurement_direction="production") + col_spec = { + 0: "date", + 1: "date", + 2: "value", + 3: "value", + 4: "fail_count", + 5: "cache", + 6: "import_clean", + 7: "blacklist", + } + all_data = app.DB.get_detail_datatable( + usage_point_id=self.usage_point_id, + order_column=col_spec[order_column], + order_dir=order_dir, + search=search, + measurement_direction="production") + data = self.datatable_detail(all_data, start_index, end_index, measurement_direction) + elif measurement_direction == "consumption_max_power": + recordsTotal = app.DB.get_daily_max_power_count(usage_point_id=self.usage_point_id) + col_spec = { + 0: "date", + 1: "date", + 2: "value", + 3: "value", + 4: "value", + 5: "fail_count", + 6: "cache", + 7: "import_clean", + 8: "blacklist", + } + all_data = app.DB.get_daily_max_power_datatable( + usage_point_id=self.usage_point_id, + order_column=col_spec[order_column], + order_dir=order_dir, + search=search) + data = self.datatable_max_power(all_data, start_index, end_index) + result = { + "draw": draw + 1, + "recordsTotal": recordsTotal, + "recordsFiltered": len(all_data), + "data": data + } + return result + + def datatable_button(self, measurement_direction, db_data): + date_text = db_data.date.strftime(self.date_format) + value = db_data.value + blacklist = db_data.blacklist + fail_count = db_data.fail_count + + btn_import = "" + btn_reset = "" + btn_blacklist = "" + btn_whitelist = "" + btn_import_disable = "" + btn_blacklist_disable = "" + + if fail_count == 0 and value > 0: + btn_import = "display:none" + btn_whitelist = "display:none" + btn_blacklist_disable = "datatable_button_disable" + elif blacklist == 1: + btn_blacklist = "display:none" + btn_reset = "display:none" + btn_import_disable = "datatable_button_disable" + else: + btn_reset = "display:none" + btn_whitelist = "display:none" + + cache_html = f""" +
+
+
+
+ """ + + blacklist_html = f""" +
+
+
+
+ """ + + btn = { + "cache": cache_html, + "blacklist": blacklist_html + } + return btn + + def datatable_daily(self, all_data, start_index, end_index, measurement_direction): + index = 0 + result = [] + for db_data in all_data: + if start_index <= index <= end_index: + date_text = db_data.date.strftime(self.date_format) + target = "daily" + # VALUE + conso_w = f"""
{db_data.value}
""" + conso_kw = f"""
{db_data.value / 1000}
""" + fail_count = f"""
{db_data.fail_count}
""" + # CACHE STATE + if db_data.fail_count == 0: + cache_state = f'
1
' + else: + cache_state = f'
0
' + day_data = [ + date_text, + conso_w, + conso_kw, + fail_count, + cache_state, + self.datatable_button(measurement_direction, db_data)["cache"], + self.datatable_button(measurement_direction, db_data)["blacklist"], + ] + result.append(day_data) + index = index + 1 + return result + + def datatable_detail(self, all_data, start_index, end_index, measurement_direction): + index = 0 + result = [] + for db_data in all_data: + if start_index <= index <= end_index: + # print(db_data) + date_text = db_data.date.strftime(self.date_format) + date_hour = db_data.date.strftime("%H:%M:%S") + target = "detail" + # VALUE + conso_w = f"""
{db_data.value}
""" + conso_kw = f"""
{db_data.value / 1000}
""" + fail_count = f"""
{db_data.fail_count}
""" + # CACHE STATE + if db_data.fail_count == 0: + cache_state = f'
1
' + else: + cache_state = f'
0
' + day_data = [ + date_text, + date_hour, + conso_w, + conso_kw, + fail_count, + cache_state, + self.datatable_button(measurement_direction, db_data)["cache"], + self.datatable_button(measurement_direction, db_data)["blacklist"], + ] + result.append(day_data) + index = index + 1 + return result + + def datatable_max_power(self, all_data, start_index, end_index): + index = 0 + result = [] + measurement_direction = "consumption_max_power" + event_date = "" + target = "daily" + contract = self.db.get_contract(self.usage_point_id) + if hasattr(contract, "subscribed_power") and contract.subscribed_power is not None: + max_power = int(contract.subscribed_power.split(' ')[0]) * 1000 + else: + max_power = 999000 + for db_data in all_data: + if start_index <= index <= end_index: + date_text = db_data.date.strftime(self.date_format) + ampere = f"{round(int(db_data.value) / 230, 2)}" + if isinstance(db_data.event_date, datetime): + event_date = db_data.event_date.strftime("%H:%M:%S") + # VALUE + if max_power <= int(db_data.value): + style = 'style="color:#FF0000; font-weight:bolder"' + elif (max_power * 90 / 100) <= db_data.value: + style = 'style="color:#FFB600; font-weight:bolder"' + else: + style = "" + data_text_event_date = f"""
{event_date}
""" + conso_w = f"""
{db_data.value}
""" + conso_kw = f"""
{db_data.value / 1000}
""" + conso_a = f"""
{ampere}
""" + fail_count = f"""
{db_data.fail_count}
""" + + # CACHE STATE + if db_data.fail_count == 0: + cache_state = f'
1
' + else: + cache_state = f'
0
' + day_data = [ + date_text, + data_text_event_date, + conso_w, + conso_kw, + conso_a, + fail_count, + cache_state, + self.datatable_button(measurement_direction, db_data)["cache"], + self.datatable_button(measurement_direction, db_data)["blacklist"], + ] + result.append(day_data) + index = index + 1 + return result diff --git a/app/models/database.py b/app/models/database.py index a1df1065..047d3acc 100644 --- a/app/models/database.py +++ b/app/models/database.py @@ -4,10 +4,6 @@ from datetime import datetime, timedelta from os.path import exists -from sqlalchemy import (create_engine, delete, inspect, select) -from sqlalchemy.orm import sessionmaker - -from config import MAX_IMPORT_TRY from db_schema import ( Config, Contracts, @@ -22,6 +18,10 @@ from dependencies import str2bool from models.config import get_version from models.log import Log +from sqlalchemy import (create_engine, delete, inspect, select, func, desc, asc) +from sqlalchemy.orm import sessionmaker + +from config import MAX_IMPORT_TRY LOG = Log() @@ -39,6 +39,8 @@ def __init__(self, path="/data"): self.lock_file = f"{self.path}/.lock" + self.yesterday = datetime.combine(datetime.now() - timedelta(days=1), datetime.max.time()) + # MIGRATE v7 to v8 if os.path.isfile(f"{self.path}/enedisgateway.db"): LOG.title_warning("Migration de l'ancienne base de données vers la nouvelle structure.") @@ -46,7 +48,7 @@ def __init__(self, path="/data"): def migratev7tov8(self): uri = f'sqlite:///{self.path}/enedisgateway.db' - engine = create_engine(uri, echo=False, query_cache_size=0) + engine = create_engine(uri, echo=True, query_cache_size=0) session = sessionmaker(engine)(autocommit=True, autoflush=True) for measurement_direction in ["consumption", "production"]: @@ -250,25 +252,25 @@ def set_usage_point(self, usage_point_id, data): else: production_price = 0 if ( - "consumption_price_base" in data - and data["consumption_price_base"] is not None - and data["consumption_price_base"] != "" + "consumption_price_base" in data + and data["consumption_price_base"] is not None + and data["consumption_price_base"] != "" ): consumption_price_base = data["consumption_price_base"] else: consumption_price_base = 0 if ( - "consumption_price_hc" in data - and data["consumption_price_hc"] is not None - and data["consumption_price_hc"] != "" + "consumption_price_hc" in data + and data["consumption_price_hc"] is not None + and data["consumption_price_hc"] != "" ): consumption_price_hc = data["consumption_price_hc"] else: consumption_price_hc = 0 if ( - "consumption_price_hp" in data - and data["consumption_price_hp"] is not None - and data["consumption_price_hp"] != "" + "consumption_price_hp" in data + and data["consumption_price_hp"] is not None + and data["consumption_price_hp"] != "" ): consumption_price_hp = data["consumption_price_hp"] else: @@ -621,6 +623,46 @@ def get_daily_all(self, usage_point_id, measurement_direction="consumption"): .order_by(table.date.desc()) ).all() + def get_daily_datatable(self, usage_point_id, order_column="date", order_dir="asc", search=None, + measurement_direction="consumption"): + if measurement_direction == "consumption": + table = ConsumptionDaily + relation = UsagePoints.relation_consumption_daily + else: + table = ProductionDaily + relation = UsagePoints.relation_production_daily + + sort = asc(order_column) if order_dir == "desc" else desc(order_column) + + if search is not None and search != "": + result = self.session.scalars(select(table) + .join(relation) + .where(UsagePoints.usage_point_id == usage_point_id) + .where((table.date.like(f"%{search}%")) | (table.value.like(f"%{search}%"))) + .where(table.date <= self.yesterday) + .order_by(sort) + ) + else: + result = self.session.scalars(select(table) + .join(relation) + .where(UsagePoints.usage_point_id == usage_point_id) + .where(table.date <= self.yesterday) + .order_by(sort) + ) + return result.all() + + def get_daily_count(self, usage_point_id, measurement_direction="consumption"): + if measurement_direction == "consumption": + table = ConsumptionDaily + relation = UsagePoints.relation_consumption_daily + else: + table = ProductionDaily + relation = UsagePoints.relation_production_daily + return self.session.scalars( + select([func.count()]).select_from(table).join(relation) + .where(UsagePoints.usage_point_id == usage_point_id) + ).one_or_none() + def get_daily_date(self, usage_point_id, date, measurement_direction="consumption"): unique_id = hashlib.md5(f"{usage_point_id}/{date}".encode('utf-8')).hexdigest() if measurement_direction == "consumption": @@ -840,6 +882,16 @@ def insert_daily(self, usage_point_id, date, value, blacklist=0, fail_count=0, ) ) + def reset_daily(self, usage_point_id, date=None, mesure_type="consumption"): + daily = self.get_daily_date(usage_point_id, date, mesure_type) + if daily is not None: + daily.value = 0 + daily.blacklist = 0 + daily.fail_count = 0 + return True + else: + return False + def delete_daily(self, usage_point_id, date=None, measurement_direction="consumption"): if measurement_direction == "consumption": table = ConsumptionDaily @@ -916,6 +968,45 @@ def get_detail_all(self, usage_point_id, begin=None, end=None, measurement_direc .order_by(table.date) ).all() + def get_detail_datatable(self, usage_point_id, order_column="date", order_dir="asc", search=None, + measurement_direction="consumption"): + if measurement_direction == "consumption": + table = ConsumptionDetail + relation = UsagePoints.relation_consumption_detail + else: + table = ProductionDetail + relation = UsagePoints.relation_production_detail + + sort = asc(order_column) if order_dir == "desc" else desc(order_column) + if search is not None and search != "": + result = self.session.scalars(select(table) + .join(relation) + .where(UsagePoints.usage_point_id == usage_point_id) + .where((table.date.like(f"%{search}%")) | (table.value.like(f"%{search}%"))) + .where(table.date <= self.yesterday) + .order_by(sort) + ) + else: + result = self.session.scalars(select(table) + .join(relation) + .where(UsagePoints.usage_point_id == usage_point_id) + .where(table.date <= self.yesterday) + .order_by(sort) + ) + return result.all() + + def get_detail_count(self, usage_point_id, measurement_direction="consumption"): + if measurement_direction == "consumption": + table = ConsumptionDetail + relation = UsagePoints.relation_consumption_detail + else: + table = ProductionDetail + relation = UsagePoints.relation_production_detail + return self.session.scalars( + select([func.count()]).select_from(table).join(relation) + .where(UsagePoints.usage_point_id == usage_point_id) + ).one_or_none() + def get_detail_date(self, usage_point_id, date, measurement_direction="consumption"): unique_id = hashlib.md5(f"{usage_point_id}/{date}".encode('utf-8')).hexdigest() if measurement_direction == "consumption": @@ -1050,6 +1141,31 @@ def insert_detail(self, usage_point_id, date, value, interval, measure_type, bla ) ) + def reset_detail(self, usage_point_id, date=None, mesure_type="consumption"): + detail = self.get_detail_date(usage_point_id, date, mesure_type) + if detail is not None: + detail.value = 0 + detail.interval = 0 + detail.blacklist = 0 + detail.fail_count = 0 + self.session.flush() + return True + else: + return False + + def reset_detail_range(self, usage_point_id, begin, end, mesure_type="consumption"): + detail = self.get_detail_range(usage_point_id, begin, end, mesure_type) + if detail is not None: + for row in detail: + row.value = 0 + row.interval = 0 + row.blacklist = 0 + row.fail_count = 0 + self.session.flush() + return True + else: + return False + def delete_detail(self, usage_point_id, date=None, mesure_type="consumption"): if mesure_type == "consumption": table = ConsumptionDetail @@ -1065,6 +1181,21 @@ def delete_detail(self, usage_point_id, date=None, mesure_type="consumption"): self.session.execute(delete(table).where(table.usage_point_id == usage_point_id)) return True + def delete_detail_range(self, usage_point_id, begin, end, mesure_type="consumption"): + if mesure_type == "consumption": + table = ConsumptionDetail + else: + table = ProductionDetail + if date is not None: + unique_id = hashlib.md5(f"{usage_point_id}/{date}".encode('utf-8')).hexdigest() + self.session.execute( + delete(table) + .where(table.id == unique_id) + ) + else: + self.session.execute(delete(table).where(table.usage_point_id == usage_point_id)) + return True + def get_ratio_hc_hp(self, usage_point_id, begin, end, mesure_type="consumption"): result = { "HC": 0, @@ -1279,6 +1410,31 @@ def insert_daily_max_power(self, usage_point_id, date, event_date, value, blackl ) ) + def get_daily_max_power_count(self, usage_point_id): + return self.session.scalars( + select([func.count()]).select_from(ConsumptionDailyMaxPower).join(UsagePoints.relation_consumption_daily_max_power) + .where(UsagePoints.usage_point_id == usage_point_id) + ).one_or_none() + + def get_daily_max_power_datatable(self, usage_point_id, order_column="date", order_dir="asc", search=None): + sort = asc(order_column) if order_dir == "desc" else desc(order_column) + if search is not None and search != "": + result = self.session.scalars(select(ConsumptionDailyMaxPower) + .join(UsagePoints.relation_consumption_daily_max_power) + .where(UsagePoints.usage_point_id == usage_point_id) + .where((ConsumptionDailyMaxPower.date.like(f"%{search}%")) | (ConsumptionDailyMaxPower.value.like(f"%{search}%"))) + .where(ConsumptionDailyMaxPower.date <= self.yesterday) + .order_by(sort) + ) + else: + result = self.session.scalars(select(ConsumptionDailyMaxPower) + .join(UsagePoints.relation_consumption_daily_max_power) + .where(UsagePoints.usage_point_id == usage_point_id) + .where(ConsumptionDailyMaxPower.date <= self.yesterday) + .order_by(sort) + ) + return result.all() + def daily_max_power_fail_increment(self, usage_point_id, date): unique_id = hashlib.md5(f"{usage_point_id}/{date}".encode('utf-8')).hexdigest() daily = self.get_daily_max_power_date(usage_point_id, date) @@ -1311,6 +1467,17 @@ def daily_max_power_fail_increment(self, usage_point_id, date): ) return fail_count + def reset_daily_max_power(self, usage_point_id, date=None): + daily = self.get_daily_max_power_date(usage_point_id, date) + if daily is not None: + daily.event_date = None + daily.value = 0 + daily.blacklist = 0 + daily.fail_count = 0 + return True + else: + return False + def delete_daily_max_power(self, usage_point_id, date=None): if date is not None: unique_id = hashlib.md5(f"{usage_point_id}/{date}".encode('utf-8')).hexdigest() @@ -1319,7 +1486,8 @@ def delete_daily_max_power(self, usage_point_id, date=None): .where(ConsumptionDailyMaxPower.id == unique_id) ) else: - self.session.execute(delete(ConsumptionDailyMaxPower).where(ConsumptionDailyMaxPower.usage_point_id == usage_point_id)) + self.session.execute( + delete(ConsumptionDailyMaxPower).where(ConsumptionDailyMaxPower.usage_point_id == usage_point_id)) return True def blacklist_daily_max_power(self, usage_point_id, date, action=True): @@ -1347,5 +1515,6 @@ def get_daily_max_power_fail_count(self, usage_point_id, date): else: return 0 + os.system("cd /app; alembic upgrade head") Database().init_database() diff --git a/app/models/jobs.py b/app/models/jobs.py index 7269d8fb..e99d0fe0 100644 --- a/app/models/jobs.py +++ b/app/models/jobs.py @@ -106,8 +106,8 @@ def job_import_data(self, wait=True, target=None): traceback.print_exc() LOG.error([f"Erreur lors de la récupération de votre production détaillée", e]) try: - # if target == "consumption_max_power" or target is None: - self.get_consumption_max_power() + if target == "consumption_max_power" or target is None: + self.get_consumption_max_power() except Exception as e: traceback.print_exc() LOG.error([f"Erreur lors de la récupération de votre puissance maximum journalière", e]) @@ -226,6 +226,7 @@ def job_import_data(self, wait=True, target=None): LOG.log( f" => Point de livraison Désactivé dans la configuration (Exemple: https://tinyurl.com/2kbd62s9).") LOG.finish() + self.usage_point_id = None DB.unlock() return { "status": True, diff --git a/app/models/log.py b/app/models/log.py index 8e03e5d8..d718f25b 100755 --- a/app/models/log.py +++ b/app/models/log.py @@ -32,7 +32,7 @@ def show(self, message): self.separator_warning() if type(message) is list: for msg in message: - pprint(f" {msg}") + pprint(f"{msg}") else: pprint(f" {message}") self.separator_warning() diff --git a/app/models/query_cache.py b/app/models/query_cache.py index 1ca4e387..effad4ac 100644 --- a/app/models/query_cache.py +++ b/app/models/query_cache.py @@ -22,6 +22,7 @@ def reset(self): target = f"{self.url}/cache/{self.usage_point_id}" response = Query(endpoint=target, headers=self.headers).delete() + print(response.text) if response.status_code == 200: try: status = json.loads(response.text) diff --git a/app/models/query_daily.py b/app/models/query_daily.py index 6768f0f7..77cdb634 100644 --- a/app/models/query_daily.py +++ b/app/models/query_daily.py @@ -1,17 +1,18 @@ import __main__ as app -import datetime import json +from datetime import datetime, timedelta + from dateutil.relativedelta import relativedelta from config import DAILY_MAX_DAYS, URL -from dependencies import * +# from dependencies import * from models.query import Query def daterange(start_date, end_date): for n in range(int((end_date - start_date).days)): - yield start_date + datetime.timedelta(n) + yield start_date + timedelta(n) class Daily: @@ -21,12 +22,13 @@ def __init__(self, headers, usage_point_id, measure_type="consumption"): self.url = URL self.max_daily = 1095 self.date_format = '%Y-%m-%d' + self.date_detail_format = '%Y-%m-%d %H:%M:%S' self.headers = headers self.usage_point_id = usage_point_id self.usage_point_config = self.db.get_usage_point(self.usage_point_id) self.contract = self.db.get_contract(self.usage_point_id) - self.daily_max_days = DAILY_MAX_DAYS - self.max_days_date = datetime.datetime.utcnow() - datetime.timedelta(days=self.daily_max_days) + self.daily_max_days = int(DAILY_MAX_DAYS) + self.max_days_date = datetime.utcnow() - timedelta(days=self.daily_max_days) if ( measure_type == "consumption" and hasattr(self.usage_point_config, "consumption_max_date") @@ -64,7 +66,7 @@ def run(self, begin, end): end_str = end.strftime(self.date_format) app.LOG.log(f"Récupération des données : {begin_str} => {end_str}") endpoint = f"daily_{self.measure_type}/{self.usage_point_id}/start/{begin_str}/end/{end_str}" - # if begin < datetime.datetime.now() - datetime.timedelta(days=7): + # if begin < now() - timedelta(days=7): if hasattr(self.usage_point_config, "cache") and self.usage_point_config.cache: endpoint += "/cache" try: @@ -78,10 +80,10 @@ def run(self, begin, end): else: app.LOG.log(f" => Chargement des données depuis MyElectricalData {begin_str} => {end_str}") data = Query(endpoint=f"{self.url}/{endpoint}/", headers=self.headers).get() - # print("----------------------") - # print(data.text) - # print("----------------------") blacklist = 0 + print("-----------------------------") + print(data.text) + print("-----------------------------") if hasattr(data, "status_code"): if data.status_code == 200: meter_reading = json.loads(data.text)['meter_reading'] @@ -94,7 +96,7 @@ def run(self, begin, end): # FOUND self.db.insert_daily( usage_point_id=self.usage_point_id, - date=datetime.datetime.combine(single_date, datetime.datetime.min.time()), + date=datetime.combine(single_date, datetime.min.time()), value=interval_reading_tmp[single_date.strftime(self.date_format)], blacklist=blacklist, measurement_direction=self.measure_type @@ -103,7 +105,7 @@ def run(self, begin, end): # NOT FOUND self.db.daily_fail_increment( usage_point_id=self.usage_point_id, - date=datetime.datetime.combine(single_date, datetime.datetime.min.time()), + date=datetime.combine(single_date, datetime.min.time()), measurement_direction=self.measure_type ) return interval_reading @@ -124,16 +126,10 @@ def run(self, begin, end): app.LOG.error(e) def get(self): - - # REMOVE TODAY - # end = datetime.datetime.combine((datetime.datetime.now() - datetime.timedelta(days=1)), datetime.datetime.max.time()) - end = datetime.datetime.combine((datetime.datetime.now()), datetime.datetime.max.time()) - # begin = datetime.datetime.combine(end - datetime.timedelta(days=self.max_daily), datetime.datetime.min.time()) - begin = datetime.datetime.combine(end - relativedelta(months=self.max_daily), datetime.datetime.min.time()) - + end = datetime.combine((datetime.now() + timedelta(days=2)), datetime.max.time()) + begin = datetime.combine(end - relativedelta(months=self.max_daily), datetime.min.time()) finish = True result = [] - while finish: if self.max_days_date > begin: # Max day reached @@ -167,22 +163,28 @@ def get(self): if "status_code" in response and (response["status_code"] == 409 or response["status_code"] == 400): finish = False error = ["Arrêt de la récupération des données suite à une erreur.", - f"Prochain lancement à {datetime.datetime.now() + datetime.timedelta(seconds=app.CONFIG.get('cycle'))}"] + f"Prochain lancement à {datetime.now() + timedelta(seconds=app.CONFIG.get('cycle'))}"] app.LOG.warning(error) return result def reset(self, date=None): if date is not None: - date = datetime.datetime.strptime(date, self.date_format) + date = datetime.strptime(date, self.date_format) + self.db.reset_daily(self.usage_point_id, date, self.measure_type) + return True + + def delete(self, date=None): + if date is not None: + date = datetime.strptime(date, self.date_format) self.db.delete_daily(self.usage_point_id, date, self.measure_type) return True def fetch(self, date): if date is not None: - date = datetime.datetime.strptime(date, self.date_format) + date = datetime.strptime(date, self.date_format) result = self.run( - date - datetime.timedelta(days=1), - date + datetime.timedelta(days=1), + datetime.combine(date - timedelta(days=2), datetime.min.time()), + datetime.combine(date + timedelta(days=2), datetime.min.time()), ) if "error" in result and result["error"]: return { @@ -201,6 +203,6 @@ def fetch(self, date): def blacklist(self, date, action): if date is not None: - date = datetime.datetime.strptime(date, self.date_format) + date = datetime.strptime(date, self.date_format) self.db.blacklist_daily(self.usage_point_id, date, action, self.measure_type) return True diff --git a/app/models/query_detail.py b/app/models/query_detail.py index b327bb19..00f39256 100644 --- a/app/models/query_detail.py +++ b/app/models/query_detail.py @@ -1,9 +1,9 @@ import __main__ as app -import datetime +from datetime import datetime, timedelta import json import re -from dependencies import * +# from dependencies import * from models.database import ConsumptionDetail, ProductionDetail from models.query import Query @@ -12,7 +12,7 @@ def daterange(start_date, end_date): for n in range(int((end_date - start_date).days)): - yield start_date + datetime.timedelta(n) + yield start_date + timedelta(n) class Detail: @@ -28,21 +28,21 @@ def __init__(self, headers, usage_point_id, measure_type="consumption"): self.usage_point_config = self.db.get_usage_point(self.usage_point_id) self.contract = self.db.get_contract(self.usage_point_id) self.daily_max_days = int(DETAIL_MAX_DAYS) - self.max_days_date = datetime.datetime.utcnow() - datetime.timedelta(days=self.daily_max_days) + self.max_days_date = datetime.utcnow() - timedelta(days=self.daily_max_days) if ( measure_type == "consumption" - and hasattr(self.usage_point_config, "consumption_max_date") - and self.usage_point_config.consumption_max_date != "" - and self.usage_point_config.consumption_max_date is not None + and hasattr(self.usage_point_config, "consumption_detail_max_date") + and self.usage_point_config.consumption_detail_max_date != "" + and self.usage_point_config.consumption_detail_max_date is not None ): - self.activation_date = self.usage_point_config.consumption_max_date + self.activation_date = self.usage_point_config.consumption_detail_max_date elif ( measure_type == "production" - and hasattr(self.usage_point_config, "production_max_date") - and self.usage_point_config.production_max_date != "" - and self.usage_point_config.production_max_date is not None + and hasattr(self.usage_point_config, "production_detail_max_date") + and self.usage_point_config.production_detail_max_date != "" + and self.usage_point_config.production_detail_max_date is not None ): - self.activation_date = self.usage_point_config.production_max_date + self.activation_date = self.usage_point_config.production_detail_max_date elif ( hasattr(self.contract, "last_activation_date") and self.contract.last_activation_date != "" @@ -72,16 +72,18 @@ def __init__(self, headers, usage_point_id, measure_type="consumption"): self.base_price = self.usage_point_config.production_price def run(self, begin, end): + if begin.strftime(self.date_format) == end.strftime(self.date_format): + end = end + timedelta(days=1) begin_str = begin.strftime(self.date_format) end_str = end.strftime(self.date_format) app.LOG.log(f"Récupération des données : {begin_str} => {end_str}") endpoint = f"{self.measure_type}_load_curve/{self.usage_point_id}/start/{begin_str}/end/{end_str}" - # if begin <= (datetime.datetime.now() - datetime.timedelta(days=8)): + # if begin <= (datetime.now() - timedelta(days=8)): if hasattr(self.usage_point_config, "cache") and self.usage_point_config.cache: endpoint += "/cache" try: current_data = self.db.get_detail(self.usage_point_id, begin, end, self.measure_type) - # current_week = datetime.datetime.now() - datetime.timedelta(days=self.max_detail + 1) + # current_week = datetime.now() - timedelta(days=self.max_detail + 1) # last_week = False # if current_week <= begin: # last_week = True @@ -95,7 +97,6 @@ def run(self, begin, end): else: app.LOG.log(f" => Chargement des données depuis MyElectricalData {begin_str} => {end_str}") data = Query(endpoint=f"{self.url}/{endpoint}/", headers=self.headers).get() - bulk_insert = [] if hasattr(data, "status_code"): if data.status_code == 200: meter_reading = json.loads(data.text)['meter_reading'] @@ -103,9 +104,9 @@ def run(self, begin, end): value = interval_reading["value"] interval = re.findall(r'\d+', interval_reading['interval_length'])[0] date = interval_reading["date"] - dateObject = datetime.datetime.strptime(date, self.date_detail_format) + dateObject = datetime.strptime(date, self.date_detail_format) # CHANGE DATE TO BEGIN RANGE - date = dateObject - datetime.timedelta(minutes=int(interval)) + date = dateObject - timedelta(minutes=int(interval)) # date = date.strftime(self.date_detail_format) # GET WEEKDAY dateDays = dateObject.weekday() @@ -117,12 +118,12 @@ def run(self, begin, end): if offpeak_hour != "None" and offpeak_hour != "" and offpeak_hour is not None: offpeak_begin = offpeak_hour.split("-")[0].replace('h', ':').replace('H', ':') # FORMAT HOUR WITH 2 DIGIT - offpeak_begin = datetime.datetime.strptime(offpeak_begin, '%H:%M') - offpeak_begin = datetime.datetime.strftime(offpeak_begin, '%H:%M') + offpeak_begin = datetime.strptime(offpeak_begin, '%H:%M') + offpeak_begin = datetime.strftime(offpeak_begin, '%H:%M') offpeak_stop = offpeak_hour.split("-")[1].replace('h', ':').replace('H', ':') # FORMAT HOUR WITH 2 DIGIT - offpeak_stop = datetime.datetime.strptime(offpeak_stop, '%H:%M') - offpeak_stop = datetime.datetime.strftime(offpeak_stop, '%H:%M') + offpeak_stop = datetime.strptime(offpeak_stop, '%H:%M') + offpeak_stop = datetime.strftime(offpeak_stop, '%H:%M') result = is_between(dateHourMinute, (offpeak_begin, offpeak_stop)) if result: measure_type = "HC" @@ -134,15 +135,6 @@ def run(self, begin, end): measure_type=measure_type, blacklist=0, ) - # bulk_insert.append(self.detail_table( - # usage_point_id=self.usage_point_id, - # date=date, - # value=value, - # interval=interval, - # measure_type=measure_type, - # blacklist=0 - # )) - # self.db.insert_detail_bulk(bulk_insert, self.measure_type) return meter_reading["interval_reading"] else: return { @@ -161,28 +153,25 @@ def run(self, begin, end): app.LOG.error(e) def get(self): - - # REMOVE TODAY - # end = datetime.datetime.combine((datetime.datetime.now() - datetime.timedelta(days=1)), datetime.datetime.max.time()) - end = datetime.datetime.combine((datetime.datetime.now()), datetime.datetime.max.time()) - begin = datetime.datetime.combine(end - datetime.timedelta(days=self.max_detail), datetime.datetime.min.time()) + end = datetime.combine((datetime.now() + timedelta(days=2)), datetime.max.time()) + begin = datetime.combine(end - timedelta(days=self.max_detail), datetime.min.time()) finish = True result = [] while finish: - if self.activation_date and self.activation_date > begin: - # Activation date reached - begin = self.activation_date - finish = False - response = self.run(begin, end) - elif self.max_days_date > begin: + if self.max_days_date > begin: # Max day reached begin = self.max_days_date finish = False response = self.run(begin, end) + elif self.activation_date and self.activation_date > begin: + # Activation date reached + begin = self.activation_date + finish = False + response = self.run(begin, end) else: response = self.run(begin, end) - begin = begin - datetime.timedelta(days=self.max_detail) - end = end - datetime.timedelta(days=self.max_detail) + begin = begin - timedelta(days=self.max_detail) + end = end - timedelta(days=self.max_detail) if response is not None: result = [*result, *response] else: @@ -201,19 +190,40 @@ def get(self): if "status_code" in response and (response["status_code"] == 409 or response["status_code"] == 400): finish = False error = ["Arrêt de la récupération des données suite à une erreur.", - f"Prochain lancement à {datetime.datetime.now() + datetime.timedelta(seconds=app.CONFIG.get('cycle'))}"] + f"Prochain lancement à {datetime.now() + timedelta(seconds=app.CONFIG.get('cycle'))}"] app.LOG.warning(error) - return result + def reset_daily(self, date): + begin = datetime.combine(datetime.strptime(date, self.date_format), datetime.min.time()) + end = datetime.combine(datetime.strptime(date, self.date_format), datetime.max.time()) + self.db.reset_detail_range(self.usage_point_id, begin, end, self.measure_type) + return True + + def delete_daily(self, date): + begin = datetime.combine(datetime.strptime(date, self.date_format), datetime.min.time()) + end = datetime.combine(datetime.strptime(date, self.date_format), datetime.max.time()) + self.db.delete_detail_range(self.usage_point_id, begin, end, self.measure_type) + return True + def reset(self, date=None): + if date is not None: + date = datetime.strptime(date, self.date_detail_format) + self.db.reset_detail(self.usage_point_id, date, self.measure_type) + return True + + def delete(self, date=None): + if date is not None: + date = datetime.strptime(date, self.date_detail_format) self.db.delete_detail(self.usage_point_id, date, self.measure_type) return True def fetch(self, date): + if date is not None: + date = datetime.strptime(date, self.date_format) result = self.run( - datetime.datetime.strptime(date, self.date_format) - datetime.timedelta(days=1), - datetime.datetime.strptime(date, self.date_format) + datetime.timedelta(days=1), + datetime.combine(date - timedelta(days=2), datetime.min.time()), + datetime.combine(date + timedelta(days=2), datetime.min.time()), ) if "error" in result and result["error"]: return { @@ -221,9 +231,15 @@ def fetch(self, date): "notif": result['description'], "fail_count": self.db.get_detail_fail_count(self.usage_point_id, date, self.measure_type) } + for item in result: - if date in item['date']: + if type(item['date']) == str: + item['date'] = datetime.strptime(item['date'], self.date_detail_format) + result_date = item['date'].strftime(self.date_format) + if date.strftime(self.date_format) in result_date: + item["date"] = result_date return item + return { "error": True, "notif": f"Aucune donnée n'est disponible chez Enedis sur cette date ({date})", diff --git a/app/models/query_power.py b/app/models/query_power.py index dfc37ec9..72891a46 100644 --- a/app/models/query_power.py +++ b/app/models/query_power.py @@ -106,12 +106,10 @@ def run(self, begin, end): app.LOG.error(e) def get(self): - end = datetime.combine((datetime.now()), datetime.max.time()) + end = datetime.combine((datetime.now() + timedelta(days=2)), datetime.min.time()) begin = datetime.combine(end - timedelta(days=self.max_daily), datetime.min.time()) - finish = True result = [] - while finish: if self.activation_date and self.activation_date > begin: @@ -151,6 +149,12 @@ def get(self): return result def reset(self, date=None): + if date is not None: + date = datetime.strptime(date, self.date_format) + self.db.reset_daily_max_power(self.usage_point_id, date) + return True + + def delete(self, date=None): if date is not None: date = datetime.strptime(date, self.date_format) self.db.delete_daily_max_power(self.usage_point_id, date) diff --git a/app/models/stat.py b/app/models/stat.py index 6c253924..4b681a87 100644 --- a/app/models/stat.py +++ b/app/models/stat.py @@ -14,6 +14,7 @@ def __init__(self, usage_point_id, measurement_direction): self.usage_point_id = usage_point_id self.measurement_direction = measurement_direction self.usage_point_id_config = app.DB.get_usage_point(self.usage_point_id) + self.usage_point_id_contract = app.DB.get_contract(self.usage_point_id) self.date_format = "%Y-%m-%d" self.date_format_detail = "%Y-%m-%d %H:%M:%S" self.now_date = datetime.now(timezone.utc) @@ -292,8 +293,9 @@ def current_month_evolution(self): app.LOG.log("current_month_evolution") if self.value_current_month_last_year != 0: self.value_current_month_evolution = ( - (100 * self.value_current_month) / self.value_current_month_last_year - ) - 100 + ( + 100 * self.value_current_month) / self.value_current_month_last_year + ) - 100 app.LOG.log(f" => {self.value_current_month_evolution}") return self.value_current_month_evolution @@ -410,7 +412,8 @@ def peak_offpeak_percent(self): def get_year(self, year, measure_type=None): begin = datetime.combine(self.now_date.replace(year=year).replace(day=1).replace(month=1), datetime.min.time()) last_day_of_month = calendar.monthrange(year, 12)[1] - end = datetime.combine(self.now_date.replace(year=year).replace(day=last_day_of_month).replace(month=12), datetime.max.time()) + end = datetime.combine(self.now_date.replace(year=year).replace(day=last_day_of_month).replace(month=12), + datetime.max.time()) value = 0 if measure_type is None: for day in app.DB.get_daily_range(self.usage_point_id, begin, end, self.measurement_direction): @@ -445,9 +448,11 @@ def get_year_linear(self, idx, measure_type=None): def get_month(self, year, month=None, measure_type=None): if month is None: month = int(datetime.now().strftime('%m')) - begin = datetime.combine(self.now_date.replace(year=year).replace(day=1).replace(month=month), datetime.min.time()) + begin = datetime.combine(self.now_date.replace(year=year).replace(day=1).replace(month=month), + datetime.min.time()) last_day_of_month = calendar.monthrange(year, month)[1] - end = datetime.combine(self.now_date.replace(year=year).replace(day=last_day_of_month).replace(month=month), datetime.max.time()) + end = datetime.combine(self.now_date.replace(year=year).replace(day=last_day_of_month).replace(month=month), + datetime.max.time()) value = 0 if measure_type is None: for day in app.DB.get_daily_range(self.usage_point_id, begin, end, self.measurement_direction): @@ -485,8 +490,12 @@ def get_week(self, year, month=None, measure_type=None): today = date.today() start = today - timedelta(days=today.weekday()) end = start + timedelta(days=6) - begin = datetime.combine(self.now_date.replace(year=year).replace(day=int(start.strftime("%d"))).replace(month=month), datetime.min.time()) - end = datetime.combine(self.now_date.replace(year=year).replace(day=int(start.strftime("%d"))).replace(month=month), datetime.max.time()) + begin = datetime.combine( + self.now_date.replace(year=year).replace(day=int(start.strftime("%d"))).replace(month=month), + datetime.min.time()) + end = datetime.combine( + self.now_date.replace(year=year).replace(day=int(start.strftime("%d"))).replace(month=month), + datetime.max.time()) value = 0 if measure_type is None: for day in app.DB.get_daily_range(self.usage_point_id, begin, end, self.measurement_direction): @@ -510,10 +519,29 @@ def get_week_linear(self, idx, measure_type=None): value = value + day.value else: for day in app.DB.get_detail_range(self.usage_point_id, begin, end, self.measurement_direction): - if day.measure_type == measure_type: - value = value + (day.value / (60 / day.interval)) + if day.measure_type == measure_type: + value = value + (day.value / (60 / day.interval)) return { "value": value, "begin": begin.strftime(self.date_format), "end": end.strftime(self.date_format) } + + def max_power_over(self, index=0): + max_power = 9999 + if hasattr(self.usage_point_id_contract, + "subscribed_power") and self.usage_point_id_contract.subscribed_power is not None: + max_power = int(self.usage_point_id_contract.subscribed_power.split(' ')[0]) + begin = datetime.combine(self.yesterday_date - timedelta(days=index), datetime.min.time()) + end = datetime.combine(begin, datetime.max.time()) + value = 0 + boolv = "false" + for data in app.DB.get_daily_max_power_range(self.usage_point_id, begin, end): + value = value + data.value + if (value / 1000) > max_power: + boolv = "true" + return { + "value": boolv, + "begin": begin.strftime(self.date_format), + "end": end.strftime(self.date_format) + } \ No newline at end of file diff --git a/app/static/css/main.css b/app/static/css/main.css index 4b8560c1..4118a8c8 100755 --- a/app/static/css/main.css +++ b/app/static/css/main.css @@ -66,33 +66,33 @@ a { h1 { font-size: 24px; - background: #FFF; - color: var(--sde-bg-color); border-radius: 10px; padding: 10px; - border: 1px solid var(--sde-bg-color); margin-top: 50px; -} - -h2 { color: var(--main-bg-color); - letter-spacing: 2px; - font-size: 17px; background: var(--sde-bg-color); border: 1px solid var(--main-bg-color); - border-radius: 10px; - padding: 10px; } -h3 { +h2 { color: var(--text-color); - font-size: 15px; + font-size: 17px; background: var(--logo); border: 1px solid var(--text-title); border-radius: 15px; padding: 10px; } +h3 { + letter-spacing: 2px; + font-size: 15px; + border-radius: 10px; + padding: 10px; + background: #FFF; + color: var(--sde-bg-color); + border: 1px solid var(--sde-bg-color); +} + #footer { position: fixed; left: 0; diff --git a/app/templates/html/usage_point_id.html b/app/templates/html/usage_point_id.html index 79dba20c..34540b36 100644 --- a/app/templates/html/usage_point_id.html +++ b/app/templates/html/usage_point_id.html @@ -4,30 +4,42 @@ MyElectricalData {{ javascript_loader }}