erikkastelec / hass-WEM-Portal

Custom component for retrieving sensor information from Weishaupt WEM Portal
MIT License
44 stars 10 forks source link

HA Energy Dashboard #19

Closed dm82m closed 2 years ago

dm82m commented 2 years ago

Hey guys,

as you already know, HA has introduced the energy dashboard feature and I really like it. What I did so far was, that I created a template sensor in configuration.yaml like this:

  - platform: template
    sensors:
      wtc_g_pc_tageswarmemenge_vortag_gesamt_we0_m3:
        unit_of_measurement: "m³"
        value_template: '{{ states("sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0") | replace(",",".") | float / 10 }}'

so I am using the gas energy used yesterday and transform it to m3 by dividing the value through 10. m3 is needed by the energy dashboard, that is why I am doing that.

then I use the customize.yaml to enable statistics for this new sensor by:

sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0_m3:
  state_class: total_increasing
  icon: mdi:gas-cylinder
  device_class: gas

and then I add this new sensor to the energy dashboard of HA.

The problem I encounter is, that if I restart HA or the hass-WEM-Portal plugin itself runs in failure and gets back online the data is re-requested and thus my custom sensor gets new data and that leads to the situation that the energy dashboard adds the amount AGAIN and that leads to complete wrong data.

so on a perfect day (no HA server restart and no outage of the wemportal) it is correct:

image

but on a day with one or more restarts its a pain:

image image

Is anyone of you having an idea on how to solve that?

Best, Dirk

dm82m commented 2 years ago

I modified my approach a bit and got it solved that the gas usage of last day is only used once a day within the energy dashboard. but I have the problem that the data is wrong. I assume that this problem is related to the energy dashboard so I filed a issue at HA: https://github.com/home-assistant/core/issues/69184

dm82m commented 2 years ago

I solved the issue with a few steps and will share how I did that here:

1) Create a new template sensor in configuration.yaml that will get '0' on initialization:

sensor:
  - platform: template
    sensors:
      wtc_g_pc_tageswarmemenge_vortag_gesamt_we0_m3:
        unit_of_measurement: "m³"
        value_template: 0

2) Create an automation that fills that template sensor once a day with the data. This is needed due to HA restarts. If we restart HA then the state of gas usage is re-set and that would lead to wrong data in energy dashboard. So I put that to automations.yaml. What I also do here is to transform from kWh to m3.

- alias: "Gas Vortag"
  trigger:
    - platform: time
      at: '05:00:00'
  action:
    - service: python_script.set_state
      data_template:
        entity_id: sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0_m3
        state: '{{ states("sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0") | float / 10 }}'
        updated_by: python_script.set_state

3) The python_script I use in 2 is put in the folder python_scripts with file name set_state.py and enabled in configuration.yaml via pythons_script:

# Usage
#
# - service: python_script.set_state
#   data_template:
#     entity_attr:
#       nuki_id: '{{ trigger.json.nukiId }}'
#     state: '{{ trigger.json.stateName }}'
#     # Attributes
#     battery_critical: '{{ trigger.json.batteryCritical }}'
#     updated_by: python_script.set_state

LOG_HANDLE = "python_script.set_state"

ATTR_ALLOW_CREATE = "allow_create"
ATTR_ENTITY_ATTR = "entity_attr"
ATTR_ENTITY_ID = "entity_id"
ATTR_STATE = "state"

def get_entity_id(data):
    entity_id = data.get(ATTR_ENTITY_ID)
    if entity_id:
        entity = hass.states.get(entity_id)
        if entity:
            return entity_id
    # Search for entity matching attribute spec
    entity_attr = data.get(ATTR_ENTITY_ATTR)
    for entity_id in hass.states.entity_ids():
        state = hass.states.get(entity_id)
        # Look for first matching entity id
        for attr_name, attr_val in entity_attr.items():
            if str(state.attributes.get(attr_name)) == str(attr_val):
                logger.debug(f"{LOG_HANDLE}: matched -> {entity_id} ({attr_name}={attr_val})")
                return entity_id

entity_id = get_entity_id(data)
logger.debug(f"{LOG_HANDLE}: Found {entity_id}")

if entity_id is None and not data.get(ATTR_ALLOW_CREATE):
    logger.error(
        f"{LOG_HANDLE}: Unable to find entity matching search criteria. You may want to add {ATTR_ALLOW_CREATE}."
    )
