Cài Đặt Zigbee2MQTT Trên Docker Với Sonoff Dongle: Nhà Thông Minh 100% Local

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

Các hub độc quyền từ Tuya, Aqara và Philips Hue rất thích liên tục gửi dữ liệu về máy chủ đám mây. Mỗi khi mất mạng internet, toàn bộ hệ thống tự động hóa chiếu sáng của bạn cũng sẽ tê liệt theo. Việc gửi tín hiệu vòng qua đám mây còn gây ra độ trễ khó chịu từ 300–800ms cho những thao tác cơ bản như bật/tắt công tắc tường. Vận hành mạng Zigbee hoàn toàn cục bộ (local) sẽ loại bỏ triệt để các nút thắt cổ chai này, hạ độ trễ thực thi lệnh xuống dưới 15ms, đồng thời giữ trọn vẹn dữ liệu cảm biến bên trong mạng nội bộ của bạn.

Sự kết hợp giữa USB Dongle Sonoff Zigbee 3.0 Plus và Zigbee2MQTT chạy trên Docker mang lại độ ổn định chuẩn doanh nghiệp ngay trên phần cứng phổ thông. Trong hệ thống homelab của tôi, chính cấu hình này đang điều phối hơn 85 thiết bị trải khắp ba tầng nhà—bao gồm bóng đèn Hue, cảm biến cửa Sonoff và cảm biến môi trường Aqara—suốt hơn 14 tháng qua mà không rớt một gói tin nào.

Khởi động nhanh (5 phút)

Hãy cắm Sonoff Dongle vào máy chủ của bạn trước khi cấu hình container. Bạn cần xác định đúng đường dẫn phần cứng cố định (persistent path) của thiết bị thay vì sử dụng tên cổng tạm thời.

Bước 1: Xác định adapter theo ID phần cứng

Truy vấn hệ thống nối tiếp (serial subsystem) của Linux bằng lệnh sau:

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

Terminal của bạn sẽ hiển thị kết quả tương tự như sau:

usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_e850b6919db1eb11b512e0e0-if00-port0 -> ../../ttyUSB0

Hãy sao chép toàn bộ đường dẫn symlink (/dev/serial/by-id/usb-ITead_Sonoff_...). Tuyệt đối không gắn kết (bind) các đường dẫn dạng thô như /dev/ttyUSB0. Nếu bạn cắm thêm một thiết bị ngoại vi chuẩn nối tiếp khác hoặc khởi động lại máy chủ, nhân Linux có thể hoán đổi số thứ tự thiết bị, khiến toàn bộ cụm container của bạn bị lỗi.

Bước 2: Tạo cấu trúc thư mục

mkdir -p ~/homelab/zigbee2mqtt/data
mkdir -p ~/homelab/mosquitto/config
mkdir -p ~/homelab/mosquitto/data
mkdir -p ~/homelab/mosquitto/log
cd ~/homelab

Bước 3: Cấu hình Mosquitto

Từ phiên bản 2.0 trở lên, Mosquitto mặc định từ chối các kết nối chưa xác thực. Tạo file ~/homelab/mosquitto/config/mosquitto.conf với nội dung chuẩn ban đầu như sau:

listener 1883
allow_anonymous true
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log

Nếu dự định mở MQTT ra ngoài mạng con nội bộ biệt lập, bạn hãy thay thế dòng allow_anonymous true bằng việc cấu hình file mật khẩu.

Bước 4: Khởi chạy bằng Docker Compose

Khai báo cấu hình các service vào file ~/homelab/docker-compose.yml:

services:
  mqtt:
    image: eclipse-mosquitto:2
    container_name: mosquitto
    restart: unless-stopped
    ports:
      - "1883:1883"
    volumes:
      - ./mosquitto/config:/mosquitto/config
      - ./mosquitto/data:/mosquitto/data
      - ./mosquitto/log:/mosquitto/log

  zigbee2mqtt:
    image: koenkk/zigbee2mqtt:latest
    container_name: zigbee2mqtt
    restart: unless-stopped
    volumes:
      - ./zigbee2mqtt/data:/app/data
      - /run/udev:/run/udev:ro
    ports:
      - "8080:8080"
    environment:
      - TZ=UTC
    devices:
      - /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_e850b6919db1eb11b512e0e0-if00-port0:/dev/ttyACM0
    depends_on:
      - mqtt

Khởi chạy các container:

docker compose up -d

Mở trình duyệt và truy cập http://<your-server-ip>:8080. Bảng điều khiển web của Zigbee2MQTT sẽ xuất hiện ngay lập tức.

Đi sâu vào chi tiết

Khởi chạy container chỉ mất chưa đầy năm phút. Tuy nhiên, để duy trì kết nối ổn định xuyên qua các bức tường bê tông và các vùng nhiễu sóng, bạn cần tinh chỉnh các thiết lập ở tầng sâu hơn.

1. Ánh xạ thiết bị và phân quyền cổng serial

Linux gán các cổng chung như ttyUSB0 một cách linh hoạt trong quá trình nhận diện phần cứng khi khởi động. Việc kết nối thêm bộ giám sát UPS hoặc bộ điều khiển Z-Wave có thể dễ dàng khiến dongle của bạn bị đổi tên thành ttyUSB1. Gắn kết qua /dev/serial/by-id/ đảm bảo container luôn trỏ chính xác đến chip sóng Texas Instruments vật lý.

Nếu log của container báo lỗi Error: Resource temporarily unavailable Cannot lock port, nguyên nhân là do người dùng chạy Docker chưa có quyền truy cập nhóm serial. Hãy thêm người dùng của bạn vào nhóm dialout:

sudo usermod -aG dialout $USER

2. Gia cố file `configuration.yaml`

Trong lần khởi động đầu tiên, container sẽ tự động sinh file ~/homelab/zigbee2mqtt/data/configuration.yaml. Hãy thay thế nội dung của file bằng cấu hình chuẩn tối ưu cho môi trường thực tế này:

homeassistant:
  enabled: true
permit_join: false
mqtt:
  base_topic: zigbee2mqtt
  server: 'mqtt://mqtt:1883'
serial:
  port: /dev/ttyACM0
  adapter: zstack
frontend:
  port: 8080
advanced:
  channel: 25
  network_key: GENERATE
  log_level: info
  pan_id: GENERATE
  ext_pan_id: GENERATE

Luôn đảm bảo rằng permit_join: false đã được thiết lập. Hãy luôn khóa chế độ ghép nối (pairing) cho đến khi bạn chủ động kết nối thêm thiết bị mới. Việc bật liên tục chế độ cho phép gia nhập có thể khiến các thiết bị của hàng xóm hoặc cảm biến lạ vô tình kết nối vào coordinator của bạn mà bạn không hay biết.

3. Nhiễu sóng vô tuyến: Xung đột kênh Wi-Fi và Zigbee

Cả hai giao thức này đều hoạt động chung trên dải tần 2.4 GHz. Các kênh Wi-Fi có độ rộng băng thông rất lớn (từ 20–40 MHz) và sẽ dễ dàng lấn át các luồng phát tín hiệu nhỏ bé của Zigbee (chỉ rộng 2 MHz). Theo mặc định, Zigbee thường chọn Kênh 11, trùng trực tiếp với Kênh 1 của Wi-Fi.

Chuyển Zigbee sang Kênh 25 (Channel 25) sẽ đưa mạng vào vùng tần số thông thoáng phía trên Kênh 11 của Wi-Fi. Thay đổi đơn giản này thường giúp giảm hơn 70% số lượng gói tin cảm biến phải truyền lại trong các môi trường dân cư thông thường.

Sử dụng nâng cao

Liên kết thiết bị trực tiếp (Direct Binding)

Các kịch bản tự động hóa tập trung trong Home Assistant xử lý rất tốt các lịch trình có điều kiện. Nhưng chuyện gì sẽ xảy ra nếu máy chủ bị treo hoặc phải khởi động lại để cập nhật kernel? Công tắc trong phòng ngủ vẫn phải bật/tắt được đèn trần.

Zigbee hỗ trợ cơ chế direct binding (liên kết trực tiếp) nguyên bản. Trong giao diện web của Zigbee2MQTT:

  1. Chọn công tắc không dây của bạn.
  2. Chuyển sang tab Bind.
  3. Chọn thiết bị đèn đích và cụm chức năng tương ứng (thường là OnOff hoặc LevelControl).
  4. Nhấn Bind.

Giờ đây, công tắc sẽ gửi lệnh trực tiếp đến bóng đèn thông qua sóng vô tuyến. Lệnh được thực thi chỉ trong khoảng 10ms—bỏ qua hoàn toàn hệ điều hành máy chủ, Docker engine và cả MQTT broker.

Cập nhật firmware qua mạng (OTA)

Zigbee2MQTT có khả năng tải về firmware đã ký số chính thức từ các nhà sản xuất như IKEA, Sonoff và Philips Hue. Bạn chỉ cần điều hướng đến tab OTA trên giao diện web và chọn Check all. Cập nhật firmware định kỳ giúp khắc phục các lỗi chu kỳ ngủ (sleep-cycle) của nhà sản xuất, sửa hiện tượng mất định tuyến trong mạng mesh và sửa lỗi báo pin thiếu chính xác.

Trực quan hóa sơ đồ mạng mesh

Mục Map hiển thị trực quan chỉ số chất lượng kết nối (LQI – Link Quality Indicator) theo thời gian thực giữa tất cả các node. Điểm LQI trên 100 thể hiện kết nối khỏe mạnh. Nếu điểm tụt xuống dưới 40, mạng có nguy cơ rớt gói tin và phản hồi chậm trễ. Khi một thiết bị đầu cuối (end device) gặp vấn đề vì LQI yếu, hãy cắm thêm một ổ cắm thông minh Zigbee dùng nguồn điện lưới ở vị trí trung gian để làm repeater mở rộng vùng phủ sóng mesh.

Lời khuyên thực tế

Luôn sử dụng dây cáp nối dài USB 2.0

Tuyệt đối không cắm trực tiếp USB coordinator Zigbee vào cổng USB 3.0 trên bo mạch chủ hoặc Raspberry Pi. Các chip điều khiển USB 3.0 không được bọc chống nhiễu kỹ càng sẽ phát ra nhiễu sóng băng rộng trên dải tần 2.4–2.5 GHz. Mức nhiễu nền này sẽ làm suy giảm nghiêm trọng khả năng thu sóng của Zigbee. Chỉ cần gắn thêm một dây nối dài USB 2.0 dài khoảng 1 mét để đưa ăng-ten cách ly khỏi nhiễu mạch bo mạch, độ nhạy kết nối sẽ tăng lên gấp đôi ngay lập tức.

Chọn đúng phiên bản Sonoff (Dongle-P và Dongle-E)

Sonoff bán ra hai phiên bản phần cứng khác nhau với tên gọi gần như tương đồng:

  • Model “ZBDongle-P” (Khuyên dùng): Trang bị chip Texas Instruments CC2652P. Phiên bản này sử dụng driver zstack đã hoàn thiện và được kiểm chứng qua thời gian dài. Hãy chọn model này nếu bạn đề cao sự ổn định tuyệt đối.
  • Model “ZBDongle-E”: Sử dụng chip Silicon Labs EFR32MG21. Phiên bản này yêu cầu driver adapter ember mới hơn. Dù vẫn hoạt động tốt, nó chưa có thời gian kiểm chứng độ tương thích lâu dài bằng với Zigbee2MQTT.

Tự động hóa sao lưu cấu hình và cơ sở dữ liệu

Khóa mã hóa mạng, bảng địa chỉ IEEE và danh sách thiết bị của bạn đều nằm trong ba file cốt lõi trong volume đã ánh xạ:

  • data/configuration.yaml
  • data/database.db
  • data/coordinator_backup.json

Hãy lên lịch sao lưu tự động hàng ngày trên máy chủ thông qua cron:

tar -czf ~/backups/z2m-$(date +%F).tar.gz ~/homelab/zigbee2mqtt/data

Nhờ file lưu trữ này cùng các đường dẫn phần cứng cố định, việc chuyển toàn bộ coordinator sang một máy chủ mới chỉ mất chưa đầy hai phút. Bạn sẽ không bao giờ phải tốn công ghép nối lại dù chỉ một công tắc hay cảm biến.

Share: