@thermal-label/brother-ql-core 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +3 -3
  2. package/data/devices.json +250 -24
  3. package/data/media.json +12 -12
  4. package/dist/__tests__/devices.test.js +12 -20
  5. package/dist/__tests__/devices.test.js.map +1 -1
  6. package/dist/__tests__/network-status.test.d.ts +2 -0
  7. package/dist/__tests__/network-status.test.d.ts.map +1 -0
  8. package/dist/__tests__/network-status.test.js +132 -0
  9. package/dist/__tests__/network-status.test.js.map +1 -0
  10. package/dist/__tests__/protocol.test.js +103 -0
  11. package/dist/__tests__/protocol.test.js.map +1 -1
  12. package/dist/__tests__/status.test.js +13 -1
  13. package/dist/__tests__/status.test.js.map +1 -1
  14. package/dist/devices.d.ts +31 -5
  15. package/dist/devices.d.ts.map +1 -1
  16. package/dist/devices.generated.d.ts +31 -4
  17. package/dist/devices.generated.d.ts.map +1 -1
  18. package/dist/devices.generated.js +38 -4
  19. package/dist/devices.generated.js.map +1 -1
  20. package/dist/devices.js +0 -12
  21. package/dist/devices.js.map +1 -1
  22. package/dist/index.d.ts +3 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/media.generated.js +24 -24
  27. package/dist/media.generated.js.map +1 -1
  28. package/dist/network-status.d.ts +45 -0
  29. package/dist/network-status.d.ts.map +1 -0
  30. package/dist/network-status.js +140 -0
  31. package/dist/network-status.js.map +1 -0
  32. package/dist/protocol.d.ts.map +1 -1
  33. package/dist/protocol.js +34 -6
  34. package/dist/protocol.js.map +1 -1
  35. package/dist/status.d.ts +5 -3
  36. package/dist/status.d.ts.map +1 -1
  37. package/dist/status.js +21 -6
  38. package/dist/status.js.map +1 -1
  39. package/dist/types.d.ts +5 -1
  40. package/dist/types.d.ts.map +1 -1
  41. package/package.json +2 -2
  42. package/src/__tests__/devices.test.ts +13 -23
  43. package/src/__tests__/network-status.test.ts +165 -0
  44. package/src/__tests__/protocol.test.ts +129 -2
  45. package/src/__tests__/status.test.ts +15 -1
  46. package/src/devices.generated.ts +38 -4
  47. package/src/devices.ts +0 -16
  48. package/src/index.ts +3 -1
  49. package/src/media.generated.ts +24 -24
  50. package/src/network-status.ts +173 -0
  51. package/src/protocol.ts +41 -7
  52. package/src/status.ts +26 -6
  53. package/src/types.ts +5 -1
