Recording a sequence of sensor data for a defined time on trigger

Hi there,

I'm new to node-RED and not familiar to java script at all.
I started an automation project at work were I want to collect sensor data from different sources and send them to a db via MQTT.

Fotos, forms (via Dashboard) and static values are no problem at all.

The "last" (ofc not the last :smiley: ) problem I want to solve is to record a series of sensor data from specific sensors on an external trigger for a specific time period. I get a trigger signal from a control unit and want to "store" all values the analog signal of the sensor gives me for a defined time (e.g. 2s). The output might be an array (JSON?) or a string (write to text file?) so I can handle it.

I don't see how to solve this problem without writing my own code in jave script and don't have the capacities to learn it right now.

Thanks for your help and regards
Bastian

Hi, welcome to the forum.

This should get you started off...

dYHfxe7sTF

[{"id":"226f9f18a6afc487","type":"function","z":"553814a2.1248ec","name":"Payload recorder","func":"\nlet recording = context.get(\"recording\") || false;//get logging recording\n\nif (msg.topic == \"start\") {\n    context.set(\"recording\", true);\n    context.set(\"measures\", []);\n    node.status({fill:\"green\",shape:\"ring\",text:\"Recording\"});\n    return [null, null];//no output\n}\n\nif (msg.topic == \"stop\") {\n    context.set(\"recording\", false);\n    msg.payload = [...context.get(\"measures\") || []];\n    context.set(\"measures\", null);\n    node.status({ fill: \"red\", shape: \"ring\", text: \"Stopped\" });\n    return [null, msg];//pass recorded data out of pin 2\n}\n\nif (recording) {\n    const measures = context.get(\"measures\") || [];\n    measures.push(msg.payload);\n    context.set(\"measures\", measures);\n    return [msg, null];//pass msg on to next node\n}\n","outputs":2,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\n\nlet recording = context.get(\"recording\") || false\nif (recording) {\n    node.status({ fill: \"green\", shape: \"ring\", text: \"Recording\" });\n} else {\n    node.status({ fill: \"red\", shape: \"ring\", text: \"Stopped\" });\n}","finalize":"","libs":[],"x":2090,"y":460,"wires":[["5999900b2df185a4"],["e6140c609f34d805"]]},{"id":"5999900b2df185a4","type":"debug","z":"553814a2.1248ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":2290,"y":420,"wires":[]},{"id":"0f206903f17e01f9","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":1870,"y":500,"wires":[["226f9f18a6afc487"]]},{"id":"08c8d12fc86a3f32","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":1870,"y":460,"wires":[["226f9f18a6afc487"]]},{"id":"e6140c609f34d805","type":"debug","z":"553814a2.1248ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":2290,"y":500,"wires":[]},{"id":"8b336f39bb3cdd09","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"2","payloadType":"num","x":1870,"y":540,"wires":[["226f9f18a6afc487"]]},{"id":"9b5e4af82c56b7c9","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"start","x":1870,"y":360,"wires":[["226f9f18a6afc487"]]},{"id":"0fc71aab7e1b81da","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"stop","x":1870,"y":400,"wires":[["226f9f18a6afc487"]]}]

In the demo i use numbers for the data but they could be anything (Object, JSON/string, Array, Buffer, etc).

NOTE: this only records the payload part of a message. If you need to store the topic also we could easily modify it to do so.

Hi Steve!
Thx for the fast answer. I tried to implement your demo code like shown below but couldn't succeed so far. I guess the function code is not active yet.


Regards
Bastian

Have you copied my flow directly into a function node?

Just press CTRL+I to import a flow.

It may look more or less like this:


I think an export via MQTT with a simple array as payload should be fine.
The trigger seems not to be able to set a topic ("stop") for stopping the record.

Did you see my previous post?

There was no need for you to re-create all the nodes - my flow had everything required to work as a demo.

Hi Steve. Sorry, I didnt read your post in time. I works perfectly fine now!

Is it possible to set a record time to end it automatically (like a trigger node does)?

Also I have investigated that the frequency of sensor values is not discrete. This means I need any type of counter or time stamp (for each value) to keep a realtistic scaling.

Thanks for your help and patience

Yes, use a trigger node to send stop in the topic after xxx seconds.

Instead of storing the payload directly, create an object, add the payload & a timestamp to the object then store the object in the context array.

I understand what you mean, but I lack the knowledge about the correct syntax and the function of objekts in Java. Would you help me out with it? :slight_smile:
payload_recorder_screenshot5

I changed my msg.payload and added 1 column for the time.
payload_recorder_screenshot8

Now my final output gets some trouble with the data format. I guess there is missing that new dimension. How can I fix this?
payload_recorder_screenshot9

I suspect the payload object is being destroyed by reference somewhere further down your flow.

This works...

[{"id":"226f9f18a6afc487","type":"function","z":"553814a2.1248ec","name":"Payload recorder","func":"\nlet recording = context.get(\"recording\") || false;//get logging recording\n\nif (msg.topic == \"start\") {\n    context.set(\"recording\", true);\n    context.set(\"measures\", []);\n    node.status({fill:\"green\",shape:\"ring\",text:\"Recording\"});\n    return [null, null];//no output\n}\n\nif (msg.topic == \"stop\") {\n    context.set(\"recording\", false);\n    msg.payload = [...context.get(\"measures\") || []];\n    context.set(\"measures\", null);\n    node.status({ fill: \"red\", shape: \"ring\", text: \"Stopped\" });\n    return [null, msg];//pass recorded data out of pin 2\n}\n\nif (recording) {\n    const measures = context.get(\"measures\") || [];\n    const o = {\n        payload: msg.payload,\n        topic: msg.topic,\n        timestamp: Date.now()\n    }\n    measures.push(o);\n    context.set(\"measures\", measures);\n    return [msg, null];//pass msg on to next node\n}\n","outputs":2,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\n\nlet recording = context.get(\"recording\") || false\nif (recording) {\n    node.status({ fill: \"green\", shape: \"ring\", text: \"Recording\" });\n} else {\n    node.status({ fill: \"red\", shape: \"ring\", text: \"Stopped\" });\n}","finalize":"","libs":[],"x":2090,"y":460,"wires":[["5999900b2df185a4"],["e6140c609f34d805"]]},{"id":"5999900b2df185a4","type":"debug","z":"553814a2.1248ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":2290,"y":420,"wires":[]},{"id":"0f206903f17e01f9","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"livingroom/switch/1","payload":"1","payloadType":"num","x":1810,"y":500,"wires":[["226f9f18a6afc487"]]},{"id":"08c8d12fc86a3f32","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"livingroom/switch/1","payload":"0","payloadType":"num","x":1810,"y":460,"wires":[["226f9f18a6afc487"]]},{"id":"e6140c609f34d805","type":"debug","z":"553814a2.1248ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":2290,"y":500,"wires":[]},{"id":"8b336f39bb3cdd09","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"bedroom/temperature","payload":"22.2","payloadType":"num","x":1830,"y":540,"wires":[["226f9f18a6afc487"]]},{"id":"9b5e4af82c56b7c9","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"start","x":1870,"y":360,"wires":[["226f9f18a6afc487"]]},{"id":"0fc71aab7e1b81da","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"stop","x":1870,"y":400,"wires":[["226f9f18a6afc487"]]},{"id":"1dfff66dc2c243ba","type":"inject","z":"553814a2.1248ec","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"bedroom/temperature","payload":"22.4","payloadType":"num","x":1830,"y":580,"wires":[["226f9f18a6afc487"]]}]

Output showing payload topic and a timestamp were saved & sent when stopped...

This works! Thank you very much, Sir! :muscle:

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