Node-RED: Wie speichere ich alle Geräte des Bosch Smart Home Systems im globalen Context
Mit Node-RED und dem Bosch Smart Home System kannst du deine Smart Home Geräte effizient verwalten. In diesem Artikel zeige ich dir, wie du alle Geräte deines Bosch Smart Home Systems im globalen Context von Node-RED speicherst, um jederzeit und in jedem Flow auf diese Informationen zugreifen zu können.

Warum solltest du Geräteinformationen im globalen Context speichern?
Wenn du mit Node-RED und dem Bosch Smart Home System arbeitest, kennst du vielleicht folgendes Problem: Du hast viele verschiedene Geräte, die jeweils kryptische IDs wie “hdm:ZigBee:12345678” haben. Beim Erstellen von Automatisierungen ist es schwierig, zu wissen, welche ID zu welchem Gerät gehört.
Durch das Speichern aller Gerätenamen im globalen Context erhältst du folgende Vorteile:
- Du kannst in allen Flows auf die Gerätenamen zugreifen, ohne jedes Mal eine API-Abfrage senden zu müssen
- Die Namen sind lesbar formatiert und enthalten auch den Raumnamen
- Du kannst diese Informationen für dynamische Dashboards oder Logik verwenden
- Du sparst Zeit bei der Entwicklung neuer Flows, da die Gerätezuordnung sofort klar ist
Dieser Ansatz ist besonders hilfreich, wenn du viele Geräte hast oder wenn mehrere Personen an deinen Node-RED Flows arbeiten.
Voraussetzungen
Bevor du mit dem Speichern der Gerätenamen beginnst, solltest du folgende Voraussetzungen erfüllen:
- Eine funktionierende Node-RED Installation
- Zugriff auf dein Bosch Smart Home System über lokale REST-API
- Die Raumnamen sollten bereits im globalen Context gespeichert sein (siehe Node-RED: Bosch Smart Home Raumnamen im globalen Kontext speichern)
Der Code, den wir verwenden werden, setzt voraus, dass die Raumnamen bereits im globalen Context unter “roomNames_BSH” gespeichert sind. Falls du diesen Schritt noch nicht durchgeführt hast, empfehle ich dir, zunächst den verlinkten Artikel zu lesen und umzusetzen.
Der Code im Detail
Schauen wir uns den vollständigen Code an, der alle Geräte des Bosch Smart Home Systems im globalen Context speichert:
// Initialize an object to store ID-name mappings let deviceNames_BSH = {};
// Load room names from the global context
let roomNames_BSH = global.get("roomNames_BSH") || {};
// Check if msg.payload is an array
if (Array.isArray(msg.payload)) {
msg.payload.forEach(device => {
let id = device.id;
let name = device.name;
let key = null;
let roomName = "Unknown Room"; // Default value if no room is found
text
// Extract the key based on the device protocol
if (id.startsWith("hdm:ZigBee:")) {
key = id.substring("hdm:ZigBee:".length);
} else if (id.startsWith("hdm:HomeMaticIP:")) {
key = id.substring("hdm:HomeMaticIP:".length);
}
if (key) {
// Optional: Assuming each device has a room ID, e.g., device.roomId
// Adjust this according to the actual structure of your device object
if (device.roomId && roomNames_BSH[device.roomId]) {
roomName = roomNames_BSH[device.roomId];
}
// Replace all spaces with dots in roomName and name
let sanitizedRoomName = roomName.replace(/\s+/g, '.');
let sanitizedName = name.replace(/\s+/g, '.');
// Add the room name to the device name
let fullName = `${sanitizedRoomName}.${sanitizedName}`;
deviceNames_BSH[key] = fullName;
}
});
// Save the object in the global context under "deviceNames_BSH"
global.set("deviceNames_BSH", deviceNames_BSH);
// Optional: Output for verification
node.warn("Device names with room names saved in the global context under 'deviceNames_BSH'");
} else {
node.error("msg.payload is not an array");
}
return msg;
Dieser Code wird in einem Function-Node verwendet, der die Gerätedaten verarbeitet, die vom Bosch Smart Home System zurückgegeben werden. Lass uns den Code Schritt für Schritt durchgehen.
Initialisierung und Vorbereitung
Zunächst initialisieren wir ein Objekt für die Gerätenamen und laden die bereits gespeicherten Raumnamen aus dem globalen Context:
// Initialize an object to store ID-name mappings
let deviceNames_BSH = {};
// Load room names from the global context
let roomNames_BSH = global.get("roomNames_BSH") || {};
Der Operator || stellt sicher, dass wir mindestens ein leeres Objekt haben, falls noch keine Raumnamen im globalen Context gespeichert wurden. Dies verhindert Fehler, wenn die Variable “roomNames_BSH” noch nicht existiert.
Verarbeitung der Gerätedaten
Anschließend überprüfen wir, ob msg.payload ein Array ist, und verarbeiten jedes Gerät:
if (Array.isArray(msg.payload)) { msg.payload.forEach(device => { let id = device.id; let name = device.name; let key = null; let roomName = "Unknown Room"; // Default value if no room is found
text
// Extract the key based on the device protocol
if (id.startsWith("hdm:ZigBee:")) {
key = id.substring("hdm:ZigBee:".length);
} else if (id.startsWith("hdm:HomeMaticIP:")) {
key = id.substring("hdm:HomeMaticIP:".length);
}
Hier passiert Folgendes:
- Wir extrahieren die ID und den Namen jedes Geräts
- Wir setzen einen Standardwert für den Raumnamen
- Wir extrahieren den relevanten Teil der Geräte-ID, abhängig vom Protokoll (ZigBee oder HomeMaticIP)
Die Geräte-IDs von Bosch Smart Home beginnen üblicherweise mit einem Präfix wie “hdm:ZigBee:” oder “hdm:HomeMaticIP:”, gefolgt von einer eindeutigen Kennung. Wir entfernen dieses Präfix, um einen klareren und kürzeren Schlüssel für unser Objekt zu erhalten.
Der nächste Schritt ist die Zuordnung des Raums und die Formatierung des Gerätenamens:
if (key) { // Optional: Assuming each device has a room ID, e.g., device.roomId // Adjust this according to the actual structure of your device object if (device.roomId && roomNames_BSH[device.roomId]) { roomName = roomNames_BSH[device.roomId]; }
text
// Replace all spaces with dots in roomName and name
let sanitizedRoomName = roomName.replace(/\s+/g, '.');
let sanitizedName = name.replace(/\s+/g, '.');
// Add the room name to the device name
let fullName = `${sanitizedRoomName}.${sanitizedName}`;
deviceNames_BSH[key] = fullName;
}
In diesem Abschnitt:
- Wir prüfen, ob das Gerät eine Raum-ID hat und ob dieser Raum in unserem roomNames_BSH-Objekt existiert
- Wir ersetzen Leerzeichen durch Punkte, um eine kompatible Benennung für Node-RED zu erhalten
- Wir erstellen einen vollständigen Namen, der aus dem Raumnamen und dem Gerätenamen besteht
- Wir speichern diesen Namen im deviceNames_BSH-Objekt mit dem extrahierten Schlüssel als Index
Das Ersetzen von Leerzeichen durch Punkte ist besonders wichtig, da wir diese Namen später möglicherweise in Topics für MQTT oder in Node-RED-Funktionen verwenden werden, wo Leerzeichen zu Problemen führen können.
Speicherung im globalen Context
Zum Schluss speichern wir das gesamte Objekt im globalen Context und geben eine Bestätigungsmeldung aus:
// Save the object in the global context under "deviceNames_BSH" global.set("deviceNames_BSH", deviceNames_BSH);
text
// Optional: Output for verification
node.warn("Device names with room names saved in the global context under 'deviceNames_BSH'");
} else {
node.error("msg.payload is not an array");
}
return msg;
Mit global.set() wird das Objekt unter dem Namen “deviceNames_BSH” im globalen Context gespeichert. Das bedeutet, dass diese Daten über alle Flows hinweg verfügbar sind und sogar nach einem Neustart von Node-RED erhalten bleiben.

Die Warnmeldung ist optional, aber hilfreich bei der Fehlerbehebung, da sie im Debug-Bereich anzeigt, dass der Prozess erfolgreich abgeschlossen wurde.
Implementierung in Node-RED
Um diesen Code in Node-RED zu implementieren, musst du einen Flow erstellen, der folgendermaßen aufgebaut ist:
- Ein Inject-Node, der regelmäßig ausgelöst wird (z.B. einmal täglich)
- Ein HTTP-Request-Node, der die Geräte vom Bosch Smart Home System abruft
- Der Function-Node mit dem oben beschriebenen Code
- Optional: Ein Debug-Node zur Überprüfung der Ausgabe
Hier ist ein Beispiel, wie der vollständige Flow aussehen könnte:
Sobald du den Flow implementiert hast, wird er die Gerätenamen im globalen Context speichern. Du kannst die gespeicherten Daten überprüfen, indem du in einem beliebigen Function-Node folgenden Code ausführst:
// Load the saved device names let deviceNames = global.get("deviceNames_BSH"); node.warn(JSON.stringify(deviceNames, null, 2)); return msg;
Dieser Code gibt die gespeicherten Gerätenamen im Debug-Bereich aus.
Anwendungsbeispiele
Nun, da du alle Gerätenamen im globalen Context gespeichert hast, gibt es viele nützliche Anwendungsmöglichkeiten:
1. Zuweisung freundlicher Namen in MQTT-Nachrichten
Wenn du Daten von Bosch-Geräten über MQTT weiterleitest, kannst du die Geräte-ID in einen benutzerfreundlichen Namen umwandeln:
// Load the saved device names let deviceNames = global.get("deviceNames_BSH"); let deviceId = msg.payload.id;
// Extract the relevant part of the ID
let key = null;
if (deviceId.startsWith("hdm:ZigBee:")) {
key = deviceId.substring("hdm:ZigBee:".length);
} else if (deviceId.startsWith("hdm:HomeMaticIP:")) {
key = deviceId.substring("hdm:HomeMaticIP:".length);
}
// Replace the ID with the friendly name
if (key && deviceNames[key]) {
msg.topic = bosch/device/${deviceNames[key]};
} else {
msg.topic = bosch/device/unknown/${deviceId};
}
return msg;
2. Dynamisches Dashboard
Du kannst ein Dashboard erstellen, das alle deine Geräte nach Räumen organisiert anzeigt:
// Load the saved device names let deviceNames = global.get("deviceNames_BSH"); let roomDevices = {};
// Group devices by room
Object.keys(deviceNames).forEach(key => {
let fullName = deviceNames[key];
let parts = fullName.split('.');
let roomName = parts;
text
if (!roomDevices[roomName]) {
roomDevices[roomName] = [];
}
roomDevices[roomName].push({
id: key,
name: parts.slice(1).join('.')
});
});
msg.payload = roomDevices;
return msg;
3. Ereignisse filtern
Du kannst eingehende Ereignisse basierend auf dem Raum oder Gerätenamen filtern:
// Load the saved device names let deviceNames = global.get("deviceNames_BSH"); let deviceId = msg.payload.id; let key = null;
// Extract the relevant part of the ID
if (deviceId.startsWith("hdm:ZigBee:")) {
key = deviceId.substring("hdm:ZigBee:".length);
} else if (deviceId.startsWith("hdm:HomeMaticIP:")) {
key = deviceId.substring("hdm:HomeMaticIP:".length);
}
// Check if the device is in the living room
if (key && deviceNames[key] && deviceNames[key].startsWith("Wohnzimmer.")) {
return [msg, null]; // Send to the first output
} else {
return [null, msg]; // Send to the second output
}
Fazit
Das Speichern der Gerätenamen des Bosch Smart Home Systems im globalen Context von Node-RED ist eine leistungsstarke Methode, um deine Smart Home Automatisierungen übersichtlicher und effizienter zu gestalten. Mit diesem Ansatz kannst du:
- Menschenlesbare Namen für deine Geräte in Flows verwenden
- Geräte nach Räumen gruppieren
- Komplexe Automatisierungen basierend auf Raum- und Gerätenamen erstellen
- Zeit sparen bei der Entwicklung neuer Flows
Die Kombination mit dem vorherigen Artikel zum Speichern von Raumnamen im globalen Context schafft eine umfassende Struktur für deine Bosch Smart Home Automatisierungen in Node-RED.
Vergiss nicht, den Flow regelmäßig ausführen zu lassen (z.B. täglich oder nach Änderungen in deinem Smart Home Setup), um sicherzustellen, dass die gespeicherten Informationen aktuell bleiben.
Der komplette Flow zum Importieren
[{"id":"c2e8f3a90731af55","type":"http request","z":"f48cf010.9333b","name":"Device Names","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://192.168.178.186:8444/smarthome/devices/","tls":"9b926ab94fdcfb8e","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":3820,"y":1540,"wires":[["6e2c454b350f53ea"]]},{"id":"2161a2331285f08a","type":"inject","z":"f48cf010.9333b","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"00 12 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":3610,"y":1500,"wires":[["c2e8f3a90731af55"]]},{"id":"6e2c454b350f53ea","type":"function","z":"f48cf010.9333b","name":"deviceNames","func":"// Initialize an object to store ID-name mappings\nlet deviceNames_BSH = {};\n\n// Load room names from the global context\nlet roomNames_BSH = global.get(\"roomNames_BSH\") || {};\n\n // Check if msg.payload is an array\nif (Array.isArray(msg.payload)) {\n msg.payload.forEach(device => {\n let id = device.id;\n let name = device.name;\n let key = null;\n let roomName = \"Unknown Room\"; // Default value if no room is found\n\n // Extract the key based on the device protocol\n if (id.startsWith(\"hdm:ZigBee:\")) {\n key = id.substring(\"hdm:ZigBee:\".length);\n } else if (id.startsWith(\"hdm:HomeMaticIP:\")) {\n key = id.substring(\"hdm:HomeMaticIP:\".length);\n }\n\n if (key) {\n // Optional: Assuming each device has a room ID, e.g., device.roomId\n // Adjust this according to the actual structure of your device object\n if (device.roomId && roomNames_BSH[device.roomId]) {\n roomName = roomNames_BSH[device.roomId];\n }\n\n // Replace all spaces with dots in roomName and name\n let sanitizedRoomName = roomName.replace(/\\s+/g, '.');\n let sanitizedName = name.replace(/\\s+/g, '.');\n\n // Add the room name to the device name\n let fullName = `${sanitizedRoomName}.${sanitizedName}`;\n\n deviceNames_BSH[key] = fullName;\n }\n });\n\n // Save the object in the global context under \"deviceNames_BSH\"\n global.set(\"deviceNames_BSH\", deviceNames_BSH);\n\n // Optional: Output for verification\n node.warn(\"Device names with room names saved in the global context under 'deviceNames_BSH'\");\n} else {\n node.error(\"msg.payload is not an array\");\n}\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":4040,"y":1540,"wires":[["c511faf4d399103b"]]},{"id":"c511faf4d399103b","type":"debug","z":"f48cf010.9333b","name":"debug 18","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":4220,"y":1540,"wires":[]},{"id":"9b926ab94fdcfb8e","type":"tls-config","name":"Controller","cert":"","key":"","ca":"","certname":"client-cert.pem","keyname":"client-key.pem","caname":"","servername":"","verifyservercert":false,"alpnprotocol":""}]
Add comment