Announce node-red-contrib-math

Hey Nick, that is indeed the way of working I always prefer. But there is no readme page and I couldn't find the package on Github. And then I gave up, since I have already too many questions, issues, pull requests, ... that have never been answered. Have toom much work and too few time to keep on waiting for the rest of the world ...

Had a weak moment, so I have considered (during two minutes) to contact the author of the original node-red-contrib-math node and create a pull request to merge my stuff into his node.

Since that node has no documentation, I have installed it to discover its functionalities.
Seems it contains currently only two operations:

image

Therefore I'm not going to spend some evenings converting all my developments/documentation into a pull request.

I'm pretty sure all of you will understand :lying_face:

Hey guys,

I have published version 1.0.0 on NPM which contains some extra operations:

  • Random value between a minimum and maximum value
  • Random from an array of values
  • Length of the input array
  • Sort array numbers ascending
  • Sort array numbers descending
3 Likes

I've release version 1.0.1 on npm with two new operations, to create a range array and calculate a distance inside an array:

image

Now I would also like to implement a moving average operation.
For example the input is an array [1, 2, 3, 4, 5, 6, 7, 8, 9] and the window size is 4.
Then the output would be following array:

image

I don't think this exist yet in other contributions? It seems to me that e.g. the node-red-node-smooth and the node-red-contrib-average nodes calculate the average across multiple messages?

But I'm not sure where the user should specify the window length. Indeed that would be the first operation that has as input both an array AND a separate number (see readme for examples of other operations). Any tips are welcome!

Bart

So how would the window work across multiple messages ? Or are they independent ? Do you have an actual use case for this ?

The batch node can create arrays with or without overlapping members - and then the join node can apply a reduce function to those - aka a sliding window... so I would say it can be done already.

1 Like

Hi Dave,
I would like to calculate it only on a single message (which contains an array), since my calc-node only operates on a single message. The other nodes (like average-node) seem to operate on data from multiple messages:
image

So a split then a join in reduce mode with a suitable expression could do same - albeit in two nodes.

If you are adding new features should it not go to 1.1.0?

Yes that is true. But I was in the mood to spoil the NR users. Remember that in Belgium tonight Saint Nicholas will throw presents through the chimney, since it is tomorrow Saint Nicholas Day ...

Yep, you are right. I shall update it, as soon as I add a new operation ... So if you have good ideas for extra operations on my node, I can set this right much faster :wink:

1 Like

Spoil or confuse ? Too much choice (or chocolate) can be a bad thing :wink:

Now I would also like to implement a moving average operation. I don't think this exist yet in other contributions?

node-red-contrib-statistics does that. You can set a window size for all of the statistical measures and pass in arrays of data.

Or are you wanting to output an array of moving averages, like a data reduction/smoothing?

Hey Dean, long time no seen ...
Yes I wanted to create an array of moving averages, based on an input array and a window size (like in my example above). But didn't know where to specify the window size, since all other operations expect (as input) an array of numbers OR a single number. But not both ...

Use the property/property type approach so that it can be specified wherever the user chooses - msg property, flow/global property, static value, calculated (jsonata).

That is indeed a possible solution.
But currently - when an operation needs two parameters - I expect them to arrive as an array of length two. Some examples:

  • Round 1.23456 at a 3 decimal places:

    Input = [1.23456, 3] => Output = [1.234]

  • 2 to the power of 3:

    Input = [2, 3] => Output = 8

But I cannot use this approach when the input is both an array AND a number (since the extra number at the end of the array will just be considered as a longer array). So when I now require an extra field to be filled in, it might be confusing.

Perhaps it is better if I drop this new operation.
Moreover, I don't want to give Dave an overdose of chocolate ...

1 Like

The property/property type approach will handle this as you can do deep object specification ie msg.payload[2] or msg.payload[1] or msg.payload.length or even msg.payload[1][0] (that's an array of arrays).

In all honesty, hard coding stuff like this just makes life difficult for everyone and really reduces the usefulness of utility nodes like this.

Let me give you an example. I have a climate monitoring flow that passes around an object containing current temp, humidity, and air pressure readings. All these readings need to stay together as they are related and represent a complex measurement. Along the way I do some calculations for heat factor which come out with an excessive number of decimal places. It would be nice to be able to pass my object through your node and tell it to round the heat factor property to a sensible 1 decimal place. In your current approach, I need to save the original climate object somewhere, extract the heat factor property, turn it into an array, add the required decimal places, pass it through your node, extract the result from the array, and insert the result back into the original climate object before sending it on its merry way. I would much prefer to just be able to pass the entire object through your node and tell it to operate on a specific property of that object.

Morning Dean, that is indeed correct. What a pitty that you were not available at the start of this discussion. Now I have published it with the array behaviour already ...

You can still do it and maintain backwards compatibility - the property/property type approach is really flexible.

Give me a shout if you would like some assistance

@BartButenaers

Just a modest question:

Did you consider the effort/effectiveness' relationship for this contrib node?

It seems to me, that it's a wrap of the Math() function. I generally use Math() in function nodes or in a contrib node, I can't see the benefit of using your node in a flow.

Could you show some practical examples?

E.g. who would use Hyperbolic cosine (cosh) in a node-red flow?

@cflurin: You haven given a very bad example :face_with_raised_eyebrow: Normally I try to add documentation for all functionalities, but on my readme page you will see that I haven't even added examples for those kind of operations. Have just added them for completeness, but they are at the end of the list to make sure they don't disturb users. I have experienced in the last two years that people do complete crazy things with my nodes, so it is just there in case some weird mind needs it...

And yes, performance will be much better when you just call the Math functions in a Function node (without type checks, and so on ....). However, this node is aimed at another user group, who prefer to search hours on Google to find an out-of-the-box solutions instead of writing a single line of Javascript... When I'm in a social mood, I develop nodes that I'm never going to use myself ... And you are also not part of my target audience :wink:

Have put it on my TODO list...

Hi Bart,

Well, it's your node and it's open source :grinning:. I hope some users will post interesting flow examples.

Generally I try to use the core nodes and only add specific contrib-nodes.
This way I can reduce the software maintenance and increase the stability.