Trying to sort data from different input prior to combined them

Hi,
I was able to get data from a mavlink stream and a serial input.
I implement a delay to limit the output rate to 1 second for all data.
Somehow the data output can be mixup and I get gas data first followed by mavlink or the other way around. I tried to implement a "sorts" node but it does'nt work. I need your help:)

In the functions nodes, I add a topic, key and parts number to the msg of each data. My idea was to sort the output base on this. It dont work. I feel this come from the fact that mavlink is an object while serial in is float.

The serial stream is this exact formatted string --> D, 1111.1,1111.11,1111.1\r where the 1111 change and are in fact float value. They are parsed and tag when they get in.

this is my flow.

[   
   {
        "id": "055aa8fd1f8a8f4e",
        "type": "tab",
        "label": "Flow 2",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "7c6626e8bf2da44f",
        "type": "websocket in",
        "z": "055aa8fd1f8a8f4e",
        "name": "heartbeat",
        "server": "397172b08ff52a59",
        "client": "",
        "x": 140,
        "y": 80,
        "wires": [
            [
                "4e1e4d987636f511"
            ]
        ]
    },
    {
        "id": "4e1e4d987636f511",
        "type": "json",
        "z": "055aa8fd1f8a8f4e",
        "name": "messages",
        "property": "payload",
        "action": "obj",
        "pretty": false,
        "x": 310,
        "y": 80,
        "wires": [
            [
                "cf22c4ccac44da55",
                "f43b7be2f74a58b8"
            ]
        ]
    },
    {
        "id": "cf22c4ccac44da55",
        "type": "switch",
        "z": "055aa8fd1f8a8f4e",
        "name": "MAvLink_split",
        "property": "payload.message.type",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "BATTERY_STATUS",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "GPS_RAW_INT",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 520,
        "y": 80,
        "wires": [
            [
                "fb1a25da9fe782ba"
            ],
            [
                "e3de8131253b36cf"
            ]
        ]
    },
    {
        "id": "fb1a25da9fe782ba",
        "type": "function",
        "z": "055aa8fd1f8a8f4e",
        "name": "vBatt",
        "func": "msg.payload = msg.payload.message.voltages[0] / 1000.00\nmsg.topic = \"Voltage\"\nmsg.key = 1\nmsg.parts = 1\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 750,
        "y": 60,
        "wires": [
            [
                "5c91fb558c0c86a9"
            ]
        ]
    },
    {
        "id": "e3de8131253b36cf",
        "type": "function",
        "z": "055aa8fd1f8a8f4e",
        "name": "lat",
        "func": "msg.payload = msg.payload.message.lat\nmsg.topic = \"latitude\"\nmsg.key = 2\nmsg.parts = 2\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 750,
        "y": 120,
        "wires": [
            [
                "5c91fb558c0c86a9"
            ]
        ]
    },
    {
        "id": "5c91fb558c0c86a9",
        "type": "delay",
        "z": "055aa8fd1f8a8f4e",
        "name": "",
        "pauseType": "timed",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "allowrate": false,
        "outputs": 1,
        "x": 1070,
        "y": 220,
        "wires": [
            [
                "c456570e893e8283"
            ]
        ]
    },
    {
        "id": "c456570e893e8283",
        "type": "debug",
        "z": "055aa8fd1f8a8f4e",
        "name": "Output",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 1280,
        "y": 40,
        "wires": []
    },
    {
        "id": "98e33ae787dd77cd",
        "type": "serial in",
        "z": "055aa8fd1f8a8f4e",
        "name": "Sensor_port",
        "serial": "1a0db8d82e42aefd",
        "x": 130,
        "y": 300,
        "wires": [
            [
                "3c6a2469bd653496"
            ]
        ]
    },
    {
        "id": "3c6a2469bd653496",
        "type": "function",
        "z": "055aa8fd1f8a8f4e",
        "name": "function 2",
        "func": "var elements = msg.payload.split(\",\");\nmsg.payload = {\n    A: parseFloat(elements[1]),\n    B: parseFloat(elements[2]),\n    C: parseFloat(elements[3]),    \n}\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 320,
        "y": 300,
        "wires": [
            [
                "ee9650c9b9db9cad",
                "0b43e1183e307ee9",
                "e41997e8a632ad3c"
            ]
        ]
    },
    {
        "id": "ee9650c9b9db9cad",
        "type": "function",
        "z": "055aa8fd1f8a8f4e",
        "name": "Gas_A_data",
        "func": "msg.payload = msg.payload.A\nmsg.topic = \"gas_A\"\nmsg.key = 3\nmsg.parts = 3\nreturn msg",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 750,
        "y": 300,
        "wires": [
            [
                "5c91fb558c0c86a9"
            ]
        ]
    },
    {
        "id": "0b43e1183e307ee9",
        "type": "function",
        "z": "055aa8fd1f8a8f4e",
        "name": "Gas_B_data",
        "func": "msg.payload = msg.payload.B\nmsg.topic = \"gas_B\"\nmsg.key = 4\nmsg.parts = 4\nreturn msg",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 750,
        "y": 380,
        "wires": [
            [
                "5c91fb558c0c86a9"
            ]
        ]
    },
    {
        "id": "e41997e8a632ad3c",
        "type": "function",
        "z": "055aa8fd1f8a8f4e",
        "name": "mBar_data",
        "func": "msg.payload = msg.payload.C\nmsg.topic = \"mBar\"\nmsg.key = 5\nmsg.parts = 5\nreturn msg",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 750,
        "y": 460,
        "wires": [
            [
                "5c91fb558c0c86a9"
            ]
        ]
    },
    {
        "id": "f43b7be2f74a58b8",
        "type": "debug",
        "z": "055aa8fd1f8a8f4e",
        "name": "debug 27",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 470,
        "y": 180,
        "wires": []
    },
    {
        "id": "397172b08ff52a59",
        "type": "websocket-listener",
        "path": "ws://192.168.2.2/mavlink2rest/ws/mavlink",
        "wholemsg": "false"
    },
    {
        "id": "1a0db8d82e42aefd",
        "type": "serial-port",
        "name": "Serial_In",
        "serialport": "/dev/ttyAMA2",
        "serialbaud": "115200",
        "databits": "8",
        "parity": "none",
        "stopbits": "1",
        "waitfor": "D",
        "dtr": "none",
        "rts": "none",
        "cts": "none",
        "dsr": "none",
        "newline": "\\r",
        "bin": "false",
        "out": "char",
        "addchar": "",
        "responsetimeout": "1000"
    }
]

