Testing a array of objects of ones and zeros to see if there are state changes from 0 -1

I am trying to make a array of Alarm status. I have IOT devices putting 1 or 0 to array indexes based on the alarm status. I want to check whether the arrray indexes changed from 0 -1 and write that data to a sql or some database. In order to do this i need to have a globle variable of previous array and current arrays. But when I compare the previous array to current they are equal all the time.

[
    {
        "id": "ec2fb1d34b168229",
        "type": "function",
        "z": "73d2f3c99532ca0a",
        "name": "function 73",
        "func": "// Retrieve the current state of the Alarm_Array from the global context\nvar currentState = global.get(\"Alarm_Array\") || [];\n\n// Output the currentState for debugging purposes\nmsg.payload = currentState;\n\n// Return the message to pass the current state down the flow\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 410,
        "y": 800,
        "wires": [
            [
                "58f654830be125b5"
            ]
        ]
    },
    {
        "id": "b2ac17077b912ea0",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 220,
        "y": 800,
        "wires": [
            [
                "ec2fb1d34b168229"
            ]
        ]
    },
    {
        "id": "58f654830be125b5",
        "type": "debug",
        "z": "73d2f3c99532ca0a",
        "name": "debug 82",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 560,
        "y": 800,
        "wires": []
    },
    {
        "id": "754fde939f2fea2a",
        "type": "modbus-write",
        "z": "73d2f3c99532ca0a",
        "name": "Adam Module",
        "showStatusActivities": true,
        "showErrors": true,
        "showWarnings": true,
        "unitid": "1",
        "dataType": "Coil",
        "adr": "17",
        "quantity": "1",
        "server": "c7e87354e3598a57",
        "emptyMsgOnFail": true,
        "keepMsgProperties": true,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 720,
        "y": 200,
        "wires": [
            [
                "5d26fdadcb96cb36"
            ],
            [
                "5d26fdadcb96cb36"
            ]
        ]
    },
    {
        "id": "5d26fdadcb96cb36",
        "type": "debug",
        "z": "73d2f3c99532ca0a",
        "name": "debug 78",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 940,
        "y": 200,
        "wires": []
    },
    {
        "id": "8c0638bef44ea9a6",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 390,
        "y": 60,
        "wires": [
            [
                "754fde939f2fea2a"
            ]
        ]
    },
    {
        "id": "2cde1fa0d610c4de",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "Reset Alarm",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "false",
        "payloadType": "bool",
        "x": 410,
        "y": 300,
        "wires": [
            [
                "754fde939f2fea2a"
            ]
        ]
    },
    {
        "id": "47157da9dc2fea3d",
        "type": "function",
        "z": "73d2f3c99532ca0a",
        "name": "function 70",
        "func": "// Retrieve the current Alarm_Array from the global context\nlet currentAlarmArray = global.get('Alarm_Array') || [];\nnode.warn('Current Alarm Array: ' + JSON.stringify(currentAlarmArray));\n\n// Retrieve the previous Alarm_Array from the global context\nlet previousAlarmArray = global.get('Previous') || new Array(currentAlarmArray.length).fill(0);\nnode.warn('Previous Alarm Array: ' + JSON.stringify(previousAlarmArray));\n\n// Check if the arrays are actually the same object\n// This check is only to warn if they are the same object reference, not their contents\nif (currentAlarmArray === previousAlarmArray) {\n    node.warn('Warning: currentAlarmArray and previousAlarmArray are the same object!');\n}\n\n// Initialize a flag to indicate if any transition occurred\nlet transitionDetected = false;\n\n// Iterate over the arrays and check for transitions from 0 to 1\nfor (let i = 0; i < currentAlarmArray.length; i++) {\n    node.warn(`Comparing index ${i}: Previous = ${previousAlarmArray[i]}, Current = ${currentAlarmArray[i]}`);\n    if (previousAlarmArray[i] === 0 && currentAlarmArray[i] === 1) {\n        node.warn('Transition detected at index ' + i);\n        transitionDetected = true;\n    }\n}\n\n// Update the previous Alarm_Array in the global context\nglobal.set('Previous', currentAlarmArray);\n\n\n// Output only if a transition was detected\nif (transitionDetected) {\n    msg.payload = true;\n    node.warn('Transition detected. Outputting message.');\n    return msg;\n} else {\n    node.warn('No transition detected.');\n    return null; // No output if no transition detected\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 450,
        "y": 200,
        "wires": [
            [
                "258c2fc7b2d85b6c",
                "754fde939f2fea2a"
            ]
        ]
    },
    {
        "id": "258c2fc7b2d85b6c",
        "type": "debug",
        "z": "73d2f3c99532ca0a",
        "name": "debug 84",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 680,
        "y": 320,
        "wires": []
    },
    {
        "id": "4d0bf768259ec284",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 240,
        "y": 200,
        "wires": [
            [
                "47157da9dc2fea3d",
                "258c2fc7b2d85b6c"
            ]
        ]
    },
    {
        "id": "e43ada5751d6d1e0",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "0 1",
        "props": [
            {
                "p": "index0",
                "v": "1",
                "vt": "num"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 500,
        "wires": [
            [
                "30ea31131727215a",
                "082622abc628597d"
            ]
        ]
    },
    {
        "id": "ce2244c43b72a0b3",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "0 0",
        "props": [
            {
                "p": "index0",
                "v": "0",
                "vt": "num"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 540,
        "wires": [
            [
                "30ea31131727215a"
            ]
        ]
    },
    {
        "id": "ad758fd558120133",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "1 1",
        "props": [
            {
                "p": "index1",
                "v": "1",
                "vt": "num"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 600,
        "wires": [
            [
                "30ea31131727215a"
            ]
        ]
    },
    {
        "id": "b645293de534bd05",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "1 0",
        "props": [
            {
                "p": "index1",
                "v": "0",
                "vt": "num"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 640,
        "wires": [
            [
                "30ea31131727215a"
            ]
        ]
    },
    {
        "id": "30ea31131727215a",
        "type": "function",
        "z": "73d2f3c99532ca0a",
        "name": "function 71",
        "func": "// Retrieve the existing Alarm_Array from the global context or initialize it if it doesn't exist\nlet Alarm_Array = global.get('Alarm_Array') || [];\n\n// Loop through the properties of the incoming message object\nfor (let key in msg) {\n    // Check if the key matches the pattern \"indexX\" where X is a number\n    if (key.startsWith('index')) {\n        // Extract the index number from the key (e.g., \"index0\" -> 0)\n        let index = parseInt(key.replace('index', ''), 10);\n\n        // Ensure the Alarm_Array is large enough to accommodate the index\n        Alarm_Array[index] = msg[key];\n    }\n}\n\n// Store the updated Alarm_Array back into the global context\nglobal.set('Alarm_Array', Alarm_Array);\n\n// Optionally, return the updated Alarm_Array in the message payload\nmsg.payload = Alarm_Array;\n\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 450,
        "y": 500,
        "wires": [
            [
                "81853fd7963ed7f2"
            ]
        ]
    },
    {
        "id": "81853fd7963ed7f2",
        "type": "debug",
        "z": "73d2f3c99532ca0a",
        "name": "debug 79",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 640,
        "y": 500,
        "wires": []
    },
    {
        "id": "082622abc628597d",
        "type": "debug",
        "z": "73d2f3c99532ca0a",
        "name": "debug 83",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 360,
        "y": 460,
        "wires": []
    },
    {
        "id": "571fc8b0f85a5d16",
        "type": "function",
        "z": "73d2f3c99532ca0a",
        "name": "function 74",
        "func": "// Retrieve the current state of the Alarm_Array from the global context\nvar currentState = global.get(\"Previous\") || [];\n\n// Output the currentState for debugging purposes\nmsg.payload = currentState;\n\n// Return the message to pass the current state down the flow\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 410,
        "y": 840,
        "wires": [
            [
                "1c6b8c8538d89779"
            ]
        ]
    },
    {
        "id": "027b062e55eaba01",
        "type": "inject",
        "z": "73d2f3c99532ca0a",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 220,
        "y": 840,
        "wires": [
            [
                "571fc8b0f85a5d16"
            ]
        ]
    },
    {
        "id": "1c6b8c8538d89779",
        "type": "debug",
        "z": "73d2f3c99532ca0a",
        "name": "debug 85",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 560,
        "y": 840,
        "wires": []
    },
    {
        "id": "f429bf45cecacf6f",
        "type": "comment",
        "z": "73d2f3c99532ca0a",
        "name": "Alarm Generating devices",
        "info": "",
        "x": 150,
        "y": 460,
        "wires": []
    },
    {
        "id": "495ecc0f6306f171",
        "type": "comment",
        "z": "73d2f3c99532ca0a",
        "name": "Test previous and current arrays",
        "info": "",
        "x": 270,
        "y": 760,
        "wires": []
    },
    {
        "id": "a54d45f333aff9a1",
        "type": "comment",
        "z": "73d2f3c99532ca0a",
        "name": "Current array",
        "info": "",
        "x": 730,
        "y": 800,
        "wires": []
    },
    {
        "id": "7b3a47670759ebe8",
        "type": "comment",
        "z": "73d2f3c99532ca0a",
        "name": "Previous array",
        "info": "",
        "x": 730,
        "y": 840,
        "wires": []
    },
    {
        "id": "c7e87354e3598a57",
        "type": "modbus-client",
        "name": "Adam Module Alarm 1",
        "clienttype": "tcp",
        "bufferCommands": true,
        "stateLogEnabled": true,
        "queueLogEnabled": true,
        "failureLogEnabled": true,
        "tcpHost": "10.141.3.200",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "serialAsciiResponseStartDelimiter": "0x3A",
        "unit_id": "1",
        "commandDelay": "1",
        "clientTimeout": "1000",
        "reconnectOnTimeout": true,
        "reconnectTimeout": "2000",
        "parallelUnitIdsAllowed": false,
        "showErrors": true,
        "showWarnings": true,
        "showLogs": true
    }
]

Chat GPT came for the rescue :smiley:
The issue you’re encountering where the previous state (Previous) seems to be updated even when the function isn’t executed is likely due to the way JavaScript handles references to objects (arrays in this case) rather than values.

Understanding the Problem:

In JavaScript, when you assign an array (or an object) to a variable, you are assigning a reference to that array, not a copy of its values. This means that if the currentAlarmArray and previousAlarmArray point to the same array object, any changes to currentAlarmArray will also affect previousAlarmArray because they both refer to the same underlying data.

Example:

javascript

Copy code

let arr1 = [1, 2, 3];
let arr2 = arr1;  // arr2 is now a reference to arr1
arr2[0] = 100;    // Modifies arr1 as well, since arr2 is just a reference
console.log(arr1); // Outputs: [100, 2, 3]

In Your Case:

  • When you retrieve the currentAlarmArray and previousAlarmArray, if they reference the same array, updating one will automatically update the other.
  • This can happen if the global.set call is not made after checking for transitions, or if the global state is shared across multiple function calls where references are reused.

Solution:

To avoid this problem, you should create a copy of the array when setting Previous or when retrieving the currentAlarmArray. This way, Previous and currentAlarmArray will refer to different arrays.

Modify the Function:

  1. Create a copy of the array when setting the Previous state:

javascript

Copy code

global.set('Previous', [...currentAlarmArray]); // Shallow copy using spread operator
  1. Alternatively, create a copy when retrieving the array:

javascript

Copy code

let previousAlarmArray = global.get('Previous') || new Array(currentAlarmArray.length).fill(0);
previousAlarmArray = [...previousAlarmArray]; // Ensure it's a copy
1 Like

Node red provides a method for cloning data to avoid this problem
let previousAlarmArray = RED.util.cloneMessage(global.get('Previous')) || new Array(currentAlarmArray.length).fill(0)

1 Like

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