Log transmitted MQTT messages (#65550)

This commit is contained in:
Erik Montnemery 2022-02-04 17:35:32 +01:00 committed by GitHub
parent a95988c970
commit 8245ff7473
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 341 additions and 177 deletions

View file

@ -1184,7 +1184,7 @@ def _matcher_for_topic(subscription: str) -> Any:
async def websocket_mqtt_info(hass, connection, msg):
"""Get MQTT debug info for device."""
device_id = msg["device_id"]
mqtt_info = await debug_info.info_for_device(hass, device_id)
mqtt_info = debug_info.info_for_device(hass, device_id)
connection.send_result(msg["id"], mqtt_info)

View file

@ -328,8 +328,7 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
"""Publish via mqtt."""
variables = {"action": action, "code": code}
payload = self._command_template(None, variables=variables)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
payload,
self._config[CONF_QOS],

View file

@ -112,8 +112,7 @@ class MqttButton(MqttEntity, ButtonEntity):
This method is a coroutine.
"""
payload = self._command_template(self._config[CONF_PAYLOAD_PRESS])
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
payload,
self._config[CONF_QOS],

View file

@ -708,8 +708,7 @@ class MqttClimate(MqttEntity, ClimateEntity):
async def _publish(self, topic, payload):
if self._topic[topic] is not None:
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[topic],
payload,
self._config[CONF_QOS],

View file

@ -534,8 +534,7 @@ class MqttCover(MqttEntity, CoverEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config.get(CONF_COMMAND_TOPIC),
self._config[CONF_PAYLOAD_OPEN],
self._config[CONF_QOS],
@ -556,8 +555,7 @@ class MqttCover(MqttEntity, CoverEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config.get(CONF_COMMAND_TOPIC),
self._config[CONF_PAYLOAD_CLOSE],
self._config[CONF_QOS],
@ -578,8 +576,7 @@ class MqttCover(MqttEntity, CoverEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config.get(CONF_COMMAND_TOPIC),
self._config[CONF_PAYLOAD_STOP],
self._config[CONF_QOS],
@ -599,8 +596,7 @@ class MqttCover(MqttEntity, CoverEntity):
"tilt_max": self._config.get(CONF_TILT_MAX),
}
tilt_payload = self._set_tilt_template(tilt_open_position, variables=variables)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config.get(CONF_TILT_COMMAND_TOPIC),
tilt_payload,
self._config[CONF_QOS],
@ -627,8 +623,7 @@ class MqttCover(MqttEntity, CoverEntity):
tilt_payload = self._set_tilt_template(
tilt_closed_position, variables=variables
)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config.get(CONF_TILT_COMMAND_TOPIC),
tilt_payload,
self._config[CONF_QOS],
@ -657,8 +652,7 @@ class MqttCover(MqttEntity, CoverEntity):
}
tilt = self._set_tilt_template(tilt, variables=variables)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config.get(CONF_TILT_COMMAND_TOPIC),
tilt,
self._config[CONF_QOS],
@ -685,8 +679,7 @@ class MqttCover(MqttEntity, CoverEntity):
}
position = self._set_position_template(position, variables=variables)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config.get(CONF_SET_POSITION_TOPIC),
position,
self._config[CONF_QOS],

View file

@ -3,13 +3,18 @@ from __future__ import annotations
from collections import deque
from collections.abc import Callable
import datetime as dt
from functools import wraps
from typing import Any
import attr
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.util import dt as dt_util
from .const import ATTR_DISCOVERY_PAYLOAD, ATTR_DISCOVERY_TOPIC
from .models import MessageCallbackType
from .models import MessageCallbackType, PublishPayloadType
DATA_MQTT_DEBUG_INFO = "mqtt_debug_info"
STORED_MESSAGES = 10
@ -42,6 +47,42 @@ def log_messages(
return _decorator
@attr.s(slots=True, frozen=True)
class TimestampedPublishMessage:
"""MQTT Message."""
topic: str = attr.ib()
payload: PublishPayloadType = attr.ib()
qos: int = attr.ib()
retain: bool = attr.ib()
timestamp: dt.datetime = attr.ib(default=None)
def log_message(
hass: HomeAssistant,
entity_id: str,
topic: str,
payload: PublishPayloadType,
qos: int,
retain: bool,
) -> None:
"""Log an outgoing MQTT message."""
debug_info = hass.data.setdefault(
DATA_MQTT_DEBUG_INFO, {"entities": {}, "triggers": {}}
)
entity_info = debug_info["entities"].setdefault(
entity_id, {"subscriptions": {}, "discovery_data": {}, "transmitted": {}}
)
if topic not in entity_info["transmitted"]:
entity_info["transmitted"][topic] = {
"messages": deque([], STORED_MESSAGES),
}
msg = TimestampedPublishMessage(
topic, payload, qos, retain, timestamp=dt_util.utcnow()
)
entity_info["transmitted"][topic]["messages"].append(msg)
def add_subscription(hass, message_callback, subscription):
"""Prepare debug data for subscription."""
if entity_id := getattr(message_callback, "__entity_id", None):
@ -49,7 +90,7 @@ def add_subscription(hass, message_callback, subscription):
DATA_MQTT_DEBUG_INFO, {"entities": {}, "triggers": {}}
)
entity_info = debug_info["entities"].setdefault(
entity_id, {"subscriptions": {}, "discovery_data": {}}
entity_id, {"subscriptions": {}, "discovery_data": {}, "transmitted": {}}
)
if subscription not in entity_info["subscriptions"]:
entity_info["subscriptions"][subscription] = {
@ -80,7 +121,7 @@ def add_entity_discovery_data(hass, discovery_data, entity_id):
DATA_MQTT_DEBUG_INFO, {"entities": {}, "triggers": {}}
)
entity_info = debug_info["entities"].setdefault(
entity_id, {"subscriptions": {}, "discovery_data": {}}
entity_id, {"subscriptions": {}, "discovery_data": {}, "transmitted": {}}
)
entity_info["discovery_data"] = discovery_data
@ -118,10 +159,10 @@ def remove_trigger_discovery_data(hass, discovery_hash):
hass.data[DATA_MQTT_DEBUG_INFO]["triggers"][discovery_hash]["discovery_data"] = None
async def info_for_device(hass, device_id):
def info_for_device(hass, device_id):
"""Get debug info for a device."""
mqtt_info = {"entities": [], "triggers": []}
entity_registry = await hass.helpers.entity_registry.async_get_registry()
entity_registry = er.async_get(hass)
entries = hass.helpers.entity_registry.async_entries_for_device(
entity_registry, device_id, include_disabled_entities=True
@ -150,6 +191,22 @@ async def info_for_device(hass, device_id):
}
for topic, subscription in entity_info["subscriptions"].items()
]
transmitted = [
{
"topic": topic,
"messages": [
{
"payload": str(msg.payload),
"qos": msg.qos,
"retain": msg.retain,
"time": msg.timestamp,
"topic": msg.topic,
}
for msg in list(subscription["messages"])
],
}
for topic, subscription in entity_info["transmitted"].items()
]
discovery_data = {
"topic": entity_info["discovery_data"].get(ATTR_DISCOVERY_TOPIC, ""),
"payload": entity_info["discovery_data"].get(ATTR_DISCOVERY_PAYLOAD, ""),
@ -159,6 +216,7 @@ async def info_for_device(hass, device_id):
"entity_id": entry.entity_id,
"subscriptions": subscriptions,
"discovery_data": discovery_data,
"transmitted": transmitted,
}
)

View file

@ -544,8 +544,7 @@ class MqttFan(MqttEntity, FanEntity):
This method is a coroutine.
"""
mqtt_payload = self._command_templates[CONF_STATE](self._payload["STATE_ON"])
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],
@ -566,8 +565,7 @@ class MqttFan(MqttEntity, FanEntity):
This method is a coroutine.
"""
mqtt_payload = self._command_templates[CONF_STATE](self._payload["STATE_OFF"])
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],
@ -587,8 +585,7 @@ class MqttFan(MqttEntity, FanEntity):
percentage_to_ranged_value(self._speed_range, percentage)
)
mqtt_payload = self._command_templates[ATTR_PERCENTAGE](percentage_payload)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_PERCENTAGE_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],
@ -611,8 +608,7 @@ class MqttFan(MqttEntity, FanEntity):
mqtt_payload = self._command_templates[ATTR_PRESET_MODE](preset_mode)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_PRESET_MODE_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],
@ -638,8 +634,7 @@ class MqttFan(MqttEntity, FanEntity):
self._payload["OSCILLATE_OFF_PAYLOAD"]
)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_OSCILLATION_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],

View file

@ -419,8 +419,7 @@ class MqttHumidifier(MqttEntity, HumidifierEntity):
This method is a coroutine.
"""
mqtt_payload = self._command_templates[CONF_STATE](self._payload["STATE_ON"])
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],
@ -437,8 +436,7 @@ class MqttHumidifier(MqttEntity, HumidifierEntity):
This method is a coroutine.
"""
mqtt_payload = self._command_templates[CONF_STATE](self._payload["STATE_OFF"])
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],
@ -455,8 +453,7 @@ class MqttHumidifier(MqttEntity, HumidifierEntity):
This method is a coroutine.
"""
mqtt_payload = self._command_templates[ATTR_HUMIDITY](humidity)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_TARGET_HUMIDITY_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],
@ -479,8 +476,7 @@ class MqttHumidifier(MqttEntity, HumidifierEntity):
mqtt_payload = self._command_templates[ATTR_MODE](mode)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_MODE_COMMAND_TOPIC],
mqtt_payload,
self._config[CONF_QOS],

