Raspberry Pi Zero W jako bridge Zigbee

Materiał przygotowany z pomocą AI

Lutowanie, programowanie i ogólnie hobbystyczne zajmowanie się elektroniką jest super. Od kilku lat mam małe czujniki do zbierania podstawowych danych środowiskowych, które działają gdzieś porozrzucane po mieszkaniu. Problem z nimi jest taki, że jest to zazwyczaj oparte o płytki stykowe, plątaninę przewodów i esp32 lub Raspberry Pi Pico. Generalnie — łatwo o przerwanie połączeń np. przy przenoszeniu. Niedawno pojawiła się u mnie potrzeba rozpoczęcia zbierania takich danych poza domem i musiałem zdecydować się na bezpieczniejsze i bardziej estetczne rozwiązanie. Żeby jednak nie było zbyt łatwo to zacząłem od zamówienia złej wersji Rpi Zero zdecydowałem się na combo Rpi Zero WH (pierwsza wersja) + bramka Sonoff MG24 + czujniki Sonoff SNZB-02D oraz SNZB-02P.

Dlaczego tak? Raspberry jest tanie i mogę później wykorzystać do innych projektów (byłoby na pewno łatwiej, gdybym zamówił wersję 2!), dongle Sonoffa może działajać jako bramka dla Zigbee i nowszego Matter/Thread. Czujniki Sonoff też cenowo są bardzo przystępne i mam gwarancję, że będą dobrze komunikować się ze swoją bramką.

Taki setup, działa, ale wymaga świadomego doboru wersji oprogramowania. Pi Zero W to platforma armv6, którą Node.js oficjalnie porzucił.

Wymagany sprzęt i punkt wyjścia

  • Raspberry Pi Zero W (lub WH) z micro-USB OTG
  • Sonoff Zigbee 3.0 USB Dongle Plus MG24
  • Czujniki Zigbee (na przykład Sonoff SNZB-02P/SNZB-02D)
  • Dostęp SSH do Pi po zainstalowanym systemie

Na Pi działa Raspberry Pi OS Lite Bullseye (bo nowsze Rapberry PI OS nie hulają) ze skonfigurowanym SSH i WiFi.

Dlaczego Bullseye?

Bookworm i nowsze wersje domyślnie używają NetworkManager do zarządzania siecią, co w trybie headless powoduje, że konfiguracja WiFi w wpa_supplicant.conf z karty SD nie jest automatycznie respektowana. Bullseye zachowuje klasyczny dhcpcd + wpa_supplicant i było mi łatwiej skonfigurować połączenie w ten sposób.

Start

Zaczynamy od aktualizacji pakietów przed rozpoczęciem pracy:

sudo apt update
sudo apt upgrade -y
sudo reboot

Identyfikacja dongle’a w systemie

Po wpięciu dongle’a do portu USB Pi Zero, sprawdzamy, że został wykryty:

lsusb

