From 6a920ce12a71d92a98d44e4cb3e49e46db386e23 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 17 Mar 2019 22:04:28 +0100 Subject: [PATCH] Nodered Timeserver fixes --- src/TTN/Nodered-Timeserver.json | 96 ++++++++++++++++----------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/src/TTN/Nodered-Timeserver.json b/src/TTN/Nodered-Timeserver.json index 24f0133a..37fe6063 100644 --- a/src/TTN/Nodered-Timeserver.json +++ b/src/TTN/Nodered-Timeserver.json @@ -1,4 +1,30 @@ [ + { + "id": "46ce842a.614d5c", + "type": "ui_gauge", + "z": "449c1517.e25f4c", + "name": "Timeserver offset", + "group": "edb7cc8d.a3817", + "order": 1, + "width": 0, + "height": 0, + "gtype": "gage", + "title": "Offset gateway to server", + "label": "milliseconds", + "format": "{{value}}", + "min": 0, + "max": "2000", + "colors": [ + "#00b500", + "#e6e600", + "#ca3838" + ], + "seg1": "", + "seg2": "", + "x": 690, + "y": 360, + "wires": [] + }, { "id": "49e3c067.e782e", "type": "change", @@ -48,7 +74,7 @@ "from": "", "to": "", "reg": false, - "x": 200, + "x": 240, "y": 420, "wires": [ [ @@ -64,7 +90,7 @@ "topic": "+/devices/+/up", "qos": "2", "broker": "2a15ab6f.ab2244", - "x": 70, + "x": 110, "y": 120, "wires": [ [ @@ -81,7 +107,7 @@ "qos": "", "retain": "", "broker": "2a15ab6f.ab2244", - "x": 690, + "x": 730, "y": 420, "wires": [] }, @@ -93,7 +119,7 @@ "property": "payload", "action": "", "pretty": false, - "x": 220, + "x": 260, "y": 200, "wires": [ [ @@ -118,7 +144,7 @@ "checkall": "true", "repair": false, "outputs": 1, - "x": 220, + "x": 260, "y": 120, "wires": [ [ @@ -134,7 +160,7 @@ "property": "payload", "action": "", "pretty": false, - "x": 540, + "x": 580, "y": 420, "wires": [ [ @@ -149,7 +175,7 @@ "name": "Decode", "action": "", "property": "payload.payload_raw", - "x": 380, + "x": 420, "y": 200, "wires": [ [ @@ -164,7 +190,7 @@ "name": "Encode", "action": "", "property": "payload.payload_raw", - "x": 380, + "x": 420, "y": 420, "wires": [ [ @@ -178,7 +204,7 @@ "z": "449c1517.e25f4c", "name": "LoRaWAN Timeserver", "info": "PLEASE NOTE: There is a patent filed for the time sync algorithm used in the\ncode of this file. The shown implementation example is covered by the\nrepository's licencse, but you may not be eligible to deploy the applied\nalgorithm in applications without granted license by the patent holder.", - "x": 120, + "x": 160, "y": 40, "wires": [] }, @@ -199,7 +225,7 @@ "checkall": "true", "repair": false, "outputs": 1, - "x": 550, + "x": 590, "y": 200, "wires": [ [ @@ -215,7 +241,7 @@ "func": "/* LoRaWAN Timeserver\n\nconstruct 6 byte timesync_answer from gateway timestamp and node's time_sync_req\n\nbyte meaning\n0 sequence number (taken from node's time_sync_req)\n1..4 current second (from epoch time 1970)\n5 1/250ths fractions of current second\n\n*/\n\nfunction timecompare(a, b) {\n \n const timeA = a.time;\n const timeB = b.time;\n\n let comparison = 0;\n if (timeA > timeB) {\n comparison = 1;\n } else if (timeA < timeB) {\n comparison = -1;\n }\n return comparison;\n}\n\nlet confidence = 2000; // max millisecond diff gateway time to server time\n\nvar gateways = msg.payload.metadata.gateways;\nvar gateway_time = gateways.map(gw => {\n return {\n time: new Date(gw.time),\n eui: gw.gtw_id,\n }\n });\nvar server_time = new Date(msg.payload.metadata.time);\n\n// validate all gateway timestamps against lorawan server_time (which is assumed to be recent)\nvar gw_timestamps = gateway_time.filter(function (element) {\n return ((element.time > (server_time - confidence) && element.time <= server_time));\n});\n\n// if no timestamp left, we have no valid one and exit\nif (gw_timestamps.length === 0) return null;\n\n// sort time array in ascending order to find most recent timestamp for time answer\ngw_timestamps.sort(timecompare);\n\nvar timestamp = gw_timestamps[0].time;\nvar eui = gw_timestamps[0].eui;\nvar offset = server_time - timestamp;\n\nvar seconds = Math.floor(timestamp/1000);\nvar fractions = (timestamp % 1000) / 4;\nvar seqno = msg.payload.payload_raw[0];\n\nlet buf = new ArrayBuffer(6);\nnew DataView(buf).setUint8(0, seqno);\nnew DataView(buf).setUint32(1, seconds);\nnew DataView(buf).setUint8(5, fractions);\n\nmsg.payload = new Buffer(new Uint8Array(buf));\nvar infoMsg = { payload: eui };\nvar offsetMsg = { payload: offset };\n\nreturn [infoMsg, msg, offsetMsg];", "outputs": 3, "noerr": 0, - "x": 380, + "x": 420, "y": 300, "wires": [ [ @@ -245,7 +271,7 @@ "console": false, "tostatus": true, "complete": "payload", - "x": 660, + "x": 700, "y": 260, "wires": [], "icon": "node-red/bridge.png" @@ -262,35 +288,20 @@ "label": "Recent timeserver was:", "format": "{{msg.payload}}", "layout": "col-center", - "x": 670, + "x": 710, "y": 320, "wires": [] }, { - "id": "46ce842a.614d5c", - "type": "ui_gauge", - "z": "449c1517.e25f4c", - "name": "offset", - "group": "edb7cc8d.a3817", - "order": 1, - "width": 0, - "height": 0, - "gtype": "gage", - "title": "Offset [ms]", - "label": "units", - "format": "{{value}}", - "min": 0, - "max": "2000", - "colors": [ - "#00b500", - "#e6e600", - "#ca3838" - ], - "seg1": "", - "seg2": "", - "x": 690, - "y": 360, - "wires": [] + "id": "edb7cc8d.a3817", + "type": "ui_group", + "z": "", + "name": "Timeserver", + "tab": "d525a5d.0832858", + "order": 4, + "disp": true, + "width": "6", + "collapse": false }, { "id": "2a15ab6f.ab2244", @@ -315,17 +326,6 @@ "willQos": "0", "willPayload": "" }, - { - "id": "edb7cc8d.a3817", - "type": "ui_group", - "z": "", - "name": "Timeserver", - "tab": "d525a5d.0832858", - "order": 4, - "disp": true, - "width": "6", - "collapse": false - }, { "id": "d525a5d.0832858", "type": "ui_tab",