use crate::master::{self, Master, SendData};
use crate::nom_parser::node::{scan_command, CommandToken};
use crate::{addr, param, value, Address, Parameter, Value};
pub struct Scanner {
expect: Expect,
read_again: Option<(Address, Parameter)>,
}
#[derive(Debug, PartialEq)]
enum Expect {
Command,
ReadResponse(Address, Parameter),
WriteResponse,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ControllerEvent {
Read(Address, Parameter),
Write(Address, Parameter, Value),
NodeTimeout,
}
#[derive(Debug, Clone)]
pub enum NodeEvent {
Write(Result<(), master::Error>),
Read(Result<Value, master::Error>),
UnexpectedTransmission,
}
pub enum Event {
Ctrl(ControllerEvent),
Node(NodeEvent),
}
impl From<ControllerEvent> for Event {
fn from(value: ControllerEvent) -> Self {
Self::Ctrl(value)
}
}
impl From<NodeEvent> for Event {
fn from(value: NodeEvent) -> Self {
Self::Node(value)
}
}
impl Default for Scanner {
fn default() -> Self {
Self::new()
}
}
impl Scanner {
pub fn new() -> Self {
Self {
expect: Expect::Command,
read_again: None,
}
}
pub fn recv_from_ctrl(&mut self, data: &[u8]) -> (usize, Option<ControllerEvent>) {
let read_again = self.read_again.take();
if self.expect != Expect::Command {
self.expect = Expect::Command;
return (0, Some(ControllerEvent::NodeTimeout));
}
let (consumed, token) = scan_command(data);
let event = match token {
CommandToken::WriteParameter(a, p, v) => {
self.expect = Expect::WriteResponse;
Some(ControllerEvent::Write(a, p, v))
}
CommandToken::ReadParameter(a, p) => {
self.expect = Expect::ReadResponse(a, p);
self.read_again = Some((a, p));
Some(ControllerEvent::Read(a, p))
}
CommandToken::ReadPrevious | CommandToken::ReadAgain | CommandToken::ReadNext
if read_again.is_some() =>
{
let (ra, rp) = read_again.unwrap();
match token {
CommandToken::ReadPrevious => rp.prev(),
CommandToken::ReadAgain => Some(rp),
CommandToken::ReadNext => rp.next(),
_ => unreachable!(),
}
.map(|p| {
self.expect = Expect::ReadResponse(ra, p);
self.read_again = Some((ra, p));
ControllerEvent::Read(ra, p)
})
}
CommandToken::ReadPrevious | CommandToken::ReadAgain | CommandToken::ReadNext => {
None }
CommandToken::InvalidPayload(_) => None,
CommandToken::NeedData => None,
};
return (consumed, event);
}
pub fn recv_from_node(&mut self, data: &[u8]) -> (usize, Option<NodeEvent>) {
let mut ctrl = Master::new();
let len = data.len();
let mut data = data.iter();
match &self.expect {
Expect::Command => return (len, NodeEvent::UnexpectedTransmission.into()),
Expect::ReadResponse(addr, param) => {
let mut send = ctrl.read_parameter(*addr, *param);
let recv = send.data_sent();
while let Some(byte) = data.next() {
if let Some(resp) = recv.receive_data([*byte].as_slice()) {
self.expect = Expect::Command;
return (len - data.as_slice().len(), NodeEvent::Read(resp).into());
}
}
}
Expect::WriteResponse => {
let mut send = ctrl.write_parameter(addr(1), param(1), value(1));
let recv = send.data_sent();
while let Some(byte) = data.next() {
if let Some(resp) = recv.receive_data([*byte].as_slice()) {
self.expect = Expect::Command;
return (len - data.as_slice().len(), NodeEvent::Write(resp).into());
}
}
}
}
return (0, None); }
}