mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-10-23 06:12:23 +00:00
Include network routes on the map (#1641)
* Initial inclusion of routes on map * Forgot to include zigbee.js * Hex string for route address * Rebaseline to dev * Cleaner merging of scan arrays * style fixes
This commit is contained in:
1 parent
c48f73e36b
commit
3981c1c6e4
2 files changed
+89
-29
No files matched your search
@@ -89,7 +89,9 @@ class NetworkMap {
|
||||
*/
|
||||
topology.filter((e) => (e.ieeeAddr === device.ieeeAddr) || (e.nwkAddr === device.nwkAddr)).forEach((e) => {
|
||||
const lineStyle = (e.lqi==0) ? `style="dashed", ` : ``;
|
||||
text += ` "${device.ieeeAddr}" -> "${e.parent}" [`+lineStyle+`label="${e.lqi}"]\n`;
|
||||
const textRoutes = e.routes.map((r) => `0x${r.toString(16)}`);
|
||||
const lineLabels = e.lqi + '\\n[' + textRoutes.join(']\\n[') + ']';
|
||||
text += ` "${e.parent}" -> "${device.ieeeAddr}" [`+lineStyle+`label="${lineLabels}"]\n`;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+86
-28
@@ -292,51 +292,110 @@ class Zigbee {
|
||||
|
||||
networkScan(callback) {
|
||||
logger.info('Starting network scan...');
|
||||
const scanList = new Set();
|
||||
const lqiScanList = new Set();
|
||||
const rtgScanList = new Set();
|
||||
const linkMap = [];
|
||||
const routeMap = [];
|
||||
|
||||
const processResponse = (error, rsp, parent) => {
|
||||
// Gather the lqi and the route info into separate lists and only collate them when done.
|
||||
const collateMap = () => {
|
||||
linkMap.sort((a, b) => (a.key > b.key) ? 1 : 0);
|
||||
logger.debug(`Link map: %j`, linkMap);
|
||||
logger.debug(`Route map: %j`, routeMap);
|
||||
// Merge the routes into the linkMap
|
||||
linkMap.forEach((link) => {
|
||||
routeMap.filter((e) => e.key === link.key).forEach((e) => {
|
||||
link.routes.push(e.destAddr);
|
||||
});
|
||||
delete link.key;
|
||||
});
|
||||
logger.debug(`Merged map: %j`, linkMap);
|
||||
callback(linkMap);
|
||||
};
|
||||
|
||||
const processLqiResponse = (error, rsp, parent) => {
|
||||
if (error) {
|
||||
logger.warn(`Failed network scan for device: '${parent}' with error: '${error}'`);
|
||||
logger.warn(`Failed network lqi scan for device: '${parent}' with error: '${error}'`);
|
||||
} else {
|
||||
if (scanList.has(parent)) {
|
||||
if (lqiScanList.has(parent)) {
|
||||
// Haven't processed this one yet
|
||||
if (rsp && rsp.status === 0 && rsp.neighborlqilist) {
|
||||
logger.debug(`Network scan ok for: '${parent}' with '${rsp.neighborlqilistcount}' neighbors`);
|
||||
logger.debug(`lqi scan ok for: '${parent}' with '${rsp.neighborlqilistcount}' neighbors`);
|
||||
rsp.neighborlqilist.forEach(function(neighbor) {
|
||||
const key = parent + '|' + neighbor.nwkAddr;
|
||||
linkMap.push({
|
||||
parent: parent, ieeeAddr: neighbor.extAddr, nwkAddr: neighbor.nwkAddr,
|
||||
lqi: neighbor.lqi, depth: neighbor.depth});
|
||||
key: key, parent: parent, ieeeAddr: neighbor.extAddr, nwkAddr: neighbor.nwkAddr,
|
||||
lqi: neighbor.lqi, depth: neighbor.depth, routes: []});
|
||||
});
|
||||
// Remove from list and if this was the last one return the completed network map
|
||||
scanList.delete(parent);
|
||||
if (scanList.size === 0) {
|
||||
lqiScanList.delete(parent);
|
||||
if (lqiScanList.size === 0 && rtgScanList === 0) {
|
||||
logger.info('Network scan completed');
|
||||
linkMap.sort((a, b) => ((a.parent + '|' + a.ieeeAddr) > (b.parent + '|' + b.ieeeAddr)) ? 1
|
||||
: (((b.parent + '|' + b.ieeeAddr) > (a.parent + '|' + a.ieeeAddr)) ? -1 : 0));
|
||||
logger.debug(`Link map (complete): %j`, linkMap);
|
||||
callback(linkMap);
|
||||
collateMap();
|
||||
} else {
|
||||
logger.debug(`Still waiting for network scans for devices: '${[...scanList].join(' ')}'`);
|
||||
logger.debug(`Outstanding network lqi scans for devices: '${[...lqiScanList].join(' ')}'`);
|
||||
logger.debug(`Outstanding network rtg scans for devices: '${[...rtgScanList].join(' ')}'`);
|
||||
}
|
||||
} else {
|
||||
logger.warn(`Empty network scan result for: '${parent}'`);
|
||||
logger.warn(`Empty network lqi scan result for: '${parent}'`);
|
||||
}
|
||||
} else {
|
||||
// This ieeeAddr has already been removed due to timeout so don't add to result network map
|
||||
logger.warn(`Ignoring late network scan result for: '${parent}'`);
|
||||
logger.warn(`Ignoring late network lqi scan result for: '${parent}'`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Queue up an lqi scan for coordinator and each router
|
||||
const processRtgResponse = (error, rsp, parent) => {
|
||||
if (error) {
|
||||
logger.warn(`Failed network rtg scan for device: '${parent}' with error: '${error}'`);
|
||||
} else {
|
||||
if (rtgScanList.has(parent)) {
|
||||
// Haven't processed this one yet
|
||||
if (rsp && rsp.status === 0 && rsp.routingtablelist) {
|
||||
logger.debug(`rtg scan ok for: '${parent}' with '${rsp.routingtablelistcount}' entries`);
|
||||
rsp.routingtablelist.forEach(function(route) {
|
||||
if (route.routeStatus === 0) {
|
||||
const key = parent + '|' + route.nextHopNwkAddr;
|
||||
routeMap.push({
|
||||
key: key, destAddr: route.destNwkAddr});
|
||||
}
|
||||
});
|
||||
// Remove from list and if this was the last one return the completed network map
|
||||
rtgScanList.delete(parent);
|
||||
if (lqiScanList.size === 0 && rtgScanList.size === 0) {
|
||||
logger.info('Network scan completed');
|
||||
collateMap();
|
||||
} else {
|
||||
logger.debug(`Outstanding network lqi scans for devices: '${[...lqiScanList].join(' ')}'`);
|
||||
logger.debug(`Outstanding network rtg scans for devices: '${[...rtgScanList].join(' ')}'`);
|
||||
}
|
||||
} else {
|
||||
logger.warn(`Empty network rtg scan result for: '${parent}'`);
|
||||
}
|
||||
} else {
|
||||
// This ieeeAddr has already been removed due to timeout so don't add to result network map
|
||||
logger.warn(`Ignoring late network rtg scan result for: '${parent}'`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Queue up an lqi scan and an rtg for coordinator and each router
|
||||
this.getScanable().forEach((dev) => {
|
||||
logger.debug(`Queing network scan for device: '${dev.ieeeAddr}'`);
|
||||
scanList.add(dev.ieeeAddr);
|
||||
logger.debug(`Queing network scans for device: '${dev.ieeeAddr}'`);
|
||||
lqiScanList.add(dev.ieeeAddr);
|
||||
this.queue.push(dev.ieeeAddr, (queueCallback) => {
|
||||
this.shepherd.controller.request('ZDO', 'mgmtLqiReq', {dstaddr: dev.nwkAddr, startindex: 0},
|
||||
(error, rsp, parent) => {
|
||||
processResponse(error, rsp, dev.ieeeAddr);
|
||||
processLqiResponse(error, rsp, dev.ieeeAddr);
|
||||
queueCallback(error);
|
||||
});
|
||||
});
|
||||
rtgScanList.add(dev.ieeeAddr);
|
||||
this.queue.push(dev.ieeeAddr, (queueCallback) => {
|
||||
this.shepherd.controller.request('ZDO', 'mgmtRtgReq', {dstaddr: dev.nwkAddr, startindex: 0},
|
||||
(error, rsp, parent) => {
|
||||
processRtgResponse(error, rsp, dev.ieeeAddr);
|
||||
queueCallback(error);
|
||||
});
|
||||
});
|
||||
@@ -344,18 +403,17 @@ class Zigbee {
|
||||
|
||||
// Wait for all device scans before forcing map with whatever results are already in
|
||||
setTimeout(() => {
|
||||
if (scanList.size === 0) {
|
||||
if (lqiScanList.size === 0 && rtgScanList.size === 0) {
|
||||
logger.info('Network scan timeout no outstanding requests');
|
||||
} else {
|
||||
logger.warn(`Network scan timeout, skipping outstanding scans for '${[...scanList].join(' ')}'`);
|
||||
logger.warn(`Network scan timeout, skipping outstanding lqi scans for '${[...lqiScanList].join(' ')}'`);
|
||||
logger.warn(`Network scan timeout, skipping outstanding rtg scans for '${[...rtgScanList].join(' ')}'`);
|
||||
// Clear remaining devices so they don't process when/if they eventually complete
|
||||
scanList.clear();
|
||||
logger.debug(`Link map (timeout): %j`, linkMap);
|
||||
linkMap.sort((a, b) => ((a.parent + '|' + a.ieeeAddr) > (b.parent + '|' + b.ieeeAddr)) ? 1
|
||||
: (((b.parent + '|' + b.ieeeAddr) > (a.parent + '|' + a.ieeeAddr)) ? -1 : 0));
|
||||
callback(linkMap);
|
||||
lqiScanList.clear();
|
||||
rtgScanList.clear();
|
||||
collateMap();
|
||||
}
|
||||
}, scanList.size * 1000);
|
||||
}, lqiScanList.size * 1000);
|
||||
}
|
||||
|
||||
getEndpoint(ieeeAddr, ep) {
|
||||
|
||||
Reference in new issue
Block a user