Skip to content

Commit

Permalink
Rediscover route when defaultResponse fails. Koenkk/zigbee2mqtt#2693
Browse files Browse the repository at this point in the history
  • Loading branch information
Koenkk committed Jan 18, 2020
1 parent 2aa58cb commit 920b4a2
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/adapter/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ abstract class Adapter extends events.EventEmitter {

public abstract setLED(enabled: boolean): Promise<void>;

public abstract discoverRoute(networkAddress: number): Promise<void>;

public abstract lqi(networkAddress: number): Promise<TsType.LQI>;

public abstract routingTable(networkAddress: number): Promise<TsType.RoutingTable>;
Expand Down
5 changes: 5 additions & 0 deletions src/adapter/z-stack/adapter/zStackAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ class ZStackAdapter extends Adapter {
await this.znp.request(Subsystem.UTIL, 'ledControl', {ledid: 3, mode: enabled ? 1 : 0});
}

public async discoverRoute(networkAddress: number): Promise<void> {
const payload = {dstAddr: networkAddress, options: 2, radius: Constants.AF.DEFAULT_RADIUS};
await this.znp.request(Subsystem.ZDO, 'extRouteDisc', payload);
}

public async nodeDescriptor(networkAddress: number): Promise<NodeDescriptor> {
return this.queue.execute<NodeDescriptor>(async () => {
const response = this.znp.waitFor(Type.AREQ, Subsystem.ZDO, 'nodeDescRsp', {nwkaddr: networkAddress});
Expand Down
11 changes: 10 additions & 1 deletion src/controller/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,16 @@ class Controller extends events.EventEmitter {
frame.getCommand().ID, 0, frame.Cluster.ID, frame.Header.transactionSequenceNumber,
);
} catch (error) {
debug.error(`Default response to ${device.ieeeAddr} failed`);
debug.error(`Default response to ${device.ieeeAddr} failed, force route discovery`);
await this.adapter.discoverRoute(device.networkAddress);

try {
await endpoint.defaultResponse(
frame.getCommand().ID, 0, frame.Cluster.ID, frame.Header.transactionSequenceNumber,
);
} catch (error) {
debug.error(`Default response to ${device.ieeeAddr} failed, even after route discovery`);
}
}
}

Expand Down
11 changes: 11 additions & 0 deletions test/adapter/z-stack/zStackAdapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ const basicMocks = () => {
return {};
} else if (subsystem === Subsystem.AF && command === 'interPanCtl') {
return {};
} else if (subsystem === Subsystem.ZDO && command === 'extRouteDisc') {
return {};
} else {
missing();
}
Expand Down Expand Up @@ -1782,6 +1784,15 @@ describe('zStackAdapter', () => {
expect(await adapter.supportsLED()).toBeTruthy();
});

it('Route discovery', async () => {
basicMocks();
await adapter.start();
mockZnpRequest.mockClear();
await adapter.discoverRoute(1239);
expect(mockZnpRequest).toBeCalledTimes(1);
expect(mockZnpRequest).toBeCalledWith(Subsystem.ZDO, 'extRouteDisc', {dstAddr: 1239, options: 2, radius: 30});
});

it('Node descriptor', async () => {
basicMocks();
let result;
Expand Down
9 changes: 6 additions & 3 deletions test/controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const mocksendZclFrameInterPANIeeeAddr = jest.fn();
const mocksendZclFrameInterPANBroadcastWithResponse = jest.fn();
const mockRestoreChannelInterPAN = jest.fn();
const mockAdapterPermitJoin = jest.fn();
const mockDiscoverRoute = jest.fn();
const mockAdapterSupportsBackup = jest.fn().mockReturnValue(true);
const mockAdapterReset = jest.fn();
const mockAdapterStop = jest.fn();
Expand Down Expand Up @@ -199,6 +200,7 @@ jest.mock('../src/adapter/z-stack/adapter/zStackAdapter', () => {
sendZclFrameNetworkAddress: mockSendZclFrameNetworkAddress,
sendZclFrameGroup: mockSendZclFrameGroup,
permitJoin: mockAdapterPermitJoin,
discoverRoute: mockDiscoverRoute,
stop: mockAdapterStop,
removeDevice: mockAdapterRemoveDevice,
lqi: (networkAddress) => {
Expand Down Expand Up @@ -1189,11 +1191,11 @@ describe('Controller', () => {
});
});

it('Receive zclData send default response fails', async () => {
it('Receive zclData send default response fails should attempt route discover', async () => {
await controller.start();
await mockAdapterEvents['deviceJoined']({networkAddress: 129, ieeeAddr: '0x129'});
mockSendZclFrameNetworkAddress.mockClear();
mockSendZclFrameNetworkAddress.mockRejectedValueOnce("");
mockSendZclFrameNetworkAddress.mockRejectedValue("");
await mockAdapterEvents['zclData']({
address: 129,
frame: ZclFrame.create(1, 1, false, 4476, 29, 1, 5, {groupid: 1, sceneid: 1}),
Expand All @@ -1202,7 +1204,8 @@ describe('Controller', () => {
groupID: 10,
});

expect(mockSendZclFrameNetworkAddress).toBeCalledTimes(1);
expect(mockDiscoverRoute).toBeCalledTimes(1);
expect(mockSendZclFrameNetworkAddress).toBeCalledTimes(2);
});

it('Respond to genTime read', async () => {
Expand Down

0 comments on commit 920b4a2

Please sign in to comment.