PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Sunday, September 18, 2022

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

 September 18, 2022     bluetooth, bluetooth-lowenergy, javascript, printing, zebra-printers     No comments   

Issue

I'm currently working on a project that involves me trying to send a ZPL-Label from a Browser to a Zebra Printer (ZQ520) using Javascript and Bluetooth.

Currently I'm able to find the printer via bluetooth 4.0 using its SUUID and its name. I'm also able to send small ZPL labels to the printer via 'characteristic.writeValue' and the printer prints them correctly immediately after I've sent them.

My main problem is that there is a max length a BLE transmission of a label can have. Anything shorter than 512 characters gets transfered and printed correctly.

If my label exceeds 512 characters, the printer throws a 'DOMException' and doesn't print anything.

My current code 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 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);
});

The 512 Byte limit of the BLE connection is also documented in the BLE documentation of the printer: "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

How can I circumvent the issue? The actual label that I have to send, has a size over 2500 byte.

The documentation mentions that a 'Long Write' via Bluetooth is also possible. I assume there is also a possibility to write small batches of data to the printer instead of sending the whole label at once.

I'm just currently struggling to find the right syntax on how to do that via Javascript.


Solution

I've found the solution with the help of this tutorial:

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

Added to the code that I had before, it basically looks like this:

  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 writes chunks of 300 bytes to the printer, until the whole label has been processed. It's important to have a small delay between each consecutive write, otherwise the printer won't respond for whatever reason.



Answered By - Anton Delticom
Answer Checked By - Gilberto Lyons (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing