fix(config_flow): bekanntes Geraet auch an der verkuerzten mDNS-MAC erkennen
Die Firmware wirbt im TXT-Satz nur mit den letzten vier Hex-Stellen der MAC. Daraus wurde bisher direkt eine Kennung gebaut - die auf keinen Eintrag passte. Folge: Home Assistant bot nach jedem Neustart dieselben, laengst eingerichteten Strips erneut an, und beim Hinzufuegen kam 'bereits konfiguriert'. Vier Stellen sind keine Kennung, aber ein Hinweis: endet genau ein Eintrag so, ist er gemeint. Bei mehreren bleibt es unentschieden und der Ablauf fragt nach - vier Stellen sind nicht eindeutig genug, um einen fremden Eintrag stillschweigend umzuschreiben. Die Tests sahen das nicht, weil ihr mDNS-Fixture die volle MAC eintrug - eine Welt, die es am Geraet nicht gibt.
This commit is contained in:
@@ -97,13 +97,38 @@ class NinstripConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
def _kennung_aus_mdns(self, roh: str) -> str | None:
|
||||
"""Die Kennung zu dem, was im TXT-Satz unter "mac" steht.
|
||||
|
||||
Eine volle MAC ist die Kennung. Die Firmware wirbt aber nur mit den
|
||||
letzten vier Hex-Stellen (`nl_wifi_mac4()`, siehe nl_mdns.c) - daraus
|
||||
laesst sich keine bauen. Als *Hinweis* taugen sie trotzdem: endet
|
||||
genau ein eingerichteter Eintrag so, ist er gemeint.
|
||||
|
||||
Bei mehreren Treffern bleibt es unentschieden. Dann lieber nachfragen
|
||||
als den falschen Eintrag stillschweigend auf eine fremde Adresse
|
||||
umzuschreiben - vier Stellen sind nicht eindeutig.
|
||||
"""
|
||||
kennung = format_mac(roh)
|
||||
if len(kennung) == 17:
|
||||
return kennung
|
||||
kurz = roh.replace(":", "").replace("-", "").lower()
|
||||
if len(kurz) != 4:
|
||||
return None
|
||||
treffer = [
|
||||
eintrag.unique_id
|
||||
for eintrag in self._async_current_entries(include_ignore=False)
|
||||
if eintrag.unique_id and eintrag.unique_id.replace(":", "").endswith(kurz)
|
||||
]
|
||||
return treffer[0] if len(treffer) == 1 else None
|
||||
|
||||
async def async_step_zeroconf(self, discovery_info: ZeroconfServiceInfo) -> ConfigFlowResult:
|
||||
"""Gefunden ueber _ninstrip._tcp."""
|
||||
self._host = discovery_info.host
|
||||
props = discovery_info.properties or {}
|
||||
mac = props.get("mac")
|
||||
if mac:
|
||||
await self.async_set_unique_id(format_mac(str(mac)))
|
||||
if mac and (kennung := self._kennung_aus_mdns(str(mac))):
|
||||
await self.async_set_unique_id(kennung)
|
||||
self._abort_if_unique_id_configured(updates={CONF_HOST: self._host})
|
||||
self._discovered_name = str(props.get("name") or discovery_info.name.split(".")[0])
|
||||
self.context["title_placeholders"] = {"name": self._discovered_name}
|
||||
|
||||
@@ -296,3 +296,46 @@ async def test_neu_konfigurieren_lehnt_ein_anderes_geraet_ab(
|
||||
assert ergebnis["type"] is FlowResultType.ABORT
|
||||
assert ergebnis["reason"] == "wrong_device"
|
||||
assert eintrag.data[CONF_HOST] == HOST_K1Y
|
||||
|
||||
|
||||
async def test_mdns_mit_verkuerzter_mac_erkennt_das_bekannte_geraet(
|
||||
hass: HomeAssistant, mock_client: MagicMock
|
||||
) -> None:
|
||||
"""Die Firmware wirbt nur mit den letzten vier Hex-Stellen der MAC.
|
||||
|
||||
Genau so steht es im TXT-Satz am Geraet (`mac=ad4c`). Wird daraus eine
|
||||
Kennung gebaut, passt sie auf keinen Eintrag - und Home Assistant bietet
|
||||
nach jedem Neustart dasselbe, laengst eingerichtete Geraet erneut an.
|
||||
"""
|
||||
eintrag = bestehender_eintrag(hass)
|
||||
ergebnis = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=zeroconf_info(mac="ad4c")
|
||||
)
|
||||
assert ergebnis["type"] is FlowResultType.ABORT
|
||||
assert ergebnis["reason"] == "already_configured"
|
||||
assert eintrag.unique_id == MAC_K1Y
|
||||
|
||||
|
||||
async def test_mdns_mit_verkuerzter_mac_bleibt_bei_zwei_treffern_unentschieden(
|
||||
hass: HomeAssistant, mock_client: MagicMock
|
||||
) -> None:
|
||||
"""Vier Hex-Stellen sind nicht eindeutig.
|
||||
|
||||
Enden zwei eingerichtete Geraete gleich, darf keines davon stillschweigend
|
||||
auf die neue Adresse umgeschrieben werden - dann wird gefragt.
|
||||
"""
|
||||
erster = bestehender_eintrag(hass, "192.168.2.5")
|
||||
zweiter = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="Zwilling",
|
||||
unique_id="aa:bb:cc:dd:ad:4c",
|
||||
data={CONF_HOST: "192.168.2.6", CONF_TOKEN: TOKEN},
|
||||
)
|
||||
zweiter.add_to_hass(hass)
|
||||
|
||||
ergebnis = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=zeroconf_info(mac="ad4c")
|
||||
)
|
||||
assert ergebnis["type"] is FlowResultType.FORM
|
||||
assert erster.data[CONF_HOST] == "192.168.2.5"
|
||||
assert zweiter.data[CONF_HOST] == "192.168.2.6"
|
||||
|
||||
Reference in New Issue
Block a user