U mnie dongle pojawia sie jako `Silicon Labs CP210x UART Bridge. Następnie sprawdzamy logi kernela:

dmesg | grep -i -E 'usb|tty|cp210' | tail -20

Kluczowy fragment:

usb 1-1: Product: SONOFF Dongle Plus MG24
usb 1-1: Manufacturer: SONOFF
cp210x converter detected
usb 1-1: cp210x converter now attached to ttyUSB0

MG24 używa CP210x jako mostka USB-UART, dlatego wystawia się jako /dev/ttyUSB0, a nie /dev/ttyACM0.

Stabilna nazwa urządzenia

/dev/ttyUSB0 to nazwa „kto pierwszy ten lepszy” — przy ponownej enumeracji USB albo dopięciu drugiego adaptera może zmienić numer. Dlatego do konfiguracji Z2M używamy stabilnej ścieżki z /dev/serial/by-id/:

ls -la /dev/serial/by-id/

Output będzie zawierał coś w stylu:

usb-SONOFF_SONOFF_Dongle_Plus_MG24_<DONGLE_SERIAL>-if00-port0 -> ../../ttyUSB0

Tę pełną ścieżkę zachowujemy — pojawi się w configuration.yaml Z2M.

Uprawnienia do portu szeregowego

Standardowo /dev/ttyUSB* ma grupę dialout. Użytkownik pi zwykle już jest jej członkiem, ale warto zweryfikować:

groups
ls -l /dev/ttyUSB0

Jeśli dialout nie ma na liście grup użytkownika:

sudo usermod -aG dialout $USER

Przygotowanie systemu — swap i aktualizacje

Domyślny swap na Raspberry Pi OS to 100 MB. Dla instalacji Z2M to za mało — kompilacja natywnych modułów potrafi zjeść więcej. Zwiększamy do 1 GB.

sudo dphys-swapfile swapoff
sudo nano /etc/dphys-swapfile

Zmieniamy jedną linię na:

CONF_SWAPSIZE=1024

Aktywujemy nowy rozmiar:

sudo dphys-swapfile setup
sudo dphys-swapfile swapon
free -h

Wyjście free -h powinno pokazać Swap: 1.0Gi.

Trwałość karty SD

Intensywne pisanie do swap zużywa karty. Po zakończonej instalacji warto rozważyć powrót do mniejszego rozmiaru, jeśli normalna praca Z2M nie wykorzystuje swapu. Jednorazowy build to akceptowalny narzut, ale ciągłe swapowanie w runtime byłoby sygnałem ostrzegawczym.

Mosquitto — lokalny broker MQTT

Z2M musi gdzieś publikować dane. Najprostsza konfiguracja na początek to broker na localhost — bez autentykacji, bez TLS, słuchający tylko na pętli zwrotnej.

sudo apt install -y mosquitto mosquitto-clients

Mosquitto na Debianie domyślnie nie zezwala na połączenia anonimowe i nie nasłuchuje na żadnym porcie poza Unix socketem. Trzeba dodać własną konfigurację:

sudo nano /etc/mosquitto/conf.d/local.conf

Treść:

listener 1883 localhost
allow_anonymous true

Restart i weryfikacja:

sudo systemctl restart mosquitto
systemctl status mosquitto

Test pub/sub

W jednym terminalu (subscriber):

mosquitto_sub -h localhost -t 'test/#' -v

W drugim (publisher):

mosquitto_pub -h localhost -t 'test/hello' -m 'works'

Subscriber powinien wyświetlić:

test/hello works

Świadomy kompromis bezpieczeństwa

Anonymous + listener na localhost to akceptowalne uproszczenie na czas testów i konfiguracji.

Node.js 18 dla armv6

Node.js oficjalnie nie wspiera armv6 od wersji 12. Dla nowszych wersji istnieją „unofficial builds” pod adresem unofficial-builds.nodejs.org. Pobieramy Node 18.20.4:

cd ~
wget https://unofficial-builds.nodejs.org/download/release/v18.20.4/node-v18.20.4-linux-armv6l.tar.xz
ls -lh node-v18.20.4-linux-armv6l.tar.xz

Plik powinien mieć ~22 MB.

Wypakowujemy i instalujemy do /usr/local:

tar -xJf node-v18.20.4-linux-armv6l.tar.xz
sudo cp -R node-v18.20.4-linux-armv6l/* /usr/local/
rm -rf node-v18.20.4-linux-armv6l node-v18.20.4-linux-armv6l.tar.xz

Weryfikacja:

node --version    # v18.20.4
npm --version     # 10.7.0
which node        # /usr/local/bin/node

Dlaczego konkretnie 18.20.4, a nie nowsze

Binarki Node 20+ z unofficial-builds są kompilowane toolchainem GCC 12 na Ubuntu 22.04 i wymagają GLIBCXX_3.4.30. Bullseye ma maksymalnie GLIBCXX_3.4.28, więc nowszy Node nie wystartuje (libstdc++.so.6: version 'GLIBCXX_3.4.30' not found). Node 18 jest ostatnią linią skompilowaną starszym toolchainem zgodnym z Bullseye.

Zigbee2MQTT 1.42 — instalacja

Z2M w wersji 2.x wymaga Node 20+, więc dla naszego stacku z Node 18 instalujemy ostatnią wersję linii 1.x — 1.42.0.

Najpierw narzędzia build (powinny być domyślnie zainstalowane, ale warto się upewnić):

sudo apt install -y git make g++ gcc

Klonujemy repozytorium do /opt/zigbee2mqtt na konkretny tag:

sudo mkdir -p /opt/zigbee2mqtt
sudo chown -R $USER:$USER /opt/zigbee2mqtt
cd /opt/zigbee2mqtt
git clone --depth 1 --branch 1.42.0 https://github.com/Koenkk/zigbee2mqtt.git .

Weryfikacja:

git tag --points-at HEAD    # 1.42.0
grep -A 3 '"engines"' package.json

Pole engines powinno zawierać ^18 || ^20 || ^22 || ^23 — czyli Node 18 jest oficjalnie wspierany w tej wersji Z2M.

Instalacja zależności

Z2M 1.x używa zwykłego npm (pnpm to wymóg, który pojawił się dopiero w 2.x). Instalację warto uruchomić w tmux, na wypadek zerwania sesji SSH:

sudo apt install -y tmux
tmux new -s z2m-install
cd /opt/zigbee2mqtt
npm ci

Odpięcie sesji bez przerywania npm ci: Ctrl+B, potem D. Powrót do sesji po ponownym zalogowaniu: tmux attach -t z2m-install.

npm ci zamiast npm install to „clean install” — używa dokładnie wersji z package-lock.json, jest deterministyczne. Na Pi Zero W ten krok zajmuje ~9 minut. W trakcie ściąga około 600 paczek i kompiluje natywne moduły (serialport, bcrypt).

Po skończeniu spodziewamy się komunikatu typu:

added X packages in 9m

X — bo nie pamiętam ile dokładnie tego jest, ale na pewno ponad 600.

Weryfikacja kompilacji

Sprawdzamy, czy główna biblioteka stosu Zigbee została skompilowana:

ls /opt/zigbee2mqtt/node_modules/zigbee-herdsman/dist/
ls /opt/zigbee2mqtt/node_modules/zigbee-herdsman/dist/adapter/

W katalogu adapter/ powinny być podkatalogi: deconz, ember, ezsp, zboss, zigate, z-stack. Dla MG24 kluczowy jest ember — to driver protokołu EmberZNet, którym mówi nasz dongle.

Konfiguracja Z2M

Tworzymy katalog na dane runtime i plik konfiguracyjny:

mkdir -p /opt/zigbee2mqtt/data
nano /opt/zigbee2mqtt/data/configuration.yaml

Treść:

# Integracja z Home Assistant przez MQTT discovery
# Włączymy gdy postawimy HA na osobnej maszynie
homeassistant: false
 
# Domyślnie sieć zamknięta - parowanie przez frontend lub MQTT
permit_join: false
 
# Lokalny broker bez autentykacji
mqtt:
  base_topic: zigbee2mqtt
  server: 'mqtt://localhost:1883'
 
# Stabilna ścieżka do dongle'a + driver ember dla MG24
serial:
  port: /dev/serial/by-id/usb-SONOFF_SONOFF_Dongle_Plus_MG24_<DONGLE_SERIAL>-if00-port0
  adapter: ember
  baudrate: 115200
 
# Network key i PAN ID generowane losowo przy pierwszym starcie
# Po starcie zostaną zapisane w tym pliku - backupować razem z coordinator_backup.json
advanced:
  network_key: GENERATE
  pan_id: GENERATE
  channel: 11
 
# Web UI
frontend:
  enabled: true
  port: 8080
  host: 0.0.0.0

Wybór kanału Zigbee

Kanały Zigbee 11-26 dzielą pasmo 2.4 GHz z WiFi. Warto sprawdzić na których działa okoliczne sieci WiFi.

Co wygenerowane = co backupować

network_key i pan_id po pierwszym starcie zostaną wpisane na sztywno do configuration.yaml. Utrata tego pliku oznacza, że wszystkie sparowane urządzenia trzeba parować od nowa, bo nie będą mogły się skomunikować z nową siecią. Plik data/coordinator_backup.json (powstaje po starcie Z2M) ma podobną wagę.

Pierwszy start Z2M — weryfikacja połączenia z dongle’em

Uruchamiamy Z2M w foreground, żeby zobaczyć każdy krok inicjalizacji:

cd /opt/zigbee2mqtt
npm start

Oczekiwana sekwencja logów:

Starting Zigbee2MQTT version 1.42.0
Starting zigbee-herdsman (2.1.9)
zh:ember: ======== Ember Adapter Starting ========
zh:ember:ezsp: ======== EZSP starting ========
zh:ember:uart:ash: RTS/CTS config is off, enabling software flow control.
zh:ember:uart:ash: Serial port opened
zh:ember:uart:ash: ======== ASH connected ========
zh:ember:ezsp: ======== EZSP started ========
zh:ember: Adapter version info: {"ezsp":13,"revision":"7.4.5 [GA]",...}
zh:ember: [INIT FORM] Forming new network with: {"panId":<NUM>,"radioChannel":11,...}
zh:ember: [INIT FORM] New network formed!
zh:controller: Wrote coordinator backup to '/opt/zigbee2mqtt/data/coordinator_backup.json'
z2m: Coordinator firmware version: '{"meta":{"ezsp":13,"revision":"7.4.5 [GA]",...},"type":"EmberZNet"}'
z2m: Currently 0 devices are joined.
z2m: Connecting to MQTT server at mqtt://localhost:1883
z2m: Connected to MQTT server
z2m: Started frontend on port 0.0.0.0:8080
z2m: Zigbee2MQTT started!

Cały start na Pi Zero W zajmuje dłuższą chwilę. Kluczowe rzeczy do weryfikacji:

  1. EZSP version — driver musi się dogadać z firmware’em dongle’a. Linia Adapter EZSP protocol version (X) lower than Host. Switched. jest OK — driver z Z2M 1.42 zna EZSP 14, MG24 z fabryki ma 13, kompatybilność wstecz działa.
  2. „New network formed” — to się dzieje tylko przy pierwszym starcie, gdy coordinator_backup.json jeszcze nie istnieje. Przy kolejnych startach Z2M wczytuje backup i nie tworzy nowej sieci.
  3. „Connected to MQTT server” — pipeline do Mosquitto działa.

W drugim terminalu można równolegle podglądać MQTT:

mosquitto_sub -h localhost -t 'zigbee2mqtt/#' -v

Po starcie powinny przylecieć:

zigbee2mqtt/bridge/state {"state":"online"}
zigbee2mqtt/bridge/info {...}
zigbee2mqtt/bridge/devices [...]

Frontend dostępny pod http://<HOSTNAME>.local:8080 (Avahi + mDNS) lub — w moim przypadku — http://<TAILSCALE_IP>:8080.

Parowanie pierwszego czujnika

W frontendzie zezwalamy na dołączanie urządzeń — Z2M otwiera sieć. Następnie na czujniku przytrzymujemy przycisk parowania ~5 sekund (procedura zależy od modelu, dla SNZB-02P/02D to długie naciśnięcie aż do szybkiego mrugania LED).

W logu Z2M pojawi się sekwencja:

zigbee2mqtt: Device '<IEEE_ADDR>' joined
zigbee2mqtt: Starting interview of '<IEEE_ADDR>'
zigbee2mqtt: Successfully interviewed '<IEEE_ADDR>', device has successfully been paired

Na MQTT pojawi się event device_interview z pełną definicją modelu (atrybuty, jednostki, opcje), a następnie rzeczywiste pomiary:

zigbee2mqtt/<IEEE_ADDR> {"battery":100,"humidity":46.4,"linkquality":4,"temperature":22.6}

O urządzeniach wcześniej sparowanych z innym hubem

Zigbee przechowuje parametry sieci (network key, PAN ID, kanał) w pamięci flash urządzenia. Po pierwszym starcie nowego koordynatora trzeba zresetować każde urządzenie (długie naciśnięcie przycisku parowania) — wtedy zapomina starą sieć i wchodzi w tryb pairing dla nowej.

Systemd service — autostart

Ręczne uruchamianie Z2M przez npm start nie nadaje się do żadnej innej roli niż weryfikacja, że stack działa. Dla autonomicznego bridge’a potrzebny jest systemd, który uruchomi Z2M przy starcie systemu i wskrzesi w razie czego.

sudo nano /etc/systemd/system/zigbee2mqtt.service

Treść:

[Unit]
Description=zigbee2mqtt
After=network-online.target mosquitto.service
Wants=network-online.target
Requires=mosquitto.service
 
[Service]
ExecStart=/usr/local/bin/node index.js
WorkingDirectory=/opt/zigbee2mqtt
StandardOutput=journal
StandardError=journal
KillSignal=SIGINT
TimeoutStopSec=30
Restart=always
RestartSec=10s
User=pi
Group=pi
IOSchedulingClass=2
IOSchedulingPriority=2
 
[Install]
WantedBy=multi-user.target

Wybrane decyzje konfiguracyjne — dlaczego tak

ExecStart=/usr/local/bin/node index.js zamiast npm start: npm start to wrapper, który spawnuje node jako podproces. Eliminacja warstwy pośredniej daje czystszy proces tree i poprawną propagację sygnałów od systemd do Z2M.

KillSignal=SIGINT zamiast domyślnego SIGTERM: Z2M ma handler clean shutdown podpięty pod SIGINT (ten sam, który dostawał wcześniej przy Ctrl+C). SIGTERM zabija mniej elegancko, bez gwarancji zapisu state.json.

Requires=mosquitto.service (twardo) vs Wants=network-online.target (miękko): Mosquitto musi działać, inaczej Z2M nie ma dokąd publikować. Sieć jest wymagana, ale na Pi Zero W bywa, że WiFi association zajmuje chwilę — twarde wymaganie sieci mogłoby blokować start w nieskończoność.

User=pi: Z2M biega bez uprawnień roota. Użytkownik pi ma dostęp do /dev/ttyUSB0 przez członkostwo w grupie dialout — to wystarczy.

Aktywacja

sudo systemctl daemon-reload
sudo systemctl enable zigbee2mqtt
sudo systemctl start zigbee2mqtt
sudo systemctl status zigbee2mqtt

Status powinien pokazać Active: active (running). Logi w czasie rzeczywistym:

journalctl -u zigbee2mqtt -f

Test autostartu

Najlepsza weryfikacja to twardy reboot:

sudo reboot

Następnie łączymy się ponownie SSH:

sudo systemctl status zigbee2mqtt
journalctl -u zigbee2mqtt -n 30

Jeśli service jest active (running) i ostatnie logi pokazują normalny start (Started Zigbee2MQTT, sparowane urządzenia widoczne w Currently N devices are joined) — autostart działa.

Odczyt danych w Pythonie

Mając Z2M publikujący do MQTT, najprostszy klient do odczytu danych z poziomu Pythona to paho-mqtt:

sudo apt install -y python3-paho-mqtt

Skrypt ~/test_z2m.py:

#!/usr/bin/env python3
"""Prosty odczyt danych z Zigbee2MQTT przez MQTT."""
 
import json
import paho.mqtt.client as mqtt
 
BROKER_HOST = "localhost"
BROKER_PORT = 1883
 
# "+" to single-level wildcard - złapie wszystkie urządzenia,
# pomijając podtopiki bridge/...
TOPIC = "zigbee2mqtt/+"
 
 
def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print(f"Połączono z brokerem MQTT na {BROKER_HOST}:{BROKER_PORT}")
        client.subscribe(TOPIC)
        print(f"Subskrybuję topic: {TOPIC}")
    else:
        print(f"Błąd połączenia, kod: {rc}")
 
 
def on_message(client, userdata, msg):
    topic = msg.topic
 
    # Pomijamy wiadomości od bridge'a (info systemowe)
    if "/bridge/" in topic:
        return
 
    try:
        payload = json.loads(msg.payload.decode())
        device = topic.split("/")[-1]
        print(f"\n--- {device} ---")
        for key, value in payload.items():
            print(f"  {key}: {value}")
    except json.JSONDecodeError:
        pass
 
 
def main():
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
 
    print("Łączenie z brokerem MQTT...")
    client.connect(BROKER_HOST, BROKER_PORT, 60)
 
    print("Wejście w pętlę odczytu (Ctrl+C aby zakończyć)\n")
    try:
        client.loop_forever()
    except KeyboardInterrupt:
        print("\nZakończono przez użytkownika.")
    finally:
        client.disconnect()
 
 
if __name__ == "__main__":
    main()

Uruchomienie:

chmod +x ~/test_z2m.py
python3 ~/test_z2m.py

Czujniki Zigbee z baterią raportują rzadko — kilka razy na godzinę albo gdy wartość zmienia się znacząco (chyba, że użytkownik zmieni reguły). Krótkie naciśnięcie przycisku zwykle wybudza urządzenie i wymusza natychmiastowy raport.

Co warto zabezpieczyć przed wdrożeniem produkcyjnym

Powyższy setup działa, ale przed wpięciem Pi do sieci, której nie kontrolujemy administracyjnie, warto domknąć kilka rzeczy.

SSH password authentication: po zweryfikowaniu, że logowanie kluczem działa, wyłączyć PasswordAuthentication:

sudo nano /etc/ssh/sshd_config
# zmień: PasswordAuthentication no
sudo systemctl restart ssh

Krytyczne ostrzeżenie

Zanim restartujesz ssh, upewnij się w nowym oknie SSH, że logowanie kluczem działa. Restart bez tej weryfikacji może zostawić Cię odciętym od urządzenia.

Wiele sieci WiFi w wpa_supplicant.conf: jeśli Pi ma trafić w miejsce, gdzie będzie mieć dostęp do 2 lub więcej sieci, można wpisać kilka możliwości połączeń z priorytetami:

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
country=PL
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="<SIEC_DOMOWA>"
    psk=<HASH_Z_WPA_PASSPHRASE>
    priority=10
}

network={
    ssid="<HOTSPOT_AWARYJNY>"
    psk=<HASH_Z_WPA_PASSPHRASE>
    priority=5
}

Hashe PSK generujemy przez wpa_passphrase <SSID> <hasło> zamiast trzymać hasła jako otwart tekst.

Backup plików stanu Z2M: pliki, których utrata wymusi parowanie wszystkich urządzeń od nowa:

ls -la /opt/zigbee2mqtt/data/
# configuration.yaml
# coordinator_backup.json
# database.db
# state.json

Skopiowanie ich poza Pi zajmuje minutę i zaoszczędza czas na rekonfiguracji.

Tailscale dla zdalnego dostępu: gdy Pi jest w sieci, której nie kontrolujemy, Tailscale daje stabilny dostęp SSH i do frontend Z2M (port 8080) bez konieczności port forwarding’u. Instalacja:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
sudo systemctl enable tailscaled

W panelu administracyjnym Tailscale warto wyłączyć key expiry dla tego węzła — Pi może być fizycznie niedostępny, gdy klucz wygaśnie.

Logi i diagnostyka

Z2M zapisuje logi w dwóch miejscach jednocześnie: do journala systemd (przez StandardOutput=journal) oraz do plików w /opt/zigbee2mqtt/data/log/<timestamp>/log.log. To daje redundancję, ale podwaja zapisy na kartę SD.

Wyłączenie zapisu do plików (zostaje tylko journal):

# w configuration.yaml
advanced:
  log_output:
    - console

Po tej zmianie wszystkie logi czyta się przez:

journalctl -u zigbee2mqtt -f             # live tail
journalctl -u zigbee2mqtt -n 100         # ostatnie 100 linii
journalctl -u zigbee2mqtt --since '1 hour ago'

Ograniczenia tego setupu

Z2M 1.42 nie dostaje już aktualizacji. Linia 1.x została zamknięta wraz z wydaniem 2.0.0. Nowe device converters, fixy bezpieczeństwa, integracje z nowszymi standardami (Matter over Thread) trafiają tylko do 2.x. Setup opisany powyżej jest stabilny, ale technologicznie zamrożony.

Node 18 jest end-of-life od kwietnia 2025. Nie dostaje już patchy bezpieczeństwa. To akceptowalne dla bridge’a w kontrolowanej sieci, ale nie ideał dla setupu z dłuższym horyzontem.

Pi Zero W ma 512 MB RAM. Z2M w runtime używa ~150-200 MB, system bazowy kolejne 100-150 MB. Margines bezpieczeństwa jest wąski. Każde dodatkowe obciążenie (np. apt upgrade w trakcie pracy Z2M) może uderzyć w swap.

Migracja na Pi Zero 2 W (armv7/aarch64) zdejmuje wszystkie trzy ograniczenia: oficjalne apt install nodejs, najnowszy Z2M 2.x, więcej mocy obliczeniowej w tej samej formie obudowy. Jeśli celem jest setup do długiego utrzymania, a nie eksperyment poznawczy — Pi Zero 2 W jest lepszym wyborem. Pi Zero W pierwszej generacji da radę, ale jak dopiero kupujemy sprzet, to lepiej wziąć nowszy sprzęt.

Podsumowanie stacku

KomponentWersjaUwagi
HardwareRaspberry Pi Zero W (BCM2835, armv6, 512 MB RAM)+ Sonoff Dongle Plus MG24
OSRaspberry Pi OS Lite Bullseye 32-bitdphys-swapfile = 1024 MB
Node.js18.20.4 (unofficial-builds armv6l)Node 20+ wymaga Bookworm
Zigbee2MQTT1.42.0ostatnia z linii 1.x wspierająca Node 18
MQTT brokerMosquitto (apt)localhost:1883, anonymous
Driver Zigbeeember (EmberZNet)wspiera MG24 fabryczny firmware EZSP 13
Autostartsystemd unit, User=piKillSignal=SIGINT, Restart=always
Zdalny dostępTailscalemDNS w sieci lokalnej

Stack realizuje cel postawiony na początku: autonomiczny bridge Zigbee, który po wpięciu zasilania samodzielnie podnosi się, rejestruje swoje urządzenia, publikuje dane do MQTT i jest dostępny zdalnie. Wszystkie zależności poza systemem operacyjnym mieszczą się w /opt/zigbee2mqtt i /etc/systemd/system/zigbee2mqtt.service, co ułatwia ewentualną migrację na inny sprzęt.

Zobacz także