use driver::{Driver, GenericType};
use error::{Error, ErrorKind};
use num::FromPrimitive;
use serial::{self, SerialPort, SystemPort};
use std::fmt;
use std::io::ErrorKind as StdErrorKind;
use std::io::{Read, Write};
use std::time::Duration;
pub struct SerialDriver {
port: SystemPort,
message_id: u8,
messages: Vec<SerialMsg>,
path: String,
}
impl SerialDriver {
pub fn new<P>(path: P) -> Result<SerialDriver, Error>
where
P: Into<String>,
{
let path = path.into();
let mut port = try!(serial::open(&path));
try!(port.reconfigure(&|settings| {
try!(settings.set_baud_rate(serial::Baud115200));
settings.set_char_size(serial::Bits8);
settings.set_parity(serial::ParityNone);
settings.set_stop_bits(serial::Stop1);
settings.set_flow_control(serial::FlowHardware);
Ok(())
}));
try!(port.set_timeout(Duration::from_millis(200)));
let driver = SerialDriver {
port: port,
message_id: 0x00,
messages: vec![],
path: path,
};
Ok(driver)
}
fn get_next_msg_id(&mut self) -> u8 {
self.message_id += 1;
if self.message_id == 0x00 {
self.message_id += 1;
}
self.message_id
}
fn read_single_msg(&mut self) -> Result<SerialMsg, Error> {
let mut buf = [0u8; 1];
let mut result: Vec<u8> = Vec::new();
self.port.read(&mut buf)?;
if buf[0] == SerialMsgHeader::SOF as u8 {
result.push(buf[0]);
self.port.read(&mut buf)?;
result.push(buf[0]);
let len = buf[0];
for _ in 0..len {
self.port.read(&mut buf)?;
result.push(buf[0]);
}
let m = SerialMsg::parse(result.as_slice());
if m.is_ok() {
self.port.write(
SerialMsg::new_header(SerialMsgHeader::ACK)
.get_command()
.as_slice(),
)?;
}
else {
self.port.write(
SerialMsg::new_header(SerialMsgHeader::NAK)
.get_command()
.as_slice(),
)?;
}
return m;
}
else if buf[0] == SerialMsgHeader::ACK as u8 {
return Ok(SerialMsg::new_header(SerialMsgHeader::ACK));
}
else if buf[0] == SerialMsgHeader::NAK as u8 {
return Ok(SerialMsg::new_header(SerialMsgHeader::NAK));
}
else if buf[0] == SerialMsgHeader::CAN as u8 {
return Ok(SerialMsg::new_header(SerialMsgHeader::CAN));
}
Err(Error::new(
ErrorKind::UnknownZWave,
"Unknown ZWave header detected",
))
}
fn read_single_msg_rty(&mut self, tries: &i32) -> Result<SerialMsg, Error> {
let mut counter: i32 = tries.clone();
loop {
if counter <= 0 {
return Err(Error::new(ErrorKind::Io(StdErrorKind::TimedOut), "Timeout"));
}
counter -= 1;
match self.read_single_msg() {
Err(e) => {
if e.kind() == ErrorKind::Io(StdErrorKind::TimedOut) {
continue;
} else {
return Err(e);
}
}
Ok(m) => {
return Ok(m);
}
}
}
}
fn read_all_msg(&mut self) -> Result<bool, Error> {
loop {
match self.read_single_msg_rty(&3) {
Err(e) => {
if e.kind() != ErrorKind::Io(StdErrorKind::TimedOut) {
return Err(e);
} else {
return Ok(true);
}
}
Ok(m) => {
if m.header == SerialMsgHeader::SOF
&& m.typ == SerialMsgType::Request
&& m.func == SerialMsgFunction::SendData
&& m.data[1] == 0
&& m.data[2] == 0
{
continue;
}
if m.header == SerialMsgHeader::SOF && m.data.len() >= 1 {
self.messages.push(m.clone());
}
}
}
}
}
fn get_bit_at(&self, input: u8, n: u8) -> bool {
if n < 8 {
input & (1 << n) != 0
} else {
false
}
}
pub fn get_messages(&self) -> Vec<SerialMsg> {
self.messages.clone()
}
}
impl Driver for SerialDriver {
fn write<M>(&mut self, message: M) -> Result<u8, Error>
where
M: Into<Vec<u8>>,
{
self.read_all_msg()?;
let mut message = message.into();
message.push(SerialTransmissionType::AutoRoute as u8);
let m_id = self.get_next_msg_id();
message.push(m_id);
let msg = SerialMsg::new(SerialMsgType::Request, SerialMsgFunction::SendData, message);
self.port.write(msg.get_command().as_slice())?;
match self.read_single_msg_rty(&10) {
Err(e) => {
return Err(e);
}
Ok(m) => {
if m.header != SerialMsgHeader::ACK {
return Err(Error::new(
ErrorKind::Io(StdErrorKind::InvalidData),
"The driver refused the data - No ACK package",
));
}
}
}
match self.read_single_msg_rty(&10) {
Err(e) => {
return Err(e);
}
Ok(m) => {
if m.header != SerialMsgHeader::SOF
|| m.typ != SerialMsgType::Response
|| m.func != SerialMsgFunction::SendData
|| m.data != vec![0x01u8]
{
return Err(Error::new(
ErrorKind::Io(StdErrorKind::InvalidData),
"The driver refused the data - Negative response message",
));
}
}
}
Ok(m_id)
}
fn read(&mut self) -> Result<SerialMsg, Error> {
self.read_all_msg()?;
if self.messages.len() < 1 {
return Err(Error::new(
ErrorKind::Io(StdErrorKind::Other),
"No message with the given id received",
));
}
Ok(self.messages.remove(0))
}
fn get_node_ids(&mut self) -> Result<Vec<u8>, Error> {
self.read_all_msg()?;
let msg = SerialMsg::new(
SerialMsgType::Request,
SerialMsgFunction::DiscoveryNodes,
vec![],
);
self.port.write(msg.get_command().as_slice())?;
match self.read_single_msg_rty(&5) {
Err(e) => {
return Err(e);
}
Ok(m) => {
if m.header != SerialMsgHeader::ACK {
return Err(Error::new(
ErrorKind::Io(StdErrorKind::InvalidData),
"The driver refused the data - No ACK package",
));
}
}
}
let msg = self.read_single_msg_rty(&10)?;
let data = msg.data;
if data.len() != 34 || data[2] != 0x1D {
return Err(Error::new(
ErrorKind::UnknownZWave,
"The ZWave message has a wrong format",
));
}
let mut nodes = Vec::new();
for i in 3..31 {
for j in 0..7 {
if self.get_bit_at(data[i], j) {
let n = ((i - 3) * 8) + (j as usize + 1);
nodes.push(n as u8);
}
}
}
Ok(nodes)
}
fn get_node_generic_class<N>(&mut self, node_id: N) -> Result<GenericType, Error>
where
N: Into<u8>,
{
self.read_all_msg()?;
let msg = SerialMsg::new(
SerialMsgType::Request,
SerialMsgFunction::GetNodeProtocolInfo,
vec![node_id.into()],
);
self.port.write(msg.get_command().as_slice())?;
match self.read_single_msg_rty(&5) {
Err(e) => {
return Err(e);
}
Ok(m) => {
if m.header != SerialMsgHeader::ACK {
return Err(Error::new(
ErrorKind::Io(StdErrorKind::InvalidData),
"The driver refused the data - No ACK package",
));
}
}
}
let msg = self.read_single_msg_rty(&10)?;
let data = msg.data;
if data.len() != 6 {
return Err(Error::new(
ErrorKind::UnknownZWave,
"The ZWave message has a wrong format",
));
}
Ok(GenericType::from_u8(data[4]).unwrap_or(GenericType::Unknown))
}
}
impl fmt::Debug for SerialDriver {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Z-Wave Driver {{path: {}}}", self.path)
}
}
#[derive(Debug, Clone)]
pub struct SerialMsg {
pub header: SerialMsgHeader,
pub typ: SerialMsgType,
pub func: SerialMsgFunction,
pub data: Vec<u8>,
}
impl SerialMsg {
pub fn new(typ: SerialMsgType, func: SerialMsgFunction, data: Vec<u8>) -> SerialMsg {
SerialMsg {
header: SerialMsgHeader::SOF,
typ: typ,
func: func,
data: data,
}
}
pub fn new_header(header: SerialMsgHeader) -> SerialMsg {
SerialMsg {
header: header,
typ: SerialMsgType::Response,
func: SerialMsgFunction::None,
data: vec![],
}
}
pub fn parse(data: &[u8]) -> Result<SerialMsg, Error> {
if data.len() < 1 {
return Err(Error::new(
ErrorKind::UnknownZWave,
"No message delivered, at least a head is needed",
));
}
let header = SerialMsgHeader::from_u8(data[0]).ok_or(Error::new(
ErrorKind::UnknownZWave,
"Unknown ZWave header detected",
))?;
if header != SerialMsgHeader::SOF {
return Ok(SerialMsg::new_header(header));
}
if data.len() < 5 {
return Err(Error::new(
ErrorKind::UnknownZWave,
"Data is too short for a ZWave message with SOF header",
));
}
if data[1] != (data.len() - 2) as u8 {
return Err(Error::new(ErrorKind::UnknownZWave, "The length of the message defined in the ZWave message didn't match with the actual length"));
}
if SerialMsg::checksum(&data[0..(data.len() - 1)]) != data[data.len() - 1] {
return Err(Error::new(
ErrorKind::UnknownZWave,
"The checksum didn't match to the message",
));
}
let typ = SerialMsgType::from_u8(data[2])
.ok_or(Error::new(ErrorKind::UnknownZWave, "Unknown message type"))?;
let function = SerialMsgFunction::from_u8(data[3]).ok_or(Error::new(
ErrorKind::UnknownZWave,
"Unknown ZWave function detected",
))?;
let msg_data: &[u8];
if data.len() > 5 {
msg_data = &data[4..(data.len() - 1)];
}
else {
msg_data = &[0; 0];
}
Ok(SerialMsg::new(typ, function, msg_data.to_vec()))
}
pub fn get_command(&self) -> Vec<u8> {
if self.header != SerialMsgHeader::SOF {
return vec![self.header as u8];
}
let mut buf: Vec<u8> = vec![
self.header as u8,
(self.data.len() + 3) as u8,
self.typ as u8,
self.func as u8,
];
buf.append(&mut self.data.clone());
let cs = SerialMsg::checksum(&buf);
buf.push(cs);
buf
}
pub fn to_hex(data: &Vec<u8>) -> String {
let mut out = String::new();
for i in 0..data.len() {
out.push_str(&*format!("{:#X} ", data[i]));
}
out
}
pub fn get_hex(&self) -> String {
SerialMsg::to_hex(&self.get_command())
}
pub fn checksum(data: &[u8]) -> u8 {
let mut ret: u8 = 0xFF;
for i in 1..data.len() {
ret ^= data[i];
}
ret
}
}
enum_from_primitive! {
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SerialMsgHeader {
SOF = 0x01, ACK = 0x06, NAK = 0x15, CAN = 0x18, }
}
enum_from_primitive! {
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SerialMsgType {
Request = 0x00,
Response = 0x01,
}
}
enum_from_primitive! {
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SerialTransmissionType {
ACK = 0x01,
LowPower = 0x02,
AutoRoute = 0x04,
Explore = 0x20,
Direct = 0x25,
}
}
enum_from_primitive! {
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SerialMsgFunction {
None = 0x00,
DiscoveryNodes = 0x02,
SerialApiApplNodeInformation = 0x03,
ApplicationCommandHandler = 0x04,
GetControllerCapabilities = 0x05,
SerialApiSetTimeouts = 0x06,
SerialGetCapabilities = 0x07,
SerialApiSoftReset = 0x08,
SetRFReceiveMode = 0x10,
SetSleepMode = 0x11,
SendNodeInformation = 0x12,
SendData = 0x13,
SendDataMulti = 0x14,
GetVersion = 0x15,
SendDataAbort = 0x16,
RFPowerLevelSet = 0x17,
SendDataMeta = 0x18,
MemoryGetId = 0x20,
MemoryGetByte = 0x21,
MemoryPutByte = 0x22,
MemoryGetBuffer = 0x23, MemoryPutBuffer = 0x24,
ClockSet = 0x30,
ClockGet = 0x31,
ClockCompare = 0x32,
RtcTimerCreate = 0x33,
RtcTimerRead = 0x34,
RtcTimerDelete = 0x35,
RtcTimerCall = 0x36,
GetNodeProtocolInfo = 0x41,
SetDefault = 0x42,
ReplicationCommandComplete = 0x44,
ReplicationSendData = 0x45,
AssignReturnRoute = 0x46,
DeleteReturnRoute = 0x47,
RequestNodeNeighborUpdate = 0x48,
ApplicationUpdate = 0x49,
AddNodeToNetwork = 0x4a,
RemoveNodeFromNetwork = 0x4b,
CreateNewPrimary = 0x4c,
ControllerChange = 0x4d,
SetLearnMode = 0x50,
AssignSucReturnRoute = 0x51,
EnableSuc = 0x52,
RequestNetworkUpdate = 0x53,
SetSucNodeId = 0x54,
DeleteSucReturnRoute = 0x55,
GetSucNodeId = 0x56,
SendSucId = 0x57,
RediscoveryNeeded = 0x59,
RequestNodeInfo = 0x60,
RemoveFailedNodeId = 0x61,
IsFailedNode = 0x62,
ReplaceFailedNode = 0x63,
TimerStart = 0x70,
TimerRestart = 0x71,
TimerCancel = 0x72,
TimerCall = 0x73,
GetRoutingTableLine = 0x80,
GetTXCounter = 0x81,
ResetTXCounter = 0x82,
StoreNodeInfo = 0x83,
StoreHomeId = 0x84,
LockRouteResponse = 0x90,
SendDataRouteDemo = 0x91,
SerialApiTest = 0x95,
SerialApiSlaveNodeInfo = 0xa0,
ApplicationSlaveCommandHandler = 0xa1,
SendSlaveNodeInfo = 0xa2,
SendSlaveData = 0xa3,
SetSlaveLearnMode = 0xa4,
GetVirtualNodes = 0xa5,
IsVirtualNode = 0xa6,
SetPromiscuousMode = 0xd0,
}}