"write up" sounds bad -> "article"

This commit is contained in:
GiggioG 2025-09-08 00:17:10 +03:00
parent a06b4dedf9
commit e03b30c9dc
3 changed files with 53 additions and 27 deletions

View File

@ -6,7 +6,7 @@ app (TinyPrint) seemed weird.
Recently I came across [WerWolv's
blogpost](https://werwolv.net/blog/cat_printer) about reverse engineering his
thermal printer's protocol and I was inspired to try with my own. Furthermore, I
decided on attempting this with as little looking at their write up as possible.
decided on attempting this with as little looking at their article rias possible.
## 1. Sniffing BLE traffic with ESP32
At first I attempted to just look at the data directly. Using the `nRF Connect`

View File

@ -1,8 +1,17 @@
# thermal-printer
A project to reverse engineer the protocol of my thermal printer - Vyzio B15 (X6) and [implement it myself](#Usage), so I can print from my laptop.
A project to reverse engineer the protocol of my thermal printer - Vyzio B15
(X6) and [implement it myself](#Usage), so I can print from my laptop.
This project was inspired by [WerWolv's Cat printer blogpost](https://werwolv.net/blog/cat_printer)
, but I avoided looking at their code and peaking at the blogpost as much as i could.
This project was inspired by
[WerWolv's Cat printer blogpost](https://werwolv.net/blog/cat_printer), but I
avoided looking at their code and peaking at the blogpost as much as i could.
In the end I made small python library, located in [/src](/src). You can see its
documentation [here](#usage).
## Article
You can read about my process of reverse engineering the protocol
[here](ARTICLE.md).
## Protocol
### Command structure
@ -18,23 +27,33 @@ Consists of commands. Each command has the following structure:
`0xFF` - End magic
### Printing an image
And the app sends the following commands to print an image (refer to the [commands](#getcommandcodecmdname)):
1. Blackening (quality) - always 51 (3) for my printer. It is from 1 to 5 (49 to 53).
2. Energy - only if the print type isn't TEXT: corresponds to the _Print depth_ set in the app, with the formula `energy = 7500 + (PD - 4)*0.15*7500`. The Print depth is from 1 to 7.
3. PrintType - Image(`0x00`), Text(`0x01`) of Label(`0x03`). Still can't find the differences between them, but I think that Image allows for darker images, but I'm not sure.
4. FeedPaper(speed) - I don't know what it does, but the speed is 10 for text and 30 for images and labels.
And the app sends the following commands to print an image (refer to the
[commands](#getcommandcodecmdname)):
1. Blackening (quality) - always 51 (3) for my printer. It is from 1 to 5 (49 to
53).
2. Energy - only if the print type isn't TEXT: corresponds to the _Print depth_
set in the app, with the formula `energy = 7500 + (PD - 4)*0.15*7500`. The Print
depth is from 1 to 7.
3. PrintType - Image(`0x00`), Text(`0x01`) of Label(`0x03`). Still can't find
the differences between them, but I think that Image allows for darker images,
but I'm not sure.
4. FeedPaper(speed) - I don't know what it does, but the speed is 10 for text
and 30 for images and labels.
5. Drawing - commands with either run-length encoded or bit-packed lines
6. FeedPaper(25), Paper(0x30), Paper(0x30), FeedPaper(25)
I don't know what the FeedPaper calls do, but the Paper command feeds the paper so the printed image emerges.
I don't know what the FeedPaper calls do, but the Paper command feeds the paper
so the printed image emerges.
## Usage
In the `./src` directory you can find python files with functions to use the protocol and example usage in `./src/main.py`.
In the `./src` directory you can find python files with functions to use the
protocol and example usage in `./src/main.py`.
### commands.py
Here you can find functions to create the bytes to command the printer.
#### checkImage(imgPath)
Checks if the image at this path is usable for the printer (384 px wide and 1bpp)
Checks if the image at this path is usable for the printer (384 px wide and
1bpp)
#### calcCrc8(data)
Calculates the crc8 checksum
@ -55,7 +74,8 @@ Returns the byte corresponding to the command. Accepts:
| PAPER | Actually feeds the paper. Takes number of lines to move, with data size 2 (potentially 16 bite, little endian). | `0xA1` |
#### runLenght(line)
Creates a byte array with the line compresses as explained above (see DRAW_COMPRESSED).
Creates a byte array with the line compresses as explained above (see
DRAW_COMPRESSED).
#### bitPack(line)
Creates a byte array with each pixel corresponding to a bit.
@ -64,7 +84,8 @@ Creates a byte array with each pixel corresponding to a bit.
Converts 16-bit number to little-endian
#### getEnergy(printDepth)
Calculates the energy corresponding to a certain value of "Print depth" in the app
Calculates the energy corresponding to a certain value of "Print depth" in the
app
#### getTypeByte(typeStr)
Returns byte code for the print type. Supports
@ -75,19 +96,22 @@ Returns byte code for the print type. Supports
| LABEL | `0x03` |
#### getSpeed(typeStr)
Returns the app's default "printSpeed" for types. Supports "IMAGE" (30) and "TEXT" (10). This is used with FEED_PAPER, idk how.
Returns the app's default "printSpeed" for types. Supports "IMAGE" (30) and
"TEXT" (10). This is used with FEED_PAPER, idk how.
#### readImage(imgPath)
Reads image from the path specified.
#### compressImageToCmds(img)
For each line applies both run-length encoding and bit packing and chooses the shorter. Packages each line's compressed data into the appropriate command.
For each line applies both run-length encoding and bit packing and chooses the
shorter. Packages each line's compressed data into the appropriate command.
#### saveCommandsToFile(commands, saveToFile=None, saveToFileHuman=None)
Saves a list of commands to a binary file and/or a human-readable hex file.
#### genMoveUp(lines=0x60)
Generates the paper feeding commands at the end of the app's routine for printing an image.
Generates the paper feeding commands at the end of the app's routine for
printing an image.
#### genCommands( img, ... _(see source code)_ )
Generates the commands for printing an image with the specified parameters.
@ -103,17 +127,21 @@ Disconnects from the device.
Sets up the Connection for the .connect method.
#### send(commands, delay=0)
Writes each command individually to the appropriate characteristic, waiting _delay_ seconds between each one. In the end asks device for status and awaits OKAY.
Writes each command individually to the appropriate characteristic, waiting
_delay_ seconds between each one. In the end asks device for status and awaits
OKAY.
#### Context managers
The Connection class supports the context manager protocol. It automatically connects and disconnects to the device.
The Connection class supports the context manager protocol. It automatically
connects and disconnects to the device.
```python
async with Connection("AA:BB:CC:DD:EE:FF") as conn:
...
```
#### FakeConnection
This class mirrors the methods of Connection, but its constructor takes paths to log files, where the sent data gets dumped.
This class mirrors the methods of Connection, but its constructor takes paths to
log files, where the sent data gets dumped.
### decode.py
#### readHumanFile(fileName)
@ -123,11 +151,9 @@ Reads a human-readable file of hex values into an array of bytes.
Reads a binary file into an array of bytes.
#### decodeCommands(cmdBytes, saveFilename=None)
Decodes the bytes given into the image they convey and returns it. If _saveFilename_ is set, then it saves the image there.
Decodes the bytes given into the image they convey and returns it. If
_saveFilename_ is set, then it saves the image there.
### textToImage.py
#### textToImage(text, ... _(see source code)_ )
Generates a PIL image from the given text.
## Write up
You can read about my process of reverse engineering the protocol [here](WRITE_UP.md).
Generates a PIL image from the given text.

View File

@ -131,5 +131,5 @@ no nqmashe da imam compressiq, da znam za type-ove, za energy i t.n.
i tuk i pri dvata `paper`-a se durji, sqkash X6 ne e isCanPrintLabel
# todo
- [X] writeup
- [ ] grammar check writeup
- [X] article
- [ ] grammar check article