zebra-day 0.0.32__py3-none-any.whl → 1.0.2__py3-none-any.whl

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 (190) hide show
  1. zebra_day/__init__.py +35 -0
  2. zebra_day/bin/fetch_zebra_config.py +15 -0
  3. zebra_day/bin/generate_coord_grid_zpl.py +50 -0
  4. zebra_day/bin/print_zpl_from_file.py +21 -0
  5. zebra_day/bin/probe_new_label_dimensions.py +75 -0
  6. zebra_day/bin/scan_for_networed_zebra_printers_curl.sh +2 -1
  7. zebra_day/bin/zserve.py +701 -259
  8. zebra_day/cli/__init__.py +240 -0
  9. zebra_day/cli/cognito.py +121 -0
  10. zebra_day/cli/gui.py +255 -0
  11. zebra_day/cli/printer.py +168 -0
  12. zebra_day/cli/template.py +176 -0
  13. zebra_day/cmd_mgr.py +35 -0
  14. zebra_day/etc/label_styles/blank.zpl +0 -0
  15. zebra_day/etc/label_styles/cornersStripOf4Squares_1inX1in.zpl +55 -0
  16. zebra_day/etc/label_styles/corners_1inX2in.zpl +28 -0
  17. zebra_day/etc/label_styles/corners_20cmX30cm.zpl +6 -0
  18. zebra_day/etc/label_styles/corners_smallTube.zpl +7 -0
  19. zebra_day/etc/label_styles/corners_unspecifiedDimensions.zpl +15 -0
  20. zebra_day/etc/label_styles/plate_1inX0.25inHD.zpl +9 -0
  21. zebra_day/etc/label_styles/smallTubeWdotHD_prod.zpl +8 -0
  22. zebra_day/etc/label_styles/smallTubeWdot_corners.zpl +7 -0
  23. zebra_day/etc/label_styles/smallTubeWdot_prod.zpl +8 -0
  24. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1.zpl +6 -0
  25. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1b.zpl +3 -0
  26. zebra_day/etc/label_styles/smallTubeWdot_prodV2.zpl +8 -0
  27. zebra_day/etc/label_styles/smallTubeWdot_reagent.zpl +29 -0
  28. zebra_day/etc/label_styles/stripOf4Squares_1inX1in.zpl +32 -0
  29. zebra_day/etc/label_styles/test_800dX800dCoordinateArray.zpl +1 -0
  30. zebra_day/etc/label_styles/tmps/tmp_zpl_templates.here +0 -0
  31. zebra_day/etc/label_styles/tube_20mmX30mmA.zpl +7 -0
  32. zebra_day/etc/label_styles/tube_2inX0.5in.zpl +15 -0
  33. zebra_day/etc/label_styles/tube_2inX0.5inHD.zpl +15 -0
  34. zebra_day/etc/label_styles/tube_2inX1inHD.zpl +22 -0
  35. zebra_day/etc/label_styles/tube_2inX1inHDv3.zpl +21 -0
  36. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.022846_printer_config.json +1 -0
  37. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.033657_printer_config.json +1 -0
  38. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.039597_printer_config.json +3 -0
  39. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.047295_printer_config.json +1 -0
  40. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.055804_printer_config.json +1 -0
  41. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.061337_printer_config.json +3 -0
  42. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.073326_printer_config.json +1 -0
  43. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.081950_printer_config.json +1 -0
  44. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.088251_printer_config.json +3 -0
  45. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.096501_printer_config.json +1 -0
  46. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.104767_printer_config.json +1 -0
  47. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.110364_printer_config.json +3 -0
  48. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.118239_printer_config.json +1 -0
  49. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.125950_printer_config.json +1 -0
  50. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.349866_printer_config.json +1 -0
  51. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.361085_printer_config.json +3 -0
  52. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.558323_printer_config.json +1 -0
  53. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.565756_printer_config.json +3 -0
  54. zebra_day/etc/old_printer_config/{2023-10-25_02:19:04.139607_printer_config.json → 2026-02-01_01:51:29.739070_printer_config.json} +4 -3
  55. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.753796_printer_config.json +1 -0
  56. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.760201_printer_config.json +3 -0
  57. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.768747_printer_config.json +1 -0
  58. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.775312_printer_config.json +3 -0
  59. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.782533_printer_config.json +1 -0
  60. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.789287_printer_config.json +1 -0
  61. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.794230_printer_config.json +3 -0
  62. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.800021_printer_config.json +5 -0
  63. zebra_day/etc/printer_config.json +3 -54
  64. zebra_day/etc/printer_config.template.json +3 -2
  65. zebra_day/etc/tmp_printers0.json +5 -0
  66. zebra_day/etc/tmp_printers374.json +5 -0
  67. zebra_day/etc/tmp_printers383.json +5 -0
  68. zebra_day/etc/tmp_printers450.json +5 -0
  69. zebra_day/etc/tmp_printers504.json +5 -0
  70. zebra_day/etc/tmp_printers608.json +5 -0
  71. zebra_day/etc/tmp_printers657.json +5 -0
  72. zebra_day/etc/tmp_printers838.json +5 -0
  73. zebra_day/etc/tmp_printers839.json +5 -0
  74. zebra_day/etc/tmp_printers933.json +5 -0
  75. zebra_day/etc/tmp_printers957.json +5 -0
  76. zebra_day/exceptions.py +88 -0
  77. zebra_day/files/hold +0 -0
  78. zebra_day/files/test_png_17696.png +0 -0
  79. zebra_day/files/test_png_23477.png +0 -0
  80. zebra_day/files/test_png_28157.png +0 -0
  81. zebra_day/files/test_png_35832.png +0 -0
  82. zebra_day/files/test_png_36400.png +0 -0
  83. zebra_day/files/test_png_40816.png +0 -0
  84. zebra_day/files/test_png_49564.png +0 -0
  85. zebra_day/files/test_png_53848.png +0 -0
  86. zebra_day/files/test_png_62542.png +0 -0
  87. zebra_day/files/test_png_91597.png +0 -0
  88. zebra_day/files/test_png_93633.png +0 -0
  89. zebra_day/files/tmpbjo3k7q1.png +0 -0
  90. zebra_day/files/tmpigtr4pwy.png +0 -0
  91. zebra_day/files/zpl_label_tube_2inX1in_2026-02-01_01:51:24.370964.png +0 -0
  92. zebra_day/logging_config.py +74 -0
  93. zebra_day/logs/.hold +0 -0
  94. zebra_day/logs/print_requests.log +2 -0
  95. zebra_day/paths.py +143 -0
  96. zebra_day/print_mgr.py +489 -103
  97. zebra_day/static/datschund.css +63 -43
  98. zebra_day/static/datschund.png +0 -0
  99. zebra_day/static/daylily.png +0 -0
  100. zebra_day/static/favicon.svg +20 -0
  101. zebra_day/static/general.css +99 -0
  102. zebra_day/static/js/zebra_modern.js +172 -0
  103. zebra_day/static/lsmc.css +354 -0
  104. zebra_day/static/moon.jpeg +0 -0
  105. zebra_day/static/oakland.css +0 -32
  106. zebra_day/static/popday_daylily.css +1 -1
  107. zebra_day/static/style.css +39 -0
  108. zebra_day/static/zebra_modern.css +771 -0
  109. zebra_day/templates/base.html +36 -0
  110. zebra_day/templates/bpr.html +72 -0
  111. zebra_day/templates/build_new_config.html +36 -0
  112. zebra_day/templates/build_print_request.html +32 -0
  113. zebra_day/templates/chg_ui_style.html +19 -0
  114. zebra_day/templates/edit_template.html +128 -0
  115. zebra_day/templates/edit_zpl.html +37 -0
  116. zebra_day/templates/index.html +82 -0
  117. zebra_day/templates/legacy/base.html +37 -0
  118. zebra_day/templates/legacy/bpr.html +72 -0
  119. zebra_day/templates/legacy/build_new_config.html +36 -0
  120. zebra_day/templates/legacy/build_print_request.html +32 -0
  121. zebra_day/templates/legacy/chg_ui_style.html +19 -0
  122. zebra_day/templates/legacy/edit_template.html +128 -0
  123. zebra_day/templates/legacy/edit_zpl.html +37 -0
  124. zebra_day/templates/legacy/index.html +82 -0
  125. zebra_day/templates/legacy/list_prior_configs.html +24 -0
  126. zebra_day/templates/legacy/print_result.html +30 -0
  127. zebra_day/templates/legacy/printer_details.html +25 -0
  128. zebra_day/templates/legacy/printer_status.html +70 -0
  129. zebra_day/templates/legacy/save_result.html +17 -0
  130. zebra_day/templates/legacy/send_print_request.html +34 -0
  131. zebra_day/templates/legacy/simple_print.html +94 -0
  132. zebra_day/templates/legacy/view_pstation_json.html +29 -0
  133. zebra_day/templates/list_prior_configs.html +24 -0
  134. zebra_day/templates/modern/base.html +98 -0
  135. zebra_day/templates/modern/config.html +141 -0
  136. zebra_day/templates/modern/dashboard.html +160 -0
  137. zebra_day/templates/modern/print_request.html +141 -0
  138. zebra_day/templates/modern/print_result.html +88 -0
  139. zebra_day/templates/modern/printer_detail.html +117 -0
  140. zebra_day/templates/modern/printers.html +133 -0
  141. zebra_day/templates/modern/save_result.html +46 -0
  142. zebra_day/templates/modern/template_editor.html +172 -0
  143. zebra_day/templates/modern/templates.html +122 -0
  144. zebra_day/templates/print_result.html +30 -0
  145. zebra_day/templates/printer_details.html +25 -0
  146. zebra_day/templates/printer_status.html +70 -0
  147. zebra_day/templates/save_result.html +17 -0
  148. zebra_day/templates/send_print_request.html +34 -0
  149. zebra_day/templates/simple_print.html +94 -0
  150. zebra_day/templates/view_pstation_json.html +29 -0
  151. zebra_day/web/__init__.py +9 -0
  152. zebra_day/web/app.py +171 -0
  153. zebra_day/web/auth.py +172 -0
  154. zebra_day/web/middleware.py +159 -0
  155. zebra_day/web/routers/__init__.py +2 -0
  156. zebra_day/web/routers/api.py +163 -0
  157. zebra_day/web/routers/ui.py +1051 -0
  158. zebra_day/zpl_renderer.py +273 -0
  159. zebra_day-1.0.2.dist-info/METADATA +786 -0
  160. zebra_day-1.0.2.dist-info/RECORD +179 -0
  161. {zebra_day-0.0.32.dist-info → zebra_day-1.0.2.dist-info}/WHEEL +1 -1
  162. zebra_day-1.0.2.dist-info/entry_points.txt +4 -0
  163. zebra_day/etc/.blind +0 -1
  164. zebra_day/etc/current_style.txt +0 -1
  165. zebra_day/etc/label_styles/test_2inX1in.zpl +0 -22
  166. zebra_day/etc/label_styles/tmps/labware_2inX1in.na.2023-10-24_12:49:21.045127.zpl +0 -21
  167. zebra_day/etc/label_styles/tmps/labware_2inX1in.naggg.2023-10-24_16:02:04.704814.8888.2023-10-24_16:02:16.443911.zpl +0 -21
  168. zebra_day/etc/label_styles/tmps/labware_2inX1in.naggg.2023-10-24_16:02:04.704814.zpl +0 -21
  169. zebra_day/etc/label_styles/tmps/test_2inX1in.na.2023-10-24_12:45:37.002774.zpl +0 -22
  170. zebra_day/etc/old_printer_config/2023-10-24_16:06:06.931764_printer_config.json +0 -67
  171. zebra_day/etc/printer_config.json~ +0 -67
  172. zebra_day/files/tmp_2olihg4.png +0 -0
  173. zebra_day/files/tmpveojoyvn.png +0 -0
  174. zebra_day/files/zpl_label_labware_2inX1in_2023-10-25_02:30:08.093631.png +0 -0
  175. zebra_day/files/zpl_label_test_2inX1in_2023-10-24_15:54:29.343124.png +0 -0
  176. zebra_day/files/zpl_label_test_2inX1in_2023-10-24_16:01:45.670132.png +0 -0
  177. zebra_day/static/beyonce.css +0 -227
  178. zebra_day/static/datschund_on_moon.css +0 -164
  179. zebra_day/static/medicalsci.css +0 -144
  180. zebra_day/static/moar_zebra.css +0 -133
  181. zebra_day/static/popday.css +0 -140
  182. zebra_day/static/popday_dark.css +0 -140
  183. zebra_day/static/popday_dog.css +0 -140
  184. zebra_day-0.0.32.dist-info/METADATA +0 -14
  185. zebra_day-0.0.32.dist-info/RECORD +0 -53
  186. zebra_day-0.0.32.dist-info/entry_points.txt +0 -2
  187. /zebra_day/{etc/label_styles/blank_0inX0in.zpl → bin/__init__.py} +0 -0
  188. /zebra_day/etc/label_styles/{labware_2inX1in.zpl → generic_2inX1in.zpl} +0 -0
  189. {zebra_day-0.0.32.dist-info → zebra_day-1.0.2.dist-info/licenses}/LICENSE +0 -0
  190. {zebra_day-0.0.32.dist-info → zebra_day-1.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,168 @@
1
+ """Printer fleet management commands for zebra_day CLI."""
2
+
3
+ import json
4
+ import socket
5
+ from typing import Optional
6
+
7
+ import typer
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+
11
+ from zebra_day import paths as xdg
12
+
13
+ printer_app = typer.Typer(help="Printer fleet management commands")
14
+ console = Console()
15
+
16
+
17
+ def _get_local_ip() -> str:
18
+ """Get local IP address."""
19
+ try:
20
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
21
+ s.connect(("8.8.8.8", 80))
22
+ ip = s.getsockname()[0]
23
+ s.close()
24
+ return ip
25
+ except Exception:
26
+ return "127.0.0.1"
27
+
28
+
29
+ @printer_app.command("scan")
30
+ def scan(
31
+ ip_stub: Optional[str] = typer.Option(None, "--ip-stub", "-i", help="IP stub to scan (e.g., 192.168.1)"),
32
+ wait: float = typer.Option(0.25, "--wait", "-w", help="Seconds to wait per IP probe"),
33
+ lab: str = typer.Option("scan-results", "--lab", "-l", help="Lab name to assign found printers"),
34
+ json_output: bool = typer.Option(False, "--json", "-j", help="Output as JSON"),
35
+ ):
36
+ """Scan network for Zebra printers."""
37
+ # Determine IP stub if not provided
38
+ if not ip_stub:
39
+ local_ip = _get_local_ip()
40
+ ip_stub = ".".join(local_ip.split(".")[:-1])
41
+
42
+ if not json_output:
43
+ console.print(f"[cyan]→[/cyan] Scanning {ip_stub}.* for Zebra printers...")
44
+ console.print("[dim] This may take a few minutes...[/dim]")
45
+
46
+ try:
47
+ import zebra_day.print_mgr as zdpm
48
+ zp = zdpm.zpl()
49
+ zp.probe_zebra_printers_add_to_printers_json(
50
+ ip_stub=ip_stub,
51
+ scan_wait=str(wait),
52
+ lab=lab,
53
+ )
54
+
55
+ found = []
56
+ if hasattr(zp, "printers") and "labs" in zp.printers and lab in zp.printers["labs"]:
57
+ for name, info in zp.printers["labs"][lab].items():
58
+ if isinstance(info, dict) and info.get("ip_address") not in ["dl_png"]:
59
+ found.append({
60
+ "name": name,
61
+ "ip": info.get("ip_address"),
62
+ "model": info.get("model", "unknown"),
63
+ "serial": info.get("serial", "unknown"),
64
+ })
65
+
66
+ if json_output:
67
+ console.print(json.dumps(found, indent=2))
68
+ else:
69
+ console.print(f"\n[green]✓[/green] Found {len(found)} printer(s)")
70
+ if found:
71
+ table = Table()
72
+ table.add_column("Name", style="cyan")
73
+ table.add_column("IP Address")
74
+ table.add_column("Model")
75
+ table.add_column("Serial")
76
+ for p in found:
77
+ table.add_row(p["name"], p["ip"], p["model"], p["serial"])
78
+ console.print(table)
79
+
80
+ except Exception as e:
81
+ if json_output:
82
+ console.print(json.dumps({"error": str(e)}))
83
+ else:
84
+ console.print(f"[red]✗[/red] Scan error: {e}")
85
+ raise typer.Exit(1)
86
+
87
+
88
+ @printer_app.command("list")
89
+ def list_printers(
90
+ lab: Optional[str] = typer.Option(None, "--lab", "-l", help="Filter by lab name"),
91
+ json_output: bool = typer.Option(False, "--json", "-j", help="Output as JSON"),
92
+ ):
93
+ """List configured printers."""
94
+ try:
95
+ import zebra_day.print_mgr as zdpm
96
+ zp = zdpm.zpl()
97
+
98
+ printers = []
99
+ if hasattr(zp, "printers") and "labs" in zp.printers:
100
+ for lab_name, lab_printers in zp.printers["labs"].items():
101
+ if lab and lab_name != lab:
102
+ continue
103
+ for name, info in lab_printers.items():
104
+ if isinstance(info, dict):
105
+ printers.append({
106
+ "lab": lab_name,
107
+ "name": name,
108
+ "ip": info.get("ip_address", "unknown"),
109
+ "model": info.get("model", "unknown"),
110
+ "styles": info.get("label_zpl_styles", []),
111
+ })
112
+
113
+ if json_output:
114
+ console.print(json.dumps(printers, indent=2))
115
+ return
116
+
117
+ if not printers:
118
+ console.print("[yellow]⚠[/yellow] No printers configured")
119
+ console.print(" Run [cyan]zday printer scan[/cyan] to discover printers")
120
+ return
121
+
122
+ table = Table(title="Configured Printers")
123
+ table.add_column("Lab", style="cyan")
124
+ table.add_column("Name")
125
+ table.add_column("IP Address")
126
+ table.add_column("Model")
127
+ table.add_column("Label Styles")
128
+ for p in printers:
129
+ styles = ", ".join(p["styles"][:2])
130
+ if len(p["styles"]) > 2:
131
+ styles += f" (+{len(p['styles'])-2})"
132
+ table.add_row(p["lab"], p["name"], p["ip"], p["model"], styles)
133
+ console.print(table)
134
+
135
+ except Exception as e:
136
+ if json_output:
137
+ console.print(json.dumps({"error": str(e)}))
138
+ else:
139
+ console.print(f"[red]✗[/red] Error: {e}")
140
+ raise typer.Exit(1)
141
+
142
+
143
+ @printer_app.command("test")
144
+ def test_print(
145
+ printer_name: str = typer.Argument(..., help="Printer name or IP address"),
146
+ lab: str = typer.Option("scan-results", "--lab", "-l", help="Lab containing the printer"),
147
+ label_style: str = typer.Option("tube_2inX1in", "--style", "-s", help="Label style to print"),
148
+ ):
149
+ """Send a test print to a specific printer."""
150
+ try:
151
+ import zebra_day.print_mgr as zdpm
152
+ zp = zdpm.zpl()
153
+
154
+ console.print(f"[cyan]→[/cyan] Sending test print to {printer_name}...")
155
+ result = zp.print_zpl(
156
+ lab=lab,
157
+ printer_name=printer_name,
158
+ uid_barcode="TEST-PRINT",
159
+ alt_a="Test Label",
160
+ alt_b="zebra_day CLI",
161
+ label_zpl_style=label_style,
162
+ )
163
+ console.print(f"[green]✓[/green] Test print sent successfully")
164
+
165
+ except Exception as e:
166
+ console.print(f"[red]✗[/red] Print error: {e}")
167
+ raise typer.Exit(1)
168
+
@@ -0,0 +1,176 @@
1
+ """ZPL template management commands for zebra_day CLI."""
2
+
3
+ import json
4
+ import os
5
+ import subprocess
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ import typer
10
+ from rich.console import Console
11
+ from rich.table import Table
12
+
13
+ from zebra_day import paths as xdg
14
+
15
+ template_app = typer.Typer(help="ZPL template management commands")
16
+ console = Console()
17
+
18
+
19
+ def _get_template_dirs() -> list[Path]:
20
+ """Get all template directories."""
21
+ from importlib.resources import files
22
+
23
+ dirs = []
24
+ # XDG data directory
25
+ xdg_styles = xdg.get_label_styles_dir()
26
+ if xdg_styles.exists():
27
+ dirs.append(xdg_styles)
28
+
29
+ # Package directory
30
+ try:
31
+ pkg_styles = Path(str(files("zebra_day"))) / "etc" / "label_styles"
32
+ if pkg_styles.exists():
33
+ dirs.append(pkg_styles)
34
+ except Exception:
35
+ pass
36
+
37
+ return dirs
38
+
39
+
40
+ def _find_template(name: str) -> Optional[Path]:
41
+ """Find a template file by name."""
42
+ for template_dir in _get_template_dirs():
43
+ # Try exact match
44
+ for ext in ["", ".zpl", ".txt"]:
45
+ path = template_dir / f"{name}{ext}"
46
+ if path.exists():
47
+ return path
48
+ # Try with zpl_ prefix
49
+ for ext in ["", ".zpl", ".txt"]:
50
+ path = template_dir / f"zpl_{name}{ext}"
51
+ if path.exists():
52
+ return path
53
+ return None
54
+
55
+
56
+ @template_app.command("list")
57
+ def list_templates(
58
+ json_output: bool = typer.Option(False, "--json", "-j", help="Output as JSON"),
59
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Show full paths"),
60
+ ):
61
+ """List available ZPL templates."""
62
+ templates = []
63
+
64
+ for template_dir in _get_template_dirs():
65
+ for f in template_dir.iterdir():
66
+ if f.is_file() and not f.name.startswith("."):
67
+ if f.suffix in [".zpl", ".txt", ""] or f.name.startswith("zpl_"):
68
+ templates.append({
69
+ "name": f.stem,
70
+ "path": str(f),
71
+ "size": f.stat().st_size,
72
+ "source": "user" if "zebra_day" not in str(template_dir) else "package",
73
+ })
74
+
75
+ # Dedupe by name, prefer user templates
76
+ seen = {}
77
+ for t in templates:
78
+ if t["name"] not in seen or t["source"] == "user":
79
+ seen[t["name"]] = t
80
+ templates = list(seen.values())
81
+
82
+ if json_output:
83
+ console.print(json.dumps(templates, indent=2))
84
+ return
85
+
86
+ if not templates:
87
+ console.print("[yellow]⚠[/yellow] No templates found")
88
+ return
89
+
90
+ table = Table(title="ZPL Templates")
91
+ table.add_column("Name", style="cyan")
92
+ table.add_column("Source")
93
+ table.add_column("Size")
94
+ if verbose:
95
+ table.add_column("Path", style="dim")
96
+
97
+ for t in sorted(templates, key=lambda x: x["name"]):
98
+ source_style = "[green]user[/green]" if t["source"] == "user" else "[dim]package[/dim]"
99
+ if verbose:
100
+ table.add_row(t["name"], source_style, f"{t['size']} bytes", t["path"])
101
+ else:
102
+ table.add_row(t["name"], source_style, f"{t['size']} bytes")
103
+
104
+ console.print(table)
105
+
106
+
107
+ @template_app.command("preview")
108
+ def preview(
109
+ template_name: str = typer.Argument(..., help="Template name to preview"),
110
+ output: Optional[str] = typer.Option(None, "--output", "-o", help="Output PNG file path"),
111
+ ):
112
+ """Generate a PNG preview of a ZPL template."""
113
+ template_path = _find_template(template_name)
114
+ if not template_path:
115
+ console.print(f"[red]✗[/red] Template not found: {template_name}")
116
+ raise typer.Exit(1)
117
+
118
+ console.print(f"[cyan]→[/cyan] Generating preview for {template_name}...")
119
+
120
+ try:
121
+ import zebra_day.print_mgr as zdpm
122
+ zp = zdpm.zpl()
123
+
124
+ # Read template
125
+ zpl_content = template_path.read_text()
126
+
127
+ # Generate PNG
128
+ if not output:
129
+ output_path = xdg.get_generated_files_dir() / f"{template_name}_preview.png"
130
+ else:
131
+ output_path = Path(output)
132
+
133
+ result = zp.generate_label_png(zpl_content, str(output_path), False)
134
+ console.print(f"[green]✓[/green] Preview generated: {output_path}")
135
+
136
+ except Exception as e:
137
+ console.print(f"[red]✗[/red] Preview error: {e}")
138
+ raise typer.Exit(1)
139
+
140
+
141
+ @template_app.command("edit")
142
+ def edit(
143
+ template_name: str = typer.Argument(..., help="Template name to edit"),
144
+ editor: Optional[str] = typer.Option(None, "--editor", "-e", help="Editor command"),
145
+ ):
146
+ """Open a ZPL template in an editor."""
147
+ template_path = _find_template(template_name)
148
+ if not template_path:
149
+ console.print(f"[red]✗[/red] Template not found: {template_name}")
150
+ raise typer.Exit(1)
151
+
152
+ # Determine editor
153
+ if not editor:
154
+ editor = os.environ.get("VISUAL") or os.environ.get("EDITOR") or "vi"
155
+
156
+ console.print(f"[cyan]→[/cyan] Opening {template_path} with {editor}...")
157
+ try:
158
+ subprocess.run([editor, str(template_path)])
159
+ except Exception as e:
160
+ console.print(f"[red]✗[/red] Error opening editor: {e}")
161
+ raise typer.Exit(1)
162
+
163
+
164
+ @template_app.command("show")
165
+ def show(
166
+ template_name: str = typer.Argument(..., help="Template name to display"),
167
+ ):
168
+ """Display the contents of a ZPL template."""
169
+ template_path = _find_template(template_name)
170
+ if not template_path:
171
+ console.print(f"[red]✗[/red] Template not found: {template_name}")
172
+ raise typer.Exit(1)
173
+
174
+ console.print(f"[dim]# {template_path}[/dim]\n")
175
+ console.print(template_path.read_text())
176
+
zebra_day/cmd_mgr.py ADDED
@@ -0,0 +1,35 @@
1
+ """
2
+ Tools to manage a zebra printer fleet and expose an API for routing print requests.
3
+ """
4
+
5
+ import socket
6
+
7
+ class ZebraPrinter:
8
+
9
+ def __init__(self, ip_address, port=9100, buffer_size=1024):
10
+ self.ip_address = ip_address
11
+ self.port = port
12
+ self.buffer_size = buffer_size
13
+
14
+
15
+ def send_command(self, command):
16
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
17
+ s.connect((self.ip_address, self.port))
18
+ s.sendall(command.encode())
19
+ response = s.recv(self.buffer_size)
20
+ return response.decode()
21
+
22
+
23
+ def get_configuration(self):
24
+ """Retrieve printer configuration using ^HH command"""
25
+ return self.send_command("^XA^HH^XZ")
26
+
27
+
28
+ def set_configuration(self, config):
29
+ """
30
+ Set printer configuration.
31
+ The `config` parameter should contain the necessary ZPL commands to adjust the configuration.
32
+ After sending the configuration commands, the ^JUS command saves the configuration.
33
+ """
34
+ self.send_command(config)
35
+ return self.send_command("^XA^JUS^XZ")
File without changes
@@ -0,0 +1,55 @@
1
+ ^XA
2
+ ^FO25,10
3
+ ^ADN,20,12
4
+ ^FDWW^FS
5
+ ^FO180,10
6
+ ^ADN,20,12
7
+ ^FDXX^FS
8
+ ^FO180,150
9
+ ^ADN,20,12
10
+ ^FDYY^FS
11
+ ^FO25,150
12
+ ^ADN,20,12
13
+ ^FDZZ^FS
14
+
15
+ ^FO225,10
16
+ ^ADN,20,12
17
+ ^FDWW^FS
18
+ ^FO380,10
19
+ ^ADN,20,12
20
+ ^FDXX^FS
21
+ ^FO380,150
22
+ ^ADN,20,12
23
+ ^FDYY^FS
24
+ ^FO225,150
25
+ ^ADN,20,12
26
+ ^FDZZ^FS
27
+
28
+ ^FO450,10
29
+ ^ADN,20,12
30
+ ^FDWW^FS
31
+ ^FO570,10
32
+ ^ADN,20,12
33
+ ^FDXX^FS
34
+ ^FO570,150
35
+ ^ADN,20,12
36
+ ^FDYY^FS
37
+ ^FO450,150
38
+ ^ADN,20,12
39
+ ^FDZZ^FS
40
+
41
+
42
+ ^FO660,10
43
+ ^ADN,20,12
44
+ ^FDWW^FS
45
+ ^FO780,10
46
+ ^ADN,20,12
47
+ ^FDXX^FS
48
+ ^FO780,150
49
+ ^ADN,20,12
50
+ ^FDYY^FS
51
+ ^FO660,150
52
+ ^ADN,20,12
53
+ ^FDZZ^FS
54
+
55
+ ^XZ
@@ -0,0 +1,28 @@
1
+ ^XA ; Start of ZPL
2
+ ^MMT ; Print mode: Tear-off
3
+ ^PW406 ; Label width: 2 inches x 203 DPI = 406 dots
4
+ ^LL203 ; Label length: 1 inch x 203 DPI = 203 dots
5
+ ^LS0 ; Label shift: no shift
6
+
7
+ ; Top-left 'X'
8
+ ^FO5,5 ; Position: 5 dots from left, 5 dots from top
9
+ ^A0N,24,24 ; Font: scalable, height: 24 dots, width: 24 dots
10
+ ^FDX^FS ; Data: 'X'
11
+
12
+ ; Top-right 'X'
13
+ ^FO376,5 ; Position: (2 inches - width of 'X' - 5 dots) from left, 5 dots from top
14
+ ^A0N,24,24
15
+ ^FDX^FS
16
+
17
+ ; Bottom-left 'X'
18
+ ^FO5,174 ; Position: 5 dots from left, (1 inch - height of 'X' - 5 dots) from top
19
+ ^A0N,24,24
20
+ ^FDX^FS
21
+
22
+ ; Bottom-right 'X'
23
+ ^FO376,174
24
+ ^A0N,24,24
25
+ ^FDX^FS
26
+
27
+ ^PQ1 ; Print quantity: 1 label
28
+ ^XZ ; End of ZPL
@@ -0,0 +1,6 @@
1
+ ^XA
2
+ ^FO300,10^FDX^FS
3
+ ^FO100,10^FDX^FS
4
+ ^FO300,150^FDX^FS
5
+ ^FO100,150^FDX^FS
6
+ ^XZ
@@ -0,0 +1,7 @@
1
+ ^XA
2
+ ^FO120,10^FDX^FS
3
+ ^FO120,110^FDX^FS
4
+ ^FO355,10^FDX^FS
5
+ ^FO355,110^FDX^FS
6
+ ^FO433,63^FDX^FS
7
+ ^XZ
@@ -0,0 +1,15 @@
1
+ ^XA
2
+ ^FO30,10
3
+ ^ADN,30,20
4
+ ^FD{XX}^FS
5
+ ^FO300,10
6
+ ^ADN,30,20
7
+ ^FD{YY}^FS
8
+ ^FO300,200
9
+ ^ADN,25,12
10
+ ^FD{ZZ}^FS
11
+ ^FO250,10
12
+ ^FO30,170
13
+ ^ADN,30,20
14
+ ^FD{WW}^FS
15
+ ^XZ
@@ -0,0 +1,9 @@
1
+ ^XA
2
+ ^FO220,15
3
+ ^BY1
4
+ ^B3N,N,33,N,N
5
+ ^FD{uid_barcode}^FS
6
+ ^FO220,53
7
+ ^ADN,30,17
8
+ ^FD{uid_barcode} : {alt_a}^FS
9
+ ^XZ
@@ -0,0 +1,8 @@
1
+ ^XA
2
+ ^FO395,23^BY1.5^BCN,75,N,N,N^FD{uid_barcode}^FS
3
+ ^FO395,105^A0N,48,48^FD{uid_barcode}^FS
4
+ ^FO395,150^A0N,48,48^FD{alt_a}^FS
5
+ ^FO815,75
6
+ ^BXN,4.5,300
7
+ ^FD{uid_barcode}^FS
8
+ ^XZ
@@ -0,0 +1,7 @@
1
+ ^XA
2
+ ^FO240,10^FDX^FS
3
+ ^FO240,110^FDX^FS
4
+ ^FO465,10^FDX^FS
5
+ ^FO465,110^FDX^FS
6
+ ^FO553,63^FDX^FS
7
+ ^XZ
@@ -0,0 +1,8 @@
1
+ ^XA
2
+ ^FO250,15^BY1^BCN,50,N,N,N^FD{uid_barcode}^FS
3
+ ^FO250,70^A0N,32,32^FD{uid_barcode}^FS
4
+ ^FO250,100^A0N,32,32^FD{alt_a}^FS
5
+ ^FO535,50
6
+ ^BXN,3,200
7
+ ^FD{uid_barcode}^FS
8
+ ^XZ
@@ -0,0 +1,6 @@
1
+ ^XA
2
+ ^FO250,15^BY1^BCN,50,N,N,N^FD{uid_barcode}^FS
3
+ ^FO250,70^A0N,32,32^FD{uid_barcode}^FS
4
+ ^FO250,100^A0N,32,32^FD{alt_a}^FS
5
+ ^FO510,65^A0N,16,16^FD{alt_a}^FS
6
+ ^XZ
@@ -0,0 +1,3 @@
1
+ ^XA
2
+ ^FO250,50^A0N,26,26^FD{alt_b}^FS
3
+ ^XZ
@@ -0,0 +1,8 @@
1
+ ^XA
2
+ ^FO350,15^A0N,32,32^FD{alt_a}^FS
3
+ ^FO350,50^A0N,16,16^FD{uid_barcode}^FS
4
+ ^FO350,70^BY1^BCN,50,N,N,N^FD{uid_barcode}^FS
5
+ ^FO265,30
6
+ ^BXN,3,200
7
+ ^FD{uid_barcode}^FS
8
+ ^XZ
@@ -0,0 +1,29 @@
1
+ ^XA
2
+ ^FO150,12
3
+ ^A0N, 12, 12
4
+ ^FDName:^FS
5
+ ^A0N, 12, 12
6
+ ^FO150,27
7
+ ^FDLot Number:^FS
8
+ ^FO150,40
9
+ ^A0N, 12, 12
10
+ ^FDPrep Date: DDMMMYYYY^FS
11
+ ^FO82,40
12
+ ^A0N, 12, 12
13
+ ^FD123456^FS
14
+ ^FO90,58
15
+ ^A0N, 12, 12
16
+ ^FD123^FS
17
+ ^FO150,54
18
+ ^A0N, 12, 12
19
+ ^FDExp Date: DDMMMYYYY^FS
20
+ ^FO150,68
21
+ ^A0N, 12, 12
22
+ ^FDStore At:^FS
23
+ ^FO150,82
24
+ ^A0N, 12, 12
25
+ ^FDMade By:^FS
26
+ ^FO300,27
27
+ ^BQN,2,3
28
+ ^FDNameLotPrepEXP^FS
29
+ ^XZ
@@ -0,0 +1,32 @@
1
+ ^XA
2
+ ^FO30,30
3
+ ^ADN,30,24
4
+ ^FD{alt_a}^FS
5
+ ^FO30,85
6
+ ^ADN,20,12
7
+ ^FD{alt_b}^FS
8
+
9
+ ^FO230,30
10
+ ^ADN,30,24
11
+ ^FD{alt_a}^FS
12
+ ^FO230,85
13
+ ^ADN,20,12
14
+ ^FD{alt_b}^FS
15
+
16
+
17
+ ^FO450,30
18
+ ^ADN,30,24
19
+ ^FD{alt_a}^FS
20
+ ^FO450,85
21
+ ^ADN,20,12
22
+ ^FD{alt_b}^FS
23
+
24
+
25
+ ^FO650,30
26
+ ^ADN,30,24
27
+ ^FD{alt_a}^FS
28
+ ^FO650,85
29
+ ^ADN,20,12
30
+ ^FD{alt_b}^FS
31
+
32
+ ^XZ
@@ -0,0 +1 @@
1
+ ^XA^FO0,0^A0N,18,18^FD0^FS^FO0,20^A0N,18,18^FD0^FS^FO0,50^A0N,18,18^FD0^FS^FO0,70^A0N,18,18^FD50^FS^FO0,100^A0N,18,18^FD0^FS^FO0,120^A0N,18,18^FD100^FS^FO0,150^A0N,18,18^FD0^FS^FO0,170^A0N,18,18^FD150^FS^FO0,200^A0N,18,18^FD0^FS^FO0,220^A0N,18,18^FD200^FS^FO0,250^A0N,18,18^FD0^FS^FO0,270^A0N,18,18^FD250^FS^FO0,300^A0N,18,18^FD0^FS^FO0,320^A0N,18,18^FD300^FS^FO0,350^A0N,18,18^FD0^FS^FO0,370^A0N,18,18^FD350^FS^FO0,400^A0N,18,18^FD0^FS^FO0,420^A0N,18,18^FD400^FS^FO0,450^A0N,18,18^FD0^FS^FO0,470^A0N,18,18^FD450^FS^FO0,500^A0N,18,18^FD0^FS^FO0,520^A0N,18,18^FD500^FS^FO0,550^A0N,18,18^FD0^FS^FO0,570^A0N,18,18^FD550^FS^FO0,600^A0N,18,18^FD0^FS^FO0,620^A0N,18,18^FD600^FS^FO0,650^A0N,18,18^FD0^FS^FO0,670^A0N,18,18^FD650^FS^FO0,700^A0N,18,18^FD0^FS^FO0,720^A0N,18,18^FD700^FS^FO0,750^A0N,18,18^FD0^FS^FO0,770^A0N,18,18^FD750^FS^FO50,0^A0N,18,18^FD50^FS^FO50,20^A0N,18,18^FD0^FS^FO50,50^A0N,18,18^FD50^FS^FO50,70^A0N,18,18^FD50^FS^FO50,100^A0N,18,18^FD50^FS^FO50,120^A0N,18,18^FD100^FS^FO50,150^A0N,18,18^FD50^FS^FO50,170^A0N,18,18^FD150^FS^FO50,200^A0N,18,18^FD50^FS^FO50,220^A0N,18,18^FD200^FS^FO50,250^A0N,18,18^FD50^FS^FO50,270^A0N,18,18^FD250^FS^FO50,300^A0N,18,18^FD50^FS^FO50,320^A0N,18,18^FD300^FS^FO50,350^A0N,18,18^FD50^FS^FO50,370^A0N,18,18^FD350^FS^FO50,400^A0N,18,18^FD50^FS^FO50,420^A0N,18,18^FD400^FS^FO50,450^A0N,18,18^FD50^FS^FO50,470^A0N,18,18^FD450^FS^FO50,500^A0N,18,18^FD50^FS^FO50,520^A0N,18,18^FD500^FS^FO50,550^A0N,18,18^FD50^FS^FO50,570^A0N,18,18^FD550^FS^FO50,600^A0N,18,18^FD50^FS^FO50,620^A0N,18,18^FD600^FS^FO50,650^A0N,18,18^FD50^FS^FO50,670^A0N,18,18^FD650^FS^FO50,700^A0N,18,18^FD50^FS^FO50,720^A0N,18,18^FD700^FS^FO50,750^A0N,18,18^FD50^FS^FO50,770^A0N,18,18^FD750^FS^FO100,0^A0N,18,18^FD100^FS^FO100,20^A0N,18,18^FD0^FS^FO100,50^A0N,18,18^FD100^FS^FO100,70^A0N,18,18^FD50^FS^FO100,100^A0N,18,18^FD100^FS^FO100,120^A0N,18,18^FD100^FS^FO100,150^A0N,18,18^FD100^FS^FO100,170^A0N,18,18^FD150^FS^FO100,200^A0N,18,18^FD100^FS^FO100,220^A0N,18,18^FD200^FS^FO100,250^A0N,18,18^FD100^FS^FO100,270^A0N,18,18^FD250^FS^FO100,300^A0N,18,18^FD100^FS^FO100,320^A0N,18,18^FD300^FS^FO100,350^A0N,18,18^FD100^FS^FO100,370^A0N,18,18^FD350^FS^FO100,400^A0N,18,18^FD100^FS^FO100,420^A0N,18,18^FD400^FS^FO100,450^A0N,18,18^FD100^FS^FO100,470^A0N,18,18^FD450^FS^FO100,500^A0N,18,18^FD100^FS^FO100,520^A0N,18,18^FD500^FS^FO100,550^A0N,18,18^FD100^FS^FO100,570^A0N,18,18^FD550^FS^FO100,600^A0N,18,18^FD100^FS^FO100,620^A0N,18,18^FD600^FS^FO100,650^A0N,18,18^FD100^FS^FO100,670^A0N,18,18^FD650^FS^FO100,700^A0N,18,18^FD100^FS^FO100,720^A0N,18,18^FD700^FS^FO100,750^A0N,18,18^FD100^FS^FO100,770^A0N,18,18^FD750^FS^FO150,0^A0N,18,18^FD150^FS^FO150,20^A0N,18,18^FD0^FS^FO150,50^A0N,18,18^FD150^FS^FO150,70^A0N,18,18^FD50^FS^FO150,100^A0N,18,18^FD150^FS^FO150,120^A0N,18,18^FD100^FS^FO150,150^A0N,18,18^FD150^FS^FO150,170^A0N,18,18^FD150^FS^FO150,200^A0N,18,18^FD150^FS^FO150,220^A0N,18,18^FD200^FS^FO150,250^A0N,18,18^FD150^FS^FO150,270^A0N,18,18^FD250^FS^FO150,300^A0N,18,18^FD150^FS^FO150,320^A0N,18,18^FD300^FS^FO150,350^A0N,18,18^FD150^FS^FO150,370^A0N,18,18^FD350^FS^FO150,400^A0N,18,18^FD150^FS^FO150,420^A0N,18,18^FD400^FS^FO150,450^A0N,18,18^FD150^FS^FO150,470^A0N,18,18^FD450^FS^FO150,500^A0N,18,18^FD150^FS^FO150,520^A0N,18,18^FD500^FS^FO150,550^A0N,18,18^FD150^FS^FO150,570^A0N,18,18^FD550^FS^FO150,600^A0N,18,18^FD150^FS^FO150,620^A0N,18,18^FD600^FS^FO150,650^A0N,18,18^FD150^FS^FO150,670^A0N,18,18^FD650^FS^FO150,700^A0N,18,18^FD150^FS^FO150,720^A0N,18,18^FD700^FS^FO150,750^A0N,18,18^FD150^FS^FO150,770^A0N,18,18^FD750^FS^FO200,0^A0N,18,18^FD200^FS^FO200,20^A0N,18,18^FD0^FS^FO200,50^A0N,18,18^FD200^FS^FO200,70^A0N,18,18^FD50^FS^FO200,100^A0N,18,18^FD200^FS^FO200,120^A0N,18,18^FD100^FS^FO200,150^A0N,18,18^FD200^FS^FO200,170^A0N,18,18^FD150^FS^FO200,200^A0N,18,18^FD200^FS^FO200,220^A0N,18,18^FD200^FS^FO200,250^A0N,18,18^FD200^FS^FO200,270^A0N,18,18^FD250^FS^FO200,300^A0N,18,18^FD200^FS^FO200,320^A0N,18,18^FD300^FS^FO200,350^A0N,18,18^FD200^FS^FO200,370^A0N,18,18^FD350^FS^FO200,400^A0N,18,18^FD200^FS^FO200,420^A0N,18,18^FD400^FS^FO200,450^A0N,18,18^FD200^FS^FO200,470^A0N,18,18^FD450^FS^FO200,500^A0N,18,18^FD200^FS^FO200,520^A0N,18,18^FD500^FS^FO200,550^A0N,18,18^FD200^FS^FO200,570^A0N,18,18^FD550^FS^FO200,600^A0N,18,18^FD200^FS^FO200,620^A0N,18,18^FD600^FS^FO200,650^A0N,18,18^FD200^FS^FO200,670^A0N,18,18^FD650^FS^FO200,700^A0N,18,18^FD200^FS^FO200,720^A0N,18,18^FD700^FS^FO200,750^A0N,18,18^FD200^FS^FO200,770^A0N,18,18^FD750^FS^FO250,0^A0N,18,18^FD250^FS^FO250,20^A0N,18,18^FD0^FS^FO250,50^A0N,18,18^FD250^FS^FO250,70^A0N,18,18^FD50^FS^FO250,100^A0N,18,18^FD250^FS^FO250,120^A0N,18,18^FD100^FS^FO250,150^A0N,18,18^FD250^FS^FO250,170^A0N,18,18^FD150^FS^FO250,200^A0N,18,18^FD250^FS^FO250,220^A0N,18,18^FD200^FS^FO250,250^A0N,18,18^FD250^FS^FO250,270^A0N,18,18^FD250^FS^FO250,300^A0N,18,18^FD250^FS^FO250,320^A0N,18,18^FD300^FS^FO250,350^A0N,18,18^FD250^FS^FO250,370^A0N,18,18^FD350^FS^FO250,400^A0N,18,18^FD250^FS^FO250,420^A0N,18,18^FD400^FS^FO250,450^A0N,18,18^FD250^FS^FO250,470^A0N,18,18^FD450^FS^FO250,500^A0N,18,18^FD250^FS^FO250,520^A0N,18,18^FD500^FS^FO250,550^A0N,18,18^FD250^FS^FO250,570^A0N,18,18^FD550^FS^FO250,600^A0N,18,18^FD250^FS^FO250,620^A0N,18,18^FD600^FS^FO250,650^A0N,18,18^FD250^FS^FO250,670^A0N,18,18^FD650^FS^FO250,700^A0N,18,18^FD250^FS^FO250,720^A0N,18,18^FD700^FS^FO250,750^A0N,18,18^FD250^FS^FO250,770^A0N,18,18^FD750^FS^FO300,0^A0N,18,18^FD300^FS^FO300,20^A0N,18,18^FD0^FS^FO300,50^A0N,18,18^FD300^FS^FO300,70^A0N,18,18^FD50^FS^FO300,100^A0N,18,18^FD300^FS^FO300,120^A0N,18,18^FD100^FS^FO300,150^A0N,18,18^FD300^FS^FO300,170^A0N,18,18^FD150^FS^FO300,200^A0N,18,18^FD300^FS^FO300,220^A0N,18,18^FD200^FS^FO300,250^A0N,18,18^FD300^FS^FO300,270^A0N,18,18^FD250^FS^FO300,300^A0N,18,18^FD300^FS^FO300,320^A0N,18,18^FD300^FS^FO300,350^A0N,18,18^FD300^FS^FO300,370^A0N,18,18^FD350^FS^FO300,400^A0N,18,18^FD300^FS^FO300,420^A0N,18,18^FD400^FS^FO300,450^A0N,18,18^FD300^FS^FO300,470^A0N,18,18^FD450^FS^FO300,500^A0N,18,18^FD300^FS^FO300,520^A0N,18,18^FD500^FS^FO300,550^A0N,18,18^FD300^FS^FO300,570^A0N,18,18^FD550^FS^FO300,600^A0N,18,18^FD300^FS^FO300,620^A0N,18,18^FD600^FS^FO300,650^A0N,18,18^FD300^FS^FO300,670^A0N,18,18^FD650^FS^FO300,700^A0N,18,18^FD300^FS^FO300,720^A0N,18,18^FD700^FS^FO300,750^A0N,18,18^FD300^FS^FO300,770^A0N,18,18^FD750^FS^FO350,0^A0N,18,18^FD350^FS^FO350,20^A0N,18,18^FD0^FS^FO350,50^A0N,18,18^FD350^FS^FO350,70^A0N,18,18^FD50^FS^FO350,100^A0N,18,18^FD350^FS^FO350,120^A0N,18,18^FD100^FS^FO350,150^A0N,18,18^FD350^FS^FO350,170^A0N,18,18^FD150^FS^FO350,200^A0N,18,18^FD350^FS^FO350,220^A0N,18,18^FD200^FS^FO350,250^A0N,18,18^FD350^FS^FO350,270^A0N,18,18^FD250^FS^FO350,300^A0N,18,18^FD350^FS^FO350,320^A0N,18,18^FD300^FS^FO350,350^A0N,18,18^FD350^FS^FO350,370^A0N,18,18^FD350^FS^FO350,400^A0N,18,18^FD350^FS^FO350,420^A0N,18,18^FD400^FS^FO350,450^A0N,18,18^FD350^FS^FO350,470^A0N,18,18^FD450^FS^FO350,500^A0N,18,18^FD350^FS^FO350,520^A0N,18,18^FD500^FS^FO350,550^A0N,18,18^FD350^FS^FO350,570^A0N,18,18^FD550^FS^FO350,600^A0N,18,18^FD350^FS^FO350,620^A0N,18,18^FD600^FS^FO350,650^A0N,18,18^FD350^FS^FO350,670^A0N,18,18^FD650^FS^FO350,700^A0N,18,18^FD350^FS^FO350,720^A0N,18,18^FD700^FS^FO350,750^A0N,18,18^FD350^FS^FO350,770^A0N,18,18^FD750^FS^FO400,0^A0N,18,18^FD400^FS^FO400,20^A0N,18,18^FD0^FS^FO400,50^A0N,18,18^FD400^FS^FO400,70^A0N,18,18^FD50^FS^FO400,100^A0N,18,18^FD400^FS^FO400,120^A0N,18,18^FD100^FS^FO400,150^A0N,18,18^FD400^FS^FO400,170^A0N,18,18^FD150^FS^FO400,200^A0N,18,18^FD400^FS^FO400,220^A0N,18,18^FD200^FS^FO400,250^A0N,18,18^FD400^FS^FO400,270^A0N,18,18^FD250^FS^FO400,300^A0N,18,18^FD400^FS^FO400,320^A0N,18,18^FD300^FS^FO400,350^A0N,18,18^FD400^FS^FO400,370^A0N,18,18^FD350^FS^FO400,400^A0N,18,18^FD400^FS^FO400,420^A0N,18,18^FD400^FS^FO400,450^A0N,18,18^FD400^FS^FO400,470^A0N,18,18^FD450^FS^FO400,500^A0N,18,18^FD400^FS^FO400,520^A0N,18,18^FD500^FS^FO400,550^A0N,18,18^FD400^FS^FO400,570^A0N,18,18^FD550^FS^FO400,600^A0N,18,18^FD400^FS^FO400,620^A0N,18,18^FD600^FS^FO400,650^A0N,18,18^FD400^FS^FO400,670^A0N,18,18^FD650^FS^FO400,700^A0N,18,18^FD400^FS^FO400,720^A0N,18,18^FD700^FS^FO400,750^A0N,18,18^FD400^FS^FO400,770^A0N,18,18^FD750^FS^FO450,0^A0N,18,18^FD450^FS^FO450,20^A0N,18,18^FD0^FS^FO450,50^A0N,18,18^FD450^FS^FO450,70^A0N,18,18^FD50^FS^FO450,100^A0N,18,18^FD450^FS^FO450,120^A0N,18,18^FD100^FS^FO450,150^A0N,18,18^FD450^FS^FO450,170^A0N,18,18^FD150^FS^FO450,200^A0N,18,18^FD450^FS^FO450,220^A0N,18,18^FD200^FS^FO450,250^A0N,18,18^FD450^FS^FO450,270^A0N,18,18^FD250^FS^FO450,300^A0N,18,18^FD450^FS^FO450,320^A0N,18,18^FD300^FS^FO450,350^A0N,18,18^FD450^FS^FO450,370^A0N,18,18^FD350^FS^FO450,400^A0N,18,18^FD450^FS^FO450,420^A0N,18,18^FD400^FS^FO450,450^A0N,18,18^FD450^FS^FO450,470^A0N,18,18^FD450^FS^FO450,500^A0N,18,18^FD450^FS^FO450,520^A0N,18,18^FD500^FS^FO450,550^A0N,18,18^FD450^FS^FO450,570^A0N,18,18^FD550^FS^FO450,600^A0N,18,18^FD450^FS^FO450,620^A0N,18,18^FD600^FS^FO450,650^A0N,18,18^FD450^FS^FO450,670^A0N,18,18^FD650^FS^FO450,700^A0N,18,18^FD450^FS^FO450,720^A0N,18,18^FD700^FS^FO450,750^A0N,18,18^FD450^FS^FO450,770^A0N,18,18^FD750^FS^FO500,0^A0N,18,18^FD500^FS^FO500,20^A0N,18,18^FD0^FS^FO500,50^A0N,18,18^FD500^FS^FO500,70^A0N,18,18^FD50^FS^FO500,100^A0N,18,18^FD500^FS^FO500,120^A0N,18,18^FD100^FS^FO500,150^A0N,18,18^FD500^FS^FO500,170^A0N,18,18^FD150^FS^FO500,200^A0N,18,18^FD500^FS^FO500,220^A0N,18,18^FD200^FS^FO500,250^A0N,18,18^FD500^FS^FO500,270^A0N,18,18^FD250^FS^FO500,300^A0N,18,18^FD500^FS^FO500,320^A0N,18,18^FD300^FS^FO500,350^A0N,18,18^FD500^FS^FO500,370^A0N,18,18^FD350^FS^FO500,400^A0N,18,18^FD500^FS^FO500,420^A0N,18,18^FD400^FS^FO500,450^A0N,18,18^FD500^FS^FO500,470^A0N,18,18^FD450^FS^FO500,500^A0N,18,18^FD500^FS^FO500,520^A0N,18,18^FD500^FS^FO500,550^A0N,18,18^FD500^FS^FO500,570^A0N,18,18^FD550^FS^FO500,600^A0N,18,18^FD500^FS^FO500,620^A0N,18,18^FD600^FS^FO500,650^A0N,18,18^FD500^FS^FO500,670^A0N,18,18^FD650^FS^FO500,700^A0N,18,18^FD500^FS^FO500,720^A0N,18,18^FD700^FS^FO500,750^A0N,18,18^FD500^FS^FO500,770^A0N,18,18^FD750^FS^FO550,0^A0N,18,18^FD550^FS^FO550,20^A0N,18,18^FD0^FS^FO550,50^A0N,18,18^FD550^FS^FO550,70^A0N,18,18^FD50^FS^FO550,100^A0N,18,18^FD550^FS^FO550,120^A0N,18,18^FD100^FS^FO550,150^A0N,18,18^FD550^FS^FO550,170^A0N,18,18^FD150^FS^FO550,200^A0N,18,18^FD550^FS^FO550,220^A0N,18,18^FD200^FS^FO550,250^A0N,18,18^FD550^FS^FO550,270^A0N,18,18^FD250^FS^FO550,300^A0N,18,18^FD550^FS^FO550,320^A0N,18,18^FD300^FS^FO550,350^A0N,18,18^FD550^FS^FO550,370^A0N,18,18^FD350^FS^FO550,400^A0N,18,18^FD550^FS^FO550,420^A0N,18,18^FD400^FS^FO550,450^A0N,18,18^FD550^FS^FO550,470^A0N,18,18^FD450^FS^FO550,500^A0N,18,18^FD550^FS^FO550,520^A0N,18,18^FD500^FS^FO550,550^A0N,18,18^FD550^FS^FO550,570^A0N,18,18^FD550^FS^FO550,600^A0N,18,18^FD550^FS^FO550,620^A0N,18,18^FD600^FS^FO550,650^A0N,18,18^FD550^FS^FO550,670^A0N,18,18^FD650^FS^FO550,700^A0N,18,18^FD550^FS^FO550,720^A0N,18,18^FD700^FS^FO550,750^A0N,18,18^FD550^FS^FO550,770^A0N,18,18^FD750^FS^FO600,0^A0N,18,18^FD600^FS^FO600,20^A0N,18,18^FD0^FS^FO600,50^A0N,18,18^FD600^FS^FO600,70^A0N,18,18^FD50^FS^FO600,100^A0N,18,18^FD600^FS^FO600,120^A0N,18,18^FD100^FS^FO600,150^A0N,18,18^FD600^FS^FO600,170^A0N,18,18^FD150^FS^FO600,200^A0N,18,18^FD600^FS^FO600,220^A0N,18,18^FD200^FS^FO600,250^A0N,18,18^FD600^FS^FO600,270^A0N,18,18^FD250^FS^FO600,300^A0N,18,18^FD600^FS^FO600,320^A0N,18,18^FD300^FS^FO600,350^A0N,18,18^FD600^FS^FO600,370^A0N,18,18^FD350^FS^FO600,400^A0N,18,18^FD600^FS^FO600,420^A0N,18,18^FD400^FS^FO600,450^A0N,18,18^FD600^FS^FO600,470^A0N,18,18^FD450^FS^FO600,500^A0N,18,18^FD600^FS^FO600,520^A0N,18,18^FD500^FS^FO600,550^A0N,18,18^FD600^FS^FO600,570^A0N,18,18^FD550^FS^FO600,600^A0N,18,18^FD600^FS^FO600,620^A0N,18,18^FD600^FS^FO600,650^A0N,18,18^FD600^FS^FO600,670^A0N,18,18^FD650^FS^FO600,700^A0N,18,18^FD600^FS^FO600,720^A0N,18,18^FD700^FS^FO600,750^A0N,18,18^FD600^FS^FO600,770^A0N,18,18^FD750^FS^FO650,0^A0N,18,18^FD650^FS^FO650,20^A0N,18,18^FD0^FS^FO650,50^A0N,18,18^FD650^FS^FO650,70^A0N,18,18^FD50^FS^FO650,100^A0N,18,18^FD650^FS^FO650,120^A0N,18,18^FD100^FS^FO650,150^A0N,18,18^FD650^FS^FO650,170^A0N,18,18^FD150^FS^FO650,200^A0N,18,18^FD650^FS^FO650,220^A0N,18,18^FD200^FS^FO650,250^A0N,18,18^FD650^FS^FO650,270^A0N,18,18^FD250^FS^FO650,300^A0N,18,18^FD650^FS^FO650,320^A0N,18,18^FD300^FS^FO650,350^A0N,18,18^FD650^FS^FO650,370^A0N,18,18^FD350^FS^FO650,400^A0N,18,18^FD650^FS^FO650,420^A0N,18,18^FD400^FS^FO650,450^A0N,18,18^FD650^FS^FO650,470^A0N,18,18^FD450^FS^FO650,500^A0N,18,18^FD650^FS^FO650,520^A0N,18,18^FD500^FS^FO650,550^A0N,18,18^FD650^FS^FO650,570^A0N,18,18^FD550^FS^FO650,600^A0N,18,18^FD650^FS^FO650,620^A0N,18,18^FD600^FS^FO650,650^A0N,18,18^FD650^FS^FO650,670^A0N,18,18^FD650^FS^FO650,700^A0N,18,18^FD650^FS^FO650,720^A0N,18,18^FD700^FS^FO650,750^A0N,18,18^FD650^FS^FO650,770^A0N,18,18^FD750^FS^FO700,0^A0N,18,18^FD700^FS^FO700,20^A0N,18,18^FD0^FS^FO700,50^A0N,18,18^FD700^FS^FO700,70^A0N,18,18^FD50^FS^FO700,100^A0N,18,18^FD700^FS^FO700,120^A0N,18,18^FD100^FS^FO700,150^A0N,18,18^FD700^FS^FO700,170^A0N,18,18^FD150^FS^FO700,200^A0N,18,18^FD700^FS^FO700,220^A0N,18,18^FD200^FS^FO700,250^A0N,18,18^FD700^FS^FO700,270^A0N,18,18^FD250^FS^FO700,300^A0N,18,18^FD700^FS^FO700,320^A0N,18,18^FD300^FS^FO700,350^A0N,18,18^FD700^FS^FO700,370^A0N,18,18^FD350^FS^FO700,400^A0N,18,18^FD700^FS^FO700,420^A0N,18,18^FD400^FS^FO700,450^A0N,18,18^FD700^FS^FO700,470^A0N,18,18^FD450^FS^FO700,500^A0N,18,18^FD700^FS^FO700,520^A0N,18,18^FD500^FS^FO700,550^A0N,18,18^FD700^FS^FO700,570^A0N,18,18^FD550^FS^FO700,600^A0N,18,18^FD700^FS^FO700,620^A0N,18,18^FD600^FS^FO700,650^A0N,18,18^FD700^FS^FO700,670^A0N,18,18^FD650^FS^FO700,700^A0N,18,18^FD700^FS^FO700,720^A0N,18,18^FD700^FS^FO700,750^A0N,18,18^FD700^FS^FO700,770^A0N,18,18^FD750^FS^FO750,0^A0N,18,18^FD750^FS^FO750,20^A0N,18,18^FD0^FS^FO750,50^A0N,18,18^FD750^FS^FO750,70^A0N,18,18^FD50^FS^FO750,100^A0N,18,18^FD750^FS^FO750,120^A0N,18,18^FD100^FS^FO750,150^A0N,18,18^FD750^FS^FO750,170^A0N,18,18^FD150^FS^FO750,200^A0N,18,18^FD750^FS^FO750,220^A0N,18,18^FD200^FS^FO750,250^A0N,18,18^FD750^FS^FO750,270^A0N,18,18^FD250^FS^FO750,300^A0N,18,18^FD750^FS^FO750,320^A0N,18,18^FD300^FS^FO750,350^A0N,18,18^FD750^FS^FO750,370^A0N,18,18^FD350^FS^FO750,400^A0N,18,18^FD750^FS^FO750,420^A0N,18,18^FD400^FS^FO750,450^A0N,18,18^FD750^FS^FO750,470^A0N,18,18^FD450^FS^FO750,500^A0N,18,18^FD750^FS^FO750,520^A0N,18,18^FD500^FS^FO750,550^A0N,18,18^FD750^FS^FO750,570^A0N,18,18^FD550^FS^FO750,600^A0N,18,18^FD750^FS^FO750,620^A0N,18,18^FD600^FS^FO750,650^A0N,18,18^FD750^FS^FO750,670^A0N,18,18^FD650^FS^FO750,700^A0N,18,18^FD750^FS^FO750,720^A0N,18,18^FD700^FS^FO750,750^A0N,18,18^FD750^FS^FO750,770^A0N,18,18^FD750^FS^XZ
File without changes
@@ -0,0 +1,7 @@
1
+ ^XA
2
+ ^FO20,20^BY2^BCN,100,Y,N,N^FDNAVA12345678^FS // 1D Barcode (Code 128)
3
+ ^FO150,140^A0N,60,60^FDNAVA12345678^FS // Human-Readable NAVA
4
+ ^FO150,200^A0N,60,60^FDMA^FS // Human-Readable MA
5
+ ^FO150,260^A0N,40,40^FD2023-10-19^FS // Date
6
+ ^FO150,300^A0N,40,40^FDcommercial^FS // String
7
+ ^XZ