You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

浏览器通过navigator.hid读取USB称重设备数据乱码问题及解决

浏览器端读取USB称重秤数据乱码问题解决方法

问题场景

在浏览器端通过HID API连接USB称重秤,获取缓冲区数据时出现乱码,尝试了MDN提及的所有编码格式均无法解决。相关代码及现象如下:

const device = (await navigator.hid.requestDevice({ filters: [] }))?.[0]
// 弹出设备选择窗口,选中设备并完成连接
await device.open()
device.oninputreport = (report) => {
  const buffer = report.data.buffer
  console.log(buffer) // 输出: ArrayBuffer(5)
  console.log(new TextDecoder('utf-8').decode(buffer)) // 输出: �j
  console.log(String.fromCharCode.apply(null, new Uint8Array(buffer))) // 输出: ÿj
  console.log(buffer.toString()) // 输出: �j
  console.log(buffer.toString('hex')) // 输出: �j 
}

注:在Node.js中使用usb模块访问该设备时,可通过buffer.toString('hex')正常转换为十六进制字符串(如"030402005005030402005005030402005005"),但浏览器端表现不一致。

解决方案

无需直接操作ArrayBuffer,而是利用report.data自带的DataView对象解析设备返回的结构化二进制数据。以下是读取DYMO M25 USB称重秤数据的完整代码:

const device = (await navigator.hid.requestDevice({ filters: [] }))?.[0]
await device.open()
device.oninputreport = (report) => {
  const { value, unit } = parseScaleData(report.data)
  console.log(value, unit)
}

function parseScaleData (data) {
  const sign = data.getUint8(0) === 4 ? 1 : -1 // 4代表正值, 5代表负值, 2代表零
  const unit = data.getUint8(1) === 2 ? 'g' : 'oz' // 2代表克, 11代表盎司
  const value = data.getUint16(3, true) // 以小端字节序读取数值
  return { value: sign * (unit === 'oz' ? value / 10 : value), unit }
}

核心原因:设备返回的是二进制协议数据,并非文本编码内容,因此用文本解码器处理必然出现乱码。通过DataView的方法可以按指定字节长度、字节序读取对应位置的数值,再结合设备协议转换为实际可读的重量和单位。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:25:12