Zigbee2mqtt network map

Python and python framework

Moderator: leecollings

Post Reply
peerkersezuuker
Posts: 70
Joined: Monday 14 December 2015 22:16
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Mierlo
Contact:

Zigbee2mqtt network map

Post by peerkersezuuker »

Hi,
Don't know if someone did this before but I wanted to visualize my zigbee network map from within domoticz.
After some digging around I found : https://community.openhab.org/t/zigbee2 ... p/57784/29
It looked realy nice, and i wanted to implement this in my domoticz environement.
So i wrote a little python script to make this possible.

Prerequisites:
Graphviz installed (sudo apt-get install graphviz)
Graphviz dev files installed (sudo apt-get install -y graphviz-dev)
Python module : Paho mqtt client (pip3 install paho-mqtt)

you need an web server to display the map.
I used the default from domoticz (/domoticz/www) because it is already available, but any other will do.

First place the following files into the web root folder :
https://github.com/ariutta/svg-pan-zoom ... oom.min.js
(you can download it with

Code: Select all

wget https://github.com/ariutta/svg-pan-zoom/blob/master/dist/svg-pan-zoom.min.js
and move it to the web root folder)
This is needed so the generated svg file can be zoomed in/out from the browser.

The create a html file in the web root folder (e.g. ZigBee.html) with the following content :
Spoiler: show

Code: Select all

<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>
Then create a python script with the following code :
Spoiler: show

Code: Select all

#!/usr/bin/python3
import os
import sys
import paho.mqtt.client as mqtt
import fileinput
import shutil

# Prerequisites:
# Graphviz (sudo apt-get install graphviz)
# Graphviz dev files (sudo apt-get install -y graphviz-dev)
# Paho mqtt client (pip3 install paho-mqtt)

# Settings for MQTT server
mqttserver = "192.168.0.31"
mqttserver_port = 1883

# File references
dotfile = "/tmp/zigbee.dot"
svgfile = "/tmp/zigbee.svg"
target_svgfile = "/home/pi/domoticz/www/zigbee.svg"

def on_connect(client, userdata, flags, rc):
    print("Connected With Result Code: {}".format(rc))

def on_disconnect(client, userdata, rc):
    print("Client Got Disconnected")

def on_message(client, userdata, message):
    print("Message Recieved: "+message.payload.decode())
    if os.path.exists(dotfile):
        os.remove(dotfile)
    file_with_data = open(dotfile,"w+")
    file_with_data.write(message.payload.decode())
    file_with_data.close()
    client.disconnect()


client = mqtt.Client()
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
client.connect(mqttserver,mqttserver_port,60)
client.subscribe("zigbee2mqtt/bridge/networkmap/graphviz")
client.publish("zigbee2mqtt/bridge/networkmap", "graphviz")

client.loop_forever() # Wait until data received, the on_message function wil handle the output and disconnect from MQTT broker

# Modify the dot file
# Firt lines a little thicker
with fileinput.FileInput(dotfile, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace("penwidth=0.5", "penwidth=3.5"), end='')

#generate svg file from dot source
command = "/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
print(command)
os.system(command)

#copy the new svg file to the webroot folder
if os.path.exists(target_svgfile):
     os.remove(target_svgfile)
shutil.copyfile(svgfile, target_svgfile)
Adjust the MQTT server settings !!!
Adjust if needed the File References settings.

Schedule the python script to run e.g. every day, (after running refresh your browser cache, as I noticed the page does not update automatically)

After running the script you can go to your domoticz url with the "ZigBee.html" in the address.
e.g. http://domoticz_server_ip:port_number/ZigBee.html

Image

What it does :
The script connects to the mqtt server and issue's two commands
An subscribe to the "zigbee2mqtt/bridge/networkmap/graphviz" topic and a publish to the "zigbee2mqtt/bridge/networkmap", "graphviz"" topic
The "client.loop_forever() is needed to wait for the mqtt server to respond with a message, because the subscribe/publish command need a little while to complete. It is basically an command to the sniffer to poll it's network and report the connections back.

This should not be done very frequently because it could congest your ZigBee network for a little while (especially in large networks with a lot of polling requests to do)

When a message is received (the data for the dot file) it wil be send to the dotfile.
This is the structure needed for graphviz to create a SVG file.

The the svg file is created with the "sfdp" command and placed into the web root folder.

Any suggestions and/or improvements are welcome.

(The next step is to replace the blocks with nice graphic/images but first I have to read in to the graphviz dot language....)

Regards
Peer
Lokonli
Posts: 2296
Joined: Monday 29 August 2016 22:40
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Zigbee2mqtt network map

Post by Lokonli »

Some time ago I made a little tool to display the zigbee2MQTT network map as well.

See https://github.com/lokonli/z2mvis


Sent from my SM-A320FL using Tapatalk

Post Reply