NEWS
Hue Push API für Hue Adapter
-
@Pman Klasse Script! Hat meine Bewegungsmelder Schaltung erst möglich gemacht.
Nun habe ich leider ein Problem, dass ich nicht gelöst bekomme:
Ich habe einen ZGPSwitch (Senic Friends of Hue) der nicht mit push updated (per polling ja, aber langsam). Ein anderer Friends of hue switch updated per push gut. ZLLSwitches gehen ebenfalls. Gibt es da irgendeinen Trick, oder Dinge die ich ausprobieren kann? Im Log finde ich nix... -
Bisher hat Philips die Push API nicht offiziell released und sie wird noch nicht vom Hue-Adapter unterstützt. Dieses Skript baut eine Verbindung zur Bridge auf und aktualisiert entsprechende States "live", ich empfehle das polling im Adapter zu deaktivieren. Welche Datenpunkte aktualisiert werden kann man in der UPDATEMAP nachlesen.
Weitere Hinweise siehe Skript.
Update
1.1.0 hue-extended support
1.1.1 ZGPSwitch support
1.1.2 bekannte push calls ignorieren um weniger log zu erzeugen
1.1.3 Zone support (only on)/** * Version: 1.1.3 (HUE + HUE-EXTENDED) * Anleitung: * - npm-Modul im Javascript-Adapter hinzufügen (Adaptereinstellung): hue-push-client * - IP: IP der Bridge eintragen * - TOKEN: gültigen User für die Bridge eintragen (z.B. aus der Hue Adapter Konfiguration) * - INSTANCE: korrekte Instanz eingeben, meist hue.0 oder hue-extended.0 **/ const IP = '<bridge ip>'; const TOKEN = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; const INSTANCE = 'hue.0'; /** * DO NOT EDIT BELOW **/ const UPDATEMAP_HUE = { //lights 'lights.status.status': {stateName: 'reachable', convert: (val) => {return val === 'connected' ? true : false;}, validTypes: ['Extended color light', 'Color temperature light', 'Dimmable light', 'On/Off plug-in unit'], after: (stateId, value) => {updateHueState(stateId.substring(0, stateId.lastIndexOf('.')) + '.on', value)}}, 'lights.on.on': {stateName: 'on', validTypes: ['Extended color light', 'Color temperature light', 'Dimmable light', 'On/Off plug-in unit']}, 'lights.dimming.brightness': {stateName: 'level', convert: (val) => {return Math.ceil(val)}, validTypes: ['Extended color light', 'Color temperature light', 'Dimmable light'], after: (stateId, value) => {updateRGBHue(stateId.substring(0, stateId.lastIndexOf('.')))}}, 'lights.color_temperature.mirek': {stateName: 'ct', convert: (val) => {return Math.round(1000000/val)}, validTypes: ['Extended color light', 'Color temperature light']}, 'lights.color.xy': {stateName: 'xy', convert: (val) => {return val.x + ',' + val.y}, validTypes: ['Extended color light'], after: (stateId, value) => {updateRGBHue(stateId.substring(0, stateId.lastIndexOf('.')))}}, //groups 'groups.on.on': {stateName: 'on', validTypes: ['Room', 'LightGroup', 'Zone']}, //sensors 'sensors.motion.motion': {stateName: 'presence', validTypes: ['ZLLPresence']}, 'sensors.light.light_level': {stateName: 'lightlevel', convert: (val) => {return Math.round(val)}, validTypes: ['ZLLLightLevel']}, 'sensors.temperature.temperature': {stateName: 'temperature', convert: (val) => {return Number.parseFloat(val.toPrecision(4))}, validTypes: ['ZLLTemperature']}, 'sensors.power_state.battery_level': {stateName: 'battery', convert: (val) => {return Math.round(val)}, validTypes: ['ZLLPresence', 'ZLLLightLevel', 'ZLLTemperature', 'ZLLSwitch']}, //buttons 'sensors.button.last_event': {stateName: 'buttonevent', convert: (val) => {return ((UUIDs[this.idv2] && UUIDs[this.idv2].metadata) ? UUIDs[this.idv2].metadata.control_id : 0) * 1000 + (val === 'repeat' ? 1 : 0) + (val === 'short_release' ? 2 : 0) + (val === 'long_release' ? 3 : 0)}, validTypes: ['ZLLSwitch', 'ZGPSwitch']}, //ignore 'lights.owner.rid':{}, 'lights.owner.rtype':{}, 'sensors.owner.rid':{}, 'sensors.owner.rtype':{}, 'sensors.power_state.battery_state': {}, }; const UPDATEMAP_HUE_EXTENDED = { //lights 'lights.status.status': {stateName: 'state.reachable', convert: (val) => {return val === 'connected' ? true : false;}, validTypes: ['Extended color light', 'Color temperature light', 'Dimmable light', 'On/Off plug-in unit']}, 'lights.on.on': {stateName: 'action.on', validTypes: ['Extended color light', 'Color temperature light', 'Dimmable light', 'On/Off plug-in unit']}, 'lights.dimming.brightness': {stateName: 'action.level', convert: (val) => {return Math.ceil(val)}, validTypes: ['Extended color light', 'Color temperature light', 'Dimmable light'], after: (stateId, value) => {updateRGBHueExtended(stateId.substring(0, stateId.lastIndexOf('.')))}}, 'lights.color_temperature.mirek': {stateName: 'action.colorTemperature', convert: (val) => {return Math.round(1000000/val)}, validTypes: ['Extended color light', 'Color temperature light']}, 'lights.color.xy': {stateName: 'action.xy', convert: (val) => {return val.x + ',' + val.y}, validTypes: ['Extended color light'], after: (stateId, value) => {updateRGBHueExtended(stateId.substring(0, stateId.lastIndexOf('.')))}}, //groups 'groups.on.on': {stateName: 'state.any_on', validTypes: ['Room', 'LightGroup', 'Zone']}, //sensors 'sensors.motion.motion': {stateName: 'state.presence', convert: (val) => {return val.toString()}, validTypes: ['ZLLPresence']}, 'sensors.light.light_level': {stateName: 'state.lightlevel', convert: (val) => {return Math.round(val).toString()}, validTypes: ['ZLLLightLevel']}, 'sensors.temperature.temperature': {stateName: 'state.temperature', convert: (val) => {return Number.parseFloat(val.toPrecision(4))}, validTypes: ['ZLLTemperature']}, 'sensors.power_state.battery_level': {stateName: 'config.battery', convert: (val) => {return Math.round(val)}, validTypes: ['ZLLPresence', 'ZLLLightLevel', 'ZLLTemperature', 'ZLLSwitch']}, //buttons 'sensors.button.last_event': {stateName: 'state.buttonevent', convert: (val) => {return ((UUIDs[this.idv2] && UUIDs[this.idv2].metadata) ? UUIDs[this.idv2].metadata.control_id : 0) * 1000 + (val === 'short_release' ? 2 : 0) + (val === 'long_release' ? 3 : 0)}, validTypes: ['ZLLSwitch', 'ZGPSwitch']}, //ignore 'lights.owner.rid':{}, 'lights.owner.rtype':{}, 'sensors.owner.rid':{}, 'sensors.owner.rtype':{}, 'sensors.power_state.battery_state': {}, }; //select UPDATEMAP for hue or hue-extended const UPDATEMAP = INSTANCE.toLowerCase().includes('extended') ? UPDATEMAP_HUE_EXTENDED : UPDATEMAP_HUE; const findState = INSTANCE.toLowerCase().includes('extended') ? findStateHueExtended : findStateHue; //connect to event stream const HuePushClient = require('hue-push-client'); const client = new HuePushClient({ip: IP, user: TOKEN}); client.addEventListener('open', function () { log('connected'); }); client.addEventListener('close', function () { log('disconnected', 'warn'); }); client.addEventListener('error', function (e) { log('connection error: ' + e.message, 'warn'); }); client.addEventListener('message', function (packet) { parsePacket(packet); }); //get resouce ids (required to identify buttons) let UUIDs = {}; async function getUUIDs() { try { UUIDs = await client.uuids(); } catch (e) { log(e, 'warn'); } }; getUUIDs(); // close connection if script is stopped onStop(function (callback) { client.close(); callback(); }, 2000); function parsePacket (packet) { log('RECEIVED PACKET: ' + "\n" + JSON.stringify(packet), 'debug'); try { if (!packet.data) { log('packet has no data: ' + JSON.stringify(packet), 'warn'); return; } for (let message of JSON.parse(packet.data)) { if (message.type !== 'update') { log ('unknown message type: ' + JSON.stringify(message), 'warn'); continue; } if (typeof message.data !== 'object') { log ('message contains no data: ' + JSON.stringify(message), 'warn'); continue; } for (let update of message.data) { parseUpdate(update); } } } catch (e) { log('could not read packet: ' + JSON.stringify(packet), 'warn'); log(e.message, 'warn'); return; } } function parseUpdate(update) { log('PARSING UPDATE: ' + "\n" + JSON.stringify(update), 'debug'); if (!update.id_v1) return; const [resource, idv1] = update.id_v1.split('/').filter(Boolean); const idv2 = update.id; //remove id, id_v1, type delete update.id; delete update.id_v1; delete update.type; //status to object as other updates are objects if (update.status) { update.status = {status: update.status}; } processUpdate(resource, idv1, idv2, update); } let IdCache = []; function processUpdate(resource, resourceId, idv2, data) { this.resource = resource; this.resourceId = resourceId; this.idv2 = idv2; this.data = data; log('PROCESSING UPDATE: ' + 'resource ' + resource + "\n" + JSON.stringify(data), 'debug'); //check for values to data for (let action in data) { if (typeof data[action] !== 'object') {continue;} //check if update invalid and delete _valid entries for (let endpoint in data[action]) { if (endpoint.substr(-6) === '_valid') { if (!data[action][endpoint]) { log('skipping invalid value' + resource + '.' + action + '.' + endpoint, 'debug'); return; } else { delete data[action][endpoint]; } } } //find hue adapter states to update and set new values for (let endpoint in data[action]) { if (UPDATEMAP[resource + '.' + action + '.' + endpoint]) { log('found UPDATEMAP for ' + resource + '.' + action + '.' + endpoint, 'debug'); let updateValue = data[action][endpoint]; //convert value? if (typeof UPDATEMAP[resource + '.' + action + '.' + endpoint].convert === 'function') { let updateValueOld = updateValue; updateValue = UPDATEMAP[resource + '.' + action + '.' + endpoint].convert.call(this, updateValue); log('converted ' + resource + '.' + action + '.' + endpoint + ' from ' + updateValueOld + ' to ' + updateValue, 'debug'); } let stateName = UPDATEMAP[resource + '.' + action + '.' + endpoint].stateName; //check if state id is cached if (!IdCache[resource + '.' + resourceId + '.' + stateName]) { findState(resource, resourceId, stateName, action, endpoint, () => { updateHueState(IdCache[resource + '.' + resourceId + '.' + stateName], updateValue, UPDATEMAP[resource + '.' + action + '.' + endpoint].after); }); } else { log('found cache entry for ' + resource + '.' + resourceId + '.' + stateName + ': ' + IdCache[resource + '.' + resourceId + '.' + stateName], 'debug'); updateHueState(IdCache[resource + '.' + resourceId + '.' + stateName], updateValue, UPDATEMAP[resource + '.' + action + '.' + endpoint].after); } } else { log('missing update instructions for ' + resource + '.' + action + '.' + endpoint); log(JSON.stringify(data)); } } } } async function findStateHue(resource, resourceId, stateName, action, endpoint, callback) { log('searching for object with id ' + resourceId + ' and stateName ' + stateName, 'debug'); $(INSTANCE + '.*' + '.' + stateName).each(function (stateId, i) { //better way to find matching objects? getObject(stateId, (err, obj) => { if (!err) { if (obj.native && obj.native.id && obj.native.id == resourceId) { log('found ' + stateId + ', checking parent for matching type...', 'debug'); //get parent object and check type let parentId = stateId.substring(0, stateId.lastIndexOf('.')); getObject(parentId, (err2, obj2) => { if (!err2) { if (obj2.native && obj2.native.type && UPDATEMAP[resource + '.' + action + '.' + endpoint].validTypes.indexOf(obj2.native.type) !== -1 && !IdCache[resource + '.' + resourceId + '.' + stateName]) { log('found matching type for ' + parentId + ': ' + obj2.native.type, 'debug'); log('save cache entry "' + resource + '.' + resourceId + '.' + stateName + '":' + stateId, 'debug'); IdCache[resource + '.' + resourceId + '.' + stateName] = stateId; callback(); } } else { log('could not find obj: ' + stateId, 'warn'); } }); } } else { log('could not find obj: ' + stateId, 'warn'); } }); }); } async function findStateHueExtended(resource, resourceId, stateName, action, endpoint, callback) { log('searching for object with id ' + resourceId + ' and stateName ' + stateName, 'debug'); $(INSTANCE + '.' + resource + '.*' + '.uid').each(async (stateId, i) => { //better way to find matching objects? const deviceId = await getStateAsync(stateId); //check if device id matches if (deviceId.val !== resourceId) { return; } const device = stateId.substr(0,stateId.length-4); //make sure final object exists const stateExists = await existsObjectAsync(device + '.' + stateName); if (!stateExists) { return; } //check if type is valid and save cache entry const deviceType = await getStateAsync(device + '.type'); if (UPDATEMAP[resource + '.' + action + '.' + endpoint].validTypes.indexOf(deviceType.val) !== -1 && !IdCache[resource + '.' + resourceId + '.' + stateName]) { log('found matching type for ' + resourceId + ': ' + deviceType.val, 'debug'); log('save cache entry "' + resource + '.' + resourceId + '.' + stateName + '":' + device + '.' + stateName, 'debug'); IdCache[resource + '.' + resourceId + '.' + stateName] = device + '.' + stateName; callback(); } }); } function updateHueState(stateId, value, after) { log('set ' + stateId + ' to ' + value + ' (' + typeof value + ')', 'debug'); setStateDelayed(stateId, value, true, 50, true, () => { if (typeof after === 'function') { log ('running function after change of ' + stateId, 'debug'); after(stateId, value); } }); } //helpers async function updateRGBHue(stateId) { let xyState = await getStateAsync(stateId + '.xy'); if (!xyState) return; let xy = xyState.val.replace('[', '').replace(']', '').split(','); let levelState = await getStateAsync(stateId + '.level'); let level = levelState.val / 100; //let onState = await getStateAsync(stateId + '.on'); //if (onState.val === false) level = 0; let rgb = HelperXYBtoRGB(xy[0], xy[1], level); updateHueState(stateId + '.r', Math.round(rgb.Red * 255)); updateHueState(stateId + '.g', Math.round(rgb.Green * 255)); updateHueState(stateId + '.b', Math.round(rgb.Blue * 255)); } async function updateRGBHueExtended(stateId) { let xyState = await getStateAsync(stateId + '.xy'); if (!xyState) return; let xy = xyState.val.replace('[', '').replace(']', '').split(','); let levelState = await getStateAsync(stateId + '.level'); let level = levelState.val / 100; let rgb = HelperXYBtoRGB(xy[0], xy[1], level); updateHueState(stateId + '.rgb', Math.round(rgb.Red * 255) + ',' + Math.round(rgb.Green * 255) + ',' + Math.round(rgb.Blue * 255)); } function HelperXYBtoRGB (x, y, Brightness) { // Source: https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md if (Brightness <= 0) { return {Red: 0, Green: 0, Blue: 0}; } Brightness = Brightness || 1.0; // Default full brightness const z = 1.0 - x - y; const Y = Brightness; const X = (Y / y) * x; const Z = (Y / y) * z; // XYZ to RGB [M]-1 for Wide RGB D65, http://www.developers.meethue.com/documentation/color-conversions-rgb-xy let Red = X * 1.656492 - Y * 0.354851 - Z * 0.255038; let Green = -X * 0.707196 + Y * 1.655397 + Z * 0.036152; let Blue = X * 0.051713 - Y * 0.121364 + Z * 1.011530; // Limit RGB on [0..1] if (Red > Blue && Red > Green && Red > 1.0) { // Red is too big Green = Green / Red; Blue = Blue / Red; Red = 1.0; } if (Red < 0) { Red = 0; } if (Green > Blue && Green > Red && Green > 1.0) { // Green is too big Red = Red / Green; Blue = Blue / Green; Green = 1.0; } if (Green < 0) { Green = 0; } if (Blue > Red && Blue > Green && Blue > 1.0) { // Blue is too big Red = Red / Blue; Green = Green / Blue; Blue = 1.0; } if (Blue < 0) { Blue = 0; } // Apply reverse gamma correction if (Red <= 0.0031308) { Red = Red * 12.92; } else { Red = 1.055 * Math.pow(Red, (1.0 / 2.4)) - 0.055; } if (Green <= 0.0031308) { Green = Green * 12.92; } else { Green = 1.055 * Math.pow(Green, (1.0 / 2.4)) - 0.055; } if (Blue <= 0.0031308) { Blue = Blue * 12.92; } else { Blue = 1.055 * Math.pow(Blue, (1.0 / 2.4)) - 0.055; } // Limit RGB on [0..1] if (Red > Blue && Red > Green && Red > 1.0) { // Red is too big Green = Green / Red; Blue = Blue / Red; Red = 1.0; } if (Red < 0) { Red = 0; } if (Green > Blue && Green > Red && Green > 1.0) { // Green is too big Red = Red / Green; Blue = Blue / Green; Green = 1.0; } if (Green < 0) { Green = 0; } if (Blue > Red && Blue > Green && Blue > 1.0) { // Blue is too big Red = Red / Blue; Green = Green / Blue; Blue = 1.0; } if (Blue < 0) { Blue = 0; } return {Red: Red, Green: Green, Blue: Blue}; };@pman Kann auch das objekt colormode (ct oder xy) auch per push abgefragt werden? Brauche das um den aktuellen Status einer Lampe zu speichern und dann später wieder aufzurufen. Nur deswegen habe ich aktuell noch polling parallel an. Das führt bei FoH Schaltern aber zu Problemen da beim Polling andere Werte zurückgegeben werden als beim Push Script.
Polling gibt 20,21, etc... und beim Script ist es 2000, 2001, etc... (nutze die den Hue adapter)Also entweder bei FoH Schaltern das gleiche zurückgeben wie beim polling, oder colormode integrieren ;).
-
Hallo,
bei mir und einem Kumpel hängt sich das Script nach 14 Tage auf. Heißt die Datenpunkte werden nicht mehr gepollt. Die Konfiguration ist bei beiden gleich. Es werden bei uns nur Hue Bewegungsmelder zur Weiterverarbeitung synchronisiert. Wenn ich den ganzen Java Adapter neustarte besteht das Problem weiterhin. Drücke ich in den Scripten einmal auf Stop und Start funktioniert das ganze wieder. Habe das ganze jetzt mehrfach über Wochen geprüft und gegen gecheckt.
Gibt es eine Möglichkeit nur das Script Zeitgesteuert neu zu starten? -
Hallo,
bei mir und einem Kumpel hängt sich das Script nach 14 Tage auf. Heißt die Datenpunkte werden nicht mehr gepollt. Die Konfiguration ist bei beiden gleich. Es werden bei uns nur Hue Bewegungsmelder zur Weiterverarbeitung synchronisiert. Wenn ich den ganzen Java Adapter neustarte besteht das Problem weiterhin. Drücke ich in den Scripten einmal auf Stop und Start funktioniert das ganze wieder. Habe das ganze jetzt mehrfach über Wochen geprüft und gegen gecheckt.
Gibt es eine Möglichkeit nur das Script Zeitgesteuert neu zu starten?@alveran bei mir hält das Script seit mittlerweile mehr als 8 Wochen keinen Tag mehr durch, nicht mal einen halben. Ich lasse es via Blockly jede Stunde neu starten. Unter Objekte/javascript/0/scriptEnabled findest Du alle Scripte und kannst den Datenpunkt einfach auf false setzen und dann wieder auf true.
Wie gesagt, ich mache das via Blockly Script jede Std.
Warum es auf einmal nicht mehr funktioniert (davor gab es nie ein Problem) schiebe ich in meinem Fall auf die Nutzung des Zigbee-Adapters, obwohl der Kanal, den er nutzt, frei ist. Aber seitdem der läuft habe ich die Probleme (zumindest ist es mir danach erst aufgefallen). -
Ich habe das Skript seit ca. 1.5 Monaten in Betrieb.
Schon am dritten Tag funktionierte es nicht mehr.
Dann das Skript neugestartet und seitdem läuft es.
Sehr komisch das Ganze. -
Nachdem ich nun eine weitere javascript-Instanz installiert habe und die beiden (ich habe zwei Hue Bridges) Push-Scripte in die Instanz 1 verschoben habe, laufen sie seit 24 Std durch?! Also scheinbar ist irgendwas in meiner javascript.0 Instanz was sie regelmäßig nach ein oder zwei Std stoppen lässt.
(Docker Image mit MACVLAN, DS1821+, 32GB RAM) -
Hallo, riesen Dank erstmal für das Script. Endlich funktionieren die BWM ohne ewige Wartezeit. Ich hab jetzt aber das Problem das mir bei einigen Lampen der DP "on" als "true" angezeigt werden obwohl sie ausgeschalten sind. Wenn ich sie dann ein und ausschalte stimmt der DP wieder bis er nach einiger Zeit wieder auf "true" springt ohne das die Lampe geschalten wurde. Ich hab die entsprechenden Lampen schon mal gelöscht und wieder neu angelernt sowie die DP gelöscht. Im Javascript Adapter hab ich "setObject" erlaubt und Polling im HUE Adpter deaktiviert. Ich nutze den normalen HUE Adapter
-
Hallo,
leider bekomme ich das script nicht zum laufen. Hab alles beachtet aber ich bekomme immer folgende Meldung es aktualisiert rein gar nichts.17:35:21.509 warn javascript.1 (4623) script.js.common.Hue.pushHue: could not read packet: {"type":"message","data":"[{\"creationtime\":\"2022-11-23T16:35:21Z\",\"data\":[{\"id\":\"5b80b735-89f1-4299-86ec-8e8f3a6a398c\",\"id_v1\":\"/lights/19\",\"on\":{\"on\":true},\"owner\":{\"rid\":\"8600a8a9-4da7-44ce-bae4-2a4d32e1b11a\",\"rtype\":\"device\"},\"type\":\"light\"},{\"id\":\"e62b1ce1-483e-40e5-8aba-9152d780f486\",\"id_v1\":\"/groups/0\",\"on\":{\"on\":true},\"owner\":{\"rid\":\"bf44f813-282a-4189-97f1-559398dc690a\",\"rtype\":\"bridge_home\"},\"type\":\"grouped_light\"},{\"dimming\":{\"brightness\":100.0},\"id\":\"e62b1ce1-483e-40e5-8aba-9152d780f486\",\"id_v1\":\"/groups/0\",\"owner\":{\"rid\":\"bf44f813-282a-4189-97f1-559398dc690a\",\"rtype\":\"bridge_home\"},\"type\":\"grouped_light\"},{\"id\":\"a77c0c6e-4e0b-44f6-bb97-87a2f513e84a\",\"id_v1\":\"/groups/9\",\"on\":{\"on\":true},\"owner\":{\"rid\":\"c40c5d3c-a2b4-412a-b138-37ae94d6b5ad\",\"rtype\":\"zone\"},\"type\":\"grouped_light\"},{\"dimming\":{\"brightness\":100.0},\"id\":\"a77c0c6e-4e0b-44f6-bb97-87a2f513e84a\",\"id_v1\":\"/groups/9\",\"owner\":{\"rid\":\"c40c5d3c-a2b4-412a-b138-37ae94d6b5ad\",\"rtype\":\"zone\"},\"type\":\"grouped_light\"},{\"id\":\"c9875030-a2ab-4f16-b649-20fb727d8b44\",\"id_v1\":\"/groups/24\",\"on\":{\"on\":true},\"owner\":{\"rid\":\"b3876cb3-dff7-44b7-b664-ce80a32f6f45\",\"rtype\":\"room\"},\"type\":\"grouped_light\"},{\"dimming\":{\"brightness\":100.0},\"id\":\"c9875030-a2ab-4f16-b649-20fb727d8b44\",\"id_v1\":\"/groups/24\",\"owner\":{\"rid\":\"b3876cb3-dff7-44b7-b664-ce80a32f6f45\",\"rtype\":\"room\"},\"type\":\"grouped_light\"}],\"id\":\"577afbf3-0e1b-4e5a-a7b9-7dbb2f579925\",\"type\":\"update\"}]","lastEventId":"1669221321:0","origin":"https://192.168.2.77"} 17:35:21.509 warn javascript.1 (4623) script.js.common.Hue.pushHue: Cannot set property 'resource' of undefined -
Hallo @Pman ,
erst mal vielen Dank für dein Skript - es sieht für mich sehr vielversprechend aus, allerdings habe ich in der aktuellsten(?) Version 1.1.3 TypeScript-Fehler, die ich nicht einordnen kann...
Der Fehler lautet "ERROR: Expected 3 arguments, but got 2. " und kommt von der Funktion updateHueState() in Zeile 263. Dort werden 3 Parameter erwartet, aber z.B. in den Zeilen 285-287 der Funktion updateRGBHue() werden auch nur 2 Parameter übergeben.
In Zeile 194 beispielsweise wird die Funktion korrekt mit 3 Parametern aufgerufen:
updateHueState(IdCache[resource + '.' + resourceId + '.' + stateName], updateValue, UPDATEMAP[resource + '.' + action + '.' + endpoint].after);Was macht der 3. Parameter, ist dieser optional? Was ist dessen Aufgabe? Sollen da Funktionsaufrufe kaskadiert werden?
Ich habe den Funktionskopf mal wie folgt abgeändert und teste mal damit, möchte aber natürlich nicht, dass dann eine wichtige Funktion davon betroffen ist...
function updateHueState(stateId, value, after = null) { -
Hallo @Pman ,
erst mal vielen Dank für dein Skript - es sieht für mich sehr vielversprechend aus, allerdings habe ich in der aktuellsten(?) Version 1.1.3 TypeScript-Fehler, die ich nicht einordnen kann...
Der Fehler lautet "ERROR: Expected 3 arguments, but got 2. " und kommt von der Funktion updateHueState() in Zeile 263. Dort werden 3 Parameter erwartet, aber z.B. in den Zeilen 285-287 der Funktion updateRGBHue() werden auch nur 2 Parameter übergeben.
In Zeile 194 beispielsweise wird die Funktion korrekt mit 3 Parametern aufgerufen:
updateHueState(IdCache[resource + '.' + resourceId + '.' + stateName], updateValue, UPDATEMAP[resource + '.' + action + '.' + endpoint].after);Was macht der 3. Parameter, ist dieser optional? Was ist dessen Aufgabe? Sollen da Funktionsaufrufe kaskadiert werden?
Ich habe den Funktionskopf mal wie folgt abgeändert und teste mal damit, möchte aber natürlich nicht, dass dann eine wichtige Funktion davon betroffen ist...
function updateHueState(stateId, value, after = null) {Leider kommt danach die nächste Fehlermeldung:
TypeScript compilation failed: 'sensors.button.last_event': { stateName: 'buttonevent', convert: (val) => { return ((UUIDs[this.idv2] && UUIDs[this.idv2].metadata) ? UUIDs[this.idv2].metadata.control_id : 0) * 1000 + (val === 'repeat' ? 1 : 0) + (val === 'short_release' ? 2 : 0) + (val === 'long_release' ? 3 : 0); }, validTypes: ['ZLLSwitch', 'ZGPSwitch'] }, ^ ERROR: Object is possibly 'undefined'.Ich kenne mich zu wenig mit TypeScript aus, um beurteilen zu können, was ihm da nicht gefällt. Aber eigentlich wird mit dem Code ja nur eine Zahl generiert, die den Tastendrücken entspricht. Wo da was undefiniert sein könnte, ist mir schleierhaft - es wird ja eigentlich immer was zurückgegeben.
Aber vielleicht kann hier jemand mit TypeScript-Erfahrung einen Tip geben? -
Leider kommt danach die nächste Fehlermeldung:
TypeScript compilation failed: 'sensors.button.last_event': { stateName: 'buttonevent', convert: (val) => { return ((UUIDs[this.idv2] && UUIDs[this.idv2].metadata) ? UUIDs[this.idv2].metadata.control_id : 0) * 1000 + (val === 'repeat' ? 1 : 0) + (val === 'short_release' ? 2 : 0) + (val === 'long_release' ? 3 : 0); }, validTypes: ['ZLLSwitch', 'ZGPSwitch'] }, ^ ERROR: Object is possibly 'undefined'.Ich kenne mich zu wenig mit TypeScript aus, um beurteilen zu können, was ihm da nicht gefällt. Aber eigentlich wird mit dem Code ja nur eine Zahl generiert, die den Tastendrücken entspricht. Wo da was undefiniert sein könnte, ist mir schleierhaft - es wird ja eigentlich immer was zurückgegeben.
Aber vielleicht kann hier jemand mit TypeScript-Erfahrung einen Tip geben? -
Lösung gefunden. Es funktioniert schon nur nicht komplett.
Ich habe einen Raum hue_Badezimmer im Raum gibt es nur eine Lampe Deckenleuchte Badezimmer. Schalte ich nun in der App den Raum erkennt das Script das Licht und schaltet die Lampe Deckenleuchte Badezimmer den on-Datenpunkt auf true. Nur der on-Datenpunkt vom Raum hue_Badezimmer bleibt auf false.
Ist das generell so oder nur ein Problem bei mir?
Bei meinen Tests habe ich immer nur auf den Raum geschaut.
habe das gleiche Bild. Der Raum schaltet nicht auf z.B. .on = false, nur die Lampen darin selbst. Das Skript funktioniert also nicht mit Räumen? Ist das so gewollt oder mache ich was falsch?
Grüße, schönes neues Jahr und @Pman: danke für das super Skript!
-
habe das gleiche Bild. Der Raum schaltet nicht auf z.B. .on = false, nur die Lampen darin selbst. Das Skript funktioniert also nicht mit Räumen? Ist das so gewollt oder mache ich was falsch?
Grüße, schönes neues Jahr und @Pman: danke für das super Skript!
@ptr was heißt das gleiche Bild? Gleiches Bild wie wer? Bei mir funktioniert es meistens. Bei einem Raum habe ich das Problem das es nicht zuverlässig ist. Ich vermute das es nicht 100% von der Bridge kommt wenn die Lampe nicht nur in einem Raum ist sondern auch noch in einer Zone.
Ansonsten wird bei mir auch der Raum richtig umgestellt. Kann aber nur für den normalen Hue-Adapter sprechen.
-
@ptr was heißt das gleiche Bild? Gleiches Bild wie wer? Bei mir funktioniert es meistens. Bei einem Raum habe ich das Problem das es nicht zuverlässig ist. Ich vermute das es nicht 100% von der Bridge kommt wenn die Lampe nicht nur in einem Raum ist sondern auch noch in einer Zone.
Ansonsten wird bei mir auch der Raum richtig umgestellt. Kann aber nur für den normalen Hue-Adapter sprechen.
@cash das gleiche Bild, dass der Raum nicht aktualisiert wird, sondern nur die Lampen darin. (Hat „Antworten“ nicht verlinkt)
Das mit der Zonensache werde ich bei mir anschauen.
Es geht um den Hue-Adapter.Gibt es Unterschiede was man verwenden sollte? ZB keine Gruppen, sondern nur Räume und Zonen zB? Gibt es da kompatibleres zB?
-
@cash das gleiche Bild, dass der Raum nicht aktualisiert wird, sondern nur die Lampen darin. (Hat „Antworten“ nicht verlinkt)
Das mit der Zonensache werde ich bei mir anschauen.
Es geht um den Hue-Adapter.Gibt es Unterschiede was man verwenden sollte? ZB keine Gruppen, sondern nur Räume und Zonen zB? Gibt es da kompatibleres zB?
@ptr wie gesagt kann ich bei mir so nicht bestätigen. Was man verwendet hängt davon ab wie man Hue organisiert. Ich nutze viele Zonen und dort dann Szenen. Somit kann ich pro Raum die Lampen einfach über Szenen unterschiedlich steuern.
Hast Du das Problem bei jeden Raum oder nur bei bestimmten?
-
@antimon musst Dich auch nicht in TypeScript auskennen. Besser in Javascript und das Script als solches anlegen…
-
@ptr wie gesagt kann ich bei mir so nicht bestätigen. Was man verwendet hängt davon ab wie man Hue organisiert. Ich nutze viele Zonen und dort dann Szenen. Somit kann ich pro Raum die Lampen einfach über Szenen unterschiedlich steuern.
Hast Du das Problem bei jeden Raum oder nur bei bestimmten?
-
@cash Habe nun eine gewisses Muster erkannt: Es gibt nur kein Push-Update von States eines Channels mit "LightGroup"-Rolle. Ist das nachvollziehbar?
@ptr wollte es gerade nachstellen aber ich habe keine Gruppen mehr. Habe nur noch Zonen definiert. Eigentlich hätte ich gedacht das ich noch eine Gruppe im Wohnzimmer habe. Weiß nicht mehr warum ich die in eine Zone geändert habe. Es gab bestimmt einen Grund…