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

pkg/wakaama: Add LwM2M Client implementation

This commit is contained in:
Leandro Lanzieri 2019-11-29 17:54:08 +01:00
parent 2826779fbf
commit c52ad2df9e
18 changed files with 1866 additions and 10 deletions

View File

@ -88,6 +88,7 @@ PSEUDOMODULES += stdio_ethos
PSEUDOMODULES += stdio_cdc_acm
PSEUDOMODULES += stdio_uart_rx
PSEUDOMODULES += suit_%
PSEUDOMODULES += wakaama_objects_%
# handle suit_v4 being a distinct module
NO_PSEUDOMODULES += suit_v4

View File

@ -6,17 +6,20 @@ PKG_LICENSE=EDL-1.0,EPL-1.0
.PHONY: all
all: patch
"$(MAKE)" -C $(PKG_BUILDDIR)/riotbuild
"$(MAKE)" -C $(PKG_BUILDDIR)
patch: git-download
mkdir -p "$(PKG_BUILDDIR)/riotbuild"
cp $(PKG_BUILDDIR)/core/*.c $(PKG_BUILDDIR)/core/*.h $(PKG_BUILDDIR)/riotbuild
cp $(PKG_BUILDDIR)/core/er-coap-13/*.c $(PKG_BUILDDIR)/core/er-coap-13/*.h $(PKG_BUILDDIR)/riotbuild
cp $(PKG_BUILDDIR)/examples/client/object_server.c $(PKG_BUILDDIR)/riotbuild
cp $(PKG_BUILDDIR)/examples/client/object_security.c $(PKG_BUILDDIR)/riotbuild
cp $(PKG_BUILDDIR)/examples/client/object_access_control.c $(PKG_BUILDDIR)/riotbuild
mkdir -p "$(PKG_BUILDDIR)"
# copy the Wakaama core files
cp $(PKG_BUILDDIR)/core/*.c $(PKG_BUILDDIR)/core/*.h $(PKG_BUILDDIR)
# copy the coap implementation from Wakaama
cp $(PKG_BUILDDIR)/core/er-coap-13/*.c $(PKG_BUILDDIR)/core/er-coap-13/*.h $(PKG_BUILDDIR)
# copy the mandatory objects, implemented on Wakaama examples
cp $(PKG_BUILDDIR)/examples/client/object_server.c $(PKG_BUILDDIR)
cp $(PKG_BUILDDIR)/examples/client/object_security.c $(PKG_BUILDDIR)
cp $(PKG_BUILDDIR)/examples/client/object_access_control.c $(PKG_BUILDDIR)
echo 'MODULE:=wakaama' > $(PKG_BUILDDIR)/riotbuild/Makefile
echo 'include $$(RIOTBASE)/Makefile.base' >> $(PKG_BUILDDIR)/riotbuild/Makefile
echo 'MODULE:=wakaama' > $(PKG_BUILDDIR)/Makefile
echo 'include $$(RIOTBASE)/Makefile.base' >> $(PKG_BUILDDIR)/Makefile
include $(RIOTBASE)/pkg/pkg.mk

17
pkg/wakaama/Makefile.dep Normal file
View File

@ -0,0 +1,17 @@
# include contrib code (platform adaption and client implementation)
USEMODULE += wakaama_contrib
# this allows us to include our own objects, implemented in the 'objects'
# folder, by adding 'wakaama_objects_<objectName>' modules
USEMODULE += wakaama_objects
# include the 'device' object implementation (mandatory)
USEMODULE += wakaama_objects_device
USEMODULE += xtimer
USEPKG += tlsf
# If logs for the package are active, we need fmt
ifneq (,$(filter -DLWM2M_WITH_LOGS,$(CFLAGS)))
USEMODULE += fmt
endif

View File

@ -1 +1,4 @@
INCLUDES += -I$(PKGDIRBASE)/wakaama/riotbuild
DIRS += $(RIOTBASE)/pkg/wakaama/contrib
INCLUDES += -I$(RIOTBASE)/pkg/wakaama/include
INCLUDES += -I$(PKGDIRBASE)/wakaama

View File

@ -0,0 +1,5 @@
MODULE := wakaama_contrib
DIRS += $(RIOTBASE)/pkg/wakaama/contrib/objects
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,200 @@
/*
* 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 "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(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, LWM2M_DEVICE_NAME, NULL,
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;
}
DEBUG("Waiting for UDP packet on port: %d\n", _client_data->sock.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(%d)\n", rcv_len);
int result = lwm2m_connection_handle_packet(conn, rcv_buf,
rcv_len,
_client_data);
if (0 != result) {
DEBUG("error handling message %d\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", rcv_len);
}
else {
DEBUG("UDP error code: %d\n", rcv_len);
}
}
return NULL;
}

View File

@ -0,0 +1,452 @@
/*******************************************************************************
*
* Copyright (c) 2015 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* The Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* David Navarro, Intel Corporation - initial API and implementation
* Christian Renz - Please refer to git log
* Christian Manal - Ported to RIOT OS
*
*******************************************************************************/
/*
* 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 Connection handle for LwM2M client implementation using Wakaama
*
* @author Christian Manal <manal@uni-bremen.de>
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
* @}
*/
#include <stddef.h>
#include "kernel_defines.h"
#include "net/netif.h"
#include "liblwm2m.h"
#include "lwm2m_client.h"
#include "lwm2m_client_config.h"
#include "lwm2m_client_connection.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define URI_LENGTH 256
/**
* @brief Creates a new connection object based on the security instance
* represented by @p instance_id.
*
* @param[in] instance_id ID number of the instance of security object
* @param[in, out] client_data LwM2M client data
*
* @return Pointer to the new connection
*/
static lwm2m_client_connection_t *_connection_create(int instance_id,
lwm2m_client_data_t *client_data);
/**
* @brief Gets the URI from an @p instance_id of a @p obj security object
*
* @param[in] obj security object
* @param[in] instance_id ID number of the instance of security object
* @param[out] uri_buffer buffer to place the URI
* @param[in] buffer_size size of @p uri_buffer
*
* @return Pointer to the URI in success
* @return NULL otherwise
*/
static char *_get_uri_from_security_obj(lwm2m_object_t *obj, int instance_id,
char *uri_buffer, int buffer_size);
/**
* @brief Sends data with a specified connection @p conn
*
* @param[in] conn connection to use to send data
* @param[in] buffer data to send
* @param[in] buffer_size size of @p buffer
* @param[in] client_data LwM2M client data
*
* @return 0 on success
* @return -1 otherwise
*/
static int _connection_send(lwm2m_client_connection_t *conn, uint8_t *buffer,
size_t buffer_size,
lwm2m_client_data_t *client_data);
/**
* @brief Parses the schema of a given URI and sets the default port for the
* found valid schema
* @param[in] uri URI string to parse
* @param[out] port will point to the default port string
* @param[in] instance_id instance ID of the connection
*
* @return pointer to the character after the schema, if found
* @return NULL if no valid schema found
*/
static char *_parse_schema(char *uri, char **port, int instance_id);
/**
* @brief Parses the host and the port part after the schema
*
* @param[in, out] host pointer to the beginning of the host
* @param[out] port pointer to store the position of the port
* @param[in] default_port default port
*/
static void _parse_host_and_port(char **host, char **port, char *default_port);
/**
* @brief Tries to find an interface in the host string. If not, it will check
* if there only exists one interface, and will use it
* @param[in] host host string
*
* @return pointer to the interface to use on success
* @return NULL on error
*/
static netif_t *_get_interface(char *host);
/**
* @brief Sets a given interface to a given UDP endpoint
*
* @param[out] ep UDP endpoint
* @param[in] netif Network interface to assign
*/
static void _set_interface(sock_udp_ep_t *ep, const netif_t *netif);
void *lwm2m_connect_server(uint16_t sec_obj_inst_id, void *user_data)
{
lwm2m_client_data_t *client_data = (lwm2m_client_data_t *)user_data;
lwm2m_list_t *instance;
lwm2m_client_connection_t *new_conn = NULL;
/* get the security object instance */
instance = LWM2M_LIST_FIND(client_data->obj_security->instanceList,
sec_obj_inst_id);
if (instance == NULL) {
DEBUG("[lwm2m_connect_server] Could not find sec object instance\n");
return NULL;
}
new_conn = _connection_create(instance->id, client_data);
if (new_conn) {
DEBUG("[lwm2m_connect_server] Connection created\n");
/* if the connections list is empty this is the first node, if not
* attach to the last one */
if (!client_data->conn_list) {
client_data->conn_list = new_conn;
}
else {
lwm2m_client_connection_t *last = client_data->conn_list;
while (last->next != NULL) {
last = last->next;
}
last->next = new_conn;
}
}
return new_conn;
}
void lwm2m_close_connection(void *sessionH, void *user_data)
{
lwm2m_client_connection_t *conn = (lwm2m_client_connection_t *) sessionH;
lwm2m_client_data_t *client_data = (lwm2m_client_data_t *) user_data;
if (conn == client_data->conn_list) {
client_data->conn_list = conn->next;
}
else {
lwm2m_client_connection_t *prev = client_data->conn_list;
while(prev != NULL && prev->next != conn) {
prev = prev->next;
}
if (prev != NULL) {
prev->next = conn->next;
lwm2m_free(conn);
}
}
}
bool lwm2m_session_is_equal(void *session1, void *session2, void *user_data)
{
(void)user_data;
lwm2m_client_connection_t *conn_1 = (lwm2m_client_connection_t *)session1;
lwm2m_client_connection_t *conn_2 = (lwm2m_client_connection_t *)session2;
return ((conn_1->remote.port == conn_2->remote.port) &&
ipv6_addr_equal((ipv6_addr_t *)&(conn_1->remote.addr.ipv6),
(ipv6_addr_t *)&(conn_2->remote.addr.ipv6)));
}
uint8_t lwm2m_buffer_send(void *sessionH, uint8_t *buffer, size_t length,
void *userdata)
{
lwm2m_client_data_t *client_data = (lwm2m_client_data_t *)userdata;
lwm2m_client_connection_t *conn = (lwm2m_client_connection_t *)sessionH;
if (!conn) {
DEBUG("[lwm2m_buffer_send] Failed to send, missing connection\n");
return COAP_500_INTERNAL_SERVER_ERROR;
}
if (_connection_send(conn, buffer, length, client_data)) {
DEBUG("[lwm2m_buffer_send] Failed to send\n");
return COAP_500_INTERNAL_SERVER_ERROR;
}
return COAP_NO_ERROR;
}
lwm2m_client_connection_t *lwm2m_client_connection_find(
lwm2m_client_connection_t *conn_list,
const sock_udp_ep_t *remote)
{
lwm2m_client_connection_t *conn = conn_list;
char ip[128];
uint8_t ip_len = 128;
ipv6_addr_to_str(ip, (ipv6_addr_t *)&remote->addr.ipv6, ip_len);
DEBUG("Looking for connection from [%s]:%d\n", ip, remote->port);
if (conn_list == NULL) {
DEBUG("Conn list is null!");
}
while(conn != NULL) {
ipv6_addr_to_str(ip, (ipv6_addr_t *)&conn->remote.addr.ipv6, ip_len);
DEBUG("Comparing to [%s]:%d\n", ip, conn->remote.port);
if ((conn->remote.port == remote->port) &&
ipv6_addr_equal((ipv6_addr_t *)&(conn->remote.addr.ipv6),
(ipv6_addr_t *)&(remote->addr.ipv6))) {
break;
}
conn = conn->next;
}
return conn;
}
int lwm2m_connection_handle_packet(lwm2m_client_connection_t *conn,
uint8_t *buffer, size_t num_bytes,
lwm2m_client_data_t *client_data)
{
lwm2m_handle_packet(client_data->lwm2m_ctx, buffer, num_bytes, conn);
return 0;
}
static int _connection_send(lwm2m_client_connection_t *conn, uint8_t *buffer,
size_t buffer_size,
lwm2m_client_data_t *client_data)
{
ssize_t sent_bytes = sock_udp_send(&(client_data->sock), buffer,
buffer_size, &(conn->remote));
if (sent_bytes <= 0) {
DEBUG("[_connection_send] Could not send UDP packet: %d\n", sent_bytes);
return -1;
}
conn->last_send = lwm2m_gettime();
return 0;
}
static char *_parse_schema(char *uri, char **port, int instance_id)
{
char *host = NULL;
if (!uri) {
DEBUG("[_parse_schema] Could not get URI of instance\n");
goto out;
}
/* parse the URI in the form "coaps://[host]:port" */
if (!strncmp(uri, SCHEME_COAPS, sizeof(SCHEME_COAPS) - 1)) {
host = uri + sizeof(SCHEME_COAPS) - 1;
}
else if (!strncmp(uri, SCHEME_COAP, sizeof(SCHEME_COAP) - 1)) {
host = uri + sizeof(SCHEME_COAP) - 1;
}
*port = (IS_ACTIVE(LWM2M_BOOTSTRAP) && !instance_id) ?
LWM2M_BSSERVER_PORT : LWM2M_STANDARD_PORT;
out:
return host;
}
static void _parse_host_and_port(char **host, char **port, char *default_port)
{
char *_port = NULL;
char *pos = *host;
if (pos[0] == '[') {
(*host)++;
pos = strrchr(pos, ']');
}
_port = strrchr(pos, ':');
if (!_port) {
*pos = '\0';
DEBUG("[_parse_port] No port specified, using default\n");
_port = default_port;
}
else {
*(_port - 1) = '\0';
_port++;
}
*port = _port;
}
static void _set_interface(sock_udp_ep_t *ep, const netif_t *netif)
{
if (netif == NULL || ep == NULL) {
return;
}
/* currently there is no way to assign a network interface to a sock
* endpoint by means of a generic API, so we need to check */
if (IS_USED(MODULE_GNRC_NETIF)) {
const gnrc_netif_t *gnrc_netif = (gnrc_netif_t *)netif;
ep->netif = (uint16_t)gnrc_netif->pid;
}
}
static netif_t *_get_interface(char *host)
{
netif_t *netif = NULL;
char *iface = ipv6_addr_split_iface(host);
if (iface == NULL) {
/* get the number of net interfaces */
unsigned netif_numof = 0;
while ((netif = netif_iter(netif)) != NULL) {
netif_numof++;
}
/* if we only have one interface use that one */
if (netif_numof == 1) {
netif = netif_iter(NULL);
}
else {
DEBUG("[_connection_create] No iface for link-local address\n");
}
}
else {
netif = netif_get_by_name(iface);
}
return netif;
}
static lwm2m_client_connection_t *_connection_create(int instance_id,
lwm2m_client_data_t *client_data)
{
lwm2m_client_connection_t *conn = NULL;
char *default_port;
char *host;
char *port;
char *uri;
char uri_buf[URI_LENGTH + 1];
memset(uri_buf, 0, sizeof(uri_buf));
DEBUG("Creating connection\n");
/* get the server URI from the requested instance */
uri = _get_uri_from_security_obj(client_data->obj_security, instance_id,
uri_buf, sizeof(uri_buf) - 1);
host = _parse_schema(uri, &default_port, instance_id);
if (!host) {
DEBUG("[_connection_create] Could not parse URI schema\n");
goto free_out;
}
_parse_host_and_port(&host, &port, default_port);
DEBUG("[_connection_create] Creating connection to Host: %s, Port: %s\n",
host, port);
/* allocate new connection */
conn = lwm2m_malloc(sizeof(lwm2m_client_connection_t));
if (!conn) {
DEBUG("[_connection_create] Could not allocate new connection\n");
goto out;
}
conn->next = client_data->conn_list;
/* configure to any IPv6 */
conn->remote.family = AF_INET6;
conn->remote.netif = SOCK_ADDR_ANY_NETIF;
conn->remote.port = atoi(port);
if (!ipv6_addr_from_str((ipv6_addr_t *)&conn->remote.addr.ipv6, host)) {
DEBUG("[_connection_create] IPv6 address malformed\n");
goto free_out;
}
if (ipv6_addr_is_unspecified((const ipv6_addr_t *)&conn->remote.addr.ipv6)) {
DEBUG("[_connection_create] Invalid server address ([::])\n");
goto free_out;
}
/* If the address is a link-local one first check if interface is specified,
* if not, check the number of interfaces and default to the first if there
* is only one defined. */
if (ipv6_addr_is_link_local((ipv6_addr_t *)&conn->remote.addr.ipv6)) {
netif_t *netif = _get_interface(host);
if (netif == NULL) {
goto free_out;
}
else {
_set_interface(&conn->remote, netif);
}
}
conn->last_send = lwm2m_gettime();
goto out;
free_out:
lwm2m_free(conn);
conn = NULL;
out:
return conn;
}
static char *_get_uri_from_security_obj(lwm2m_object_t *obj, int instance_id,
char *uri_buffer, int buffer_size)
{
int size = 1;
char *res = NULL;
/* allocate a data instance */
lwm2m_data_t *data = lwm2m_data_new(size);
/* get the uri from the security object */
data->id = 0;
obj->readFunc(instance_id, &size, &data, obj);
if (data != NULL && data->type == LWM2M_TYPE_STRING &&
data->value.asBuffer.length > 0) {
if ((size_t)buffer_size > data->value.asBuffer.length) {
strncpy(uri_buffer, (char *)data->value.asBuffer.buffer,
data->value.asBuffer.length);
res = uri_buffer;
}
}
lwm2m_data_free(size, data);
return res;
}

