I was able to print the thermal printer "PAPERANG" from Python (Windows10, Python3.6)

Sorry I made you wait! I was able to print the thermal printer "PAPERANG" from Python.

Sample code

Download from here

Environment

$ conda create -n paperang python=3.6
$ conda activate paperang
$ cd miaomiaoji-tool
$ pip install PyBluez-win10
$ pip install opencv-python

Run

$ python message_process.py

Commentary

I am changing the forked one from here.

When I try to run message_process.py, I get an error in the filter function. Enclose the filter functions on lines 47 and 64 in a list. How to use map / filter in Python3

valid_devices = list(filter(lambda d: len(d) == 2 and d[1] in valid_names, nearby_devices))
 ・ ・ ・
valid_service = list(filter(
    lambda s: 'protocol' in s and 'name' in s and s['protocol'] == 'RFCOMM' and s['name'] == 'SerialPort',
    service_matches
))

With pybluez, OSError appears at find_service on the 63rd line, so PyBluez-win10 is used. * OS Error when program try to use functions from bluetooth._msbt # 279

service_matches = find_service(uuid=self.uuid, address=self.address)

I get an error that the service name cannot be found, so let's print and display service_matches.

[{'host': '00:15:83:B7:11:AF', 'name': b'SerialPort', 'description': '', 'port': 1, 'protocol': 'RFCOMM', 'rawrecord': b'5J\t\x00\x00\n\x00\x01\x00\x0f\t\x00\x015\x03\x19\x11\x01\t\x00\x045\x0c5\x03\x19\x01\x005\x05\x19\x00\x03\x08\x01\t\x00\x055\x03\x19\x10\x02\t\x00\x08\x08\xff\t\x00\t5\x085\x06\x19\x11\x01\t\x01\x02\t\x01\x00%\nSerialPort', 'service-classes': [b'1101'], 'profiles': [(b'1101', 258)], 'provider': None, 'service-id': None, 'handle': 65551}, {'host': '00:15:83:B7:11:AF', 'name': b'WeChat', 'description': '', 'port': 8, 'protocol': 'RFCOMM', 'rawrecord': b'5T\t\x00\x00\n\x00\x01\x00\x0e\t\x00\x015\x11\x1c\xe5\xb1R\xedkF\t\xe9Fxf^\x9a\x97,\xbc\t\x00\x045\x0c5\x03\x19\x01\x005\x05\x19\x00\x03\x08\x08\t\x00\x055\x03\x19\x10\x02\t\x00\x08\x08\xff\t\x00\t5\x085\x06\x19\x11\x01\t\x01\x02\t\x01\x00%\x06WeChat', 'service-classes': ['E5B152ED-6B46-09E9-4678-665E9A972CBC'], 'profiles': [(b'1101', 258)], 'provider': None, 'service-id': None, 'handle': 65550}]

'name': b Since it is'SerialPort', add b to'SerialPort' on line 65.

lambda s: 'protocol' in s and 'name' in s and s['protocol'] == 'RFCOMM' and s['name'] == b'SerialPort',

When I print service_matches, I get the following struct.pack error.

 File "message_process.py", line 88, in packPerBytes
    result += struct.pack('<i', self.crc32(bytes))
struct.error: argument out of range

Let's change <i on line 88 to <I. struct — Interpret bytes as packed binary data

result += struct.pack('<I', self.crc32(bytes))

Then I get an encode error, so

File "message_process.py", line 110, in recv
    logging.info("Recv: " + raw_msg.encode('hex'))
AttributeError: 'bytes' object has no attribute 'encode'

Change .encode ('hex') on lines 110 and 122 to .hex (). [How do I fix AttributeError:'bytes' object has no attribute'encode'?](Https://stackoverflow.com/questions/55701623/how-do-i-fix-attributeerror-bytes-object-has-no- attribute-encode)

logging.info("Recv: " + raw_msg.hex())
 ・ ・ ・
, self.payload_length, self.payload.hex()

Since the error of the map function appears in image_process.py, enclose the map function on the 32nd line in list.

File "\miaomiaoji-tool\image_process.py", line 20, in frombits
    for b in range(len(bits) / 8):
TypeError: object of type 'map' has no len()

Also, since the range range of the for statement on the 20th line is float, cast it to int.

for b in range(int(len(bits) / 8)):

I get an error in struct.pack on line 153, so comment it out and it's OK.

 msg = struct.pack("<%dc" % len(binary_img, *binary_img)

To print a 300-line line, it must be binary. The contents of sendImageToBt are msg with the binary string as it is.

def sendImageToBt(self, binary_img):
    self.sendPaperTypeToBt()
    # msg = struct.pack("<%dc" % len(binary_img, *binary_img)
    msg = binary_img
    self.sendToBt(msg, BtCommandByte.PRT_PRINT_DATA, need_reply=False)
    self.sendFeedLineToBt(self.padding_line)

 Print a pure black image with 300 lines
img = b'\xff' * 48 * 300
mmj.sendImageToBt(img)

I was able to print. 86242649_182835276314024_4717528697094012928_n.jpg

In fact, you need to send to self.sendToBt for each line.

def sendImageToBt(self, binary_img):
    self.sendPaperTypeToBt()
    # msg = struct.pack("<%dc" % len(binary_img, *binary_img)
    msgs = [binary_img[x: x+192] for x in range(0, len(binary_img), 192)] # 4*48
    for msg in msgs:
        self.sendToBt(msg, BtCommandByte.PRT_PRINT_DATA, need_reply=False)
    self.sendFeedLineToBt(self.padding_line)

This is the true 300 line line. I changed the function name to sendBinaryToBt.

86189532_333920134236910_8458868322023243776_n.jpg

\ xff is black and \ x00 is white. It is easy to understand if \ xff is converted to a binary number, but \ xff becomes 0b11111111 and eight black vertical lines are drawn. Therefore, 8 bits represent 8 pixels of the image. The width of the horizontal line is up to 48'\ xff'. That is, the image width is 8 x 48 = 384 pixels.

The image is resized, binarized, converted to a value of [0,1], converted to hexadecimal by 8 pixels, and printed line by line.

def sendImageToBt(self, binary_img):
    self.sendPaperTypeToBt()
    height, width = binary_img.shape[:]
    for line in range(height):
        bits = [0 if x > 0 else 1 for x in binary_img[line]]
        bits = [bits[x:x+8] for x in range(0, len(bits), 8)]
        msg = ''
        for bit in bits:
            bin = '0b'+''.join(str(x) for x in bit)
            msg += '{:02x}'.format(int(bin, 0))
        msg = bytes.fromhex(msg)
        self.sendToBt(msg, BtCommandByte.PRT_PRINT_DATA, need_reply=False)
    self.sendFeedLineToBt(self.padding_line)

 ・ ・ ・
 Print an existing image(need opencv):
img = cv2.imread('kumamcn.png', 0)
ret, binary_img = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
height, width = binary_img.shape[:]
binary_img = cv2.resize(binary_img, (384, int(height*384.0/width)), cv2.INTER_AREA)
mmj.sendImageToBt(binary_img)

done. Now you can print any image! 86259996_614941075716724_5170025822672650240_n.jpg

If this article is useful, please buy raw oysters in the book.

Recommended Posts

I was able to print the thermal printer "PAPERANG" from Python (Windows10, Python3.6)
I tried changing the python script from 2.7.11 to 3.6.0 on windows10
I was able to recurse in Python: lambda
I wanted to use the Python library from MATLAB
I was able to repeat it in Python: lambda
I want to use jar from python
What I was addicted to Python autorun
When I tried to run Python, it was skipped to the Microsoft Store
A story I was addicted to when inserting from Python to a PostgreSQL table
Use Python from Java with Jython. I was also addicted to it.
The file name was bad in Python and I was addicted to import
python I don't know how to get the printer name that I usually use.
I want to use Python in the environment of pyenv + pipenv on Windows 10
I want to email from Gmail using Python.
[Python] I want to manage 7DaysToDie from Discord! 1/3
I was able to mock AWS-Batch with python, moto, so I will leave it
[IBM Cloud] I tried to access the Db2 on Cloud table from Cloud Funtions (python)
I want to use ceres solver from python
What I did when updating from Python 2.6 to 2.7
[Python] I tried to get the type name as a string from the type function
[Python] I want to manage 7DaysToDie from Discord! 2/3
I want to make C ++ code from Python code!
[Python] I will upload the FTP to the FTP server.
I want to display the progress in Python!
I was soberly addicted to calling awscli from a Python 2.7 script registered in crontab
[Python] I made a system to introduce "recipes I really want" from the recipe site!
I raised the Python version from 2 to 3, but every time I restart the ubuntu terminal, the version remains 2.
I want to see the file name from DataLoader
[Python] How to remove duplicate values from the list
I tried to graph the packages installed in Python
The wall of changing the Django service from Python 2.7 to Python 3
I tried to detect the iris from the camera image
I tried to touch the CSV file with Python
Output the time from the time the program was started in python
I tried to solve the soma cube with python
I was addicted to scraping with Selenium (+ Python) in 2020
I want to inherit to the back with python dataclass
[Python3] I want to generate harassment names from Japanese!
The first step to getting Blender available from Python
[Python] I tried to graph the top 10 eyeshadow rankings
I want to write in Python! (3) Utilize the mock
I tried to solve the problem with Python Vol.1
I felt that I ported the Python code to C ++ 98.
I read the Chainer reference (updated from time to time)
I want to use the R dataset in python
What I was addicted to when using Python tornado
I tried to summarize the string operations of Python
Changes from Python 3.0 to Python 3.5
Changes from Python 2 to Python 3.0
[Qualification] I studied Python from the basics to take the python3 engineer certification basic exam (examination record)
[Qualification] I studied Python from the basics to take the python3 engineer certification basic exam (study edition)
I tried to find the entropy of the image with python
I want to initialize if the value is empty (python)
I replaced the Windows PowerShell cookbook with a python script.
[Python] I started Poetry & Impression that I moved from Pipenv to poetry
I tried to simulate how the infection spreads with Python
I was hooked for 2 minutes with the Python debugger pdb
I tried to create API list.csv in Python from swagger.yaml
I tried using the Python library from Ruby with PyCall
I wanted to solve the Panasonic Programming Contest 2020 with Python
I was able to implement web app authentication with flask-login