else:
    state = hass.states.get(entity_id)  # current state
    new_state = data.get(ATTR_STATE, state.state)  # default to current state
    new_attributes = state.attributes.copy()

    # Update attributes
    reserved_keys = [ATTR_ALLOW_CREATE, ATTR_ENTITY_ATTR, ATTR_ENTITY_ID, ATTR_STATE]
    for key, val in {x: data[x] for x in data if x not in reserved_keys}.items():
        logger.debug(f"{LOG_HANDLE}: {key}={val}")
        new_attributes[key] = val

    hass.states.set(entity_id, new_state, new_attributes)

4) Due to the fact that the data is going to 0 every day the last_reset needs to be set. As I found no suitable way doing that I created a new energy meter in configuration.yaml:

utility_meter:
  gas_vortag:
    source: sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0_m3
    cycle: daily

And then I add some custom attributes to this new utility meter in customize.yaml to enabe the statistics feature.

sensor.gas_vortag:
  state_class: total_increasing
  icon: mdi:gas-cylinder
  device_class: gas
  unit_of_measurement: "m³"

5) Add that sensor.gas_vortag to the energy dashboard.

6) If you have a better idea, please feel free to tell me! :)

SKis274 commented 1 year ago

Hey there,

I had problems with the python script, so I was looking for another solution. At the end I solve it with two triggered template sensors defined in configuration.yaml.

template:
  - trigger:
    - platform: time
      at: "01:00:00"
    sensor: 
      - name: Gasverbrauch Warmwasser
        unique_id: sensor.gasverbrauch_warmwasser
        state: "{{ states('sensor.gasverbrauch_warmwasser')|float + states('sensor.wtc_g_pc_tageswarmemenge_vortag_warmwasserbetrieb_we0')|float }}"
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total_increasing
  - trigger:
    - platform: time
      at: "01:00:00"
    sensor: 
      - name: Gasverbrauch Heizung
        unique_id: sensor.gasverbrauch_heizung
        state: "{{ states('sensor.gasverbrauch_heizung')|float + states('sensor.wtc_g_pc_tageswarmemenge_vortag_heizbetrieb_we0')|float }}"
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total_increasing

Both can be added directly to the energy dashboard.

Feel free to optimize it :)

thoe25 commented 1 year ago

Hi @SKis274,

I copied your code into my configuration.yaml, but the "Gasverbrauch Warmwasser" and "Gasverbrauch Heizung" status is not available. The Energy Dashboard shows the following:

statistics_not_defined

Entität nicht verfügbar Der Status dieser konfigurierten Entitäten ist derzeit nicht verfügbar:

statistics_not_defined

Entität nicht verfügbar Der Status dieser konfigurierten Entitäten ist derzeit nicht verfügbar:

sensor.wtc_g_pc_tageswarmemenge_vortag_warmwasserbetrieb_we0 and sensor.wtc_g_pc_tageswarmemenge_vortag_heizbetrieb_we0 are available with values.

Do you have an idea why it doesn't work?

Thank you.

SKis274 commented 1 year ago

Hello @thoe25,

I had the same problem. It was trigged by this issue: https://github.com/erikkastelec/hass-WEM-Portal/issues/37

Because of this the template sensor starts writing uncorrect values to the database.

image

To solve this issue I modifed both template sensors for ONE TIME! I set the time-at value some minutes in future and the state value to the correct value it has to been. In case of the heating value it was 190.19. You get the values from the wem portal for example. Then I reloaded the template-entities in the yaml dev-tools.

template:
  - trigger:
    - platform: time
      at: "21:15:00"
    sensor: 
      - name: Gasverbrauch Warmwasser
        unique_id: sensor.gasverbrauch_warmwasser
        state: "{{ SET_HERE_THE_CORRECT_VALUE }}"
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total_increasing
  - trigger:
    - platform: time
      at: "21:15:00"
    sensor: 
      - name: Gasverbrauch Heizung
        unique_id: sensor.gasverbrauch_heizung
        state: "{{ SET_HERE_THE_CORRECT_VALUE }}"
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total_increasing

After the time passed by a new record was created with a correct value in the database. Then I changed it all back and it still works right now.

Please let me know if this fix works for you. And maybe it's possible to build a fix for future issues right in the template sensor :)

Gonzo-Goe commented 1 year ago

Hey Together, I've try both variants, but it won't work. At the first one the sensor gives me "0" and i can not integrate the sensor.gas_vortag in the Energy Dashboard.

at the second one the sensor.gasverbrauch_warmwasser, sensor.gasverbrauch_heizung gives me unavailable. I dont know why.

Can someone Help me?

Thank you

Gonzo-Goe commented 1 year ago

Hey Dirk, after our mail from Today here my stats:

