Integração OMIE: preços horários, diários, mecanismo de ajuste

@luuuis uma duvida

nessa imagem, que está a vermelho esse valor corresponde à meia noite de Portugal ?
e é o valor sobre a venda e nao da compra correcto?

É o valor de referência para a hora 1 do dia, que corresponde ao período entre as 00:00 e 00:59 no horário CET usado em Espanha. Em Portugal continental corresponde então à última hora da véspera.

A v1(beta) já torna isso explicito ao associar uma hora a cada valor.

Já experimentei a versão beta, e pareceu funcionar tudo muito bem, mas não consegui colocar nos gráficos à conta das etiquetas de tempo. Fico à espera da atualização do wiki… :wink:

Basicamente onde tens isto:

  data_generator: >
    return entity.attributes.day_hours.map((price, hour) => [ new Date(new Date().setHours(hour, 0, 0, 0)), price ])

passas a usar:

  data_generator: >
    return ((hs) => Object.keys(hs).map((dt) => [ new Date(dt), hs[dt]
    ]))(entity.attributes.today_hours)

e igual para o entity.attributes.tomorrow_hours se for caso disso.

Portanto nesta imagem já está correcto esse valor de 90.3 corresponde então à meia noite correcto?
Pergunto isto, porque quero criar uma automação que me diga qual a hora mais barata do dia seguinte, para que consiga por alguns aparelhos gulosos a trabalhar. Se isto funcionar correctamente consigo saber quando ligar os aparelhos.
Idealmente a ideia era trabalhar com esses valores mais baixos juntamente com a produção dos paineis, ando a estudar uma forma “provisoria” de saber os picos de maior produção embora seja dificil.

Para fazer isso à maneira existem componentes de Programação Linear que calculam a melhor hora para ligar ou desligar as cargas baseado na previsão solar e preço de compra e venda do kWh. Pessoalmente tenho seguido com interesse o EMHASS Add-on.

Difícil porquê, não basta usar o Forecast.Solar ou o Solcast? Ou entendi mal?

Home Assistant - Home – Home Assistant 2023-05-02 08-22-08

1 Curtiu

Não conhecia isso vou nvestigar logo após o trabalho. Difícil no sentido que isso é uma previsão e não te dá certezas que nessa hora não exista algumas nuvens por exemplo que te estrague os cálculos. Ou estou a viajar demasiado nos pensamentos?

Para concluir o off-topic que eu próprio iniciei :sweat_smile: o Solcast pelo menos leva em contas nuvens (previsão e vai actualizando ao longo do dia). É certo que não há certezas a nível de meteorologia mas corresponde bastante bem à realidade.

Certo tens toda a razão iremos continuar a falar disto em outro tópico :slight_smile:

E em relação ao preço da Coopérnico? Será a mesma alteração?

Aí infelizmente é um pouco mais complicado, é preciso actualizar o template sensor primeiro e depois os gráficos.

Já tenho isso feito localmente, vou tentar publicar mais logo.

1 Curtiu

De momento não tenho tempo para actualizar o Wiki de modo que partilho aqui os sensores que tenho no meu ambiente de testes, já actualizados para a v1.

Gists:

2 Curtiram

Ontem libertei a v1.0.0. O wiki também está actualizado, se derem por alguma coisa que está mal avisem.

3 Curtiram

Muito obrigado, @luuuis!
Consegui adaptar tudo com a ajuda dos links e ficou fantástico!

1 Curtiu

Está bonito, sim senhor. Isso é com apexcharts-card? Hás-de me dizer como é que colocas a unidade (€) ao lado dos valores no eixo vertical.

nao queres partilhar o codigo desses graficos? :slight_smile:

Não tenho mérito nenhum: é a proposta do André Leal Thy_Hunter, que está mais acima no fórum. Não sei especificamente o que faz colocar o €, mas deve estar no código do André. Eu adaptei aos sensores… Cá vai:

type: custom:apexcharts-card
card_mod:
  style: |
    ha-card {
      width: 450px;
      border: none;
      background: transparent
    }
header:
  show: true
  title: OMIE Horário - Hoje e Venda à Rede
update_interval: 10m
now:
  show: true
span:
  end: day
graph_span: 24h
series:
  - entity: sensor.omie_spot_price_pt
    name: Hourly price
    yaxis_id: price
    stroke_width: 1
    type: column
    color: '#FA7000'
    group_by:
      func: last
      duration: 1h
    show:
      extremas: true
      legend_value: true
    data_generator: >
      return ((hs) => Object.keys(hs).map((dt) => [ new Date(dt), hs[dt]
      ]))(entity.attributes.today_hours)
  - entity: sensor.venda_24h_rede
    name: Injeção
    yaxis_id: injeção
    type: line
    stroke_width: 3
    group_by:
      fill: zero
      func: diff
      duration: 1h
      start_with_last: false
    color: green
