Access discontinued parameters

I come up with another weired question. Ages ago I started to develop a node. With the time, more and more parameters were added and now (with a major version bump) I'm going to move these parameters to a configSet.

The scenario I'm considering only deals with users who updates the node. They probably have set a bunch of individual settings. These settings vanish with the update, where they have moved in the configSet. I see no possibility to automatically create a new configSet with the prior settings (please oh please correct me if I'm wrong).

My idea was to print the old settings as plain HTML where the settings have been before with:

<script type="text/html" data-template-name="powerswitch">
  ...
  <!-- Present old settings -->
  <div class="form-row">
    <div id="oldSettings"></div>
  </div>
</script>
<script type="text/javascript">
  RED.nodes.registerType('powerswitch',{
    ...
    oneditprepare: function() {
      $("#oldSettings").append("toggleTopic was '" + this.toggleTopic + "'<br>")
    }
  })
</script>

But console.log(this) shows, that after the update, all parameter elements have all gone already, resulting in undefined.

I see that the settings still persist in the flows.json.

{
  "id": "7b2043b67c5ca772",
  "type": "powerswitch",
  "z": "cbc11d2d06a171d8",
  "name": "my name is this",
  "toggleTopic": "toggleTopic",
  ...
}

They most probably exist until deployment of the updated flow. But as long as they exist, can I access and print these settings somehow (which miracuously would also solve my question)?

Respectfully, Tom

Yep you have to leave the property in default and remove value to not create one
So:

default: {
  toggleTopic: {} // may contains validator and label
}

Why not? You have the old data and all you need is to transfer to the new config and set a flag to say you've done it - and probably then blank the old data.

One thing I've set up with uibuilder is a version check - I set a value in code and if node-red has nodes that were set up on a prior major version, I simply set all the nodes to "dirty" to force a re-deploy or to invalid if flow editors need to do something new.

That was EXACTLY my idea :star_struck: But how to generate a new configSet automatically? :thinking:

Oh damn, of course, that's it... :face_with_peeking_eye:

It is not that hard. You would check whether your new fields contained anything and if not, run a function to copy from the old to the new.

The complexity is in the time period between installing the new version with the new settings and when an admin user has had a chance to update the data and re-deploy.

So your runtime needs to be able to cope with having no data in the new settings and being able to continue with the old data. It would be up to you whether the runtime could/should actually continue to work on the old settings or whether you simply want to output an error and stop. Depends on what the node is doing.

Then the Editor component needs to check for those new settings and if not set, either mark the node as invalid to force users to update it manually, or simply copy over the old to the new fields and mark the node as "dirty" so that the editor user knows that they need to re-deploy (that will probably happen automatically if you do a copy).

In the editor, it is worth understanding the order in which things happen because it can be quite confusing (well, to me it is anyway!). I've found that the safest place to do checks like this is in a custom validation function. That is because they are called when the Editor page is loaded as well as after any change to the values. You do have some other choices though and you should check out the different function calls in the node definition and could also use the global RED.events.on('nodes:add', function(node) { ... }) event handler to detect when your nodes are added to the flow since that is also triggered when the Editor page is loaded. I use this in UIBUILDER to keep track of all urls used by uibuilder nodes even if they haven't yet been deployed & also can blank out some fields if the node was added via a copy/paste or library import (to avoid duplicate names) - with some code in a common resource library that looks like this:

       /** Track which urls have been used - required to handle copy/paste and import
         *  as these can contain duplicate urls before deployment.
         */
        RED.events.on('nodes:add', function(node) {
            // For any newly added uib node, track what type of addition this is
            if ( uibuilder.uibNodeTypes.includes(node.type) ) {
                if (node.changed === false && !('moved' in node)) node.addType = 'load'
                else if (!('_config' in node)) node.addType = 'new'
                else if (node.changed === true && ('_config' in node)) node.addType = 'paste/import'
            }

            // ....
       })
1 Like

That's valuable information, many thanks. Basically, all the things around work already. I'm still unsure about one thing: The previous version of the node had only some plain parameters. No configSet. The new version has that. But afaik, the user must first create a configuration node to be able to assign this to the configSet (usually done in the edit dialogue). If there is no configuration node yet (which is the situation after the update), can I write code to automatically create such a configuration node and assign it to the node?

Ah, yes. That is indeed a bit of an issue. I've fallen foul of this myself in UIBUILDER.

It should be possible to automate the creation of a config node? I've never worked it out though I'm afraid and I can't immediately find any documentation or a thread.

Hopefully someone in this thread may have done it or knows how. I'm afraid I don't.

Yes, I have an example from Victron:

1 Like

Thanks for that. Maybe I'll finally get round to re-factoring UIBUILDER to use a config node! :wink:

That's a sweet reference and I'd like to discuss it with you.

victron seems to deal with strings as the id, am I getting this wrong? It then creates the object victronClientNode and writes id: "victron-client-id". But isn't the ID always some 16 digit random hex thing? Then, what to write as the id value?

As I see, onadd is being executed when a node is beind dragged from the palette. As I try to deal with those who update, this users have the node already on the flow. Now, the only solution I see is to execute it in the oneditprepare phase. I can then creae a configuration with the API function RED.nodes.add(). But I have to close and re-open the edit dialogue in order to find the newly created configSet in the dropdown list. Now any idea how to solve this properly? Here's my solution so far.

The questions are now:

  • What to write in the id field?
  • Is it the best option to create a new configSet in the onloadedit sequence?
  • If so, can I trigger a update of the dropdown in order to see the newly created configSet?

It's not an error, it's a choice to explicitly recognize this node.
Victron systems have mdns (discovery) and therefore the config node does not need configurations to be deployed.

RED.utils.generateId() in the runtime
RED.nodes.id() in the editor

I'll look at the rest tomorrow :wink:

When?, I don't know about this event
I recommend using it in oneditprepare - you must remember that it is a migration (only applies to existing nodes)

if (!hasConfigSet && hasV1Parameters) {
  const configNode = {
    id: RED.nodes.id(),
    _def: RED.nodes.getType("powerswitch configuration"),
    type: "powerswitch configuration",
    name: "",
    toggleTopic: "suchAtoggleTOPIC",
    users: []
  };

  // Complete the dropdown here - reopening the editor is now no needed
  this.configSet = configNode.id;

  RED.nodes.add(configNode)
  RED.nodes.dirty(true)
  console.log("DEBUG: ADDED!")
}

onadd - (ref) this does not appear to be documented anywhere?

It also seems to fire a bit too quickly. If you are pasting or importing, it fires BEFORE you actually add the node to the flow and so if the paste/import is cancelled, it will already have fired.

Oh, another possible issue - this inside the function can be 2 different things it seems. For a drag from the palette, this is the node. But for a paste or import it is actually a proxy wrapper around the node. Not sure if this is important.

Normally no - same as the node object

OK, but otherwise, we are generally warned not to use undocumented features in Node-RED so I'm not sure whether onadd is valid or not?

I believe this is an oversight, plugins and nodes have an onadd property.

This property is old and was internally used for the feature: Allow node name to be auto-generated when added by knolleary · Pull Request #3478 · node-red/node-red · GitHub

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