feat: bump client-services (accumulated feature work + deploy fixes)
Snapshot of in-progress work across local_backend, manager_dashboard, and waiter_pwa (pricing, chat, fiscal, prep zones, recovery codes, CRM, inventory, permissions), plus the nginx/docker-compose deploy fixes for the Unraid + NPM reverse-proxy setup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
114
local_backend/print_codepage_probe.py
Normal file
114
local_backend/print_codepage_probe.py
Normal file
@@ -0,0 +1,114 @@
|
||||
"""
|
||||
Greek code page probe — NETUM NT8330L (or any unknown printer)
|
||||
Usage: python print_codepage_probe.py <IP> [PORT]
|
||||
Example: python print_codepage_probe.py 192.168.1.50 9100
|
||||
|
||||
Prints one long receipt that tries every candidate (n, encoding) combination.
|
||||
Circle the block where you can read "ΚΑΛΗΜΕΡΑ ΕΛΛΑΔΑ" correctly.
|
||||
That block tells you the codepage_n value to use in the printer profile.
|
||||
"""
|
||||
import sys
|
||||
from escpos.printer import Network
|
||||
|
||||
IP = sys.argv[1] if len(sys.argv) > 1 else "192.168.1.50"
|
||||
PORT = int(sys.argv[2]) if len(sys.argv) > 2 else 9100
|
||||
|
||||
# (n_value, python_encoding, label)
|
||||
# Each will be tested independently with a fresh ESC @ reset.
|
||||
CANDIDATES = [
|
||||
# Standard Epson table assignments for Greek
|
||||
(14, "cp737", "n=14 CP737 (Epson standard slot)"),
|
||||
(38, "cp737", "n=38 CP737 (alt slot / CP869 area)"),
|
||||
(11, "cp737", "n=11 CP737 (CP851 slot)"),
|
||||
(47, "cp737", "n=47 CP737 (CP1253 slot, cp737 bytes)"),
|
||||
# Same slots but with cp869 encoding (different byte layout)
|
||||
(14, "cp869", "n=14 CP869 (Greek DOS #2)"),
|
||||
(38, "cp869", "n=38 CP869 (alt slot)"),
|
||||
# Windows / ISO encodings
|
||||
(47, "cp1253", "n=47 CP1253 (Windows Greek)"),
|
||||
(15, "iso8859_7", "n=15 ISO-8859-7"),
|
||||
(14, "iso8859_7", "n=14 ISO-8859-7"),
|
||||
# The Jolimark value, for reference
|
||||
(29, "cp737", "n=29 CP737 (Jolimark confirmed)"),
|
||||
# A few more obscure slots some Chinese-made printers use
|
||||
(16, "cp737", "n=16 CP737 (rare slot)"),
|
||||
(18, "cp737", "n=18 CP737 (rare slot)"),
|
||||
(21, "cp737", "n=21 CP737 (rare slot)"),
|
||||
]
|
||||
|
||||
GREEK_SAMPLE = "ΚΑΛΗΜΕΡΑ ΕΛΛΑΔΑ"
|
||||
GREEK_LOWER = "καλημέρα ελλάδα"
|
||||
GREEK_DIGITS = "ΤΙΜΗ: 12.50 ευρώ"
|
||||
|
||||
def probe(n: int, encoding: str, label: str):
|
||||
try:
|
||||
p = Network(IP, PORT, timeout=8)
|
||||
p._raw(b'\x1b\x40') # ESC @ full reset
|
||||
p._raw(bytes([0x1b, 0x74, n])) # ESC t n — select code page
|
||||
|
||||
# Label in plain ASCII (always safe)
|
||||
p._raw(b'\x1b\x21\x00') # normal size
|
||||
p._raw(f"[{label}]\n".encode('ascii', errors='replace'))
|
||||
|
||||
# Greek sample in the candidate encoding
|
||||
try:
|
||||
greek_bytes = GREEK_SAMPLE.encode(encoding, errors='replace')
|
||||
lower_bytes = GREEK_LOWER.encode(encoding, errors='replace')
|
||||
digit_bytes = GREEK_DIGITS.encode(encoding, errors='replace')
|
||||
except LookupError:
|
||||
p._raw(b' (encoding not available)\n')
|
||||
p._raw(b'\n')
|
||||
p.close()
|
||||
return
|
||||
|
||||
p._raw(b'\x1b\x21\x08') # bold
|
||||
p._raw(greek_bytes + b'\n')
|
||||
p._raw(b'\x1b\x21\x00') # normal
|
||||
p._raw(lower_bytes + b'\n')
|
||||
p._raw(digit_bytes + b'\n')
|
||||
p._raw(b'\n') # spacer
|
||||
p.close()
|
||||
print(f" OK {label}")
|
||||
except Exception as e:
|
||||
print(f" ERR {label}: {e}")
|
||||
|
||||
def main():
|
||||
print(f"Probing {IP}:{PORT}")
|
||||
print(f"Testing {len(CANDIDATES)} combinations...\n")
|
||||
|
||||
# Print header block
|
||||
try:
|
||||
p = Network(IP, PORT, timeout=8)
|
||||
p._raw(b'\x1b\x40')
|
||||
p._raw(b'\x1b\x61\x01') # center
|
||||
p._raw(b'\x1b\x21\x30') # double width+height
|
||||
p._raw(b'GREEK PROBE\n')
|
||||
p._raw(b'\x1b\x21\x00')
|
||||
p._raw(b'\x1b\x61\x00') # left
|
||||
p._raw(b'Circle the block with readable Greek.\n')
|
||||
p._raw(b'Looking for: KALIMERA ELLADA\n')
|
||||
p._raw(b'================================================\n')
|
||||
p._raw(b'\n')
|
||||
p.close()
|
||||
except Exception as e:
|
||||
print(f"Header failed: {e}")
|
||||
return
|
||||
|
||||
for (n, enc, label) in CANDIDATES:
|
||||
probe(n, enc, label)
|
||||
|
||||
# Footer + cut
|
||||
try:
|
||||
p = Network(IP, PORT, timeout=8)
|
||||
p._raw(b'\x1b\x40')
|
||||
p._raw(b'================================================\n')
|
||||
p._raw(b'END OF PROBE\n')
|
||||
p._raw(b'\n\n\n')
|
||||
p.cut()
|
||||
p.close()
|
||||
print("\nDone. Read the printout and note which block shows readable Greek.")
|
||||
except Exception as e:
|
||||
print(f"Footer failed: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user