Beispiel #1
0
def _async_migrate_unique_id(hass: HomeAssistant,
                             platform_config: list[ConfigType]) -> None:
    """Change unique_ids used in 2021.4 to include target_temperature GA."""
    entity_registry = er.async_get(hass)
    for entity_config in platform_config:
        # normalize group address strings - ga_temperature_state was the old uid
        ga_temperature_state = parse_device_group_address(
            entity_config[ClimateSchema.CONF_TEMPERATURE_ADDRESS][0])
        old_uid = str(ga_temperature_state)

        entity_id = entity_registry.async_get_entity_id(
            "climate", DOMAIN, old_uid)
        if entity_id is None:
            continue
        ga_target_temperature_state = parse_device_group_address(entity_config[
            ClimateSchema.CONF_TARGET_TEMPERATURE_STATE_ADDRESS][0])
        target_temp = entity_config.get(
            ClimateSchema.CONF_TARGET_TEMPERATURE_ADDRESS)
        ga_target_temperature = (parse_device_group_address(target_temp[0])
                                 if target_temp is not None else None)
        setpoint_shift = entity_config.get(
            ClimateSchema.CONF_SETPOINT_SHIFT_ADDRESS)
        ga_setpoint_shift = (parse_device_group_address(setpoint_shift[0])
                             if setpoint_shift is not None else None)
        new_uid = (f"{ga_temperature_state}_"
                   f"{ga_target_temperature_state}_"
                   f"{ga_target_temperature}_"
                   f"{ga_setpoint_shift}")
        entity_registry.async_update_entity(entity_id, new_unique_id=new_uid)
Beispiel #2
0
def _async_migrate_unique_id(hass: HomeAssistant,
                             discovery_info: DiscoveryInfoType | None) -> None:
    """Change unique_ids used in 2021.4 to include position_target GA."""
    entity_registry = er.async_get(hass)
    if not discovery_info or not discovery_info["platform_config"]:
        return

    platform_config = discovery_info["platform_config"]
    for entity_config in platform_config:
        # normalize group address strings - ga_updown was the old uid but is optional
        updown_addresses = entity_config.get(
            CoverSchema.CONF_MOVE_LONG_ADDRESS)
        if updown_addresses is None:
            continue
        ga_updown = parse_device_group_address(updown_addresses[0])
        old_uid = str(ga_updown)

        entity_id = entity_registry.async_get_entity_id(
            "cover", DOMAIN, old_uid)
        if entity_id is None:
            continue
        position_target_addresses = entity_config.get(
            CoverSchema.CONF_POSITION_ADDRESS)
        ga_position_target = (parse_device_group_address(
            position_target_addresses[0]) if position_target_addresses
                              is not None else None)
        new_uid = f"{ga_updown}_{ga_position_target}"
        entity_registry.async_update_entity(entity_id, new_unique_id=new_uid)
Beispiel #3
0
def ga_validator(value: Any) -> str | int:
    """Validate that value is parsable as GroupAddress or InternalGroupAddress."""
    if isinstance(value, (str, int)):
        try:
            parse_device_group_address(value)
            return value
        except CouldNotParseAddress:
            pass
    raise vol.Invalid(
        f"value '{value}' is not a valid KNX group address '<main>/<middle>/<sub>', '<main>/<sub>' or '<free>' (eg.'1/2/3', '9/234', '123'), nor xknx internal address 'i-<string>'."
    )
