1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-02 08:26:41 +01:00

Add light support for HmIP-MP3P (Combination Signalling Device) (#162825)

This commit is contained in:
Christian Lackas
2026-03-16 20:43:36 +01:00
committed by GitHub
parent 4d8cedb061
commit 879178e8a2
3 changed files with 131 additions and 2 deletions

View File

@@ -11,10 +11,14 @@ from homematicip.base.enums import (
OpticalSignalBehaviour,
RGBColorState,
)
from homematicip.base.functionalChannels import NotificationLightChannel
from homematicip.base.functionalChannels import (
NotificationLightChannel,
NotificationMp3SoundChannel,
)
from homematicip.device import (
BrandDimmer,
BrandSwitchNotificationLight,
CombinationSignallingDevice,
Device,
Dimmer,
DinRailDimmer3,
@@ -108,6 +112,8 @@ async def async_setup_entry(
entities.append(
HomematicipOpticalSignalLight(hap, device, ch.index, led_number)
)
elif isinstance(device, CombinationSignallingDevice):
entities.append(HomematicipCombinationSignallingLight(hap, device))
async_add_entities(entities)
@@ -586,3 +592,70 @@ class HomematicipOpticalSignalLight(HomematicipGenericEntity, LightEntity):
rgb=simple_rgb_color,
dimLevel=0.0,
)
class HomematicipCombinationSignallingLight(HomematicipGenericEntity, LightEntity):
"""Representation of the HomematicIP combination signalling device light (HmIP-MP3P)."""
_attr_color_mode = ColorMode.HS
_attr_supported_color_modes = {ColorMode.HS}
_color_switcher: dict[str, tuple[float, float]] = {
RGBColorState.WHITE: (0.0, 0.0),
RGBColorState.RED: (0.0, 100.0),
RGBColorState.YELLOW: (60.0, 100.0),
RGBColorState.GREEN: (120.0, 100.0),
RGBColorState.TURQUOISE: (180.0, 100.0),
RGBColorState.BLUE: (240.0, 100.0),
RGBColorState.PURPLE: (300.0, 100.0),
}
def __init__(
self, hap: HomematicipHAP, device: CombinationSignallingDevice
) -> None:
"""Initialize the combination signalling light entity."""
super().__init__(hap, device, channel=1, is_multi_channel=False)
@property
def _func_channel(self) -> NotificationMp3SoundChannel:
return self._device.functionalChannels[self._channel]
@property
def is_on(self) -> bool:
"""Return true if light is on."""
return self._func_channel.on
@property
def brightness(self) -> int:
"""Return the brightness of this light between 0..255."""
return int((self._func_channel.dimLevel or 0.0) * 255)
@property
def hs_color(self) -> tuple[float, float]:
"""Return the hue and saturation color value [float, float]."""
simple_rgb_color = self._func_channel.simpleRGBColorState
return self._color_switcher.get(simple_rgb_color, (0.0, 0.0))
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the light on."""
hs_color = kwargs.get(ATTR_HS_COLOR, self.hs_color)
simple_rgb_color = _convert_color(hs_color)
brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness)
# Default to full brightness when no kwargs given
if not kwargs:
brightness = 255
# Minimum brightness is 10, otherwise the LED is disabled
brightness = max(10, brightness)
dim_level = brightness / 255.0
await self._func_channel.set_rgb_dim_level_async(
rgb_color_state=simple_rgb_color.name,
dim_level=dim_level,
)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
await self._func_channel.turn_off_async()

View File

@@ -22,7 +22,7 @@ async def test_hmip_load_all_supported_devices(
test_devices=None, test_groups=None
)
assert len(mock_hap.hmip_device_by_entity_id) == 350
assert len(mock_hap.hmip_device_by_entity_id) == 351
async def test_hmip_remove_device(

View File

@@ -854,3 +854,59 @@ async def test_hmip_wired_push_button_led_2(
assert hmip_device.mock_calls[-1][0] == "set_optical_signal_async"
assert hmip_device.mock_calls[-1][2]["channelIndex"] == 8
assert len(hmip_device.mock_calls) == service_call_counter + 1
async def test_hmip_combination_signalling_light(
hass: HomeAssistant, default_mock_hap_factory: HomeFactory
) -> None:
"""Test HomematicipCombinationSignallingLight (HmIP-MP3P)."""
entity_id = "light.kombisignalmelder"
entity_name = "Kombisignalmelder"
device_model = "HmIP-MP3P"
mock_hap = await default_mock_hap_factory.async_get_mock_hap(
test_devices=["Kombisignalmelder"]
)
ha_state, hmip_device = get_and_check_entity_basics(
hass, mock_hap, entity_id, entity_name, device_model
)
# Fixture has dimLevel=0.5, simpleRGBColorState=RED, on=true
assert ha_state.state == STATE_ON
assert ha_state.attributes[ATTR_COLOR_MODE] == ColorMode.HS
assert ha_state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.HS]
assert ha_state.attributes[ATTR_SUPPORTED_FEATURES] == 0
assert ha_state.attributes[ATTR_BRIGHTNESS] == 127 # 0.5 * 255
assert ha_state.attributes[ATTR_HS_COLOR] == (0.0, 100.0) # RED
functional_channel = hmip_device.functionalChannels[1]
service_call_counter = len(functional_channel.mock_calls)
# Test turn_on with color and brightness
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": entity_id, ATTR_HS_COLOR: [240.0, 100.0], ATTR_BRIGHTNESS: 255},
blocking=True,
)
assert functional_channel.mock_calls[-1][0] == "set_rgb_dim_level_async"
assert functional_channel.mock_calls[-1][2] == {
"rgb_color_state": "BLUE",
"dim_level": 1.0,
}
assert len(functional_channel.mock_calls) == service_call_counter + 1
# Test turn_off
await hass.services.async_call(
"light",
"turn_off",
{"entity_id": entity_id},
blocking=True,
)
assert functional_channel.mock_calls[-1][0] == "turn_off_async"
assert len(functional_channel.mock_calls) == service_call_counter + 2
# Test state update when turned off
await async_manipulate_test_data(hass, hmip_device, "on", False, channel=1)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF