Skip to content

Commit e8a7e6f

Browse files
authored
fix: Home Assistant: mark device settings as config (#32439)
1 parent 3760e63 commit e8a7e6f

2 files changed

Lines changed: 111 additions & 1 deletion

File tree

lib/extension/homeassistant.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ const COVER_STOPPED_LOOKUP: ReadonlyArray<string> = ["stopped", "stop", "pause",
5151
const CONFIG_SWITCH_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
5252
auto_lock: {entity_category: "config", icon: "mdi:lock"},
5353
away_mode: {entity_category: "config", icon: "mdi:home-export-outline"},
54+
comfort_smiley: {entity_category: "config", icon: "mdi:emoticon-happy-outline"},
55+
enable_display: {entity_category: "config", icon: "mdi:monitor"},
56+
indicator: {entity_category: "config", icon: "mdi:led-on"},
57+
tilt_mode: {entity_category: "config", icon: "mdi:angle-acute"},
5458
valve_detection: {entity_category: "config", icon: "mdi:pipe-valve"},
5559
window_detection: {entity_category: "config", icon: "mdi:window-open-variant"},
5660
} as const;
@@ -67,6 +71,8 @@ const BINARY_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
6771
battery_low: {entity_category: "diagnostic", device_class: "battery"},
6872
button_lock: {entity_category: "config", icon: "mdi:lock"},
6973
calibration: {entity_category: "config", icon: "mdi:progress-wrench"},
74+
calibration_left: {entity_category: "config", icon: "mdi:progress-wrench"},
75+
calibration_right: {entity_category: "config", icon: "mdi:progress-wrench"},
7076
capabilities_configurable_curve: {entity_category: "diagnostic", icon: "mdi:tune"},
7177
capabilities_forward_phase_control: {entity_category: "diagnostic", icon: "mdi:tune"},
7278
capabilities_overload_detection: {entity_category: "diagnostic", icon: "mdi:tune"},
@@ -82,15 +88,19 @@ const BINARY_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
8288
frost_protection: {entity_category: "config", icon: "mdi:snowflake-thermometer"},
8389
heating_stop: {entity_category: "config", icon: "mdi:radiator-off"},
8490
eco_mode: {entity_category: "config", icon: "mdi:leaf"},
91+
enable_display: {entity_category: "config", icon: "mdi:monitor"},
8592
expose_pin: {entity_category: "config", icon: "mdi:pin"},
8693
flip_indicator_light: {entity_category: "config", icon: "mdi:arrow-left-right"},
8794
gas: {device_class: "gas"},
95+
indicator: {entity_category: "config", icon: "mdi:led-on"},
8896
indicator_mode: {entity_category: "config", icon: "mdi:led-on"},
8997
invert_cover: {entity_category: "config", icon: "mdi:arrow-left-right"},
9098
led_disabled_night: {entity_category: "config", icon: "mdi:led-off"},
9199
led_indication: {entity_category: "config", icon: "mdi:led-on"},
92100
led_enable: {entity_category: "config", icon: "mdi:led-on"},
93101
motor_reversal: {entity_category: "config", icon: "mdi:arrow-left-right"},
102+
motor_reversal_left: {entity_category: "config", icon: "mdi:arrow-left-right"},
103+
motor_reversal_right: {entity_category: "config", icon: "mdi:arrow-left-right"},
94104
moving: {device_class: "moving"},
95105
no_position_support: {entity_category: "config", icon: "mdi:minus-circle-outline"},
96106
noise_detected: {device_class: "sound"},
@@ -111,6 +121,7 @@ const BINARY_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
111121
temperature_scale: {entity_category: "config", icon: "mdi:temperature-celsius"},
112122
test: {entity_category: "diagnostic", icon: "mdi:test-tube"},
113123
th_heater: {icon: "mdi:heat-wave"},
124+
tilt_mode: {entity_category: "config", icon: "mdi:angle-acute"},
114125
trigger_indicator: {icon: "mdi:led-on"},
115126
valve_alarm: {device_class: "problem"},
116127
valve_detection: {entity_category: "config", icon: "mdi:pipe-valve"},
@@ -147,8 +158,14 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
147158
boost_time: {entity_category: "config", icon: "mdi:timer"},
148159
calibration: {entity_category: "config", icon: "mdi:wrench-clock"},
149160
calibration_time: {entity_category: "config", icon: "mdi:wrench-clock"},
161+
calibration_time_left: {entity_category: "config", icon: "mdi:wrench-clock"},
162+
calibration_time_right: {entity_category: "config", icon: "mdi:wrench-clock"},
150163
co2: {device_class: "carbon_dioxide", state_class: "measurement"},
164+
comfort_humidity_max: {device_class: "humidity", entity_category: "config", icon: "mdi:water-percent"},
165+
comfort_humidity_min: {device_class: "humidity", entity_category: "config", icon: "mdi:water-percent"},
151166
comfort_temperature: {entity_category: "config", icon: "mdi:thermometer"},
167+
comfort_temperature_max: {device_class: "temperature", entity_category: "config", icon: "mdi:thermometer-high"},
168+
comfort_temperature_min: {device_class: "temperature", entity_category: "config", icon: "mdi:thermometer-low"},
152169
cpu_temperature: {
153170
device_class: "temperature",
154171
entity_category: "diagnostic",
@@ -159,6 +176,7 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
159176
current_phase_b: {device_class: "current", state_class: "measurement"},
160177
current_phase_c: {device_class: "current", state_class: "measurement"},
161178
deadzone_temperature: {entity_category: "config", icon: "mdi:thermometer"},
179+
detection_delay: {entity_category: "config", icon: "mdi:timer"},
162180
detection_interval: {icon: "mdi:timer"},
163181
device_temperature: {
164182
device_class: "temperature",
@@ -174,6 +192,7 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
174192
external_temperature_input: {device_class: "temperature", icon: "mdi:thermometer"},
175193
external_temperature: {device_class: "temperature", icon: "mdi:thermometer", state_class: "measurement"},
176194
external_humidity: {device_class: "humidity", icon: "mdi:water-percent", state_class: "measurement"},
195+
fading_time: {entity_category: "config", icon: "mdi:timer"},
177196
formaldehyd: {state_class: "measurement"},
178197
flow: {device_class: "volume_flow_rate", state_class: "measurement"},
179198
gas: {device_class: "gas", state_class: "total_increasing", icon: "mdi:meter-gas"},
@@ -189,6 +208,7 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
189208
illuminance_calibration: {entity_category: "config", icon: "mdi:wrench-clock"},
190209
illuminance: {device_class: "illuminance", state_class: "measurement"},
191210
illuminance_raw: {state_class: "measurement"},
211+
interval_time: {entity_category: "config", icon: "mdi:timer"},
192212
internalTemperature: {
193213
device_class: "temperature",
194214
entity_category: "diagnostic",
@@ -202,13 +222,20 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
202222
},
203223
load_estimate: {state_class: "measurement"},
204224
local_temperature: {device_class: "temperature", state_class: "measurement"},
225+
large_motion_detection_distance: {entity_category: "config", icon: "mdi:signal-distance-variant"},
226+
large_motion_detection_sensitivity: {entity_category: "config", icon: "mdi:motion-sensor"},
205227
max_range: {entity_category: "config", icon: "mdi:signal-distance-variant"},
206228
max_temperature: {entity_category: "config", icon: "mdi:thermometer-high"},
207229
max_temperature_limit: {entity_category: "config", icon: "mdi:thermometer-high"},
230+
maximum_range: {entity_category: "config", icon: "mdi:signal-distance-variant"},
231+
measurement_interval: {entity_category: "config", icon: "mdi:clock-out"},
208232
min_temperature_limit: {entity_category: "config", icon: "mdi:thermometer-low"},
209233
min_temperature: {entity_category: "config", icon: "mdi:thermometer-low"},
234+
minimum_range: {entity_category: "config", icon: "mdi:signal-distance-variant"},
210235
minimum_on_level: {entity_category: "config"},
211236
measurement_poll_interval: {entity_category: "config", icon: "mdi:clock-out"},
237+
medium_motion_detection_distance: {entity_category: "config", icon: "mdi:signal-distance-variant"},
238+
medium_motion_detection_sensitivity: {entity_category: "config", icon: "mdi:motion-sensor"},
212239
motion_sensitivity: {entity_category: "config", icon: "mdi:motion-sensor"},
213240
noise: {device_class: "sound_pressure", state_class: "measurement"},
214241
noise_detect_level: {icon: "mdi:volume-equal"},
@@ -244,14 +271,21 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
244271
icon: "mdi:brightness-5",
245272
},
246273
smoke_density: {icon: "mdi:google-circles-communities", state_class: "measurement"},
274+
sensitivity: {entity_category: "config", icon: "mdi:tune"},
275+
small_detection_distance: {entity_category: "config", icon: "mdi:signal-distance-variant"},
276+
small_detection_sensitivity: {entity_category: "config", icon: "mdi:motion-sensor"},
277+
soil_calibration: {entity_category: "config", icon: "mdi:wrench-clock"},
247278
soil_fertility: {device_class: "conductivity", state_class: "measurement"},
248279
soil_moisture: {device_class: "moisture", state_class: "measurement"},
280+
soil_sampling: {entity_category: "config", icon: "mdi:clock-out"},
281+
soil_warning: {entity_category: "config", icon: "mdi:water-percent-alert"},
249282
temperature: {device_class: "temperature", state_class: "measurement"},
250283
temperature_probe: {device_class: "temperature", state_class: "measurement"},
251284
temperature_calibration: {entity_category: "config", icon: "mdi:wrench-clock"},
252285
temperature_max: {entity_category: "config", icon: "mdi:thermometer-plus"},
253286
temperature_min: {entity_category: "config", icon: "mdi:thermometer-minus"},
254287
temperature_offset: {icon: "mdi:thermometer-lines"},
288+
temperature_sampling: {entity_category: "config", icon: "mdi:clock-out"},
255289
transition: {entity_category: "config", icon: "mdi:transition"},
256290
trigger_count: {icon: "mdi:counter", enabled_by_default: false, state_class: "measurement"},
257291
uv_index: {icon: "mdi:white-balance-sunny", state_class: "measurement"},
@@ -298,6 +332,7 @@ const ENUM_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
298332
mode_phase_control: {entity_category: "config", icon: "mdi:tune"},
299333
mode: {entity_category: "config", icon: "mdi:tune"},
300334
mode_switch: {icon: "mdi:tune"},
335+
motor_direction: {entity_category: "config", icon: "mdi:arrow-left-right"},
301336
motion_sensitivity: {entity_category: "config", icon: "mdi:tune"},
302337
operation_mode: {entity_category: "config", icon: "mdi:tune"},
303338
power_on_behavior: {entity_category: "config", icon: "mdi:power-settings"},
@@ -308,11 +343,13 @@ const ENUM_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
308343
sensitivity: {entity_category: "config", icon: "mdi:tune"},
309344
sensor: {icon: "mdi:tune"},
310345
sensors_type: {entity_category: "config", icon: "mdi:tune"},
346+
set_limits: {entity_category: "config", icon: "mdi:ray-start-end"},
311347
sound_volume: {entity_category: "config", icon: "mdi:volume-high"},
312348
status: {icon: "mdi:state-machine"},
313349
switch_type: {entity_category: "config", icon: "mdi:tune"},
314350
temperature_display_mode: {entity_category: "config", icon: "mdi:thermometer"},
315351
temperature_sensor_select: {entity_category: "config", icon: "mdi:home-thermometer"},
352+
temperature_unit: {entity_category: "config", icon: "mdi:temperature-celsius"},
316353
thermostat_unit: {entity_category: "config", icon: "mdi:thermometer"},
317354
update: {device_class: "update"},
318355
volume: {entity_category: "config", icon: "mdi: volume-high"},
@@ -324,7 +361,7 @@ const LIST_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
324361
color_options: {icon: "mdi:palette"},
325362
level_config: {entity_category: "diagnostic"},
326363
programming_mode: {icon: "mdi:calendar-clock"},
327-
schedule_settings: {icon: "mdi:calendar-clock"},
364+
schedule_settings: {entity_category: "config", icon: "mdi:calendar-clock"},
328365
} as const;
329366

330367
const featurePropertyWithoutEndpoint = (feature: zhc.Feature): string => {

test/extensions/homeassistant.test.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,79 @@ describe("Extension: HomeAssistant", () => {
174174
}
175175
});
176176

177+
it("Should mark device settings as config entities", () => {
178+
const getDiscoveryConfigs = (expose: zhc.Expose): KeyValueAny[] => {
179+
const device = {
180+
definition: {},
181+
isDevice: (): boolean => true,
182+
isGroup: (): boolean => false,
183+
endpoint: () => undefined,
184+
options: {},
185+
exposes: (): zhc.Expose[] => [expose],
186+
zh: {endpoints: []},
187+
};
188+
// @ts-expect-error private method and minimal test device
189+
return extension.getConfigs(device);
190+
};
191+
192+
const enumExposes = [
193+
new zhc.Enum("set_limits", zhc.access.STATE_SET, ["START", "END", "RESET"]),
194+
new zhc.Enum("motor_direction", zhc.access.STATE_SET, ["forward", "back"]),
195+
new zhc.Enum("temperature_unit", zhc.access.STATE_SET, ["celsius", "fahrenheit"]),
196+
];
197+
198+
for (const expose of enumExposes) {
199+
const [config] = getDiscoveryConfigs(expose);
200+
expect(config.type).toStrictEqual("select");
201+
expect(config.object_id).toStrictEqual(expose.property);
202+
expect(config.discovery_payload.entity_category).toStrictEqual("config");
203+
}
204+
205+
const binaryExposes = [
206+
new zhc.Binary("tilt_mode", zhc.access.STATE_SET, "ON", "OFF"),
207+
new zhc.Binary("calibration_left", zhc.access.STATE_SET, "ON", "OFF"),
208+
new zhc.Binary("motor_reversal_right", zhc.access.STATE_SET, "ON", "OFF"),
209+
new zhc.Binary("enable_display", zhc.access.STATE_SET, "ON", "OFF"),
210+
new zhc.Binary("indicator", zhc.access.STATE_SET, "ON", "OFF"),
211+
];
212+
213+
for (const expose of binaryExposes) {
214+
const [config] = getDiscoveryConfigs(expose);
215+
expect(config.type).toStrictEqual("switch");
216+
expect(config.object_id).toStrictEqual(`switch_${expose.property}`);
217+
expect(config.discovery_payload.entity_category).toStrictEqual("config");
218+
}
219+
220+
const numericExposes = [
221+
new zhc.Numeric("calibration_time_left", zhc.access.STATE_SET),
222+
new zhc.Numeric("comfort_temperature_min", zhc.access.STATE_SET),
223+
new zhc.Numeric("comfort_humidity_max", zhc.access.STATE_SET),
224+
new zhc.Numeric("measurement_interval", zhc.access.STATE_SET),
225+
new zhc.Numeric("minimum_range", zhc.access.STATE_SET),
226+
new zhc.Numeric("maximum_range", zhc.access.STATE_SET),
227+
new zhc.Numeric("detection_delay", zhc.access.STATE_SET),
228+
new zhc.Numeric("fading_time", zhc.access.STATE_SET),
229+
new zhc.Numeric("large_motion_detection_sensitivity", zhc.access.STATE_SET),
230+
new zhc.Numeric("medium_motion_detection_distance", zhc.access.STATE_SET),
231+
new zhc.Numeric("small_detection_sensitivity", zhc.access.STATE_SET),
232+
new zhc.Numeric("soil_calibration", zhc.access.STATE_SET),
233+
new zhc.Numeric("soil_sampling", zhc.access.STATE_SET),
234+
new zhc.Numeric("soil_warning", zhc.access.STATE_SET),
235+
];
236+
237+
for (const expose of numericExposes) {
238+
const [config] = getDiscoveryConfigs(expose);
239+
expect(config.type).toStrictEqual("number");
240+
expect(config.object_id).toStrictEqual(expose.property);
241+
expect(config.discovery_payload.entity_category).toStrictEqual("config");
242+
}
243+
244+
const [textConfig] = getDiscoveryConfigs(new zhc.Text("schedule_settings", zhc.access.STATE_SET));
245+
expect(textConfig.type).toStrictEqual("text");
246+
expect(textConfig.object_id).toStrictEqual("schedule_settings");
247+
expect(textConfig.discovery_payload.entity_category).toStrictEqual("config");
248+
});
249+
177250
it("Should apply expose-level Home Assistant discovery metadata", () => {
178251
const createDevice = (exposes: zhc.Expose[]): Device =>
179252
({

0 commit comments

Comments
 (0)