4.2. Installing mandatory Objects
To connect to a LwM2M server and handle incoming packets, the client must support the following mandatory LwM2M Objects:
LwM2M Security (
/0
)LwM2M Server (
/1
)
Anjay provides pre-implemented modules for all two objects, making setup straightforward.
Note
Users can still provide their own implementation of these Objects if needed — Anjay remains fully flexible.
When Anjay is first instantiated (as in our previous hello world example), it has no knowledge about the Data Model, i.e., no LwM2M Objects are registered within it. You must explicitly install the required Objects, as shown below.
4.2.1. Installing Objects
Each LwM2M Object is defined by an instance of the anjay_dm_object_def_t
structure. To add support for a new Object, you’d need to:
fill the
anjay_dm_object_def_t
structure,implement appropriate callback functions,
register created object in Anjay.
However, for now, we are going to install our pre-implemented LwM2M Objects (Security, Server), so that you don’t have to worry about initializing the structure and object registration on your own. In case you are interested in this topic, Implementing standard Object section provides more information on this subject.
Use the following functions to install the Objects:
anjay_security_object_install()
anjay_server_object_install()
Important
To use these function you must include the following headers:
anjay/security.h
anjay/server.h
4.2.2. Setting up Server and Security Objects
This section shows how to implement and register the mandatory Objects: Security and Server. It builds upon the setup from the previous tutorial.
4.2.2.1. Security Object
The Security Object holds connection parameters for the LwM2M server. In this example, we configure a non-secure connection to the Coiote IoT Device Management platform. A secure connection setup will be described in a later section.
To use Coiote:
Create an account at avsystem.com/coiote-iot-device-management-platform.
Add your device entry in the Coiote interface using the following URI for the connection:
coap://eu.iot.avsystem.cloud:5683
If you are using another server, replace the URI with your target address.
// Installs Security Object and adds and instance of it.
// An instance of Security Object provides information needed to connect to
// LwM2M server.
static int setup_security_object(anjay_t *anjay) {
if (anjay_security_object_install(anjay)) {
return -1;
}
const anjay_security_instance_t security_instance = {
.ssid = 1,
.server_uri = "coap://eu.iot.avsystem.cloud:5683",
.security_mode = ANJAY_SECURITY_NOSEC
};
// Anjay will assign Instance ID automatically
anjay_iid_t security_instance_id = ANJAY_ID_INVALID;
if (anjay_security_object_add_instance(anjay, &security_instance,
&security_instance_id)) {
return -1;
}
return 0;
}
4.2.2.2. Server Object
The Server Object defines registration parameters like lifetime and binding mode.
// Installs Server Object and adds and instance of it.
// An instance of Server Object provides the data related to a LwM2M Server.
static int setup_server_object(anjay_t *anjay) {
if (anjay_server_object_install(anjay)) {
return -1;
}
const anjay_server_instance_t server_instance = {
// Server Short ID
.ssid = 1,
// Client will send Update message often than every 60 seconds
.lifetime = 60,
// Disable Default Minimum Period resource
.default_min_period = -1,
// Disable Default Maximum Period resource
.default_max_period = -1,
// Disable Disable Timeout resource
.disable_timeout = -1,
// Sets preferred transport to UDP
.binding = "U"
};
// Anjay will assign Instance ID automatically
anjay_iid_t server_instance_id = ANJAY_ID_INVALID;
if (anjay_server_object_add_instance(anjay, &server_instance,
&server_instance_id)) {
return -1;
}
return 0;
}
Both Security and Server instances are linked together by the Short Server ID
Resource (ssid
). That is why the ssid value must match between the Security
and Server instances.
4.2.2.3. Integrate Object Installation
Once the installation functions are implemented, call them from your main()
function:
int main(int argc, char *argv[]) {
if (argc != 2) {
avs_log(tutorial, ERROR, "usage: %s ENDPOINT_NAME", argv[0]);
return -1;
}
const anjay_configuration_t CONFIG = {
.endpoint_name = argv[1],
.in_buffer_size = 4000,
.out_buffer_size = 4000,
.msg_cache_size = 4000
};
anjay_t *anjay = anjay_new(&CONFIG);
if (!anjay) {
avs_log(tutorial, ERROR, "Could not create Anjay object");
return -1;
}
int result = 0;
// Setup necessary objects
if (setup_security_object(anjay) || setup_server_object(anjay)) {
result = -1;
}
if (!result) {
result = anjay_event_loop_run(
anjay, avs_time_duration_from_scalar(1, AVS_TIME_S));
}
anjay_delete(anjay);
return result;
}
Note
anjay_delete()
will automatically delete installed modules after
destruction of Anjay instance.
Note
Complete code of this example can be found in examples/tutorial/BC-MandatoryObjects subdirectory of main Anjay project repository.
4.2.2.3.1. Logs example
After running the client, you should see registration successful, location =
/rd/<server-dependent identifier>
once and registration successfully
updated
every 30 seconds in logs. It means, that the client has connected to
the server and successfully sends Update messages. You can now perform
operations like Read from the server side.
4.2.3. Application events
The example code shown above covers events managed internally by the Anjay library. However, most real-world applications also need to handle their own logic. How to implement application-specific functionality will be explained in the following sections.
4.2.4. Coiote experience
At this stage, you can log in to Coiote IoT Device Management and open the Device Center for your registered device to explore the platform functionality. Check the Data Model tab to see which LwM2M Objects are currently exposed. You will notice that the Server object is visible, but the Security object is not. This is expected behavior defined by the LwM2M specification — the Security object is neither readable nor discoverable from the device to protect sensitive configuration data.