forked from cyberman54/ESP32-Paxcounter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimeserver.java
86 lines (66 loc) · 2.47 KB
/
timeserver.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* LoRaWAN Timeserver
VERSION: 1.3
construct 6 byte timesync_answer from gateway timestamp and node's time_sync_req
byte meaning
1 sequence number (taken from node's time_sync_req)
2..5 current second (from GPS epoch starting 1980)
6 1/250ths fractions of current second
*/
function timecompare(a, b) {
const timeA = a.time;
const timeB = b.time;
let comparison = 0;
if (timeA > timeB) {
comparison = 1;
} else if (timeA < timeB) {
comparison = -1;
}
return comparison;
}
let confidence = 1000; // max millisecond diff gateway time to server time
// guess if we have received a valid time_sync_req command
if (msg.payload.payload_raw.length != 1)
return;
var deviceMsg = { payload: msg.payload.dev_id };
var seqNo = msg.payload.payload_raw[0];
var seqNoMsg = { payload: seqNo };
var gateway_list = msg.payload.metadata.gateways;
// filter all gateway timestamps that have milliseconds part (which we assume have a ".")
var gateways = gateway_list.filter(function (element) {
return (element.time.includes("."));
});
var gateway_time = gateways.map(gw => {
return {
time: new Date(gw.time),
eui: gw.gtw_id,
}
});
var server_time = new Date(msg.payload.metadata.time);
// validate all gateway timestamps against lorawan server_time (which is assumed to be recent)
var gw_timestamps = gateway_time.filter(function (element) {
return ((element.time > (server_time - confidence) && element.time <= server_time));
});
// if no timestamp left, we have no valid one and exit
if (gw_timestamps.length === 0) {
var notavailMsg = { payload: "n/a" };
var notimeMsg = { payload: 0xff };
var buf2 = Buffer.alloc(1);
msg.payload = new Buffer(buf2.fill(0xff));
msg.port = 9; // Paxcounter TIMEPORT
return [notavailMsg, notavailMsg, deviceMsg, seqNoMsg, msg];}
// sort time array in ascending order to find most recent timestamp for time answer
gw_timestamps.sort(timecompare);
var timestamp = gw_timestamps[0].time;
var eui = gw_timestamps[0].eui;
var offset = server_time - timestamp;
var seconds = Math.floor(timestamp/1000);
var fractions = (timestamp % 1000) / 4;
let buf = new ArrayBuffer(6);
new DataView(buf).setUint8(0, seqNo);
new DataView(buf).setUint32(1, seconds);
new DataView(buf).setUint8(5, fractions);
msg.payload = new Buffer(new Uint8Array(buf));
msg.port = 9; // Paxcounter TIMEPORT
var euiMsg = { payload: eui };
var offsetMsg = { payload: offset };
return [euiMsg, offsetMsg, deviceMsg, seqNoMsg, msg];