if (!Array.isArray(msg.payload)) {
node.error("msg.payload is not an array");
return null;
}
let points = msg.payload.map(item => {
if (!item._time || typeof item._value === "undefined") {
node.warn("missed incorrect data element");
return null;
}
// convert time to ISO 8601
let isoTime = new Date(item._time).toISOString(); // "2025-04-21T08:02:17.123Z"
isoTime = isoTime.replace(/\.\d{3}Z$/, "Z"); // "2025-04-21T08:02:17Z"
// convert value to a number
let valueNum = Number(item._value);
if (isNaN(valueNum)) {
node.warn("value is not number: " + item._value);
return null;
}
return { x: isoTime, y: valueNum };
}).filter(p => p !== null);
if (points.length === 0) {
node.error("no correct data for chart");
return null;
}
msg.payload = points;
return msg;
And finally - Chart.
Type = line chart,
X-axis Label = Automatic
And only see error: "Bad data inject"
As I can understand, data to chart is correct and in correct format?
Where's the issue?
Error was gone, but chart is empty (no axis, no legends - only label).
Noticed, that in date debug is in future (my TZ is +3). Changed it to local - anyway chart is empty:
if (!Array.isArray(msg.payload)) {
node.error("msg.payload is not an array");
return null;
}
node.warn("Payload length: " + msg.payload.length);
let dataArray = msg.payload.map(item => {
if (!item._time || typeof item._value === "undefined") {
node.warn("missed element without _time or _value");
return null;
}
// convert time from UTC то local
let localTime = new Date(item._time).toLocaleString("ru-RU", { timeZone: "Europe/Moscow" });
return {
x: localTime,
y: Number(item._value)
};
}).filter(p => p !== null);
node.warn("dataArray length: " + dataArray.length);
msg.payload = [
{
series: ["line_name"],
data: dataArray
}
];
return msg;
The times do not look like ISO timestamps which you showed in previous post, maybe convert to ISO or millisecond unix timestamps, but most probably The issue Steve has shown ( i have fixed the example i showed.).
Best to supply an example minimal flow with attached data, as Steve has show how to get. This way we can run the flow and see the settings.
I'm not sure the time correction is necessary, but I will check this later.
So, the code:
for (let i = 0; i < msg.payload.length; i++) {
let obj = msg.payload[i];
if (obj._value === null ||
obj._value === "" ) {
console.log(Zero: ${obj._value});
obj._value = 0;
}
obj._value = Number(obj._value);
console.log(Converted: ${obj._value});
// manual time correction (+3 hours)
if (obj._start) {
const dateObj = new Date(obj._time);
dateObj.setHours(dateObj.getHours() + 3); // +3 hours
obj._time = dateObj.toISOString(); // saving back to ISO format
const dateObj_start = new Date(obj._start);
dateObj_start.setHours(dateObj_start.getHours() + 3); //+3 hours
obj._start = dateObj_start.toISOString(); // saving back to ISO format
const dateObj_stop = new Date(obj._stop);
dateObj_stop.setHours(dateObj_stop.getHours() + 3); // +3 hours
obj._stop = dateObj_stop.toISOString(); // saving back to ISO format
}