Fix deviceinfo missing mac and s/n for Midea (#180594)

This commit is contained in:
Simone Chemelli
2026-08-29 13:01:46 +02:00
committed by GitHub
parent 9575dd00a7
commit 51765a13c1
9 changed files with 189 additions and 14 deletions
+1
View File
@@ -174,6 +174,7 @@ def mock_config_entry() -> Callable[[DummyDevice], MockConfigEntry]:
def _create(device: DummyDevice) -> MockConfigEntry:
return MockConfigEntry(
domain=DOMAIN,
minor_version=2,
data={
**BASE_DATA,
CONF_TYPE: device.device_type,
+4 -1
View File
@@ -2,11 +2,12 @@
from midealocal.const import ProtocolVersion
from homeassistant.components.midea.const import CONF_KEY, CONF_SUBTYPE
from homeassistant.components.midea.const import CONF_KEY, CONF_SN, CONF_SUBTYPE
from homeassistant.components.midea.device_catalog import MIDEA_DEVICE_NAMES
from homeassistant.const import (
CONF_DEVICE_ID,
CONF_IP_ADDRESS,
CONF_MAC,
CONF_MODEL,
CONF_PORT,
CONF_PROTOCOL,
@@ -38,6 +39,8 @@ DISCOVERY_RESULT = {
TEST_DEVICE_ID: {
**BASE_DATA,
CONF_TYPE: TEST_TYPE,
CONF_MAC: TEST_MAC_ADDRESS,
CONF_SN: TEST_SERIAL_NUMBER,
}
}
@@ -29,7 +29,7 @@
'discovery_keys': dict({
}),
'domain': 'midea',
'minor_version': 1,
'minor_version': 2,
'options': dict({
}),
'pref_disable_new_entities': False,
+15 -1
View File
@@ -17,6 +17,7 @@ from homeassistant.components.midea.const import (
CONF_ACCOUNT,
CONF_KEY,
CONF_SERVER,
CONF_SN,
CONF_SUBTYPE,
DOMAIN,
)
@@ -26,6 +27,7 @@ from homeassistant.const import (
CONF_DEVICE,
CONF_DEVICE_ID,
CONF_IP_ADDRESS,
CONF_MAC,
CONF_MODEL,
CONF_NAME,
CONF_PASSWORD,
@@ -44,9 +46,11 @@ from .const import (
TEST_DEVICE_ID,
TEST_IP_ADDRESS,
TEST_KEY,
TEST_MAC_ADDRESS,
TEST_MODEL,
TEST_PORT,
TEST_PROTOCOL,
TEST_SERIAL_NUMBER,
TEST_SUBTYPE,
TEST_TOKEN,
TEST_TYPE,
@@ -104,6 +108,8 @@ async def test_manual_flow_success(hass: HomeAssistant) -> None:
CONF_SUBTYPE: TEST_SUBTYPE,
CONF_TOKEN: TEST_TOKEN,
CONF_KEY: TEST_KEY,
CONF_MAC: TEST_MAC_ADDRESS,
CONF_SN: TEST_SERIAL_NUMBER,
}
@@ -1056,7 +1062,13 @@ async def test_auto_flow_v1_v2_success_when_cloud_down(
) -> None:
"""Test v1/v2 devices are added without ever using the cloud, even if it is down."""
mock_devices = {
TEST_DEVICE_ID: {**BASE_DATA, CONF_TYPE: TEST_TYPE, CONF_PROTOCOL: protocol},
TEST_DEVICE_ID: {
**BASE_DATA,
CONF_TYPE: TEST_TYPE,
CONF_PROTOCOL: protocol,
CONF_MAC: TEST_MAC_ADDRESS,
CONF_SN: TEST_SERIAL_NUMBER,
},
}
result = await hass.config_entries.flow.async_init(
@@ -1105,6 +1117,8 @@ async def test_auto_flow_v1_v2_success_when_cloud_down(
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"][CONF_DEVICE_ID] == TEST_DEVICE_ID
assert result["data"][CONF_PROTOCOL] == protocol
assert result["data"][CONF_MAC] == TEST_MAC_ADDRESS
assert result["data"][CONF_SN] == TEST_SERIAL_NUMBER
async def test_login_credentials_step_renders_with_cloud_servers(
+99 -5
View File
@@ -4,11 +4,12 @@ from unittest.mock import patch
from midealocal.const import DeviceType, ProtocolVersion
from homeassistant.components.midea.const import CONF_KEY, CONF_SUBTYPE, DOMAIN
from homeassistant.components.midea.const import CONF_KEY, CONF_SN, CONF_SUBTYPE, DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import (
CONF_DEVICE_ID,
CONF_IP_ADDRESS,
CONF_MAC,
CONF_MODEL,
CONF_NAME,
CONF_PORT,
@@ -17,10 +18,11 @@ from homeassistant.const import (
CONF_TYPE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.setup import async_setup_component
from .conftest import DummyDevice
from .const import TEST_DEVICE_ID
from .const import TEST_DEVICE_ID, TEST_IP_ADDRESS, TEST_MAC_ADDRESS, TEST_SERIAL_NUMBER
from tests.common import MockConfigEntry
@@ -45,7 +47,7 @@ async def test_async_setup(hass: HomeAssistant) -> None:
async def test_unload_entry(hass: HomeAssistant) -> None:
"""Test async_unload_entry unloads platforms and closes the device."""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA)
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA, minor_version=2)
entry.add_to_hass(hass)
device = DummyDevice(DeviceType.AC)
with patch(
@@ -62,7 +64,7 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
async def test_async_setup_entry_paths(hass: HomeAssistant) -> None:
"""Test async_setup_entry for success and no-device return."""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA)
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA, minor_version=2)
entry.add_to_hass(hass)
with patch(
"homeassistant.components.midea.device_selector",
@@ -74,6 +76,7 @@ async def test_async_setup_entry_paths(hass: HomeAssistant) -> None:
entry2 = MockConfigEntry(
domain=DOMAIN,
data={**_ENTRY_DATA, CONF_DEVICE_ID: TEST_DEVICE_ID + 1},
minor_version=2,
)
entry2.add_to_hass(hass)
with patch(
@@ -94,7 +97,7 @@ async def test_setup_entry_not_ready_on_connect_failure(
It can also leave the socket open in that case (e.g. when authentication
fails), so the socket must be closed explicitly to avoid a ResourceWarning.
"""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA)
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA, minor_version=2)
entry.add_to_hass(hass)
device = DummyDevice(DeviceType.AC)
with (
@@ -164,3 +167,94 @@ async def test_setup_entry_no_recovery_when_device_not_discovered(
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.SETUP_RETRY
assert entry.data[CONF_IP_ADDRESS] == _ENTRY_DATA[CONF_IP_ADDRESS]
async def test_migrate_entry_backfills_mac_and_serial_number(
hass: HomeAssistant,
) -> None:
"""Test migration to minor_version 2 backfills mac and serial number."""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA, minor_version=1)
entry.add_to_hass(hass)
with (
patch(
"homeassistant.components.midea.discover",
return_value={
TEST_DEVICE_ID: {
CONF_IP_ADDRESS: TEST_IP_ADDRESS,
CONF_MAC: TEST_MAC_ADDRESS,
CONF_SN: TEST_SERIAL_NUMBER,
}
},
),
patch(
"homeassistant.components.midea.device_selector",
return_value=DummyDevice(DeviceType.AC),
),
):
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED
assert entry.minor_version == 2
assert entry.data[CONF_MAC] == TEST_MAC_ADDRESS
assert entry.data[CONF_SN] == TEST_SERIAL_NUMBER
async def test_migrate_entry_drops_empty_mac_connection(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test migration removes a leftover empty network-mac connection."""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA, minor_version=1)
entry.add_to_hass(hass)
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, str(TEST_DEVICE_ID))},
connections={
(dr.CONNECTION_NETWORK_MAC, "None"),
(dr.CONNECTION_NETWORK_MAC, TEST_MAC_ADDRESS),
},
)
with (
patch(
"homeassistant.components.midea.discover",
return_value={
TEST_DEVICE_ID: {
CONF_IP_ADDRESS: TEST_IP_ADDRESS,
CONF_MAC: TEST_MAC_ADDRESS,
CONF_SN: TEST_SERIAL_NUMBER,
}
},
),
patch(
"homeassistant.components.midea.device_selector",
return_value=DummyDevice(DeviceType.AC),
),
):
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED
device_entry = device_registry.async_get_device_by_identifier(
(DOMAIN, str(TEST_DEVICE_ID)), entry.entry_id
)
assert device_entry is not None
assert device_entry.connections == {(dr.CONNECTION_NETWORK_MAC, TEST_MAC_ADDRESS)}
async def test_migrate_entry_without_discovery_result(hass: HomeAssistant) -> None:
"""Test migration still completes when discovery finds nothing."""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA, minor_version=1)
entry.add_to_hass(hass)
with (
patch("homeassistant.components.midea.discover", return_value={}),
patch(
"homeassistant.components.midea.device_selector",
return_value=DummyDevice(DeviceType.AC),
),
):
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED
assert entry.minor_version == 2
assert CONF_MAC not in entry.data
assert CONF_SN not in entry.data