"write up" sounds bad -> "article"
This commit is contained in:
parent
a06b4dedf9
commit
e03b30c9dc
|
@ -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`
|
74
README.md
74
README.md
|
@ -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.
|
|
@ -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
|
Loading…
Reference in New Issue