Beispiel #4
0
    async def service_send_to_knx_bus(self, call: ServiceCall) -> None:
        """Service for sending an arbitrary KNX message to the KNX bus."""
        attr_address = call.data[KNX_ADDRESS]
        attr_payload = call.data[SERVICE_KNX_ATTR_PAYLOAD]
        attr_type = call.data.get(SERVICE_KNX_ATTR_TYPE)
        attr_response = call.data[SERVICE_KNX_ATTR_RESPONSE]

        payload: DPTBinary | DPTArray
        if attr_type is not None:
            transcoder = DPTBase.parse_transcoder(attr_type)
            if transcoder is None:
                raise ValueError(
                    f"Invalid type for knx.send service: {attr_type}")
            payload = DPTArray(transcoder.to_knx(attr_payload))
        elif isinstance(attr_payload, int):
            payload = DPTBinary(attr_payload)
        else:
            payload = DPTArray(attr_payload)

        for address in attr_address:
            telegram = Telegram(
                destination_address=parse_device_group_address(address),
                payload=GroupValueResponse(payload)
                if attr_response else GroupValueWrite(payload),
            )
            await self.xknx.telegrams.put(telegram)
 async def service_read_to_knx_bus(self, call: ServiceCall) -> None:
     """Service for sending a GroupValueRead telegram to the KNX bus."""
     for address in call.data[KNX_ADDRESS]:
         telegram = Telegram(
             destination_address=parse_device_group_address(address),
             payload=GroupValueRead(),
         )
         await self.xknx.telegrams.put(telegram)
Beispiel #6
0
 def unpack_group_addresses(
     addresses: GroupAddressesType | None,
 ) -> DeviceGroupAddress | None:
     """Parse group addresses and assign passive addresses when given."""
     if addresses is None:
         return None
     if not isinstance(addresses, list):
         return parse_device_group_address(addresses)
     active, *passive = map(parse_device_group_address, addresses)
     self.passive_group_addresses.extend(passive)  # type: ignore
     return active
Beispiel #7
0
def _async_migrate_unique_id(hass: HomeAssistant,
                             platform_config: list[ConfigType]) -> None:
    """Change unique_ids used in 2021.4 to exchange individual color switch address for brightness address."""
    entity_registry = er.async_get(hass)
    for entity_config in platform_config:
        individual_colors_config = entity_config.get(
            LightSchema.CONF_INDIVIDUAL_COLORS)
        if individual_colors_config is None:
            continue
        try:
            ga_red_switch = individual_colors_config[
                LightSchema.CONF_RED][KNX_ADDRESS][0]
            ga_green_switch = individual_colors_config[
                LightSchema.CONF_GREEN][KNX_ADDRESS][0]
            ga_blue_switch = individual_colors_config[
                LightSchema.CONF_BLUE][KNX_ADDRESS][0]
        except KeyError:
            continue
        # normalize group address strings
        ga_red_switch = parse_device_group_address(ga_red_switch)
        ga_green_switch = parse_device_group_address(ga_green_switch)
        ga_blue_switch = parse_device_group_address(ga_blue_switch)
        # white config is optional so it has to be checked for `None` extra
        white_config = individual_colors_config.get(LightSchema.CONF_WHITE)
        white_switch = (white_config.get(KNX_ADDRESS)
                        if white_config is not None else None)
        ga_white_switch = (parse_device_group_address(white_switch[0])
                           if white_switch is not None else None)

        old_uid = (f"{ga_red_switch}_"
                   f"{ga_green_switch}_"
                   f"{ga_blue_switch}_"
                   f"{ga_white_switch}")
        entity_id = entity_registry.async_get_entity_id(
            "light", DOMAIN, old_uid)
        if entity_id is None:
            continue

        ga_red_brightness = parse_device_group_address(
            individual_colors_config[LightSchema.CONF_RED][
                LightSchema.CONF_BRIGHTNESS_ADDRESS][0])
        ga_green_brightness = parse_device_group_address(
            individual_colors_config[LightSchema.CONF_GREEN][
                LightSchema.CONF_BRIGHTNESS_ADDRESS][0])
        ga_blue_brightness = parse_device_group_address(
            individual_colors_config[LightSchema.CONF_BLUE][
                LightSchema.CONF_BRIGHTNESS_ADDRESS][0])

        new_uid = f"{ga_red_brightness}_{ga_green_brightness}_{ga_blue_brightness}"
        entity_registry.async_update_entity(entity_id, new_unique_id=new_uid)
Beispiel #8
0
 def test_parse_invalid(self, address_test):
     """Test if the function raises CouldNotParseAddress on invalid values."""
     with pytest.raises(CouldNotParseAddress):
         parse_device_group_address(address_test)
Beispiel #9
0
 def test_parse_internal_group_address(self, address_test):
     """Test if the function returns InternalGroupAddress objects."""
     assert isinstance(parse_device_group_address(address_test),
                       InternalGroupAddress)