View File

@ -0,0 +1,71 @@
/*
* 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 Helper functions to interact with the basic objects provided by
* Wakaama from a LwM2M client.
*
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
* @}
*/
#include "kernel_defines.h"
#include "lwm2m_client.h"
#include "lwm2m_client_config.h"
#include "lwm2m_client_objects.h"
/* These functions are defined by the objects (object_security.c and
* object_server.c are implemented by the Wakaama package. device.c can be
* found in 'contrib/objects') */
lwm2m_object_t *get_security_object(int server_id, const char *server_uri,
char *bs_psk_id, char *psk,
uint16_t psk_len, bool is_bootstrap);
lwm2m_object_t *get_server_object(int server_id, const char *binding,
int lifetime, bool storing);
lwm2m_object_t *lwm2m_get_object_device(void);
lwm2m_object_t *lwm2m_client_get_security_object(
lwm2m_client_data_t *client_data)
{
lwm2m_object_t *ret;
char *server_uri = LWM2M_SERVER_URI;
int server_id = LWM2M_SERVER_ID;
uint16_t psk_len = -1;
char *psk_buffer = NULL;
char *psk_id = NULL;
ret = get_security_object(server_id, server_uri, psk_id, psk_buffer,
psk_len, IS_ACTIVE(LWM2M_BOOTSTRAP));
client_data->obj_security = ret;
return ret;
}
lwm2m_object_t *lwm2m_client_get_server_object(
lwm2m_client_data_t *client_data)
{
(void)client_data;
lwm2m_object_t *ret;
int server_id = LWM2M_SERVER_ID;
int lifetime = LWM2M_DEVICE_TTL;
ret = get_server_object(server_id, LWM2M_DEVICE_BINDINGS, lifetime, false);
return ret;
}
lwm2m_object_t *lwm2m_client_get_device_object(
lwm2m_client_data_t *client_data)
{
(void)client_data;
return lwm2m_get_object_device();
}