Hello @Phyto , welcome to the forum.

I get the impression you are trying to reinvent the Split and Join nodes as Functions.

Put debug nodes on your two inputs so we can see some real data. (post the data not a picture and falsify any confidential properties).

What output or outputs do you expect to get from these?

Hi @jbudd

I am uncertain as how to put real data. Let try this:

Mavlink is highly volubile thing. Debug on the fisrt node would fill the whole forum :). here is the output from the mavlink split node:

vBatt:

{"header":{"component_id":1,"sequence":206,"system_id":1},"message":{"battery_function":{"type":"MAV_BATTERY_FUNCTION_UNKNOWN"},"battery_remaining":-1,"charge_state":{"type":"MAV_BATTERY_CHARGE_STATE_OK"},"current_battery":88,"current_consumed":170,"energy_consumed":95,"id":0,"mavtype":{"type":"MAV_BATTERY_TYPE_UNKNOWN"},"temperature":32767,"time_remaining":0,"type":"BATTERY_STATUS","voltages":[15438,65535,65535,65535,65535,65535,65535,65535,65535,65535]}}

lat:

{"header":{"component_id":1,"sequence":216,"system_id":1},"message":{"alt":-17000,"alt_ellipsoid":0,"cog":0,"eph":9999,"epv":9999,"fix_type":{"type":"GPS_FIX_TYPE_NO_FIX"},"h_acc":4294967295,"hdg_acc":0,"lat":0,"lon":0,"satellites_visible":0,"time_usec":0,"type":"GPS_RAW_INT","v_acc":3750074112,"vel":0,"vel_acc":20000,"yaw":0}}

Sensor data directly at the (serial port). Please note that this string come from a microcontroller. I spend some time to format and split it and it never work until i build the split function myself. I am new to node-red... So all this to say that I can manipulate this string in the microcontroller to make it more usefull in node-red if it is needed. For example, I can remove the comma or the "D".

D,1159.5,3.02,1008.4

My final goal is to store those data in a txt file. This part is actually working but depending on boot/rebbot cycle, I end up with a final txt file in which data are not always in the same order. This is what I want to avoid using sort..

edit: I forgot to mention and it is not in my flow. Of course, I have a join node at the very end of this. I tried to input a sort node before the join. I also tried after sort node. In both case the output stop at the sort node. Whatever get in never get out of it.

