Add climate platform to qbus (#139327)
* Add climate platform * Add unit tests for climate platform * Use setup_integration fixture * Apply new import order * Undo import order * Code review * Throw an exception on invalid preset mode * Let device response determine state * Remove hvac mode OFF * Remove hvac mode OFF * Setup debouncer when being added to hass * Fix typopull/141431/head^2
parent
e2a3bfca9a
commit
2208650fde
|
@ -0,0 +1,172 @@
|
|||
"""Support for Qbus thermostat."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from qbusmqttapi.const import KEY_PROPERTIES_REGIME, KEY_PROPERTIES_SET_TEMPERATURE
|
||||
from qbusmqttapi.discovery import QbusMqttOutput
|
||||
from qbusmqttapi.state import QbusMqttThermoState, StateType
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ClimateEntity,
|
||||
ClimateEntityFeature,
|
||||
HVACAction,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.components.mqtt import ReceiveMessage, client as mqtt
|
||||
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
from homeassistant.helpers.debounce import Debouncer
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import QbusConfigEntry
|
||||
from .entity import QbusEntity, add_new_outputs
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
STATE_REQUEST_DELAY = 2
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: QbusConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up climate entities."""
|
||||
|
||||
coordinator = entry.runtime_data
|
||||
added_outputs: list[QbusMqttOutput] = []
|
||||
|
||||
def _check_outputs() -> None:
|
||||
add_new_outputs(
|
||||
coordinator,
|
||||
added_outputs,
|
||||
lambda output: output.type == "thermo",
|
||||
QbusClimate,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
_check_outputs()
|
||||
entry.async_on_unload(coordinator.async_add_listener(_check_outputs))
|
||||
|
||||
|
||||
class QbusClimate(QbusEntity, ClimateEntity):
|
||||
"""Representation of a Qbus climate entity."""
|
||||
|
||||
_attr_hvac_modes = [HVACMode.HEAT]
|
||||
_attr_supported_features = (
|
||||
ClimateEntityFeature.PRESET_MODE | ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
)
|
||||
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
|
||||
def __init__(self, mqtt_output: QbusMqttOutput) -> None:
|
||||
"""Initialize climate entity."""
|
||||
|
||||
super().__init__(mqtt_output)
|
||||
|
||||
self._attr_hvac_action = HVACAction.IDLE
|
||||
self._attr_hvac_mode = HVACMode.HEAT
|
||||
|
||||
set_temp: dict[str, Any] = mqtt_output.properties.get(
|
||||
KEY_PROPERTIES_SET_TEMPERATURE, {}
|
||||
)
|
||||
current_regime: dict[str, Any] = mqtt_output.properties.get(
|
||||
KEY_PROPERTIES_REGIME, {}
|
||||
)
|
||||
|
||||
self._attr_min_temp: float = set_temp.get("min", 0)
|
||||
self._attr_max_temp: float = set_temp.get("max", 35)
|
||||
self._attr_target_temperature_step: float = set_temp.get("step", 0.5)
|
||||
self._attr_preset_modes: list[str] = current_regime.get("enumValues", [])
|
||||
self._attr_preset_mode: str = (
|
||||
self._attr_preset_modes[0] if len(self._attr_preset_modes) > 0 else ""
|
||||
)
|
||||
|
||||
self._request_state_debouncer: Debouncer | None = None
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Run when entity about to be added to hass."""
|
||||
self._request_state_debouncer = Debouncer(
|
||||
self.hass,
|
||||
_LOGGER,
|
||||
cooldown=STATE_REQUEST_DELAY,
|
||||
immediate=False,
|
||||
function=self._async_request_state,
|
||||
)
|
||||
await super().async_added_to_hass()
|
||||
|
||||
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Set new target preset mode."""
|
||||
|
||||
if preset_mode not in self._attr_preset_modes:
|
||||
raise ServiceValidationError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="invalid_preset",
|
||||
translation_placeholders={
|
||||
"preset": preset_mode,
|
||||
"options": ", ".join(self._attr_preset_modes),
|
||||
},
|
||||
)
|
||||
|
||||
state = QbusMqttThermoState(id=self._mqtt_output.id, type=StateType.STATE)
|
||||
state.write_regime(preset_mode)
|
||||
|
||||
await self._async_publish_output_state(state)
|
||||
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set new target temperature."""
|
||||
temperature = kwargs.get(ATTR_TEMPERATURE)
|
||||
|
||||
if temperature is not None and isinstance(temperature, float):
|
||||
state = QbusMqttThermoState(id=self._mqtt_output.id, type=StateType.STATE)
|
||||
state.write_set_temperature(temperature)
|
||||
|
||||
await self._async_publish_output_state(state)
|
||||
|
||||
async def _state_received(self, msg: ReceiveMessage) -> None:
|
||||
state = self._message_factory.parse_output_state(
|
||||
QbusMqttThermoState, msg.payload
|
||||
)
|
||||
|
||||
if state is None:
|
||||
return
|
||||
|
||||
if preset_mode := state.read_regime():
|
||||
self._attr_preset_mode = preset_mode
|
||||
|
||||
if current_temperature := state.read_current_temperature():
|
||||
self._attr_current_temperature = current_temperature
|
||||
|
||||
if target_temperature := state.read_set_temperature():
|
||||
self._attr_target_temperature = target_temperature
|
||||
|
||||
self._set_hvac_action()
|
||||
|
||||
# When the state type is "event", the payload only contains the changed
|
||||
# property. Request the state to get the full payload. However, changing
|
||||
# temperature step by step could cause a flood of state requests, so we're
|
||||
# holding off a few seconds before requesting the full state.
|
||||
if state.type == StateType.EVENT:
|
||||
assert self._request_state_debouncer is not None
|
||||
await self._request_state_debouncer.async_call()
|
||||
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
def _set_hvac_action(self) -> None:
|
||||
if self.target_temperature is None or self.current_temperature is None:
|
||||
self._attr_hvac_action = HVACAction.IDLE
|
||||
return
|
||||
|
||||
self._attr_hvac_action = (
|
||||
HVACAction.HEATING
|
||||
if self.target_temperature > self.current_temperature
|
||||
else HVACAction.IDLE
|
||||
)
|
||||
|
||||
async def _async_request_state(self) -> None:
|
||||
request = self._message_factory.create_state_request([self._mqtt_output.id])
|
||||
await mqtt.async_publish(self.hass, request.topic, request.payload)
|
|
@ -6,6 +6,7 @@ from homeassistant.const import Platform
|
|||
|
||||
DOMAIN: Final = "qbus"
|
||||
PLATFORMS: list[Platform] = [
|
||||
Platform.CLIMATE,
|
||||
Platform.LIGHT,
|
||||
Platform.SWITCH,
|
||||
]
|
||||
|
|
|
@ -15,5 +15,10 @@
|
|||
"error": {
|
||||
"no_controller": "No controllers were found"
|
||||
}
|
||||
},
|
||||
"exceptions": {
|
||||
"invalid_preset": {
|
||||
"message": "Preset mode \"{preset}\" is not valid. Valid preset modes are: {options}."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
"""Test fixtures for qbus."""
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.qbus.const import CONF_SERIAL_NUMBER, DOMAIN
|
||||
|
@ -7,9 +9,13 @@ from homeassistant.const import CONF_ID
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util.json import JsonObjectType
|
||||
|
||||
from .const import FIXTURE_PAYLOAD_CONFIG
|
||||
from .const import FIXTURE_PAYLOAD_CONFIG, TOPIC_CONFIG
|
||||
|
||||
from tests.common import MockConfigEntry, load_json_object_fixture
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
async_fire_mqtt_message,
|
||||
load_json_object_fixture,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -31,3 +37,18 @@ def mock_config_entry(hass: HomeAssistant) -> MockConfigEntry:
|
|||
def payload_config() -> JsonObjectType:
|
||||
"""Return the config topic payload."""
|
||||
return load_json_object_fixture(FIXTURE_PAYLOAD_CONFIG, DOMAIN)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def setup_integration(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
payload_config: JsonObjectType,
|
||||
) -> None:
|
||||
"""Set up the integration."""
|
||||
|
||||
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
async_fire_mqtt_message(hass, TOPIC_CONFIG, json.dumps(payload_config))
|
||||
await hass.async_block_till_done()
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
{
|
||||
"id": "UL15",
|
||||
"location": "Media room",
|
||||
"locationId": 0,
|
||||
"locationId": 1,
|
||||
"name": "MEDIA ROOM",
|
||||
"originalName": "MEDIA ROOM",
|
||||
"refId": "000001/28",
|
||||
|
@ -65,6 +65,40 @@
|
|||
"write": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "UL20",
|
||||
"location": "Living",
|
||||
"locationId": 0,
|
||||
"name": "LIVING TH",
|
||||
"originalName": "LIVING TH",
|
||||
"refId": "000001/120",
|
||||
"type": "thermo",
|
||||
"actions": {},
|
||||
"properties": {
|
||||
"currRegime": {
|
||||
"enumValues": ["MANUEEL", "VORST", "ECONOMY", "COMFORT", "NACHT"],
|
||||
"read": true,
|
||||
"type": "enumString",
|
||||
"write": true
|
||||
},
|
||||
"currTemp": {
|
||||
"max": 35,
|
||||
"min": 0,
|
||||
"read": true,
|
||||
"step": 0.5,
|
||||
"type": "number",
|
||||
"write": false
|
||||
},
|
||||
"setTemp": {
|
||||
"max": 35,
|
||||
"min": 0,
|
||||
"read": true,
|
||||
"step": 0.5,
|
||||
"type": "number",
|
||||
"write": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
"""Test Qbus light entities."""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import MagicMock, call
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ATTR_CURRENT_TEMPERATURE,
|
||||
ATTR_HVAC_ACTION,
|
||||
ATTR_PRESET_MODE,
|
||||
DOMAIN as CLIMATE_DOMAIN,
|
||||
SERVICE_SET_PRESET_MODE,
|
||||
SERVICE_SET_TEMPERATURE,
|
||||
ClimateEntity,
|
||||
HVACAction,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.components.qbus.climate import STATE_REQUEST_DELAY
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
from homeassistant.helpers.entity_platform import EntityPlatform
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from tests.common import async_fire_mqtt_message, async_fire_time_changed
|
||||
from tests.typing import MqttMockHAClient
|
||||
|
||||
_CURRENT_TEMPERATURE = 21.5
|
||||
_SET_TEMPERATURE = 20.5
|
||||
_REGIME = "COMFORT"
|
||||
|
||||
_PAYLOAD_CLIMATE_STATE_TEMP = (
|
||||
f'{{"id":"UL20","properties":{{"setTemp":{_SET_TEMPERATURE}}},"type":"event"}}'
|
||||
)
|
||||
_PAYLOAD_CLIMATE_STATE_TEMP_FULL = f'{{"id":"UL20","properties":{{"currRegime":"MANUEEL","currTemp":{_CURRENT_TEMPERATURE},"setTemp":{_SET_TEMPERATURE}}},"type":"state"}}'
|
||||
|
||||
_PAYLOAD_CLIMATE_STATE_PRESET = (
|
||||
f'{{"id":"UL20","properties":{{"currRegime":"{_REGIME}"}},"type":"event"}}'
|
||||
)
|
||||
_PAYLOAD_CLIMATE_STATE_PRESET_FULL = f'{{"id":"UL20","properties":{{"currRegime":"{_REGIME}","currTemp":{_CURRENT_TEMPERATURE},"setTemp":22.0}},"type":"state"}}'
|
||||
|
||||
_PAYLOAD_CLIMATE_SET_TEMP = f'{{"id": "UL20", "type": "state", "properties": {{"setTemp": {_SET_TEMPERATURE}}}}}'
|
||||
_PAYLOAD_CLIMATE_SET_PRESET = (
|
||||
'{"id": "UL20", "type": "state", "properties": {"currRegime": "COMFORT"}}'
|
||||
)
|
||||
|
||||
_TOPIC_CLIMATE_STATE = "cloudapp/QBUSMQTTGW/UL1/UL20/state"
|
||||
_TOPIC_CLIMATE_SET_STATE = "cloudapp/QBUSMQTTGW/UL1/UL20/setState"
|
||||
_TOPIC_GET_STATE = "cloudapp/QBUSMQTTGW/getState"
|
||||
|
||||
_CLIMATE_ENTITY_ID = "climate.living_th"
|
||||
|
||||
|
||||
async def test_climate(
|
||||
hass: HomeAssistant,
|
||||
mqtt_mock: MqttMockHAClient,
|
||||
setup_integration: None,
|
||||
) -> None:
|
||||
"""Test climate temperature & preset."""
|
||||
|
||||
# Set temperature
|
||||
mqtt_mock.reset_mock()
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_TEMPERATURE,
|
||||
{
|
||||
ATTR_ENTITY_ID: _CLIMATE_ENTITY_ID,
|
||||
ATTR_TEMPERATURE: _SET_TEMPERATURE,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
_TOPIC_CLIMATE_SET_STATE, _PAYLOAD_CLIMATE_SET_TEMP, 0, False
|
||||
)
|
||||
|
||||
# Simulate a partial state response
|
||||
async_fire_mqtt_message(hass, _TOPIC_CLIMATE_STATE, _PAYLOAD_CLIMATE_STATE_TEMP)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check state
|
||||
entity = hass.states.get(_CLIMATE_ENTITY_ID)
|
||||
assert entity
|
||||
assert entity.attributes[ATTR_TEMPERATURE] == _SET_TEMPERATURE
|
||||
assert entity.attributes[ATTR_CURRENT_TEMPERATURE] is None
|
||||
assert entity.attributes[ATTR_PRESET_MODE] == "MANUEEL"
|
||||
assert entity.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
|
||||
assert entity.state == HVACMode.HEAT
|
||||
|
||||
# After a delay, a full state request should've been sent
|
||||
_wait_and_assert_state_request(hass, mqtt_mock)
|
||||
|
||||
# Simulate a full state response
|
||||
async_fire_mqtt_message(
|
||||
hass, _TOPIC_CLIMATE_STATE, _PAYLOAD_CLIMATE_STATE_TEMP_FULL
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check state after full state response
|
||||
entity = hass.states.get(_CLIMATE_ENTITY_ID)
|
||||
assert entity
|
||||
assert entity.attributes[ATTR_TEMPERATURE] == _SET_TEMPERATURE
|
||||
assert entity.attributes[ATTR_CURRENT_TEMPERATURE] == _CURRENT_TEMPERATURE
|
||||
assert entity.attributes[ATTR_PRESET_MODE] == "MANUEEL"
|
||||
assert entity.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
|
||||
assert entity.state == HVACMode.HEAT
|
||||
|
||||
# Set preset
|
||||
mqtt_mock.reset_mock()
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_PRESET_MODE,
|
||||
{
|
||||
ATTR_ENTITY_ID: _CLIMATE_ENTITY_ID,
|
||||
ATTR_PRESET_MODE: _REGIME,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
_TOPIC_CLIMATE_SET_STATE, _PAYLOAD_CLIMATE_SET_PRESET, 0, False
|
||||
)
|
||||
|
||||
# Simulate a partial state response
|
||||
async_fire_mqtt_message(hass, _TOPIC_CLIMATE_STATE, _PAYLOAD_CLIMATE_STATE_PRESET)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check state
|
||||
entity = hass.states.get(_CLIMATE_ENTITY_ID)
|
||||
assert entity
|
||||
assert entity.attributes[ATTR_TEMPERATURE] == _SET_TEMPERATURE
|
||||
assert entity.attributes[ATTR_CURRENT_TEMPERATURE] == _CURRENT_TEMPERATURE
|
||||
assert entity.attributes[ATTR_PRESET_MODE] == _REGIME
|
||||
assert entity.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
|
||||
assert entity.state == HVACMode.HEAT
|
||||
|
||||
# After a delay, a full state request should've been sent
|
||||
_wait_and_assert_state_request(hass, mqtt_mock)
|
||||
|
||||
# Simulate a full state response
|
||||
async_fire_mqtt_message(
|
||||
hass, _TOPIC_CLIMATE_STATE, _PAYLOAD_CLIMATE_STATE_PRESET_FULL
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check state after full state response
|
||||
entity = hass.states.get(_CLIMATE_ENTITY_ID)
|
||||
assert entity
|
||||
assert entity.attributes[ATTR_TEMPERATURE] == 22.0
|
||||
assert entity.attributes[ATTR_CURRENT_TEMPERATURE] == _CURRENT_TEMPERATURE
|
||||
assert entity.attributes[ATTR_PRESET_MODE] == _REGIME
|
||||
assert entity.attributes[ATTR_HVAC_ACTION] == HVACAction.HEATING
|
||||
assert entity.state == HVACMode.HEAT
|
||||
|
||||
|
||||
async def test_climate_when_invalid_state_received(
|
||||
hass: HomeAssistant,
|
||||
mqtt_mock: MqttMockHAClient,
|
||||
setup_integration: None,
|
||||
) -> None:
|
||||
"""Test climate when no valid state is received."""
|
||||
|
||||
platform: EntityPlatform = hass.data["entity_components"][CLIMATE_DOMAIN]
|
||||
entity: ClimateEntity = next(
|
||||
(
|
||||
entity
|
||||
for entity in platform.entities
|
||||
if entity.entity_id == _CLIMATE_ENTITY_ID
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
assert entity
|
||||
entity.async_schedule_update_ha_state = MagicMock()
|
||||
|
||||
# Simulate state response
|
||||
async_fire_mqtt_message(hass, _TOPIC_CLIMATE_STATE, "")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity.async_schedule_update_ha_state.assert_not_called()
|
||||
|
||||
|
||||
async def test_climate_with_fast_subsequent_changes(
|
||||
hass: HomeAssistant,
|
||||
mqtt_mock: MqttMockHAClient,
|
||||
setup_integration: None,
|
||||
) -> None:
|
||||
"""Test climate with fast subsequent changes."""
|
||||
|
||||
# Simulate two subsequent partial state responses
|
||||
async_fire_mqtt_message(hass, _TOPIC_CLIMATE_STATE, _PAYLOAD_CLIMATE_STATE_TEMP)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(hass, _TOPIC_CLIMATE_STATE, _PAYLOAD_CLIMATE_STATE_TEMP)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# State request should be requested only once
|
||||
_wait_and_assert_state_request(hass, mqtt_mock)
|
||||
|
||||
|
||||
async def test_climate_with_unknown_preset(
|
||||
hass: HomeAssistant,
|
||||
mqtt_mock: MqttMockHAClient,
|
||||
setup_integration: None,
|
||||
) -> None:
|
||||
"""Test climate with passing an unknown preset value."""
|
||||
|
||||
with pytest.raises(ServiceValidationError):
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_PRESET_MODE,
|
||||
{
|
||||
ATTR_ENTITY_ID: _CLIMATE_ENTITY_ID,
|
||||
ATTR_PRESET_MODE: "What is cooler than being cool?",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
def _wait_and_assert_state_request(
|
||||
hass: HomeAssistant, mqtt_mock: MqttMockHAClient
|
||||
) -> None:
|
||||
mqtt_mock.reset_mock()
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(STATE_REQUEST_DELAY))
|
||||
mqtt_mock.async_publish.assert_has_calls(
|
||||
[call(_TOPIC_GET_STATE, '["UL20"]', 0, False)],
|
||||
any_order=True,
|
||||
)
|
|
@ -1,7 +1,5 @@
|
|||
"""Test Qbus light entities."""
|
||||
|
||||
import json
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
DOMAIN as LIGHT_DOMAIN,
|
||||
|
@ -10,11 +8,8 @@ from homeassistant.components.light import (
|
|||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util.json import JsonObjectType
|
||||
|
||||
from .const import TOPIC_CONFIG
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_mqtt_message
|
||||
from tests.common import async_fire_mqtt_message
|
||||
from tests.typing import MqttMockHAClient
|
||||
|
||||
# 186 = 73% (rounded)
|
||||
|
@ -44,17 +39,10 @@ _LIGHT_ENTITY_ID = "light.media_room"
|
|||
async def test_light(
|
||||
hass: HomeAssistant,
|
||||
mqtt_mock: MqttMockHAClient,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
payload_config: JsonObjectType,
|
||||
setup_integration: None,
|
||||
) -> None:
|
||||
"""Test turning on and off."""
|
||||
|
||||
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
async_fire_mqtt_message(hass, TOPIC_CONFIG, json.dumps(payload_config))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Switch ON
|
||||
mqtt_mock.reset_mock()
|
||||
await hass.services.async_call(
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
"""Test Qbus switch entities."""
|
||||
|
||||
import json
|
||||
|
||||
from homeassistant.components.switch import (
|
||||
DOMAIN as SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
|
@ -9,11 +7,8 @@ from homeassistant.components.switch import (
|
|||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util.json import JsonObjectType
|
||||
|
||||
from .const import TOPIC_CONFIG
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_mqtt_message
|
||||
from tests.common import async_fire_mqtt_message
|
||||
from tests.typing import MqttMockHAClient
|
||||
|
||||
_PAYLOAD_SWITCH_STATE_ON = '{"id":"UL10","properties":{"value":true},"type":"state"}'
|
||||
|
@ -34,17 +29,10 @@ _SWITCH_ENTITY_ID = "switch.living"
|
|||
async def test_switch_turn_on_off(
|
||||
hass: HomeAssistant,
|
||||
mqtt_mock: MqttMockHAClient,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
payload_config: JsonObjectType,
|
||||
setup_integration: None,
|
||||
) -> None:
|
||||
"""Test turning on and off."""
|
||||
|
||||
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
async_fire_mqtt_message(hass, TOPIC_CONFIG, json.dumps(payload_config))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Switch ON
|
||||
mqtt_mock.reset_mock()
|
||||
await hass.services.async_call(
|
||||
|
|
Loading…
Reference in New Issue