Filtro para remoção de dropouts com Restful Sensor

Para o meu painel de energia, estou puxando os dados do inversor da cloud para o meu inversor Studer. Infelizmente, eu só tenho um API da cloud em vez de um local. Quando estou puxando da cloud, às vezes eu tenho problemas com dropouts. Quando estas dropouts ocorrem, o valor pode voltar como “unavailable”, mas outras vezes como 0, o que pode realmente estragar os cálculos, como a produção horária de PV em kWh.

A cloud de Studer parece ser buggy, pois tenho problemas semelhantes com a web de relatórios Studer, e a aplicação móvel Studer. Já vi outros reclamarem de problemas semelhantes com outros puxões de dados baseados na cloud. Eu tentei um filtro outlier, mas não tive sorte com ele. Alguém pode recomendar um filtro que eu possa tentar que ignore as dropouts a 0? Talvez um filtro template? Eu ainda não tenho experiência com templates, então qualquer code que você já tenha seria apreciado.

Se utilizares Node Red é muito fácil filtrar os valores 0 e unknown.

Se utilizares templates tens alguma exemplos na página oficial.

1 Curtiu

Tentei seguir um exemplo na página do Template, mas estou a receber um erro:
Invalid config for [template]: invalid template (TemplateSyntaxError: expected token ‘end of print statement’, got ‘else’) for dictionary value @ data[‘sensor’][1][‘state’]. Got “{{ is_state_attr((‘sensor.studer’, ‘energy’)[‘solar’] , 0) else state_attr(‘sensor.studer’, ‘energy’)[‘solar’] }}”. (See /config/configuration.yaml, line 180).

Original:

    - name: "Solar Production"
      state: "{{ state_attr('sensor.studer', 'energy')['solar'] }}"
      unit_of_measurement: "kWh"
      unique_id: "studer.solar_prod"
      device_class: energy
      state_class: total_increasing

Modificado:

- name: "Solar Production"
      state: "{{ is_state_attr(('sensor.studer', 'energy')['solar'] , 0) else state_attr('sensor.studer', 'energy')['solar'] }}"
      unit_of_measurement: "kWh"
      unit_of_measurement: "kWh"
      unique_id: "studer.solar_prod"
      device_class: energy
      state_class: total_increasing

Estás a usar else sem o resto das condições…

template:
#
  - sensor:
#
    - name: "Solar Production"
      state: >-
        {% set x = state_attr('sensor.studer', 'energy')['solar'] %}
        {% if x > 0 %}
          {{ x }}
        {% else %}
          {{ states('sensor.solar_production') }}
        {% endif %}
      unit_of_measurement: "kWh"
      unique_id: "studer.solar_prod"
      device_class: energy
      state_class: total_increasing

Obrigado pela sugestão. Creio que “>-” é um erro tipográfico, por isso substituí-o por “>”. Agora eu recebo o seguinte erro:
Invalid config for [template]: [value_template] is an invalid option for [template]. Check: template->sensor->1->value_template. (See /config/configuration.yaml, line 180).

Se eu substituir “{{ states(‘sensor.solar_production’) }}” com um saída mais trivial “{{ x }}” Eu recebo a seguinte mensagem de erro:
Error loading /config/configuration.yaml: while scanning for the next token found character ‘%’ that cannot start any token in “/config/configuration.yaml”, line 198, column 10

template:
#
  - sensor:
#
    - name: "Sun Elevation"
      state: >-
        {% set x = state_attr('sun.sun', 'elevation')|float(0) %}
        {% if x > 0 %}
          {{ x }}
        {% else %}
          {{ 0 }}
        {% endif %}
      state_class: measurement
      unit_of_measurement: '°'
      icon: "mdi:sun-angle"

É que estou a perder o “if” no condicional? Se eu adicionar um “if” Eu entendo:

