darra-ethercat-master 2.6.0

Commercial EtherCAT master protocol stack, real-time kernel driver integration, Windows and Linux support, multi-language SDKs, complex topology and hot-plug support.
Documentation

use std::collections::VecDeque;
use std::sync::Mutex;
use std::time::SystemTime;

#[derive(Clone, Debug)]
pub struct EmergencyMessage {

    pub error_code: u16,

    pub error_register: u8,

    pub data: [u8; 5],

    pub slave_index: u16,

    pub timestamp: SystemTime,
}

impl EmergencyMessage {

    pub fn error_description(&self) -> &str {
        match self.error_code >> 8 {
            0x00 => "已复位/无错误",
            0x10 => "通用错误",
            0x20 => "电流错误",
            0x21 => "设备输入侧电流错误",
            0x22 => "设备内部电流错误",
            0x23 => "设备输出侧电流错误",
            0x30 => "电压错误",
            0x31 => "主电源电压错误",
            0x32 => "设备内部电压错误",
            0x33 => "输出电压错误",
            0x40 => "温度错误",
            0x41 => "环境温度错误",
            0x42 => "设备温度错误",
            0x50 => "设备硬件错误",
            0x60 => "设备软件错误",
            0x61 => "内部软件错误",
            0x62 => "用户软件错误",
            0x63 => "数据集错误",
            0x70 => "附加模块错误",
            0x80 => "监控错误",
            0x81 => "通信错误",
            0x82 => "协议错误",
            0x90 => "外部错误",
            0xF0 => "附加功能错误",
            0xFF => "设备特定错误",
            _ => "未知错误类别",
        }
    }
}

impl std::fmt::Display for EmergencyMessage {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "EMCY[从站{}] 0x{:04X} ({}) 寄存器=0x{:02X}",
            self.slave_index, self.error_code,
            self.error_description(), self.error_register
        )
    }
}

pub struct EmcyRecorder {
    history: Mutex<VecDeque<EmergencyMessage>>,
    max_size: usize,
}

const MAX_EMCY_HISTORY_SIZE: usize = 256;

impl EmcyRecorder {

    pub fn new() -> Self {
        Self {
            history: Mutex::new(VecDeque::with_capacity(MAX_EMCY_HISTORY_SIZE)),
            max_size: MAX_EMCY_HISTORY_SIZE,
        }
    }

    pub fn record(
        &self,
        slave_index: u16,
        error_code: u16,
        error_reg: u16,
        b1: u8,
        w1: u16,
        w2: u16,
    ) {
        let msg = EmergencyMessage {
            error_code,
            error_register: (error_reg & 0xFF) as u8,
            data: [
                b1,
                (w1 & 0xFF) as u8,
                (w1 >> 8) as u8,
                (w2 & 0xFF) as u8,
                (w2 >> 8) as u8,
            ],
            slave_index,
            timestamp: SystemTime::now(),
        };

        if let Ok(mut history) = self.history.lock() {
            if history.len() >= self.max_size {
                history.pop_front();
            }
            history.push_back(msg);
        }
    }

    pub fn history(&self) -> Vec<EmergencyMessage> {
        self.history
            .lock()
            .map(|h| h.iter().cloned().collect())
            .unwrap_or_default()
    }

    pub fn clear_history(&self) {
        if let Ok(mut history) = self.history.lock() {
            history.clear();
        }
    }

    pub fn count(&self) -> usize {
        self.history.lock().map(|h| h.len()).unwrap_or(0)
    }
}

impl Default for EmcyRecorder {
    fn default() -> Self {
        Self::new()
    }
}