One feature I absolutely love in Zigbee2MQTT is the network map. You can request zigbee2mqtt to put out a Graphviz representation of how your ZigBee network is set up. That way you can easily tell which of your devices are connected / paired to which and how big your ZigBee network grew over time.
It also will help you understand that with each non-battery powered ZigBee device your network will be more stable and allow for even more endpoints. It’s important to know that there are 3 types of ZigBee devices:
- Coordinators
- Routers
- End Devices
Routers are ZigBee devices that End Devices can be paired to and that will route communications to other ZigBee devices. In order to do this they will have to be always on and can’t be in Standby. Therefore battery-driven sensors can not be routers! All mains powered devices though should be routers (e.g. bulbs, power plugs etc). Coordinators are routers that have one additional feature: they span the network and define all the network parameters. There can only be ONE coordinator per ZigBee network. This will be your XBee, CC2531, Qivicon etc stick. Routers/coordinators can be paired with a given number of ZigBee devices (for the CC2531 there is a limit of roughly 20). End Devices are all sensors that are low-energy and battery-driven (e.g. door sensors, temperature sensors). They will go to standby/sleep every now and then and will only sporadically send data. This is normal in order to save energy.
If you understand this concept it is clear that a ZigBee network can grow much bigger than what your coordinator is limited to. Each router will up the number of possible devices.
But back to topic…
Prerequisites
You will need to render GraphViz data so install graphviz via:
sudo apt-get install graphviz
You will also need to check your permissions for the 2 files zigbee.dot and zigbee.svg in the html folder. Those files need to be writeable for user openhab.
Last thing you will need is the great JavaScript library svg-pan.zoom by aruitta. It will allow you to zoom and pan the generated network map. Download it here:
/etc/openhab2/html/zigbee.map
This is a mapping file and will allow the rule below to replace network addresses with names. You can do this in zigbee2mqtt but you would have to do it again if you re-paired devices. I like to have this mapping in a separate file. You can use an empty file if you don’t want to replace anything. Otherwise define it like this:
0x000b14eacc194ff0=Dimmer Living Room
0x000b32add31850f=Dimmer Kitchen
If you’re paranoid don’t put this file into the html folder as it will be exposed by the web server. If you chose to place it in another place you will have to customize the rules file below.
Items
String zigbee_NetworkMap { mqtt="<[broker:zigbee/bridge/networkmap/graphviz:state:default" }
Group zigbee_NetworkMap_Webview "ZigBee Topologie"
Sitemap
This webview item will display the HTML file below.
Group item=zigbee_NetworkMap_Webview {
Webview url="/static/zigbee.html" height=16 icon="network"
}
Rules
This is were the heavy lifting is done. There are 2 rules. One is periodically requesting zigbee2mqtt for the network map. I do this once at night. The second rule will fire when the network map in Graphviz format has been sent by zigbee2mqtt. It will then replace all network addresses with nice display names from zigbee.map and also render the data into a SVG file. There are a lot of layout options that I chose fit my style. Feel free to modify this through the sfdp parameters.
import java.io.FileWriter
import java.io.FileReader
import java.io.BufferedReader
// parameters
val String dotFile = "/etc/openhab2/html/zigbee.dot"
val String mapFile = "/etc/openhab2/html/zigbee.map"
val String svgFile = "/etc/openhab2/html/zigbee.svg"
rule "Request ZigBee Network Map in Graphviz format"
when
Time cron "0 0 4 * * ?"
then
// ask zigbee2mqtt to generate graphviz network map (in DOT format)
publish("broker", "zigbee2mqtt/bridge/networkmap", "graphviz")
end
rule "Fetch ZigBee tree in Graphviz format"
when
Item zigbee_NetworkMap changed
then
// once zigbee2mqtt sent graphviz network map => store it and convert it to PNG/SVG
if (zigbee_NetworkMap.state !== NULL && zigbee_NetworkMap.state != "") {
var String dotString = zigbee_NetworkMap.state.toString
// load mapping file and regex-replace network addresses with friendly names
var FileReader fr = new FileReader(mapFile);
var BufferedReader br = new BufferedReader(fr);
var String line
var String[] split
var String regex
var String replace
while ((line = br.readLine()) !== null) {
split = line.split("=")
if(split.length == 2) {
regex = "(label=.*)(" + split.get(0) + ")(.*)"
replace = "$1" + split.get(1) + "$3"
dotString = dotString.replaceFirst(regex, replace)
}
}
fr.close();
// store result to DOT file
var fw = new FileWriter(dotFile, false);
fw.write(dotString);
fw.flush();
fw.close();
// render PNG/SVG
executeCommandLine("/usr/bin/sfdp -Nfontname=Arial -Nfontsize=9 -Ncolor=#666666 -Nstyle=filled -Nfillcolor=#eeeeee -Efontname=Arial -Efontsize=8 -Efontcolor=#cc0000 -Ecolor=#cccccc -Tsvg -o" + svgFile + " " + dotFile, 5000)
}
end
Attention: Customize the 2 parameters for publish command in the 1st rule to reflect the name of your defined MQTT broker and the MQTT topic zigbee2mqtt uses.
Static HTML page (/etc/openhab2/html/zigbee.html)
This is a simple wrapper HTML file that embeds the rendered SVG file and also loads a JavaScript library to pan and zoom into the graph (it can be quite big!).
<html>
<head>
<script src="svg-pan-zoom.min.js"></script>
</head>
<body style="margin: 0; padding: 0">
<embed type="image/svg+xml" src="zigbee.svg" id="map" width="100%" height="100%"/>
<script language="JavaScript">
document.getElementById('map').addEventListener('load', function(){
// Will get called after embed element was loaded
svgPanZoom(document.getElementById('map'), {
controlIconsEnabled: true
});
})
var panZoomMap = svgPanZoom('#map');
</script>
</body>
</html>