blob: ea77695b757414bbd5207d05494916dd10fcb5a2 [file] [log] [blame]
/*
* Copyright (c) 2017 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
#define SYS_LOG_DOMAIN "lwm2m-client"
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
#define NET_LOG_ENABLED 1
#include <board.h>
#include <zephyr.h>
#include <gpio.h>
#include <net/lwm2m.h>
#define APP_BANNER "Run LWM2M client"
#if !defined(CONFIG_NET_APP_PEER_IPV4_ADDR)
#define CONFIG_NET_APP_PEER_IPV4_ADDR ""
#endif
#if !defined(CONFIG_NET_APP_PEER_IPV6_ADDR)
#define CONFIG_NET_APP_PEER_IPV6_ADDR ""
#endif
#define WAIT_TIME K_SECONDS(10)
#define CONNECT_TIME K_SECONDS(10)
#define CLIENT_MANUFACTURER "Zephyr"
#define CLIENT_MODEL_NUMBER "OMA-LWM2M Sample Client"
#define CLIENT_SERIAL_NUMBER "345000123"
#define CLIENT_FIRMWARE_VER "1.0"
#define CLIENT_DEVICE_TYPE "OMA-LWM2M Client"
#define CLIENT_HW_VER "1.0.1"
#define ENDPOINT_LEN 32
#if defined(LED0_GPIO_PORT)
#define LED_GPIO_PORT LED0_GPIO_PORT
#define LED_GPIO_PIN LED0_GPIO_PIN
#else
#define LED_GPIO_PORT "(fail)"
#define LED_GPIO_PIN 0
#endif
static int pwrsrc_bat;
static int pwrsrc_usb;
static int battery_voltage = 3800;
static int battery_current = 125;
static int usb_voltage = 5000;
static int usb_current = 900;
static struct device *led_dev;
static u32_t led_state;
static struct lwm2m_ctx client;
static struct k_sem quit_lock;
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
NET_PKT_TX_SLAB_DEFINE(lwm2m_tx_udp, 5);
NET_PKT_DATA_POOL_DEFINE(lwm2m_data_udp, 20);
static struct k_mem_slab *tx_udp_slab(void)
{
return &lwm2m_tx_udp;
}
static struct net_buf_pool *data_udp_pool(void)
{
return &lwm2m_data_udp;
}
#else
#define tx_udp_slab NULL
#define data_udp_pool NULL
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
/* TODO: Move to a pre write hook that can handle ret codes once available */
static int led_on_off_cb(u16_t obj_inst_id, u8_t *data, u16_t data_len,
bool last_block, size_t total_size)
{
int ret = 0;
u32_t led_val;
led_val = *(u8_t *) data;
if (led_val != led_state) {
ret = gpio_pin_write(led_dev, LED_GPIO_PIN, led_val);
if (ret) {
/*
* We need an extra hook in LWM2M to better handle
* failures before writing the data value and not in
* post_write_cb, as there is not much that can be
* done here.
*/
SYS_LOG_ERR("Fail to write to GPIO %d", LED_GPIO_PIN);
return ret;
}
led_state = led_val;
/* TODO: Move to be set by an internal post write function */
lwm2m_engine_set_s32("3311/0/5852", 0);
}
return ret;
}
static int init_led_device(void)
{
int ret;
led_dev = device_get_binding(LED_GPIO_PORT);
if (!led_dev) {
return -ENODEV;
}
ret = gpio_pin_configure(led_dev, LED_GPIO_PIN, GPIO_DIR_OUT);
if (ret) {
return ret;
}
ret = gpio_pin_write(led_dev, LED_GPIO_PIN, 0);
if (ret) {
return ret;
}
return 0;
}
static int device_reboot_cb(u16_t obj_inst_id)
{
SYS_LOG_INF("DEVICE: REBOOT");
/* Add an error for testing */
lwm2m_device_add_err(LWM2M_DEVICE_ERROR_LOW_POWER);
/* Change the battery voltage for testing */
lwm2m_device_set_pwrsrc_voltage_mv(pwrsrc_bat, --battery_voltage);
return 1;
}
static int device_factory_default_cb(u16_t obj_inst_id)
{
SYS_LOG_INF("DEVICE: FACTORY DEFAULT");
/* Add an error for testing */
lwm2m_device_add_err(LWM2M_DEVICE_ERROR_GPS_FAILURE);
/* Change the USB current for testing */
lwm2m_device_set_pwrsrc_current_ma(pwrsrc_usb, --usb_current);
return 1;
}
#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT)
static int firmware_update_cb(u16_t obj_inst_id)
{
SYS_LOG_DBG("UPDATE");
/* TODO: kick off update process */
/* If success, set the update result as RESULT_SUCCESS.
* In reality, it should be set at function lwm2m_setup()
*/
lwm2m_engine_set_u8("5/0/3", STATE_IDLE);
lwm2m_engine_set_u8("5/0/5", RESULT_SUCCESS);
return 1;
}
#endif
#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT)
static int firmware_block_received_cb(u16_t obj_inst_id,
u8_t *data, u16_t data_len,
bool last_block, size_t total_size)
{
SYS_LOG_INF("FIRMWARE: BLOCK RECEIVED: len:%u last_block:%d",
data_len, last_block);
return 1;
}
#endif
static int lwm2m_setup(void)
{
struct float32_value float_value;
/* setup SECURITY object */
/* setup SERVER object */
/* setup DEVICE object */
lwm2m_engine_set_string("3/0/0", CLIENT_MANUFACTURER);
lwm2m_engine_set_string("3/0/1", CLIENT_MODEL_NUMBER);
lwm2m_engine_set_string("3/0/2", CLIENT_SERIAL_NUMBER);
lwm2m_engine_set_string("3/0/3", CLIENT_FIRMWARE_VER);
lwm2m_engine_register_exec_callback("3/0/4", device_reboot_cb);
lwm2m_engine_register_exec_callback("3/0/5", device_factory_default_cb);
lwm2m_engine_set_u8("3/0/9", 95); /* battery level */
lwm2m_engine_set_u32("3/0/10", 15); /* mem free */
lwm2m_engine_set_string("3/0/17", CLIENT_DEVICE_TYPE);
lwm2m_engine_set_string("3/0/18", CLIENT_HW_VER);
lwm2m_engine_set_u8("3/0/20", LWM2M_DEVICE_BATTERY_STATUS_CHARGING);
lwm2m_engine_set_u32("3/0/21", 25); /* mem total */
pwrsrc_bat = lwm2m_device_add_pwrsrc(LWM2M_DEVICE_PWR_SRC_TYPE_BAT_INT);
if (pwrsrc_bat < 0) {
SYS_LOG_ERR("LWM2M battery power source enable error (err:%d)",
pwrsrc_bat);
return pwrsrc_bat;
}
lwm2m_device_set_pwrsrc_voltage_mv(pwrsrc_bat, battery_voltage);
lwm2m_device_set_pwrsrc_current_ma(pwrsrc_bat, battery_current);
pwrsrc_usb = lwm2m_device_add_pwrsrc(LWM2M_DEVICE_PWR_SRC_TYPE_USB);
if (pwrsrc_usb < 0) {
SYS_LOG_ERR("LWM2M usb power source enable error (err:%d)",
pwrsrc_usb);
return pwrsrc_usb;
}
lwm2m_device_set_pwrsrc_voltage_mv(pwrsrc_usb, usb_voltage);
lwm2m_device_set_pwrsrc_current_ma(pwrsrc_usb, usb_current);
/* setup FIRMWARE object */
#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT)
lwm2m_firmware_set_write_cb(firmware_block_received_cb);
#endif
#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT)
lwm2m_firmware_set_update_cb(firmware_update_cb);
#endif
/* setup TEMP SENSOR object */
lwm2m_engine_create_obj_inst("3303/0");
/* dummy temp data in C*/
float_value.val1 = 25;
float_value.val2 = 0;
lwm2m_engine_set_float32("3303/0/5700", &float_value);
/* IPSO: Light Control object */
if (init_led_device() == 0) {
lwm2m_engine_create_obj_inst("3311/0");
lwm2m_engine_register_post_write_callback("3311/0/5850",
led_on_off_cb);
}
return 0;
}
static void rd_client_event(struct lwm2m_ctx *client,
enum lwm2m_rd_client_event client_event)
{
switch (client_event) {
case LWM2M_RD_CLIENT_EVENT_NONE:
/* do nothing */
break;
case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_FAILURE:
SYS_LOG_DBG("Bootstrap failure!");
break;
case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_COMPLETE:
SYS_LOG_DBG("Bootstrap complete");
break;
case LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE:
SYS_LOG_DBG("Registration failure!");
break;
case LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE:
SYS_LOG_DBG("Registration complete");
break;
case LWM2M_RD_CLIENT_EVENT_REG_UPDATE_FAILURE:
SYS_LOG_DBG("Registration update failure!");
break;
case LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE:
SYS_LOG_DBG("Registration update complete");
break;
case LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE:
SYS_LOG_DBG("Deregister failure!");
break;
case LWM2M_RD_CLIENT_EVENT_DISCONNECT:
SYS_LOG_DBG("Disconnected");
break;
}
}
void main(void)
{
int ret;
SYS_LOG_INF(APP_BANNER);
k_sem_init(&quit_lock, 0, UINT_MAX);
ret = lwm2m_setup();
if (ret < 0) {
SYS_LOG_ERR("Cannot setup LWM2M fields (%d)", ret);
return;
}
memset(&client, 0x0, sizeof(client));
client.net_init_timeout = WAIT_TIME;
client.net_timeout = CONNECT_TIME;
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
client.tx_slab = tx_udp_slab;
client.data_pool = data_udp_pool;
#endif
#if defined(CONFIG_NET_IPV6)
ret = lwm2m_rd_client_start(&client, CONFIG_NET_APP_PEER_IPV6_ADDR,
CONFIG_LWM2M_PEER_PORT, CONFIG_BOARD,
rd_client_event);
#elif defined(CONFIG_NET_IPV4)
ret = lwm2m_rd_client_start(&client, CONFIG_NET_APP_PEER_IPV4_ADDR,
CONFIG_LWM2M_PEER_PORT, CONFIG_BOARD,
rd_client_event);
#else
SYS_LOG_ERR("LwM2M client requires IPv4 or IPv6.");
ret = -EPROTONOSUPPORT;
#endif
if (ret < 0) {
SYS_LOG_ERR("LWM2M init LWM2M RD client error (%d)",
ret);
return;
}
k_sem_take(&quit_lock, K_FOREVER);
}