Como formatar Python String para uma impressora POS específica

Nov 16 2020

Estou usando uma impressora térmica de recibos POS-8330 encontrada AQUI

Estou escrevendo um código que envia uma string Python para a impressora, aqui está o código que realiza isso

companyName = "Hilton Steel and Cement"
paytype = self.payment_Mode
companyName = companyName + "\n\nSale Receipt\n\nOpp Golden Line Mall\nP.O BOX 3404-20100\n TEL: 0727441192\nEMAIL: [email protected]"
receiptNo = randint(1, 100000)
finalString = companyName + "\n\nReceipt No:" + str(receiptNo) + "\n\n" + self.getproductList()\
                              + "\n______________________________________\n" + "Total Due:        " + str(self.totaltoBePaid)  + "\n______________________________________\n\n" + "Paid In:     " + paytype + "\n\n"+ "Served By:     " + str(self.user) +"\n" + "Payment:           " + str(self.finalvariables[1])+ "\nBalance:            " + str(self.finalvariables[0])  + "\n\n\nWelcome Back"

open(self.filename, "w").write(finalString)
os.startfile(self.filename, "print")

A impressora tem um manual de programação encontrado AQUI , mas não consigo decifrar nada dele ou particularmente como aplicá-lo. Por favor, me ajude com o seguinte

  1. Para reduzir o tamanho da fonte
  2. Para reduzir as margens horizontais para que a impressão possa começar da extremidade esquerda.

O código que escrevi fornece esse resultado na impressora POS.

Em uma impressora normal de tamanho normal, dá

que é exatamente o que eu quero.

Respostas

1 RolandSmith Nov 17 2020 at 18:31

Olhando para o manual, esta impressora usa caracteres de controle (os primeiros 32 caracteres em ASCII) para iniciar comandos e separá-los do texto.

Assim, você pode intercalar texto e comandos de impressora. Apenas certifique-se de abrir o arquivo de saída no binarymodo!

Por exemplo, olhando a página 17 do manual de programação, o comando ESC @reinicializa a impressora. Este comando consiste em dois caracteres (bytes); decimal 27 seguido pelo decimal 64. Você pode criar esse comando da seguinte maneira:

In [7]: bytes([27,64])
Out[7]: b'\x1b@'

Você deve definir a margem esquerda (comando GS L, página 37) e a largura da área de impressão (comando GS W, página 38). Observe que "unidades de movimento horizontal" é explicado no GS Pcomando na página 38. A unidade de movimento horizontal padrão é 25,4 / 180 = 0,1411 mm ou 1/180 = 0,0055 polegadas.

Portanto, se você deseja definir a margem esquerda para aproximadamente 5 mm (4,94 mm para ser mais preciso), você deve enviar o seguinte comando:

dIn [14]: bytes([29, 76, 35,0])
Out[14]: b'\x1dL#\x00'

O valor 35 é calculado assim:

In [13]: round(5/(25.4/180))
Out[13]: 35

Se você também deseja definir a largura de impressão para 60 mm, o argumento para o GS Wcomando deve ser:

In [15]: round(60/(25.4/180))
Out[15]: 425

Isso é maior que 255, portanto, teria que ser distribuído por dois bytes;

In [17]: 425-256
Out[17]: 169

O comando seria:

In [18]: bytes([29, 87, 169,1])
Out[18]: b'\x1dW\xa9\x01'

Você pode combinar esses comandos, eu acho:

In [20]: bytes([29, 76, 35, 0, 29, 87, 169,1])
Out[20]: b'\x1dL#\x00\x1dW\xa9\x01'

Editar:

Adicionar os comandos de impressão aos dados é fácil:

printdata = b'\x1dL#\x00\x1dW\xa9\x01' + finalString.encode('utf-8')

Observe que você precisa encodeda string, uma vez que os comandos da impressora são binários.

Observe também que você precisa gravar a string em um arquivo no modo binário .

with open(self.filename, "wb") outf:
    outf.write(printdata)
os.startfile(self.filename, "print")

Por fim, usei withpara que o arquivo seja devidamente fechado após a gravação. A maneira como você está usando deixa o arquivo aberto.