Skip to content

[BUG] _keepalive_loop blocks Home Assistant startup (bootstrap timeout) #283

Description

@xIceTea

HoymilesMqttDriver._ensure_keepalive() starts the endless _keepalive_loop()
through hass.async_create_task(). Home Assistant waits for tasks created that
way while it finishes the start phase, so bootstrap runs into its timeout and
the start phase never completes cleanly.

From the system log:

Setup timed out for bootstrap waiting on {<Task pending name='Task-1386'
coro=<HoymilesMqttDriver._keepalive_loop() running at
/config/custom_components/omnibattery/drivers/hoymiles.py:518>
wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[set.remove()]>} - moving forward

Right after that:

Something is blocking Home Assistant from wrapping up the start up phase.
We're going to continue anyway. Please report the following info at
https://github.com/home-assistant/core/issues: <long list of every integration
that had not finished yet>

GET /api/config then keeps reporting "state": "NOT_RUNNING" for several
minutes after a restart. Entities work and values are fresh during that time,
so the effect is limited to the startup phase — but anything hooked to
homeassistant_started is delayed, and the warning above sends people chasing
the wrong integration.

Source

custom_components/omnibattery/drivers/hoymiles.py:

def _ensure_keepalive(self) -> None:
    if self._keepalive_task is None or self._keepalive_task.done():
        self._keepalive_task = self.hass.async_create_task(self._keepalive_loop())

async def _keepalive_loop(self) -> None:
    delay_s = _KEEPALIVE_S
    try:
        while True:
            await asyncio.sleep(delay_s)
            ...

Suggested fix

Long-running loops belong in a background task — those are excluded from the
startup wait and are cancelled automatically when the entry unloads:

self._keepalive_task = self.hass.async_create_background_task(
    self._keepalive_loop(), name="omnibattery hoymiles keepalive"
)

ConfigEntry.async_create_background_task(hass, coro, name) works as well and
ties the task to the entry.

Environment

  • Omnibattery 1.3.0
  • Home Assistant 2026.7.4, Home Assistant OS, container
  • Batteries configured: Marstek Venus E (v3) and Hoymiles MS-A2 (v2)
