First time with node red, issue with chart node

Hi I am new here and work with node red the first time.
I am a programmer in vb.net. So some knowledge about programming is there.
I want to display some values with the chart node.
I imported a flow from the www to learn, but I get "no data available" with that.
It contains an inject node, which triggers a function node, that increases a simple value every 3 seconds. thes values i want to display with a bar chart. But the dashboard say "no data available".

code in the function node:

var i = 0;

i = i + 5;

msg.payload = {
"series": ["Wert"],
"data": [
[20 + i]
],
"labels": ["Zeit"]
};

return msg;

What I did wrong?

Wrap it in [ ]

var i = 0;

i = i + 5;

msg.payload = [{
"series": ["Wert"],
"data": [
[20 + i]
],
"labels": ["Zeit"]
}];

return msg;

Add an inject node to trigger the data

1 Like

thank you!

please what is wrong here: I want to output 3 values, but chart shows me the first only.

msg.payload = [
    { 
        topic: "Strompreis", 
        payload: 84.75, 
        timestamp: "Jetzt" 
    },
    { 
        topic: "w", 
        payload: 78.50, 
        timestamp: "Nächste Stunde" 
    },
    { 
        topic: "1", 
        payload: 79.00, 
        timestamp: "Übermorgen" 
    }
];

node.warn(msg.payload); // Gibt das Array von Objekten aus

return msg;

Try...

const messages = [
    { 
        topic: "Strompreis", 
        payload: 84.75, 
        timestamp: "Jetzt" 
    },
    { 
        topic: "w", 
        payload: 78.50, 
        timestamp: "Nächste Stunde" 
    },
    { 
        topic: "1", 
        payload: 79.00, 
        timestamp: "Übermorgen" 
    }
]
return messages

I think that should be

const messages = [
  [  
    { 
        topic: "Strompreis", 
        payload: 84.75, 
        timestamp: "Jetzt" 
    },
    { 
        topic: "w", 
        payload: 78.50, 
        timestamp: "Nächste Stunde" 
    },
    { 
        topic: "1", 
        payload: 79.00, 
        timestamp: "Übermorgen" 
    }
  ]
]
return messages

Hi! Both versions work, many thanks.
Could anybody explain why I need to save these value in a CONST first and not directly into msg.payload?

Because they are completely different operations.

Setting msg.payload then returning the msg will simply return 1 msg with the payload set as an array.

Returning an array of messages will cause the function to output multiple messages.

This is easily verified and can be visually understood by putting a debug node on the output of the function. Your original version will send 1 message. Colins code will send 3 messages.

https://nodered.org/docs/user-guide/writing-functions#multiple-messages

1 Like

thank you very much.

I have an other question:

I am reading in a JSON from a power supplier from www with http request, it contains 24 prices and the corresponding time stamps (hour). I am reading in this JSON every 24h.

In my function node I output these 24 values in a chart and also in 24 checkboxes. I filter the lowest 4 prices and check the checkboxes accordingly. When the actual hour corresponds with the hour of one of the 4 prices it activates loading my house battery.
Additionally I could check/uncheck one or some of these 24 checkboxes manually as well.

So far so good.

The problem is, that the function node runs the code just once in 24h. But it shall run at least every hour. So I need a second inject node which is directly connected to the function node. But if I do so I get an error in a debug node, which says "invalid payload format". But why is it invalid suddenly, I just run the code more often!?

Any idea why?

Where is the debug node connected to? A node it is connected to is presumably generating the error.

I found the error. But I have another big issue since weeks.
MY function node is triggered every 5 sec and additionally one a day when it gets new values via http request (24 arrays object).
I create 24 checkboxes and dependant on the new values via http request, 4 checkboxes of the 24 are set accordingly to the lowest current prices automatically.
Additionally I may change them manually.

The automatic setting works.
But when I change them manually, this change is reset every 5 sec.
I tried to save the checkboxes manually and load them freshly, but it does not work and I do not find this annoying error

Hope somebody could help me in this issue.

Please see my flow attached.

