use crate::utils::ffi;
use crate::data::error::EcState;
pub fn abort() {
unsafe { ffi::AbortNetwork(); }
}
pub fn reset_abort() {
unsafe { ffi::ResetAbortNetwork(); }
}
pub fn abort_scan() {
unsafe { ffi::AbortScan(); }
}
pub fn reset_scan_abort() {
unsafe { ffi::ResetScanAbort(); }
}
pub fn emergency_close_nics() {
unsafe { ffi::EmergencyCloseNics(); }
}
pub fn get_cpu_cores() -> i32 {
unsafe { ffi::GetAvailableCpuCores() }
}
pub fn set_cpu_affinity(master_index: u16, base_cpu_core: i32) -> bool {
unsafe { ffi::SetMasterCpuAffinity(master_index, base_cpu_core) != 0 }
}
pub fn set_process_cpu_affinity(cpu_core: i32) -> bool {
unsafe { ffi::SetProcessCpuAffinity(cpu_core) != 0 }
}
pub fn apply_realtime_optimizations() -> bool {
unsafe { ffi::ApplyRealtimeOptimizations() != 0 }
}
pub fn remove_realtime_optimizations() -> bool {
unsafe { ffi::RemoveRealtimeOptimizations() != 0 }
}
pub fn get_realtime_optimizations_status() -> bool {
unsafe { ffi::GetRealtimeOptimizationsStatus() != 0 }
}
pub fn set_all_slave_watchdog(master_index: u16, timeout_ms: u32) -> i32 {
unsafe { ffi::SetAllSlaveWatchdog(master_index, timeout_ms) }
}
pub fn set_all_slave_pdi_watchdog(master_index: u16, timeout_ms: u32) -> i32 {
unsafe { ffi::SetAllSlavePdiWatchdog(master_index, timeout_ms) }
}
pub fn get_max_master_instances() -> i32 {
unsafe { ffi::GetMaxMasterInstances() }
}
pub fn apply_auto_cpu_affinity(master_index: u16) -> bool {
let cpu_cores = get_cpu_cores();
if cpu_cores < 2 {
return false;
}
let cores_per_instance = 2;
let instance_offset = (master_index as i32 - 1) * cores_per_instance;
let mut base_cpu_core = (cpu_cores - 1) - instance_offset;
if base_cpu_core < 1 {
base_cpu_core = std::cmp::min(1, cpu_cores - 1);
}
if base_cpu_core >= cpu_cores {
base_cpu_core = cpu_cores - 1;
}
if base_cpu_core < 0 {
base_cpu_core = 0;
}
set_cpu_affinity(master_index, base_cpu_core)
}
pub fn init_console_info(_log_level: i32) {
}
#[derive(Debug, Clone)]
pub struct StartupVerifyResult {
pub valid: bool,
pub slave_count: u16,
pub issues: Vec<String>,
}
pub fn wait_for_state(master_index: u16, target: EcState,
timeout_ms: u32, poll_interval_ms: u32) -> bool {
use std::time::{Duration, Instant};
let deadline = Instant::now() + Duration::from_millis(timeout_ms as u64);
let interval = Duration::from_millis(poll_interval_ms.max(1) as u64);
let target_raw = target as u8;
loop {
let ptr = unsafe { ffi::GetMasterState(master_index) };
if !ptr.is_null() {
let cur = unsafe { *(ptr as *const u16) } as u8;
if (cur & 0x0F) == (target_raw & 0x0F) {
return true;
}
}
if Instant::now() >= deadline {
let ptr = unsafe { ffi::GetMasterState(master_index) };
if !ptr.is_null() {
let cur = unsafe { *(ptr as *const u16) } as u8;
return (cur & 0x0F) == (target_raw & 0x0F);
}
return false;
}
std::thread::sleep(interval);
}
}
pub fn wait_for_slave_state(master_index: u16, slave_index: u16, target: EcState,
timeout_ms: u32, poll_interval_ms: u32) -> bool {
use std::time::{Duration, Instant};
let deadline = Instant::now() + Duration::from_millis(timeout_ms as u64);
let interval = Duration::from_millis(poll_interval_ms.max(1) as u64);
let target_raw = (target as u8) & 0x0F;
loop {
let cur = unsafe { ffi::GetSlaveState(master_index, slave_index) } & 0x0F;
if cur == target_raw {
return true;
}
if Instant::now() >= deadline {
let final_state = unsafe { ffi::GetSlaveState(master_index, slave_index) } & 0x0F;
return final_state == target_raw;
}
std::thread::sleep(interval);
}
}
pub fn verify_startup_configuration(master_index: u16) -> StartupVerifyResult {
let mut issues = Vec::new();
let mut slave_count: u16 = 0;
let link = unsafe { ffi::GetLinkStatus(master_index) };
if link == 0 {
issues.push("链路未连接".to_string());
}
for si in 1u16..256 {
let s_state = unsafe { ffi::GetSlaveState(master_index, si) };
if s_state == 0 {
break;
}
slave_count += 1;
let base = s_state & 0x0F;
if base < 2 {
issues.push(format!("从站 {} 状态异常: 0x{:02X}", si, s_state));
}
if (s_state & 0x10) != 0 {
let al_code = unsafe { ffi::GetSlaveALStatusCode(master_index, si) };
issues.push(format!("从站 {} 有 AL 错误: 0x{:04X}", si, al_code));
}
}
let result = unsafe { ffi::ec_validate_config(master_index) };
if result != 0 {
issues.push(format!("配置验证失败: 错误码 {}", result));
}
StartupVerifyResult {
valid: issues.is_empty(),
slave_count,
issues,
}
}