Skip to content

Commit

Permalink
fix(modify): Implement nwkUpdateID in all adapters.
Browse files Browse the repository at this point in the history
  • Loading branch information
danyinhao committed Feb 6, 2025
1 parent 629088f commit 5b7d829
Show file tree
Hide file tree
Showing 8 changed files with 25 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/adapter/deconz/adapter/deconzAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ export class DeconzAdapter extends Adapter {
panID: panid as number,
extendedPanID: expanid as string, // read as `0x...`
channel: channel as number,
nwkUpdateID: 0 as number,
};
} catch (error) {
const msg = 'get network parameters Error:' + error;
Expand Down
2 changes: 1 addition & 1 deletion src/adapter/tstype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@ export interface NetworkParameters {
panID: number;
extendedPanID: string; // `0x${string}` same as IEEE address
channel: number;
nwkUpdateID?: number;
nwkUpdateID: number;
}
4 changes: 4 additions & 0 deletions src/adapter/z-stack/adapter/zStackAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import Adapter from '../../adapter';
import * as Events from '../../events';
import {AdapterOptions, CoordinatorVersion, NetworkOptions, NetworkParameters, SerialPortOptions, StartResult} from '../../tstype';
import * as Constants from '../constants';
import {NvItemsIds} from '../constants/common';
import * as Structs from '../structs';
import {Constants as UnpiConstants} from '../unpi';
import {Znp, ZpiObject} from '../znp';
import Definition from '../znp/definition';
Expand Down Expand Up @@ -885,10 +887,12 @@ export class ZStackAdapter extends Adapter {

public async getNetworkParameters(): Promise<NetworkParameters> {
const result = await this.znp.requestWithReply(Subsystem.ZDO, 'extNwkInfo', {});
const nwkUpdateID = (await this.adapterManager.nv.readItem(NvItemsIds.NIB, 0, Structs.nib))?.nwkUpdateId ?? 0;
return {
panID: result.payload.panid as number,
extendedPanID: result.payload.extendedpanid as string, // read as IEEEADDR, so `0x${string}`
channel: result.payload.channel as number,
nwkUpdateID,
};
}

Expand Down
1 change: 1 addition & 0 deletions src/adapter/zboss/adapter/zbossAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export class ZBOSSAdapter extends Adapter {
panID,
extendedPanID: ZSpec.Utils.eui64LEBufferToHex(Buffer.from(extendedPanID)),
channel,
nwkUpdateID: 0,
};
});
}
Expand Down
1 change: 1 addition & 0 deletions src/adapter/zigate/adapter/zigateAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export class ZiGateAdapter extends Adapter {
panID: result.payload.PANID as number,
extendedPanID: result.payload.ExtPANID as string, // read as IEEEADDR, so `0x${string}`
channel: result.payload.Channel as number,
nwkUpdateID: 0 as number,
};
} catch (error) {
throw new Error(`Get network parameters failed ${error}`);
Expand Down
15 changes: 8 additions & 7 deletions src/controller/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,7 @@ export class Controller extends events.EventEmitter<ControllerEventMap> {
const netParams = await this.getNetworkParameters();
const configuredChannel = this.options.network.channelList[0];
const adapterChannel = netParams.channel;
// According to the Zigbee specification:
// When broadcasting a Mgmt_NWK_Update_req to notify devices of a new channel, the nwkUpdateId parameter should be incremented in the NIB and included in the Mgmt_NWK_Update_req.
// The valid range of nwkUpdateId is 0x00 to 0xFF, and it should wrap back to 0 if necessary.
let nwkUpdateID = netParams.nwkUpdateID ?? 0;
if (++nwkUpdateID > 0xff) {
nwkUpdateID = 0x00;
}
const nwkUpdateID = netParams.nwkUpdateID;

if (configuredChannel != adapterChannel) {
logger.info(`Configured channel '${configuredChannel}' does not match adapter channel '${adapterChannel}', changing channel`, NS);
Expand Down Expand Up @@ -506,6 +500,13 @@ export class Controller extends events.EventEmitter<ControllerEventMap> {
private async changeChannel(oldChannel: number, newChannel: number, nwkUpdateID: number): Promise<void> {
logger.warning(`Changing channel from '${oldChannel}' to '${newChannel}'`, NS);

// According to the Zigbee specification:
// When broadcasting a Mgmt_NWK_Update_req to notify devices of a new channel, the nwkUpdateId parameter should be incremented in the NIB and included in the Mgmt_NWK_Update_req.
// The valid range of nwkUpdateId is 0x00 to 0xFF, and it should wrap back to 0 if necessary.
if (++nwkUpdateID > 0xff) {
nwkUpdateID = 0x00;
}

const clusterId = Zdo.ClusterId.NWK_UPDATE_REQUEST;
const zdoPayload = Zdo.Buffalo.buildRequest(
this.adapter.hasZdoMessageOverhead,
Expand Down
4 changes: 2 additions & 2 deletions test/adapter/z-stack/adapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3507,9 +3507,9 @@ describe('zstack-adapter', () => {
mockZnpRequest.mockClear();
mockQueueExecute.mockClear();
const result = await adapter.getNetworkParameters();
expect(mockZnpRequest).toHaveBeenCalledTimes(1);
expect(mockZnpRequest).toHaveBeenCalledTimes(3);
expect(mockZnpRequest).toHaveBeenCalledWith(Subsystem.ZDO, 'extNwkInfo', {});
expect(result).toStrictEqual({channel: 21, extendedPanID: '0x00124b0009d69f77', panID: 123});
expect(result).toStrictEqual({channel: 21, extendedPanID: '0x00124b0009d69f77', panID: 123, nwkUpdateID: 0});
});

it('Set interpan channel', async () => {
Expand Down
13 changes: 7 additions & 6 deletions test/controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const mockAdapterReset = vi.fn();
const mockAdapterStop = vi.fn();
const mockAdapterStart = vi.fn().mockReturnValue('resumed');
const mockAdapterGetCoordinatorIEEE = vi.fn().mockReturnValue('0x0000012300000000');
const mockAdapterGetNetworkParameters = vi.fn().mockReturnValue({panID: 1, extendedPanID: '0x64c5fd698daf0c00', channel: 15});
const mockAdapterGetNetworkParameters = vi.fn().mockReturnValue({panID: 1, extendedPanID: '0x64c5fd698daf0c00', channel: 15, nwkUpdateID: 0});
const mocksendZclFrameToGroup = vi.fn();
const mocksendZclFrameToAll = vi.fn();
const mockAddInstallCode = vi.fn();
Expand Down Expand Up @@ -1556,7 +1556,7 @@ describe('Controller', () => {

it('Change channel on start', async () => {
mockAdapterStart.mockReturnValueOnce('resumed');
mockAdapterGetNetworkParameters.mockReturnValueOnce({panID: 1, extendedPanID: '0x64c5fd698daf0c00', channel: 25});
mockAdapterGetNetworkParameters.mockReturnValueOnce({panID: 1, extendedPanID: '0x64c5fd698daf0c00', channel: 25, nwkUpdateID: 0});
// @ts-expect-error private
const changeChannelSpy = vi.spyOn(controller, 'changeChannel');
await controller.start();
Expand All @@ -1569,7 +1569,8 @@ describe('Controller', () => {
zdoPayload,
true,
);
expect(await controller.getNetworkParameters()).toEqual({panID: 1, channel: 15, extendedPanID: '0x64c5fd698daf0c00'});
mockAdapterGetNetworkParameters.mockReturnValueOnce({panID: 1, extendedPanID: '0x64c5fd698daf0c00', channel: 15, nwkUpdateID: 1});
expect(await controller.getNetworkParameters()).toEqual({panID: 1, channel: 15, extendedPanID: '0x64c5fd698daf0c00', nwkUpdateID: 1});
expect(changeChannelSpy).toHaveBeenCalledTimes(1);
});

Expand All @@ -1588,7 +1589,7 @@ describe('Controller', () => {
zdoPayload,
true,
);
expect(await controller.getNetworkParameters()).toEqual({panID: 1, channel: 15, extendedPanID: '0x64c5fd698daf0c00'});
expect(await controller.getNetworkParameters()).toEqual({panID: 1, channel: 15, extendedPanID: '0x64c5fd698daf0c00', nwkUpdateID: 0});
expect(changeChannelSpy).toHaveBeenCalledTimes(1);
});

Expand All @@ -1608,9 +1609,9 @@ describe('Controller', () => {

it('Get network parameters', async () => {
await controller.start();
expect(await controller.getNetworkParameters()).toEqual({panID: 1, channel: 15, extendedPanID: '0x64c5fd698daf0c00'});
expect(await controller.getNetworkParameters()).toEqual({panID: 1, channel: 15, extendedPanID: '0x64c5fd698daf0c00', nwkUpdateID: 0});
// cached
expect(await controller.getNetworkParameters()).toEqual({panID: 1, channel: 15, extendedPanID: '0x64c5fd698daf0c00'});
expect(await controller.getNetworkParameters()).toEqual({panID: 1, channel: 15, extendedPanID: '0x64c5fd698daf0c00', nwkUpdateID: 0});
expect(mockAdapterGetNetworkParameters).toHaveBeenCalledTimes(1);
});

Expand Down

0 comments on commit 5b7d829

Please sign in to comment.