davidusb-geek / emhass

emhass: Energy Management for Home Assistant, is a Python module designed to optimize your home energy interfacing with Home Assistant.
MIT License
278 stars 54 forks source link

Feature Request: get Solar Forecast data from HASS #108

Closed HACS-bank closed 10 months ago

HACS-bank commented 1 year ago

Home Assistant users may well already have a Solcast account in which case adding it to EMHASS may exceed their API allowance.

Perhaps EMHASS could detect and access Solcast data already in HASS Energy Dashboard?

https://community.home-assistant.io/t/solcast-global-solar-power-forecast-integration/334681 goes into details.

Octofinger commented 1 year ago

This is pretty easily managed by passing the Solcast forecast to EMHASS instead of letting EMHASS query Solcast itself. Then leave to HA to control when Solcast is updated so you don't exceed your API limit.

Extract the Solcast forecast for the next 24 hours to a variable as a list. Solcast use kWh/hour values, so I just multiply by 1000 to get a power average for that hour. Adapt the logic if you use the more detailed 30 minute Solcast forecast.

{%- set solcast=((state_attr('sensor.solcast_forecast_today', 'forecast') | 
    map(attribute='pv_estimate') | map('multiply',1000) | map('int') | list
    + state_attr('sensor.solcast_forecast_tomorrow', 'forecast') | 
    map(attribute='pv_estimate') | map('multiply',1000) | map('int') | list))
    [now().hour:][:24] %}

Pass the variable to the call to your optimization as described in the documentation here: https://emhass.readthedocs.io/en/latest/intro.html#passing-your-own-data. E.g. like this

"curl -i -H 'Content-Type:application/json' -X POST -d '{\"pv_power_forecast\" : {solcast} }' http://localhost:5000/action/dayahead-optim
davidusb-geek commented 1 year ago

Thanks @Octofinger for your comment. A long time ago I tried to find a way to import the data from the Energy Management Dashboard, but I couldn't find a proper way. I even opened a topic here: https://community.home-assistant.io/t/access-data-from-forecast-solar/435964 The easiest is like Octofinger said, if you already have that data in Home Assistant just pass it to EMHASS using the templates provided.

HACS-bank commented 1 year ago

If only the Solcast service within HASS would save all the data from the API and make it available to you.

HACS-bank commented 10 months ago

@Octofinger , I am just coming back to this after a long time away from HA :) and I now realise that I don't completely understand your method. Where in HA do you use the {%- set solcast=((state_attr ... [now().hour:][:24] %} construct? Is this in the configuration.yaml definition of the shell_command, or somewhere else?

Octofinger commented 10 months ago

@HACS-bank I set this in a HA script that generates the entire JSON that is then passed to a REST command that is set up in configuration.yaml. That way I can tweak the REST call to my hearts content without having to reboot HA every time...

The REST command in configuration.yaml

rest_command:
  emhass_naive_mpc_optim_2:
    url: 'http://localhost:5000/action/naive-mpc-optim'
    method: 'POST'
    content_type: 'application/json'
    payload: >-
      { {{json}} }

The script. Sorry that HA "pretty prints" scripts to total obfuscation...

alias: EMHASS Naive MPC optim call
mode: single
variables:
  json_string: >
    {%- set tax=states('input_number.elpris_skatt_per_kwh_ink_moms')|float %}
    {%- set
    transfer_fee=states('input_number.elpris_vattenfall_overforingsavgift_per_kwh_inkl_moms')|float
    %} {%- set
    extra_fee=states('input_number.elpris_tranas_paslag_per_kwh_ink_moms')|float
    %} {%- set
    tax_return=states('input_number.elpris_skatteaterbaring_per_kwh')|float %}
    {%- set
    extra_sales_fee=states('input_number.elpris_tranas_avdrag_per_kwh_ink_moms')|float
    %} {%- set
    energy_compensation=states('input_number.elpris_vattenfall_energiersattning_per_kwh')|float
    %} {%- if
    state_attr('sensor.nordpool_kwh_se3_sek_0_10_025','tomorrow_valid') == true
    %}
      {%- set nordpool=((state_attr('sensor.nordpool_kwh_se3_sek_0_10_025', 'raw_today') | map(attribute='value') | list
        + state_attr('sensor.nordpool_kwh_se3_sek_0_10_025', 'raw_tomorrow') | map(attribute='value') | list))
        [now().hour:][:24] %}
    {%- else %}
      {%- set nordpool=(state_attr('sensor.nordpool_kwh_se3_sek_0_10_025', 'raw_today')
      | map(attribute='value') | list) [now().hour:][:24] %}
    {%- endif %} {%- set nordpool_sell = namespace(values=[]) %} {%- set
    nordpool_buy = namespace(values=[]) %} {%- for i in nordpool %} {%- set
    nordpool_sell.values=nordpool_sell.values+[((i+energy_compensation-extra_sales_fee+tax_return)/100)|round(2)]%}
    {%- set
    nordpool_buy.values=nordpool_buy.values+[((i+transfer_fee+extra_fee+tax)/100)|round(2)]%}
    {%- endfor %} {%- set solcast=((state_attr('sensor.solcast_forecast_today',
    'forecast') | map(attribute='pv_estimate') | map('multiply',1000) |
    map('int') | list
      + state_attr('sensor.solcast_forecast_tomorrow', 'forecast') | map(attribute='pv_estimate') | map('multiply',1000) | map('int') | list))
      [now().hour:][:24] %}
    {%- set horizon = [nordpool_sell.values|length, nordpool_buy.values|length,
    solcast|length]|min %} {%- set soc_init =
    min(max((states('sensor.battery_level')|float(0)/100)|round(2),0.05),0.95)
    %} "prediction_horizon": {{ horizon }}, "soc_init": {{ soc_init }},
    "soc_final": 0.5, "def_total_hours": [], "load_cost_forecast": {{
    nordpool_buy.values }}, "prod_price_forecast": {{ nordpool_sell.values }},
    "pv_power_forecast": {{ solcast }}
sequence:
  - service: rest_command.emhass_naive_mpc_optim_2
    data:
      json: "{{ json_string }}"
robinostlund commented 10 months ago

Seems that providing data in pv_power_forecast doesn't work for me, i am providing a list with data and the length of the list is the same as prediction_horizon. What happens is that the pv_power_forecast data gets summarized and shown on the first hour in emhass like this:

Screenshot 2023-11-01 at 10 25 05

This is the data in pw_power_forecast: [2627, 3069, 3357, 2850, 1918, 655, 9, 0, 0, 0, 0, 0, 0, 0]

poolski commented 2 months ago

This is pretty easily managed by passing the Solcast forecast to EMHASS instead of letting EMHASS query Solcast itself. Then leave to HA to control when Solcast is updated so you don't exceed your API limit.

Extract the Solcast forecast for the next 24 hours to a variable as a list. Solcast use kWh/hour values, so I just multiply by 1000 to get a power average for that hour. Adapt the logic if you use the more detailed 30 minute Solcast forecast.

{%- set solcast=((state_attr('sensor.solcast_forecast_today', 'forecast') | 
    map(attribute='pv_estimate') | map('multiply',1000) | map('int') | list
    + state_attr('sensor.solcast_forecast_tomorrow', 'forecast') | 
    map(attribute='pv_estimate') | map('multiply',1000) | map('int') | list))
    [now().hour:][:24] %}

Pass the variable to the call to your optimization as described in the documentation here: https://emhass.readthedocs.io/en/latest/intro.html#passing-your-own-data. E.g. like this

"curl -i -H 'Content-Type:application/json' -X POST -d '{\"pv_power_forecast\" : {solcast} }' http://localhost:5000/action/dayahead-optim

I'm a bit confused about where to define this variable. I'm using the EMHASS extension, so its inner workings are a bit unclear to me.