Diagnostics (device id redacted)
{
  "home_assistant": {
    "arch": "x86_64",
    "dev": false,
    "docker": true,
    "hassio": true,
    "installation_type": "Home Assistant OS",
    "os_name": "Linux",
    "os_version": "6.18.37-haos",
    "python_version": "3.14.6",
    "timezone": "Europe/Berlin",
    "version": "2026.7.4",
    "virtualenv": false,
    "container_arch": "amd64",
    "supervisor": "2026.07.5",
    "host_os": "Home Assistant OS 18.1",
    "docker_version": "29.5.3",
    "chassis": "vm",
    "run_as_root": true
  },
  "custom_components": {
    "ha_washdata": {
      "documentation": "https://github.com/3dg1luk43/ha_washdata",
      "version": "0.5.3",
      "requirements": [
        "numpy"
      ]
    },
    "heatnexus": {
      "documentation": "https://github.com/xIceTea/HeatNexus",
      "version": "1.10.0-dev.7",
      "requirements": []
    },
    "mammotion": {
      "documentation": "https://github.com/mikey0000/Mammotion-HA/wiki",
      "version": "0.6.3",
      "requirements": [
        "pymammotion==0.8.4"
      ]
    },
    "bambu_lab": {
      "documentation": "https://github.com/greghesp/ha-bambulab",
      "version": "2.2.22",
      "requirements": [
        "beautifulsoup4"
      ]
    },
    "tado_ce": {
      "documentation": "https://github.com/hiall-fyi/tado_ce",
      "version": "4.2.1",
      "requirements": [
        "aiohttp>=3.8.0",
        "aiohomekit==3.2.20"
      ]
    },
    "webrtc": {
      "documentation": "https://github.com/AlexxIT/WebRTC",
      "version": "v3.6.1",
      "requirements": []
    },
    "smartthinq_sensors": {
      "documentation": "https://github.com/ollo69/ha-smartthinq-sensors",
      "version": "0.43.0",
      "requirements": [
        "pycountry>=23.12.11",
        "xmltodict>=0.13.0",
        "charset_normalizer>=3.2.0"
      ]
    },
    "xiaomi_miot": {
      "documentation": "https://github.com/al-one/hass-xiaomi-miot",
      "version": "1.1.4",
      "requirements": [
        "construct>=2.10.68",
        "python-miio>=0.5.12",
        "micloud>=0.5"
      ]
    },
    "alexa_media": {
      "documentation": "https://github.com/alandtse/alexa_media_player/wiki",
      "version": "5.15.7",
      "requirements": [
        "alexapy==1.29.25",
        "packaging>=20.3",
        "wrapt>=1.14.0",
        "dictor>=0.1.12,<0.2"
      ]
    },
    "ugreen": {
      "documentation": "https://github.com/Tom-Bom-badil/home-assistant_ugreen-nas/wiki",
      "version": "v2026.07.1",
      "requirements": []
    },
    "windhager": {
      "documentation": "https://github.com/vermi0ffh/ha-windhager",
      "version": "0.8.2",
      "requirements": []
    },
    "omnibattery": {
      "documentation": "https://github.com/ffunes/omnibattery",
      "version": "1.3.0",
      "requirements": [
        "pymodbus>=3.8.0",
        "pyserial>=3.5"
      ]
    },
    "evcc_intg": {
      "documentation": "https://github.com/marq24/ha-evcc",
      "version": "2026.7.6",
      "requirements": [
        "packaging>=21.0"
      ]
    },
    "hacs": {
      "documentation": "https://hacs.xyz/docs/use/",
      "version": "2.0.5",
      "requirements": [
        "aiogithubapi>=22.10.1"
      ]
    },
    "petkit": {
      "documentation": "https://github.com/Jezza34000/homeassistant_petkit",
      "version": "1.26.0",
      "requirements": [
        "pypetkitapi==1.26.1",
        "aiofiles==24.1.0",
        "paho-mqtt==2.1.0",
        "websockets==15.0.1",
        "sdp-transform==1.1.0"
      ]
    },
    "haghs": {
      "documentation": "https://github.com/d-n91/home-assistant-global-health-score",
      "version": "2.3.0",
      "requirements": []
    }
  },
  "integration_manifest": {
    "domain": "omnibattery",
    "name": "Omnibattery",
    "after_dependencies": [
      "recorder",
      "esphome",
      "mqtt"
    ],
    "codeowners": [
      "ffunes"
    ],
    "config_flow": true,
    "dependencies": [
      "http",
      "frontend",
      "panel_custom"
    ],
    "dhcp": [
      {
        "registered_devices": true
      }
    ],
    "documentation": "https://github.com/ffunes/omnibattery",
    "integration_type": "device",
    "iot_class": "local_polling",
    "issue_tracker": "https://github.com/ffunes/omnibattery/issues",
    "requirements": [
      "pymodbus>=3.8.0",
      "pyserial>=3.5"
    ],
    "version": "1.3.0",
    "zeroconf": [
      "_modbus._tcp.local."
    ],
    "is_built_in": false,
    "overwrites_built_in": false
  },
  "setup_times": {
    "null": {
      "setup": 1.1902069672942162e-05
    },
    "01KWCZG5JDR9C3AWXMZMYV4KWG": {
      "wait_import_platforms": -0.014065091032534838,
      "config_entry_setup": 8.568988482933491
    }
  },
  "data": {
    "entry": {
      "title": "Omnibattery",
      "version": 11,
      "data": {
        "batteries": [
          {
            "backup_offgrid_threshold": 40,
            "battery_phase": "unassigned",
            "battery_version": "v3",
            "brand": "marstek",
            "charge_hysteresis_percent": 2,
            "enable_charge_hysteresis": true,
            "full_charge_voltage_taper_enabled": true,
            "host": "**REDACTED**",
            "mac": "",
            "manual_force_mode": "None",
            "max_charge_power": 2500,
            "max_discharge_power": 2500,
            "max_soc": 100,
            "min_soc": 12,
            "name": "Marstek Venus E",
            "port": 502,
            "rs485_user_disabled": false,
            "serial_port": "",
            "shadow_select_user_work_mode": 1,
            "slave_id": 1,
            "track_mac": false
          },
          {
            "backup_offgrid_threshold": 50,
            "battery_capacity_kwh": 2.24,
            "battery_phase": "unassigned",
            "battery_version": "v2",
            "brand": "hoymiles",
            "charge_hysteresis_percent": 2,
            "device_id": "**REDACTED**",
            "device_max_charge_power": 1000,
            "device_max_discharge_power": 1000,
            "enable_charge_hysteresis": true,
            "full_charge_voltage_taper_enabled": false,
            "host": "**REDACTED**",
            "hoymiles_model": "ms_a2",
            "hoymiles_model_label": "MS-A2",
            "mac": "",
            "manual_force_mode": "None",
            "manual_set_charge_power": 0,
            "manual_set_discharge_power": 0,
            "max_charge_power": 1000,
            "max_discharge_power": 1000,
            "max_soc": 100,
            "min_soc": 10,
            "name": "Hoymiles MS-A2 2",
            "port": 0,
            "track_mac": false
          }
        ],
        "capacity_protection_enabled": false,
        "capacity_protection_excluded_devices": false,
        "charging_time_slot": null,
        "consumption_sensor": "sensor.shelly_pro_3em_fast_netz_gesamtleistung",
        "delay_soc_setpoint_enabled": false,
        "enable_balance_monitor": true,
        "enable_charge_delay": false,
        "enable_hourly_balance": false,
        "enable_predictive_charging": false,
        "enable_system_power_limits": false,
        "enable_temp_charge_limit": false,
        "enable_weekly_full_charge": true,
        "excluded_devices": [
          {
            "allow_solar_surplus": true,
            "cover_home_when_active": true,
            "ev_charger_no_telemetry": false,
            "included_in_consumption": true,
            "power_sensor": "sensor.wallbox_bmw_ladeleistung_w"
          },
          {
            "allow_solar_surplus": true,
            "cover_home_when_active": true,
            "ev_charger_no_telemetry": false,
            "included_in_consumption": true,
            "power_sensor": "sensor.wallbox_garage_ladeleistung_w"
          }
        ],
        "hourly_balance_deadband_wh": 0.0,
        "hourly_balance_hysteresis_w": 15,
        "hourly_balance_max_offset_w": 1000,
        "hourly_balance_target_net_wh": 0.0,
        "manual_mode_enabled": false,
        "max_contracted_power": 7000.0,
        "meter_inverted": false,
        "no_discharge_time_slots": [],
        "no_pd_mode_enabled": false,
        "num_batteries": 2,
        "pd_controller_deadband": 40.0,
        "pd_controller_direction_hysteresis": 40.0,
        "pd_controller_kd": 0.45,
        "pd_controller_kp": 0.55,
        "pd_controller_max_power_change": 1200,
        "pd_min_charge_power": 0,
        "pd_min_discharge_power": 0,
        "pd_target_grid_power": 0,
        "pd_tuning_profile": "aggressive",
        "predictive_charging_mode": "time_slot",
        "solar_forecast_sensor": "sensor.energy_production_today",
        "solar_production_sensor": "sensor.pv_leistung_gesamt",
        "system_max_charge_power": 0,
        "system_max_discharge_power": 0,
        "three_phase_enabled": true,
        "weekly_full_charge_day": "mon",
        "weekly_full_charge_skip_delay": false
      },
      "options": {}
    },
    "batteries": [
      {
        "health": {
          "name": "Marstek Venus E",
          "brand": "marstek",
          "battery_version": "v3",
          "battery_manual_mode_enabled": false,
          "connected": true,
          "available": true,
          "shutting_down": false,
          "consecutive_failures": 0,
          "max_failures_before_reconnect": 3,
          "max_failures_before_suspend": 5,
          "suspended": false,
          "suspension_reset_time": null,
          "last_write_failure_reason": null,
          "last_update_times": {
            "max_cell_voltage,min_cell_voltage": "2026-08-15T21:00:47.615401+00:00",
            "set_charge_power,set_discharge_power": "2026-08-15T21:00:47.615401+00:00",
            "max_charge_power,max_discharge_power": "2026-08-15T21:00:43.615607+00:00",
            "battery_soc": "2026-08-15T21:00:43.615607+00:00",
            "battery_total_energy": "2026-08-15T21:00:18.616148+00:00",
            "battery_voltage": "2026-08-15T21:00:43.615607+00:00",
            "battery_power": "2026-08-15T21:00:43.615607+00:00",
            "ac_offgrid_power": "2026-08-15T21:00:43.615607+00:00",
            "internal_temperature": "2026-08-15T21:00:43.615607+00:00",
            "ac_power": "2026-08-15T21:00:43.615607+00:00",
            "total_charging_energy": "2026-08-15T21:00:18.616148+00:00",
            "total_discharging_energy": "2026-08-15T21:00:18.616148+00:00",
            "inverter_state": "2026-08-15T21:00:43.615607+00:00",
            "battery_cycle_count": "2026-08-15T21:00:18.616148+00:00",
            "device_name": "2026-08-15T20:52:28.616341+00:00",
            "bms_version": "2026-08-15T20:52:28.616341+00:00",
            "vms_version": "2026-08-15T20:52:28.616341+00:00",
            "ems_version": "2026-08-15T20:52:28.616341+00:00",
            "comm_module_firmware": "2026-08-15T20:52:28.616341+00:00",
            "mac_address": "2026-08-15T20:52:28.616341+00:00",
            "wifi_signal_strength": "2026-08-15T21:00:18.616148+00:00",
            "force_mode": "2026-08-15T21:00:43.615607+00:00",
            "user_work_mode": "2026-08-15T21:00:43.615607+00:00",
            "backup_function": "2026-08-15T21:00:43.615607+00:00",
            "rs485_control_mode": "2026-08-15T21:00:43.615607+00:00",
            "wifi_status": "2026-08-15T21:00:18.616148+00:00",
            "balancing_mode": "2026-08-15T21:00:18.616148+00:00"
          }
        },
        "driver": {
          "connected": true,
          "model_label": "Venus E v3",
          "capabilities": {
            "hardware_soc_cutoff": false,
            "has_force_mode": true,
            "push_telemetry": false,
            "max_charge_power_w": 2500,
            "max_discharge_power_w": 2500,
            "has_mppt_pv": false,
            "has_alarm_registers": false,
            "has_rs485_control": true,
            "has_energy_counters": true,
            "has_nominal_capacity": true,
            "cycles_from_discharge_only": false,
            "has_daily_energy_counters": false,
            "setpoint_confirm_reliable": true,
            "actuator_latency_s": 0.8,
            "readback_latency_s": null,
            "engage_grace_s": null,
            "min_charge_power_w": 800,
            "min_discharge_power_w": 800
          }
        },
        "tracker": {
          "excluded": false,
          "fail_count": 0,
          "reason": null,
          "retry_attempted": false,
          "wake_used": false
        },
        "runtime": {
          "battery_manual_mode_enabled": false,
          "automatic_pool": true
        }
      },
      {
        "health": {
          "name": "Hoymiles MS-A2 2",
          "brand": "hoymiles",
          "battery_version": "v2",
          "battery_manual_mode_enabled": false,
          "connected": true,
          "available": true,
          "shutting_down": false,
          "consecutive_failures": 0,
          "max_failures_before_reconnect": 3,
          "max_failures_before_suspend": 5,
          "suspended": false,
          "suspension_reset_time": null,
          "last_write_failure_reason": null,
          "last_update_times": {
            "battery_soc,battery_power,battery_voltage,battery_current,internal_temperature,wifi_signal_strength,inverter_state,pack_count,max_charge_power,max_discharge_power,total_daily_charging_energy,total_daily_discharging_energy": "2026-08-15T21:00:45.662962+00:00"
          }
        },
        "driver": {
          "connected": true,
          "model_label": "MS-A2",
          "capabilities": {
            "hardware_soc_cutoff": false,
            "has_force_mode": false,
            "push_telemetry": true,
            "max_charge_power_w": 1000,
            "max_discharge_power_w": 1000,
            "has_mppt_pv": false,
            "has_alarm_registers": false,
            "has_rs485_control": false,
            "has_energy_counters": true,
            "has_nominal_capacity": false,
            "cycles_from_discharge_only": false,
            "has_daily_energy_counters": true,
            "setpoint_confirm_reliable": false,
            "actuator_latency_s": 1.8,
            "readback_latency_s": 4.0,
            "engage_grace_s": null,
            "min_charge_power_w": 0,
            "min_discharge_power_w": 0
          }
        },
        "tracker": {
          "excluded": false,
          "fail_count": 0,
          "reason": null,
          "retry_attempted": false,
          "wake_used": false
        },
        "runtime": {
          "battery_manual_mode_enabled": false,
          "automatic_pool": true
        }
      }
    ],
    "control_pool": {
      "manual_batteries": [],
      "automatic_batteries": [
        "Marstek Venus E",
        "Hoymiles MS-A2 2"
      ]
    },
    "dynamic_pricing": {
      "negative_price_charging_enabled": false,
      "active_slot_purpose": null,
      "schedule_type": null,
      "selected_slots": []
    },
    "curtailment": {
      "status": "disabled",
      "reason": "feature_disabled",
      "required_headroom_kwh": 0.0,
      "current_headroom_kwh": 0.0,
      "forecast_solar_surplus_kwh": 0.0,
      "solar_reserve_remaining_kwh": 0.0,
      "solar_reserve_source": "_curtailment_solar_reserve_remaining_kwh",
      "current_free_space_kwh": 0.0,
      "current_free_space_source": "current_headroom_kwh",
      "opportunistic_space_available_kwh": 0.0,
      "opportunistic_space_source": "_curtailment_opportunistic_space_kwh",
      "charge_limit_reason": "feature_disabled",
      "charge_limit_reasons": [
        "feature_disabled"
      ],
      "charge_blocked": false,
      "charge_blockers": {
        "global": {},
        "batteries": {}
      },
      "active_slot_purpose": null,
      "export": {
        "mode": "self_consumption",
        "mode_label": "Solo autoconsumo",
        "limit_w": 0.0,
        "limit_description": "Límite de exportación deliberada a red, no potencia total de descarga"
      },
      "export_mode": "self_consumption",
      "export_limit_w": 0.0
    },
    "phase_protection": {
      "state": "active",
      "enabled": true,
      "protection_enabled": true,
      "meter_inverted": false,
      "limited_batteries": [],
      "limited_battery_details": [],
      "unassigned_batteries": [
        "Marstek Venus E",
        "Hoymiles MS-A2 2"
      ],
      "degraded_phases": [],
      "sensors": {
        "phase_1_current_sensor": null,
        "phase_2_current_sensor": null,
        "phase_3_current_sensor": null
      },
      "fuse_sizes_a": {
        "phase_1_fuse_size": 0.0,
        "phase_2_fuse_size": 0.0,
        "phase_3_fuse_size": 0.0
      },
      "current_conversion": {
        "nominal_voltage_v": 230.0,
        "battery_power_factor": 0.9,
        "watts_per_amp": 207.0
      },
      "phases": {
        "l1": {
          "phase": "l1",
          "sensor": null,
          "configured": false,
          "reading_a": null,
          "limit_a": null,
          "base_a": null,
          "charge_budget_a": 0.0,
          "discharge_budget_a": 0.0,
          "charge_budget_w": 0.0,
          "discharge_budget_w": 0.0,
          "assigned_power_w": 0.0,
          "requested_power_w": 0.0,
          "degraded": false,
          "reason": "not_configured",
          "batteries": []
        },
        "l2": {
          "phase": "l2",
          "sensor": null,
          "configured": false,
          "reading_a": null,
          "limit_a": null,
          "base_a": null,
          "charge_budget_a": 0.0,
          "discharge_budget_a": 0.0,
          "charge_budget_w": 0.0,
          "discharge_budget_w": 0.0,
          "assigned_power_w": 0.0,
          "requested_power_w": 0.0,
          "degraded": false,
          "reason": "not_configured",
          "batteries": []
        },
        "l3": {
          "phase": "l3",
          "sensor": null,
          "configured": false,
          "reading_a": null,
          "limit_a": null,
          "base_a": null,
          "charge_budget_a": 0.0,
          "discharge_budget_a": 0.0,
          "charge_budget_w": 0.0,
          "discharge_budget_w": 0.0,
          "assigned_power_w": 0.0,
          "requested_power_w": 0.0,
          "degraded": false,
          "reason": "not_configured",
          "batteries": []
        }
      },
      "manual_mode_warning": false
    }
  },
  "issues": []
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingimplementedBug fixed or feature implemented

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions