extern crate bitreader;
extern crate failure;
extern crate log;
extern crate num_enum;
extern crate serial;
pub mod error;
pub mod protocol;
use log::{debug, warn};
use serial::core::prelude::*;
use std::io::Read;
use std::iter;
use std::time::Duration;
use crate::error::Result;
use crate::protocol::{
convert_from_frequency, Command, CommandType, InventoryItem, InventoryResult, MemoryBank,
ReadResult, Response, START_BYTE, ResponseCode
};
const READ_TIMEOUT: Duration = Duration::from_millis(5000);
pub struct Reader {
port: serial::SystemPort,
antenna_count: usize,
address: u8,
}
impl Reader {
pub fn new(port: &str, address: u8, antenna_count: u8) -> Result<Reader> {
let mut port = serial::open(port)
.map_err(|e| format!("Unable to connect to serial port {}: {:?}", port, e))?;
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::FlowNone);
Ok(())
})
.map_err(|e| format!("Failed to configure serial port: {}", e))?;
port.set_timeout(READ_TIMEOUT)
.map_err(|e| format!("Failed to set serial port timeout: {}", e))?;
Ok(Reader {
port: port,
address: address,
antenna_count: antenna_count as usize,
})
}
fn send(&mut self, cmd: Command) -> Result<()> {
let cmd_bytes = cmd.to_bytes();
debug!("Send {:?}: {:?}", cmd.command, cmd_bytes);
std::io::Write::write(&mut self.port, &cmd_bytes)?;
Ok(())
}
fn wait_for_start(&mut self) -> Result<u8> {
let mut start = [0u8; 1];
loop {
std::io::Read::read_exact(&mut self.port, &mut start)?;
if start[0] == START_BYTE {
return Ok(start[0]);
}
}
}
fn receive_packet(&mut self) -> Result<Response> {
let start = self.wait_for_start()?;
let mut len = [0u8; 1];
std::io::Read::read_exact(&mut self.port, &mut len)?;
let len = len[0] as usize;
let mut response: Vec<u8> = Vec::with_capacity(len + 2);
response.extend(&[start, len as u8]);
{
let reference = self.port.by_ref();
reference.take(len as u64).read_to_end(&mut response)?;
}
debug!("Receive: {:?}", response);
Ok(Response::from_bytes(&response)?)
}
fn receive(&mut self, command_type: CommandType) -> Result<Response> {
loop {
let packet = self.receive_packet()?;
if packet.command == command_type {
return Ok(packet);
} else {
warn!("Dropped packet due to incorrect command type: {:?}", packet);
}
}
}
fn exchange(&mut self, command: Command) -> Result<Response> {
let command_type = command.command;
self.send(command)?;
self.receive(command_type)
}
fn exchange_simple(&mut self, command: CommandType) -> Result<Response> {
let cmd = Command {
address: self.address,
command: command,
data: vec![],
};
self.exchange(cmd)
}
pub fn reset(&mut self) -> Result<()> {
self.exchange_simple(CommandType::Reset)?;
Ok(())
}
pub fn get_version(&mut self) -> Result<(u8, u8)> {
let response = self.exchange_simple(CommandType::GetFirmwareVersion)?;
Ok((response.data[0], response.data[1]))
}
pub fn set_work_antenna(&mut self, antenna_id: u8) -> Result<()> {
let cmd = Command {
address: self.address,
command: CommandType::SetWorkAntenna,
data: vec![antenna_id],
};
self.exchange(cmd)?;
Ok(())
}
pub fn get_work_antenna(&mut self) -> Result<u8> {
let response = self.exchange_simple(CommandType::GetWorkAntenna)?;
Ok(response.data[0])
}
pub fn get_antenna_connection_detector(&mut self) -> Result<i8> {
let response = self.exchange_simple(CommandType::GetAntConnectionDetector)?;
Ok(-(response.data[0] as i8))
}
pub fn set_output_power(&mut self, power: &[u8]) -> Result<()> {
assert_eq!(power.len(), self.antenna_count);
let cmd = Command {
address: self.address,
command: CommandType::SetOutputPower,
data: power.to_vec(),
};
self.exchange(cmd)?;
Ok(())
}
pub fn get_output_power(&mut self) -> Result<Vec<u8>> {
let response = self.exchange_simple(CommandType::GetOutputPower)?;
if response.data.len() == 1 {
return Ok(iter::repeat(response.data[0])
.take(self.antenna_count)
.collect());
}
Ok(response.data)
}
pub fn get_temperature(&mut self) -> Result<i8> {
let response = self.exchange_simple(CommandType::GetReaderTemperature)?;
let mut temp = response.data[1] as i8;
if response.data[0] == 0x00 {
temp = -temp;
}
Ok(temp)
}
pub fn measure_return_loss(&mut self, frequency: f32) -> Result<i8> {
let cmd = Command {
address: self.address,
command: CommandType::GetRFPortReturnLoss,
data: vec![convert_from_frequency(frequency)?],
};
let response = self.exchange(cmd)?;
Ok(-(response.data[0] as i8))
}
pub fn real_time_inventory(&mut self, repeat: u8) -> Result<InventoryResult> {
let cmd = Command {
address: self.address,
command: CommandType::RealTimeInventory,
data: vec![repeat],
};
self.send(cmd)?;
let mut tags: Vec<InventoryItem> = Vec::new();
loop {
let response = self.receive(CommandType::RealTimeInventory)?;
if response.data.len() < 8 {
return InventoryResult::from_bytes(&response.data, tags);
};
tags.push(InventoryItem::from_bytes(&response.data)?);
}
}
pub fn read(
&mut self,
bank: MemoryBank,
password: &[u8],
start: u8,
length: u8,
) -> Result<Vec<ReadResult>> {
let mut data = vec![bank as u8, start, length];
data.extend(password);
let cmd = Command {
address: self.address,
command: CommandType::Read,
data: data,
};
self.send(cmd)?;
let mut results = Vec::new();
loop {
let response = self.receive(CommandType::Read)?;
if response.status == Some(ResponseCode::NoTagError) {
return Ok(results);
}
let (tag_count, packet) = ReadResult::from_bytes(&response.data)?;
results.push(packet);
if results.len() == tag_count {
return Ok(results);
}
}
}
pub fn set_epc_match(&mut self, epc: &[u8]) -> Result<()> {
let mut mode = 0x00;
if epc.len() == 0 {
mode = 0x01; }
let mut data = vec![mode, epc.len() as u8];
data.extend(epc);
let cmd = Command {
address: self.address,
command: CommandType::SetAccessEPCMatch,
data: data,
};
self.exchange(cmd)?;
Ok(())
}
}