Kubernetes,  QNAP

kubernetes. k0s – Instalación de Zigbee2MQTT

De nuevo vamos a acercar kubernetes a la parte física. No voy a explicar el propósito de Zigbee2MQTT, y simplemente nombraré que con este proyecto podemos tener un HUB para nuestros dispositivos Zigbee. Con este HUB vas a poder gestionar dispositivos de diferentes fabricantes y así puedes escapar de tener todo tu ecosistema de un fabricante o tener que comprar múltiples HUBs (uno por cada fabricante).

A jugar!

Primero pinto un esquema de los diferentes elementos usados. Destaco, que he desvinculado el servicio de Zigbee2MQTT del dispositivo USB que actúa de receptor. Para conseguirlo, utilizo la aplicación ser2net. Éste servicio, se queda a la escucha y pone a disposición de la red el puerto USB donde está pinchado el dispositivo Zigbee. No he conectado el USB al servidor (NAS), como en otras ocasiones, ya que está alejado de la mayoría de los dispositivos Zigbee finales.

También por comodidad he creado una regla udev en la Raspberry PI para que nombre de manera más amigable el Dongle USB. El dispositivo siempre se podrá encontrar en /dev/zigbee01 pinchándolo en cualquier puerto de la Raspberry PI.

$ cat /etc/udev/rules.d/zigbee-controller.rules

# Product: Sonoff Zigbee 3.0 USB Dongle Plus
KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE="0666", SYMLINK+="zigbee01"

El servicio ser2net es muy sencillo de configurar. Una vez levantado se mantiene a la escucha en el puerto 20108 (según configuración). En el ejemplo se puede ver una conexión ya levantada desde el clúster de kubernetes.

$ cat /etc/ser2net.conf 

20108:raw:0:/dev/zigbee01:115200 8DATABITS NONE 1STOPBIT

$ sudo systemctl status ser2net
● ser2net.service - LSB: Allows network connections to serial ports
   Loaded: loaded (/etc/init.d/ser2net; generated)
   Active: active (running) since Wed 2024-03-13 23:33:40 CET; 6 days ago
     Docs: man:systemd-sysv-generator(8)
  Process: 756 ExecStart=/etc/init.d/ser2net start (code=exited, status=0/SUCCESS)
    Tasks: 1 (limit: 2059)
   CGroup: /system.slice/ser2net.service
           └─766 /usr/sbin/ser2net -c /etc/ser2net.conf -P /run/ser2net.pid
           
$ sudo netstat -patun
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:20108           0.0.0.0:*               LISTEN      766/ser2net               
tcp        0      0 ip_raspberrypi:20108    ip_nodokubernetes:45919 ESTABLISHED 766/ser2net         

Kubernetes

Empiezo por el final. Pego el .yaml con toda la configuración y comento lo que considero tiene más importancia. El Deployment contiene 2 imágenes; que corresponden al servicio MOSQUITTO y al servicio ZIGBEE2MQTT. Los dos servicios son necesarios y los creado compartiendo POD, para que compartan el mismo espacio de red. Esto me permite, por ejemplo, hacer referencia a mosquitto simplemente haciendo peticiones a localhost (mqtt://localhost:1883).

En cuanto a los volúmenes, he ido comprobando los necesarios. Como siempre utilizo recursos NFS que comparto desde el NAS, que a su vez, también alberga el clúster de Kubernetes.

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
  labels:
    app: zigbee2mqtt
  name: zigbee2mqtt
  namespace: homeassistant
spec:
  replicas: 1
  selector:
    matchLabels:
      app: zigbee2mqtt
  template:
    metadata:
      labels:
        app: zigbee2mqtt
    spec:
      containers:

      - image: eclipse-mosquitto
        name: mosquitto
        ports:
          - containerPort: 1883 
          - containerPort: 9001
        volumeMounts:
        - mountPath: /mosquito/config
          name: mosquitto-storage-config
        - mountPath: /mosquito/data
          name: mosquitto-storage-data
        - mountPath: /mosquito/log
          name: mosquitto-storage-log

      - image: koenkk/zigbee2mqtt
        name: zigbee2mqtt
        ports:
          - containerPort: 8080
        env:
          - name: "TZ"
            value: "Europe/Madrid"
        volumeMounts:
        - mountPath: /app/data
          name: zigbee2mqtt-storage

      volumes:
      - name: mosquitto-storage-config
        nfs:
          path: /DPVs/mosquitto/config
          server: tuserver
      - name: mosquitto-storage-data
        nfs:
          path: /DPVs/mosquitto/data
          server: tuserver
      - name: mosquitto-storage-log
        nfs:
          path: /DPVs/mosquitto/log
          server: tuserver
      - name: zigbee2mqtt-storage
        nfs:
          path: /DPVs/zigbee2mqtt
          server: tuserver

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: zigbee2mqtt
  name: zigbee2mqtt
  namespace: homeassistant
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: zigbee2mqtt
  type: ClusterIP


---
También puedes publicar un Ingress. No todo va a ser copiar y pegar.
Lo puedes ver en otras entradas del Blog.

Configuraciones

# cat zigbee2mqtt/configuration.yaml
homeassistant: false
permit_join: true
mqtt:
  base_topic: zigbee2mqtt
  server: mqtt://localhost:1883
serial:
  port: tcp://tuservidor_ser2net:20108
advanced:
  homeassistant_legacy_entity_attributes: false
  legacy_api: false
  legacy_availability_payload: false
device_options:
  legacy: false
frontend: true
# cat mosquitto/config/mosquitto.conf
port 1883
listener 9001
allow_anonymous true
protocol websockets
persistence true
persistence_location /mosquitto/data/ log_dest file /mosquito/log/mosquitto.log

La hora de la verdad

Bueno todo esto es para añadir cacharritos zigbee. Voy a probar con este:

Cuando realizamos el típico proceso de JOIN se puede ver en el log que se ha añadido correctamente. Como diría uno que yo me sé –> “ea … pues ya estaría …”

Info 2024-03-21 02:57:43Device '0xa4c138656' joined
Info 2024-03-21 02:57:43MQTT publish: topic 'zigbee2mqtt/bridge/event', payload '{"data":{"friendly_name":"0xa4c1386563a5c2ac","ieee_address":"0xa4c138656"},"type":"device_joined"}'
Info 2024-03-21 02:57:43Starting interview of '0xa4c138656'
Info 2024-03-21 02:57:43MQTT publish: topic 'zigbee2mqtt/bridge/event', payload '{"data":{"friendly_name":"0xa4c138656","ieee_address":"0xa4c138656","status":"started"},"type":"device_interview"}'
Info 2024-03-21 02:58:33Device '0xa4c138656' is supported, identified as: TuYa Door sensor (TS0203)

De nuevo un ejercicio de acercamiento de Kubernetes al mundo físico, utilizando elementos Hardware distribuidos y dando servicio a la infraestructura Domótica.