#[derive(Debug, Clone)]
pub struct TagInfo {
pub epc: String,
pub rssi: u8,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum MemoryBank {
Reserved = 0x00,
Epc = 0x01,
Tid = 0x02,
User = 0x03,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum SelectTarget {
#[default]
S0 = 0x00,
S1 = 0x01,
S2 = 0x02,
S3 = 0x03,
Sl = 0x04,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum SelectAction {
#[default]
Action0 = 0x00,
Action1 = 0x01,
Action2 = 0x02,
Action3 = 0x03,
Action4 = 0x04,
Action5 = 0x05,
Action6 = 0x06,
Action7 = 0x07,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum SelectMode {
Always = 0x00,
#[default]
Disabled = 0x01,
NonPolling = 0x02,
}
#[derive(Debug, Clone)]
pub struct SelectParams {
pub target: SelectTarget,
pub action: SelectAction,
pub mem_bank: MemoryBank,
pub pointer: u32,
pub mask: Vec<u8>,
pub truncate: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Region {
China900 = 0x01,
Us = 0x02,
Europe = 0x03,
China800 = 0x04,
Korea = 0x06,
}
impl Region {
pub fn base_frequency(&self) -> f64 {
match self {
Region::China900 => 920.125,
Region::Us => 902.25,
Region::Europe => 865.1,
Region::China800 => 840.125,
Region::Korea => 917.1,
}
}
pub fn channel_spacing(&self) -> f64 {
match self {
Region::China900 => 0.25,
Region::Us => 0.5,
Region::Europe => 0.2,
Region::China800 => 0.25,
Region::Korea => 0.2,
}
}
pub fn channel_from_frequency(&self, freq_mhz: f64) -> u8 {
((freq_mhz - self.base_frequency()) / self.channel_spacing()) as u8
}
pub fn frequency_from_channel(&self, channel: u8) -> f64 {
(channel as f64) * self.channel_spacing() + self.base_frequency()
}
}
impl TryFrom<u8> for Region {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x01 => Ok(Region::China900),
0x02 => Ok(Region::Us),
0x03 => Ok(Region::Europe),
0x04 => Ok(Region::China800),
0x06 => Ok(Region::Korea),
_ => Err(()),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct QueryParams {
pub sel: QuerySel,
pub session: QuerySession,
pub target: QueryTarget,
pub q: u8,
}
impl Default for QueryParams {
fn default() -> Self {
Self {
sel: QuerySel::All,
session: QuerySession::S0,
target: QueryTarget::A,
q: 4,
}
}
}
impl QueryParams {
pub fn to_bytes(&self) -> [u8; 2] {
let byte0 = 0x10 | ((self.sel as u8) << 2) | (self.session as u8);
let byte1 = ((self.target as u8) << 7) | ((self.q & 0x0F) << 3);
[byte0, byte1]
}
pub fn from_bytes(bytes: [u8; 2]) -> Self {
let sel = match (bytes[0] >> 2) & 0x03 {
0 | 1 => QuerySel::All,
2 => QuerySel::NotSl,
3 => QuerySel::Sl,
_ => QuerySel::All,
};
let session = match bytes[0] & 0x03 {
0 => QuerySession::S0,
1 => QuerySession::S1,
2 => QuerySession::S2,
3 => QuerySession::S3,
_ => QuerySession::S0,
};
let target = if (bytes[1] >> 7) & 0x01 == 0 {
QueryTarget::A
} else {
QueryTarget::B
};
let q = (bytes[1] >> 3) & 0x0F;
Self {
sel,
session,
target,
q,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum QuerySel {
#[default]
All = 0x00,
NotSl = 0x02,
Sl = 0x03,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum QuerySession {
#[default]
S0 = 0x00,
S1 = 0x01,
S2 = 0x02,
S3 = 0x03,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum QueryTarget {
#[default]
A = 0x00,
B = 0x01,
}
impl PartialEq for TagInfo {
fn eq(&self, other: &Self) -> bool {
self.epc == other.epc
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum LockAction {
Unlock = 0x00,
Lock = 0x01,
PermUnlock = 0x02,
PermLock = 0x03,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum LockTarget {
User = 0x01,
Tid = 0x02,
Epc = 0x03,
AccessPassword = 0x04,
KillPassword = 0x05,
}
#[derive(Debug, Clone)]
pub struct LockPayload {
pub target: LockTarget,
pub action: LockAction,
}
impl LockPayload {
pub fn to_bytes(&self) -> [u8; 3] {
let shift = match self.target {
LockTarget::User => 0,
LockTarget::Tid => 2,
LockTarget::Epc => 4,
LockTarget::AccessPassword => 6,
LockTarget::KillPassword => 8,
};
let mask: u16 = 0x03 << shift;
let action: u16 = (self.action as u16) << shift;
let payload: u32 = ((mask as u32) << 10) | (action as u32);
[
((payload >> 16) & 0xFF) as u8,
((payload >> 8) & 0xFF) as u8,
(payload & 0xFF) as u8,
]
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum RfLinkProfile {
Fm0_40kHz = 0xD0,
Fm0_400kHz = 0xD1,
Miller4_250kHz = 0xD2,
Miller4_300kHz = 0xD3,
Miller2_40kHzDrm = 0xD4,
}
impl TryFrom<u8> for RfLinkProfile {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0xD0 => Ok(RfLinkProfile::Fm0_40kHz),
0xD1 => Ok(RfLinkProfile::Fm0_400kHz),
0xD2 => Ok(RfLinkProfile::Miller4_250kHz),
0xD3 => Ok(RfLinkProfile::Miller4_300kHz),
0xD4 => Ok(RfLinkProfile::Miller2_40kHzDrm),
_ => Err(()),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct QtControl {
pub short_range: bool,
pub persistence: bool,
}
impl QtControl {
pub fn to_byte(&self) -> u8 {
let mut byte = 0u8;
if self.short_range {
byte |= 0x01;
}
if self.persistence {
byte |= 0x02;
}
byte
}
}
#[derive(Debug)]
pub enum UhfError {
Transport(String),
InvalidParameter(String),
InvalidResponse(String),
}
pub(crate) fn bytes_to_hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{:02X}", b)).collect()
}