|
2 | 2 | * ============================================================================== |
3 | 3 | * ioBroker Script: Automatische Bettbeleuchtung |
4 | 4 | * ============================================================================== |
5 | | - * @version 1.1.0 |
| 5 | + * @version 1.1.3 |
6 | 6 | * @author Sanweb |
7 | 7 | * @license MIT License |
8 | 8 | * @description |
|
32 | 32 | // ============================================ |
33 | 33 | const DP = { |
34 | 34 | links: { |
35 | | - ledCmd: 'mqtt.1.zigbee2mqtt.Bettlicht_Rosie.set', // MQTT Set-Datenpunkt für links |
| 35 | + ledCmd: 'mqtt.1.zigbee2mqtt.Bettlicht Rosie.set', // ioBroker ID (ohne Unterstrich) |
| 36 | + ledTopic: 'zigbee2mqtt/Bettlicht Rosie/set', // Echtes MQTT Topic |
36 | 37 | motion: 'zigbee2mqtt.0.0xa4c1387d7ee56494.presence', // Zigbee Bewegungsmelder |
37 | 38 | matte: 'hm-rpc.0.001E1D899E94B0.1.STATE' // Homematic Kontaktmatte |
38 | 39 | }, |
39 | 40 | rechts: { |
40 | | - ledCmd: 'mqtt.1.zigbee2mqtt.Bettlicht_Alex.set', // MQTT Set-Datenpunkt für rechts |
| 41 | + ledCmd: 'mqtt.1.zigbee2mqtt.Bettlicht Alex.set', // ioBroker ID (ohne Unterstrich) |
| 42 | + ledTopic: 'zigbee2mqtt/Bettlicht Alex/set', // Echtes MQTT Topic |
41 | 43 | motion: 'zigbee2mqtt.0.0xa4c138f5aeea45b6.presence', // Zigbee Bewegungsmelder |
42 | 44 | matte: 'hm-rpc.0.001E1D899E922D.1.STATE' // Homematic Kontaktmatte |
43 | 45 | }, |
|
75 | 77 | // Hilfsfunktionen: Logging & Timer Cleanup |
76 | 78 | // ============================================ |
77 | 79 |
|
78 | | - /** |
79 | | - * Loggt eine Nachricht mit dem konfigurierten Präfix |
80 | | - * @param {string} msg - Die Log-Nachricht |
81 | | - * @param {'info' | 'warn' | 'error' | 'debug' | 'silly'} [level='info'] - Das ioBroker Log-Level |
82 | | - */ |
83 | 80 | function scriptLog(msg, level = 'info') { |
84 | 81 | log(CONFIG.logPrefix + msg, level); |
85 | 82 | } |
|
106 | 103 | // ============================================ |
107 | 104 | scriptLog('Führe Systemprüfung der Datenpunkte durch...', 'info'); |
108 | 105 |
|
109 | | - // MQTT Datenpunkte prüfen und ggf. automatisch anlegen |
110 | | - const mqttDPs = [DP.links.ledCmd, DP.rechts.ledCmd]; |
111 | | - for (const id of mqttDPs) { |
112 | | - if (!existsState(id)) { |
113 | | - scriptLog(`MQTT Datenpunkt ${id} fehlt. Versuche Erstellung in fremdem Namensraum...`, 'warn'); |
| 106 | + // MQTT Datenpunkte prüfen und ggf. automatisch mit exaktem Topic anlegen |
| 107 | + const mqttTargets = [ |
| 108 | + { id: DP.links.ledCmd, topic: DP.links.ledTopic }, |
| 109 | + { id: DP.rechts.ledCmd, topic: DP.rechts.ledTopic } |
| 110 | + ]; |
| 111 | + |
| 112 | + for (const target of mqttTargets) { |
| 113 | + if (!existsState(target.id)) { |
| 114 | + scriptLog(`MQTT Datenpunkt ${target.id} fehlt. Wird mit Ziel-Topic "${target.topic}" angelegt...`, 'warn'); |
114 | 115 |
|
115 | | - setObject(id, { |
| 116 | + setObject(target.id, { |
116 | 117 | type: 'state', |
117 | 118 | common: { |
118 | | - name: id.split('.').pop(), |
| 119 | + name: 'set', |
119 | 120 | type: 'string', |
120 | 121 | role: 'state', |
121 | 122 | read: true, |
122 | 123 | write: true, |
123 | 124 | desc: 'Automatisch angelegt durch Bettlicht-Skript' |
124 | 125 | }, |
125 | | - native: {} |
| 126 | + native: { |
| 127 | + topic: target.topic // <--- HIER IST DIE MAGIE: Das exakte MQTT Topic für den Adapter! |
| 128 | + } |
126 | 129 | }, function(err) { |
127 | 130 | if (err) { |
128 | | - scriptLog(`FEHLER beim Anlegen von ${id}: ${err} -> Bitte in den JavaScript-Instanz-Einstellungen "Erlaube das Kommando setObj" aktivieren!`, 'error'); |
| 131 | + scriptLog(`FEHLER beim Anlegen von ${target.id}: ${err}`, 'error'); |
129 | 132 | } else { |
130 | | - scriptLog(`Erfolgreich angelegt: ${id}`, 'info'); |
| 133 | + scriptLog(`Erfolgreich angelegt: ${target.id}`, 'info'); |
131 | 134 | // Startwert setzen |
132 | | - setState(id, JSON.stringify({ state: "OFF" }), true); |
| 135 | + setState(target.id, JSON.stringify({ state: "OFF" }), true); |
133 | 136 | } |
134 | 137 | }); |
135 | 138 | } |
|
176 | 179 | const ledCmdId = DP[side].ledCmd; |
177 | 180 | const payloadString = JSON.stringify({ state: state ? "ON" : "OFF" }); |
178 | 181 |
|
179 | | - // Letzter gesendeter Befehl (da .set kein echter Status-DP ist, enthält er nur den letzten String) |
180 | 182 | const rawCurrent = existsState(ledCmdId) ? getState(ledCmdId)?.val : null; |
181 | 183 |
|
182 | 184 | if (!CONFIG.forceSend && rawCurrent === payloadString) { |
183 | 185 | debugLog(`Licht ${side}: bereits ${state ? 'AN' : 'AUS'}, blockiert durch Schonung`); |
184 | 186 | return; |
185 | 187 | } |
186 | 188 |
|
187 | | - // WICHTIG: Das 'false' als 3. Parameter ist das ack-Flag. |
188 | | - // false = Befehl an Hardware senden (Command) |
189 | 189 | setState(ledCmdId, payloadString, false); |
190 | 190 | scriptLog(`Licht ${side}: ${state ? 'AN' : 'AUS'} (MQTT Payload: ${payloadString})`, 'info'); |
191 | 191 | } |
|
205 | 205 | return; |
206 | 206 | } |
207 | 207 |
|
208 | | - // Logik: Matte = leer UND Motion = true |
209 | 208 | if (isMatteEmpty && isMotion) { |
210 | 209 | setLight(side, true); |
211 | 210 |
|
|
228 | 227 | // ============================================ |
229 | 228 | ['links', 'rechts'].forEach(side => { |
230 | 229 |
|
231 | | - // Trigger: Bewegung |
232 | 230 | on({ id: DP[side].motion, change: 'any' }, function(obj) { |
233 | 231 | const motionVal = parseBool(obj.state?.val); |
234 | 232 | const isOccupied = getMatteOccupiedState(getState(DP[side].matte)?.val); |
|
238 | 236 | processSide(side, motionVal, isOccupied, nachtVal); |
239 | 237 | }); |
240 | 238 |
|
241 | | - // Trigger: Kontaktmatte |
242 | 239 | on({ id: DP[side].matte, change: 'any' }, function(obj) { |
243 | 240 | const isOccupied = getMatteOccupiedState(obj.state?.val); |
244 | 241 | const motionVal = parseBool(getState(DP[side].motion)?.val); |
|
0 commit comments