Skip to content

Commit ef6524b

Browse files
authored
fix: Fix dual cover Home Assistant discovery (#25240)
1 parent 9822c75 commit ef6524b

File tree

3 files changed

+90
-5
lines changed

3 files changed

+90
-5
lines changed

lib/extension/homeassistant.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ export default class HomeAssistant extends Extension {
781781
const motorState = allExposes
782782
?.filter(isEnumExpose)
783783
.find((e) => ['motor_state', 'moving'].includes(e.name) && e.access === ACCESS_STATE);
784-
const running = allExposes?.find((e) => e.type === 'binary' && e.name === 'running');
784+
const running = allExposes?.filter(isBinaryExpose)?.find((e) => e.name === 'running');
785785

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

@@ -819,8 +819,8 @@ export default class HomeAssistant extends Extension {
819819
discoveryEntry.discovery_payload.state_closing = closingState;
820820
discoveryEntry.discovery_payload.state_stopped = stoppedState;
821821
discoveryEntry.discovery_payload.value_template =
822-
`{% if "${motorState.property}" in value_json ` +
823-
`and value_json.${motorState.property} %} {{ value_json.${motorState.property} }} {% else %} ` +
822+
`{% if "${featurePropertyWithoutEndpoint(motorState)}" in value_json ` +
823+
`and value_json.${featurePropertyWithoutEndpoint(motorState)} %} {{ value_json.${featurePropertyWithoutEndpoint(motorState)} }} {% else %} ` +
824824
`${stoppedState} {% endif %}`;
825825
}
826826
}

test/extensions/homeassistant.test.ts

+70
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,76 @@ describe('Extension: HomeAssistant', () => {
10071007
});
10081008
});
10091009

1010+
it('Should discover dual cover devices', async () => {
1011+
const payload_left = {
1012+
availability: [
1013+
{
1014+
topic: 'zigbee2mqtt/bridge/state',
1015+
value_template: '{{ value_json.state }}',
1016+
},
1017+
],
1018+
command_topic: 'zigbee2mqtt/0xa4c138018cf95021/left/set',
1019+
device: {
1020+
identifiers: ['zigbee2mqtt_0xa4c138018cf95021'],
1021+
manufacturer: 'Lonsonho',
1022+
model: 'Dual curtain/blind module (TS130F_dual)',
1023+
name: '0xa4c138018cf95021',
1024+
via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae',
1025+
},
1026+
name: 'Left',
1027+
object_id: '0xa4c138018cf95021_left',
1028+
origin: origin,
1029+
position_template: '{{ value_json.position }}',
1030+
position_topic: 'zigbee2mqtt/0xa4c138018cf95021/left',
1031+
set_position_template: '{ "position_left": {{ position }} }',
1032+
set_position_topic: 'zigbee2mqtt/0xa4c138018cf95021/left/set',
1033+
state_closing: 'DOWN',
1034+
state_opening: 'UP',
1035+
state_stopped: 'STOP',
1036+
state_topic: 'zigbee2mqtt/0xa4c138018cf95021/left',
1037+
unique_id: '0xa4c138018cf95021_cover_left_zigbee2mqtt',
1038+
value_template: '{% if "moving" in value_json and value_json.moving %} {{ value_json.moving }} {% else %} STOP {% endif %}',
1039+
};
1040+
const payload_right = {
1041+
availability: [
1042+
{
1043+
topic: 'zigbee2mqtt/bridge/state',
1044+
value_template: '{{ value_json.state }}',
1045+
},
1046+
],
1047+
command_topic: 'zigbee2mqtt/0xa4c138018cf95021/right/set',
1048+
device: {
1049+
identifiers: ['zigbee2mqtt_0xa4c138018cf95021'],
1050+
manufacturer: 'Lonsonho',
1051+
model: 'Dual curtain/blind module (TS130F_dual)',
1052+
name: '0xa4c138018cf95021',
1053+
via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae',
1054+
},
1055+
name: 'Right',
1056+
object_id: '0xa4c138018cf95021_right',
1057+
origin: origin,
1058+
position_template: '{{ value_json.position }}',
1059+
position_topic: 'zigbee2mqtt/0xa4c138018cf95021/right',
1060+
set_position_template: '{ "position_right": {{ position }} }',
1061+
set_position_topic: 'zigbee2mqtt/0xa4c138018cf95021/right/set',
1062+
state_closing: 'DOWN',
1063+
state_opening: 'UP',
1064+
state_stopped: 'STOP',
1065+
state_topic: 'zigbee2mqtt/0xa4c138018cf95021/right',
1066+
unique_id: '0xa4c138018cf95021_cover_right_zigbee2mqtt',
1067+
value_template: '{% if "moving" in value_json and value_json.moving %} {{ value_json.moving }} {% else %} STOP {% endif %}',
1068+
};
1069+
1070+
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('homeassistant/cover/0xa4c138018cf95021/cover_left/config', stringify(payload_left), {
1071+
retain: true,
1072+
qos: 1,
1073+
});
1074+
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('homeassistant/cover/0xa4c138018cf95021/cover_right/config', stringify(payload_right), {
1075+
retain: true,
1076+
qos: 1,
1077+
});
1078+
});
1079+
10101080
it('Should discover devices with custom homeassistant.discovery_topic', async () => {
10111081
settings.set(['homeassistant'], {discovery_topic: 'my_custom_discovery_topic'});
10121082
await resetExtension();

test/mocks/zigbeeHerdsman.ts

+15
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,21 @@ export const devices = {
983983
'Mains (single phase)',
984984
'J1 (5502)',
985985
),
986+
TS130F_DUAL_COVER_SWITCH: new Device(
987+
'Router',
988+
'0xa4c138018cf95021',
989+
46163,
990+
4417,
991+
[
992+
new Endpoint(1, [0, 4, 5, 6, 258, 57345], [10, 25], '0xa4c138018cf95021'),
993+
new Endpoint(2, [0, 4, 5, 6, 258, 57345], [10, 25], '0xa4c138018cf95021'),
994+
],
995+
true,
996+
'Mains (single phase)',
997+
'TS130F',
998+
false,
999+
'_TZ3000_j1xl73iw',
1000+
),
9861001
TS0601_thermostat: TS0601_thermostat,
9871002
TS0601_switch: TS0601_switch,
9881003
TS0601_cover_switch: TS0601_cover_switch,

0 commit comments

Comments
 (0)