New 5-byte time sync protocol
This commit is contained in:
parent
11f184e67a
commit
dd661254b5
@ -7,11 +7,11 @@
|
||||
#include "timekeeper.h"
|
||||
|
||||
//#define TIME_SYNC_TRIGGER 100 // threshold for time sync [milliseconds]
|
||||
#define TIME_SYNC_FRAME_LENGTH 0x06 // timeserver answer frame length [bytes]
|
||||
#define TIME_SYNC_FRAME_LENGTH 0x05 // timeserver answer frame length [bytes]
|
||||
#define TIME_SYNC_FIXUP 6 // calibration to fixup processing time [milliseconds]
|
||||
|
||||
void send_timesync_req(void);
|
||||
int recv_timesync_ans(uint8_t buf[], uint8_t buf_len);
|
||||
int recv_timesync_ans(uint8_t seq_no, uint8_t buf[], uint8_t buf_len);
|
||||
void process_timesync_req(void *taskparameter);
|
||||
void store_time_sync_req(uint32_t t_millisec);
|
||||
void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec);
|
||||
|
File diff suppressed because one or more lines are too long
@ -256,16 +256,24 @@ void onEvent(ev_t ev) {
|
||||
sprintf(display_line6, "RSSI %d SNR %d", LMIC.rssi, LMIC.snr / 4);
|
||||
|
||||
if (LMIC.txrxFlags & TXRX_PORT) { // FPort -> use to switch
|
||||
|
||||
switch (LMIC.frame[LMIC.dataBeg - 1]) {
|
||||
#if (TIME_SYNC_LORASERVER)
|
||||
case TIMEPORT: // timesync answer -> call timesync processor
|
||||
recv_timesync_ans(LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case RCMDPORT: // opcode -> call rcommand interpreter
|
||||
rcommand(LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
|
||||
break;
|
||||
|
||||
default: // unknown port -> display info
|
||||
|
||||
#if (TIME_SYNC_LORASERVER)
|
||||
// timesync answer -> call timesync processor
|
||||
if ((LMIC.frame[LMIC.dataBeg - 1] >= TIMEANSWERPORT_MIN) &&
|
||||
(LMIC.frame[LMIC.dataBeg - 1] <= TIMEANSWERPORT_MAX)) {
|
||||
recv_timesync_ans(LMIC.frame[LMIC.dataBeg - 1],
|
||||
LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Received data on unsupported port #%d",
|
||||
LMIC.frame[LMIC.dataBeg - 1]);
|
||||
break;
|
||||
|
@ -91,7 +91,9 @@
|
||||
#define BEACONPORT 6 // beacon alarms
|
||||
#define BMEPORT 7 // BME680 sensor
|
||||
#define BATTPORT 8 // battery voltage
|
||||
#define TIMEPORT 9 // time
|
||||
#define TIMEPORT 9 // time query
|
||||
#define TIMEANSWERPORT_MIN 0xA0 // time answer, start of port range
|
||||
#define TIMEANSWERPORT_MAX 0xDF // time answer, end of port range
|
||||
#define SENSOR1PORT 10 // user sensor #1
|
||||
#define SENSOR2PORT 11 // user sensor #2
|
||||
#define SENSOR3PORT 12 // user sensor #3
|
||||
|
@ -20,7 +20,7 @@ static const char TAG[] = __FILE__;
|
||||
|
||||
TaskHandle_t timeSyncReqTask;
|
||||
|
||||
static uint8_t time_sync_seqNo = 0;
|
||||
static uint8_t time_sync_seqNo = TIMEANSWERPORT_MIN;
|
||||
static bool lora_time_sync_pending = false;
|
||||
|
||||
typedef std::chrono::system_clock myClock;
|
||||
@ -75,9 +75,6 @@ void process_timesync_req(void *taskparameter) {
|
||||
// enqueue timestamp samples in lora sendqueue
|
||||
for (uint8_t i = 0; i < TIME_SYNC_SAMPLES; i++) {
|
||||
|
||||
// wrap around seqNo 0 .. 254
|
||||
time_sync_seqNo = (time_sync_seqNo < 255) ? time_sync_seqNo + 1 : 0;
|
||||
|
||||
// send sync request to server
|
||||
payload.reset();
|
||||
payload.addByte(time_sync_seqNo);
|
||||
@ -96,6 +93,11 @@ void process_timesync_req(void *taskparameter) {
|
||||
time_offset_ms += time_point_cast<milliseconds>(time_sync_rx[k]) -
|
||||
time_point_cast<milliseconds>(time_sync_tx[k]);
|
||||
|
||||
// wrap around seqNo keeping it in time port range
|
||||
time_sync_seqNo = (time_sync_seqNo < TIMEANSWERPORT_MAX)
|
||||
? time_sync_seqNo + 1
|
||||
: TIMEANSWERPORT_MIN;
|
||||
|
||||
if (i < TIME_SYNC_SAMPLES - 1) {
|
||||
// wait until next cycle
|
||||
vTaskDelay(pdMS_TO_TICKS(TIME_SYNC_CYCLE * 1000));
|
||||
@ -149,19 +151,21 @@ error:
|
||||
// called from lorawan.cpp after time_sync_req was sent
|
||||
void store_time_sync_req(uint32_t timestamp) {
|
||||
|
||||
uint8_t k = time_sync_seqNo % TIME_SYNC_SAMPLES;
|
||||
if (lora_time_sync_pending) {
|
||||
|
||||
uint8_t k = time_sync_seqNo % TIME_SYNC_SAMPLES;
|
||||
time_sync_tx[k] += milliseconds(timestamp);
|
||||
|
||||
ESP_LOGD(TAG, "[%0.3f] Timesync request #%d sent at %d.%03d",
|
||||
millis() / 1000.0, time_sync_seqNo, timestamp / 1000,
|
||||
timestamp % 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// process timeserver timestamp answer, called from lorawan.cpp
|
||||
int recv_timesync_ans(uint8_t buf[], uint8_t buf_len) {
|
||||
int recv_timesync_ans(uint8_t seq_no, uint8_t buf[], uint8_t buf_len) {
|
||||
|
||||
// if no timesync handshake is pending or spurious buffer then exit
|
||||
// if no timesync handshake is pending then exit
|
||||
if (!lora_time_sync_pending)
|
||||
return 0; // failure
|
||||
|
||||
@ -178,18 +182,18 @@ int recv_timesync_ans(uint8_t buf[], uint8_t buf_len) {
|
||||
|
||||
else { // we received a probably valid time frame
|
||||
|
||||
uint8_t seq_no = buf[0], k = seq_no % TIME_SYNC_SAMPLES;
|
||||
uint8_t k = seq_no % TIME_SYNC_SAMPLES;
|
||||
uint16_t timestamp_msec; // convert 1/250th sec fractions to ms
|
||||
uint32_t timestamp_sec;
|
||||
|
||||
// fetch timeserver time from 4 bytes containing the UTC seconds since
|
||||
// unix epoch. Octet order is big endian. Casts are necessary, because buf
|
||||
// is an array of single byte values, and they might overflow when shifted
|
||||
timestamp_sec = ((uint32_t)buf[4]) | (((uint32_t)buf[3]) << 8) |
|
||||
(((uint32_t)buf[2]) << 16) | (((uint32_t)buf[1]) << 24);
|
||||
timestamp_sec = ((uint32_t)buf[3]) | (((uint32_t)buf[2]) << 8) |
|
||||
(((uint32_t)buf[1]) << 16) | (((uint32_t)buf[0]) << 24);
|
||||
|
||||
// the 5th byte contains the fractional seconds in 2^-8 second steps
|
||||
timestamp_msec = 4 * buf[5];
|
||||
timestamp_msec = 4 * buf[4];
|
||||
|
||||
// construct the timepoint when message was seen on gateway
|
||||
time_sync_rx[k] += seconds(timestamp_sec) + milliseconds(timestamp_msec);
|
||||
|
Loading…
Reference in New Issue
Block a user