Lighting Reformat in Function Node with Google Home

Yes and no. Once you get comfortable with Node-Red, you have a lot of control. It just takes a little time, lots of searching/reading and some experimentation.

Hi

I am new to Nodered, can you show me how i make a function that changes the On: false state to true when I change the brightness in light off state.

I won't be in front of a computer for a few days, but the basic approach I'd take would be at the output of the Nora node:

  • check for a change in the payload brightness against a flow variable of the previous brightness (Switch node)
  • if true, store the new brightness in the flow variable (Change node) then check if the payload light on state is false (Switch node)
  • If true, then send an on:true payload to the input of the Nora node (Change node)

You could do this with a series of nodes stand alone, a series of nodes in a sub-flow so you can reuse it, or by coding into a single function node.

Hope that helps. I can do a sample flow in a few days when I'm back in front of a computer if you don't figure it out by then.

Hope that helps.

I am to trainee to figure it out just by this sorry, so iā€™m hopping for a bit more guidens

I'd suggest spending some time with the node-red docs on the nodes I flagged above and on context variables. Then put out any specific questions as you experiment and run into road blocks. Best way to learn is through experimentation.

Hi

I did try to make a function that sets the brightness to 0 if a false is sent.
But I canā€™t figure out how I remember the last brightness state and compare the new brightness to the saved one.

    {
        "id": "9fa04880.614c78",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": ""
    },
    {
        "id": "35c7fb70.6f2a4c",
        "type": "debug",
        "z": "9fa04880.614c78",
        "name": "Function",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 760,
        "y": 280,
        "wires": []
    },
    {
        "id": "bab3ace2.38937",
        "type": "change",
        "z": "9fa04880.614c78",
        "name": "Convert",
        "rules": [
            {
                "t": "set",
                "p": "payload.L",
                "pt": "msg",
                "to": "(payload.L*2.5)",
                "tot": "jsonata"
            },
            {
                "t": "change",
                "p": "payload.Power",
                "pt": "msg",
                "from": "true",
                "fromt": "bool",
                "to": "1",
                "tot": "num"
            },
            {
                "t": "change",
                "p": "payload.Power",
                "pt": "msg",
                "from": "false",
                "fromt": "bool",
                "to": "4",
                "tot": "num"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 580,
        "y": 280,
        "wires": [
            [
                "35c7fb70.6f2a4c"
            ]
        ]
    },
    {
        "id": "92bd4aa3.1fa85",
        "type": "inject",
        "z": "9fa04880.614c78",
        "name": "",
        "topic": "",
        "payload": "{\"on\":true,\"brightness\":100}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 210,
        "y": 140,
        "wires": [
            [
                "ce4c63c8.5ea7b8"
            ]
        ]
    },
    {
        "id": "194671ab.a865ce",
        "type": "debug",
        "z": "9fa04880.614c78",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 570,
        "y": 380,
        "wires": []
    },
    {
        "id": "ce4c63c8.5ea7b8",
        "type": "nora-light",
        "z": "9fa04880.614c78",
        "devicename": "Test lys",
        "lightcolor": false,
        "brightnesscontrol": true,
        "passthru": true,
        "statepayload": true,
        "brightnessoverride": "",
        "roomhint": "Loft",
        "name": "",
        "nora": "764f0148.f2e248",
        "topic": "",
        "onvalue": "1C,05,06,70,77,55,33,66",
        "onvalueType": "bin",
        "offvalue": "Den er off",
        "offvalueType": "str",
        "x": 180,
        "y": 280,
        "wires": [
            [
                "eaa01173.4b6df",
                "f4159265.7ff6c"
            ]
        ]
    },
    {
        "id": "c5e9b1f3.db556",
        "type": "inject",
        "z": "9fa04880.614c78",
        "name": "",
        "topic": "",
        "payload": "{\"on\":false,\"brightness\":100}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 190,
        "y": 180,
        "wires": [
            [
                "ce4c63c8.5ea7b8"
            ]
        ]
    },
    {
        "id": "eaa01173.4b6df",
        "type": "function",
        "z": "9fa04880.614c78",
        "name": "Function",
        "func": "m = msg.payload.on\nb = msg.payload.brightness\na = 2\nc = 1\n\nif (m === false) {\n   msg = {payload:{A:a,C:c,L:0}} \n    \n}\nelse if (m === true) {\nmsg = {payload:{A:a,C:c,L:msg.payload.brightness}}\n}\n\nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "x": 380,
        "y": 260,
        "wires": [
            [
                "bab3ace2.38937",
                "194671ab.a865ce"
            ]
        ]
    },
    {
        "id": "f4159265.7ff6c",
        "type": "debug",
        "z": "9fa04880.614c78",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 380,
        "y": 420,
        "wires": []
    },
    {
        "id": "764f0148.f2e248",
        "type": "nora-config",
        "z": "",
        "name": "nora config",
        "group": "",
        "notify": false
    }
]

So I hope you can help me a bit

I do it through flow nodes but the concept would be the same. You need to store it in a flow variable (Writing Functions : Node-RED).

Using your function as a baseline I'd make it work along these lines (I didn't test and am assuming your core function works properly, though I added the missing ;'s and var's in my edits):

var m = msg.payload.on;
var b = msg.payload.brightness;
var a = 2;
var c = 1;
var oldBrightness = flow.get("oldBrightness")||0;

if (b != oldBrightness) {
    if (m === false) {
        msg = {payload:{A:a,C:c,L:0}}; 
    }
    else if (m === true) {
        msg = {payload:{A:a,C:c,L:msg.payload.brightness}};
    }
    flow.set ("oldBrightness",b);
}

return msg;

If you are going to use a function, I'd suggest just moving the changes from your Change node into the function as well. Then you can store the function in the function library to make it easy to reuse

Hope that helps.

If the value is only used in one function node then it is probably best to use context.set/get rather than flow.set/get. That way the value is entirely contained within that function node.

1 Like

Hi

I made it work by changing the function slightly, because payload.on was not changed to true if you changed the brightness directly in the google home app.

but i need to convert the 0-100 % to 0-254, how do I do this ?

I did try to do this with a change node, directly to 0-254, but i also get comma numbers and that dosen't work for me.
How do i include my payloads to my buffer in my convert node?

[
    {
        "id": "9fa04880.614c78",
        "type": "tab",
        "label": "GH to Dynet",
        "disabled": false,
        "info": ""
    },
    {
        "id": "35c7fb70.6f2a4c",
        "type": "debug",
        "z": "9fa04880.614c78",
        "name": "Dynet output",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 810,
        "y": 260,
        "wires": []
    },
    {
        "id": "bab3ace2.38937",
        "type": "change",
        "z": "9fa04880.614c78",
        "name": "Convert",
        "rules": [
            {
                "t": "set",
                "p": "payload.L",
                "pt": "msg",
                "to": "(payload.L*2.5)",
                "tot": "jsonata"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[28,\"payload.A\",\"payload.L\",\"payload.C\",255,100,255,154]",
                "tot": "bin"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 620,
        "y": 260,
        "wires": [
            [
                "35c7fb70.6f2a4c"
            ]
        ]
    },
    {
        "id": "92bd4aa3.1fa85",
        "type": "inject",
        "z": "9fa04880.614c78",
        "name": "",
        "topic": "",
        "payload": "{\"on\":true,\"brightness\":100}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 110,
        "y": 80,
        "wires": [
            [
                "ce4c63c8.5ea7b8"
            ]
        ]
    },
    {
        "id": "194671ab.a865ce",
        "type": "debug",
        "z": "9fa04880.614c78",
        "name": "Output 1",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 620,
        "y": 160,
        "wires": []
    },
    {
        "id": "ce4c63c8.5ea7b8",
        "type": "nora-light",
        "z": "9fa04880.614c78",
        "devicename": "Test lys",
        "lightcolor": false,
        "brightnesscontrol": true,
        "passthru": true,
        "statepayload": true,
        "brightnessoverride": "",
        "roomhint": "Loft",
        "name": "",
        "nora": "764f0148.f2e248",
        "topic": "",
        "onvalue": "1C,05,06,70,77,55,33,66",
        "onvalueType": "bin",
        "offvalue": "Den er off",
        "offvalueType": "str",
        "x": 180,
        "y": 280,
        "wires": [
            [
                "f02ce5c7.3babe8",
                "51ba19e4.4c2708"
            ]
        ]
    },
    {
        "id": "c5e9b1f3.db556",
        "type": "inject",
        "z": "9fa04880.614c78",
        "name": "",
        "topic": "",
        "payload": "{\"on\":false,\"brightness\":100}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 110,
        "y": 140,
        "wires": [
            [
                "ce4c63c8.5ea7b8"
            ]
        ]
    },
    {
        "id": "f4159265.7ff6c",
        "type": "debug",
        "z": "9fa04880.614c78",
        "name": "Output 2",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 600,
        "y": 400,
        "wires": []
    },
    {
        "id": "51ba19e4.4c2708",
        "type": "debug",
        "z": "9fa04880.614c78",
        "name": "Direct",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 330,
        "y": 440,
        "wires": []
    },
    {
        "id": "f02ce5c7.3babe8",
        "type": "function",
        "z": "9fa04880.614c78",
        "name": "GH to Dynet",
        "func": "var m = msg.payload.on;\nvar b = msg.payload.brightness;\nvar a = 129;\nvar c = 1;\nvar oldBrightness = flow.get(\"oldBrightness\")||0;\n\nif (b != oldBrightness) {\n    if (m === false) {\n        msg2 = {payload:{\"on\":true,\"brightness\":msg.payload.brightness}}; \n        flow.set (\"oldBrightness\",b);\n    return [,msg2];    \n    }\n    else if (m === true) {\n        msg = {payload:{A:a,C:c,L:msg.payload.brightness}};\n    }\n    \n}\n\nelse if (m === false) {\n    msg = {payload:{A:a,C:c,L:0}}; \n}\n\nelse if (m === true) {\n     msg = {payload:{A:a,C:c,L:b}};\n}\n\nflow.set (\"oldBrightness\",b);\n\nreturn msg;",
        "outputs": 2,
        "noerr": 0,
        "x": 390,
        "y": 220,
        "wires": [
            [
                "194671ab.a865ce",
                "bab3ace2.38937"
            ],
            [
                "ce4c63c8.5ea7b8",
                "f4159265.7ff6c"
            ]
        ]
    },
    {
        "id": "764f0148.f2e248",
        "type": "nora-config",
        "z": "",
        "name": "nora config",
        "group": "",
        "notify": false
    }
]

Does this function node achieve what you need?

[{"id":"d729bb06.70fae8","type":"debug","z":"cd8d2802.a6a288","name":"Dynet output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1030,"y":280,"wires":[]},{"id":"1e9916b9.b9a589","type":"inject","z":"cd8d2802.a6a288","name":"","topic":"","payload":"{\"on\":true,\"brightness\":100}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":80,"wires":[["8ed50ede.e4cb2"]]},{"id":"da372162.4a822","type":"debug","z":"cd8d2802.a6a288","name":"Output 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":620,"y":160,"wires":[]},{"id":"8ed50ede.e4cb2","type":"nora-light","z":"cd8d2802.a6a288","devicename":"Test lys","lightcolor":false,"brightnesscontrol":true,"passthru":true,"statepayload":true,"brightnessoverride":"","roomhint":"Loft","name":"","nora":"9980ab73.1c0948","topic":"","onvalue":"1C,05,06,70,77,55,33,66","onvalueType":"bin","offvalue":"Den er off","offvalueType":"str","x":180,"y":280,"wires":[["dd53ac4.3b7f65","c3357f47.e1566"]]},{"id":"cfa3d336.b409e","type":"inject","z":"cd8d2802.a6a288","name":"","topic":"","payload":"{\"on\":false,\"brightness\":100}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":160,"wires":[["8ed50ede.e4cb2"]]},{"id":"af44d9dc.b50498","type":"debug","z":"cd8d2802.a6a288","name":"Output 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":580,"y":400,"wires":[]},{"id":"c3357f47.e1566","type":"debug","z":"cd8d2802.a6a288","name":"Direct","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":330,"y":440,"wires":[]},{"id":"dd53ac4.3b7f65","type":"function","z":"cd8d2802.a6a288","name":"GH to Dynet","func":"var m = msg.payload.on;\nvar b = msg.payload.brightness;\nvar a = 2;\nvar c = 1;\nvar oldBrightness = flow.get(\"oldBrightness\")||0;\n\nif (b != oldBrightness) {\n    if (m === false) {\n        msg2 = {payload:{\"on\":true,\"brightness\":msg.payload.brightness}}; \n        flow.set (\"oldBrightness\",b);\n    return [,msg2];    \n    }\n    else if (m === true) {\n        msg = {payload:{A:a,C:c,L:msg.payload.brightness}};\n    }\n    \n}\n\nelse if (m === false) {\n    msg = {payload:{A:a,C:c,L:0}}; \n}\n\nelse if (m === true) {\n     msg = {payload:{A:a,C:c,L:b}};\n}\n\nflow.set (\"oldBrightness\",b);\n\nreturn msg;","outputs":2,"noerr":0,"x":390,"y":220,"wires":[["da372162.4a822","6d448fd5.6bba5"],["af44d9dc.b50498","8ed50ede.e4cb2"]]},{"id":"61796e5b.c8b05","type":"inject","z":"cd8d2802.a6a288","name":"","topic":"","payload":"{\"on\":true,\"brightness\":51}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":120,"wires":[["8ed50ede.e4cb2"]]},{"id":"6d448fd5.6bba5","type":"function","z":"cd8d2802.a6a288","name":"Convert payload L","func":"a = msg.payload.A\nc = msg.payload.C\nl = msg.payload.L\n\nl = Math.round(l*2.5)/1\n\nmsg = {payload:{A:a,C:c,L:l}};\n\nreturn msg;","outputs":1,"noerr":0,"x":750,"y":280,"wires":[["d729bb06.70fae8"]]},{"id":"9980ab73.1c0948","type":"nora-config","z":"","name":"nora config","group":"","notify":false}]

Yes that did it with the 0-100 to 0-254 convert, but I need it to be the other way around.
So the convert is
0% = Value 255
1% = Value 253
100% = Value 1

Could you help me?

You can use the Range node to do the scaling, mapping the range 0:100 to 255:1. The Range node is one of the standard built in nodes.

Thanks,
.

@zamzon - I noticed an error in the previous Function node. The Math.round should be as follows -

l = Math.round(l*2.55)/1

The Range node suggested by @Colin works fine but for my own learning I'm trying to work out how to do this in the Function node.

I found this code, but I'm struggling to work out how to apply it to msg.payload.L.

var value = msg.payload;//value to be ranged

//range limits
var inputrange = msg.inputrange || [0,255];//expected range of input value. an array containing min and max 
var outputrange = msg.outputrange || [255,0] // range into the value to be converted. an array containing min and max 

// range limits can also be represented as Object if you like. 
// var ranges = {mininput:0,maxinput:255,minoutput:255,maxoutput:0};


//you should store input and output ranges into context memory 
//so you don't need to send them with every message but only when needed
// see https://nodered.org/docs/writing-functions#storing-data


//brain of the whole thing. hard work is done here
const mapNumber = (number, in_min, in_max, out_min, out_max) => {
  return (number - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
};


// here how the brain is used
var output = mapNumber(value,inputrange[0],inputrange[1],outputrange[0],outputrange[1]);

// hard work is done, place the ranged number into outgoing msg payload
msg.payload = output;

return msg;

Can this be incorporated directly after the Math.round in the function node?

a = msg.payload.A
c = msg.payload.C
l = msg.payload.L

l = Math.round(l*2.55)/1

msg = {payload:{A:a,C:c,L:l}};

return msg;

If you want to do the same in a function node as the Range node then you just need

// maps the payload range inA:inB to outA:outB
// input range
const inA = 0
const inB = 100
// output range
const outA = 255
const outB = 1
msg.payload = (msg.payload - inA) / (inB - inA) * (outB - outA) + outA
return msg;

Sample flow:

[{"id":"a68ba3e6.84e8f8","type":"debug","z":"5bb5a6a6.97527","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":555,"y":526,"wires":[]},{"id":"905087e5.33f5d8","type":"inject","z":"5bb5a6a6.97527","name":"","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":137,"y":475,"wires":[["866d79b2.f562d8"]]},{"id":"16de85b0.ca5e0a","type":"inject","z":"5bb5a6a6.97527","name":"","topic":"","payload":"50","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":139,"y":525,"wires":[["866d79b2.f562d8"]]},{"id":"ed22eb7.b133118","type":"inject","z":"5bb5a6a6.97527","name":"","topic":"","payload":"100","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":138,"y":585,"wires":[["866d79b2.f562d8"]]},{"id":"866d79b2.f562d8","type":"function","z":"5bb5a6a6.97527","name":"Range","func":"// maps the payload range inA:inB to outA:outB\n// input range\nconst inA = 0\nconst inB = 100\n// output range\nconst outA = 255\nconst outB = 1\nmsg.payload = (msg.payload - inA) / (inB - inA) * (outB - outA) + outA\nreturn msg;","outputs":1,"noerr":0,"x":336,"y":527,"wires":[["a68ba3e6.84e8f8"]]}]

I have a little problem with the color transmit to google. I can set the on/off and brightness status but my color wonĀ“t be accept.

{
    "on": true,
    "brightness": 60,
    "color": {
        "spectrumHsv": {
            "hue": 32.94117736816406,
            "saturation": 0.8607594966888428,
            "value": 0.929411768913269
        }
    }
}

This is the JSON but color is not working. Can someone help me?