4.1. Anjay initialization

First, let’s create a minimum build environment for our example client. We will be using a following directory structure:

example/
  ├── CMakeLists.txt
  └── src/
      └── main.c

Note that all code found in this tutorial is available under examples/tutorial/BC* in Anjay source directory. Each tutorial project follows the same project directory layout.

4.1.1. Build system

We are going to use CMake as a build system. Let’s create an initial minimal CMakeLists.txt:

cmake_minimum_required(VERSION 3.1)
project(anjay-bc-initialization C)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_EXTENSIONS OFF)

add_compile_options(-Wall -Wextra)

find_package(anjay REQUIRED)

add_executable(${PROJECT_NAME} src/main.c)
target_link_libraries(${PROJECT_NAME} PRIVATE anjay)

4.1.2. Hello World client code

Now, we can begin the actual client implementation. Simple program with instantiation of Anjay object is presented below:

#include <anjay/anjay.h>
#include <avsystem/commons/avs_log.h>

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;
    }

    anjay_event_loop_run(anjay, avs_time_duration_from_scalar(1, AVS_TIME_S));

    anjay_delete(anjay);
    return 0;
}

Note

Complete code of this example can be found in examples/tutorial/BC-Initialization subdirectory of main Anjay project repository.

4.1.3. Code analysis

Note

We recommend you to look at the doxygen generated API documentation if something isn’t immediately clear to you.

First, we call the anjay_new() function that initializes the client. It needs to be passed an anjay_configuration_t structure that contains basic runtime configuration of the client.

The example code above configures the basic values that are most essential:

  • endpoint_name sets the Endpoint Client Name - see Clients and servers.

  • in_buffer_size and out_buffer_size control sizes of the buffers used for network communication.

  • msg_cache_size sets the size of the message cache - this is not strictly necessary for the client to work, but it is used to internally cache responses so that retransmitted packets are properly handled as duplicates. The bigger this buffer, the older packets the library will be able to detect as retransmissions.

After initializing the library, anjay_event_loop_run() is called. This function doesn’t return unless there is a fatal error, instead acting as the main loop of the LwM2M client.

In more complicated applications, this function would typically be run in a dedicated thread, while other threads would perform tasks not directly related to LwM2M and communicate with the LwM2M thread when necessary.

Important

If you intend to run Anjay event loop in a dedicated thread, please make sure that the code is properly synchronized. The WITH_THREAD_SAFETY and WITH_SCHEDULER_THREAD_SAFE compile-time configuration options may be helpful in achieving this goal.

The second argument specifies the maximum time for which the loop is allowed to wait for incoming events in a single iteration - 1 second in this example. The shorter the time, the more responsive the loop will be in handling asynchronous requests (e.g. jobs scheduled from another threads), but the average CPU usage level of the main loop may be higher.

In case the event loop finishes, anjay_delete() - a function that cleans up all resources used by the client - is called.

4.1.4. Building and running

Let’s build our minimal client:

$ cmake . && make

If that succeeds, we can now run it. We need to pass an endpoint name as the program’s argument - this is not important now, but when we get to the point of being able to communicate with a server, this will be a name that the client uses to identify itself to the server. Please look into the brief description of LwM2M for details on recommended formats of the endpoint name.

A simple idea for generating an endpoint name is to use the local hostname:

$ ./anjay-bc-initialization urn:dev:os:$(hostname)

Important

Project will not be configured successfully until you install Anjay library, see Compiling client applications for details how to do it.

You will see only some logs and the application will appear to freeze - that’s because without any server configuration, there are no tasks to do. However, if you do not see “Could not create Anjay object” there, then Anjay was properly initialized. We will connect to LwM2M Server in the next steps.