@@ -0,0 +1,165 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { parseMediaName, statusFromPrinterMib, type PrinterMibStatus } from '../network-status.js';
3
+
4
+ /** Bench values, QL-820NWBc 2026-09-15 (plan 17 Context). */
5
+ const DK_11201_NAME = '29mm x 90mm / 1.1" x 3.5"';
6
+ const DK_22205_NAME = '62mm / 2.4"';
7
+
8
+ function mib(overrides: Partial<PrinterMibStatus> = {}): PrinterMibStatus {
9
+ return {
10
+ printerStatus: 3,
11
+ errorState: new Uint8Array([0x00]),
12
+ mediaName: DK_22205_NAME,
13
+ feedDir: -1,
14
+ xFeedDir: -1,
15
+ ...overrides,
16
+ };
17
+ }
18
+
19
+ /** Octets with the given RFC 2790 bit numbers set (bit 0 = MSB of octet 0). */
20
+ function errorBits(...bits: number[]): Uint8Array {
21
+ const octets = new Uint8Array(2);
22
+ for (const bit of bits) octets[bit >> 3] = (octets[bit >> 3] ?? 0) | (0x80 >> (bit & 7));
23
+ return octets;
24
+ }
25
+
26
+ describe('parseMediaName', () => {
27
+ it.each([
28
+ [DK_11201_NAME, { widthMm: 29, heightMm: 90 }],
29
+ [DK_22205_NAME, { widthMm: 62 }],
30
+ ['17mm x 54mm / 0.66" x 2.1"', { widthMm: 17, heightMm: 54 }],
31
+ ['62mm', { widthMm: 62 }],
32
+ ['24mm Dia / 0.9" Dia', { widthMm: 24, heightMm: 24 }],
33
+ ['29 mm × 90 mm', { widthMm: 29, heightMm: 90 }],
34
+ ])('%s', (name, expected) => {
35
+ expect(parseMediaName(name)).toEqual(expected);
36
+ });
37
+
38
+ it.each(['', 'garbage', '2.4"', 'mm', '62 / 2.4"', 'Roll 62'])('rejects %j', name => {
39
+ expect(parseMediaName(name)).toBeUndefined();
40
+ });
41
+ });
42
+
43
+ describe('statusFromPrinterMib', () => {
44
+ it('idle, no errors, 62 mm continuous → ready with DK-22205 and the two-colour warning', () => {
45
+ const status = statusFromPrinterMib(mib());
46
+ expect(status.ready).toBe(true);
47
+ expect(status.errors).toEqual([]);
48
+ expect(status.mediaLoaded).toBe(true);
49
+ expect(status.detectedMedia?.id).toBe(259);
50
+ expect(status.rawBytes).toHaveLength(0);
51
+ expect(status.details).toContainEqual({
52
+ label: 'Two-colour',
53
+ value: 'not detectable over network',
54
+ severity: 'warn',
55
+ });
56
+ expect(status.details?.find(d => d.label === 'Printer state')?.value).toBe('idle');
57
+ });
58
+
59
+ it('29×90 die-cut → DK-11201, no two-colour row', () => {
60
+ const status = statusFromPrinterMib(mib({ mediaName: DK_11201_NAME }));
61
+ expect(status.detectedMedia?.id).toBe(271);
62
+ expect(status.details?.some(d => d.label === 'Two-colour')).toBe(false);
63
+ });
64
+
65
+ it('printing counts as ready; warmup, other and unknown do not', () => {
66
+ expect(statusFromPrinterMib(mib({ printerStatus: 4 })).ready).toBe(true);
67
+ expect(statusFromPrinterMib(mib({ printerStatus: 5 })).ready).toBe(false);
68
+ expect(statusFromPrinterMib(mib({ printerStatus: 1 })).ready).toBe(false);
69
+ expect(statusFromPrinterMib(mib({ printerStatus: 99 })).ready).toBe(false);
70
+ expect(
71
+ statusFromPrinterMib(mib({ printerStatus: 99 })).details?.find(
72
+ d => d.label === 'Printer state',
73
+ )?.value,
74
+ ).toBe('unknown');
75
+ });
76
+
77
+ it.each([
78
+ [1, 'no_media', 'No media'],
79
+ [4, 'cover_open', 'Cover open'],
80
+ [5, 'cutter_jam', 'Jammed'],
81
+ [6, 'not_ready', 'Offline'],
82
+ [7, 'system_error', 'Service requested'],
83
+ [13, 'no_media', 'Input tray empty'],
84
+ [8, 'system_error', 'inputTrayMissing'],
85
+ [14, 'system_error', 'overduePreventMaint'],
86
+ ])('error-state bit %i → %s', (bit, code, message) => {
87
+ const status = statusFromPrinterMib(mib({ errorState: errorBits(bit) }));
88
+ expect(status.errors).toEqual([{ code, message }]);
89
+ expect(status.ready).toBe(false);
90
+ });
91
+
92
+ it('lowPaper is a warning row, not an error', () => {
93
+ const status = statusFromPrinterMib(mib({ errorState: errorBits(0) }));
94
+ expect(status.errors).toEqual([]);
95
+ expect(status.ready).toBe(true);
96
+ expect(status.details).toContainEqual({ label: 'Media', value: 'Media low', severity: 'warn' });
97
+ });
98
+
99
+ it('reads error state from 0, 1 and 2 octets', () => {
100
+ expect(statusFromPrinterMib(mib({ errorState: new Uint8Array(0) })).errors).toEqual([]);
101
+ expect(statusFromPrinterMib(mib({ errorState: new Uint8Array([0x08]) })).errors).toEqual([
102
+ { code: 'cover_open', message: 'Cover open' },
103
+ ]);
104
+ expect(statusFromPrinterMib(mib({ errorState: new Uint8Array([0x00, 0x04]) })).errors).toEqual([
105
+ { code: 'no_media', message: 'Input tray empty' },
106
+ ]);
107
+ });
108
+
109
+ it('the name wins over Dim OIDs (bench: unit 4 claimed, 1/100 mm sent)', () => {
110
+ const status = statusFromPrinterMib(
111
+ mib({ mediaName: DK_11201_NAME, xFeedDir: 2900, feedDir: 9000, dimUnit: 4 }),
112
+ );
113
+ expect(status.detectedMedia?.id).toBe(271);
114
+ });
115
+
116
+ it('falls back to Dim OIDs in ten-thousandths of an inch (unit 3)', () => {
117
+ // 29 mm = 11417, 90 mm = 35433 ten-thousandths of an inch.
118
+ const status = statusFromPrinterMib(
119
+ mib({ mediaName: 'nonsense', xFeedDir: 11417, feedDir: 35433, dimUnit: 3 }),
120
+ );
121
+ expect(status.detectedMedia?.id).toBe(271);
122
+ });
123
+
124
+ it('falls back to Dim OIDs in micrometres (unit 4)', () => {
125
+ const status = statusFromPrinterMib(
126
+ mib({ mediaName: 'nonsense', xFeedDir: 62000, feedDir: -1, dimUnit: 4 }),
127
+ );
128
+ expect(status.detectedMedia?.id).toBe(259);
129
+ });
130
+
131
+ it('no media when the name is unparseable and the Dim OIDs are negative or unitless', () => {
132
+ expect(
133
+ statusFromPrinterMib(mib({ mediaName: 'nonsense', xFeedDir: -1, feedDir: -1, dimUnit: 3 }))
134
+ .detectedMedia,
135
+ ).toBeUndefined();
136
+ expect(
137
+ statusFromPrinterMib(mib({ mediaName: 'nonsense', xFeedDir: 11417, feedDir: 35433 }))
138
+ .detectedMedia,
139
+ ).toBeUndefined();
140
+ // RFC 3805 only defines 3 and 4; anything else is not converted.
141
+ expect(
142
+ statusFromPrinterMib(
143
+ mib({ mediaName: 'nonsense', xFeedDir: 11417, feedDir: 35433, dimUnit: 1 }),
144
+ ).detectedMedia,
145
+ ).toBeUndefined();
146
+ });
147
+
148
+ it('unrecognised media name → no media, warn row with the raw string', () => {
149
+ const status = statusFromPrinterMib(mib({ mediaName: 'Roll 62' }));
150
+ expect(status.mediaLoaded).toBe(false);
151
+ expect(status.detectedMedia).toBeUndefined();
152
+ expect(status.details).toContainEqual({
153
+ label: 'Media',
154
+ value: 'not recognised: "Roll 62"',
155
+ severity: 'warn',
156
+ });
157
+ expect(status.ready).toBe(true);
158
+ });
159
+
160
+ it('a recognised size with no registry entry → warn row, no media', () => {
161
+ const status = statusFromPrinterMib(mib({ mediaName: '99mm x 99mm / x' }));
162
+ expect(status.detectedMedia).toBeUndefined();
163
+ expect(status.details?.some(d => d.value.startsWith('not recognised'))).toBe(true);
164
+ });
165
+ });
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { createBitmap } from '@mbtech-nl/bitmap';
2
+ import { createBitmap, type LabelBitmap } from '@mbtech-nl/bitmap';
3
3
  import {
4
4
  buildInvalidate,
5
5
  buildInitialize,
@@ -16,7 +16,7 @@ import {
16
16
  encodeJobForEngine,
17
17
  type EncoderEngine,
18
18
  } from '../protocol.js';
19
- import type { PageData } from '../types.js';
19
+ import type { BrotherQLMedia, PageData } from '../types.js';
20
20
  import { MEDIA } from '../media.js';
21
21
 
22
22
  describe('buildInvalidate', () => {
@@ -494,3 +494,130 @@ describe('encodeJob legacy entry point — back compat', () => {
494
494
  expect(out[204]).toBe(0x1b);
495
495
  });
496
496
  });
497
+
498
+ describe('die-cut page length (reference §2.3.2(b), §2.3.3, §2.3.4)', () => {
499
+ const DK_29X90 = MEDIA[271]!; // print area length 991 dots
500
+ const DK_62MM = MEDIA[259]!;
501
+ const QL_ENGINE: EncoderEngine = {
502
+ protocol: 'ql-raster',
503
+ headDots: 720,
504
+ capabilities: { autocut: true, mediaDetection: true },
505
+ };
506
+
507
+ /** Bitmap with every pixel of one row set, so the row is recognisable on the wire. */
508
+ function bitmapWithBlackRow(widthPx: number, heightPx: number, row: number): LabelBitmap {
509
+ const bitmap = createBitmap(widthPx, heightPx);
510
+ const bytesPerRow = Math.ceil(widthPx / 8);
511
+ bitmap.data.fill(0xff, row * bytesPerRow, (row + 1) * bytesPerRow);
512
+ return bitmap;
513
+ }
514
+
515
+ function findCmd(buf: Uint8Array, third: number): number {
516
+ for (let i = 0; i < buf.length - 4; i++) {
517
+ if (buf[i] === 0x1b && buf[i + 1] === 0x69 && buf[i + 2] === third) return i;
518
+ }
519
+ return -1;
520
+ }
521
+ const rasterNumber = (buf: Uint8Array): number => {
522
+ const i = findCmd(buf, 0x7a);
523
+ return (buf[i + 7] ?? 0) | ((buf[i + 8] ?? 0) << 8);
524
+ };
525
+ const marginDots = (buf: Uint8Array): number => {
526
+ const i = findCmd(buf, 0x64);
527
+ return (buf[i + 3] ?? 0) | ((buf[i + 4] ?? 0) << 8);
528
+ };
529
+ /** Raster rows as [opcode, colour, payload] triples, in wire order. */
530
+ function rasterRows(buf: Uint8Array): { op: number; color: number; payload: Uint8Array }[] {
531
+ const rows = [];
532
+ // Rows start after ESC i d (5 bytes) and run until the print command.
533
+ let i = findCmd(buf, 0x64) + 5;
534
+ while (i < buf.length && (buf[i] === 0x67 || buf[i] === 0x77)) {
535
+ const len = buf[i + 2] ?? 0;
536
+ rows.push({ op: buf[i]!, color: buf[i + 1]!, payload: buf.subarray(i + 3, i + 3 + len) });
537
+ i += 3 + len;
538
+ }
539
+ return rows;
540
+ }
541
+
542
+ it('sends the print-area length as the raster number and margin 0 on DK-11201', () => {
543
+ const bitmap = createBitmap(306, 608);
544
+ const out = encodeJobForEngine([{ bitmap, media: DK_29X90 }], {}, QL_ENGINE);
545
+ expect(rasterNumber(out)).toBe(991);
546
+ expect(marginDots(out)).toBe(0);
547
+ expect(rasterRows(out)).toHaveLength(991);
548
+ });
549
+
550
+ it('ignores marginDots on die-cut media', () => {
551
+ const bitmap = createBitmap(306, 10);
552
+ const out = encodeJobForEngine(
553
+ [{ bitmap, media: DK_29X90, options: { marginDots: 100 } }],
554
+ {},
555
+ QL_ENGINE,
556
+ );
557
+ expect(marginDots(out)).toBe(0);
558
+ });
559
+
560
+ it('centres the bitmap in the page', () => {
561
+ const bitmap = bitmapWithBlackRow(306, 3, 1);
562
+ const out = encodeJobForEngine([{ bitmap, media: DK_29X90 }], {}, QL_ENGINE);
563
+ const rows = rasterRows(out);
564
+ const black = rows.map((r, i) => (r.payload.some(b => b !== 0) ? i : -1)).filter(i => i >= 0);
565
+ // padTop = floor((991 - 3) / 2) = 494; the black row is bitmap row 1.
566
+ expect(black).toEqual([495]);
567
+ });
568
+
569
+ it('doubles the page length when QL high-res rows are supplied', () => {
570
+ const bitmap = createBitmap(306, 100);
571
+ const out = encodeJob([{ bitmap, media: DK_29X90, options: { highResolution: true } }]);
572
+ expect(rasterNumber(out)).toBe(1982);
573
+ expect(rasterRows(out)).toHaveLength(1982);
574
+ expect(marginDots(out)).toBe(0);
575
+ });
576
+
577
+ it('rejects a bitmap taller than the page, naming both numbers', () => {
578
+ const bitmap = createBitmap(306, 1200);
579
+ expect(() => encodeJobForEngine([{ bitmap, media: DK_29X90 }], {}, QL_ENGINE)).toThrow(
580
+ /1200 rows.*exactly 991/,
581
+ );
582
+ });
583
+
584
+ it('pads both planes alike on two-colour die-cut', () => {
585
+ const bitmap = bitmapWithBlackRow(306, 3, 1);
586
+ const redBitmap = bitmapWithBlackRow(306, 3, 1);
587
+ const out = encodeJobForEngine([{ bitmap, redBitmap, media: DK_29X90 }], {}, QL_ENGINE);
588
+ const rows = rasterRows(out);
589
+ expect(rows).toHaveLength(991 * 2);
590
+ const inked = rows
591
+ .map((r, i) => (r.payload.some(b => b !== 0) ? { i, color: r.color } : undefined))
592
+ .filter(r => r !== undefined);
593
+ expect(inked).toEqual([
594
+ { i: 495 * 2, color: 0x01 },
595
+ { i: 495 * 2 + 1, color: 0x02 },
596
+ ]);
597
+ });
598
+
599
+ it('throws when a die-cut entry lacks dieCutMaskedAreaDots', () => {
600
+ const media: BrotherQLMedia = { ...DK_29X90 };
601
+ delete media.dieCutMaskedAreaDots;
602
+ const bitmap = createBitmap(306, 10);
603
+ expect(() => encodeJobForEngine([{ bitmap, media }], {}, QL_ENGINE)).toThrow(
604
+ /dieCutMaskedAreaDots/,
605
+ );
606
+ });
607
+
608
+ it('leaves the continuous path byte-identical', async () => {
609
+ const { createHash } = await import('node:crypto');
610
+ const bitmap = bitmapWithBlackRow(696, 40, 7);
611
+ const out = encodeJobForEngine(
612
+ [{ bitmap, media: DK_62MM, options: { marginDots: 50 } }],
613
+ { copies: 2 },
614
+ QL_ENGINE,
615
+ );
616
+ expect(rasterNumber(out)).toBe(40);
617
+ expect(marginDots(out)).toBe(50);
618
+ // Digest recorded from the encoder before die-cut padding existed.
619
+ expect(createHash('sha256').update(out).digest('hex')).toBe(
620
+ 'ebc2b5f467faca133f0f72c6f3123671d4e4dc130f2dd8cad8d9a69fa50e95fc',
621
+ );
622
+ });
623
+ });
@@ -18,7 +18,8 @@ function makeStatusBytes(
18
18
  bytes[0] = 0x80;
19
19
  bytes[1] = 0x20;
20
20
  bytes[2] = 0x42;
21
- bytes[3] = 0x30;
21
+ bytes[3] = 0x34;
22
+ bytes[4] = 0x41;
22
23
  bytes[8] = overrides?.errInfo1 ?? 0;
23
24
  bytes[9] = overrides?.errInfo2 ?? 0;
24
25
  bytes[10] = overrides?.mediaWidthMm ?? 62;
@@ -150,6 +151,18 @@ describe('parseStatus', () => {
150
151
  });
151
152
 
152
153
  describe('parseStatus — details[]', () => {
154
+ it('model-code row renders bytes 3/4 as ASCII (4A = QL-820NWB capture)', () => {
155
+ const status = parseStatus(CAPTURE_DK_22205);
156
+ expect(status.details?.[0]).toEqual({ label: 'Model code', value: '4A' });
157
+ });
158
+
159
+ it('model-code row falls back to hex for unprintable bytes', () => {
160
+ const bytes = makeStatusBytes();
161
+ bytes[3] = 0x00;
162
+ bytes[4] = 0x41;
163
+ expect(parseStatus(bytes).details?.[0]?.value).toBe('0x00 0x41');
164
+ });
165
+
153
166
  it('always emits a Print phase row', () => {
154
167
  const status = parseStatus(makeStatusBytes());
155
168
  expect(status.details).toBeDefined();
@@ -196,6 +209,7 @@ describe('parseStatus — details[]', () => {
196
209
  it('details carries both phase and cooling rows while printing + cooling', () => {
197
210
  const status = parseStatus(makeStatusBytes({ phaseType: 0x01, notification: 0x03 }));
198
211
  expect(status.details).toEqual([
212
+ { label: 'Model code', value: '4A' },
199
213
  { label: 'Print phase', value: 'printing' },
200
214
  { label: 'Head cooling', value: 'cooling started', severity: 'warn' },
201
215
  ]);
@@ -661,9 +661,24 @@ export const REGISTRY = {
661
661
  },
662
662
  "hardwareQuirks": "Cassette-based media detection. Printer hard-rejects with an error code if the host job dimensions do not match the loaded DK cassette. Apps that compare detected vs selected media should switch to the matching cassette before sending.",
663
663
  "support": {
664
- "status": "untested"
664
+ "status": "verified",
665
+ "transports": {
666
+ "usb": "verified"
667
+ },
668
+ "lastVerified": "2026-05-21",
669
+ "packageVersion": "0.6.0",
670
+ "reports": [
671
+ {
672
+ "issue": 1,
673
+ "reporter": "@Leeft",
674
+ "date": "2026-05-21",
675
+ "result": "verified",
676
+ "os": "Windows",
677
+ "notes": "WebUSB on Edge 148 / Windows 11, 62mm continuous (DK-22205). Pre- and post-print status clean: no errors, phase advanced to printing."
678
+ }
679
+ ]
665
680
  },
666
- "supportStatus": "expected"
681
+ "supportStatus": "verified"
667
682
  },
668
683
  {
669
684
  "key": "QL_710W",
@@ -764,9 +779,24 @@ export const REGISTRY = {
764
779
  "editorLite": true
765
780
  },
766
781
  "support": {
767
- "status": "untested"
782
+ "status": "verified",
783
+ "transports": {
784
+ "usb": "verified"
785
+ },
786
+ "lastVerified": "2026-05-30",
787
+ "packageVersion": "0.6.1",
788
+ "reports": [
789
+ {
790
+ "issue": 2,
791
+ "reporter": "@nkaredia",
792
+ "date": "2026-05-22",
793
+ "result": "verified",
794
+ "os": "Windows",
795
+ "notes": "QL-800 USB print confirmed (reporter produced output). The report revealed the DK continuous margins were stored right-registered, parking the printable area off the left-seated paper; the left-registration fix (leftMarginPins=6 for 29mm) merged in PR #3 and shipped in 0.6.1."
796
+ }
797
+ ]
768
798
  },
769
- "supportStatus": "expected"
799
+ "supportStatus": "verified"
770
800
  },
771
801
  {
772
802
  "key": "QL_810W",
@@ -808,6 +838,10 @@ export const REGISTRY = {
808
838
  {
809
839
  "key": "QL_820NWBc",
810
840
  "name": "QL-820NWBc",
841
+ "modelNames": [
842
+ "QL-820NWB",
843
+ "QL-820NWBc"
844
+ ],
811
845
  "family": "brother-ql",
812
846
  "transports": {
813
847
  "usb": {
package/src/devices.ts CHANGED
@@ -6,18 +6,6 @@ import { DEVICES, REGISTRY } from './devices.generated.js';
6
6
  // labelwriter-aligned `REGISTRY` symbol.
7
7
  export const DEVICE_REGISTRY = REGISTRY;
8
8
 
9
- // Mass-storage PIDs aligned to Linux usb-ids (gowdy.us / linux-usb.org).
10
- // Each large-format printer with Editor Lite enumerates as USB Mass
11
- // Storage Class on this alternate PID until the user holds the Editor
12
- // Lite button to switch back to printer-class. Aggregated from each
13
- // device entry's `capabilities.massStoragePid`.
14
- const MASS_STORAGE_PIDS = new Set<number>(
15
- Object.values(DEVICES).flatMap(d => {
16
- const pid = d.capabilities?.massStoragePid;
17
- return typeof pid === 'string' ? [parseInt(pid, 16)] : [];
18
- }),
19
- );
20
-
21
9
  export { DEVICES };
22
10
 
23
11
  /**
@@ -39,7 +27,3 @@ export function findDevice(vid: number, pid: number): BrotherQLDevice | undefine
39
27
  return ids?.vid === vid && ids.pid === pid;
40
28
  });
41
29
  }
42
-
43
- export function isMassStorageMode(pid: number): boolean {
44
- return MASS_STORAGE_PIDS.has(pid);
45
- }
package/src/index.ts CHANGED
@@ -33,7 +33,7 @@ export {
33
33
  UnsupportedOperationError,
34
34
  } from '@thermal-label/contracts';
35
35
 
36
- export { DEVICE_REGISTRY, DEVICES, findDevice, getUsbIds, isMassStorageMode } from './devices.js';
36
+ export { DEVICE_REGISTRY, DEVICES, findDevice, getUsbIds } from './devices.js';
37
37
 
38
38
  /**
39
39
  * Protocols this core's encoder produces correct wire bytes for.
@@ -63,6 +63,8 @@ export {
63
63
  } from './protocol.js';
64
64
  export type { EncoderEngine, RasterProtocolConfig } from './protocol.js';
65
65
  export { parseStatus, STATUS_REQUEST } from './status.js';
66
+ export { hasTwoColourSibling, parseMediaName, statusFromPrinterMib } from './network-status.js';
67
+ export type { PrinterMibStatus } from './network-status.js';
66
68
  export { createPreviewOffline } from './preview.js';
67
69
 
68
70
  export type {
@@ -53,8 +53,8 @@ const MEDIA_BY_ID: Record<number, BrotherQLMedia> = {
53
53
  ],
54
54
  "category": "continuous",
55
55
  "printableDots": 106,
56
- "leftMarginPins": 585,
57
- "rightMarginPins": 29
56
+ "leftMarginPins": 29,
57
+ "rightMarginPins": 585
58
58
  },
59
59
  "258": {
60
60
  "id": 258,
@@ -70,8 +70,8 @@ const MEDIA_BY_ID: Record<number, BrotherQLMedia> = {
70
70
  ],
71
71
  "category": "continuous",
72
72
  "printableDots": 306,
73
- "leftMarginPins": 408,
74
- "rightMarginPins": 6
73
+ "leftMarginPins": 6,
74
+ "rightMarginPins": 408
75
75
  },
76
76
  "259": {
77
77
  "id": 259,
@@ -104,8 +104,8 @@ const MEDIA_BY_ID: Record<number, BrotherQLMedia> = {
104
104
  ],
105
105
  "category": "continuous",
106
106
  "printableDots": 1164,
107
- "leftMarginPins": 76,
108
- "rightMarginPins": 56
107
+ "leftMarginPins": 56,
108
+ "rightMarginPins": 76
109
109
  },
110
110
  "261": {
111
111
  "id": 261,
@@ -121,8 +121,8 @@ const MEDIA_BY_ID: Record<number, BrotherQLMedia> = {
121
121
  ],
122
122
  "category": "continuous",
123
123
  "printableDots": 590,
124
- "leftMarginPins": 130,
125
- "rightMarginPins": 0
124
+ "leftMarginPins": 0,
125
+ "rightMarginPins": 130
126
126
  },
127
127
  "262": {
128
128
  "id": 262,
@@ -138,8 +138,8 @@ const MEDIA_BY_ID: Record<number, BrotherQLMedia> = {
138
138
  ],
139
139
  "category": "continuous",
140
140
  "printableDots": 554,
141
- "leftMarginPins": 154,
142
- "rightMarginPins": 12
141
+ "leftMarginPins": 12,
142
+ "rightMarginPins": 154
143
143
  },
144
144
  "264": {
145
145
  "id": 264,
@@ -155,8 +155,8 @@ const MEDIA_BY_ID: Record<number, BrotherQLMedia> = {
155
155
  ],
156
156
  "category": "continuous",
157
157
  "printableDots": 413,
158
- "leftMarginPins": 295,
159
- "rightMarginPins": 12
158
+ "leftMarginPins": 12,
159
+ "rightMarginPins": 295
160
160
  },
161
161
  "269": {
162
162
  "id": 269,
@@ -839,8 +839,8 @@ export const MEDIA_LIST: readonly BrotherQLMedia[] = Object.freeze([
839
839
  ],
840
840
  "category": "continuous",
841
841
  "printableDots": 106,
842
- "leftMarginPins": 585,
843
- "rightMarginPins": 29
842
+ "leftMarginPins": 29,
843
+ "rightMarginPins": 585
844
844
  },
845
845
  {
846
846
  "id": 258,
@@ -856,8 +856,8 @@ export const MEDIA_LIST: readonly BrotherQLMedia[] = Object.freeze([
856
856
  ],
857
857
  "category": "continuous",
858
858
  "printableDots": 306,
859
- "leftMarginPins": 408,
860
- "rightMarginPins": 6
859
+ "leftMarginPins": 6,
860
+ "rightMarginPins": 408
861
861
  },
862
862
  {
863
863
  "id": 264,
@@ -873,8 +873,8 @@ export const MEDIA_LIST: readonly BrotherQLMedia[] = Object.freeze([
873
873
  ],
874
874
  "category": "continuous",
875
875
  "printableDots": 413,
876
- "leftMarginPins": 295,
877
- "rightMarginPins": 12
876
+ "leftMarginPins": 12,
877
+ "rightMarginPins": 295
878
878
  },
879
879
  {
880
880
  "id": 262,
@@ -890,8 +890,8 @@ export const MEDIA_LIST: readonly BrotherQLMedia[] = Object.freeze([
890
890
  ],
891
891
  "category": "continuous",
892
892
  "printableDots": 554,
893
- "leftMarginPins": 154,
894
- "rightMarginPins": 12
893
+ "leftMarginPins": 12,
894
+ "rightMarginPins": 154
895
895
  },
896
896
  {
897
897
  "id": 261,
@@ -907,8 +907,8 @@ export const MEDIA_LIST: readonly BrotherQLMedia[] = Object.freeze([
907
907
  ],
908
908
  "category": "continuous",
909
909
  "printableDots": 590,
910
- "leftMarginPins": 130,
911
- "rightMarginPins": 0
910
+ "leftMarginPins": 0,
911
+ "rightMarginPins": 130
912
912
  },
913
913
  {
914
914
  "id": 259,
@@ -976,8 +976,8 @@ export const MEDIA_LIST: readonly BrotherQLMedia[] = Object.freeze([
976
976
  ],
977
977
  "category": "continuous",
978
978
  "printableDots": 1164,
979
- "leftMarginPins": 76,
980
- "rightMarginPins": 56
979
+ "leftMarginPins": 56,
980
+ "rightMarginPins": 76
981
981
  },
982
982
  {
983
983
  "id": 269,