@ecobridge.xyz/devicemanager 3.0.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 (137) hide show
  1. package/.gitea/workflows/default_nottags.yaml +66 -0
  2. package/.gitea/workflows/default_tags.yaml +124 -0
  3. package/.vscode/launch.json +11 -0
  4. package/.vscode/settings.json +26 -0
  5. package/changelog.md +91 -0
  6. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  7. package/dist_ts/00_commitinfo_data.js +9 -0
  8. package/dist_ts/device/device.classes.device.d.ts +205 -0
  9. package/dist_ts/device/device.classes.device.js +344 -0
  10. package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
  11. package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
  12. package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
  13. package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
  14. package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
  15. package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
  16. package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
  17. package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
  18. package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
  19. package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
  20. package/dist_ts/factories/index.d.ts +190 -0
  21. package/dist_ts/factories/index.js +350 -0
  22. package/dist_ts/features/feature.abstract.d.ts +118 -0
  23. package/dist_ts/features/feature.abstract.js +172 -0
  24. package/dist_ts/features/feature.camera.d.ts +95 -0
  25. package/dist_ts/features/feature.camera.js +162 -0
  26. package/dist_ts/features/feature.climate.d.ts +174 -0
  27. package/dist_ts/features/feature.climate.js +328 -0
  28. package/dist_ts/features/feature.cover.d.ts +121 -0
  29. package/dist_ts/features/feature.cover.js +217 -0
  30. package/dist_ts/features/feature.fan.d.ts +127 -0
  31. package/dist_ts/features/feature.fan.js +235 -0
  32. package/dist_ts/features/feature.light.d.ts +156 -0
  33. package/dist_ts/features/feature.light.js +296 -0
  34. package/dist_ts/features/feature.lock.d.ts +103 -0
  35. package/dist_ts/features/feature.lock.js +170 -0
  36. package/dist_ts/features/feature.playback.d.ts +98 -0
  37. package/dist_ts/features/feature.playback.js +191 -0
  38. package/dist_ts/features/feature.power.d.ts +79 -0
  39. package/dist_ts/features/feature.power.js +173 -0
  40. package/dist_ts/features/feature.print.d.ts +78 -0
  41. package/dist_ts/features/feature.print.js +226 -0
  42. package/dist_ts/features/feature.scan.d.ts +79 -0
  43. package/dist_ts/features/feature.scan.js +315 -0
  44. package/dist_ts/features/feature.sensor.d.ts +95 -0
  45. package/dist_ts/features/feature.sensor.js +147 -0
  46. package/dist_ts/features/feature.snmp.d.ts +88 -0
  47. package/dist_ts/features/feature.snmp.js +175 -0
  48. package/dist_ts/features/feature.switch.d.ts +75 -0
  49. package/dist_ts/features/feature.switch.js +126 -0
  50. package/dist_ts/features/feature.volume.d.ts +104 -0
  51. package/dist_ts/features/feature.volume.js +186 -0
  52. package/dist_ts/features/index.d.ts +19 -0
  53. package/dist_ts/features/index.js +23 -0
  54. package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
  55. package/dist_ts/helpers/helpers.iprange.js +151 -0
  56. package/dist_ts/helpers/helpers.retry.d.ts +25 -0
  57. package/dist_ts/helpers/helpers.retry.js +69 -0
  58. package/dist_ts/index.d.ts +15 -0
  59. package/dist_ts/index.js +40 -0
  60. package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
  61. package/dist_ts/interfaces/feature.interfaces.js +6 -0
  62. package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
  63. package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
  64. package/dist_ts/interfaces/index.d.ts +330 -0
  65. package/dist_ts/interfaces/index.js +16 -0
  66. package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
  67. package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
  68. package/dist_ts/paths.d.ts +1 -0
  69. package/dist_ts/paths.js +3 -0
  70. package/dist_ts/plugins.d.ts +23 -0
  71. package/dist_ts/plugins.js +30 -0
  72. package/dist_ts/protocols/index.d.ts +12 -0
  73. package/dist_ts/protocols/index.js +21 -0
  74. package/dist_ts/protocols/protocol.escl.d.ts +58 -0
  75. package/dist_ts/protocols/protocol.escl.js +364 -0
  76. package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
  77. package/dist_ts/protocols/protocol.homeassistant.js +611 -0
  78. package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
  79. package/dist_ts/protocols/protocol.ipp.js +284 -0
  80. package/dist_ts/protocols/protocol.nut.d.ts +160 -0
  81. package/dist_ts/protocols/protocol.nut.js +364 -0
  82. package/dist_ts/protocols/protocol.sane.d.ts +104 -0
  83. package/dist_ts/protocols/protocol.sane.js +597 -0
  84. package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
  85. package/dist_ts/protocols/protocol.snmp.js +333 -0
  86. package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
  87. package/dist_ts/protocols/protocol.upnp.js +442 -0
  88. package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
  89. package/dist_ts/protocols/protocol.upssnmp.js +263 -0
  90. package/npmextra.json +24 -0
  91. package/package.json +39 -0
  92. package/readme.hints.md +115 -0
  93. package/readme.md +624 -0
  94. package/test/test.ts +261 -0
  95. package/ts/00_commitinfo_data.ts +8 -0
  96. package/ts/device/device.classes.device.ts +454 -0
  97. package/ts/devicemanager.classes.devicemanager.ts +1219 -0
  98. package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
  99. package/ts/discovery/discovery.classes.mdns.ts +347 -0
  100. package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
  101. package/ts/discovery/discovery.classes.ssdp.ts +357 -0
  102. package/ts/factories/index.ts +696 -0
  103. package/ts/features/feature.abstract.ts +251 -0
  104. package/ts/features/feature.camera.ts +214 -0
  105. package/ts/features/feature.climate.ts +407 -0
  106. package/ts/features/feature.cover.ts +278 -0
  107. package/ts/features/feature.fan.ts +296 -0
  108. package/ts/features/feature.light.ts +369 -0
  109. package/ts/features/feature.lock.ts +223 -0
  110. package/ts/features/feature.playback.ts +246 -0
  111. package/ts/features/feature.power.ts +231 -0
  112. package/ts/features/feature.print.ts +297 -0
  113. package/ts/features/feature.scan.ts +370 -0
  114. package/ts/features/feature.sensor.ts +202 -0
  115. package/ts/features/feature.snmp.ts +235 -0
  116. package/ts/features/feature.switch.ts +170 -0
  117. package/ts/features/feature.volume.ts +256 -0
  118. package/ts/features/index.ts +25 -0
  119. package/ts/helpers/helpers.iprange.ts +172 -0
  120. package/ts/helpers/helpers.retry.ts +100 -0
  121. package/ts/index.ts +165 -0
  122. package/ts/interfaces/feature.interfaces.ts +359 -0
  123. package/ts/interfaces/homeassistant.interfaces.ts +666 -0
  124. package/ts/interfaces/index.ts +421 -0
  125. package/ts/interfaces/smarthome.interfaces.ts +421 -0
  126. package/ts/paths.ts +5 -0
  127. package/ts/plugins.ts +41 -0
  128. package/ts/protocols/index.ts +59 -0
  129. package/ts/protocols/protocol.escl.ts +439 -0
  130. package/ts/protocols/protocol.homeassistant.ts +737 -0
  131. package/ts/protocols/protocol.ipp.ts +329 -0
  132. package/ts/protocols/protocol.nut.ts +471 -0
  133. package/ts/protocols/protocol.sane.ts +694 -0
  134. package/ts/protocols/protocol.snmp.ts +439 -0
  135. package/ts/protocols/protocol.upnp.ts +627 -0
  136. package/ts/protocols/protocol.upssnmp.ts +377 -0
  137. package/tsconfig.json +12 -0
@@ -0,0 +1,597 @@
1
+ import * as plugins from '../plugins.js';
2
+ /**
3
+ * SANE network protocol RPC codes
4
+ */
5
+ var SaneRpc;
6
+ (function (SaneRpc) {
7
+ SaneRpc[SaneRpc["INIT"] = 0] = "INIT";
8
+ SaneRpc[SaneRpc["GET_DEVICES"] = 1] = "GET_DEVICES";
9
+ SaneRpc[SaneRpc["OPEN"] = 2] = "OPEN";
10
+ SaneRpc[SaneRpc["CLOSE"] = 3] = "CLOSE";
11
+ SaneRpc[SaneRpc["GET_OPTION_DESCRIPTORS"] = 4] = "GET_OPTION_DESCRIPTORS";
12
+ SaneRpc[SaneRpc["CONTROL_OPTION"] = 5] = "CONTROL_OPTION";
13
+ SaneRpc[SaneRpc["GET_PARAMETERS"] = 6] = "GET_PARAMETERS";
14
+ SaneRpc[SaneRpc["START"] = 7] = "START";
15
+ SaneRpc[SaneRpc["CANCEL"] = 8] = "CANCEL";
16
+ SaneRpc[SaneRpc["AUTHORIZE"] = 9] = "AUTHORIZE";
17
+ SaneRpc[SaneRpc["EXIT"] = 10] = "EXIT";
18
+ })(SaneRpc || (SaneRpc = {}));
19
+ /**
20
+ * SANE status codes
21
+ */
22
+ var SaneStatus;
23
+ (function (SaneStatus) {
24
+ SaneStatus[SaneStatus["GOOD"] = 0] = "GOOD";
25
+ SaneStatus[SaneStatus["UNSUPPORTED"] = 1] = "UNSUPPORTED";
26
+ SaneStatus[SaneStatus["CANCELLED"] = 2] = "CANCELLED";
27
+ SaneStatus[SaneStatus["DEVICE_BUSY"] = 3] = "DEVICE_BUSY";
28
+ SaneStatus[SaneStatus["INVAL"] = 4] = "INVAL";
29
+ SaneStatus[SaneStatus["EOF"] = 5] = "EOF";
30
+ SaneStatus[SaneStatus["JAMMED"] = 6] = "JAMMED";
31
+ SaneStatus[SaneStatus["NO_DOCS"] = 7] = "NO_DOCS";
32
+ SaneStatus[SaneStatus["COVER_OPEN"] = 8] = "COVER_OPEN";
33
+ SaneStatus[SaneStatus["IO_ERROR"] = 9] = "IO_ERROR";
34
+ SaneStatus[SaneStatus["NO_MEM"] = 10] = "NO_MEM";
35
+ SaneStatus[SaneStatus["ACCESS_DENIED"] = 11] = "ACCESS_DENIED";
36
+ })(SaneStatus || (SaneStatus = {}));
37
+ /**
38
+ * SANE option types
39
+ */
40
+ var SaneValueType;
41
+ (function (SaneValueType) {
42
+ SaneValueType[SaneValueType["BOOL"] = 0] = "BOOL";
43
+ SaneValueType[SaneValueType["INT"] = 1] = "INT";
44
+ SaneValueType[SaneValueType["FIXED"] = 2] = "FIXED";
45
+ SaneValueType[SaneValueType["STRING"] = 3] = "STRING";
46
+ SaneValueType[SaneValueType["BUTTON"] = 4] = "BUTTON";
47
+ SaneValueType[SaneValueType["GROUP"] = 5] = "GROUP";
48
+ })(SaneValueType || (SaneValueType = {}));
49
+ /**
50
+ * SANE option units
51
+ */
52
+ var SaneUnit;
53
+ (function (SaneUnit) {
54
+ SaneUnit[SaneUnit["NONE"] = 0] = "NONE";
55
+ SaneUnit[SaneUnit["PIXEL"] = 1] = "PIXEL";
56
+ SaneUnit[SaneUnit["BIT"] = 2] = "BIT";
57
+ SaneUnit[SaneUnit["MM"] = 3] = "MM";
58
+ SaneUnit[SaneUnit["DPI"] = 4] = "DPI";
59
+ SaneUnit[SaneUnit["PERCENT"] = 5] = "PERCENT";
60
+ SaneUnit[SaneUnit["MICROSECOND"] = 6] = "MICROSECOND";
61
+ })(SaneUnit || (SaneUnit = {}));
62
+ /**
63
+ * SANE constraint types
64
+ */
65
+ var SaneConstraintType;
66
+ (function (SaneConstraintType) {
67
+ SaneConstraintType[SaneConstraintType["NONE"] = 0] = "NONE";
68
+ SaneConstraintType[SaneConstraintType["RANGE"] = 1] = "RANGE";
69
+ SaneConstraintType[SaneConstraintType["WORD_LIST"] = 2] = "WORD_LIST";
70
+ SaneConstraintType[SaneConstraintType["STRING_LIST"] = 3] = "STRING_LIST";
71
+ })(SaneConstraintType || (SaneConstraintType = {}));
72
+ /**
73
+ * SANE control option actions
74
+ */
75
+ var SaneAction;
76
+ (function (SaneAction) {
77
+ SaneAction[SaneAction["GET_VALUE"] = 0] = "GET_VALUE";
78
+ SaneAction[SaneAction["SET_VALUE"] = 1] = "SET_VALUE";
79
+ SaneAction[SaneAction["SET_AUTO"] = 2] = "SET_AUTO";
80
+ })(SaneAction || (SaneAction = {}));
81
+ const SANE_PORT = 6566;
82
+ const SANE_NET_PROTOCOL_VERSION = 3;
83
+ /**
84
+ * Status code to error message mapping
85
+ */
86
+ const STATUS_MESSAGES = {
87
+ [SaneStatus.GOOD]: 'Success',
88
+ [SaneStatus.UNSUPPORTED]: 'Operation not supported',
89
+ [SaneStatus.CANCELLED]: 'Operation cancelled',
90
+ [SaneStatus.DEVICE_BUSY]: 'Device busy',
91
+ [SaneStatus.INVAL]: 'Invalid argument',
92
+ [SaneStatus.EOF]: 'End of file',
93
+ [SaneStatus.JAMMED]: 'Document feeder jammed',
94
+ [SaneStatus.NO_DOCS]: 'No documents in feeder',
95
+ [SaneStatus.COVER_OPEN]: 'Scanner cover open',
96
+ [SaneStatus.IO_ERROR]: 'I/O error',
97
+ [SaneStatus.NO_MEM]: 'Out of memory',
98
+ [SaneStatus.ACCESS_DENIED]: 'Access denied',
99
+ };
100
+ /**
101
+ * SANE network protocol client
102
+ */
103
+ export class SaneProtocol {
104
+ socket = null;
105
+ address;
106
+ port;
107
+ handle = -1;
108
+ options = [];
109
+ readBuffer = Buffer.alloc(0);
110
+ constructor(address, port = SANE_PORT) {
111
+ this.address = address;
112
+ this.port = port;
113
+ }
114
+ /**
115
+ * Connect to SANE daemon
116
+ */
117
+ async connect() {
118
+ return new Promise((resolve, reject) => {
119
+ this.socket = plugins.net.createConnection({ host: this.address, port: this.port }, () => {
120
+ this.init()
121
+ .then(() => resolve())
122
+ .catch(reject);
123
+ });
124
+ this.socket.on('error', reject);
125
+ this.socket.on('data', (data) => {
126
+ this.readBuffer = Buffer.concat([this.readBuffer, data]);
127
+ });
128
+ });
129
+ }
130
+ /**
131
+ * Disconnect from SANE daemon
132
+ */
133
+ async disconnect() {
134
+ if (this.handle >= 0) {
135
+ await this.close();
136
+ }
137
+ await this.exit();
138
+ if (this.socket) {
139
+ this.socket.destroy();
140
+ this.socket = null;
141
+ }
142
+ }
143
+ /**
144
+ * Initialize connection (SANE_NET_INIT)
145
+ */
146
+ async init() {
147
+ const request = this.buildRequest(SaneRpc.INIT);
148
+ this.writeWord(request, SANE_NET_PROTOCOL_VERSION);
149
+ this.writeString(request, ''); // Username (empty for now)
150
+ await this.sendRequest(request);
151
+ const response = await this.readResponse();
152
+ const status = this.readWord(response);
153
+ const version = this.readWord(response);
154
+ if (status !== SaneStatus.GOOD) {
155
+ throw new Error(`SANE init failed: ${STATUS_MESSAGES[status] || 'Unknown error'}`);
156
+ }
157
+ }
158
+ /**
159
+ * Get available devices (SANE_NET_GET_DEVICES)
160
+ */
161
+ async getDevices() {
162
+ const request = this.buildRequest(SaneRpc.GET_DEVICES);
163
+ await this.sendRequest(request);
164
+ const response = await this.readResponse();
165
+ const status = this.readWord(response);
166
+ if (status !== SaneStatus.GOOD) {
167
+ throw new Error(`Failed to get devices: ${STATUS_MESSAGES[status]}`);
168
+ }
169
+ const devices = [];
170
+ const count = this.readWord(response);
171
+ for (let i = 0; i < count; i++) {
172
+ const hasDevice = this.readWord(response);
173
+ if (hasDevice) {
174
+ devices.push({
175
+ name: this.readString(response),
176
+ vendor: this.readString(response),
177
+ model: this.readString(response),
178
+ type: this.readString(response),
179
+ });
180
+ }
181
+ }
182
+ return devices;
183
+ }
184
+ /**
185
+ * Open a device (SANE_NET_OPEN)
186
+ */
187
+ async open(deviceName) {
188
+ const request = this.buildRequest(SaneRpc.OPEN);
189
+ this.writeString(request, deviceName);
190
+ await this.sendRequest(request);
191
+ const response = await this.readResponse();
192
+ const status = this.readWord(response);
193
+ if (status !== SaneStatus.GOOD) {
194
+ // Check for authorization required
195
+ const resource = this.readString(response);
196
+ if (resource) {
197
+ throw new Error(`Authorization required for: ${resource}`);
198
+ }
199
+ throw new Error(`Failed to open device: ${STATUS_MESSAGES[status]}`);
200
+ }
201
+ this.handle = this.readWord(response);
202
+ this.readString(response); // resource (should be empty on success)
203
+ // Get option descriptors
204
+ await this.getOptionDescriptors();
205
+ }
206
+ /**
207
+ * Close the current device (SANE_NET_CLOSE)
208
+ */
209
+ async close() {
210
+ if (this.handle < 0) {
211
+ return;
212
+ }
213
+ const request = this.buildRequest(SaneRpc.CLOSE);
214
+ this.writeWord(request, this.handle);
215
+ await this.sendRequest(request);
216
+ await this.readResponse(); // Just read to clear buffer
217
+ this.handle = -1;
218
+ this.options = [];
219
+ }
220
+ /**
221
+ * Exit connection (SANE_NET_EXIT)
222
+ */
223
+ async exit() {
224
+ const request = this.buildRequest(SaneRpc.EXIT);
225
+ await this.sendRequest(request);
226
+ }
227
+ /**
228
+ * Get option descriptors (SANE_NET_GET_OPTION_DESCRIPTORS)
229
+ */
230
+ async getOptionDescriptors() {
231
+ const request = this.buildRequest(SaneRpc.GET_OPTION_DESCRIPTORS);
232
+ this.writeWord(request, this.handle);
233
+ await this.sendRequest(request);
234
+ const response = await this.readResponse();
235
+ const count = this.readWord(response);
236
+ this.options = [];
237
+ for (let i = 0; i < count; i++) {
238
+ const hasOption = this.readWord(response);
239
+ if (!hasOption) {
240
+ continue;
241
+ }
242
+ const option = {
243
+ name: this.readString(response),
244
+ title: this.readString(response),
245
+ description: this.readString(response),
246
+ type: this.mapValueType(this.readWord(response)),
247
+ unit: this.mapUnit(this.readWord(response)),
248
+ size: this.readWord(response),
249
+ capabilities: this.readWord(response),
250
+ constraintType: this.mapConstraintType(this.readWord(response)),
251
+ };
252
+ // Read constraint based on type
253
+ if (option.constraintType === 'range') {
254
+ option.constraint = {
255
+ range: {
256
+ min: this.readWord(response),
257
+ max: this.readWord(response),
258
+ quant: this.readWord(response),
259
+ },
260
+ };
261
+ }
262
+ else if (option.constraintType === 'word_list') {
263
+ const wordCount = this.readWord(response);
264
+ const words = [];
265
+ for (let j = 0; j < wordCount; j++) {
266
+ words.push(this.readWord(response));
267
+ }
268
+ option.constraint = { wordList: words };
269
+ }
270
+ else if (option.constraintType === 'string_list') {
271
+ const strings = [];
272
+ let str;
273
+ while ((str = this.readString(response)) !== '') {
274
+ strings.push(str);
275
+ }
276
+ option.constraint = { stringList: strings };
277
+ }
278
+ this.options.push(option);
279
+ }
280
+ }
281
+ /**
282
+ * Set an option value
283
+ */
284
+ async setOption(name, value) {
285
+ const optionIndex = this.options.findIndex((o) => o.name === name);
286
+ if (optionIndex < 0) {
287
+ throw new Error(`Unknown option: ${name}`);
288
+ }
289
+ const option = this.options[optionIndex];
290
+ const request = this.buildRequest(SaneRpc.CONTROL_OPTION);
291
+ this.writeWord(request, this.handle);
292
+ this.writeWord(request, optionIndex);
293
+ this.writeWord(request, SaneAction.SET_VALUE);
294
+ this.writeWord(request, option.type === 'string' ? value.length + 1 : option.size);
295
+ // Write value based on type
296
+ if (option.type === 'bool' || option.type === 'int') {
297
+ this.writeWord(request, value);
298
+ }
299
+ else if (option.type === 'fixed') {
300
+ this.writeWord(request, Math.round(value * 65536));
301
+ }
302
+ else if (option.type === 'string') {
303
+ this.writeString(request, value);
304
+ }
305
+ await this.sendRequest(request);
306
+ const response = await this.readResponse();
307
+ const status = this.readWord(response);
308
+ if (status !== SaneStatus.GOOD) {
309
+ throw new Error(`Failed to set option ${name}: ${STATUS_MESSAGES[status]}`);
310
+ }
311
+ }
312
+ /**
313
+ * Get scan parameters (SANE_NET_GET_PARAMETERS)
314
+ */
315
+ async getParameters() {
316
+ const request = this.buildRequest(SaneRpc.GET_PARAMETERS);
317
+ this.writeWord(request, this.handle);
318
+ await this.sendRequest(request);
319
+ const response = await this.readResponse();
320
+ const status = this.readWord(response);
321
+ if (status !== SaneStatus.GOOD) {
322
+ throw new Error(`Failed to get parameters: ${STATUS_MESSAGES[status]}`);
323
+ }
324
+ const formatCode = this.readWord(response);
325
+ const format = this.mapFormat(formatCode);
326
+ return {
327
+ format,
328
+ lastFrame: this.readWord(response) === 1,
329
+ bytesPerLine: this.readWord(response),
330
+ pixelsPerLine: this.readWord(response),
331
+ lines: this.readWord(response),
332
+ depth: this.readWord(response),
333
+ };
334
+ }
335
+ /**
336
+ * Start scanning (SANE_NET_START)
337
+ */
338
+ async start() {
339
+ const request = this.buildRequest(SaneRpc.START);
340
+ this.writeWord(request, this.handle);
341
+ await this.sendRequest(request);
342
+ const response = await this.readResponse();
343
+ const status = this.readWord(response);
344
+ if (status !== SaneStatus.GOOD) {
345
+ throw new Error(`Failed to start scan: ${STATUS_MESSAGES[status]}`);
346
+ }
347
+ const port = this.readWord(response);
348
+ const byteOrder = this.readWord(response) === 0x1234 ? 'little' : 'big';
349
+ this.readString(response); // resource
350
+ return { port, byteOrder };
351
+ }
352
+ /**
353
+ * Cancel scanning (SANE_NET_CANCEL)
354
+ */
355
+ async cancel() {
356
+ const request = this.buildRequest(SaneRpc.CANCEL);
357
+ this.writeWord(request, this.handle);
358
+ await this.sendRequest(request);
359
+ await this.readResponse();
360
+ }
361
+ /**
362
+ * Perform a complete scan
363
+ */
364
+ async scan(options) {
365
+ // Configure scan options
366
+ await this.configureOptions(options);
367
+ // Get parameters
368
+ const params = await this.getParameters();
369
+ // Start scan and get data port
370
+ const { port, byteOrder } = await this.start();
371
+ // Connect to data port and read image data
372
+ const imageData = await this.readImageData(port, params, byteOrder);
373
+ return {
374
+ data: imageData,
375
+ format: options.format ?? 'png',
376
+ width: params.pixelsPerLine,
377
+ height: params.lines,
378
+ resolution: options.resolution ?? 300,
379
+ colorMode: options.colorMode ?? 'color',
380
+ mimeType: `image/${options.format ?? 'png'}`,
381
+ };
382
+ }
383
+ /**
384
+ * Configure scan options based on IScanOptions
385
+ */
386
+ async configureOptions(options) {
387
+ // Set resolution
388
+ if (options.resolution) {
389
+ const resOption = this.options.find((o) => o.name === 'resolution');
390
+ if (resOption) {
391
+ await this.setOption('resolution', options.resolution);
392
+ }
393
+ }
394
+ // Set color mode
395
+ if (options.colorMode) {
396
+ const modeOption = this.options.find((o) => o.name === 'mode');
397
+ if (modeOption) {
398
+ const modeValue = this.mapColorMode(options.colorMode);
399
+ await this.setOption('mode', modeValue);
400
+ }
401
+ }
402
+ // Set scan area
403
+ if (options.area) {
404
+ const tlxOption = this.options.find((o) => o.name === 'tl-x');
405
+ const tlyOption = this.options.find((o) => o.name === 'tl-y');
406
+ const brxOption = this.options.find((o) => o.name === 'br-x');
407
+ const bryOption = this.options.find((o) => o.name === 'br-y');
408
+ if (tlxOption)
409
+ await this.setOption('tl-x', options.area.x);
410
+ if (tlyOption)
411
+ await this.setOption('tl-y', options.area.y);
412
+ if (brxOption)
413
+ await this.setOption('br-x', options.area.x + options.area.width);
414
+ if (bryOption)
415
+ await this.setOption('br-y', options.area.y + options.area.height);
416
+ }
417
+ // Set source
418
+ if (options.source) {
419
+ const sourceOption = this.options.find((o) => o.name === 'source');
420
+ if (sourceOption) {
421
+ await this.setOption('source', options.source);
422
+ }
423
+ }
424
+ }
425
+ /**
426
+ * Read image data from data port
427
+ */
428
+ async readImageData(port, params, _byteOrder) {
429
+ return new Promise((resolve, reject) => {
430
+ const dataSocket = plugins.net.createConnection({ host: this.address, port }, () => {
431
+ const chunks = [];
432
+ dataSocket.on('data', (data) => {
433
+ // Data format: 4 bytes length + data
434
+ // Read records until length is 0xFFFFFFFF (end marker)
435
+ let offset = 0;
436
+ while (offset < data.length) {
437
+ if (offset + 4 > data.length) {
438
+ break;
439
+ }
440
+ const length = data.readUInt32BE(offset);
441
+ offset += 4;
442
+ if (length === 0xffffffff) {
443
+ // End of data
444
+ dataSocket.destroy();
445
+ resolve(Buffer.concat(chunks));
446
+ return;
447
+ }
448
+ if (offset + length > data.length) {
449
+ // Incomplete record, wait for more data
450
+ break;
451
+ }
452
+ chunks.push(data.subarray(offset, offset + length));
453
+ offset += length;
454
+ }
455
+ });
456
+ dataSocket.on('end', () => {
457
+ resolve(Buffer.concat(chunks));
458
+ });
459
+ dataSocket.on('error', reject);
460
+ });
461
+ dataSocket.on('error', reject);
462
+ });
463
+ }
464
+ /**
465
+ * Map color mode to SANE mode string
466
+ */
467
+ mapColorMode(mode) {
468
+ switch (mode) {
469
+ case 'color':
470
+ return 'Color';
471
+ case 'grayscale':
472
+ return 'Gray';
473
+ case 'blackwhite':
474
+ return 'Lineart';
475
+ default:
476
+ return 'Color';
477
+ }
478
+ }
479
+ /**
480
+ * Map SANE format code to string
481
+ */
482
+ mapFormat(code) {
483
+ const formats = {
484
+ 0: 'gray',
485
+ 1: 'rgb',
486
+ 2: 'red',
487
+ 3: 'green',
488
+ 4: 'blue',
489
+ };
490
+ return formats[code] ?? 'gray';
491
+ }
492
+ /**
493
+ * Map value type code to string
494
+ */
495
+ mapValueType(code) {
496
+ const types = {
497
+ [SaneValueType.BOOL]: 'bool',
498
+ [SaneValueType.INT]: 'int',
499
+ [SaneValueType.FIXED]: 'fixed',
500
+ [SaneValueType.STRING]: 'string',
501
+ [SaneValueType.BUTTON]: 'button',
502
+ [SaneValueType.GROUP]: 'group',
503
+ };
504
+ return types[code] ?? 'int';
505
+ }
506
+ /**
507
+ * Map unit code to string
508
+ */
509
+ mapUnit(code) {
510
+ const units = {
511
+ [SaneUnit.NONE]: 'none',
512
+ [SaneUnit.PIXEL]: 'pixel',
513
+ [SaneUnit.BIT]: 'bit',
514
+ [SaneUnit.MM]: 'mm',
515
+ [SaneUnit.DPI]: 'dpi',
516
+ [SaneUnit.PERCENT]: 'percent',
517
+ [SaneUnit.MICROSECOND]: 'microsecond',
518
+ };
519
+ return units[code] ?? 'none';
520
+ }
521
+ /**
522
+ * Map constraint type code to string
523
+ */
524
+ mapConstraintType(code) {
525
+ const types = {
526
+ [SaneConstraintType.NONE]: 'none',
527
+ [SaneConstraintType.RANGE]: 'range',
528
+ [SaneConstraintType.WORD_LIST]: 'word_list',
529
+ [SaneConstraintType.STRING_LIST]: 'string_list',
530
+ };
531
+ return types[code] ?? 'none';
532
+ }
533
+ // =========================================================================
534
+ // Low-level protocol helpers
535
+ // =========================================================================
536
+ buildRequest(rpc) {
537
+ const chunks = [];
538
+ const header = Buffer.alloc(4);
539
+ header.writeUInt32BE(rpc, 0);
540
+ chunks.push(header);
541
+ return chunks;
542
+ }
543
+ writeWord(chunks, value) {
544
+ const buf = Buffer.alloc(4);
545
+ buf.writeUInt32BE(value >>> 0, 0);
546
+ chunks.push(buf);
547
+ }
548
+ writeString(chunks, str) {
549
+ const strBuf = Buffer.from(str + '\0', 'utf-8');
550
+ this.writeWord(chunks, strBuf.length);
551
+ chunks.push(strBuf);
552
+ }
553
+ async sendRequest(chunks) {
554
+ if (!this.socket) {
555
+ throw new Error('Not connected');
556
+ }
557
+ const data = Buffer.concat(chunks);
558
+ return new Promise((resolve, reject) => {
559
+ this.socket.write(data, (err) => {
560
+ if (err)
561
+ reject(err);
562
+ else
563
+ resolve();
564
+ });
565
+ });
566
+ }
567
+ async readResponse() {
568
+ // Wait for data
569
+ await this.waitForData(4);
570
+ return { buffer: this.readBuffer, offset: 0 };
571
+ }
572
+ async waitForData(minBytes) {
573
+ const startTime = Date.now();
574
+ const timeout = 30000;
575
+ while (this.readBuffer.length < minBytes) {
576
+ if (Date.now() - startTime > timeout) {
577
+ throw new Error('Timeout waiting for SANE response');
578
+ }
579
+ await plugins.smartdelay.delayFor(10);
580
+ }
581
+ }
582
+ readWord(response) {
583
+ const value = response.buffer.readUInt32BE(response.offset);
584
+ response.offset += 4;
585
+ return value;
586
+ }
587
+ readString(response) {
588
+ const length = this.readWord(response);
589
+ if (length === 0) {
590
+ return '';
591
+ }
592
+ const str = response.buffer.toString('utf-8', response.offset, response.offset + length - 1);
593
+ response.offset += length;
594
+ return str;
595
+ }
596
+ }
597
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuc2FuZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3Byb3RvY29scy9wcm90b2NvbC5zYW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBVXpDOztHQUVHO0FBQ0gsSUFBVyxPQVlWO0FBWkQsV0FBVyxPQUFPO0lBQ2hCLHFDQUFRLENBQUE7SUFDUixtREFBZSxDQUFBO0lBQ2YscUNBQVEsQ0FBQTtJQUNSLHVDQUFTLENBQUE7SUFDVCx5RUFBMEIsQ0FBQTtJQUMxQix5REFBa0IsQ0FBQTtJQUNsQix5REFBa0IsQ0FBQTtJQUNsQix1Q0FBUyxDQUFBO0lBQ1QseUNBQVUsQ0FBQTtJQUNWLCtDQUFhLENBQUE7SUFDYixzQ0FBUyxDQUFBO0FBQ1gsQ0FBQyxFQVpVLE9BQU8sS0FBUCxPQUFPLFFBWWpCO0FBRUQ7O0dBRUc7QUFDSCxJQUFXLFVBYVY7QUFiRCxXQUFXLFVBQVU7SUFDbkIsMkNBQVEsQ0FBQTtJQUNSLHlEQUFlLENBQUE7SUFDZixxREFBYSxDQUFBO0lBQ2IseURBQWUsQ0FBQTtJQUNmLDZDQUFTLENBQUE7SUFDVCx5Q0FBTyxDQUFBO0lBQ1AsK0NBQVUsQ0FBQTtJQUNWLGlEQUFXLENBQUE7SUFDWCx1REFBYyxDQUFBO0lBQ2QsbURBQVksQ0FBQTtJQUNaLGdEQUFXLENBQUE7SUFDWCw4REFBa0IsQ0FBQTtBQUNwQixDQUFDLEVBYlUsVUFBVSxLQUFWLFVBQVUsUUFhcEI7QUFFRDs7R0FFRztBQUNILElBQVcsYUFPVjtBQVBELFdBQVcsYUFBYTtJQUN0QixpREFBUSxDQUFBO0lBQ1IsK0NBQU8sQ0FBQTtJQUNQLG1EQUFTLENBQUE7SUFDVCxxREFBVSxDQUFBO0lBQ1YscURBQVUsQ0FBQTtJQUNWLG1EQUFTLENBQUE7QUFDWCxDQUFDLEVBUFUsYUFBYSxLQUFiLGFBQWEsUUFPdkI7QUFFRDs7R0FFRztBQUNILElBQVcsUUFRVjtBQVJE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LENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3BDLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLEtBQWUsQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFFRCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFFM0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN2QyxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsSUFBSSxLQUFLLGVBQWUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDOUUsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxhQUFhO1FBQ3hCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVyQyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFFM0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN2QyxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsZUFBZSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMxRSxDQUFDO1FBRUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzQyxNQUFNLE1BQU0sR0FB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