跳转到内容

Rust SDK

Rust SDK 适用于 Rust 语言开发,提供类型安全、高性能的打印机控制接口,支持跨平台应用开发。

Rust SDK 使用 Cargo 管理依赖。在 Cargo.toml 中添加:

[dependencies]
psdk-father = { path = "path/to/psdk/rust/frame/father" }
psdk-cpcl = { path = "path/to/psdk/rust/fruits/cpcl" }
psdk-esc = { path = "path/to/psdk/rust/fruits/esc" }
psdk-tspl = { path = "path/to/psdk/rust/fruits/tspl" }
Crate说明
psdk-father核心框架
psdk-extension扩展功能
psdk-toolkit工具集
psdk-cpclCPCL 指令
psdk-escESC 指令
psdk-tsplTSPL 指令
use psdk_father::{ConnectedDevice, Commander};
use psdk_cpcl::{CPCL, args::*};
// 实现 ConnectedDevice trait
struct MyDevice {
// 设备信息
}
impl ConnectedDevice for MyDevice {
fn write(&mut self, data: &[u8]) -> Result<usize, std::io::Error> {
// 实现写入逻辑
Ok(data.len())
}
fn read(&mut self) -> Result<Vec<u8>, std::io::Error> {
// 实现读取逻辑
Ok(Vec::new())
}
fn device_name(&self) -> String {
"Printer".to_string()
}
fn is_connected(&self) -> bool {
true
}
}
let device = MyDevice::new();
let mut printer = CPCL::generic(device);
// 打印标签
printer
.page(Page::new(576, 400))
.text(Text::new(50, 50, "商品标签"))
.barcode(Barcode::new(50, 150, "1234567890"))
.print()
.write()?;

CPCL 指令用于便携式标签打印机。详细指令说明请参考 CPCL 指令文档

use psdk_cpcl::{CPCL, args::*, marks::*};
let device = create_device(); // 创建设备连接
let mut printer = CPCL::generic(device);
// 打印简单标签
printer
.page(Page::new(576, 400))
.text(Text::builder()
.x(50)
.y(50)
.font(Font::TSS24)
.content("商品标签")
.build())
.barcode(Barcode::builder()
.x(50)
.y(150)
.code_type(CodeType::Code128)
.height(50)
.content("1234567890")
.build())
.print()
.write()?;
use psdk_cpcl::{CPCL, args::*, marks::*};
let mut printer = CPCL::generic(device);
// 构建完整标签
printer
// 页面设置
.page(Page::builder()
.width(576)
.height(400)
.copies(1)
.build())
// 标题(居中、加粗)
.center()
.bold(true)
.text(Text::builder()
.x(0)
.y(30)
.font(Font::TSS24MAX1)
.content("商品标签")
.build())
.bold(false)
.left()
// 分隔线
.line(Line::builder()
.x1(30).y1(70)
.x2(546).y2(70)
.width(2)
.build())
// 商品信息
.text(Text::builder()
.x(30).y(90)
.font(Font::TSS24)
.content("名称: 有机苹果")
.build())
.text(Text::builder()
.x(30).y(130)
.font(Font::TSS24)
.content("规格: 500g/袋")
.build())
.text(Text::builder()
.x(30).y(170)
.font(Font::TSS24)
.bold(true)
.content("价格: ¥25.90")
.build())
// 一维条码
.barcode(Barcode::builder()
.x(80).y(220)
.code_type(CodeType::Code128)
.height(50)
.line_width(1)
.content("6901234567890")
.build())
// 二维码
.qrcode(QRCode::builder()
.x(400).y(90)
.width(5)
.level(CorrectLevel::M)
.content("https://example.com")
.build())
// 边框
.box_rect(BoxRect::builder()
.x1(20).y1(20)
.x2(556).y2(380)
.width(2)
.build())
// 打印
.print()
.write()?;
// 居中对齐
printer.center();
printer.text(Text::new(0, 50, "居中文本"));
// 左对齐
printer.left();
printer.text(Text::new(30, 100, "左对齐文本"));
// 右对齐
printer.right();
printer.text(Text::new(0, 150, "右对齐文本"));
use psdk_cpcl::marks::Font;
// 可用字体
Font::TSS16 // 16点阵
Font::TSS20 // 20点阵
Font::TSS24 // 24点阵(推荐)
Font::TSS28 // 28点阵
Font::TSS32 // 32点阵
Font::TSS24MAX1 // 24点阵2倍放大
Font::TSS24MAX2 // 24点阵3倍放大
use psdk_cpcl::marks::CodeType;
// 可用条码类型
CodeType::Code128 // Code 128(推荐)
CodeType::Code39 // Code 39
CodeType::Code93 // Code 93
CodeType::EAN8 // EAN-8
CodeType::EAN13 // EAN-13
CodeType::UPCA // UPC-A
CodeType::UPCE // UPC-E
CodeType::Codabar // Codabar
CodeType::I2OF5 // Interleaved 2 of 5
// 查询打印机状态
printer.status().write()?;
// 查询 SN 号
printer.sn().write()?;
// 查询电量
printer.battery_volume().write()?;
// 查询型号
printer.model().write()?;
// 查询版本
printer.version().write()?;

