Skip to content

Help with using server observable notifications #14

@petardimitrijevic

Description

@petardimitrijevic

I'm trying to use server observable notifications, but I'm not sure how to do it.

The problem that I would like to solve is to change the data that is sent to the observers outside of the process loop (some other thread) and notify them using the notify_observers method.

I'm starting with the following code mostly taken from the documentation:

use std::{
    net::UdpSocket,
    time::Duration,
};

use libcoap_rs::{
    CoapContext,
    message::{CoapMessageCommon, CoapResponse, CoapRequest},
    protocol::{CoapRequestCode, CoapResponseCode},
    CoapRequestHandler, CoapResource,
    session::{CoapSessionCommon, CoapServerSession},
};

fn main() {
    let server_address = UdpSocket::bind("127.0.0.1:5683")
        .expect("Failed to bind server socket")
        .local_addr()
        .expect("Failed to get server socket address");

    // a new CoAP context and bind to the generated SocketAddr.
    let mut context = CoapContext::new().expect("Failed to create CoAP context");
    context.add_endpoint_udp(server_address).expect("Unable to add/bind to endpoint");

    let handler = CoapRequestHandler::new(
        |completed: &mut (), session: &mut CoapServerSession, request: &CoapRequest, mut response: CoapResponse| {
            // Set content of the response message to "Hello World!"
            let data = Vec::<u8>::from("Hello World!".as_bytes());
            response.set_data(Some(data));
            // Set the response code to 2.00 "Content"
            response.set_code(CoapResponseCode::Content);
            // Send the response message.
            session.send(response).expect("Unable to send response");
        },
    );

    // Create a new resource that is available at the URI path `hello_world`
    // The second argument can be used to provide any kind of user-specific data, which will
    // then be passed to the handler function.
    let resource = CoapResource::new("hello_world", (), true);
    // Set a method handler for the GET method.
    resource.set_method_handler(
        CoapRequestCode::Get,
        Some(handler),
    );
    resource.set_observe_notify_confirmable(true);

    // Add the resource to the context.
    context.add_resource(resource);

    println!("Starting server...");
    loop {
        // process IO in a loop...
        if let Err(e) = context.do_io(Some(Duration::from_secs(1))) {
            break;
        }
        // ...until we want to shut down.
    }
    // Properly shut down, completing outstanding IO requests and properly closing sessions.
    context.shutdown(Some(Duration::from_secs(0))).unwrap();
}

The changes that I've made are creation of the resource with notify_con=true and call to resource.set_observe_notify_confirmable(true);.

The problem that I'm facing is that once I give ownership of the resource to the context through context.add_resource(resource); it is not possible to invoke resource.notify_observers() since it is owned by the context.

I wasn't able to find anything about the intended use in the documentation. What am I missing?

Metadata

Metadata

Assignees

Labels

libcoap-parityFeatures that libcoap offers, but libcoap-rs currently does not

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions