use crate::data::error::SyncWindowStatus;
use crate::utils::ffi;
#[derive(Debug, Clone)]
pub struct EscPortErrors {
pub rx_error: [u8; 4],
pub invalid_frame: [u8; 4],
pub lost_link: [u8; 4],
}
impl EscPortErrors {
pub fn has_errors(&self) -> bool {
self.rx_error.iter().any(|&b| b > 0)
|| self.invalid_frame.iter().any(|&b| b > 0)
|| self.lost_link.iter().any(|&b| b > 0)
}
}
pub struct SlaveDCDiagnostics {
master_index: u16,
slave_index: u16,
}
impl SlaveDCDiagnostics {
pub(crate) fn new(master_index: u16, slave_index: u16) -> Self {
Self { master_index, slave_index }
}
pub fn is_in_sync(&self) -> bool {
let mut diff_ns: i32 = 0;
let mut max_diff_ns: i32 = 0;
let mut min_diff_ns: i32 = 0;
let mut in_sync: i32 = 0;
let mut out_of_sync_count: u32 = 0;
let ret = unsafe {
ffi::GetSlaveSyncWindowStatus(
self.master_index, self.slave_index,
&mut diff_ns, &mut max_diff_ns, &mut min_diff_ns,
&mut in_sync, &mut out_of_sync_count,
)
};
ret != 0 && in_sync != 0
}
pub fn sync_time_difference(&self) -> i32 {
let mut diff_ns: i32 = 0;
let mut max_diff_ns: i32 = 0;
let mut min_diff_ns: i32 = 0;
let mut in_sync: i32 = 0;
let mut out_of_sync_count: u32 = 0;
let ret = unsafe {
ffi::GetSlaveSyncWindowStatus(
self.master_index, self.slave_index,
&mut diff_ns, &mut max_diff_ns, &mut min_diff_ns,
&mut in_sync, &mut out_of_sync_count,
)
};
if ret != 0 { diff_ns } else { 0 }
}
pub fn sync_window_status(&self) -> Option<SyncWindowStatus> {
let mut diff_ns: i32 = 0;
let mut max_diff_ns: i32 = 0;
let mut min_diff_ns: i32 = 0;
let mut in_sync: i32 = 0;
let mut out_of_sync_count: u32 = 0;
let ret = unsafe {
ffi::GetSlaveSyncWindowStatus(
self.master_index, self.slave_index,
&mut diff_ns, &mut max_diff_ns, &mut min_diff_ns,
&mut in_sync, &mut out_of_sync_count,
)
};
if ret != 0 {
Some(SyncWindowStatus {
diff_ns,
max_diff_ns,
min_diff_ns,
in_sync: in_sync != 0,
out_of_sync_count,
})
} else {
None
}
}
pub fn reset_stats(&self) {
unsafe { ffi::ResetSlaveSyncWindowStats(self.master_index, self.slave_index) };
}
}
pub struct SlaveDiagnostics {
master_index: u16,
slave_index: u16,
}
impl SlaveDiagnostics {
pub(crate) fn new(master_index: u16, slave_index: u16) -> Self {
Self { master_index, slave_index }
}
pub fn dc(&self) -> SlaveDCDiagnostics {
SlaveDCDiagnostics::new(self.master_index, self.slave_index)
}
pub fn read_port_errors(&self) -> Option<EscPortErrors> {
let mut rx_error = [0u8; 4];
let mut invalid_frame = [0u8; 4];
let mut lost_link = [0u8; 4];
let ret = unsafe {
ffi::ReadSlavePortErrorCounters(
self.master_index, self.slave_index,
rx_error.as_mut_ptr(), invalid_frame.as_mut_ptr(), lost_link.as_mut_ptr(),
)
};
if ret != 0 {
Some(EscPortErrors { rx_error, invalid_frame, lost_link })
} else {
None
}
}
pub fn reset_port_errors(&self) -> bool {
unsafe { ffi::ResetSlavePortErrorCounters(self.master_index, self.slave_index) != 0 }
}
pub fn link_quality(&self) -> i16 {
unsafe { ffi::GetSlaveLinkQuality(self.master_index, self.slave_index) }
}
pub fn redundancy_activated(&self) -> bool {
let mode = unsafe { ffi::GetRingMode(self.master_index) };
mode == 1 }
pub fn primary_link_broken(&self) -> bool {
if let Some(errors) = self.read_port_errors() {
errors.lost_link[0] > 0
} else {
false
}
}
pub fn secondary_link_broken(&self) -> bool {
if let Some(errors) = self.read_port_errors() {
errors.lost_link[1] > 0
} else {
false
}
}
}