View File

@ -0,0 +1,122 @@
/*******************************************************************************
*
* Copyright (c) 2013, 2014, 2015 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* The Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* David Navarro, Intel Corporation - initial API and implementation
* Christian Manal - Ported to RIOT OS
*******************************************************************************/
/**
* Copyright (C) 2018 Beduino Master Projekt - University of Bremen
* 2019 HAW Hamburg
* @{
* @ingroup pkg_wakaama
*
* @file
* @brief Platform adaption for Wakaama package
*
* @author Christian Manal <manal@uni-bremen.de>
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
* @}
*/
#include <liblwm2m.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xtimer.h"
#include "tlsf.h"
#include "lwm2m_platform.h"
#include "lwm2m_client_config.h"
static uint32_t _tlsf_heap[(LWM2M_TLSF_BUFFER / sizeof(uint32_t))];
static tlsf_t _tlsf;
typedef struct {
unsigned free; /**< total free size */
unsigned used; /**< total used size */
} _tlsf_size_container_t;
static void _tlsf_size_walker(void* ptr, size_t size, int used, void* user)
{
printf("\t%p %s size: %u (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, ptr);
if (used) {
((_tlsf_size_container_t *)user)->used += (unsigned int)size;
}
else {
((_tlsf_size_container_t *)user)->free += (unsigned int)size;
}
}
void lwm2m_tlsf_status(void)
{
puts("\nTLSF usage:");
_tlsf_size_container_t sizes = { .free = 0, .used = 0 };
tlsf_walk_pool(tlsf_get_pool(_tlsf), _tlsf_size_walker, &sizes);
printf("\tTotal free size: %u\n", sizes.free);
printf("\tTotal used size: %u\n", sizes.used);
}
void lwm2m_platform_init(void)
{
_tlsf = tlsf_create_with_pool(_tlsf_heap, sizeof(_tlsf_heap));
}
void *lwm2m_malloc(size_t s)
{
return tlsf_malloc(_tlsf, s);
}
void lwm2m_free(void *p)
{
tlsf_free(_tlsf, p);
}
char *lwm2m_strdup(const char *str)
{
size_t len = strlen(str) + 1;
void *new = lwm2m_malloc(len);
if (new == NULL) {
return NULL;
}
return strncpy(new, str, len);
}
int lwm2m_strncmp(const char *s1, const char *s2, size_t n)
{
return strncmp(s1, s2, n);
}
time_t lwm2m_gettime(void)
{
return (time_t)(xtimer_now_usec64() / US_PER_SEC);
}
/* For clang we need to specify that the first argument will be a format string
* for print
*/
__attribute__((__format__ (__printf__, 1, 0)))
void lwm2m_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
}

