use crate::logical_address::LogicalAddress;
use automotive_wire_codec::{read_array, read_u8, read_u16_be, write_all, write_u8, write_u16_be};
use super::message_error::MessageError;
use super::traits::{Decode, Encode};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FurtherActionRequired {
NoFurtherActionRequired,
Reserved(u8),
RoutingActivationRequiredToInitiateCentralSecurity,
VehicleManufacturerSpecific(u8),
}
impl From<u8> for FurtherActionRequired {
fn from(value: u8) -> Self {
match value {
0x00 => FurtherActionRequired::NoFurtherActionRequired,
0x01..=0x0F => FurtherActionRequired::Reserved(value),
0x10 => FurtherActionRequired::RoutingActivationRequiredToInitiateCentralSecurity,
0x11..=0xFF => FurtherActionRequired::VehicleManufacturerSpecific(value),
}
}
}
impl From<FurtherActionRequired> for u8 {
fn from(value: FurtherActionRequired) -> Self {
match value {
FurtherActionRequired::NoFurtherActionRequired => 0x00,
FurtherActionRequired::RoutingActivationRequiredToInitiateCentralSecurity => 0x10,
FurtherActionRequired::Reserved(value)
| FurtherActionRequired::VehicleManufacturerSpecific(value) => value,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum VinGidSyncStatus {
Synchronized,
Reserved(u8),
Incomplete,
}
impl From<u8> for VinGidSyncStatus {
fn from(value: u8) -> Self {
match value {
0x00 => VinGidSyncStatus::Synchronized,
0x10 => VinGidSyncStatus::Incomplete,
_ => VinGidSyncStatus::Reserved(value),
}
}
}
impl From<VinGidSyncStatus> for u8 {
fn from(value: VinGidSyncStatus) -> Self {
match value {
VinGidSyncStatus::Synchronized => 0x00,
VinGidSyncStatus::Incomplete => 0x10,
VinGidSyncStatus::Reserved(value) => value,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct VehicleIdentificationResponse {
pub vin: [u8; 17],
pub logical_address: LogicalAddress,
pub entity_id: [u8; 6],
pub group_id: Option<[u8; 6]>,
pub further_action: FurtherActionRequired,
pub vin_gid_sync_status: VinGidSyncStatus,
}
impl<'a> Decode<'a> for VehicleIdentificationResponse {
type Error = MessageError;
fn decode(buf: &'a [u8]) -> Result<(Self, &'a [u8]), MessageError> {
let (vin, rest) = read_array::<17>(buf)?;
let (logical_address, rest) = read_u16_be(rest)?;
let (entity_id, rest) = read_array::<6>(rest)?;
let (group_id, rest) = read_array::<6>(rest)?;
let group_id = if group_id == [0x00; 6] || group_id == [0xFF; 6] {
None
} else {
Some(group_id)
};
let (further_action, rest) = read_u8(rest)?;
let further_action = FurtherActionRequired::from(further_action);
let (vin_gid_sync_status, rest) = read_u8(rest)?;
let vin_gid_sync_status = VinGidSyncStatus::from(vin_gid_sync_status);
Ok((
Self {
vin,
logical_address: LogicalAddress(logical_address),
entity_id,
group_id,
further_action,
vin_gid_sync_status,
},
rest,
))
}
}
impl Encode for VehicleIdentificationResponse {
type Error = MessageError;
fn encoded_size(&self) -> Result<usize, MessageError> {
Ok(33)
}
fn encode(&self, writer: &mut impl embedded_io::Write) -> Result<usize, MessageError> {
write_all(writer, &self.vin)?;
write_u16_be(writer, self.logical_address.into())?;
write_all(writer, &self.entity_id)?;
if let Some(group_id) = self.group_id {
write_all(writer, &group_id)?;
} else {
write_all(writer, &[0x00; 6])?;
}
write_u8(writer, self.further_action.into())?;
write_u8(writer, self.vin_gid_sync_status.into())?;
Ok(33)
}
}