From d4ddb4811fb418f2c7f7a21a321762249a06fff0 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 24 Mar 2019 23:23:00 +0100 Subject: [PATCH] Timeserver: filter gateway with ms timestamp --- .../Nodered-Timeserver.json | 41 ++++--------------- 1 file changed, 8 insertions(+), 33 deletions(-) rename src/{TTN => Timeserver}/Nodered-Timeserver.json (81%) diff --git a/src/TTN/Nodered-Timeserver.json b/src/Timeserver/Nodered-Timeserver.json similarity index 81% rename from src/TTN/Nodered-Timeserver.json rename to src/Timeserver/Nodered-Timeserver.json index 5f608a24..b3f68ef9 100644 --- a/src/TTN/Nodered-Timeserver.json +++ b/src/Timeserver/Nodered-Timeserver.json @@ -153,7 +153,7 @@ "y": 200, "wires": [ [ - "f868bce2.dde67" + "831ab883.d6a238" ] ] }, @@ -182,37 +182,12 @@ "y": 40, "wires": [] }, - { - "id": "f868bce2.dde67", - "type": "switch", - "z": "449c1517.e25f4c", - "name": "Timechecker", - "property": "payload.metadata.gateways[0].time", - "propertyType": "msg", - "rules": [ - { - "t": "lte", - "v": "payload.metadata.time", - "vt": "msg" - } - ], - "checkall": "true", - "repair": false, - "outputs": 1, - "x": 590, - "y": 200, - "wires": [ - [ - "831ab883.d6a238" - ] - ] - }, { "id": "831ab883.d6a238", "type": "function", "z": "449c1517.e25f4c", "name": "Generate Time Answer", - "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 deviceMsg = { payload: msg.payload.dev_id };\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 [\"n/a\", \"n/a\", deviceMsg, 0xff];\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 euiMsg = { payload: eui };\nvar offsetMsg = { payload: offset };\n\nreturn [euiMsg, offsetMsg, deviceMsg, msg];", + "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 deviceMsg = { payload: msg.payload.dev_id };\nvar gateway_list = msg.payload.metadata.gateways;\n\n// filter all gateway timestamps that have milliseconds part (which we assume have a \".\")\nvar gateways = gateway_list.filter(function (element) {\n return (element.time.includes(\".\"));\n});\n\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 [\"n/a\", \"n/a\", deviceMsg, 0xff];\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 euiMsg = { payload: eui };\nvar offsetMsg = { payload: offset };\n\nreturn [euiMsg, offsetMsg, deviceMsg, msg];", "outputs": 4, "noerr": 0, "x": 360, @@ -251,7 +226,7 @@ "tostatus": true, "complete": "payload", "x": 700, - "y": 280, + "y": 240, "wires": [], "icon": "node-red/bridge.png" }, @@ -268,7 +243,7 @@ "format": "{{msg.payload}}", "layout": "col-center", "x": 810, - "y": 336, + "y": 300, "wires": [] }, { @@ -294,7 +269,7 @@ "seg1": "", "seg2": "", "x": 710, - "y": 416, + "y": 380, "wires": [] }, { @@ -310,7 +285,7 @@ "format": "{{msg.payload}}", "layout": "col-center", "x": 700, - "y": 376, + "y": 340, "wires": [] }, { @@ -322,7 +297,7 @@ "outputs": 1, "noerr": 0, "x": 670, - "y": 336, + "y": 300, "wires": [ [ "8712a5ac.ed18e8" @@ -342,7 +317,7 @@ "format": "{{msg.payload}}", "layout": "col-center", "x": 700, - "y": 456, + "y": 420, "wires": [] }, {