From ec1cdfbbe6c263cb3605597929289ef52d096df2 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 13:58:52 +0000 Subject: [PATCH 01/13] Fix copy/paste errors in determination of height --- src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index c7995723..4a0089ca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -424,9 +424,9 @@ function getScanConfiguration(option: OptionValues) { ? Number.MAX_SAFE_INTEGER : parseInt(configWidth, 10); - const configHeight = (option.width || getConfig("height") || "0").toString(); + const configHeight = (option.height || getConfig("height") || 0).toString(); const height = - configWidth.toLowerCase() === "max" + configHeight.toLowerCase() === "max" ? Number.MAX_SAFE_INTEGER : parseInt(configHeight, 10); From 4a4dd8bf2fe45a8ce519e182668127606b3852b7 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 14:46:02 +0000 Subject: [PATCH 02/13] Add duplex max dimensions to ScanCaps and DeviceCapabilities --- src/DeviceCapabilities.ts | 2 ++ src/ScanCaps.ts | 32 ++++++++++++++++++++++++++++++++ src/readDeviceCapabilities.ts | 2 ++ 3 files changed, 36 insertions(+) diff --git a/src/DeviceCapabilities.ts b/src/DeviceCapabilities.ts index 1c53d151..78b5a0f0 100644 --- a/src/DeviceCapabilities.ts +++ b/src/DeviceCapabilities.ts @@ -5,4 +5,6 @@ export interface DeviceCapabilities { platenMaxHeight: number | null; adfMaxWidth: number | null; adfMaxHeight: number | null; + adfDuplexMaxWidth: number | null; + adfDuplexMaxHeight: number | null; } diff --git a/src/ScanCaps.ts b/src/ScanCaps.ts index 55ef077b..3667b0e3 100644 --- a/src/ScanCaps.ts +++ b/src/ScanCaps.ts @@ -17,6 +17,10 @@ export interface ScanCapsData { MaxWidth: string[]; MaxHeight: string[]; }[]; + AdfDuplexer: { + AdfDuplexMaxWidth: string[]; + AdfDuplexMaxHeight: string[]; + }[]; }[]; }; } @@ -78,4 +82,32 @@ export default class ScanCaps { return null; } } + + get adfDuplexMaxWidth(): number | null { + if ( + Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf")) + && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"], "AdfDuplexer") + ) { + return Number.parseInt( + this.data["ScanCaps"]["Adf"][0]["AdfDuplexer"][0]["AdfDuplexMaxWidth"][0], + 10, + ); + } else { + return this.adfMaxWidth; + } + } + + get adfDuplexMaxHeight(): number | null { + if ( + Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf")) + && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"], "AdfDuplexer") + ) { + return Number.parseInt( + this.data["ScanCaps"]["Adf"][0]["AdfDuplexer"][0]["AdfDuplexMaxHeight"][0], + 10, + ); + } else { + return this.adfMaxHeight; + } + } } diff --git a/src/readDeviceCapabilities.ts b/src/readDeviceCapabilities.ts index 6a36deab..369ba221 100644 --- a/src/readDeviceCapabilities.ts +++ b/src/readDeviceCapabilities.ts @@ -48,5 +48,7 @@ export async function readDeviceCapabilities(): Promise { platenMaxHeight: scanCaps?.platenMaxHeight || null, adfMaxWidth: scanCaps?.adfMaxWidth || null, adfMaxHeight: scanCaps?.adfMaxHeight || null, + adfDuplexMaxWidth: scanCaps?.adfDuplexMaxWidth || null, + adfDuplexMaxHeight: scanCaps?.adfDUplexMaxHeight || null, }; } From 3978a7d70e2d161c3f787861acc1a1237a84257b Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 14:52:41 +0000 Subject: [PATCH 03/13] Add example XML with ADF duplexer --- test/asset/ScanCaps_duplex_adf.xml | 216 +++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 test/asset/ScanCaps_duplex_adf.xml diff --git a/test/asset/ScanCaps_duplex_adf.xml b/test/asset/ScanCaps_duplex_adf.xml new file mode 100644 index 00000000..7b1ba2bc --- /dev/null +++ b/test/asset/ScanCaps_duplex_adf.xml @@ -0,0 +1,216 @@ + + + + + HP OfficeJet Pro 9010 series + 58 + + + + K1 + + Raw + + + ToneMap + Sharpening + BwThreshold + + + + Gray8 + + Raw + Jpeg + + + ToneMap + Sharpening + + + + Color8 + + Raw + Jpeg + + + ToneMap + Sharpening + + + + + + 8 + 8 + 2550 + 3534 + 30 + 30 + 30 + 44 + 75 + 1200 + 1200 + + + 75 + 75 + 1 + + K1 + Gray8 + Color8 + + + + 100 + 100 + 1 + + K1 + Gray8 + Color8 + + + + 150 + 150 + 1 + + K1 + Gray8 + Color8 + + + + 200 + 200 + 1 + + K1 + Gray8 + Color8 + + + + 300 + 300 + 1 + + K1 + Gray8 + Color8 + + + + 400 + 400 + 1 + + K1 + Gray8 + Color8 + + + + 600 + 600 + 1 + + K1 + Gray8 + Color8 + + + + 1200 + 1200 + 1 + + K1 + Gray8 + Color8 + + + + + + + + 8 + 8 + 2550 + 4200 + 16 + 0 + 35 + 35 + 75 + 300 + 300 + + + 75 + 75 + 1 + + K1 + Gray8 + Color8 + + + + 100 + 100 + 1 + + K1 + Gray8 + Color8 + + + + 150 + 150 + 1 + + K1 + Gray8 + Color8 + + + + 200 + 200 + 1 + + K1 + Gray8 + Color8 + + + + 300 + 300 + 1 + + K1 + Gray8 + Color8 + + + + + 35 + + 2550 + 3508 + + + DetectPaperLoaded + Duplex + + + From b6579f5814c66c6a1fa9da3500d90d8ebbe400ca Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 15:05:18 +0000 Subject: [PATCH 04/13] Fix detection of ADF duplexer --- src/ScanCaps.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScanCaps.ts b/src/ScanCaps.ts index 3667b0e3..4a680d5a 100644 --- a/src/ScanCaps.ts +++ b/src/ScanCaps.ts @@ -85,7 +85,7 @@ export default class ScanCaps { get adfDuplexMaxWidth(): number | null { if ( - Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf")) + Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf") && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"], "AdfDuplexer") ) { return Number.parseInt( @@ -99,7 +99,7 @@ export default class ScanCaps { get adfDuplexMaxHeight(): number | null { if ( - Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf")) + Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf") && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"], "AdfDuplexer") ) { return Number.parseInt( From da7774b10c5a15261ebe6b6b5938e480ca4fe867 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 15:19:34 +0000 Subject: [PATCH 05/13] Add tests for caps parsing --- test/ScanCaps.test.ts | 51 +++++++++++++++++++ ...x_adf.xml => ScanCaps_with_duplex_adf.xml} | 4 +- test/scanProcessing.test.ts | 2 + 3 files changed, 55 insertions(+), 2 deletions(-) rename test/asset/{ScanCaps_duplex_adf.xml => ScanCaps_with_duplex_adf.xml} (97%) diff --git a/test/ScanCaps.test.ts b/test/ScanCaps.test.ts index e6ab96f5..62d25938 100644 --- a/test/ScanCaps.test.ts +++ b/test/ScanCaps.test.ts @@ -25,6 +25,12 @@ describe("ScanCaps", () => { it("AdfMaxHeight", async () => { expect(scanCaps.adfMaxHeight).to.be.eq(4200); }); + it("AdfDuplexMaxWidth", async () => { + expect(scanCaps.adfDuplexMaxWidth).to.be.eq(2550); + }); + it("AdfDuplexMaxHeight", async () => { + expect(scanCaps.adfDuplexMaxHeight).to.be.eq(4200); + }); it("PlatenMaxWidth", async () => { expect(scanCaps.platenMaxWidth).to.be.eq(2550); }); @@ -52,6 +58,12 @@ describe("ScanCaps", () => { it("AdfMaxHeight", async () => { expect(scanCaps.adfMaxHeight).to.be.eq(null); }); + it("AdfDuplexMaxWidth", async () => { + expect(scanCaps.adfDuplexMaxWidth).to.be.eq(null); + }); + it("AdfDuplexMaxHeight", async () => { + expect(scanCaps.adfDuplexMaxHeight).to.be.eq(null); + }); it("PlatenMaxWidth", async () => { expect(scanCaps.platenMaxWidth).to.be.eq(2550); }); @@ -79,6 +91,12 @@ describe("ScanCaps", () => { it("AdfMaxHeight", async () => { expect(scanCaps.adfMaxHeight).to.be.eq(5100); }); + it("AdfDuplexMaxWidth", async () => { + expect(scanCaps.adfDuplexMaxWidth).to.be.eq(2550); + }); + it("AdfDuplexMaxHeight", async () => { + expect(scanCaps.adfDuplexMaxHeight).to.be.eq(5100); + }); it("PlatenMaxWidth", async () => { expect(scanCaps.platenMaxWidth).to.be.eq(null); }); @@ -86,4 +104,37 @@ describe("ScanCaps", () => { expect(scanCaps.platenMaxHeight).to.be.eq(null); }); }); + describe("Parsing ScanCaps_with_duplex_adf.xml", async () => { + let scanCaps: ScanCaps; + + before(async () => { + const content: string = await fs.readFile( + path.resolve( + __dirname, + "./asset/ScanCaps_with_duplex_adf.xml" + ), + { encoding: "utf8" } // + ); + scanCaps = await ScanCaps.createScanCaps(content); + }); + + it("AdfMaxWidth", async () => { + expect(scanCaps.adfMaxWidth).to.be.eq(2550); + }); + it("AdfMaxHeight", async () => { + expect(scanCaps.adfMaxHeight).to.be.eq(4200); + }); + it("AdfDuplexMaxWidth", async () => { + expect(scanCaps.adfDuplexMaxWidth).to.be.eq(2550); + }); + it("AdfDuplexMaxHeight", async () => { + expect(scanCaps.adfDuplexMaxHeight).to.be.eq(3508); + }); + it("PlatenMaxWidth", async () => { + expect(scanCaps.platenMaxWidth).to.be.eq(2550); + }); + it("PlatenMaxHeight", async () => { + expect(scanCaps.platenMaxHeight).to.be.eq(3534); + }); + }); }); diff --git a/test/asset/ScanCaps_duplex_adf.xml b/test/asset/ScanCaps_with_duplex_adf.xml similarity index 97% rename from test/asset/ScanCaps_duplex_adf.xml rename to test/asset/ScanCaps_with_duplex_adf.xml index 7b1ba2bc..c264ed5e 100644 --- a/test/asset/ScanCaps_duplex_adf.xml +++ b/test/asset/ScanCaps_with_duplex_adf.xml @@ -1,6 +1,6 @@ - + - + HP OfficeJet Pro 9010 series 58 diff --git a/test/scanProcessing.test.ts b/test/scanProcessing.test.ts index ea256e82..ac9be98d 100644 --- a/test/scanProcessing.test.ts +++ b/test/scanProcessing.test.ts @@ -32,6 +32,8 @@ describe("scanProcessing", () => { platenMaxHeight: null, adfMaxWidth: null, adfMaxHeight: null, + adfDuplexMaxWidth: null, + adfDuplexMaxHeight: null, }; }); From e84a65a0780066dfc3f80b581da5cad6c3c78270 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 15:20:47 +0000 Subject: [PATCH 06/13] Fix check for presence of ADF duplexer --- src/ScanCaps.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScanCaps.ts b/src/ScanCaps.ts index 4a680d5a..378d339d 100644 --- a/src/ScanCaps.ts +++ b/src/ScanCaps.ts @@ -86,7 +86,7 @@ export default class ScanCaps { get adfDuplexMaxWidth(): number | null { if ( Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf") - && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"], "AdfDuplexer") + && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"][0], "AdfDuplexer") ) { return Number.parseInt( this.data["ScanCaps"]["Adf"][0]["AdfDuplexer"][0]["AdfDuplexMaxWidth"][0], @@ -100,7 +100,7 @@ export default class ScanCaps { get adfDuplexMaxHeight(): number | null { if ( Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf") - && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"], "AdfDuplexer") + && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"][0], "AdfDuplexer") ) { return Number.parseInt( this.data["ScanCaps"]["Adf"][0]["AdfDuplexer"][0]["AdfDuplexMaxHeight"][0], From 26de2893b1aca2feb750883f682eab0591ab3faa Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 15:41:14 +0000 Subject: [PATCH 07/13] Take duplex state into account when calculating dimensions --- src/scanProcessing.ts | 36 ++++++++++++++++++------------------ test/scanProcessing.test.ts | 24 ++++++++++++------------ 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/scanProcessing.ts b/src/scanProcessing.ts index 93e044b1..30283e49 100644 --- a/src/scanProcessing.ts +++ b/src/scanProcessing.ts @@ -310,22 +310,21 @@ export function getScanWidth( scanConfig: ScanConfig, inputSource: InputSource, deviceCapabilities: DeviceCapabilities, + isDuplex: boolean, ): number | null { - if (scanConfig.width && scanConfig.width > 0) { - const maxWidth = - inputSource === InputSource.Adf - ? deviceCapabilities.adfMaxWidth - : deviceCapabilities.platenMaxWidth; + const maxWidth = + inputSource === InputSource.Adf + ? (isDuplex ? deviceCapabilities.adfDuplexMaxWidth : deviceCapabilities.adfMaxWidth) + : deviceCapabilities.platenMaxWidth; + if (scanConfig.width && scanConfig.width > 0) { if (maxWidth && scanConfig.width > maxWidth) { return maxWidth; } else { return scanConfig.width; } } else { - return inputSource === InputSource.Adf - ? deviceCapabilities.adfMaxWidth - : deviceCapabilities.platenMaxWidth; + return maxWidth; } } @@ -333,22 +332,21 @@ export function getScanHeight( scanConfig: ScanConfig, inputSource: InputSource, deviceCapabilities: DeviceCapabilities, + isDuplex: boolean, ): number | null { - if (scanConfig.height && scanConfig.height > 0) { - const maxHeight = - inputSource === InputSource.Adf - ? deviceCapabilities.adfMaxHeight - : deviceCapabilities.platenMaxHeight; + const maxHeight = + inputSource === InputSource.Adf + ? (isDuplex ? deviceCapabilities.adfDuplexMaxHeight : deviceCapabilities.adfMaxHeight) + : deviceCapabilities.platenMaxHeight; + if (scanConfig.height && scanConfig.height > 0) { if (maxHeight && scanConfig.height > maxHeight) { return maxHeight; } else { return scanConfig.height; } } else { - return inputSource === InputSource.Adf - ? deviceCapabilities.adfMaxHeight - : deviceCapabilities.platenMaxHeight; + return maxHeight; } } @@ -403,8 +401,8 @@ export async function saveScanFromEvent( console.log("Afd is : " + scanStatus.adfState); const inputSource = scanStatus.getInputSource(); - const scanWidth = getScanWidth(scanConfig, inputSource, deviceCapabilities); - const scanHeight = getScanHeight(scanConfig, inputSource, deviceCapabilities); + const scanWidth = getScanWidth(scanConfig, inputSource, deviceCapabilities, isDuplex); + const scanHeight = getScanHeight(scanConfig, inputSource, deviceCapabilities, isDuplex); const scanJobSettings = new ScanJobSettings( inputSource, @@ -495,11 +493,13 @@ export async function scanFromAdf( adfAutoScanConfig, InputSource.Adf, deviceCapabilities, + adfAutoScanConfig.isDuplex, ); const scanHeight = getScanHeight( adfAutoScanConfig, InputSource.Adf, deviceCapabilities, + adfAutoScanConfig.isDuplex, ); const scanJobSettings = new ScanJobSettings( diff --git a/test/scanProcessing.test.ts b/test/scanProcessing.test.ts index ac9be98d..029ac379 100644 --- a/test/scanProcessing.test.ts +++ b/test/scanProcessing.test.ts @@ -41,34 +41,34 @@ describe("scanProcessing", () => { const inputSource = InputSource.Adf; describe("Adf", async () => { it("Does not define a value if nothing provided", async () => { - const width = getScanWidth(scanConfig, inputSource, deviceCapabilities); + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(null); }); it("Does not define a value if negative provided", async () => { scanConfig.width = -1; - const width = getScanWidth(scanConfig, inputSource, deviceCapabilities); + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(null); }); it("Define the value if no max available from device", async () => { scanConfig.width = 2583; - const width = getScanWidth(scanConfig, inputSource, deviceCapabilities); + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(2583); }); }); describe("Platen", async () => { const inputSource = InputSource.Platen; it("Does not define a value if nothing provided", async () => { - const width = getScanWidth(scanConfig, inputSource, deviceCapabilities); + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(null); }); it("Does not define a value if negative provided", async () => { scanConfig.width = -1; - const width = getScanWidth(scanConfig, inputSource, deviceCapabilities); + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(null); }); it("Define the value if no max available from device", async () => { scanConfig.width = 2583; - const width = getScanWidth(scanConfig, inputSource, deviceCapabilities); + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(2583); }); }); @@ -78,34 +78,34 @@ describe("scanProcessing", () => { const inputSource = InputSource.Adf; describe("Adf", async () => { it("Does not define a value if nothing provided", async () => { - const height = getScanHeight(scanConfig, inputSource, deviceCapabilities); + const height = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); expect(height).to.be.eq(null); }); it("Does not define a value if negative provided", async () => { scanConfig.height = -1; - const height = getScanHeight(scanConfig, inputSource, deviceCapabilities); + const height = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); expect(height).to.be.eq(null); }); it("Define the value if no max available from device", async () => { scanConfig.height = 1269; - const width = getScanHeight(scanConfig, inputSource, deviceCapabilities); + const width = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(1269); }); }); describe("Platen", async () => { const inputSource = InputSource.Platen; it("Does not define a value if nothing provided", async () => { - const height = getScanHeight(scanConfig, inputSource, deviceCapabilities); + const height = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); expect(height).to.be.eq(null); }); it("Does not define a value if negative provided", async () => { scanConfig.height = -1; - const height = getScanHeight(scanConfig, inputSource, deviceCapabilities); + const height = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); expect(height).to.be.eq(null); }); it("Define the value if no max available from device", async () => { scanConfig.height = 1269; - const height = getScanHeight(scanConfig, inputSource, deviceCapabilities); + const height = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); expect(height).to.be.eq(1269); }); }); From 4f88d0a79657b5ace5f1f3cb5c0c0f4679b85a24 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 15:44:16 +0000 Subject: [PATCH 08/13] Run prettier --- src/ScanCaps.ts | 22 ++++++++++++++++------ src/scanProcessing.ts | 22 ++++++++++++++++++---- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/ScanCaps.ts b/src/ScanCaps.ts index 378d339d..9f892c93 100644 --- a/src/ScanCaps.ts +++ b/src/ScanCaps.ts @@ -85,11 +85,16 @@ export default class ScanCaps { get adfDuplexMaxWidth(): number | null { if ( - Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf") - && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"][0], "AdfDuplexer") + Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf") && + Object.prototype.hasOwnProperty.call( + this.data["ScanCaps"]["Adf"][0], + "AdfDuplexer", + ) ) { return Number.parseInt( - this.data["ScanCaps"]["Adf"][0]["AdfDuplexer"][0]["AdfDuplexMaxWidth"][0], + this.data["ScanCaps"]["Adf"][0]["AdfDuplexer"][0][ + "AdfDuplexMaxWidth" + ][0], 10, ); } else { @@ -99,11 +104,16 @@ export default class ScanCaps { get adfDuplexMaxHeight(): number | null { if ( - Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf") - && Object.prototype.hasOwnProperty.call(this.data["ScanCaps"]["Adf"][0], "AdfDuplexer") + Object.prototype.hasOwnProperty.call(this.data["ScanCaps"], "Adf") && + Object.prototype.hasOwnProperty.call( + this.data["ScanCaps"]["Adf"][0], + "AdfDuplexer", + ) ) { return Number.parseInt( - this.data["ScanCaps"]["Adf"][0]["AdfDuplexer"][0]["AdfDuplexMaxHeight"][0], + this.data["ScanCaps"]["Adf"][0]["AdfDuplexer"][0][ + "AdfDuplexMaxHeight" + ][0], 10, ); } else { diff --git a/src/scanProcessing.ts b/src/scanProcessing.ts index 30283e49..f5b0f7f2 100644 --- a/src/scanProcessing.ts +++ b/src/scanProcessing.ts @@ -314,7 +314,9 @@ export function getScanWidth( ): number | null { const maxWidth = inputSource === InputSource.Adf - ? (isDuplex ? deviceCapabilities.adfDuplexMaxWidth : deviceCapabilities.adfMaxWidth) + ? isDuplex + ? deviceCapabilities.adfDuplexMaxWidth + : deviceCapabilities.adfMaxWidth : deviceCapabilities.platenMaxWidth; if (scanConfig.width && scanConfig.width > 0) { @@ -336,7 +338,9 @@ export function getScanHeight( ): number | null { const maxHeight = inputSource === InputSource.Adf - ? (isDuplex ? deviceCapabilities.adfDuplexMaxHeight : deviceCapabilities.adfMaxHeight) + ? isDuplex + ? deviceCapabilities.adfDuplexMaxHeight + : deviceCapabilities.adfMaxHeight : deviceCapabilities.platenMaxHeight; if (scanConfig.height && scanConfig.height > 0) { @@ -401,8 +405,18 @@ export async function saveScanFromEvent( console.log("Afd is : " + scanStatus.adfState); const inputSource = scanStatus.getInputSource(); - const scanWidth = getScanWidth(scanConfig, inputSource, deviceCapabilities, isDuplex); - const scanHeight = getScanHeight(scanConfig, inputSource, deviceCapabilities, isDuplex); + const scanWidth = getScanWidth( + scanConfig, + inputSource, + deviceCapabilities, + isDuplex, + ); + const scanHeight = getScanHeight( + scanConfig, + inputSource, + deviceCapabilities, + isDuplex, + ); const scanJobSettings = new ScanJobSettings( inputSource, From 5adc2cca83a66d3a262fb66b83dc0aa0c81136b7 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 15:45:47 +0000 Subject: [PATCH 09/13] Add tested printer --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3c4f9eb2..6c0a1a93 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ It has been developed and tested with the following HP All-in-One Printers: - HP DeskJet 3520 - HP OfficeJet 6500A Plus - HP Smart Tank Plus 570 series +- HP OfficeJet Pro 9019e Additionally, it has been reported to work on several other HP printer models. - HP DeskJet 3050 All-in-One - J610a From 992887ce1ea53595f9d5085032d000abd8347227 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 15:49:02 +0000 Subject: [PATCH 10/13] Fix typo --- src/readDeviceCapabilities.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/readDeviceCapabilities.ts b/src/readDeviceCapabilities.ts index 369ba221..f1aeadf3 100644 --- a/src/readDeviceCapabilities.ts +++ b/src/readDeviceCapabilities.ts @@ -49,6 +49,6 @@ export async function readDeviceCapabilities(): Promise { adfMaxWidth: scanCaps?.adfMaxWidth || null, adfMaxHeight: scanCaps?.adfMaxHeight || null, adfDuplexMaxWidth: scanCaps?.adfDuplexMaxWidth || null, - adfDuplexMaxHeight: scanCaps?.adfDUplexMaxHeight || null, + adfDuplexMaxHeight: scanCaps?.adfDuplexMaxHeight || null, }; } From cef28fa374162d371f85be0bd1359ae6063a84de Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 16:02:28 +0000 Subject: [PATCH 11/13] Fix typos in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6c0a1a93..51607db2 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Please note that the `node-hp-scan-to` project is not endorsed by nor affiliated - ✔️ Customizable resolution - ✔️ Customizable label on the device - ✔️ Multi platform: Linux, Windows and most probably macOS -- ✔️ Mutile target supported: folder, [paperless-ngx](https://docs.paperless-ngx.com/) api upload, nextcloud webdav upload +- ✔️ Mutiple target supported: folder, [paperless-ngx](https://docs.paperless-ngx.com/) api upload, nextcloud webdav upload - ✔️ Clear all registered target - ✔️ Automatic scan when automatic document feeder is getting loaded @@ -136,7 +136,7 @@ Exhaustive list of supported environment variables and their meaning, or corresp - `NEXTCLOUD_USERNAME`: nextcloud user name - `NEXTCLOUD_PASSWORD`: password of nextcloud user. Either this or `NEXTCLOUD_PASSWORD_FILE` is required. If both are provided, value of `NEXTCLOUD_PASSWORD_FILE` is used. - `NEXTCLOUD_PASSWORD_FILE`: file name containing password of nextcloud user. Either this or `NEXTCLOUD_PASSWORD` is required. If both are provided, this value is used. For example: `NEXTCLOUD_PASSWORD_FILE=./nextcloud_password.secret`. Preferably for use in [docker compose secrets](https://docs.docker.com/reference/compose-file/secrets/) -- `$KEEP_FILES`: if set the scanned files will not be deleted, after uploading to paperless-ngx or nextcloud +- `KEEP_FILES`: if set the scanned files will not be deleted, after uploading to paperless-ngx or nextcloud - `CMDLINE`: additional command-line flags that will be put at the end of the command. __To enable debug logs set the environment variable `CMDLINE` to `-D`.__ From d6dfa62093c6d4de3a793dacd3dfb0c0715f78d1 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Tue, 28 Jan 2025 16:23:40 +0000 Subject: [PATCH 12/13] Add more tests for ADF duplexer behaviour --- test/scanProcessing.test.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/scanProcessing.test.ts b/test/scanProcessing.test.ts index 029ac379..10312b11 100644 --- a/test/scanProcessing.test.ts +++ b/test/scanProcessing.test.ts @@ -54,6 +54,23 @@ describe("scanProcessing", () => { const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(2583); }); + it("Limits the value if available from device", async () => { + scanConfig.width = 2583; + deviceCapabilities.adfMaxWidth = 1000; + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); + expect(width).to.be.eq(1000); + }); + it("Uses the max value if available from device", async () => { + deviceCapabilities.adfMaxWidth = 1000; + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, false); + expect(width).to.be.eq(1000); + }); + it("Uses the duplexer value if available from device", async () => { + deviceCapabilities.adfMaxWidth = 1000; + deviceCapabilities.adfDuplexMaxWidth = 2000; + const width = getScanWidth(scanConfig, inputSource, deviceCapabilities, true); + expect(width).to.be.eq(2000); + }); }); describe("Platen", async () => { const inputSource = InputSource.Platen; @@ -91,6 +108,23 @@ describe("scanProcessing", () => { const width = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); expect(width).to.be.eq(1269); }); + it("Limits the value if available from device", async () => { + scanConfig.height = 1269; + deviceCapabilities.adfMaxHeight = 1000; + const width = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); + expect(width).to.be.eq(1000); + }); + it("Uses the max value if available from device", async () => { + deviceCapabilities.adfMaxHeight = 1000; + const width = getScanHeight(scanConfig, inputSource, deviceCapabilities, false); + expect(width).to.be.eq(1000); + }); + it("Uses the duplexer value if available from device", async () => { + deviceCapabilities.adfMaxHeight = 1000; + deviceCapabilities.adfDuplexMaxHeight = 2000; + const width = getScanHeight(scanConfig, inputSource, deviceCapabilities, true); + expect(width).to.be.eq(2000); + }); }); describe("Platen", async () => { const inputSource = InputSource.Platen; From 7bb5fe27b468218d951857ad711c2178844bdda8 Mon Sep 17 00:00:00 2001 From: Adam Liddell Date: Thu, 30 Jan 2025 09:40:59 +0000 Subject: [PATCH 13/13] Refector readDeviceCapabilities Dead code path for devices without scanToComp, as this will be exercised later when registration occurs --- src/readDeviceCapabilities.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/readDeviceCapabilities.ts b/src/readDeviceCapabilities.ts index f1aeadf3..655c6760 100644 --- a/src/readDeviceCapabilities.ts +++ b/src/readDeviceCapabilities.ts @@ -1,32 +1,30 @@ import { DeviceCapabilities } from "./DeviceCapabilities"; import HPApi from "./HPApi"; -import WalkupScanToCompCaps from "./WalkupScanToCompCaps"; import ScanCaps from "./ScanCaps"; export async function readDeviceCapabilities(): Promise { let supportsMultiItemScanFromPlaten = true; + let useWalkupScanToComp = false; + const discoveryTree = await HPApi.getDiscoveryTree(); - let walkupScanToCompCaps: WalkupScanToCompCaps | null = null; + if (discoveryTree.WalkupScanToCompManifestURI != null) { + useWalkupScanToComp = true; const walkupScanToCompManifest = await HPApi.getWalkupScanToCompManifest( discoveryTree.WalkupScanToCompManifestURI, ); if (walkupScanToCompManifest.WalkupScanToCompCapsURI != null) { - walkupScanToCompCaps = await HPApi.getWalkupScanToCompCaps( + const walkupScanToCompCaps = await HPApi.getWalkupScanToCompCaps( walkupScanToCompManifest.WalkupScanToCompCapsURI, ); supportsMultiItemScanFromPlaten = walkupScanToCompCaps.supportsMultiItemScanFromPlaten; } } else if (discoveryTree.WalkupScanManifestURI != null) { - const walkupScanManifest = await HPApi.getWalkupScanManifest( + // No caps to load here but check we can load the specified manifest + await HPApi.getWalkupScanManifest( discoveryTree.WalkupScanManifestURI, ); - if (walkupScanManifest.walkupScanDestinationsURI != null) { - await HPApi.getWalkupScanDestinations( - walkupScanManifest.walkupScanDestinationsURI, - ); - } } else { console.log("Unknown device!"); } @@ -43,7 +41,7 @@ export async function readDeviceCapabilities(): Promise { return { supportsMultiItemScanFromPlaten, - useWalkupScanToComp: walkupScanToCompCaps != null, + useWalkupScanToComp, platenMaxWidth: scanCaps?.platenMaxWidth || null, platenMaxHeight: scanCaps?.platenMaxHeight || null, adfMaxWidth: scanCaps?.adfMaxWidth || null,