node-hp-scan-to 1.2.1 → 1.3.0

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 (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +49 -10
  3. package/dist/Destination.js +36 -84
  4. package/dist/Destination.js.map +1 -1
  5. package/dist/DeviceCapabilities.d.ts +4 -0
  6. package/dist/DeviceCapabilities.js +3 -0
  7. package/dist/DeviceCapabilities.js.map +1 -0
  8. package/dist/DiscoveryTree.d.ts +16 -0
  9. package/dist/DiscoveryTree.js +38 -0
  10. package/dist/DiscoveryTree.js.map +1 -0
  11. package/dist/Event.d.ts +1 -1
  12. package/dist/Event.js +24 -39
  13. package/dist/Event.js.map +1 -1
  14. package/dist/EventTable.d.ts +5 -0
  15. package/dist/EventTable.js +24 -18
  16. package/dist/EventTable.js.map +1 -1
  17. package/dist/HPApi.d.ts +26 -18
  18. package/dist/HPApi.js +386 -461
  19. package/dist/HPApi.js.map +1 -1
  20. package/dist/Job.d.ts +8 -7
  21. package/dist/Job.js +69 -86
  22. package/dist/Job.js.map +1 -1
  23. package/dist/JpegUtil.js +73 -82
  24. package/dist/JpegUtil.js.map +1 -1
  25. package/dist/KnownShortcut.d.ts +1 -0
  26. package/dist/KnownShortcut.js +3 -0
  27. package/dist/KnownShortcut.js.map +1 -0
  28. package/dist/PathHelper.d.ts +2 -1
  29. package/dist/PathHelper.js +41 -68
  30. package/dist/PathHelper.js.map +1 -1
  31. package/dist/ScanCaps.d.ts +7 -0
  32. package/dist/ScanCaps.js +17 -0
  33. package/dist/ScanCaps.js.map +1 -0
  34. package/dist/ScanContent.js +18 -73
  35. package/dist/ScanContent.js.map +1 -1
  36. package/dist/ScanJobManifest.d.ts +23 -0
  37. package/dist/ScanJobManifest.js +24 -0
  38. package/dist/ScanJobManifest.js.map +1 -0
  39. package/dist/ScanJobSettings.d.ts +3 -1
  40. package/dist/ScanJobSettings.js +48 -88
  41. package/dist/ScanJobSettings.js.map +1 -1
  42. package/dist/ScanStatus.d.ts +1 -0
  43. package/dist/ScanStatus.js +27 -28
  44. package/dist/ScanStatus.js.map +1 -1
  45. package/dist/WalkupScanDestination.d.ts +11 -13
  46. package/dist/WalkupScanDestination.js +32 -35
  47. package/dist/WalkupScanDestination.js.map +1 -1
  48. package/dist/WalkupScanDestinations.d.ts +1 -0
  49. package/dist/WalkupScanDestinations.js +21 -18
  50. package/dist/WalkupScanDestinations.js.map +1 -1
  51. package/dist/WalkupScanManifest.d.ts +23 -0
  52. package/dist/WalkupScanManifest.js +25 -0
  53. package/dist/WalkupScanManifest.js.map +1 -0
  54. package/dist/WalkupScanToCompCaps.d.ts +12 -0
  55. package/dist/WalkupScanToCompCaps.js +20 -0
  56. package/dist/WalkupScanToCompCaps.js.map +1 -0
  57. package/dist/WalkupScanToCompDestination.d.ts +10 -14
  58. package/dist/WalkupScanToCompDestination.js +32 -38
  59. package/dist/WalkupScanToCompDestination.js.map +1 -1
  60. package/dist/WalkupScanToCompDestinations.d.ts +1 -0
  61. package/dist/WalkupScanToCompDestinations.js +21 -18
  62. package/dist/WalkupScanToCompDestinations.js.map +1 -1
  63. package/dist/WalkupScanToCompEvent.d.ts +2 -1
  64. package/dist/WalkupScanToCompEvent.js +14 -11
  65. package/dist/WalkupScanToCompEvent.js.map +1 -1
  66. package/dist/WalkupScanToCompManifest.d.ts +23 -0
  67. package/dist/WalkupScanToCompManifest.js +25 -0
  68. package/dist/WalkupScanToCompManifest.js.map +1 -0
  69. package/dist/delay.d.ts +1 -0
  70. package/dist/delay.js +10 -0
  71. package/dist/delay.js.map +1 -0
  72. package/dist/fixJpegSize.d.ts +19 -0
  73. package/dist/fixJpegSize.js +292 -0
  74. package/dist/fixJpegSize.js.map +1 -0
  75. package/dist/index.js +209 -607
  76. package/dist/index.js.map +1 -1
  77. package/dist/listening.d.ts +9 -0
  78. package/dist/listening.js +108 -0
  79. package/dist/listening.js.map +1 -0
  80. package/dist/readDeviceCapabilities.d.ts +2 -0
  81. package/dist/readDeviceCapabilities.js +41 -0
  82. package/dist/readDeviceCapabilities.js.map +1 -0
  83. package/dist/scanProcess.d.ts +19 -0
  84. package/dist/scanProcess.js +292 -0
  85. package/dist/scanProcess.js.map +1 -0
  86. package/dist/scanProcessing.d.ts +20 -0
  87. package/dist/scanProcessing.js +320 -0
  88. package/dist/scanProcessing.js.map +1 -0
  89. package/dist/src/Destination.d.ts +8 -0
  90. package/dist/src/Destination.js +68 -0
  91. package/dist/src/Destination.js.map +1 -0
  92. package/dist/src/DiscoveryTree.d.ts +16 -0
  93. package/dist/src/DiscoveryTree.js +38 -0
  94. package/dist/src/DiscoveryTree.js.map +1 -0
  95. package/dist/src/Event.d.ts +21 -0
  96. package/dist/src/Event.js +32 -0
  97. package/dist/src/Event.js.map +1 -0
  98. package/dist/src/EventTable.d.ts +16 -0
  99. package/dist/src/EventTable.js +33 -0
  100. package/dist/src/EventTable.js.map +1 -0
  101. package/dist/src/HPApi.d.ts +50 -0
  102. package/dist/src/HPApi.js +454 -0
  103. package/dist/src/HPApi.js.map +1 -0
  104. package/dist/src/Job.d.ts +37 -0
  105. package/dist/src/Job.js +78 -0
  106. package/dist/src/Job.js.map +1 -0
  107. package/dist/src/JpegUtil.d.ts +26 -0
  108. package/dist/src/JpegUtil.js +229 -0
  109. package/dist/src/JpegUtil.js.map +1 -0
  110. package/dist/src/KnownShortcut.d.ts +1 -0
  111. package/dist/src/KnownShortcut.js +3 -0
  112. package/dist/src/KnownShortcut.js.map +1 -0
  113. package/dist/src/PathHelper.d.ts +6 -0
  114. package/dist/src/PathHelper.js +52 -0
  115. package/dist/src/PathHelper.js.map +1 -0
  116. package/dist/src/ScanCaps.d.ts +7 -0
  117. package/dist/src/ScanCaps.js +17 -0
  118. package/dist/src/ScanCaps.js.map +1 -0
  119. package/dist/src/ScanJobManifest.d.ts +23 -0
  120. package/dist/src/ScanJobManifest.js +24 -0
  121. package/dist/src/ScanJobManifest.js.map +1 -0
  122. package/dist/src/ScanJobSettings.d.ts +8 -0
  123. package/dist/src/ScanJobSettings.js +56 -0
  124. package/dist/src/ScanJobSettings.js.map +1 -0
  125. package/dist/src/ScanStatus.d.ts +19 -0
  126. package/dist/src/ScanStatus.js +35 -0
  127. package/dist/src/ScanStatus.js.map +1 -0
  128. package/dist/src/WalkupScanDestination.d.ts +22 -0
  129. package/dist/src/WalkupScanDestination.js +38 -0
  130. package/dist/src/WalkupScanDestination.js.map +1 -0
  131. package/dist/src/WalkupScanDestinations.d.ts +12 -0
  132. package/dist/src/WalkupScanDestinations.js +30 -0
  133. package/dist/src/WalkupScanDestinations.js.map +1 -0
  134. package/dist/src/WalkupScanManifest.d.ts +23 -0
  135. package/dist/src/WalkupScanManifest.js +25 -0
  136. package/dist/src/WalkupScanManifest.js.map +1 -0
  137. package/dist/src/WalkupScanToCompCaps.d.ts +12 -0
  138. package/dist/src/WalkupScanToCompCaps.js +20 -0
  139. package/dist/src/WalkupScanToCompCaps.js.map +1 -0
  140. package/dist/src/WalkupScanToCompDestination.d.ts +22 -0
  141. package/dist/src/WalkupScanToCompDestination.js +38 -0
  142. package/dist/src/WalkupScanToCompDestination.js.map +1 -0
  143. package/dist/src/WalkupScanToCompDestinations.d.ts +12 -0
  144. package/dist/src/WalkupScanToCompDestinations.js +30 -0
  145. package/dist/src/WalkupScanToCompDestinations.js.map +1 -0
  146. package/dist/src/WalkupScanToCompEvent.d.ts +11 -0
  147. package/dist/src/WalkupScanToCompEvent.js +20 -0
  148. package/dist/src/WalkupScanToCompEvent.js.map +1 -0
  149. package/dist/src/WalkupScanToCompManifest.d.ts +23 -0
  150. package/dist/src/WalkupScanToCompManifest.js +25 -0
  151. package/dist/src/WalkupScanToCompManifest.js.map +1 -0
  152. package/dist/src/delay.d.ts +1 -0
  153. package/dist/src/delay.js +10 -0
  154. package/dist/src/delay.js.map +1 -0
  155. package/dist/test/DiscoveryTree.test.d.ts +1 -0
  156. package/dist/test/DiscoveryTree.test.js +68 -0
  157. package/dist/test/DiscoveryTree.test.js.map +1 -0
  158. package/dist/test/EtagEventTable.test.d.ts +1 -0
  159. package/dist/test/EtagEventTable.test.js +93 -0
  160. package/dist/test/EtagEventTable.test.js.map +1 -0
  161. package/dist/test/Job.test.d.ts +1 -0
  162. package/dist/test/Job.test.js +104 -0
  163. package/dist/test/Job.test.js.map +1 -0
  164. package/dist/test/JpegUtil.test.d.ts +1 -0
  165. package/dist/test/JpegUtil.test.js +51 -0
  166. package/dist/test/JpegUtil.test.js.map +1 -0
  167. package/dist/test/PathHelper.test.d.ts +1 -0
  168. package/dist/test/PathHelper.test.js +99 -0
  169. package/dist/test/PathHelper.test.js.map +1 -0
  170. package/dist/test/ScanJobManifest.test.d.ts +1 -0
  171. package/dist/test/ScanJobManifest.test.js +56 -0
  172. package/dist/test/ScanJobManifest.test.js.map +1 -0
  173. package/dist/test/ScanJobSettings.test.d.ts +1 -0
  174. package/dist/test/ScanJobSettings.test.js +53 -0
  175. package/dist/test/ScanJobSettings.test.js.map +1 -0
  176. package/dist/test/ScanStatus.test.d.ts +1 -0
  177. package/dist/test/ScanStatus.test.js +75 -0
  178. package/dist/test/ScanStatus.test.js.map +1 -0
  179. package/dist/test/WalkupScanDestination.test.d.ts +1 -0
  180. package/dist/test/WalkupScanDestination.test.js +80 -0
  181. package/dist/test/WalkupScanDestination.test.js.map +1 -0
  182. package/dist/test/WalkupScanDestinations.test.d.ts +1 -0
  183. package/dist/test/WalkupScanDestinations.test.js +68 -0
  184. package/dist/test/WalkupScanDestinations.test.js.map +1 -0
  185. package/dist/test/WalkupScanManifest.test.d.ts +1 -0
  186. package/dist/test/WalkupScanManifest.test.js +46 -0
  187. package/dist/test/WalkupScanManifest.test.js.map +1 -0
  188. package/dist/test/WalkupScanToCompCaps.test.d.ts +1 -0
  189. package/dist/test/WalkupScanToCompCaps.test.js +56 -0
  190. package/dist/test/WalkupScanToCompCaps.test.js.map +1 -0
  191. package/dist/test/WalkupScanToCompDestination.test.d.ts +1 -0
  192. package/dist/test/WalkupScanToCompDestination.test.js +58 -0
  193. package/dist/test/WalkupScanToCompDestination.test.js.map +1 -0
  194. package/dist/test/WalkupScanToCompDestinations.test.d.ts +1 -0
  195. package/dist/test/WalkupScanToCompDestinations.test.js +58 -0
  196. package/dist/test/WalkupScanToCompDestinations.test.js.map +1 -0
  197. package/dist/test/WalkupScanToCompEvent.test.d.ts +1 -0
  198. package/dist/test/WalkupScanToCompEvent.test.js +46 -0
  199. package/dist/test/WalkupScanToCompEvent.test.js.map +1 -0
  200. package/dist/test/WalkupScanToCompManifest.test.d.ts +1 -0
  201. package/dist/test/WalkupScanToCompManifest.test.js +46 -0
  202. package/dist/test/WalkupScanToCompManifest.test.js.map +1 -0
  203. package/dist/test/clean.d.ts +1 -0
  204. package/dist/test/clean.js +21 -0
  205. package/dist/test/clean.js.map +1 -0
  206. package/package.json +27 -18
  207. package/src/Destination.ts +1 -1
  208. package/src/DeviceCapabilities.ts +4 -0
  209. package/src/DiscoveryTree.ts +56 -0
  210. package/src/Event.ts +17 -7
  211. package/src/EventTable.ts +20 -0
  212. package/src/HPApi.ts +245 -103
  213. package/src/Job.ts +51 -29
  214. package/src/JpegUtil.ts +8 -4
  215. package/src/KnownShortcut.ts +6 -0
  216. package/src/PathHelper.ts +47 -13
  217. package/src/ScanCaps.ts +19 -0
  218. package/src/ScanContent.ts +4 -1
  219. package/src/ScanJobManifest.ts +55 -0
  220. package/src/ScanJobSettings.ts +18 -3
  221. package/src/ScanStatus.ts +9 -0
  222. package/src/WalkupScanDestination.ts +42 -18
  223. package/src/WalkupScanDestinations.ts +12 -0
  224. package/src/WalkupScanManifest.ts +59 -0
  225. package/src/WalkupScanToCompCaps.ts +36 -0
  226. package/src/WalkupScanToCompDestination.ts +38 -24
  227. package/src/WalkupScanToCompDestinations.ts +12 -0
  228. package/src/WalkupScanToCompEvent.ts +15 -3
  229. package/src/WalkupScanToCompManifest.ts +59 -0
  230. package/src/delay.ts +5 -0
  231. package/src/index.ts +267 -465
  232. package/src/listening.ts +145 -0
  233. package/src/readDeviceCapabilities.ts +46 -0
  234. package/src/scanProcessing.ts +535 -0
  235. package/tsconfig.json +1 -1
@@ -0,0 +1,535 @@
1
+ import Event from "./Event";
2
+ import WalkupScanDestination from "./WalkupScanDestination";
3
+ import WalkupScanToCompDestination from "./WalkupScanToCompDestination";
4
+ import HPApi from "./HPApi";
5
+ import fs from "fs/promises";
6
+ import JpegUtil from "./JpegUtil";
7
+ import { DeviceCapabilities } from "./DeviceCapabilities";
8
+ import { waitForScanEvent, waitScanRequest } from "./listening";
9
+ import ScanJobSettings from "./ScanJobSettings";
10
+ import { createPdfFrom, ScanContent, ScanPage } from "./ScanContent";
11
+ import Job from "./Job";
12
+ import { delay } from "./delay";
13
+ import PathHelper from "./PathHelper";
14
+ import ScanStatus from "./ScanStatus";
15
+
16
+ async function waitDeviceUntilItIsReadyToUploadOrCompleted(
17
+ jobUrl: string
18
+ ): Promise<Job> {
19
+ let job = null;
20
+ let isReadyToUpload = false;
21
+ do {
22
+ job = await HPApi.getJob(jobUrl);
23
+ if (job.jobState === "Canceled") {
24
+ return job;
25
+ } else if (
26
+ job.pageState === "ReadyToUpload" ||
27
+ job.jobState === "Completed"
28
+ ) {
29
+ isReadyToUpload = true;
30
+ } else if (job.jobState == "Processing") {
31
+ isReadyToUpload = false;
32
+ } else {
33
+ console.log(`Unknown jobState: ${job.jobState}`);
34
+ }
35
+ await delay(300);
36
+ } while (!isReadyToUpload);
37
+ return job;
38
+ }
39
+
40
+ async function TryGetDestination(
41
+ event: Event
42
+ ): Promise<WalkupScanDestination | WalkupScanToCompDestination | null> {
43
+ //this code can in some cases be executed before the user actually chooses between Document or Photo
44
+ //so lets fetch the contentType (Document or Photo) until we get a value
45
+ let destination: WalkupScanDestination | WalkupScanToCompDestination | null =
46
+ null;
47
+
48
+ for (let i = 0; i < 20; i++) {
49
+ const destinationURI = event.destinationURI;
50
+ if (destinationURI) {
51
+ destination = await HPApi.getDestination(destinationURI);
52
+
53
+ const shortcut = destination.shortcut;
54
+ if (shortcut != null) {
55
+ return destination;
56
+ }
57
+ } else {
58
+ console.log(`No destination URI found`);
59
+ }
60
+
61
+ console.log(`No shortcut yet available, attempt: ${i + 1}/20`);
62
+ await new Promise((resolve) => setTimeout(resolve, 1000)); //wait 1s
63
+ }
64
+
65
+ console.log("Failing to detect destination shortcut");
66
+ console.log(JSON.stringify(destination));
67
+ return null;
68
+ }
69
+
70
+ async function scanProcessing(filePath: string): Promise<number | null> {
71
+ const buffer: Buffer = await fs.readFile(filePath);
72
+
73
+ let height = JpegUtil.fixSizeWithDNL(buffer);
74
+ if (height != null) {
75
+ // rewrite the fixed file
76
+ await fs.writeFile(filePath, buffer);
77
+ return height;
78
+ }
79
+ return null;
80
+ }
81
+
82
+ function createScanPage(
83
+ job: Job,
84
+ currentPageNumber: number,
85
+ filePath: string,
86
+ sizeFixed: number | null
87
+ ): ScanPage {
88
+ let height = sizeFixed ?? job.imageHeight;
89
+ return {
90
+ path: filePath,
91
+ pageNumber: currentPageNumber,
92
+ width: job.imageWidth ?? 0,
93
+ height: height ?? 0,
94
+ xResolution: job.xResolution ?? 200,
95
+ yResolution: job.yResolution ?? 200
96
+ };
97
+ }
98
+
99
+ async function handleProcessingState(
100
+ job: Job,
101
+ inputSource: "Adf" | "Platen",
102
+ folder: string,
103
+ scanCount: number,
104
+ currentPageNumber: number,
105
+ filePattern: string | undefined
106
+ ): Promise<ScanPage | null> {
107
+ if (
108
+ job.pageState == "ReadyToUpload" &&
109
+ job.binaryURL != null &&
110
+ job.currentPageNumber != null
111
+ ) {
112
+ console.log(
113
+ `Ready to download page job page ${job.currentPageNumber} at:`,
114
+ job.binaryURL
115
+ );
116
+
117
+ const destinationFilePath = PathHelper.getFileForPage(
118
+ folder,
119
+ scanCount,
120
+ currentPageNumber,
121
+ filePattern,
122
+ "jpg"
123
+ );
124
+ const filePath = await HPApi.downloadPage(
125
+ job.binaryURL,
126
+ destinationFilePath
127
+ );
128
+ console.log("Page downloaded to:", filePath);
129
+
130
+ let sizeFixed: null | number = null;
131
+ if (inputSource == "Adf") {
132
+ sizeFixed = await scanProcessing(filePath);
133
+ if (sizeFixed == null) {
134
+ console.log(
135
+ `File size has not been fixed, DNF may not have been found and approximate height is: ${job.imageHeight}`
136
+ );
137
+ }
138
+ }
139
+ return createScanPage(job, currentPageNumber, filePath, sizeFixed);
140
+ } else {
141
+ console.log(`Unknown pageState: ${job.pageState}`);
142
+ await delay(200);
143
+ return null;
144
+ }
145
+ }
146
+
147
+ async function executeScanJob(
148
+ scanJobSettings: ScanJobSettings,
149
+ inputSource: "Adf" | "Platen",
150
+ folder: string,
151
+ scanCount: number,
152
+ scanJobContent: ScanContent,
153
+ filePattern: string | undefined
154
+ ): Promise<"Completed" | "Canceled"> {
155
+ const jobUrl = await HPApi.postJob(scanJobSettings);
156
+
157
+ console.log("New job created:", jobUrl);
158
+
159
+ let job = await HPApi.getJob(jobUrl);
160
+ while (job.jobState !== "Completed") {
161
+ job = await waitDeviceUntilItIsReadyToUploadOrCompleted(jobUrl);
162
+
163
+ if (job.jobState == "Completed") {
164
+ continue;
165
+ }
166
+
167
+ if (job.jobState === "Processing") {
168
+ const page = await handleProcessingState(
169
+ job,
170
+ inputSource,
171
+ folder,
172
+ scanCount,
173
+ scanJobContent.elements.length + 1,
174
+ filePattern
175
+ );
176
+ job = await HPApi.getJob(jobUrl);
177
+ if (page != null && job.jobState != "Canceled") {
178
+ scanJobContent.elements.push(page);
179
+ }
180
+ } else if (job.jobState === "Canceled") {
181
+ console.log("Job cancelled by device");
182
+ break;
183
+ } else {
184
+ console.log(`Unhandled jobState: ${job.jobState}`);
185
+ await delay(200);
186
+ }
187
+ }
188
+ console.log(
189
+ `Job state: ${job.jobState}, totalPages: ${scanJobContent.elements.length}:`
190
+ );
191
+ return job.jobState;
192
+ }
193
+
194
+ async function waitScanNewPageRequest(compEventURI: string): Promise<boolean> {
195
+ let startNewScanJob = false;
196
+ let wait = true;
197
+ while (wait) {
198
+ await new Promise((resolve) => setTimeout(resolve, 1000)); //wait 1s
199
+
200
+ let walkupScanToCompEvent = await HPApi.getWalkupScanToCompEvent(
201
+ compEventURI
202
+ );
203
+ let message = walkupScanToCompEvent.eventType;
204
+
205
+ if (message === "ScanNewPageRequested") {
206
+ startNewScanJob = true;
207
+ wait = false;
208
+ } else if (message === "ScanPagesComplete") {
209
+ wait = false;
210
+ } else if (message === "ScanRequested") {
211
+ // continue waiting
212
+ } else {
213
+ wait = false;
214
+ console.log(`Unknown eventType: ${message}`);
215
+ }
216
+ }
217
+ return startNewScanJob;
218
+ }
219
+
220
+ async function executeScanJobs(
221
+ scanJobSettings: ScanJobSettings,
222
+ inputSource: "Adf" | "Platen",
223
+ folder: string,
224
+ scanCount: number,
225
+ scanJobContent: ScanContent,
226
+ firstEvent: Event,
227
+ deviceCapabilities: DeviceCapabilities,
228
+ filePattern: string | undefined
229
+ ) {
230
+ let jobState = await executeScanJob(
231
+ scanJobSettings,
232
+ inputSource,
233
+ folder,
234
+ scanCount,
235
+ scanJobContent,
236
+ filePattern
237
+ );
238
+ let lastEvent = firstEvent;
239
+ if (
240
+ jobState === "Completed" &&
241
+ lastEvent.compEventURI &&
242
+ inputSource !== "Adf" &&
243
+ lastEvent.destinationURI &&
244
+ deviceCapabilities.supportsMultiItemScanFromPlaten
245
+ ) {
246
+ lastEvent = await waitForScanEvent(
247
+ lastEvent.destinationURI,
248
+ lastEvent.agingStamp
249
+ );
250
+ if (!lastEvent.compEventURI) {
251
+ return;
252
+ }
253
+ let startNewScanJob = await waitScanNewPageRequest(lastEvent.compEventURI);
254
+ while (startNewScanJob) {
255
+ jobState = await executeScanJob(
256
+ scanJobSettings,
257
+ inputSource,
258
+ folder,
259
+ scanCount,
260
+ scanJobContent,
261
+ filePattern
262
+ );
263
+ if (jobState !== "Completed") {
264
+ return;
265
+ }
266
+ if (!lastEvent.destinationURI) {
267
+ break;
268
+ }
269
+ lastEvent = await waitForScanEvent(
270
+ lastEvent.destinationURI,
271
+ lastEvent.agingStamp
272
+ );
273
+ if (!lastEvent.compEventURI) {
274
+ return;
275
+ }
276
+ startNewScanJob = await waitScanNewPageRequest(lastEvent.compEventURI);
277
+ }
278
+ }
279
+ }
280
+
281
+ async function mergeToPdf(
282
+ folder: string,
283
+ scanCount: number,
284
+ scanJobContent: ScanContent,
285
+ filePattern: string | undefined
286
+ ): Promise<string | null> {
287
+ if (scanJobContent.elements.length > 0) {
288
+ const pdfFilePath = PathHelper.getFileForScan(
289
+ folder,
290
+ scanCount,
291
+ filePattern,
292
+ "pdf"
293
+ );
294
+ await createPdfFrom(scanJobContent, pdfFilePath);
295
+ scanJobContent.elements.forEach((e) => fs.unlink(e.path));
296
+ return pdfFilePath;
297
+ }
298
+ console.log(`No page available to build a pdf file`);
299
+ return null;
300
+ }
301
+
302
+ function displayPdfScan(
303
+ pdfFilePath: string | null,
304
+ scanJobContent: ScanContent
305
+ ) {
306
+ if (pdfFilePath === null) {
307
+ console.log(`Pdf generated has not been generated`);
308
+ return;
309
+ }
310
+ console.log(
311
+ `The following page(s) have been rendered inside '${pdfFilePath}': `
312
+ );
313
+ scanJobContent.elements.forEach((e) =>
314
+ console.log(
315
+ `\t- page ${e.pageNumber.toString().padStart(3, " ")} - ${e.width}x${
316
+ e.height
317
+ }`
318
+ )
319
+ );
320
+ }
321
+
322
+ function displayJpegScan(scanJobContent: ScanContent) {
323
+ scanJobContent.elements.forEach((e) =>
324
+ console.log(
325
+ `\t- page ${e.pageNumber.toString().padStart(3, " ")} - ${e.width}x${
326
+ e.height
327
+ } - ${e.path}`
328
+ )
329
+ );
330
+ }
331
+
332
+ function isPdf(
333
+ destination: WalkupScanDestination | WalkupScanToCompDestination
334
+ ) {
335
+ if (
336
+ destination.shortcut === "SavePDF" ||
337
+ destination.shortcut === "EmailPDF" ||
338
+ destination.shortcut == "SaveDocument1"
339
+ ) {
340
+ return true;
341
+ } else if (
342
+ destination.shortcut === "SaveJPEG" ||
343
+ destination.shortcut === "SavePhoto1"
344
+ ) {
345
+ return false;
346
+ } else {
347
+ console.log(
348
+ `Unexpected shortcut received: ${destination.shortcut}, considering it as non pdf target!`
349
+ );
350
+ return false;
351
+ }
352
+ }
353
+
354
+ export async function saveScan(
355
+ event: Event,
356
+ folder: string,
357
+ tempFolder: string,
358
+ scanCount: number,
359
+ deviceCapabilities: DeviceCapabilities,
360
+ scanConfig: ScanConfig
361
+ ): Promise<void> {
362
+ if (event.compEventURI) {
363
+ const proceedToScan = await waitScanRequest(event.compEventURI);
364
+ if (!proceedToScan) {
365
+ return;
366
+ }
367
+ }
368
+
369
+ const destination = await TryGetDestination(event);
370
+ if (!destination) {
371
+ console.log("No shortcut selected!");
372
+ return;
373
+ }
374
+ console.log("Selected shortcut: " + destination.shortcut);
375
+
376
+ let toPdf: boolean;
377
+ let destinationFolder: string;
378
+ let contentType: "Document" | "Photo";
379
+ if (isPdf(destination)) {
380
+ toPdf = true;
381
+ contentType = "Document";
382
+ destinationFolder = tempFolder;
383
+ console.log(
384
+ `Scan will be converted to pdf, using ${destinationFolder} as temp scan output directory for individual pages`
385
+ );
386
+ } else {
387
+ toPdf = false;
388
+ contentType = "Photo";
389
+ destinationFolder = folder;
390
+ }
391
+
392
+ const isDuplex =
393
+ destination.scanPlexMode != null && destination.scanPlexMode != "Simplex";
394
+ console.log("ScanPlexMode is : " + destination.scanPlexMode);
395
+
396
+ const scanStatus = await HPApi.getScanStatus();
397
+ console.log("Afd is : " + scanStatus.adfState);
398
+
399
+ const inputSource = scanStatus.getInputSource();
400
+
401
+ const scanJobSettings = new ScanJobSettings(
402
+ inputSource,
403
+ contentType,
404
+ scanConfig.resolution,
405
+ isDuplex
406
+ );
407
+
408
+ const scanJobContent: ScanContent = { elements: [] };
409
+
410
+ await executeScanJobs(
411
+ scanJobSettings,
412
+ inputSource,
413
+ destinationFolder,
414
+ scanCount,
415
+ scanJobContent,
416
+ event,
417
+ deviceCapabilities,
418
+ scanConfig.directoryConfig.filePattern
419
+ );
420
+
421
+ console.log(
422
+ `Scan of page(s) completed totalPages: ${scanJobContent.elements.length}:`
423
+ );
424
+
425
+ if (toPdf) {
426
+ const pdfFilePath = await mergeToPdf(
427
+ folder,
428
+ scanCount,
429
+ scanJobContent,
430
+ scanConfig.directoryConfig.filePattern
431
+ );
432
+ displayPdfScan(pdfFilePath, scanJobContent);
433
+ } else {
434
+ displayJpegScan(scanJobContent);
435
+ }
436
+ }
437
+
438
+ export type DirectoryConfig = {
439
+ directory: string | undefined;
440
+ tempDirectory: string | undefined;
441
+ filePattern: string | undefined;
442
+ };
443
+ export type ScanConfig = {
444
+ resolution: number;
445
+ directoryConfig: DirectoryConfig;
446
+ };
447
+ export type AdfAutoScanConfig = ScanConfig & {
448
+ isDuplex: boolean;
449
+ generatePdf: boolean;
450
+ pollingInterval: number;
451
+ startScanDelay: number;
452
+ };
453
+
454
+ export async function scanFromAdf(
455
+ scanCount: number,
456
+ folder: string,
457
+ tempFolder: string,
458
+ adfAutoScanConfig: AdfAutoScanConfig
459
+ ) {
460
+ let destinationFolder: string;
461
+ let contentType: "Document" | "Photo";
462
+ if (adfAutoScanConfig.generatePdf) {
463
+ contentType = "Document";
464
+ destinationFolder = tempFolder;
465
+ console.log(
466
+ `Scan will be converted to pdf, using ${destinationFolder} as temp scan output directory for individual pages`
467
+ );
468
+ } else {
469
+ contentType = "Photo";
470
+ destinationFolder = folder;
471
+ }
472
+
473
+ const scanJobSettings = new ScanJobSettings(
474
+ "Adf",
475
+ contentType,
476
+ adfAutoScanConfig.resolution,
477
+ adfAutoScanConfig.isDuplex
478
+ );
479
+
480
+ const scanJobContent: ScanContent = { elements: [] };
481
+
482
+ await executeScanJob(
483
+ scanJobSettings,
484
+ "Adf",
485
+ destinationFolder,
486
+ scanCount,
487
+ scanJobContent,
488
+ adfAutoScanConfig.directoryConfig.filePattern
489
+ );
490
+
491
+ console.log(
492
+ `Scan of page(s) completed totalPages: ${scanJobContent.elements.length}:`
493
+ );
494
+
495
+ if (adfAutoScanConfig.generatePdf) {
496
+ const pdfFilePath = await mergeToPdf(
497
+ folder,
498
+ scanCount,
499
+ scanJobContent,
500
+ adfAutoScanConfig.directoryConfig.filePattern
501
+ );
502
+ displayPdfScan(pdfFilePath, scanJobContent);
503
+ } else {
504
+ displayJpegScan(scanJobContent);
505
+ }
506
+ }
507
+
508
+ export async function waitAdfLoaded(pollingInterval: number, startScanDelay: number) {
509
+ let ready = false;
510
+ while (!ready) {
511
+ let scanStatus: ScanStatus = await HPApi.getScanStatus();
512
+ while (!scanStatus.isLoaded()) {
513
+ await delay(pollingInterval);
514
+ scanStatus = await HPApi.getScanStatus();
515
+ }
516
+ console.log(`ADF load detected`);
517
+
518
+ let loaded = true;
519
+ let counter = 0;
520
+ const shortPollingInterval = 500;
521
+ while (loaded && counter < startScanDelay) {
522
+ await delay(shortPollingInterval);
523
+ scanStatus = await HPApi.getScanStatus();
524
+ loaded = scanStatus.isLoaded();
525
+ counter += shortPollingInterval;
526
+ }
527
+
528
+ if (loaded && counter >= startScanDelay) {
529
+ ready = true;
530
+ console.log(`ADF still loaded, proceeding`);
531
+ } else {
532
+ console.log(`ADF not loaded anymore, waiting...`);
533
+ }
534
+ }
535
+ }
package/tsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "outDir": "dist",
4
4
  "module": "commonjs",
5
- "target": "es5",
5
+ "target": "es2019",
6
6
  "noImplicitAny": true,
7
7
  "sourceMap": true,
8
8
  "inlineSources": true,