Printers protocol
Packet structure
Main packet

- Prefix - prefix
0x03is present in only one command - Connect. - Head - always 2 bytes (
0x550x55). - Command - command (packet) identifier.
- Data Length - number of bytes of data.
- Data - data with Data length length.
- Checksum - calculated by XOR of all bytes from Command to the last byte of Data (inclusive).
- Tail - always 2 bytes (
0xAA0xAA).
16-bit length packet

- Head - always 2 bytes (
0x550x55). - Command - command (packet) identifier.
- Data Length - number of bytes of data, encoded as a big-endian
u16. - Data - data with Data length length.
- Checksum - XOR of Command, both bytes of Data Length, and all Data bytes (inclusive).
- Tail - always 2 bytes (
0xAA0xAA).
Used by the grayscale row command PrintBitmapRowGray (0x8d), whose payload can exceed 255 bytes.
CRC32 (firmware) packet

- Head - always 2 bytes (
0x550x55). - Command - command (packet) identifier.
- Index - firmware chunk index, used only in
FirmwareChunkandIn_RequestFirmwareChunkpackets, otherwise equals zero. - Data Length - number of bytes of data.
- Data - data with Data length length.
- Checksum - crc32 checksum of all bytes from Command to the last byte of Data (inclusive).
- Tail - always 2 bytes (
0xAA0xAA).
List of packet commands
Client → Printer (Request IDs)
| Request ID | Name | Response ID(s) | Simple OUT | Simple IN |
|---|---|---|---|---|
0x01 |
PrintStart | 0x02 |
❌ | ✅ |
0x03 |
PageStart | 0x04 |
✅ | ✅ |
0x05 |
PrinterLog | 0x06 |
✅ | ❌ |
0x07 |
PrinterConfig2 | 0x08 |
❌ | ❌ |
0x09 |
GetKeyFunction | 0x0a |
✅ | ❌ |
0x0b |
AntiFake | 0x0c |
❌ | ❌ |
0x0d |
GetPrintQuality | 0x0d |
❌ | ❌ |
0x0e |
TubeSettings | 0x0e |
❌ | ❌ |
0x0f |
TubeTypeAndWidth | 0x0f |
❌ | ❌ |
0x10 |
SetOutNet | 0x10 |
❌ | ❌ |
0x11 |
SetLocalTemplate / SetCurrentTimeFormat | 0x11, 0x12 |
❌ | ❌ |
0x12 |
GetCurrentTimeFormat | 0x11 |
✅ | ❌ |
0x13 |
SetPageSize | 0x14 |
❌ | ✅ |
0x14 |
PageHeight | 0x14 |
❌ | ❌ |
0x15 |
PrintQuantity | 0x16 |
❌ | ✅ |
0x17 |
TemplateHistory | 0x17, 0x63 |
❌ | ❌ |
0x19 |
PrinterUsage | 0x19 |
❌ | ❌ |
0x1a |
RfidInfo | 0x1b |
✅ | ❌ |
0x1c |
RfidInfo2 | 0x1d |
✅ | ❌ |
0x1e |
SetReversePrinterFeed | 0x1f |
❌ | ❌ |
0x1f |
MarginTopHeight | 0x1f |
❌ | ❌ |
0x20 |
PrintClear | 0x30 |
✅ | ✅ |
0x21 |
SetDensity | 0x31 |
❌ | ✅ |
0x22 |
SetPrintSpeed | 0x32 |
❌ | ❌ |
0x23 |
SetLabelType | 0x33 |
❌ | ✅ |
0x26 |
SetLanguageType | 0x36 |
❌ | ❌ |
0x27 |
SetAutoShutdownTime | 0x37 |
❌ | ✅ |
0x28 |
PrinterReset | 0x38 |
✅ | ❌ |
0x2c |
SetPrintMode | 0x3c |
❌ | ❌ |
0x2d |
SetLabelMaterial | 0x3d |
❌ | ❌ |
0x2e |
SetVolumeLevel | 0x3e |
❌ | ❌ |
0x2f |
SetAntiSetter | 0x3f |
❌ | ❌ |
0x40 |
PrinterInfo | 0x41–0x4f |
✅ | ❌ |
0x52 |
PrintingHistory | 0x62–0x63 |
❌ | ❌ |
0x54 |
RfidSuccessTimes | 0x64 |
✅ | ❌ |
0x58 |
SoundSettings | 0x68 |
❌ | ❌ |
0x59 |
GetPaperInfo | 0x69 |
❌ | ❓ |
0x5a |
PrintTestPage | 0x6a |
✅ | ✅ |
0x5c |
HalfCut | 0x6c |
❌ | ❌ |
0x70 |
GetVolumeLevel / WriteRFID | 0x71 |
❓ | ❓ |
0x83 |
PrintBitmapRowIndexed | ❌ (one-way) | ❌ | — |
0x84 |
PrintEmptyRow | ❌ (one-way) | ❌ | — |
0x85 |
PrintBitmapRow | ❌ (one-way) | ❌ | — |
0x8a |
PrintBitmapRowDoubleColor | ❌ (one-way) | ❌ | — |
0x8d |
PrintBitmapRowGray | ❌ (one-way) | ❌ | — |
0x86 |
PrinterCheckLine | 0xd3 |
❌ | ❌ |
0x87 |
CompressCommand | ❌ (one-way) | ❌ | — |
0x8e |
LabelPositioningCalibration | 0x8f |
✅ | ✅ |
0xa1 |
SetPrinterConfigurationWifi | 0xb1 |
❌ | ❌ |
0xa6 |
Pause | 0xb6 |
❌ | ❌ |
0xa2 |
GetPrinterConfigurationWifi | 0xb2 |
✅ | ❌ |
0xa3 |
PrintStatus | 0xb3 |
✅ | ❌ |
0xa5 |
PrinterStatusData | 0xb5 |
✅ | ❌ |
0xa7 |
CompressImage | ❌ (one-way) | ❌ | — |
0xaf |
GetPrinterCapabilities | 0xbf |
❌ | ❌ |
0xc1 |
Connect | 0xc2 |
✅ | ❌ |
0xc3 |
PrinterFree | 0xc4 |
❌ | ❌ |
0xda |
CancelPrint | 0xd0 |
✅ | ✅ |
0xdc |
Heartbeat | 0xde, 0xdf, 0xdd, 0xd9 |
❌ | ❌ |
0xe3 |
PageEnd | 0xe4 |
✅ | ✅ |
0xf3 |
PrintEnd | 0xf4 |
✅ | ✅ |
0xf5 |
StartFirmwareUpgrade | 0xf6 |
❌ | ✅ |
CRC32 firmware packets (Client → Printer, one-way)
| Request ID | Name | Notes |
|---|---|---|
0x91 |
FirmwareCrc | Carries CRC32 of entire firmware blob (4-byte payload, index=0) |
0x92 |
FirmwareCommit | Signals printer to apply the firmware (payload=01, index=0) |
0x9b |
FirmwareChunk | One 200-byte chunk; index = chunk number |
0x9c |
FirmwareNoMoreChunks | Signals end of chunk stream (payload=01, index=0) |
Printer → Client only
| Response ID | Name | Notes |
|---|---|---|
0xe0 |
In_PrinterPageIndex | |
0xd3 |
In_PrinterCheckLine | |
0xdb |
In_PrintError | |
0x90 |
In_RequestFirmwareCrc (CRC32) | Requests client to send firmware checksum |
0x9a |
In_RequestFirmwareChunk (CRC32) | Requests specific chunk; index = requested chunk number |
0x9d |
In_FirmwareCheckResult (CRC32) | CRC verification result; data 01 = success |
0x9e |
In_FirmwareResult (CRC32) | Final flashing result; data 01 = success |
Packet details
Two-byte values are usually u16 (big-endian).
Common packet parts:
LL- payload size (if not fixed)CS- checksum
Simple request packet
This packet has Request ID, Data length = 1, and Data = 1.
Checksum will be same as Request ID because N^1^1 == N.
Example (RfidInfo):
55 55 1a 01 01 1a aa aa
│ │ │ │
│ │ │ └─ Checksum (0x1a ^ 0x01 ^ 0x01 = 0x1a)
│ │ └─ Data = 1
│ └─ Data length = 1
└─ RfidInfo command
Simple response packet
Same structure as simple request. Data = 01 on success, 00 on failure.
Example (In_SetDensity, 0x31):
55 55 31 01 01 31 aa aa
│ │ │ │
│ │ │ └─ Checksum (0x31 ^ 0x01 ^ 0x01 = 0x31)
│ │ └─ Data (1 = success, 0 = error)
│ └─ Data length = 1
└─ In_SetDensity command
Connect
The only packet that is prefixed with 0x03 before the standard header.
03 55 55 c1 01 01 c1 aa aa
│ │ │ │ │
│ │ │ │ └─ Checksum
│ │ │ └─ Data = 1
│ │ └─ Data length = 1
│ └─ Connect command
└─ Prefix byte (only for Connect)
Response (0xc2)
Data length = 1. The single byte is a ConnectResult code:
| Value | Name | Meaning |
|---|---|---|
0x00 |
Disconnect | Not connected |
0x01 |
Connected | Connected (protocol version 0) |
0x02 |
ConnectedNew | Connected (protocol version 1) |
0x03 |
ConnectedV3 | Connected (protocol version ≥ 3; version determined via PrinterStatusData) |
0x5a |
FirmwareErrors | Firmware error state |
Protocol version negotiation:
- Send
Connect→ receiveIn_Connect. - If result =
ConnectedNew→protocolVersion = 1. - If result =
ConnectedV3→ sendPrinterStatusData→ parseprotocolVersionfrom bytes[11]and[12]of response:n = data[11]*100 + data[12]protocolVersion=3if204 ≤ n < 300,protocolVersion=4if300 ≤ n < 302,protocolVersion=5ifn ≥ 302.- Otherwise
protocolVersion = 0.
PrinterStatusData
Request: simple.
Response (0xb5)
55 55 b5 LL XX XX SC SC PS PS PL PL PI XX CS VH VL DC DC CS aa aa
└──┤ └──┤ └──┤ │ │ └──┤ └──┤
│ │ │ │ │ │ └─ Double Color Max Cache Size
│ │ │ │ │ └─────── Protocol Version
│ │ │ │ └───────────── Supports color
│ │ │ └─────────────────── Packet Interval
│ │ └────────────────────── Max Send Size
│ └──────────────────────────── Single Packet Size
└────────────────────────────────── Single Color Max Cache Size
Packet length may vary depending on the printer model.
PrinterInfo
Request: data = 1 byte.
| Type value | Name | Response ID | Response data, notes |
|---|---|---|---|
0x01 |
Density | 0x41 |
1 byte |
0x02 |
Speed | 0x42 |
1 byte |
0x03 |
LabelType | 0x43 |
1 byte |
0x04 |
PrinterHeadWidth | 0x44 |
2 bytes; doesn't seem to be used in firmware |
0x05 |
PrintingAccuracy | 0x45 |
1 byte; doesn't seem to be used in firmware |
0x06 |
Language | 0x46 |
1 byte |
0x07 |
AutoShutdownTime | 0x47 |
1 byte |
0x08 |
PrinterModelId | 0x48 |
1–2 bytes model ID (if 1 byte, value is [VV 00]) |
0x09 |
SoftWareVersion | 0x49 |
2 bytes; format varies by model |
0x0a |
BatteryChargeLevel | 0x4a |
1 byte (0–4) |
0x0b |
SerialNumber | 0x4b |
Variable: ASCII string if ≥8 bytes, hex of first 4 bytes otherwise |
0x0c |
HardWareVersion | 0x4c |
2 bytes; format varies by model |
0x0d |
BluetoothAddress | 0x4d |
6 bytes reversed (varies by model) |
0x0e |
PrintMode | 0x4e |
1 byte |
0x0f |
Area | 0x4f |
unknown |
Example (get serial number):
55 55 40 01 0b CS aa aa
│ │ │
│ │ │
│ │ └─ Data = 0x0b (SerialNumber)
│ └─ Data length = 1
└─ PrinterInfo command
Battery charge level values
| Value | Level |
|---|---|
0 |
0% |
1 |
25% |
2 |
50% |
3 |
75% |
4 |
100% |
SetDensity
55 55 21 01 VV CS aa aa
│ │ │
│ │ │
│ │ └─ Density value (model-specific range, typically 1–5)
│ └─ Data length = 1
└─ SetDensity command
Response (0x31): simple.
SetPrintSpeed
55 55 22 01 VV CS aa aa
│ │ │
│ │ │
│ │ └─ Print speed value
│ └─ Data length = 1
└─ SetPrintSpeed command
Response (0x32): simple.
SetLabelType
55 55 23 01 VV CS aa aa
│ │ │
│ │ │
│ │ └─ LabelType value
│ └─ Data length = 1
└─ SetLabelType command
Response (0x33): simple.
SetLanguageType
55 55 26 01 VV CS aa aa
│ │ │
│ │ │
│ │ └─ Language type value
│ └─ Data length = 1
└─ SetLanguageType command
Response (0x36): simple.
SetAutoShutdownTime
55 55 27 01 VV CS aa aa
│ │ │
│ │ │
│ │ └─ AutoShutdownTime value (1–4)
│ └─ Data length = 1
└─ SetAutoShutdownTime command
Response (0x37): simple.
AutoShutdownTime values
| Value | Typical duration |
|---|---|
1 |
15 minutes |
2 |
30 minutes |
3 |
45 or 60 minutes (model-dependent) |
4 |
60 minutes or never (model-dependent) |
SetVolumeLevel
55 55 2e 01 VV CS aa aa
│ │ │
│ │ │
│ │ └─ Volume level value
│ └─ Data length = 1
└─ SetVolumeLevel command
Response (0x3e): simple.
SetCurrentTimeFormat
55 55 11 02 02 VV CS aa aa
│ │ │ │
│ │ │ │
│ │ │ └─ Format value
│ │ └─ Constant byte (0x02)
│ └─ Data length = 2
└─ SetCurrentTimeFormat command
Response (0x12): simple.
SetReversePrinterFeed
55 55 1e 09 01 00 01 00 00 02 f8 01 f4 CS aa aa
│ │
│ │
│ └─ Data length = 9
└─ SetReversePrinterFeed command
Response (0x1f).
HalfCut
Request ID 0x5c, response 0x6c.
55 55 5c 02 OP VV CS aa aa
│ │ │ │
│ │ │ │
│ │ │ └─ Value
│ │ └─ Operation
│ └─ Data length = 2
└─ HalfCut command
Operation: 0x01 = set, 0x02 = get.
Data: 0x01 = on, 0x00 = off, 0x01 is used for get operation.
PrintQuantity
55 55 15 02 QH QL CS aa aa
│ │ └──┤
│ │ │
│ │ └─ Quantity
│ └─ Data length = 2
└─ PrintQuantity command
Response (0x16): simple.
PrintStart
Different variants are used depending on the printer model.
Response (0x02): simple.
1 byte — used in D110, OldD11, B21V1
55 55 01 01 01 01 aa aa
2 bytes
55 55 01 02 PH PL CS aa aa
│ │ └──┤
│ │ │
│ │ └─ Total pages
│ └─ Data length = 2
└─ PrintStart command
7 bytes — used in B1 and newer printers
55 55 01 07 PH PL 00 00 00 00 CC CS aa aa
│ │ └──┤ └──┴──┴──┘ │
│ │ │ Always 0 │
│ │ │ └─ Page color (0 = default)
│ │ └─ Total pages
│ └─ Data length = 7
└─ PrintStart command
9 bytes — first seen on D110M v4 / B21_PRO
55 55 01 09 PH PL 00 00 00 00 CC SS FF CS aa aa
│ │ └──┤ └──┴──┴──┘ │ │ │
│ │ │ Always 0 │ │ │
│ │ │ │ │ └─ Some flag (purpose unknown)
│ │ │ │ └─ Speed (0 = quality/slow, 1 = speed/fast)
│ │ │ └─ Page color
│ │ └─ Total pages
│ └─ Data length = 9
└─ PrintStart command
Page color values
Used by the page color byte (CC) in the 7-byte and 9-byte variants:
| Value | Name | Meaning |
|---|---|---|
0 |
SingleColor | Single-color (black/white) printing |
1 |
DoubleColor | Two-color (black/red) printing |
2 |
SingleColorAlt | Alternate single-color mode |
3 |
Grayscale | 16-level grayscale printing |
SetPageSize
Can have different payload size depending on the model. Column count must not exceed the printhead pixel width.
2 bytes
55 55 13 02 RR RR CS aa aa
│ │ └──┤
│ │ │
│ │ └─ Row count (height in pixels)
│ └─ Data length = 2
└─ SetPageSize command
4 bytes
55 55 13 04 RR RR CC CC CS aa aa
│ │ └──┤ └──┤
│ │ │ │
│ │ │ └─ Column count (width in pixels)
│ │ └─ Row count (height in pixels)
│ └─ Data length = 4
└─ SetPageSize command
6 bytes
55 55 13 06 RR RR CC CC QQ QQ CS aa aa
│ │ └──┤ └──┤ └──┤
│ │ │ │ │
│ │ │ │ └─ Copies count
│ │ │ └─ Column count (width in pixels)
│ │ └─ Row count (height in pixels)
│ └─ Data length = 6
└─ SetPageSize command
9 bytes
55 55 13 09 RR RR CC CC QQ QQ SS SS 00 CS aa aa
│ │ └──┤ └──┤ └──┤ └──┤ │
│ │ │ │ │ │ │
│ │ │ │ │ │ └─ Is divide (0 or 1; purpose unknown)
│ │ │ │ │ └─ Some size (purpose unknown)
│ │ │ │ └─ Copies count
│ │ │ └─ Column count
│ │ └─ Row count
│ └─ Data length = 9
└─ SetPageSize command
13 bytes
55 55 13 0d RR RR CC CC QQ QQ KK KK CT 00 SA PP PP CS aa aa
│ │ └──┤ └──┤ └──┤ └──┤ │ │ └──┤
│ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ └─ Part height (u16, purpose unknown)
│ │ │ │ │ │ │ └─ Send all flag (0 or 1)
│ │ │ │ │ │ └─ Cut type (purpose unknown)
│ │ │ │ │ └─ Cut height
│ │ │ │ └─ Copies count
│ │ │ └─ Column count
│ │ └─ Row count
│ └─ Data length = 13
└─ SetPageSize command
45 bytes
55 55 13 0d RR RR CC CC QQ QQ KK KK CT 00 SA PP PP [SS..SS] CS aa aa
│ │ └──┤ └──┤ └──┤ └──┤ │ │ └──┤ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ └─ Serial (32 bytes)
│ │ │ │ │ │ │ │ └─ Part height (u16, purpose unknown)
│ │ │ │ │ │ │ └─ Send all flag (0 or 1)
│ │ │ │ │ │ └─ Cut type (purpose unknown)
│ │ │ │ │ └─ Cut height
│ │ │ │ └─ Copies count
│ │ │ └─ Column count
│ │ └─ Row count
│ └─ Data length = 13
└─ SetPageSize command
Response (0x14): simple.
PrintEnd
Request (0xf3): simple.
Response (0xf4): data length = 1. Value 01 = print finished (accepted), 00 = still printing (not ready yet).
PrintStatus
Request (0xa3): simple.
Response (0xb3)
Minimum 4 bytes; may be 8 or 10 bytes.
55 55 B3 LL PH PL PP PF XX XX EC CS aa aa
│ └──┤ │ │ │
│ │ │ │ │
│ │ │ │ └─ Error code (present if LL == 10; non-zero triggers PrintError)
│ │ │ └─ Page feed progress (0-100 %)
│ │ └─ Page print progress (0-100 %)
│ └─ Current page index (u16)
└─ Data length
Note
For some printers (B2 PRO for example), the pageFeedProgress is not in 0-100 range.
PrinterConfig2
Request ID 0x07, response 0x08.
Payload layout: [item, operation, data]
Operation: 0x01 = set, 0x02 = get.
Data: 0x01 is used for get operation.
Known items:
| Byte | Operation |
|---|---|
0x02 |
getPrinterTime |
0x08 |
setPrinterTime |
Set Printer Time (0x07)
55 55 07 08 01 YH YL MM DD hh mm ss CS aa aa
│ │ │ └──┤ │ │ │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ └─ Second
│ │ │ │ │ │ │ └─ Minute
│ │ │ │ │ │ └─ Hour
│ │ │ │ │ └─ Day
│ │ │ │ └─ Month
│ │ │ └─ Year
│ │ └─ Set operation
│ └─ Data length = 8
└─ PrinterConfig2 command
Response (0x08): simple.
SoundSettings
Data = 3 bytes: [operation, soundItem, value]
Operation: 0x01 = set, 0x02 = get.
Sound items: 0x01 = BluetoothConnectionSound, 0x02 = PowerSound
Value: 0x01 = on, 0x00 = off, 0x01 is used for get operation.
Examples:
55 55 58 03 01 01 01 5a aa aa ← Enable Bluetooth connection sound
55 55 58 03 01 01 00 5b aa aa ← Disable Bluetooth connection sound
55 55 58 03 01 02 01 59 aa aa ← Enable Power sound
55 55 58 03 02 01 01 59 aa aa ← Query Bluetooth connection sound state
RfidInfo / RfidInfo2
RfidInfo (0x1a) reads the paper NFC tag. RfidInfo2 (0x1c) reads the ribbon NFC tag.
Request: simple.
Response (0x1b / 0x1d)
If dataLength == 1: tag not present.
55 55 ID LL U1 U2 U3 U4 U5 U6 U7 U8 BC ... SN ... AP AP UP UP CT [CP CP] U1 U2 U3 U4 U5 U6 U7 U8 CS aa aa
│ │ └────────────────────┤ │ │ └──┤ └──┤ │ └──┤ └────────────────────┤
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ └─ Secondary tag UUID (optional)
│ │ │ │ │ │ │ │ └─ Capacity (u16, optional)
│ │ │ │ │ │ │ └─ Consumable type (u8)
│ │ │ │ │ │ └─ Used paper (u16)
│ │ │ │ │ └─ Total paper capacity (u16)
│ │ │ │ └─ Serial number (length-prefixed str)
│ │ │ └─ Barcode (length-prefixed str)
│ │ └─ Tag UUID
│ └─ Data length
└─ Response command (0x1b or 0x1d)
TubeSettings
55 55 0e 03 02 01 01 CS aa aa ← tube calibration
55 55 0e 03 02 02 01 CS aa aa ← set tube length
TubeTypeAndWidth
Get request:
55 55 0f 03 02 01 01 0f aa aa
Set request:
55 55 0f 05 01 01 TT WW WH CS aa aa
where TT is tube type and WW WH is width multiplied by 100 and encoded as u16 big-endian. Data length is 5.
Response command is 0x0f.
PrinterUsage
Request:
55 55 19 01 01 19 aa aa
The response contains two u32 counters:
55 55 19 08 IU IU IU IU OU OU OU OU CS aa aa
│ │ └────────┤ └────────┤
│ │ │ │
│ │ │ └─ Outer use counter (u32)
│ │ └─ Inner use counter (u32)
│ └─ Data length = 8
└─ PrinterUsage command
SetPrintMode
Two request values are supported:
55 55 2c 01 01 2c aa aa ← Thermal
55 55 2c 01 02 2f aa aa ← Heat transfer
Response 0x3c:
01= accepted;00= rejected.
SetAntiSetter
Request:
55 55 2f 01 VV CS aa aa
where VV is the anti-counterfeit level.
Response 0x3f:
01= accepted;00= rejected.
SetLabelMaterial
Request:
55 55 2d 01 VV CS aa aa
where VV is the label-material value.
Response 0x3d:
01= accepted;00= rejected.
LabelPositioningCalibration
Request:
55 55 8e 01 VV CS aa aa
Response 0x8f:
01= calibration accepted;00= calibration rejected.
Not sure what it does. It just throws some paper without pulling it back.
PrintTestPage
55 55 5a 01 01 5a aa aa
Response: 0x6a.
GetPaperInfo
Returns the current paper information from RFID tag. Only available for protocolVersion 4+ printers.
55 55 59 01 01 59 aa aa
Response: 0x69.
55 55 69 12 GH GL TH TL PT GH GL TH TL PW PL PW PL DR TL TL TL TL CS aa aa
│ │ └──┤ └──┤ │ └──┤ └──┤ └──┤ └──┤ │ └──┤ └──┤
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ │ └─ Tail length (u16 / 10)
│ │ │ │ │ │ │ │ │ │ └─ Tail length pixel (u16)
│ │ │ │ │ │ │ │ │ └─ Direction (u8)
│ │ │ │ │ │ │ │ └─ Paper width (u16 / 10)
│ │ │ │ │ │ │ └─ Paper width pixel (u16)
│ │ │ │ │ │ └─ Total height (u16 / 10)
│ │ │ │ │ └─ Gap height (u16 / 10)
│ │ │ │ └─ Paper type (u8, present if LL >= 9)
│ │ │ └─ Total height pixel (u16)
│ │ └─ Gap height pixel (u16)
│ └─ Data length
└─ GetPaperInfo
SetPrinterConfigurationWifi
Get request:
55 55 a2 01 01 a2 aa aa
Response: 0xb2.
GetPrinterConfigurationWifi
Response (0xb1): simple.
PrinterFree
Request:
55 55 c3 01 01 c3 aa aa
Response 0xc4:
01= printer free;00= printer busy.
SetLocalTemplate / SetCurrentTimeFormat
0x11 is shared by two operations.
Current time format:
55 55 11 02 02 VV CS aa aa
where VV is the time-format value.
Local template data:
55 55 11 LL 01 ... CS aa aa
The first data byte is 0x01; each local-template record occupies 33 bytes. The Official SDK starts the request with 0x11, payload length 1 + 33 * recordCount, and then serializes the template records.
Pause
55 55 a6 01 VV CS aa aa
│
└─ Data = 0x01 (pause) or 0x02 (resume)
Response (0xb6): simple.
PrintingHistory
The SDK requests history records with a sequence of packets:
55 55 52 01 NN CS aa aa
where NN starts at 0x01 and increments while records are returned.
Response data uses:
0x62— history data;0x63— end/pass marker.
The high-level parser extracts UUID, limit and already-used paper values from the returned records.
TemplateHistory
The response is variable-length.
0x62/0x63 are used for RFID/printing-history acquisition, with 0x63 marking completion.
Packet details (image data packets)
PrintEmptyRow
Fills a row range with blank (white) pixels. One-way (no response expected).
55 55 84 03 RR RR NN CS aa aa
│ │ └──┤ │
│ │ │ │
│ │ │ └─ Repeat count (print this empty row NN times)
│ │ └─ Row number
│ └─ Data length = 3
└─ PrintEmptyRow command
PrintBitmapRow
Sends a full bitmap row including both black and white pixels. One-way (no response expected).
55 55 85 LL RR RR C1 C2 C3 NN DD ... DD CS aa aa
│ │ └──┤ └──┴──┤ │ └─────┤
│ │ │ │ │ │
│ │ │ │ │ └─ Pixel data (cols/8 bytes)
│ │ │ │ └─ Repeat count
│ │ │ └─ Black pixel count segment (3 bytes, see below)
│ │ └─ Row number
│ └─ Data length
└─ PrintBitmapRow command
Image row example:
![]()
Packet example:
55 55 85 0a 00 00 13 00 00 01 ff 00 df 0f CS aa aa
│ │ └──┤ └──┴──┤ │ └──┴──┴──┤
│ │ │ │ │ └─ Draw 32 pixels (19 black, 13 empty)
│ │ │ │ └─ Repeat count (repeat row 1 time)
│ │ │ └─ Black pixel count (19)
│ │ └─ Row number is 0
│ └─ Data length
└─ PrintBitmapRow command
PrintBitmapRowDoubleColor
Color mode:
0 - empty
2 - black
1 - red
3 - mixed (pattern)
PrintEmptyRow (SubCmd 0x84)
55 55 8a 05 00 84 RR RR NN CS aa aa
│ │ │ │ └──┤ │
│ │ │ │ │ │
│ │ │ │ │ └─ Repeat count
│ │ │ │ └─ Row number
│ │ │ └─ Sub-command = 0x84
│ │ └─ Color mode (empty)
│ └─ Data length
└─ PrintBitmapRowDoubleColor command
PrintBitmapRowIndexed (SubCmd 0x83)
55 55 8a LL CC 83 RR RR NN II II ... CS aa aa
│ │ │ │ └──┤ │ └──────┤
│ │ │ │ │ │ │
│ │ │ │ │ │ └─ Pixel indexes (2 bytes per index)
│ │ │ │ │ └─ Repeat count
│ │ │ │ └─ Row number
│ │ │ └─ Sub-command = 0x83
│ │ └─ Color mode
│ └─ Data length
└─ PrintBitmapRowDoubleColor command
PrintBitmapRow (SubCmd 0x85)
55 55 8a LL CC 85 RR RR NN DD ... DD CS aa aa
│ │ │ │ └──┤ │ └──────┤
│ │ │ │ │ │ │
│ │ │ │ │ │ └─ Raw pixel data
│ │ │ │ │ └─ Repeat count
│ │ │ │ └─ Row number
│ │ │ └─ Sub-command = 0x85
│ │ └─ Color mode
│ └─ Data length
└─ PrintBitmapRowDoubleColor command
Data Pattern Mode (Color mode 0x03)
55 55 8a LL 03 RR RR NN DD ... DD CS aa aa
│ │ │ └──┤ │ └─────┤
│ │ │ │ │ │
│ │ │ │ │ └─ Presence mask + Color mask
│ │ │ │ └─ Repeat count
│ │ │ └─ Row number
│ │ └─ Pattern mode = 0x03
│ └─ Data length
└─ PrintBitmapRowDoubleColor command
Example
Example for 576 px row:
576 / 8 = 72 bytes
The first part of DD is therefore always 72 bytes.
Presence mask
black = 1
red = 1
empty = 0
576 pixels → 72 bytes.
Bits are packed MSB-first:
pixels: . . . . . R R R
mask: 0 0 0 0 0 1 1 1
byte: 00000111 = 07
Color mask
For every non-empty 8-pixel block:
black = 0
red = 1
empty = 0
The bit positions are preserved.
Example:
. . . R R R R R
0 0 0 1 1 1 1 1
= 0x1F
Another:
R R R R R R . .
1 1 1 1 1 1 0 0
= 0xFC
A completely empty 8-pixel block produces no color byte at all.
Therefore:
DD = presence_mask[72 bytes] + color_bytes[variable length]
Example: black → red → black
For 576 px:
BLACK: x = 45..175
RED: x = 219..349
BLACK: x = 391..521
The presence mask contains: 72 bytes There are 52 non-empty 8-pixel blocks: 17 + 17 + 18 = 52
Therefore:
DD.length = 72 + 52 = 124 = 0x7C
LL = 124 + 4 = 128 = 0x80
Color data is:
17 bytes: 00 // black
17 bytes: 1F FF ... FC // red
18 bytes: 00 // black
Complete packet
55 55 8A 80 03 RR RR NN
72-byte presence mask
52-byte color mask
CS
AA AA
Black pixel count segment (3 bytes: C1, C2, C3)
Counts non-zero bits in the pixel data array. Two modes:
Split mode (default when dataSize ≤ printhead_pixels / 8):
Data is divided into three equal chunks (chunk size = printhead_pixels / 8 / 3). C1, C2, C3 = black pixel count in each chunk respectively (each capped at 255).
Total mode (used when data is wider than printhead, or explicitly requested):
C1 = 0, C2 = lowByte(total), C3 = highByte(total) — i.e. total pixel count in little-endian in bytes 2–3.
auto mode (default): uses split if data fits, total otherwise.
Usually the printer works correctly when all three bytes are 0x00.
Example:
55 55 85 0a 00 00 13 00 00 01 ff 00 df 0f CS aa aa
│ │ └──┤ └──┴──┤ │ └──┴──┴──┤
│ │ │ │ │ │
│ │ │ │ │ └─ 4 bytes pixel data (32 pixels: 19 black, 13 white)
│ │ │ │ └─ Repeat = 1
│ │ │ └─ Pixel count segment: C1=0x00, C2=0x00, C3=0x13 (19 total)
│ │ └─ Row number = 0
│ └─ Data length = 10
└─ PrintBitmapRow command
PrintBitmapRowIndexed
Used when black pixel count ≤ 6. Encodes only the positions of black pixels as unsigned 16-bit indexes. One-way (no response expected).
If the pixel count exceeds 6, PrintBitmapRow must be used instead.
55 55 83 LL RR RR C1 C2 C3 NN II II II II ... CS aa aa
│ │ └──┤ └──┴──┤ │ └──┴──┴──────┤
│ │ │ │ │ │
│ │ │ │ │ └─ Pixel indexes (2 bytes each)
│ │ │ │ └─ Repeat count
│ │ │ └─ Black pixel count segment (same format as PrintBitmapRow)
│ │ └─ Row number
│ └─ Data length
└─ PrintBitmapRowIndexed command
Example (2 black pixels at positions 10, 320):
55 55 83 0a 00 03 02 00 00 02 00 0a 01 40 CS aa aa
│ │ └──┤ └──┴──┤ │ └──┤ └──┤
│ │ │ │ │ │ │
│ │ │ │ │ │ └─ Pixel at x=320
│ │ │ │ │ └─ Pixel at index x=10
│ │ │ │ └─ Repeat = 2
│ │ │ └─ Pixel count: C1=0x02, C2=0x00, C3=0x00
│ │ └─ Row number = 3
│ └─ Data length = 10
└─ PrintBitmapRowIndexed command
PrintBitmapRowGray
Request ID 0x8d. One-way (no response expected). Uses the 16-bit length packet framing because a grayscale row payload can exceed 255 bytes. Grayscale printing is selected with page color 3 in PrintStart.
The payload starts with a sub-command:
| Sub-command | Name | Purpose |
|---|---|---|
0x84 |
Blank rows | Advance one or more rows without sending pixel data |
0x86 |
Data row | One run-length encoded grayscale row |
These sub-command values are scoped to the 0x8d payload. The same byte values are also standalone command IDs elsewhere in the protocol.
Grayscale dots use 16 levels: 0 = white, 15 = black. Two dots are packed into each data byte, high nibble first:
byte = (level[2n] << 4) | level[2n + 1]
The row width must therefore be even. Encoders normally pad each row to a multiple of 8 columns with white (0) before packing.
Blank rows (0x84)
55 55 8d LH LL 84 RH RL NN 00 CS aa aa
│ │ │ └──┤ │ │
│ │ │ │ │ └─ Zero (no pixel data)
│ │ │ │ └─ Repeat count (1-255)
│ │ │ └─ First row number (u16)
│ │ └─ Sub-command = 0x84 (blank rows)
│ └─ Data length (u16) = 5
└─ Command 0x8d
The whole row range is left blank (white). NN blank rows are emitted starting at row RH RL.
Example: rows 4 and 5 blank:
55 55 8d 00 05 84 00 04 02 00 0a aa aa
│ │ │ └──┤ │ │
│ │ │ │ │ └─ Zero = no pixel data
│ │ │ │ └─ Repeat count = 2
│ │ │ └─ First row = 4
│ │ └─ Sub-command = 0x84
│ └─ Data length = 5
└─ Command 0x8d
Data rows (0x86)
55 55 8d LH LL 86 RH RL NN RC RUNS... DATA... CS aa aa
│ │ │ └──┤ │ │ └─────┤ └─────┤
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ └─ Packed dot data (2 dots per byte)
│ │ │ │ │ │ └─ Run descriptors (2 bytes each)
│ │ │ │ │ └─ Number of run-descriptor bytes (RC)
│ │ │ │ └─ Repeat count (1-255)
│ │ │ └─ First row number (u16)
│ │ └─ Sub-command = 0x86 (data row)
│ └─ Data length (u16)
└─ Command 0x8d
RCis the byte length of theRUNSsection, not the number of runs. Because each descriptor is two bytes,RC = 2 * runCount.DATAcontains the row's packed dots with run dots removed, except for the first data byte of each run.Data length = 5 + RC + DATA.length.NNrepeats the same rowNNtimes. Repeat counts are one byte, so a repeated row range longer than255is split into multiple packets; the row number of each subsequent packet advances by the number of rows already sent.
Run-length encoding
A row is encoded from its 4-bit dot levels before the packet is built.
- Expand
DATAinto dot levels, high nibble first. - Walk the dots in pairs. For each pair
(a, b), append(a << 4) | bto the outputDATA. - If
a != b, continue with the next pair. - If
a == b, count the following dots that have the same level. The count is limited to252and rounded down to an even number. - If the count is less than
6, do not emit a run. The total run would be shorter than 8 dots, so storing it literally is not larger. - Otherwise, the run length is
count + 2(the initial pair plus the counted dots). Emit a descriptor and skip thecountdots; the skipped dots are reconstructed by the printer. - An encoder may stop emitting new runs after a fixed number of descriptors and store the remaining dots literally. A common limit is 126 run descriptors per row.
A run descriptor is two bytes:
run[0] = runLength | ((dataPos >> 8) & 1)
run[1] = dataPos & 0xFF
runLength = run[0] & 0xFE
dataPos = ((run[0] & 0x01) << 8) | run[1]
runLengthis the number of dots produced by the run, always even, in the range8-254.- The low bit of
run[0]carries bit 8 ofdataPos; this is possible becauserunLengthalways has bit 0 clear. dataPosis a 9-bit index (0-511) intoDATA, pointing at the first data byte of the run.- The printer repeats the last dot of the referenced data byte until
runLengthdots have been produced.
Examples
Row 0x0102, repeat 1, no runs, dots 1 2 3 4 5 6 7 8:
55 55 8d 00 09 86 01 02 01 00 12 34 56 78 08 aa aa
│ │ │ └──┤ │ │ └────────┤
│ │ │ │ │ │ └─ DATA = 12 34 56 78 (levels 1,2 / 3,4 / 5,6 / 7,8)
│ │ │ │ │ └─ RC = 0 (no runs)
│ │ │ │ └─ Repeat = 1
│ │ │ └─ Row = 0x0102
│ │ └─ Sub-command = 0x86
│ └─ Data length = 9
└─ Command 0x8d
32 dots of level 5 (16 bytes of 0x55), row 0, repeat 1:
55 55 8d 00 08 86 00 00 01 02 20 00 55 75 aa aa
│ │ │ └──┤ │ └──┤ │
│ │ │ │ │ │ └─ DATA = 55 (two level-5 dots)
│ │ │ │ │ └─ RUNS = 20 00 (run length 32, data position 0)
│ │ │ │ └─ RC = 2 (one descriptor)
│ │ │ └─ Row = 0, repeat = 1
│ │ └─ Sub-command = 0x86
│ └─ Data length = 8
└─ Command 0x8d
Encoding grayscale image pixels
- Convert each RGB pixel to a 4-bit level using inverted ITU-R BT.601 luminance:
Y = 0.299 * R + 0.587 * G + 0.114 * B
level = clamp(round((1 - Y / 255) * 15), 0, 15)
White becomes 0; black becomes 15.
- Pad the row to an even number of columns with white (level
0). Padding to a multiple of 8 is common because the non-grayscale row encoders operate on 8-pixel blocks. - Pack consecutive dot pairs into bytes, high nibble first.
- If every dot in a row is
0, send it as a blank row (0x84) instead of a data row (0x86). - Merge consecutive identical rows into one packet by increasing
NN. - Printers that support 16-level grayscale report their maximum grayscale buffer size in
GetPrinterCapabilitiesfield0x20(SixteenGrayMaxBuffer).
CompressCommand
Request ID 0x87. Wraps and compresses image row data or commands.
55 55 87 LL LL CH CL XX ... XX CS aa aa
│ └──┤ └──┤ │ │
│ │ │ │ │
│ │ │ └──────┴─ Compressed payload bytes
│ │ └─ Original uncompressed length (u16)
│ └─ Data length (u16) = payload_len + 2
└─ CompressCommand identifier
CompressImage
Request ID 0xa7. Transmits large compressed image packets.
55 55 a7 L1 L2 L3 L4 CH CL XX ... XX CS aa aa
│ └───────┤ └──┤ │ │
│ │ │ │ │
│ │ │ └──────┴─ Compressed bitmap data bytes
│ │ └─ Original size (u16)
│ └─ Data length (u32) = bitmap_len + 2
└─ CompressImage identifier
GetPrinterCapabilities
Request ID 0xaf, response 0xbf.
Request: simple (55 55 af 01 01 af aa aa).
Response (0xbf)
Payload consists of TLV (Type-Length-Value) blocks encoded sequentially:
- Type (
u8): Capability Field ID. - Length (
u8): Byte length of the field value. - Value: Field-specific value representation.
55 55 bf LL T1 L1 V1... T2 L2 V2... CS aa aa
│ │ │ └──┴──┤
│ │ │ └─────── Next TLV block
│ │ └────────────────── Value (L1 bytes)
│ └───────────────────── Length of field (L1 bytes)
└──────────────────────── Field ID (Type)
Capability Field IDs
| Field ID | Field Name | Data Type & Format | Description / Notes |
|---|---|---|---|
0x01 |
Language |
uint8 (bitmask) |
Supported languages (bit positions) |
0x02 |
PrintMode |
uint8 (bitmask) |
Supported print modes |
0x03 |
UhfRfid |
uint8 (bitmask) |
UHF RFID capabilities |
0x04 |
PrintheadDpi |
uint16 |
DPI classification (e.g. 200 or 300) |
0x05 |
RfidSupport |
uint8 (bitmask) |
RFID tag support flags |
0x06 |
BatteryRange |
uint8[2] ([max, min]) |
Battery level bounds |
0x07 |
DensityRange |
uint8[2] ([max, min]) |
Density adjustment range |
0x08 |
SpeedRange |
uint8[2] ([max, min]) |
Speed adjustment range |
0x09 |
SupportedLabelTypes |
uint8[4] (bitmask) |
Supported label types |
0x0a |
PrintheadWidth |
uint16 |
Printhead width in pixels/dots |
0x0b |
MaxPrintHeight |
uint16 |
Maximum print height in pixels/dots |
0x0c |
LabelHeightAndGap |
uint8 |
Default label height / gap setting |
0x0d |
PrintheadPosition |
uint8 |
Printhead physical position code |
0x0e |
VolumeSupport |
uint8 (bitmask) |
Audio volume support |
0x0f |
HostStyle |
uint8 (bitmask) |
Supported host communication styles |
0x10 |
PrintProtocol |
uint8 (bitmask) |
Supported print protocol options |
0x11 |
AutoShutdownRange |
uint8[2] ([max, min]) |
Auto-shutdown options range |
0x12 |
CutterSupport |
uint8 (bitmask) |
Paper cutter capabilities |
0x13 |
CutterDepthRange |
uint8[2] ([max, min]) |
Cutter depth range |
0x14 |
PrintControl |
uint8 (bitmask) |
Supported print control flags |
0x15 |
PauseTimeSupport |
uint8 (bitmask) |
Pause interval options |
0x16 |
PaperDetection |
uint8 |
Paper detection mechanism type |
0x17 |
RealTimeClock |
uint8 (bitmask) |
RTC features support |
0x18 |
KeyFunctions |
uint8[] (5 bytes/item) |
Physical key mappings: key (u8), functions (uint8[4] bitmask) |
0x19 |
Unknown19 |
uint8 |
Unknown / reserved |
0x1a |
PrintColor |
uint8 (bitmask) |
Supported color modes |
0x1b |
SpeedQualityMode |
uint8 (bitmask) |
Supported speed/quality modes |
0x1c |
TubeCalibration |
uint8 (bitmask) |
Tube calibration options |
0x1d |
PartialRetransmitSupport |
uint8 (bitmask) |
Partial retransmit capability |
0x1e |
MaxCompressLines |
uint16 |
Max line count per compression unit |
0x1f |
TubeSupport |
uint8 (bitmask) |
Tube printing support |
0x20 |
SixteenGrayMaxBuffer |
uint16 |
Maximum buffer size for 16-gray scale |
0x21 |
LocalTemplateSupport |
uint8 (bitmask) |
Local template capabilities |
0x22 |
ImageCompressSupport |
uint8 (bitmask) |
Supported image compression modes |
0x23 |
MaxImageCompressBytes |
uint32 |
Maximum image compression buffer size |
0x24 |
LocalTemplateMaxTimeCount |
uint8 |
Max local template execution/time count |
PrinterCheckLine
Sent from the printer periodically during printing (every 200 rows).
55 55 86 03 RR RR 01 CS aa aa
│ │ └──┤ │
│ │ │ │
│ │ │ └─ Always 0x01
│ │ └─ Row number
│ └─ Data length = 3
└─ PrinterCheckLine command
Heartbeat
Sent by the client every 2000 ms (default interval) after connection.
Request
Type 1 — Advanced1 (used when protocolVersion < 3)
55 55 dc 01 01 dc aa aa
Type 2 — PrinterInfo
55 55 dc 01 03 dc aa aa
Type 4 — Advanced2 (used when protocolVersion >= 3)
55 55 dc 01 04 d9 aa aa
Response — Advanced1 (0xdd)
Purpose of skipped bytes is unknown, they are ignored in official SDK.
10 bytes (e.g. D110)
55 55 dd 0a [8 bytes skipped] LC CL CS aa aa
│ │
│ │
│ └─ Lid Closed (0 = closed)
└─ Charge Level
13 bytes (e.g. B1)
55 55 dd 0d [9 bytes skipped] LC CL PI RF CS aa aa
│ │ │ │
│ │ │ │
│ │ │ └─ Paper RFID Success (1 = ok)
│ │ └─ Paper Inserted (0 = inserted)
│ └─ Charge Level
└─ Lid Closed (0 = closed)
19 bytes
55 55 dd 13 [15 bytes skipped] LC CL PI RF CS aa aa
│ │ │ │
│ │ │ │
│ │ │ └─ Paper RFID Success (1 = ok)
│ │ └─ Paper Inserted (0 = inserted)
│ └─ Charge Level
└─ Lid Closed (0 = closed)
20 bytes
55 55 dd 14 [18 bytes skipped] PI RF CS aa aa
│ │
│ │
│ └─ Paper RFID Success (1 = ok)
└─ Paper Inserted (0 = inserted)
For the legacy 0xdd response, the Official SDK parser selects the payload layout from the printer model ID:
| Printer model ID | Payload length | Parsed fields |
|---|---|---|
256, 257, 258, 260, 262 |
17 | lid/cover state |
512, 513, 514, 1792, 2304, 2560, 272, 273, 274, 3584, 3840, 4352, 5120 |
17 | lid/cover, charge, paper RFID |
768, 769, 770, 771, 772, 774, 775, 776, 2816, 4096 |
20 | lid/cover, charge, paper, paper RFID |
1025 |
27 | paper, ribbon RFID |
2049, 2050, 2051, 2052 |
26 | lid/cover, charge, paper, ribbon RFID |
Note
For models with IDs 512, 513, 514, 272, 273, 274, 1792, 2304, 2560, 3584, 3840, 4352, 5120
the lidClosed byte meaning is inverted (1 = closed instead of 0 = closed).
Response — Advanced2 (0xd9)
Minimum payload length: 9 bytes.
┌ Other bytes starting from this byte are optional (inclusive)
│
55 55 d9 LL 2e c3 64 4d 00 00 01 01 00 00 00 00 00 00 CS aa aa
│ │ │ │ │ │ │ └──┤ │ │
│ │ │ │ │ │ │ │ │ └─ VoltageState
│ │ │ │ │ │ │ │ └─ LightingErrorCode
│ │ │ │ │ │ │ └─ Wifi RSSI
│ │ │ │ │ │ └─ Ribbon inserted
│ │ │ │ │ └─ Ribbon RFID Success (1 - RFID ok)
│ │ │ │ └─ Paper RFID Success (0 - RFID ok)
│ │ │ └─ Paper Inserted (0 - inserted)
│ │ └─ Lid Closed (0 - closed)
│ └─ Temperature
└─ Charge Level
Response — PrinterInfo (0xde)
55 55 de 0a VH VL VH VL WH WL AC HA SR SW CS aa aa
└──┤ └──┤ └──┤ │ │ │ │
│ │ │ │ │ │ └─ Supports write RFID
│ │ │ │ │ └─ Supports RFID
│ │ │ │ └─ Printhead alignment
│ │ │ └─ Print accuracy
│ │ └─ Printhead width (u16)
│ └─ Software version (u16)
└─ Hardware version (u16)
Print accuracy actually looks like DPI classification:
| Byte | Meaning |
|---|---|
| 0x02 | 203 dpi |
| 0x03 | 300 dpi |
Example:
55 55 DE 0A 05 0A 05 16 01 80 02 02 01 00 48 AA AA - B1
55 55 DE 0A 03 01 03 09 02 40 03 02 01 00 9E AA AA - B21 Pro
StartFirmwareUpgrade
Firmware upgrade uses CRC32 packets exclusively. The exchange is driven by the printer.
Full sequence
Client Printer
│ │
├─ StartFirmwareUpgrade (0xf5) ─────►│ payload: [major, minor] version bytes
│◄─ In_StartFirmwareUpgrade (0xf6) ──┤ simple response
│ │
│◄─ In_RequestFirmwareCrc (0x90) ────┤ printer initiates CRC request
├─ FirmwareCrc (0x91) ──────────────►│ payload: CRC32 of full firmware blob (4 bytes big-endian)
│ │
│ ↻ chunk loop (printer-driven): │
│◄─ In_RequestFirmwareChunk (0x9a) ──┤ index = requested chunk number
├─ FirmwareChunk (0x9b) ────────────►│ index = chunk number, data = up to 200 bytes
│ │
├─ FirmwareNoMoreChunks (0x9c) ─────►│ payload: 01 (signals no more data)
│◄─ In_FirmwareCheckResult (0x9d) ───┤ data[0] = 1 (CRC ok) or 0 (error)
│ │
├─ FirmwareCommit (0x92) ───────────►│ payload: 01
│◄─ In_FirmwareResult (0x9e) ────────┤ data[0] = 1 (success) or 0 (error)
- Chunk size: 200 bytes.
FirmwareCrc,FirmwareChunk,FirmwareNoMoreChunks,FirmwareCommitare one-way (no response waited per packet — the printer drives the exchange).- CRC32 checksum in firmware packets covers
[cmd, indexHigh, indexLow, dataLen, ...data].
Printer error codes
Returned with In_PrintError.
| Code | Name |
|---|---|
0x01 |
CoverOpen |
0x02 |
LackPaper (no paper) |
0x03 |
LowBattery |
0x04 |
BatteryException |
0x05 |
UserCancel |
0x06 |
DataError |
0x07 |
Overheat |
0x08 |
PaperOutException |
0x09 |
PrinterBusy |
0x0a |
NoPrinterHead |
0x0b |
TemperatureLow |
0x0c |
PrinterHeadLoose |
0x0d |
NoRibbon |
0x0e |
WrongRibbon |
0x0f |
UsedRibbon |
0x10 |
WrongPaper |
0x11 |
SetPaperFail |
0x12 |
SetPrintModeFail |
0x13 |
SetPrintDensityFail |
0x14 |
WriteRfidFail |
0x15 |
SetMarginFail |
0x16 |
CommunicationException |
0x17 |
Disconnect |
0x18 |
CanvasParameterError |
0x19 |
RotationParameterException |
0x1a |
JsonParameterException |
0x1b |
B3sAbnormalPaperOutput |
0x1c |
ECheckPaper |
0x1d |
RfidTagNotWritten |
0x1e |
SetPrintDensityNoSupport |
0x1f |
SetPrintModeNoSupport |
0x20 |
SetPrintLabelMaterialError |
0x21 |
SetPrintLabelMaterialNoSupport |
0x22 |
NotSupportWrittenRfid |
0x32 |
IllegalPage |
0x33 |
IllegalRibbonPage |
0x34 |
ReceiveDataTimeout |
0x35 |
NonDedicatedRibbon |