feat(v0.4): SoC↔MCU протокол + кодек (CRC/replay/desync-guard, B08)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Alexander <akotenev2003@gmail.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
//! Типы сообщений SoC↔MCU (B08, спека v0.4 §6.1). seq — поле кадра (codec), не сообщения.
|
||||
|
||||
pub mod wire {
|
||||
pub const HEARTBEAT: u8 = 0x01;
|
||||
pub const SHUTDOWN_IMMINENT: u8 = 0x02;
|
||||
pub const SAFE_TO_CUT: u8 = 0x03;
|
||||
pub const ACK: u8 = 0x81;
|
||||
pub const ACC: u8 = 0x82;
|
||||
pub const VOLTAGE: u8 = 0x83;
|
||||
pub const CUT_WARNING: u8 = 0x84;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SocToMcu {
|
||||
Heartbeat,
|
||||
ShutdownImminent { budget: u8 },
|
||||
SafeToCut,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum McuToSoc {
|
||||
Ack,
|
||||
Acc { on: bool },
|
||||
Voltage { mv: u16 },
|
||||
CutWarning,
|
||||
}
|
||||
|
||||
impl SocToMcu {
|
||||
pub fn wire_type(&self) -> u8 {
|
||||
match self {
|
||||
SocToMcu::Heartbeat => wire::HEARTBEAT,
|
||||
SocToMcu::ShutdownImminent { .. } => wire::SHUTDOWN_IMMINENT,
|
||||
SocToMcu::SafeToCut => wire::SAFE_TO_CUT,
|
||||
}
|
||||
}
|
||||
pub fn payload(&self) -> Vec<u8> {
|
||||
match self {
|
||||
SocToMcu::ShutdownImminent { budget } => vec![*budget],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
pub fn from_wire(t: u8, p: &[u8]) -> Option<Self> {
|
||||
match t {
|
||||
wire::HEARTBEAT => Some(SocToMcu::Heartbeat),
|
||||
wire::SHUTDOWN_IMMINENT => Some(SocToMcu::ShutdownImminent { budget: *p.first()? }),
|
||||
wire::SAFE_TO_CUT => Some(SocToMcu::SafeToCut),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl McuToSoc {
|
||||
pub fn wire_type(&self) -> u8 {
|
||||
match self {
|
||||
McuToSoc::Ack => wire::ACK,
|
||||
McuToSoc::Acc { .. } => wire::ACC,
|
||||
McuToSoc::Voltage { .. } => wire::VOLTAGE,
|
||||
McuToSoc::CutWarning => wire::CUT_WARNING,
|
||||
}
|
||||
}
|
||||
pub fn payload(&self) -> Vec<u8> {
|
||||
match self {
|
||||
McuToSoc::Acc { on } => vec![*on as u8],
|
||||
McuToSoc::Voltage { mv } => mv.to_be_bytes().to_vec(),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
pub fn from_wire(t: u8, p: &[u8]) -> Option<Self> {
|
||||
match t {
|
||||
wire::ACK => Some(McuToSoc::Ack),
|
||||
wire::ACC => Some(McuToSoc::Acc { on: *p.first()? != 0 }),
|
||||
wire::VOLTAGE => Some(McuToSoc::Voltage {
|
||||
mv: u16::from_be_bytes([*p.first()?, *p.get(1)?]),
|
||||
}),
|
||||
wire::CUT_WARNING => Some(McuToSoc::CutWarning),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user