lorawan: add devicetime request support

Add devicetime request support.
Update lorawan sample
Related to Issue #55072

Co-authored-by: Jan Kowalewski <jkowalewski@cthings.co>

Signed-off-by: romain pelletant <romain.pelletant@fullfreqs.com>
Signed-off-by: Jan Kowalewski <jkowalewski@cthings.co>
This commit is contained in:
romain pelletant 2023-08-19 19:26:03 +02:00 committed by Anas Nashif
parent 866905fd6a
commit ae0c1b72cf
4 changed files with 79 additions and 9 deletions

View file

@ -108,6 +108,7 @@ enum lorawan_message_type {
*/ */
enum lorawan_dl_flags { enum lorawan_dl_flags {
LORAWAN_DATA_PENDING = BIT(0), LORAWAN_DATA_PENDING = BIT(0),
LORAWAN_TIME_UPDATED = BIT(1),
}; };
/** /**
@ -378,6 +379,32 @@ void lorawan_get_payload_sizes(uint8_t *max_next_payload_size,
*/ */
int lorawan_set_region(enum lorawan_region region); int lorawan_set_region(enum lorawan_region region);
/**
* @brief Request for time according to DeviceTimeReq MAC cmd
*
* Append MAC DevTimeReq command. It will be processed on next send
* message or force sending empty message to request time immediately.
*
* @param force_request Immediately send an empty message to execute the request
* @return 0 if successful, negative errno otherwise
*/
int lorawan_request_device_time(bool force_request);
/**
* @brief Retrieve the current time from LoRaWAN stack updated by
* DeviceTimeAns on MAC layer.
*
* This function uses the GPS epoch format, as used in all LoRaWAN services.
*
* The GPS epoch started on 1980-01-06T00:00:00Z, but has since diverged
* from UTC, as it does not consider corrections like leap seconds.
*
* @param gps_time Synchronized time in GPS epoch format truncated to 32-bit.
*
* @return 0 if successful, -EAGAIN if the clock is not yet synchronized.
*/
int lorawan_device_time_get(uint32_t *gps_time);
#ifdef CONFIG_LORAWAN_APP_CLOCK_SYNC #ifdef CONFIG_LORAWAN_APP_CLOCK_SYNC
/** /**

View file

@ -27,12 +27,11 @@ LOG_MODULE_REGISTER(lorawan_class_a);
char data[] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}; char data[] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'};
static void dl_callback(uint8_t port, uint8_t flags, static void dl_callback(uint8_t port, uint8_t flags, int16_t rssi, int8_t snr, uint8_t len,
int16_t rssi, int8_t snr, const uint8_t *hex_data)
uint8_t len, const uint8_t *hex_data)
{ {
LOG_INF("Port %d, Pending %d, RSSI %ddB, SNR %ddBm", LOG_INF("Port %d, Pending %d, RSSI %ddB, SNR %ddBm, Time %d", port,
port, flags & LORAWAN_DATA_PENDING, rssi, snr); flags & LORAWAN_DATA_PENDING, rssi, snr, !!(flags & LORAWAN_TIME_UPDATED));
if (hex_data) { if (hex_data) {
LOG_HEXDUMP_INF(hex_data, len, "Payload: "); LOG_HEXDUMP_INF(hex_data, len, "Payload: ");
} }

View file

@ -24,11 +24,10 @@ LOG_MODULE_REGISTER(lorawan_fuota, CONFIG_LORAWAN_SERVICES_LOG_LEVEL);
char data[] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}; char data[] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'};
static void downlink_info(uint8_t port, bool data_pending, int16_t rssi, int8_t snr, static void downlink_info(uint8_t port, uint8_t flags, int16_t rssi, int8_t snr, uint8_t len,
uint8_t len, const uint8_t *data) const uint8_t *data)
{ {
LOG_INF("Received from port %d, pending %d, RSSI %ddB, SNR %ddBm", LOG_INF("Received from port %d, flags %d, RSSI %ddB, SNR %ddBm", port, flags, rssi, snr);
port, data_pending, rssi, snr);
if (data) { if (data) {
LOG_HEXDUMP_INF(data, len, "Payload: "); LOG_HEXDUMP_INF(data, len, "Payload: ");
} }

View file

@ -68,6 +68,7 @@ K_MUTEX_DEFINE(lorawan_send_mutex);
static enum lorawan_datarate default_datarate; static enum lorawan_datarate default_datarate;
static enum lorawan_datarate current_datarate; static enum lorawan_datarate current_datarate;
static bool lorawan_adr_enable; static bool lorawan_adr_enable;
static bool lorawan_device_time_updated_once;
static sys_slist_t dl_callbacks; static sys_slist_t dl_callbacks;
@ -162,9 +163,14 @@ static void mcps_indication_handler(McpsIndication_t *mcps_indication)
if (lorawan_adr_enable) { if (lorawan_adr_enable) {
datarate_observe(false); datarate_observe(false);
} }
/* Save time has been updated at least once */
if (!lorawan_device_time_updated_once && mcps_indication->DeviceTimeAnsReceived) {
lorawan_device_time_updated_once = true;
}
/* IsUplinkTxPending also indicates pending downlinks */ /* IsUplinkTxPending also indicates pending downlinks */
flags |= (mcps_indication->IsUplinkTxPending == 1 ? LORAWAN_DATA_PENDING : 0); flags |= (mcps_indication->IsUplinkTxPending == 1 ? LORAWAN_DATA_PENDING : 0);
flags |= (mcps_indication->DeviceTimeAnsReceived ? LORAWAN_TIME_UPDATED : 0);
/* Iterate over all registered downlink callbacks */ /* Iterate over all registered downlink callbacks */
SYS_SLIST_FOR_EACH_CONTAINER(&dl_callbacks, cb, node) { SYS_SLIST_FOR_EACH_CONTAINER(&dl_callbacks, cb, node) {
@ -202,6 +208,9 @@ static void mlme_confirm_handler(MlmeConfirm_t *mlme_confirm)
/* Not implemented */ /* Not implemented */
LOG_INF("Link check not implemented yet!"); LOG_INF("Link check not implemented yet!");
break; break;
case MLME_DEVICE_TIME:
LOG_INF("DevTimeReq done");
break;
default: default:
break; break;
} }
@ -382,6 +391,42 @@ int lorawan_set_region(enum lorawan_region region)
return 0; return 0;
} }
int lorawan_request_device_time(bool force_request)
{
int ret = 0;
LoRaMacStatus_t status;
MlmeReq_t mlme_req;
mlme_req.Type = MLME_DEVICE_TIME;
status = LoRaMacMlmeRequest(&mlme_req);
if (status != LORAMAC_STATUS_OK) {
LOG_ERR("DeviceTime Req. failed: %s", lorawan_status2str(status));
ret = lorawan_status2errno(status);
return ret;
}
if (force_request) {
ret = lorawan_send(0U, "", 0U, LORAWAN_MSG_UNCONFIRMED);
}
return ret;
}
int lorawan_device_time_get(uint32_t *gps_time)
{
SysTime_t local_time;
__ASSERT(gps_time != NULL, "gps_time parameter is required");
if (lorawan_device_time_updated_once) {
local_time = SysTimeGet();
*gps_time = local_time.Seconds - UNIX_GPS_EPOCH_OFFSET;
return 0;
} else {
return -EAGAIN;
}
}
int lorawan_join(const struct lorawan_join_config *join_cfg) int lorawan_join(const struct lorawan_join_config *join_cfg)
{ {
MibRequestConfirm_t mib_req; MibRequestConfirm_t mib_req;