docs, clippy

This commit is contained in:
Robin Appelman 2024-02-24 15:25:38 +01:00
commit e55e68920c
3 changed files with 50 additions and 13 deletions

View file

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
description = "A library for interfacing with the HLK-LD6002 respiratory and heartbeat radar module" description = "A library for interfacing with the HLK-LD6002 respiratory and heartbeat radar module"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
repository = "https://github.com/icewind1991/hlk_ld6002"
[dependencies] [dependencies]
bytemuck = { version = "1.14.3", features = ["derive"] } bytemuck = { version = "1.14.3", features = ["derive"] }

View file

@ -6,13 +6,13 @@ use std::time::{Duration, Instant};
fn main() { fn main() {
let port = args().nth(1).expect("no port provided"); let port = args().nth(1).expect("no port provided");
let port = serialport::new(&port, 1_382_400) let port = serialport::new(port, 1_382_400)
.timeout(Duration::from_millis(50)) .timeout(Duration::from_millis(50))
.open() .open()
.expect("Failed to open port"); .expect("Failed to open port");
port.clear(ClearBuffer::All).expect("clear"); port.clear(ClearBuffer::All).expect("clear");
let mut messages = MessageStream::new(FromStd::new(port)); let messages = MessageStream::new(FromStd::new(port));
let mut data = Data::default(); let mut data = Data::default();
@ -20,9 +20,7 @@ fn main() {
print!("{}", termion::cursor::Save); print!("{}", termion::cursor::Save);
loop { for message in messages.flatten() {
if let Some(message) = messages.next() {
if let Ok(message) = message {
data.update(message); data.update(message);
if last.elapsed() > Duration::from_millis(100) { if last.elapsed() > Duration::from_millis(100) {
last = Instant::now(); last = Instant::now();
@ -30,5 +28,3 @@ fn main() {
} }
} }
} }
}
}

View file

@ -1,25 +1,57 @@
#![no_std] #![no_std]
//! A library for community with [HLK-LD6002](https://www.hlktech.net/index.php?id=1180) radar respiratory and heartbeat sensors.
//!
//! ## Usage
//!
//! ```rust,no_run
//! use embedded_io_adapters::std::FromStd;
//! use hlk_ld6002::{Data, MessageStream};
//! use serialport::ClearBuffer;
//! use std::time::Duration;
//!
//! let port = serialport::new("/dev/ttyUSB0", 1_382_400)
//! .timeout(Duration::from_millis(50))
//! .open()
//! .expect("Failed to open port");
//!
//! let mut messages = MessageStream::new(FromStd::new(port));
//!
//! let mut data = Data::default();
//!
//! for message in messages.flatten() {
//! data.update(message);
//! println!("{data:?}");
//! }
//! ```
use bytemuck::{cast, cast_slice}; use bytemuck::{cast, cast_slice};
use embedded_io::{Error, Read, ReadExactError}; use embedded_io::{Error, Read, ReadExactError};
use embedded_io_async::Read as AsyncRead; use embedded_io_async::Read as AsyncRead;
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
/// Error type for reading data from the sensor
#[derive(Debug)] #[derive(Debug)]
pub enum LdError<E> { pub enum LdError<E> {
/// The message received from the sensor had an unknown message type
InvalidMessageType(u16), InvalidMessageType(u16),
/// The message received from the sensor had an invalid length for the message type
InvalidDataLength { InvalidDataLength {
expected: u16, expected: u16,
got: u16, got: u16,
ty: MessageType, ty: MessageType,
}, },
/// The message received from the sensor had an invalid checksum
InvalidChecksum { InvalidChecksum {
ty: &'static str, ty: &'static str,
got: u8, got: u8,
expected: u8, expected: u8,
}, },
/// The data read from the sensor didn't start as expected
InvalidFrameStart(u8), InvalidFrameStart(u8),
/// Unexpected end of data
Eof, Eof,
/// Error while reading from the serial device
Read(E), Read(E),
} }
@ -32,6 +64,7 @@ impl<E> From<ReadExactError<E>> for LdError<E> {
} }
} }
/// Message type sent by the sensor
#[derive(Debug, Clone, Copy, TryFromPrimitive)] #[derive(Debug, Clone, Copy, TryFromPrimitive)]
#[repr(u16)] #[repr(u16)]
pub enum MessageType { pub enum MessageType {
@ -105,6 +138,7 @@ impl FrameHeader {
} }
} }
/// A frame of data received from the sensor
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[allow(dead_code)] #[allow(dead_code)]
struct Frame { struct Frame {
@ -178,11 +212,11 @@ impl<const N: usize> FrameData<N> {
fn validate<E>(header: &FrameHeader) -> Result<(), LdError<E>> { fn validate<E>(header: &FrameHeader) -> Result<(), LdError<E>> {
if header.length as usize > N || header.length != header.ty.expected_length() { if header.length as usize > N || header.length != header.ty.expected_length() {
return Err(LdError::InvalidDataLength { Err(LdError::InvalidDataLength {
got: header.length, got: header.length,
expected: header.ty.expected_length(), expected: header.ty.expected_length(),
ty: header.ty, ty: header.ty,
}); })
} else { } else {
Ok(()) Ok(())
} }
@ -227,6 +261,7 @@ impl<const N: usize> AsRef<[u8]> for FrameData<N> {
} }
impl Frame { impl Frame {
/// Decode the body of the message according to the message type
fn body<E: Error>(&self) -> Result<MessageBody, LdError<E>> { fn body<E: Error>(&self) -> Result<MessageBody, LdError<E>> {
let numbers = cast_slice::<_, u32>(self.data.as_ref()); let numbers = cast_slice::<_, u32>(self.data.as_ref());
@ -257,6 +292,7 @@ impl Frame {
} }
} }
/// The decoded message from the sensor
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum MessageBody { pub enum MessageBody {
Phase([f32; 3]), Phase([f32; 3]),
@ -265,6 +301,7 @@ pub enum MessageBody {
Distance(Option<f32>), Distance(Option<f32>),
} }
/// A wrapper around [`Read`](embedded-io::Read) for reading messages from the sensor
pub struct MessageStream<R> { pub struct MessageStream<R> {
reader: R, reader: R,
} }
@ -292,6 +329,7 @@ impl<R: Read> Iterator for MessageStream<R> {
} }
} }
/// A wrapper around [`AsyncRead`](embedded-io-async::AsyncRead) for reading messages from the sensor
pub struct AsyncMessageStream<R> { pub struct AsyncMessageStream<R> {
reader: R, reader: R,
} }
@ -305,12 +343,14 @@ impl<R: AsyncRead> AsyncMessageStream<R> {
Frame::read_async(&mut self.reader).await Frame::read_async(&mut self.reader).await
} }
/// Read the next message from the sensor
pub async fn next(&mut self) -> Result<MessageBody, LdError<R::Error>> { pub async fn next(&mut self) -> Result<MessageBody, LdError<R::Error>> {
let frame = self.read().await?; let frame = self.read().await?;
frame.body() frame.body()
} }
} }
/// A helper struct to store the received data
#[derive(Default, Debug, Copy, Clone)] #[derive(Default, Debug, Copy, Clone)]
pub struct Data { pub struct Data {
pub respiratory: f32, pub respiratory: f32,