Public Access
Align status decoding with the manual
Decodes the model code (byte 4) to a name, adds the cooling notification values, and rewords the error-information-2 bit 0 message. That bit is a media mismatch, which in practice means a monochrome job sent to a black/red roll — the exact failure seen on the QL-820NWB here.
This commit is contained in:
+40
-15
@@ -1,23 +1,26 @@
|
||||
/**
|
||||
* Decoder for the 32-byte status frame the QL series sends back.
|
||||
*
|
||||
* This is what the Python brother_ql path could never give us: real printer
|
||||
* state rather than a parsed traceback. Cover open, roll empty and wrong roll
|
||||
* width can all be reported before a label is wasted.
|
||||
* Field layout and every code below is from Brother's "Raster Command
|
||||
* Reference, QL-800/810W/820NWB v1.01", section 4, "Status information
|
||||
* request".
|
||||
*
|
||||
* Note this is only useful over USB. Manual section 5.9 shows the network
|
||||
* flow: over a TCP/IP port the print data is simply sent as-is and no status
|
||||
* comes back. See probeStatus in ql-transport.js.
|
||||
*
|
||||
* Layout (confirmed against Brother's reference and live QL-8xx captures):
|
||||
* 0 print head mark (0x80)
|
||||
* 1 size (0x20)
|
||||
* 2 fixed 'B' (0x42)
|
||||
* 3-4 device dependent (model code)
|
||||
* 5 fixed '0' (0x30)
|
||||
* 6-7 fixed
|
||||
* 3 series code, fixed '4' (0x34)
|
||||
* 4 model code
|
||||
* 5-7 fixed
|
||||
* 8 error information 1
|
||||
* 9 error information 2
|
||||
* 10 media width in mm
|
||||
* 11 media type
|
||||
* 12-13 fixed
|
||||
* 14 reserved
|
||||
* 14 fixed 0x3F
|
||||
* 15 mode
|
||||
* 16 fixed
|
||||
* 17 media length in mm
|
||||
@@ -41,13 +44,17 @@ const ERROR_BITS_1 = [
|
||||
];
|
||||
|
||||
const ERROR_BITS_2 = [
|
||||
[0x01, 'Wrong media for this job'],
|
||||
[
|
||||
0x01,
|
||||
'Media mismatch — the loaded roll does not match the job. A black/red ' +
|
||||
'roll rejects a monochrome job, and vice versa.',
|
||||
],
|
||||
[0x02, 'Expansion buffer full'],
|
||||
[0x04, 'Transmission or communication error'],
|
||||
[0x04, 'Communication error'],
|
||||
[0x08, 'Communication buffer full'],
|
||||
[0x10, 'Cover is open'],
|
||||
[0x20, 'Cancelled at the printer'],
|
||||
[0x40, 'Media cannot be fed'],
|
||||
[0x40, 'Media cannot be fed, or the end of the media was detected'],
|
||||
[0x80, 'System error'],
|
||||
];
|
||||
|
||||
@@ -65,6 +72,20 @@ const PHASE_TYPES = {
|
||||
0x01: 'printing',
|
||||
};
|
||||
|
||||
/** Notification numbers. Cooling pauses printing but is not a failure. */
|
||||
const NOTIFICATIONS = {
|
||||
0x00: null,
|
||||
0x03: 'Print head cooling (started)',
|
||||
0x04: 'Print head cooling (finished)',
|
||||
};
|
||||
|
||||
/** Byte 4 of the status frame. */
|
||||
const MODEL_CODES = {
|
||||
0x38: 'QL-800',
|
||||
0x39: 'QL-810W',
|
||||
0x41: 'QL-820NWB',
|
||||
};
|
||||
|
||||
const MEDIA_TYPES = {
|
||||
0x00: 'none',
|
||||
0x0a: 'continuous',
|
||||
@@ -94,7 +115,7 @@ function decodeStatus(buf) {
|
||||
const statusType = STATUS_TYPES[buf[18]] || `unknown_0x${buf[18].toString(16)}`;
|
||||
|
||||
return {
|
||||
modelCode: buf.readUInt16BE(3),
|
||||
model: MODEL_CODES[buf[4]] || `unknown_0x${buf[4].toString(16)}`,
|
||||
errors,
|
||||
hasError: errors.length > 0 || buf[18] === 0x02,
|
||||
mediaWidthMm: buf[10],
|
||||
@@ -104,7 +125,8 @@ function decodeStatus(buf) {
|
||||
statusType,
|
||||
phaseType: PHASE_TYPES[buf[19]] || `unknown_0x${buf[19].toString(16)}`,
|
||||
phaseNumber: buf.readUInt16BE(20),
|
||||
notification: buf[22],
|
||||
notification: NOTIFICATIONS[buf[22]] ?? `unknown_0x${buf[22].toString(16)}`,
|
||||
cooling: buf[22] === 0x03,
|
||||
raw: Buffer.from(buf.subarray(0, FRAME_LENGTH)),
|
||||
};
|
||||
}
|
||||
@@ -140,8 +162,10 @@ function describeProblem(status) {
|
||||
/**
|
||||
* Check the loaded roll matches what the job expects.
|
||||
*
|
||||
* Worth doing before sending: a two-colour job on a plain roll is refused with
|
||||
* "wrong roll type", which gives nobody a clue that a colour setting caused it.
|
||||
* Worth doing before sending where status is available: a monochrome job on a
|
||||
* black/red roll is refused outright, and the printer's own message ("change
|
||||
* it to Monochrome media") points at the driver rather than at the roll
|
||||
* setting, which sends people the wrong way.
|
||||
*
|
||||
* @returns {string|null} a problem description, or null if it matches.
|
||||
*/
|
||||
@@ -163,6 +187,7 @@ function checkMediaMatches(status, media) {
|
||||
|
||||
export {
|
||||
FRAME_LENGTH,
|
||||
MODEL_CODES,
|
||||
decodeStatus,
|
||||
decodeAll,
|
||||
describeProblem,
|
||||
|
||||
Reference in New Issue
Block a user