Skip to content

Instantly share code, notes, and snippets.

@b2un0
Last active September 20, 2025 09:53
Show Gist options
  • Save b2un0/bce147fecca8e4fc3df7acbf1d8119eb to your computer and use it in GitHub Desktop.
Save b2un0/bce147fecca8e4fc3df7acbf1d8119eb to your computer and use it in GitHub Desktop.
zigbee2mqtt cleanup stale devices (nvram / trust center full)
#!/usr/bin/env bash
set -euo pipefail
# --- inputs in current directory ---
DB="database.db" # Zigbee2MQTT JSONL database
BACKUP="coordinator_backup.json" # coordinator backup JSON
CLEANED="z2m_coordinator_backup.cleaned.json"
# -----------------------------------
# sanity checks
[[ -f "$DB" ]] || { echo "missing $DB"; exit 1; }
[[ -f "$BACKUP" ]] || { echo "missing $BACKUP"; exit 1; }
# 1) extract IEEE from Z2M DB (lowercase, without 0x)
jq -r 'select(.ieeeAddr!=null) | .ieeeAddr | ascii_downcase | sub("^0x";"")' \
"$DB" | sort -u > z2m_db_ieee.txt
# 2) extract IEEE from coordinator backup (lowercase, already without 0x)
jq -r '.devices[]? | .ieee_address // empty | ascii_downcase' \
"$BACKUP" | sort -u > z2m_backup_ieee.txt
# 3) diff lists
comm -23 z2m_backup_ieee.txt z2m_db_ieee.txt > z2m_stale_on_coord.txt
comm -13 z2m_backup_ieee.txt z2m_db_ieee.txt > z2m_missing_in_backup.txt
# 4) build cleaned backup that keeps only devices present in DB
jq --rawfile keep z2m_db_ieee.txt '
($keep | split("\n") | map(select(length>0)) | unique) as $keep
| .devices = (.devices // [] | map(select((.ieee_address // "" | ascii_downcase) as $ieee | ($keep | index($ieee)))))
' "$BACKUP" > "$CLEANED"
# 5) show before/after device counts
before=$(jq '.devices|length' "$BACKUP")
after=$(jq '.devices|length' "$CLEANED")
echo "stale_on_coord: $(wc -l < z2m_stale_on_coord.txt)"
echo "missing_in_backup:$(wc -l < z2m_missing_in_backup.txt)"
echo "devices before: $before"
echo "devices after: $after"
echo "cleaned backup written to: $CLEANED"
#!/usr/bin/env bash
set -euo pipefail
# --- user settings ---
CONTAINER="zigbee2mqtt" # docker container name
DEV="/dev/serial/by-id/usb-Silicon_Labs_Sonoff_Zigbee_3.0_USB_Dongle_Plus_0001-if00-port0" # coordinator serial
DATA_DIR="/apps/zigbee2mqtt/data" # Z2M data folder
CLEANED="${DATA_DIR}/coordinator_backup.cleaned.json" # cleaned backup produced earlier
TARGET="${DATA_DIR}/coordinator_backup.json" # file Z2M restores from
# ----------------------
# sanity checks
[[ -r "$CLEANED" ]] || { echo "cleaned backup not found: $CLEANED"; exit 1; }
[[ -e "$DEV" ]] || { echo "serial device not found: $DEV"; exit 1; }
# stop Z2M so the serial port is free
echo "Stopping container ${CONTAINER} ..."
docker stop "$CONTAINER" >/dev/null
# create throwaway venv for zigpy-znp
VENV="$(mktemp -d)"
python3 -m venv "$VENV"
# shellcheck disable=SC1090
source "$VENV/bin/activate"
pip install --upgrade --quiet pip zigpy-znp
# reset coordinator NVRAM
echo "Resetting NVRAM on ${DEV} ..."
python -m zigpy_znp.tools.nvram_reset "$DEV"
# leave and remove venv
deactivate
rm -rf "$VENV"
# backup current coordinator_backup.json if present
if [[ -f "$TARGET" ]]; then
cp -a "$TARGET" "${TARGET}.bak.$(date +%Y%m%d-%H%M%S)"
echo "Existing ${TARGET} backed up"
fi
# place cleaned backup as the restore source
cp -f "$CLEANED" "$TARGET"
echo "Placed cleaned backup at ${TARGET}"
# start Z2M so it restores onto an empty NVRAM
echo "Starting container ${CONTAINER} ..."
docker start "$CONTAINER" >/dev/null
echo "Done"
echo "Watch the Zigbee2MQTT logs for 'Restored network from coordinator_backup.json'"
@b2un0
Copy link
Author

b2un0 commented Sep 12, 2025

@Mrsash2020
Copy link

I have this issue with mine. How do you use this? I have home assistant on VMware.

@b2un0
Copy link
Author

b2un0 commented Sep 20, 2025

I cant help you with VMware.

Write down your Environment to an AI of your Choice and paste the link to this gist too.

@Mrsash2020
Copy link

Thanks that helped me action it in terminal with AI help ...... but my problem still remains. I am thinking its this one device I have that is the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment