Trying to set a payload.name in a function node

I am setting values in my function:

let sync = context.get('sync') || {};
const nodeName = msg.nodeName;
sync[nodeName] = msg.payload.value;
const sync_array = Object.values(sync);

if (sync_array.length >= 3) {
    msg = { payload: (sync_array.reduce((acc, num) => acc + num, 0) + " Watts"), color: "lime", strongcolor: "deepSkyBlue", nodeName: "Plinth Lights" 
}
    sync = undefined;
}else{
    msg = null;
}

context.set("sync", sync)

return msg;

So that is all working fine. What I could not get to work (I found a workaround but want to learn as thats important to know) is in the msg = { payload: (sync_array.reduce... I also wanted to set payload.name. I tried various things, the best I managed was a name object. A lot of things I tried adding to that line to set payload.name ended in errors in the function. If I set it after the msg = {payload... then it deletes everything I set before...

I could be wrong in the interpretation here (just passing by :sweat_smile: )

But you are setting payload to the value of
(sync_array.reduce((acc, num) => acc + num, 0) + " Watts")

it essentially looks like this.

{
   payload: "00.0 Watts",
   color: "lime",
   strongcolor: "deepSkyBlue",
   nodeName: "Plinth Lights" 
}

if you wanted to add name to payload, then you should do.

{
   payload: {
       value: "00.0 Watts",
       name: 'name here'
   },
   color: "lime"
   strongcolor: "deepSkyBlue",
   nodeName: "Plinth Lights" 
}

msg.payload.name = the name
msg.payload.value = the value

payload needs to be an object {} to add further properties later

I was sure I tried your version... but obviously I didnt as this works. Too many {{{}}} got me confused... yeah that makes sense now. I thought it should be easy... Saved it to my library for future ref

1 Like

any property can be anything (within reason :sweat_smile: )

payload : "some string" < a string
payload : 10 < a number
payload : {} < an object

objects supports properties or further objects

payload: {
    name: 'Some Name',
    some_data_object: {
      value: 10,
      name: 'some name'
    }
}

msg its self is an obejct

You can set the payload properties individually to avoid { } if you wish

let sync = context.get('sync') || {};
const nodeName = msg.nodeName;
sync[nodeName] = msg.payload.value;
const sync_array = Object.values(sync);
msg.payload = {};
if (sync_array.length >= 3) {
    msg.payload.value =  sync_array.reduce((acc, num) => acc+num, 0)
    msg.payload.units = "watts";
    msg.payload.color = "lime";
    msg.payload.strongcolor = "deepSkyBlue";
    msg.payload.nodeName = "Plinth Lights";
    sync = undefined;
}else{
    msg = null;
}

context.set("sync", sync)
return msg;

Actually that looks a lot easier, also much easier to debug or change. I'll change my function but save both versions to my library for future ref

Actually, I just seen that is isnt working. I need the value in msg.payload, not payload.value

So I tried this:

let sync = context.get('sync') || {};
const nodeName = msg.nodeName;
sync[nodeName] = msg.payload.value;
const sync_array = Object.values(sync);
msg.payload = {};
if (sync_array.length >= 3) {
    msg.payload = sync_array.reduce((acc, num) => acc + num, 0).toFixed(1) + " Watts"
    msg.payload.name = "Test"
    msg.color = "lime";
    msg.strongcolor = "deepSkyBlue";
    msg.nodeName = "Plinth Lights";
    sync = undefined;
} else {
    msg = null;
}

context.set("sync", sync)
return msg;

image

But that doesnt write anything into payload.name

msg.payload can be a string or an object not both, what you are asking is impossible. Unless you use the new Quantum_properties JS

Ok so the solution would be to have the value in payload.value then the name in payload.name. I would then set my graph to display payload.value instead of payload. Either way, I had it working anyway (I used nodeName instead of payload.name) and now understand why it would not let me set this, and you have shown me a easier way of setting various objects, so it was worth the exercise. I am slowly feeling a bit more confident programming the function node, I have done a few things now myself without help, but there is still a lot to learn. And I am sure there will be more questions in the future. I do look at the manual, sometimes I can follow what they mean, other times its just way over my head.

Essentially.
To extend on the answer given by @E1cid, A property can only be represented as 1 type.

  • string -> "Hello, World"
  • number -> 100
  • array -> ["Hello", "World"]
  • object -> {'property_name': 'property_value', 'another_property_name': 'another_property_value'}

therefore payload can only be one of these types

So that then explains, when I set payload to a value (or string), it cannot be a object payload.name at the same time. Clear.

Correct!

payload:"some string" is a string, a string does not have properties.

however, an object does
payload: {}

Bonus content! :smile:

Thats not to say you can change the type (in most cases)

msg.payload = "Some String" /* payload is now a string */
msg.payload.name = 'bla'    /* invalid */
msg.payload = {}            /* payload is now an object */
msg.payload.name = 'bla'    /* Valid */
1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.