Chapter 3 - Functional description of Azure RTOS NetX LWM2M
This chapter contains a functional description of Azure RTOS NetX LWM2M.
LWM2M Client Initialization
The LWM2M Client is initialized by calling nx_lwm2m_client_create service. The LWM2M Client runs in its own thread and can report some events to the application through the use of callbacks, or by calling methods of the custom objects implemented by the application.
In addition, LWM2M Client Sessions must be created by calling nx_lwm2m_client_session_create for enabling communication with one or more servers. A session can communicate with two different types of servers: a Bootstrap Server or a LWM2M Server (Device Management).
Bootstrap Server Session
A communication session with a Bootstrap Server is used to provision essential information into the LWM2M Client to enable the LWM2M Client to perform the operation "Register" with one or more LWM2M Servers. This type of server is used during the Client Initiated and Server Initiated Bootstrap modes.
The application can start a Bootstrap session by calling nx_lwm2m_client_session_bootstrap or nx_lwm2m_client_session_bootstrap_dtls, it must provide the IP address and port number of the server, and an optional Security Object Instance ID. The nx_lwm2m_client_session_bootstrap function uses insecure communication, whereas nx_lwm2m_client_session_bootstrap_dtls establishes a secure DTLS connection with the server.
If the Bootstrap operation is successful, the Bootstrap server should have created Security Object Instance(s) for the Bootstrap and LWM2M Servers, and Server Object Instance(s) for the LWM2M Servers. The application must use this information for establishing a session with the LWM2M Server(s).
The Bootstrap data should be saved to non-volatile memory by the application in order to configure the LWM2M Client at the next reboot of the device.
LWM2M Server Session
A communication session with a LWM2M Server is used for Registration, Device Management and Service Enablement.
The application can register the LWM2M Client to a server by calling nx_lwm2m_client_session_register or nx_lwm2m_client_session_register_dtls, it must provide the IP address and port number of the server, and the Short Server ID which corresponds to an existing Server Object Instance. The nx_lwm2m_client_session_register function uses insecure communication, whereas nx_lwm2m_client_session_register_dtls establishes a secure DTLS connection with the server.
The application can de-register the LWM2M Client by calling nx_lwm2m_client_session_deregister, and ask the client to send an 'Update' message by calling nx_lwm2m_client_session_update.
Session State Callback
The application registers a callback at creation of a session which is called when the state of the session is updated, the callback function NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK has the following prototype:
typedef VOID (*NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK)
(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT state);
The following states are defined :
NX_LWM2M_CLIENT_SESSION_INIT: The initial state after session creation.
NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_WAITING: The client is waiting for the expiration of the 'Hold Off' timer or Server Initiated Bootstrap.
NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING: The client has sent a 'Request' message to the Bootstrap Server (Client Initiated Bootstrap).
NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED: The client is receiving data from the Bootstrap Server.
NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_FINISHED: The Bootstrap Server has sent a 'Finished' message.
NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR: The bootstrap session has failed.
NX_LWM2M_CLIENT_SESSION_REGISTERING: The client has sent a 'Register' message to the LWM2M Server.
NX_LWM2M_CLIENT_SESSION_REGISTERED: The client is registered to the LWM2M Server.
NX_LWM2M_CLIENT_SESSION_UPDATING: The client has sent an 'Update' message to the LWM2M Server.
NX_LWM2M_CLIENT_SESSION_DEREGISTERING: The client has sent an 'De-register' message to the LWM2M Server.
NX_LWM2M_CLIENT_SESSION_DEREGISTERED: The client is de-registered from the LWM2M Server.
NX_LWM2M_CLIENT_SESSION_DISABLED: The LWM2M Server is disabled. A 'Register' will be sent after the expiration of the disable timer.
NX_LWM2M_CLIENT_SESSION_ERROR: The registration or update operation to the LWM2M Server has failed.
NX_LWM2M_CLIENT_SESSION_DELETED: The Server Object Instance corresponding to the LWM2M Server has been deleted. In case of error the application can retrieve the cause of the error by calling nx_lwm2m_client_session_error_get.
Local Device Management
The application can access the Objects of the LWM2M Client by using the local device management functions. The following functions are provided:
nx_lwm2m_client_object_read: Read resources from an Object Instance.
nx_lwm2m_client_object_discover: Get the list of the resources of an Object Instance.
nx_lwm2m_client_object_write: Write resources to an Object Instance
nx_lwm2m_client_object_execute: Perform the Execute operation on a resource of an Object Instance.
nx_lwm2m_client_object_create: Create a new Object Instance.
nx_lwm2m_client_object_delete: Delete an existing Object Instance.
nx_lwm2m_client_object_get_next: Get the next Object ID implemented by the LWM2M Client.
nx_lwm2m_client_object_instance_get_next: Get the next Instance of an Object.
Resource Information
When reading from and writing to Objects a Resource is represented by the NX_LWM2M_RESOURCE structure. This structure contains the ID of the Resource/Instance and its value. The encoding of the value depends on its type and its origin (application or network).
The NX_LWM2M_RESOURCE structure has the following definition:
typedef struct NX_LWM2M_RESOURCE_STRUCT
{
NX_LWM2M_ID nx_lwm2m_resource_id;
UCHAR nx_lwm2m_resource_type;
union
{
struct
{
const VOID * nx_lwm2m_resource_buffer_ptr;
UINT nx_lwm2m_resource_buffer_length;
} nx_lwm2m_resource_bufferdata;
const CHAR * nx_lwm2m_resource_stringdata;
NX_LWM2M_INT32 nx_lwm2m_resource_integer32data;
NX_LWM2M_INT64 nx_lwm2m_resource_integer64data;
NX_LWM2M_FLOAT32 nx_lwm2m_resource_float32data;
NX_LWM2M_FLOAT64 nx_lwm2m_resource_float64data;
NX_LWM2M_BOOL nx_lwm2m_resource_booleandata;
NX_LWM2M_OBJLNK nx_lwm2m_resource_objlnkdata;
struct
{
const VOID * nx_lwm2m_resource_multiple_ptr;
UINT nx_lwm2m_resource_multiple_dim;
} nx_lwm2m_resource_multipledata;
} nx_lwm2m_resource_value;
} NX_LWM2M_RESOURCE;
- nx_lwm2m_resource_id: The ID of the Resource or the Instance.
- nx_lwm2m_resource_type: The type of the value, see below.
- nx_lwm2m_resource_value: The value of the Resource, depends on the type of the value.
The following type of values are defined :
NX_LWM2M_RESOURCE_NONE: Empty resource.
NX_LWM2M_RESOURCE_STRING: A null-terminated UTF-8 string value stored in nx_lwm2m_resource_stringdata.
NX_LWM2M_RESOURCE_INTEGER32: A 32-Bit Integer value stored in nx_lwm2m_resource_integer32data.
NX_LWM2M_RESOURCE_INTEGER64: A 64-Bit Integer value stored in nx_lwm2m_resource_integer64data.
NX_LWM2M_RESOURCE_FLOAT32: A 32-Bit Floating Point value stored in nx_lwm2m_resource_float32data.
NX_LWM2M_RESOURCE_FLOAT64: A 64-Bit Floating Point value stored in nx_lwm2m_resource_float64data.
NX_LWM2M_RESOURCE_BOOLEAN: A Boolean value stored in nx_lwm2m_resource_booleandata.
NX_LWM2M_RESOURCE_OPAQUE: An Opaque value defined by nx_lwm2m_resource_bufferdata.
NX_LWM2M_RESOURCE_OBJLNK: An Object Link value stored in nx_lwm2m_resource_objlnkdata.
NX_LWM2M_RESOURCE_TLV: A TLV encoded value defined by nx_lwm2m_resource_bufferdata.
NX_LWM2M_RESOURCE_TEXT: A Plain-Text encoded value defined by nx_lwm2m_resource_bufferdata.
NX_LWM2M_RESOURCE_MULTIPLE: A Multiple Resource defined by nx_lwm2m_resource_multipledata. nx_lwm2m_resource_multiple_ptr is a pointer to an array of NX_LWM2M_RESOURCE structures containing information about each Resource Instances.
NX_LWM2M_RESOURCE_MULTIPLE_TLV: A Multiple Resource defined by nx_lwm2m_resource_multipledata. nx_lwm2m_resource_multiple_ptr is a pointer to a TLV encoded buffer.
Convenience functions are provided for retrieving the value and checking its type, the application should never directly access the nx_lwm2m_resource_value field when getting a value from a NX_LWM2M_RESOURCE structure. The following functions are defined :
- nx_lwm2m_resource_get_: Get a value with the given type.
- nx_lwm2m_resource_multiple_get_: Get a value with the given type from a Multiple Resource.
The macro NX_LWM2M_RESOURCE_IS_MULTIPLE(type) can be used to check if a resource type is a Multiple Resource.
Object Implementation
The LWM2M Client implements the mandatory OMA LWM2M Objects: Security (0), Server (1), Access Control (2) and Device (3). Other device specific objects must be implemented by the application.
Two data structures are used to define an Object: the NX_LWM2M_OBJECT structure defines the Object implementation, including the Object ID and the object methods, and the NX_LWM2M_OBJECT_INSTANCE structure contains the data of an Object Instance.
The NX_LWM2M_OBJECT structure has the following definition:
typedef struct NX_LWM2M_OBJECT_STRUCT
{
NX_LWM2M_OBJECT * nx_lwm2m_object_next;
NX_LWM2M_ID nx_lwm2m_object_id;
UINT (*nx_lwm2m_object_read)(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, UINT num_values,
NX_LWM2M_RESOURCE *values);
UINT (*nx_lwm2m_object_discover)(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, UINT *num_resources,
NX_LWM2M_RESOURCE_INFO *resources);
UINT (*nx_lwm2m_object_write)(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, UINT num_values, const
NX_LWM2M_RESOURCE *values, UINT write_op);
UINT (*nx_lwm2m_object_execute)(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id,
const CHAR *args_ptr, UINT args_length);
UINT (*nx_lwm2m_object_create)(NX_LWM2M_OBJECT * object_ptr,
NX_LWM2M_ID instance_id, UINT num_values, const NX_LWM2M_RESOURCE
*values, NX_LWM2M_OBJECT_INSTANCE **instance_ptr);
UINT (*nx_lwm2m_object_delete)(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr);
NX_LWM2M_OBJECT_INSTANCE * nx_lwm2m_object_instances;
} NX_LWM2M_OBJECT;
- nx_lwm2m_object_next: The next object in the list.
- nx_lwm2m_object_id: The Object ID.
- nx_lwm2m_object_read: The 'Read' method, see below.
- nx_lwm2m_object_discover: The 'Discover' method, see below.
- nx_lwm2m_object_write: The 'Write' method, see below.
- nx_lwm2m_object_execute: The 'Execute' method, see below.
- nx_lwm2m_object_create: The 'Create' method, see below.
- nx_lwm2m_object_delete: The 'Delete' method, see below.
- nx_lwm2m_object_instances: The NULL-terminated list of object instances.
The NX_LWM2M_OBJECT_INSTANCE structure has the following definition:
typedef struct NX_LWM2M_OBJECT_INSTANCE_STRUCT
{
NX_LWM2M_OBJECT_INSTANCE * nx_lwm2m_object_instance_next;
NX_LWM2M_ID nx_lwm2m_object_instance_id;
} NX_LWM2M_OBJECT_INSTANCE;
- nx_lwm2m_object_instance_next: The next instance in the list.
- nx_lwm2m_object_instance_id: The Object Instance ID.
The Object must implement the methods corresponding to the operations defined by the LWM2M Device Management Interface: 'Read', 'Discover', 'Write', 'Execute', 'Create' and 'Delete'. The 'Create' and 'Delete' methods can be set to NULL if the object doesn't support dynamic creation of instances.
The 'Read' Method
The 'Read' method is used to read Resource values from an Object Instance, the function has the following definition:
UINT nx_lwm2m_object_read(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, UINT num_values,
NX_LWM2M_RESOURCE *values_ptr);
The input parameters are defined as follows:
object_ptr: Pointer to the Object implementation.
instance_ptr: Pointer to the Object Instance.
num_values: The number of resources to read.
values_ptr: Pointer to an array of NX_LWM2M_RESOURCE containing the IDs of the resources to read. On return the array is filled with the corresponding types and values.
The 'Discover' Method
The 'Discover' method is used to retrieve the list of all Resources implemented by an Object, the function has the following definition:
UINT nx_lwm2m_object_discover(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, UINT *num_resources_ptr,
NX_LWM2M_RESOURCE_INFO *resources_ptr);
The input parameters are defined as follows:
object_ptr: Pointer to the Object implementation.
instance_ptr: Pointer to the Object Instance.
num_resources_ptr: On input the size of the destination buffer, on output the number of elements writen to the buffer.
resources_ptr: Pointer to the destination buffer.
The resource information is returned in a NX_LWM2M_RESOURCE_INFO structure defined as follows:
typedef struct NX_LWM2M_RESOURCE_INFO_STRUCT
{
NX_LWM2M_ID nx_lwm2m_resource_info_id;
USHORT nx_lwm2m_resource_info_flags;
UINT nx_lwm2m_resource_info_dim;
} NX_LWM2M_RESOURCE_INFO;
nx_lwm2m_resource_info_id: The ID of the Resource.
nx_lwm2m_resource_info_flags: See below.
nx_lwm2m_resource_info_dim: The dimension of Multiple Resource if the flag NX_LWM2M_RESOURCE_INFO_MULTIPLE is set.
The field nx_lwm2m_resource_flags can have to the following values:
0: Single readable resource.
NX_LWM2M_RESOURCE_INFO_MULTIPLE: Multiple Resource, nx_lwm2m_resource_info_dim must be defined.
NX_LWM2M_RESOURCE_INFO_EXECUTABLE: Executable or Non-Readable Resource.
The 'Write' Method
The 'Write' method is used to update or replace resources of an Object Instance, the function has the following definition:
UINT nx_lwm2m_object_write(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, UINT num_values,
const NX_LWM2M_RESOURCE *values_ptr, UINT write_op);
The input parameters are defined as follows:
- object_ptr: Pointer to the Object implementation.
- instance_ptr: Pointer to the Object Instance.
- num_values: The number of resources to write.
- values_ptr: Pointer to the resources values.
- write_op: The type of write operations.
The following write operations can be specified to the write_op parameter :
0 — Partial Update: adds or updates Resources provided in the new value and leaves other existing Resources unchanged,
NX_LWM2M_OBJECT_WRITE_REPLACE_INSTANCE — Replace Instance: replaces the Object Instance with the new provided resource values.
NX_LWM2M_OBJECT_WRITE_REPLACE_RESOURCE — Replace Resource: replaces the Resources with the new provided resource values (used to replace Multiple Resources).
NX_LWM2M_OBJECT_WRITE_CREATE — Create Instance: initializes the newly created Object Instance with the provided resource values (called from the nx_lwm2m_object_create method).
NX_LWM2M_OBJECT_WRITE_BOOTSTRAP — Bootstrap Write: called during Bootstrap sequence.
The 'Execute' Method
The 'Execute' method implements the execution of an Object Resource, the function has the following definition:
UINT nx_lwm2m_object_execute(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id,
const CHAR *arguments_ptr);
The input parameters are defined as follows:
- object_ptr: Pointer to the Object implementation
- instance_ptr: Pointer to the Object Instance.
- resource_id: The Resource ID.
- arguments_ptr: Pointer to the arguments of the execute operation. Can be NULL if arguments_length is zero.
- arguments_length: The length of the arguments.
The function must return NX_LWM2M_NOT_FOUND if the Resource ID doesn't exist, or NX_LWM2M_METHOD_NOT_ALLOWED if it doesn't support execution.
The 'Create' Method
The 'Create' method implements the creation of a new Object Instance, the function has the following definition:
UINT nx_lwm2m_object_create(NX_LWM2M_OBJECT * object_ptr,
NX_LWM2M_ID instance_id, UINT num_values, const NX_LWM2M_RESOURCE *values_ptr,
NX_LWM2M_OBJECT_INSTANCE **instance_ptr, NX_LWM2M_BOOL bootstrap);
The input parameters are defined as follows:
- object_ptr: Pointer to the Object implementation.
- instance_id: The ID of the new Instance.
- num_values: The number of resources to initialize.
- values_ptr: Pointer to the resources values.
- instance_ptr: Pointer to the destination pointer of the created instance.
- bootstrap: True if called from bootstrap sequence.
The Object must allocate and initialiaze a new Object instance, using the provided list of resource values.
The 'Delete' Method
The 'Delete' method implements the deletion of an object instance, the function has the following definition:
UINT nx_lwm2m_object_delete(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr);
The input parameters are defined as follows:
- object_ptr: Pointer to the Object implementation.
- instance_ptr: Pointer to the Object Instance.
On success the Object must release the Object Instance data and any other resource allocated by the instance.
Adding Object Implementations and Instances to the LWM2M Client
The application can add new object implementation to the LWM2M Client by calling the nx_lwm2m_client_object_add service.
If the Object doesn't support dynamic creation of Instances, for example if it's a single instance only Object, the nx_lwm2m_object_instances field of the object structure should point to the list of the static instances structures.
If the Object supports dynamic instance creation, nx_lwm2m_object_instances should be set to NULL and the nx_lwm2m_client_object_create service should be used instead in order to call the 'Create' method of the object.
Example of LWM2M Client Application
The following code is an example of a simple LWM2M Client Application which implements a custom device consisting of a temperature sensor and a light switch.
The device allows a server to read the value of the temperature sensor and the boolean state of the light switch, and to set the light switch to on/off.
#include "nx_lwm2m_client.h"
/* Custom Object implementation */
/* Define the Custom Object Instance structure */
typedef struct
{
/* The LWM2M Object Instance */
NX_LWM2M_OBJECT_INSTANCE lwm2m;
/* Resources Data */
NX_LWM2M_FLOAT32 temperature;
NX_LWM2M_BOOL light;
} MYOBJECT_INSTANCE;
/* Define the Resources IDs */
#define MYOBJECT_RES_TEMPERATURE 0 /* temperature sensor */
#define MYOBJECT_RES_LIGHT 1 /* light switch */
/* Define the 'Read' Method */
UINT myobject_read(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr,
UINT num_values, NX_LWM2M_RESOURCE *values)
{
UINT i;
for (i=0; i<num_values; i++)
{
switch (values[i].nx_lwm2m_resource_id)
{
case MYOBJECT_RES_TEMPERATURE:
/* return the temperature value */
values[i].nx_lwm2m_resource_type = NX_LWM2M_RESOURCE_FLOAT32;
values[i].nx_lwm2m_resource_value.nx_lwm2m_resource_float32data =
((MYOBJECT_INSTANCE *) instance_ptr)->temperature;
break;
case MYOBJECT_RES_LIGHT:
/* return the state of the light switch */
values[i].nx_lwm2m_resource_type = NX_LWM2M_RESOURCE_BOOLEAN;
values[i].nx_lwm2m_resource_value.nx_lwm2m_resource_booleandata =
((MYOBJECT_INSTANCE *) instance_ptr)->light;
break;
default:
/* unknown resource ID */
return NX_LWM2M_NOT_FOUND;
}
}
return NX_SUCCESS;
}
/* Define the 'Discover' method */
UINT myobject_discover(NX_LWM2M_OBJECT *object_ptr, NX_LWM2M_OBJECT_INSTANCE *instance_ptr,
UINT *num_resources, NX_LWM2M_RESOURCE_INFO *resources)
{
if (*num_resources < 2)
{
return NX_LWM2M_BUFFER_TOO_SMALL;
}
/* return the list of supported resources IDs */
*num_resources = 2;
resources[0].nx_lwm2m_resource_info_id = MYOBJECT_RES_TEMPERATURE;
resources[0].nx_lwm2m_resource_info_flags = 0;
resources[1].nx_lwm2m_resource_info_id = MYOBJECT_RES_LIGHT;
resources[1].nx_lwm2m_resource_info_flags = 0;
return NX_SUCCESS;
}
/* Define the 'Write' method */
UINT myobject_write(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, UINT num_values,
const NX_LWM2M_RESOURCE *values, UINT flags)
{
UINT i;
for (i=0; i<num_values; i++)
{
UINT ret;
switch (values[i].nx_lwm2m_resource_id)
{
case MYOBJECT_RES_TEMPERATURE:
/* read-only resource */
return NX_LWM2M_METHOD_NOT_ALLOWED;
case MYOBJECT_RES_LIGHT:
/* assign boolean value */
ret = nx_lwm2m_resource_get_boolean(&values[i],
&((MYOBJECT_INSTANCE *) instance_ptr)->light);
if (ret != NX_SUCCESS)
{
/* invalid value type */
return ret;
}
break;
default:
/* unknown resource ID */
return NX_LWM2M_NOT_FOUND;
}
}
return NX_SUCCESS;
}
/* Define the 'Execute' method */
UINT myobject_execute(NX_LWM2M_OBJECT *object_ptr,
NX_LWM2M_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id,
const CHAR *args_ptr, UINT args_length)
{
switch (resource_id)
{
case MYOBJECT_RES_TEMPERATURE:
case MYOBJECT_RES_LIGHT:
/* read-only resource */
return NX_LWM2M_METHOD_NOT_ALLOWED;
default:
/* unknown resource ID */
return NX_LWM2M_NOT_FOUND;
}
}
/* NetX data */
NX_IP ip;
NX_PACKET_POOL packet_pool;
/* LWM2M Client data */
NX_LWM2M_CLIENT client;
ULONG client_stack[4096 / sizeof(ULONG)];
NX_LWM2M_CLIENT_SESSION session;
/* Custom Object Data */
NX_LWM2M_OBJECT myobject;
MYOBJECT_INSTANCE myinstance;
/* Define the session state callback */
void session_callback(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT state)
{
switch (state)
{
case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_FINISHED:
/* Bootstrap session done, we can register to the LWM2M Server */
{
NX_LWM2M_ID security_id;
/* find the Security Object Instance of the LWM2M Server */
security_id = NX_LWM2M_RESERVED_ID;
while (nx_lwm2m_client_object_instance_get_next(&client,
NX_LWM2M_SECURITY_OBJECT_ID, &security_id) == NX_SUCCESS)
{
NX_LWM2M_RESOURCE res[3];
/* retrieve instance data: */
/* Bootstrap server flag */
res[0].nx_lwm2m_resource_id = NX_LWM2M_SECURITY_BOOTSTRAP_ID;
/* URI of server */
res[1].nx_lwm2m_resource_id = NX_LWM2M_SECURITY_URI_ID;
/* Short Server ID */
res[2].nx_lwm2m_resource_id = NX_LWM2M_SECURITY_SHORT_SERVER_ID;
/* Read Object Instance: */
nx_lwm2m_client_object_read(&client,
NX_LWM2M_SECURITY_OBJECT_ID, security_id, 3, res);
/* Not a bootstrap server? */
if (!res[0].nx_lwm2m_resource_value.nx_lwm2m_resource_booleandata)
{
ULONG ip_addr;
UINT udp_port;
/* get IP address and UDP port from server URI */
parse_uri(res[1].nx_lwm2m_resource_value.nx_lwm2m_resource_stringdata, &ip_addr, &udp_port);
/* Start registration to the LWM2M server */
nx_lwm2m_client_session_register(&session,
(NX_LWM2M_ID) res[2].nx_lwm2m_resource_value.
nx_lwm2m_resource_integer32data,
ip_addr, udp_port);
break;
}
}
}
break;
case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR:
/* Failed to Bootstrap the LWM2M Client. */
break;
case NX_LWM2M_CLIENT_SESSION_REGISTERED:
/* Registration to the LWM2M Client done. */
break;
case NX_LWM2M_CLIENT_SESSION_ERROR:
/* Failed to register to the LWM2M Client. */
break;
}
}
/* Application main thread */
void application_thread(ULONG info)
{
NX_LWM2M_RESOURCE res[4];
NX_LWM2M_ID security_id;
/* Create the LWM2M client */
nx_lwm2m_client_create(&client, &ip, &packet_pool, NX_LWM2M_COAP_PORT,
"mylwm2mclient", NULL, NX_LWM2M_BINDING_U,
client_stack, sizeof(client_stack));
/* Define our custom object */
myobject.nx_lwm2m_object_id = 1024;
myobject.nx_lwm2m_object_read = myobject_read;
myobject.nx_lwm2m_object_discover = myobject_discover;
myobject.nx_lwm2m_object_write = myobject_write;
myobject.nx_lwm2m_object_execute = myobject_execute;
myobject.nx_lwm2m_object_create = NULL;
myobject.nx_lwm2m_object_delete = NULL;
/* Define a single instance */
myobject.nx_lwm2m_object_instances = (NX_LWM2M_OBJECT_INSTANCE *) &myinstance;
myinstance.lwm2m.nx_lwm2m_object_instance_id = 0;
myinstance.lwm2m.nx_lwm2m_object_instance_next = NULL;
myinstance.temperature = 22.5f;
myinstance.light = NX_FALSE;
/* Add the object to the LWM2M Client */
nx_lwm2m_client_object_add(&client, &myobject);
/* Create a security entry for the bootstrap server */
security_id = 0;
/* set the URI of the server */
res[0].nx_lwm2m_resource_id = NX_LWM2M_SECURITY_URI_ID;
res[0].nx_lwm2m_resource_type = NX_LWM2M_RESOURCE_STRING;
res[0].nx_lwm2m_resource_value.nx_lwm2m_resource_stringdata = "coap://1.2.3.4";
/* set the Bootstrap flag */
res[1].nx_lwm2m_resource_id = NX_LWM2M_SECURITY_BOOTSTRAP_ID;
res[1].nx_lwm2m_resource_type = NX_LWM2M_RESOURCE_BOOLEAN;
res[1].nx_lwm2m_resource_value.nx_lwm2m_resource_booleandata = NX_TRUE;
/* set the security mode */
res[2].nx_lwm2m_resource_id = NX_LWM2M_SECURITY_MODE_ID;
res[2].nx_lwm2m_resource_type = NX_LWM2M_RESOURCE_INTEGER32;
res[2].nx_lwm2m_resource_value.nx_lwm2m_resource_integer32data =
NX_LWM2M_SECURITY_MODE_NOSEC;
/* set the Hold Off timer */
res[3].nx_lwm2m_resource_id = NX_LWM2M_SECURITY_HOLD_OFF_ID;
res[3].nx_lwm2m_resource_type = NX_LWM2M_RESOURCE_INTEGER32;
res[3].nx_lwm2m_resource_value.nx_lwm2m_resource_integer32data = 10;
nx_lwm2m_client_object_create(&client, NX_LWM2M_SECURITY_OBJECT_ID,
&security_id, 4, res);
/* Create a session */
nx_lwm2m_client_session_create(&session, &client, session_callback);
/* start bootstrap session */
nx_lwm2m_client_session_bootstrap(&session, security_id,
IP_ADDRESS(1, 2, 3, 4), 5683);
/* Application main loop */
while (1)
{
/* ...application code... */
}
/* Terminate the LWM2M Client */
nx_lwm2m_client_delete(&client);
}