diff --git a/futurehome/config.yaml b/futurehome/config.yaml index deea287..2464cff 100644 --- a/futurehome/config.yaml +++ b/futurehome/config.yaml @@ -1,6 +1,6 @@ # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config name: Futurehome -version: "0.0.32" +version: "0.0.33" slug: futurehome description: Local Futurehome Smarthub integration url: "https://github.com/adrianjagielak/home-assistant-futurehome" diff --git a/futurehome/src/ha/abbreviate_ha_mqtt_keys.ts b/futurehome/src/ha/abbreviate_ha_mqtt_keys.ts new file mode 100644 index 0000000..b2b8ee2 --- /dev/null +++ b/futurehome/src/ha/abbreviate_ha_mqtt_keys.ts @@ -0,0 +1,300 @@ +/// Abbreviations supported by MQTT discovery. +/// +/// Reference: https://github.com/home-assistant/core/blob/dev/homeassistant/components/mqtt/abbreviations.py +const abbrevMap: { [key: string]: string } = { + action_topic: 'act_t', + action_template: 'act_tpl', + activity_state_topic: 'act_stat_t', + activity_value_template: 'act_val_tpl', + automation_type: 'atype', + available_tones: 'av_tones', + availability: 'avty', + availability_mode: 'avty_mode', + availability_topic: 'avty_t', + availability_template: 'avty_tpl', + blue_template: 'b_tpl', + brightness_command_template: 'bri_cmd_tpl', + brightness_command_topic: 'bri_cmd_t', + brightness_scale: 'bri_scl', + brightness_state_topic: 'bri_stat_t', + brightness_template: 'bri_tpl', + brightness_value_template: 'bri_val_tpl', + color_temp_command_template: 'clr_temp_cmd_tpl', + color_mode: 'clrm', + color_mode_state_topic: 'clrm_stat_t', + color_mode_value_template: 'clrm_val_tpl', + color_temp_command_topic: 'clr_temp_cmd_t', + color_temp_kelvin: 'clr_temp_k', + color_temp_state_topic: 'clr_temp_stat_t', + color_temp_template: 'clr_temp_tpl', + color_temp_value_template: 'clr_temp_val_tpl', + command_off_template: 'cmd_off_tpl', + command_on_template: 'cmd_on_tpl', + command_topic: 'cmd_t', + command_template: 'cmd_tpl', + components: 'cmps', + code_arm_required: 'cod_arm_req', + code_disarm_required: 'cod_dis_req', + code_format: 'cod_form', + code_trigger_required: 'cod_trig_req', + content_type: 'cont_type', + current_humidity_topic: 'curr_hum_t', + current_humidity_template: 'curr_hum_tpl', + current_temperature_topic: 'curr_temp_t', + current_temperature_template: 'curr_temp_tpl', + device: 'dev', + device_class: 'dev_cla', + direction_command_topic: 'dir_cmd_t', + direction_command_template: 'dir_cmd_tpl', + direction_state_topic: 'dir_stat_t', + direction_value_template: 'dir_val_tpl', + display_precision: 'dsp_prc', + dock_command_topic: 'dock_cmd_t', + dock_command_template: 'dock_cmd_tpl', + encoding: 'e', + enabled_by_default: 'en', + entity_category: 'ent_cat', + entity_picture: 'ent_pic', + event_types: 'evt_typ', + fan_speed_list: 'fanspd_lst', + flash: 'flsh', + flash_time_long: 'flsh_tlng', + flash_time_short: 'flsh_tsht', + effect_command_template: 'fx_cmd_tpl', + effect_command_topic: 'fx_cmd_t', + effect_list: 'fx_list', + effect_state_topic: 'fx_stat_t', + effect_template: 'fx_tpl', + effect_value_template: 'fx_val_tpl', + expire_after: 'exp_aft', + fan_mode_command_template: 'fan_mode_cmd_tpl', + fan_mode_command_topic: 'fan_mode_cmd_t', + fan_mode_state_template: 'fan_mode_stat_tpl', + fan_mode_state_topic: 'fan_mode_stat_t', + force_update: 'frc_upd', + green_template: 'g_tpl', + hs_command_topic: 'hs_cmd_t', + hs_command_template: 'hs_cmd_tpl', + hs_state_topic: 'hs_stat_t', + hs_value_template: 'hs_val_tpl', + icon: 'ic', + image_encoding: 'img_e', + image_topic: 'img_t', + initial: 'init', + target_humidity_command_topic: 'hum_cmd_t', + target_humidity_command_template: 'hum_cmd_tpl', + target_humidity_state_topic: 'hum_stat_t', + target_humidity_state_template: 'hum_state_tpl', + json_attributes: 'json_attr', + json_attributes_topic: 'json_attr_t', + json_attributes_template: 'json_attr_tpl', + last_reset_value_template: 'lrst_val_tpl', + max: 'max', + min: 'min', + max_humidity: 'max_hum', + min_humidity: 'min_hum', + max_mireds: 'max_mirs', + min_mireds: 'min_mirs', + max_kelvin: 'max_k', + min_kelvin: 'min_k', + max_temp: 'max_temp', + min_temp: 'min_temp', + migrate_discovery: 'migr_discvry', + mode: 'mode', + mode_command_template: 'mode_cmd_tpl', + mode_command_topic: 'mode_cmd_t', + mode_state_topic: 'mode_stat_t', + mode_state_template: 'mode_stat_tpl', + modes: 'modes', + name: 'name', + origin: 'o', + object_id: 'obj_id', + off_delay: 'off_dly', + on_command_type: 'on_cmd_type', + options: 'ops', + optimistic: 'opt', + oscillation_command_topic: 'osc_cmd_t', + oscillation_command_template: 'osc_cmd_tpl', + oscillation_state_topic: 'osc_stat_t', + oscillation_value_template: 'osc_val_tpl', + platform: 'p', + pause_command_topic: 'pause_cmd_t', + pause_command_template: 'pause_mw_cmd_tpl', + percentage_command_topic: 'pct_cmd_t', + percentage_command_template: 'pct_cmd_tpl', + percentage_state_topic: 'pct_stat_t', + percentage_value_template: 'pct_val_tpl', + payload: 'pl', + payload_arm_away: 'pl_arm_away', + payload_arm_home: 'pl_arm_home', + payload_arm_night: 'pl_arm_nite', + payload_arm_vacation: 'pl_arm_vacation', + payload_arm_custom_bypass: 'pl_arm_custom_b', + payload_available: 'pl_avail', + payload_clean_spot: 'pl_cln_sp', + payload_close: 'pl_cls', + payload_disarm: 'pl_disarm', + payload_home: 'pl_home', + payload_lock: 'pl_lock', + payload_locate: 'pl_loc', + payload_not_available: 'pl_not_avail', + payload_not_home: 'pl_not_home', + payload_off: 'pl_off', + payload_on: 'pl_on', + payload_open: 'pl_open', + payload_oscillation_off: 'pl_osc_off', + payload_oscillation_on: 'pl_osc_on', + payload_pause: 'pl_paus', + payload_press: 'pl_prs', + payload_reset: 'pl_rst', + payload_reset_humidity: 'pl_rst_hum', + payload_reset_mode: 'pl_rst_mode', + payload_reset_percentage: 'pl_rst_pct', + payload_reset_preset_mode: 'pl_rst_pr_mode', + payload_stop: 'pl_stop', + payload_stop_tilt: 'pl_stop_tilt', + payload_start: 'pl_strt', + payload_return_to_base: 'pl_ret', + payload_turn_off: 'pl_toff', + payload_turn_on: 'pl_ton', + payload_trigger: 'pl_trig', + payload_unlock: 'pl_unlk', + reports_position: 'pos', + position_closed: 'pos_clsd', + position_open: 'pos_open', + power_command_topic: 'pow_cmd_t', + power_command_template: 'pow_cmd_tpl', + preset_mode_command_topic: 'pr_mode_cmd_t', + preset_mode_command_template: 'pr_mode_cmd_tpl', + preset_mode_state_topic: 'pr_mode_stat_t', + preset_mode_value_template: 'pr_mode_val_tpl', + preset_modes: 'pr_modes', + pattern: 'ptrn', + red_template: 'r_tpl', + release_summary: 'rel_s', + release_url: 'rel_u', + retain: 'ret', + rgb_command_template: 'rgb_cmd_tpl', + rgb_command_topic: 'rgb_cmd_t', + rgb_state_topic: 'rgb_stat_t', + rgb_value_template: 'rgb_val_tpl', + rgbw_command_template: 'rgbw_cmd_tpl', + rgbw_command_topic: 'rgbw_cmd_t', + rgbw_state_topic: 'rgbw_stat_t', + rgbw_value_template: 'rgbw_val_tpl', + rgbww_command_template: 'rgbww_cmd_tpl', + rgbww_command_topic: 'rgbww_cmd_t', + rgbww_state_topic: 'rgbww_stat_t', + rgbww_value_template: 'rgbww_val_tpl', + send_command_topic: 'send_cmd_t', + send_if_off: 'send_if_off', + set_fan_speed_topic: 'set_fan_spd_t', + set_position_template: 'set_pos_tpl', + set_position_topic: 'set_pos_t', + position_topic: 'pos_t', + position_template: 'pos_tpl', + speed_range_min: 'spd_rng_min', + speed_range_max: 'spd_rng_max', + source_type: 'src_type', + state_class: 'stat_cla', + state_closed: 'stat_clsd', + state_closing: 'stat_closing', + state_jammed: 'stat_jam', + state_off: 'stat_off', + state_on: 'stat_on', + state_open: 'stat_open', + state_opening: 'stat_opening', + state_stopped: 'stat_stopped', + state_locked: 'stat_locked', + state_locking: 'stat_locking', + state_unlocked: 'stat_unlocked', + state_unlocking: 'stat_unlocking', + state_topic: 'stat_t', + state_template: 'stat_tpl', + state_value_template: 'stat_val_tpl', + step: 'step', + start_mowing_command_topic: 'strt_mw_cmd_t', + start_mowing_command_template: 'strt_mw_cmd_tpl', + subtype: 'stype', + suggested_display_precision: 'sug_dsp_prc', + support_duration: 'sup_dur', + support_volume_set: 'sup_vol', + supported_features: 'sup_feat', + supported_color_modes: 'sup_clrm', + swing_horizontal_mode_command_template: 'swing_h_mode_cmd_tpl', + swing_horizontal_mode_command_topic: 'swing_h_mode_cmd_t', + swing_horizontal_mode_state_template: 'swing_h_mode_stat_tpl', + swing_horizontal_mode_state_topic: 'swing_h_mode_stat_t', + swing_horizontal_modes: 'swing_h_modes', + swing_mode_command_template: 'swing_mode_cmd_tpl', + swing_mode_command_topic: 'swing_mode_cmd_t', + swing_mode_state_template: 'swing_mode_stat_tpl', + swing_mode_state_topic: 'swing_mode_stat_t', + swing_modes: 'swing_modes', + temperature_command_template: 'temp_cmd_tpl', + temperature_command_topic: 'temp_cmd_t', + temperature_high_command_template: 'temp_hi_cmd_tpl', + temperature_high_command_topic: 'temp_hi_cmd_t', + temperature_high_state_template: 'temp_hi_stat_tpl', + temperature_high_state_topic: 'temp_hi_stat_t', + temperature_low_command_template: 'temp_lo_cmd_tpl', + temperature_low_command_topic: 'temp_lo_cmd_t', + temperature_low_state_template: 'temp_lo_stat_tpl', + temperature_low_state_topic: 'temp_lo_stat_t', + temperature_state_template: 'temp_stat_tpl', + temperature_state_topic: 'temp_stat_t', + temperature_unit: 'temp_unit', + tilt_closed_value: 'tilt_clsd_val', + tilt_command_topic: 'tilt_cmd_t', + tilt_command_template: 'tilt_cmd_tpl', + tilt_max: 'tilt_max', + tilt_min: 'tilt_min', + tilt_opened_value: 'tilt_opnd_val', + tilt_optimistic: 'tilt_opt', + tilt_status_topic: 'tilt_status_t', + tilt_status_template: 'tilt_status_tpl', + title: 'tit', + topic: 't', + transition: 'trns', + unique_id: 'uniq_id', + unit_of_measurement: 'unit_of_meas', + url_topic: 'url_t', + url_template: 'url_tpl', + value_template: 'val_tpl', + white_command_topic: 'whit_cmd_t', + white_scale: 'whit_scl', + xy_command_topic: 'xy_cmd_t', + xy_command_template: 'xy_cmd_tpl', + xy_state_topic: 'xy_stat_t', + xy_value_template: 'xy_val_tpl', + latest_version_topic: 'l_ver_t', + latest_version_template: 'l_ver_tpl', + payload_install: 'pl_inst', + connections: 'cns', + configuration_url: 'cu', + identifiers: 'ids', + manufacturer: 'mf', + model: 'mdl', + model_id: 'mdl_id', + hw_version: 'hw', + sw_version: 'sw', + suggested_area: 'sa', + serial_number: 'sn', + support_url: 'url', +}; + +/// Abbreviate HA MQTT keys in MQTT discovery message object. +export function abbreviateHaMqttKeys(obj: any): any { + if (Array.isArray(obj)) { + return obj.map((item) => abbreviateHaMqttKeys(item)); + } else if (obj !== null && typeof obj === 'object') { + return Object.fromEntries( + Object.entries(obj).map(([key, value]) => { + const newKey = abbrevMap[key] || key; + return [newKey, abbreviateHaMqttKeys(value)]; + }), + ); + } + + return obj; +} diff --git a/futurehome/src/ha/publish_device.ts b/futurehome/src/ha/publish_device.ts index 86803a7..f1e24ef 100644 --- a/futurehome/src/ha/publish_device.ts +++ b/futurehome/src/ha/publish_device.ts @@ -52,6 +52,7 @@ import { sensor_watpressure__components } from '../services/sensor_watpressure'; import { sensor_wattemp__components } from '../services/sensor_wattemp'; import { sensor_weight__components } from '../services/sensor_weight'; import { thermostat__components } from '../services/thermostat'; +import { abbreviateHaMqttKeys } from './abbreviate_ha_mqtt_keys'; import { ha } from './globals'; import { HaMqttComponent } from './mqtt_components/_component'; @@ -130,7 +131,7 @@ type HaDeviceConfig = { }; origin: { name: 'futurehome'; - url: 'https://github.com/adrianjagielak/home-assistant-futurehome'; + support_url: 'https://github.com/adrianjagielak/home-assistant-futurehome'; }; components: { [key: string]: HaMqttComponent; @@ -273,7 +274,7 @@ export function haPublishDevice(parameters: { }, origin: { name: 'futurehome', - url: 'https://github.com/adrianjagielak/home-assistant-futurehome', + support_url: 'https://github.com/adrianjagielak/home-assistant-futurehome', }, components: components, state_topic: stateTopic, @@ -282,7 +283,7 @@ export function haPublishDevice(parameters: { }; log.debug(`Publishing HA device "${configTopic}"`); - ha?.publish(configTopic, JSON.stringify(config), { retain: true, qos: 2 }); + ha?.publish(configTopic, JSON.stringify(abbreviateHaMqttKeys(config)), { retain: true, qos: 2 }); return { commandHandlers: handlers }; }