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.