Parsing binary encoded data from decimal array

might also look at node-red-contrib-bitunloader, which parses integers such as your 383 into a few different forms of binary output, depending on how you want to process it. But under the hood it just converts numbers into a binary string (383).toString(2).padStart(16,'0') //for a 16 bit number

Personally I'd map each array index to an object property with a meaningful name, then process each of these individually in series until you get a well formed object with all needed information.

Exactly what buffer parser does

Exactly what buffer parser does.

2 Likes

Perfect then.

With Claude.ai's help I've ended up with this function

[
    {
        "id": "393939344a9cb6e3",
        "type": "inject",
        "z": "b3efb06892b4f0b6",
        "name": "Create Buffer",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "[5,901,1260,383,720,840,65,720,900,62,1260,1439,383,0,480,383,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",
        "payloadType": "json",
        "x": 450,
        "y": 3060,
        "wires": [
            [
                "dddbc461ef50e71a",
                "d35da5f211a44433"
            ]
        ]
    },
    {
        "id": "dddbc461ef50e71a",
        "type": "function",
        "z": "b3efb06892b4f0b6",
        "name": "Claude",
        "func": "// Input array from msg.payload\nconst data = msg.payload;\n\n// Extract number of periods\nconst numPeriods = data[0];\n\n// Function to decode mode and days\nfunction decodeModeAndDays(value) {\n    // Extract lower 8 bits (days of week)\n    const daysValue = value & 0xFF;\n    \n    // Extract upper 8 bits (mode flag)\n    const mode = (value >> 8) & 0xFF;\n    \n    // Decode individual days (bits 0-6 represent days)\n    const days = {\n        Sunday: (daysValue & 0x01) !== 0,\n        Monday: (daysValue & 0x02) !== 0,\n        Tuesday: (daysValue & 0x04) !== 0,\n        Wednesday: (daysValue & 0x08) !== 0,\n        Thursday: (daysValue & 0x10) !== 0,\n        Friday: (daysValue & 0x20) !== 0,\n        Saturday: (daysValue & 0x40) !== 0\n    };\n    \n    // Get active days as array\n    const activeDays = Object.keys(days).filter(day => days[day]);\n    \n    return {\n        mode: mode === 1 ? \"Discharge\" : \"Charge\",\n        modeValue: mode,\n        daysValue: daysValue,\n        days: days,\n        activeDays: activeDays,\n        binary: value.toString(2).padStart(16, '0')\n    };\n}\n\n// Function to convert minutes to time string\nfunction minutesToTime(minutes) {\n    const hours = Math.floor(minutes / 60);\n    const mins = minutes % 60;\n    return `${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`;\n}\n\n// Parse all periods\nconst periods = [];\nfor (let i = 0; i < numPeriods; i++) {\n    const baseIndex = 1 + (i * 3); // Each period uses 3 values\n    \n    const startTime = data[baseIndex];\n    const endTime = data[baseIndex + 1];\n    const flagDays = data[baseIndex + 2];\n    \n    const decoded = decodeModeAndDays(flagDays);\n    \n    periods.push({\n        period: i + 1,\n        startTimeFormatted: minutesToTime(startTime),\n        endTimeFormatted: minutesToTime(endTime),\n        mode: decoded.mode,\n        activeDays: decoded.activeDays,\n        daysDetail: decoded.days,\n        binary: decoded.binary\n    });\n}\n\n// Output the decoded data\nmsg.payload = {\n    numberOfPeriods: numPeriods,\n    periods: periods\n};\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 720,
        "y": 3200,
        "wires": [
            [
                "81a16b5f21889ecf"
            ]
        ]
    },
    {
        "id": "81a16b5f21889ecf",
        "type": "debug",
        "z": "b3efb06892b4f0b6",
        "name": "debug 8",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 920,
        "y": 3200,
        "wires": []
    }
]

It's a little bit overkill really, but very easy to see what's coming out. Once I've worked out exactly how I want to use the output I'll probably remove anything that's surplus.

I tried @berijan 's buffer-parser flow - good to understand how that would work, I had tried but failed.

These AI tools open up a whole new world to we bumbling programmers. No way I could have produced something like that in less than a week, if ever!
It must be turning the industry on it's head.

What was it that failed?

I used Your array as input for my test and got out the data You wanted.
Can I be that I used uint16be (Big Endian) but Your actual data is uint16le (Little Endian).

I wasn't clear sorry.

I failed to figure how to make buffer-parser work when I first tried.

Your node worked fine, & now I have a better understanding of how to parse the individual bits, thanks.

2 Likes