coap-zero 0.3.0

CoAP protocol implementation for no_std without alloc
Documentation
// Copyright Open Logistics Foundation
//
// Licensed under the Open Logistics Foundation License 1.3.
// For details on the licensing terms, see the LICENSE file.
// SPDX-License-Identifier: OLFL-1.3

//! Sends two CONfirmable GET requests to "coap://coap.me:5683/hello" and decodes/prints the
//! answer.

use std::{
    fs::File,
    io::Read,
    time::{Duration, SystemTime},
};

use embedded_timers::clock::{Clock, ClockError, Instant};
use try_ascii::try_ascii;

use coap_zero::{
    endpoint::{outgoing::OutgoingEvent, CoapEndpoint, TransmissionParameters},
    message::{
        codes::RequestCode,
        options::{CoapOption, CoapOptionName},
        Message,
    },
};
use heapless::Vec;
use std_embedded_nal::Stack;

#[derive(Debug)]
pub struct Random;

impl embedded_hal::blocking::rng::Read for Random {
    type Error = std::io::Error;

    fn read(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
        File::open("/dev/urandom")?.read_exact(buf)
    }
}

#[derive(Debug)]
struct SystemClock;

impl Clock for SystemClock {
    fn try_now(&self) -> Result<Instant, ClockError> {
        Ok(SystemTime::now()
            .duration_since(SystemTime::UNIX_EPOCH)
            .unwrap())
    }
}

static CLOCK: SystemClock = SystemClock;

pub fn main() {
    simple_logger::SimpleLogger::new().env().init().unwrap();

    let mut stack = Stack::default();
    let mut receive_buffer = [0_u8; coap_zero::DEFAULT_COAP_MESSAGE_SIZE];

    let mut endpoint: CoapEndpoint<
        '_,
        Stack,
        Random,
        SystemClock,
        8,
        32,
        128,
        //{ coap_zero::DEFAULT_COAP_MESSAGE_SIZE },
    > = CoapEndpoint::try_new(
        TransmissionParameters::default(),
        Random {},
        &CLOCK,
        &mut receive_buffer,
    )
    .unwrap();

    endpoint
        .connect_to_url(&mut stack, "coap://coap.me:5683")
        .unwrap();

    let uri_path = CoapOption {
        name: CoapOptionName::UriPath,
        value: b"hello",
    };

    let mut options_vec = heapless::Vec::new();
    options_vec.push(uri_path).unwrap();

    println!();
    println!("Send Confirmable from constructed Message");
    println!();

    endpoint
        .outgoing()
        .schedule_con(RequestCode::Get, options_vec, None, Duration::from_secs(5))
        .unwrap();

    loop {
        std::thread::sleep(Duration::from_millis(25));

        let (_incoming, outgoing, _endpoint) = endpoint.process(&mut stack).unwrap();

        use OutgoingEvent::*;
        match outgoing {
            Ok(Success(response)) => {
                let decoded_message: Message<'_, { coap_zero::DEFAULT_MAX_OPTION_COUNT }> =
                    Message::try_from(response).unwrap();

                println!("DecodedMessage: {decoded_message:?}");
                if let Some(payload) = decoded_message.payload() {
                    println!("Payload Length: {}", payload.len());
                    println!("Payload: \"{:?}\"", try_ascii(payload));
                }
                break;
            }
            Ok(Nothing) => {}
            Ok(AckReceived) => {
                println!("ACK received");
            }
            Ok(ev) => {
                println!("Other event: {ev:?}");
            }
            Err(e) => {
                println!("Warn: {e:?}");
            }
        }
    }

    println!();
    println!("Send Confirmable from URI");
    println!();

    let outgoing = endpoint.outgoing();
    outgoing
        .schedule_con(
            RequestCode::Get,
            outgoing
                .parse_options("coap://coap.me:5683/hello", Vec::new())
                .unwrap(),
            None,
            Duration::from_secs(5),
        )
        .unwrap();

    loop {
        std::thread::sleep(Duration::from_millis(25));

        let (_incoming, outgoing, _endpoint) = endpoint.process(&mut stack).unwrap();

        use OutgoingEvent::*;
        match outgoing.unwrap() {
            Success(response) => {
                let decoded_message: Message<'_, { coap_zero::DEFAULT_MAX_OPTION_COUNT }> =
                    Message::try_from(response).unwrap();

                println!("DecodedMessage: {decoded_message:?}");
                if let Some(payload) = decoded_message.payload() {
                    println!("Payload Length: {}", payload.len());
                    println!("Payload: \"{:?}\"", try_ascii(payload));
                }
                break;
            }
            Nothing => {}
            AckReceived => {
                println!("ACK received");
            }
            other => {
                println!("Other event: {other:?}");
            }
        }
    }
}