Skip to main content

piper_can/
lib.rs

1//! # Piper CAN Adapter Layer
2//!
3//! CAN 硬件抽象层,提供统一的 CAN 接口抽象。
4
5use std::time::Duration;
6use thiserror::Error;
7
8// 重新导出 piper-protocol 中的 PiperFrame
9pub use piper_protocol::PiperFrame;
10
11// SocketCAN (Linux only)
12// 优先级:mock 优先级最高,然后是显式 feature,最后是 auto-backend
13#[cfg(all(
14    not(feature = "mock"),                          // ⚠️ 确保 mock 模式下彻底禁用硬件
15    any(
16        feature = "socketcan",                      // 显式启用
17        all(feature = "auto-backend", target_os = "linux")  // 自动推导
18    )
19))]
20pub mod socketcan;
21
22#[cfg(all(
23    not(feature = "mock"),
24    any(
25        feature = "socketcan",
26        all(feature = "auto-backend", target_os = "linux")
27    )
28))]
29pub use socketcan::SocketCanAdapter;
30
31#[cfg(all(
32    not(feature = "mock"),
33    any(
34        feature = "socketcan",
35        all(feature = "auto-backend", target_os = "linux")
36    )
37))]
38pub use socketcan::split::{SocketCanRxAdapter, SocketCanTxAdapter};
39
40// GS-USB (所有平台)
41// 优先级:mock 优先级最高,然后是显式 feature,最后是 auto-backend
42#[cfg(all(
43    not(feature = "mock"),                          // mock 模式下禁用
44    any(
45        feature = "gs_usb",                         // 显式启用
46        feature = "auto-backend"                    // 自动推导
47    )
48))]
49pub mod gs_usb;
50
51#[cfg(all(
52    not(feature = "mock"),
53    any(feature = "gs_usb", feature = "auto-backend")
54))]
55pub use gs_usb::GsUsbCanAdapter;
56
57// GS-UDP 守护进程客户端库(UDS/UDP)
58// 不受 mock 模式影响(因为它是网络层,不直接访问硬件)
59pub mod gs_usb_udp;
60
61// 导出 split 相关的类型(如果可用)
62#[cfg(all(
63    not(feature = "mock"),
64    any(feature = "gs_usb", feature = "auto-backend")
65))]
66pub use gs_usb::split::{GsUsbRxAdapter, GsUsbTxAdapter};
67
68// Mock Adapter (用于测试)
69#[cfg(feature = "mock")]
70pub mod mock;
71
72#[cfg(feature = "mock")]
73pub use mock::MockCanAdapter;
74
75/// CAN 适配层统一错误类型
76#[derive(Error, Debug)]
77pub enum CanError {
78    #[error("IO Error: {0}")]
79    Io(#[from] std::io::Error),
80    #[error("Device Error: {0}")]
81    Device(#[from] CanDeviceError),
82    #[error("Read timeout")]
83    Timeout,
84    #[error("Buffer overflow")]
85    BufferOverflow,
86    #[error("Bus off")]
87    BusOff,
88    #[error("Device not started")]
89    NotStarted,
90}
91
92/// 设备/后端错误的结构化分类
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub enum CanDeviceErrorKind {
95    Unknown,
96    NotFound,
97    NoDevice,
98    AccessDenied,
99    Busy,
100    UnsupportedConfig,
101    InvalidResponse,
102    InvalidFrame,
103    Backend,
104}
105
106/// 结构化设备错误
107#[derive(Error, Debug, Clone)]
108#[error("{kind:?}: {message}")]
109pub struct CanDeviceError {
110    pub kind: CanDeviceErrorKind,
111    pub message: String,
112}
113
114impl CanDeviceError {
115    pub fn new(kind: CanDeviceErrorKind, message: impl Into<String>) -> Self {
116        Self {
117            kind,
118            message: message.into(),
119        }
120    }
121
122    pub fn is_fatal(&self) -> bool {
123        matches!(
124            self.kind,
125            CanDeviceErrorKind::NoDevice
126                | CanDeviceErrorKind::AccessDenied
127                | CanDeviceErrorKind::NotFound
128        )
129    }
130}
131
132impl From<String> for CanDeviceError {
133    fn from(message: String) -> Self {
134        Self::new(CanDeviceErrorKind::Unknown, message)
135    }
136}
137
138impl From<&str> for CanDeviceError {
139    fn from(message: &str) -> Self {
140        Self::new(CanDeviceErrorKind::Unknown, message)
141    }
142}
143
144pub trait CanAdapter {
145    fn send(&mut self, frame: PiperFrame) -> Result<(), CanError>;
146    fn receive(&mut self) -> Result<PiperFrame, CanError>;
147    fn set_receive_timeout(&mut self, _timeout: Duration) {}
148    fn receive_timeout(&mut self, timeout: Duration) -> Result<PiperFrame, CanError> {
149        self.set_receive_timeout(timeout);
150        self.receive()
151    }
152    fn try_receive(&mut self) -> Result<Option<PiperFrame>, CanError> {
153        match self.receive_timeout(Duration::ZERO) {
154            Ok(frame) => Ok(Some(frame)),
155            Err(CanError::Timeout) => Ok(None),
156            Err(e) => Err(e),
157        }
158    }
159    fn send_timeout(&mut self, frame: PiperFrame, _timeout: Duration) -> Result<(), CanError> {
160        self.send(frame)
161    }
162}
163
164pub trait RxAdapter {
165    fn receive(&mut self) -> Result<PiperFrame, CanError>;
166}
167
168pub trait TxAdapter {
169    fn send(&mut self, frame: PiperFrame) -> Result<(), CanError>;
170}
171
172pub trait SplittableAdapter: CanAdapter {
173    type RxAdapter: RxAdapter;
174    type TxAdapter: TxAdapter;
175    fn split(self) -> Result<(Self::RxAdapter, Self::TxAdapter), CanError>;
176}