Hi,
I’ve used node red on several projects over the years and recently started with home assistant because I felt I could rely on some node red experience to start with some automations.
I bought an Aqara AQ1 vibration sensor to help report on the Velux roof window opening. I paired it with ZHA. Using NodeRed I can trap the current_orientation event and then with some borrowed binary to decimal and trig functions I can get the tilt angle of the sensor.
[{"id":"dcf521ad5833f797","type":"server-events","z":"fb781577ee0a6ffe","name":"","server":"2be748d3.da7088","version":2,"eventType":"","exposeToHomeAssistant":false,"eventData":"{ \"device_ieee\": \"00:15:8d:00:08:74:7e:61\" }","haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"waitForRunning":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"$outputData(\"eventData\").event_type","valueType":"jsonata"}],"event_type":"","x":140,"y":120,"wires":[["02143a259fe8e393"]]},{"id":"96452fde42340884","type":"function","z":"fb781577ee0a6ffe","name":"Handle current_orientation","func":"\nvar rawX = msg.payload.event.args.rawValueX\nvar rawY = msg.payload.event.args.rawValueY\nvar rawZ = msg.payload.event.args.rawValueZ\n\nvar newX = twosComplementToInteger(rawX);\nvar newY = twosComplementToInteger(rawY);\nvar newZ = twosComplementToInteger(rawZ);\n\nmsg.payload = calculateAngle(newX,newY,newZ);\n\nreturn msg;\n\nfunction twosComplementToInteger(num) {\n // If the MSB is 1, it means the number is negative\n if (num & 0x8000) {\n // Convert the negative two's complement representation to a negative integer\n // by taking the two's complement and negating the result\n return -((~num + 1) & 0x7FFF);\n } else {\n // If the MSB is 0, the number is positive\n // The number itself is the positive integer\n return num;\n }\n}\n\nfunction calculateAngle(valueX, valueY, valueZ) {\n const angleX = Math.round((Math.atan(valueX / Math.sqrt(valueZ * valueZ + valueY * valueY)) * 1800) / Math.PI / 10);\n const angleY = Math.round((Math.atan(valueY / Math.sqrt(valueX * valueX + valueZ * valueZ)) * 1800) / Math.PI / 10);\n const angleZ = Math.round((Math.atan(valueZ / Math.sqrt(valueX * valueX + valueY * valueY)) * 1800) / Math.PI / 10);\n\n return { angleX, angleY, angleZ };\n}\n\n// Test the function\n//const twosComplementNum = 0b1111111111110001; // This represents -15 in two's complement\n//const result = twosComplementToInteger(twosComplementNum);\n//console.log(result); // Output: -15\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":180,"wires":[["5d036dabcf96c1a0"]]},{"id":"02143a259fe8e393","type":"switch","z":"fb781577ee0a6ffe","name":"","property":"payload.event.command","propertyType":"msg","rules":[{"t":"eq","v":"current_orientation","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":150,"y":180,"wires":[["96452fde42340884"],["2f59491d565c4894"]]},{"id":"5d036dabcf96c1a0","type":"switch","z":"fb781577ee0a6ffe","name":"","property":"payload.angleY","propertyType":"msg","rules":[{"t":"btwn","v":"55","vt":"num","v2":"70","v2t":"num"},{"t":"btwn","v":"10","vt":"num","v2":"25","v2t":"num"},{"t":"btwn","v":"-15","vt":"num","v2":"-30","v2t":"num"},{"t":"btwn","v":"-31","vt":"num","v2":"-80","v2t":"num"}],"checkall":"true","repair":false,"outputs":4,"x":390,"y":380,"wires":[["9038c9cd9d50607e"],["95bc2bb1d8dfe6a3"],["c5b881fa67747992"],["dbb2b5845f881b47"]]},{"id":"9038c9cd9d50607e","type":"debug","z":"fb781577ee0a6ffe","name":"Locked","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"\"locked\"","targetType":"jsonata","statusVal":"","statusType":"auto","x":580,"y":320,"wires":[]},{"id":"95bc2bb1d8dfe6a3","type":"debug","z":"fb781577ee0a6ffe","name":"Vented","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"\"vented\"","targetType":"jsonata","statusVal":"","statusType":"auto","x":570,"y":360,"wires":[]},{"id":"c5b881fa67747992","type":"debug","z":"fb781577ee0a6ffe","name":"Open","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"\"open\"","targetType":"jsonata","statusVal":"","statusType":"auto","x":570,"y":400,"wires":[]},{"id":"dbb2b5845f881b47","type":"debug","z":"fb781577ee0a6ffe","name":"Wide Open","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"\"wide open\"","targetType":"jsonata","statusVal":"","statusType":"auto","x":590,"y":440,"wires":[]},{"id":"2f59491d565c4894","type":"debug","z":"fb781577ee0a6ffe","name":"Other events","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":330,"y":220,"wires":[]},{"id":"2be748d3.da7088","type":"server","name":"Home Assistant","addon":true}]
I’m trying to work out how to put the information back into HomeAssistant. I created a Text Helper that I thought I could update from this flow, but did not see how to do this.
What I think I want is to create a virtual window with states closed/locked or open+angle with the optional state of vented/not vented. I would then have a graph showing when the window was open and ultimately create alerts when leaving the house or when adverse weather is detected.
Where do I start getting node red into dashboard or other automations?
regards
Steve