Live Zigbee2MQTT link quality on a MainUI floor plan, generated, no YAML editing

When a Zigbee device drops off or reacts slowly, the first question is usually: how good is its radio link, and where in the house is the mesh weak? Zigbee2MQTT has a network map, but it shows a graph, not your rooms. I wanted the answer on my floor plan, live, with one tap.

Easy to setup yourself

zigbee-radio-map

(Demo floor plan from the openHAB demo instance, real devices of mine placed on it.)

What it does

  • One marker per Zigbee2MQTT device on your floor plan image. Colour = LQI of the last hop: red at 30 or less, yellow at 75, green at 120 or more, smooth in between. White = no value yet, grey = offline, pale = older than the current live session. Routers and end devices have different icons; tap a marker for name, LQI and age.
  • A Live button on the page. Live switches itself off after 15 minutes (configurable). Outside live nothing is written, so the page simply shows the last values.
  • Routers with a state (plugs, lights) are asked for it when live starts, so they report within seconds. Sleeping end devices show up as soon as they send something anyway.

You don’t write YAML

The repo contains generator.html, a single HTML file that runs offline in your browser (nothing is sent anywhere). You paste the device list (zigbee2mqtt/bridge/devices, or simply one name per line), pick your floor plan image (only its size is read) and get:

  1. the two MQTT trigger channels to add to a broker thing,
  2. the rule (paste into a new rule’s code tab, run once: it creates its two items itself),
  3. the page (paste into a new floor plan page’s code tab).

Then drag the markers to their rooms in the page editor. Adding a device later: copy a marker, type the device name into “name”, done. Every marker is the same; it reads its device from its own name.

How it works

  • Two Publish Trigger channels on an MQTT broker thing (<base>/+ and <base>/+/availability) feed one JavaScript rule.
  • The rule keeps LQI, availability and timestamp per device and writes them as one compact JSON text into a String item, at most once per second during live.
  • The page’s markers read that item with MainUI expressions; no item per device.
  • Recommended: a second broker thing used only for the map. The rule enables it when live starts and disables it afterwards, so outside live there is no extra event and no events.log line at all. (The quick start with the channels on your main broker thing works too, but then every Zigbee2MQTT message is a trigger event.)
  • Tip: exclude the two items from persistence (!ZigbeeMap_Live, !ZigbeeMap_Data).

Requirements

  • openHAB 5.1 or newer (tested on 5.1.4), JS Scripting add-on, MQTT binding
  • Zigbee2MQTT on the same broker (default output mode json or attribute_and_json)

Demo without Zigbee

demo/ has a rule and a page with invented devices on the openHAB demo floor plan. The rule feeds simulated messages through the same code, no MQTT needed, if you just want to see it.

Download

Full install steps, limits and uninstall are in the README. Licence: EPL-2.0, the same as openHAB.

Limits

  • LQI is the quality of the last hop only (device to its parent router or the coordinator), not of the whole path.
  • Device names containing / need an extra channel.
  • Retained MQTT messages count as fresh values when live starts.

Feedback welcome, especially from setups other than mine (other openHAB versions, many more devices, the quick-start path).