diff --git a/lib/extension/homeassistant.ts b/lib/extension/homeassistant.ts index babe2676e3..c97a3f0fbe 100644 --- a/lib/extension/homeassistant.ts +++ b/lib/extension/homeassistant.ts @@ -590,7 +590,7 @@ export class HomeAssistant extends Extension { name: endpointName ? utils.capitalize(endpointName) : null, payload_off: state.value_off, payload_on: state.value_on, - value_template: `{{ value_json.${property} }}`, + value_template: `{{ value_json["${property}"] }}`, command_topic: true, command_topic_prefix: endpointName, }, @@ -636,7 +636,7 @@ export class HomeAssistant extends Extension { max_temp: setpoint.value_max.toString(), // Temperature current_temperature_topic: true, - current_temperature_template: `{{ value_json.${temperature.property} }}`, + current_temperature_template: `{{ value_json["${temperature.property}"] }}`, command_topic_prefix: endpointName, }, }; @@ -650,7 +650,7 @@ export class HomeAssistant extends Extension { mode.values.splice(mode.values.indexOf("sleep"), 1); } discoveryEntry.discovery_payload.mode_state_topic = true; - discoveryEntry.discovery_payload.mode_state_template = `{{ value_json.${mode.property} }}`; + discoveryEntry.discovery_payload.mode_state_template = `{{ value_json["${mode.property}"] }}`; discoveryEntry.discovery_payload.modes = mode.values; discoveryEntry.discovery_payload.mode_command_topic = true; } @@ -659,20 +659,20 @@ export class HomeAssistant extends Extension { if (state) { discoveryEntry.mockProperties.push({property: state.property, value: null}); discoveryEntry.discovery_payload.action_topic = true; - discoveryEntry.discovery_payload.action_template = `{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json.${state.property}] }}`; + discoveryEntry.discovery_payload.action_template = `{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json["${state.property}"]] }}`; } const coolingSetpoint = (firstExpose as zhc.Climate).features.find((f) => f.name === "occupied_cooling_setpoint"); if (coolingSetpoint) { discoveryEntry.discovery_payload.temperature_low_command_topic = setpoint.name; - discoveryEntry.discovery_payload.temperature_low_state_template = `{{ value_json.${setpoint.property} }}`; + discoveryEntry.discovery_payload.temperature_low_state_template = `{{ value_json["${setpoint.property}"] }}`; discoveryEntry.discovery_payload.temperature_low_state_topic = true; discoveryEntry.discovery_payload.temperature_high_command_topic = coolingSetpoint.name; - discoveryEntry.discovery_payload.temperature_high_state_template = `{{ value_json.${coolingSetpoint.property} }}`; + discoveryEntry.discovery_payload.temperature_high_state_template = `{{ value_json["${coolingSetpoint.property}"] }}`; discoveryEntry.discovery_payload.temperature_high_state_topic = true; } else { discoveryEntry.discovery_payload.temperature_command_topic = setpoint.name; - discoveryEntry.discovery_payload.temperature_state_template = `{{ value_json.${setpoint.property} }}`; + discoveryEntry.discovery_payload.temperature_state_template = `{{ value_json["${setpoint.property}"] }}`; discoveryEntry.discovery_payload.temperature_state_topic = true; } @@ -680,7 +680,7 @@ export class HomeAssistant extends Extension { if (fanMode) { discoveryEntry.discovery_payload.fan_modes = fanMode.values; discoveryEntry.discovery_payload.fan_mode_command_topic = true; - discoveryEntry.discovery_payload.fan_mode_state_template = `{{ value_json.${fanMode.property} }}`; + discoveryEntry.discovery_payload.fan_mode_state_template = `{{ value_json["${fanMode.property}"] }}`; discoveryEntry.discovery_payload.fan_mode_state_topic = true; } @@ -688,7 +688,7 @@ export class HomeAssistant extends Extension { if (swingMode) { discoveryEntry.discovery_payload.swing_modes = swingMode.values; discoveryEntry.discovery_payload.swing_mode_command_topic = true; - discoveryEntry.discovery_payload.swing_mode_state_template = `{{ value_json.${swingMode.property} }}`; + discoveryEntry.discovery_payload.swing_mode_state_template = `{{ value_json["${swingMode.property}"] }}`; discoveryEntry.discovery_payload.swing_mode_state_topic = true; } @@ -696,7 +696,7 @@ export class HomeAssistant extends Extension { if (preset) { discoveryEntry.discovery_payload.preset_modes = preset.values; discoveryEntry.discovery_payload.preset_mode_command_topic = "preset"; - discoveryEntry.discovery_payload.preset_mode_value_template = `{{ value_json.${preset.property} }}`; + discoveryEntry.discovery_payload.preset_mode_value_template = `{{ value_json["${preset.property}"] }}`; discoveryEntry.discovery_payload.preset_mode_state_topic = true; } @@ -710,7 +710,7 @@ export class HomeAssistant extends Extension { mockProperties: [{property: tempCalibration.property, value: null}], discovery_payload: { name: endpointName ? `${tempCalibration.label} ${endpointName}` : tempCalibration.label, - value_template: `{{ value_json.${tempCalibration.property} }}`, + value_template: `{{ value_json["${tempCalibration.property}"] }}`, command_topic: true, command_topic_prefix: endpointName, command_topic_postfix: tempCalibration.property, @@ -735,7 +735,7 @@ export class HomeAssistant extends Extension { mockProperties: [{property: piHeatingDemand.property, value: null}], discovery_payload: { name: endpointName ? `${piHeatingDemand.label} ${endpointName}` : piHeatingDemand.label, - value_template: `{{ value_json.${piHeatingDemand.property} }}`, + value_template: `{{ value_json["${piHeatingDemand.property}"] }}`, ...(piHeatingDemand.unit && {unit_of_measurement: piHeatingDemand.unit}), icon: "mdi:radiator", }, @@ -766,7 +766,7 @@ export class HomeAssistant extends Extension { mockProperties: [{property: piCoolingDemand.property, value: null}], discovery_payload: { name: endpointName ? /* v8 ignore next */ `${piCoolingDemand.label} ${endpointName}` : piCoolingDemand.label, - value_template: `{{ value_json.${piCoolingDemand.property} }}`, + value_template: `{{ value_json["${piCoolingDemand.property}"] }}`, ...(piCoolingDemand.unit && {unit_of_measurement: piCoolingDemand.unit}), entity_category: "diagnostic", icon: "mdi:air-conditioner", @@ -788,7 +788,7 @@ export class HomeAssistant extends Extension { mockProperties: [{property: localTemperature.property, value: null}], discovery_payload: { name: endpointName ? `${localTemperature.label} ${endpointName}` : localTemperature.label, - value_template: `{{ value_json.${localTemperature.property} }}`, + value_template: `{{ value_json["${localTemperature.property}"] }}`, ...(localTemperature.unit && {unit_of_measurement: localTemperature.unit}), device_class: "temperature", state_class: "measurement", @@ -800,7 +800,7 @@ export class HomeAssistant extends Extension { const currentHumidity = allExposes?.filter(isNumericExpose).find((e) => e.name === "humidity" && e.access & ACCESS_STATE); if (currentHumidity) { - discoveryEntry.discovery_payload.current_humidity_template = `{{ value_json.${currentHumidity.property} }}`; + discoveryEntry.discovery_payload.current_humidity_template = `{{ value_json["${currentHumidity.property}"] }}`; discoveryEntry.discovery_payload.current_humidity_topic = true; } @@ -820,7 +820,7 @@ export class HomeAssistant extends Extension { name: endpointName ? utils.capitalize(endpointName) : null, command_topic_prefix: endpointName, command_topic: true, - value_template: `{{ value_json.${state.property} }}`, + value_template: `{{ value_json["${state.property}"] }}`, state_locked: state.value_on, state_unlocked: state.value_off, /* v8 ignore next */ @@ -863,7 +863,7 @@ export class HomeAssistant extends Extension { // The movement direction is calculated (assumed) in this case. if (running) { assert(position, `Cover must have 'position' when it has 'running'`); - discoveryEntry.discovery_payload.value_template = `{% if "${featurePropertyWithoutEndpoint(running)}" in value_json and value_json.${featurePropertyWithoutEndpoint(running)} %} {% if value_json.${featurePropertyWithoutEndpoint(position)} > 0 %} closing {% else %} opening {% endif %} {% else %} stopped {% endif %}`; + discoveryEntry.discovery_payload.value_template = `{% if "${featurePropertyWithoutEndpoint(running)}" in value_json and value_json["${featurePropertyWithoutEndpoint(running)}"] %} {% if value_json["${featurePropertyWithoutEndpoint(position)}"] > 0 %} closing {% else %} opening {% endif %} {% else %} stopped {% endif %}`; } // If curtains have `motor_state` or `moving` property, lookup for possible @@ -877,13 +877,13 @@ export class HomeAssistant extends Extension { discoveryEntry.discovery_payload.state_opening = openingState; discoveryEntry.discovery_payload.state_closing = closingState; discoveryEntry.discovery_payload.state_stopped = stoppedState; - discoveryEntry.discovery_payload.value_template = `{% if "${featurePropertyWithoutEndpoint(motorState)}" in value_json and value_json.${featurePropertyWithoutEndpoint(motorState)} %} {{ value_json.${featurePropertyWithoutEndpoint(motorState)} }} {% else %} ${stoppedState} {% endif %}`; + discoveryEntry.discovery_payload.value_template = `{% if "${featurePropertyWithoutEndpoint(motorState)}" in value_json and value_json["${featurePropertyWithoutEndpoint(motorState)}"] %} {{ value_json["${featurePropertyWithoutEndpoint(motorState)}"] }} {% else %} ${stoppedState} {% endif %}`; } } // If curtains do not have `running`, `motor_state` or `moving` properties. if (!discoveryEntry.discovery_payload.value_template) { - discoveryEntry.discovery_payload.value_template = `{{ value_json.${featurePropertyWithoutEndpoint(state)} }}`; + discoveryEntry.discovery_payload.value_template = `{{ value_json["${featurePropertyWithoutEndpoint(state)}"] }}`; discoveryEntry.discovery_payload.state_open = "OPEN"; discoveryEntry.discovery_payload.state_closed = "CLOSE"; discoveryEntry.discovery_payload.state_stopped = "STOP"; @@ -898,7 +898,7 @@ export class HomeAssistant extends Extension { if (position) { discoveryEntry.discovery_payload = { ...discoveryEntry.discovery_payload, - position_template: `{{ value_json.${featurePropertyWithoutEndpoint(position)} }}`, + position_template: `{{ value_json["${featurePropertyWithoutEndpoint(position)}"] }}`, set_position_template: `{ "${getProperty(position)}": {{ position }} }`, set_position_topic: true, position_topic: true, @@ -910,7 +910,7 @@ export class HomeAssistant extends Extension { ...discoveryEntry.discovery_payload, tilt_command_topic: true, tilt_status_topic: true, - tilt_status_template: `{{ value_json.${featurePropertyWithoutEndpoint(tilt)} }}`, + tilt_status_template: `{{ value_json["${featurePropertyWithoutEndpoint(tilt)}"] }}`, }; } @@ -975,14 +975,14 @@ export class HomeAssistant extends Extension { discoveryEntry.discovery_payload.percentage_state_topic = true; discoveryEntry.discovery_payload.percentage_command_topic = "fan_mode"; - discoveryEntry.discovery_payload.percentage_value_template = `{{ {${percentValues}}[value_json.${modeEmulatedSpeed.property}] | default('None') }}`; + discoveryEntry.discovery_payload.percentage_value_template = `{{ {${percentValues}}[value_json["${modeEmulatedSpeed.property}"]] | default('None') }}`; discoveryEntry.discovery_payload.percentage_command_template = `{{ {${percentCommands}}[value] | default('') }}`; discoveryEntry.discovery_payload.speed_range_min = 1; discoveryEntry.discovery_payload.speed_range_max = speeds.length - 1; assert(presets.length !== 0); discoveryEntry.discovery_payload.preset_mode_state_topic = true; discoveryEntry.discovery_payload.preset_mode_command_topic = "fan_mode"; - discoveryEntry.discovery_payload.preset_mode_value_template = `{{ value_json.${modeEmulatedSpeed.property} if value_json.${modeEmulatedSpeed.property} in [${presetList}] else 'None' | default('None') }}`; + discoveryEntry.discovery_payload.preset_mode_value_template = `{{ value_json["${modeEmulatedSpeed.property}"] if value_json["${modeEmulatedSpeed.property}"] in [${presetList}] else 'None' | default('None') }}`; discoveryEntry.discovery_payload.preset_modes = presets; // Emulate state based on mode @@ -991,7 +991,7 @@ export class HomeAssistant extends Extension { } else if (nativeSpeed) { discoveryEntry.discovery_payload.percentage_state_topic = true; discoveryEntry.discovery_payload.percentage_command_topic = "speed"; - discoveryEntry.discovery_payload.percentage_value_template = `{{ value_json.${nativeSpeed.property} | default('None') }}`; + discoveryEntry.discovery_payload.percentage_value_template = `{{ value_json["${nativeSpeed.property}"] | default('None') }}`; discoveryEntry.discovery_payload.percentage_command_template = `{{ value | default('') }}`; discoveryEntry.discovery_payload.speed_range_min = nativeSpeed.value_min; discoveryEntry.discovery_payload.speed_range_max = nativeSpeed.value_max; @@ -1021,8 +1021,8 @@ export class HomeAssistant extends Extension { name: endpointName ? /* v8 ignore next */ `${firstExpose.label} ${endpointName}` : firstExpose.label, value_template: typeof firstExpose.value_on === "boolean" - ? `{% if value_json.${firstExpose.property} %}true{% else %}false{% endif %}` - : `{{ value_json.${firstExpose.property} }}`, + ? `{% if value_json["${firstExpose.property}"] %}true{% else %}false{% endif %}` + : `{{ value_json["${firstExpose.property}"] }}`, payload_on: firstExpose.value_on.toString(), payload_off: firstExpose.value_off.toString(), command_topic: true, @@ -1040,7 +1040,7 @@ export class HomeAssistant extends Extension { mockProperties: [{property: firstExpose.property, value: null}], discovery_payload: { name: endpointName ? /* v8 ignore next */ `${firstExpose.label} ${endpointName}` : firstExpose.label, - value_template: `{{ value_json.${firstExpose.property} }}`, + value_template: `{{ value_json["${firstExpose.property}"] }}`, payload_on: firstExpose.value_on, payload_off: firstExpose.value_off, ...(BINARY_DISCOVERY_LOOKUP[firstExpose.name] || {}), @@ -1065,7 +1065,7 @@ export class HomeAssistant extends Extension { mockProperties: [{property: firstExpose.property, value: null}], discovery_payload: { name: endpointName ? `${firstExpose.label} ${endpointName}` : firstExpose.label, - value_template: `{{ value_json.${firstExpose.property} }}`, + value_template: `{{ value_json["${firstExpose.property}"] }}`, command_topic: true, command_topic_prefix: endpointName, command_topic_postfix: firstExpose.property, @@ -1116,7 +1116,7 @@ export class HomeAssistant extends Extension { mockProperties: [{property: firstExpose.property, value: null}], discovery_payload: { name: endpointName ? `${firstExpose.label} ${endpointName}` : firstExpose.label, - value_template: `{{ value_json.${firstExpose.property} }}`, + value_template: `{{ value_json["${firstExpose.property}"] }}`, enabled_by_default: !allowsSet, ...(firstExpose.unit && {unit_of_measurement: firstExpose.unit}), ...NUMERIC_DISCOVERY_LOOKUP[key], @@ -1170,7 +1170,7 @@ export class HomeAssistant extends Extension { } } - const valueTemplate = firstExpose.access & ACCESS_STATE ? `{{ value_json.${firstExpose.property} }}` : undefined; + const valueTemplate = firstExpose.access & ACCESS_STATE ? `{{ value_json["${firstExpose.property}"] }}` : undefined; /** * If enum has only one item and has SET access then expose as BUTTON entity. @@ -1299,7 +1299,7 @@ export class HomeAssistant extends Extension { discovery_payload: { name: endpointName ? `${firstExposeTyped.label} ${endpointName}` : firstExposeTyped.label, state_topic: firstExposeTyped.access & ACCESS_STATE, - value_template: `{{ value_json.${firstExposeTyped.property} }}`, + value_template: `{{ value_json["${firstExposeTyped.property}"] }}`, command_topic_prefix: endpointName, command_topic: true, command_topic_postfix: firstExposeTyped.property, @@ -1317,7 +1317,7 @@ export class HomeAssistant extends Extension { name: endpointName ? `${firstExposeTyped.label} ${endpointName}` : firstExposeTyped.label, // Truncate text if it's too long // https://github.com/Koenkk/zigbee2mqtt/issues/23199 - value_template: `{{ value_json.${firstExposeTyped.property} | default('',True) | string | truncate(254, True, '', 0) }}`, + value_template: `{{ value_json["${firstExposeTyped.property}"] | default('',True) | string | truncate(254, True, '', 0) }}`, ...LIST_DISCOVERY_LOOKUP[firstExposeTyped.name], }, }); diff --git a/test/extensions/homeassistant.test.ts b/test/extensions/homeassistant.test.ts index a29ab275e9..806437c9fb 100644 --- a/test/extensions/homeassistant.test.ts +++ b/test/extensions/homeassistant.test.ts @@ -239,7 +239,7 @@ describe("Extension: HomeAssistant", () => { unique_id: "9_switch_zigbee2mqtt", group: ["0x0017880104e45542_switch_right_zigbee2mqtt"], origin: origin, - value_template: "{{ value_json.state }}", + value_template: '{{ value_json["state"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith( @@ -252,7 +252,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "°C", device_class: "temperature", state_class: "measurement", - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_temperature", default_entity_id: "sensor.weather_sensor_temperature", @@ -279,7 +279,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "%", device_class: "humidity", state_class: "measurement", - value_template: "{{ value_json.humidity }}", + value_template: '{{ value_json["humidity"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_humidity", default_entity_id: "sensor.weather_sensor_humidity", @@ -306,7 +306,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "hPa", device_class: "atmospheric_pressure", state_class: "measurement", - value_template: "{{ value_json.pressure }}", + value_template: '{{ value_json["pressure"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_pressure", default_entity_id: "sensor.weather_sensor_pressure", @@ -333,7 +333,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "%", device_class: "battery", state_class: "measurement", - value_template: "{{ value_json.battery }}", + value_template: '{{ value_json["battery"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_battery", default_entity_id: "sensor.weather_sensor_battery", @@ -363,7 +363,7 @@ describe("Extension: HomeAssistant", () => { entity_category: "diagnostic", unit_of_measurement: "lqi", state_class: "measurement", - value_template: "{{ value_json.linkquality }}", + value_template: '{{ value_json["linkquality"] }}', state_topic: "zigbee2mqtt/weather_sensor", name: "Linkquality", object_id: "weather_sensor_linkquality", @@ -405,7 +405,7 @@ describe("Extension: HomeAssistant", () => { default_entity_id: "switch.wall_switch_double_left", unique_id: "0x0017880104e45542_switch_left_zigbee2mqtt", origin: origin, - value_template: "{{ value_json.state_left }}", + value_template: '{{ value_json["state_left"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/switch/0x0017880104e45542/switch_left/config", stringify(payload), { @@ -432,7 +432,7 @@ describe("Extension: HomeAssistant", () => { default_entity_id: "switch.wall_switch_double_right", unique_id: "0x0017880104e45542_switch_right_zigbee2mqtt", origin: origin, - value_template: "{{ value_json.state_right }}", + value_template: '{{ value_json["state_right"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/switch/0x0017880104e45542/switch_right/config", stringify(payload), { @@ -535,7 +535,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "%", device_class: "humidity", state_class: "measurement", - value_template: "{{ value_json.humidity }}", + value_template: '{{ value_json["humidity"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_humidity", default_entity_id: "sensor.weather_sensor_humidity", @@ -607,7 +607,7 @@ describe("Extension: HomeAssistant", () => { device_class: "temperature", state_class: "measurement", enabled_by_default: true, - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_temperature", default_entity_id: "sensor.weather_sensor_temperature", @@ -633,7 +633,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "%", device_class: "humidity", state_class: "measurement", - value_template: "{{ value_json.humidity }}", + value_template: '{{ value_json["humidity"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_humidity", default_entity_id: "sensor.weather_sensor_humidity", @@ -660,7 +660,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "hPa", device_class: "atmospheric_pressure", state_class: "measurement", - value_template: "{{ value_json.pressure }}", + value_template: '{{ value_json["pressure"] }}', state_topic: "zigbee2mqtt/weather_sensor", enabled_by_default: true, object_id: "weather_sensor_pressure", @@ -718,7 +718,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "°C", device_class: "temperature", state_class: "measurement", - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor", enabled_by_default: true, object_id: "weather_sensor_temperature", @@ -748,7 +748,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "%", device_class: "humidity", state_class: "measurement", - value_template: "{{ value_json.humidity }}", + value_template: '{{ value_json["humidity"] }}', state_topic: "zigbee2mqtt/weather_sensor", enabled_by_default: true, device: { @@ -791,7 +791,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "°C", device_class: "temperature", state_class: "measurement", - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_temperature", default_entity_id: "sensor.weather_sensor_temperature", @@ -818,7 +818,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "%", device_class: "humidity", state_class: "measurement", - value_template: "{{ value_json.humidity }}", + value_template: '{{ value_json["humidity"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_humidity", default_entity_id: "sensor.weather_sensor_humidity", @@ -881,7 +881,7 @@ describe("Extension: HomeAssistant", () => { default_entity_id: "light.my_switch", unique_id: "0x0017880104e45541_light_zigbee2mqtt", origin: origin, - value_template: "{{ value_json.state }}", + value_template: '{{ value_json["state"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/light/0x0017880104e45541/light/config", stringify(payload), { @@ -927,11 +927,11 @@ describe("Extension: HomeAssistant", () => { command_topic: "zigbee2mqtt/fan/set/fan_state", percentage_state_topic: "zigbee2mqtt/fan", percentage_command_topic: "zigbee2mqtt/fan/set/fan_mode", - percentage_value_template: "{{ {'off':0, 'low':1, 'medium':2, 'high':3, 'on':4}[value_json.fan_mode] | default('None') }}", + percentage_value_template: "{{ {'off':0, 'low':1, 'medium':2, 'high':3, 'on':4}[value_json[\"fan_mode\"]] | default('None') }}", percentage_command_template: "{{ {0:'off', 1:'low', 2:'medium', 3:'high', 4:'on'}[value] | default('') }}", preset_mode_state_topic: "zigbee2mqtt/fan", preset_mode_command_topic: "zigbee2mqtt/fan/set/fan_mode", - preset_mode_value_template: "{{ value_json.fan_mode if value_json.fan_mode in ['smart'] else 'None' | default('None') }}", + preset_mode_value_template: "{{ value_json[\"fan_mode\"] if value_json[\"fan_mode\"] in ['smart'] else 'None' | default('None') }}", preset_modes: ["smart"], speed_range_min: 1, speed_range_max: 4, @@ -1003,7 +1003,7 @@ describe("Extension: HomeAssistant", () => { command_topic: "zigbee2mqtt/fanbee/set/state", percentage_state_topic: "zigbee2mqtt/fanbee", percentage_command_topic: "zigbee2mqtt/fanbee/set/speed", - percentage_value_template: "{{ value_json.speed | default('None') }}", + percentage_value_template: "{{ value_json[\"speed\"] | default('None') }}", percentage_command_template: "{{ value | default('') }}", speed_range_min: 1, speed_range_max: 254, @@ -1036,7 +1036,7 @@ describe("Extension: HomeAssistant", () => { it("Should discover thermostat devices", () => { const payload = { action_template: - "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json.running_state] }}", + "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json[\"running_state\"]] }}", action_topic: "zigbee2mqtt/TS0601_thermostat", availability: [ { @@ -1044,7 +1044,7 @@ describe("Extension: HomeAssistant", () => { value_template: "{{ value_json.state }}", }, ], - current_temperature_template: "{{ value_json.local_temperature }}", + current_temperature_template: '{{ value_json["local_temperature"] }}', current_temperature_topic: "zigbee2mqtt/TS0601_thermostat", device: { identifiers: ["zigbee2mqtt_0x0017882104a44559"], @@ -1056,18 +1056,18 @@ describe("Extension: HomeAssistant", () => { }, preset_mode_command_topic: "zigbee2mqtt/TS0601_thermostat/set/preset", preset_modes: ["schedule", "manual", "boost", "complex", "comfort", "eco", "away"], - preset_mode_value_template: "{{ value_json.preset }}", + preset_mode_value_template: '{{ value_json["preset"] }}', preset_mode_state_topic: "zigbee2mqtt/TS0601_thermostat", max_temp: "35", min_temp: "5", mode_command_topic: "zigbee2mqtt/TS0601_thermostat/set/system_mode", - mode_state_template: "{{ value_json.system_mode }}", + mode_state_template: '{{ value_json["system_mode"] }}', mode_state_topic: "zigbee2mqtt/TS0601_thermostat", modes: ["heat", "auto", "off"], name: null, temp_step: 0.5, temperature_command_topic: "zigbee2mqtt/TS0601_thermostat/set/current_heating_setpoint", - temperature_state_template: "{{ value_json.current_heating_setpoint }}", + temperature_state_template: '{{ value_json["current_heating_setpoint"] }}', temperature_state_topic: "zigbee2mqtt/TS0601_thermostat", temperature_unit: "C", object_id: "ts0601_thermostat", @@ -1107,7 +1107,7 @@ describe("Extension: HomeAssistant", () => { state_topic: "zigbee2mqtt/thermostat", unique_id: "0x0017880104e45550_pi_heating_demand_zigbee2mqtt", unit_of_measurement: "%", - value_template: "{{ value_json.pi_heating_demand }}", + value_template: '{{ value_json["pi_heating_demand"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/sensor/0x0017880104e45550/pi_heating_demand/config", stringify(payload), { @@ -1144,7 +1144,7 @@ describe("Extension: HomeAssistant", () => { state_topic: "zigbee2mqtt/bosch_radiator", unique_id: "0x18fc2600000d7ae2_pi_heating_demand_zigbee2mqtt", unit_of_measurement: "%", - value_template: "{{ value_json.pi_heating_demand }}", + value_template: '{{ value_json["pi_heating_demand"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/number/0x18fc2600000d7ae2/pi_heating_demand/config", stringify(payload), { @@ -1156,10 +1156,10 @@ describe("Extension: HomeAssistant", () => { it("Should discover Bosch BTH-RA with a compatibility mapping", () => { const payload = { action_template: - "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json.running_state] }}", + "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json[\"running_state\"]] }}", action_topic: "zigbee2mqtt/bosch_radiator", availability: [{topic: "zigbee2mqtt/bridge/state", value_template: "{{ value_json.state }}"}], - current_temperature_template: "{{ value_json.local_temperature }}", + current_temperature_template: '{{ value_json["local_temperature"] }}', current_temperature_topic: "zigbee2mqtt/bosch_radiator", device: { identifiers: ["zigbee2mqtt_0x18fc2600000d7ae2"], @@ -1184,7 +1184,7 @@ describe("Extension: HomeAssistant", () => { origin: origin, temp_step: 0.5, temperature_command_topic: "zigbee2mqtt/bosch_radiator/set/occupied_heating_setpoint", - temperature_state_template: "{{ value_json.occupied_heating_setpoint }}", + temperature_state_template: '{{ value_json["occupied_heating_setpoint"] }}', temperature_state_topic: "zigbee2mqtt/bosch_radiator", temperature_unit: "C", unique_id: "0x18fc2600000d7ae2_climate_zigbee2mqtt", @@ -1211,10 +1211,10 @@ describe("Extension: HomeAssistant", () => { const payload = { action_template: - "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json.running_state] }}", + "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json[\"running_state\"]] }}", action_topic: "zigbee2mqtt/bosch_radiator", availability: [{topic: "zigbee2mqtt/bridge/state", value_template: "{{ value_json.state }}"}], - current_temperature_template: "{{ value_json.local_temperature }}", + current_temperature_template: '{{ value_json["local_temperature"] }}', current_temperature_topic: "zigbee2mqtt/bosch_radiator", device: { identifiers: ["zigbee2mqtt_0x18fc2600000d7ae2"], @@ -1228,7 +1228,7 @@ describe("Extension: HomeAssistant", () => { max_temp: "30", min_temp: "5", mode_command_topic: "zigbee2mqtt/bosch_radiator/set/system_mode", - mode_state_template: "{{ value_json.system_mode }}", + mode_state_template: '{{ value_json["system_mode"] }}', mode_state_topic: "zigbee2mqtt/bosch_radiator", modes: ["heat"], name: null, @@ -1237,7 +1237,7 @@ describe("Extension: HomeAssistant", () => { origin: origin, temp_step: 0.5, temperature_command_topic: "zigbee2mqtt/bosch_radiator/set/occupied_heating_setpoint", - temperature_state_template: "{{ value_json.occupied_heating_setpoint }}", + temperature_state_template: '{{ value_json["occupied_heating_setpoint"] }}', temperature_state_topic: "zigbee2mqtt/bosch_radiator", temperature_unit: "C", unique_id: "0x18fc2600000d7ae2_climate_zigbee2mqtt", @@ -1255,12 +1255,12 @@ describe("Extension: HomeAssistant", () => { it("Should discover Bosch BTH-RM230Z with a current_humidity attribute", () => { const payload = { action_template: - "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json.running_state] }}", + "{% set values = {None:None,'idle':'idle','heat':'heating','cool':'cooling','fan_only':'fan'} %}{{ values[value_json[\"running_state\"]] }}", action_topic: "zigbee2mqtt/bosch_rm230z", availability: [{topic: "zigbee2mqtt/bridge/state", value_template: "{{ value_json.state }}"}], - current_humidity_template: "{{ value_json.humidity }}", + current_humidity_template: '{{ value_json["humidity"] }}', current_humidity_topic: "zigbee2mqtt/bosch_rm230z", - current_temperature_template: "{{ value_json.local_temperature }}", + current_temperature_template: '{{ value_json["local_temperature"] }}', current_temperature_topic: "zigbee2mqtt/bosch_rm230z", default_entity_id: "climate.bosch_rm230z", device: { @@ -1285,10 +1285,10 @@ describe("Extension: HomeAssistant", () => { origin, temp_step: 0.5, temperature_high_command_topic: "zigbee2mqtt/bosch_rm230z/set/occupied_cooling_setpoint", - temperature_high_state_template: "{{ value_json.occupied_cooling_setpoint }}", + temperature_high_state_template: '{{ value_json["occupied_cooling_setpoint"] }}', temperature_high_state_topic: "zigbee2mqtt/bosch_rm230z", temperature_low_command_topic: "zigbee2mqtt/bosch_rm230z/set/occupied_heating_setpoint", - temperature_low_state_template: "{{ value_json.occupied_heating_setpoint }}", + temperature_low_state_template: '{{ value_json["occupied_heating_setpoint"] }}', temperature_low_state_topic: "zigbee2mqtt/bosch_rm230z", temperature_unit: "C", unique_id: "0x18fc2600000d7ae3_climate_zigbee2mqtt", @@ -1319,7 +1319,7 @@ describe("Extension: HomeAssistant", () => { state_topic: "zigbee2mqtt/bosch_rm230z", unique_id: "0x18fc2600000d7ae3_local_temperature_zigbee2mqtt", unit_of_measurement: "°C", - value_template: "{{ value_json.local_temperature }}", + value_template: '{{ value_json["local_temperature"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/sensor/0x18fc2600000d7ae3/local_temperature/config", stringify(payload), { @@ -1336,9 +1336,9 @@ describe("Extension: HomeAssistant", () => { position_topic: "zigbee2mqtt/smart vent", set_position_topic: "zigbee2mqtt/smart vent/set", set_position_template: '{ "position": {{ position }} }', - position_template: "{{ value_json.position }}", + position_template: '{{ value_json["position"] }}', state_topic: "zigbee2mqtt/smart vent", - value_template: "{{ value_json.state }}", + value_template: '{{ value_json["state"] }}', state_open: "OPEN", state_closed: "CLOSE", state_stopped: "STOP", @@ -1375,7 +1375,7 @@ describe("Extension: HomeAssistant", () => { via_device: "zigbee2mqtt_bridge_0x00124b00120144ae", }, name: "L6", - position_template: "{{ value_json.position }}", + position_template: '{{ value_json["position"] }}', position_topic: "zigbee2mqtt/zigfred_plus/l6", set_position_template: '{ "position_l6": {{ position }} }', set_position_topic: "zigbee2mqtt/zigfred_plus/l6/set", @@ -1384,13 +1384,13 @@ describe("Extension: HomeAssistant", () => { state_open: "OPEN", state_topic: "zigbee2mqtt/zigfred_plus/l6", tilt_command_topic: "zigbee2mqtt/zigfred_plus/l6/set/tilt", - tilt_status_template: "{{ value_json.tilt }}", + tilt_status_template: '{{ value_json["tilt"] }}', tilt_status_topic: "zigbee2mqtt/zigfred_plus/l6", object_id: "zigfred_plus_l6", default_entity_id: "cover.zigfred_plus_l6", unique_id: "0xf4ce368a38be56a1_cover_l6_zigbee2mqtt", origin: origin, - value_template: "{{ value_json.state }}", + value_template: '{{ value_json["state"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/cover/0xf4ce368a38be56a1/cover_l6/config", stringify(payload), { @@ -1420,7 +1420,7 @@ describe("Extension: HomeAssistant", () => { object_id: "0xa4c138018cf95021_left", default_entity_id: "cover.0xa4c138018cf95021_left", origin: origin, - position_template: "{{ value_json.position }}", + position_template: '{{ value_json["position"] }}', position_topic: "zigbee2mqtt/0xa4c138018cf95021/left", set_position_template: '{ "position_left": {{ position }} }', set_position_topic: "zigbee2mqtt/0xa4c138018cf95021/left/set", @@ -1429,7 +1429,7 @@ describe("Extension: HomeAssistant", () => { state_stopped: "STOP", state_topic: "zigbee2mqtt/0xa4c138018cf95021/left", unique_id: "0xa4c138018cf95021_cover_left_zigbee2mqtt", - value_template: '{% if "moving" in value_json and value_json.moving %} {{ value_json.moving }} {% else %} STOP {% endif %}', + value_template: '{% if "moving" in value_json and value_json["moving"] %} {{ value_json["moving"] }} {% else %} STOP {% endif %}', }; const payload_right = { availability: [ @@ -1451,7 +1451,7 @@ describe("Extension: HomeAssistant", () => { object_id: "0xa4c138018cf95021_right", default_entity_id: "cover.0xa4c138018cf95021_right", origin: origin, - position_template: "{{ value_json.position }}", + position_template: '{{ value_json["position"] }}', position_topic: "zigbee2mqtt/0xa4c138018cf95021/right", set_position_template: '{ "position_right": {{ position }} }', set_position_topic: "zigbee2mqtt/0xa4c138018cf95021/right/set", @@ -1460,11 +1460,9 @@ describe("Extension: HomeAssistant", () => { state_stopped: "STOP", state_topic: "zigbee2mqtt/0xa4c138018cf95021/right", unique_id: "0xa4c138018cf95021_cover_right_zigbee2mqtt", - value_template: '{% if "moving" in value_json and value_json.moving %} {{ value_json.moving }} {% else %} STOP {% endif %}', + value_template: '{% if "moving" in value_json and value_json["moving"] %} {{ value_json["moving"] }} {% else %} STOP {% endif %}', }; - console.log(mockMQTTPublishAsync.mock.calls.find((c) => c[0] === "homeassistant/cover/0xa4c138018cf95021/cover_left/config")); - expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/cover/0xa4c138018cf95021/cover_left/config", stringify(payload_left), { retain: true, qos: 1, @@ -1483,7 +1481,7 @@ describe("Extension: HomeAssistant", () => { unit_of_measurement: "°C", device_class: "temperature", state_class: "measurement", - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor", enabled_by_default: true, object_id: "weather_sensor_temperature", @@ -1669,7 +1667,7 @@ describe("Extension: HomeAssistant", () => { device_class: "temperature", enabled_by_default: true, state_class: "measurement", - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_temperature", default_entity_id: "sensor.weather_sensor_temperature", @@ -1830,7 +1828,7 @@ describe("Extension: HomeAssistant", () => { device_class: "temperature", enabled_by_default: true, state_class: "measurement", - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_temperature", default_entity_id: "sensor.weather_sensor_temperature", @@ -1900,7 +1898,7 @@ describe("Extension: HomeAssistant", () => { device_class: "temperature", state_class: "measurement", enabled_by_default: true, - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor_renamed", object_id: "weather_sensor_renamed_temperature", default_entity_id: "sensor.weather_sensor_renamed_temperature", @@ -2034,7 +2032,7 @@ describe("Extension: HomeAssistant", () => { device_class: "temperature", state_class: "measurement", enabled_by_default: true, - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor_renamed", object_id: "weather_sensor_renamed_temperature", default_entity_id: "sensor.weather_sensor_renamed_temperature", @@ -2644,7 +2642,7 @@ describe("Extension: HomeAssistant", () => { device_class: "temperature", state_class: "measurement", enabled_by_default: true, - value_template: "{{ value_json.temperature }}", + value_template: '{{ value_json["temperature"] }}', state_topic: "zigbee2mqtt/weather_sensor", object_id: "weather_sensor_temperature", default_entity_id: "sensor.weather_sensor_temperature", @@ -3011,7 +3009,7 @@ describe("Extension: HomeAssistant", () => { origin: origin, state_topic: "zigbee2mqtt/0x18fc26000000cafe", unique_id: "0x18fc26000000cafe_device_mode_zigbee2mqtt", - value_template: "{{ value_json.device_mode }}", + value_template: '{{ value_json["device_mode"] }}', }; expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/select/0x18fc26000000cafe/device_mode/config", stringify(payload), { retain: true,