Skip to content

Instantly share code, notes, and snippets.

@shrickus
Last active January 19, 2018 17:39
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save shrickus/e9aaad549f13dc279dbaa05a9540113a to your computer and use it in GitHub Desktop.
Display line chart data as Elapsed Time since the first event was received

Normally, the ui_chart node expects the x-axis values to be real-time dates or timestamps. In this case, we want to see 00:00:00 on the left side of the chart, with elapsed time offsets along the x-axis. Currently, this mode is not supported by the chart node.

elapsed time chart example

Instead of passing each msg individually to the chart, the function node context is used to hold a growing array of relative timestamps, which is passed into the chart node every time a new msg arrives. NB: In order to show the elapsed time starting at 00:00:00 (local time), each relative timestamp must be adjusted for the current timezone's offset from UTC at the time of the epoch.

elapsed time flow sample

The function node's context can be reset by passing in an empty array, or can be "pre-loaded" with a saved data array. The format of the saved data array must match the sample "old data" inject node in this flow -- namely, the first data point's x-value is the absolute timestamp, and the rest of the data points are relative offsets (in millis) to that timestamp:

[[1497621600000,0],[18000000,86],[18030004,75],[18060007,92],[18090008,90]]

Finally, the array is trimmed to remove old data once it gets above a certain size (e.g. 100 points). This prevents the flow from unbounded growth, and avoids overloading the chart with points that cannot be differentiated.

[
{
"id": "f0434b54.e1d088",
"type": "inject",
"z": "d388adbc.37c1c",
"name": "",
"topic": "Current",
"payload": "",
"payloadType": "date",
"repeat": "30",
"crontab": "",
"once": false,
"x": 160,
"y": 740,
"wires": [
[
"1decfb98.ae60d4"
]
]
},
{
"id": "1decfb98.ae60d4",
"type": "function",
"z": "d388adbc.37c1c",
"name": "Random",
"func": "msg.payload = Math.round(Math.random() * 100);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 360,
"y": 740,
"wires": [
[
"f601569c.b2ebe8",
"48d2c199.c9ff4",
"4ec2099d.b43a08"
]
]
},
{
"id": "d15c669e.b12458",
"type": "inject",
"z": "d388adbc.37c1c",
"name": "Clear all data",
"topic": "",
"payload": "[]",
"payloadType": "json",
"repeat": "",
"crontab": "",
"once": false,
"x": 190,
"y": 800,
"wires": [
[
"4ec2099d.b43a08"
]
]
},
{
"id": "4d54bec5.f29c",
"type": "debug",
"z": "d388adbc.37c1c",
"name": "",
"active": false,
"console": "false",
"complete": "false",
"x": 750,
"y": 780,
"wires": []
},
{
"id": "a3109e12.c21cb",
"type": "ui_chart",
"z": "d388adbc.37c1c",
"name": "",
"group": "f3e75316.ec407",
"order": 1,
"width": 0,
"height": 0,
"label": "Elapsed time",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm:ss",
"interpolate": "linear",
"nodata": "",
"ymin": "",
"ymax": "",
"removeOlder": 1,
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"x": 570,
"y": 800,
"wires": [
[
"4d54bec5.f29c"
],
[]
]
},
{
"id": "4ec2099d.b43a08",
"type": "function",
"z": "d388adbc.37c1c",
"name": "relative data",
"func": "// get current time and context array\nvar now = Date.now();\nvar off = new Date(70, 0, 1) - new Date(0);\nvar arr = context.get(\"data\") || [];\n\n// reset the data if empty array is received\nif (Array.isArray(msg.payload)) {\n if (msg.payload.length === 0) {\n context.set(\"data\", msg.payload);\n return msg; // to clear the chart\n }\n else {\n arr = msg.payload;\n }\n}\nelse {\n // get/set the initial (absolute) timestamp\n var dt0 = arr.length ? arr[0][0] : now;\n if (arr.length === 0) {\n arr.push([ dt0, 0 ]);\n }\n \n // calculate time since last msg\n var dt1 = msg.timestamp || now;\n var dlt = (dt1 - dt0) + off;\n \n // add new relative data point to array\n arr.push([ dlt, msg.payload ]);\n}\n\n// limit the array to the last 100 points\nvar lim = 100;\nif (arr.length > lim+1) {\n // remove the oldest point(s)\n arr.splice(1, arr.length-lim-1);\n}\ncontext.set(\"data\", arr);\n\n// build the chart msg with the array\nvar key = msg.topic || \"Test Data\";\nmsg.payload = [{ \"key\": key, \"values\": arr.slice(1) }];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 390,
"y": 800,
"wires": [
[
"a3109e12.c21cb"
]
]
},
{
"id": "f01469e4.4d9838",
"type": "inject",
"z": "d388adbc.37c1c",
"name": "Historical data",
"topic": "History",
"payload": "[[1497621600000,0],[18000000,86],[18030004,5],[18060007,92],[18090008,90]]",
"payloadType": "json",
"repeat": "",
"crontab": "",
"once": false,
"x": 190,
"y": 840,
"wires": [
[
"4ec2099d.b43a08"
]
]
},
{
"id": "f3e75316.ec407",
"type": "ui_group",
"z": "",
"name": "Relative",
"tab": "379107b8.4087e8",
"order": 2,
"disp": true,
"width": "12"
},
{
"id": "379107b8.4087e8",
"type": "ui_tab",
"z": "",
"name": "Random",
"icon": "dashboard"
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment