Module lib.plugins.electricmeter.webpage
Web page displaying electricity consumption per minute, day, month. The principle is based on counting the pulses generated by the electric meter, via the LED which flashes on the electric meter (1 wh per flash).
Expand source code
# Distributed under Pycameresp License
# Copyright (c) 2023 Remi BERTHOLET
""" Web page displaying electricity consumption per minute, day, month.
The principle is based on counting the pulses generated by the electric meter,
via the LED which flashes on the electric meter (1 wh per flash). """
# pylint:disable=anomalous-unicode-escape-in-string
# pylint:disable=wrong-import-order
# pylint:disable=unused-import
import json
import server.httpserver
from htmltemplate import *
import webpage.mainpage
import tools.date
import tools.strings
import tools.lang
from plugins import electricmeter
from plugins.electricmeter import lang
@server.httpserver.HttpServer.add_route(b'/hourly', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_hour)
async def hourly_page_page(request, response, args):
""" Daily consumption graph hour by hour """
geolocation = electricmeter.config.GeolocationConfig.get_config()
day = tools.date.html_to_date(request.params.get(b"day",b""))
if request.params.get(b"direction",b"") == b"next":
day += 86400
elif request.params.get(b"direction",b"") == b"previous":
day -= 86400
step = int(request.params.get(b"step",b"1"))
steps = []
for s in [1,5,10,15,30]:
if s == step:
selected = True
else:
selected = False
steps.append(Option(text=b"%d %s"%(s, electricmeter.lang.step_minutes), value=b"%d"%s, selected=selected))
unit = request.params.get(b"unit",b"power")
with open(WWW_DIR + "electricmeter.html", "rb") as file:
content = file.read()
link_up = b"daily?year="+tools.date.date_to_html(day)[0:4] + b"&month="+tools.date.date_to_html(day)[5:7] + b"&unit=" + unit
temperature = request.params.get(b"temperature")
if temperature is None or temperature == b"0":
with_temperature = b"false"
temperature = None
else:
with_temperature = b"true"
link_up += b"&temperature=1"
page_content = \
[
Div(
[
Div(
[
Button(type=b"submit", text=b"<-", name=b"direction", value=b"previous"),Space(),
Link(type=b"button", class_=b"btn btn-outline-primary", text=b"\xE2\xA4\xB4", href=link_up),Space(),
Button(type=b"submit", text=b"->", name=b"direction", value=b"next")
], class_=b'col-md-2 mb-1'),
Div(
[
Input (type=b"date", class_=b"form-label border rounded p-1", name=b"day", value= tools.date.date_to_html(day), event=b'onchange="this.form.submit()"'),Space(),
], class_=b'col-md-2'),
Div(
[
Select(steps, spacer=b"", text=electricmeter.lang.step_minutes, name=b"step", event=b'onchange="this.form.submit()"')
], class_=b'col-md-2'),
Div([
Select(
[
Option(text=electricmeter.lang.type_price, value=b"price", selected= True if unit == b"price" else False),
Option(text=electricmeter.lang.type_power, value=b"power", selected= True if unit == b"power" else False),
], spacer=b"", text=electricmeter.lang.step_minutes, name=b"unit", event=b'onchange="this.form.submit()"')
], class_=b'col-md-1'),
Div(
[
Switch(text=electricmeter.lang.temperature, name=b"temperature", checked=temperature, event=b'onchange="this.form.submit()"')
], class_=b'col-md-2')
], class_=b"row"),
Tag(content%(b"hourly",
step,
tools.date.date_to_html(day),
tools.lang.translate_date(day),
unit,
electricmeter.lang.power_consumed,
geolocation.latitude,
geolocation.longitude,
with_temperature))
]
page = webpage.mainpage.main_frame(request, response, args,electricmeter.lang.title_electricmeter + electricmeter.lang.item_hour.lower(),Form(page_content))
await response.send_page(page)
@server.httpserver.HttpServer.add_route(b'/hourly_datas')
async def hourly_page_datas(request, response, args):
""" Send pulses of hours and rates """
day = tools.date.html_to_date(request.params.get(b"day",b""))
result = {"pulses":None}
result["rates"] = []
for cost in electricmeter.config.TimeSlotsConfig.get_cost(day):
result["rates"].append(cost.to_dict())
try:
result["pulses"] = electricmeter.meter.HourlyCounter.get_datas(day)
await response.send_buffer(b"pulses", buffer=tools.strings.tobytes(json.dumps(result)), mime_type=b"application/json")
except Exception as err:
await response.send_not_found(err)
@server.httpserver.HttpServer.add_route(b'/power_datas')
async def power_page_datas(request, response, args):
""" Send current power consumed """
try:
power = {"power":electricmeter.meter.HourlyCounter.get_power()}
await response.send_buffer(b"pulses", buffer=tools.strings.tobytes(json.dumps(power)), mime_type=b"application/json")
except Exception as err:
await response.send_not_found(err)
@server.httpserver.HttpServer.add_route(b'/daily', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_day)
async def daily_page(request, response, args):
""" Consumption graph day by day """
geolocation = electricmeter.config.GeolocationConfig.get_config()
y,m = tools.date.local_time()[:2]
year = int(request.params.get(b"year",b"%d"%y))
month = int(request.params.get(b"month",b"%d"%m))
if request.params.get(b"direction",b"") == b"next":
if month == 12:
month = 1
year += 1
else:
month += 1
elif request.params.get(b"direction",b"") == b"previous":
if month == 1:
month = 12
year -= 1
else:
month -= 1
day = tools.date.html_to_date(b"%04d-%02d-01"%(year, month))
unit = request.params.get(b"unit",b"power")
temperature = request.params.get(b"temperature")
if temperature is None or temperature == b"0":
with_temperature = b"false"
temperature = None
else:
with_temperature = b"true"
months_combo = []
month_id = 1
for m in tools.lang.months:
months_combo.append(Option(text=m, value=b"%d"%month_id, selected= True if month_id == month else False))
month_id += 1
with open(WWW_DIR + "electricmeter.html", "rb") as file:
content = file.read()
page_content = \
[
Div(
[
Div(
[
Button(type=b"submit", text=b"<-", name=b"direction", value=b"previous"),Space(),
Link(type=b"button", class_=b"btn btn-outline-primary", text=b"\xE2\xA4\xB4", href=b"monthly?year="+tools.date.date_to_html(day)[0:4]),Space(),
Button(type=b"submit", text=b"->", name=b"direction", value=b"next")
], class_=b'col-md-2 mb-2'),
Div(
[
Edit (name=b"year", spacer=b"", type=b"number", step=b"1", required=True, value=b"%d"%year, event=b'onchange="this.form.submit()"'),
], class_=b'col-md-2'),
Div(
[
Select(months_combo, spacer=b"", name=b"month", event=b'onchange="this.form.submit()"'),
], class_=b'col-md-2 mb-2'),
Div(
[
Select(
[
Option(text=electricmeter.lang.type_price, value=b"price", selected= True if unit == b"price" else False),
Option(text=electricmeter.lang.type_power, value=b"power", selected= True if unit == b"power" else False),
], spacer=b"", text=electricmeter.lang.step_minutes, name=b"unit", event=b'onchange="this.form.submit()"')
], class_=b'col-md-2'),
Div(
[
Switch(text=electricmeter.lang.temperature, name=b"temperature", checked=temperature, event=b'onchange="this.form.submit()"')
], class_=b'col-md-2')
], class_=b"row"),
Tag(content%(b"daily", 86400, tools.date.date_to_html(day), tools.lang.translate_date(day, False), unit, electricmeter.lang.power_consumed, geolocation.latitude, geolocation.longitude, with_temperature))
]
page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.title_electricmeter + electricmeter.lang.item_day.lower(),Form(page_content))
await response.send_page(page)
@server.httpserver.HttpServer.add_route(b'/daily_datas')
async def daily_datas(request, response, args):
""" Send pulses of month and rates """
month = tools.date.html_to_date(request.params.get(b"month",b""))
result = {"time_slots":None}
result["rates"] = []
for cost in electricmeter.config.TimeSlotsConfig.get_cost(month):
result["rates"].append(cost.to_dict())
try:
result["time_slots"] = electricmeter.meter.DailyCounter.get_datas(month)
await response.send_buffer(b"pulses", buffer=tools.strings.tobytes(json.dumps(result)), mime_type=b"application/json")
except Exception as err:
await response.send_not_found(err)
@server.httpserver.HttpServer.add_route(b'/monthly', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_month)
async def monthly_page(request, response, args):
""" Consumption graph month by month """
geolocation = electricmeter.config.GeolocationConfig.get_config()
y = tools.date.local_time()[0]
year = int(request.params.get(b"year",b"%d"%y))
if request.params.get(b"direction",b"") == b"next":
year += 1
elif request.params.get(b"direction",b"") == b"previous":
year -= 1
month = tools.date.html_to_date(b"%04d-01-01"%(year))
unit = request.params.get(b"unit",b"power")
with open(WWW_DIR + "electricmeter.html", "rb") as file:
content = file.read()
page_content = \
[
Div(
[
Div(
[
Button(type=b"submit", text=b"<-", name=b"direction", value=b"previous"),Space(),
Button(type=b"submit", text=b"->", name=b"direction", value=b"next")
], class_=b'col-md-2 mb-2'),
Div(\
[
Edit (name=b"year", spacer=b"", type=b"number", step=b"1", required=True, value=b"%d"%year, event=b'onchange="this.form.submit()"'),
], class_=b'col-md-2'),
Div(
[
Select(
[
Option(text=electricmeter.lang.type_price, value=b"price", selected= True if unit == b"price" else False),
Option(text=electricmeter.lang.type_power, value=b"power", selected= True if unit == b"power" else False),
], spacer=b"", text=electricmeter.lang.step_minutes, name=b"unit", event=b'onchange="this.form.submit()"')
],class_=b'col-md-2')
], class_=b"row"),
Tag(content%(b"monthly", 86400, tools.date.date_to_html(month), tools.lang.translate_date(month, False), unit, electricmeter.lang.power_consumed, geolocation.latitude, geolocation.longitude, b""))
]
page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.title_electricmeter + electricmeter.lang.item_month.lower(),Form(page_content))
await response.send_page(page)
@server.httpserver.HttpServer.add_route(b'/monthly_datas')
async def monthly_datas(request, response, args):
""" Send pulses of month and rates """
year = tools.date.html_to_date(request.params.get(b"year",b""))
result = {"time_slots":None}
result["rates"] = []
for cost in electricmeter.config.TimeSlotsConfig.get_cost(year):
result["rates"].append(cost.to_dict())
try:
result["time_slots"] = electricmeter.meter.MonthlyCounter.get_datas(year)
await response.send_buffer(b"pulses", buffer=tools.strings.tobytes(json.dumps(result)), mime_type=b"application/json")
except Exception as err:
await response.send_not_found(err)
@server.httpserver.HttpServer.add_route(b'/rate', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_rate)
async def rate_page(request, response, args):
""" Electric rate configuration page """
rates = electricmeter.config.RatesConfig.get_config()
current = electricmeter.config.RateConfig()
# If new rate added
if request.params.get(b"add",None) is not None:
current.update(request.params, show_error=False)
rates.append(current)
rates.save()
# If a rate must be deleted
elif request.params.get(b"remove",None) is not None:
rates.remove(request.params.get(b"remove",b"none"))
rates.save()
# If a rate must be edited
elif request.params.get(b"edit",None) is not None:
current = rates.get(request.params.get(b"edit",b"none"))
# List all rates
rate_items = []
identifier = 0
while True:
rate = rates.get(identifier)
if rate is not None:
rate_items.append(
ListItem(
[
Link(text=b" %s : %f %s %s %s "%(rate.name, rate.price, rate.currency, electricmeter.lang.from_the, tools.lang.translate_date(rate.validity_date)), href=b"rate?edit=%d"%identifier ),
Link(text=electricmeter.lang.remove_button , class_=b"btn position-absolute top-50 end-0 translate-middle-y", href=b"rate?remove=%d"%identifier, onclick=b"return window.confirm('%s')"%electricmeter.lang.remove_dialog)
]))
else:
break
identifier += 1
# Build page
page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.title_rate,
[
Form(
[
Edit (text=electricmeter.lang.name, name=b"name", placeholder=electricmeter.lang.field_rate, required=True, value=current.name),
Edit (text=electricmeter.lang.validy_date, name=b"validity_date", type=b"date", required=True, value=b"%04d-%02d-%02d"%tools.date.local_time(current.validity_date)[:3]),
Edit (text=electricmeter.lang.price, name=b"price", type=b"number", step=b"0.0001", required=True, value=b"%f"%current.price),
Edit (text=electricmeter.lang.currency, name=b"currency", placeholder=electricmeter.lang.field_currency, required=True, value=current.currency),
Submit(text=electricmeter.lang.add_button, name=b"add")
]),
List(rate_items)
])
await response.send_page(page)
@server.httpserver.HttpServer.add_route(b'/time_slots', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_time_slots)
async def time_slots_page(request, response, args):
""" Electric time slots configuration page """
time_slots = electricmeter.config.TimeSlotsConfig.get_config()
rates = electricmeter.config.RatesConfig.get_config()
current = electricmeter.config.TimeSlotConfig()
# If new time_slot added
if request.params.get(b"add",None) is not None:
current.update(request.params, show_error=False)
time_slots.append(current)
time_slots.save()
# If a time_slot must be deleted
elif request.params.get(b"remove",None) is not None:
time_slots.remove(request.params.get(b"remove",b"none"))
time_slots.save()
# If a time_slot must be edited
elif request.params.get(b"edit",None) is not None:
current = time_slots.get(request.params.get(b"edit",b"none"))
# List all rates names
rates_combo = []
names = {}
identifier = 0
while True:
rate = rates.get(identifier)
if rate is not None:
if rate.name not in names:
rates_combo.append(Option(text=rate.name, value=rate.name, selected=b"selected" if current.rate == rate.name else b""))
else:
break
names[rate.name] = b""
identifier += 1
# List all rates
time_slots_items = []
identifier = 0
while True:
time_slot = time_slots.get(identifier)
if time_slot is not None:
time_slots_items.append(
ListItem(
[
Label(text=b" ", style=b"background-color: %s"%time_slot.color),
Space(),Space(),
Link(text=b"%s - %s : %s "%(tools.date.time_to_html(time_slot.start_time), tools.date.time_to_html(time_slot.end_time), time_slot.rate),href=b"time_slots?edit=%d"%identifier),
Link(text=electricmeter.lang.remove_button , class_=b"btn position-absolute top-50 end-0 translate-middle-y", href=b"time_slots?remove=%d"%identifier, onclick=b"return window.confirm('%s')"%electricmeter.lang.remove_dialog)
]))
else:
break
identifier += 1
# Build page
page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.title_time_slots,
[
Form(
[
Edit (text=electricmeter.lang.field_start, name=b"start_time", type=b"time", required=True, value=tools.date.time_to_html(current.start_time)),
Edit (text=electricmeter.lang.field_end, name=b"end_time", type=b"time", required=True, value=tools.date.time_to_html(current.end_time)),
Label(text=electricmeter.lang.field_time_rate),
Select(rates_combo,name=b"rate", required=True),
Edit (text=electricmeter.lang.field_color, name=b"color", type=b"color", required=True, value=current.color),
Submit(text=electricmeter.lang.add_button, name=b"add")
]),
List(time_slots_items)
])
await response.send_page(page)
@server.httpserver.HttpServer.add_route(b'/geolocation', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_geolocation)
async def geolocation_page(request, response, args):
""" Determines the geolocation of the device """
config = electricmeter.config.GeolocationConfig.get_config()
disabled, action, submit = webpage.mainpage.manage_default_button(request, config)
page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.item_geolocation,
Form(
[
Edit (text=electricmeter.lang.latitude, name=b"latitude", type=b"number", step=b"0.0001", required=True, min=b"-90.", max=b"90." , value=b"%.3f"%config.latitude, disabled=disabled),
Edit (text=electricmeter.lang.longitude, name=b"longitude", type=b"number", step=b"0.0001", required=True, min=b"-180.", max=b"180.", value=b"%.3f"%config.longitude,disabled=disabled),
submit, None
]))
await response.send_page(page)
Functions
async def daily_datas(request, response, args)-
Send pulses of month and rates
Expand source code
@server.httpserver.HttpServer.add_route(b'/daily_datas') async def daily_datas(request, response, args): """ Send pulses of month and rates """ month = tools.date.html_to_date(request.params.get(b"month",b"")) result = {"time_slots":None} result["rates"] = [] for cost in electricmeter.config.TimeSlotsConfig.get_cost(month): result["rates"].append(cost.to_dict()) try: result["time_slots"] = electricmeter.meter.DailyCounter.get_datas(month) await response.send_buffer(b"pulses", buffer=tools.strings.tobytes(json.dumps(result)), mime_type=b"application/json") except Exception as err: await response.send_not_found(err) async def daily_page(request, response, args)-
Consumption graph day by day
Expand source code
@server.httpserver.HttpServer.add_route(b'/daily', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_day) async def daily_page(request, response, args): """ Consumption graph day by day """ geolocation = electricmeter.config.GeolocationConfig.get_config() y,m = tools.date.local_time()[:2] year = int(request.params.get(b"year",b"%d"%y)) month = int(request.params.get(b"month",b"%d"%m)) if request.params.get(b"direction",b"") == b"next": if month == 12: month = 1 year += 1 else: month += 1 elif request.params.get(b"direction",b"") == b"previous": if month == 1: month = 12 year -= 1 else: month -= 1 day = tools.date.html_to_date(b"%04d-%02d-01"%(year, month)) unit = request.params.get(b"unit",b"power") temperature = request.params.get(b"temperature") if temperature is None or temperature == b"0": with_temperature = b"false" temperature = None else: with_temperature = b"true" months_combo = [] month_id = 1 for m in tools.lang.months: months_combo.append(Option(text=m, value=b"%d"%month_id, selected= True if month_id == month else False)) month_id += 1 with open(WWW_DIR + "electricmeter.html", "rb") as file: content = file.read() page_content = \ [ Div( [ Div( [ Button(type=b"submit", text=b"<-", name=b"direction", value=b"previous"),Space(), Link(type=b"button", class_=b"btn btn-outline-primary", text=b"\xE2\xA4\xB4", href=b"monthly?year="+tools.date.date_to_html(day)[0:4]),Space(), Button(type=b"submit", text=b"->", name=b"direction", value=b"next") ], class_=b'col-md-2 mb-2'), Div( [ Edit (name=b"year", spacer=b"", type=b"number", step=b"1", required=True, value=b"%d"%year, event=b'onchange="this.form.submit()"'), ], class_=b'col-md-2'), Div( [ Select(months_combo, spacer=b"", name=b"month", event=b'onchange="this.form.submit()"'), ], class_=b'col-md-2 mb-2'), Div( [ Select( [ Option(text=electricmeter.lang.type_price, value=b"price", selected= True if unit == b"price" else False), Option(text=electricmeter.lang.type_power, value=b"power", selected= True if unit == b"power" else False), ], spacer=b"", text=electricmeter.lang.step_minutes, name=b"unit", event=b'onchange="this.form.submit()"') ], class_=b'col-md-2'), Div( [ Switch(text=electricmeter.lang.temperature, name=b"temperature", checked=temperature, event=b'onchange="this.form.submit()"') ], class_=b'col-md-2') ], class_=b"row"), Tag(content%(b"daily", 86400, tools.date.date_to_html(day), tools.lang.translate_date(day, False), unit, electricmeter.lang.power_consumed, geolocation.latitude, geolocation.longitude, with_temperature)) ] page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.title_electricmeter + electricmeter.lang.item_day.lower(),Form(page_content)) await response.send_page(page) async def geolocation_page(request, response, args)-
Determines the geolocation of the device
Expand source code
@server.httpserver.HttpServer.add_route(b'/geolocation', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_geolocation) async def geolocation_page(request, response, args): """ Determines the geolocation of the device """ config = electricmeter.config.GeolocationConfig.get_config() disabled, action, submit = webpage.mainpage.manage_default_button(request, config) page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.item_geolocation, Form( [ Edit (text=electricmeter.lang.latitude, name=b"latitude", type=b"number", step=b"0.0001", required=True, min=b"-90.", max=b"90." , value=b"%.3f"%config.latitude, disabled=disabled), Edit (text=electricmeter.lang.longitude, name=b"longitude", type=b"number", step=b"0.0001", required=True, min=b"-180.", max=b"180.", value=b"%.3f"%config.longitude,disabled=disabled), submit, None ])) await response.send_page(page) async def hourly_page_datas(request, response, args)-
Send pulses of hours and rates
Expand source code
@server.httpserver.HttpServer.add_route(b'/hourly_datas') async def hourly_page_datas(request, response, args): """ Send pulses of hours and rates """ day = tools.date.html_to_date(request.params.get(b"day",b"")) result = {"pulses":None} result["rates"] = [] for cost in electricmeter.config.TimeSlotsConfig.get_cost(day): result["rates"].append(cost.to_dict()) try: result["pulses"] = electricmeter.meter.HourlyCounter.get_datas(day) await response.send_buffer(b"pulses", buffer=tools.strings.tobytes(json.dumps(result)), mime_type=b"application/json") except Exception as err: await response.send_not_found(err) async def hourly_page_page(request, response, args)-
Daily consumption graph hour by hour
Expand source code
@server.httpserver.HttpServer.add_route(b'/hourly', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_hour) async def hourly_page_page(request, response, args): """ Daily consumption graph hour by hour """ geolocation = electricmeter.config.GeolocationConfig.get_config() day = tools.date.html_to_date(request.params.get(b"day",b"")) if request.params.get(b"direction",b"") == b"next": day += 86400 elif request.params.get(b"direction",b"") == b"previous": day -= 86400 step = int(request.params.get(b"step",b"1")) steps = [] for s in [1,5,10,15,30]: if s == step: selected = True else: selected = False steps.append(Option(text=b"%d %s"%(s, electricmeter.lang.step_minutes), value=b"%d"%s, selected=selected)) unit = request.params.get(b"unit",b"power") with open(WWW_DIR + "electricmeter.html", "rb") as file: content = file.read() link_up = b"daily?year="+tools.date.date_to_html(day)[0:4] + b"&month="+tools.date.date_to_html(day)[5:7] + b"&unit=" + unit temperature = request.params.get(b"temperature") if temperature is None or temperature == b"0": with_temperature = b"false" temperature = None else: with_temperature = b"true" link_up += b"&temperature=1" page_content = \ [ Div( [ Div( [ Button(type=b"submit", text=b"<-", name=b"direction", value=b"previous"),Space(), Link(type=b"button", class_=b"btn btn-outline-primary", text=b"\xE2\xA4\xB4", href=link_up),Space(), Button(type=b"submit", text=b"->", name=b"direction", value=b"next") ], class_=b'col-md-2 mb-1'), Div( [ Input (type=b"date", class_=b"form-label border rounded p-1", name=b"day", value= tools.date.date_to_html(day), event=b'onchange="this.form.submit()"'),Space(), ], class_=b'col-md-2'), Div( [ Select(steps, spacer=b"", text=electricmeter.lang.step_minutes, name=b"step", event=b'onchange="this.form.submit()"') ], class_=b'col-md-2'), Div([ Select( [ Option(text=electricmeter.lang.type_price, value=b"price", selected= True if unit == b"price" else False), Option(text=electricmeter.lang.type_power, value=b"power", selected= True if unit == b"power" else False), ], spacer=b"", text=electricmeter.lang.step_minutes, name=b"unit", event=b'onchange="this.form.submit()"') ], class_=b'col-md-1'), Div( [ Switch(text=electricmeter.lang.temperature, name=b"temperature", checked=temperature, event=b'onchange="this.form.submit()"') ], class_=b'col-md-2') ], class_=b"row"), Tag(content%(b"hourly", step, tools.date.date_to_html(day), tools.lang.translate_date(day), unit, electricmeter.lang.power_consumed, geolocation.latitude, geolocation.longitude, with_temperature)) ] page = webpage.mainpage.main_frame(request, response, args,electricmeter.lang.title_electricmeter + electricmeter.lang.item_hour.lower(),Form(page_content)) await response.send_page(page) async def monthly_datas(request, response, args)-
Send pulses of month and rates
Expand source code
@server.httpserver.HttpServer.add_route(b'/monthly_datas') async def monthly_datas(request, response, args): """ Send pulses of month and rates """ year = tools.date.html_to_date(request.params.get(b"year",b"")) result = {"time_slots":None} result["rates"] = [] for cost in electricmeter.config.TimeSlotsConfig.get_cost(year): result["rates"].append(cost.to_dict()) try: result["time_slots"] = electricmeter.meter.MonthlyCounter.get_datas(year) await response.send_buffer(b"pulses", buffer=tools.strings.tobytes(json.dumps(result)), mime_type=b"application/json") except Exception as err: await response.send_not_found(err) async def monthly_page(request, response, args)-
Consumption graph month by month
Expand source code
@server.httpserver.HttpServer.add_route(b'/monthly', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_month) async def monthly_page(request, response, args): """ Consumption graph month by month """ geolocation = electricmeter.config.GeolocationConfig.get_config() y = tools.date.local_time()[0] year = int(request.params.get(b"year",b"%d"%y)) if request.params.get(b"direction",b"") == b"next": year += 1 elif request.params.get(b"direction",b"") == b"previous": year -= 1 month = tools.date.html_to_date(b"%04d-01-01"%(year)) unit = request.params.get(b"unit",b"power") with open(WWW_DIR + "electricmeter.html", "rb") as file: content = file.read() page_content = \ [ Div( [ Div( [ Button(type=b"submit", text=b"<-", name=b"direction", value=b"previous"),Space(), Button(type=b"submit", text=b"->", name=b"direction", value=b"next") ], class_=b'col-md-2 mb-2'), Div(\ [ Edit (name=b"year", spacer=b"", type=b"number", step=b"1", required=True, value=b"%d"%year, event=b'onchange="this.form.submit()"'), ], class_=b'col-md-2'), Div( [ Select( [ Option(text=electricmeter.lang.type_price, value=b"price", selected= True if unit == b"price" else False), Option(text=electricmeter.lang.type_power, value=b"power", selected= True if unit == b"power" else False), ], spacer=b"", text=electricmeter.lang.step_minutes, name=b"unit", event=b'onchange="this.form.submit()"') ],class_=b'col-md-2') ], class_=b"row"), Tag(content%(b"monthly", 86400, tools.date.date_to_html(month), tools.lang.translate_date(month, False), unit, electricmeter.lang.power_consumed, geolocation.latitude, geolocation.longitude, b"")) ] page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.title_electricmeter + electricmeter.lang.item_month.lower(),Form(page_content)) await response.send_page(page) async def power_page_datas(request, response, args)-
Send current power consumed
Expand source code
@server.httpserver.HttpServer.add_route(b'/power_datas') async def power_page_datas(request, response, args): """ Send current power consumed """ try: power = {"power":electricmeter.meter.HourlyCounter.get_power()} await response.send_buffer(b"pulses", buffer=tools.strings.tobytes(json.dumps(power)), mime_type=b"application/json") except Exception as err: await response.send_not_found(err) async def rate_page(request, response, args)-
Electric rate configuration page
Expand source code
@server.httpserver.HttpServer.add_route(b'/rate', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_rate) async def rate_page(request, response, args): """ Electric rate configuration page """ rates = electricmeter.config.RatesConfig.get_config() current = electricmeter.config.RateConfig() # If new rate added if request.params.get(b"add",None) is not None: current.update(request.params, show_error=False) rates.append(current) rates.save() # If a rate must be deleted elif request.params.get(b"remove",None) is not None: rates.remove(request.params.get(b"remove",b"none")) rates.save() # If a rate must be edited elif request.params.get(b"edit",None) is not None: current = rates.get(request.params.get(b"edit",b"none")) # List all rates rate_items = [] identifier = 0 while True: rate = rates.get(identifier) if rate is not None: rate_items.append( ListItem( [ Link(text=b" %s : %f %s %s %s "%(rate.name, rate.price, rate.currency, electricmeter.lang.from_the, tools.lang.translate_date(rate.validity_date)), href=b"rate?edit=%d"%identifier ), Link(text=electricmeter.lang.remove_button , class_=b"btn position-absolute top-50 end-0 translate-middle-y", href=b"rate?remove=%d"%identifier, onclick=b"return window.confirm('%s')"%electricmeter.lang.remove_dialog) ])) else: break identifier += 1 # Build page page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.title_rate, [ Form( [ Edit (text=electricmeter.lang.name, name=b"name", placeholder=electricmeter.lang.field_rate, required=True, value=current.name), Edit (text=electricmeter.lang.validy_date, name=b"validity_date", type=b"date", required=True, value=b"%04d-%02d-%02d"%tools.date.local_time(current.validity_date)[:3]), Edit (text=electricmeter.lang.price, name=b"price", type=b"number", step=b"0.0001", required=True, value=b"%f"%current.price), Edit (text=electricmeter.lang.currency, name=b"currency", placeholder=electricmeter.lang.field_currency, required=True, value=current.currency), Submit(text=electricmeter.lang.add_button, name=b"add") ]), List(rate_items) ]) await response.send_page(page) async def time_slots_page(request, response, args)-
Electric time slots configuration page
Expand source code
@server.httpserver.HttpServer.add_route(b'/time_slots', menu=electricmeter.lang.menu_electricmeter, item=electricmeter.lang.item_time_slots) async def time_slots_page(request, response, args): """ Electric time slots configuration page """ time_slots = electricmeter.config.TimeSlotsConfig.get_config() rates = electricmeter.config.RatesConfig.get_config() current = electricmeter.config.TimeSlotConfig() # If new time_slot added if request.params.get(b"add",None) is not None: current.update(request.params, show_error=False) time_slots.append(current) time_slots.save() # If a time_slot must be deleted elif request.params.get(b"remove",None) is not None: time_slots.remove(request.params.get(b"remove",b"none")) time_slots.save() # If a time_slot must be edited elif request.params.get(b"edit",None) is not None: current = time_slots.get(request.params.get(b"edit",b"none")) # List all rates names rates_combo = [] names = {} identifier = 0 while True: rate = rates.get(identifier) if rate is not None: if rate.name not in names: rates_combo.append(Option(text=rate.name, value=rate.name, selected=b"selected" if current.rate == rate.name else b"")) else: break names[rate.name] = b"" identifier += 1 # List all rates time_slots_items = [] identifier = 0 while True: time_slot = time_slots.get(identifier) if time_slot is not None: time_slots_items.append( ListItem( [ Label(text=b" ", style=b"background-color: %s"%time_slot.color), Space(),Space(), Link(text=b"%s - %s : %s "%(tools.date.time_to_html(time_slot.start_time), tools.date.time_to_html(time_slot.end_time), time_slot.rate),href=b"time_slots?edit=%d"%identifier), Link(text=electricmeter.lang.remove_button , class_=b"btn position-absolute top-50 end-0 translate-middle-y", href=b"time_slots?remove=%d"%identifier, onclick=b"return window.confirm('%s')"%electricmeter.lang.remove_dialog) ])) else: break identifier += 1 # Build page page = webpage.mainpage.main_frame(request, response, args, electricmeter.lang.title_time_slots, [ Form( [ Edit (text=electricmeter.lang.field_start, name=b"start_time", type=b"time", required=True, value=tools.date.time_to_html(current.start_time)), Edit (text=electricmeter.lang.field_end, name=b"end_time", type=b"time", required=True, value=tools.date.time_to_html(current.end_time)), Label(text=electricmeter.lang.field_time_rate), Select(rates_combo,name=b"rate", required=True), Edit (text=electricmeter.lang.field_color, name=b"color", type=b"color", required=True, value=current.color), Submit(text=electricmeter.lang.add_button, name=b"add") ]), List(time_slots_items) ]) await response.send_page(page)