[
    {
        "id": "277a00131d48d196",
        "type": "inject",
        "z": "38565ad851da076a",
        "name": "alle 24h aktualisieren",
        "props": [],
        "repeat": "86400",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "x": 260,
        "y": 260,
        "wires": [
            [
                "37a5e4cee357045b"
            ]
        ]
    },
    {
        "id": "6b43156f871e2d4c",
        "type": "inject",
        "z": "38565ad851da076a",
        "name": "5 sek",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": true,
        "onceDelay": "5",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 450,
        "y": 140,
        "wires": [
            [
                "1f03e8f1369b3c06"
            ]
        ]
    },
    {
        "id": "37a5e4cee357045b",
        "type": "http request",
        "z": "38565ad851da076a",
        "name": "Preise von awattar laden",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "https://api.awattar.at/v1/marketdata",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 510,
        "y": 260,
        "wires": [
            [
                "1f03e8f1369b3c06",
                "82f6c05fca8a53c6"
            ]
        ]
    },
    {
        "id": "1f03e8f1369b3c06",
        "type": "function",
        "z": "38565ad851da076a",
        "name": "",
        "func": "// Strompreise und Stunden aus Flow-Variablen abrufen oder initialisieren\nlet Strompreise24 = flow.get(\"Strompreise24\") || [];\nlet Stunden24 = flow.get(\"Stunden24\") || [];\nlet finalCheckboxState = flow.get(\"finalCheckboxState\") || new Array(24).fill(false); // Manuell gesetzte Checkboxen\n\n// **Wenn neue Daten vom HTTP-Request Node empfangen werden**\nif (msg.payload && msg.payload.data && Array.isArray(msg.payload.data)) {\n    node.warn(\"Neue Daten empfangen, aktualisiere Strompreise...\");\n\n    // Strompreise und Stunden leeren, bevor neue Daten eingefügt werden\n    Strompreise24 = [];\n    Stunden24 = [];\n\n    // Strompreise und Labels extrahieren\n    msg.payload.data.forEach((entry) => {\n        Strompreise24.push(entry.marketprice / 10); // Strompreis skalieren\n        let date = new Date(entry.start_timestamp);\n        Stunden24.push(date.getHours() + \":\" + (\"0\" + date.getMinutes()).slice(-2)); // Stunden:Minuten\n    });\n\n    // Die aktualisierten Strompreise und Stunden in Flow-Variablen speichern\n    flow.set(\"Strompreise24\", Strompreise24);\n    flow.set(\"Stunden24\", Stunden24);\n\n    // **Alle Checkboxen zurücksetzen (auf false setzen), aber manuell gesetzte beibehalten**\n    let updatedCheckboxState = new Array(24).fill(false); // Alle Checkboxen auf false setzen\n\n    // 4 niedrigste Strompreise finden (unter Beibehaltung der Indizes)\n    let indexedPrices = Strompreise24.map((price, index) => ({ price, index }));\n    indexedPrices.sort((a, b) => a.price - b.price);\n\n    // Sicherstellen, dass nur 4 niedrigste Preise genommen werden\n    let lowestIndices = indexedPrices.slice(0, 4).map(entry => entry.index);\n\n    // Die 4 niedrigsten Checkboxen auf `true` setzen\n    lowestIndices.forEach((index) => {\n        updatedCheckboxState[index] = true;\n    });\n\n    // Manuell gesetzte Checkboxen aus Flow beibehalten\n    lowestIndices.forEach((index) => {\n        if (finalCheckboxState[index] === true) {\n            updatedCheckboxState[index] = true;\n        }\n    });\n\n    // Den neuen Zustand der Checkboxen in Flow-Variable speichern\n    flow.set(\"checkboxState\", updatedCheckboxState);\n    flow.set(\"finalCheckboxState\", finalCheckboxState); // Manuell gesetzte Checkboxen bleiben erhalten\n    node.warn(\"Aktualisierter Zustand der Checkboxen (mit neuen Daten): \", updatedCheckboxState);\n\n} else {\n    node.warn(\"Keine neuen Daten erhalten, der Zustand bleibt unverändert.\");\n}\n\n// **Wenn es der 1-Sekunden-Trigger ist, nur die Text-Ausgabe und Chart aktualisieren**\nif (msg.payload && msg.payload !== \"\") { // msg.payload ist hier ein Zeitstempel, aber wir ignorieren den Inhalt\n    node.warn(\"Trigger: Jede Sekunde, prüfe aktuelle Checkbox...\");\n\n    // Prüfen, ob Daten vorhanden sind\n    if (Strompreise24.length > 0 && Stunden24.length > 0) {\n        // Aktuelle Stunde ermitteln\n        let now = new Date();\n        let currentHour = now.getHours();\n\n        // Zustand der aktuellen Checkbox nur lesen (nicht ändern)\n        let currentCheckboxState = flow.get(\"checkboxState\")[currentHour] || false;\n\n        node.warn(\"Aktuelle Stunde: \", currentHour);\n        node.warn(\"Zustand der aktuellen Checkbox: \", currentCheckboxState);\n\n        // Text-Ausgabe basierend auf dem Zustand der aktuellen Checkbox\n        let textOutput = {\n            payload: currentCheckboxState ? \"Akku lädt\" : \"Akku wird nicht geladen\"\n        };\n\n        node.warn(\"Text-Ausgabe (Akku laden): \", textOutput.payload);\n\n        // 1. Ausgabe für das Chart\n        let chartOutput = {\n            payload: [{\n                series: [\"Strompreise\"],\n                data: [Strompreise24],\n                labels: Stunden24\n            }]\n        };\n\n        node.warn(\"Chart-Ausgabe: \", chartOutput.payload);\n\n        // 2. Ausgabe für die Checkboxen\n        let checkboxOutput = {\n            payload: {\n                Strompreise24: Strompreise24,\n                Stunden24: Stunden24,\n                checkboxes: flow.get(\"checkboxState\") // Nutzung des aktuellen Zustands der Checkboxen\n            }\n        };\n\n        node.warn(\"Checkbox-Ausgabe: \", checkboxOutput.payload);\n\n        // Rückgabe: [Chart-Ausgabe, Checkbox-Ausgabe, Text-Ausgabe]\n        return [chartOutput, checkboxOutput, textOutput];\n    } else {\n        node.warn(\"Fehler: Keine gültigen Strompreise oder Stunden verfügbar!\");\n        return [null, null, null];\n    }\n} else {\n    node.warn(\"Fehler: Kein gültiger Trigger empfangen\");\n    return null;\n}\n",
        "outputs": 3,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 680,
        "y": 140,
        "wires": [
            [
                "7cae2eb7a1fe7246"
            ],
            [
                "2b29818e62b35a16",
                "f9473b51329b3e04",
                "3f65bdd08084c6ba"
            ],
            [
                "f179424e292e9072"
            ]
        ]
    },
    {
        "id": "82f6c05fca8a53c6",
        "type": "debug",
        "z": "38565ad851da076a",
        "name": "debug 6",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 760,
        "y": 260,
        "wires": []
    },
    {
        "id": "f179424e292e9072",
        "type": "ui_text",
        "z": "38565ad851da076a",
        "group": "472a29f10598521a",
        "order": 7,
        "width": 0,
        "height": 0,
        "name": "Akku lädt?",
        "label": "text",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1030,
        "y": 180,
        "wires": []
    },
    {
        "id": "f9473b51329b3e04",
        "type": "debug",
        "z": "38565ad851da076a",
        "name": "debug 5",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1020,
        "y": 140,
        "wires": []
    },
    {
        "id": "3f65bdd08084c6ba",
        "type": "ui_template",
        "z": "38565ad851da076a",
        "group": "472a29f10598521a",
        "name": "Checkboxes Wärmepumpe",
        "order": 8,
        "width": 0,
        "height": 0,
        "format": "\n<div style=\"display: flex; flex-wrap: wrap; gap: 10px;padding-left: 37px;\">\n  <div ng-repeat=\"n in [].constructor(24) track by $index\">\n    <label>\n      <input type=\"checkbox\" ng-model=\"checkboxes[$index]\">\n    </label>\n  </div>\n</div>\n\n<script>\n  (function(scope) {\n    scope.$watch('msg.payload', function(data) {\n      if (data) {\n        scope.prices = data.prices; // Optional: falls du die Preise irgendwo verwenden willst\n        scope.checkboxes = data.checkboxes;\n      }\n    });\n  })(scope);\n</script>\n",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 1080,
        "y": 100,
        "wires": [
            []
        ]
    },
    {
        "id": "2b29818e62b35a16",
        "type": "ui_template",
        "z": "38565ad851da076a",
        "group": "472a29f10598521a",
        "name": "Checkboxes Akku",
        "order": 6,
        "width": "10",
        "height": "2",
        "format": "<div style=\"display: flex; flex-wrap: wrap; gap: 0px;padding-left: 37px;\">\n  <div ng-repeat=\"n in [].constructor(24) track by $index\">\n    <label>\n      <input type=\"checkbox\" ng-model=\"checkboxes[$index]\" ng-change=\"sendCheckboxState()\">\n    </label>\n  </div>\n</div>\n\n<script>\n  (function(scope) {\n    // Initialisieren von checkboxen, falls msg.payload.checkboxes verfügbar ist\n    scope.$watch('msg.payload', function(data) {\n      if (data) {\n        scope.checkboxes = data.checkboxes || new Array(24).fill(false); // Wenn keine Checkboxen vorhanden, auf false setzen\n      }\n    });\n\n    // Funktion, um den Zustand der Checkboxen an den Flow zu senden\n    scope.sendCheckboxState = function() {\n      var checkboxState = scope.checkboxes; // Zustand der Checkboxen\n\n      // Die Nachricht mit den aktuellen Checkboxen an den Flow senden\n      scope.send({ payload: { checkboxes: checkboxState } });\n    };\n  })(scope);\n</script>\n",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 1050,
        "y": 60,
        "wires": [
            []
        ]
    },
    {
        "id": "7cae2eb7a1fe7246",
        "type": "ui_chart",
        "z": "38565ad851da076a",
        "name": "",
        "group": "472a29f10598521a",
        "order": 5,
        "width": "10",
        "height": "4",
        "label": "Strompreise",
        "chartType": "bar",
        "legend": "false",
        "xformat": "auto",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "useOneColor": true,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 1030,
        "y": 20,
        "wires": [
            []
        ]
    },
    {
        "id": "472a29f10598521a",
        "type": "ui_group",
        "name": "Awattar_Group",
        "tab": "2dde8bcb178d77da",
        "order": 2,
        "disp": true,
        "width": "15",
        "collapse": false,
        "className": ""
    },
    {
        "id": "2dde8bcb178d77da",
        "type": "ui_tab",
        "name": "Home",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]

sorry, not everything was copied