Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ jobs:

# home-assistant/wheels doesn't support sha pinning
- name: Build wheels
uses: home-assistant/[email protected].0
uses: home-assistant/[email protected].1
with:
abi: ${{ matrix.abi }}
tag: musllinux_1_2
Expand Down Expand Up @@ -221,7 +221,7 @@ jobs:

# home-assistant/wheels doesn't support sha pinning
- name: Build wheels
uses: home-assistant/[email protected].0
uses: home-assistant/[email protected].1
with:
abi: ${{ matrix.abi }}
tag: musllinux_1_2
Expand Down
10 changes: 0 additions & 10 deletions homeassistant/components/bang_olufsen/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,12 @@ beolink_allstandby:
entity:
integration: bang_olufsen
domain: media_player
device:
integration: bang_olufsen

beolink_expand:
target:
entity:
integration: bang_olufsen
domain: media_player
device:
integration: bang_olufsen
fields:
all_discovered:
required: false
Expand All @@ -37,8 +33,6 @@ beolink_join:
entity:
integration: bang_olufsen
domain: media_player
device:
integration: bang_olufsen
fields:
jid_options:
collapsed: false
Expand Down Expand Up @@ -71,16 +65,12 @@ beolink_leave:
entity:
integration: bang_olufsen
domain: media_player
device:
integration: bang_olufsen

beolink_unexpand:
target:
entity:
integration: bang_olufsen
domain: media_player
device:
integration: bang_olufsen
fields:
jid_options:
collapsed: false
Expand Down
12 changes: 8 additions & 4 deletions homeassistant/components/comelit/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,27 @@
from .utils import async_client_session

DEFAULT_HOST = "192.168.1.252"
DEFAULT_PIN = 111111
DEFAULT_PIN = "111111"


pin_regex = r"^[0-9]{4,10}$"

USER_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST, default=DEFAULT_HOST): cv.string,
vol.Required(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_PIN, default=DEFAULT_PIN): cv.positive_int,
vol.Optional(CONF_PIN, default=DEFAULT_PIN): cv.matches_regex(pin_regex),
vol.Required(CONF_TYPE, default=BRIDGE): vol.In(DEVICE_TYPE_LIST),
}
)
STEP_REAUTH_DATA_SCHEMA = vol.Schema({vol.Required(CONF_PIN): cv.positive_int})
STEP_REAUTH_DATA_SCHEMA = vol.Schema(
{vol.Required(CONF_PIN): cv.matches_regex(pin_regex)}
)
STEP_RECONFIGURE = vol.Schema(
{
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PORT): cv.port,
vol.Optional(CONF_PIN, default=DEFAULT_PIN): cv.positive_int,
vol.Optional(CONF_PIN, default=DEFAULT_PIN): cv.matches_regex(pin_regex),
}
)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/home_connect/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
"iot_class": "cloud_push",
"loggers": ["aiohomeconnect"],
"quality_scale": "platinum",
"requirements": ["aiohomeconnect==0.19.0"],
"requirements": ["aiohomeconnect==0.20.0"],
"zeroconf": ["_homeconnect._tcp.local."]
}
58 changes: 37 additions & 21 deletions homeassistant/components/zha/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from homeassistant.components.homeassistant_yellow import hardware as yellow_hardware
from homeassistant.config_entries import (
SOURCE_IGNORE,
SOURCE_ZEROCONF,
ConfigEntry,
ConfigEntryBaseFlow,
ConfigEntryState,
Expand Down Expand Up @@ -183,27 +184,17 @@ def hass(self, hass: HomeAssistant) -> None:
self._hass = hass
self._radio_mgr.hass = hass

async def _get_config_entry_data(self) -> dict:
def _get_config_entry_data(self) -> dict[str, Any]:
"""Extract ZHA config entry data from the radio manager."""
assert self._radio_mgr.radio_type is not None
assert self._radio_mgr.device_path is not None
assert self._radio_mgr.device_settings is not None

try:
device_path = await self.hass.async_add_executor_job(
usb.get_serial_by_id, self._radio_mgr.device_path
)
except OSError as error:
raise AbortFlow(
reason="cannot_resolve_path",
description_placeholders={"path": self._radio_mgr.device_path},
) from error

return {
CONF_DEVICE: DEVICE_SCHEMA(
{
**self._radio_mgr.device_settings,
CONF_DEVICE_PATH: device_path,
CONF_DEVICE_PATH: self._radio_mgr.device_path,
}
),
CONF_RADIO_TYPE: self._radio_mgr.radio_type.name,
Expand Down Expand Up @@ -662,13 +653,8 @@ async def _set_unique_id_and_update_ignored_flow(
"""Set the flow's unique ID and update the device path in an ignored flow."""
current_entry = await self.async_set_unique_id(unique_id)

if not current_entry:
return

if current_entry.source != SOURCE_IGNORE:
self._abort_if_unique_id_configured()
else:
# Only update the current entry if it is an ignored discovery
# Only update the current entry if it is an ignored discovery
if current_entry and current_entry.source == SOURCE_IGNORE:
self._abort_if_unique_id_configured(
updates={
CONF_DEVICE: {
Expand Down Expand Up @@ -703,6 +689,36 @@ async def async_step_confirm(
DOMAIN, include_ignore=False
)

if self._radio_mgr.device_path is not None:
# Ensure the radio manager device path is unique and will match ZHA's
try:
self._radio_mgr.device_path = await self.hass.async_add_executor_job(
usb.get_serial_by_id, self._radio_mgr.device_path
)
except OSError as error:
raise AbortFlow(
reason="cannot_resolve_path",
description_placeholders={"path": self._radio_mgr.device_path},
) from error

# mDNS discovery can advertise the same adapter on multiple IPs or via a
# hostname, which should be considered a duplicate
current_device_paths = {self._radio_mgr.device_path}

if self.source == SOURCE_ZEROCONF:
discovery_info = self.init_data
current_device_paths |= {
f"socket://{ip}:{discovery_info.port}"
for ip in discovery_info.ip_addresses
}

for entry in zha_config_entries:
path = entry.data.get(CONF_DEVICE, {}).get(CONF_DEVICE_PATH)

# Abort discovery if the device path is already configured
if path is not None and path in current_device_paths:
return self.async_abort(reason="single_instance_allowed")

# Without confirmation, discovery can automatically progress into parts of the
# config flow logic that interacts with hardware.
if user_input is not None or (
Expand Down Expand Up @@ -873,7 +889,7 @@ async def _async_create_radio_entry(self) -> ConfigFlowResult:
zha_config_entries = self.hass.config_entries.async_entries(
DOMAIN, include_ignore=False
)
data = await self._get_config_entry_data()
data = self._get_config_entry_data()

if len(zha_config_entries) == 1:
return self.async_update_reload_and_abort(
Expand Down Expand Up @@ -976,7 +992,7 @@ async def _async_create_radio_entry(self):
# Avoid creating both `.options` and `.data` by directly writing `data` here
self.hass.config_entries.async_update_entry(
entry=self.config_entry,
data=await self._get_config_entry_data(),
data=self._get_config_entry_data(),
options=self.config_entry.options,
)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/zha/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"zha",
"universal_silabs_flasher"
],
"requirements": ["zha==0.0.72"],
"requirements": ["zha==0.0.73"],
"usb": [
{
"vid": "10C4",
Expand Down
4 changes: 2 additions & 2 deletions requirements_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions requirements_test_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions tests/components/comelit/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@

BRIDGE_HOST = "fake_bridge_host"
BRIDGE_PORT = 80
BRIDGE_PIN = 1234
BRIDGE_PIN = "1234"

VEDO_HOST = "fake_vedo_host"
VEDO_PORT = 8080
VEDO_PIN = 5678
VEDO_PIN = "5678"

FAKE_PIN = 0000
FAKE_PIN = "0000"
BAD_PIN = "abcd"

LIGHT0 = ComelitSerialBridgeObject(
index=0,
Expand Down
46 changes: 45 additions & 1 deletion tests/components/comelit/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_HOST, CONF_PIN, CONF_PORT, CONF_TYPE
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.data_entry_flow import FlowResultType, InvalidData

from .const import (
BAD_PIN,
BRIDGE_HOST,
BRIDGE_PIN,
BRIDGE_PORT,
Expand Down Expand Up @@ -310,3 +311,46 @@ async def test_reconfigure_fails(
CONF_PIN: BRIDGE_PIN,
CONF_TYPE: BRIDGE,
}


async def test_pin_format_serial_bridge(
hass: HomeAssistant,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
) -> None:
"""Test PIN is valid format."""

result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"

with pytest.raises(InvalidData):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: BRIDGE_HOST,
CONF_PORT: BRIDGE_PORT,
CONF_PIN: BAD_PIN,
},
)
assert result["type"] is FlowResultType.FORM

result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: BRIDGE_HOST,
CONF_PORT: BRIDGE_PORT,
CONF_PIN: BRIDGE_PIN,
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"] == {
CONF_HOST: BRIDGE_HOST,
CONF_PORT: BRIDGE_PORT,
CONF_PIN: BRIDGE_PIN,
CONF_TYPE: BRIDGE,
}
assert not result["result"].unique_id
await hass.async_block_till_done()
Loading
Loading