JavaScript SDK
The JavaScript SDK supports WeChat Mini Programs, UniApp, Taro, and similar frontend frameworks, connecting to printers over Bluetooth Low Energy (BLE).
Installation
Section titled “Installation”All packages are published on npm with the @psdk/ prefix.
npm install @psdk/frame-father @psdk/cpcl @psdk/device-ble-uniappAvailable packages
Section titled “Available packages”Core packages
Section titled “Core packages”| Package name | Description |
|---|---|
@psdk/frame-father | Core framework |
Command packages
Section titled “Command packages”| Package name | Description |
|---|---|
@psdk/cpcl | CPCL commands |
@psdk/esc | ESC commands |
@psdk/tspl | TSPL commands |
Device packages
Section titled “Device packages”| Package name | Description |
|---|---|
@psdk/device-ble-uniapp | UniApp BLE |
@psdk/device-ble-wechat | WeChat Mini Programs BLE |
@psdk/device-ble-taro | Taro BLE |
Quick start
Section titled “Quick start”1. Import dependencies
Section titled “1. Import dependencies”import { UniappBleBluetooth } from "@psdk/device-ble-uniapp";import { ConnectedDevice, Lifecycle, Raw } from '@psdk/frame-father';2. Initialize Bluetooth
Section titled “2. Initialize Bluetooth”const bluetooth = new UniappBleBluetooth({ allowNoName: false, // Allow devices without names});3. Scan for devices
Section titled “3. Scan for devices”// Listen for discovered devicesbluetooth.discovered(async (devices) => { if (!devices.length) return;
console.log('Device found:', devices);
// Connect when the target device is found const targetDevice = devices.find(d => d.name.includes('Printer')); if (targetDevice) { await connectDevice(targetDevice); }});
// Start scanningawait bluetooth.startDiscovery();4. Connect to a device
Section titled “4. Connect to a device”let connectedDevice;
async function connectDevice(device) { try { connectedDevice = await bluetooth.connect(device); console.log('Connected:', connectedDevice.name); } catch (error) { console.error('Connection failed:', error); }}5. Disconnect
Section titled “5. Disconnect”await bluetooth.disconnect();CPCL command usage
Section titled “CPCL command usage”CPCL commands are used by portable label printers. See the CPCL command reference for details.
Basic printing
Section titled “Basic printing”import { CPCL } from '@psdk/cpcl';import { Lifecycle } from '@psdk/frame-father';
const lifecycle = new Lifecycle(connectedDevice);const cpcl = CPCL.generic(lifecycle);
const reporter = await cpcl .page({ width: 576, height: 400 }) .text({ x: 50, y: 50, content: '商品标签' }) .barcode({ x: 50, y: 150, content: '1234567890' }) .print() .write({ chunkSize: 512 });
console.log('Print result:', reporter);Complete label example
Section titled “Complete label example”import { CPCL } from '@psdk/cpcl';import { Lifecycle } from '@psdk/frame-father';
const lifecycle = new Lifecycle(connectedDevice);const cpcl = CPCL.generic(lifecycle);
await cpcl .page({ width: 576, height: 400 }) // Title .center() .text({ x: 0, y: 30, font: 4, size: 2, content: '商品标签', }) // Product information .left() .text({ x: 30, y: 100, content: '名称: 有机苹果' }) .text({ x: 30, y: 140, content: '规格: 500g/袋' }) .text({ x: 30, y: 180, content: '价格: ¥25.90' }) // Barcode .barcode({ x: 100, y: 230, type: '128', height: 60, content: '6901234567890', }) // QR code .qrcode({ x: 400, y: 100, content: 'https://example.com', }) .print() .write({ chunkSize: 512 });ESC command usage
Section titled “ESC command usage”ESC commands are widely used by thermal receipt printers. See the ESC command reference for details.
Basic printing
Section titled “Basic printing”import { ESC } from '@psdk/esc';import { Lifecycle } from '@psdk/frame-father';
const lifecycle = new Lifecycle(connectedDevice);const esc = ESC.generic(lifecycle);
await esc .initialize() .align('center') .text('收银小票') .align('left') .text('商品A x1 ¥29.90') .cut() .write({ chunkSize: 512 });Receipt printing example
Section titled “Receipt printing example”import { ESC } from '@psdk/esc';import { Lifecycle } from '@psdk/frame-father';
const lifecycle = new Lifecycle(connectedDevice);const esc = ESC.generic(lifecycle);
await esc .initialize() // Title .align('center') .textSize({ width: 2, height: 2 }) .bold(true) .text('XX 便利店') .bold(false) .textSize({ width: 1, height: 1 }) .text('订单号: 20240115001') .text('================================') // Product list .align('left') .text('可乐 500ml x2 ¥6.00') .text('薯片 大包 x1 ¥8.50') .text('--------------------------------') // Total .textSize({ width: 1, height: 2 }) .text('合计: ¥14.50') .textSize({ width: 1, height: 1 }) // QR code .align('center') .qrcode({ content: 'https://shop.example.com', size: 5 }) .text('扫码关注店铺') .feed(3) .cut() .write({ chunkSize: 512 });TSPL command usage
Section titled “TSPL command usage”TSPL commands are used by label and barcode printers. See the TSPL command reference for details.
Basic printing
Section titled “Basic printing”import { TSPL } from '@psdk/tspl';import { Lifecycle } from '@psdk/frame-father';
const lifecycle = new Lifecycle(connectedDevice);const tspl = TSPL.generic(lifecycle);
await tspl .page({ width: 60, height: 40 }) .cls() .text({ x: 50, y: 50, content: '标签内容' }) .print(1) .write({ chunkSize: 512 });Complete label example
Section titled “Complete label example”import { TSPL } from '@psdk/tspl';import { Lifecycle } from '@psdk/frame-father';
const lifecycle = new Lifecycle(connectedDevice);const tspl = TSPL.generic(lifecycle);
await tspl .page({ width: 60, height: 40 }) .gap(3) .direction('up') .cls() // Title .text({ x: 180, y: 30, font: 'TSS24.BF2', xMulti: 2, yMulti: 2, content: '商品标签', }) // Separator line .bar({ x: 30, y: 80, width: 420, height: 2 }) // Product information .text({ x: 30, y: 100, content: '品名: 有机苹果' }) .text({ x: 30, y: 140, content: '规格: 500g/袋' }) .text({ x: 30, y: 180, content: '价格: ¥25.90' }) // Barcode .barcode({ x: 100, y: 220, type: '128', height: 60, content: '6901234567890', }) // QR code .qrcode({ x: 350, y: 100, cellWidth: 4, content: 'https://example.com', }) .print(1) .write({ chunkSize: 512 });Send raw commands
Section titled “Send raw commands”import { Raw } from '@psdk/frame-father';
// Send raw binary commandsconst reporter = await cpcl .raw(Raw.binary(new Uint8Array([0x10, 0xff, 0xbf]))) .write({ chunkSize: 512 });WeChat Mini Program example
Section titled “WeChat Mini Program example”import { WechatBleBluetooth } from "@psdk/device-ble-wechat";import { CPCL } from '@psdk/cpcl';import { Lifecycle } from '@psdk/frame-father';
Page({ data: { deviceList: [], connectedDevice: null, },
onLoad() { this.bluetooth = new WechatBleBluetooth();
// Listen for devices this.bluetooth.discovered((devices) => { this.setData({ deviceList: devices }); }); },
// Start scanning async startScan() { await this.bluetooth.startDiscovery(); },
// Connect to a device async connectDevice(e) { const device = e.currentTarget.dataset.device; try { const connectedDevice = await this.bluetooth.connect(device); this.setData({ connectedDevice }); wx.showToast({ title: 'Connected' }); } catch (error) { wx.showToast({ title: 'Connection failed', icon: 'error' }); } },
// Print async print() { const { connectedDevice } = this.data; if (!connectedDevice) return;
const lifecycle = new Lifecycle(connectedDevice); const cpcl = CPCL.generic(lifecycle);
await cpcl .page({ width: 576, height: 400 }) .text({ x: 50, y: 50, content: '小程序打印测试' }) .print() .write({ chunkSize: 512 });
wx.showToast({ title: 'Printing complete' }); },});Taro example
Section titled “Taro example”import { TaroBleBluetooth } from "@psdk/device-ble-taro";import { CPCL } from '@psdk/cpcl';import { Lifecycle } from '@psdk/frame-father';
// Initialize as with UniApp Sameconst bluetooth = new TaroBleBluetooth();
// Scan for devicesbluetooth.discovered((devices) => { console.log('Device found:', devices);});
await bluetooth.startDiscovery();
// Connect to a deviceconst connectedDevice = await bluetooth.connect(device);
// Printconst lifecycle = new Lifecycle(connectedDevice);const cpcl = CPCL.generic(lifecycle);
await cpcl .page({ width: 576, height: 400 }) .text({ x: 50, y: 50, content: 'Taro 打印测试' }) .print() .write({ chunkSize: 512 });Error handling
Section titled “Error handling”try { await cpcl.write({ chunkSize: 512 }); console.log('Print successful');} catch (error) { if (error.code === 'BLE_DISCONNECTED') { console.error('Bluetooth disconnected'); } else if (error.code === 'BLE_TIMEOUT') { console.error('Bluetooth timeout'); } else { console.error('Printing failed:', error.message); }}Example projects
Section titled “Example projects”For complete examples, see: