diff --git a/lib/util/settings.js b/lib/util/settings.js index b19abd7a..fcf4b2ab 100644 --- a/lib/util/settings.js +++ b/lib/util/settings.js @@ -218,6 +218,11 @@ function validate() { errors.push(`advanced.network_key: should be array or 'GENERATE' (is '${_settings.advanced.network_key}')`); } + if (_settings.advanced && _settings.advanced.pan_id && typeof _settings.advanced.pan_id === 'string' && + _settings.advanced.pan_id !== 'GENERATE') { + errors.push(`advanced.pan_id: should be number or 'GENERATE' (is '${_settings.advanced.pan_id}')`); + } + // Verify that all friendly names are unique const names = []; const check = (name) => { diff --git a/lib/util/settings.schema.json b/lib/util/settings.schema.json index a0489aec..dc284bae 100644 --- a/lib/util/settings.schema.json +++ b/lib/util/settings.schema.json @@ -190,7 +190,15 @@ "default": true }, "pan_id": { - "type": "number", + "oneOf": [{ + "type": "string", + "title": "Pan ID (string)" + }, + { + "type": "number", + "title": "Pan ID (number)" + } + ], "title": "Pan ID", "description": "ZigBee pan ID" }, diff --git a/lib/zigbee.js b/lib/zigbee.js index ab892460..7b6ead0f 100644 --- a/lib/zigbee.js +++ b/lib/zigbee.js @@ -53,6 +53,12 @@ class Zigbee extends events.EventEmitter { herdsmanSettings.network.networkKey = newKey; } + if (herdsmanSettings.network.panID === 'GENERATE') { + const newPanID = Math.floor(Math.random() * (0xFFFF - 2)) + 1; + settings.set(['advanced', 'pan_id'], newPanID); + herdsmanSettings.network.panID = newPanID; + } + try { herdsmanSettings.acceptJoiningDeviceHandler = this.acceptJoiningDeviceHandler; this.herdsman = new ZigbeeHerdsman.Controller(herdsmanSettings); diff --git a/test/controller.test.js b/test/controller.test.js index dec20b76..cf9eab71 100644 --- a/test/controller.test.js +++ b/test/controller.test.js @@ -93,12 +93,15 @@ describe('Controller', () => { expect(MQTT.connect).toHaveBeenCalledWith("mqtt://localhost", expected); }); - it('Should generate network_key when set to GENERATE', async () => { + it('Should generate network_key and pan_id when set to GENERATE', async () => { settings.set(['advanced', 'network_key'], 'GENERATE'); + settings.set(['advanced', 'pan_id'], 'GENERATE'); await controller.start(); await flushPromises(); expect(zigbeeHerdsman.constructor.mock.calls[0][0].network.networkKey.length).toStrictEqual(16); + expect(zigbeeHerdsman.constructor.mock.calls[0][0].network.panID).toStrictEqual(expect.any(Number)); expect(data.read().advanced.network_key.length).toStrictEqual(16); + expect(data.read().advanced.pan_id).toStrictEqual(expect.any(Number)); }); it('Start controller should publish cached states', async () => { diff --git a/test/settings.test.js b/test/settings.test.js index 04e58461..4bafd221 100644 --- a/test/settings.test.js +++ b/test/settings.test.js @@ -622,6 +622,18 @@ describe('Settings', () => { expect(settings.validate()).toEqual(expect.arrayContaining([error])); }); + it('Should not allow any string values for pan_id', () => { + write(configurationFile, { + ...minimalConfig, + advanced: {pan_id: 'NOT_GENERATE'}, + }); + + settings._reRead(); + + const error = `advanced.pan_id: should be number or 'GENERATE' (is 'NOT_GENERATE')`; + expect(settings.validate()).toEqual(expect.arrayContaining([error])); + }); + it('Should allow retention configuration with MQTT v5', () => { write(configurationFile, { ...minimalConfig,