#coap-message #coap #environments #low-level #building-block #bare-metal

no-std coap-lite

A lightweight CoAP message manipulation crate, ideal for embedded environments

25 releases

0.12.0 Apr 29, 2024
0.11.5 Feb 25, 2024
0.11.4 Jan 20, 2024
0.11.3 Aug 12, 2023
0.3.0 Sep 12, 2019

#62 in Embedded development

Download history 1623/week @ 2024-03-14 2920/week @ 2024-03-21 2409/week @ 2024-03-28 2044/week @ 2024-04-04 2427/week @ 2024-04-11 2448/week @ 2024-04-18 2488/week @ 2024-04-25 1901/week @ 2024-05-02 2138/week @ 2024-05-09 2268/week @ 2024-05-16 2392/week @ 2024-05-23 2712/week @ 2024-05-30 2819/week @ 2024-06-06 2237/week @ 2024-06-13 3043/week @ 2024-06-20 2058/week @ 2024-06-27

10,863 downloads per month
Used in 6 crates


3.5K SLoC


Latest version Documentation License

A lightweight low-level CoAP message manipulation crate.

Its goal is to be compliant with the CoAP standards and to provide a building block for libraries (e.g. coap) and applications.

coap-lite supports #![no_std] and embedded environments.

It was originally based on the improved low-level message handling code from the coap crate as well as rust-async-coap, made to work in bare metal environments.

Supported RFCs


This crate provides several types that can be used to build, modify and encode/decode CoAP messages to/from their byte representation.

Note for no_std users: it does require allocation, so you might have to set a global allocator depending on your target.


The following example uses std::net::UdpSocket to send the UDP packet but you can use anything, e.g. smoltcp for embedded.

use coap_lite::{
    CoapRequest, RequestType as Method
use std::net::{SocketAddr, UdpSocket};

fn main() {
    let mut request: CoapRequest<SocketAddr> = CoapRequest::new();


    let socket = UdpSocket::bind("").unwrap();

    let packet = request.message.to_bytes().unwrap();
    socket.send_to(&packet[..], "").expect("Could not send the data");


use coap_lite::{CoapRequest, Packet};
use std::net::{UdpSocket};

fn main() {
    let socket = UdpSocket::bind("").unwrap();
    let mut buf = [0; 100];
    let (size, src) = socket.recv_from(&mut buf).expect("Didn't receive data");

    println!("Payload {:x?}", &buf[..size]);

    let packet = Packet::from_bytes(&buf[..size]).unwrap();
    let request = CoapRequest::from_packet(packet, src);

    let method = request.get_method().clone();
    let path = request.get_path();

    println!("Received CoAP request '{:?} {}' from {}", method, path, src);

    let mut response = request.response.unwrap();
    response.message.payload = b"OK".to_vec();

    let packet = response.message.to_bytes().unwrap();
    socket.send_to(&packet[..], &src).expect("Could not send the data");

Low-level binary conversion

use coap_lite::{
    CoapOption, MessageClass, MessageType,
    Packet, RequestType, ResponseType,

let mut request = Packet::new();
request.header.message_id = 23839;
request.header.code = MessageClass::Request(RequestType::Get);
request.set_token(vec![0, 0, 57, 116]);
request.add_option(CoapOption::UriHost, b"localhost".to_vec());
request.add_option(CoapOption::UriPath, b"tv1".to_vec());
        0x44, 0x01, 0x5D, 0x1F, 0x00, 0x00, 0x39, 0x74, 0x39, 0x6C, 0x6F,
        0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, 0x83, 0x74, 0x76, 0x31,

let response = Packet::from_bytes(&[
    0x64, 0x45, 0x5D, 0x1F, 0x00, 0x00, 0x39, 0x74, 0xFF, 0x48, 0x65,
    0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21,
assert_eq!(23839, response.header.message_id);
assert_eq!(MessageType::Acknowledgement, response.header.get_type());
assert_eq!([0, 0, 57, 116], response.get_token()[..]);
assert_eq!(b"Hello World!", &response.payload[..]);


Licensed under either of

at your option.

This is a modification of the coap and rust-async-coap crates, their licenses are in LICENSE-3RD-PARTY.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.