From f8f3629efd5986f5f7bc0f4bffb7edec98129468 Mon Sep 17 00:00:00 2001 From: Marco Argiolas Date: Tue, 6 Dec 2022 20:31:48 +0800 Subject: [PATCH] net: lib: lwm2m: add uCIFI LPWAN object Add support for Low Power Wide Area Network (LPWAN) Object (ID 3412) Signed-off-by: Marco Argiolas --- subsys/net/lib/lwm2m/CMakeLists.txt | 3 + subsys/net/lib/lwm2m/Kconfig.ucifi | 76 ++++++++++++ subsys/net/lib/lwm2m/ucifi_lpwan.c | 181 ++++++++++++++++++++++++++++ subsys/net/lib/lwm2m/ucifi_lpwan.h | 43 +++++++ tests/net/all/prj.conf | 2 + 5 files changed, 305 insertions(+) create mode 100644 subsys/net/lib/lwm2m/ucifi_lpwan.c create mode 100644 subsys/net/lib/lwm2m/ucifi_lpwan.h diff --git a/subsys/net/lib/lwm2m/CMakeLists.txt b/subsys/net/lib/lwm2m/CMakeLists.txt index b472d1e5f6b..9188a3eb4f7 100644 --- a/subsys/net/lib/lwm2m/CMakeLists.txt +++ b/subsys/net/lib/lwm2m/CMakeLists.txt @@ -51,6 +51,9 @@ zephyr_library_sources_ifdef(CONFIG_LWM2M_EVENT_LOG_OBJ_SUPPORT zephyr_library_sources_ifdef(CONFIG_LWM2M_ACCESS_CONTROL_ENABLE lwm2m_obj_access_control.c ) +zephyr_library_sources_ifdef(CONFIG_LWM2M_UCIFI_LPWAN + ucifi_lpwan.c + ) # TLV Support zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_OMA_TLV_SUPPORT diff --git a/subsys/net/lib/lwm2m/Kconfig.ucifi b/subsys/net/lib/lwm2m/Kconfig.ucifi index 0062f08c32c..6dda4eb89b8 100644 --- a/subsys/net/lib/lwm2m/Kconfig.ucifi +++ b/subsys/net/lib/lwm2m/Kconfig.ucifi @@ -25,4 +25,80 @@ config LWM2M_UCIFI_BATTERY_INSTANCE_COUNT endif # LWM2M_UCIFI_BATTERY +menuconfig LWM2M_UCIFI_LPWAN + bool "uCIFI LPWAN (3412) Support" + help + The uCIFI LPWAN object provides attributes to monitor and maintain + Low-Power Wide Area Networks. + +if LWM2M_UCIFI_LPWAN + +config LWM2M_UCIFI_LPWAN_INSTANCE_COUNT + int "Maximum # of uCIFI LPWAN object instances" + default 1 + range 1 4 + help + This value sets the maximum allowable number of LPWAN instances. + +config LWM2M_UCIFI_LPWAN_IPV4_ADDRESS_MAX + int "Maximum # of IPv4 addresses" + default 0 + range 0 20 + help + This value sets the maximum number of IPv4 addresses assigned to a + device that can be stored in this object. + +config LWM2M_UCIFI_LPWAN_IPV6_ADDRESS_MAX + int "Maximum # of IPv6 addresses" + default 0 + range 0 20 + help + This value sets the maximum number of IPv6 addresses assigned to a + device that can be stored in this object. + +config LWM2M_UCIFI_LPWAN_NETWORK_ADDRESS_MAX + int "Maximum # of network addresses" + default 0 + range 0 20 + help + This value sets the maximum number of LPWAN network addresses assigned + to a device that can be stored in this object. + +config LWM2M_UCIFI_LPWAN_SECONDARY_NETWORK_ADDRESS_MAX + int "Maximum # of secondary network addresses" + default 0 + range 0 20 + help + This value sets the maximum number of secondary addresses used to + communicate with the device on the LPWAN network assigned that can be + stored in this object. + +config LWM2M_UCIFI_LPWAN_PEER_ADDRESS_MAX + int "Maximum # of peer node addresses" + default 0 + range 0 64 + help + This value sets the maximum number of LPWAN addresses of peer nodes + that can be stored in this object. + +config LWM2M_UCIFI_LPWAN_MULTICAST_GRP_ADDRESS_MAX + int "Maximum # of multicast group addresses" + default 0 + range 0 20 + help + This value sets the maximum number of multicast group addresses (from + which the device should accept incoming messages and/or commands) + that can be stored in this object. + +config LWM2M_UCIFI_LPWAN_MULTICAST_GRP_KEY_MAX + int "Maximum # of multicast group keys" + default 0 + range 0 20 + help + This value sets the maximum number of security key (e.g. AES128) to + be shared with other members to be part of a multicast group that can + be stored in this object. + +endif # LWM2M_UCIFI_LPWAN + endif # LWM2M_UCIFI_SUPPORT diff --git a/subsys/net/lib/lwm2m/ucifi_lpwan.c b/subsys/net/lib/lwm2m/ucifi_lpwan.c new file mode 100644 index 00000000000..77019022b96 --- /dev/null +++ b/subsys/net/lib/lwm2m/ucifi_lpwan.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2022 FTP Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Source material for uCIFI LPWAN object (3412): + * https://raw.githubusercontent.com/OpenMobileAlliance/lwm2m-registry/prod/3412.xml + */ + +#define LOG_MODULE_NAME net_ucifi_lpwan +#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL + +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +#include +#include + +#include + +#include "lwm2m_object.h" +#include "lwm2m_engine.h" +#include "ucifi_lpwan.h" + +#define LPWAN_VERSION_MAJOR 1 +#define LPWAN_VERSION_MINOR 0 + +/* clang-format off */ +#define MAX_INSTANCE_COUNT CONFIG_LWM2M_UCIFI_LPWAN_INSTANCE_COUNT +#define IPV4_ADDRESS_MAX CONFIG_LWM2M_UCIFI_LPWAN_IPV4_ADDRESS_MAX +#define IPV6_ADDRESS_MAX CONFIG_LWM2M_UCIFI_LPWAN_IPV6_ADDRESS_MAX +#define NETWORK_ADDRESS_MAX CONFIG_LWM2M_UCIFI_LPWAN_NETWORK_ADDRESS_MAX +#define SECONDARY_NETWORK_ADDRESS_MAX CONFIG_LWM2M_UCIFI_LPWAN_SECONDARY_NETWORK_ADDRESS_MAX +#define PEER_ADDRESS_MAX CONFIG_LWM2M_UCIFI_LPWAN_PEER_ADDRESS_MAX +#define MULTICAST_GRP_ADDRESS_MAX CONFIG_LWM2M_UCIFI_LPWAN_MULTICAST_GRP_ADDRESS_MAX +#define MULTICAST_GRP_KEY_MAX CONFIG_LWM2M_UCIFI_LPWAN_MULTICAST_GRP_KEY_MAX +/* clang-format on */ + +/* + * Calculate resource instances as follows: + * start with UCIFI_LPWAN_MAX_RID + * subtract EXEC resources (0) + * subtract MULTI resources because their counts include 0 resource (7) + * add UCIFI_LPWAN_IPV4_ADDRESS_RID resource instances + * add UCIFI_LPWAN_IPV6_ADDRESS_RID resource instances + * add UCIFI_LPWAN_NETWORK_ADDRESS_RID resource instances + * add UCIFI_LPWAN_SECONDARY_ADDRESS_RID resource instances + * add UCIFI_LPWAN_PEER_ADDRESS_RID resource instances + * add UCIFI_LPWAN_MULTICAST_GRP_ADDRESS_RID resource instances + * add UCIFI_LPWAN_MULTICAST_GRP_KEY_RID resource instances + */ +#define NUMBER_EXEC_RESOURCES 0 +#define NUMBER_MULTI_RESOURCES 7 +#define RESOURCE_INSTANCE_COUNT \ + (UCIFI_LPWAN_MAX_RID - NUMBER_EXEC_RESOURCES - NUMBER_MULTI_RESOURCES + IPV4_ADDRESS_MAX + \ + IPV6_ADDRESS_MAX + NETWORK_ADDRESS_MAX + SECONDARY_NETWORK_ADDRESS_MAX + \ + PEER_ADDRESS_MAX + MULTICAST_GRP_ADDRESS_MAX + MULTICAST_GRP_KEY_MAX) + +static struct lwm2m_engine_obj lpwan; +static struct lwm2m_engine_obj_field fields[] = { + OBJ_FIELD_DATA(UCIFI_LPWAN_NETWORK_TYPE_RID, R_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_IPV4_ADDRESS_RID, RW_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_IPV6_ADDRESS_RID, RW_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_NETWORK_ADDRESS_RID, RW_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_SECONDARY_ADDRESS_RID, RW_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_MAC_ADDRESS_RID, RW, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_PEER_ADDRESS_RID, R_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_MULTICAST_GRP_ADDRESS_RID, RW_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_MULTICAST_GRP_KEY_RID, RW_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_DATA_RATE_RID, RW_OPT, INT), + OBJ_FIELD_DATA(UCIFI_LPWAN_TRANSMIT_POWER_RID, R_OPT, FLOAT), + OBJ_FIELD_DATA(UCIFI_LPWAN_FREQUENCY_RID, RW_OPT, FLOAT), + OBJ_FIELD_DATA(UCIFI_LPWAN_SESSION_TIME_RID, RW_OPT, TIME), + OBJ_FIELD_DATA(UCIFI_LPWAN_SESSION_DURATION_RID, R_OPT, TIME), + OBJ_FIELD_DATA(UCIFI_LPWAN_MESH_NODE_RID, RW_OPT, BOOL), + OBJ_FIELD_DATA(UCIFI_LPWAN_MAX_REPEAT_TIME_RID, RW_OPT, INT), + OBJ_FIELD_DATA(UCIFI_LPWAN_NUMBER_REPEATS_RID, R_OPT, INT), + OBJ_FIELD_DATA(UCIFI_LPWAN_SIGNAL_NOISE_RATIO_RID, R_OPT, FLOAT), + OBJ_FIELD_DATA(UCIFI_LPWAN_COMM_FAILURE_RID, R_OPT, BOOL), + OBJ_FIELD_DATA(UCIFI_LPWAN_RSSI_RID, R_OPT, FLOAT), + OBJ_FIELD_DATA(UCIFI_LPWAN_IMSI_RID, R_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_IMEI_RID, R_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_COMM_OPERATOR_RID, R_OPT, STRING), + OBJ_FIELD_DATA(UCIFI_LPWAN_IC_CARD_IDENTIFIER_RID, R_OPT, STRING), +}; + +static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; +static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][UCIFI_LPWAN_MAX_RID]; +static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; + +/* resource state variables */ +static char mac[MAX_INSTANCE_COUNT][MAC_ADDRESS_SIZE]; + +static struct lwm2m_engine_obj_inst *lpwan_create(uint16_t obj_inst_id) +{ + int index, i = 0, j = 0; + + /* Check that there is no other instance with this ID */ + for (index = 0; index < MAX_INSTANCE_COUNT; index++) { + if ((inst[index].obj != NULL) && (inst[index].obj_inst_id == obj_inst_id)) { + LOG_ERR("Can not create instance - already existing: %u", obj_inst_id); + return NULL; + } + } + + for (index = 0; index < MAX_INSTANCE_COUNT; index++) { + if (inst[index].obj == NULL) { + break; + } + } + + if (index >= MAX_INSTANCE_COUNT) { + LOG_ERR("Can not create instance - no more room: %u", obj_inst_id); + return NULL; + } + + /* Reset to uninitialised values */ + (void)memset(res[index], 0, sizeof(res[index])); + mac[index][0] = '\0'; + + init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index])); + + /* initialize instance resource data */ + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_NETWORK_TYPE_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_IPV4_ADDRESS_RID, res[index], i, res_inst[index], j, + IPV4_ADDRESS_MAX, false); + INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_IPV6_ADDRESS_RID, res[index], i, res_inst[index], j, + IPV6_ADDRESS_MAX, false); + INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_NETWORK_ADDRESS_RID, res[index], i, res_inst[index], + j, NETWORK_ADDRESS_MAX, false); + INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_SECONDARY_ADDRESS_RID, res[index], i, + res_inst[index], j, SECONDARY_NETWORK_ADDRESS_MAX, false); + INIT_OBJ_RES_DATA(UCIFI_LPWAN_MAC_ADDRESS_RID, res[index], i, res_inst[index], j, + mac[index], MAC_ADDRESS_SIZE); + INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_PEER_ADDRESS_RID, res[index], i, res_inst[index], j, + PEER_ADDRESS_MAX, false); + INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_MULTICAST_GRP_ADDRESS_RID, res[index], i, + res_inst[index], j, MULTICAST_GRP_ADDRESS_MAX, false); + INIT_OBJ_RES_MULTI_OPTDATA(UCIFI_LPWAN_MULTICAST_GRP_KEY_RID, res[index], i, + res_inst[index], j, MULTICAST_GRP_KEY_MAX, false); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_DATA_RATE_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_TRANSMIT_POWER_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_FREQUENCY_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_SESSION_TIME_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_SESSION_DURATION_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_MESH_NODE_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_MAX_REPEAT_TIME_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_NUMBER_REPEATS_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_SIGNAL_NOISE_RATIO_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_COMM_FAILURE_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_RSSI_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_IMSI_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_IMEI_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_COMM_OPERATOR_RID, res[index], i, res_inst[index], j); + INIT_OBJ_RES_OPTDATA(UCIFI_LPWAN_IC_CARD_IDENTIFIER_RID, res[index], i, res_inst[index], j); + + inst[index].resources = res[index]; + inst[index].resource_count = i; + + LOG_DBG("Create access control instance: %d", obj_inst_id); + return &inst[index]; +} + +static int ucifi_lpwan_init(const struct device *dev) +{ + lpwan.obj_id = LWM2M_UCIFI_LPWAN_ID; + lpwan.version_major = LPWAN_VERSION_MAJOR; + lpwan.version_minor = LPWAN_VERSION_MINOR; + lpwan.is_core = false; + lpwan.fields = fields; + lpwan.field_count = ARRAY_SIZE(fields); + lpwan.max_instance_count = MAX_INSTANCE_COUNT; + lpwan.create_cb = lpwan_create; + lwm2m_register_obj(&lpwan); + + return 0; +} + +SYS_INIT(ucifi_lpwan_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/subsys/net/lib/lwm2m/ucifi_lpwan.h b/subsys/net/lib/lwm2m/ucifi_lpwan.h new file mode 100644 index 00000000000..e82061d5d17 --- /dev/null +++ b/subsys/net/lib/lwm2m/ucifi_lpwan.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 FTP Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __LWM2M_UCIFI_LPWAN__ +#define __LWM2M_UCIFI_LPWAN__ + +#define LWM2M_UCIFI_LPWAN_ID 3412 +/* Mandatory resource: ID 6 - IEEE MAC address of the device (up to 64 bits) */ +#define MAC_ADDRESS_SIZE 17 /* 16 hex digits, eg. "01a2b3c4d5e6f708\0" */ + +/* Device resource IDs */ +/* clang-format off */ +#define UCIFI_LPWAN_NETWORK_TYPE_RID 1 +#define UCIFI_LPWAN_IPV4_ADDRESS_RID 2 +#define UCIFI_LPWAN_IPV6_ADDRESS_RID 3 +#define UCIFI_LPWAN_NETWORK_ADDRESS_RID 4 +#define UCIFI_LPWAN_SECONDARY_ADDRESS_RID 5 +#define UCIFI_LPWAN_MAC_ADDRESS_RID 6 +#define UCIFI_LPWAN_PEER_ADDRESS_RID 7 +#define UCIFI_LPWAN_MULTICAST_GRP_ADDRESS_RID 8 +#define UCIFI_LPWAN_MULTICAST_GRP_KEY_RID 9 +#define UCIFI_LPWAN_DATA_RATE_RID 10 +#define UCIFI_LPWAN_TRANSMIT_POWER_RID 11 +#define UCIFI_LPWAN_FREQUENCY_RID 12 +#define UCIFI_LPWAN_SESSION_TIME_RID 13 +#define UCIFI_LPWAN_SESSION_DURATION_RID 14 +#define UCIFI_LPWAN_MESH_NODE_RID 15 +#define UCIFI_LPWAN_MAX_REPEAT_TIME_RID 16 +#define UCIFI_LPWAN_NUMBER_REPEATS_RID 17 +#define UCIFI_LPWAN_SIGNAL_NOISE_RATIO_RID 18 +#define UCIFI_LPWAN_COMM_FAILURE_RID 19 +#define UCIFI_LPWAN_RSSI_RID 20 +#define UCIFI_LPWAN_IMSI_RID 21 +#define UCIFI_LPWAN_IMEI_RID 22 +#define UCIFI_LPWAN_COMM_OPERATOR_RID 23 +#define UCIFI_LPWAN_IC_CARD_IDENTIFIER_RID 24 +/* clang-format on */ + +#define UCIFI_LPWAN_MAX_RID UCIFI_LPWAN_IC_CARD_IDENTIFIER_RID + +#endif /* __LWM2M_UCIFI_LPWAN__ */ diff --git a/tests/net/all/prj.conf b/tests/net/all/prj.conf index 523a374ec67..29e94bf09a4 100644 --- a/tests/net/all/prj.conf +++ b/tests/net/all/prj.conf @@ -302,6 +302,8 @@ CONFIG_LWM2M_IPSO_PUSH_BUTTON=y CONFIG_LWM2M_IPSO_CURRENT_SENSOR=y CONFIG_LWM2M_IPSO_FILLING_SENSOR=y CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT=y +CONFIG_LWM2M_UCIFI_SUPPORT=y +CONFIG_LWM2M_UCIFI_LPWAN=y # VLAN CONFIG_NET_VLAN=y