yaxis:
  - id: injeção
    max: 4
    opposite: true
    show: true
    decimals: 2
    apex_config:
      forceNiceScale: 'yes'
      labels:
        show: true
        style:
          colors: '#ffffff'
          fontSize: 10px
        offsetX: 0
        offsetY: 0
      axisBorder:
        show: false
        color: '#78909C'
  - id: price
    show: true
    decimals: 1
    apex_config:
      forceNiceScale: 'yes'
      labels:
        show: true
        formatter: |
          EVAL:function(value) {
          let text = parseFloat(value).toFixed(2);
          let result = "€" +text.replace(".", ",");
          return result;
          }
        style:
          colors: '#ffffff'
          fontSize: 10px
        offsetX: 0
        offsetY: 0
      axisBorder:
        show: false
        color: '#78909C'
apex_config:
  tooltip:
    enabled: true
    shared: true
    followCursor: false
    intersect: false
    inverseOrder: false
    fillSeriesColor: true
    theme: false
    onDatasetHover:
      highlightDataSeries: false
    x:
      show: false
  legend:
    show: false
    position: top
  annotations:
    position: back
  chart:
    height: 250
    type: bar
  grid:
    show: true
    strokeDashArray: '0'
    borderColor: '#666666'

type: custom:apexcharts-card
card_mod:
  style: |
    ha-card {
      width: 450px;
      border: none;
      background: transparent
    }
header:
  show: true
  title: OMIE Horário - Amanhã
update_interval: 10m
now:
  show: true
span:
  start: day
  offset: +24h
graph_span: 24h
series:
  - entity: sensor.omie_spot_price_pt
    name: Hourly price
    yaxis_id: price
    stroke_width: 1
    type: column
    color: '#FA7000'
    group_by:
      func: last
      duration: 1h
    show:
      extremas: true
      legend_value: true
    data_generator: >
      return ((hs) => Object.keys(hs).map((dt) => [ new Date(dt), hs[dt]
      ]))(entity.attributes.tomorrow_hours)
yaxis:
  - id: price
    show: true
    decimals: 1
    apex_config:
      forceNiceScale: 'yes'
      labels:
        show: true
        formatter: |
          EVAL:function(value) {
          let text = parseFloat(value).toFixed(2);
          let result = "€" +text.replace(".", ",");
          return result;
          }
        style:
          colors: '#ffffff'
          fontSize: 10px
        offsetX: 0
        offsetY: 0
      axisBorder:
        show: false
        color: '#78909C'
apex_config:
  tooltip:
    enabled: true
    shared: true
    followCursor: false
    intersect: false
    inverseOrder: false
    fillSeriesColor: true
    theme: false
    onDatasetHover:
      highlightDataSeries: false
    x:
      show: false
  legend:
    show: false
    position: top
  annotations:
    position: back
  chart:
    height: 250
    type: bar
  grid:
    show: true
    strokeDashArray: '0'
    borderColor: '#666666'

type: custom:apexcharts-card
card_mod:
  style: |
    ha-card {
      width: 450px;
      border: none;
      background: transparent
    }
header:
  show: true
  title: Coopérnico Spot Bi-horário - Hoje e Compra à Rede
update_interval: 10m
now:
  show: true
span:
  end: day
graph_span: 24h
series:
  - entity: sensor.template_coopernico_spot_price_bihorario
    name: Hourly price
    yaxis_id: price
    stroke_width: 1
    type: column
    color: '#FA7000'
    group_by:
      func: last
      duration: 1h
    show:
      extremas: true
      legend_value: true
    data_generator: >
      return ((hs) => Object.keys(hs).map((dt) => [ new Date(dt), hs[dt]
      ]))(entity.attributes.today_hours)
  - entity: sensor.consumo_24h_rede
    name: Consumo
    yaxis_id: consumo
    type: line
    stroke_width: 3
    group_by:
      fill: zero
      func: diff
      duration: 1h
      start_with_last: false
    color: green
yaxis:
  - id: consumo
    max: 5
    opposite: true
    show: true
    decimals: 2
    apex_config:
      forceNiceScale: 'yes'
      labels:
        show: true
        style:
          colors: '#ffffff'
          fontSize: 10px
        offsetX: 0
        offsetY: 0
      axisBorder:
        show: false
        color: '#78909C'
  - id: price
    show: true
    decimals: 1
    apex_config:
      forceNiceScale: 'yes'
      labels:
        show: true
        formatter: |
          EVAL:function(value) {
          let text = parseFloat(value).toFixed(2);
          let result = "€" +text.replace(".", ",");
          return result;
          }
        style:
          colors: '#ffffff'
          fontSize: 10px
        offsetX: 0
        offsetY: 0
      axisBorder:
        show: false
        color: '#78909C'
