@peterfido
Hier ist der ganze Flow, den ich unterdessen zusammen habe:
[
{
"id": "26771494c726dd85",
"type": "tab",
"label": "Pytes",
"disabled": false,
"info": "",
"env": []
},
{
"id": "09a7088a7c52e930",
"type": "inject",
"z": "26771494c726dd85",
"name": "Start Impuls",
"props": [
{
"p": "payload"
}
],
"repeat": "900",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "bat",
"payloadType": "str",
"x": 130,
"y": 60,
"wires": [
[
"f6f7978549817c9b",
"dd20c6bfc8c1643a",
"aae8b0af1ff64ae1",
"6df4f9bd092fdcd3",
"d81970d6d1e4cca6",
"c8cc5a91dbf6eb1a",
"09faeaa564e7d7ea",
"027109f5112c3c3e"
]
]
},
{
"id": "f6f7978549817c9b",
"type": "trigger",
"z": "26771494c726dd85",
"name": "bat 1",
"op1": "bat 1",
"op2": "",
"op1type": "str",
"op2type": "nul",
"duration": "250",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 690,
"y": 60,
"wires": [
[
"f1e94e531bb2b4f9"
]
]
},
{
"id": "f1e94e531bb2b4f9",
"type": "serial request",
"z": "26771494c726dd85",
"name": "BMSMaster",
"serial": "d031dd424e7b1ff2",
"x": 890,
"y": 60,
"wires": [
[
"79724f85531596e4",
"4b31f05c7b6c5425"
]
]
},
{
"id": "79724f85531596e4",
"type": "function",
"z": "26771494c726dd85",
"name": "convert to msgs",
"func": "const text = msg.payload;\n\nif (typeof text !== \"string\") {\n node.error(\"msg.payload ist kein String\", msg);\n return null;\n}\n\n// In einzelne Zeilen zerlegen\nconst lines = text\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== \"\");\n\n// Nur Zeilen berücksichtigen, die mit einer Batterienummer beginnen\nconst dataLines = lines.filter(line => /^\\d+\\s/.test(line));\n\nconst messages = [];\n\nfor (const line of dataLines) {\n\n // Spalten sind durch mindestens 2 Leerzeichen getrennt\n const columns = line.split(/\\s{2,}/);\n\n if (columns.length < 9) {\n node.warn(\"Zeile konnte nicht verarbeitet werden: \" + line);\n continue;\n }\n\n const battery = {\n battery: Number(columns[0]),\n volt: Number(columns[1]),\n tempr: Number(columns[2]),\n baseState: columns[3],\n voltState: columns[4],\n currState: columns[5],\n tempState: columns[6],\n coulomb: Number(columns[7].replace(\"%\", \"\")),\n capacity: Number(columns[8].replace(/[^\\d]/g, \"\"))\n };\n\n messages.push({\n ...msg,\n payload: battery\n });\n}\n\n// Alle Nachrichten nacheinander über denselben Ausgang senden\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1080,
"y": 60,
"wires": [
[
"4a8dcae7d0f7d8a8"
]
]
},
{
"id": "68c635b31d513d6d",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 4",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1440,
"y": 120,
"wires": []
},
{
"id": "6a16c00e7b0e2997",
"type": "ioBroker out",
"z": "26771494c726dd85",
"name": "",
"topic": "",
"ack": "true",
"autoCreate": "true",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1460,
"y": 60,
"wires": []
},
{
"id": "4a8dcae7d0f7d8a8",
"type": "function",
"z": "26771494c726dd85",
"name": "function 2",
"func": "const battery = msg.payload;\n\nif (!battery || battery.battery === undefined) {\n node.error(\"Ungültiges Battery-Objekt\", msg);\n return null;\n}\n\nconst batteryId = battery.battery;\n\nconst states = [\n {\n id: \"voltage\",\n value: battery.volt,\n name: \"Voltage\",\n role: \"value.voltage\",\n type: \"number\",\n readonly: true,\n unit: \"mV\",\n min: 0\n },\n {\n id: \"temperature\",\n value: battery.tempr / 1000,\n name: \"Temperature\",\n role: \"value.temperature\",\n type: \"number\",\n readonly: true,\n unit: \"°C\"\n },\n {\n id: \"baseState\",\n value: battery.baseState,\n name: \"Base State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"voltageState\",\n value: battery.voltState,\n name: \"Voltage State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"currentState\",\n value: battery.currState,\n name: \"Current State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"temperatureState\",\n value: battery.tempState,\n name: \"Temperature State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"charge\",\n value: battery.coulomb,\n name: \"Charge\",\n role: \"value.battery\",\n type: \"number\",\n readonly: true,\n unit: \"%\",\n min: 0,\n max: 100\n },\n {\n id: \"capacity\",\n value: battery.capacity,\n name: \"Capacity\",\n role: \"value\",\n type: \"number\",\n readonly: true,\n unit: \"mAh\",\n min: 0\n }\n];\n\nconst messages = [];\n\nfor (const state of states) {\n const out = {\n topic: `0_userdata.0.pytes.01.${batteryId}.${state.id}`,\n payload: state.value,\n\n stateName: state.name,\n stateRole: state.role,\n stateType: state.type,\n stateReadonly: state.readonly\n };\n\n if (state.unit !== undefined) {\n out.stateUnit = state.unit;\n }\n\n if (state.min !== undefined) {\n out.stateMin = state.min;\n }\n\n if (state.max !== undefined) {\n out.stateMax = state.max;\n }\n\n messages.push(out);\n}\n\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 60,
"wires": [
[
"6a16c00e7b0e2997",
"68c635b31d513d6d"
]
]
},
{
"id": "dd20c6bfc8c1643a",
"type": "delay",
"z": "26771494c726dd85",
"name": "",
"pauseType": "delay",
"timeout": "1",
"timeoutUnits": "minutes",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 520,
"y": 200,
"wires": [
[
"0dc431cc8e3444fa"
]
]
},
{
"id": "3cce03774442db86",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 2",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1440,
"y": 260,
"wires": []
},
{
"id": "0dc431cc8e3444fa",
"type": "trigger",
"z": "26771494c726dd85",
"name": "bat 2",
"op1": "bat 2",
"op2": "",
"op1type": "str",
"op2type": "nul",
"duration": "250",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 730,
"y": 200,
"wires": [
[
"72209bb281ee39b7"
]
]
},
{
"id": "72209bb281ee39b7",
"type": "serial request",
"z": "26771494c726dd85",
"name": "BMSMaster",
"serial": "d031dd424e7b1ff2",
"x": 890,
"y": 200,
"wires": [
[
"9441d38d2c549fb8"
]
]
},
{
"id": "9441d38d2c549fb8",
"type": "function",
"z": "26771494c726dd85",
"name": "convert to msgs",
"func": "const text = msg.payload;\n\nif (typeof text !== \"string\") {\n node.error(\"msg.payload ist kein String\", msg);\n return null;\n}\n\n// In einzelne Zeilen zerlegen\nconst lines = text\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== \"\");\n\n// Nur Zeilen berücksichtigen, die mit einer Batterienummer beginnen\nconst dataLines = lines.filter(line => /^\\d+\\s/.test(line));\n\nconst messages = [];\n\nfor (const line of dataLines) {\n\n // Spalten sind durch mindestens 2 Leerzeichen getrennt\n const columns = line.split(/\\s{2,}/);\n\n if (columns.length < 9) {\n node.warn(\"Zeile konnte nicht verarbeitet werden: \" + line);\n continue;\n }\n\n const battery = {\n battery: Number(columns[0]),\n volt: Number(columns[1]),\n tempr: Number(columns[2]),\n baseState: columns[3],\n voltState: columns[4],\n currState: columns[5],\n tempState: columns[6],\n coulomb: Number(columns[7].replace(\"%\", \"\")),\n capacity: Number(columns[8].replace(/[^\\d]/g, \"\"))\n };\n\n messages.push({\n ...msg,\n payload: battery\n });\n}\n\n// Alle Nachrichten nacheinander über denselben Ausgang senden\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1080,
"y": 200,
"wires": [
[
"c7f18bb5735b986f"
]
]
},
{
"id": "5f5f0afbf22fe52b",
"type": "ioBroker out",
"z": "26771494c726dd85",
"name": "",
"topic": "",
"ack": "true",
"autoCreate": "true",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1460,
"y": 200,
"wires": []
},
{
"id": "c7f18bb5735b986f",
"type": "function",
"z": "26771494c726dd85",
"name": "function 3",
"func": "const battery = msg.payload;\n\nif (!battery || battery.battery === undefined) {\n node.error(\"Ungültiges Battery-Objekt\", msg);\n return null;\n}\n\nconst batteryId = battery.battery;\n\nconst states = [\n {\n id: \"voltage\",\n value: battery.volt,\n name: \"Voltage\",\n role: \"value.voltage\",\n type: \"number\",\n readonly: true,\n unit: \"mV\",\n min: 0\n },\n {\n id: \"temperature\",\n value: battery.tempr / 1000,\n name: \"Temperature\",\n role: \"value.temperature\",\n type: \"number\",\n readonly: true,\n unit: \"°C\"\n },\n {\n id: \"baseState\",\n value: battery.baseState,\n name: \"Base State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"voltageState\",\n value: battery.voltState,\n name: \"Voltage State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"currentState\",\n value: battery.currState,\n name: \"Current State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"temperatureState\",\n value: battery.tempState,\n name: \"Temperature State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"charge\",\n value: battery.coulomb,\n name: \"Charge\",\n role: \"value.battery\",\n type: \"number\",\n readonly: true,\n unit: \"%\",\n min: 0,\n max: 100\n },\n {\n id: \"capacity\",\n value: battery.capacity,\n name: \"Capacity\",\n role: \"value\",\n type: \"number\",\n readonly: true,\n unit: \"mAh\",\n min: 0\n }\n];\n\nconst messages = [];\n\nfor (const state of states) {\n const out = {\n topic: `0_userdata.0.pytes.02.${batteryId}.${state.id}`,\n payload: state.value,\n\n stateName: state.name,\n stateRole: state.role,\n stateType: state.type,\n stateReadonly: state.readonly\n };\n\n if (state.unit !== undefined) {\n out.stateUnit = state.unit;\n }\n\n if (state.min !== undefined) {\n out.stateMin = state.min;\n }\n\n if (state.max !== undefined) {\n out.stateMax = state.max;\n }\n\n messages.push(out);\n}\n\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 200,
"wires": [
[
"5f5f0afbf22fe52b",
"3cce03774442db86"
]
]
},
{
"id": "aae8b0af1ff64ae1",
"type": "delay",
"z": "26771494c726dd85",
"name": "",
"pauseType": "delay",
"timeout": "2",
"timeoutUnits": "minutes",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 520,
"y": 340,
"wires": [
[
"085f008ec32136f1"
]
]
},
{
"id": "acfcfbc9dab48c55",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 5",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1440,
"y": 400,
"wires": []
},
{
"id": "085f008ec32136f1",
"type": "trigger",
"z": "26771494c726dd85",
"name": "bat 3",
"op1": "bat 3",
"op2": "",
"op1type": "str",
"op2type": "nul",
"duration": "250",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 730,
"y": 340,
"wires": [
[
"7134518ae47c75db"
]
]
},
{
"id": "7134518ae47c75db",
"type": "serial request",
"z": "26771494c726dd85",
"name": "BMSMaster",
"serial": "d031dd424e7b1ff2",
"x": 890,
"y": 340,
"wires": [
[
"2819be0b93263306"
]
]
},
{
"id": "2819be0b93263306",
"type": "function",
"z": "26771494c726dd85",
"name": "convert to msgs",
"func": "const text = msg.payload;\n\nif (typeof text !== \"string\") {\n node.error(\"msg.payload ist kein String\", msg);\n return null;\n}\n\n// In einzelne Zeilen zerlegen\nconst lines = text\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== \"\");\n\n// Nur Zeilen berücksichtigen, die mit einer Batterienummer beginnen\nconst dataLines = lines.filter(line => /^\\d+\\s/.test(line));\n\nconst messages = [];\n\nfor (const line of dataLines) {\n\n // Spalten sind durch mindestens 2 Leerzeichen getrennt\n const columns = line.split(/\\s{2,}/);\n\n if (columns.length < 9) {\n node.warn(\"Zeile konnte nicht verarbeitet werden: \" + line);\n continue;\n }\n\n const battery = {\n battery: Number(columns[0]),\n volt: Number(columns[1]),\n tempr: Number(columns[2]),\n baseState: columns[3],\n voltState: columns[4],\n currState: columns[5],\n tempState: columns[6],\n coulomb: Number(columns[7].replace(\"%\", \"\")),\n capacity: Number(columns[8].replace(/[^\\d]/g, \"\"))\n };\n\n messages.push({\n ...msg,\n payload: battery\n });\n}\n\n// Alle Nachrichten nacheinander über denselben Ausgang senden\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1080,
"y": 340,
"wires": [
[
"ca02643445158e40"
]
]
},
{
"id": "ea0794a8642caf84",
"type": "ioBroker out",
"z": "26771494c726dd85",
"name": "",
"topic": "",
"ack": "true",
"autoCreate": "true",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1460,
"y": 340,
"wires": []
},
{
"id": "ca02643445158e40",
"type": "function",
"z": "26771494c726dd85",
"name": "function 4",
"func": "const battery = msg.payload;\n\nif (!battery || battery.battery === undefined) {\n node.error(\"Ungültiges Battery-Objekt\", msg);\n return null;\n}\n\nconst batteryId = battery.battery;\n\nconst states = [\n {\n id: \"voltage\",\n value: battery.volt,\n name: \"Voltage\",\n role: \"value.voltage\",\n type: \"number\",\n readonly: true,\n unit: \"mV\",\n min: 0\n },\n {\n id: \"temperature\",\n value: battery.tempr / 1000,\n name: \"Temperature\",\n role: \"value.temperature\",\n type: \"number\",\n readonly: true,\n unit: \"°C\"\n },\n {\n id: \"baseState\",\n value: battery.baseState,\n name: \"Base State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"voltageState\",\n value: battery.voltState,\n name: \"Voltage State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"currentState\",\n value: battery.currState,\n name: \"Current State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"temperatureState\",\n value: battery.tempState,\n name: \"Temperature State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"charge\",\n value: battery.coulomb,\n name: \"Charge\",\n role: \"value.battery\",\n type: \"number\",\n readonly: true,\n unit: \"%\",\n min: 0,\n max: 100\n },\n {\n id: \"capacity\",\n value: battery.capacity,\n name: \"Capacity\",\n role: \"value\",\n type: \"number\",\n readonly: true,\n unit: \"mAh\",\n min: 0\n }\n];\n\nconst messages = [];\n\nfor (const state of states) {\n const out = {\n topic: `0_userdata.0.pytes.03.${batteryId}.${state.id}`,\n payload: state.value,\n\n stateName: state.name,\n stateRole: state.role,\n stateType: state.type,\n stateReadonly: state.readonly\n };\n\n if (state.unit !== undefined) {\n out.stateUnit = state.unit;\n }\n\n if (state.min !== undefined) {\n out.stateMin = state.min;\n }\n\n if (state.max !== undefined) {\n out.stateMax = state.max;\n }\n\n messages.push(out);\n}\n\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 340,
"wires": [
[
"ea0794a8642caf84",
"acfcfbc9dab48c55"
]
]
},
{
"id": "6df4f9bd092fdcd3",
"type": "delay",
"z": "26771494c726dd85",
"name": "",
"pauseType": "delay",
"timeout": "3",
"timeoutUnits": "minutes",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 520,
"y": 480,
"wires": [
[
"a832dedddd9504c7"
]
]
},
{
"id": "b7c07a571002ad06",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 6",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1440,
"y": 540,
"wires": []
},
{
"id": "a832dedddd9504c7",
"type": "trigger",
"z": "26771494c726dd85",
"name": "bat 4",
"op1": "bat 4",
"op2": "",
"op1type": "str",
"op2type": "nul",
"duration": "250",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 730,
"y": 480,
"wires": [
[
"b82258c553850a68"
]
]
},
{
"id": "b82258c553850a68",
"type": "serial request",
"z": "26771494c726dd85",
"name": "BMSMaster",
"serial": "d031dd424e7b1ff2",
"x": 890,
"y": 480,
"wires": [
[
"4387216c1822cbcf"
]
]
},
{
"id": "4387216c1822cbcf",
"type": "function",
"z": "26771494c726dd85",
"name": "convert to msgs",
"func": "const text = msg.payload;\n\nif (typeof text !== \"string\") {\n node.error(\"msg.payload ist kein String\", msg);\n return null;\n}\n\n// In einzelne Zeilen zerlegen\nconst lines = text\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== \"\");\n\n// Nur Zeilen berücksichtigen, die mit einer Batterienummer beginnen\nconst dataLines = lines.filter(line => /^\\d+\\s/.test(line));\n\nconst messages = [];\n\nfor (const line of dataLines) {\n\n // Spalten sind durch mindestens 2 Leerzeichen getrennt\n const columns = line.split(/\\s{2,}/);\n\n if (columns.length < 9) {\n node.warn(\"Zeile konnte nicht verarbeitet werden: \" + line);\n continue;\n }\n\n const battery = {\n battery: Number(columns[0]),\n volt: Number(columns[1]),\n tempr: Number(columns[2]),\n baseState: columns[3],\n voltState: columns[4],\n currState: columns[5],\n tempState: columns[6],\n coulomb: Number(columns[7].replace(\"%\", \"\")),\n capacity: Number(columns[8].replace(/[^\\d]/g, \"\"))\n };\n\n messages.push({\n ...msg,\n payload: battery\n });\n}\n\n// Alle Nachrichten nacheinander über denselben Ausgang senden\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1080,
"y": 480,
"wires": [
[
"94e6b42f7309c443"
]
]
},
{
"id": "51c2e01cf0878450",
"type": "ioBroker out",
"z": "26771494c726dd85",
"name": "",
"topic": "",
"ack": "true",
"autoCreate": "true",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1460,
"y": 480,
"wires": []
},
{
"id": "94e6b42f7309c443",
"type": "function",
"z": "26771494c726dd85",
"name": "function 5",
"func": "const battery = msg.payload;\n\nif (!battery || battery.battery === undefined) {\n node.error(\"Ungültiges Battery-Objekt\", msg);\n return null;\n}\n\nconst batteryId = battery.battery;\n\nconst states = [\n {\n id: \"voltage\",\n value: battery.volt,\n name: \"Voltage\",\n role: \"value.voltage\",\n type: \"number\",\n readonly: true,\n unit: \"mV\",\n min: 0\n },\n {\n id: \"temperature\",\n value: battery.tempr / 1000,\n name: \"Temperature\",\n role: \"value.temperature\",\n type: \"number\",\n readonly: true,\n unit: \"°C\"\n },\n {\n id: \"baseState\",\n value: battery.baseState,\n name: \"Base State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"voltageState\",\n value: battery.voltState,\n name: \"Voltage State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"currentState\",\n value: battery.currState,\n name: \"Current State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"temperatureState\",\n value: battery.tempState,\n name: \"Temperature State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"charge\",\n value: battery.coulomb,\n name: \"Charge\",\n role: \"value.battery\",\n type: \"number\",\n readonly: true,\n unit: \"%\",\n min: 0,\n max: 100\n },\n {\n id: \"capacity\",\n value: battery.capacity,\n name: \"Capacity\",\n role: \"value\",\n type: \"number\",\n readonly: true,\n unit: \"mAh\",\n min: 0\n }\n];\n\nconst messages = [];\n\nfor (const state of states) {\n const out = {\n topic: `0_userdata.0.pytes.04.${batteryId}.${state.id}`,\n payload: state.value,\n\n stateName: state.name,\n stateRole: state.role,\n stateType: state.type,\n stateReadonly: state.readonly\n };\n\n if (state.unit !== undefined) {\n out.stateUnit = state.unit;\n }\n\n if (state.min !== undefined) {\n out.stateMin = state.min;\n }\n\n if (state.max !== undefined) {\n out.stateMax = state.max;\n }\n\n messages.push(out);\n}\n\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 480,
"wires": [
[
"51c2e01cf0878450",
"b7c07a571002ad06"
]
]
},
{
"id": "d81970d6d1e4cca6",
"type": "delay",
"z": "26771494c726dd85",
"name": "",
"pauseType": "delay",
"timeout": "4",
"timeoutUnits": "minutes",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 520,
"y": 620,
"wires": [
[
"f1fd5ef8888380ad"
]
]
},
{
"id": "fb84ec681c169cd6",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 7",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1440,
"y": 680,
"wires": []
},
{
"id": "f1fd5ef8888380ad",
"type": "trigger",
"z": "26771494c726dd85",
"name": "bat 5",
"op1": "bat 5",
"op2": "",
"op1type": "str",
"op2type": "nul",
"duration": "250",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 730,
"y": 620,
"wires": [
[
"75f9d95891961faf"
]
]
},
{
"id": "75f9d95891961faf",
"type": "serial request",
"z": "26771494c726dd85",
"name": "BMSMaster",
"serial": "d031dd424e7b1ff2",
"x": 890,
"y": 620,
"wires": [
[
"c4b473ff613b76e2"
]
]
},
{
"id": "c4b473ff613b76e2",
"type": "function",
"z": "26771494c726dd85",
"name": "convert to msgs",
"func": "const text = msg.payload;\n\nif (typeof text !== \"string\") {\n node.error(\"msg.payload ist kein String\", msg);\n return null;\n}\n\n// In einzelne Zeilen zerlegen\nconst lines = text\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== \"\");\n\n// Nur Zeilen berücksichtigen, die mit einer Batterienummer beginnen\nconst dataLines = lines.filter(line => /^\\d+\\s/.test(line));\n\nconst messages = [];\n\nfor (const line of dataLines) {\n\n // Spalten sind durch mindestens 2 Leerzeichen getrennt\n const columns = line.split(/\\s{2,}/);\n\n if (columns.length < 9) {\n node.warn(\"Zeile konnte nicht verarbeitet werden: \" + line);\n continue;\n }\n\n const battery = {\n battery: Number(columns[0]),\n volt: Number(columns[1]),\n tempr: Number(columns[2]),\n baseState: columns[3],\n voltState: columns[4],\n currState: columns[5],\n tempState: columns[6],\n coulomb: Number(columns[7].replace(\"%\", \"\")),\n capacity: Number(columns[8].replace(/[^\\d]/g, \"\"))\n };\n\n messages.push({\n ...msg,\n payload: battery\n });\n}\n\n// Alle Nachrichten nacheinander über denselben Ausgang senden\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1080,
"y": 620,
"wires": [
[
"4603fd0d509f8f04"
]
]
},
{
"id": "d35fbb5808f3ecae",
"type": "ioBroker out",
"z": "26771494c726dd85",
"name": "",
"topic": "",
"ack": "true",
"autoCreate": "true",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1460,
"y": 620,
"wires": []
},
{
"id": "4603fd0d509f8f04",
"type": "function",
"z": "26771494c726dd85",
"name": "function 6",
"func": "const battery = msg.payload;\n\nif (!battery || battery.battery === undefined) {\n node.error(\"Ungültiges Battery-Objekt\", msg);\n return null;\n}\n\nconst batteryId = battery.battery;\n\nconst states = [\n {\n id: \"voltage\",\n value: battery.volt,\n name: \"Voltage\",\n role: \"value.voltage\",\n type: \"number\",\n readonly: true,\n unit: \"mV\",\n min: 0\n },\n {\n id: \"temperature\",\n value: battery.tempr / 1000,\n name: \"Temperature\",\n role: \"value.temperature\",\n type: \"number\",\n readonly: true,\n unit: \"°C\"\n },\n {\n id: \"baseState\",\n value: battery.baseState,\n name: \"Base State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"voltageState\",\n value: battery.voltState,\n name: \"Voltage State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"currentState\",\n value: battery.currState,\n name: \"Current State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"temperatureState\",\n value: battery.tempState,\n name: \"Temperature State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"charge\",\n value: battery.coulomb,\n name: \"Charge\",\n role: \"value.battery\",\n type: \"number\",\n readonly: true,\n unit: \"%\",\n min: 0,\n max: 100\n },\n {\n id: \"capacity\",\n value: battery.capacity,\n name: \"Capacity\",\n role: \"value\",\n type: \"number\",\n readonly: true,\n unit: \"mAh\",\n min: 0\n }\n];\n\nconst messages = [];\n\nfor (const state of states) {\n const out = {\n topic: `0_userdata.0.pytes.05.${batteryId}.${state.id}`,\n payload: state.value,\n\n stateName: state.name,\n stateRole: state.role,\n stateType: state.type,\n stateReadonly: state.readonly\n };\n\n if (state.unit !== undefined) {\n out.stateUnit = state.unit;\n }\n\n if (state.min !== undefined) {\n out.stateMin = state.min;\n }\n\n if (state.max !== undefined) {\n out.stateMax = state.max;\n }\n\n messages.push(out);\n}\n\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 620,
"wires": [
[
"d35fbb5808f3ecae",
"fb84ec681c169cd6"
]
]
},
{
"id": "c8cc5a91dbf6eb1a",
"type": "delay",
"z": "26771494c726dd85",
"name": "",
"pauseType": "delay",
"timeout": "5",
"timeoutUnits": "minutes",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 520,
"y": 760,
"wires": [
[
"188d8b0ef9b1ec1c"
]
]
},
{
"id": "810cc1a467a83b14",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 8",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1440,
"y": 820,
"wires": []
},
{
"id": "188d8b0ef9b1ec1c",
"type": "trigger",
"z": "26771494c726dd85",
"name": "bat 6",
"op1": "bat 6",
"op2": "",
"op1type": "str",
"op2type": "nul",
"duration": "250",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 730,
"y": 760,
"wires": [
[
"2fd087fa4da3841b"
]
]
},
{
"id": "2fd087fa4da3841b",
"type": "serial request",
"z": "26771494c726dd85",
"name": "BMSMaster",
"serial": "d031dd424e7b1ff2",
"x": 890,
"y": 760,
"wires": [
[
"59e325c588ae2c94"
]
]
},
{
"id": "59e325c588ae2c94",
"type": "function",
"z": "26771494c726dd85",
"name": "convert to msgs",
"func": "const text = msg.payload;\n\nif (typeof text !== \"string\") {\n node.error(\"msg.payload ist kein String\", msg);\n return null;\n}\n\n// In einzelne Zeilen zerlegen\nconst lines = text\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== \"\");\n\n// Nur Zeilen berücksichtigen, die mit einer Batterienummer beginnen\nconst dataLines = lines.filter(line => /^\\d+\\s/.test(line));\n\nconst messages = [];\n\nfor (const line of dataLines) {\n\n // Spalten sind durch mindestens 2 Leerzeichen getrennt\n const columns = line.split(/\\s{2,}/);\n\n if (columns.length < 9) {\n node.warn(\"Zeile konnte nicht verarbeitet werden: \" + line);\n continue;\n }\n\n const battery = {\n battery: Number(columns[0]),\n volt: Number(columns[1]),\n tempr: Number(columns[2]),\n baseState: columns[3],\n voltState: columns[4],\n currState: columns[5],\n tempState: columns[6],\n coulomb: Number(columns[7].replace(\"%\", \"\")),\n capacity: Number(columns[8].replace(/[^\\d]/g, \"\"))\n };\n\n messages.push({\n ...msg,\n payload: battery\n });\n}\n\n// Alle Nachrichten nacheinander über denselben Ausgang senden\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1080,
"y": 760,
"wires": [
[
"5d321ccd3cdb9ce7"
]
]
},
{
"id": "b60baba38d523d1e",
"type": "ioBroker out",
"z": "26771494c726dd85",
"name": "",
"topic": "",
"ack": "true",
"autoCreate": "true",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1460,
"y": 760,
"wires": []
},
{
"id": "5d321ccd3cdb9ce7",
"type": "function",
"z": "26771494c726dd85",
"name": "function 7",
"func": "const battery = msg.payload;\n\nif (!battery || battery.battery === undefined) {\n node.error(\"Ungültiges Battery-Objekt\", msg);\n return null;\n}\n\nconst batteryId = battery.battery;\n\nconst states = [\n {\n id: \"voltage\",\n value: battery.volt,\n name: \"Voltage\",\n role: \"value.voltage\",\n type: \"number\",\n readonly: true,\n unit: \"mV\",\n min: 0\n },\n {\n id: \"temperature\",\n value: battery.tempr / 1000,\n name: \"Temperature\",\n role: \"value.temperature\",\n type: \"number\",\n readonly: true,\n unit: \"°C\"\n },\n {\n id: \"baseState\",\n value: battery.baseState,\n name: \"Base State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"voltageState\",\n value: battery.voltState,\n name: \"Voltage State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"currentState\",\n value: battery.currState,\n name: \"Current State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"temperatureState\",\n value: battery.tempState,\n name: \"Temperature State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"charge\",\n value: battery.coulomb,\n name: \"Charge\",\n role: \"value.battery\",\n type: \"number\",\n readonly: true,\n unit: \"%\",\n min: 0,\n max: 100\n },\n {\n id: \"capacity\",\n value: battery.capacity,\n name: \"Capacity\",\n role: \"value\",\n type: \"number\",\n readonly: true,\n unit: \"mAh\",\n min: 0\n }\n];\n\nconst messages = [];\n\nfor (const state of states) {\n const out = {\n topic: `0_userdata.0.pytes.06.${batteryId}.${state.id}`,\n payload: state.value,\n\n stateName: state.name,\n stateRole: state.role,\n stateType: state.type,\n stateReadonly: state.readonly\n };\n\n if (state.unit !== undefined) {\n out.stateUnit = state.unit;\n }\n\n if (state.min !== undefined) {\n out.stateMin = state.min;\n }\n\n if (state.max !== undefined) {\n out.stateMax = state.max;\n }\n\n messages.push(out);\n}\n\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 760,
"wires": [
[
"b60baba38d523d1e",
"810cc1a467a83b14"
]
]
},
{
"id": "09faeaa564e7d7ea",
"type": "delay",
"z": "26771494c726dd85",
"name": "",
"pauseType": "delay",
"timeout": "6",
"timeoutUnits": "minutes",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 520,
"y": 900,
"wires": [
[
"c0c69b8e170813f8"
]
]
},
{
"id": "0e613121bc95e046",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 9",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1440,
"y": 960,
"wires": []
},
{
"id": "c0c69b8e170813f8",
"type": "trigger",
"z": "26771494c726dd85",
"name": "bat 7",
"op1": "bat 7",
"op2": "",
"op1type": "str",
"op2type": "nul",
"duration": "250",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 730,
"y": 900,
"wires": [
[
"5e45ba1558c0e2c5"
]
]
},
{
"id": "5e45ba1558c0e2c5",
"type": "serial request",
"z": "26771494c726dd85",
"name": "BMSMaster",
"serial": "d031dd424e7b1ff2",
"x": 890,
"y": 900,
"wires": [
[
"56d333a3d08a8b60"
]
]
},
{
"id": "56d333a3d08a8b60",
"type": "function",
"z": "26771494c726dd85",
"name": "convert to msgs",
"func": "const text = msg.payload;\n\nif (typeof text !== \"string\") {\n node.error(\"msg.payload ist kein String\", msg);\n return null;\n}\n\n// In einzelne Zeilen zerlegen\nconst lines = text\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== \"\");\n\n// Nur Zeilen berücksichtigen, die mit einer Batterienummer beginnen\nconst dataLines = lines.filter(line => /^\\d+\\s/.test(line));\n\nconst messages = [];\n\nfor (const line of dataLines) {\n\n // Spalten sind durch mindestens 2 Leerzeichen getrennt\n const columns = line.split(/\\s{2,}/);\n\n if (columns.length < 9) {\n node.warn(\"Zeile konnte nicht verarbeitet werden: \" + line);\n continue;\n }\n\n const battery = {\n battery: Number(columns[0]),\n volt: Number(columns[1]),\n tempr: Number(columns[2]),\n baseState: columns[3],\n voltState: columns[4],\n currState: columns[5],\n tempState: columns[6],\n coulomb: Number(columns[7].replace(\"%\", \"\")),\n capacity: Number(columns[8].replace(/[^\\d]/g, \"\"))\n };\n\n messages.push({\n ...msg,\n payload: battery\n });\n}\n\n// Alle Nachrichten nacheinander über denselben Ausgang senden\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1080,
"y": 900,
"wires": [
[
"8dc1347bba1166d9"
]
]
},
{
"id": "a2f16c5161ec9254",
"type": "ioBroker out",
"z": "26771494c726dd85",
"name": "",
"topic": "",
"ack": "true",
"autoCreate": "true",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1460,
"y": 900,
"wires": []
},
{
"id": "8dc1347bba1166d9",
"type": "function",
"z": "26771494c726dd85",
"name": "function 8",
"func": "const battery = msg.payload;\n\nif (!battery || battery.battery === undefined) {\n node.error(\"Ungültiges Battery-Objekt\", msg);\n return null;\n}\n\nconst batteryId = battery.battery;\n\nconst states = [\n {\n id: \"voltage\",\n value: battery.volt,\n name: \"Voltage\",\n role: \"value.voltage\",\n type: \"number\",\n readonly: true,\n unit: \"mV\",\n min: 0\n },\n {\n id: \"temperature\",\n value: battery.tempr / 1000,\n name: \"Temperature\",\n role: \"value.temperature\",\n type: \"number\",\n readonly: true,\n unit: \"°C\"\n },\n {\n id: \"baseState\",\n value: battery.baseState,\n name: \"Base State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"voltageState\",\n value: battery.voltState,\n name: \"Voltage State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"currentState\",\n value: battery.currState,\n name: \"Current State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"temperatureState\",\n value: battery.tempState,\n name: \"Temperature State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"charge\",\n value: battery.coulomb,\n name: \"Charge\",\n role: \"value.battery\",\n type: \"number\",\n readonly: true,\n unit: \"%\",\n min: 0,\n max: 100\n },\n {\n id: \"capacity\",\n value: battery.capacity,\n name: \"Capacity\",\n role: \"value\",\n type: \"number\",\n readonly: true,\n unit: \"mAh\",\n min: 0\n }\n];\n\nconst messages = [];\n\nfor (const state of states) {\n const out = {\n topic: `0_userdata.0.pytes.07.${batteryId}.${state.id}`,\n payload: state.value,\n\n stateName: state.name,\n stateRole: state.role,\n stateType: state.type,\n stateReadonly: state.readonly\n };\n\n if (state.unit !== undefined) {\n out.stateUnit = state.unit;\n }\n\n if (state.min !== undefined) {\n out.stateMin = state.min;\n }\n\n if (state.max !== undefined) {\n out.stateMax = state.max;\n }\n\n messages.push(out);\n}\n\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 900,
"wires": [
[
"a2f16c5161ec9254",
"0e613121bc95e046"
]
]
},
{
"id": "027109f5112c3c3e",
"type": "delay",
"z": "26771494c726dd85",
"name": "",
"pauseType": "delay",
"timeout": "7",
"timeoutUnits": "minutes",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 520,
"y": 1040,
"wires": [
[
"98d31a678f60f56d"
]
]
},
{
"id": "8ed399995f0adf29",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 10",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1440,
"y": 1100,
"wires": []
},
{
"id": "98d31a678f60f56d",
"type": "trigger",
"z": "26771494c726dd85",
"name": "bat 8",
"op1": "bat 8",
"op2": "",
"op1type": "str",
"op2type": "nul",
"duration": "250",
"extend": false,
"overrideDelay": false,
"units": "ms",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 730,
"y": 1040,
"wires": [
[
"abed25adf4a19908"
]
]
},
{
"id": "abed25adf4a19908",
"type": "serial request",
"z": "26771494c726dd85",
"name": "BMSMaster",
"serial": "d031dd424e7b1ff2",
"x": 890,
"y": 1040,
"wires": [
[
"dfa2e714a883320c"
]
]
},
{
"id": "dfa2e714a883320c",
"type": "function",
"z": "26771494c726dd85",
"name": "convert to msgs",
"func": "const text = msg.payload;\n\nif (typeof text !== \"string\") {\n node.error(\"msg.payload ist kein String\", msg);\n return null;\n}\n\n// In einzelne Zeilen zerlegen\nconst lines = text\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== \"\");\n\n// Nur Zeilen berücksichtigen, die mit einer Batterienummer beginnen\nconst dataLines = lines.filter(line => /^\\d+\\s/.test(line));\n\nconst messages = [];\n\nfor (const line of dataLines) {\n\n // Spalten sind durch mindestens 2 Leerzeichen getrennt\n const columns = line.split(/\\s{2,}/);\n\n if (columns.length < 9) {\n node.warn(\"Zeile konnte nicht verarbeitet werden: \" + line);\n continue;\n }\n\n const battery = {\n battery: Number(columns[0]),\n volt: Number(columns[1]),\n tempr: Number(columns[2]),\n baseState: columns[3],\n voltState: columns[4],\n currState: columns[5],\n tempState: columns[6],\n coulomb: Number(columns[7].replace(\"%\", \"\")),\n capacity: Number(columns[8].replace(/[^\\d]/g, \"\"))\n };\n\n messages.push({\n ...msg,\n payload: battery\n });\n}\n\n// Alle Nachrichten nacheinander über denselben Ausgang senden\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1080,
"y": 1040,
"wires": [
[
"4127ce3ea3ebf45b"
]
]
},
{
"id": "9d3e816f7aae72a8",
"type": "ioBroker out",
"z": "26771494c726dd85",
"name": "",
"topic": "",
"ack": "true",
"autoCreate": "true",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1460,
"y": 1040,
"wires": []
},
{
"id": "4127ce3ea3ebf45b",
"type": "function",
"z": "26771494c726dd85",
"name": "function 9",
"func": "const battery = msg.payload;\n\nif (!battery || battery.battery === undefined) {\n node.error(\"Ungültiges Battery-Objekt\", msg);\n return null;\n}\n\nconst batteryId = battery.battery;\n\nconst states = [\n {\n id: \"voltage\",\n value: battery.volt,\n name: \"Voltage\",\n role: \"value.voltage\",\n type: \"number\",\n readonly: true,\n unit: \"mV\",\n min: 0\n },\n {\n id: \"temperature\",\n value: battery.tempr / 1000,\n name: \"Temperature\",\n role: \"value.temperature\",\n type: \"number\",\n readonly: true,\n unit: \"°C\"\n },\n {\n id: \"baseState\",\n value: battery.baseState,\n name: \"Base State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"voltageState\",\n value: battery.voltState,\n name: \"Voltage State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"currentState\",\n value: battery.currState,\n name: \"Current State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"temperatureState\",\n value: battery.tempState,\n name: \"Temperature State\",\n role: \"text\",\n type: \"string\",\n readonly: true\n },\n {\n id: \"charge\",\n value: battery.coulomb,\n name: \"Charge\",\n role: \"value.battery\",\n type: \"number\",\n readonly: true,\n unit: \"%\",\n min: 0,\n max: 100\n },\n {\n id: \"capacity\",\n value: battery.capacity,\n name: \"Capacity\",\n role: \"value\",\n type: \"number\",\n readonly: true,\n unit: \"mAh\",\n min: 0\n }\n];\n\nconst messages = [];\n\nfor (const state of states) {\n const out = {\n topic: `0_userdata.0.pytes.08.${batteryId}.${state.id}`,\n payload: state.value,\n\n stateName: state.name,\n stateRole: state.role,\n stateType: state.type,\n stateReadonly: state.readonly\n };\n\n if (state.unit !== undefined) {\n out.stateUnit = state.unit;\n }\n\n if (state.min !== undefined) {\n out.stateMin = state.min;\n }\n\n if (state.max !== undefined) {\n out.stateMax = state.max;\n }\n\n messages.push(out);\n}\n\nreturn [messages];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 1040,
"wires": [
[
"9d3e816f7aae72a8",
"8ed399995f0adf29"
]
]
},
{
"id": "4b31f05c7b6c5425",
"type": "debug",
"z": "26771494c726dd85",
"name": "debug 11",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1060,
"y": 120,
"wires": []
},
{
"id": "d031dd424e7b1ff2",
"type": "serial-port",
"name": "Pytes",
"serialport": "/dev/serial/by-id/usb-FTDI_USB_Serial_Converter_FTFS8I5L-if00-port0",
"serialbaud": "115200",
"databits": 8,
"parity": "none",
"stopbits": 1,
"waitfor": "@",
"dtr": "none",
"rts": "none",
"cts": "none",
"dsr": "none",
"newline": "250",
"bin": "false",
"out": "time",
"addchar": "\\r\\n",
"responsetimeout": "250"
},
{
"id": "655fb8e61b544b29",
"type": "global-config",
"env": [],
"modules": {
"node-red-node-serialport": "2.0.3"
}
}
]
Es ist äusserst interessant, ich habe heute mal die Schnittstellen durchreichung in den Iobroker Proxmox LXC neu, mit den offiziellen Proxmox Werkzeugen neu gemacht. Dabei ist mir aufgefallen, das der Flow mehrere male sauber läuft, plötzlich kommt die Meldung:
node-red.0
2026-08-15 16:54:00.757 error Node-RED: 15 Aug 16:54:00 - [error] [function:convert to msgs] msg.payload ist kein String
und auch im Flow wird dann beim entsprechenden Node aus einem "verbunden" ein "Timeout". Nach einem deaktivieren des ganzen Flow und deploy und anschliessendem aktivieren und deploy läuft er wieder ein paar Stunden ohne irgendwelche Probleme. Beim Fehler kommt scheinbar einfach keine Antwort mehr und der "function-Node" wirft dann den Fehler raus. Ist ja richtig und auch verständlich.
Kann es sein, dass es mit meiner vervielfachung auch quasi mehrere offenen Schnittstellen Task gibt?
Ich habe mich gefragt ob es allenfalls besser wäre trigger-Node so umzubauen das er eben nicht einfach nur den Text sendet, sondern das er quasi eine Liste mit den Texten abarbeitet. Oder das nach dem function Node ein zusätzlicher Node angestossen würde der die Schnittstelle schliesst? Nur da habe ich bis jetzt keinerlei Hinweise gefunden wie man eine solche serielle Schnittstelle schliessen kann.