androiddelphiprintingfiremonkeyposprinter

Generate QRCode and Print in Printer Thermal using ESC POS - ZIJIANG 58mm - Delphi 10.2


I'm trying to print qr code, on a thermal pos bluetooth printer in delphi, android platform (firemonkey). the printer is connected, I can print the text, but I can't generate and print the qr code, I would be grateful if someone can help.

The mark of the pos printer is P08-580LD (ZIJIANG).

this is the code i use in delphi-android 10.2 .

        sock.connect;
         // Reset Printer
         ostream.write(StringToJA(escResetPrinter,'iso8859-2'));

        ostream.write(StringToJA(pO8escBoldOn,'iso8859-2'));
        ostream.write(StringToJA('Naziv 1'+escNewLine    , 'iso8859-2'));
        ostream.write(StringToJA(pO8escBoldOff,'iso8859-2'));

        ostream.write(StringToJA(pO8escFontA,'iso8859-2'));
        ostream.write(StringToJA('Adresa'+escNewLine    , 'iso8859-2'));
        ostream.write(StringToJA(escResetPrinter,'iso8859-2'));

        ostream.write(StringToJA(pO8escFontB,'iso8859-2'));
        ostream.write(StringToJA('MB xxxxx, ID HR-AB-99-0125--54'+escNewLine    , 'iso8859-2'));
        ostream.write(StringToJA(escResetPrinter,'iso8859-2'));

        ostream.write(StringToJA(pO8escUnerlineOn,'iso8859-2'));
        ostream.write(StringToJA('IBAN: xxxxxxxxx'+escNewLine    , 'iso8859-2'));
        ostream.write(StringToJA(pO8escUnerlineOff,'iso8859-2'));

        ostream.write(StringToJA('OIB 99999999'+escNewLine    , 'iso8859-2'));

       // start - qr-code //
        ostream.write(StringToJA(chr(27)+chr(90)+chr(0)+chr(7)+chr(15)+chr(25)+chr(30)+'dada'  ,'iso8859-2'));

        ostream.write(StringToJA(escResetPrinter,'iso8859-2'));

   Sleep(250);
   ostream.flush();
   ostream.close;

This is documentation from the printer, and it says how to build the code, (decimal).

https://mega.nz/file/fu4zTCSR#UZ53LSty7dUpRyqzvz8li27amG1KvVlLk0slQFhd5Os

I managed to generate the qr code as below in the picture but it is not ok.

enter image description here

This is how the qr code should be generated according to the printer documentation

enter image description here

I found a function in android studio, how to build qr code, I would be grateful if someone knows how to turn a function into delphi.

.....

 byte[] qrcode = PrinterCommand.getBarCommand("Zijiang Electronic Thermal Receipt Printer!", 0, 3, 6);//
 Command.ESC_Align[2] = 0x01;
 SendDataByte(Command.ESC_Align);
 SendDataByte(qrcode);

public static byte[] getBarCommand(String str, int nVersion, int nErrorCorrectionLevel, int nMagnification)

{   
  if(nVersion<0 | nVersion >19 | nErrorCorrectionLevel<0 | nErrorCorrectionLevel > 3
            | nMagnification < 1 | nMagnification > 8){
          return null;
      }
      
     byte[] bCodeData = null;
     try
     {
      bCodeData = str.getBytes("GBK");
       
     }
     catch (UnsupportedEncodingException e)
     {
       e.printStackTrace();
       return null;
     }

     byte[] command = new byte[bCodeData.length + 7];     
     command[0] = 27;
     command[1] = 90;
     command[2] = ((byte)nVersion);
     command[3] = ((byte)nErrorCorrectionLevel);
     command[4] = ((byte)nMagnification);
     command[5] = (byte)(bCodeData.length & 0xff);
     command[6] = (byte)((bCodeData.length & 0xff00) >> 8);
     System.arraycopy(bCodeData, 0, command, 7, bCodeData.length);
     return command;
   }

Solution

  • Having quite similar issues on that kind of mini POS printers. When directly printing from Kotlin (Android Studio, native), I managed, somehow, to interpret partially their official manual and concluded that ESC Z works little different (actually it coresponds to the Java code you found)...

    1. ESC Z (27 90)
    2. first byte relates to table row ("version"), if 0 then it will "autoselect"
    3. at first, I thougth second byte must be 'M' (77) - 'L', 'Q', 'H' - didn't manage it to work?! (actually it has to be 0,1,2,3 based on error correction - as suggested in Java code you found and posted here)
    4. this byte relates to QR code size, 1-8
    5. lower byte of string size (for example, for your "dada" it would be 4)
    6. higher byte of string size (for your "dada" it would be 0... if longer than 256 characters, this shall be length div 256)
    7. string characters

    In your Delphi code, I would change (step-by-step, you can binary mask the length...):

    // start - qr-code //
    ps := 'dada'; // your content string... detalji o računu ili štogod...
    l1 := length(ps);
    y  := l1 div 256;
    x  := l1 - y * 256; 
    ostream.write(StringToJA(chr(27)+chr(90)+chr(7)+chr(1)+chr(6)+chr(x)+chr(y)+ps  ,'iso8859-2'));
    
    // please not that 7-1-6 is fixed combination - 7 relates to the table from documentation, 1 relates to error correction (use 0 for "smaller" QR with less redundany, or 2 and 3 for larger more complex QR), 6 relates to size of printed code (can be set lower)