View File

@ -0,0 +1,5 @@
MODULE := wakaama_objects
SUBMODULES = 1
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,312 @@
/*
* Copyright (C) 2018 Beduino Master Projekt - University of Bremen
*
* 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_objects_device
*
* @file
* @brief Device object implementation for LwM2M client using Wakaama
*
* @author Christian Manal <manal@uni-bremen.de>
* @}
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "liblwm2m.h"
#include "objects/device.h"
#include "lwm2m_client_config.h"
/* Set to true if reboot requested. */
static bool reboot;
/* Lookup table for static resources of device object */
static const char *_static_resources[] = {
[LWM2M_RES_MANUFACTURER] = LWM2M_DEVICE_MANUFACTURER,
[LWM2M_RES_MODEL_NO] = LWM2M_DEVICE_MODEL,
[LWM2M_RES_SERIAL] = LWM2M_DEVICE_SERIAL,
[LWM2M_RES_FW_VER] = LWM2M_DEVICE_FW_VERSION,
[LWM2M_RES_BINDINGS] = LWM2M_DEVICE_BINDINGS,
[LWM2M_RES_TYPE] = LWM2M_DEVICE_TYPE,
[LWM2M_RES_HW_VERSION] = LWM2M_DEVICE_HW_VERSION,
[LWM2M_RES_SW_VERSION] = LWM2M_DEVICE_SW_VERSION,
[LWM2M_DEVICE_RESOURCES] = NULL
};
/*Descriptor of a LwM2M device object instance */
typedef struct {
uint8_t *power_sources; /**< types of power sources (0-7) */
uint16_t *power_voltage; /**< voltage of power sources in mV */
uint16_t *power_current; /**< current of power sources in mA */
uint8_t battery_status; /**< battery status (0-6) */
uint32_t mem_total; /**< amount of memory on the device in kB */
uint16_t(*ext_dev_info)[2]; /**< external devices information */
uint8_t ext_dev_info_len; /**< amount of external devices information */
uint8_t error_code[7]; /**< error codes */
uint8_t error_code_used; /**< amount of error codes used */
} dev_data_t;
static uint8_t prv_device_discover(uint16_t instance_id, int *num_dataP,
lwm2m_data_t **data_arrayP,
lwm2m_object_t *objectP)
{
uint8_t result;
int i;
(void)objectP;
if (instance_id != 0) {
return COAP_404_NOT_FOUND;
}
result = COAP_205_CONTENT;
if (*num_dataP == 0) {
/* This list must contain all available resources */
uint16_t res[] = {
LWM2M_RES_MANUFACTURER, LWM2M_RES_MODEL_NO, LWM2M_RES_SERIAL,
LWM2M_RES_FW_VER, LWM2M_RES_REBOOT, LWM2M_RES_ERROR_CODE,
/* LWM2M_RES_ERROR_CODE_RESET, TODO */
LWM2M_RES_BINDINGS, LWM2M_RES_TYPE, LWM2M_RES_HW_VERSION,
LWM2M_RES_SW_VERSION,
};
int len = sizeof(res) / sizeof(uint16_t);
*data_arrayP = lwm2m_data_new(len);
if (*data_arrayP == NULL) {
return COAP_500_INTERNAL_SERVER_ERROR;
}
*num_dataP = len;
for (i = 0; i < len; i++) {
(*data_arrayP)[i].id = res[i];
}
}
else {
/* Check if each given resource is present */
for (i = 0; i < *num_dataP && result == COAP_205_CONTENT; i++) {
switch ((*data_arrayP)[i].id) {
case LWM2M_RES_MANUFACTURER:
case LWM2M_RES_MODEL_NO:
case LWM2M_RES_SERIAL:
case LWM2M_RES_FW_VER:
case LWM2M_RES_REBOOT:
case LWM2M_RES_ERROR_CODE:
/* case LWM2M_RES_ERROR_CODE_RESET: TODO */
case LWM2M_RES_BINDINGS:
case LWM2M_RES_TYPE:
case LWM2M_RES_HW_VERSION:
case LWM2M_RES_SW_VERSION:
break;
default:
result = COAP_404_NOT_FOUND;
}
}
}
return result;
}
static uint8_t prv_device_read(uint16_t instance_id, int *num_dataP,
lwm2m_data_t **data_arrayP,
lwm2m_object_t *objectP)
{
int i;
uint8_t result = COAP_404_NOT_FOUND;
dev_data_t *data = (dev_data_t *)objectP->userData;
(void)data;
/* Single instance object */
if (instance_id != 0) {
goto out;
}
/* Full object requested */
if (*num_dataP == 0) {
/* This list must contain all readable resources */
uint16_t resList[] = {
LWM2M_RES_MANUFACTURER, LWM2M_RES_MODEL_NO, LWM2M_RES_SERIAL,
LWM2M_RES_FW_VER, LWM2M_RES_HW_VERSION, LWM2M_RES_SW_VERSION,
LWM2M_RES_BINDINGS, LWM2M_RES_TYPE, LWM2M_RES_ERROR_CODE,
};
int cnt = sizeof(resList) / sizeof(uint16_t);
*data_arrayP = lwm2m_data_new(cnt);
if (*data_arrayP == NULL) {
result = COAP_500_INTERNAL_SERVER_ERROR;
goto out;
}
*num_dataP = cnt;
for (i = 0; i < cnt; i++) {
(*data_arrayP)[i].id = resList[i];
}
}
for (i = 0; i < *num_dataP; i++) {
switch ((*data_arrayP)[i].id) {
/* Exec resources */
case LWM2M_RES_REBOOT:
case LWM2M_RES_FRESET:
case LWM2M_RES_ERROR_CODE_RESET:
result = COAP_405_METHOD_NOT_ALLOWED;
goto out;
break;
case LWM2M_RES_ERROR_CODE:
/* TODO: Here some error reporting should be implemented. */
lwm2m_data_encode_int(LWM2M_DEVICE_ERR_NO_ERR, *data_arrayP + i);
result = COAP_205_CONTENT;
break;
/* The rest are either static or not defined resources */
default:
if (_static_resources[(*data_arrayP)[i].id]) {
lwm2m_data_encode_string(
_static_resources[(*data_arrayP)[i].id],
*data_arrayP + i);
result = COAP_205_CONTENT;
}
else {
result = COAP_404_NOT_FOUND;
goto out;
}
}
}
out:
return result;
}
static uint8_t prv_device_write(uint16_t instance_id, int num_data,
lwm2m_data_t *data_array,
lwm2m_object_t *objectP)
{
dev_data_t *data = (dev_data_t *)objectP->userData;
(void)data;
(void)instance_id;
(void)num_data;
(void)data_array;
if (data_array[0].id < LWM2M_DEVICE_RESOURCES) {
/* for now not writing resources */
return COAP_405_METHOD_NOT_ALLOWED;
}
else {
return COAP_404_NOT_FOUND;
}
}
static uint8_t prv_device_execute(uint16_t instance_id, uint16_t resource_id,
uint8_t *buffer, int length,
lwm2m_object_t *objectP)
{
uint8_t result;
dev_data_t *data = (dev_data_t *)objectP->userData;
(void)data;
(void)buffer;
(void)length;
(void)objectP;
/* single instance object */
if (instance_id != 0) {
result = COAP_404_NOT_FOUND;
goto err_out;
}
if (length != 0) {
result = COAP_400_BAD_REQUEST;
goto err_out;
}
switch (resource_id) {
case LWM2M_RES_REBOOT:
reboot = true;
result = COAP_204_CHANGED;
break;
case LWM2M_RES_ERROR_CODE_RESET:
/* TODO */
case LWM2M_RES_FRESET:
/* TODO Callback? */
default:
result = COAP_405_METHOD_NOT_ALLOWED;
}
err_out:
return result;
}
/*
* Call this from the main loop to check whether a reboot was requested.
*/
bool lwm2m_device_reboot_requested(void)
{
return reboot;
}
lwm2m_object_t *lwm2m_get_object_device(void)
{
lwm2m_object_t *obj;
obj = (lwm2m_object_t *)lwm2m_malloc(sizeof(lwm2m_object_t));
if (obj == NULL) {
goto err_out;
}
memset(obj, 0, sizeof(lwm2m_object_t));
obj->instanceList = (lwm2m_list_t *)lwm2m_malloc(sizeof(lwm2m_list_t));
if (obj->instanceList == NULL) {
goto free_obj;
}
memset(obj->instanceList, 0, sizeof(lwm2m_list_t));
obj->objID = LWM2M_DEVICE_OBJECT_ID;
obj->readFunc = prv_device_read;
obj->writeFunc = prv_device_write;
obj->executeFunc = prv_device_execute;
obj->discoverFunc = prv_device_discover;
/* Don't allocate memory for stuff that isn't used at the moment */
/* obj->userData = lwm2m_malloc(sizeof(dev_data_t)); */
/* if (obj->userData == NULL) { */
/* goto free_ilist; */
/* } */
/* */
/* memset(obj->userData, 0, sizeof(dev_data_t)); */
/* INT USER DATA HERE */
return obj;
/* free_ilist: */
/* lwm2m_free(obj->instanceList); */
free_obj:
lwm2m_free(obj);
err_out:
return NULL;
}
void lwm2m_free_object_device(lwm2m_object_t *obj)
{
if (obj == NULL) {
return;
}
if (obj->userData) {
lwm2m_free(obj->userData);
}
if (obj->instanceList) {
lwm2m_free(obj->instanceList);
}
lwm2m_free(obj);
}

View File

@ -0,0 +1,124 @@
/*
* 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 pkg_wakaama
* @defgroup lwm2m_client LwM2M Client using Wakaama
* @brief Wakaama adaption to RIOT for implementing a LwM2M client
* @{
* @file
* @brief Definitions and public API for a LwM2M client using Wakaama
*
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*/
#ifndef LWM2M_CLIENT_H
#define LWM2M_CLIENT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include "periph/pm.h"
#include "net/sock/udp.h"
#include "lwm2m_client_config.h"
#include "liblwm2m.h"
/**
* @brief Connection to server descriptor
*/
typedef struct lwm2m_client_connection {
struct lwm2m_client_connection *next; /**< pointer to the next connection */
sock_udp_ep_t remote; /**< remote endpoint */
time_t last_send; /**< last sent packet to the server */
} lwm2m_client_connection_t;
/**
* @brief LwM2M client descriptor
*/
typedef struct {
kernel_pid_t pid; /**< PID of the client thread */
sock_udp_t sock; /**< UDP server sock */
sock_udp_ep_t local_ep; /**< Local endpoint */
lwm2m_context_t *lwm2m_ctx; /**< LwM2M context */
lwm2m_object_t *obj_security; /**< LwM2M security object */
lwm2m_client_connection_t *conn_list; /**< LwM2M connections list */
} lwm2m_client_data_t;
/**
* @brief Size of the buffer for the UDP packet reception
*/
#define LWM2M_CLIENT_RCV_BUFFER_SIZE (200)
/**
* @brief Time in seconds to wait until reboot after a server
* request
*/
#define LWM2M_CLIENT_REBOOT_TIME (5)
/**
* @brief Time in seconds to wait until LwM2M is refreshed.
*
* @note This time is used as the timeout for receiving UDP packets and will be
* the maximum time to wait between calls to wakaama core.
*/
#define LWM2M_CLIENT_MIN_REFRESH_TIME (1)
/**
* @brief Starts a LwM2M client
*
* @param[in, out] client_data Pointer to a LwM2M client data descriptor
* @param[in] obj_list List of LwM2M objects to be registered
* @param[in] obj_numof Number of objects in @p obj_list
*
* @return Context of the LwM2M client
*/
lwm2m_context_t *lwm2m_client_run(lwm2m_client_data_t *client_data,
lwm2m_object_t *obj_list[],
uint16_t obj_numof);
/**
* @brief Initializes a LwM2M client
*
* @note This functions initializes the memory allocation and is needed before
* calling any object creation (i.e. any call to lwm2m_malloc).
*
* @param[in] client_data Pointer to a LwM2M client data descriptor
*/
void lwm2m_client_init(lwm2m_client_data_t *client_data);
/**
* @brief Returns the LwM2M context of a LwM2M client
*
* @param[in] client_data pointer to the LwM2M client descriptor
*
* @return Pointer to the LwM2M context
*/
static inline lwm2m_context_t *lwm2m_client_get_ctx(
lwm2m_client_data_t *client_data)
{
return client_data->lwm2m_ctx;
}
#ifdef __cplusplus
}
#endif
#endif /* LWM2M_CLIENT_H */
/** @} */

