Skip to content

Commit

Permalink
coap: Run an actual CoAP server
Browse files Browse the repository at this point in the history
  • Loading branch information
chrysn committed Apr 8, 2024
1 parent 3af9b87 commit 50cee0c
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 2 deletions.
7 changes: 7 additions & 0 deletions examples/coap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ embedded-nal-async = "0.7"
# actually patched with https://github.com/smoltcp-rs/smoltcp/pull/904 but
# patch.crates-io takes care of that
smoltcp = { version = "0.11", default-features = false }
embedded-nal-coap = "0.1.0-alpha.2"
coap-request = "0.2.0-alpha.2"
coap-message = "0.3.1"
embassy-futures = "0.1.1"
coap-message-demos = { version = "0.4.0", default-features = false }
coap-request-implementations = "0.1.0-alpha.4"
rand = { version = "0.8.5", default-features = false, features = [ "small_rng" ] }

[features]
default = [ "proto-ipv4" ] # shame
Expand Down
112 changes: 110 additions & 2 deletions examples/coap/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,43 @@

use riot_rs::{debug::println, embassy::network};

use embassy_net::udp::{PacketMetadata, UdpSocket};

// Moving work from https://github.com/embassy-rs/embassy/pull/2519 in here for the time being
mod udp_nal;

#[riot_rs::task(autostart)]
async fn udp_echo() {
async fn coap_run() {
let stack = network::network_stack().await.unwrap();

// FIXME trim to CoAP requirements
let mut rx_meta = [PacketMetadata::EMPTY; 16];
let mut rx_buffer = [0; 4096];
let mut tx_meta = [PacketMetadata::EMPTY; 16];
let mut tx_buffer = [0; 4096];
let mut buf = [0; 4096];

let mut socket = UdpSocket::new(
stack,
&mut rx_meta,
&mut rx_buffer,
&mut tx_meta,
&mut tx_buffer,
);

println!("Starting up CoAP server");

todo!("Work with {stack:p}");
// Can't that even bind to the Any address??
// let local_any = "0.0.0.0:5683".parse().unwrap(); // shame
let local_any = "10.42.0.61:5683".parse().unwrap(); // shame
let mut unconnected = udp_nal::UnconnectedUdp::bind_multiple(socket, local_any)
.await
.unwrap();

// NAL time
use embedded_nal_async::UnconnectedUdp;

run(unconnected).await;
}

// FIXME: So far, this is necessary boiler plate; see ../README.md#networking for details
Expand All @@ -25,3 +55,81 @@ fn network_config() -> embassy_net::Config {
gateway: Some(Ipv4Address::new(10, 42, 0, 1)),
})
}

// Rest is from coap-message-demos/examples/std_embedded_nal_coap.rs

/// This function works on *any* UdpFullStack, including embedded ones -- only main() is what makes
/// this use POSIX sockets. (It does make use of a std based RNG, but that could be passed in just
/// as well for no_std operation).
async fn run<S>(mut sock: S)
where
S: embedded_nal_async::UnconnectedUdp,
{
let log = None;

let mut handler = coap_message_demos::full_application_tree(log);

println!("Server is ready.");

let coap = embedded_nal_coap::CoAPShared::<3>::new();
let (client, server) = coap.split();

// going with an embassy_futures join instead of an async_std::task::spawn b/c CoAPShared is not
// Sync, and async_std expects to work in multiple threads
embassy_futures::join::join(
async {
let mut rand = rand::rngs::SmallRng::seed_from_u64(4);
use rand::SeedableRng;
server
.run(
&mut sock,
&mut handler,
&mut rand,
)
.await
.expect("UDP error")
},
run_client_operations(client),
)
.await;
}

/// In parallel to server operation, this function performs some operations as a client.
///
/// This doubles as an experimentation ground for the client side of embedded_nal_coap and
/// coap-request in general.
async fn run_client_operations<const N: usize>(
client: embedded_nal_coap::CoAPRuntimeClient<'_, N>,
) {
use coap_message::Code;

// shame
let demoserver = "10.42.0.1:1234".parse().unwrap();

use coap_request::Stack;
println!("Sending GET to {}...", demoserver);
let response = client
.to(demoserver)
.request(
coap_request_implementations::Code::get()
.with_path("/other/separate")
.processing_response_payload_through(|p| {
println!("Got payload {:?}", p);
}),
)
.await;
println!("Response {:?}", response);

let req = coap_request_implementations::Code::post().with_path("/uppercase");

println!("Sending POST...");
let mut response = client.to(demoserver);
let response = response.request(
req.with_request_payload_slice(b"Set time to 1955-11-05")
.processing_response_payload_through(|p| {
println!("Uppercase is {}", core::str::from_utf8(p).unwrap())
}),
);
let response = response.await;
println!("Response {:?}", response);
}

0 comments on commit 50cee0c

Please sign in to comment.