# Loads default set of integrations. Do not remove.
default_config:

# Text to speech
tts:
  - platform: google_translate

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

wemportal:
  #scan_interval: 300
  #api_scan_interval: 300
  #language: de
  #mode: both
  username: ***
  password: ***

sensor:
  - platform: template
    sensors:
      wtc_g_pc_tageswarmemenge_vortag_gesamt_we0_m3:
        unit_of_measurement: "m³"
        value_template: 0

logger:
  default: warn
  logs:
    custom_components.wemportal: debug

http:
    base_url: ***
    ssl_certificate: /ssl/fullchain.pem
    ssl_key: /ssl/privkey.pem
    cors_allowed_origins:
    - https://google.com
    - Https://www.home-assistant.io
    ip_ban_enabled: true
    login_attempts_threshold: 5

utility_meter:
  gas_vortag:
    source: sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0_m3
    cycle: daily

automations.yaml:

- id: '1679049078753'
  alias: "Gas Vortag"
  trigger:
    - platform: time
      at: '05:00:00'
  action:
    - service: python_script.set_state
      data_template:
        entity_id: sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0_m3
        state: '{{ states("sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0") | float / 10 }}'
        updated_by: python_script.set_state

/config/Python_Scripts/set_state.py:

# Usage
#
# - service: python_script.set_state
#   data_template:
#     entity_attr:
#       nuki_id: '{{ trigger.json.nukiId }}'
#     state: '{{ trigger.json.stateName }}'
#     # Attributes
#     battery_critical: '{{ trigger.json.batteryCritical }}'
#     updated_by: python_script.set_state

LOG_HANDLE = "python_script.set_state"

ATTR_ALLOW_CREATE = "allow_create"
ATTR_ENTITY_ATTR = "entity_attr"
ATTR_ENTITY_ID = "entity_id"
ATTR_STATE = "state"

def get_entity_id(data):
    entity_id = data.get(ATTR_ENTITY_ID)
    if entity_id:
        entity = hass.states.get(entity_id)
        if entity:
            return entity_id
    # Search for entity matching attribute spec
    entity_attr = data.get(ATTR_ENTITY_ATTR)
    for entity_id in hass.states.entity_ids():
        state = hass.states.get(entity_id)
        # Look for first matching entity id
        for attr_name, attr_val in entity_attr.items():
            if str(state.attributes.get(attr_name)) == str(attr_val):
                logger.debug(f"{LOG_HANDLE}: matched -> {entity_id} ({attr_name}={attr_val})")
                return entity_id

entity_id = get_entity_id(data)
logger.debug(f"{LOG_HANDLE}: Found {entity_id}")

if entity_id is None and not data.get(ATTR_ALLOW_CREATE):
    logger.error(
        f"{LOG_HANDLE}: Unable to find entity matching search criteria. You may want to add {ATTR_ALLOW_CREATE}."
    )
else:
    state = hass.states.get(entity_id)  # current state
    new_state = data.get(ATTR_STATE, state.state)  # default to current state
    new_attributes = state.attributes.copy()

    # Update attributes
    reserved_keys = [ATTR_ALLOW_CREATE, ATTR_ENTITY_ATTR, ATTR_ENTITY_ID, ATTR_STATE]
    for key, val in {x: data[x] for x in data if x not in reserved_keys}.items():
        logger.debug(f"{LOG_HANDLE}: {key}={val}")
        new_attributes[key] = val

    hass.states.set(entity_id, new_state, new_attributes)

costomize.yaml:

sensor.gas_vortag:
  state_class: total_increasing
  icon: mdi:gas-cylinder
  device_class: gas
  unit_of_measurement: "m³"

I hope you can help me. Daniel

dm82m commented 1 year ago

please check if the sensor sensor.wtc_g_pc_tageswarmemenge_vortag_gesamt_we0 is existing in your setup? or if the name is different? the sensor should be provided by the wemportal integration.

Gonzo-Goe commented 1 year ago

where can i see it ?

dm82m commented 1 year ago

Check the entities that are provided by the wemportal integration.

Gonzo-Goe commented 1 year ago

These are all entities that under the WEMPortal integration WEM

dm82m commented 1 year ago

You need to enable mode: both otherwise you are only using mobile api and this one does not give you the date you need.

Gonzo-Goe commented 1 year ago

the mode in the Configuration.yaml is on Both, how can i Refresh the entities ?

dm82m commented 1 year ago

It has a # infront, that means commented out and so not active. Remove the # and restart your server.

Gonzo-Goe commented 1 year ago

no i Have the entity. I will try to add it.