Skip to content

Porting LWM2M to a new platform environment

Joakim Eriksson edited this page Dec 11, 2018 · 5 revisions

Porting Contiki-NG LWM2M to other OS:es

The Contiki-NG LWM2M implementation is possible to use without using uIP and Contiki-NG itself. This is useful in the case when using LWM2M over SMS or other non-IP based communication or when in need of a LWM2M stack in a OS where there is a IP/UDP stack.

Requirement for supporting CoAP and LWM2M from Contiki-NG

There are basically two needed things for getting the CoAP and LWM2M stack working:

  • periodic calls into a timer subsystem (the coap timer the is used for periodic maintenance)
  • handling input/output of the CoAP / LWM2M payload

Needed by implementations for any other transport then uIP.

  1. The coap timer needs to have a full implementation in order to keep all periodic activities working in CoAP and LWM2M. There is an example implementation in this repository that show how to implement coap timer on linux.
  typedef struct {
  void     (* init)(void);
  uint64_t (* uptime)(void);
  void     (* update)(void);
} coap_timer_driver_t;
  • init will be called to initialise the timer subsystem.
  • uptime returns milliseconds since boot.
  • update is called whenever the list of timers have changed if the implementation needs to setup scheduling of timer ISRs, etc to allow tickless operation.
  1. The coap_endpoint needs to be implemented (support for the addressing using this specific transport)
/**
 * \brief      Copy a CoAP endpoint from one memory area to another.
 *
 * \param dest A pointer to a CoAP endpoint to copy to.
 * \param src  A pointer to a CoAP endpoint to copy from.
 */
void coap_endpoint_copy(coap_endpoint_t *dest, const coap_endpoint_t *src);

/**
 * \brief      Compare two CoAP endpoints.
 *
 * \param e1   A pointer to the first CoAP endpoint.
 * \param e2   A pointer to the second CoAP endpoint.
 * \return     Non-zero if the endpoints are identical and zero otherwise.
 */
int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2);

/**
 * \brief      Print a CoAP endpoint via the logging module.
 *
 * \param ep   A pointer to the CoAP endpoint to log.
 */
void coap_endpoint_log(const coap_endpoint_t *ep);

/**
 * \brief      Print a CoAP endpoint.
 *
 * \param ep   A pointer to the CoAP endpoint to print.
 */
void coap_endpoint_print(const coap_endpoint_t *ep);

/**
 * \brief      Print a CoAP endpoint to a string. The output is always
 *             null-terminated unless size is zero.
 *
 * \param str  The string to write to.
 * \param size The max number of characters to write.
 * \param ep   A pointer to the CoAP endpoint to print.
 * \return     Returns the number of characters needed for the output
 *             excluding the ending null-terminator or negative if an
 *             error occurred.
 */
int  coap_endpoint_snprint(char *str, size_t size,
                           const coap_endpoint_t *ep);

/**
 * \brief      Parse a CoAP endpoint.
 *
 * \param text The string to parse.
 * \param size The max number of characters in the string.
 * \param ep   A pointer to the CoAP endpoint to write to.
 * \return     Returns non-zero if the endpoint was successfully parsed and
 *             zero otherwise.
 */
int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep);

/**
 * \brief      Check if a CoAP endpoint is secure (encrypted).
 *
 * \param ep   A pointer to a CoAP endpoint.
 * \return     Returns non-zero if the endpoint is secure and zero otherwise.
 */
int coap_endpoint_is_secure(const coap_endpoint_t *ep);

/**
 * \brief      Check if a CoAP endpoint is connected.
 *
 * \param ep   A pointer to a CoAP endpoint.
 * \return     Returns non-zero if the endpoint is connected and zero otherwise.
 */
int coap_endpoint_is_connected(const coap_endpoint_t *ep);

/**
 * \brief      Request a connection to a CoAP endpoint.
 *
 * \param ep   A pointer to a CoAP endpoint.
 * \return     Returns zero if an error occured and non-zero otherwise.
 */
int coap_endpoint_connect(coap_endpoint_t *ep);

/**
 * \brief      Request that any connection to a CoAP endpoint is discontinued.
 *
 * \param ep   A pointer to a CoAP endpoint.
 */
void coap_endpoint_disconnect(coap_endpoint_t *ep);
  1. Finally coap_transport needs to be implemented
/**
 * \brief      Returns a common data buffer that can be used when
 *             generating CoAP messages for transmission. The buffer
 *             size is at least COAP_MAX_PACKET_SIZE bytes.
 *
 *             In Contiki-NG, this corresponds to the uIP buffer.
 *
 * \return     A pointer to a data buffer where a CoAP message can be stored.
 */
uint8_t *coap_databuf(void);

/**
 * \brief      Send a message to the specified CoAP endpoint
 * \param ep   A pointer to a CoAP endpoint
 * \param data A pointer to data to send
 * \param len  The size of the data to send
 * \return     The number of bytes sent or negative if an error occurred.
 */
int coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len);

/**
 * \brief      Initialize the CoAP transport.
 *
 *             This function initializes the CoAP transport implementation and
 *             should only be called by the CoAP engine.
 */
void coap_transport_init(void);

Note that the CoAP transport also needs to call coap_receive() when a packet arrived. Typically this will be like:

  coap_receive(coap_src_endpoint(), coap_databuf(), coap_datalen());