Add test case to identify missing MQTT configuration abbreviations (#25616)

* Add missing abbreviations

* Move abbreviations to own file, add script to find missing abbreviations

* Move check from script to test case

* Lint

* Rewrite to use pathlib

* Lint
This commit is contained in:
Erik Montnemery 2019-08-07 02:32:15 +02:00 committed by Paulus Schoutsen
parent 506350da11
commit e0be4efe3e
3 changed files with 241 additions and 144 deletions

View File

@ -0,0 +1,180 @@
"""Abbreviations supported by MQTT discovery."""
ABBREVIATIONS = {
"act_t": "action_topic",
"act_tpl": "action_template",
"aux_cmd_t": "aux_command_topic",
"aux_stat_tpl": "aux_state_template",
"aux_stat_t": "aux_state_topic",
"avty_t": "availability_topic",
"away_mode_cmd_t": "away_mode_command_topic",
"away_mode_stat_tpl": "away_mode_state_template",
"away_mode_stat_t": "away_mode_state_topic",
"b_tpl": "blue_template",
"bri_cmd_t": "brightness_command_topic",
"bri_scl": "brightness_scale",
"bri_stat_t": "brightness_state_topic",
"bri_tpl": "brightness_template",
"bri_val_tpl": "brightness_value_template",
"clr_temp_cmd_tpl": "color_temp_command_template",
"bat_lev_t": "battery_level_topic",
"bat_lev_tpl": "battery_level_template",
"chrg_t": "charging_topic",
"chrg_tpl": "charging_template",
"clr_temp_cmd_t": "color_temp_command_topic",
"clr_temp_stat_t": "color_temp_state_topic",
"clr_temp_tpl": "color_temp_template",
"clr_temp_val_tpl": "color_temp_value_template",
"cln_t": "cleaning_topic",
"cln_tpl": "cleaning_template",
"cmd_off_tpl": "command_off_template",
"cmd_on_tpl": "command_on_template",
"cmd_t": "command_topic",
"cmd_tpl": "command_template",
"cod_arm_req": "code_arm_required",
"cod_dis_req": "code_disarm_required",
"curr_temp_t": "current_temperature_topic",
"curr_temp_tpl": "current_temperature_template",
"dev": "device",
"dev_cla": "device_class",
"dock_t": "docked_topic",
"dock_tpl": "docked_template",
"err_t": "error_topic",
"err_tpl": "error_template",
"fanspd_t": "fan_speed_topic",
"fanspd_tpl": "fan_speed_template",
"fanspd_lst": "fan_speed_list",
"flsh_tlng": "flash_time_long",
"flsh_tsht": "flash_time_short",
"fx_cmd_t": "effect_command_topic",
"fx_list": "effect_list",
"fx_stat_t": "effect_state_topic",
"fx_tpl": "effect_template",
"fx_val_tpl": "effect_value_template",
"exp_aft": "expire_after",
"fan_mode_cmd_t": "fan_mode_command_topic",
"fan_mode_stat_tpl": "fan_mode_state_template",
"fan_mode_stat_t": "fan_mode_state_topic",
"frc_upd": "force_update",
"g_tpl": "green_template",
"hold_cmd_t": "hold_command_topic",
"hold_stat_tpl": "hold_state_template",
"hold_stat_t": "hold_state_topic",
"hs_cmd_t": "hs_command_topic",
"hs_stat_t": "hs_state_topic",
"hs_val_tpl": "hs_value_template",
"ic": "icon",
"init": "initial",
"json_attr": "json_attributes",
"json_attr_t": "json_attributes_topic",
"json_attr_tpl": "json_attributes_template",
"max_temp": "max_temp",
"min_temp": "min_temp",
"mode_cmd_t": "mode_command_topic",
"mode_stat_tpl": "mode_state_template",
"mode_stat_t": "mode_state_topic",
"name": "name",
"off_dly": "off_delay",
"on_cmd_type": "on_command_type",
"opt": "optimistic",
"osc_cmd_t": "oscillation_command_topic",
"osc_stat_t": "oscillation_state_topic",
"osc_val_tpl": "oscillation_value_template",
"pl_arm_away": "payload_arm_away",
"pl_arm_home": "payload_arm_home",
"pl_arm_nite": "payload_arm_night",
"pl_avail": "payload_available",
"pl_cln_sp": "payload_clean_spot",
"pl_cls": "payload_close",
"pl_disarm": "payload_disarm",
"pl_hi_spd": "payload_high_speed",
"pl_lock": "payload_lock",
"pl_loc": "payload_locate",
"pl_lo_spd": "payload_low_speed",
"pl_med_spd": "payload_medium_speed",
"pl_not_avail": "payload_not_available",
"pl_off": "payload_off",
"pl_off_spd": "payload_off_speed",
"pl_on": "payload_on",
"pl_open": "payload_open",
"pl_osc_off": "payload_oscillation_off",
"pl_osc_on": "payload_oscillation_on",
"pl_paus": "payload_pause",
"pl_stop": "payload_stop",
"pl_strt": "payload_start",
"pl_stpa": "payload_start_pause",
"pl_ret": "payload_return_to_base",
"pl_toff": "payload_turn_off",
"pl_ton": "payload_turn_on",
"pl_unlk": "payload_unlock",
"pos_clsd": "position_closed",
"pos_open": "position_open",
"pow_cmd_t": "power_command_topic",
"pow_stat_t": "power_state_topic",
"pow_stat_tpl": "power_state_template",
"r_tpl": "red_template",
"ret": "retain",
"rgb_cmd_tpl": "rgb_command_template",
"rgb_cmd_t": "rgb_command_topic",
"rgb_stat_t": "rgb_state_topic",
"rgb_val_tpl": "rgb_value_template",
"send_cmd_t": "send_command_topic",
"send_if_off": "send_if_off",
"set_fan_spd_t": "set_fan_speed_topic",
"set_pos_tpl": "set_position_template",
"set_pos_t": "set_position_topic",
"pos_t": "position_topic",
"spd_cmd_t": "speed_command_topic",
"spd_stat_t": "speed_state_topic",
"spd_val_tpl": "speed_value_template",
"spds": "speeds",
"stat_clsd": "state_closed",
"stat_off": "state_off",
"stat_on": "state_on",
"stat_open": "state_open",
"stat_t": "state_topic",
"stat_tpl": "state_template",
"stat_val_tpl": "state_value_template",
"sup_feat": "supported_features",
"swing_mode_cmd_t": "swing_mode_command_topic",
"swing_mode_stat_tpl": "swing_mode_state_template",
"swing_mode_stat_t": "swing_mode_state_topic",
"temp_cmd_t": "temperature_command_topic",
"temp_hi_cmd_t": "temperature_high_command_topic",
"temp_hi_stat_tpl": "temperature_high_state_template",
"temp_hi_stat_t": "temperature_high_state_topic",
"temp_lo_cmd_t": "temperature_low_command_topic",
"temp_lo_stat_tpl": "temperature_low_state_template",
"temp_lo_stat_t": "temperature_low_state_topic",
"temp_stat_tpl": "temperature_state_template",
"temp_stat_t": "temperature_state_topic",
"tilt_clsd_val": "tilt_closed_value",
"tilt_cmd_t": "tilt_command_topic",
"tilt_inv_stat": "tilt_invert_state",
"tilt_max": "tilt_max",
"tilt_min": "tilt_min",
"tilt_opnd_val": "tilt_opened_value",
"tilt_opt": "tilt_optimistic",
"tilt_status_t": "tilt_status_topic",
"tilt_status_tpl": "tilt_status_template",
"t": "topic",
"uniq_id": "unique_id",
"unit_of_meas": "unit_of_measurement",
"val_tpl": "value_template",
"whit_val_cmd_t": "white_value_command_topic",
"whit_val_scl": "white_value_scale",
"whit_val_stat_t": "white_value_state_topic",
"whit_val_tpl": "white_value_template",
"xy_cmd_t": "xy_command_topic",
"xy_stat_t": "xy_state_topic",
"xy_val_tpl": "xy_value_template",
}
DEVICE_ABBREVIATIONS = {
"cns": "connections",
"ids": "identifiers",
"name": "name",
"mf": "manufacturer",
"mdl": "model",
"sw": "sw_version",
}

View File

@ -10,6 +10,7 @@ from homeassistant.helpers.discovery import async_load_platform
from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.typing import HomeAssistantType from homeassistant.helpers.typing import HomeAssistantType
from .abbreviations import ABBREVIATIONS, DEVICE_ABBREVIATIONS
from .const import ATTR_DISCOVERY_HASH, CONF_STATE_TOPIC from .const import ATTR_DISCOVERY_HASH, CONF_STATE_TOPIC
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -64,150 +65,6 @@ MQTT_DISCOVERY_NEW = "mqtt_discovery_new_{}_{}"
TOPIC_BASE = "~" TOPIC_BASE = "~"
ABBREVIATIONS = {
"aux_cmd_t": "aux_command_topic",
"aux_stat_tpl": "aux_state_template",
"aux_stat_t": "aux_state_topic",
"avty_t": "availability_topic",
"away_mode_cmd_t": "away_mode_command_topic",
"away_mode_stat_tpl": "away_mode_state_template",
"away_mode_stat_t": "away_mode_state_topic",
"b_tpl": "blue_template",
"bri_cmd_t": "brightness_command_topic",
"bri_scl": "brightness_scale",
"bri_stat_t": "brightness_state_topic",
"bri_tpl": "brightness_template",
"bri_val_tpl": "brightness_value_template",
"clr_temp_cmd_tpl": "color_temp_command_template",
"bat_lev_t": "battery_level_topic",
"bat_lev_tpl": "battery_level_template",
"chrg_t": "charging_topic",
"chrg_tpl": "charging_template",
"clr_temp_cmd_t": "color_temp_command_topic",
"clr_temp_stat_t": "color_temp_state_topic",
"clr_temp_val_tpl": "color_temp_value_template",
"cln_t": "cleaning_topic",
"cln_tpl": "cleaning_template",
"cmd_off_tpl": "command_off_template",
"cmd_on_tpl": "command_on_template",
"cmd_t": "command_topic",
"curr_temp_t": "current_temperature_topic",
"curr_temp_tpl": "current_temperature_template",
"dev": "device",
"dev_cla": "device_class",
"dock_t": "docked_topic",
"dock_tpl": "docked_template",
"err_t": "error_topic",
"err_tpl": "error_template",
"fanspd_t": "fan_speed_topic",
"fanspd_tpl": "fan_speed_template",
"fanspd_lst": "fan_speed_list",
"fx_cmd_t": "effect_command_topic",
"fx_list": "effect_list",
"fx_stat_t": "effect_state_topic",
"fx_tpl": "effect_template",
"fx_val_tpl": "effect_value_template",
"exp_aft": "expire_after",
"fan_mode_cmd_t": "fan_mode_command_topic",
"fan_mode_stat_tpl": "fan_mode_state_template",
"fan_mode_stat_t": "fan_mode_state_topic",
"frc_upd": "force_update",
"g_tpl": "green_template",
"hold_cmd_t": "hold_command_topic",
"hold_stat_tpl": "hold_state_template",
"hold_stat_t": "hold_state_topic",
"ic": "icon",
"init": "initial",
"json_attr": "json_attributes",
"json_attr_t": "json_attributes_topic",
"max_temp": "max_temp",
"min_temp": "min_temp",
"mode_cmd_t": "mode_command_topic",
"mode_stat_tpl": "mode_state_template",
"mode_stat_t": "mode_state_topic",
"name": "name",
"on_cmd_type": "on_command_type",
"opt": "optimistic",
"osc_cmd_t": "oscillation_command_topic",
"osc_stat_t": "oscillation_state_topic",
"osc_val_tpl": "oscillation_value_template",
"pl_arm_away": "payload_arm_away",
"pl_arm_home": "payload_arm_home",
"pl_avail": "payload_available",
"pl_cls": "payload_close",
"pl_disarm": "payload_disarm",
"pl_hi_spd": "payload_high_speed",
"pl_lock": "payload_lock",
"pl_lo_spd": "payload_low_speed",
"pl_med_spd": "payload_medium_speed",
"pl_not_avail": "payload_not_available",
"pl_off": "payload_off",
"pl_on": "payload_on",
"pl_open": "payload_open",
"pl_osc_off": "payload_oscillation_off",
"pl_osc_on": "payload_oscillation_on",
"pl_stop": "payload_stop",
"pl_unlk": "payload_unlock",
"pow_cmd_t": "power_command_topic",
"r_tpl": "red_template",
"ret": "retain",
"rgb_cmd_tpl": "rgb_command_template",
"rgb_cmd_t": "rgb_command_topic",
"rgb_stat_t": "rgb_state_topic",
"rgb_val_tpl": "rgb_value_template",
"send_cmd_t": "send_command_topic",
"send_if_off": "send_if_off",
"set_pos_tpl": "set_position_template",
"set_pos_t": "set_position_topic",
"pos_t": "position_topic",
"spd_cmd_t": "speed_command_topic",
"spd_stat_t": "speed_state_topic",
"spd_val_tpl": "speed_value_template",
"spds": "speeds",
"stat_clsd": "state_closed",
"stat_off": "state_off",
"stat_on": "state_on",
"stat_open": "state_open",
"stat_t": "state_topic",
"stat_tpl": "state_template",
"stat_val_tpl": "state_value_template",
"sup_feat": "supported_features",
"swing_mode_cmd_t": "swing_mode_command_topic",
"swing_mode_stat_tpl": "swing_mode_state_template",
"swing_mode_stat_t": "swing_mode_state_topic",
"temp_cmd_t": "temperature_command_topic",
"temp_stat_tpl": "temperature_state_template",
"temp_stat_t": "temperature_state_topic",
"tilt_clsd_val": "tilt_closed_value",
"tilt_cmd_t": "tilt_command_topic",
"tilt_inv_stat": "tilt_invert_state",
"tilt_max": "tilt_max",
"tilt_min": "tilt_min",
"tilt_opnd_val": "tilt_opened_value",
"tilt_status_opt": "tilt_status_optimistic",
"tilt_status_t": "tilt_status_topic",
"t": "topic",
"uniq_id": "unique_id",
"unit_of_meas": "unit_of_measurement",
"val_tpl": "value_template",
"whit_val_cmd_t": "white_value_command_topic",
"whit_val_scl": "white_value_scale",
"whit_val_stat_t": "white_value_state_topic",
"whit_val_tpl": "white_value_template",
"xy_cmd_t": "xy_command_topic",
"xy_stat_t": "xy_state_topic",
"xy_val_tpl": "xy_value_template",
}
DEVICE_ABBREVIATIONS = {
"cns": "connections",
"ids": "identifiers",
"name": "name",
"mf": "manufacturer",
"mdl": "model",
"sw": "sw_version",
}
def clear_discovery_hash(hass, discovery_hash): def clear_discovery_hash(hass, discovery_hash):
"""Clear entry in ALREADY_DISCOVERED list.""" """Clear entry in ALREADY_DISCOVERED list."""

View File

@ -1,7 +1,14 @@
"""The tests for the MQTT discovery.""" """The tests for the MQTT discovery."""
from pathlib import Path
import re
from unittest.mock import patch from unittest.mock import patch
from homeassistant.components import mqtt from homeassistant.components import mqtt
from homeassistant.components.mqtt.abbreviations import (
ABBREVIATIONS,
DEVICE_ABBREVIATIONS,
)
from homeassistant.components.mqtt.discovery import ALREADY_DISCOVERED, async_start from homeassistant.components.mqtt.discovery import ALREADY_DISCOVERED, async_start
from homeassistant.const import STATE_OFF, STATE_ON from homeassistant.const import STATE_OFF, STATE_ON
@ -245,6 +252,59 @@ async def test_discovery_expansion(hass, mqtt_mock, caplog):
assert state.state == STATE_ON assert state.state == STATE_ON
ABBREVIATIONS_WHITE_LIST = [
# MQTT client/server settings
"CONF_BIRTH_MESSAGE",
"CONF_BROKER",
"CONF_CERTIFICATE",
"CONF_CLIENT_CERT",
"CONF_CLIENT_ID",
"CONF_CLIENT_KEY",
"CONF_DISCOVERY",
"CONF_DISCOVERY_PREFIX",
"CONF_EMBEDDED",
"CONF_KEEPALIVE",
"CONF_TLS_INSECURE",
"CONF_TLS_VERSION",
"CONF_WILL_MESSAGE",
# Undocumented device configuration
"CONF_DEPRECATED_VIA_HUB",
"CONF_VIA_DEVICE",
# Already short
"CONF_FAN_MODE_LIST",
"CONF_HOLD_LIST",
"CONF_HS",
"CONF_MODE_LIST",
"CONF_PRECISION",
"CONF_QOS",
"CONF_SCHEMA",
"CONF_SWING_MODE_LIST",
"CONF_TEMP_STEP",
]
async def test_missing_discover_abbreviations(hass, mqtt_mock, caplog):
"""Check MQTT platforms for missing abbreviations."""
missing = []
regex = re.compile(r"(CONF_[a-zA-Z\d_]*) *= *[\'\"]([a-zA-Z\d_]*)[\'\"]")
for fil in Path(mqtt.__file__).parent.rglob("*.py"):
with open(fil) as file:
matches = re.findall(regex, file.read())
for match in matches:
if (
match[1] not in ABBREVIATIONS.values()
and match[1] not in DEVICE_ABBREVIATIONS.values()
and match[0] not in ABBREVIATIONS_WHITE_LIST
):
missing.append(
"{}: no abbreviation for {} ({})".format(
fil, match[1], match[0]
)
)
assert not missing
async def test_implicit_state_topic_alarm(hass, mqtt_mock, caplog): async def test_implicit_state_topic_alarm(hass, mqtt_mock, caplog):
"""Test implicit state topic for alarm_control_panel.""" """Test implicit state topic for alarm_control_panel."""
entry = MockConfigEntry(domain=mqtt.DOMAIN) entry = MockConfigEntry(domain=mqtt.DOMAIN)