Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,090 changes: 567 additions & 523 deletions demo/advanced.html

Large diffs are not rendered by default.

616 changes: 308 additions & 308 deletions demo/index.html

Large diffs are not rendered by default.

744 changes: 375 additions & 369 deletions demo/test_advanced.ts

Large diffs are not rendered by default.

618 changes: 309 additions & 309 deletions demo/test_index.ts

Large diffs are not rendered by default.

440 changes: 438 additions & 2 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@vitest/coverage-v8": "^2.1.6",
"eslint": "^9.9.0",
"globals": "^15.9.0",
"happy-dom": "^15.11.7",
"https-localhost": "^4.7.1",
"typescript": "^5.7.2",
"typescript-eslint": "^8.16.0",
Expand Down
30 changes: 16 additions & 14 deletions src/Commands/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,12 @@ export type CommandType
| "SetLabelToMarkMedia"
| "SetPrintDirection"
| "SetPrintSpeed"
| "SetBackfeedAfterTaken"
// Document handling
| "NewLabel"
| "StartLabel"
| "EndLabel"
| "CutNow"
| "EnableFeedBackup"
| "SuppressFeedBackup"
| "Print"
// Content
| "ClearImageBuffer"
Expand Down Expand Up @@ -167,18 +166,6 @@ export class CutNowCommand extends BasicCommand {
constructor() { super(['actuatesCutter']); }
}

export class SuppressFeedBackupCommand extends BasicCommand {
name = 'Disable feed backup after printing label (be sure to re-enable!)';
type: CommandType = 'SuppressFeedBackup';
constructor() { super([]); }
}

export class EnableFeedBackupCommand extends BasicCommand {
name = 'Enable feed backup after printing label.';
type: CommandType = 'EnableFeedBackup';
constructor() { super([]); }
}

/** A command to clear the image buffer. */
export class ClearImageBufferCommand extends BasicCommand {
name = 'Clear image buffer';
Expand Down Expand Up @@ -222,6 +209,21 @@ export class SetDarknessCommand implements IPrinterCommand {
effectFlags = new CommandEffectFlags(['altersConfig']);
}

export class SetBackfeedAfterTakenMode implements IPrinterCommand {
name = 'Set backfeed mode after label is taken';
type: CommandType = 'SetBackfeedAfterTaken';
toDisplay(): string {
if (this.mode === 'disabled') {
return 'Disable backfeed';
} else {
return `Set backfeed to ${this.mode}% after label cut/taken.`;
}
}
effectFlags = new CommandEffectFlags(['altersConfig']);

constructor(public readonly mode: Conf.BackfeedAfterTaken) { }
}

/** A command to set the direction a label prints, either upside down or not. */
export class SetPrintDirectionCommand implements IPrinterCommand {
name = 'Set print direction';
Expand Down
8 changes: 3 additions & 5 deletions src/Commands/Messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,9 @@ export type AwaitedCommand = {
export interface ISettingUpdateMessage {
messageType: 'SettingUpdateMessage';

printerHardware: Conf.IPrinterHardwareUpdate;
printerMedia: Conf.IPrinterMediaUpdate;

printerDistanceIn?: number;
headDistanceIn?: number;
printerHardware?: Conf.IPrinterHardwareUpdate;
printerMedia ?: Conf.IPrinterMediaUpdate;
printerSettings?: Conf.IPrinterSettingsUpdate;
}

/** A status message sent by the printer. */
Expand Down
42 changes: 22 additions & 20 deletions src/Commands/PrinterConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,28 @@ export class PrinterConfig extends Conf.BasePrinterConfig {

/** Update these options with newly transmitted settings. */
public update(msg: ISettingUpdateMessage) {
this._model = msg.printerHardware.model ?? this._model;
this._manufacturer = msg.printerHardware.manufacturer ?? this._manufacturer;
this._serial = msg.printerHardware.serialNumber ?? this._serial;
this._dpi = msg.printerHardware.dpi ?? this._dpi;
this._speedTable = msg.printerHardware.speedTable ?? this._speedTable;
this._maxMediaDarkness = msg.printerHardware.maxMediaDarkness ?? this._maxMediaDarkness;
this._firmware = msg.printerHardware.firmware ?? this._firmware;
this._maxMediaLengthDots = msg.printerHardware.maxMediaLengthDots ?? this._maxMediaLengthDots;
this._maxMediaWidthDots = msg.printerHardware.maxMediaWidthDots ?? this._maxMediaWidthDots;
this._model = msg.printerHardware?.model ?? this._model;
this._manufacturer = msg.printerHardware?.manufacturer ?? this._manufacturer;
this._serial = msg.printerHardware?.serialNumber ?? this._serial;
this._dpi = msg.printerHardware?.dpi ?? this._dpi;
this._speedTable = msg.printerHardware?.speedTable ?? this._speedTable;
this._maxMediaDarkness = msg.printerHardware?.maxMediaDarkness ?? this._maxMediaDarkness;
this._firmware = msg.printerHardware?.firmware ?? this._firmware;
this._maxMediaLengthDots = msg.printerHardware?.maxMediaLengthDots ?? this._maxMediaLengthDots;
this._maxMediaWidthDots = msg.printerHardware?.maxMediaWidthDots ?? this._maxMediaWidthDots;

this._speed = msg.printerMedia.speed ?? this._speed;
this._darkness = msg.printerMedia.darknessPercent ?? this._darkness;
this._thermalPrintMode = msg.printerMedia.thermalPrintMode ?? this._thermalPrintMode;
this._mediaPrintMode = msg.printerMedia.mediaPrintMode ?? this._mediaPrintMode;
this._printOrientation = msg.printerMedia.printOrientation ?? this._printOrientation;
this._mediaGapDetectMode = msg.printerMedia.mediaGapDetectMode ?? this._mediaGapDetectMode;
this._mediaPrintOriginOffsetDots = msg.printerMedia.mediaPrintOriginOffsetDots ?? this._mediaPrintOriginOffsetDots;
this._mediaGapDots = msg.printerMedia.mediaGapDots ?? this._mediaGapDots;
this._mediaLineOffsetDots = msg.printerMedia.mediaLineOffsetDots ?? this._mediaLineOffsetDots;
this._mediaWidthDots = msg.printerMedia.mediaWidthDots ?? this._mediaWidthDots;
this._mediaLengthDots = msg.printerMedia.mediaLengthDots ?? this._mediaLengthDots;
this._speed = msg.printerMedia?.speed ?? this._speed;
this._darkness = msg.printerMedia?.darknessPercent ?? this._darkness;
this._thermalPrintMode = msg.printerMedia?.thermalPrintMode ?? this._thermalPrintMode;
this._mediaPrintMode = msg.printerMedia?.mediaPrintMode ?? this._mediaPrintMode;
this._printOrientation = msg.printerMedia?.printOrientation ?? this._printOrientation;
this._mediaGapDetectMode = msg.printerMedia?.mediaGapDetectMode ?? this._mediaGapDetectMode;
this._mediaPrintOriginOffsetDots = msg.printerMedia?.mediaPrintOriginOffsetDots ?? this._mediaPrintOriginOffsetDots;
this._mediaGapDots = msg.printerMedia?.mediaGapDots ?? this._mediaGapDots;
this._mediaLineOffsetDots = msg.printerMedia?.mediaLineOffsetDots ?? this._mediaLineOffsetDots;
this._mediaWidthDots = msg.printerMedia?.mediaWidthDots ?? this._mediaWidthDots;
this._mediaLengthDots = msg.printerMedia?.mediaLengthDots ?? this._mediaLengthDots;

this._backfeedAfterTaken = msg.printerSettings?.backfeedAfterTaken ?? this._backfeedAfterTaken;
}
}
13 changes: 8 additions & 5 deletions src/Configs/BasePrinterConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MediaMediaGapDetectionMode, MediaPrintMode, PrintOrientation, PrintSpeed, PrintSpeedSettings, SpeedTable, ThermalPrintMode, type Coordinate, type DarknessPercent, type IPrinterHardware } from "./ConfigurationTypes.js";
import { MediaMediaGapDetectionMode, MediaPrintMode, PrintOrientation, PrintSpeed, PrintSpeedSettings, SpeedTable, ThermalPrintMode, type BackfeedAfterTaken, type Coordinate, type DarknessPercent, type IPrinterHardware, type IPrinterMedia, type IPrinterSettings } from "./ConfigurationTypes.js";

/** Configured options for a label printer */
export abstract class BasePrinterConfig implements IPrinterHardware {
/** Configured options for a printer */
export abstract class BasePrinterConfig implements IPrinterHardware, IPrinterSettings, IPrinterMedia {

// Read-only printer config info
protected _serial = 'no_serial_nm';
Expand All @@ -19,8 +19,6 @@ export abstract class BasePrinterConfig implements IPrinterHardware {
protected _firmware = '';
get firmware() { return this._firmware; }

public labelDimensionRoundingStep = 0.25;

protected _speed = new PrintSpeedSettings(PrintSpeed.unknown);
get speed() { return this._speed; }

Expand All @@ -30,6 +28,9 @@ export abstract class BasePrinterConfig implements IPrinterHardware {
protected _darkness: DarknessPercent = 50;
get darknessPercent() { return this._darkness; }

protected _backfeedAfterTaken: BackfeedAfterTaken = '90';
get backfeedAfterTaken() { return this._backfeedAfterTaken; }

protected _maxMediaDarkness = 15;
get maxMediaDarkness() { return this._maxMediaDarkness; }

Expand All @@ -39,6 +40,8 @@ export abstract class BasePrinterConfig implements IPrinterHardware {
protected _mediaPrintMode = MediaPrintMode.tearOff;
get mediaPrintMode() { return this._mediaPrintMode; }

public mediaDimensionRoundingStep = 0.25;

protected _printOrientation = PrintOrientation.normal;
get printOrientation() { return this._printOrientation; }

Expand Down
111 changes: 68 additions & 43 deletions src/Configs/ConfigurationTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface Coordinate {
top: number;
}

/** The orientation of a label as it comes out of the printer. */
/** The orientation of a media as it comes out of the printer. */
export enum PrintOrientation {
/** Right-side up when the printer faces the user. */
normal,
Expand Down Expand Up @@ -60,13 +60,13 @@ export enum ThermalPrintMode {
transfer
}

/** Describes the way the labels are marked for the printer to detect separate labels. */
/** Describes the way the medias are marked for the printer to detect separate medias. */
export enum MediaMediaGapDetectionMode {
/** Media is one continuous label with no gaps. Used with cutters usually. */
/** Media is one continuous media with no gaps. Used with cutters usually. */
continuous,
/** Media is opaque with gaps between labels that can be sensed by the printer. */
/** Media is opaque with gaps between medias that can be sensed by the printer. */
webSensing,
/** Media has black marks indicating label spacing. */
/** Media has black marks indicating media spacing. */
markSensing,
/** Autodetect during calibration. G-series printers only. */
autoDuringCalibration,
Expand All @@ -76,28 +76,43 @@ export enum MediaMediaGapDetectionMode {

/** Printing behavior */
export enum MediaPrintMode {
/** Label advances so web is over tear bar, to be torn manually. */
/** Media advances so web is over tear bar, to be torn manually. */
tearOff,
/** Label advances over Label Taken sensor. Printing pauses until label is removed. */
/** Media advances over Media Taken sensor. Printing pauses until media is removed. */
peel,
/** Peel mode, but each label is fed to pre-peel a small portion. Helps some media types. ZPL only.*/
/** Peel mode, but each media is fed to pre-peel a small portion. Helps some media types. ZPL only.*/
peelWithPrePeel,
/** Peel mode, but printer waits for button tap between labels. */
/** Peel mode, but printer waits for button tap between medias. */
peelWithButtonTap,
/** Label advances until web is over cutter. */
/** Media advances until web is over cutter. */
cutter,
/** Cutter, but cut operation waits for separate command. ZPL only. */
cutterWaitForCommand,
/** Label and liner are rewound on an external device. No backfeed motion. ZPL only. */
/** Media and liner are rewound on an external device. No backfeed motion. ZPL only. */
rewind,
/** Label advances far enough for applicator device to grab. Printers with applicator ports only. */
/** Media advances far enough for applicator device to grab. Printers with applicator ports only. */
applicator,
/** Removes backfeed between RFID labels, improving throughput. RFID printers only. */
/** Removes backfeed between RFID medias, improving throughput. RFID printers only. */
rfid,
/** Label is moved into a presentation position. ZPL only.*/
/** Media is moved into a presentation position. ZPL only.*/
kiosk
}

/** Percentage to backfeed after taking/cutting label, vs before printing the next. */
export type BackfeedAfterTaken
= 'disabled'
| '0'
| '10'
| '20'
| '30'
| '40'
| '50'
| '60'
| '70'
| '80'
| '90'
| '100';

/** Class for representing a printer's relationship between speeds and raw values */
export class SpeedTable {
// Speed is determined by what the printer supports
Expand Down Expand Up @@ -189,7 +204,7 @@ export class PrintSpeedSettings {

/** Speed during printing media. */
printSpeed: PrintSpeed;
/** Speed during feeding a blank label. ZPL only, same as media speed for EPL. */
/** Speed during feeding a blank media. ZPL only, same as media speed for EPL. */
slewSpeed: PrintSpeed;
}

Expand Down Expand Up @@ -235,59 +250,69 @@ export interface IPrinterHardwareUpdate {
speedTable?: SpeedTable;
}

/** Printer options related to the label media being printed */
/** Settings for printer behavior */
export interface IPrinterSettings {
/** What percentage of backfeed happens after cutting/taking label, vs before printing. */
readonly backfeedAfterTaken: BackfeedAfterTaken;
}

export interface IPrinterSettingsUpdate {
backfeedAfterTaken?: BackfeedAfterTaken;
}

/** Printer options related to the media media being printed */
export interface IPrinterMedia {
/** How dark to print. 0 is blank, 99 is max darkness */
darknessPercent: DarknessPercent;
/** Mode the printer uses to detect separate labels when printing. */
labelGapDetectMode: MediaMediaGapDetectionMode;
/** Mode the printer uses to detect separate medias when printing. */
mediaGapDetectMode: MediaMediaGapDetectionMode;
/**
* The gap / mark length between labels. Mandatory for markSensing black line mode.
* The gap / mark length between medias. Mandatory for markSensing black line mode.
* Media with webSensing gaps can use AutoSense to get this value.
*/
get labelGapInches(): number;
/** Label gap in dots */
labelGapDots: number;
/** The offset in inches from the normal location of the label gap or black line. Can be negative. */
get labelLineOffsetInches(): number;
/** The offset in dots from the normal location of the label gap or black line. Can be negative. */
labelLineOffsetDots: number;
/** The length of the label media, in inches. */
get labelLengthInches(): number;
/** The length of the label media, in dots. */
labelLengthDots: number;
/** The width of the label media, in inches. */
get labelWidthInches(): number;
/** The width of the label media, in dots. */
labelWidthDots: number;
get mediaGapInches(): number;
/** Media web gap in dots */
mediaGapDots: number;
/** The offset in inches from the normal location of the media gap or black line. Can be negative. */
get mediaLineOffsetInches(): number;
/** The offset in dots from the normal location of the media gap or black line. Can be negative. */
mediaLineOffsetDots: number;
/** The length of the media media, in inches. */
get mediaLengthInches(): number;
/** The length of the media media, in dots. */
mediaLengthDots: number;
/** The width of the media media, in inches. */
get mediaWidthInches(): number;
/** The width of the media media, in dots. */
mediaWidthDots: number;

/** The offset of the printable area, from the top-left corner. */
labelPrintOriginOffsetDots: Coordinate;
mediaPrintOriginOffsetDots: Coordinate;

/**
* Value to use for rounding read-from-config label sizes.
* Value to use for rounding read-from-config media sizes.
*
* When reading the config from a printer the label width and length may be
* variable. When you set the label width to 4 inches it's translated into
* When reading the config from a printer the media width and length may be
* variable. When you set the media width to 4 inches it's translated into
* dots, and then the printer adds a calculated offset to that. This offset
* is unique per printer (so far as I have observed) and introduces noise.
* This value rounds the returned value to the nearest fraction of an inch.
*
* For example, with a rounding step of 0.25 (the default) if the printer
* returns a width 4.113 it will be rounded to 4.0
*/
labelDimensionRoundingStep: number;
mediaDimensionRoundingStep: number;

/** Label print speed settings */
/** Media print speed settings */
speed: PrintSpeedSettings;

/** The label media thermal print mode. */
/** The media thermal print mode. */
thermalPrintMode: ThermalPrintMode;

/** The behavior of media after form printing. */
mediaPrintMode: MediaPrintMode;

/** Whether the label prints right-side-up or upside-down. */
/** Whether the media prints right-side-up or upside-down. */
printOrientation: PrintOrientation;
}

Expand All @@ -299,7 +324,7 @@ export interface IPrinterMediaUpdate {
mediaLengthDots?: number;
mediaWidthDots?: number;
mediaPrintOriginOffsetDots?: Coordinate;
labelDimensionRoundingStep?: number;
mediaDimensionRoundingStep?: number;
thermalPrintMode?: ThermalPrintMode;
mediaPrintMode?: MediaPrintMode;
printOrientation?: PrintOrientation;
Expand Down
7 changes: 7 additions & 0 deletions src/Documents/ConfigDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ export class ConfigDocumentBuilder
autosenseLabelLength() {
return this.andThen(new Cmds.AutosenseLabelDimensionsCommand()).finalize();
}

setBackfeedAfterTakenMode(mode: Conf.BackfeedAfterTaken) {
return this.andThen(new Cmds.SetBackfeedAfterTakenMode(mode));
}

setLabelDimensions(widthInInches: number, lengthInInches?: number, gapLengthInInches?: number) {
this._doSave = true;
Expand Down Expand Up @@ -273,6 +277,9 @@ export interface IPrinterLabelConfigBuilder {
/** Run the autosense operation to get label length. Must be last command. */
autosenseLabelLength(): IDocument;

/** Set the backfeed behavior after cut/take of label. */
setBackfeedAfterTakenMode(mode: Conf.BackfeedAfterTaken): IConfigDocumentBuilder;

/** Sets the media type to continuous (gapless) media. */
setLabelMediaToContinuous(labelLengthInDots: number): IConfigDocumentBuilder;

Expand Down
Loading
Loading