diff --git a/demo/test_advanced.ts b/demo/test_advanced.ts
index 8bb669c..21e4914 100644
--- a/demo/test_advanced.ts
+++ b/demo/test_advanced.ts
@@ -163,6 +163,12 @@ interface ConfigModalForm extends HTMLCollection {
// Power up/head close actions
modalZplPowerUpAction : HTMLSelectElement
modalZplHeadCloseAction: HTMLSelectElement
+
+ // Networking
+ modalNetworkProtocolMode : HTMLSelectElement
+ modalNetworkIpAddress : HTMLInputElement
+ modalNetworkDefaultGateway: HTMLInputElement
+ modalNetworkNetmask : HTMLInputElement
}
// A function to find and hide any alerts for a given alert ID.
@@ -308,6 +314,11 @@ class BasicLabelDesignerApp {
const config = printer.printerOptions;
// If the printer uses ZPL it will have a special config, show those!
const isZpl = config instanceof WebLabel.ZPL.ZplPrinterConfig;
+ // If the printer has an IP address show the networking config!
+ let isNetwork = false;
+ if (isZpl) {
+ isNetwork = config.ipResolutionMode !== undefined;
+ }
const formElement = this.configModal.querySelector('form')!;
const form = formElement.elements as ConfigModalForm;
@@ -320,6 +331,13 @@ class BasicLabelDesignerApp {
e.classList.add('d-none');
}
}
+ for (const e of formElement.querySelectorAll('.modal-setting-network')) {
+ if (isNetwork) {
+ e.classList.remove('d-none');
+ } else {
+ e.classList.add('d-none');
+ }
+ }
// Translate the available speeds to options to be selected
form.modalSpeed.innerHTML = '';
@@ -376,6 +394,14 @@ class BasicLabelDesignerApp {
form.modalZplPowerUpAction.value = config.actionPowerUp.toString();
form.modalZplHeadCloseAction.value = config.actionHeadClose.toString();
+
+ if (isNetwork) {
+ form.modalNetworkIpAddress.value = config.ipAddress ?? "";
+ form.modalNetworkDefaultGateway.value = config.defaultGateway ?? "";
+ form.modalNetworkNetmask.value = config.subnetMask ?? "";
+ form.modalNetworkProtocolMode.value = config.ipResolutionMode ?? "ALL";
+ // TODO: On protocol change lock out IP settings for DHCP
+ }
}
this.configModalHandle.show();
@@ -681,6 +707,17 @@ class BasicLabelDesignerApp {
ribbonThreshold : Number(form.modalZplRibbonTHold.value),
webThreshold : Number(form.modalZplWebTHold.value),
}));
+
+
+ const isNetwork = printer.printerOptions.ipResolutionMode !== undefined;
+ if (isNetwork) {
+ configDoc.andThen(new WebLabel.ZPL.CmdSetNetworkIpResolutionMode(
+ form.modalNetworkProtocolMode.value as WebLabel.ZPL.NetworkIpResolutionMode,
+ form.modalNetworkIpAddress.value,
+ form.modalNetworkNetmask.value,
+ form.modalNetworkDefaultGateway.value
+ ))
+ }
}
let doc: WebLabel.IDocument;
diff --git a/docs/zpl/networks.md b/docs/zpl/networks.md
new file mode 100644
index 0000000..a22de42
--- /dev/null
+++ b/docs/zpl/networks.md
@@ -0,0 +1,128 @@
+# Networks of ZPL Printers
+
+ZPL supports several networking methodologies
+
+## Ethernet
+
+### Config
+
+> EPL doesn't appear to have a way to directly configure network settings, the manuals only reference SGD commands.
+
+ZPL has several commands to set network settings, they act slightly differently depending on firmware version and hardware config.
+
+* The `^NS` command appears to be oldest, with the first 4 parameters (a,b,c,d) seemingly being universal.
+* As early as 2006 the "Wireless and Wireless Plus print servers" added parameters to the NS command, up to `^NSa,b,c,d,e,f,g,h,i`.
+* The separate `^WI` command was added for configuring wireless network settings, see the wifi section below.
+* Later firmware versions added the `^ND` command, which can set external wired, internal wired, or wireless settings using the same command. It'll work as an alias for `^NS` or `^ND` depending on the `a` parameter.
+
+Example to set a static IP of `192.168.1.151`:
+
+`^NSP,192.168.1.151,255.255.255.0,192.168.1.1`
+
+The default IP resolution mode is `all`.
+
+### ZebraNet PrintServer II
+
+For a while Zebra offered an external ZebraNet PrintServer II device that plugged directly into the parallel port on most printers. On some models they also offered this as an embedded option, either as a module or directly on the same circuit board in the case of some LP-2844 series.
+
+Newer models offer a more integrated networking stack.
+
+Different features are supported depending on generation, though the ZebraNet PrintServer II era tend to be very similar.
+
+Ports:
+
+* 21 - FTP
+* 23 - Telnet
+* 80 - HTTP web server
+* 161 - SNMP
+* 162 - SNMP Trap on ZebraNet Alert
+* 515 - Printer port (Line Printer Daemon)
+* 631 - IPP (Limited models)
+* 4201 - (UDP) Zebra network auto-discovery port
+* 9100 - Raw network printing
+* 20035 - (UDP) WCSO wireless auto-discovery port
+
+ZebraNet may negotiate some dynamic ports too.
+
+### LinkOS Printers
+
+These are more complex and add additional ports in addition to the above. They can also be configured.
+
+* 443 - HTTPS web GUI
+* 9143, 9243 - TLSRAW connections
+
+### Discovery Protocol
+
+This section is copy/pasted [from JFR's blog post here](https://jfr.im/blog/2024/09/zebra-network-discovery-protocol/).
+
+> Discovery client sends a UDP packet to port 4201 (unicast or broadcast), containing the data: `0x2e2c3a010000`, or `.,:\x01\x00\x00`.
+>
+> Actually, the discovery client sends 3 identical such packets (from the same socket), then waits 1 second, then repeats the process from a new source port. It sends 3 packets 3 times, for a total of 9 packets. This appears to be meant to handle UDP’s lack of reliability; the printers reply to each packet (for a total of 9 replies from each printer).
+>
+> The printers reply back with a (now unicast) packet beginning with `0x3a2c2e` or `:,.`. This is followed by a 0x03 byte, I’m not sure if this is part of the magic bytes or part of the data, and then the data begins with the “Product Number”.
+>
+> This set of information is displayed verbatim in the ZebraNet Bridge tool:
+
+```text
+0000 3a 2c 2e 03 37 39 30 37 31 00 00 00 5a 65 62 72 :,..79071...Zebr
+ ^-Cmd?----^ ^-Product #--^-------?^ ^-Name-----
+0010 61 4e 65 74 20 57 69 72 65 64 20 50 53 00 00 00 aNet Wired PS...
+ -------------------------------------^------?^
+0020 31 31 36 36 41 00 00 56 35 36 2e 31 37 2e 31 31 1166A..V56.17.11
+ ^-Datecode---^----?^ ^-FW Version--------------
+0030 5a 5a 42 52 00 61 00 07 4d 41 08 bd 34 32 36 32 ZZBR.a..MA..4262
+ -^ ^-S/N------
+0040 30 37 37 00 00 00 01 00 0a 01 00 9e ff ff ff 00 077.............
+ -------^-------?^ ^-IP------^ ^-Netmask-^
+ 01 00: "Using Net Protocol: TRUE"?
+0050 0a 01 00 01 5a 42 52 34 32 36 32 30 37 37 00 00 ....ZBR4262077..
+ ^-Gateway-^ ^-System Name (hostname?)---^---?
+```
+
+> Unfortunately, I have no idea what the remainder of the message is:
+
+```text
+0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00d0 00 00 00 00 7a 00 6d 14 7a 16 11 1c 2b 3a 35 30 ....z.m.z...+:50
+00e0 3f 4e 59 54 53 52 5d 68 67 66 61 6c 7b 8a 85 80 ?NYTSR]hgfal{...
+00f0 8f 9e a9 a4 ee 18 e1 14 ee 0e 8d 0c 8f 0a 91 08 ................
+0100 93 06 95 04 97 02 99 00 9b 3e dd 7c 1f ba 21 b8 .........>.|..!.
+0110 23 b6 25 b4 4e 6f 6e 65 00 0e 8d 0c 8f 0a 91 08 #.%.None........
+0120 93 06 95 04 97 02 99 00 9b 3e dd 7c 1f ba 21 b8 .........>.|..!.
+0130 23 b6 25 b4 00 00 00 00 00 00 00 00 00 00 00 00 #.%.............
+0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+0150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+0160 00 00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 ................
+0170 00 00 00 00 00 00 00 .......
+```
+
+## Wifi
+
+I don't have a machine with wifi! These include lots of fun commands.
+
+## Bluetooth Serial
+
+I don't have an older style bluetooth machine!
+
+## Bluetooth LE
+
+Modern LinkOS devices tend to support Bluetooth LE, especially if they have a tap-to-connect NFC tag.
+
+## RS-485
+
+WebZLP does not currently implement RS-485 networking. Ask if you need this, I would very much like to know more about why!
+
+Some models of printers are designed to be connected on an RS-485 serial bus network. When connected to such a network each printer has a _Network ID_ that controls how to talk to a given printer. Each network ID is 3 digits, 000 through 999.
+
+Several commands are used for controlling serial networks:
+
+* `~NC` - Network Connect, used at the start of the label to wake up the printer and send subsequent commands.
+* `^NI` - Assign network ID number to a given printer.
+* `~NR` - Set all network printers "transparent" (disconnect)
+* `~NT` - Set current printer "transparent" (disconnect)
diff --git a/src/Languages/Zpl/CmdHostConfig.test.ts b/src/Languages/Zpl/CmdHostConfig.test.ts
index 2218119..452989e 100644
--- a/src/Languages/Zpl/CmdHostConfig.test.ts
+++ b/src/Languages/Zpl/CmdHostConfig.test.ts
@@ -37,6 +37,14 @@ describe('parseCmdHostConfig', () => {
});
});
+ describe("LP2844-Z-NET", () => {
+ const conf = tf.LP2844_Z_NET_TXT();
+ const snap = tf.LP2844_Z_NET_CONF;
+ it('Parses host config', () => {
+ expect(parseCmdHostConfig(conf, cmd)).toMatchFileSnapshot(snap);
+ });
+ });
+
describe("TLP2844-Z", () => {
const conf = tf.TLP2844_Z_TXT();
const snap = tf.TLP2844_Z_CONF;
diff --git a/src/Languages/Zpl/CmdHostConfig.ts b/src/Languages/Zpl/CmdHostConfig.ts
index 8c6ca8b..7f9fdb5 100644
--- a/src/Languages/Zpl/CmdHostConfig.ts
+++ b/src/Languages/Zpl/CmdHostConfig.ts
@@ -2,7 +2,7 @@
import * as Conf from '../../Configs/index.js';
import * as Cmds from '../../Commands/index.js';
import * as Util from '../../Util/index.js';
-import type { IZplSettingUpdateMessage, PowerUpAction } from './Config.js';
+import type { IZplSettingUpdateMessage, NetworkIpResolutionMode, PowerUpAction } from './Config.js';
const powerUpMap: Record
= {
"NO MOTION": 'none',
@@ -10,6 +10,16 @@ const powerUpMap: Record = {
"FEED": 'feedBlank',
}
+const ipProtocolMap: Record = {
+ 'ALL': 'ALL',
+ 'BOOTP': 'BOOTP',
+ 'DHCP': 'DHCP',
+ 'PERMANENT': 'PERMANENT',
+ 'DHCP AND BOOTP': 'DHCP_AND_BOOTP',
+ 'GLEANING': 'GLEANING',
+ 'RARP': 'RARP',
+}
+
export class CmdHostConfig implements Cmds.IPrinterExtendedCommand {
public static typeE = Symbol("CmdHostStatus");
typeExtended = CmdHostConfig.typeE;
@@ -299,6 +309,31 @@ export function parseCmdHostConfig(
case "RTC TIME":
break;
+ // Networking
+ // These values are not present in the XML block on early firmware so
+ // pull them from here instead
+
+ // TODO: Figure out if this is a config or a status
+ // PERMANENT, ???
+ case "IP RESOLUTION":
+ break;
+ case "IP PROTOCOL":
+ //ALL,
+ update.printerZplSettings!.ipResolutionMode = ipProtocolMap[l.value];
+ break;
+
+ // Addresses are zero-padded IPv4 addressses like 010.048.112.191
+ // TODO: Safer parsing!
+ case "IP ADDRESS": //010.048.112.191
+ update.printerZplSettings!.ipAddress = l.value;
+ break;
+ case "SUBNET MASK": //255.255.255.000
+ update.printerZplSettings!.subnetMask = l.value;
+ break;
+ case "DEFAULT GATEWAY": //010.048.112.001
+ update.printerZplSettings!.defaultGateway = l.value;
+ break;
+
// There is one non-resettable counter and two resettable ones
// like a car odometer and trip, haha.
// Unfortunately, they use the same key! You have to split by suffix.
diff --git a/src/Languages/Zpl/CmdNetworkSettings.ts b/src/Languages/Zpl/CmdNetworkSettings.ts
new file mode 100644
index 0000000..931d160
--- /dev/null
+++ b/src/Languages/Zpl/CmdNetworkSettings.ts
@@ -0,0 +1,54 @@
+import * as Conf from '../../Configs/index.js';
+import * as Cmds from '../../Commands/index.js';
+import type { NetworkIpResolutionMode } from './Config.js';
+
+const networkIpToCmd: Record = {
+ ALL: 'A',
+ BOOTP: 'B',
+ DHCP_AND_BOOTP: 'C',
+ DHCP: 'D',
+ GLEANING: 'G',
+ RARP: 'R',
+ PERMANENT: 'P'
+}
+
+export class CmdSetNetworkIpResolutionMode implements Cmds.IPrinterExtendedCommand {
+ public static typeE = Symbol("CmdSetNetworkIpResolutionMode");
+ typeExtended = CmdSetNetworkIpResolutionMode.typeE;
+ commandLanguageApplicability = Conf.PrinterCommandLanguage.zpl;
+ name = 'Set the network IP address resolution mode.';
+ type = "CustomCommand" as const;
+ effectFlags = new Cmds.CommandEffectFlags(['altersConfig']);
+ toDisplay(): string {
+ return `Set IP resolution mode to ${this.ipMode}`;
+ }
+
+ constructor(
+ public readonly ipMode: NetworkIpResolutionMode,
+ public readonly ipAddress: string, // TODO: real types
+ public readonly subnetMask: string,
+ public readonly defaultGateway: string,
+ // TODO: Add support for extended NS/ND commands
+ // public readonly winsServerAddress?: string,
+ // public readonly timeoutChecking?: boolean,
+ // public readonly timeoutValue?: number, // TODO: Clamp 0 to 9999
+ // public readonly arpBroadcastInterval?: number, // TODO: Clamp 0 to 30
+ // public readonly baseRawPortNumber?: number, // TODO: Clamp 1 through 65535
+ // public readonly networkInterface: NetworkInterface = 'ExternalWired',
+ ) {}
+}
+
+export const cmdSetNetworkIpResolutionModeMapping: Cmds.IPrinterCommandMapping = {
+ commandType: CmdSetNetworkIpResolutionMode.typeE,
+ transpile: handleCmdSetNetworkIpResolutionMode,
+}
+
+export function handleCmdSetNetworkIpResolutionMode(
+ cmd: Cmds.IPrinterCommand,
+): string {
+ if (cmd instanceof CmdSetNetworkIpResolutionMode) {
+ const ip = networkIpToCmd[cmd.ipMode];
+ return `^NS${ip},${cmd.ipAddress},${cmd.subnetMask},${cmd.defaultGateway}`;
+ }
+ return '';
+}
diff --git a/src/Languages/Zpl/CmdXmlQuery.test.ts b/src/Languages/Zpl/CmdXmlQuery.test.ts
index eaed08c..d7d5b3b 100644
--- a/src/Languages/Zpl/CmdXmlQuery.test.ts
+++ b/src/Languages/Zpl/CmdXmlQuery.test.ts
@@ -20,6 +20,9 @@ describe('parseCmdXmlQueryResponse', () => {
it('LP2844_Z', async () => {
await expect(parseCmdXmlQuery(tf.LP2844_Z_XML(), cmd)).toMatchFileSnapshot(tf.LP2844_Z_FULL);
});
+ it('LP2844_Z_NET', async () => {
+ await expect(parseCmdXmlQuery(tf.LP2844_Z_NET_XML(), cmd)).toMatchFileSnapshot(tf.LP2844_Z_NET_FULL);
+ });
it('TLP2844_Z', async () => {
await expect(parseCmdXmlQuery(tf.TLP2844_Z_XML(), cmd)).toMatchFileSnapshot(tf.TLP2844_Z_FULL);
});
diff --git a/src/Languages/Zpl/Config.ts b/src/Languages/Zpl/Config.ts
index 5e53ffb..3b8d908 100644
--- a/src/Languages/Zpl/Config.ts
+++ b/src/Languages/Zpl/Config.ts
@@ -31,6 +31,20 @@ export interface IZplSettingUpdateMessage extends Cmds.ISettingUpdateMessage {
printerZplSettings?: Conf.UpdateFor;
}
+export type NetworkIpResolutionMode
+ = 'ALL'
+ | 'BOOTP'
+ | 'DHCP_AND_BOOTP'
+ | 'DHCP'
+ | 'GLEANING'
+ | 'RARP'
+ | 'PERMANENT';
+
+export type NetworkInterface
+ = 'ExternalWired'
+ | 'InternalWired'
+ | 'Wireless';
+
/** ZPL-specific config information about a printer. */
export interface IZplPrinterSettings extends SensorLevels {
/** The action the printer takes on power up. */
@@ -38,6 +52,14 @@ export interface IZplPrinterSettings extends SensorLevels {
/** The action the printer takes when the head is closed. */
actionHeadClose: PowerUpAction;
+
+ ipResolutionMode?: NetworkIpResolutionMode;
+
+ ipAddress?: string | undefined;
+
+ subnetMask?: string | undefined;
+
+ defaultGateway?: string | undefined;
}
export class ZplPrinterConfig extends Cmds.PrinterConfig implements IZplPrinterSettings, SensorLevels {
@@ -119,6 +141,24 @@ export class ZplPrinterConfig extends Cmds.PrinterConfig implements IZplPrinterS
return this._takeLabelThreshold;
}
+ // Networking, if hardware is present
+ private _ipResolutionMode?: NetworkIpResolutionMode = undefined;
+ public get ipResolutionMode(): NetworkIpResolutionMode | undefined {
+ return this._ipResolutionMode;
+ }
+ private _ipAddress?: string; // TODO: Real types
+ public get ipAddress(): string | undefined {
+ return this._ipAddress;
+ }
+ private _subnetMask?: string;
+ public get subnetMask(): string | undefined {
+ return this._subnetMask;
+ }
+ private _defaultGateway?: string;
+ public get defaultGateway(): string | undefined {
+ return this._defaultGateway;
+ }
+
public override update(msg: Cmds.ISettingUpdateMessage | IZplSettingUpdateMessage) {
super.update(msg);
@@ -140,6 +180,11 @@ export class ZplPrinterConfig extends Cmds.PrinterConfig implements IZplPrinterS
this._ribbonGain = s?.ribbonGain ?? this._ribbonGain
this._ribbonThreshold = s?.ribbonThreshold ?? this._ribbonThreshold
this._ribbonBrightness = s?.ribbonBrightness ?? this._ribbonBrightness
+
+ this._ipAddress = s?.ipAddress ?? this._ipAddress;
+ this._subnetMask = s?.subnetMask ?? this._subnetMask;
+ this._defaultGateway = s?.defaultGateway ?? this._defaultGateway;
+ this._ipResolutionMode = s?.ipResolutionMode ?? this._ipResolutionMode;
}
}
diff --git a/src/Languages/Zpl/ZplPrinterCommandSet.ts b/src/Languages/Zpl/ZplPrinterCommandSet.ts
index 67e2884..ce64d9c 100644
--- a/src/Languages/Zpl/ZplPrinterCommandSet.ts
+++ b/src/Languages/Zpl/ZplPrinterCommandSet.ts
@@ -12,6 +12,7 @@ import { cmdGraphSensorCalibrationMapping } from './CmdGraphSensorCalibration.js
import { cmdSetSensorCalibrationMapping } from './CmdSetSensorCalibration.js';
import { ZplPrinterConfig } from './Config.js';
import { cmdSetPowerUpAndHeadCloseActionMapping } from './CmdSetPowerUpAndHeadCloseAction.js';
+import { cmdSetNetworkIpResolutionModeMapping } from './CmdNetworkSettings.js';
/** Command set for communicating with a ZPL II printer. */
export class ZplPrinterCommandSet extends Cmds.StringCommandSet {
@@ -182,14 +183,15 @@ export class ZplPrinterCommandSet extends Cmds.StringCommandSet {
},
[
cmdConfigUpdateMapping,
+ cmdGraphSensorCalibrationMapping,
cmdHostConfigMapping,
- cmdXmlQueryTypeMapping,
cmdHostIdentificationMapping,
cmdHostQueryMapping,
cmdHostStatusMapping,
+ cmdSetNetworkIpResolutionModeMapping,
cmdSetPowerUpAndHeadCloseActionMapping,
- cmdGraphSensorCalibrationMapping,
cmdSetSensorCalibrationMapping,
+ cmdXmlQueryTypeMapping,
...extendedCommands,
]
);
diff --git a/src/Languages/Zpl/index.ts b/src/Languages/Zpl/index.ts
index 9f0d2d5..1d7be86 100644
--- a/src/Languages/Zpl/index.ts
+++ b/src/Languages/Zpl/index.ts
@@ -7,6 +7,7 @@ export { CmdHostConfig } from './CmdHostConfig.js';
export { CmdHostIdentification } from './CmdHostIdentification.js';
export { CmdHostQuery, HostQueryErrorFlags, HostQueryWarningFlags } from './CmdHostQuery.js';
export { CmdHostStatus } from './CmdHostStatus.js';
+export { CmdSetNetworkIpResolutionMode } from './CmdNetworkSettings.js';
export { CmdSetPowerUpAndHeadCloseAction } from './CmdSetPowerUpAndHeadCloseAction.js';
export { CmdSetSensorCalibration } from './CmdSetSensorCalibration.js';
export { CmdXmlQuery } from './CmdXmlQuery.js';export type { CmdXmlQueryType } from './CmdXmlQuery.js';
diff --git a/src/Languages/Zpl/test_files/LP2844_Z_NET.txt b/src/Languages/Zpl/test_files/LP2844_Z_NET.txt
new file mode 100644
index 0000000..6fea514
--- /dev/null
+++ b/src/Languages/Zpl/test_files/LP2844_Z_NET.txt
@@ -0,0 +1,55 @@
+ 46J000000000
+ +21 DARKNESS
+ +000 TEAR OFF
+ TEAR OFF PRINT MODE
+ NON-CONTINUOUS MEDIA TYPE
+ WEB SENSOR TYPE
+ DIRECT-THERMAL PRINT METHOD
+ 100 0/8 MM PRINT WIDTH
+ 1327 LABEL LENGTH
+ 12.0IN 304MM MAXIMUM LENGTH
+ CONNECTED USB COMM.
+ PARALLEL PARALLEL COMM.
+ RS232 SERIAL COMM.
+ 9600 BAUD
+ 8 BITS DATA BITS
+ NONE PARITY
+ XON/XOFF HOST HANDSHAKE
+ NONE PROTOCOL
+ 000 NETWORK ID
+ NORMAL MODE COMMUNICATIONS
+ <~> 7EH CONTROL PREFIX
+ <^> 5EH FORMAT PREFIX
+ <,> 2CH DELIMITER CHAR
+ ZPL II ZPL MODE
+ NO MOTION MEDIA POWER UP
+ FEED HEAD CLOSE
+ DEFAULT BACKFEED
+ +000 LABEL TOP
+ +0000 LEFT POSITION
+ 079 WEB S.
+ 090 MEDIA S.
+ 017 MARK S.
+ 009 MARK MED S.
+ 070 MEDIA LED
+ 050 RIBBON LED
+ 087 MARK LED
+ CS MODES ENABLED
+ .. MODES DISABLED
+ 832 8/MM FULL RESOLUTION
+ V45.11.7Z <- FIRMWARE
+ V22.0.0.42 HARDWARE ID
+ CUSTOMIZED CONFIGURATION
+ 8192.............R: RAM
+ 2816.............E: ONBOARD FLASH
+ NONE FORMAT CONVERT
+ TWINAX/COAX ID
+ FW VERSION IDLE DISPLAY
+ 05/05/37 RTC DATE
+ 00:00 RTC TIME
+ PERMANENT IP RESOLUTION
+ ALL IP PROTOCOL
+ 010.048.112.191 IP ADDRESS
+ 255.255.255.000 SUBNET MASK
+ 010.048.112.001 DEFAULT GATEWAY
+
\ No newline at end of file
diff --git a/src/Languages/Zpl/test_files/LP2844_Z_NET.xml b/src/Languages/Zpl/test_files/LP2844_Z_NET.xml
new file mode 100644
index 0000000..581b43a
--- /dev/null
+++ b/src/Languages/Zpl/test_files/LP2844_Z_NET.xml
@@ -0,0 +1,458 @@
+
+
+
+ LP2844-Z
+ V45.11.7Z
+ MANUFACTURER:Zebra Technologies;COMMAND SET:ZPL;MODEL:ZTC
+ LP2844-Z-200dpi;CLASS:PRINTER;PROTOCOLS:IEEE1284.4;
+ 8
+ 832
+
+ R
+ 8388608
+ 4153324
+
+
+ E
+ 2883584
+ 2819572
+
+
+ N
+ N
+ N
+ N
+ Y
+ N
+ N
+
+
+
+ SHS_LPRBC1_P4
+
+
+ 21
+ 21
+ 10
+
+
+ 0
+ 0
+ 0
+
+
+
+ TEAR OFF
+ TEAR OFF
+ TEAR OFF
+
+
+
+ NONCONT-WEB
+ NONCONT-WEB
+ NONCONT-WEB
+
+
+ DIRECT-THERMAL
+ DIRECT-THERMAL
+ DIRECT-THERMAL
+
+
+ 800
+ 800
+ 832
+
+
+
+ 9600
+ 9600
+ 9600
+
+
+ 8 BITS
+ 8 BITS
+ 8 BITS
+
+
+ NONE
+ NONE
+ NONE
+
+
+ 2 STOP BITS
+ 1 STOP BIT
+ 1 STOP BIT
+
+
+ XON/XOFF
+ XON/XOFF
+ XON/XOFF
+
+
+ NONE
+ NONE
+ NONE
+
+
+
+ 0
+ 0
+ 0
+
+
+ Y
+ N
+ N
+
+
+ Y
+ Y
+ Y
+
+
+ 126
+ 126
+ 126
+
+
+ 94
+ 94
+ 94
+
+
+ 44
+ 44
+ 44
+
+
+ ZPL II
+ ZPL II
+ ZPL II
+
+
+
+ NO MOTION
+ NO MOTION
+ CALIBRATION
+
+
+ FEED
+ FEED
+ CALIBRATION
+
+
+
+ DEFAULT
+ DEFAULT
+ DEFAULT
+
+
+
+ N
+ N
+ N
+
+
+ 0
+ 0
+ 0
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ 1327
+ 1327
+ 1225
+
+
+ 79
+ 79
+ 50
+
+
+ 90
+ 90
+ 0
+
+
+ 75
+ 75
+ 60
+
+
+ 17
+ 17
+ 50
+
+
+ 9
+ 9
+ 0
+
+
+ 70
+ 70
+ 70
+
+
+ 50
+ 50
+ 50
+
+
+ 87
+ 87
+ 87
+
+
+
+ N
+ N
+ N
+
+
+ ENGLISH
+ ENGLISH
+ ENGLISH
+
+
+
+ N
+ N
+ N
+
+
+ N
+ N
+ N
+
+
+ N
+ N
+ N
+
+
+ N
+ N
+ N
+
+
+ N
+ N
+ N
+
+
+ N
+ N
+ N
+
+
+ N
+ N
+ N
+
+
+ N
+ N
+ N
+
+
+
+
+ B
+ B
+ B
+
+
+ E
+ E
+ E
+
+
+ R
+ R
+ R
+
+
+
+ 1234
+ 1234
+ 1234
+
+
+ AUTO DETECT
+ NONE
+ NONE
+
+
+ HIGH
+ LOW
+ LOW
+
+
+ 2436
+ 2436
+ 7917
+
+
+ 0
+ 0
+ 0
+
+
+ OFF
+ OFF
+ OFF
+
+
+ OFF
+ OFF
+ OFF
+
+
+ PULSE MODE
+ PULSE MODE
+ PULSE MODE
+
+
+ FEED MODE
+ FEED MODE
+ FEED MODE
+
+
+ N
+ N
+ N
+
+
+
+ N
+ N
+ N
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+ N
+ Y
+ DOTS
+ 1327
+ N
+ 0
+
+ 10
+ 37
+
+ 0
+ 2
+ 2
+ 2
+
+ N
+ 0
+ 9999
+
+
+ 65
+ 9
+ 5
+
+
+ 3.0
+ 2
+ 10
+
+
+
+ 0
+ 0
+
+ 300
+ -1
+ 22
+
+
+ N
+
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+
+ 70
+ 0
+
+ N
+
+ 50
+ 0
+
+ 0
+ 1
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+ N
+
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 19??7???
+
+ 7?:??:7?
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Languages/Zpl/test_files/LP2844_Z_NET_CONF.ts.snap b/src/Languages/Zpl/test_files/LP2844_Z_NET_CONF.ts.snap
new file mode 100644
index 0000000..92e9484
--- /dev/null
+++ b/src/Languages/Zpl/test_files/LP2844_Z_NET_CONF.ts.snap
@@ -0,0 +1,31 @@
+{
+ "messageIncomplete": false,
+ "messageMatchedExpectedCommand": true,
+ "messages": [
+ {
+ "messageType": "SettingUpdateMessage",
+ "printerHardware": {},
+ "printerMedia": {
+ "mediaGapDetectMode": 1,
+ "mediaLengthDots": 1327,
+ },
+ "printerSettings": {},
+ "printerZplSettings": {
+ "actionHeadClose": "feedBlank",
+ "actionPowerUp": "none",
+ "defaultGateway": "010.048.112.001",
+ "ipAddress": "010.048.112.191",
+ "ipResolutionMode": "ALL",
+ "markGain": 87,
+ "markMediaThreshold": 9,
+ "markThreshold": 17,
+ "mediaThreshold": 90,
+ "ribbonGain": 50,
+ "subnetMask": "255.255.255.000",
+ "transGain": 70,
+ "webThreshold": 79,
+ },
+ },
+ ],
+ "remainder": "",
+}
\ No newline at end of file
diff --git a/src/Languages/Zpl/test_files/LP2844_Z_NET_FULL.ts.snap b/src/Languages/Zpl/test_files/LP2844_Z_NET_FULL.ts.snap
new file mode 100644
index 0000000..8b50c45
--- /dev/null
+++ b/src/Languages/Zpl/test_files/LP2844_Z_NET_FULL.ts.snap
@@ -0,0 +1,61 @@
+{
+ "messageIncomplete": false,
+ "messageMatchedExpectedCommand": true,
+ "messages": [
+ {
+ "messageType": "SettingUpdateMessage",
+ "printerHardware": {
+ "dpi": 200,
+ "firmware": "V45.11.7Z ",
+ "maxMediaDarkness": 30,
+ "maxMediaLengthDots": 7917,
+ "maxMediaWidthDots": 832,
+ "model": "LP2844-Z",
+ "speedTable": SpeedTable {
+ "speedTable": Map {
+ 0 => 0,
+ 1 => 2,
+ 1000 => 4,
+ 4 => 2,
+ 6 => 3,
+ 8 => 4,
+ },
+ },
+ },
+ "printerMedia": {
+ "darknessPercent": 70,
+ "mediaGapDetectMode": 1,
+ "mediaLengthDots": 1350,
+ "mediaPrintMode": 0,
+ "mediaPrintOriginOffsetDots": {
+ "left": 0,
+ "top": 0,
+ },
+ "mediaWidthDots": 800,
+ "printOrientation": 0,
+ "speed": PrintSpeedSettings {
+ "printSpeed": 4,
+ "slewSpeed": 4,
+ },
+ "thermalPrintMode": 0,
+ },
+ "printerSettings": {
+ "backfeedAfterTaken": "90",
+ },
+ "printerZplSettings": {
+ "actionHeadClose": "feedBlank",
+ "actionPowerUp": "none",
+ "markGain": 87,
+ "markMediaThreshold": 9,
+ "markThreshold": 17,
+ "mediaThreshold": 90,
+ "ribbonGain": 50,
+ "ribbonThreshold": 75,
+ "transBrightness": undefined,
+ "transGain": 70,
+ "webThreshold": 79,
+ },
+ },
+ ],
+ "remainder": "",
+}
\ No newline at end of file
diff --git a/src/Languages/Zpl/test_files/index.test.ts b/src/Languages/Zpl/test_files/index.test.ts
index ed86928..ff1db84 100644
--- a/src/Languages/Zpl/test_files/index.test.ts
+++ b/src/Languages/Zpl/test_files/index.test.ts
@@ -42,6 +42,11 @@ export const LP2844_Z_FULL = getSnap("LP2844_Z_FULL");
export const LP2844_Z_TXT = () => getFile("LP2844_Z.txt");
export const LP2844_Z_CONF = getSnap("LP2844_Z_CONF");
+export const LP2844_Z_NET_XML = () => getFile("LP2844_Z_NET.xml");
+export const LP2844_Z_NET_FULL = getSnap("LP2844_Z_NET_FULL");
+export const LP2844_Z_NET_TXT = () => getFile("LP2844_Z_NET.txt");
+export const LP2844_Z_NET_CONF = getSnap("LP2844_Z_NET_CONF");
+
export const TLP2844_Z_XML = () => getFile("TLP2844_Z.xml");
export const TLP2844_Z_FULL = getSnap("TLP2844_Z_FULL");
export const TLP2844_Z_TXT = () => getFile("TLP2844_Z.txt");