View File

@ -0,0 +1,190 @@
/*
* Copyright (C) 2018 Beduino Master Projekt - University of Bremen
* 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 pkg_wakaama
* @ingroup config
* @defgroup lwm2m_client_config Wakaama LwM2M Client configuration
*
* @brief Configuration options for the LwM2M client implementation
* based on the Wakaama package.
* @{
*
* @file
* @brief LwM2M client configurations
*
* @author Christian Manal <manal@uni-bremen.de>
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*/
#ifndef LWM2M_CLIENT_CONFIG_H
#define LWM2M_CLIENT_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief CoAP default port of the LwM2M server
*/
#ifndef LWM2M_STANDARD_PORT
#define LWM2M_STANDARD_PORT "5683"
#endif
/**
* @brief CoAPS default port of the LwM2M server
*/
#ifndef LWM2M_DTLS_PORT
#define LWM2M_DTLS_PORT "5684"
#endif
/**
* @brief CoAP default port of the LwM2M bootstrap server
*/
#ifndef LWM2M_BSSERVER_PORT
#define LWM2M_BSSERVER_PORT "5685"
#endif
/**
* @brief Default port for the local LwM2M instance
*/
#ifndef LWM2M_LOCAL_PORT
#define LWM2M_LOCAL_PORT "5683"
#endif
/**
* @brief Device name used to register at the LwM2M server
*/
#ifndef LWM2M_DEVICE_NAME
#define LWM2M_DEVICE_NAME "testRIOTDevice"
#endif
/**
* @brief Lifetime of the device object on the LwM2M server
*/
#ifndef LWM2M_DEVICE_TTL
#define LWM2M_DEVICE_TTL 300
#endif
/**
* @brief LwM2M server URI to register/bootstrap with
*
* @note The host part of the URI MUST be a valid IPv6 address. Host names can
* not be resolved at this time.
*/
#ifndef LWM2M_SERVER_URI
#define LWM2M_SERVER_URI "coap://[fd00:dead:beef::1]"
#endif
/**
* @brief Numeric ID of LWM2M_SERVER_URI
*/
#ifndef LWM2M_SERVER_ID
#define LWM2M_SERVER_ID 10
#endif
/**
* @brief Alternate path to place LwM2M resources
*/
#ifndef LWM2M_ALT_PATH
#define LWM2M_ALT_PATH NULL
#endif
/**
* @brief Define to 1 to specify that @ref LWM2M_SERVER_URI is a bootstrap server
*
* To define just add it to your `CFLAGS` in your application's Makefile:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
* CFLAGS += -DLWM2M_BOOTSTRAP=1
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifdef DOXYGEN
#define LWM2M_BOOTSTRAP
#endif
/**
* @brief Device object manufacturer string
*/
#ifndef LWM2M_DEVICE_MANUFACTURER
#define LWM2M_DEVICE_MANUFACTURER "A RIOT maker"
#endif
/**
* @brief Device object model.
*
* @note Defaults to the board name
*/
#ifndef LWM2M_DEVICE_MODEL
#define LWM2M_DEVICE_MODEL RIOT_BOARD
#endif
/**
* @brief Device object serial number
*/
#ifndef LWM2M_DEVICE_SERIAL
#define LWM2M_DEVICE_SERIAL "undefined"
#endif
/**
* @brief Device object firmware version
*
* @note Defaults to the running RIOT version
*/
#ifndef LWM2M_DEVICE_FW_VERSION
#define LWM2M_DEVICE_FW_VERSION RIOT_VERSION
#endif
/**
* @brief Device object binding and queue mode
*
* Valid values are:
* - U: UDP
* - UQ: UDP with Queue mode
* - S: SMS
* - SQ: SMS with Queue mode
* - US: UDP and SMS
* - UQS: UDP with Queue mode and SMS
*/
#ifndef LWM2M_DEVICE_BINDINGS
#define LWM2M_DEVICE_BINDINGS "U"
#endif
/**
* @brief Device object device type
*/
#ifndef LWM2M_DEVICE_TYPE
#define LWM2M_DEVICE_TYPE "RIOT device"
#endif
/**
* @brief Device object hardware version
*
* @note Defaults to the board name
*/
#ifndef LWM2M_DEVICE_HW_VERSION
#define LWM2M_DEVICE_HW_VERSION RIOT_BOARD
#endif
/**
* @brief Device object software version
*
* @note Defaults to the running RIOT version
*/
#ifndef LWM2M_DEVICE_SW_VERSION
#define LWM2M_DEVICE_SW_VERSION RIOT_VERSION
#endif
/** @} */
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* LWM2M_CLIENT_CONFIG_H */

