use crate::master::core::EtherCATMaster;
use std::sync::mpsc::{channel, sync_channel, Receiver, TryRecvError};
use std::sync::Mutex;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SlaveStateChangeEvent {
pub master: u16,
pub slave: u16,
pub old_state: i32,
pub new_state: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EmergencyEvent {
pub master: u16,
pub slave: u16,
pub error_code: u16,
pub error_register: u16,
pub b1: u8,
pub w1: u16,
pub w2: u16,
}
pub struct MasterStateStream {
rx: Receiver<SlaveStateChangeEvent>,
}
impl MasterStateStream {
pub fn recv(&self) -> Result<SlaveStateChangeEvent, std::sync::mpsc::RecvError> {
self.rx.recv()
}
pub fn try_recv(&self) -> Result<SlaveStateChangeEvent, TryRecvError> {
self.rx.try_recv()
}
pub fn into_inner(self) -> Receiver<SlaveStateChangeEvent> {
self.rx
}
}
impl IntoIterator for MasterStateStream {
type Item = SlaveStateChangeEvent;
type IntoIter = std::sync::mpsc::IntoIter<SlaveStateChangeEvent>;
fn into_iter(self) -> Self::IntoIter {
self.rx.into_iter()
}
}
pub struct EmergencyStream {
rx: Receiver<EmergencyEvent>,
}
impl EmergencyStream {
pub fn recv(&self) -> Result<EmergencyEvent, std::sync::mpsc::RecvError> {
self.rx.recv()
}
pub fn try_recv(&self) -> Result<EmergencyEvent, TryRecvError> {
self.rx.try_recv()
}
pub fn into_inner(self) -> Receiver<EmergencyEvent> {
self.rx
}
}
impl IntoIterator for EmergencyStream {
type Item = EmergencyEvent;
type IntoIter = std::sync::mpsc::IntoIter<EmergencyEvent>;
fn into_iter(self) -> Self::IntoIter {
self.rx.into_iter()
}
}
pub trait MasterStreamExt {
fn state_stream(&self) -> MasterStateStream;
fn state_stream_with_capacity(&self, cap: usize) -> MasterStateStream;
fn emergency_stream(&self) -> EmergencyStream;
}
impl MasterStreamExt for EtherCATMaster {
fn state_stream(&self) -> MasterStateStream {
self.state_stream_with_capacity(1024)
}
fn state_stream_with_capacity(&self, cap: usize) -> MasterStateStream {
let (tx, rx) = sync_channel::<SlaveStateChangeEvent>(cap);
let tx = Mutex::new(tx);
self.events().on_slave_state_changed_async(move |master, slave, old_state, new_state| {
let ev = SlaveStateChangeEvent { master, slave, old_state, new_state };
if let Ok(guard) = tx.lock() {
let _ = guard.try_send(ev);
}
});
MasterStateStream { rx }
}
fn emergency_stream(&self) -> EmergencyStream {
let (tx, rx) = channel::<EmergencyEvent>();
let tx = Mutex::new(tx);
self.events().on_emergency(move |master, slave, error_code, error_register, b1, w1, w2| {
let ev = EmergencyEvent {
master, slave, error_code, error_register, b1, w1, w2,
};
if let Ok(guard) = tx.lock() {
let _ = guard.send(ev);
}
});
EmergencyStream { rx }
}
}