1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

examples/gcoap: add observable /rtc resource to monitor RIOT epoch

This commit is contained in:
Fabian Hüßler 2024-06-05 21:01:41 +02:00
parent a2a7f41a59
commit f45ab68d04
2 changed files with 73 additions and 0 deletions

View File

@ -54,6 +54,9 @@ USEMODULE += shell_cmds_default
USEMODULE += uri_parser
USEMODULE += ps
# /rtc resource for regular observe notifications
FEATURES_OPTIONAL += periph_rtc
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
@ -81,6 +84,13 @@ DOCKER_ENV_VARS += ZEP_PORT_BASE
include $(RIOTBASE)/Makefile.include
ifneq (,$(filter periph_rtc,$(USEMODULE)))
USEMODULE += event_periodic
USEMODULE += event_periodic_callback
USEMODULE += event_thread
USEMODULE += ztimer_msec
endif
# For now this goes after the inclusion of Makefile.include so Kconfig symbols
# are available. Only set configuration via CFLAGS if Kconfig is not being used
# for this module.

View File

@ -23,11 +23,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "event/periodic_callback.h"
#include "event/thread.h"
#include "fmt.h"
#include "net/gcoap.h"
#include "net/utils.h"
#include "od.h"
#include "periph/rtc.h"
#include "time_units.h"
#include "gcoap_example.h"
@ -60,11 +65,17 @@ static ssize_t _encode_link(const coap_resource_t *resource, char *buf,
size_t maxlen, coap_link_encoder_ctx_t *context);
static ssize_t _stats_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, coap_request_ctx_t *ctx);
static ssize_t _riot_board_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, coap_request_ctx_t *ctx);
#if IS_USED(MODULE_PERIPH_RTC)
static ssize_t _rtc_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, coap_request_ctx_t *ctx);
#endif
/* CoAP resources. Must be sorted by path (ASCII order). */
static const coap_resource_t _resources[] = {
{ "/cli/stats", COAP_GET | COAP_PUT, _stats_handler, NULL },
{ "/riot/board", COAP_GET, _riot_board_handler, NULL },
#if IS_USED(MODULE_PERIPH_RTC)
{ "/rtc", COAP_GET, _rtc_handler, NULL },
#endif
};
static const char *_link_params[] = {
@ -100,6 +111,53 @@ static ssize_t _encode_link(const coap_resource_t *resource, char *buf,
return res;
}
#if IS_USED(MODULE_PERIPH_RTC)
static void _rtc_notify_observers(void *arg)
{
(void)arg;
struct tm tm_now;
if (rtc_get_time(&tm_now)) {
DEBUG_PUTS("gcoap_server: RTC error");
return;
}
size_t len;
char str_time[20] = "";
uint8_t buf[sizeof(coap_hdr_t) + COAP_TOKEN_LENGTH_MAX + 1 + sizeof(str_time)];
coap_pkt_t pdu;
switch (gcoap_obs_init(&pdu, buf, sizeof(buf), &_resources[2])) {
case GCOAP_OBS_INIT_OK:
len = coap_opt_finish(&pdu, COAP_OPT_FINISH_PAYLOAD);
memcpy(pdu.payload, str_time, strftime(str_time, sizeof(str_time), "%Y-%m-%d %H:%M:%S", &tm_now));
pdu.payload_len = strlen(str_time);
len += pdu.payload_len;
if (!gcoap_obs_send(buf, len, &_resources[2])) {
DEBUG_PUTS("gcoap_server: cannot send /rtc notification");
}
break;
case GCOAP_OBS_INIT_UNUSED:
DEBUG_PUTS("gcoap_server: no observer for /rtc");
break;
case GCOAP_OBS_INIT_ERR:
DEBUG_PUTS("gcoap_server: error initializing /rtc notification");
break;
}
}
static ssize_t _rtc_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, coap_request_ctx_t *ctx)
{
(void)ctx;
struct tm tm_now;
rtc_get_time(&tm_now);
gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
size_t resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);
char str_time[20] = "";
memcpy(pdu->payload, str_time, strftime(str_time, sizeof(str_time), "%Y-%m-%d %H:%M:%S", &tm_now));
pdu->payload_len = strlen(str_time);
resp_len += pdu->payload_len;
return resp_len;
}
#endif
/*
* Server callback for /cli/stats. Accepts either a GET or a PUT.
*
@ -202,4 +260,9 @@ void server_init(void)
#endif
gcoap_register_listener(&_listener);
#if IS_USED(MODULE_PERIPH_RTC)
static event_periodic_callback_t _ev_pcb_rtc;
event_periodic_callback_init(&_ev_pcb_rtc, ZTIMER_MSEC, EVENT_PRIO_MEDIUM, _rtc_notify_observers, NULL);
event_periodic_callback_start(&_ev_pcb_rtc, 10 * MS_PER_SEC);
#endif
}