ESC 指令广泛用于热敏小票打印机。详细指令说明请参考 ESC 指令文档

use psdk_esc::{ESC, args::*};
let mut printer = ESC::generic(device);
// 完整打印流程
printer
.wakeup()
.enable()
.image(Image::builder()
.data(image_data)
.mode(ImageMode::Normal)
.compress(false)
.build())
.position()
.stop_job()
.write()?;

推荐的打印顺序:

  1. 唤醒打印机
  2. 使能打印机
  3. 打印图片
  4. 打印定位(连续纸不需要)
  5. 结束打印任务
let mut printer = ESC::generic(device);
// 1. 唤醒打印机
printer.wakeup();
// 2. 使能打印机
printer.enable();
// 3. 打印图片
let image = Image::builder()
.data(image_data)
.mode(ImageMode::Normal)
.compress(false)
.threshold(190)
.build();
printer.image(image);
// 4. 打印定位(标签纸需要)
printer.position();
// 5. 结束打印任务
printer.stop_job();
// 执行写入
let result = printer.write()?;
println!("打印成功,写入 {} 字节", result.bytes_written);
// 设置打印浓度(0-2)
printer.thickness(Thickness::Medium);
// 设置关机时间(分钟)
printer.set_shutdown_time(10);
// 设置纸张类型
printer.paper_type(PaperType::builder()
.paper_type(PaperTypeEnum::Continuous)
.build());
// 设置纸张类型(Q系列)
printer.paper_type_q3(PaperTypeQ3::builder()
.paper_type(PaperTypeQ3Enum::Gap)
.build());
// 查询打印机信息
printer.info().write()?;
// 查询打印机状态
printer.state().write()?;
// 查询电量
printer.battery_volume().write()?;
// 查询 MAC 地址
printer.mac().write()?;
// 查询 SN 号
printer.sn().write()?;
// 查询型号
printer.model().write()?;
// 查询固件版本
printer.printer_version().write()?;

TSPL 指令用于标签条码打印机。详细指令说明请参考 TSPL 指令文档

use psdk_tspl::{TSPL, args::*, marks::*};
let mut printer = TSPL::generic(device);
// 打印简单标签
printer
.page(Page::new(60, 40))
.gap(true)
.direction(Direction::new(DirectionType::Up, false))
.cls()
.text(Text::builder()
.x(50).y(50)
.font(Font::TSS24)
.content("标签内容")
.build())
.print(1)
.write()?;
let mut printer = TSPL::generic(device);
printer
// 页面设置
.page(Page::new(60, 40))
.gap(true)
.direction(Direction::new(DirectionType::Up, false))
.density(8)
.speed(4)
.cls()
// 标题
.text(Text::builder()
.x(180).y(30)
.font(Font::TSS24)
.x_multi(2).y_multi(2)
.content("商品标签")
.build())
// 分隔线
.bar(Bar::builder()
.x(30).y(80)
.width(420).height(2)
.build())
// 商品信息
.text(Text::builder()
.x(30).y(100)
.font(Font::TSS24)
.content("品名: 有机苹果")
.build())
.text(Text::builder()
.x(30).y(140)
.font(Font::TSS24)
.content("规格: 500g/袋")
.build())
.text(Text::builder()
.x(30).y(180)
.font(Font::TSS24)
.is_bold(true)
.content("价格: ¥25.90")
.build())
// 一维条码
.barcode(Barcode::builder()
.x(100).y(220)
.code_type(CodeType::Code128)
.height(60)
.show_type(ShowType::Below)
.content("6901234567890")
.build())
// 二维码
.qrcode(QRCode::builder()
.x(380).y(90)
.cell_width(4)
.correct_level(CorrectLevel::M)
.content("https://example.com")
.build())
// 边框
.box_rect(BoxRect::builder()
.x(20).y(20)
.x_end(460).y_end(310)
.line_width(2)
.build())
// 打印
.print(1)
.write()?;
// 设置页面尺寸(mm)
printer.page(Page::new(60, 40));
// 设置缝隙纸
printer.gap(true);
// 设置黑标纸
printer.bline();
// 设置连续纸
printer.continuous();
// 设置打印方向
printer.direction(Direction::new(DirectionType::Up, false));
// 设置浓度(0-15)
printer.density(8);
// 设置速度(1-6)
printer.speed(4);
// 清除缓冲区
printer.cls();
// 填充矩形
printer.bar(Bar::builder()
.x(50).y(100)
.width(200).height(2)
.build());
// 空心矩形
printer.box_rect(BoxRect::builder()
.x(50).y(50)
.x_end(300).y_end(200)
.line_width(2)
.build());
// 画线
printer.line(Line::builder()
.x(50).y(50)
.x_end(300).y_end(200)
.line_width(2)
.build());
// 画圆
printer.circle(Circle::builder()
.x(200).y(200)
.diameter(100)
.line_width(2)
.build());
// 椭圆
printer.ellipse(Ellipse::builder()
.x(200).y(200)
.width(150).height(80)
.line_width(2)
.build());
// 反色区域
printer.reverse(Reverse::builder()
.x(50).y(50)
.width(200).height(100)
.build());

Rust SDK 使用 Result 类型处理错误:

use std::error::Error;
fn print_label(device: impl ConnectedDevice) -> Result<(), Box<dyn Error>> {
let mut printer = CPCL::generic(device);
let result = printer
.page(Page::new(576, 400))
.text(Text::new(50, 50, "测试标签"))
.print()
.write()?;
println!("打印成功,写入 {} 字节", result.bytes_written);
Ok(())
}
// 使用
match print_label(device) {
Ok(_) => println!("打印完成"),
Err(e) => eprintln!("打印失败: {}", e),
}

Rust SDK 支持异步操作(需要启用 async 特性):

use tokio;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let device = create_async_device().await?;
let mut printer = CPCL::generic(device);
printer
.page(Page::new(576, 400))
.text(Text::new(50, 50, "异步打印"))
.print()
.write()
.await?;
Ok(())
}

CPCL、ESC、TSPL 打印机实例不是 SendSync 的,如需在多线程环境使用,建议:

use std::sync::{Arc, Mutex};
let printer = Arc::new(Mutex::new(CPCL::generic(device)));
// 在不同线程中使用
let printer_clone = Arc::clone(&printer);
std::thread::spawn(move || {
let mut p = printer_clone.lock().unwrap();
p.page(Page::new(576, 400))
.text(Text::new(50, 50, "线程打印"))
.print()
.write()
.unwrap();
});
use psdk_cpcl::{CPCL, args::*, marks::*};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
// 创建设备连接
let device = create_bluetooth_device("Printer")?;
// 创建打印机实例
let mut printer = CPCL::generic(device);
// 打印标签
printer
.page(Page::new(576, 400))
.center()
.bold(true)
.text(Text::builder()
.x(0).y(30)
.font(Font::TSS24MAX1)
.content("商品标签")
.build())
.bold(false)
.left()
.line(Line::new(30, 70, 546, 70, 2))
.text(Text::new(30, 90, "名称: 有机苹果"))
.text(Text::new(30, 130, "规格: 500g/袋"))
.text(Text::new(30, 170, "价格: ¥25.90"))
.barcode(Barcode::builder()
.x(80).y(220)
.code_type(CodeType::Code128)
.height(50)
.content("6901234567890")
.build())
.qrcode(QRCode::builder()
.x(400).y(90)
.width(5)
.level(CorrectLevel::M)
.content("https://example.com")
.build())
.box_rect(BoxRect::new(20, 20, 556, 380, 2))
.print()
.write()?;
println!("打印成功");
Ok(())
}

使用 Builder 模式构建复杂参数:

let text = Text::builder()
.x(50)
.y(50)
.font(Font::TSS24)
.rotation(Rotation::Rotate0)
.bold(true)
.underline(true)
.content("复杂文本")
.build();
printer.text(text);
for i in 0..10 {
printer
.page(Page::new(576, 400))
.text(Text::new(50, 50, &format!("标签 #{}", i + 1)))
.print()
.write()?;
// 短暂延迟避免打印机缓冲区溢出
std::thread::sleep(std::time::Duration::from_millis(100));
}

Rust SDK 提供 C/JNI FFI 接口,可在其他语言中调用:

use psdk_extension::export_c::*;
#[no_mangle]
pub extern "C" fn psdk_cpcl_print(
device_ptr: *mut ConnectedDevice,
width: i32,
height: i32,
text: *const c_char,
) -> i32 {
// FFI 实现
}
use psdk_extension::export_jni::*;
#[no_mangle]
pub extern "system" fn Java_com_printer_psdk_CPCL_print(
env: JNIEnv,
class: JClass,
device: JObject,
width: jint,
height: jint,
text: JString,
) -> jint {
// JNI 实现
}

完整示例请参考: