use std::{convert::TryFrom, fmt};
use crate::error::*;
use crate::frame::*;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Command {
On,
OnFast,
Off,
OffFast,
Ping,
VersionQuery,
CancelLinking,
StartLinking,
StatusRequest,
Beep,
Other(u8),
None,
}
impl Default for Command {
fn default() -> Self {
Command::None
}
}
impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl From<u8> for Command {
fn from(b: u8) -> Self {
use Command::*;
match b {
0x08u8 => CancelLinking,
0x09u8 => StartLinking,
0x0du8 => VersionQuery,
0x0fu8 => Ping,
0x19u8 => StatusRequest,
0x11u8 => On,
0x12u8 => OnFast,
0x13u8 => Off,
0x14u8 => OffFast,
0x30u8 => Beep,
0 => None,
_ => Other(b),
}
}
}
impl From<Command> for u8 {
fn from(c: Command) -> Self {
use Command::*;
match c {
On => 0x11u8,
OnFast => 0x12u8,
Off => 0x13u8,
OffFast => 0x14u8,
Ping => 0x0fu8,
VersionQuery => 0x0du8,
CancelLinking => 0x08u8,
StartLinking => 0x09u8,
StatusRequest => 0x19u8,
Beep => 0x30u8,
Other(cmd) => cmd,
None => 0u8,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Message {
pub from: Address,
pub to: Address,
pub flags: MessageFlags,
pub hops_remaining: u8,
pub max_hops: u8,
pub cmd1: Command,
pub cmd2: Command,
pub data: [u8; 14],
}
impl Message {
pub fn is_ack(&self, other: &Message) -> bool {
match *other {
Message { from, flags, .. } if self.to == from && flags.contains(MessageFlags::ACK) => {
true
}
_ => false,
}
}
}
impl Default for Message {
fn default() -> Self {
Message {
from: Address::default(),
to: Address::default(),
flags: MessageFlags::default(),
hops_remaining: 3,
max_hops: 3,
cmd1: Command::default(),
cmd2: Command::default(),
data: [0u8; 14],
}
}
}
impl From<(Address, Command)> for Message {
fn from(c: (Address, Command)) -> Self {
let mut msg = Message::default();
let (to, cmd1) = c;
msg.to = to;
msg.cmd1 = cmd1;
msg
}
}
impl From<(Address, Command, Command)> for Message {
fn from(c: (Address, Command, Command)) -> Self {
let mut msg = Message::default();
let (to, cmd1, cmd2) = c;
msg.to = to;
msg.cmd1 = cmd1;
msg.cmd2 = cmd2;
msg
}
}
impl From<(Address, Command, MessageFlags)> for Message {
fn from(c: (Address, Command, MessageFlags)) -> Self {
let mut msg = Message::default();
let (to, cmd1, flags) = c;
msg.to = to;
msg.cmd1 = cmd1;
msg.flags = flags;
msg
}
}
impl From<(Address, Command, Command, MessageFlags)> for Message {
fn from(c: (Address, Command, Command, MessageFlags)) -> Self {
let mut msg = Message::default();
let (to, cmd1, cmd2, flags) = c;
msg.to = to;
msg.cmd1 = cmd1;
msg.cmd2 = cmd2;
msg.flags = flags;
msg
}
}
impl TryFrom<Frame> for Message {
type Error = Error;
fn try_from(frame: Frame) -> Result<Self, Self::Error> {
match frame {
Frame::StandardInsteonReceive {
from,
to,
flags,
hops_remaining,
max_hops,
cmd1,
cmd2,
} => Ok(Message {
from,
to,
flags,
hops_remaining,
max_hops,
cmd1: cmd1.into(),
cmd2: cmd2.into(),
data: [0u8; 14],
}),
Frame::ExtendedInsteonReceive {
from,
to,
flags,
hops_remaining,
max_hops,
cmd1,
cmd2,
data,
} => Ok(Message {
from,
to,
flags,
hops_remaining,
max_hops,
cmd1: cmd1.into(),
cmd2: cmd2.into(),
data,
}),
_ => Err(Error::UnexpectedResponse),
}
}
}