Skip to content

Teslemetry: Powerwall never exports — tariff pushed without optimization_strategy, so TBC stays in Balanced #4600

Description

@springfall2008

Summary

teslemetry.py never sends optimization_strategy when it pushes the ToU tariff, so the Powerwall's Time-Based Control stays in Balanced mode. In Balanced, TBC discharges only to offset house load and never exports stored energy to the grid — no matter how high the synthetic ON_PEAK sell price in the boost window is.

Net effect: Predbat reports Exporting, every device command succeeds, and the battery exports nothing. Planned exports have never executed on this site.

The defect

set_tariff (teslemetry.py, ~line 1155):

return await self._apply_command(
    "tariff",
    signature,
    lambda: self._command("time_of_use_settings", {"tou_settings": {"tariff_content_v2": tariff}}),
    force=force,
)

The Fleet API tou_settings object accepts optimization_strategy: economics | balanced. We set the tariff but never set the dial that decides whether the Powerwall acts on it commercially. Whatever the customer's Tesla app happens to hold, stands.

Per Tesla's own description of Balanced: "once peak rates kick in, the Powerwall will start discharging to offset what your house is consuming." Offset load — not export. economics ("Cost Saving") is the strategy that will export for price.

Evidence

Real site, Powerwall 2 (13.5 kWh), Intelligent Octopus Go import (6.9p / 28.56p), Octopus Outgoing Fixed export (flat 12p).

1. The control path is correct. Entering an export window, all four commands landed successfully:

22:05:41  POST grid_import_export  200        -> battery_ok, grid charging off
22:05:41  POST operation           200 Code 200 -> autonomous
21:53:36  POST time_of_use_settings 200 Code 201 -> boosted tariff
          (backup reserve deduped, device already at 4%)
22:05:58  record_status Exporting target 56%-4%

2. The tariff itself is correct. Rebuilt locally with the site's real rates — the boost lands exactly on the window, on the right day-of-week:

=== SELL side ===   rates: {"SUPER_OFF_PEAK": 0.12, "ON_PEAK": 0.58}
  SUPER_OFF_PEAK   day 3-3  00:00 -> 07:25
  ON_PEAK          day 3-3  07:25 -> 09:30
  SUPER_OFF_PEAK   day 3-3  09:30 -> 00:00
=== BUY side ===    rates: {"SUPER_OFF_PEAK": 0.07, "OFF_PEAK": 0.29, "ON_PEAK": 0.58}
  ON_PEAK          day 3-3  07:25 -> 09:30

3. The Powerwall just load-follows. Through the whole 80-minute Exporting target 56%->4% window, battery_power tracked load_power to the watt and grid stayed at zero:

22:41:54  soc=53.6%  batt=  440  solar=0  load=  440  grid=    0
22:45:55  soc=53.2%  batt=  500  solar=0  load=  500  grid=    0
22:51:57  soc=52.8%  batt=  570  solar=0  load=  570  grid=    0
23:12:04  soc=51.4%  batt= 2140  solar=0  load= 2140  grid=    0
23:24:08  soc=50.4%  batt=  500  solar=0  load=  500  grid=    0

SoC drifted 53.6% -> 50.0% on house load alone, against a 4% target.

4. Charging works instantly, which rules out a broken command channel. The moment the plan flipped to Charging at 23:26, the next sample obeyed:

23:28:09  soc=50.0%  batt=-3640  load=  658  grid= 4298

5. Same story with a full battery. A second window (07:25-09:30, armed at 08:59:56) held battery_power at exactly 0 W for all 30 minutes while 5-7 kW of solar exported freely:

09:01:22  soc=100.0%  batt=0  solar=5614  load=327  grid=-5287
09:15:27  soc=100.0%  batt=0  solar=5739  load=250  grid=-5489
09:29:31  soc=100.0%  batt=0  solar=6981  load=336  grid=-6645

Suggested fix

{"tou_settings": {"optimization_strategy": "economics", "tariff_content_v2": tariff}}

Notes for whoever picks this up:

  • Include the strategy in the _apply_command dedupe signature so changing it forces a re-push.
  • Worth asserting on every tariff push rather than once at boot — the customer's Tesla app can set it back to Balanced at any time, and there is no read endpoint to detect that drift (site_info does not expose optimization_strategy).
  • Probably belongs behind the same read-only gate as the rest of sync_tariff.

Secondary issue (separate, lower priority)

Tesla clamps buy up to sell when buy < sell at any given time. On a flat-export tariff this bites overnight: buy SUPER_OFF_PEAK 0.07 vs sell 0.12, so the Powerwall models cheap IOG import as 12p and its own charge decisions are distorted. Not the cause of the export failure, but worth a look once export works.

Caveat

optimization_strategy is not exposed on any read endpoint, so the current device value could not be read back directly. The diagnosis rests on the field never being sent plus the behavioural signature (battery == load, grid == 0) matching documented Balanced behaviour exactly. Setting economics and observing a window is the confirming test.

Environment

  • Predbat v8.48.8
  • Tesla Backup Gateway 2 + 1x Powerwall 2, firmware 26.18.3
  • Teslemetry API, teslemetry_automatic (TESLA inverter type)
  • Not a regression — this site ran Read-Only until recently, so the component's export path had never actually been exercised.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions