Skip to content

Bug: Charge PV sub-strategy blocked by lingering charge_disabled flag from export peak shaving #151

Description

@WS8411

Setup

  • Strategy: Dynamic 2
  • Sub-strategy during neutral periods: Charge PV
  • Export peak shaving: enabled (was set to 500W limit)
  • 2x Marstek Venus batteries (M1 + M2), connected via Modbus/UTP
  • Home Battery Control v4.10.1

Observed behavior

When Dynamic 2 runs Charge PV during a neutral period, both batteries remain on stop (0W) even when there is significant PV surplus being exported to the grid (e.g. -730W grid power). The PID controller shows a small output (~73W) but load distribution skips both batteries.

Switching manually to Self-consumption resolves the issue immediately — batteries start charging as expected.

Root cause (identified with help from Claude AI)

The flow has two parallel branches triggered from Operating mode:

  1. Strat → Charge PV → Self-consumption → Battery solutions
  2. Peak shaving → Self-consumption → Peak check → Battery solutions

The Peak shaving node sets advanced_settings.charge_disabled = true (for export peak shaving direction) using RED.util.setMessageProperty with the persistent flag. This value persists in flow context across cycles. When peak shaving is later disabled or no longer active, the charge_disabled = true flag is never cleared.

The Charge PV node only sets discharge_disabled = true but does not explicitly reset charge_disabled. As a result, every subsequent Charge PV execution inherits the stale charge_disabled = true flag and the load distribution blocks charging.

Suggested fix

At the start of the Charge PV function node, explicitly reset both flags before setting the intended one:

// Reset any lingering advanced_settings flags from previous cycles
RED.util.setMessageProperty(msg, "advanced_settings.charge_disabled", false, true);
RED.util.setMessageProperty(msg, "advanced_settings.discharge_disabled", false, true);

// Then set the intended flag for Charge PV
const DISCHARGE_DISABLED = true;
RED.util.setMessageProperty(msg, "advanced_settings.discharge_disabled", DISCHARGE_DISABLED, true);

The same reset may be needed in other sub-strategy nodes (Zero import, Standby) that can follow a peak shaving cycle.

Note: This analysis was done with assistance from Claude (Anthropic AI), by inspecting the exported flow JSON and tracing the flag through the node logic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions