更新记录

1.0.2(2026-10-14) 下载此版本

  • 承接项目侧下沉:pairable 协议(ident / link / syncPairableLinks / 开线解析)
  • 新增 WiredDeviceBase(有线设备开线公共基类)
  • formatPairIdentDesc:local 通道返回 "local",不再含中文「本机」(本地化由项目 catalog)

1.0.1(2026-10-14) 下载此版本

  • 边界收敛:PrintError / WeightError 下沉至能力包,core 仅保留通用设备错误
  • 修正插件描述与 keywords(去掉打印 / BLE 域语义)

1.0.0(2026-10-14) 下载此版本

  • 首次发布
  • 提供设备框架核心:能力接口、状态机、注册表、会话管理与打印模型
查看更多

平台兼容性

uni-app(5.06)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ √ - - √ - √ - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
√ - - - - - - - - - - -

pro-device-core — 设备框架核心

设备管理框架的基础层。提供连接状态机、设备注册表、会话管理器、传输层接口以及 ConnectableBase 基类。

不包含任何具体设备或传输层实现,各能力域由独立插件提供:

插件 职责
pro-device-core 框架核心(本包)
pro-device-print 打印接口、画布模型、SDKPrinterBase
pro-device-scale 称重接口 IWeighable、ScaleDevice 类型
pro-device-scanner 扫码接口 IScannable、ScannerDevice 类型
pro-device-terminal 终端接口 TerminalDevice、TerminalCapabilities
pro-device-adp-ble BLE 传输适配器 BLEAdapter
pro-device-adp-uart 板载 tty 串口 SerialAdapter(仅 Android)
pro-device-adp-usb USB Host 串口 UsbSerialAdapter(仅 Android)
pro-device-adp-sunmi 商米 UTS 原生适配层

架构总览

┌──────────────────────────────────────────────────────────────┐
│                        业务层 (Vue / Pinia)                  │
└─────────────────────────────┬────────────────────────────────┘
                              │ useAppDeviceStore / createDeviceSession
┌─────────────────────────────▼────────────────────────────────┐
│              项目层 src/devices/                              │
│  DeviceRegistry  ·  createDeviceSession()  ·  detect*()      │
│  具体设备: GPrinterGPM421 / FayaBX380 / SunmiScanner ...    │
└──────┬──────────────────────┬──────────────────────┬─────────┘
       │                      │                      │
┌──────▼──────┐  ┌────────────▼──────┐  ┌───────────▼─────────┐
│pro-device   │  │ pro-device-print  │  │  pro-device-scale   │
│   -core     │  │ pro-device-adp-ble    │  │  pro-device-scanner │
│ (本包)      │  │ pro-device-adp-sunmi  │  │  pro-device-terminal│
└─────────────┘  └───────────────────┘  └─────────────────────┘

快速上手

1. 最小示例:连接一台 BLE 打印机并打印

import { DeviceRegistry, DeviceSession } from '@/uni_modules/pro-device-core'
import { SDKPrinterBase } from '@/uni_modules/pro-device-print'
// 项目中实际通过 src/devices/index.ts 封装好的工厂函数调用,此处展示底层逻辑

type MyDeviceMap = { print: GPrinterGPM421 }

const registry = new DeviceRegistry<GPrinterGPM421>()
  .registerModel('Gprinter', 'GP-M421', cfg => new GPrinterGPM421(cfg))

const session = new DeviceSession<MyDeviceMap>()
  .setRegistry('print', registry)

// ── 连接 ──────────────────────────────────────────────────────
const printer = await session.acquire('print', {
  brand: 'Gprinter',
  model: 'GP-M421',
  ident: 'AA:BB:CC:DD:EE:FF',  // BLE MAC 地址或 deviceId
})

// ── 打印 ──────────────────────────────────────────────────────
const label = new HazardousWasteLabel({ chemName: '废矿物油', code: 'HW08-001' })
await printer.print(label)

// ── 清理(组件 onUnmounted) ─────────────────────────────────
await session.releaseAll()

核心 API

ConnectionState — 连接状态枚举

import { ConnectionState } from '@/uni_modules/pro-device-core'

ConnectionState.Disconnected   // 'disconnected'  初始/断开后
ConnectionState.Connecting     // 'connecting'    连接中
ConnectionState.Connected      // 'connected'     已连接
ConnectionState.Disconnecting  // 'disconnecting' 断开中
ConnectionState.Error          // 'error'         连接失败

合法的状态跳转:

Disconnected → Connecting → Connected → Disconnecting → Disconnected
                          ↘                           ↗
                           Error → Connecting / Disconnected

ConnectableBase — 可连接设备基类

所有需要"连接/断开"能力的设备都应继承此类。它内嵌 ConnectionStateMachine,子类只需实现 connect() / disconnect()。

import { ConnectableBase } from '@/uni_modules/pro-device-core'
import type { IConnectable, Unsubscribe } from '@/uni_modules/pro-device-core'

export class MyDevice extends ConnectableBase {
  // 当前连接状态(继承自基类)
  // get state(): ConnectionState

  async connect(): Promise<void> {
    this._sm.transition(ConnectionState.Connecting)
    await openHardware()
    this._sm.transition(ConnectionState.Connected)
  }

  async disconnect(): Promise<void> {
    this._sm.transition(ConnectionState.Disconnecting)
    await closeHardware()
    this._sm.forceSet(ConnectionState.Disconnected)
  }
}

// ── 使用 ──────────────────────────────────────────────────────
const device = new MyDevice()

// 订阅状态变化
const unsub: Unsubscribe = device.onStateChange(state => {
  console.log('状态变化:', state)
})

await device.connect()           // → Connecting → Connected
console.log(device.state)       // 'connected'
await device.disconnect()        // → Disconnecting → Disconnected

unsub()                          // 取消订阅

DeviceRegistry<T> — 设备注册表

使用 matcher 断言函数匹配设备,支持模糊匹配。注册顺序决定优先级(先注册先匹配)。

import { DeviceRegistry } from '@/uni_modules/pro-device-core'

// 按型号前缀注册(推荐用于同型号系列)
const registry = new DeviceRegistry<MyPrinter>()
  .registerModel('Gprinter', 'GP-M421', cfg => new GPrinterGPM421(cfg))
  .registerModel('Xprinter', 'XP-P441B', cfg => new XPrinterXPP441B(cfg))

// 按品牌注册(同品牌共用实现)
registry.registerBrand('sunmi', cfg => new SunmiBuiltInPrinter(cfg))

// 完全自定义 matcher(例如匹配多个型号)
registry.register(
  (brand, model) => brand === 'Faya' && ['BX380', 'E350', 'E360'].includes(model),
  cfg => new FayaScale(cfg),
)

// ── 解析 ──────────────────────────────────────────────────────
const printer = registry.resolve({ brand: 'Gprinter', model: 'GP-M421', ident: '...' })

// ── 探测(不实例化) ──────────────────────────────────────────
if (registry.canResolve('sunmi', 'T2')) {
  console.log('当前终端有内置打印机')
}

DeviceSession<TMap> — 设备会话管理器

统一管理多台设备的生命周期。TMap 由项目层传入,将设备类型键映射到对应实例类型。

import { DeviceSession } from '@/uni_modules/pro-device-core'

// 项目层类型映射(src/devices/index.ts 中定义)
type ProjectDeviceTypeMap = {
  print:    PrintDevice
  scale:    ScaleDevice
  scanner:  ScannerDevice
  terminal: TerminalDevice
}

const session = new DeviceSession<ProjectDeviceTypeMap>()
  .setRegistry('print',    printRegistry)
  .setRegistry('scale',    scaleRegistry)
  .setRegistry('scanner',  scannerRegistry)
  .setRegistry('terminal', terminalRegistry)

acquire(type, config) — 连接并获取设备

// 返回类型由 TMap 精确推导,无需类型断言
const printer  = await session.acquire('print',   { brand: 'Gprinter', model: 'GP-M421', ident: '...' })
const scale    = await session.acquire('scale',   { brand: 'Faya', model: 'BX380', ident: 'AA:BB:...' })
const scanner  = await session.acquire('scanner', { brand: 'sunmi', model: 'T2' })
const terminal = await session.acquire('terminal', { brand: 'sunmi', model: 'T2' })
  • 若设备已连接(相同 type|brand|model|ident),直接复用实例,不重复连接
  • 非可连接设备(如 SunmiTerminal)自动走缓存,避免重复读取系统信息

