Update VERSION to v6.2.10
New features Revision of the documentation Fix bug
This commit is contained in:
50
README.md
50
README.md
@@ -61,6 +61,10 @@ The software also includes a configurable printer dictionary, which can be easil
|
||||
|
||||
- Import and export printer configuration datasets in various formats: epson_print_conf pickle, Reinkpy XML, Reinkpy TOML.
|
||||
|
||||
- Interactive Console (API Playground).
|
||||
|
||||
The application includes an integrated Interactive Console. It allows Python developers to interact with the application's runtime environment, evaluate expressions, test APIs, and inspect variables. This console acts as a live API Playground, ideal for debugging, printer configuration testing and rapid prototyping.
|
||||
|
||||
- Access various administrative and debugging options.
|
||||
|
||||
- __Available Interfaces__:
|
||||
@@ -80,6 +84,8 @@ cd epson_print_conf
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
On Linux, you might also install the tkinter module: `sudo apt install python3-tk`.
|
||||
|
||||
This program exploits [pysnmp v7+](https://github.com/lextudio/pysnmp) and [pysnmp-sync-adapter](https://github.com/Ircama/pysnmp-sync-adapter).
|
||||
|
||||
It is tested with Ubuntu / Windows Subsystem for Linux, Windows.
|
||||
@@ -673,7 +679,7 @@ To return the value of the OID query: `self.fetch_oid_values(oid)[0][1]`.
|
||||
|
||||
Open the *epson_print_conf* application, set printer model and IP address, test printer connection. Then: Settings > Debug Shell.
|
||||
|
||||
The following are examples of instructions to test the END4 commands:
|
||||
The following are examples of instructions to test the EPSON-CTRL commands:
|
||||
|
||||
```python
|
||||
# cs
|
||||
@@ -734,7 +740,47 @@ for i in ec_sequences:
|
||||
|
||||
Comprehensive, unified documentation for Epson’s Remote Mode commands does not exist: support varies by model, and command references are scattered across service manuals, programming guides and third-party sources (for example, the [Developer's Guide to Gutenprint](https://gimp-print.sourceforge.io/reference-html/x952.html) or [GIMP-Print - ESC/P2 Remote Mode Commands](http://osr507doc.xinuos.com/en/OSAdminG/OSAdminG_gimp/manual-html/gimpprint_37.html)).
|
||||
|
||||
Check `self.printer.check_nozzles()` and `self.printer.clean_nozzles(0)` for examples of usage of remote commands.
|
||||
The `EpsonLpr` class is used for sending Epson LPR commands over a RAW, unidirectional TCP connection on port 9100. This channel does not support receiving responses from the printer.
|
||||
|
||||
| **Method** | **Description** |
|
||||
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `connect` | Opens a TCP socket connection to the printer at the specified host and port, with timeout. |
|
||||
| `disconnect` | Gracefully shuts down and closes the socket connection if open. |
|
||||
| `send(data)` | Sends raw `bytes` directly to the printer over the socket connection. |
|
||||
| `remote_cmd(cmd, args)` | Constructs a Remote Mode command: 2-byte ASCII command + 2-byte little-endian length + arguments. |
|
||||
|
||||
Predefined remote mode commands in this class:
|
||||
|
||||
| **Command** | **Description** |
|
||||
| --------------------- | ------------------------------------------------------- |
|
||||
| `LF` | Line Feed (new line). |
|
||||
| `FF` | Form Feed; flushes the buffer / ejects the page. |
|
||||
| `EXIT_PACKET_MODE` | Exits IEEE 1284.4 (D4) packet mode. |
|
||||
| `INITIALIZE_PRINTER` | Resets printer to default state (ESC @). |
|
||||
| `REMOTE_MODE` | Enter Epson Remote Command mode. |
|
||||
| `ENTER_REMOTE_MODE` | Initialize printer and enter Epson Remote Command mode. |
|
||||
| `EXIT_REMOTE_MODE` | Exits Remote Mode. |
|
||||
| `JOB_START` | Begins a print job (JS). |
|
||||
| `JOB_END` | Ends a print job (JE). |
|
||||
| `PRINT_NOZZLE_CHECK` | Triggers a nozzle check print pattern (NC). |
|
||||
| `VERSION_INFORMATION` | Requests firmware or printer version info (VI). |
|
||||
| `LD` | (unknown). |
|
||||
|
||||
Check `self.printer.check_nozzles()` and `self.printer.clean_nozzles(0)` for examples of usage. The following code prints the nozzle-check print pattern (copy and paste the code to the Interactive Console after selecting a printer and related host address):
|
||||
|
||||
```python
|
||||
from epson_print_conf import EpsonLpr
|
||||
lpr = EpsonLpr(self.printer.hostname)
|
||||
data = (
|
||||
lpr.EXIT_PACKET_MODE + # Exit packet mode
|
||||
lpr.ENTER_REMOTE_MODE + # Engage remote mode commands
|
||||
lpr.PRINT_NOZZLE_CHECK + # Issue nozzle-check print pattern
|
||||
lpr.EXIT_REMOTE_MODE + # Disengage remote control
|
||||
lpr.JOB_END # Mark maintenance job complete
|
||||
)
|
||||
print(f"\nDump of data:\n{self.printer.hexdump(data)}\n")
|
||||
lpr.connect().send(data).disconnect()
|
||||
```
|
||||
|
||||
## ST2 Status Reply Codes
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ class EpsonLpr:
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.sock.settimeout(self.timeout)
|
||||
self.sock.connect((self.hostname, self.port))
|
||||
return self
|
||||
|
||||
def disconnect(self) -> None:
|
||||
"""Shutdown and close the socket."""
|
||||
@@ -86,12 +87,14 @@ class EpsonLpr:
|
||||
pass
|
||||
self.sock.close()
|
||||
self.sock = None
|
||||
return self
|
||||
|
||||
def send(self, data: bytes) -> None:
|
||||
"""Send raw bytes to the printer."""
|
||||
if not self.sock:
|
||||
raise RuntimeError("Not connected to printer")
|
||||
self.sock.sendall(data)
|
||||
return self
|
||||
|
||||
def remote_cmd(self, cmd, args):
|
||||
"Generate a Remote Mode command."
|
||||
@@ -1137,6 +1140,46 @@ class EpsonPrinter:
|
||||
"""
|
||||
return(filter(lambda x: x.startswith("get_"), dir(self)))
|
||||
|
||||
def hexdump(self, data: Union[bytes, bytearray], width: int = 16) -> str:
|
||||
"""
|
||||
Produce a hex + ASCII dump of the given data.
|
||||
|
||||
Each line shows:
|
||||
- 8-digit hex offset
|
||||
- hex bytes (grouped by width, with extra space every 8 bytes)
|
||||
- printable ASCII (non-printables as '.')
|
||||
|
||||
:param data: Bytes to dump.
|
||||
:param width: Number of bytes per line (default: 16).
|
||||
:return: The formatted hexdump.
|
||||
"""
|
||||
lines = []
|
||||
for offset in range(0, len(data), width):
|
||||
chunk = data[offset : offset + width]
|
||||
|
||||
# Hex part, with a space every byte and extra gap at half‑width
|
||||
hex_bytes = ' '.join(f"{b:02X}" for b in chunk)
|
||||
half = width // 2
|
||||
if len(chunk) > half:
|
||||
# insert extra space between halves
|
||||
parts = hex_bytes.split(' ')
|
||||
hex_bytes = (
|
||||
' '.join(parts[:half]) + ' ' + ' '.join(parts[half:])
|
||||
)
|
||||
|
||||
# Pad hex part so ASCII column aligns
|
||||
expected_len = width * 2 + (width - 1) + 2 # bytes*2 hex + spaces + extra half‑split
|
||||
hex_part = hex_bytes.ljust(expected_len)
|
||||
|
||||
# ASCII part: printable or '.'
|
||||
ascii_part = (
|
||||
''.join(chr(b) if 32 <= b < 127 else '.' for b in chunk)
|
||||
)
|
||||
|
||||
lines.append(f"{offset:08X} {hex_part} {ascii_part}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def expand_printer_conf(self, conf):
|
||||
"""
|
||||
Expand "alias" and "same-as" of a printer database for all printers
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
pyyaml
|
||||
pysnmp>=7.1.20
|
||||
pysnmp_sync_adapter>=1.0.6
|
||||
pysnmp_sync_adapter>=1.0.8
|
||||
tkcalendar
|
||||
pyperclip
|
||||
black
|
||||
tomli
|
||||
text-console>=2.0.0
|
||||
text-console>=2.0.2
|
||||
|
||||
24
ui.py
24
ui.py
@@ -37,7 +37,7 @@ from find_printers import PrinterScanner
|
||||
from text_console import TextConsole
|
||||
|
||||
|
||||
VERSION = "6.2.0"
|
||||
VERSION = "6.2.10"
|
||||
|
||||
NO_CONF_ERROR = (
|
||||
" Please select a printer model and a valid IP address,"
|
||||
@@ -55,7 +55,9 @@ CONFIRM_MESSAGE = (
|
||||
|
||||
class EpcTextConsole(TextConsole):
|
||||
|
||||
show_about_message = "epson_print_conf Debug Console."
|
||||
show_about_message = (
|
||||
"Epson Printer Configuration Interactive Console (API Playground)."
|
||||
)
|
||||
|
||||
def show_help(self):
|
||||
"""Open a separate window with help text."""
|
||||
@@ -67,13 +69,15 @@ class EpcTextConsole(TextConsole):
|
||||
scrollbar = tk.Scrollbar(help_window)
|
||||
scrollbar.pack(side="right", fill="y")
|
||||
|
||||
help_text = tk.Text(help_window, wrap="word", yscrollcommand=scrollbar.set)
|
||||
help_text = tk.Text(
|
||||
help_window, wrap="word", yscrollcommand=scrollbar.set
|
||||
)
|
||||
help_text.tag_configure("title", foreground="purple")
|
||||
help_text.tag_configure("section", foreground="blue")
|
||||
|
||||
help_text.insert(
|
||||
tk.END,
|
||||
'Welcome to the epson_print_conf Debug Console\n\n',
|
||||
f'Welcome to the {self.show_about_message}\n\n',
|
||||
"title"
|
||||
)
|
||||
help_text.insert(
|
||||
@@ -98,7 +102,7 @@ class EpcTextConsole(TextConsole):
|
||||
help_text.insert(
|
||||
tk.END,
|
||||
(
|
||||
"- F7: Open the debug console.\n\n"
|
||||
"- F7: Open the Interactive Console (API Playground).\n\n"
|
||||
)
|
||||
)
|
||||
help_text.insert(
|
||||
@@ -370,8 +374,8 @@ class EpsonPrinterUI(tk.Tk):
|
||||
help_menu.add_command(label="Clear printer list", command=self.clear_printer_list)
|
||||
help_menu.entryconfig("Clear printer list", accelerator="F6")
|
||||
|
||||
help_menu.add_command(label="Debug shell", command=self.tk_console)
|
||||
help_menu.entryconfig("Debug shell", accelerator="F7")
|
||||
help_menu.add_command(label="Interactive Console (API Playground)", command=self.tk_console)
|
||||
help_menu.entryconfig("Interactive Console (API Playground)", accelerator="F7")
|
||||
|
||||
help_menu.add_command(label="Remove selected printer configuration", command=self.remove_printer_conf)
|
||||
help_menu.entryconfig("Remove selected printer configuration", accelerator="F8")
|
||||
@@ -1186,7 +1190,9 @@ class EpsonPrinterUI(tk.Tk):
|
||||
return
|
||||
|
||||
self._console_window = tk.Toplevel(self)
|
||||
self._console_window.title("Debug Console")
|
||||
self._console_window.title(
|
||||
"Epson Printer Configuration Interactive Console (API Playground)"
|
||||
)
|
||||
self._console_window.geometry("800x400")
|
||||
|
||||
console = EpcTextConsole(self, self._console_window)
|
||||
@@ -3596,7 +3602,7 @@ def main():
|
||||
import pickle
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
epilog='epson_print_conf GUI'
|
||||
epilog='Epson Printer Configuration GUI'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-m',
|
||||
|
||||
Reference in New Issue
Block a user