# 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"&lt;-", 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"-&gt;", 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"&lt;-", 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"-&gt;", 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"&lt;-", name=b"direction",  value=b"previous"),Space(),
                                    Button(type=b"submit", text=b"-&gt;", 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"&nbsp;&nbsp;&nbsp;&nbsp;", 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"&lt;-", 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"-&gt;", 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"&lt;-", 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"-&gt;", 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"&lt;-", name=b"direction",  value=b"previous"),Space(),
                                      Button(type=b"submit", text=b"-&gt;", 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"&nbsp;&nbsp;&nbsp;&nbsp;", 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)