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).
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) | ❌ | — |
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
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 in library): 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 pixel count exceeds 6 the library throws an error and uses PrintBitmapRow 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
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 (u32 BE) |
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 |