Module lib.electricmeter.webpage

Function define the web page to view recent motion detection

Expand source code
# Distributed under Pycameresp License
# Copyright (c) 2023 Remi BERTHOLET
""" Function define the web page to view recent motion detection """
# pylint:disable=anomalous-unicode-escape-in-string
# pylint:disable=wrong-import-order
import json
import server.httpserver
from htmltemplate           import *
import webpage.mainpage
import tools.date
import tools.strings
import tools.lang
import electricmeter.config
import electricmeter.meter
import electricmeter.em_lang

@server.httpserver.HttpServer.add_route(b'/hourly', menu=electricmeter.em_lang.menu_electricmeter, item=electricmeter.em_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

        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"

        step = int(request.params.get(b"step",b"30"))
        steps = []
        for s in [1,2,3,5,10,15,30,60]:
                if s == step:
                        selected = True
                else:
                        selected = False
                steps.append(Option(text=b"%d %s"%(s, electricmeter.em_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()

        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-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.em_lang.step_minutes, name=b"step",                 event=b'onchange="this.form.submit()"')
                        ], class_=b'col-md-2'),
                        Div([
                                Select(
                                [
                                        Option(text=electricmeter.em_lang.type_price, value=b"price", selected= True if unit == b"price" else False),
                                        Option(text=electricmeter.em_lang.type_power, value=b"power", selected= True if unit == b"power" else False),
                                ], spacer=b"", text=electricmeter.em_lang.step_minutes, name=b"unit",                 event=b'onchange="this.form.submit()"')
                        ], class_=b'col-md-1'),
                        Div(
                        [
                                Switch(text=electricmeter.em_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.em_lang.power_consumed,
                        geolocation.latitude,
                        geolocation.longitude,
                        with_temperature))
        ]
        page = webpage.mainpage.main_frame(request, response, args,electricmeter.em_lang.title_electricmeter + electricmeter.em_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"] = tools.strings.tostrings(electricmeter.config.TimeSlotsConfig.get_cost(day))
        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.em_lang.menu_electricmeter, item=electricmeter.em_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(),
                                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.em_lang.type_price, value=b"price", selected= True if unit == b"price" else False),
                                        Option(text=electricmeter.em_lang.type_power, value=b"power", selected= True if unit == b"power" else False),
                                ], spacer=b"", text=electricmeter.em_lang.step_minutes, name=b"unit",                 event=b'onchange="this.form.submit()"')
                        ], class_=b'col-md-2'),
                        Div(
                        [
                                Switch(text=electricmeter.em_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.em_lang.power_consumed, geolocation.latitude, geolocation.longitude, with_temperature))
        ]
        page = webpage.mainpage.main_frame(request, response, args, electricmeter.em_lang.title_electricmeter + electricmeter.em_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"] = tools.strings.tostrings(electricmeter.config.TimeSlotsConfig.get_cost(month))
        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.em_lang.menu_electricmeter, item=electricmeter.em_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.em_lang.type_price, value=b"price", selected= True if unit == b"price" else False),
                                        Option(text=electricmeter.em_lang.type_power, value=b"power", selected= True if unit == b"power" else False),
                                ], spacer=b"", text=electricmeter.em_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.em_lang.power_consumed, geolocation.latitude, geolocation.longitude, b""))
        ]
        page = webpage.mainpage.main_frame(request, response, args, electricmeter.em_lang.title_electricmeter + electricmeter.em_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"] = tools.strings.tostrings(electricmeter.config.TimeSlotsConfig.get_cost(year))
        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.em_lang.menu_electricmeter, item=electricmeter.em_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.update(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[b"name"], rate[b"price"], rate[b"currency"], electricmeter.em_lang.from_the, tools.lang.translate_date(rate[b"validity_date"])), href=b"rate?edit=%d"%identifier ),
                                                Link(text=electricmeter.em_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.em_lang.remove_dialog)
                                        ]))
                else:
                        break
                identifier += 1

        # Build page
        page = webpage.mainpage.main_frame(request, response, args, electricmeter.em_lang.title_rate,
        [
                Form(
                [
                        Edit  (text=electricmeter.em_lang.name,          name=b"name",          placeholder=electricmeter.em_lang.field_rate,     required=True, value=current.name),
                        Edit  (text=electricmeter.em_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.em_lang.price,         name=b"price",         type=b"number", step=b"0.0001",  required=True, value=b"%f"%current.price),
                        Edit  (text=electricmeter.em_lang.currency,      name=b"currency",      placeholder=electricmeter.em_lang.field_currency, required=True, value=current.currency),
                        Submit(text=electricmeter.em_lang.add_button,    name=b"add")
                ]),
                List(rate_items)
        ])
        await response.send_page(page)

@server.httpserver.HttpServer.add_route(b'/time_slots', menu=electricmeter.em_lang.menu_electricmeter, item=electricmeter.em_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 rate must be edited
        elif request.params.get(b"edit",None) is not None:
                current.update(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[b"name"] not in names:
                                rates_combo.append(Option(text=rate[b"name"], value=rate[b"name"], selected=b"selected" if current.rate == rate[b"name"] else b""))
                else:
                        break
                names[rate[b"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[b"color"]),
                                                Space(),Space(),
                                                Link(text=b"%s - %s : %s "%(tools.date.time_to_html(time_slot[b"start_time"]), tools.date.time_to_html(time_slot[b"end_time"]), time_slot[b"rate"]),href=b"time_slots?edit=%d"%identifier),
                                                Link(text=electricmeter.em_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.em_lang.remove_dialog)
                                        ]))
                else:
                        break
                identifier += 1

        # Build page
        page = webpage.mainpage.main_frame(request, response, args, electricmeter.em_lang.title_time_slots,
        [
                Form(
                [
                        Edit (text=electricmeter.em_lang.field_start,      name=b"start_time", type=b"time", required=True, value=tools.date.time_to_html(current.start_time)),
                        Edit (text=electricmeter.em_lang.field_end,        name=b"end_time",   type=b"time", required=True, value=tools.date.time_to_html(current.end_time)),
                        Label(text=electricmeter.em_lang.field_time_rate),
                        Select(rates_combo,name=b"rate",                                    required=True),
                        Edit (text=electricmeter.em_lang.field_color,      name=b"color", type=b"color",     required=True, value=current.color),
                        Submit(text=electricmeter.em_lang.add_button,      name=b"add")
                ]),
                List(time_slots_items)
        ])
        await response.send_page(page)

@server.httpserver.HttpServer.add_route(b'/geolocation', menu=electricmeter.em_lang.menu_electricmeter, item=electricmeter.em_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.em_lang.item_geolocation,
                Form(
                [
                        Edit  (text=electricmeter.em_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.em_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"] = tools.strings.tostrings(electricmeter.config.TimeSlotsConfig.get_cost(month))
        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.em_lang.menu_electricmeter, item=electricmeter.em_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(),
                                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.em_lang.type_price, value=b"price", selected= True if unit == b"price" else False),
                                        Option(text=electricmeter.em_lang.type_power, value=b"power", selected= True if unit == b"power" else False),
                                ], spacer=b"", text=electricmeter.em_lang.step_minutes, name=b"unit",                 event=b'onchange="this.form.submit()"')
                        ], class_=b'col-md-2'),
                        Div(
                        [
                                Switch(text=electricmeter.em_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.em_lang.power_consumed, geolocation.latitude, geolocation.longitude, with_temperature))
        ]
        page = webpage.mainpage.main_frame(request, response, args, electricmeter.em_lang.title_electricmeter + electricmeter.em_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.em_lang.menu_electricmeter, item=electricmeter.em_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.em_lang.item_geolocation,
                Form(
                [
                        Edit  (text=electricmeter.em_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.em_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"] = tools.strings.tostrings(electricmeter.config.TimeSlotsConfig.get_cost(day))
        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.em_lang.menu_electricmeter, item=electricmeter.em_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

        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"

        step = int(request.params.get(b"step",b"30"))
        steps = []
        for s in [1,2,3,5,10,15,30,60]:
                if s == step:
                        selected = True
                else:
                        selected = False
                steps.append(Option(text=b"%d %s"%(s, electricmeter.em_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()

        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-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.em_lang.step_minutes, name=b"step",                 event=b'onchange="this.form.submit()"')
                        ], class_=b'col-md-2'),
                        Div([
                                Select(
                                [
                                        Option(text=electricmeter.em_lang.type_price, value=b"price", selected= True if unit == b"price" else False),
                                        Option(text=electricmeter.em_lang.type_power, value=b"power", selected= True if unit == b"power" else False),
                                ], spacer=b"", text=electricmeter.em_lang.step_minutes, name=b"unit",                 event=b'onchange="this.form.submit()"')
                        ], class_=b'col-md-1'),
                        Div(
                        [
                                Switch(text=electricmeter.em_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.em_lang.power_consumed,
                        geolocation.latitude,
                        geolocation.longitude,
                        with_temperature))
        ]
        page = webpage.mainpage.main_frame(request, response, args,electricmeter.em_lang.title_electricmeter + electricmeter.em_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"] = tools.strings.tostrings(electricmeter.config.TimeSlotsConfig.get_cost(year))
        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.em_lang.menu_electricmeter, item=electricmeter.em_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.em_lang.type_price, value=b"price", selected= True if unit == b"price" else False),
                                        Option(text=electricmeter.em_lang.type_power, value=b"power", selected= True if unit == b"power" else False),
                                ], spacer=b"", text=electricmeter.em_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.em_lang.power_consumed, geolocation.latitude, geolocation.longitude, b""))
        ]
        page = webpage.mainpage.main_frame(request, response, args, electricmeter.em_lang.title_electricmeter + electricmeter.em_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.em_lang.menu_electricmeter, item=electricmeter.em_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.update(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[b"name"], rate[b"price"], rate[b"currency"], electricmeter.em_lang.from_the, tools.lang.translate_date(rate[b"validity_date"])), href=b"rate?edit=%d"%identifier ),
                                                Link(text=electricmeter.em_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.em_lang.remove_dialog)
                                        ]))
                else:
                        break
                identifier += 1

        # Build page
        page = webpage.mainpage.main_frame(request, response, args, electricmeter.em_lang.title_rate,
        [
                Form(
                [
                        Edit  (text=electricmeter.em_lang.name,          name=b"name",          placeholder=electricmeter.em_lang.field_rate,     required=True, value=current.name),
                        Edit  (text=electricmeter.em_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.em_lang.price,         name=b"price",         type=b"number", step=b"0.0001",  required=True, value=b"%f"%current.price),
                        Edit  (text=electricmeter.em_lang.currency,      name=b"currency",      placeholder=electricmeter.em_lang.field_currency, required=True, value=current.currency),
                        Submit(text=electricmeter.em_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.em_lang.menu_electricmeter, item=electricmeter.em_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 rate must be edited
        elif request.params.get(b"edit",None) is not None:
                current.update(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[b"name"] not in names:
                                rates_combo.append(Option(text=rate[b"name"], value=rate[b"name"], selected=b"selected" if current.rate == rate[b"name"] else b""))
                else:
                        break
                names[rate[b"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[b"color"]),
                                                Space(),Space(),
                                                Link(text=b"%s - %s : %s "%(tools.date.time_to_html(time_slot[b"start_time"]), tools.date.time_to_html(time_slot[b"end_time"]), time_slot[b"rate"]),href=b"time_slots?edit=%d"%identifier),
                                                Link(text=electricmeter.em_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.em_lang.remove_dialog)
                                        ]))
                else:
                        break
                identifier += 1

        # Build page
        page = webpage.mainpage.main_frame(request, response, args, electricmeter.em_lang.title_time_slots,
        [
                Form(
                [
                        Edit (text=electricmeter.em_lang.field_start,      name=b"start_time", type=b"time", required=True, value=tools.date.time_to_html(current.start_time)),
                        Edit (text=electricmeter.em_lang.field_end,        name=b"end_time",   type=b"time", required=True, value=tools.date.time_to_html(current.end_time)),
                        Label(text=electricmeter.em_lang.field_time_rate),
                        Select(rates_combo,name=b"rate",                                    required=True),
                        Edit (text=electricmeter.em_lang.field_color,      name=b"color", type=b"color",     required=True, value=current.color),
                        Submit(text=electricmeter.em_lang.add_button,      name=b"add")
                ]),
                List(time_slots_items)
        ])
        await response.send_page(page)