WebBluetoothCG / demos

Demo applications showing off Web Bluetooth
https://webbluetoothcg.github.io/demos/
Apache License 2.0
624 stars 188 forks source link

can't print a qrcode #72

Closed fjdevesa closed 3 years ago

fjdevesa commented 6 years ago

Hi,

I'm trying to print a QRCode modifiying your Web Bluetooth Printer demo in: https://github.com/WebBluetoothCG/demos/tree/gh-pages/bluetooth-printer

I'm using script qrious from https://github.com/neocotic/qrious to generate a canvas with QRCODE. Attach my html file:

<!DOCTYPE html>
<html>
<head>
    <title>QrCode Print Via Bluetooth</title>
    <script src="/qrious.min.js"></script>

</head>
<body>
    <canvas id="qr"></canvas>
    <br />
    <button onclick="onButtonClick()" style="height: 200px; width: 400px;">Imprimir por Bluetooth</button>

    <script>
        (function () {
            var qr = new QRious({
                element: document.getElementById('qr'),
                value: 'https://www.centauro.net'
            });
        })();

        var canvas = document.getElementById("qr");
        var context = canvas.getContext("2d");

        let imageData = context.getImageData(0, 0, canvas.width, canvas.height).data;

        var printCharacteristic;
        let index = 0;
        let data;

        async function connectToPrinter() {
            return new Promise(function (resolve) {
                navigator.bluetooth.requestDevice({
                    filters: [{ //Mostrar solo los dispositivos bluetooth que puedan imprimir.//000018f0 00001101
                        services: ['000018f0-0000-1000-8000-00805f9b34fb']
                    }]
                })
                    .then(device => {
                        //console.log('> Found ' + device.name);
                        //alert('Connecting to GATT Server...');
                        return device.gatt.connect();
                    })
                    .then(server => server.getPrimaryService("000018f0-0000-1000-8000-00805f9b34fb"))
                    .then(service => service.getCharacteristic("00002af1-0000-1000-8000-00805f9b34fb"))
                    .then(characteristic => {
                        // Cache the characteristic
                        printCharacteristic = characteristic; //Guardamos en la variable para poder imprimir de nuevo sin pedir autorización.
                    })
                    .then(() => { resolve() })
                    .catch(handleError);
            });
        }
        //****************************

        function getDarkPixel(x, y) {
            // Return the pixels that will be printed black
            let red = imageData[((canvas.width * y) + x) * 4];
            let green = imageData[((canvas.width * y) + x) * 4 + 1];
            let blue = imageData[((canvas.width * y) + x) * 4 + 2];
            return (red + green + blue) > 0 ? 1 : 0;
        }
        function getImagePrintData() {
            if (imageData == null) {
                alert('No image to print!');
                return new Uint8Array([]);
            }
            // Each 8 pixels in a row is represented by a byte
            let printData = new Uint8Array(canvas.width / 8 * canvas.height + 8);
            let offset = 0;
            // Set the header bytes for printing the image
            printData[0] = 29;  // Print raster bitmap
            printData[1] = 118; // Print raster bitmap
            printData[2] = 48; // Print raster bitmap
            printData[3] = 0;  // Normal 203.2 DPI
            printData[4] = canvas.width / 8; // Number of horizontal data bits (LSB)
            printData[5] = 0; // Number of horizontal data bits (MSB)
            printData[6] = canvas.height % 256; // Number of vertical data bits (LSB)
            printData[7] = canvas.height / 256;  // Number of vertical data bits (MSB)
            offset = 7;
            // Loop through image rows in bytes
            for (let i = 0; i < canvas.height; ++i) {
                for (let k = 0; k < canvas.width / 8; ++k) {
                    let k8 = k * 8;

                    //  Pixel to bit position mapping
                    printData[++offset] = getDarkPixel(k8 + 0, i) * 128 + getDarkPixel(k8 + 1, i) * 64 +
                        getDarkPixel(k8 + 2, i) * 32 + getDarkPixel(k8 + 3, i) * 16 +
                        getDarkPixel(k8 + 4, i) * 8 + getDarkPixel(k8 + 5, i) * 4 +
                        getDarkPixel(k8 + 6, i) * 2 + getDarkPixel(k8 + 7, i);
                }
            }
            return printData;
        }

        String.prototype.toBytes = function () {
            var arr = []
            for (var i = 0; i < this.length; i++) {
                arr.push(this[i].charCodeAt(0))
            }
            return arr
        }
        //FIN ****************************
        function handleError(error) {
            alert(error);
        }

        function sendNextImageDataBatch(resolve, reject) {
            //alert("12312");
            // Can only write 512 bytes at a time to the characteristic
            // Need to send the image data in 512 byte batches
            if (index + 512 < data.length) {
                printCharacteristic.writeValue(data.slice(index, index + 512)).then(() => {
                    index += 512;
                    sendNextImageDataBatch(resolve, reject);
                })
                    .catch(error => reject(error));
            } else {
                // Send the last bytes
                if (index < data.length) {
                    printCharacteristic.writeValue(data.slice(index, data.length) + '\u000A\u000D').then(() => {
                        resolve();
                    })
                        .catch(error => reject(error));
                } else {
                    resolve();
                }
            }
        }
        function sendImageData() {
            index = 0;
            data = getImagePrintData();
            //alert(data);
            return new Promise(function (resolve, reject) {
                sendNextImageDataBatch(resolve, reject);
            });
        }
        async function onButtonClick() {
            if (printCharacteristic == null) {
                await connectToPrinter();
                sendImageData();
            }
            else {
                //impreme cuando ya tiene la impresora vinculada.
                sendImageData();

            }
        };
    </script>

</body>
</html>

When I call to printCharacteristic.writeValue in function sendNextImageDataBatch nothing happens in my printer that is the same than https://www.amazon.com/Version-AGPtek%C2%AE-Portable-Bluetooth-Wireless/dp/B00XL3DY2E Soo many days frustated with it. I use your example to print text and don't have any issue. Aslo try to print with this manual http://reliance-escpos-commands.readthedocs.io/en/latest/imaging.html for generate and print a QRCode with esc/pos native (not use a qrcode in canvas) but not works.

But also I want to create a canvas with my company site to print it for this reason wants to print a canvas and not use Esc/Pos codes.

Attach screen captures from my printer: img_20180411_131950 img_20180411_131955

Thanks for your help in advance

luisvinicius167 commented 6 years ago

same problem here. @fjdevesa do you found any solution?

fjdevesa commented 6 years ago

Hi @luisvinicius167,

I don't find any solution to it and finally don't need to print a QR Code.

luisvinicius167 commented 6 years ago

Yeah, thanks @fjdevesa!

reillyeon commented 6 years ago

@beaufortfrancois do you still have this printer to verify that the demo code is still working?

@luisvinicius167 you said you were able to print text. The original demo also prints an image. Does that work correctly on your device?

luisvinicius167 commented 6 years ago

@reillyeon text works! But image, not.

beaufortfrancois commented 6 years ago

@reillyeon I don't have it. @entertailion may still have though. Can you verify that the demo code for an image is still working?

NoRulesJustFeels commented 6 years ago

Sorry, I don't have the printer anymore.

alexlovato303 commented 5 years ago

If anyone comes across this issue, I had luck with a MunByn thermal printer

I changed the byte size to 20 instead of 512 when looping through printData, and updated the canvas height and width to 320 by 320, although this will vary for each type of printer

kwatog commented 5 years ago

@alexlovato303, did you manage to print image? I can print some blank lines but that is after modifying the getDarkPixel. Otherwise, I can only print text.

inggil2407 commented 4 years ago

i already test for print image, it will become success if the image heigth is greater then width or image height and width is equal, i have test image size for less or equal 400px, for canvas width and height max value is 400 the best value is 360, and background must be transparent not white or other color

scheib commented 3 years ago

Thanks for the issue and discussion on this demo. I'm closing the issue as there's no recent activity. If anyone would like to improve the demos please see https://github.com/WebBluetoothCG/demos/blob/gh-pages/bluetooth-printer/CONTRIBUTING.md