Skip to content

Commit 5d02efe

Browse files
authored
fix(ignore): zigate: Workaround missing ZDO LEAVE_RESPONSE (#1204)
1 parent c661d2e commit 5d02efe

File tree

2 files changed

+37
-25
lines changed

2 files changed

+37
-25
lines changed

src/adapter/zigate/adapter/zigateAdapter.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,6 @@ class ZiGateAdapter extends Adapter {
229229
prefixedPayload.set(payload, 0);
230230

231231
payload = prefixedPayload;
232-
// XXX: zigate is missing ZDO LEAVE_RESPONSE, force disable to avoid waitress timeout (LeaveIndication will do the rest)
233-
disableResponse = true;
234232
break;
235233
}
236234

@@ -271,7 +269,10 @@ class ZiGateAdapter extends Adapter {
271269
if (responseClusterId) {
272270
waiter = this.driver.zdoWaitFor({
273271
clusterId: responseClusterId,
274-
target: responseClusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE ? ieeeAddress : networkAddress,
272+
target:
273+
responseClusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE || responseClusterId === Zdo.ClusterId.LEAVE_RESPONSE
274+
? ieeeAddress
275+
: networkAddress,
275276
});
276277
}
277278
}
@@ -282,9 +283,6 @@ class ZiGateAdapter extends Adapter {
282283
const result = await waiter.start().promise;
283284

284285
return result.zdo as ZdoTypes.RequestToResponseMap[K];
285-
} else if (clusterId === Zdo.ClusterId.LEAVE_REQUEST) {
286-
// mock missing response (see above)
287-
return [Zdo.Status.SUCCESS, undefined];
288286
}
289287
}, networkAddress);
290288
}

src/adapter/zigate/driver/zigate.ts

+33-19
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {logger} from '../../../utils/logger';
1111
import Waitress from '../../../utils/waitress';
1212
import * as ZSpec from '../../../zspec';
1313
import * as Zdo from '../../../zspec/zdo';
14-
import {EndDeviceAnnounce, GenericZdoResponse} from '../../../zspec/zdo/definition/tstypes';
14+
import {EndDeviceAnnounce, GenericZdoResponse, ResponseMap as ZdoResponseMap} from '../../../zspec/zdo/definition/tstypes';
1515
import {SerialPort} from '../../serialPort';
1616
import SerialPortUtils from '../../serialPortUtils';
1717
import SocketPortUtils from '../../socketPortUtils';
@@ -345,33 +345,47 @@ export default class ZiGate extends EventEmitter<ZiGateEventMap> {
345345

346346
this.zdoWaitress.resolve({ziGatePayload, zdo});
347347
this.emit('zdoResponse', ziGatePayload.clusterID, zdo);
348+
} else if (code === ZiGateMessageCode.LeaveIndication && ziGateObject.payload.rejoin === 0) {
349+
// mock a ZDO response (if waiter present) as zigate does not follow spec on this (missing ZDO LEAVE_RESPONSE)
350+
const ziGatePayload: ZdoWaitressPayload['ziGatePayload'] = {
351+
status: 0,
352+
profileID: Zdo.ZDO_PROFILE_ID,
353+
clusterID: Zdo.ClusterId.LEAVE_RESPONSE, // only piece actually required for waitress validation
354+
sourceEndpoint: Zdo.ZDO_ENDPOINT,
355+
destinationEndpoint: Zdo.ZDO_ENDPOINT,
356+
sourceAddressMode: 0x03,
357+
sourceAddress: ziGateObject.payload.extendedAddress,
358+
destinationAddressMode: 0x03,
359+
destinationAddress: ZSpec.BLANK_EUI64,
360+
// @ts-expect-error not used
361+
payload: undefined,
362+
};
363+
364+
// Workaround: `zdo` is not valid for LEAVE_RESPONSE, but required to pass altered waitress validation (in sendZdo)
365+
if (this.zdoWaitress.resolve({ziGatePayload, zdo: [Zdo.Status.SUCCESS, {eui64: ziGateObject.payload.extendedAddress}]})) {
366+
this.emit('zdoResponse', Zdo.ClusterId.LEAVE_RESPONSE, [
367+
Zdo.Status.SUCCESS,
368+
undefined,
369+
] as ZdoResponseMap[Zdo.ClusterId.LEAVE_RESPONSE]);
370+
}
371+
372+
this.emit('LeaveIndication', ziGateObject);
348373
} else {
349374
this.waitress.resolve(ziGateObject);
350-
}
351375

352-
switch (code) {
353-
case ZiGateMessageCode.DataIndication:
354-
switch (ziGateObject.payload.profileID) {
355-
case Zdo.ZDO_PROFILE_ID:
356-
// handled above
357-
break;
358-
case ZSpec.HA_PROFILE_ID:
359-
this.emit('received', ziGateObject);
360-
break;
361-
default:
362-
logger.debug('not implemented profile: ' + ziGateObject.payload.profileID, NS);
376+
if (code === ZiGateMessageCode.DataIndication) {
377+
if (ziGateObject.payload.profileID === ZSpec.HA_PROFILE_ID) {
378+
this.emit('received', ziGateObject);
379+
} else {
380+
logger.debug('not implemented profile: ' + ziGateObject.payload.profileID, NS);
363381
}
364-
break;
365-
case ZiGateMessageCode.LeaveIndication:
366-
this.emit('LeaveIndication', ziGateObject);
367-
break;
368-
case ZiGateMessageCode.DeviceAnnounce:
382+
} else if (code === ZiGateMessageCode.DeviceAnnounce) {
369383
this.emit('DeviceAnnounce', {
370384
nwkAddress: ziGateObject.payload.shortAddress,
371385
eui64: ziGateObject.payload.ieee,
372386
capabilities: ziGateObject.payload.MACcapability,
373387
});
374-
break;
388+
}
375389
}
376390
} catch (error) {
377391
logger.error(`Parsing error: ${error}`, NS);

0 commit comments

Comments
 (0)