Skip to content

Commit b48ea73

Browse files
st03psnclaude
andcommitted
Gate offline-tolerant startup behind an "Allow offline startup" option
Add a boolean option (default off) to the options flow so the offline-tolerant startup is opt-in. When disabled, setup keeps the standard ConfigEntryNotReady behavior; when enabled, an unreachable device with cached capabilities starts unavailable instead of showing a setup error. Capabilities are still cached unconditionally so the option works immediately once enabled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f8a90b5 commit b48ea73

5 files changed

Lines changed: 24 additions & 14 deletions

File tree

custom_components/midea_ac/__init__.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
from msmart.device import CommercialAirConditioner as CC
1818
from msmart.lan import AuthenticationError
1919

20-
from .const import (CONF_ADDITIONAL_OPERATION_MODES, CONF_CACHED_CAPS,
21-
CONF_CAPABILITY_OVERRIDES,
20+
from .const import (CONF_ADDITIONAL_OPERATION_MODES, CONF_ALLOW_OFFLINE_STARTUP,
21+
CONF_CACHED_CAPS, CONF_CAPABILITY_OVERRIDES,
2222
CONF_DEVICE_TYPE, CONF_ENERGY_DATA_FORMAT,
2323
CONF_ENERGY_DATA_SCALE, CONF_ENERGY_SENSOR, CONF_KEY,
2424
CONF_MAX_CONNECTION_LIFETIME,
@@ -80,9 +80,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
8080
"Setting maximum connection lifetime to %s seconds for device ID %s.", lifetime, device.id)
8181
device.set_max_connection_lifetime(lifetime)
8282

83-
# Capabilities cached from a previous successful setup. Lets the entry start
84-
# while the device is offline instead of raising ConfigEntryNotReady.
83+
# Capabilities cached from a previous successful setup. When "Allow offline
84+
# startup" is enabled, they let the entry start while the device is offline
85+
# instead of raising ConfigEntryNotReady.
8586
cached_caps = config_entry.data.get(CONF_CACHED_CAPS)
87+
allow_offline = config_entry.options.get(CONF_ALLOW_OFFLINE_STARTUP, False)
8688
reachable = True
8789

8890
# Configure token and k1 as needed
@@ -92,9 +94,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
9294
try:
9395
await device.authenticate(token, key)
9496
except AuthenticationError as e:
95-
# Without cached capabilities we cannot build entities, so keep HA's
96-
# standard "retry setup" behavior.
97-
if not cached_caps:
97+
# Keep HA's standard "retry setup" behavior unless offline startup is
98+
# allowed and we have cached capabilities to build entities from.
99+
if not (allow_offline and cached_caps):
98100
raise ConfigEntryNotReady(
99101
"Failed to authenticate with device.") from e
100102
_LOGGER.warning(
@@ -117,7 +119,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
117119
config_entry,
118120
data={**config_entry.data, CONF_CACHED_CAPS: caps})
119121
except Exception as e: # noqa: BLE001 - fall back to cache on any query failure
120-
if not cached_caps:
122+
if not (allow_offline and cached_caps):
121123
raise ConfigEntryNotReady(
122124
f"Failed to query device capabilities: {e}") from e
123125
_LOGGER.warning(

custom_components/midea_ac/config_flow.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
from msmart.discover import CloudError, Discover
3232
from msmart.lan import AuthenticationError
3333

34-
from .const import (CONF_BEEP, CONF_CAPABILITY_OVERRIDES,
34+
from .const import (CONF_ALLOW_OFFLINE_STARTUP, CONF_BEEP,
35+
CONF_CAPABILITY_OVERRIDES,
3536
CONF_CLOUD_COUNTRY_CODES, CONF_DEFAULT_CLOUD_COUNTRY,
3637
CONF_DEVICE_TYPE, CONF_ENERGY_DATA_FORMAT,
3738
CONF_ENERGY_DATA_SCALE, CONF_ENERGY_SENSOR,
@@ -49,7 +50,8 @@
4950
CONF_MAX_CONNECTION_LIFETIME: None,
5051
CONF_SWING_ANGLE_RTL: False,
5152
CONF_CAPABILITY_OVERRIDES: "",
52-
CONF_MERGE_CAPABILITY_OVERRIDES: True
53+
CONF_MERGE_CAPABILITY_OVERRIDES: True,
54+
CONF_ALLOW_OFFLINE_STARTUP: False
5355
}
5456

5557
_DEFAULT_AC_OPTIONS = {
@@ -471,6 +473,7 @@ class MideaOptionsFlow(OptionsFlow):
471473
)
472474
),
473475
vol.Optional(CONF_MERGE_CAPABILITY_OVERRIDES): cv.boolean,
476+
vol.Optional(CONF_ALLOW_OFFLINE_STARTUP): cv.boolean,
474477
}
475478
)
476479

custom_components/midea_ac/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
CONF_CAPABILITY_OVERRIDES = "capability_overrides"
2828
CONF_MERGE_CAPABILITY_OVERRIDES = "merge_capability_overrides"
2929
CONF_CACHED_CAPS = "cached_capabilities"
30+
CONF_ALLOW_OFFLINE_STARTUP = "allow_offline_startup"
3031

3132
PRESET_IECO = "ieco"
3233
PRESET_SILENT = "silent"

custom_components/midea_ac/translations/de.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,14 @@
7878
"temp_step": "Temperaturschritte",
7979
"fan_speed_step": "Lüftergeschwindigkeitsschritte",
8080
"max_connection_lifetime": "Maximale Verbindungsdauer",
81-
"swing_angle_rtl": "Horizontalen Schwenkwinkel umkehren"
81+
"swing_angle_rtl": "Horizontalen Schwenkwinkel umkehren",
82+
"allow_offline_startup": "Offline-Start erlauben"
8283
},
8384
"data_description": {
8485
"temp_step": "Schrittgröße für Temperatureinstellung",
8586
"fan_speed_step": "Schrittgröße für Lüftergeschwindigkeit",
86-
"max_connection_lifetime": "Maximale Zeit in Sekunden, die eine Verbindung verwendet wird (mindestens 15 Sekunden)"
87+
"max_connection_lifetime": "Maximale Zeit in Sekunden, die eine Verbindung verwendet wird (mindestens 15 Sekunden)",
88+
"allow_offline_startup": "Beim Start aus zwischengespeicherten Fähigkeiten laden, wenn das Gerät offline ist, statt einen Einrichtungsfehler anzuzeigen. Entitäten bleiben nicht verfügbar, bis das Gerät wieder verbunden ist."
8789
},
8890
"sections": {
8991
"energy_sensor": {

custom_components/midea_ac/translations/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,16 @@
8080
"max_connection_lifetime": "Maximum Connection Lifetime",
8181
"swing_angle_rtl": "Reverse Horizontal Swing Angle",
8282
"capability_overrides": "Capability Overrides",
83-
"merge_capability_overrides": "Merge Overrides"
83+
"merge_capability_overrides": "Merge Overrides",
84+
"allow_offline_startup": "Allow offline startup"
8485
},
8586
"data_description": {
8687
"temp_step": "Step size for temperature set point",
8788
"fan_speed_step": "Step size for custom fan speeds",
8889
"max_connection_lifetime": "Maximum time in seconds a connection will be used (15 second minimum)",
8990
"capability_overrides": "Device capability overrides in YAML format",
90-
"merge_capability_overrides": "Merge overrides with existing device capabilities"
91+
"merge_capability_overrides": "Merge overrides with existing device capabilities",
92+
"allow_offline_startup": "Start from previously cached capabilities when the device is offline, instead of showing a setup error. Entities remain unavailable until the device reconnects."
9193
},
9294
"sections": {
9395
"energy_sensor": {

0 commit comments

Comments
 (0)