EMHASS: An Energy Management for Home Assistant

Hi all,

Struggling here to minimise grid import this time of year. The problem is that the forecast for charging the battery sometimes uses import from the grid during the day on moments that the PV output (sensor.inverter_ingangsvermogen) is less then the Battery Power Forecast (EMHASS calculates zero grid import). I am trying to prevent this with this automation, but doesn’t work, can’t figure out what’s wrong. It uses the actual PV output instead of the calculated Battery Power Forecast.
What am I doing wrong here?

- conditions:
          - condition: numeric_state
            entity_id: sensor.battery_batterijpercentage
            below: sensor.soc_batt_forecast
          - condition: numeric_state
            entity_id: sensor.p_batt_forecast
            above: sensor.inverter_ingangsvermogen
          - condition: numeric_state
            entity_id: sensor.p_grid_forecast
            below: 1
            enabled: true
        sequence:
          - service: huawei_solar.forcible_charge_soc
            data:
              target_soc: "{{states('sensor.soc_batt_forecast')|int(0)}}"
              power: >-
                {{(states('sensor.inverter_ingangsvermogen') | int(0) | abs) -
                (states('sensor.power_load_no_var_loads') | int(0) | abs)}}

With Add-on from 0.9.2 to 0.10.2 I had nothing to do manually.
set_deferrable_startup_penalty: 0 was already there, I just had to reduce the list as it was showing one extra item (2) compared to my existing list (1) of deferrable loads.
But even with 2 items my MPC optimization worked, before I caught this one.
About the PV inverter model it’s worth having a look at the dedicated app by David, I think.

1 Like

Yes that should be it. Pick a proper inverter from the database. Yes the dedicated webapp can help on this: https://emhass-pvlib-database.streamlit.app/

1 Like

another thank you to @davidusb.
I’m loving the ability to use Pc_max with my hybrid inverter. It allows me to increase and reduce my max charge rate based on the time of day i run the optimisations to allow EMHASS to handle increased charging when the sun is out.

At the moment I’m experimenting with adding the average PV Forecast over the next 6 hours to my inverters max charge rate when i run the MPC optimisation each minute.
Here’s my template sensor, which is based on what @markpurcell uses for the Solcast PV Forecast:

Edit 1: Removed sort function.
{{([states("sensor.power_solar_generation")|int(0)] + state_attr("sensor.solcast_pv_forecast_forecast_today", "detailedForecast")|selectattr("period_start","gt",utcnow()) | map(attribute="pv_estimate")|map("multiply",1000)|map("int")|list + state_attr("sensor.solcast_pv_forecast_forecast_tomorrow", "detailedForecast")|selectattr("period_start","gt",utcnow()) | map(attribute="pv_estimate")|map("multiply",1000)|map("int")|list)[:12] | average|int(0) +5000 }}

which I then pass to "Pc_max": in my rest command.

I’ll continue to play with this and see if 6 hours is the right window to consider, or if I need to do some further conditions based on the time of day. Unfortunately it’s overcast for the next few days so not the best time for testing.

I upgraded to 0.10.2 without issue except I am getting an MPC POST failure every 30 minutes. I’ve seen this behaviour before and usually just ignore it. I POST every 60 seconds.

Logs:

2024-07-08 10:29:56,947 - web_server - INFO - Passed runtime parameters: {'prod_price_forecast': [0.29, 0.28, 0.18, 0.1, 0.1, 0.1, 0.12, 0.1, 0.1, 0.1, 0.17, 0.13, 0.17, 0.16, 0.33, 0.34, 0.34, 0.34, 0.31, 0.17, 0.26, 0.16, 0.13, 0.09, 0.13, 0.12, 0.1, 0.1, 0.16, 0.12, 0.12, 0.13, 0.12, 0.11, 0.09, 0.09], 'load_cost_forecast': [0.4, 0.4, 0.29, 0.2, 0.2, 0.2, 0.21, 0.2, 0.2, 0.2, 0.26, 0.21, 0.23, 0.22, 0.41, 0.42, 0.42, 0.42, 0.39, 0.24, 0.33, 0.22, 0.21, 0.18, 0.22, 0.21, 0.18, 0.18, 0.25, 0.21, 0.21, 0.21, 0.21, 0.19, 0.17, 0.17], 'pv_power_forecast': [433, 1423, 1328, 1243, 1222, 1222, 1193, 1153, 988, 694, 441, 203, 68, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 80, 268, 643, 965, 1289, 1539, 1722, 1845, 1895, 1909, 1866, 1917, 2011, 1942, 1751, 1475, 1120, 664, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'load_power_forecast': [356, 415, 1714, 852, 2655, 2145, 1711, 2297, 1286, 643, 382, 459, 454, 468, 861, 853, 2181, 739, 643, 639, 722, 669, 948, 584, 597, 534, 573, 763, 552, 431, 405, 303, 327, 321, 312, 313, 301, 315, 305, 317, 315, 318, 304, 303, 364, 428, 431, 503, 465], 'prediction_horizon': 36, 'num_def_loads': 2, 'def_total_hours': [1, 0], 'P_deferrable_nom': [1300, 2300], 'treat_def_as_semi_cont': [1, 0], 'set_def_constant': [0, 0], 'soc_init': 0.23, 'soc_final': 0.3, 'alpha': 1, 'beta': 0}
2024-07-08 10:29:56,947 - web_server - INFO -  >> Setting input data dict
2024-07-08 10:29:56,948 - web_server - INFO - Setting up needed data
2024-07-08 10:29:56,952 - web_server - INFO - Retrieve hass get data method initiated...
2024-07-08 10:30:01,771 - web_server - INFO - Retrieving weather forecast data using method = list
2024-07-08 10:30:01,774 - web_server - INFO -  >> Performing naive MPC optimization...
2024-07-08 10:30:01,774 - web_server - INFO - Performing naive MPC optimization
2024-07-08 10:30:01,786 - web_server - INFO - Perform an iteration of a naive MPC controller
2024-07-08 10:30:01,827 - web_server - DEBUG - Deferrable load 0: Proposed optimization window: 0 --> 0
2024-07-08 10:30:01,827 - web_server - DEBUG - Deferrable load 0: Validated optimization window: 0 --> 0
2024-07-08 10:30:01,830 - web_server - DEBUG - Deferrable load 1: Proposed optimization window: 0 --> 0
2024-07-08 10:30:01,830 - web_server - DEBUG - Deferrable load 1: Validated optimization window: 0 --> 0
2024-07-08 10:30:01,891 - web_server - ERROR - Exception on /action/naive-mpc-optim [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 1473, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 882, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 880, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/flask/app.py", line 865, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/web_server.py", line 168, in action_call
    opt_res = naive_mpc_optim(input_data_dict, app.logger)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/command_line.py", line 446, in naive_mpc_optim
    opt_res_naive_mpc = input_data_dict["opt"].perform_naive_mpc_optim(
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/optimization.py", line 804, in perform_naive_mpc_optim
    self.opt_res = self.perform_optimization(df_input_data, P_PV.values.ravel(), P_load.values.ravel(),
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/emhass/optimization.py", line 606, in perform_optimization
    opt_model.solve(COIN_CMD(msg=0, path=self.lp_solver_path))
  File "/usr/local/lib/python3.11/dist-packages/pulp/pulp.py", line 1883, in solve
    status = solver.actualSolve(self, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pulp/apis/coin_api.py", line 112, in actualSolve
    return self.solve_CBC(lp, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/pulp/apis/coin_api.py", line 188, in solve_CBC
    raise PulpSolverError("Pulp: Error while executing " + self.path)
pulp.apis.core.PulpSolverError: Pulp: Error while executing /usr/bin/cbc
2024-07-08 10:30:01,935 - web_server - INFO - Passed runtime parameters: {}
2024-07-08 10:30:01,935 - web_server - INFO -  >> Setting input data dict
2024-07-08 10:30:01,935 - web_server - INFO - Setting up needed data
2024-07-08 10:30:01,938 - web_server - INFO -  >> Publishing data...
2024-07-08 10:30:01,938 - web_server - INFO - Publishing data to HASS instance
2024-07-08 10:30:01,956 - web_server - INFO - Successfully posted to sensor.p_pv_forecast = 1423
2024-07-08 10:30:01,968 - web_server - INFO - Successfully posted to sensor.p_load_forecast = 415
2024-07-08 10:30:01,978 - web_server - INFO - Successfully posted to sensor.p_deferrable0 = 0.0
2024-07-08 10:30:01,985 - web_server - INFO - Successfully posted to sensor.p_deferrable1 = 0.0
2024-07-08 10:30:01,995 - web_server - INFO - Successfully posted to sensor.p_batt_forecast = 7992.0
2024-07-08 10:30:02,003 - web_server - INFO - Successfully posted to sensor.soc_batt_forecast = 30.0
2024-07-08 10:30:02,013 - web_server - INFO - Successfully posted to sensor.p_grid_forecast = -9000.0
2024-07-08 10:30:02,023 - web_server - INFO - Successfully posted to sensor.total_cost_fun_value = 26.82
2024-07-08 10:30:02,033 - web_server - INFO - Successfully posted to sensor.optim_status = Infeasible
2024-07-08 10:30:02,044 - web_server - INFO - Successfully posted to sensor.unit_load_cost = 0.4
2024-07-08 10:30:02,058 - web_server - INFO - Successfully posted to sensor.unit_prod_price = 0.28

It’s infeasible at the moment becuase battery is below target state which is the case every evening and into the morning until the sun charges battery back to target or I charge overnight for morning peak usage. Normal process for me.

What could be causing this 30 minute error?

Amber on Ausgrid have recently moved me to a tariff that has a demand component of their tariff. As such I’ve updated my automation to not charge my battery from the grid during this window.
The next thing I’m trying to do is getting the EMHASS model to avoid charging during the same window (i.e. charge ahead of that window).

Does anyone have any ideas of how to instruct EMHASS to not charge in that window? My first instinct is to just bump the unit_load_cost during that time so that it’s not financially feasible to do this. However I’m having trouble replacing the prices for that period based on my current list of 48 prices. (I’m running MPC every minute with a list of the next 48 prices from amber)

I’ve been able to work out the start and finish windows, but struggling to amend the array I have based on the start or finish windows

demand_window: >-
  {% set current_time = now() %}
  {% set demand_tariff = ["14:00:00","21:00:00"] %}
  {% set start_time = current_time.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(hours=(demand_tariff[0].split(':')[0]|int), minutes=(demand_tariff[0].split(':')[1]|int)) %}
  {% if start_time <= current_time %}
    {% set start_time = start_time + timedelta(days=1) %}
  {% endif %}
  {% set start_time_difference = start_time - current_time %}

  {% set end_time = current_time.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(hours=(demand_tariff[1].split(':')[0]|int), minutes=(demand_tariff[1].split(':')[1]|int)) %}
  {% if end_time <= current_time %}
    {% set end_time = end_time + timedelta(days=1) %}
  {% endif %}
  {% set end_time_difference = end_time - current_time %}

  {% set start_window = max(0,start_time_difference.total_seconds() / 3600 * 2)|int(0) %}
  {% set end_window = max(0,end_time_difference.total_seconds() / 3600 * 2)|int(0) %}

I think look for def_start_timestep and def_stop_timeset.

Let me think about it. I use deferrable loads for controlling things like my hot water heater, however I haven’t considered it as a way to add extra power requirements to the model so that it excludes exports during that time.

You should be able to set a start and stop timestep. See → An EMS based on Linear Programming — emhass 0.10.3 documentation look for Time windows for deferrable loads

I’m only just looking into it myself for the same reason (Demand Tariff).

  • def_start_timestep: The timestep as from which each deferrable load is allowed to operate (if you don’t want the deferrable load to use the whole optimization timewindow). If you specify a value of 0 (or negative), the deferrable load will be optimized as from the beginning of the complete prediction horizon window. For example:
    • 0
    • 1
  • def_end_timestep: The timestep before which each deferrable load should operate. The deferrable load is not allowed to operate after the specified timestep. If a value of 0 (or negative) is provided, the deferrable load is allowed to operate in the complete optimization window). For example:
    • 0
    • 3

I don’t think the battery is a deferable load though, when you enable the battery in EMHASS the optimisation calculates the best time to charge and discharge the battery based on the cost (whether that’s from the grid or from solar).

1 Like

Ok you’re trying to stop the battery from charging between 3:00 and 8:30. I don’t seem to have that problem. (so far) But perhaps I need to think about it.

I don’t have a battery (yet).
But can you pass "SOCtarget": {{ states("sensor.current_soc")}} "soc_final": {{ states("sensor.current_soc")}} at runtime?

I am passing soc_final, but as I run it every minute it’s calculating that for in 24 hours time.

I think I’ve been able to work this out (no doubt I’ve done this the longest way possible with superfluous code ), but it seems to correctly assign a cost of $1 per kWh for the demand tariff period which means my optimisation doesn’t try and charge the battery during this time.

Here’s what I’m using in my REST command

      "load_cost_forecast":
      {% set current_time = now() %}
      {% set demand_tariff = ["15:00:00","21:00:00"] %}
      {% set start_time = current_time.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(hours=(demand_tariff[0].split(":")[0]|int), minutes=(demand_tariff[0].split(":")[1]|int)) %}
      {% if start_time <= current_time %}
        {% set start_time = start_time + timedelta(days=1) %}
      {% endif %}
      {% set start_time_difference = start_time - current_time %}
      {% set end_time = current_time.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(hours=(demand_tariff[1].split(":")[0]|int), minutes=(demand_tariff[1].split(":")[1]|int)) %}
      {% if end_time <= current_time %}
        {% set end_time = end_time + timedelta(days=1) %}
      {% endif %}
      {% set end_time_difference = end_time - current_time %}
      {% set start_window = max(0,start_time_difference.total_seconds() / 3600 * 2)|int(0) %}
      {% set end_window = max(0,end_time_difference.total_seconds() / 3600 * 2)|int(0) %}
      {% set values = ([states("sensor.amber_general_price")|float(0)] + state_attr("sensor.amber_general_forecast", "forecasts")|map(attribute="per_kwh")|list)[:48] %}
      {% set ns = namespace( x=[]) %}
      {% if end_window < 12 %}
        {% for y in values[0:end_window+1] %}
          {% set ns.x = ns.x + [1|float(2)] %}
        {% endfor %}
        {% for y in values[end_window+1:start_window+1] %}
          {% set ns.x = ns.x + [y|round(2)] %}
        {% endfor %}
        {% for y in values[start_window+1:48] %}
          {% set ns.x = ns.x + [1|float(2)] %}  
        {% endfor %}   
        {{ ns.x }}
      {% else %}
        {% for y in values[0:start_window+1] %}
          {% set ns.x = ns.x + [y|round(2)] %}{% endfor %}
        {% for y in values[start_window+1:end_window+1] %}
          {% set ns.x = ns.x + [1|float(2)] %}{% endfor %}
        {% for y in values[end_window+1:48] %}
          {% set ns.x = ns.x +  [y|round(2)] %}{% endfor %}
        {{ ns.x }}
      {% endif %},

Hi all,

sorry to come up with maybe dumb newbie questions (newbie to EMHASS, …). I have some experience with HA automations and templates, but none with NodeRed (but that should be manageable if needed), and some 20 years Linux administration

I’m planning to use EMHASS in a perhaps a bit complex environment:

  • PV modules on 4 roofs (2x west, 2x east)
  • 2x Deye Hybrid High Voltage inverters
  • each of which has a HV battery (Enerlution)
  • HA running supervised in a Debian virtual machine
  • hourly energy prices (Tibber Germany)
  • fixed amount for energy sold to the grid (0.0744 EUR/kWh)
  • three deferrable loads (washing machine, dishwasher, tumble dryer)

I do have a high 24/7 consumption due to some servers running 24/7, so the batteries do not last the whole night, sometime between 4am and 6am they are empty, normally.

The Deye inverters are connected to HA via Modbus and the Sunsyk/Deye Add-On.
Grid sell/buy is currently read from the energy meter, has to be switched to Tibber integration, I guess (Tibber Pulse needed, at that blocks the IR interface I’m currently using).
All loads are genuinely dump, but are controlled by ZigBee smart plugs with energy metering.
I have modeled the 4 PV strings in Forecast.Solar. Tibber should give the day-ahead-prices via the HA integration, I hope.

The goal is to minimize overall energy cost:

  • don’t run deferrable loads in peak cost hours (which vary from day to day)
  • possible load batteries from grid if suitable (this one is tricky, as a) the price difference between buy at night for charging and consumption during peak/next day has to be sufficiently high, taking into account 20% charge/discharge loss)
  • but only charge battery during night enough to cover the morning price peak and not block charging from PV during the rest of the day
  • no discharge to grid from battery (that’s not allowed under German EEG rules)

4 strings= with 18, 16, 12 and 12 modules, bifacial 430Wp each
both inverters have a 10 kWh Enerlution GroundHV-2500 battery pack each

I’m pretty sure I got some good grasp of the EMHASS concepts, but I do have problems/challenges in translating this into HA configs/automations.

Challenges:

  • I can’t find any Deye inverter in https://emhass-pvlib-database.streamlit.app/ - I have
    two Deye SUN-10K-SG01HP3-EU-AM2 (master/slave mode)
  • I can’t find the PV modules there either: bifacial (there is not a single bifacial JA Solar module in the database) JA Solar JAM5-4D41-430/LB - 430Wp, Voc=38,5V, Vmp=32.12V, Isc=14.14A, Imp=13.39A
  • I do not know how to get the day-ahead prices from Tibber integration into EMHASS
  • I am not totally sure how to get the Forecast.Solar values for the 4 configured roofs into EMHASS
  • I did find some examples how to switch the deferrable loads on and off using values from EMHASS with HA automations, but I do not completely understand them
  • the biggest challenge for me is the control of battery charging: Deye uses “Time of use” timetables with 6 timeslots, each having a switch for “Grid Charge” (fine), “start time”, “end time” (represented in HA as “select.*” entities via the Sunsyk/Deye-Addon, a “POWER” input variable and a “SOC” input entity. The select entities’ step size can be configured in the Sunsyk-Addon, default is 15 minutes. I honestly have no idea which values from EMHASS have to go into that - and even less of an idea of how to write an automation that feeds these values into the inverters (using the Sunsyk Addon) (a set of NodeRed flows would to as well, I guess)

Any example or hint where to find more specific information of howtos … all very welcome.

Thanks in advance

I’ll try to answer some of the questions:

Then just don’t set anything, use either the Solcast or the Solar.Forecast methods.

In EMHASS you pass this type of data at runtime, this is in a template on the shell command that you will be using in the automation to launch the energy optimization.
Here is the example for Nordpool: https://emhass.readthedocs.io/en/latest/forecasts.html#example-using-the-nordpool-integration

Some info here: https://community.home-assistant.io/t/forecast-solar-forecast-with-panels-on-both-sides-of-the-roof/475071
Otherwise we can go back to challenge number 1 and try to find an inverter and PV module in the DB with similar nominal powers as yours.

Here are the examples: https://emhass.readthedocs.io/en/latest/intro.html#common-for-any-installation-method
What part you don’t understand?

Yes this is the hardest part. You will need to figure out how to set values on your battery yourself or find someone with the same model as yours and look for help.
From EMHASS you basically will have the optimal SOC (state of charge) trajectory and also the charge/discharge powers that are related to that SOC. Now you need to build a custom automation to tell your battery to follow that SOC as close as possible. This is hardly generalizable and depends/differs on the various battery manufacturers out there.

Don’t know if it would help but my config using mostly node red is here EMHASS: An Energy Management for Home Assistant - #1027 by rcruikshank

I have setup an EMHASS instance with a dual deye inverter setup, so the battery automation should work directly for you.

We setup four scripts to control the battery:

alias: Grid Power Forecast Automation - Battery VDC based
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.p_grid_forecast
    to: null
    enabled: false
  - platform: time_pattern
    minutes: /3
condition:
  - condition: state
    entity_id: sensor.optim_status
    state: Optimal
action:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.p_grid_forecast
            above: 5000
          - condition: numeric_state
            entity_id: sensor.p_batt_forecast
            below: -5000
        sequence:
          - service: script.turn_on
            metadata: {}
            data: {}
            target:
              entity_id: script.charge
        alias: Charge from Grid at MAX rate
      - conditions:
          - condition: numeric_state
            entity_id: sensor.p_grid_forecast
            below: -900
          - condition: numeric_state
            entity_id: sensor.p_batt_forecast
            above: 1000
          - alias: When Battery Voltage is above 49.5VDC
            condition: numeric_state
            entity_id: sensor.sunsynk_battery_voltage
            above: 49.2
        sequence:
          - service: script.turn_on
            metadata: {}
            data: {}
            target:
              entity_id: script.discharge
        alias: Discharge to Grid at MAX rate
      - conditions:
          - condition: numeric_state
            entity_id: sensor.p_grid_forecast
            below: -900
          - condition: numeric_state
            entity_id: sensor.p_batt_forecast
            above: 1000
          - alias: When Battery Voltage is below 49.5VDC
            condition: numeric_state
            entity_id: sensor.sunsynk_battery_voltage
            below: 49.2
        sequence:
          - service: script.turn_on
            metadata: {}
            data: {}
            target:
              entity_id:
                - script.discharge_battery_to_load_only_grid_off
        alias: Discharge to Load only at low SoC
      - conditions:
          - alias: When Battery_power_forecast = 0
            condition: numeric_state
            entity_id: sensor.p_batt_forecast
            below: 0.1
            above: -0.1
          - condition: numeric_state
            entity_id: sensor.p_grid_forecast
            above: 0.1
        sequence:
          - service: script.turn_on
            metadata: {}
            data: {}
            target:
              entity_id:
                - script.maintain_soc_consume_grid_pv
        alias: Consume Grid, no Charge
    default:
      - service: script.turn_on
        metadata: {}
        data: {}
        target:
          entity_id: script.discharge_battery_to_load_only_grid_off
mode: single




Wish the powerwall had this level of control, we are looking at moving to the country soon so will be looking at batteries that have local control.

Speaking off is there any way to tell EMHASS that a powerwall can only charge at particular rates e.g. 1kw or 5kw if TOU is used?

Agreed on the Powerwall front.

Moves afoot to get greater control but I’m not sure Tesla are that interested, although they did open FleetAPI up to open source yesterday.

https://developer.tesla.com/docs/fleet-api#faq

My experience is TBC sets it’s own charging rates, but they do vary with price (I’m injecting Amber price).

I can control difference charging rates 1.7 kW (raise SOC), 3.3 kW (backup mode), 5 kW (TBC+ OFFPEAK), but can only get one discharge rate 5 kW (TBC + PEAK).

1 Like