apex_config:
  tooltip:
    enabled: true
    shared: true
    followCursor: false
    intersect: false
    inverseOrder: false
    fillSeriesColor: true
    theme: false
    onDatasetHover:
      highlightDataSeries: false
    x:
      show: false
  legend:
    show: false
    position: top
  annotations:
    position: back
  chart:
    height: 250
    type: bar
  grid:
    show: true
    strokeDashArray: '0'
    borderColor: '#666666'

type: custom:apexcharts-card
card_mod:
  style: |
    ha-card {
      width: 450px;
      border: none;
      background: transparent
    }
header:
  show: true
  title: Coopérnico Spot Bi-horário - Amanhã
update_interval: 10m
span:
  start: day
  offset: +24h
graph_span: 24h
series:
  - entity: sensor.template_coopernico_spot_price_bihorario
    name: Hourly price
    yaxis_id: price
    stroke_width: 1
    type: column
    color: '#FA7000'
    group_by:
      func: last
      duration: 1h
    show:
      extremas: true
      legend_value: true
    data_generator: >
      return ((hs) => Object.keys(hs).map((dt) => [ new Date(dt), hs[dt]
      ]))(entity.attributes.tomorrow_hours)
yaxis:
  - id: price
    show: true
    decimals: 1
    apex_config:
      forceNiceScale: 'yes'
      labels:
        show: true
        formatter: |
          EVAL:function(value) {
          let text = parseFloat(value).toFixed(2);
          let result = "€" +text.replace(".", ",");
          return result;
          }
        style:
          colors: '#ffffff'
          fontSize: 10px
        offsetX: 0
        offsetY: 0
      axisBorder:
        show: false
        color: '#78909C'
apex_config:
  tooltip:
    enabled: true
    shared: true
    followCursor: false
    intersect: false
    inverseOrder: false
    fillSeriesColor: true
    theme: false
    onDatasetHover:
      highlightDataSeries: false
    x:
      show: false
  legend:
    show: false
    position: top
  annotations:
    position: back
  chart:
    height: 250
    type: bar
  grid:
    show: true
    strokeDashArray: '0'
    borderColor: '#666666'

É o formatter do yaxis. :+1:

O SQL da Wiki só é válido para SQLite. Eu não sou muito entendido, mas consegui adaptar um dos sensores SQL para MariaDB.

Deixo aqui caso seja util a alguém, e caso saibam de uma forma melhor de conseguir o mesmo, aceito sugestões.

name: OMIE PT Spot Price Month to Date Average
query: |-
  SELECT FROM_UNIXTIME(stats.start_billing_ts) AS window_start,
        FROM_UNIXTIME(stats.start_of_day_ts) AS window_end,
        FROM_UNIXTIME(MIN(start_ts)) AS oldest_measurement,
        FROM_UNIXTIME(MAX(start_ts)) AS newest_measurement,
        COUNT(*) AS measurement_count,
        ROUND(AVG(s.mean), 2) AS mean
  FROM statistics s 
  JOIN statistics_meta m ON s.metadata_id = m.id 
  CROSS JOIN (
      SELECT UNIX_TIMESTAMP(CASE 
                                WHEN DAY(NOW()) > billing_offset 
                                THEN CONCAT_WS('-', YEAR(NOW()), MONTH(NOW()), billing_offset) 
                                ELSE CONCAT_WS('-', YEAR(NOW() - INTERVAL 1 MONTH), MONTH(NOW() - INTERVAL 1 MONTH), billing_offset) 
                            END) AS start_billing_ts,
            UNIX_TIMESTAMP(CURDATE()) AS start_of_day_ts
      FROM (
          -- ⚠️ ADJUST HERE AS NECESSARY (e.g. 20 to start billing cycle at midnight on day 21):
          SELECT 20 AS billing_offset
          ) cfg
  ) AS stats
  WHERE statistic_id = 'sensor.omie_spot_price_pt' 
  AND start_ts >= stats.start_billing_ts 
  AND start_ts < stats.start_of_day_ts;
column: 'mean'
unit_of_measurement: 'EUR/MWh'
1 Curtiu

notei que tens uma entity chamada

sensor.venda_24h_rede

isto é baseado em quê exatamente, extrais do teu inverter ou algum custom que construiste?

acho estranho estar a ter problemas com todos os graficos que referem o valor do dia seguinte, quaisquer configuração que use (inclusive um simple copy & paste da wiki) mete-se o grafico sempre em Loading… e não sai dai.


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


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