如何通过 Javascript 将多个值写入 BLE 特性?

How can I write multiple values to a BLE characteristic via Javascript?

我目前正在进行一个项目,该项目涉及尝试使用 Javascript 和蓝牙将 ZPL 标签从浏览器发送到 Zebra 打印机 (ZQ520)。

目前我可以使用打印机的 SUUID 及其名称通过蓝牙 4.0 找到打印机。 我还可以通过 'characteristic.writeValue' 将小型 ZPL 标签发送到打印机,打印机在我发送后立即正确打印它们。

我的主要问题是标签的 BLE 传输可以有最大长度。任何短于 512 个字符的内容都会被正确传输和打印。

如果我的标签超过 512 个字符,打印机将抛出 'DOMException' 并且不打印任何内容。

我当前的代码是:

navigator.bluetooth.requestDevice({
  filters:[
    { name: 'deviceName' }, { services: [ServiceUUID] }
  ]
}
.then(device => {
    console.log(device);
    return device.gatt.connect();
})
.then(server => {
  console.log(server);
  serverInstance = server; 
  return server.getPrimaryService(ServiceUUID);
})
.then(service => {
  console.log(service);
  return service.getCharacteristic(commandCharacteristicUUID);
})
.then(characteristic => {
  var zpl = "^FS^FT66,339^A0N,68,83^FDBeispieltext^FS^FT66,439^A0N,68,83^FDBeispieltext^FS^FT66,539^A0N,68,83^FDBeispieltext^FS^FT66,639^A0N,68,83^FDBeispieltext^FS^FT66,739^A0N,68,83^FDBeispieltext^FS^FT66,839^A0N,68,83^FDBeispieltext^FS^FT66,939^A0N,68,83^FDBeispieltext^FS^PQ1,0,1,Y^XZ";
  var encoder = new TextEncoder();
  var data = encoder.encode(zpl);
  console.log(data);
  return characteristic.writeValue(data);
})
.catch(error => {
   console.log('Connection failed!', error);
});

打印机的BLE文档中也记录了BLE连接的512字节限制: "The amount of data that can be written to the characteristic is the minimum of the remote connection’s ATT MTU and 512 bytes." https://www.zebra.com/content/dam/zebra/software/en/application-notes/AppNote-BlueToothLE-v4.pdf

我怎样才能避免这个问题?我必须发送的实际标签大小超过 2500 字节。

文档提到也可以通过蓝牙 'Long Write'。我假设也有可能将小批量数据写入打印机,而不是一次发送整个标签。

我目前正在努力寻找关于如何通过 Javascript 执行此操作的正确语法。

我在本教程的帮助下找到了解决方案:

https://github.com/Zebra/Zebra-Printer-Samples/blob/master/WeChat-MiniProgram-Samples/WeChatPrintDemo/README.md

加上我之前的代码,基本上是这样的:

  var zpl = "..."; // whatever your label is

  navigator.bluetooth.requestDevice({
    filters:[
      { name: 'deviceName' },
      { services: [ServiceUUID] }
    ]
  })
  .then(device => {
    console.log(device);
    return device.gatt.connect();
  })
  .then(server => {
    console.log(server);
    serverInstance = server; 
    return server.getPrimaryService(ServiceUUID);
  })
  .then(service => {
    console.log(service);
    return service.getCharacteristic(commandCharacteristicUUID);
  })
  .then(characteristic => {
    var maxChunk = 300;
    var j = 0;

    if ( zpl.length > maxChunk ) {
      for ( var i = 0; i < zpl.length; i += maxChunk ) {
        var subStr;
        if ( i + maxChunk <= zpl.length ) {
          subStr = zpl.substring(i, i + maxChunk);

        } else {
          subStr = zpl.substring(i, zpl.length);
        }

        setTimeout(writeStrToCharacteristic, 250 * j, subStr);
        j++;
      }
    } else {
      writeStrToCharacteristic(zpl);
    }

    function writeStrToCharacteristic (str) {
      let buffer = new ArrayBuffer(str.length);
      let dataView = new DataView(buffer);
      for (var i = 0; i <str.length; i++) {
        dataView.setUint8( i, str.charAt(i).charCodeAt() );
      }
      console.log('accessing the device');
      return characteristic.writeValue(buffer);
    }
  })
  .catch(error => {
    console.log('Connection failed!', error);
  });

JavaScript 将 300 字节的块写入打印机,直到处理完整个标签。 在每次连续写入之间有一个小的延迟很重要,否则打印机无论出于何种原因都不会响应。