release(device) — 断开指定设备

await session.release(printer)   // 断开打印机,从会话移除

releaseAll() — 断开所有设备

// 在 onUnmounted 中调用,防止内存泄漏
onUnmounted(() => session.releaseAll())

完整 Vue 组件示例

import { onMounted, onUnmounted, ref } from 'vue'
import { createDeviceSession } from '@/devices'

const session = createDeviceSession()
const printer = ref<PrintDevice | null>(null)

onMounted(async () => {
  try {
    printer.value = await session.acquire('print', {
      brand: 'Gprinter',
      model: 'GP-M421',
      ident: 'AA:BB:CC:DD:EE:FF',
    })
  } catch (e) {
    uni.showToast({ title: '打印机连接失败', icon: 'none' })
  }
})

onUnmounted(() => session.releaseAll())

ConnectionStateMachine — 状态机

通常通过 ConnectableBase._sm 使用,无需直接实例化。

import { ConnectionStateMachine } from '@/uni_modules/pro-device-core'
import { ConnectionState } from '@/uni_modules/pro-device-core'

const sm = new ConnectionStateMachine()

sm.transition(ConnectionState.Connecting)   // 合法跳转
sm.forceSet(ConnectionState.Error)          // 强制设置(用于外部事件,如蓝牙断连通知)

const unsub = sm.onStateChange(state => console.log(state))
unsub()  // 取消订阅

ITransport — 传输层接口

BLEAdapter、SerialAdapter、UsbSerialAdapter 均满足此接口(结构类型,无 implements)。

连接 vs 断开(抹平通道差异)

语义 统一入口 说明
连接 await open(config) resolve = 会话已建立;不需要再订 onConnect
主动断开 await close() 不触发 onDisconnect
意外断开 onDisconnect(cb) BLE/USB:原生事件;tty:可用 SessionProbe 合成
import type { ITransport, TransportConfig, TransportDisconnectReason } from '@/uni_modules/pro-device-core'
import { SessionProbe, CallbackHub } from '@/uni_modules/pro-device-core'

// 设备基类只订统一断开,不关心来源是 native 还是 probe
transport.onDisconnect((reason: TransportDisconnectReason) => {
  // remote | io-error | probe-timeout | unknown
})
方法 签名 说明
open(config) Promise<void> 连接同步点
close() Promise<void> 主动断开(不发 onDisconnect)
send(data) Promise<void> 发送 ArrayBuffer
onReceive(cb) TransportUnsubscribe 订阅数据接收
onDisconnect(cb) TransportUnsubscribe 订阅意外断开(cb(reason) 必收原因)
connected boolean 当前连接状态

辅助:SessionProbe(会话探活)、CallbackHub(多订阅者)、TransportLinkCapability(native | probe | none)。


错误体系

core 只提供通用设备错误;打印 / 称重错误分别在能力包:

import {
  DeviceError,
  DeviceNotFoundError,
  ConnectionError,
  CommunicationError,
  InvalidStateError,
} from '@/uni_modules/pro-device-core'
import { PrintError } from '@/uni_modules/pro-device-print'
import { WeightError } from '@/uni_modules/pro-device-scale'

try {
  await session.acquire('print', { brand: 'Unknown', model: 'X1' })
} catch (e) {
  if (e instanceof DeviceNotFoundError) {
    console.error('未知设备', e.message)
  }
}

try {
  await device.connect()
} catch (e) {
  if (e instanceof ConnectionError) {
    console.error('连接失败', e.message, e.device, e.cause)
  }
}
错误类 所在包 触发场景
DeviceNotFoundError core registry.resolve() 无匹配条目
ConnectionError core connect() / disconnect() 失败
CommunicationError core 传输层读写失败
InvalidStateError core 未连接断言 / 状态机非法跳转
PrintError pro-device-print 打印失败
WeightError pro-device-scale 称重失败

平台支持

本包为纯 TypeScript,无任何平台 API 调用,支持所有 uni-app 平台。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

许可协议

MIT协议

暂无用户评论。