# Zigbee & Zigbee2MQTT Integration **Meta-Description:** Zigbee Smart Home mit Zigbee2MQTT. Lokale Kontrolle, MQTT Bridge, Device Pairing und Home Assistant Integration. **Keywords:** Zigbee, Zigbee2MQTT, Smart Home, MQTT, Home Assistant, Local Control, Mesh Network --- ## Einführung **Zigbee** ist das bewährte Protokoll für batteriebetriebene Smart Home Geräte. **Zigbee2MQTT** macht es unabhängig von proprietären Bridges – lokale Kontrolle via MQTT mit über 4.000 unterstützten Geräten. --- ## Zigbee Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ ZIGBEE2MQTT ARCHITECTURE │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Applications │ │ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ │ │ Home │ │ Node │ │ Custom │ │ │ │ │ │ Assistant │ │ RED │ │ App │ │ │ │ │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │ │ │ └────────┼──────────────┼──────────────┼─────────────┘ │ │ │ │ │ │ │ ┌────────┴──────────────┴──────────────┴─────────────┐ │ │ │ MQTT Broker │ │ │ │ (Mosquitto / EMQX) │ │ │ └────────────────────────┬───────────────────────────┘ │ │ │ │ │ ┌────────────────────────┴───────────────────────────┐ │ │ │ Zigbee2MQTT │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ │ │ │ │ Frontend │ │ Bridge │ │ Converters│ │ │ │ │ │ (Web UI) │ │ (Core) │ │ (4000+) │ │ │ │ │ └─────────────┘ └─────────────┘ └───────────┘ │ │ │ └────────────────────────┬───────────────────────────┘ │ │ │ │ │ ┌────────────────────────┴───────────────────────────┐ │ │ │ zigbee-herdsman │ │ │ │ (Zigbee Protocol Stack) │ │ │ └────────────────────────┬───────────────────────────┘ │ │ │ │ │ ┌────────────────────────┴───────────────────────────┐ │ │ │ USB Adapter (Coordinator) │ │ │ │ Sonoff ZBDongle-P / ConBee II / CC2652P │ │ │ └────────────────────────┬───────────────────────────┘ │ │ │ │ │ ┌────────────────────────┴───────────────────────────┐ │ │ │ Zigbee Mesh Network │ │ │ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ │ │Router│───│Router│───│Router│───│ End │ │ │ │ │ │(Plug)│ │(Bulb)│ │(Plug)│ │Device│ │ │ │ │ └──────┘ └──────┘ └──────┘ └──────┘ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Installation ```bash # Docker Installation (empfohlen) mkdir zigbee2mqtt-data cd zigbee2mqtt-data # configuration.yaml erstellen cat > configuration.yaml << 'EOF' homeassistant: true permit_join: false mqtt: base_topic: zigbee2mqtt server: mqtt://localhost:1883 user: mqtt_user password: mqtt_password serial: port: /dev/ttyUSB0 adapter: zstack frontend: port: 8080 advanced: network_key: GENERATE pan_id: GENERATE channel: 15 log_level: info last_seen: 'ISO_8601' EOF ``` ```yaml # docker-compose.yml version: '3.8' services: zigbee2mqtt: container_name: zigbee2mqtt image: koenkk/zigbee2mqtt:latest restart: unless-stopped volumes: - ./zigbee2mqtt-data:/app/data - /run/udev:/run/udev:ro ports: - 8080:8080 environment: - TZ=Europe/Berlin devices: - /dev/ttyUSB0:/dev/ttyUSB0 depends_on: - mosquitto mosquitto: container_name: mosquitto image: eclipse-mosquitto:2 restart: unless-stopped volumes: - ./mosquitto/config:/mosquitto/config - ./mosquitto/data:/mosquitto/data - ./mosquitto/log:/mosquitto/log ports: - 1883:1883 - 9001:9001 ``` --- ## MQTT Topics ```typescript // Zigbee2MQTT MQTT Topic Structure // Base Topic: zigbee2mqtt // Device State (Subscribe) // zigbee2mqtt/[friendly_name] { "state": "ON", "brightness": 254, "color_temp": 370, "linkquality": 156, "last_seen": "2026-01-18T10:30:00.000Z" } // Device Control (Publish) // zigbee2mqtt/[friendly_name]/set { "state": "ON", "brightness": 200, "color_temp": 300, "transition": 2 } // Device Availability // zigbee2mqtt/[friendly_name]/availability "online" | "offline" // Bridge Status // zigbee2mqtt/bridge/state "online" | "offline" // Bridge Info // zigbee2mqtt/bridge/info { "version": "1.40.0", "commit": "abc123", "coordinator": { "ieee_address": "0x00124b001cda7a45", "type": "zStack3x0" }, "network": { "channel": 15, "pan_id": 6754, "extended_pan_id": "0xdddddddddddddddd" } } // Device List // zigbee2mqtt/bridge/devices [ { "ieee_address": "0x00158d00012345678", "friendly_name": "living_room_light", "type": "Router", "model": "LED1545G12", "vendor": "IKEA" } ] ``` --- ## Node.js Integration ```typescript // lib/zigbee2mqtt-client.ts import mqtt, { MqttClient } from 'mqtt'; interface Z2MDevice { ieee_address: string; friendly_name: string; type: 'Coordinator' | 'Router' | 'EndDevice'; model?: string; vendor?: string; supported: boolean; definition?: { description: string; supports: string; exposes: Z2MExpose[]; }; } interface Z2MExpose { type: string; name: string; property: string; access: number; values?: string[]; value_min?: number; value_max?: number; } interface DeviceState { state?: 'ON' | 'OFF'; brightness?: number; color_temp?: number; color?: { x: number; y: number }; temperature?: number; humidity?: number; battery?: number; occupancy?: boolean; contact?: boolean; linkquality?: number; last_seen?: string; } class Zigbee2MQTTClient { private client: MqttClient; private baseTopic: string; private devices: Map = new Map(); private states: Map = new Map(); private listeners: Map void>> = new Map(); constructor( brokerUrl: string, baseTopic: string = 'zigbee2mqtt' ) { this.baseTopic = baseTopic; this.client = mqtt.connect(brokerUrl); this.client.on('connect', () => this.onConnect()); this.client.on('message', (topic, payload) => this.onMessage(topic, payload.toString()) ); } private onConnect(): void { console.log('Connected to MQTT broker'); // Subscribe to all Z2M topics this.client.subscribe(`${this.baseTopic}/#`); // Request device list this.publish('bridge/request/devices', ''); } private onMessage(topic: string, payload: string): void { const relativeTopic = topic.replace(`${this.baseTopic}/`, ''); // Bridge Events if (relativeTopic === 'bridge/devices') { const devices = JSON.parse(payload) as Z2MDevice[]; this.updateDeviceList(devices); return; } if (relativeTopic === 'bridge/state') { console.log(`Bridge state: ${payload}`); return; } // Device State Updates if (!relativeTopic.includes('/') || relativeTopic.endsWith('/availability')) { return; } // State Update für Gerät const deviceName = relativeTopic.split('/')[0]; try { const state = JSON.parse(payload) as DeviceState; this.states.set(deviceName, { ...this.states.get(deviceName), ...state }); // Listener benachrichtigen this.listeners.get(deviceName)?.forEach(cb => cb(state)); this.listeners.get('*')?.forEach(cb => cb(state)); } catch { // Nicht-JSON Payload ignorieren } } private updateDeviceList(devices: Z2MDevice[]): void { devices.forEach(device => { this.devices.set(device.friendly_name, device); }); console.log(`Loaded ${devices.length} devices`); } private publish(topic: string, payload: any): void { const fullTopic = `${this.baseTopic}/${topic}`; const message = typeof payload === 'string' ? payload : JSON.stringify(payload); this.client.publish(fullTopic, message); } // Public API getDevices(): Z2MDevice[] { return Array.from(this.devices.values()); } getDevice(name: string): Z2MDevice | undefined { return this.devices.get(name); } getState(deviceName: string): DeviceState | undefined { return this.states.get(deviceName); } // Device Control setState(deviceName: string, state: Partial): void { this.publish(`${deviceName}/set`, state); } turnOn(deviceName: string): void { this.setState(deviceName, { state: 'ON' }); } turnOff(deviceName: string): void { this.setState(deviceName, { state: 'OFF' }); } toggle(deviceName: string): void { this.publish(`${deviceName}/set`, { state: 'TOGGLE' }); } setBrightness(deviceName: string, brightness: number, transition?: number): void { this.setState(deviceName, { brightness: Math.min(254, Math.max(0, brightness)), ...(transition && { transition }) }); } setColorTemp(deviceName: string, colorTemp: number): void { // Mired: 153 (cool) - 500 (warm) this.setState(deviceName, { color_temp: colorTemp }); } setColor(deviceName: string, x: number, y: number): void { this.setState(deviceName, { color: { x, y } }); } // Event Listener onStateChange( deviceName: string, callback: (state: DeviceState) => void ): () => void { if (!this.listeners.has(deviceName)) { this.listeners.set(deviceName, new Set()); } this.listeners.get(deviceName)!.add(callback); return () => { this.listeners.get(deviceName)?.delete(callback); }; } // Bridge Control permitJoin(permit: boolean, duration?: number): void { this.publish('bridge/request/permit_join', { value: permit, time: duration || 120 }); } renameDevice(oldName: string, newName: string): void { this.publish('bridge/request/device/rename', { from: oldName, to: newName }); } removeDevice(deviceName: string, force?: boolean): void { this.publish('bridge/request/device/remove', { id: deviceName, force: force || false }); } // OTA Updates checkOTAUpdates(): void { this.publish('bridge/request/device/ota_update/check', ''); } updateDevice(deviceName: string): void { this.publish('bridge/request/device/ota_update/update', { id: deviceName }); } disconnect(): void { this.client.end(); } } export { Zigbee2MQTTClient }; ``` --- ## Express API Wrapper ```typescript // api/zigbee-api.ts import express from 'express'; import { Zigbee2MQTTClient } from '../lib/zigbee2mqtt-client'; const router = express.Router(); const z2m = new Zigbee2MQTTClient(process.env.MQTT_URL || 'mqtt://localhost:1883'); // GET /api/devices router.get('/devices', (req, res) => { const devices = z2m.getDevices() .filter(d => d.type !== 'Coordinator') .map(d => ({ name: d.friendly_name, ieee: d.ieee_address, type: d.type, model: d.model, vendor: d.vendor, state: z2m.getState(d.friendly_name) })); res.json(devices); }); // GET /api/devices/:name router.get('/devices/:name', (req, res) => { const device = z2m.getDevice(req.params.name); if (!device) { return res.status(404).json({ error: 'Device not found' }); } res.json({ ...device, state: z2m.getState(req.params.name) }); }); // POST /api/devices/:name/set router.post('/devices/:name/set', (req, res) => { const device = z2m.getDevice(req.params.name); if (!device) { return res.status(404).json({ error: 'Device not found' }); } z2m.setState(req.params.name, req.body); res.json({ success: true }); }); // POST /api/devices/:name/toggle router.post('/devices/:name/toggle', (req, res) => { z2m.toggle(req.params.name); res.json({ success: true }); }); // Groups // POST /api/groups/:name/set router.post('/groups/:name/set', (req, res) => { z2m.setState(req.params.name, req.body); res.json({ success: true }); }); // Bridge Control // POST /api/bridge/permit_join router.post('/bridge/permit_join', (req, res) => { const { permit, duration } = req.body; z2m.permitJoin(permit, duration); res.json({ success: true }); }); export default router; ``` --- ## Home Assistant Auto-Discovery ```typescript // Zigbee2MQTT sendet automatisch Home Assistant Discovery Messages // homeassistant/light/0x00158d00012345678/light/config { "name": "Living Room Light", "unique_id": "0x00158d00012345678_light_zigbee2mqtt", "state_topic": "zigbee2mqtt/living_room_light", "command_topic": "zigbee2mqtt/living_room_light/set", "availability": [ { "topic": "zigbee2mqtt/bridge/state" }, { "topic": "zigbee2mqtt/living_room_light/availability" } ], "brightness": true, "brightness_scale": 254, "color_mode": true, "supported_color_modes": ["color_temp", "xy"], "min_mireds": 153, "max_mireds": 500, "schema": "json", "device": { "identifiers": ["zigbee2mqtt_0x00158d00012345678"], "name": "Living Room Light", "model": "LED1545G12", "manufacturer": "IKEA", "via_device": "zigbee2mqtt_bridge" } } ``` --- ## Device Groups ```yaml # configuration.yaml groups: living_room: friendly_name: Wohnzimmer devices: - living_room_light_1 - living_room_light_2 - living_room_light_3 all_lights: friendly_name: Alle Lichter devices: - living_room_light_1 - living_room_light_2 - bedroom_light - kitchen_light ``` ```typescript // Gruppen steuern z2m.setState('living_room', { state: 'ON', brightness: 200 }); // Alle Lichter aus z2m.turnOff('all_lights'); ``` --- ## Scenes & Automations ```yaml # configuration.yaml # Szenen definieren scenes: - name: movie_mode data: living_room: state: 'ON' brightness: 50 color_temp: 500 kitchen: state: 'OFF' - name: morning_routine data: bedroom_light: state: 'ON' brightness: 100 color_temp: 250 ``` ```typescript // Szene aktivieren z2m.publish('scene/recall', { scene: 'movie_mode' }); // Custom Automation z2m.onStateChange('motion_sensor', (state) => { if (state.occupancy) { z2m.turnOn('hallway_light'); // Auto-Off nach 5 Minuten setTimeout(() => { const currentState = z2m.getState('motion_sensor'); if (!currentState?.occupancy) { z2m.turnOff('hallway_light'); } }, 5 * 60 * 1000); } }); // Temperature-basierte Automation z2m.onStateChange('temperature_sensor', (state) => { if (state.temperature && state.temperature > 25) { z2m.publish('fan/set', { state: 'ON', preset_mode: 'high' }); } }); ``` --- ## Zigbee Network Map ```typescript // Network Topology abrufen // zigbee2mqtt/bridge/request/networkmap z2m.publish('bridge/request/networkmap', { type: 'raw' }); // Antwort auf zigbee2mqtt/bridge/response/networkmap interface NetworkMap { nodes: Array<{ ieee_address: string; friendly_name: string; type: 'Coordinator' | 'Router' | 'EndDevice'; network_address: number; lqi: number; // Link Quality Indicator relationship: number; }>; links: Array<{ source: { ieee_address: string }; target: { ieee_address: string }; lqi: number; depth: number; }>; } ``` --- ## Troubleshooting ```typescript // Häufige Probleme und Lösungen // 1. Gerät reagiert nicht async function troubleshootDevice(deviceName: string) { const state = z2m.getState(deviceName); // Linkqualität prüfen if (state?.linkquality && state.linkquality < 50) { console.log('Low link quality - consider adding router devices'); } // Availability prüfen // Subscribe to zigbee2mqtt/[device]/availability // Device Interview neu durchführen z2m.publish('bridge/request/device/interview', { id: deviceName }); } // 2. Pairing funktioniert nicht function resetAndPair() { // Permit Join aktivieren z2m.permitJoin(true, 180); // 3 Minuten // Gerät in Pairing-Modus versetzen (geräteabhängig) console.log('Reset device and put in pairing mode'); } // 3. Mesh-Netzwerk optimieren function optimizeMesh() { // Router-Geräte (Steckdosen, Lampen) sind wichtig für Mesh // Mindestens ein Router pro Raum const devices = z2m.getDevices(); const routers = devices.filter(d => d.type === 'Router'); const endDevices = devices.filter(d => d.type === 'EndDevice'); console.log(`Routers: ${routers.length}, End Devices: ${endDevices.length}`); if (endDevices.length / routers.length > 6) { console.log('Warning: Not enough routers for stable mesh'); } } ``` --- ## Fazit Zigbee2MQTT bietet: 1. **Lokale Kontrolle**: Keine Cloud-Abhängigkeit 2. **4000+ Geräte**: Herstellerunabhängig 3. **MQTT Integration**: Einfache Anbindung 4. **Open Source**: Aktive Community Der beste Weg für ein offenes Smart Home. --- ## Bildprompts 1. "Zigbee mesh network diagram with router and end devices connected" 2. "Zigbee2MQTT web interface showing device list and controls" 3. "USB Zigbee coordinator stick connected to Raspberry Pi, smart home hub" --- ## Quellen - [Zigbee2MQTT Documentation](https://www.zigbee2mqtt.io/) - [zigbee-herdsman GitHub](https://github.com/Koenkk/zigbee-herdsman) - [Supported Devices](https://www.zigbee2mqtt.io/supported-devices/) - [Zigbee Technology 2026](https://zigbeehubs.com/zigbee-technology-2026/)