use crate::packet::Packet;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Cmd {
PrintStart = 0x01,
PageStart = 0x03,
SetPageSize = 0x13,
PrintQuantity = 0x15,
RfidInfo = 0x1a,
PrintClear = 0x20,
SetDensity = 0x21,
SetLabelType = 0x23,
PrinterInfo = 0x40,
PrintBitmapRowIndexed = 0x83,
PrintEmptyRow = 0x84,
PrintBitmapRow = 0x85,
PrinterCheckLine = 0x86,
PrintStatus = 0xa3,
Connect = 0xc1,
CancelPrint = 0xda,
Heartbeat = 0xdc,
PageEnd = 0xe3,
PrintEnd = 0xf3,
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InfoKey {
Density = 1,
PrintSpeed = 2,
LabelType = 3,
LanguageType = 6,
AutoShutdownTime = 7,
DeviceType = 8,
SoftVersion = 9,
Battery = 10,
DeviceSerial = 11,
HardVersion = 12,
}
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Default,
Hash,
clap::ValueEnum,
serde::Serialize,
serde::Deserialize,
)]
#[value(rename_all = "lower")]
#[serde(rename_all = "lowercase")]
pub enum Model {
#[default]
B1,
B1Pro,
B21Pro,
B18,
D11,
D11H,
D110,
}
impl Model {
pub fn as_str(self) -> &'static str {
match self {
Self::B1 => "b1",
Self::B1Pro => "b1pro",
Self::B21Pro => "b21pro",
Self::B18 => "b18",
Self::D11 => "d11",
Self::D11H => "d11h",
Self::D110 => "d110",
}
}
pub fn parse(s: &str) -> Option<Self> {
match s.to_ascii_lowercase().as_str() {
"b1" => Some(Self::B1),
"b1pro" | "b1_pro" => Some(Self::B1Pro),
"b21pro" | "b21_pro" => Some(Self::B21Pro),
"b18" => Some(Self::B18),
"d11" => Some(Self::D11),
"d11h" | "d11_h" => Some(Self::D11H),
"d110" => Some(Self::D110),
_ => None,
}
}
}
#[derive(Debug, thiserror::Error)]
#[error("unknown model '{0}' (try b1, b1pro, b21pro, b18, d11, d11h, d110)")]
pub struct ModelParseError(pub String);
impl std::str::FromStr for Model {
type Err = ModelParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s).ok_or_else(|| ModelParseError(s.to_string()))
}
}
impl std::fmt::Display for Model {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.pad(self.as_str())
}
}
pub fn pkt(cmd: Cmd, data: impl Into<Vec<u8>>) -> Packet {
Packet::new(cmd as u8, data)
}
pub fn info(key: InfoKey) -> Packet {
pkt(Cmd::PrinterInfo, vec![key as u8])
}
pub fn connect() -> Packet {
pkt(Cmd::Connect, vec![0x01])
}
pub fn heartbeat() -> Packet {
pkt(Cmd::Heartbeat, vec![0x01])
}
pub fn rfid() -> Packet {
pkt(Cmd::RfidInfo, vec![0x01])
}
pub fn set_density(level: u8) -> Packet {
pkt(Cmd::SetDensity, vec![level])
}
pub fn set_label_type(t: u8) -> Packet {
pkt(Cmd::SetLabelType, vec![t])
}
pub fn print_end() -> Packet {
pkt(Cmd::PrintEnd, vec![0x01])
}
pub fn cancel_print() -> Packet {
pkt(Cmd::CancelPrint, vec![0x01])
}
pub fn print_status() -> Packet {
pkt(Cmd::PrintStatus, vec![0x01])
}
pub fn printer_status_data() -> Packet {
Packet::new(0xa5, vec![0x01])
}
pub fn print_bitmap_row(row_index: u16, repeats: u8, pixels: &[u8]) -> Packet {
let mut data = Vec::with_capacity(6 + pixels.len());
data.extend_from_slice(&row_index.to_be_bytes());
data.extend_from_slice(&[0, 0, 0]); data.push(repeats);
data.extend_from_slice(pixels);
pkt(Cmd::PrintBitmapRow, data)
}
pub fn print_empty_row(row_index: u16, repeats: u8) -> Packet {
let mut data = Vec::with_capacity(3);
data.extend_from_slice(&row_index.to_be_bytes());
data.push(repeats);
pkt(Cmd::PrintEmptyRow, data)
}