The `change` node..... Checking what I expect to what it does

I don't know what is happening or why I am doing this/these things.

I am trying to get things working and when I rationalise it down to a small flow and try to test things: it gets nasty.

What exactly does a change node allow?

Originally I was smitten with the function node and constructing messages as I needed them.
Then one day I had explained how the change node works and how it can set/change message properties.

But can it? (Dramatic - and probably a bit sarcastic - music)

This is the test flow:

[{"id":"3ec09b8a.1278d4","type":"inject","z":"184dc884.7aba5f","name":"","topic":"","payload":"blah","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":3610,"wires":[["1c72b687.d72189","bec8c490.70c218"]]},{"id":"bec8c490.70c218","type":"change","z":"184dc884.7aba5f","name":"","rules":[{"t":"set","p":"topic.part1","pt":"msg","to":"extended topic","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":3660,"wires":[["c3dc56fb.cc28e"]]},{"id":"c3dc56fb.cc28e","type":"debug","z":"184dc884.7aba5f","name":"Extra","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":530,"y":3660,"wires":[]}]

I want to construct a message topic of/being:
msg.topic.part1 and set it to "Extended topic".

It doesn't work.

Is it I am expecting too much of the node?
(I have to now sit down and re-write some code to test something and then when that is resolved I may have to then apply the greater changes to a lot of stuff.)

Not in a place to import your flow at the moment, so not entirely sure what you mean.

Do you mean you have msg.topic and you want to set a property under that called msg.topic.part1?

That will not work if msg.topic is a String because in JavaScript, Strings cannot have properties. (likewise numbers and booleans).

Not quite.

I was messing around with JSON and MQTT stuff.

I was wanting to create a fake MQTT message and so I needed complex messages like:
msg.payload.payload = "this is the payload"

I tried the topic just out of desperation trying to create that because payload didn't work and the payload was already being used.

I have kind of resolved the problem in my inject timestamp project I shared.

Please don't waste time on it, other than to tell me if the change node can do what I think it can.

eg: make msg.payload.payload to a string in the node's settings.

It can, as long as msg.payload either doesn't exist (it will create each 'missing' level), or if it does already exist then it is a type that can have properties (ie, not a string, number or Boolean)

1 Like

so yes you need to delete the existing topic (which is an empty string) - and then add it.

[{"id":"137679d7.eadbe6","type":"inject","z":"f8040b0d.914298","name":"","topic":"","payload":"blah","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":600,"wires":[["ca7892f6.9148e"]]},{"id":"ca7892f6.9148e","type":"change","z":"f8040b0d.914298","name":"","rules":[{"t":"delete","p":"topic","pt":"msg"},{"t":"set","p":"topic.part1","pt":"msg","to":"extended topic","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":600,"wires":[["5433391b.2749d8"]]},{"id":"5433391b.2749d8","type":"debug","z":"f8040b0d.914298","name":"Extra","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":510,"y":600,"wires":[]}]
1 Like

Thanks.

Just thinking: It may be nice if an error is generated if people do it the way I did it the first time.

I guess this would never happen in the real world. Thanks @dceejay
I just seem to have this ability to do weird things.

It's not weird if someone thought of it! :rofl:

Believe me: if I think of it, it is not - usually - normal.

I seem to have a nearly constant mental dissonance. Or live in a world of mental dissonance.
(Which ever)

I may have mentioned before that this isn't as unusual as you think. Happens to me all the time where I seem to be out of step with other people's thoughts.

I still (after 60 years :slight_smile:) find it surprising that so many people eventually come round to my way of thinking, it just takes time :rofl:

4 Likes

I think this thread is adding to the case for the change node to just automatically delete an existing msg.payload if its not an object (or msg.topic in this case), if the user wants to set a property on it

(Can't find the previous discussion on this but it was a few days ago)

I don't think that is the right behaviour.

The choice is between:

  1. Try to set a property... Oh why hasn't that property been set? (As-is behaviour)
  2. Set a property .... Oh, where has my payload gone?!

I don't see why 2 is better than 1.

I must have missed the previous thread you refer to as I hadn't seen it when Dave spoke to me about it... If someone does have a link, please do share.

I think the right approach will be a warning message if you try setting a property on a thing that cannot have a property.

I can understand why it looks wrong at first glance

But at present time, we can move the payload to a sub-property and the change node does it.

So I think the behaviour of ignoring non object type and just doing it is already in use.

[edit]
@zenofmud has found previous reference

While it won't fix the general problem - the latest PR work to update the inject node will help alleviate this as in the simple cases (like this), the new inject could just set the topic sub-property directly so removing the need for the following change node :slight_smile:

1 Like

That is, in my mind, a different case entirely. In that instance, the user has asked to move payload to a property under itself. The original value of payload no longer exists, so the node creates an empty object - as it does where any part of the message it needs doesn't exist. Nothing is lost.

But as Dave says, the new Inject node work will remove one of the common causes of this confusion as you won't need to do a Inject (timestamp) -> Change node combination as often when you want the payload to be an object out of the box.

I'd better say something as I am not sure that we are all on the page at which I am looking.

I was wanting to construct a msg.payload.payload. It wasn't happening.
I (now) see that is a problem because msg.payload existed - it was the trigger/input to the node.

Ok, that was a bit of time wasted. My fault.

So to test a theory, I decided to make it change the topic to topic.part1
That too failed.

Why?

Given what I read, it should have worked. Why?

Well, case 1 it didn't because I had sent in a msg.payload.
Case 2 should have worked because the inject node did not have a topic set.

So getting the change node make a topic.part1 and it failed.... "That does not compute" (Robot accent of 70's "lost in space")

I don't have that any more. Way under the bridge.

See below.

So for me the question remains:

I inject an input to the change node with only a msg.payload and get it to set msg.topic.part1 and it is not created.

Is that a problem?

This is the flow:

[{"id":"52d4d57.adcb5ac","type":"inject","z":"184dc884.7aba5f","name":"","topic":"","payload":"blah","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":820,"y":3680,"wires":[["c73a13c2.b628e8"]]},{"id":"db74d9c3.992de8","type":"debug","z":"184dc884.7aba5f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1190,"y":3680,"wires":[]},{"id":"c73a13c2.b628e8","type":"change","z":"184dc884.7aba5f","name":"","rules":[{"t":"set","p":"topic.part1","pt":"msg","to":"this is the topic","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1020,"y":3680,"wires":[["db74d9c3.992de8"]]}]

This is what I get:

Where is the existing msg.topic which needs to be deleted?

If you set up a default inject node (timestamp) connected to a debug node set to show complete message - what do you see in the debug window.... ?


image
So msg.topic exists (as an empty string - but a string none the less) - so no you can't then just add another property to it by trying to set msg.topic.part1

@Trying_to_learn your screenshot shows very clearly that msg.topic exists and is a blank string. As I said, Strings cannot have properties.

(Argh!) (Just an expression. Not to you.)
And in reply to @dceejay who said nearly the same thing.

Ok, but to idiots like me, it is not being used.

So as far as I am concerned, I haven't used the topic.

So I wasted 20 minutes yesterday trying to create msg.topic.part1 and it didn't do anything.
If the node had spat out an error: "msg.topic is not blank" then I may have worked it out quicker/easier/sooner.

Had I picked something else like msg.foo.boo it would have worked too. Just msg.topic is a well used thing.

Rather there is no error and so I was running in circles trying to understand what is going on.

Given: I'm stupid and don't get all these givens in Javascript. But for new people (who are probably smarter than me, and so may not fall for the trap) it is not helping.

If you were to go for more verbose errors, I think a proper error message here would be, as opposed to the above, something akin to “you can’t set a property to msg.topic as it exists and is not an object, but rather <insert type>”

I would like to clarify my take on the whole thing.

You and Paul (@dceejay) explained that to me.

And: I retrospect I can see that.

But that the topic is "" I didn't set that. The inject node did it.

So to me: I didn't set the topic.

Maybe I should say that it is not a good idea that an inject node, if all I enter is stuff for the payload, makes the topic null (or should that be undefined?) rather than "".

It is only my take on the bigger picture of what happened and why.

I know: I'm wrong, because that's the way it is.... But I honestly think that is not consistent with how things should work.

I don't enter anything in the inject topic field, the topic should not be set.