# Combine different reading (in time) to one average

**URL:** <https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892>\
**Category:** General\
**Created:** [27 April 2022 19:51 UTC](https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892 "2022-04-27T19:51:24Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![promy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/promy/32/60721_2.png) [@promy](https://discourse.nodered.org/u/promy)\
**Post date:** [27 April 2022 19:51 UTC](https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892/1 "2022-04-27T19:51:24Z")

</div>

I have a moisture sensor (esp8266) waking up from deep sleep and sending 2 of 3 reading to a mtqq.  
These readings are approx 60 seconds apart.  
After this it goes to deep sleep again for an hour.  
I would like to make an average from these values and send that to my influxdb.

I'm thinking to use a trigger to detect if it was more than 90 seconds since the last value, but how do you store the previous values to make an average?

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [27 April 2022 20:34 UTC](https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892/2 "2022-04-27T20:34:10Z")

</div>

Hello Promy ..

> [@promy](#):
>
> how do you store the previous values to make an average?

You can use Node-red's Context in order to save those values.  
Flow Context could be an Array in this case and you can push the moisture values to this array until the time to make the average. You can read more about Context in the documentation [here](https://nodered.org/docs/user-guide/writing-functions#storing-data)

I think trying to work out a solution based on timing could be a little tricky and values could get out of sync.  
Would it be possible, if you have access to the code on the ESP8266, to send a msg to Node-red (ie `complete`) to notify Node-red that the last value is sent (before it goes to deep sleep) so you can then make the average calculation ?

**Example Flow using Context and calc. average on complete :**

```auto
[{"id":"260f4b90e1219457","type":"function","z":"54efb553244c241f","name":"Average","func":"// if msg from mqtt is \"complete\"\nif (msg.payload === \"complete\") {\n let moisture = flow.get(\"moisture\")\n let total = 0\n let average = 0\n\n if (moisture.length > 0) {\n moisture.forEach(val => total += val)\n average = total / moisture.length\n\n // send message\n node.send({\n \"topic\": \"moisture\",\n \"payload\": average\n })\n\n flow.set(\"moisture\", []) // reset Context to empty array\n }\n}\n\n// if payload is a Number\nelse if (!isNaN(msg.payload)) {\n let moisture = flow.get(\"moisture\") || []\n moisture.push(msg.payload) // add to Array\n flow.set(\"moisture\", moisture) // save to Context\n}\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":2160,"wires":[["2bd3a9df9a604fdc"]]},{"id":"2bd3a9df9a604fdc","type":"debug","z":"54efb553244c241f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":610,"y":2160,"wires":[]},{"id":"ccafb3ce4b544815","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":210,"y":2060,"wires":[["260f4b90e1219457"]]},{"id":"90ca977ae11dcbe8","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"20","payloadType":"num","x":210,"y":2120,"wires":[["260f4b90e1219457"]]},{"id":"7e7542a9e2ab98d8","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"70","payloadType":"num","x":210,"y":2180,"wires":[["260f4b90e1219457"]]},{"id":"ea19a230362b35c5","type":"inject","z":"54efb553244c241f","name":"complete","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"complete","payloadType":"str","x":200,"y":2260,"wires":[["260f4b90e1219457"]]}]

```

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [27 April 2022 20:38 UTC](https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892/3 "2022-04-27T20:38:33Z")

</div>

You could set it up to complete a join and average the array. logic as below. You never gave any examples of the payloads so you will have to edit to suit. Edit 5 seconds to 90 or what ever suits.

```auto
[{"id":"fd0823d2.c0d288","type":"inject","z":"264dfde8ecb5ecec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"20","payloadType":"num","x":220,"y":160,"wires":[["3c3dc8f9.5284b","b5b5e1fa.953208"]]},{"id":"3c3dc8f9.5284b","type":"trigger","z":"264dfde8ecb5ecec","name":"","op1":"","op2":"true","op1type":"nul","op2type":"bool","duration":"5","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":400,"y":160,"wires":[["7b983965.74a0f8"]]},{"id":"b5b5e1fa.953208","type":"join","z":"264dfde8ecb5ecec","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":420,"y":240,"wires":[["3ce507b4.961278"]]},{"id":"7b983965.74a0f8","type":"change","z":"264dfde8ecb5ecec","name":"","rules":[{"t":"move","p":"payload","pt":"msg","to":"complete","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":160,"wires":[["b5b5e1fa.953208"]]},{"id":"3ce507b4.961278","type":"change","z":"264dfde8ecb5ecec","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$average($$.payload)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":260,"wires":[["96d12108.11f94"]]},{"id":"96d12108.11f94","type":"debug","z":"264dfde8ecb5ecec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":860,"y":260,"wires":[]}]

```

---

<div class="post-metadata">

**Author:** ![9toejack](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/9toejack/32/56868_2.png) [@9toejack](https://discourse.nodered.org/u/9toejack)\
**Post date:** [28 April 2022 04:33 UTC](https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892/4 "2022-04-28T04:33:33Z")

</div>

i was using the smooth node to get the mean value of so many readings.  
have you looked into using it for your average needs?  
here is a small example.

```auto
[{"id":"e693b71ef4b3f0ae","type":"inject","z":"ef2a7eeb036d3b29","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"16","payloadType":"num","x":85.56596374511719,"y":296.9331833862305,"wires":[["ab1b33eeda1dfa36"]]},{"id":"39e3b18a3298285e","type":"inject","z":"ef2a7eeb036d3b29","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"15","payloadType":"num","x":80.56596374511719,"y":349.9279648803711,"wires":[["ab1b33eeda1dfa36"]]},{"id":"cb5c2adb8c74fe7b","type":"inject","z":"ef2a7eeb036d3b29","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"22","payloadType":"num","x":71.56423950195312,"y":393.9297043823242,"wires":[["ab1b33eeda1dfa36"]]},{"id":"ab1b33eeda1dfa36","type":"smooth","z":"ef2a7eeb036d3b29","name":"","property":"payload","action":"mean","count":"3","round":"","mult":"single","reduce":false,"x":274.55902099609375,"y":363.9904648803711,"wires":[[]]}]

```

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [28 April 2022 04:41 UTC](https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892/5 "2022-04-28T04:41:37Z")

</div>

I'm not sure this will help, but I went down a similar path a while ago.

I am getting timed things and wanted to get Maximum, Minimum and Average values.  
(Daily)

Of course _Average_ in itself is a can of worms.  
There are a lot of different meanings in every day talk.

There is "Average", then "Median", "Mean" and a few more.

This `function` node with a bit of code may help.

```auto
[{"id":"acbd4dca.cd318","type":"function","z":"78d17e5b.9e6ff","g":"7e49ed3d.35f9cc","name":"Avg/Max/Min readings","func":"let max = context.get(\"max\") || 0;\nlet counter = context.get(\"counter\") || 0;\nlet min = context.get(\"min\") || null;\nlet avg = context.get(\"avg\") || null;\nlet total = context.get(\"total\") || 0;\n\n\n//node.warn(\"Initial total reading is \" + total);\n//total = total;\n\nlet new_value = parseInt(msg.payload);\n\nmsg1 = {};\nmsg2 = {};\n\nif (msg.reset == true)\n{\n // Reset all things\n node.warn(\"RESET\");\n context.set(\"max\",0);\n context.set(\"counter\",0);\n context.set(\"min\",0);\n context.set(\"avg\",0);\n context.set(\"total\",0);\n return;\n}\n\nif (counter === 0)\n{\n // First pass\n context.set(\"max\",new_value);\n context.set(\"min\",new_value)\n context.set(\"avg\",new_value);\n min = new_value;\n max = new_value;\n avg = new_value;\n total = new_value;\n}\n\n//new_value = msg.payload;\n\nif (new_value > max)\n{\n max = new_value;\n context.set(\"max\",new_value);\n}\n\nif (new_value < min)\n{\n\tmin = new_value;\n\tcontext.set(\"min\",new_value);\n}\n\ncounter = counter + 1;\ncontext.set(\"counter\",counter);\n\ntotal = context.get(\"total\") || 0;\n//node.warn(\"context TOTAL is \" + total);\ntotal = total + new_value;\n//node.warn(\"TOTAL IS NOW \" + total);\ncontext.set(\"total\",total);\navg = Math.round((total / counter));\n\n//\n\n//msg.payload = \"My calculated average is \" + avg;\nmsg.payload = Math.round(avg);\nmsg1.payload = Math.round(max);\nmsg2.payload = Math.round(min);\nreturn [msg,msg1,msg2];","outputs":3,"noerr":0,"initialize":"","finalize":"","x":2170,"y":1670,"wires":[["b6b37cab.88821","267b42e0.270b16"],["e631bde7.36527","1b588bd.547a2f4"],["e8ec38d8.a3c568","89fd7801.01c23"]],"outputLabels":["AVG","MAX","MIN"]}]

```

You will need to send a special message into it to signal a `New day` and that will reset things for the next/new day.

Hope it helps.

This is a bigger picture of how it is in my flow.

 ![Screenshot from 2022-04-28 14-42-41](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/4/84d2bd5c1a0cf64cbe7be7bc55e37eba7904a8b6.png)

The input is at the red arrow.  
The New day pulse is into the `New Day` input.  
The 3 outputs of the node are labelled if/when you import it and put the mouse over them.  
At the top that is a bit more stuff I do which you may/not want to use.

But the `function` node does what you want - I hope.

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [28 April 2022 08:49 UTC](https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892/6 "2022-04-28T08:49:42Z")

</div>

For an average (mean) value you only need a total and a count. It seems over the top to save all the readings in memory.

You could accumulate the total and count in flow context.

To reset them a trigger node set to send nothing, after 5 minutes send a message to a change node to reset.

I am not very familiar with influxdb. If it was SQL I would insert a record if flow.count == 1, update the latest record if flow.count \> 1.

Or, if you prefer, insert an average reading immediately before resetting the context variables

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [27 June 2022 08:50 UTC](https://discourse.nodered.org/t/combine-different-reading-in-time-to-one-average/61892/7 "2022-06-27T08:50:19Z")

</div>

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