can_types/protocol/j1939/
address.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//! # Vehicle Control Units/Modules, Source Adresses, and Destination Addresses
9
10if_alloc! {
11    use crate::alloc::fmt::{Display, Formatter, Result};
12}
13
14/// The [`Addr`] enum represents various types of electronic control units (ECUs) and modules
15/// commonly found in automotive and heavy-duty vehicle networks. Each variant corresponds to a
16/// specific ECU or system component that communicates over the network.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum Addr {
19    PrimaryEngineController,
20    SecondaryEngineController,
21    PrimaryTransmissionController,
22    TransmissionShiftSelector,
23    Brakes,
24    Retarder,
25    CruiseControl,
26    FuelSystem,
27    SteeringController,
28    InstrumentCluster,
29    ClimateControl1,
30    Compass,
31    BodyController,
32    OffVehicleGateway,
33    DidVid,
34    RetarderExhaustEngine1,
35    HeadwayController,
36    Suspension,
37    CabController,
38    TirePressureController,
39    LightingControlModule,
40    ClimateControl2,
41    ExhaustEmissionController,
42    AuxiliaryHeater,
43    ChassisController,
44    CommunicationsUnit,
45    Radio,
46    SafetyRestraintSystem,
47    AftertreatmentControlModule,
48    MultiPurposeCamera,
49    SwitchExpansionModule,
50    AuxillaryGaugeSwitchPack,
51    Iteris,
52    QualcommPeopleNetTranslatorBox,
53    StandAloneRealTimeClock,
54    CenterPanel1,
55    CenterPanel2,
56    CenterPanel3,
57    CenterPanel4,
58    CenterPanel5,
59    WabcoOnGuardRadar,
60    SecondaryInstrumentCluster,
61    OffboardDiagnostics,
62    Trailer3Bridge,
63    Trailer2Bridge,
64    Trailer1Bridge,
65    SafetyDirectProcessor,
66    ForwardRoadImageProcessor,
67    LeftRearDoorPod,
68    RightRearDoorPod,
69    DoorController1,
70    DoorController2,
71    Tachograph,
72    HybridSystem,
73    AuxiliaryPowerUnit,
74    ServiceTool,
75    SourceAddressRequest0,
76    SourceAddressRequest1,
77    Unknown(u8),
78}
79
80impl From<u8> for Addr {
81    fn from(value: u8) -> Self {
82        match value {
83            0 => Addr::PrimaryEngineController,
84            1 => Addr::SecondaryEngineController,
85            3 => Addr::PrimaryTransmissionController,
86            5 => Addr::TransmissionShiftSelector,
87            11 => Addr::Brakes,
88            15 => Addr::Retarder,
89            17 => Addr::CruiseControl,
90            18 => Addr::FuelSystem,
91            19 => Addr::SteeringController,
92            23 => Addr::InstrumentCluster,
93            25 => Addr::ClimateControl1,
94            28 => Addr::Compass,
95            33 => Addr::BodyController,
96            37 => Addr::OffVehicleGateway,
97            40 => Addr::DidVid,
98            41 => Addr::RetarderExhaustEngine1,
99            42 => Addr::HeadwayController,
100            47 => Addr::Suspension,
101            49 => Addr::CabController,
102            51 => Addr::TirePressureController,
103            55 => Addr::LightingControlModule,
104            58 => Addr::ClimateControl2,
105            61 => Addr::ExhaustEmissionController,
106            69 => Addr::AuxiliaryHeater,
107            71 => Addr::ChassisController,
108            74 => Addr::CommunicationsUnit,
109            76 => Addr::Radio,
110            83 => Addr::SafetyRestraintSystem,
111            85 => Addr::AftertreatmentControlModule,
112            127 => Addr::MultiPurposeCamera,
113            128 => Addr::SwitchExpansionModule,
114            132 => Addr::AuxillaryGaugeSwitchPack,
115            139 => Addr::Iteris,
116            142 => Addr::QualcommPeopleNetTranslatorBox,
117            150 => Addr::StandAloneRealTimeClock,
118            151 => Addr::CenterPanel1,
119            152 => Addr::CenterPanel2,
120            153 => Addr::CenterPanel3,
121            154 => Addr::CenterPanel4,
122            155 => Addr::CenterPanel5,
123            160 => Addr::WabcoOnGuardRadar,
124            167 => Addr::SecondaryInstrumentCluster,
125            172 => Addr::OffboardDiagnostics,
126            184 => Addr::Trailer3Bridge,
127            192 => Addr::Trailer2Bridge,
128            200 => Addr::Trailer1Bridge,
129            209 => Addr::SafetyDirectProcessor,
130            232 => Addr::ForwardRoadImageProcessor,
131            233 => Addr::LeftRearDoorPod,
132            234 => Addr::RightRearDoorPod,
133            236 => Addr::DoorController1,
134            237 => Addr::DoorController2,
135            238 => Addr::Tachograph,
136            239 => Addr::HybridSystem,
137            247 => Addr::AuxiliaryPowerUnit,
138            249 => Addr::ServiceTool,
139            254 => Addr::SourceAddressRequest0,
140            255 => Addr::SourceAddressRequest1,
141            a => Addr::Unknown(a),
142        }
143    }
144}
145
146impl From<Addr> for u8 {
147    fn from(value: Addr) -> Self {
148        match value {
149            Addr::PrimaryEngineController => 0,
150            Addr::SecondaryEngineController => 1,
151            Addr::PrimaryTransmissionController => 3,
152            Addr::TransmissionShiftSelector => 5,
153            Addr::Brakes => 11,
154            Addr::Retarder => 15,
155            Addr::CruiseControl => 17,
156            Addr::FuelSystem => 18,
157            Addr::SteeringController => 19,
158            Addr::InstrumentCluster => 23,
159            Addr::ClimateControl1 => 25,
160            Addr::Compass => 28,
161            Addr::BodyController => 33,
162            Addr::OffVehicleGateway => 37,
163            Addr::DidVid => 40,
164            Addr::RetarderExhaustEngine1 => 41,
165            Addr::HeadwayController => 42,
166            Addr::Suspension => 47,
167            Addr::CabController => 49,
168            Addr::TirePressureController => 51,
169            Addr::LightingControlModule => 55,
170            Addr::ClimateControl2 => 58,
171            Addr::ExhaustEmissionController => 61,
172            Addr::AuxiliaryHeater => 69,
173            Addr::ChassisController => 71,
174            Addr::CommunicationsUnit => 74,
175            Addr::Radio => 76,
176            Addr::SafetyRestraintSystem => 83,
177            Addr::AftertreatmentControlModule => 85,
178            Addr::MultiPurposeCamera => 127,
179            Addr::SwitchExpansionModule => 128,
180            Addr::AuxillaryGaugeSwitchPack => 132,
181            Addr::Iteris => 139,
182            Addr::QualcommPeopleNetTranslatorBox => 142,
183            Addr::StandAloneRealTimeClock => 150,
184            Addr::CenterPanel1 => 151,
185            Addr::CenterPanel2 => 152,
186            Addr::CenterPanel3 => 153,
187            Addr::CenterPanel4 => 154,
188            Addr::CenterPanel5 => 155,
189            Addr::WabcoOnGuardRadar => 160,
190            Addr::SecondaryInstrumentCluster => 167,
191            Addr::OffboardDiagnostics => 172,
192            Addr::Trailer3Bridge => 184,
193            Addr::Trailer2Bridge => 192,
194            Addr::Trailer1Bridge => 200,
195            Addr::SafetyDirectProcessor => 209,
196            Addr::ForwardRoadImageProcessor => 232,
197            Addr::LeftRearDoorPod => 233,
198            Addr::RightRearDoorPod => 234,
199            Addr::DoorController1 => 236,
200            Addr::DoorController2 => 237,
201            Addr::Tachograph => 238,
202            Addr::HybridSystem => 239,
203            Addr::AuxiliaryPowerUnit => 247,
204            Addr::ServiceTool => 249,
205            Addr::SourceAddressRequest0 => 254,
206            Addr::SourceAddressRequest1 => 255,
207            Addr::Unknown(a) => a,
208        }
209    }
210}
211
212#[cfg(feature = "alloc")]
213impl Display for Addr {
214    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
215        match *self {
216            Addr::PrimaryEngineController => write!(f, "Primary Engine Controller | (CPC, ECM)"),
217            Addr::SecondaryEngineController => write!(f, "Secondary Engine Controller | (MCM, ECM #2)"),
218            Addr::PrimaryTransmissionController => write!(f, "Primary Transmission Controller | (TCM)"),
219            Addr::TransmissionShiftSelector => write!(f, "Transmission Shift Selector | (TSS)"),
220            Addr::Brakes => write!(f, "Brakes | System Controller (ABS)"),
221            Addr::Retarder => write!(f, "Retarder"),
222            Addr::CruiseControl => write!(f, "Cruise Control | (IPM, PCC)"),
223            Addr::FuelSystem => write!(f, "Fuel System | Controller (CNG)"),
224            Addr::SteeringController => write!(f, "Steering Controller | (SAS)"),
225            Addr::InstrumentCluster => write!(f, "Instrument Guage Cluster (EGC) | (ICU, RX)"),
226            Addr::ClimateControl1 => write!(f, "Climate Control #1 | (FCU)"),
227            Addr::Compass => write!(f, "Compass"),
228            Addr::BodyController => write!(f, "Body Controller | (SSAM, SAM-CAB, BHM)"),
229            Addr::OffVehicleGateway => write!(f, "Off-Vehicle Gateway | (CGW)"),
230            Addr::DidVid => write!(f, "Vehicle Information Display | Driver Information Display"),
231            Addr::RetarderExhaustEngine1 => write!(f, "Retarder, Exhaust, Engine #1"),
232            Addr::HeadwayController => write!(f, "Headway Controller | (RDF) | (OnGuard)"),
233            Addr::Suspension => write!(f, "Suspension | System Controller (ECAS)"),
234            Addr::CabController => write!(f, "Cab Controller | Primary (MSF, SHM, ECC)"),
235            Addr::TirePressureController => write!(f, "Tire Pressure Controller | (TPMS)"),
236            Addr::LightingControlModule => write!(f, "Lighting Control Module | (LCM)"),
237            Addr::ClimateControl2 => write!(f, "Climate Control #2 | Rear HVAC | (ParkSmart)"),
238            Addr::ExhaustEmissionController => write!(f, "Exhaust Emission Controller | (ACM) | (DCU)"),
239            Addr::AuxiliaryHeater => write!(f, "Auxiliary Heater | (ACU)"),
240            Addr::ChassisController => write!(f, "Chassis Controller | (CHM, SAM-Chassis)"),
241            Addr::CommunicationsUnit => write!(f, "Communications Unit | Cellular (CTP, VT)"),
242            Addr::Radio => write!(f, "Radio"),
243            Addr::SafetyRestraintSystem => write!(f, "Safety Restraint System | Air Bag | (SRS)"),
244            Addr::AftertreatmentControlModule => write!(f, "Aftertreatment Control Module | (ACM)"),
245            Addr::MultiPurposeCamera => write!(f, "Multi-Purpose Camera | (MPC)"),
246            Addr::SwitchExpansionModule => write!(f, "Switch Expansion Module | (SEM #1)"),
247            Addr::AuxillaryGaugeSwitchPack => write!(f, "Auxiliary Gauge Switch Pack | (AGSP3)"),
248            Addr::Iteris => write!(f, "Iteris"),
249            Addr::QualcommPeopleNetTranslatorBox => write!(f, "Qualcomm - PeopleNet Translator Box"),
250            Addr::StandAloneRealTimeClock => write!(f, "Stand-Alone Real Time Clock | (SART)"),
251            Addr::CenterPanel1 => write!(f, "Center Panel MUX Switch Pack #1"),
252            Addr::CenterPanel2 => write!(f, "Center Panel MUX Switch Pack #2"),
253            Addr::CenterPanel3 => write!(f, "Center Panel MUX Switch Pack #3"),
254            Addr::CenterPanel4 => write!(f, "Center Panel MUX Switch Pack #4"),
255            Addr::CenterPanel5 => write!(f, "Center Panel MUX Switch Pack #5"),
256            Addr::WabcoOnGuardRadar => write!(f, "Wabco OnGuard Radar | OnGuard Display | Collison Mitigation System"),
257            Addr::SecondaryInstrumentCluster => write!(f, "Secondary Instrument Cluster | (SIC)"),
258            Addr::OffboardDiagnostics => write!(f, "Offboard Diagnostics"),
259            Addr::Trailer3Bridge => write!(f, "Trailer #3 Bridge"),
260            Addr::Trailer2Bridge => write!(f, "Trailer #2 Bridge"),
261            Addr::Trailer1Bridge => write!(f, "Trailer #1 Bridge"),
262            Addr::SafetyDirectProcessor => write!(f, "Bendix Camera | Safety Direct Processor (SDP) Module"),
263            Addr::ForwardRoadImageProcessor => write!(f, "Forward Road Image Processor | PAM Module | Lane Departure Warning (LDW) Module | (VRDU)"),
264            Addr::LeftRearDoorPod => write!(f, "Left Rear Door Pod"),
265            Addr::RightRearDoorPod => write!(f, "Right Rear Door Pod"),
266            Addr::DoorController1 => write!(f, "Door Controller #1"),
267            Addr::DoorController2 => write!(f, "Door Controller #2"),
268            Addr::Tachograph => write!(f, "Tachograph | (TCO)"),
269            Addr::HybridSystem => write!(f, "Hybrid System"),
270            Addr::AuxiliaryPowerUnit => write!(f, "Auxiliary Power Unit | (APU)"),
271            Addr::ServiceTool => write!(f, "Service Tool"),
272            Addr::SourceAddressRequest0 => write!(f, "Source Address Request 0"),
273            Addr::SourceAddressRequest1 => write!(f, "Source Address Request 1"),
274            Addr::Unknown(num) => write!(f, "Unknown({num})"),
275        }
276    }
277}
278
279/// Represents the source address.
280#[derive(Debug, Clone, Copy, PartialEq, Eq)]
281pub enum SourceAddr {
282    /// No source address.
283    None,
284    /// Source address with a specific value.
285    Some(u8),
286}
287
288/// Represents the destination address.
289#[derive(Debug, Clone, Copy, PartialEq, Eq)]
290pub enum DestinationAddr {
291    /// No destination address.
292    None,
293    /// Destination address with a specific value.
294    Some(u8),
295}
296
297impl SourceAddr {
298    /// Lookup and translate the [`SourceAddr`] object.
299    ///
300    /// # Returns
301    /// - `Some(Addr)`: If generic J1939 address is known.
302    /// - `None`: If the pdu specific bits do not contain a destination address.
303    #[must_use]
304    pub fn lookup(self) -> Option<Addr> {
305        match self {
306            SourceAddr::Some(value) => Some(value.into()),
307            SourceAddr::None => None,
308        }
309    }
310}
311
312impl DestinationAddr {
313    /// Lookup and translate the [`DestinationAddr`] object.
314    ///
315    /// # Returns
316    /// - `Some(Addr)`: If generic J1939 address is known.
317    /// - `None`: If the pdu specific bits do not contain a destination address.
318    #[must_use]
319    pub fn lookup(self) -> Option<Addr> {
320        match self {
321            DestinationAddr::Some(value) => Some(value.into()),
322            DestinationAddr::None => None,
323        }
324    }
325}
326
327#[cfg(test)]
328mod sa_tests {
329    if_alloc! {
330        use alloc::format;
331    }
332
333    use super::*;
334
335    #[cfg(feature = "alloc")]
336    #[test]
337    fn test_translate() {
338        let sa_translated: Addr = 41.into();
339        assert_eq!("Retarder, Exhaust, Engine #1", format!("{sa_translated}"));
340
341        let sa_value: u8 = Addr::RetarderExhaustEngine1.into();
342        assert_eq!(41, sa_value)
343    }
344}