fix: Home Assistant: mark device settings as config (#32439)

This commit is contained in:
Darafei Praliaskouski
2026-06-30 23:00:16 +04:00
committed by GitHub
parent 3760e63183
commit e8a7e6f29d
2 changed files with 111 additions and 1 deletions
+38 -1
View File
@@ -51,6 +51,10 @@ const COVER_STOPPED_LOOKUP: ReadonlyArray<string> = ["stopped", "stop", "pause",
const CONFIG_SWITCH_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
auto_lock: {entity_category: "config", icon: "mdi:lock"},
away_mode: {entity_category: "config", icon: "mdi:home-export-outline"},
comfort_smiley: {entity_category: "config", icon: "mdi:emoticon-happy-outline"},
enable_display: {entity_category: "config", icon: "mdi:monitor"},
indicator: {entity_category: "config", icon: "mdi:led-on"},
tilt_mode: {entity_category: "config", icon: "mdi:angle-acute"},
valve_detection: {entity_category: "config", icon: "mdi:pipe-valve"},
window_detection: {entity_category: "config", icon: "mdi:window-open-variant"},
} as const;
@@ -67,6 +71,8 @@ const BINARY_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
battery_low: {entity_category: "diagnostic", device_class: "battery"},
button_lock: {entity_category: "config", icon: "mdi:lock"},
calibration: {entity_category: "config", icon: "mdi:progress-wrench"},
calibration_left: {entity_category: "config", icon: "mdi:progress-wrench"},
calibration_right: {entity_category: "config", icon: "mdi:progress-wrench"},
capabilities_configurable_curve: {entity_category: "diagnostic", icon: "mdi:tune"},
capabilities_forward_phase_control: {entity_category: "diagnostic", icon: "mdi:tune"},
capabilities_overload_detection: {entity_category: "diagnostic", icon: "mdi:tune"},
@@ -82,15 +88,19 @@ const BINARY_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
frost_protection: {entity_category: "config", icon: "mdi:snowflake-thermometer"},
heating_stop: {entity_category: "config", icon: "mdi:radiator-off"},
eco_mode: {entity_category: "config", icon: "mdi:leaf"},
enable_display: {entity_category: "config", icon: "mdi:monitor"},
expose_pin: {entity_category: "config", icon: "mdi:pin"},
flip_indicator_light: {entity_category: "config", icon: "mdi:arrow-left-right"},
gas: {device_class: "gas"},
indicator: {entity_category: "config", icon: "mdi:led-on"},
indicator_mode: {entity_category: "config", icon: "mdi:led-on"},
invert_cover: {entity_category: "config", icon: "mdi:arrow-left-right"},
led_disabled_night: {entity_category: "config", icon: "mdi:led-off"},
led_indication: {entity_category: "config", icon: "mdi:led-on"},
led_enable: {entity_category: "config", icon: "mdi:led-on"},
motor_reversal: {entity_category: "config", icon: "mdi:arrow-left-right"},
motor_reversal_left: {entity_category: "config", icon: "mdi:arrow-left-right"},
motor_reversal_right: {entity_category: "config", icon: "mdi:arrow-left-right"},
moving: {device_class: "moving"},
no_position_support: {entity_category: "config", icon: "mdi:minus-circle-outline"},
noise_detected: {device_class: "sound"},
@@ -111,6 +121,7 @@ const BINARY_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
temperature_scale: {entity_category: "config", icon: "mdi:temperature-celsius"},
test: {entity_category: "diagnostic", icon: "mdi:test-tube"},
th_heater: {icon: "mdi:heat-wave"},
tilt_mode: {entity_category: "config", icon: "mdi:angle-acute"},
trigger_indicator: {icon: "mdi:led-on"},
valve_alarm: {device_class: "problem"},
valve_detection: {entity_category: "config", icon: "mdi:pipe-valve"},
@@ -147,8 +158,14 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
boost_time: {entity_category: "config", icon: "mdi:timer"},
calibration: {entity_category: "config", icon: "mdi:wrench-clock"},
calibration_time: {entity_category: "config", icon: "mdi:wrench-clock"},
calibration_time_left: {entity_category: "config", icon: "mdi:wrench-clock"},
calibration_time_right: {entity_category: "config", icon: "mdi:wrench-clock"},
co2: {device_class: "carbon_dioxide", state_class: "measurement"},
comfort_humidity_max: {device_class: "humidity", entity_category: "config", icon: "mdi:water-percent"},
comfort_humidity_min: {device_class: "humidity", entity_category: "config", icon: "mdi:water-percent"},
comfort_temperature: {entity_category: "config", icon: "mdi:thermometer"},
comfort_temperature_max: {device_class: "temperature", entity_category: "config", icon: "mdi:thermometer-high"},
comfort_temperature_min: {device_class: "temperature", entity_category: "config", icon: "mdi:thermometer-low"},
cpu_temperature: {
device_class: "temperature",
entity_category: "diagnostic",
@@ -159,6 +176,7 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
current_phase_b: {device_class: "current", state_class: "measurement"},
current_phase_c: {device_class: "current", state_class: "measurement"},
deadzone_temperature: {entity_category: "config", icon: "mdi:thermometer"},
detection_delay: {entity_category: "config", icon: "mdi:timer"},
detection_interval: {icon: "mdi:timer"},
device_temperature: {
device_class: "temperature",
@@ -174,6 +192,7 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
external_temperature_input: {device_class: "temperature", icon: "mdi:thermometer"},
external_temperature: {device_class: "temperature", icon: "mdi:thermometer", state_class: "measurement"},
external_humidity: {device_class: "humidity", icon: "mdi:water-percent", state_class: "measurement"},
fading_time: {entity_category: "config", icon: "mdi:timer"},
formaldehyd: {state_class: "measurement"},
flow: {device_class: "volume_flow_rate", state_class: "measurement"},
gas: {device_class: "gas", state_class: "total_increasing", icon: "mdi:meter-gas"},
@@ -189,6 +208,7 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
illuminance_calibration: {entity_category: "config", icon: "mdi:wrench-clock"},
illuminance: {device_class: "illuminance", state_class: "measurement"},
illuminance_raw: {state_class: "measurement"},
interval_time: {entity_category: "config", icon: "mdi:timer"},
internalTemperature: {
device_class: "temperature",
entity_category: "diagnostic",
@@ -202,13 +222,20 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
},
load_estimate: {state_class: "measurement"},
local_temperature: {device_class: "temperature", state_class: "measurement"},
large_motion_detection_distance: {entity_category: "config", icon: "mdi:signal-distance-variant"},
large_motion_detection_sensitivity: {entity_category: "config", icon: "mdi:motion-sensor"},
max_range: {entity_category: "config", icon: "mdi:signal-distance-variant"},
max_temperature: {entity_category: "config", icon: "mdi:thermometer-high"},
max_temperature_limit: {entity_category: "config", icon: "mdi:thermometer-high"},
maximum_range: {entity_category: "config", icon: "mdi:signal-distance-variant"},
measurement_interval: {entity_category: "config", icon: "mdi:clock-out"},
min_temperature_limit: {entity_category: "config", icon: "mdi:thermometer-low"},
min_temperature: {entity_category: "config", icon: "mdi:thermometer-low"},
minimum_range: {entity_category: "config", icon: "mdi:signal-distance-variant"},
minimum_on_level: {entity_category: "config"},
measurement_poll_interval: {entity_category: "config", icon: "mdi:clock-out"},
medium_motion_detection_distance: {entity_category: "config", icon: "mdi:signal-distance-variant"},
medium_motion_detection_sensitivity: {entity_category: "config", icon: "mdi:motion-sensor"},
motion_sensitivity: {entity_category: "config", icon: "mdi:motion-sensor"},
noise: {device_class: "sound_pressure", state_class: "measurement"},
noise_detect_level: {icon: "mdi:volume-equal"},
@@ -244,14 +271,21 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
icon: "mdi:brightness-5",
},
smoke_density: {icon: "mdi:google-circles-communities", state_class: "measurement"},
sensitivity: {entity_category: "config", icon: "mdi:tune"},
small_detection_distance: {entity_category: "config", icon: "mdi:signal-distance-variant"},
small_detection_sensitivity: {entity_category: "config", icon: "mdi:motion-sensor"},
soil_calibration: {entity_category: "config", icon: "mdi:wrench-clock"},
soil_fertility: {device_class: "conductivity", state_class: "measurement"},
soil_moisture: {device_class: "moisture", state_class: "measurement"},
soil_sampling: {entity_category: "config", icon: "mdi:clock-out"},
soil_warning: {entity_category: "config", icon: "mdi:water-percent-alert"},
temperature: {device_class: "temperature", state_class: "measurement"},
temperature_probe: {device_class: "temperature", state_class: "measurement"},
temperature_calibration: {entity_category: "config", icon: "mdi:wrench-clock"},
temperature_max: {entity_category: "config", icon: "mdi:thermometer-plus"},
temperature_min: {entity_category: "config", icon: "mdi:thermometer-minus"},
temperature_offset: {icon: "mdi:thermometer-lines"},
temperature_sampling: {entity_category: "config", icon: "mdi:clock-out"},
transition: {entity_category: "config", icon: "mdi:transition"},
trigger_count: {icon: "mdi:counter", enabled_by_default: false, state_class: "measurement"},
uv_index: {icon: "mdi:white-balance-sunny", state_class: "measurement"},
@@ -298,6 +332,7 @@ const ENUM_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
mode_phase_control: {entity_category: "config", icon: "mdi:tune"},
mode: {entity_category: "config", icon: "mdi:tune"},
mode_switch: {icon: "mdi:tune"},
motor_direction: {entity_category: "config", icon: "mdi:arrow-left-right"},
motion_sensitivity: {entity_category: "config", icon: "mdi:tune"},
operation_mode: {entity_category: "config", icon: "mdi:tune"},
power_on_behavior: {entity_category: "config", icon: "mdi:power-settings"},
@@ -308,11 +343,13 @@ const ENUM_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
sensitivity: {entity_category: "config", icon: "mdi:tune"},
sensor: {icon: "mdi:tune"},
sensors_type: {entity_category: "config", icon: "mdi:tune"},
set_limits: {entity_category: "config", icon: "mdi:ray-start-end"},
sound_volume: {entity_category: "config", icon: "mdi:volume-high"},
status: {icon: "mdi:state-machine"},
switch_type: {entity_category: "config", icon: "mdi:tune"},
temperature_display_mode: {entity_category: "config", icon: "mdi:thermometer"},
temperature_sensor_select: {entity_category: "config", icon: "mdi:home-thermometer"},
temperature_unit: {entity_category: "config", icon: "mdi:temperature-celsius"},
thermostat_unit: {entity_category: "config", icon: "mdi:thermometer"},
update: {device_class: "update"},
volume: {entity_category: "config", icon: "mdi: volume-high"},
@@ -324,7 +361,7 @@ const LIST_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
color_options: {icon: "mdi:palette"},
level_config: {entity_category: "diagnostic"},
programming_mode: {icon: "mdi:calendar-clock"},
schedule_settings: {icon: "mdi:calendar-clock"},
schedule_settings: {entity_category: "config", icon: "mdi:calendar-clock"},
} as const;
const featurePropertyWithoutEndpoint = (feature: zhc.Feature): string => {
+73
View File
@@ -174,6 +174,79 @@ describe("Extension: HomeAssistant", () => {
}
});
it("Should mark device settings as config entities", () => {
const getDiscoveryConfigs = (expose: zhc.Expose): KeyValueAny[] => {
const device = {
definition: {},
isDevice: (): boolean => true,
isGroup: (): boolean => false,
endpoint: () => undefined,
options: {},
exposes: (): zhc.Expose[] => [expose],
zh: {endpoints: []},
};
// @ts-expect-error private method and minimal test device
return extension.getConfigs(device);
};
const enumExposes = [
new zhc.Enum("set_limits", zhc.access.STATE_SET, ["START", "END", "RESET"]),
new zhc.Enum("motor_direction", zhc.access.STATE_SET, ["forward", "back"]),
new zhc.Enum("temperature_unit", zhc.access.STATE_SET, ["celsius", "fahrenheit"]),
];
for (const expose of enumExposes) {
const [config] = getDiscoveryConfigs(expose);
expect(config.type).toStrictEqual("select");
expect(config.object_id).toStrictEqual(expose.property);
expect(config.discovery_payload.entity_category).toStrictEqual("config");
}
const binaryExposes = [
new zhc.Binary("tilt_mode", zhc.access.STATE_SET, "ON", "OFF"),
new zhc.Binary("calibration_left", zhc.access.STATE_SET, "ON", "OFF"),
new zhc.Binary("motor_reversal_right", zhc.access.STATE_SET, "ON", "OFF"),
new zhc.Binary("enable_display", zhc.access.STATE_SET, "ON", "OFF"),
new zhc.Binary("indicator", zhc.access.STATE_SET, "ON", "OFF"),
];
for (const expose of binaryExposes) {
const [config] = getDiscoveryConfigs(expose);
expect(config.type).toStrictEqual("switch");
expect(config.object_id).toStrictEqual(`switch_${expose.property}`);
expect(config.discovery_payload.entity_category).toStrictEqual("config");
}
const numericExposes = [
new zhc.Numeric("calibration_time_left", zhc.access.STATE_SET),
new zhc.Numeric("comfort_temperature_min", zhc.access.STATE_SET),
new zhc.Numeric("comfort_humidity_max", zhc.access.STATE_SET),
new zhc.Numeric("measurement_interval", zhc.access.STATE_SET),
new zhc.Numeric("minimum_range", zhc.access.STATE_SET),
new zhc.Numeric("maximum_range", zhc.access.STATE_SET),
new zhc.Numeric("detection_delay", zhc.access.STATE_SET),
new zhc.Numeric("fading_time", zhc.access.STATE_SET),
new zhc.Numeric("large_motion_detection_sensitivity", zhc.access.STATE_SET),
new zhc.Numeric("medium_motion_detection_distance", zhc.access.STATE_SET),
new zhc.Numeric("small_detection_sensitivity", zhc.access.STATE_SET),
new zhc.Numeric("soil_calibration", zhc.access.STATE_SET),
new zhc.Numeric("soil_sampling", zhc.access.STATE_SET),
new zhc.Numeric("soil_warning", zhc.access.STATE_SET),
];
for (const expose of numericExposes) {
const [config] = getDiscoveryConfigs(expose);
expect(config.type).toStrictEqual("number");
expect(config.object_id).toStrictEqual(expose.property);
expect(config.discovery_payload.entity_category).toStrictEqual("config");
}
const [textConfig] = getDiscoveryConfigs(new zhc.Text("schedule_settings", zhc.access.STATE_SET));
expect(textConfig.type).toStrictEqual("text");
expect(textConfig.object_id).toStrictEqual("schedule_settings");
expect(textConfig.discovery_payload.entity_category).toStrictEqual("config");
});
it("Should apply expose-level Home Assistant discovery metadata", () => {
const createDevice = (exposes: zhc.Expose[]): Device =>
({