Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't write special characters #444

Closed
angelod1as opened this issue Jan 22, 2021 · 10 comments
Closed

Can't write special characters #444

angelod1as opened this issue Jan 22, 2021 · 10 comments

Comments

@angelod1as
Copy link

I have:

  • [X ] searched open and closed issues for duplicates

Bug description

When trying to print special characters, an error is thrown.

Code:

from escpos.printer import Usb

""" Seiko Epson Corp. Receipt Printer (EPSON TM-T88III) """
p = Usb(0x0416, 0x5011, 0 , 0x81, 0x03)

p.text("À noite, vovô Kowalsky vê o ímã cair no pé do pinguim queixoso e vovó põe açúcar no chá de tâmaras do jabuti feliz\n")
p.cut()

Error:

  File "index.py", line 6
SyntaxError: Non-ASCII character '\xc3' in file index.py on line 6, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

Steps to reproduce

  • Insert a string with special characters into p.text, as seen above
  • See error

Device info

Printer: POS-5890C

python-escpos version: 2.2.0

python version: 2.7.18

operating system: Pop!_OS 20.04 LTS x86_64

@belono
Copy link
Contributor

belono commented Jan 25, 2021

Hi @angelod1as

Maybe you need to set the encoding at the start of your script, or encode the string in utf-8 or latin-1.

You can also try updating python-escpos to version 3 (pre-release) and run your script in python3 which defaults to utf-8 encoding.
Additionally you can add p.charcode(yourcharcode) and p.codepage(yourprintercodepage) to the commands sent to the printer before p.text().

@angelod1as
Copy link
Author

angelod1as commented Jan 26, 2021

Sorry if they're silly questions, I'm not a python programmer and I'm swimming in unknown waters here.

I thank you, @belono, for your patience in advance.


First, I don't know how to update to version 3.


When you say charcode you mean like UTF-8?

Is there a place to find a list of available charcodes (and how to write them in this function)? I searched the code but couldn't find the answer.

When I try p.charcode('latin-1') or p.charcode('utf-8') this error is thrown:

Traceback (most recent call last):
  File "index.py", line 9, in <module>
    p.charcode('latin-1')
  File "/usr/local/lib/python2.7/dist-packages/escpos/escpos.py", line 293, in charcode
    raise CharCodeError()
escpos.exceptions.CharCodeError: Valid char code must be set

Is there a place or source I can find about yourprintercodepage?

I tried running this example but got the following error:

  File "codepage.py", line 8, in <module>
    from escpos.constants import CODEPAGE_CHANGE, ESC, CTL_LF, CTL_FF, CTL_CR, CTL_HT, CTL_VT
ImportError: cannot import name CODEPAGE_CHANGE

The I removed CODEPAGE_CHANGE from the code and it printed the following on my console:

BUSA


B  0123456789abcdef
     
B� b
B !"#$%&'()*+,-./
B0123456789:;<=>?
B@ABCDEFGHIJKLMNO
BPQRSTUVWXYZ[\]^_
B`abcdefghijklmno
Bpqrstuvwxyz{|}~
B����������������
B����������������
B����������������
B����������������
B����������������
B����������������
B����������������
B����������������

V

When trying # -*- coding: latin-1 -*- or # -*- coding: utf-8 -*-, the following errors is thrown:

  File "index.py", line 9, in <module>
    p.text("À noite, vovô Kowalsky vê o ímã cair no pé do pinguim queixoso e vovó põe açúcar no chá de tâmaras do jabuti feliz\n")
  File "/usr/local/lib/python2.7/dist-packages/escpos/escpos.py", line 437, in text
    self._raw(txt.encode())
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

@belono
Copy link
Contributor

belono commented Jan 26, 2021

Don't worry, I'm glad to help if I can.

To upgrade to python-escpos v.3.0a just:

  • Install python3-pip if you don't have it already:
    sudo apt install python3-pip

  • Then install python-escpos pre-release:
    pip3 install -U python-escpos --user --pre

  • Now you can run your script in python3:
    python3 yourscript.py

  • Or try your commands in the interactive interpreter:
    python3

>>> from escpos.printer import Usb
>>> p = Usb(0x0416, 0x5011, 0 , 0x81, 0x03)
>>> p.charcode('ISO_8859-15')  # latin-1
>>> p.text('yourstring')

This should avoid the UnicodeDecodeError but your printer has to understand the charcode you send to it.
Get the full list of charcodes at our friend escpos-printer-db

Hope it helps, and fell free to ask whatever you need.

@angelod1as
Copy link
Author

This is my printer. I see it has all those pages, I just don't understand which one I should choose or how to make the change.

I tried to run your code in python3 interactive interpreter but it threw an error. I then tried to run it in a file, same error:

from escpos.printer import Usb
p = Usb(0x0416, 0x5011, 0 , 0x81, 0x03)
p.charcode('ISO_8859-15')  # latin-1
p.text('yourstring')

Error:

raceback (most recent call last):
  File "/usr/lib/python3/dist-packages/usb/core.py", line 223, in get_interface_and_endpoint
    return self._ep_info[endpoint_address]
KeyError: 1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "new.py", line 3, in <module>
    p.charcode('ISO_8859-15')  # latin-1
  File "/home/angelo/.local/lib/python3.8/site-packages/escpos/escpos.py", line 295, in charcode
    self.magic.force_encoding(code)
  File "/home/angelo/.local/lib/python3.8/site-packages/escpos/magicencode.py", line 240, in force_encoding
    self.write_with_encoding(encoding, None)
  File "/home/angelo/.local/lib/python3.8/site-packages/escpos/magicencode.py", line 287, in write_with_encoding
    self.driver._raw(
  File "/home/angelo/.local/lib/python3.8/site-packages/escpos/printer.py", line 100, in _raw
    self.device.write(self.out_ep, msg, self.timeout)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 940, in write
    intf, ep = self._ctx.setup_request(self, endpoint)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 102, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 215, in setup_request
    intf, ep = self.get_interface_and_endpoint(device, endpoint_address)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 102, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 231, in get_interface_and_endpoint
    raise ValueError('Invalid endpoint address ' + hex(endpoint_address))
ValueError: Invalid endpoint address 0x1

I thought I had the wrong IN and OUT codes, but running lsusb it seems I do got the correct ones.

Bus 003 Device 009: ID 0416:5011 Winbond Electronics Corp. Virtual Com Port
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0416 Winbond Electronics Corp.
  idProduct          0x5011 Virtual Com Port
  bcdDevice            2.00
  iManufacturer           1 STMicroelectronics
  iProduct                2 POS58 Printer USB       
  iSerial                 3 Printer
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0020
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          5 (error)
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         7 Printer
      bInterfaceSubClass      1 Printer
      bInterfaceProtocol      2 Bidirectional
      iInterface              4 (error)
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
can't get device qualifier: Resource temporarily unavailable
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

Researching here I found that portuguese charcode is CP860. In the aforementioned link about my printer, I see that CP860 is page 3, so I tried running (using python and python3):

from escpos.printer import Usb
p = Usb(0x0416, 0x5011, 0 , 0x81, 0x03)
p.codepage(3)
p.text('yourstring')

The error:

Traceback (most recent call last):
  File "new.py", line 3, in <module>
    p.codepage(3)
AttributeError: 'Usb' object has no attribute 'codepage'

Fidling with [this example as basis], I wrote the following code:

#!/usr/bin/python
# -*- coding: ISO_8859-15 -*-

from escpos import printer

dummy = printer.Dummy()
dummy.hw('init')
dummy.set(height=2, width=2)
dummy._raw("À noite, vovô Kowalsky vê o ímã cair no pé do pinguim queixoso e vovó põe açúcar no chá de tâmaras do jabuti feliz\n")
dummy.cut()

print(dummy.output)

And it print the string perfectly into my console.

I don't know if this sheds any light but, as you can see, I'm trying real hard here.

@belono
Copy link
Contributor

belono commented Jan 27, 2021

I think we're close.

Remember that to print via the USB device you need libusb-1.0-0 installed in your distro

Now, based on your last code:

#!/usr/bin/python
# -*- coding: ISO_8859-15 -*-

from escpos import printer

# We use Dummy printer to pre-process commands
dummy = printer.Dummy('POS-5890')  # Select the escpos-printer-db profile for your printer
dummy.charcode()  # Automatic selection of the charcode thanks to the profile, if fails then set the charcode CP860 manually
dummy.hw('init')
dummy.set(height=2, width=2)
dummy.text("À noite, vovô Kowalsky vê o ímã cair no pé do pinguim queixoso e vovó põe açúcar no chá de tâmaras do jabuti feliz\n")  # text() method should work and is more intuitive
dummy.cut()

# Then we send the raw output to the real printer
p = printer.Usb(0x0416, 0x5011, 0 , 0x81, 0x03)
p._raw(dummy.output)

Hope it works!

@angelod1as
Copy link
Author

libusb-1.0-0 is properly installed.


When I run this with python:

#!/usr/bin/python
# -*- coding: ISO_8859-15 -*-

from escpos.printer import Usb

p = Usb(0x0416, 0x5011, 0 , 0x81, 0x03)

p.text('My String')
p.cut()

My printer prontly works and prints "y String" (I'll worry with the lack of the first M later)

When I run it with python3, it throws me:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/usb/core.py", line 223, in get_interface_and_endpoint
    return self._ep_info[endpoint_address]
KeyError: 1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "index.py", line 16, in <module>
    p._raw(dummy.output)
  File "/home/angelo/.local/lib/python3.8/site-packages/escpos/printer.py", line 100, in _raw
    self.device.write(self.out_ep, msg, self.timeout)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 940, in write
    intf, ep = self._ctx.setup_request(self, endpoint)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 102, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 215, in setup_request
    intf, ep = self.get_interface_and_endpoint(device, endpoint_address)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 102, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 231, in get_interface_and_endpoint
    raise ValueError('Invalid endpoint address ' + hex(endpoint_address))
ValueError: Invalid endpoint address 0x1

I did this test to make sure basic strings are working, with no fancy stuff, and they are not.


Running your script with python:

Traceback (most recent call last):
  File "index.py", line 8, in <module>
    dummy.charcode()  # Automatic selection of the charcode thanks to the profile, if fails then set the charcode CP860 manually
TypeError: charcode() takes exactly 2 arguments (1 given)

Now with python3:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/usb/core.py", line 223, in get_interface_and_endpoint
    return self._ep_info[endpoint_address]
KeyError: 1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "index.py", line 16, in <module>
    p._raw(dummy.output)
  File "/home/angelo/.local/lib/python3.8/site-packages/escpos/printer.py", line 100, in _raw
    self.device.write(self.out_ep, msg, self.timeout)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 940, in write
    intf, ep = self._ctx.setup_request(self, endpoint)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 102, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 215, in setup_request
    intf, ep = self.get_interface_and_endpoint(device, endpoint_address)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 102, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 231, in get_interface_and_endpoint
    raise ValueError('Invalid endpoint address ' + hex(endpoint_address))
ValueError: Invalid endpoint address 0x1

When I python3 without the last part (after the # Then we send...), and with a print(dummy.output), it consoles:

b'\x1b@\x1b!\x00\x1b!\x00\x1b!\x00\x1b{\x00\x1db\x00\x1bE\x00\x1b-\x00\x1bM\x00\x1ba\x00\x1dB\x00\x1bt\x02\xc7\x1bt\x01\x80 noite, vov\x1bt5\xc7\x1bt\x19\xde Kowalsky v\x1bt7\x8e\xa6 o \x8e\x1bt \xadm\x1bt=\xc7\x9c cair no p\xc7\xb8 do pinguim queixoso e vov\xc7\xfc p\xc7\xe6e a\xc7\xf5\xc7\xd0car no ch\xc7\xad de t\xc7\xbdmaras do jabuti feliz\n\x1bd\x06'

At last, I tried commenting every line of the proposed script to see which one would throw the error and didn't have much success, as it's the last one (p._raw(dummy.output)) that does.

@belono
Copy link
Contributor

belono commented Jan 27, 2021

The printer.Usb() connector takes, at least, the params idVendor, idProduct, usb_args=None, timeout=0, in_ep=0x82, out_ep=0x01.
The two first arguments are mandatory, the rest are optional, so they have a default value assigned, but your printer has a non default configuration, so you need to change the default in_ep and out_ep.

The error is that we are passing the values to the Usb() constructor positional and we forgot an argument, the usb_args param, so the rest values are wrong, and the last is missed.

You can keep all your arguments positional:
p = Usb(0x0416, 0x5011, None, 0 , 0x81, 0x03)

All your arguments named:
p = Usb(idVendor=0x0416, idProduct=0x5011, usb_args=None, timeout=0 , in_ep=0x81, out_ep=0x03)

Or, the preferred way, keep the mandatory arguments positional and name the optional arguments you need to change:
p = Usb(0x0416, 0x5011, in_ep=0x81, out_ep=0x03)

I'm crossing my fingers ;)

@angelod1as
Copy link
Author

OH MY GOD IT WORKED!

This was THE ISSUE, this arguments problem.

This code just worked:

from escpos.printer import Usb
p = Usb(0x0416, 0x5011, in_ep=0x81, out_ep=0x03)
p.charcode('CP860')
p.text('À noite, vovô Kowalsky vê o ímã cair no pé do pinguim queixoso e vovó põe açúcar no chá de tâmaras do jabuti feliz\n')
p.cut()

And, as a parallel information: I kid you not, it was playing Darude - Sandstorm when I hit the first enter. Imagine me dancing and screaming here at home.

It's printing a t character before the full string but this is manageable, I'll search around how to kill it.

image

Holy @belono, you are a saint.

@belono
Copy link
Contributor

belono commented Jan 28, 2021

Hahaha, I'm happy too.
That's a good song to dance, it recalls me my youth.

I don't like this t character, if you need help fixing it, don't doubt in open a new issue.

Cheers!!

@angelod1as
Copy link
Author

Apparently, the p.cut() inserts a t character. Will investigate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants