can_types/
lib.rs

1// Copyright (c) 2024 Nathan H. Keough
2//
3// This work is dual-licensed under MIT OR Apache 2.0 (or any later version).
4// You may choose between one of them if you use this work.
5//
6// For further detail, please refer to the individual licenses located at the root of this crate.
7
8//! A rust crate for encoding or decoding various Controller Area Network (CAN) data types, including the SAE J1939 standard.
9//!
10//! ## Supported CAN Protocols
11//! This crate provides decoding capabilities for Controller Area Network (CAN) protocols utilizing both 11-bit and 29-bit identifiers.
12//! - **CAN 2.0 (Classical CAN)**: Commonly used in automotive applications and industrial automation.
13//! - **SAE J1939**: Commonly used in heavy-duty trucks and buses.
14//!
15//! ## `no_std` Support
16//! This crate supports `no_std`, meaning it can be used in resource-constrained environments like embedded systems and `IoT` devices, allowing for minimal memory usage without compromising functionality.
17//!
18//! To enable `no_std`, use the `--no-default-features` flag:
19//! ```shell
20//! $ cargo add can_types --no-default-features
21//! ```
22//!
23//! ### `no_std` limitations:
24//! - This mode does not support generating [`String`](alloc::string::String) or string slice hexadecimal representations of the provided data structures.
25//!
26//! # Examples
27//! ## Hex to J1939 Identifier
28//! ```rust
29//! # use can_types::prelude::*;
30//! # fn main() -> Result<(), anyhow::Error> {
31//! let id_a = IdJ1939::try_from_hex("0CF00400")?;
32//!
33//! assert_eq!(3, id_a.priority());
34//! assert_eq!(SourceAddr::Some(0), id_a.source_address());
35//! assert_eq!(Some(Addr::PrimaryEngineController), id_a.source_address().lookup());
36//! # Ok(())
37//! # }
38//! ```
39//!
40//! ## Decode J1939 PGN
41//! ```rust
42//! # use can_types::prelude::*;
43//! # fn main() -> Result<(), anyhow::Error> {
44//! let id_a = IdJ1939::try_from_hex("18FEF200")?;
45//!
46//! assert_eq!(CommunicationMode::Broadcast, id_a.pgn().communication_mode());
47//! assert_eq!(GroupExtension::Some(242), id_a.pgn().group_extension());
48//!  
49//! let id_b = IdJ1939::try_from_hex("0C00290B")?;
50//!         
51//! // SA 11 = Brakes
52//! assert_eq!(SourceAddr::Some(11), id_b.source_address());
53//! assert_eq!(Some(Addr::Brakes), id_b.source_address().lookup());
54//!
55//! assert_eq!(PduFormat::Pdu1(0), id_b.pgn().pdu_format());
56//! assert_eq!(CommunicationMode::P2P, id_b.pgn().communication_mode());
57//! assert_eq!(GroupExtension::None, id_b.pgn().group_extension());
58//!
59//! // DA 41 = Retarder, Exhaust, Engine
60//! assert_eq!(DestinationAddr::Some(41), id_b.pgn().destination_address());
61//! assert_eq!(Some(Addr::RetarderExhaustEngine1), id_b.pgn().destination_address().lookup());   
62//! # Ok(())
63//! # }
64//! ```
65
66#![no_std]
67
68macro_rules! if_alloc {
69    ($($i:item)*) => ($(
70        #[cfg(feature = "alloc")] $i
71    )*)
72}
73
74if_alloc! {
75    extern crate alloc;
76}
77
78pub mod conversion;
79pub mod identifier;
80pub mod message;
81pub mod payload;
82pub mod protocol;
83
84#[doc(hidden)]
85pub mod prelude {
86    use super::{conversion, identifier, message, payload, protocol};
87
88    pub use conversion::Conversion;
89    pub use identifier::{Id, IsProtocol};
90    pub use message::Message;
91    pub use payload::{Data, IsDataUnit, Name, Pdu};
92    pub use protocol::{
93        can2_a::identifier::{Can2A, IdCan2A},
94        can2_b::identifier::{Can2B, IdCan2B},
95        j1939::{
96            address::{Addr, DestinationAddr, SourceAddr},
97            identifier::{IdJ1939, J1939},
98            pgn::{CommunicationMode, GroupExtension, PduAssignment, PduFormat, Pgn},
99        },
100    };
101}