View File

@ -0,0 +1,89 @@
/*******************************************************************************
*
* Copyright (c) 2015 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* The Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Simon Bernard - initial API and implementation
* Christian Renz - Please refer to git log
* Christian Manal - Ported to RIOT OS
*
*******************************************************************************/
/*
* 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
* @brief Public API and definitions of the connection handle for
* LwM2M client implementation using Wakaama
* @{
*
* @file
*
* @author Christian Manal <manal@uni-bremen.de>
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*/
#ifndef LWM2M_CLIENT_CONNECTION_H
#define LWM2M_CLIENT_CONNECTION_H
#ifdef __cplusplus
extern "C" {
#endif
#include "net/ipv6/addr.h"
#include "net/sock/udp.h"
#include "lwm2m_client.h"
#include "lwm2m_client_config.h"
#define SCHEME_COAPS "coaps://"
#define SCHEME_COAP "coap://"
/**
* @brief Tries to find an existing connection based on a remote UDP endpoint
*
* @param[in] conn_list connections list to search
* @param[in] remote remote UDP endpoint to compare to
*
* @return pointer to the connection in success
* @return NULL otherwise
*/
lwm2m_client_connection_t *lwm2m_client_connection_find(
lwm2m_client_connection_t *conn_list,
const sock_udp_ep_t *remote);
/**
* @brief Handles a received packet from a connection
*
* @param[in] conn connection from where the packet came from
* @param[in] buffer received packet
* @param[in] num_bytes size of the packet
* @param[in] client_data LwM2M client data
*
* @return 0 on success
* @return non-zero otherwise
*/
int lwm2m_connection_handle_packet(lwm2m_client_connection_t *conn,
uint8_t *buffer, size_t num_bytes,
lwm2m_client_data_t *client_data);
#ifdef __cplusplus
}
#endif
#endif /* LWM2M_CLIENT_CONNECTION_H */
/** @} */

View File

@ -0,0 +1,95 @@
/*
* 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
* @{
* @brief Public API and definitions for the helper functions to
* interact with basic objects from a LwM2M client.
*
* @file
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*/
#ifndef LWM2M_CLIENT_OBJECTS_H
#define LWM2M_CLIENT_OBJECTS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lwm2m_client.h"
/**
* @name Access Control Bits
* @brief Bit definitions for the ACL property of the LwM2M Access Control
* Object.
*
* @see http://www.openmobilealliance.org/tech/profiles/LWM2M_Access_Control-v1_0_3.xml
* @{
*/
#define LWM2M_ACC_CTRL_READ (1 << 0) /**< Read access */
#define LWM2M_ACC_CTRL_WRITE (1 << 1) /**< Write access */
#define LWM2M_ACC_CTRL_EXECUTE (1 << 2) /**< Execution access */
#define LWM2M_ACC_CTRL_DELETE (1 << 3) /**< Deletion access */
#define LWM2M_ACC_CTRL_CREATE (1 << 4) /**< Creation access */
/** @} */
/**
* @brief Creates a LwM2M security object with the default configuration from
* net/lwm2m.h
*
* @param[in, out] client_data Pointer to a LwM2M client data descriptor
*
* @return Pointer to the created object in success
* @return NULL otherwise
*/
lwm2m_object_t *lwm2m_client_get_security_object(
lwm2m_client_data_t *client_data);
/**
* @brief Creates a LwM2M server object with the default configuration from
* net/lwm2m.h
*
* @param[in, out] client_data Pointer to a LwM2M client data descriptor
*
* @return Pointer to the created object
* @return NULL otherwise
*/
lwm2m_object_t *lwm2m_client_get_server_object(
lwm2m_client_data_t *client_data);
/**
* @brief Creates a LwM2M device object with the default configuration from
* net/lwm2m.h
* @param[in, out] client_data Pointer to a LwM2M client data descriptor
*
* @return Pointer to the created object
* @return NULL otherwise
*/
lwm2m_object_t *lwm2m_client_get_device_object(
lwm2m_client_data_t *client_data);
/**
* @brief Creates a LwM2M access control object with the default configuration
*
* @param[in] client_data Pointer to a LwM2M client data descriptor
*
* @return Pointer to the created object
* @return NULL otherwise
*/
lwm2m_object_t *lwm2m_client_get_acc_ctrl_object(
lwm2m_client_data_t *client_data);
#ifdef __cplusplus
}
#endif
#endif /* LWM2M_CLIENT_OBJECTS_H */
/** @} */

View File

@ -0,0 +1,54 @@
/*
* 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 pkg_wakaama
* @defgroup lwm2m_platform Platform adaption for Wakaama package
* @brief Adaption of Wakaama LwM2M package to RIOT
* @{
* @file
* @brief Definitions and public API for Wakaama adaption layer
*
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*/
#ifndef LWM2M_PLATFORM_H
#define LWM2M_PLATFORM_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup lwm2m_platform_conf Wakaama LwM2M platform adaption
* @ingroup config
* @brief Compile-time configuration options for the Wakaama LwM2M platform
* adaption layer.
* @{
*/
/** @brief Size of allocation buffer in bytes */
#ifndef LWM2M_TLSF_BUFFER
#define LWM2M_TLSF_BUFFER 5120
#endif
/** @} */
/**
* @brief Initializes the platform adaption for Wakaama LwM2M
*/
void lwm2m_platform_init(void);
/**
* @brief Prints the status of TLSF allocation buffer, for development use.
*/
void lwm2m_tlsf_status(void);
#ifdef __cplusplus
}
#endif
#endif /* LWM2M_PLATFORM_H */
/** @} */

View File

@ -0,0 +1,105 @@
/*
* 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_objects
* @defgroup lwm2m_objects_device Device LwM2M object
* @brief Device object implementation for LwM2M client using Wakaama
* @{
*
* @file
*
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*/
#ifndef OBJECTS_DEVICE_H
#define OBJECTS_DEVICE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "liblwm2m.h"
#include "lwm2m_client_config.h"
/**
* @brief Resources of the LwM2M device object instance
*
* @see http://www.openmobilealliance.org/tech/profiles/LWM2M_Device-v1_0_3.xml
*/
enum lwm2m_device_resources {
LWM2M_RES_MANUFACTURER = 0, /**< Human readable manufacturer name */
LWM2M_RES_MODEL_NO, /**< Model identifier (manufacturer specified string) */
LWM2M_RES_SERIAL, /**< Serial number */
LWM2M_RES_FW_VER, /**< Current firmware version of the device */
LWM2M_RES_REBOOT, /**< Reboot the device */
LWM2M_RES_FRESET, /**< Perform a factory reset of the device */
LWM2M_RES_POWER_SRC, /**< Available power sources */
LWM2M_RES_POWER_VOL, /**< Present voltage for each power source */
LWM2M_RES_POWER_AMP, /**< Present current for each power source */
LWM2M_RES_BATTERY_LEVEL, /**< Current battery level as a percentage */
LWM2M_RES_MEM_FREE, /**< Estimated current available storage (kB) */
LWM2M_RES_ERROR_CODE, /**< Last error code */
LWM2M_RES_ERROR_CODE_RESET, /**< Delete all error code instances */
LWM2M_RES_TIME, /**< Current UNIX time of the client */
LWM2M_RES_TIME_OFFSET, /**< Indicated the UTC offset for the device */
LWM2M_RES_TIME_ZONE, /**< Indicates the time zone of the device */
LWM2M_RES_BINDINGS, /**< Indicates supported bindings and modes on the client */
LWM2M_RES_TYPE, /**< Type of device */
LWM2M_RES_HW_VERSION, /**< Current hardware version of the device */
LWM2M_RES_SW_VERSION, /**< Current software version on the device */
LWM2M_RES_BATTERY_STATUS, /**< Battery status when internal battery is present */
LWM2M_RES_MEM_TOTAL, /**< Total amount of storage space in the device (kB*/
LWM2M_RES_EXT_DEV_INFO, /**< External device object instance */
LWM2M_DEVICE_RESOURCES /**< Number of resources */
};
/**
* @brief Error codes for the
* @ref lwm2m_device_resources::LWM2M_RES_ERROR_CODE "Error" resource in the
* device object of LwM2M
*/
enum lwm2m_device_error_codes {
LWM2M_DEVICE_ERR_NO_ERR = 0, /**< No error */
LWM2M_DEVICE_ERR_LOW_BATT = 1, /**< Low battery power */
LWM2M_DEVICE_ERR_EXT_OFF = 2, /**< External power supply off */
LWM2M_DEVICE_ERR_GPS_ERR = 3, /**< GPS module failure */
LWM2M_DEVICE_ERR_LOW_SIGNAL = 4, /**< Low received signal strength */
LWM2M_DEVICE_ERR_NO_MEM = 5, /**< Out of memory */
LWM2M_DEVICE_ERR_SMS_ERR = 6, /**< SMS failure */
LWM2M_DEVICE_ERR_IP_ERR = 7, /**< IP connectivity failure */
LWM2M_DEVICE_ERR_PERIPH_ERR = 8 /**< Peripheral malfunction */
};
/**
* @brief Frees the memory of @p obj device object
*
* @param[in] obj pointer to the device object
*/
void lwm2m_free_object_device(lwm2m_object_t *obj);
/**
* @brief Determines if a reboot request has been issued to the device by a
* server.
*
* @return true reboot has been requested
* @return false reboot has not been requested
*/
bool lwm2m_device_reboot_requested(void);
#ifdef __cplusplus
}
#endif
#endif /* OBJECTS_DEVICE_H */
/** @} */

View File

@ -0,0 +1,8 @@
/**
* @defgroup lwm2m_objects LwM2M Object implementations
* @ingroup pkg_wakaama
* @brief Implementations of LwM2M objects using Wakaama. For a complete
list of the objects supported by the LwM2M protocol check the
object registry:
* @see http://www.openmobilealliance.org/wp/OMNA/LwM2M/LwM2MRegistry.html
*/