1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/wakaama/contrib/lwm2m_client.c
2021-08-13 19:50:38 +02:00

205 lines
6.5 KiB
C

/*
* Copyright (C) 2018 Beduino Master Projekt - University of Bremen
* Copyright (C) 2019 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
* @ingroup lwm2m_client
*
* @file
* @brief LwM2M client implementation using Wakaama
*
* @author Christian Manal <manal@uni-bremen.de>
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
* @}
*/
#include <string.h>
#include "timex.h"
#include "liblwm2m.h"
#include "lwm2m_platform.h"
#include "lwm2m_client.h"
#include "lwm2m_client_config.h"
#include "lwm2m_client_connection.h"
#define ENABLE_DEBUG 0
#include "debug.h"
/**
* @brief Determines if there has been a reboot request on the device object
*
* @note This function is implemented in object_device.c
*
* @return true Reboot has been requested
* @return false Reboot has not been requested
*/
bool lwm2m_device_reboot_requested(void);
/**
* @brief Thread with the main loop for receiving packets and stepping the LwM2M
* FSM.
*
* @param arg ignored
*/
static void *_lwm2m_client_run(void *arg);
static char _lwm2m_client_stack[THREAD_STACKSIZE_MAIN +
THREAD_EXTRA_STACKSIZE_PRINTF];
static lwm2m_client_data_t *_client_data;
void lwm2m_client_init(lwm2m_client_data_t *client_data)
{
(void)client_data;
lwm2m_platform_init();
}
lwm2m_context_t *lwm2m_client_run(lwm2m_client_data_t *client_data,
lwm2m_object_t *obj_list[],
uint16_t obj_numof)
{
int res;
_client_data = client_data;
_client_data->local_ep.family = AF_INET6;
_client_data->local_ep.netif = SOCK_ADDR_ANY_NETIF;
/* create sock for UDP server */
_client_data->local_ep.port = atoi(CONFIG_LWM2M_LOCAL_PORT);
if (sock_udp_create(&_client_data->sock, &_client_data->local_ep, NULL, 0)) {
DEBUG("[lwm2m_client_run] Can't create server socket\n");
return NULL;
}
/* initiate LwM2M */
_client_data->lwm2m_ctx = lwm2m_init(_client_data);
if (!_client_data->lwm2m_ctx) {
DEBUG("[lwm2m_client_run] Failed to initiate LwM2M\n");
return NULL;
}
res = lwm2m_configure(_client_data->lwm2m_ctx, CONFIG_LWM2M_DEVICE_NAME, NULL,
CONFIG_LWM2M_ALT_PATH, obj_numof, obj_list);
if (res) {
DEBUG("[lwm2m_client_run] Failed to configure LwM2M\n");
return NULL;
}
_client_data->pid = thread_create(_lwm2m_client_stack,
sizeof(_lwm2m_client_stack),
THREAD_PRIORITY_MAIN - 1,
THREAD_CREATE_STACKTEST,
_lwm2m_client_run,
NULL,
"LwM2M client");
return _client_data->lwm2m_ctx;
}
static void *_lwm2m_client_run(void *arg)
{
(void) arg;
time_t reboot_time = 0;
while (1) {
time_t tv = LWM2M_CLIENT_MIN_REFRESH_TIME;
uint8_t rcv_buf[LWM2M_CLIENT_RCV_BUFFER_SIZE];
ssize_t rcv_len = sizeof(rcv_buf);
sock_udp_ep_t remote;
if (lwm2m_device_reboot_requested()) {
time_t tv_sec;
tv_sec = lwm2m_gettime();
if (0 == reboot_time) {
DEBUG("reboot requested; rebooting in %u seconds\n",
LWM2M_CLIENT_REBOOT_TIME);
reboot_time = tv_sec + LWM2M_CLIENT_REBOOT_TIME;
}
if (reboot_time < tv_sec) {
DEBUG("reboot time expired, rebooting ...\n");
pm_reboot();
}
else {
tv = reboot_time - tv_sec;
}
}
/*
* This function does two things:
* - first it does the work needed by liblwm2m (eg. (re)sending some
* packets).
* - Secondly it adjusts the timeout value (default 60s) depending on the
* state of the transaction
* (eg. retransmission) and the time between the next operation
*/
lwm2m_step(_client_data->lwm2m_ctx, &tv);
DEBUG(" -> State: ");
switch (_client_data->lwm2m_ctx->state) {
case STATE_INITIAL:
DEBUG("STATE_INITIAL\n");
break;
case STATE_BOOTSTRAP_REQUIRED:
DEBUG("STATE_BOOTSTRAP_REQUIRED\n");
break;
case STATE_BOOTSTRAPPING:
DEBUG("STATE_BOOTSTRAPPING\n");
break;
case STATE_REGISTER_REQUIRED:
DEBUG("STATE_REGISTER_REQUIRED\n");
break;
case STATE_REGISTERING:
DEBUG("STATE_REGISTERING\n");
break;
case STATE_READY:
DEBUG("STATE_READY\n");
if (tv > LWM2M_CLIENT_MIN_REFRESH_TIME) {
tv = LWM2M_CLIENT_MIN_REFRESH_TIME;
}
break;
default:
DEBUG("Unknown...\n");
break;
}
sock_udp_ep_t local;
int res = sock_udp_get_local(&_client_data->sock, &local);
assert(res >= 0);
DEBUG("Waiting for UDP packet on port: %d\n", local.port);
rcv_len = sock_udp_recv(&_client_data->sock, rcv_buf, sizeof(rcv_buf),
tv * US_PER_SEC, &remote);
DEBUG("sock_udp_recv()\n");
if (rcv_len > 0) {
DEBUG("Finding connection\n");
lwm2m_client_connection_t *conn = lwm2m_client_connection_find(
_client_data->conn_list, &remote);
if (conn) {
DEBUG("lwm2m_connection_handle_packet(%i)\n", (int)rcv_len);
int result = lwm2m_connection_handle_packet(conn, rcv_buf,
rcv_len,
_client_data);
if (0 != result) {
DEBUG("error handling message %i\n", result);
}
}
else {
DEBUG("Could not find incoming connection\n");
}
}
else if ((rcv_len < 0) &&
((rcv_len != -EAGAIN) && (rcv_len != -ETIMEDOUT))) {
DEBUG("Unexpected sock_udp_recv error code %i\n", (int)rcv_len);
}
else {
DEBUG("UDP error code: %i\n", (int)rcv_len);
}
}
return NULL;
}