Skip to content

Commit

Permalink
fix: Fix dual cover Home Assistant discovery (#25240)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xyaren authored Dec 17, 2024
1 parent 9822c75 commit ef6524b
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 5 deletions.
10 changes: 5 additions & 5 deletions lib/extension/homeassistant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ export default class HomeAssistant extends Extension {
const motorState = allExposes
?.filter(isEnumExpose)
.find((e) => ['motor_state', 'moving'].includes(e.name) && e.access === ACCESS_STATE);
const running = allExposes?.find((e) => e.type === 'binary' && e.name === 'running');
const running = allExposes?.filter(isBinaryExpose)?.find((e) => e.name === 'running');

const discoveryEntry: DiscoveryEntry = {
type: 'cover',
Expand All @@ -801,8 +801,8 @@ export default class HomeAssistant extends Extension {
if (running) {
assert(position, `Cover must have 'position' when it has 'running'`);
discoveryEntry.discovery_payload.value_template =
`{% if "${running.property}" in value_json ` +
`and value_json.${running.property} %} {% if value_json.${position.property} > 0 %} closing ` +
`{% if "${featurePropertyWithoutEndpoint(running)}" in value_json ` +
`and value_json.${featurePropertyWithoutEndpoint(running)} %} {% if value_json.${featurePropertyWithoutEndpoint(position)} > 0 %} closing ` +
`{% else %} opening {% endif %} {% else %} stopped {% endif %}`;
}

Expand All @@ -819,8 +819,8 @@ export default class HomeAssistant extends Extension {
discoveryEntry.discovery_payload.state_closing = closingState;
discoveryEntry.discovery_payload.state_stopped = stoppedState;
discoveryEntry.discovery_payload.value_template =
`{% if "${motorState.property}" in value_json ` +
`and value_json.${motorState.property} %} {{ value_json.${motorState.property} }} {% else %} ` +
`{% if "${featurePropertyWithoutEndpoint(motorState)}" in value_json ` +
`and value_json.${featurePropertyWithoutEndpoint(motorState)} %} {{ value_json.${featurePropertyWithoutEndpoint(motorState)} }} {% else %} ` +
`${stoppedState} {% endif %}`;
}
}
Expand Down
70 changes: 70 additions & 0 deletions test/extensions/homeassistant.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,76 @@ describe('Extension: HomeAssistant', () => {
});
});

it('Should discover dual cover devices', async () => {
const payload_left = {
availability: [
{
topic: 'zigbee2mqtt/bridge/state',
value_template: '{{ value_json.state }}',
},
],
command_topic: 'zigbee2mqtt/0xa4c138018cf95021/left/set',
device: {
identifiers: ['zigbee2mqtt_0xa4c138018cf95021'],
manufacturer: 'Lonsonho',
model: 'Dual curtain/blind module (TS130F_dual)',
name: '0xa4c138018cf95021',
via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae',
},
name: 'Left',
object_id: '0xa4c138018cf95021_left',
origin: origin,
position_template: '{{ value_json.position }}',
position_topic: 'zigbee2mqtt/0xa4c138018cf95021/left',
set_position_template: '{ "position_left": {{ position }} }',
set_position_topic: 'zigbee2mqtt/0xa4c138018cf95021/left/set',
state_closing: 'DOWN',
state_opening: 'UP',
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 %}',
};
const payload_right = {
availability: [
{
topic: 'zigbee2mqtt/bridge/state',
value_template: '{{ value_json.state }}',
},
],
command_topic: 'zigbee2mqtt/0xa4c138018cf95021/right/set',
device: {
identifiers: ['zigbee2mqtt_0xa4c138018cf95021'],
manufacturer: 'Lonsonho',
model: 'Dual curtain/blind module (TS130F_dual)',
name: '0xa4c138018cf95021',
via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae',
},
name: 'Right',
object_id: '0xa4c138018cf95021_right',
origin: origin,
position_template: '{{ value_json.position }}',
position_topic: 'zigbee2mqtt/0xa4c138018cf95021/right',
set_position_template: '{ "position_right": {{ position }} }',
set_position_topic: 'zigbee2mqtt/0xa4c138018cf95021/right/set',
state_closing: 'DOWN',
state_opening: 'UP',
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 %}',
};

expect(mockMQTT.publishAsync).toHaveBeenCalledWith('homeassistant/cover/0xa4c138018cf95021/cover_left/config', stringify(payload_left), {
retain: true,
qos: 1,
});
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('homeassistant/cover/0xa4c138018cf95021/cover_right/config', stringify(payload_right), {
retain: true,
qos: 1,
});
});

it('Should discover devices with custom homeassistant.discovery_topic', async () => {
settings.set(['homeassistant'], {discovery_topic: 'my_custom_discovery_topic'});
await resetExtension();
Expand Down
15 changes: 15 additions & 0 deletions test/mocks/zigbeeHerdsman.ts
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,21 @@ export const devices = {
'Mains (single phase)',
'J1 (5502)',
),
TS130F_DUAL_COVER_SWITCH: new Device(
'Router',
'0xa4c138018cf95021',
46163,
4417,
[
new Endpoint(1, [0, 4, 5, 6, 258, 57345], [10, 25], '0xa4c138018cf95021'),
new Endpoint(2, [0, 4, 5, 6, 258, 57345], [10, 25], '0xa4c138018cf95021'),
],
true,
'Mains (single phase)',
'TS130F',
false,
'_TZ3000_j1xl73iw',
),
TS0601_thermostat: TS0601_thermostat,
TS0601_switch: TS0601_switch,
TS0601_cover_switch: TS0601_cover_switch,
Expand Down

0 comments on commit ef6524b

Please sign in to comment.