mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Add scene platform to Qbus integration (#144032)
* Add scene platform * Remove updating last_activated * Simplify device info * Move _attr_name to specific classes * Refactor device info --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
54dce53628
commit
486535c189
@ -57,6 +57,7 @@ async def async_setup_entry(
|
||||
class QbusClimate(QbusEntity, ClimateEntity):
|
||||
"""Representation of a Qbus climate entity."""
|
||||
|
||||
_attr_name = None
|
||||
_attr_hvac_modes = [HVACMode.HEAT]
|
||||
_attr_supported_features = (
|
||||
ClimateEntityFeature.PRESET_MODE | ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
|
@ -8,6 +8,7 @@ DOMAIN: Final = "qbus"
|
||||
PLATFORMS: list[Platform] = [
|
||||
Platform.CLIMATE,
|
||||
Platform.LIGHT,
|
||||
Platform.SCENE,
|
||||
Platform.SWITCH,
|
||||
]
|
||||
|
||||
|
@ -105,6 +105,7 @@ class QbusControllerCoordinator(DataUpdateCoordinator[list[QbusMqttOutput]]):
|
||||
device_registry = dr.async_get(self.hass)
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=self.config_entry.entry_id,
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, self._controller.mac)},
|
||||
identifiers={(DOMAIN, format_mac(self._controller.mac))},
|
||||
manufacturer=MANUFACTURER,
|
||||
model="CTD3.x",
|
||||
|
@ -54,34 +54,39 @@ def format_ref_id(ref_id: str) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def create_main_device_identifier(mqtt_output: QbusMqttOutput) -> tuple[str, str]:
|
||||
"""Create the identifier referring to the main device this output belongs to."""
|
||||
return (DOMAIN, format_mac(mqtt_output.device.mac))
|
||||
|
||||
|
||||
class QbusEntity(Entity, ABC):
|
||||
"""Representation of a Qbus entity."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
_attr_name = None
|
||||
_attr_should_poll = False
|
||||
|
||||
def __init__(self, mqtt_output: QbusMqttOutput) -> None:
|
||||
"""Initialize the Qbus entity."""
|
||||
|
||||
self._mqtt_output = mqtt_output
|
||||
|
||||
self._topic_factory = QbusMqttTopicFactory()
|
||||
self._message_factory = QbusMqttMessageFactory()
|
||||
self._state_topic = self._topic_factory.get_output_state_topic(
|
||||
mqtt_output.device.id, mqtt_output.id
|
||||
)
|
||||
|
||||
ref_id = format_ref_id(mqtt_output.ref_id)
|
||||
|
||||
self._attr_unique_id = f"ctd_{mqtt_output.device.serial_number}_{ref_id}"
|
||||
|
||||
# Create linked device
|
||||
self._attr_device_info = DeviceInfo(
|
||||
name=mqtt_output.name.title(),
|
||||
manufacturer=MANUFACTURER,
|
||||
identifiers={(DOMAIN, f"{mqtt_output.device.serial_number}_{ref_id}")},
|
||||
suggested_area=mqtt_output.location.title(),
|
||||
via_device=(DOMAIN, format_mac(mqtt_output.device.mac)),
|
||||
)
|
||||
|
||||
self._mqtt_output = mqtt_output
|
||||
self._state_topic = self._topic_factory.get_output_state_topic(
|
||||
mqtt_output.device.id, mqtt_output.id
|
||||
via_device=create_main_device_identifier(mqtt_output),
|
||||
)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
|
@ -43,6 +43,7 @@ async def async_setup_entry(
|
||||
class QbusLight(QbusEntity, LightEntity):
|
||||
"""Representation of a Qbus light entity."""
|
||||
|
||||
_attr_name = None
|
||||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||
_attr_color_mode = ColorMode.BRIGHTNESS
|
||||
|
||||
|
66
homeassistant/components/qbus/scene.py
Normal file
66
homeassistant/components/qbus/scene.py
Normal file
@ -0,0 +1,66 @@
|
||||
"""Support for Qbus scene."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from qbusmqttapi.discovery import QbusMqttOutput
|
||||
from qbusmqttapi.state import QbusMqttState, StateAction, StateType
|
||||
|
||||
from homeassistant.components.mqtt import ReceiveMessage
|
||||
from homeassistant.components.scene import Scene
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from .coordinator import QbusConfigEntry
|
||||
from .entity import QbusEntity, add_new_outputs, create_main_device_identifier
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: QbusConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up scene entities."""
|
||||
|
||||
coordinator = entry.runtime_data
|
||||
added_outputs: list[QbusMqttOutput] = []
|
||||
|
||||
def _check_outputs() -> None:
|
||||
add_new_outputs(
|
||||
coordinator,
|
||||
added_outputs,
|
||||
lambda output: output.type == "scene",
|
||||
QbusScene,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
_check_outputs()
|
||||
entry.async_on_unload(coordinator.async_add_listener(_check_outputs))
|
||||
|
||||
|
||||
class QbusScene(QbusEntity, Scene):
|
||||
"""Representation of a Qbus scene entity."""
|
||||
|
||||
def __init__(self, mqtt_output: QbusMqttOutput) -> None:
|
||||
"""Initialize scene entity."""
|
||||
|
||||
super().__init__(mqtt_output)
|
||||
|
||||
# Add to main controller device
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={create_main_device_identifier(mqtt_output)}
|
||||
)
|
||||
self._attr_name = mqtt_output.name.title()
|
||||
|
||||
async def async_activate(self, **kwargs: Any) -> None:
|
||||
"""Activate scene."""
|
||||
state = QbusMqttState(
|
||||
id=self._mqtt_output.id, type=StateType.ACTION, action=StateAction.ACTIVE
|
||||
)
|
||||
await self._async_publish_output_state(state)
|
||||
|
||||
async def _state_received(self, msg: ReceiveMessage) -> None:
|
||||
# Nothing to do
|
||||
pass
|
@ -42,6 +42,7 @@ async def async_setup_entry(
|
||||
class QbusSwitch(QbusEntity, SwitchEntity):
|
||||
"""Representation of a Qbus switch entity."""
|
||||
|
||||
_attr_name = None
|
||||
_attr_device_class = SwitchDeviceClass.SWITCH
|
||||
|
||||
def __init__(self, mqtt_output: QbusMqttOutput) -> None:
|
||||
|
@ -99,6 +99,19 @@
|
||||
"write": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "UL25",
|
||||
"location": "Living",
|
||||
"locationId": 0,
|
||||
"name": "Watching TV",
|
||||
"originalName": "Watching TV",
|
||||
"refId": "000001/105/3",
|
||||
"type": "scene",
|
||||
"actions": {
|
||||
"active": null
|
||||
},
|
||||
"properties": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
45
tests/components/qbus/test_scene.py
Normal file
45
tests/components/qbus/test_scene.py
Normal file
@ -0,0 +1,45 @@
|
||||
"""Test Qbus scene entities."""
|
||||
|
||||
from homeassistant.components.scene import DOMAIN as SCENE_DOMAIN, SERVICE_TURN_ON
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import async_fire_mqtt_message
|
||||
from tests.typing import MqttMockHAClient
|
||||
|
||||
_PAYLOAD_SCENE_STATE = '{"id":"UL25","properties":{"value":true},"type":"state"}'
|
||||
_PAYLOAD_SCENE_ACTIVATE = '{"id": "UL25", "type": "action", "action": "active"}'
|
||||
|
||||
_TOPIC_SCENE_STATE = "cloudapp/QBUSMQTTGW/UL1/UL25/state"
|
||||
_TOPIC_SCENE_SET_STATE = "cloudapp/QBUSMQTTGW/UL1/UL25/setState"
|
||||
|
||||
_SCENE_ENTITY_ID = "scene.ctd_000001_watching_tv"
|
||||
|
||||
|
||||
async def test_scene(
|
||||
hass: HomeAssistant,
|
||||
mqtt_mock: MqttMockHAClient,
|
||||
setup_integration: None,
|
||||
) -> None:
|
||||
"""Test scene."""
|
||||
|
||||
assert hass.states.get(_SCENE_ENTITY_ID).state == STATE_UNKNOWN
|
||||
|
||||
# Activate scene
|
||||
mqtt_mock.reset_mock()
|
||||
await hass.services.async_call(
|
||||
SCENE_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: _SCENE_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
_TOPIC_SCENE_SET_STATE, _PAYLOAD_SCENE_ACTIVATE, 0, False
|
||||
)
|
||||
|
||||
# Simulate response
|
||||
async_fire_mqtt_message(hass, _TOPIC_SCENE_STATE, _PAYLOAD_SCENE_STATE)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(_SCENE_ENTITY_ID).state != STATE_UNKNOWN
|
Loading…
x
Reference in New Issue
Block a user