timeserver (experimental)
This commit is contained in:
parent
71475678cd
commit
bd8718f23f
@ -5,7 +5,7 @@
|
|||||||
#include "timesync.h"
|
#include "timesync.h"
|
||||||
#include "timekeeper.h"
|
#include "timekeeper.h"
|
||||||
|
|
||||||
#define TIME_SYNC_SAMPLES 1 // number of time requests for averaging
|
#define TIME_SYNC_SAMPLES 3 // number of time requests for averaging
|
||||||
#define TIME_SYNC_CYCLE 30 // seconds between two time requests
|
#define TIME_SYNC_CYCLE 30 // seconds between two time requests
|
||||||
#define TIME_SYNC_TIMEOUT 120 // timeout seconds waiting for timeserver answer
|
#define TIME_SYNC_TIMEOUT 120 // timeout seconds waiting for timeserver answer
|
||||||
#define TIME_SYNC_TRIGGER 1.0f // time deviation threshold triggering time sync
|
#define TIME_SYNC_TRIGGER 1.0f // time deviation threshold triggering time sync
|
||||||
|
@ -131,7 +131,7 @@
|
|||||||
"type": "function",
|
"type": "function",
|
||||||
"z": "449c1517.e25f4c",
|
"z": "449c1517.e25f4c",
|
||||||
"name": "Time_Sync_Ans",
|
"name": "Time_Sync_Ans",
|
||||||
"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\n let buf = new ArrayBuffer(6);\n let timestamp = (+new Date(msg.payload.metadata.gateways[0].time));\n \n var seconds = Math.floor(timestamp/1000);\n var fractions = timestamp % 250;\n var seqno = msg.payload.payload_raw[0];\n\n new DataView(buf).setUint8(0, seqno);\n new DataView(buf).setUint32(1, seconds);\n new DataView(buf).setUint8(5, fractions);\n\n msg.payload = new Buffer(new Uint8Array(buf));\n \n return 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\n let buf = new ArrayBuffer(6);\n let timestamp = (+new Date(msg.payload.metadata.gateways[0].time));\n \n var seconds = Math.floor(timestamp/1000);\n var fractions = (timestamp % 1000) / 4;\n var seqno = msg.payload.payload_raw[0];\n\n new DataView(buf).setUint8(0, seqno);\n new DataView(buf).setUint32(1, seconds);\n new DataView(buf).setUint8(5, fractions);\n\n msg.payload = new Buffer(new Uint8Array(buf));\n \n return msg;",
|
||||||
"outputs": 1,
|
"outputs": 1,
|
||||||
"noerr": 0,
|
"noerr": 0,
|
||||||
"x": 400,
|
"x": 400,
|
||||||
|
@ -19,8 +19,8 @@ static const char TAG[] = __FILE__;
|
|||||||
TaskHandle_t timeSyncReqTask;
|
TaskHandle_t timeSyncReqTask;
|
||||||
time_sync_message_t time_sync_messages[TIME_SYNC_SAMPLES] = {0},
|
time_sync_message_t time_sync_messages[TIME_SYNC_SAMPLES] = {0},
|
||||||
time_sync_answers[TIME_SYNC_SAMPLES] = {0};
|
time_sync_answers[TIME_SYNC_SAMPLES] = {0};
|
||||||
uint8_t time_sync_seqNo = 0;
|
static uint8_t time_sync_seqNo = 0;
|
||||||
bool time_sync_pending = false;
|
static bool time_sync_pending = false;
|
||||||
|
|
||||||
// send time request message
|
// send time request message
|
||||||
void send_Servertime_req() {
|
void send_Servertime_req() {
|
||||||
@ -59,15 +59,18 @@ void recv_Servertime_ans(uint8_t buf[], uint8_t buf_len) {
|
|||||||
if ((!time_sync_pending) || (buf_len != TIME_SYNC_FRAME_LENGTH))
|
if ((!time_sync_pending) || (buf_len != TIME_SYNC_FRAME_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8_t seq_no = buf[0];
|
uint8_t seq_no = buf[0], k = seq_no % TIME_SYNC_SAMPLES;
|
||||||
uint32_t timestamp_sec = 0, timestamp_ms = 0;
|
uint32_t timestamp_sec = 0;
|
||||||
|
|
||||||
for (uint8_t i = 1; i <= 4; i++)
|
for (uint8_t i = 1; i <= 4; i++) {
|
||||||
time_sync_answers[seq_no].seconds = (timestamp_sec <<= 8) |= buf[i];
|
time_sync_answers[k].seconds = (timestamp_sec <<= 8) |= buf[i];
|
||||||
time_sync_answers[seq_no].fractions = timestamp_ms = 4 * buf[5];
|
}
|
||||||
|
time_sync_answers[k].fractions = buf[5];
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Timeserver answer #%d received: timestamp=%d.%03d", seq_no,
|
ESP_LOGD(TAG, "Timeserver answer:");
|
||||||
timestamp_sec, timestamp_ms);
|
|
||||||
|
ESP_LOGD(TAG, "ans.sec(%d)=%d / ans.ms(%d)=%d", k,
|
||||||
|
time_sync_answers[k].seconds, k, time_sync_answers[k].fractions);
|
||||||
|
|
||||||
// inform processing task
|
// inform processing task
|
||||||
if (timeSyncReqTask)
|
if (timeSyncReqTask)
|
||||||
@ -77,11 +80,10 @@ void recv_Servertime_ans(uint8_t buf[], uint8_t buf_len) {
|
|||||||
// task for sending time sync requests
|
// task for sending time sync requests
|
||||||
void process_Servertime_sync_req(void *taskparameter) {
|
void process_Servertime_sync_req(void *taskparameter) {
|
||||||
|
|
||||||
time_t time_to_set = 0;
|
time_t t = 0, time_to_set = 0;
|
||||||
uint32_t seq_no = 0;
|
uint32_t seq_no = 0, k = 0;
|
||||||
int16_t time_diff_ms = 0;
|
int time_diff_frac = 0, time_diff_ms = 0;
|
||||||
int64_t time_diff_sec = 0;
|
long time_diff_sec = 0, time_offset = 0;
|
||||||
float time_offset = 0.0f;
|
|
||||||
|
|
||||||
// enqueue timestamp samples in lora sendqueue
|
// enqueue timestamp samples in lora sendqueue
|
||||||
for (uint8_t i = 1; i <= TIME_SYNC_SAMPLES; i++) {
|
for (uint8_t i = 1; i <= TIME_SYNC_SAMPLES; i++) {
|
||||||
@ -94,10 +96,12 @@ void process_Servertime_sync_req(void *taskparameter) {
|
|||||||
payload.addByte(time_sync_seqNo);
|
payload.addByte(time_sync_seqNo);
|
||||||
SendPayload(TIMEPORT, prio_high);
|
SendPayload(TIMEPORT, prio_high);
|
||||||
|
|
||||||
|
/* -> do we really need this? maybe for SF9 up?
|
||||||
// send dummy packet to trigger receive answer
|
// send dummy packet to trigger receive answer
|
||||||
//payload.reset();
|
payload.reset();
|
||||||
//payload.addByte(0x99); // flush
|
payload.addByte(0x99); // flush
|
||||||
//SendPayload(RCMDPORT, prio_low); // to open receive slot for answer
|
SendPayload(RCMDPORT, prio_low); // to open receive slot for answer
|
||||||
|
*/
|
||||||
|
|
||||||
// process answer
|
// process answer
|
||||||
if ((xTaskNotifyWait(0x00, ULONG_MAX, &seq_no,
|
if ((xTaskNotifyWait(0x00, ULONG_MAX, &seq_no,
|
||||||
@ -109,20 +113,29 @@ void process_Servertime_sync_req(void *taskparameter) {
|
|||||||
} // no valid sequence received before timeout
|
} // no valid sequence received before timeout
|
||||||
|
|
||||||
else { // calculate time diff from set of collected timestamps
|
else { // calculate time diff from set of collected timestamps
|
||||||
uint8_t k = seq_no % TIME_SYNC_SAMPLES;
|
|
||||||
|
k = seq_no % TIME_SYNC_SAMPLES;
|
||||||
|
|
||||||
time_diff_sec +=
|
time_diff_sec +=
|
||||||
(time_sync_messages[k].seconds - time_sync_answers[k].seconds);
|
((time_sync_messages[k].seconds - time_sync_answers[k].seconds) / TIME_SYNC_SAMPLES);
|
||||||
time_diff_ms += (4 * (time_sync_messages[k].fractions -
|
|
||||||
time_sync_answers[k].fractions));
|
time_diff_frac +=
|
||||||
|
((time_sync_messages[k].fractions - time_sync_answers[k].fractions) / TIME_SYNC_SAMPLES);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "time_diff_sec=%d / time_diff_frac=%d", time_diff_sec,
|
||||||
|
time_diff_frac);
|
||||||
}
|
}
|
||||||
} // for
|
} // for
|
||||||
|
|
||||||
// calculate time offset and set time if necessary
|
// calculate time offset and set time if necessary
|
||||||
time_offset = (time_diff_sec + time_diff_ms / 1000.0f) / TIME_SYNC_SAMPLES;
|
time_diff_ms = 4 * time_diff_frac;
|
||||||
ESP_LOGD(TAG, "Timesync time offset=%.3f", time_offset);
|
time_offset = (time_diff_sec + (long) (time_diff_ms / 1000));
|
||||||
ESP_LOGD(TAG, "Timesync time_diff_ms=%03d", time_diff_ms);
|
|
||||||
|
|
||||||
if (time_offset >= TIME_SYNC_TRIGGER) {
|
ESP_LOGD(TAG, "Timesync time offset=%d", time_offset);
|
||||||
|
|
||||||
|
t = now();
|
||||||
|
|
||||||
|
if (labs(time_offset) >= (t + TIME_SYNC_TRIGGER)) {
|
||||||
// wait until top of second
|
// wait until top of second
|
||||||
if (time_diff_ms > 0) // clock is fast
|
if (time_diff_ms > 0) // clock is fast
|
||||||
vTaskDelay(pdMS_TO_TICKS(time_diff_ms));
|
vTaskDelay(pdMS_TO_TICKS(time_diff_ms));
|
||||||
@ -130,8 +143,8 @@ void process_Servertime_sync_req(void *taskparameter) {
|
|||||||
vTaskDelay(pdMS_TO_TICKS(1000 + time_diff_ms));
|
vTaskDelay(pdMS_TO_TICKS(1000 + time_diff_ms));
|
||||||
|
|
||||||
time_diff_sec++;
|
time_diff_sec++;
|
||||||
time_to_set = time_t(now() + time_diff_sec);
|
time_to_set = t - time_t(time_diff_sec);
|
||||||
ESP_LOGD(TAG, "Time to set = %d", time_to_set);
|
ESP_LOGD(TAG, "Now()=%d, Time to set = %d", t, time_to_set);
|
||||||
|
|
||||||
// adjust system time
|
// adjust system time
|
||||||
if (timeIsValid(time_to_set)) {
|
if (timeIsValid(time_to_set)) {
|
||||||
@ -156,8 +169,9 @@ finish:
|
|||||||
// called from lorawan.cpp after time_sync_req was sent
|
// called from lorawan.cpp after time_sync_req was sent
|
||||||
void store_time_sync_req(time_t secs, uint32_t micros) {
|
void store_time_sync_req(time_t secs, uint32_t micros) {
|
||||||
uint8_t k = time_sync_seqNo % TIME_SYNC_SAMPLES;
|
uint8_t k = time_sync_seqNo % TIME_SYNC_SAMPLES;
|
||||||
time_sync_messages[k].seconds = secs;
|
|
||||||
time_sync_messages[k].fractions = micros / 250; // 4ms resolution
|
time_sync_messages[k].seconds = (uint32_t) secs;
|
||||||
|
time_sync_messages[k].fractions = (uint8_t) (micros / 4000); // 4ms resolution
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Timeserver request #%d sent at %d.%03d", time_sync_seqNo,
|
ESP_LOGD(TAG, "Timeserver request #%d sent at %d.%03d", time_sync_seqNo,
|
||||||
time_sync_messages[k].seconds, time_sync_messages[k].fractions);
|
time_sync_messages[k].seconds, time_sync_messages[k].fractions);
|
||||||
|
Loading…
Reference in New Issue
Block a user