const {ZnpCommandStatus, NvSystemIds} = require('zigbee-herdsman/dist/adapter/z-stack/constants/common'); const {ZnpVersion} = require('zigbee-herdsman/dist/adapter/z-stack/adapter/tstype'); const {Subsystem} = require('zigbee-herdsman/dist/adapter/z-stack/unpi/constants'); const {Znp} = require('zigbee-herdsman/dist/adapter/z-stack/znp'); var fs = require('fs'); class ZStackNvMemReader { constructor(device) { this.znp = new Znp(device, 115200, false); } async start() { await this.znp.open(); const attempts = 3; for (let i = 0; i < attempts; i++) { try { await this.znp.request(Subsystem.SYS, 'ping', {capabilities: 1}); break; } catch (e) { if (attempts - 1 === i) { throw new Error(`Failed to connect to the adapter (${e})`); } } } // Old firmware did not support version, assume it's Z-Stack 1.2 for now. try { this.version = (await this.znp.request(Subsystem.SYS, 'version', {})).payload; } catch (e) { console.log(`Failed to get zStack version, assuming 1.2`); this.version = {'transportrev': 2, 'product': 0, 'majorrel': 2, 'minorrel': 0, 'maintrel': 0, 'revision': ''}; } console.log(`Detected znp version '${ZnpVersion[this.version.product]}' (${JSON.stringify(this.version)})`); await this.clearAllNvMemItems(); process.exit(0); } async clearAllNvMemItems() { let maxNvMemId; switch (this.version.product) { case ZnpVersion.zStack12: maxNvMemId = 0x0302; break; case ZnpVersion.zStack30x: maxNvMemId = 0x033F; break; case ZnpVersion.zStack3x0: maxNvMemId = 0x032F; break; } var result = "ID;Requested Length;Response Status;Response Length;Response Data\n"; let readCount = 0; console.log(`Reading all NVMEM items, from 0 to ${maxNvMemId}`); for (let id=0; id<=maxNvMemId; id++) { let len; const needOsal = !(this.version.product == ZnpVersion.zStack3x0 && id <= 7); if (needOsal) { const lengthRes = await this.znp.request(Subsystem.SYS, 'osalNvLength', {id: id}); len = lengthRes.payload['length']; } else { const lengthRes = await this.znp.request(Subsystem.SYS, 'nvLength', {sysid: NvSystemIds.ZSTACK, itemid: id, subid: 0}); len = lengthRes.payload['len']; } if (len != 0) { console.log(`NVMEM item #${id} - reading, size: ${len}`); if (needOsal) { const readRes = await this.znp.request(Subsystem.SYS, 'osalNvRead', {id: id, offset:0}, null, [ZnpCommandStatus.SUCCESS, ZnpCommandStatus.NV_ITEM_INITIALIZED]); //console.log(`Response: (${readRes.payload['status']}:${readRes.payload['len']}) ${readRes.payload['value'].toString('hex')} `) result = result + `${id};${len};${readRes.payload['status']};${readRes.payload['len']};${readRes.payload['value'].toString('hex')}\n` } else { const readRes = await this.znp.request(Subsystem.SYS, 'nvRead', {sysid: NvSystemIds.ZSTACK, itemid: id, subid: 0, offset:0, len:len}, null, [ZnpCommandStatus.SUCCESS, ZnpCommandStatus.NV_ITEM_INITIALIZED]); //status, len, value //console.log(`Response: (${readRes.payload['status']}:${readRes.payload['len']}) ${readRes.payload['value'].toString('hex')} `) result = result + `${id};${len};${readRes.payload['status']};${readRes.payload['len']};${readRes.payload['value'].toString('hex')}\n` } readCount++; } } console.log(`Reading all NVMEM items finished, read ${readCount} items`); //console.log(result); fs.writeFileSync('nvmemcontent.txt', result); } } const processArgs = process.argv.slice(2); if (processArgs.length != 1) { console.log('ZStack NVMEM reader.'); console.log('Usage:'); console.log(' node zStackReadAllNvMem.js '); process.exit(1); } const reader = new ZStackNvMemReader(processArgs[0]); reader.start();