Support abbreviations in discovery topic (#16635)
* Support abbreviations in discovery topic * Add abbreviations for all words. Add testcase. Add missing docstring. * Add missing abbreviations * Support topic prefix * Update test case * Restrict topic prefix * Fix merge * Simplify abbreviations expanding, assume TOPIC_PREFIX is one character long * Support abbreviated keys instead of words * Remove redundant abbreviations * Remove extra spaces in abbreviation list * Make topic prefix less restrictive * Make topix prefix a bit more restrictive again
This commit is contained in:
parent
7bb60068d7
commit
b2789d9883
2 changed files with 165 additions and 8 deletions
|
@ -58,6 +58,114 @@ CONFIG_ENTRY_IS_SETUP = 'mqtt_config_entry_is_setup'
|
|||
MQTT_DISCOVERY_UPDATED = 'mqtt_discovery_updated_{}'
|
||||
MQTT_DISCOVERY_NEW = 'mqtt_discovery_new_{}_{}'
|
||||
|
||||
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',
|
||||
'bri_cmd_t': 'brightness_command_topic',
|
||||
'bri_scl': 'brightness_scale',
|
||||
'bri_stat_t': 'brightness_state_topic',
|
||||
'bri_val_tpl': 'brightness_value_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',
|
||||
'cmd_t': 'command_topic',
|
||||
'curr_temp_t': 'current_temperature_topic',
|
||||
'dev_cla': 'device_class',
|
||||
'fx_cmd_t': 'effect_command_topic',
|
||||
'fx_list': 'effect_list',
|
||||
'fx_stat_t': 'effect_state_topic',
|
||||
'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',
|
||||
'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',
|
||||
'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',
|
||||
'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_if_off': 'send_if_off',
|
||||
'set_pos_tpl': 'set_position_template',
|
||||
'set_pos_t': 'set_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_val_tpl': 'state_value_template',
|
||||
'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_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',
|
||||
}
|
||||
|
||||
|
||||
async def async_start(hass: HomeAssistantType, discovery_topic, hass_config,
|
||||
config_entry=None) -> bool:
|
||||
|
@ -75,6 +183,29 @@ async def async_start(hass: HomeAssistantType, discovery_topic, hass_config,
|
|||
_LOGGER.warning("Component %s is not supported", component)
|
||||
return
|
||||
|
||||
if payload:
|
||||
try:
|
||||
payload = json.loads(payload)
|
||||
except ValueError:
|
||||
_LOGGER.warning("Unable to parse JSON %s: '%s'",
|
||||
object_id, payload)
|
||||
return
|
||||
|
||||
payload = dict(payload)
|
||||
|
||||
for key in list(payload.keys()):
|
||||
abbreviated_key = key
|
||||
key = ABBREVIATIONS.get(key, key)
|
||||
payload[key] = payload.pop(abbreviated_key)
|
||||
|
||||
if TOPIC_BASE in payload:
|
||||
base = payload[TOPIC_BASE]
|
||||
for key, value in payload.items():
|
||||
if value[0] == TOPIC_BASE and key.endswith('_topic'):
|
||||
payload[key] = "{}{}".format(base, value[1:])
|
||||
if value[-1] == TOPIC_BASE and key.endswith('_topic'):
|
||||
payload[key] = "{}{}".format(value[:-1], base)
|
||||
|
||||
# If present, the node_id will be included in the discovered object id
|
||||
discovery_id = '_'.join((node_id, object_id)) if node_id else object_id
|
||||
|
||||
|
@ -91,14 +222,6 @@ async def async_start(hass: HomeAssistantType, discovery_topic, hass_config,
|
|||
hass, MQTT_DISCOVERY_UPDATED.format(discovery_hash), payload)
|
||||
elif payload:
|
||||
# Add component
|
||||
try:
|
||||
payload = json.loads(payload)
|
||||
except ValueError:
|
||||
_LOGGER.warning("Unable to parse JSON %s: '%s'",
|
||||
object_id, payload)
|
||||
return
|
||||
|
||||
payload = dict(payload)
|
||||
platform = payload.get(CONF_PLATFORM, 'mqtt')
|
||||
if platform not in ALLOWED_PLATFORMS.get(component, []):
|
||||
_LOGGER.warning("Platform %s (component %s) is not allowed",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue