Print QR code "GS ( k <Function 180>" with more than 124 bytes via "PrintNormal"?

3.9k Views Asked by At

I have an Epson TM-T88VI printer and use the Microsoft.PointOfService.PosPrinter in C# for printing.

I try to print QR codes via ESC POS commands.

Everything works OK until printing QR code data with 125+ bytes.

This is my function:

    private string fct180(string data)
    {
        byte[] barr = System.Text.ASCIIEncoding.ASCII.GetBytes(data);
        int len = barr.Length + 3;
        byte pH = (byte)(len / 256);
        byte pL = (byte)(len - (256 * pH));
        byte[] cmd = new byte[8 + barr.Length];
        cmd[0] = 29;
        cmd[1] = 40;
        cmd[2] = 107;
        cmd[3] = pL;
        cmd[4] = pH;
        cmd[5] = 49;
        cmd[6] = 80;
        cmd[7] = 48;
        Array.Copy(barr, 0, cmd, 8, barr.Length);
        string testing = System.Text.ASCIIEncoding.ASCII.GetString(cmd);
        byte[] rere = System.Text.ASCIIEncoding.ASCII.GetBytes(testing);
        string ret = System.Text.ASCIIEncoding.ASCII.GetString(cmd);

        return ret;
    }

My situation:

1) At first I try to generate a QR code with a content string length of 124: data is "AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXX"

This QR code is printed correctly (pL is 127, pH is 0), pL is encoded as "\u007f":
"\u001d(k\u007f\01P0AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXX" Value of rere[3]: 127, value of rere[4] = 0

2) Then I try to generate a QR code with a string length of 125: data is "AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXXT"

This QR code is not printed (pL is 128, pH is 0), pL is encoded as "?" which has a byte value of 63:

"\u001d(k?\01P0AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXXT"

Value of rere[3]: 63, value of rere[4] = 0

I want to get two barcodes after each other, but I only get one and part of the second QR codes content as plain string text. As you can see here: result The picture shows the QR code of 1) and the text part of 2)

The first 63 character are wiped and the characters 64+ are printed as normal text. OK, thats because the byte value is 63 instead of 128. But why is the QR code not printed with 63 char?

That is because the byte value 128 is encoded as string char "?". But how can I print my QR-Code with Microsoft.PointOfService.PosPrinter.PrintNormal if I can't keep strings with byte values > 127?

Is there an alternative function call in the PosPrinter class which accepts plain byte arrays? I have not found one yet.

Is there any other solution except PosPrinter.PrintBarcode?

What would you suggest?

EDIT: Solution I used the byte array and then convert each single byte (via char) to string. That string uses plain byte values instead of encoding. Then I use the escape sequence "ESC|[*]#E". It is then used in PrintNormal. This directs the string directly to the printer without being processed in between. Now also byte values > 127 can be processed.

        string ESC = System.Text.ASCIIEncoding.ASCII.GetString(new byte[] { 27 });
        byte[] bqr = ...;
        string data = "";
        for (int i = 0; i < bqr.Length; ++i)
        {
            data += (char)bqr[i];
        }
        string cmd = ESC + "|*" + data.Length + "E" + data;
        printer.PrintNormal(PrinterStation.Receipt, cmd)
2

There are 2 best solutions below

1
On BEST ANSWER

There are a lot of complications involved in this.


First, as I answered the previous question, if you are using POS for.NET(including OPOS/JavaPOS), don't send the printer's ESC/POS control command directly with the PrintNormal method.

If you want to print a QR code, it may be supported by PrintBarcode method, please check the ADK document of EPSON, and if you can't find it in the ADK document, please contact EPSON support desk.

It is possible to send ESC/POS control commands for the printer according to the UnifiedPOS specification.
A UnifiedPOS POSPrinter escape sequence called "Path through embedded data" (ESC|[*]#E) will send the bytes of data specified in # directly to the printer.
However, it is assumed that the service object supports the feature. Please check with your ADK documentation or support contacts for support availability.


Next, it depends on whether you're using a POS for.NET native service object or an OPOS service object via COM Interop.

When using OPOS service objects, the conversion from Unicode to ANSI code pages is done automatically by the OLE runtime function during the method call, and character codes greater than 127 can be changed by the system code page. Also, if there is a 0x00 in the middle of the data, it will be terminated there and the rest of the data will be ignored.

This is because the parameter of the PrintNormal method are string, not a byte array.

ILegacyControlObject.BinaryConversion property of the service object can be changed to Nibble or Decimal instead of the default value of None.
However, depending on the implementation of COM Interop of POS for.NET, attention may be needed, so it is better to contact the support desk about how to use it.

If you're using a native service object in POS for.NET, it depends on how it's implemented. Again, please check with your ADK documentation or contact support desk for more information.

0
On

I had the same problem but fixed it in a different way

The problem is with using strings, we use SerialPort.Write() to send data to the printer.

https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.write?view=dotnet-plat-ext-6.0

And it has this interesting clause

By default, SerialPort uses ASCIIEncoding to encode the characters. ASCIIEncoding encodes all characters greater than 127 as (char)63 or '?'. To support additional characters in that range, set Encoding to UTF8Encoding, UTF32Encoding, or UnicodeEncoding.

So we:

  • Reverted all data to bytes.

    Set SerialPort to UTF-8 encoding.

    And sent the bytes directly.

We can now print QR codes up to 7000 bits