Diary data average value


Is node-red able to send an media value of the data that is receiving from a PLC.
For example to know the speed that the robot has been working during the day.
So one value has been changing all day and at the end of the day I want to know the media value can I do it with node-red?



The inject node can be scheduled to repeat every 24 hours. When the node fires use your existing code to retrieve data from the robot.

If the robot can make an http call to send data to node-red you can start the flow with an http node.

How you process the data in node-red is another topic depending upon what you want to do. Adding a debug node will allow you to see values during testing. You can send values back to robot using http or other methods.

A best practice when asking questions is to include how you plan to implement a soultion conceptually. Like node-red calls robot REST API once per day receiving data in JSON format. The data includes hourly speed values. Node-red needs to do x and send resulting data to robot using REST API in JSON fromat. Then list the format needed. If you already know how you will achieve the above then it’s not needed.

1 Like


I connect the robot with the node -red via s7 node because I have a PLC, but I don´t know how to connect inject with the s7 node to notify the value when I set it in the inject.
Any example? Thank you



By media value do you mean the average (median)?
If so then you could feed the values into a function node and keep a running total and a count in the node context, then at the end of the day you can get the median.



okey and do you know which command do I need to put? I am new at this tings sorry :sweat_smile:



Looks like the s7 node supports inbound communication. Is you PLC able to communicate via ethernet? Is the computer running plc programmer also running node-red?
Node-red configurqtion suggestions. https://flows.nodered.org/node/node-red-contrib-s7

The node-red code appers to be writting on top of s7 which provides more information. https://github.com/plcpeople/nodeS7.

After reading these it appears s7 node should work with S7-300/400/1200/1500 PLCs using the Siemens S7 Ethernet protocol. Do you have model 300 or higher which includes ethernet?



yes I can see the PLC signals in node red but I want to receive a notification of the average value of motor sepeed for example durimg the day and I don´t know what to do for that



Are you able to get the motor speed?
Also, is the PLC able to work out the median for you?



but the value changes during the day so I want to calculate with NOde-red the average value and then send a notification



so have one flow that calculates the average value and stores it as a context value.

Have another flow triggered at the end of the day that gets the context value and resets the average. Context values are explined in the documentation and there are examples in the cookbook



There is a calculator node that will perform averages https://flows.nodered.org/node/node-red-contrib-calc. Takes an array so you will need to capture speed value from the robot and add to array.

Simplistic example.
Use your s7 node. Set interval to read speed variable. I assume speed value appears in a debug node under msg.payload.

Connect s7 node output to a function node.

//****** Start Paste in this code:
//assumes speed is coming in on payload. Could be another topic like msg.speed...
// like this from Debug payload: array[1] / Debug payload. Indicates it's an array.
//0: 100 // 0: ia the array number and 100 is the speed value.
// You may have to put your speed value into an array if not already.
// msg.payload = [100]; where 100 is the speed value captured.

var speed = msg.payload; //set a variable to speed value in payload object.

var speedSamples = flow.get("speedSamples");
var speedSampleslength = speedSamples.length; // gets the length (depth) of the array
speedSamples[speedSampleslength] = speed; // now add the current speed reading to the end of the array. (length)
flow.set("speedSamples", speedSamples); // save the context. Esentially this is a variable with the scope of the current flow.

msg.speedSamples = speedSamples; //Add the contents of Variable seedSamples to the message topic speedSamples. Could also set to msg.payload. does not matter

msg.length= speedSampleslength; // added just to Debug the new array size.
return msg;

//***********End paste code

Add a calculator node to node-red https://flows.nodered.org/node/node-red-contrib-calc
Can add this via Node-Red Manage Pallet -> Install ( Select from upper right Hamburger icon)
Set calculator node
1.Input field to msg.speedSamples
2. Output to msg.payload
3. Operation to Average

Connect to Debug node for test.

Connect another function step to output of calculator
//****** Start Paste in this code:
var speedAverage = msg.payload; //set a variable to speed value in payload objrvy
flow.set("speedAverage",speedAverage); // Set context to hold last average value
return msg;
//***********End paste code

Need to reset the speedSamples array and set to the last average value. I made this up so you may want to change how this works. Instead of letting the size of the array grow indefinitely you will want to maintain it's length (depth). I am resetting the length to 1 and the value to the last average. You may want to maintain a sliding window For example a thousands speedSamples. That requires some array work and you should look up how to do this. Copying arrays.

Now add an Inject node and function node.
Connect Inject node to function node.
Check the box inject once after .1 seconds and then Repeat none. // This will initialize the speedAverages array to 1 with a value of 50. You can change the starting value in the function coming up next.
Use the inject to reset just like a push button.

In the function node.
//****** Start Paste in this code:
var speedAverage = flow.get("speedAverage");
if (isNaN(speedAverage)){
speedAverage = 50; // if context is lost use the value 50 for speed starting point. Random choice.
flow.set("speedSamples", [speedAverage]);
return msg;
//***********End paste code

Put Debug nodes everywhere to start. Set to object. When you come home you will see every value captured throughout the day in msg.speedSamples array.
You will also see current average speed of the day.

This should get you started.



Or use the node-red-contrib-smooth node if you want the running mean/average of a certain number of incoming payloads.


[{"id":"c9a971b0.f6cd4","type":"inject","z":"76677361.7da3fc","name":"","topic":"","payload":"50","payloadType":"num","repeat":"","crontab":"","once":true,"onceDelay":".1","x":190,"y":980,"wires":[["f39b6ed0.f1c65"]]},{"id":"95b2538e.a4d93","type":"calculator","z":"76677361.7da3fc","name":"","inputMsgField":"speedSamples","outputMsgField":"payload","operation":"avg","constant":"","x":920,"y":831,"wires":[["e0685778.cc2eb8","9387d7c5.fbcee8"]]},{"id":"e0685778.cc2eb8","type":"debug","z":"76677361.7da3fc","name":"view speedAverage","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1450,"y":820,"wires":[]},{"id":"d77acc39.5f5bc","type":"debug","z":"76677361.7da3fc","name":"view speedSamples array","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1470,"y":760,"wires":[]},{"id":"d80f5de0.cc356","type":"function","z":"76677361.7da3fc","name":"add new speed value to array","func":"//assumes speed is coming in on payload. Could be another topic like msg.speed...\n\nvar speed = msg.payload; //set a variable to speed value in payload object. \n\n// get speedSamples array from context and set speedSamples array variable\nvar speedSamples = flow.get(\"speedSamples\");\n// if speedSamples array is invalid then set first array element to current speed. Note: more could go wrong here. More checks may be needed. \nif (isNaN(speedSamples)){\n    speedSamples[0] = speed;\n}\n\nvar speedSampleslength = speedSamples.length; // gets the length (depth) of the array\nspeedSamples[speedSampleslength] = speed; // now add the current speed reading to the end of the array. (length)\nflow.set(\"speedSamples\", speedSamples); // save the context. Esentially this is a variable with the scope of the current flow. \n\nmsg.speedSamples = speedSamples; //Add the contents of Variable seedSamples to the message topic speedSamples. Could also set to msg.payload. does not matter\n\nmsg.length= speedSampleslength; // added just to Debug the new array size.\nreturn msg;","outputs":1,"noerr":0,"x":659,"y":830,"wires":[["d77acc39.5f5bc","95b2538e.a4d93","9603c79.75ea338"]]},{"id":"cc098779.8f15c8","type":"inject","z":"76677361.7da3fc","name":"speed value 25","topic":"","payload":"25","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":"","x":200,"y":855,"wires":[["d80f5de0.cc356"]]},{"id":"f39b6ed0.f1c65","type":"function","z":"76677361.7da3fc","name":"Initialize array with value of msg.payload","func":"\n\n\nvar speedAverage = flow.get(\"speedAverage\");\nif (isNaN(speedAverage)){\n    speedAverage = msg.payload;\n}\n// sets array to 1 entry. Used to clear speedAverage array.\n// option uncomment one or the other\n//flow.set(\"speedSamples\", [speedAverage]); uncomment to use last average speed to initial array.\nflow.set(\"speedSamples\", [msg.payload]); //uncomment to use inject or other input to set starting average. Maybe current speed.\n\nreturn msg;","outputs":1,"noerr":0,"x":500,"y":980,"wires":[[]]},{"id":"9387d7c5.fbcee8","type":"change","z":"76677361.7da3fc","name":"set flow.speedAverage from payload","rules":[{"t":"set","p":"speedAverage","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1170,"y":900,"wires":[["e22d5e9d.b0d79"]]},{"id":"13b9bf2f.640961","type":"inject","z":"76677361.7da3fc","name":"speed value 13","topic":"","payload":"13","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":"","x":200,"y":895,"wires":[["d80f5de0.cc356"]]},{"id":"23b2e8c5.05c2b8","type":"inject","z":"76677361.7da3fc","name":"speed value 49","topic":"","payload":"49","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":"","x":200,"y":814,"wires":[["d80f5de0.cc356"]]},{"id":"e523c9c6.662388","type":"inject","z":"76677361.7da3fc","name":"speed value 100","topic":"","payload":"100","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":"","x":200,"y":773,"wires":[["d80f5de0.cc356"]]},{"id":"9603c79.75ea338","type":"change","z":"76677361.7da3fc","name":"set flow.speedSamples from payload","rules":[{"t":"set","p":"speedSamples","pt":"msg","to":"speedSamples","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":1170,"y":940,"wires":[["c315ab13.a64348"]]},{"id":"e22d5e9d.b0d79","type":"debug","z":"76677361.7da3fc","name":"view speedAverage flow context set","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1510,"y":900,"wires":[]},{"id":"c315ab13.a64348","type":"debug","z":"76677361.7da3fc","name":"view speedSamples flow context set","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1510,"y":940,"wires":[]}]