`state: "{{ if is_state_attr(('sensor.studer', 'energy')['solar'] , 0) else state_attr('sensor.studer', 'energy')['solar'] }}"`
'''
Eu recebo a seguinte mensagem de erro:
* Invalid config for [template]: [value_template] is an invalid option for [template]. Check: template->sensor->1->value_template. (See /config/configuration.yaml, line 180).

Este é o formato que funcionou para mim, que é exatamente como você tinha sugerido. Eu posso ter tido alguns caracteres brancos algures no código que estavam a causar problemas. Também para tentar depurar partes do código, inseri “#” para comentar algumas linhas. Parece que não é permitido colocar comentários como esse nas declarações IF. Eu descobri que o código parece funcionar igualmente se eu usar “state: >” ou “state: >-”. Eu não sei qual é a diferença entre os dois. Onde posso encontrar mais detalhes sobre a formatação de templates?

template:
    - name: "Solar Production"
      unit_of_measurement: "kWh"
      unique_id: "studer.solar_prod"
      device_class: energy
      state_class: total_increasing
#      state: "{{ state_attr('sensor.studer', 'energy')['solar'] }}"
      state: >-
        {% set x = state_attr('sensor.studer', 'energy')['solar'] %}
        {% if x > 0 %}
          {{ x }}
        {% else %}
          {{ states('sensor.solar_prod') }}
        {% endif %}
##      state: "{{ if is_state_attr(('sensor.studer', 'energy')['solar'] , 0) else state_attr('sensor.studer', 'energy')['solar'] }}"

Há uma instância legítima quando o template deve aceitar 0 como entrada, que é todas as noites às 23h, o equipamento repõe o contador totalizador de kWh de volta a 0. Alguma dica sobre como posso acomodar isso?
Pensando bem, talvez ter a contagem de kWh permanecendo alta não seja um problema, uma vez que não vai aumentar durante a noite, não haverá nenhum registro de produção adicional, mesmo que o sensor do equipamento seja 0. Então, no dia seguinte, quando o sensor do equipamento se desliga 0, a contagem de kWh irá para o valor baixo lido do sensor. Isto resultará no que deve ser um erro minúsculo na contagem total de kWh.

1 Curtiu

A mudança para o template parece estar a funcionar. O sensor já não vai a 0. Embora a outra parte do condicional se comporte de forma diferente do que eu esperava. Eu pensei que o

        {% else %}
          {{ states('sensor.solar_prod') }}

teria feito com que o sensor repetisse o último valor numérico. Alguma ideia do porquê de não funcionar dessa forma?

O que o else faz é dar um valor no caso de nunhuma das condições anteriores se aplicar.

O que eu entendi que aconteceria é que se o teste do número positivo falhasse, o else e que o valor anterior do sensor seria impresso de volta para o sensor, para que o valor do sensor permaneça com o último valor positivo.

{% set x = state_attr('sensor.studer', 'energy')['solar']|float(0) %}

Eu acrescentei o pipe com o float filtro com um valor padrão de 0. Verá os resultados amanhã quando o equipamento começar a fornecer valores positivos e o “unavailable” O estado está apagado.

    - name: "Solar Production"
      unit_of_measurement: "kWh"
      unique_id: "studer.solar_prod"
      device_class: energy
      state_class: total_increasing
      state: >-
        {% set x = state_attr('sensor.studer', 'energy')['solar']|float(0) %}
        {% if x > 0 %}
          {{ x }}
        {% else %}
          {{ states('sensor.solar_prod') }}
        {% endif %}

Estou a ver como isto deve funcionar. O float(0) deve converter quaisquer entradas não-numéricas para 0, depois o ramo > teste para o else para valores não positivos e, finalmente, imprimir o valor do sensor anterior para reter o último valor numérico bom. Mas o painel ainda mostra estados não numéricos, e o gráfico da história não mostra o último valor numérico. Parece que o float(0) não está substituindo os estados não-numéricos por 0.
Tanto o Battery SOC como a Solar Production utilizam templates semelhantes.
image

O float(0) tira as casas decimais. Talvez o melhor seja leres um pouco sobre templates e Jinja2.

Pode ser que eu esteja a entender mal o que está na página de documentação da jinja. https://jinja.palletsprojects.com/en/latest/templates/
jinja-filters.float( value: Any , default: float = 0.0 ) → float

Convert the value into a floating point number. If the conversion doesn’t work it will return 0.0 . You can override this default using the first parameter.

O que eu entendo aqui é que float(0) irá converter valores numéricos para ponto flutuante, e não numéricos para um valor de ponto flutuante de 0.0 O que é que eu estou a entender mal aqui?

1 Curtiu

Não tira. Isso é o round(0)


Copyright © 2017-2021. Todos os direitos reservados
CPHA.pt - info@cpha.pt


FAQ | Termos de Serviço/Regras | Política de Privacidade