1.. _lwm2m_interface:
2
3Lightweight M2M (LWM2M)
4#######################
5
6.. contents::
7    :local:
8    :depth: 2
9
10Overview
11********
12
13Lightweight Machine to Machine (LwM2M) is an application layer protocol
14designed with device management, data reporting and device actuation in mind.
15Based on CoAP/UDP, `LwM2M`_ is a
16`standard <http://openmobilealliance.org/release/LightweightM2M/>`_ defined by
17the Open Mobile Alliance and suitable for constrained devices by its use of
18CoAP packet-size optimization and a simple, stateless flow that supports a
19REST API.
20
21One of the key differences between LwM2M and CoAP is that an LwM2M client
22initiates the connection to an LwM2M server.  The server can then use the
23REST API to manage various interfaces with the client.
24
25LwM2M uses a simple resource model with the core set of objects and resources
26defined in the specification.
27
28Example LwM2M object and resources: Device
29******************************************
30
31*Object definition*
32
33.. list-table::
34   :header-rows: 1
35
36   * - Object ID
37     - Name
38     - Instance
39     - Mandatory
40
41   * - 3
42     - Device
43     - Single
44     - Mandatory
45
46*Resource definitions*
47
48``* R=Read, W=Write, E=Execute``
49
50.. list-table::
51   :header-rows: 1
52
53   * - ID
54     - Name
55     - OP\*
56     - Instance
57     - Mandatory
58     - Type
59
60   * - 0
61     - Manufacturer
62     - R
63     - Single
64     - Optional
65     - String
66
67   * - 1
68     - Model
69     - R
70     - Single
71     - Optional
72     - String
73
74   * - 2
75     - Serial number
76     - R
77     - Single
78     - Optional
79     - String
80
81   * - 3
82     - Firmware version
83     - R
84     - Single
85     - Optional
86     - String
87
88   * - 4
89     - Reboot
90     - E
91     - Single
92     - Mandatory
93     -
94
95   * - 5
96     - Factory Reset
97     - E
98     - Single
99     - Optional
100     -
101
102   * - 6
103     - Available Power Sources
104     - R
105     - Multiple
106     - Optional
107     - Integer 0-7
108
109   * - 7
110     - Power Source Voltage (mV)
111     - R
112     - Multiple
113     - Optional
114     - Integer
115
116   * - 8
117     - Power Source Current (mA)
118     - R
119     - Multiple
120     - Optional
121     - Integer
122
123   * - 9
124     - Battery Level %
125     - R
126     - Single
127     - Optional
128     - Integer
129
130   * - 10
131     - Memory Free (Kb)
132     - R
133     - Single
134     - Optional
135     - Integer
136
137   * - 11
138     - Error Code
139     - R
140     - Multiple
141     - Optional
142     - Integer 0-8
143
144   * - 12
145     - Reset Error
146     - E
147     - Single
148     - Optional
149     -
150
151   * - 13
152     - Current Time
153     - RW
154     - Single
155     - Optional
156     - Time
157
158   * - 14
159     - UTC Offset
160     - RW
161     - Single
162     - Optional
163     - String
164
165   * - 15
166     - Timezone
167     - RW
168     - Single
169     - Optional
170     - String
171
172   * - 16
173     - Supported Binding
174     - R
175     - Single
176     - Mandatory
177     - String
178
179   * - 17
180     - Device Type
181     - R
182     - Single
183     - Optional
184     - String
185
186   * - 18
187     - Hardware Version
188     - R
189     - Single
190     - Optional
191     - String
192
193   * - 19
194     - Software Version
195     - R
196     - Single
197     - Optional
198     - String
199
200   * - 20
201     - Battery Status
202     - R
203     - Single
204     - Optional
205     - Integer 0-6
206
207   * - 21
208     - Memory Total (Kb)
209     - R
210     - Single
211     - Optional
212     - Integer
213
214   * - 22
215     - ExtDevInfo
216     - R
217     - Multiple
218     - Optional
219     - ObjLnk
220
221The server could query the ``Manufacturer`` resource for ``Device`` object
222instance 0 (the default and only instance) by sending a ``READ 3/0/0``
223operation to the client.
224
225The full list of registered objects and resource IDs can be found in the
226`LwM2M registry`_.
227
228Zephyr's LwM2M library lives in the :zephyr_file:`subsys/net/lib/lwm2m`, with a
229client sample in :zephyr_file:`samples/net/lwm2m_client`.  For more information
230about the provided sample see: :zephyr:code-sample:`lwm2m-client`. The sample can be
231configured to use normal unsecure network sockets or sockets secured via DTLS.
232
233The Zephyr LwM2M library implements the following items:
234
235* engine to process networking events and core functions
236* RD client which performs BOOTSTRAP and REGISTRATION functions
237* SenML CBOR, SenML JSON, CBOR, TLV, JSON, and plain text formatting functions
238* LwM2M Technical Specification Enabler objects such as Security, Server,
239  Device, Firmware Update, etc.
240* Extended IPSO objects such as Light Control, Temperature Sensor, and Timer
241
242By default, the library implements `LwM2M specification 1.0.2`_ and can be set to
243`LwM2M specification 1.1.1`_ with a Kconfig option.
244
245For more information about LwM2M visit `OMA Specworks LwM2M`_.
246
247Sample usage
248************
249
250To use the LwM2M library, start by creating an LwM2M client context
251:c:struct:`lwm2m_ctx` structure:
252
253.. code-block:: c
254
255	/* LwM2M client context */
256	static struct lwm2m_ctx client;
257
258Create callback functions for LwM2M resource executions:
259
260.. code-block:: c
261
262	static int device_reboot_cb(uint16_t obj_inst_id, uint8_t *args,
263				    uint16_t args_len)
264	{
265		LOG_INF("Device rebooting.");
266		LOG_PANIC();
267		sys_reboot(0);
268		return 0; /* won't reach this */
269	}
270
271The LwM2M RD client can send events back to the sample.  To receive those
272events, setup a callback function:
273
274.. code-block:: c
275
276	static void rd_client_event(struct lwm2m_ctx *client,
277				    enum lwm2m_rd_client_event client_event)
278	{
279		switch (client_event) {
280
281		case LWM2M_RD_CLIENT_EVENT_NONE:
282			/* do nothing */
283			break;
284
285		case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE:
286			LOG_DBG("Bootstrap registration failure!");
287			break;
288
289		case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE:
290			LOG_DBG("Bootstrap registration complete");
291			break;
292
293		case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE:
294			LOG_DBG("Bootstrap transfer complete");
295			break;
296
297		case LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE:
298			LOG_DBG("Registration failure!");
299			break;
300
301		case LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE:
302			LOG_DBG("Registration complete");
303			break;
304
305		case LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT:
306			LOG_DBG("Registration timeout!");
307			break;
308
309		case LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE:
310			LOG_DBG("Registration update complete");
311			break;
312
313		case LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE:
314			LOG_DBG("Deregister failure!");
315			break;
316
317		case LWM2M_RD_CLIENT_EVENT_DISCONNECT:
318			LOG_DBG("Disconnected");
319			break;
320
321		case LWM2M_RD_CLIENT_EVENT_REG_UPDATE:
322			LOG_DBG("Registration update");
323			break;
324
325		case LWM2M_RD_CLIENT_EVENT_DEREGISTER:
326			LOG_DBG("Deregistration client");
327			break;
328
329		}
330	}
331
332Next we assign ``Security`` resource values to let the client know where and how
333to connect as well as set the ``Manufacturer`` and ``Reboot`` resources in the
334``Device`` object with some data and the callback we defined above:
335
336.. code-block:: c
337
338	/*
339	 * Server URL of default Security object = 0/0/0
340	 * Use leshan.eclipse.org server IP (5.39.83.206) for connection
341	 */
342	lwm2m_set_string(&LWM2M_OBJ(0, 0, 0), "coap://5.39.83.206");
343
344	/*
345	 * Security Mode of default Security object = 0/0/2
346	 * 3 = NoSec mode (no security beware!)
347	 */
348	lwm2m_set_u8(&LWM2M_OBJ(0, 0, 2), 3);
349
350	#define CLIENT_MANUFACTURER "Zephyr Manufacturer"
351
352	/*
353	 * Manufacturer resource of Device object = 3/0/0
354	 * We use lwm2m_set_res_data() function to set a pointer to the
355	 * CLIENT_MANUFACTURER string.
356	 * Note the LWM2M_RES_DATA_FLAG_RO flag which stops the engine from
357	 * trying to assign a new value to the buffer.
358	 */
359	lwm2m_set_res_data(&LWM2M_OBJ(3, 0, 0), CLIENT_MANUFACTURER,
360			   sizeof(CLIENT_MANUFACTURER),
361			   LWM2M_RES_DATA_FLAG_RO);
362
363	/* Reboot resource of Device object = 3/0/4 */
364	lwm2m_register_exec_callback(&LWM2M_OBJ(3, 0, 4), device_reboot_cb);
365
366Lastly, we start the LwM2M RD client (which in turn starts the LwM2M engine).
367The second parameter of :c:func:`lwm2m_rd_client_start` is the client
368endpoint name.  This is important as it needs to be unique per LwM2M server:
369
370.. code-block:: c
371
372	(void)memset(&client, 0x0, sizeof(client));
373	lwm2m_rd_client_start(&client, "unique-endpoint-name", 0, rd_client_event);
374
375.. _lwm2m_security:
376
377LwM2M security modes
378********************
379
380The Zephyr LwM2M library can be used either without security or use DTLS to secure the communication channel.
381When using DTLS with the LwM2M engine, PSK (Pre-Shared Key) and X.509 certificates are the security modes that can be used to secure the communication.
382The engine uses LwM2M Security object (Id 0) to read the stored credentials and feed keys from the security object into
383the TLS credential subsystem, see :ref:`secure sockets documentation <secure_sockets_interface>`.
384Enable the :kconfig:option:`CONFIG_LWM2M_DTLS_SUPPORT` Kconfig option to use the security.
385
386Depending on the selected mode, the security object must contain following data:
387
388PSK
389  Security Mode (Resource ID 2) set to zero (Pre-Shared Key mode).
390  Identity (Resource ID 3) contains PSK ID in binary form.
391  Secret key (Resource ID 5) contains the PSK key in binary form.
392  If the key or identity is provided as a hex string, it must be converted to binary before storing into the security object.
393
394X509
395  When X509 certificates are used, set Security Mode (ID 2) to ``2`` (Certificate mode).
396  Identity (ID 3) is used to store the client certificate and Secret key (ID 5) must have a private key associated with the certificate.
397  Server Public Key resource (ID 4) must contain a server certificate or CA certificate used to sign the certificate chain.
398  If the :kconfig:option:`CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT` Kconfig option is enabled, certificates and private key can be entered in PEM format.
399  Otherwise, they must be in binary DER format.
400
401NoSec
402  When no security is used, set Security Mode (Resource ID 2) to ``3`` (NoSec).
403
404In all modes, Server URI resource (ID 0) must contain the full URI for the target server.
405When DNS names are used, the DNS resolver must be enabled.
406
407LwM2M stack provides callbacks in the :c:struct:`lwm2m_ctx` structure.
408They are used to feed keys from the LwM2M security object into the TLS credential subsystem.
409By default, these callbacks can be left as NULL pointers, in which case default callbacks are used.
410When an external TLS stack, or non-default socket options are required, you can overwrite the :c:func:`lwm2m_ctx.load_credentials` or :c:func:`lwm2m_ctx.set_socketoptions` callbacks.
411
412An example of setting up the security object for PSK mode:
413
414.. code-block:: c
415
416	/* "000102030405060708090a0b0c0d0e0f" */
417	static unsigned char client_psk[] = {
418		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
419		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
420	};
421
422	static const char client_identity[] = "Client_identity";
423
424	lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 0), "coaps://lwm2m.example.com");
425	lwm2m_set_u8(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 2), LWM2M_SECURITY_PSK);
426	/* Set the client identity as a string, but this could be binary as well */
427	lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 3), client_identity);
428	/* Set the client pre-shared key (PSK) */
429	lwm2m_set_opaque(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 5), client_psk, sizeof(client_psk));
430
431An example of setting up the security object for X509 certificate mode:
432
433.. code-block:: c
434
435	static const char certificate[] = "-----BEGIN CERTIFICATE-----\nMIIB6jCCAY+gAw...";
436	static const char key[] = "-----BEGIN EC PRIVATE KEY-----\nMHcCAQ...";
437	static const char root_ca[] = "-----BEGIN CERTIFICATE-----\nMIIBaz...";
438
439	lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 0), "coaps://lwm2m.example.com");
440	lwm2m_set_u8(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 2), LWM2M_SECURITY_CERT);
441	lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 3), certificate);
442	lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 5), key);
443	lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 5), root_ca);
444
445Before calling :c:func:`lwm2m_rd_client_start` assign the tls_tag # where the
446LwM2M library should store the DTLS information prior to connection (normally a
447value of 1 is ok here).
448
449.. code-block:: c
450
451	(void)memset(&client, 0x0, sizeof(client));
452	client.tls_tag = 1; /* <---- */
453	lwm2m_rd_client_start(&client, "endpoint-name", 0, rd_client_event);
454
455For a more detailed LwM2M client sample see: :zephyr:code-sample:`lwm2m-client`.
456
457Multi-thread usage
458******************
459Writing a value to a resource can be done using functions like lwm2m_set_u8. When writing
460to multiple resources, the function lwm2m_registry_lock will ensure that the
461client halts until all writing operations are finished:
462
463.. code-block:: c
464
465  lwm2m_registry_lock();
466  lwm2m_set_u32(&LWM2M_OBJ(1, 0, 1), 60);
467  lwm2m_set_u8(&LWM2M_OBJ(5, 0, 3), 0);
468  lwm2m_set_f64(&LWM2M_OBJ(3303, 0, 5700), value);
469  lwm2m_registry_unlock();
470
471This is especially useful if the server is composite-observing the resources being
472written to. Locking will then ensure that the client only updates and sends notifications
473to the server after all operations are done, resulting in fewer messages in general.
474
475Support for time series data
476****************************
477
478LwM2M version 1.1 adds support for SenML CBOR and SenML JSON data formats. These data formats add
479support for time series data. Time series formats can be used for READ, NOTIFY and SEND operations.
480When data cache is enabled for a resource, each write will create a timestamped entry in a cache,
481and its content is then returned as a content in in READ, NOTIFY or SEND operation for a given
482resource.
483
484Data cache is only supported for resources with a fixed data size.
485
486Supported resource types:
487
488* Signed and unsigned 8-64-bit integers
489* Float
490* Boolean
491
492Enabling and configuring
493========================
494
495Enable data cache by selecting :kconfig:option:`CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT`.
496Application needs to allocate an array of :c:struct:`lwm2m_time_series_elem` structures and then
497enable the cache by calling :c:func:`lwm2m_engine_enable_cache` for a given resource. Earch resource
498must be enabled separately and each resource needs their own storage.
499
500.. code-block:: c
501
502  /* Allocate data cache storage */
503  static struct lwm2m_time_series_elem temperature_cache[10];
504  /* Enable data cache */
505  lwm2m_engine_enable_cache(LWM2M_PATH(IPSO_OBJECT_TEMP_SENSOR_ID, 0, SENSOR_VALUE_RID),
506          temperature_cache, ARRAY_SIZE(temperature_cache));
507
508LwM2M engine have room for four resources that have cache enabled. Limit can be increased by
509changing :kconfig:option:`CONFIG_LWM2M_MAX_CACHED_RESOURCES`. This affects a static memory usage of
510engine.
511
512Data caches depends on one of the SenML data formats
513:kconfig:option:`CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT` or
514:kconfig:option:`CONFIG_LWM2M_RW_SENML_JSON_SUPPORT` and needs :kconfig:option:`CONFIG_POSIX_CLOCK`
515so it can request a timestamp from the system and :kconfig:option:`CONFIG_RING_BUFFER` for ring
516buffer.
517
518Read and Write operations
519=========================
520
521Full content of data cache is written into a payload when any READ, SEND or NOTIFY operation
522internally reads the content of a given resource. This has a side effect that any read callbacks
523registered for a that resource are ignored when cache is enabled.
524Data is written into a cache when any of the ``lwm2m_set_*`` functions are called. To filter
525the data entering the cache, application may register a validation callback using
526:c:func:`lwm2m_register_validate_callback`.
527
528Limitations
529===========
530
531Cache size should be manually set so small that the content can fit normal packets sizes.
532When cache is full, new values are dropped.
533
534LwM2M engine and application events
535***********************************
536
537The Zephyr LwM2M engine defines events that can be sent back to the application through callback
538functions.
539The engine state machine shows when the events are spawned.
540Events depicted in the diagram are listed in the table.
541The events are prefixed with ``LWM2M_RD_CLIENT_EVENT_``.
542
543.. figure:: images/lwm2m_engine_state_machine.png
544    :alt: LwM2M engine state machine
545
546    State machine for the LwM2M engine
547
548.. list-table:: LwM2M RD Client events
549   :widths: auto
550   :header-rows: 1
551
552   * - Event ID
553     - Event Name
554     - Description
555     - Actions
556   * - 0
557     - NONE
558     - No event
559     - Do nothing
560   * - 1
561     - BOOTSTRAP_REG_FAILURE
562     - Bootstrap registration failed.
563       Occurs if there is a timeout or failure in bootstrap registration.
564     - Retry bootstrap
565   * - 2
566     - BOOTSTRAP_REG_COMPLETE
567     - Bootstrap registration complete.
568       Occurs after successful bootstrap registration.
569     - No actions needed
570   * - 3
571     - BOOTSTRAP_TRANSFER_COMPLETE
572     - Bootstrap finish command received from the server.
573     - No actions needed, client proceeds to registration.
574   * - 4
575     - REGISTRATION_FAILURE
576     - Registration to LwM2M server failed.
577       Occurs if there is a failure in the registration.
578     - Retry registration
579   * - 5
580     - REGISTRATION_COMPLETE
581     - Registration to LwM2M server successful.
582       Occurs after a successful registration reply from the LwM2M server
583       or when session resumption is used.
584     - No actions needed
585   * - 6
586     - REG_TIMEOUT
587     - Registration or registration update timeout.
588       Occurs if there is a timeout during registration.
589       NOTE: If registration fails without a timeout,
590       a full registration is triggered automatically and
591       no registration update failure event is generated.
592     - No actions needed, client proceeds to re-registration automatically.
593   * - 7
594     - REG_UPDATE_COMPLETE
595     - Registration update completed.
596       Occurs after successful registration update reply from the LwM2M server.
597     - No actions needed
598   * - 8
599     - DEREGISTER_FAILURE
600     - Deregistration to LwM2M server failed.
601       Occurs if there is a timeout or failure in the deregistration.
602     - No actions needed, client proceeds to idle state automatically.
603   * - 9
604     - DISCONNECT
605     - Disconnected from LwM2M server.
606       Occurs if there is a timeout during communication with server.
607       Also triggered after deregistration has been done.
608     - If connection is required, the application should restart the client.
609   * - 10
610     - QUEUE_MODE_RX_OFF
611     - Used only in queue mode, not actively listening for incoming packets.
612       In queue mode the client is not required to actively listen for the incoming packets
613       after a configured time period.
614     - No actions needed
615   * - 11
616     - ENGINE_SUSPENDED
617     - Indicate that client has now paused as a result of calling :c:func:`lwm2m_engine_pause`.
618       State machine is no longer running and the handler thread is suspended.
619       All timers are stopped so notifications are not triggered.
620     - Engine can be resumed by calling :c:func:`lwm2m_engine_resume`.
621   * - 12
622     - NETWORK_ERROR
623     - Sending messages to the network failed too many times.
624       If sending a message fails, it will be retried.
625       If the retry counter reaches its limits, this event will be triggered.
626     - No actions needed, client will do a re-registrate automatically.
627
628.. _lwm2m_shell:
629
630LwM2M shell
631***********
632For testing the client it is possible to enable Zephyr's shell and LwM2M specific commands which
633support changing the state of the client. Operations supported are read, write and execute
634resources. Client start, stop, pause and resume are also available. The feature is enabled by
635selecting :kconfig:option:`CONFIG_LWM2M_SHELL`. The shell is meant for testing so productions
636systems should not enable it.
637
638One imaginable scenario, where to use the shell, would be executing client side actions over UART
639when a server side tests would require those. It is assumed that not all tests are able to trigger
640required actions from the server side.
641
642.. code-block:: console
643
644  uart:~$ lwm2m
645  lwm2m - LwM2M commands
646  Subcommands:
647    send    :send PATHS
648            LwM2M SEND operation
649
650    exec    :exec PATH [PARAM]
651            Execute a resource
652
653    read    :read PATH [OPTIONS]
654            Read value from LwM2M resource
655            -x   Read value as hex stream (default)
656            -s   Read value as string
657            -b   Read value as bool (1/0)
658            -uX  Read value as uintX_t
659            -sX  Read value as intX_t
660            -f   Read value as float
661            -t   Read value as time_t
662
663    write   :write PATH [OPTIONS] VALUE
664            Write into LwM2M resource
665            -s   Write value as string (default)
666            -b   Write value as bool
667            -uX  Write value as uintX_t
668            -sX  Write value as intX_t
669            -f   Write value as float
670            -t   Write value as time_t
671
672    create  :create PATH
673            Create object instance
674
675    cache   :cache PATH NUM
676            Enable data cache for resource
677            PATH is LwM2M path
678            NUM how many elements to cache
679
680    start   :start EP_NAME [BOOTSTRAP FLAG]
681            Start the LwM2M RD (Registration / Discovery) Client
682            -b   Set the bootstrap flag (default 0)
683
684    stop    :stop [OPTIONS]
685            Stop the LwM2M RD (De-register) Client
686            -f   Force close the connection
687
688    update  :Trigger Registration Update of the LwM2M RD Client
689
690    pause   :LwM2M engine thread pause
691    resume  :LwM2M engine thread resume
692    lock    :Lock the LwM2M registry
693    unlock  :Unlock the LwM2M registry
694
695
696
697
698.. _lwm2m_api_reference:
699
700API Reference
701*************
702
703.. doxygengroup:: lwm2m_api
704
705.. _LwM2M:
706   https://www.omaspecworks.org/what-is-oma-specworks/iot/lightweight-m2m-lwm2m/
707
708.. _LwM2M registry:
709   http://www.openmobilealliance.org/wp/OMNA/LwM2M/LwM2MRegistry.html
710
711.. _OMA Specworks LwM2M:
712   https://www.omaspecworks.org/what-is-oma-specworks/iot/lightweight-m2m-lwm2m/
713
714.. _LwM2M specification 1.0.2:
715   http://openmobilealliance.org/release/LightweightM2M/V1_0_2-20180209-A/OMA-TS-LightweightM2M-V1_0_2-20180209-A.pdf
716
717.. _LwM2M specification 1.1.1:
718   http://openmobilealliance.org/release/LightweightM2M/V1_1_1-20190617-A/
719