Here is an example of a manual key value join.

[{"id":"d81cf4b2b1fb6a72","type":"inject","z":"055aa8fd1f8a8f4e","name":"vBatt","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"header\":{\"component_id\":1,\"sequence\":206,\"system_id\":1},\"message\":{\"battery_function\":{\"type\":\"MAV_BATTERY_FUNCTION_UNKNOWN\"},\"battery_remaining\":-1,\"charge_state\":{\"type\":\"MAV_BATTERY_CHARGE_STATE_OK\"},\"current_battery\":88,\"current_consumed\":170,\"energy_consumed\":95,\"id\":0,\"mavtype\":{\"type\":\"MAV_BATTERY_TYPE_UNKNOWN\"},\"temperature\":32767,\"time_remaining\":0,\"type\":\"BATTERY_STATUS\",\"voltages\":[15438,65535,65535,65535,65535,65535,65535,65535,65535,65535]}}","payloadType":"str","x":110,"y":60,"wires":[["4e1e4d987636f511"]]},{"id":"4e1e4d987636f511","type":"json","z":"055aa8fd1f8a8f4e","name":"messages","property":"payload","action":"obj","pretty":false,"x":310,"y":80,"wires":[["cf22c4ccac44da55"]]},{"id":"158b2f6dc1c82d9e","type":"inject","z":"055aa8fd1f8a8f4e","name":"lat","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"header\":{\"component_id\":1,\"sequence\":216,\"system_id\":1},\"message\":{\"alt\":-17000,\"alt_ellipsoid\":0,\"cog\":0,\"eph\":9999,\"epv\":9999,\"fix_type\":{\"type\":\"GPS_FIX_TYPE_NO_FIX\"},\"h_acc\":4294967295,\"hdg_acc\":0,\"lat\":0,\"lon\":0,\"satellites_visible\":0,\"time_usec\":0,\"type\":\"GPS_RAW_INT\",\"v_acc\":3750074112,\"vel\":0,\"vel_acc\":20000,\"yaw\":0}}","payloadType":"str","x":110,"y":100,"wires":[["4e1e4d987636f511"]]},{"id":"cf22c4ccac44da55","type":"switch","z":"055aa8fd1f8a8f4e","name":"MAvLink_split","property":"payload.message.type","propertyType":"msg","rules":[{"t":"eq","v":"BATTERY_STATUS","vt":"str"},{"t":"eq","v":"GPS_RAW_INT","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":480,"y":80,"wires":[["fb1a25da9fe782ba"],["e3de8131253b36cf"]]},{"id":"fb1a25da9fe782ba","type":"function","z":"055aa8fd1f8a8f4e","name":"vBatt","func":"msg.payload = msg.payload.message.voltages[0] / 1000.00\nmsg.topic = \"Voltage\"\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":630,"y":60,"wires":[["a50ad5cbf62f02bb"]]},{"id":"e3de8131253b36cf","type":"function","z":"055aa8fd1f8a8f4e","name":"lat","func":"msg.payload = msg.payload.message.lat\nmsg.topic = \"latitude\"\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":630,"y":120,"wires":[["a50ad5cbf62f02bb"]]},{"id":"a50ad5cbf62f02bb","type":"join","z":"055aa8fd1f8a8f4e","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"5","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":770,"y":160,"wires":[["c456570e893e8283"]]},{"id":"3c6a2469bd653496","type":"function","z":"055aa8fd1f8a8f4e","name":"function 2","func":"let elements = msg.payload.split(\",\");\nlet topics = [\"Gas_A\", \"Gas_B\", \"mBar\"];\nelements.slice(1).forEach((str, index) => {\n    node.send({\n        payload: parseFloat(str),\n        topic: topics[index]\n    })\n})\nreturn null;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":200,"wires":[["a50ad5cbf62f02bb"]]},{"id":"c456570e893e8283","type":"debug","z":"055aa8fd1f8a8f4e","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":910,"y":160,"wires":[]},{"id":"a58aea6baceaa571","type":"inject","z":"055aa8fd1f8a8f4e","name":"serial","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"\"D, 1111.1,1111.11,1111.1\\r\"","payloadType":"json","x":110,"y":200,"wires":[["3c6a2469bd653496"]]}]

Here is an example of a manual merge join.

[{"id":"4e1e4d987636f511","type":"json","z":"055aa8fd1f8a8f4e","name":"messages","property":"payload","action":"obj","pretty":false,"x":310,"y":80,"wires":[["cf22c4ccac44da55"]]},{"id":"d81cf4b2b1fb6a72","type":"inject","z":"055aa8fd1f8a8f4e","name":"vBatt","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"header\":{\"component_id\":1,\"sequence\":206,\"system_id\":1},\"message\":{\"battery_function\":{\"type\":\"MAV_BATTERY_FUNCTION_UNKNOWN\"},\"battery_remaining\":-1,\"charge_state\":{\"type\":\"MAV_BATTERY_CHARGE_STATE_OK\"},\"current_battery\":88,\"current_consumed\":170,\"energy_consumed\":95,\"id\":0,\"mavtype\":{\"type\":\"MAV_BATTERY_TYPE_UNKNOWN\"},\"temperature\":32767,\"time_remaining\":0,\"type\":\"BATTERY_STATUS\",\"voltages\":[15438,65535,65535,65535,65535,65535,65535,65535,65535,65535]}}","payloadType":"str","x":110,"y":60,"wires":[["4e1e4d987636f511"]]},{"id":"158b2f6dc1c82d9e","type":"inject","z":"055aa8fd1f8a8f4e","name":"lat","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"header\":{\"component_id\":1,\"sequence\":216,\"system_id\":1},\"message\":{\"alt\":-17000,\"alt_ellipsoid\":0,\"cog\":0,\"eph\":9999,\"epv\":9999,\"fix_type\":{\"type\":\"GPS_FIX_TYPE_NO_FIX\"},\"h_acc\":4294967295,\"hdg_acc\":0,\"lat\":0,\"lon\":0,\"satellites_visible\":0,\"time_usec\":0,\"type\":\"GPS_RAW_INT\",\"v_acc\":3750074112,\"vel\":0,\"vel_acc\":20000,\"yaw\":0}}","payloadType":"str","x":110,"y":100,"wires":[["4e1e4d987636f511"]]},{"id":"cf22c4ccac44da55","type":"switch","z":"055aa8fd1f8a8f4e","name":"MAvLink_split","property":"payload.message.type","propertyType":"msg","rules":[{"t":"eq","v":"BATTERY_STATUS","vt":"str"},{"t":"eq","v":"GPS_RAW_INT","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":480,"y":80,"wires":[["fb1a25da9fe782ba"],["e3de8131253b36cf"]]},{"id":"fb1a25da9fe782ba","type":"function","z":"055aa8fd1f8a8f4e","name":"vBatt","func":"msg.payload = {\n    Voltage: msg.payload.message.voltages[0] / 1000.00\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":630,"y":60,"wires":[["a50ad5cbf62f02bb"]]},{"id":"e3de8131253b36cf","type":"function","z":"055aa8fd1f8a8f4e","name":"lat","func":"msg.payload = {\n    latitude: msg.payload.message.lat\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":630,"y":120,"wires":[["a50ad5cbf62f02bb"]]},{"id":"a50ad5cbf62f02bb","type":"join","z":"055aa8fd1f8a8f4e","name":"","mode":"custom","build":"merged","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"5","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":770,"y":160,"wires":[["c456570e893e8283"]]},{"id":"3c6a2469bd653496","type":"function","z":"055aa8fd1f8a8f4e","name":"function 2","func":"let elements = msg.payload.split(\",\");\nlet topics = [\"Gas_A\", \"Gas_B\", \"mBar\"];\nmsg.payload = {};\nelements.slice(1).forEach((str, index) => {\n    msg.payload[topics[index]] =  parseFloat(str);\n})\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":200,"wires":[["a50ad5cbf62f02bb"]]},{"id":"c456570e893e8283","type":"debug","z":"055aa8fd1f8a8f4e","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":910,"y":160,"wires":[]},{"id":"a58aea6baceaa571","type":"inject","z":"055aa8fd1f8a8f4e","name":"serial","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"\"D, 1111.1,1111.11,1111.1\\r\"","payloadType":"json","x":110,"y":200,"wires":[["3c6a2469bd653496"]]}]

Hope they help.

To create a text line in same order, pass the joined object through a template node.
e.g.

[{"id":"093b58a8fc7c2335","type":"inject","z":"d1395164b4eec73e","name":"serial","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"Voltage\":15.438,\"latitude\":0,\"Gas_A\":1111.1,\"Gas_B\":1111.11,\"mBar\":1111.1}","payloadType":"json","x":150,"y":4480,"wires":[["fe2264d4aeef9f93"]]},{"id":"fe2264d4aeef9f93","type":"template","z":"d1395164b4eec73e","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\"Voltage\":{{payload.Voltage}},\"latitude\":{{payload.latitude}},\"Gas_A\":{{payload.Gas_A}},\"Gas_B\":{{payload.Gas_B}},\"mBar\":{{payload.mBar}}}","output":"str","x":300,"y":4480,"wires":[["031d99a3059dbe68"]]},{"id":"031d99a3059dbe68","type":"debug","z":"d1395164b4eec73e","name":"debug 2489","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":450,"y":4480,"wires":[]}]

Then the order will be certain.

@E1cid that gives an identical value for each of gas_A, gas_B and mBar.

No they are slightly different.

1 Like

So using the data you posted above, I get an object
image

Do I understand correctly that this would be one line of your text file?

{"Voltage":15.438,"latitude":0,"gas_A":1159.5,"gas_B":3.02,"mBar":1008.4}

But the next line might be like this?

{"Gas_A":1111.1,"Gas_B":1111.11,"mBar":1111.1"Voltage":15.438,"latitude":0}

Yes @jbudd exactly what I get. But no 1111.1 but rather the real value:)

This is different output I get in my text file on two consecutive line. This shift occur only when I redeploy node-red (after a modification) or reboot. Once in a certain "order", it remain like this.
Example below of the output I get. Sometime it start with gas, then by depth then by latitude.

{"Gas A":null,"Gas_B":null,"mBar":null,"Depth":0,"Voltage":15.634,"latitude":0,"longitude":0,"Sat_count":0,"GPS_fix":"GPS_FIX_TYPE_NO_FIX","UTC Time":"2024-05-15 20:27:00"}
{"Depth":0,"Voltage":15.619,"Gas_A":1460.4,"Gas_B":2.85,"mBar":988,"latitude":0,"longitude":0,"Sat_count":0,"GPS_fix":"GPS_FIX_TYPE_NO_FIX","UTC Time":"2024-05-15 20:40:58"}
{"latitude":0,"longitude":0,"Sat_count":0,"GPS_fix":"GPS_FIX_TYPE_NO_FIX","Gas_A":1110.6,"Gas_B":2.92,"mBar":988,"Depth":0,"Voltage":15.564,"UTC Time":"2024-05-15 20:55:31"}

As you can see there is more mavlink message comming than those you expect from the flow I posted in this thread. I removed some data from the Mavlink_split node to simplify the discussion. They are all the same but with different msg.topic. If we sort the 5 output GasA, B, mbar, vbatt and Lat, I hope I will be able to scale it up to my entire flow.

The order would not matter, when you reread the data as each line is a json and can be read into memory easily.

If you want it just for human reading ,a csv might be a simpler option, and the csv node would order it for you.

But you are mixing data and complicating thing a little.

a csv could also do.
edit. but I fail to make it work on the mavlink part.
edit: the order matter for later analysis of the data.

Hum. I need to investigate this template node. Would it work on the payload of my serial data directly? I see that you parse them differently then my original function node?

No unless you split it into an array, then you could use {{payload.1}} for Gas_A etc.

An example using csv node to order the data saved to text file

[{"id":"093b58a8fc7c2335","type":"inject","z":"d1395164b4eec73e","name":"gas","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"Gas_A\":null,\"Gas_B\":null,\"mBar\":null,\"Depth\":0,\"Voltage\":15.634,\"latitude\":0,\"longitude\":0,\"Sat_count\":0,\"GPS_fix\":\"GPS_FIX_TYPE_NO_FIX\",\"UTC Time\":\"2024-05-15 20:27:00\"}","payloadType":"json","x":150,"y":4480,"wires":[["e2508c8c3a9abf11"]]},{"id":"e2508c8c3a9abf11","type":"csv","z":"d1395164b4eec73e","name":"","sep":",","hdrin":"","hdrout":"once","multi":"one","ret":"\\n","temp":"Gas_A,Gas_B,mBar,Depth,Voltage,latitude,longitude,Sat_count,GPS_fix,UTC Time","skip":"0","strings":true,"include_empty_strings":"","include_null_values":"","x":370,"y":4500,"wires":[["031d99a3059dbe68"]]},{"id":"2a47e24a98b55c59","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"latitude\":0,\"longitude\":0,\"Sat_count\":0,\"GPS_fix\":\"GPS_FIX_TYPE_NO_FIX\",\"Gas_A\":1110.6,\"Gas_B\":2.92,\"mBar\":988,\"Depth\":0,\"Voltage\":15.564,\"UTC Time\":\"2024-05-15 20:55:31\"}","payloadType":"json","x":150,"y":4540,"wires":[["e2508c8c3a9abf11"]]},{"id":"031d99a3059dbe68","type":"debug","z":"d1395164b4eec73e","name":"debug 2489","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":530,"y":4500,"wires":[]}]

All columns are added to columns input field of the csv node this denotes the order. If data is missing an empty string is added in its place. It is easier to parse the data back in this form. Or maybe look at a Database.

And what are you going to do with the data next?
As long as it is processed by something that understands json, the latitude will always be (eg) msg.payload.latitude. The voltage will always be msg.payload.Voltage.

If you want to import it into a spreadsheet then as @E1cid says, a CSV format might be better.

But you can force the properties into any preferred order with a function node after your join:

msg.payload = {
    "mBar": msg.payload.mBar,
    "gas_B": msg.payload.gas_B,
    "gas_A": msg.payload.gas_A,
    "latitude": msg.payload.latitude,
    "Voltage": msg.payload.Voltage
}
return msg;

I finally made it work using the template node. The csv output also work (except for the timestamp as string) but there was text before every numbers (see below). Since I use excel for data analysis it was not super handy to end up with this on each line:

{"UTC Time":"2024-05-16 19:29:20","Depth":0,"CO2":1296.9,"CH4":2.94,"Latitude":0,"Longitude":0,"mBar":1006.9,"Voltage":15.157,"Sat_count":0,"GPS_fix":"GPS_FIX_TYPE_NO_FIX"}

Another problem I faced was that I join 10 msg and get 10 line in the txt file or csv file. The value did not change for the 10 lines. I think it record 1 line for every joined msp.payload. Thus there was redudancy. I end up including one more join node to convert to string and thus to 1 payload. It give me a steady output now.

[
    {
        "id": "0a01f56c6c8138ad",
        "type": "delay",
        "z": "2ca6ebad5d7e3813",
        "name": "",
        "pauseType": "timed",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "allowrate": false,
        "outputs": 1,
        "x": 1170,
        "y": 120,
        "wires": [
            [
                "7e6d6701cc7c4415"
            ]
        ]
    },
    {
        "id": "7e6d6701cc7c4415",
        "type": "join",
        "z": "2ca6ebad5d7e3813",
        "name": "",
        "mode": "custom",
        "build": "object",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": ";",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "10",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "num",
        "reduceFixup": "",
        "x": 1370,
        "y": 120,
        "wires": [
            [
                "1b7094c48024dc6d"
            ]
        ]
    },
    {
        "id": "8956ae7f1b362ded",
        "type": "file",
        "z": "2ca6ebad5d7e3813",
        "name": "",
        "filename": "/data/data.txt",
        "filenameType": "str",
        "appendNewline": true,
        "createDir": true,
        "overwriteFile": "false",
        "encoding": "utf8",
        "x": 1770,
        "y": 120,
        "wires": [
            [
                "042971daba4d9a72"
            ]
        ]
    },
    {
        "id": "042971daba4d9a72",
        "type": "debug",
        "z": "2ca6ebad5d7e3813",
        "name": "debug 24",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 1920,
        "y": 120,
        "wires": []
    },
    {
        "id": "1b7094c48024dc6d",
        "type": "template",
        "z": "2ca6ebad5d7e3813",
        "name": "",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "{{payload.UTC_Time}},{{payload.latitude}},{{payload.longitude}},{{payload.Depth}},{{payload.CO2}},{{payload.CH4}},{{payload.mBar}},{{payload.Voltage}},{{payload.Sat_count}},{{payload.GPS_fix}}",
        "output": "str",
        "x": 1500,
        "y": 120,
        "wires": [
            [
                "352365b90e0d3d1a"
            ]
        ]
    },
    {
        "id": "352365b90e0d3d1a",
        "type": "join",
        "z": "2ca6ebad5d7e3813",
        "name": "",
        "mode": "custom",
        "build": "string",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": ";",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "1",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 1630,
        "y": 120,
        "wires": [
            [
                "8956ae7f1b362ded"
            ]
        ]
    }
]

Thank you for your help and for the speed at which you provided it! I hope I will also be able to contribute later on the track.