View file

@ -833,8 +833,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
async def publish(topic, payload):
"""Publish an MQTT message."""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[topic],
payload,
self._config[CONF_QOS],
@ -1081,8 +1080,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_COMMAND_TOPIC],
self._payload["off"],
self._config[CONF_QOS],

View file

@ -638,8 +638,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
self._white_value = kwargs[ATTR_WHITE_VALUE]
should_update = True
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_COMMAND_TOPIC],
json.dumps(message),
self._config[CONF_QOS],
@ -664,8 +663,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
self._set_flash_and_transition(message, **kwargs)
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topic[CONF_COMMAND_TOPIC],
json.dumps(message),
self._config[CONF_QOS],

View file

@ -392,8 +392,7 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
if ATTR_TRANSITION in kwargs:
values["transition"] = kwargs[ATTR_TRANSITION]
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topics[CONF_COMMAND_TOPIC],
self._templates[CONF_COMMAND_ON_TEMPLATE].async_render(
parse_result=False, **values
@ -418,8 +417,7 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
if ATTR_TRANSITION in kwargs:
values["transition"] = kwargs[ATTR_TRANSITION]
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._topics[CONF_COMMAND_TOPIC],
self._templates[CONF_COMMAND_OFF_TEMPLATE].async_render(
parse_result=False, **values

View file

@ -179,8 +179,7 @@ class MqttLock(MqttEntity, LockEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
self._config[CONF_PAYLOAD_LOCK],
self._config[CONF_QOS],
@ -197,8 +196,7 @@ class MqttLock(MqttEntity, LockEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
self._config[CONF_PAYLOAD_UNLOCK],
self._config[CONF_QOS],
@ -215,8 +213,7 @@ class MqttLock(MqttEntity, LockEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
self._config[CONF_PAYLOAD_OPEN],
self._config[CONF_QOS],

View file

@ -42,7 +42,7 @@ from homeassistant.helpers.entity import (
)
from homeassistant.helpers.typing import ConfigType
from . import DATA_MQTT, MqttValueTemplate, debug_info, publish, subscription
from . import DATA_MQTT, MqttValueTemplate, async_publish, debug_info, subscription
from .const import (
ATTR_DISCOVERY_HASH,
ATTR_DISCOVERY_PAYLOAD,
@ -51,13 +51,14 @@ from .const import (
CONF_ENCODING,
CONF_QOS,
CONF_TOPIC,
DEFAULT_ENCODING,
DEFAULT_PAYLOAD_AVAILABLE,
DEFAULT_PAYLOAD_NOT_AVAILABLE,
DOMAIN,
MQTT_CONNECTED,
MQTT_DISCONNECTED,
)
from .debug_info import log_messages
from .debug_info import log_message, log_messages
from .discovery import (
MQTT_DISCOVERY_DONE,
MQTT_DISCOVERY_NEW,
@ -65,7 +66,7 @@ from .discovery import (
clear_discovery_hash,
set_discovery_hash,
)
from .models import ReceiveMessage
from .models import PublishPayloadType, ReceiveMessage
from .subscription import (
async_prepare_subscribe_topics,
async_subscribe_topics,
@ -552,7 +553,7 @@ class MqttDiscoveryUpdate(Entity):
# Clear the discovery topic so the entity is not rediscovered after a restart
discovery_topic = self._discovery_data[ATTR_DISCOVERY_TOPIC]
publish(self.hass, discovery_topic, "", retain=True)
await async_publish(self.hass, discovery_topic, "", retain=True)
@callback
def add_to_platform_abort(self) -> None:
@ -709,6 +710,25 @@ class MqttEntity(
await MqttAvailability.async_will_remove_from_hass(self)
await MqttDiscoveryUpdate.async_will_remove_from_hass(self)
async def async_publish(
self,
topic: str,
payload: PublishPayloadType,
qos: int = 0,
retain: bool = False,
encoding: str = DEFAULT_ENCODING,
):
"""Publish message to an MQTT topic."""
log_message(self.hass, self.entity_id, topic, payload, qos, retain)
await async_publish(
self.hass,
topic,
payload,
qos,
retain,
encoding,
)
@staticmethod
@abstractmethod
def config_schema():

View file

@ -257,8 +257,7 @@ class MqttNumber(MqttEntity, NumberEntity, RestoreEntity):
self._current_number = current_number
self.async_write_ha_state()
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
payload,
self._config[CONF_QOS],

View file

@ -183,8 +183,7 @@ class MqttSelect(MqttEntity, SelectEntity, RestoreEntity):
self._attr_current_option = option
self.async_write_ha_state()
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
payload,
self._config[CONF_QOS],

View file

@ -328,8 +328,7 @@ class MqttSiren(MqttEntity, SirenEntity):
else json.dumps(template_variables)
)
if payload and payload not in PAYLOAD_NONE:
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[topic],
payload,
self._config[CONF_QOS],

View file

@ -197,8 +197,7 @@ class MqttSwitch(MqttEntity, SwitchEntity, RestoreEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
self._config[CONF_PAYLOAD_ON],
self._config[CONF_QOS],
@ -215,8 +214,7 @@ class MqttSwitch(MqttEntity, SwitchEntity, RestoreEntity):
This method is a coroutine.
"""
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._config[CONF_COMMAND_TOPIC],
self._config[CONF_PAYLOAD_OFF],
self._config[CONF_QOS],

View file

@ -388,8 +388,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
if self.supported_features & SUPPORT_TURN_ON == 0:
return
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._payloads[CONF_PAYLOAD_TURN_ON],
self._qos,
@ -404,8 +403,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
if self.supported_features & SUPPORT_TURN_OFF == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._payloads[CONF_PAYLOAD_TURN_OFF],
self._qos,
@ -420,8 +418,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
if self.supported_features & SUPPORT_STOP == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._payloads[CONF_PAYLOAD_STOP],
self._qos,
@ -436,8 +433,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
if self.supported_features & SUPPORT_CLEAN_SPOT == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._payloads[CONF_PAYLOAD_CLEAN_SPOT],
self._qos,
@ -452,8 +448,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
if self.supported_features & SUPPORT_LOCATE == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._payloads[CONF_PAYLOAD_LOCATE],
self._qos,
@ -468,8 +463,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
if self.supported_features & SUPPORT_PAUSE == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._payloads[CONF_PAYLOAD_START_PAUSE],
self._qos,
@ -484,8 +478,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
if self.supported_features & SUPPORT_RETURN_HOME == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._payloads[CONF_PAYLOAD_RETURN_TO_BASE],
self._qos,
@ -502,8 +495,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
) or fan_speed not in self._fan_speed_list:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._set_fan_speed_topic,
fan_speed,
self._qos,
@ -523,8 +515,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
message = json.dumps(message)
else:
message = command
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._send_command_topic,
message,
self._qos,

View file

@ -260,8 +260,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
"""Start the vacuum."""
if self.supported_features & SUPPORT_START == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._config[CONF_PAYLOAD_START],
self._config[CONF_QOS],
@ -273,8 +272,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
"""Pause the vacuum."""
if self.supported_features & SUPPORT_PAUSE == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._config[CONF_PAYLOAD_PAUSE],
self._config[CONF_QOS],
@ -286,8 +284,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
"""Stop the vacuum."""
if self.supported_features & SUPPORT_STOP == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._config[CONF_PAYLOAD_STOP],
self._config[CONF_QOS],
@ -301,8 +298,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
fan_speed not in self._fan_speed_list
):
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._set_fan_speed_topic,
fan_speed,
self._config[CONF_QOS],
@ -314,8 +310,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
"""Tell the vacuum to return to its dock."""
if self.supported_features & SUPPORT_RETURN_HOME == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._config[CONF_PAYLOAD_RETURN_TO_BASE],
self._config[CONF_QOS],
@ -327,8 +322,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
"""Perform a spot clean-up."""
if self.supported_features & SUPPORT_CLEAN_SPOT == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._config[CONF_PAYLOAD_CLEAN_SPOT],
self._config[CONF_QOS],
@ -340,8 +334,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
"""Locate the vacuum (usually by playing a song)."""
if self.supported_features & SUPPORT_LOCATE == 0:
return None
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._command_topic,
self._config[CONF_PAYLOAD_LOCATE],
self._config[CONF_QOS],
@ -359,8 +352,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
message = json.dumps(message)
else:
message = command
await mqtt.async_publish(
self.hass,
await self.async_publish(
self._send_command_topic,
message,
self._config[CONF_QOS],

View file

@ -771,7 +771,12 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, alarm_control_panel.DOMAIN, DEFAULT_CONFIG
hass,
mqtt_mock,
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG,
alarm_control_panel.SERVICE_ALARM_DISARM,
command_payload="DISARM",
)

View file

@ -868,7 +868,7 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, binary_sensor.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, binary_sensor.DOMAIN, DEFAULT_CONFIG, None
)

View file

@ -18,6 +18,7 @@ from .test_common import (
help_test_discovery_update,
help_test_discovery_update_attr,
help_test_discovery_update_unchanged,
help_test_entity_debug_info_message,
help_test_entity_device_info_remove,
help_test_entity_device_info_update,
help_test_entity_device_info_with_connection,
@ -302,6 +303,19 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
)
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass,
mqtt_mock,
button.DOMAIN,
DEFAULT_CONFIG,
button.SERVICE_PRESS,
command_payload="PRESS",
state_topic=None,
)
async def test_invalid_device_class(hass, mqtt_mock):
"""Test device_class option with invalid value."""
assert await async_setup_component(

View file

@ -237,7 +237,13 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, camera.DOMAIN, DEFAULT_CONFIG, "test_topic", b"ON"
hass,
mqtt_mock,
camera.DOMAIN,
DEFAULT_CONFIG,
None,
state_topic="test_topic",
state_payload=b"ON",
)

View file

@ -1240,11 +1240,19 @@ async def test_entity_debug_info_message(hass, mqtt_mock):
CLIMATE_DOMAIN: {
"platform": "mqtt",
"name": "test",
"mode_command_topic": "command-topic",
"mode_state_topic": "test-topic",
}
}
await help_test_entity_debug_info_message(
hass, mqtt_mock, CLIMATE_DOMAIN, config, "test-topic"
hass,
mqtt_mock,
CLIMATE_DOMAIN,
config,
climate.SERVICE_TURN_ON,
command_topic="command-topic",
command_payload="heat",
state_topic="test-topic",
)

View file

@ -43,6 +43,8 @@ DEFAULT_CONFIG_DEVICE_INFO_MAC = {
"configuration_url": "http://example.com",
}
_SENTINEL = object()
async def help_test_availability_when_connection_lost(hass, mqtt_mock, domain, config):
"""Test availability after MQTT disconnection."""
@ -1110,7 +1112,7 @@ async def help_test_entity_debug_info(hass, mqtt_mock, domain, config):
device = registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"]) == 1
assert (
debug_info_data["entities"][0]["discovery_data"]["topic"]
@ -1121,6 +1123,7 @@ async def help_test_entity_debug_info(hass, mqtt_mock, domain, config):
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
"subscriptions"
]
assert debug_info_data["entities"][0]["transmitted"] == []
assert len(debug_info_data["triggers"]) == 0
@ -1143,7 +1146,7 @@ async def help_test_entity_debug_info_max_messages(hass, mqtt_mock, domain, conf
device = registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) == 1
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
"subscriptions"
@ -1155,7 +1158,7 @@ async def help_test_entity_debug_info_max_messages(hass, mqtt_mock, domain, conf
for i in range(0, debug_info.STORED_MESSAGES + 1):
async_fire_mqtt_message(hass, "test-topic", f"{i}")
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) == 1
assert (
len(debug_info_data["entities"][0]["subscriptions"][0]["messages"])
@ -1177,9 +1180,18 @@ async def help_test_entity_debug_info_max_messages(hass, mqtt_mock, domain, conf
async def help_test_entity_debug_info_message(
hass, mqtt_mock, domain, config, topic=None, payload=None
hass,
mqtt_mock,
domain,
config,
service,
command_topic=_SENTINEL,
command_payload=_SENTINEL,
state_topic=_SENTINEL,
state_payload=_SENTINEL,
service_parameters=None,
):
"""Test debug_info message overflow.
"""Test debug_info.
This is a test helper for MQTT debug_info.
"""
@ -1188,13 +1200,21 @@ async def help_test_entity_debug_info_message(
config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID)
config["unique_id"] = "veryunique"
if topic is None:
if command_topic is _SENTINEL:
# Add default topic to config
config["command_topic"] = "command-topic"
command_topic = "command-topic"
if command_payload is _SENTINEL:
command_payload = "ON"
if state_topic is _SENTINEL:
# Add default topic to config
config["state_topic"] = "state-topic"
topic = "state-topic"
state_topic = "state-topic"
if payload is None:
payload = "ON"
if state_payload is _SENTINEL:
state_payload = "ON"
registry = dr.async_get(hass)
@ -1205,31 +1225,69 @@ async def help_test_entity_debug_info_message(
device = registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {"topic": topic, "messages": []} in debug_info_data["entities"][0][
"subscriptions"
]
debug_info_data = debug_info.info_for_device(hass, device.id)
start_dt = datetime(2019, 1, 1, 0, 0, 0)
with patch("homeassistant.util.dt.utcnow") as dt_utcnow:
dt_utcnow.return_value = start_dt
async_fire_mqtt_message(hass, topic, payload)
debug_info_data = await debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {
"topic": topic,
"messages": [
if state_topic is not None:
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {"topic": state_topic, "messages": []} in debug_info_data["entities"][0][
"subscriptions"
]
with patch("homeassistant.util.dt.utcnow") as dt_utcnow:
dt_utcnow.return_value = start_dt
async_fire_mqtt_message(hass, state_topic, state_payload)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {
"topic": state_topic,
"messages": [
{
"payload": str(state_payload),
"qos": 0,
"retain": False,
"time": start_dt,
"topic": state_topic,
}
],
} in debug_info_data["entities"][0]["subscriptions"]
expected_transmissions = []
if service:
# Trigger an outgoing MQTT message
with patch("homeassistant.util.dt.utcnow") as dt_utcnow:
dt_utcnow.return_value = start_dt
if service:
service_data = {ATTR_ENTITY_ID: f"{domain}.test"}
if service_parameters:
service_data.update(service_parameters)
await hass.services.async_call(
domain,
service,
service_data,
blocking=True,
)
expected_transmissions = [
{
"payload": str(payload),
"qos": 0,
"retain": False,
"time": start_dt,
"topic": topic,
"topic": command_topic,
"messages": [
{
"payload": str(command_payload),
"qos": 0,
"retain": False,
"time": start_dt,
"topic": command_topic,
}
],
}
],
} in debug_info_data["entities"][0]["subscriptions"]
]
debug_info_data = debug_info.info_for_device(hass, device.id)
assert debug_info_data["entities"][0]["transmitted"] == expected_transmissions
async def help_test_entity_debug_info_remove(hass, mqtt_mock, domain, config):
@ -1251,7 +1309,7 @@ async def help_test_entity_debug_info_remove(hass, mqtt_mock, domain, config):
device = registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"]) == 1
assert (
debug_info_data["entities"][0]["discovery_data"]["topic"]
@ -1269,7 +1327,7 @@ async def help_test_entity_debug_info_remove(hass, mqtt_mock, domain, config):
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", "")
await hass.async_block_till_done()
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"]) == 0
assert len(debug_info_data["triggers"]) == 0
assert entity_id not in hass.data[debug_info.DATA_MQTT_DEBUG_INFO]["entities"]
@ -1295,7 +1353,7 @@ async def help_test_entity_debug_info_update_entity_id(hass, mqtt_mock, domain,
device = dev_registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"]) == 1
assert (
debug_info_data["entities"][0]["discovery_data"]["topic"]
@ -1313,7 +1371,7 @@ async def help_test_entity_debug_info_update_entity_id(hass, mqtt_mock, domain,
await hass.async_block_till_done()
await hass.async_block_till_done()
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"]) == 1
assert (
debug_info_data["entities"][0]["discovery_data"]["topic"]

View file

@ -2521,7 +2521,12 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, cover.DOMAIN, DEFAULT_CONFIG
hass,
mqtt_mock,
cover.DOMAIN,
DEFAULT_CONFIG,
SERVICE_OPEN_COVER,
command_payload="OPEN",
)

View file

@ -1246,7 +1246,7 @@ async def test_trigger_debug_info(hass, mqtt_mock):
)
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"]) == 0
assert len(debug_info_data["triggers"]) == 2
topic_map = {
@ -1268,7 +1268,7 @@ async def test_trigger_debug_info(hass, mqtt_mock):
async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", "")
await hass.async_block_till_done()
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"]) == 0
assert len(debug_info_data["triggers"]) == 1
assert (

View file

@ -1724,7 +1724,7 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, fan.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, fan.DOMAIN, DEFAULT_CONFIG, fan.SERVICE_TURN_ON
)

View file

@ -1102,7 +1102,7 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, humidifier.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, humidifier.DOMAIN, DEFAULT_CONFIG, humidifier.SERVICE_TURN_ON
)

View file

@ -1533,6 +1533,7 @@ async def test_mqtt_ws_get_device_debug_info(
"payload": config,
"topic": "homeassistant/sensor/bla/config",
},
"transmitted": [],
}
],
"triggers": [],
@ -1595,6 +1596,7 @@ async def test_mqtt_ws_get_device_debug_info_binary(
"payload": config,
"topic": "homeassistant/camera/bla/config",
},
"transmitted": [],
}
],
"triggers": [],
@ -1662,7 +1664,7 @@ async def test_debug_info_multiple_devices(hass, mqtt_mock):
device = registry.async_get_device({("mqtt", id)})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
if d["domain"] != "device_automation":
assert len(debug_info_data["entities"]) == 1
assert len(debug_info_data["triggers"]) == 0
@ -1739,7 +1741,7 @@ async def test_debug_info_multiple_entities_triggers(hass, mqtt_mock):
device_id = config[0]["config"]["device"]["identifiers"][0]
device = registry.async_get_device({("mqtt", device_id)})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"]) == 2
assert len(debug_info_data["triggers"]) == 2
@ -1786,7 +1788,7 @@ async def test_debug_info_non_mqtt(hass, device_reg, entity_reg):
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {"platform": "test"}})
debug_info_data = await debug_info.info_for_device(hass, device_entry.id)
debug_info_data = debug_info.info_for_device(hass, device_entry.id)
assert len(debug_info_data["entities"]) == 0
assert len(debug_info_data["triggers"]) == 0
@ -1810,7 +1812,7 @@ async def test_debug_info_wildcard(hass, mqtt_mock):
device = registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {"topic": "sensor/#", "messages": []} in debug_info_data["entities"][0][
"subscriptions"
@ -1821,7 +1823,7 @@ async def test_debug_info_wildcard(hass, mqtt_mock):
dt_utcnow.return_value = start_dt
async_fire_mqtt_message(hass, "sensor/abc", "123")
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {
"topic": "sensor/#",
@ -1856,7 +1858,7 @@ async def test_debug_info_filter_same(hass, mqtt_mock):
device = registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {"topic": "sensor/#", "messages": []} in debug_info_data["entities"][0][
"subscriptions"
@ -1871,7 +1873,7 @@ async def test_debug_info_filter_same(hass, mqtt_mock):
dt_utcnow.return_value = dt2
async_fire_mqtt_message(hass, "sensor/abc", "123")
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) == 1
assert len(debug_info_data["entities"][0]["subscriptions"][0]["messages"]) == 2
assert {
@ -1915,7 +1917,7 @@ async def test_debug_info_same_topic(hass, mqtt_mock):
device = registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {"topic": "sensor/status", "messages": []} in debug_info_data["entities"][0][
"subscriptions"
@ -1926,7 +1928,7 @@ async def test_debug_info_same_topic(hass, mqtt_mock):
dt_utcnow.return_value = start_dt
async_fire_mqtt_message(hass, "sensor/status", "123", qos=0, retain=False)
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) == 1
assert {
"payload": "123",
@ -1966,7 +1968,7 @@ async def test_debug_info_qos_retain(hass, mqtt_mock):
device = registry.async_get_device({("mqtt", "helloworld")})
assert device is not None
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) >= 1
assert {"topic": "sensor/#", "messages": []} in debug_info_data["entities"][0][
"subscriptions"
@ -1979,7 +1981,7 @@ async def test_debug_info_qos_retain(hass, mqtt_mock):
async_fire_mqtt_message(hass, "sensor/abc", "123", qos=1, retain=True)
async_fire_mqtt_message(hass, "sensor/abc", "123", qos=2, retain=False)
debug_info_data = await debug_info.info_for_device(hass, device.id)
debug_info_data = debug_info.info_for_device(hass, device.id)
assert len(debug_info_data["entities"][0]["subscriptions"]) == 1
assert {
"payload": "123",

View file

@ -747,14 +747,14 @@ async def test_entity_debug_info_message(hass, mqtt_mock):
vacuum.DOMAIN: {
"platform": "mqtt",
"name": "test",
"battery_level_topic": "test-topic",
"battery_level_topic": "state-topic",
"battery_level_template": "{{ value_json.battery_level }}",
"command_topic": "command-topic",
"availability_topic": "avty-topic",
"payload_turn_on": "ON",
}
}
await help_test_entity_debug_info_message(
hass, mqtt_mock, vacuum.DOMAIN, config, "test-topic"
hass, mqtt_mock, vacuum.DOMAIN, config, vacuum.SERVICE_TURN_ON
)

View file

@ -3343,7 +3343,7 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, light.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, light.DOMAIN, DEFAULT_CONFIG, light.SERVICE_TURN_ON
)

View file

@ -1894,7 +1894,13 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, light.DOMAIN, DEFAULT_CONFIG, payload='{"state":"ON"}'
hass,
mqtt_mock,
light.DOMAIN,
DEFAULT_CONFIG,
light.SERVICE_TURN_ON,
command_payload='{"state": "ON"}',
state_payload='{"state":"ON"}',
)

View file

@ -1082,12 +1082,14 @@ async def test_entity_debug_info_message(hass, mqtt_mock):
"schema": "template",
"name": "test",
"command_topic": "test-topic",
"command_on_template": "on,{{ transition }}",
"command_on_template": "ON",
"command_off_template": "off,{{ transition|d }}",
"state_template": '{{ value.split(",")[0] }}',
}
}
await help_test_entity_debug_info_message(hass, mqtt_mock, light.DOMAIN, config)
await help_test_entity_debug_info_message(
hass, mqtt_mock, light.DOMAIN, config, light.SERVICE_TURN_ON
)
async def test_max_mireds(hass, mqtt_mock):

View file

@ -590,7 +590,12 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
hass,
mqtt_mock,
LOCK_DOMAIN,
DEFAULT_CONFIG,
SERVICE_LOCK,
command_payload="LOCK",
)

View file

@ -541,7 +541,14 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, number.DOMAIN, DEFAULT_CONFIG, payload="1"
hass,
mqtt_mock,
number.DOMAIN,
DEFAULT_CONFIG,
SERVICE_SET_VALUE,
service_parameters={ATTR_VALUE: 45},
command_payload="45",
state_payload="1",
)

View file

@ -475,7 +475,14 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, select.DOMAIN, DEFAULT_CONFIG, payload="milk"
hass,
mqtt_mock,
select.DOMAIN,
DEFAULT_CONFIG,
select.SERVICE_SELECT_OPTION,
service_parameters={ATTR_OPTION: "beer"},
command_payload="beer",
state_payload="milk",
)

View file

@ -906,7 +906,7 @@ async def test_entity_debug_info_max_messages(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, sensor.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, sensor.DOMAIN, DEFAULT_CONFIG, None
)

View file

@ -802,7 +802,12 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, siren.DOMAIN, DEFAULT_CONFIG
hass,
mqtt_mock,
siren.DOMAIN,
DEFAULT_CONFIG,
siren.SERVICE_TURN_ON,
command_payload='{"state": "ON"}',
)

View file

@ -510,7 +510,13 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, vacuum.DOMAIN, DEFAULT_CONFIG_2, payload="{}"
hass,
mqtt_mock,
vacuum.DOMAIN,
DEFAULT_CONFIG_2,
vacuum.SERVICE_START,
command_payload="start",
state_payload="{}",
)

View file

@ -499,7 +499,7 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock):
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, switch.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, switch.DOMAIN, DEFAULT_CONFIG, switch.SERVICE_TURN_ON
)