[Raspberry Pi] ZigBee: zigbee2mqtt einrichten, mosquitto broker installieren

zigbee2mqtt installieren

USB-Gerät an Raspberry anstecken und danach den Bezeichner ((z.B.: /dev/ttyUSB0) für die weitere Einrichtung ermitteln

ls -l /dev/serial/by-id/

Systemupdate durchführen

sudo apt-get update && sudo apt-get upgrade

NodeJS installieren

sudo curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs git make g++ gcc

Yarn installieren

curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update
sudo apt-get install yarn -y

zigbee2mqtt von git clonen und Verzeichnisberechtigungen für User “pi” setzen

sudo git clone https://github.com/Koenkk/zigbee2mqtt.git /opt/zigbee2mqtt
sudo chown -R pi:pi /opt/zigbee2mqtt

zigbee2mqtt Konfiguration editieren

nano /opt/zigbee2mqtt/data/configuration.yaml

Konfiguration für lokale Ausführung des mqtt-Servers (mosquitto) und zigbee2mqtt (Frontend läuft auf localhost, port 8080 ohne Username und Passwort) – Einrückungen beachten!

homeassistant: false
permit_join: false
mqtt:
  base_topic: zigbee2mqtt
  server: mqtt://localhost
serial:
  port: /dev/ttyUSB0
advanced:
  network_key: GENERATE
  ikea_ota_use_test_url: true
  legacy_api: false
  log_level: debug
  homeassistant_legacy_entity_attributes: false
  legacy_availability_payload: false
frontend:
  port: 8080
device_options:
  legacy: false

Installation von zigbee2mqtt starten

cd /opt/zigbee2mqtt
npm ci

zigbee2mqtt als Service einrichten

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

Dateiinhalt der Datei zigbee2mqtt.service

[Unit]
Description=zigbee2mqtt
After=network.target

[Service]
ExecStart=/usr/bin/npm start
WorkingDirectory=/opt/zigbee2mqtt
StandardOutput=inherit
# Or use StandardOutput=null if you don't want Zigbee2MQTT messages filling syslog, for more options see systemd.exec(5)
StandardError=inherit
Restart=always
User=pi

[Install]
WantedBy=multi-user.target

Autostart einrichten

sudo systemctl enable zigbee2mqtt.service

reboot durchführen

reboot

Sytemdienst adminstrieren

# zigbee2mqtt starten
sudo systemctl start zigbee2mqtt

# zigbee2mqtt stoppen
sudo systemctl stop zigbee2mqtt

# zigbee2mqtt neu starten
sudo systemctl restart zigbee2mqtt

# Log anschauen
sudo journalctl -f -u zigbee2mqtt

# Manuell starten
# Achtung: wenn zigbee2mqtt schon als Dienst eingerichtet ist und läuft führt das manuelle Ausführen zu einem Fehler
# Error: Error while opening serialport 'Error: Error Resource temporarily unavailable Cannot lock port'
cd /opt/zigbee2mqtt
npm start

mosquitto broker einrichten

mosquitto installieren

sudo apt update && sudo apt upgrade
sudo apt install -y mosquitto mosquitto-clients

mosquitto service einrichten

sudo systemctl enable mosquitto.service

broker testen, Versionsnummer ausgeben

mosquitto -v

mosquitto Konfiguration einrichten

sudo nano /etc/mosquitto/mosquitto.conf

Inhalt der Konfigurationsdatei mosquitto.conf (Reihenfolge beachten!)

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /run/mosquitto/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

listener 1883
allow_anonymous true

zigbee2mqtt Frontend starten

mosquitto Konfiguration einrichten

http://localhost:8080/

neue Zigbee-Geräte anlernen

  • Button “Anlernen aktivieren (alle)”

Links

[Raspberry Pi] Objekte und Klassen

class Car:
# Klassenvariablen (statisch)     
    name = "Mercedes"
    color = "blau"
 
    def __init__(self, cartype):
# Instanzvariable (self)
        self.cartype = cartype

    def drive(self, sound):
        print("Typ:", self.cartype)
        print("Geräusch:", sound)

# Werte der Klassenvariablen ausgeben
print(Car.name)
print(Car.color)

# Object instanziieren
auto = Car("Kombi")
auto.drive("brumm")

Links

[Raspberry Pi] Enumerator in Python

import enum
 
# Enumerator, wird als Klasse repräsentiert
class Cars(enum.Enum):
    Mercedes = 1
    Audi = 2
    BMW = 3

# Mercedes
print(Cars.Mercedes)
# Representation
print(repr(Cars.Mercedes))
# Type
print(type(Cars.Mercedes))
# Name
print(Cars.Mercedes.name)
# Wert
print(Cars.Mercedes.value)
# 3. Element
print(Cars(3))
# Element 'Mercedes'
print(Cars['Mercedes'])

# enum als Liste ausgeben
for c in Cars:
    print(c)
 
# hashed List mit enum
hli = {}
hli[Cars.Mercedes] = 'gelb'
hli[Cars.Audi] = 'grün'
hli[Cars.BMW] = 'blau'

print(hli[Cars.Mercedes])

[Raspberry Pi] Fmp4streamer: H264-Videostream direkt über den Browser bereitstellen

Auf Github gibt es ein interessantes Projekt, welches einen per V4L2 bereitgestellten Videostream als einen fragmentierten MP4-Stream (H264) bereitstellt. Das Ganze ist in Python geschrieben, lässt sich einfach installieren, braucht wenig CPU und man kann den Stream direkt im Browser anzeigen: Fmp4Streamer

[Raspberry Pi] Legacy Camera Stack unter Bullseye verwenden

Mit Raspian OS auf Basis von Debian 11 Bullseye wurde der alte Kamerastack von raspivid/raspistill auf libcamera geändert. Hierzu gibt es auf der folgenden Seite nähere Infos, insbesondere, wenn man derzeit noch die alten Treiber und Bibliotheken für V4L2 benötigt:
Legacy camera stack under Bullseye

[Raspberry Pi] Verarbeitung von Kommandozeilenparametern

import sys
import getopt

# Beispiel für Kommandozeile: test.py -i inp.py --output out.py -h
n = len(sys.argv)

print("Scriptname:", sys.argv[0])
print("Anz. Parameter:", n)
print("Parameterliste:", str(sys.argv))

for i in range(0, n):
    print("Parameter", i, ":", sys.argv[i])

try:
# ersten Parameter (Scriptname) aus der Liste entfernen
    pars = sys.argv[1:]

# Options und Argumente aus Parameterliste parsen
    opts, args = getopt.getopt(pars, "hi:o:", ["help", "input=", "output="])

# Options durchlaufen
    for arg, val in opts:
        if arg in ("-i", "--input"):
            print("Input:", arg, "Value:", val)
        elif arg in ("-o", "--output"):
            print("Output:", arg, "Value:", val)
        elif arg in ("-h", "--help"):
            print("Help:", arg, "Value:", val)

# Parse-Exception abfagen
except getopt.error as err:
    print (str(err))

Links

[Raspberry Pi] Exception-Handling

import sys
 
try:
# provoziert Division durch 0 --> ArithmeticError
    a = 1/0
    print(a)
except ArithmeticError as err:
# Ausgabe der Exception
    print("Fehler:", err)
# detailliertere Infos
    print("Detail:", sys.exc_info())
else:
# optional: wird nur erreicht, wenn keine Exception
    print("Alles ok.")
finally:
# optional: wird in jedem Fall erreicht
    print("Aufräumen.")

# hier wieder regulärer Programmablauf
print("Normal weiter.")

Links