Skip to content

Commit

Permalink
Document console subsystem
Browse files Browse the repository at this point in the history
  • Loading branch information
ataffanel committed Nov 24, 2021
1 parent 92bd4bf commit a9f9297
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 7 deletions.
5 changes: 2 additions & 3 deletions examples/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Scann for Crazyflies on the default address
let found = link_context.scan([0xE7; 5]).await?;

if let Some(_uri) = found.last() {
let uri = "radio://0/60/2M/E7E7E7E7E7";
if let Some(uri) = found.last() {
println!("Connecting to {} ...", uri);

let cf = crazyflie_lib::Crazyflie::connect_from_uri(
Expand All @@ -22,7 +21,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
)
.await?;

let mut console_stream = cf.console.get_stream().await;
let mut console_stream = cf.console.line_stream_no_history().await;

while let Ok(Some(line)) = timeout(Duration::from_secs(10), console_stream.next()).await {
println!("{}", line);
Expand Down
82 changes: 78 additions & 4 deletions src/subsystems/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,56 @@
//!
//! The Crazyflie has a test console that is used to communicate various information
//! and debug message to the ground.
//!
//! The log is available either as a data stream that produces the same data as
//! returned by the crazyflie (ie. can be incomplete lines):
//! ``` no_run
//! use futures::StreamExt;
//!
//! # async fn as_stream(crazyflie: &crazyflie_lib::Crazyflie) {
//! let mut console_stream = crazyflie.console.stream().await;
//!
//! while let Some(data) = console_stream.next().await {
//! println!("{}", data);
//! }
//! // If the Crazflie send "Hello .................................................... World!"
//! // The println would show:
//! // Hello ........................
//! // ............................ W
//! // orld!
//! # }
//! ```
//!
//! Or a line streams that assemble and returns full lines:
//! ``` no_run
//! use futures::StreamExt;
//!
//! # async fn as_stream(crazyflie: &crazyflie_lib::Crazyflie) {
//! let mut line_stream = crazyflie.console.line_stream().await;
//!
//! while let Some(data) = line_stream.next().await {
//! println!("{}", data);
//! }
//! // If the Crazflie send "Hello .................................................... World!"
//! // The println would show:
//! // Hello .................................................... World!
//! # }
//! ```
//!
//! The data received from the Crazyflie is decoded as
//! [UTF8 lossy](String::from_utf8_lossy()). before being sent as [String] to the
//! streams.
//!
//! ## History or no History
//!
//! By default, the [Console::stream()] and [Console::line_stream()] functions
//! will return a stream that will produce the full console history since connection
//! and then produce the console as it arrives from the Crazyflie. This is needed
//! if the startup message needs to be displayed but can be problematic for more
//! advanced use-case to observe the console some time after the connection only.
//!
//! There exist fonctions for both data stream and line stream to get the stream
//! without getting the history first.
use std::{sync::Arc};

Expand Down Expand Up @@ -67,27 +117,51 @@ impl Console {
})
}

pub async fn get_stream(&self) -> impl Stream<Item = String> {
/// Return a [Stream] that generates a [String] each time a console packet
/// is received from the Crazyflie.
///
/// With the current Crazyflie algorithms, packets are up to 30 character
/// long and a new line triggers the send of a packet. Though this is not a
/// guarantee and nothing should be expected from this Stream other that
/// getting the console data when they are received.
///
/// The lib keeps track of the console history since connection, the stream
/// will first produce the full history since connection in one String and then
/// will start returning Strings as they come from the Crazyflie.
pub async fn stream(&self) -> impl Stream<Item = String> {
let buffer = self.console_buffer.lock().await;
let history_buffer = buffer.clone();
let history_stream = futures::stream::once(async { history_buffer }).boxed();

history_stream.chain(self.stream_broadcast_receiver.clone())
}

pub async fn get_stream_no_history(&self) -> impl Stream<Item = String> {
/// Version of [Console::stream()] but that does not produce the history
/// first.
pub async fn stream_no_history(&self) -> impl Stream<Item = String> {
self.stream_broadcast_receiver.clone()
}

pub async fn get_line_stream(&self) -> impl Stream<Item = String> {
/// Return a [Stream] that generate a [String] each time a line is received
/// from the Crazyflie.
///
/// This is a useful function if you want to receive the console line by line.
/// (for example to print it in a terminal or a file)
///
/// Similar to [Console::stream()], this stream will generate first the
/// console history since connection. The history is generated by the Stream
/// line-by-line.
pub async fn line_stream(&self) -> impl Stream<Item = String> {
let lines = self.console_lines.lock().await;
let history_lines = lines.clone();
let history_stream = futures::stream::iter(history_lines.into_iter()).boxed();

history_stream.chain(self.line_broadcast_receiver.clone())
}

pub async fn get_line_stream_no_history(&self) -> impl Stream<Item = String> {
/// Version of [Console::line_stream()] but that does not produce the history
/// first.
pub async fn line_stream_no_history(&self) -> impl Stream<Item = String> {
self.line_broadcast_receiver.clone()
}
}

0 comments on commit a9f9297

Please sign in to comment.