How to visualize the status of Zigbee devices in Openhab App / sitemap via webview

This is my solution how to visualize the status (Online / Offline) of zigbee devices in OpenHAB Android / iOS app by integrating a webview element in my sitemap.

The Rule uses Rest API to query information about devices belonging to a specific zigbee coordinator. You do not need to specifiy your devices, everything is being collected automatically. You only need to insert the UID of your zigbee coordinator in the .rules file.


  • This only works for zigbee binding, not for zigbee2mqtt!
  • It can be useful to monitor devices that may periodically fail (e.g. Xiaomi sensors) or devices that might have range issues.
  • This can also be a starting point to query other information about the devices (e.g. link quality, power level, …).

How the result will look like in OpenhHAB App:

How to set up

  1. Create a .rules-File in your rules-directory and copy/paste the content below.

  2. At the very beginning of the rule, adjust the string “Coordinator” to the UID of your zigbee coordinator. You can find this UID e.g. in Paper UI: Screenshot_20200102_180336
    You may also want to adjust the trigger of the rule. It is configured to run every ten minutes, of course this can be changed.

  3. Include the ZigbeeStatus.html file in your sitemap by using a webview element:

Text label="Zigbee Status" icon="text" {
    Webview url="static/ZigbeeStatus.html"

The url “static/ZigbeeStatus.html” without IP-adress/hostname works fine for me for the OpenHAB Android app (local access or remote access via OpenHAB cloud). You may need to adjust the URL to get it working in a browser.

Now here is the Rule:

rule "Zigbee Status"
                //Rule will run every 10 minutes
                Time cron "0 0/10 * 1/1 * ? *"
                //Edit your coordiantor UID
                var String Coordinator = "zigbee:coordinator_ember:013827EC"

                //Process coordinator information
                var String url = String::format("", Coordinator)
                var String json = sendHttpGetRequest(url)
                var String sLabelCoordinator = transform("JSONPATH", "$.label", json)
                var String sStatusCoordinator = transform("JSONPATH", "$.statusInfo.status", json)

                //Build coordinator HTML table rows
                var String sTableCoordinator = "<tr><td>" + sLabelCoordinator + "</td><td>"
                if (sStatusCoordinator == "ONLINE") {
                        sTableCoordinator += "<font color=\"green\">"
                } else if (sStatusCoordinator == "OFFLINE") {
                        sTableCoordinator += "<font color=\"red\">"
                } else {
                        sTableCoordinator += "<font color=\"grey\">"
                sTableCoordinator += sStatusCoordinator + "</td></tr>"

                //Process nodes / devices
                url =""
                json = sendHttpGetRequest(url)
                var String sDevices = transform("JSONPATH", "$[?(@.bridgeUID == '" + Coordinator +"')].UID", json)
                var Number nDevices = Integer::parseInt(transform("JSONPATH", "$.length()", sDevices))

                //Only for debugging
                //logInfo("Rules", "STemp: {}", sDevices)
                //logInfo("Rules", "Length: {}", nDevices)

                //Build node HTML table rows
                var Number i = 0
                var String sTable = ""

                while (i < nDevices) {

                        var String sTemp = transform("JSONPATH", "$[" + i.toString  +"]", sDevices)
                        var String sLabel =  transform("JSONPATH", "$[?(@.UID == '" + sTemp + "')].label", json)
                        var String sStatus = transform("JSONPATH", "$[?(@.UID == '" + sTemp + "')].statusInfo.status", json)

                        sTable += "<tr><td>" + sLabel + "</td><td>"
                        if (sStatus == "ONLINE") {
                                sTable += "<font color=\"green\">"
                        } else if (sStatus == "OFFLINE") {
                                sTable += "<font color=\"red\">"
                        } else {
                                sTable += "<font color=\"grey\">"
                        sTable += sStatus + "</td></tr>"

                        //Only for debugging
                        //logInfo("Rules", "i: {}", i)
                        //logInfo("Rules", "sLabel: {}", sLabel)
                        //logInfo("Rules", "sStatus: {}", sStatus)

                        i += 1

                //Create html content
                var sHTML = "<html><body><table style=\"width:100%\"><tr><th style=\"text-align:left\">Coordinator</th><th style=\"text-align:left;width:80px\">Status</th></tr>" + sTableCoordinator + "</table><br><table style=\"width:100%\"><tr><th style=\"text-align:left\">Node</th><th style=\"text-align:left;width:80px\">Status</th></tr>" + sTable + "</table><br>Total Nodes: " + nDevices.toString + "</body></html>"

                //Write file to disc
                var sCommand = "/bin/sh@@-c@@(echo '"+ sHTML + "' > /etc/openhab2/html/ZigbeeStatus.html) >/dev/null 2>&1; echo $?"
                var String sResult = executeCommandLine(sCommand, 5000)

                //Only for debugging
                //logInfo("Rules", "Exec Result: {}", sResult)

                //Log write error
                if (sResult != "0") {
                        logError("Rules", "Error writing Zigbee Status HTML-File. Please check permissions!")

The rule will create the file “ZigbeeStatus.html” in the folder “/etc/openhab2/html/”. If you adjust the path, just make sure the user “openhab” has write access to this folder.

Have fun!


zigbee2mqtt provides a LWT topic which can be used for this purpose

Just wanted to make clear what this rule does. :slight_smile: But of course it should also be possible to build something similar for zigbee2mqtt.

as a heads-up: if your OH http port isn’t 8080 you will need to adjust this too

Hi, this is perfect for what i’m looking to do for my new Zigbee items and was looking to add this to OH3.2. Code does not work directly as is. Has anyone converted this to OH3?