UI menu bar, import/export conf files from the UI, exclude L3250

This commit is contained in:
Ircama 2024-11-03 13:13:56 +01:00
parent 1f993d77a2
commit 6304a02a83
5 changed files with 434 additions and 89 deletions

2
.gitignore vendored
View file

@ -160,3 +160,5 @@ cython_debug/
#.idea/
devices.xml
*.toml
*.srs
*.pickle

View file

@ -8,6 +8,8 @@ The *Epson Printer Configuration Tool* simplifies the management of Epson printe
A range of features are offered for both end-users and developers, making it easier to administer and maintain Epson printers.
The software provides a configurable printer dictionary, which can be easily extended. In addition, it is possible to import and convert external Epson printer configuration databases.
## Key Features
- __SNMP Interface__: Seamlessly connect and manage Epson printers using SNMP over TCP/IP, supporting Wi-Fi connections (not USB).
@ -24,36 +26,27 @@ A range of features are offered for both end-users and developers, making it eas
- Reset the ink waste counter.
The ink waste counters track the amount of ink discarded during maintenance tasks to prevent overflow in the waste ink pads. Once the counters indicate that one of the printer pads is full, the printer will stop working to avoid potential damage or ink spills. Resetting the ink waste counter extends the printer operation while a pad maintenance or tank replacement is programmed.
- Adjust the power-off timer for more accurate energy efficiency.
- Adjust the power-off timer (for more accurate energy efficiency).
- Change the _First TI Received Time_,
The *First TI Received Time* in Epson printers typically refers to the timestamp of the first transmission instruction to the printer when it was first set up. This feature tracks when the printer first operated.
- Change the printer WiFi MAC address and the printer serial number (typically used in specialized scenarios where specific device identifiers are required).
- Access various administrative and debugging options.
- Read and write to EEPROM addresses for advanced configurations.
- Dump and analyze sets of EEPROM addresses.
- Detect the access key (*read_key* and *write_key*) and some attributes of the printer configuration.
The GUI includes some features that attempt to detect the attributes of an Epson printer whose model is not included in the configuration, which can also be used with known printers, to detect additional parameters.
- Import and export printer configuration datasets in various formats: epson_print_conf pickle, Reinkpy XML, Reinkpy TOML.
- Access various administrative and debugging options.
- __User-Friendly Interfaces__:
- __Graphical User Interface (GUI)__: Intuitive interface with an autodiscovery function that detects printer IP addresses and model names.
- __Command Line Tool__: For users who prefer command-line interactions, providing the full set of features.
- __Python API Interface__: For developers to integrate and automate printer management tasks.
The GUI can automatically find and display printer IP addresses and model names, allowing users to:
- Check printer status
- Open the printer web interface
- Change the printer power-off timer, the _First TI Received Time_, the printer WiFi MAC address, and the printer serial number
- Read and write the EEPROM
- Detect the access key (*read_key* and *write_key*) and some attributes of the printer configuration
- Reset the ink waste counter
Special features allow showing the internal configuration settings.
The *First TI Received Time* in Epson printers typically refers to the timestamp of the first transmission instruction to the printer when it was first set up. This feature tracks when the printer first operated.
The software provides a configurable printer dictionary, which can be easily extended. In addition, a tool allows importing and converting an extensive Epson printer configuration DB.
The GUI includes some features that attempt to detect the attributes of an Epson printer whose model is not included in the configuration. First press "Detect Printers". If the printer is not in the configuration, press "Detect Access Keys". If the output does not show errors, press "Detect Configuration". These commands produce a tree view and a text view, which are useful to analyze whether there is a configured model that might be close or possibly same to target one. Notice that these operations take many minutes to complete and the printer shall be kept switched on for the whole period. Temporarily disabling the auto power-off timer is suggested.
"Detect Configuration" can also be used with known printers, to detect additional parameters.
Note on the ink waste counter reset feature: resetting the ink waste counter is just removing a lock; not replacing the tank will reduce the print quality and make the ink spill.
## Installation
@ -75,6 +68,8 @@ pip3 install pyasn1==0.4.8
pip3 install git+https://github.com/etingof/pysnmp.git
pip3 install tkcalendar
pip3 install pyperclip
pip3 install black
pip3 install tomli
cd epson_print_conf
```
@ -125,6 +120,28 @@ optional arguments:
epson_print_conf GUI
```
### How to import an external printer configuration DB
With the GUI, the following operations are possible (from the file menu):
- Load a PICKLE configuration file or web URL.
This operation allows to open a file saved with the GUI ("Save the selected printer configuration to a PICKLE file") or with the *parse_devices.py* utility. In addition to the printer configuration DB, this file includes the last used IP address and printer model in order to simplify the GUI usage.
- Import an XML configuration file or web URL
This option allows to import the XML configuration file downloaded from https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25bac4495a1d. Alternatively, this option directly accepts the [source Web URL](https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25bac4495a1d) of this file, incorporating the download operation into the GUI.
- Import a TOML configuration file or web URL
Similar to the XML import, this option allows to load the TOML configuration file downloaded from https://codeberg.org/atufi/reinkpy/raw/branch/main/reinkpy/epson.toml and also accepts the [source Web URL](https://codeberg.org/atufi/reinkpy/raw/branch/main/reinkpy/epson.toml) of this file, incorporating the download operation into the GUI.
Other menu options allow to filter or clean up the configuration list, as well as select a specific printer model and then save data to a PICKLE file.
### How to detect parameters of an unknown printer
First press "Detect Printers". If the printer is not in the configuration, press "Detect Access Keys". If the output does not show errors, press "Detect Configuration". These commands produce a tree view and a text view, which are useful to analyze whether there is a configured model that might be close or possibly same to target one. Notice that these operations take many minutes to complete and the printer shall be kept switched on for the whole period. Temporarily disabling the auto power-off timer is suggested.
### How to revert a change performed through the GUI
The GUI displays a `[NOTE]` in the status box before performing any change, specifying the current EEPROM values before the rewrite operation. This line can be copied and pasted as is into the text box that appears when the "Write EEPROM" button is pressed; the execution of the related action reverts the changes to their original values.
@ -649,14 +666,16 @@ Example of advanced printer status with an XP-205 printer:
## Resources
### snmpget (Linux)
### snmpget
Installation:
Installation with Linux:
```
sudo apt-get install snmp
```
There are also [binaries for Windows](https://netcologne.dl.sourceforge.net/project/net-snmp/net-snmp%20binaries/5.7-binaries/net-snmp-5.7.0-1.x86.exe?viasf=1) which include snmpget.exe, running with the same arguments.
Usage:
```
@ -695,7 +714,7 @@ emanage x900: https://github.com/abrasive/x900-otsakupuhastajat/
- Epson Maintenance Reset Utility: https://epson.com/epsonstorefront/orbeon/fr/us_regular_s03/us_ServiceInk_Pad_Reset/new
- Epson Ink Pads Reset Utility Terms and Conditions: https://epson.com/Support/wa00370
- Epson Adjustment Program (developed by EPSON)
- WIC-Reset: https://wic-reset.com / https://www.2manuals.com / https://resetters.com (Use at your risk)
- WIC-Reset: https://www.wic.support/download/ / https://www.2manuals.com / (Use at your risk)
- PrintHelp: https://printhelp.info/ (Use at your risk)
### Other resources

View file

@ -16,6 +16,7 @@ import logging
import os
import yaml
from pathlib import Path
import pickle
# The pysnmp module uses functionality from importlib.util and
# importlib.machinery, which were seperated from the importlib module
@ -262,6 +263,7 @@ class EpsonPrinter:
},
"serial_number": range(192, 202),
},
"""
"L3250": {
"alias": ["L3251", "L3253", "L3255"],
"read_key": [74, 54],
@ -290,6 +292,7 @@ class EpsonPrinter:
"Total scan counter": [1843, 1842, 1841, 1840],
},
},
"""
"ET-2400": {
"alias": ["ET-2401", "ET-2403", "ET-2405"],
"read_key": [74, 54],
@ -2480,6 +2483,41 @@ class EpsonPrinter:
return True
def get_printer_models(input_string):
# Tokenize the string
tokens = re.split(" |/", input_string)
if not len(tokens):
return []
# Define the words to remove (uppercase, then case insensitive)
remove_tokens = {"EPSON", "SERIES"}
# Process tokens
processed_tokens = []
non_numeric_part = ""
pre_model = ""
for token in tokens:
upper_token = token.upper()
# Remove tokens that match remove_tokens
if any(word == upper_token for word in remove_tokens):
continue
if not any(char.isdigit() for char in token): # no alphanum inside
pre_model = pre_model + token + " "
continue
# Identify the non-numeric part of the first token
if not token.isnumeric() and not non_numeric_part:
non_numeric_part = "".join(c for c in token if not c.isdigit())
# if token is numeric, prepend the non-numeric part
if token.isnumeric():
processed_tokens.append(f"{pre_model}{non_numeric_part}{token}")
else:
processed_tokens.append(f"{pre_model}{token}")
if not processed_tokens and pre_model:
processed_tokens.append(pre_model.strip())
return processed_tokens
if __name__ == "__main__":
import argparse
from pprint import pprint
@ -2687,7 +2725,11 @@ if __name__ == "__main__":
conf_dict = {}
if args.pickle:
conf_dict = pickle.load(args.pickle[0])
try:
conf_dict = pickle.load(args.pickle[0])
except Exception as e:
print("Error while loading the pickle file:", e)
quit(1)
printer = EpsonPrinter(
conf_dict=conf_dict,
@ -2733,7 +2775,7 @@ if __name__ == "__main__":
print("List of known keys:")
print("\n".join(printer.list_known_keys()))
else:
print(f"Cannot found read_key")
print(f"Could not detect read_key.")
if args.ftrt:
print_opt = True
if printer.write_first_ti_received_time(

View file

@ -7,7 +7,7 @@ import itertools
import textwrap
import tomli
from ui import get_printer_models
from epson_print_conf import get_printer_models, EpsonPrinter
WASTE_LABELS = [
"main_waste", "borderless_waste", "third_waste", "fourth_waste",
@ -53,7 +53,7 @@ def traverse_data(element, depth=0):
def generate_config_from_xml(
config, traverse, add_fatal_errors, full, printer_model
config, traverse=False, add_fatal_errors=False, full=False, printer_model=False
):
irc_pattern = [
r'Ink replacement counter %-% (\w+) % \((\w+)\)',
@ -231,12 +231,12 @@ def generate_config_from_xml(
def normalize_config(
config,
remove_invalid,
expand_names,
add_alias,
aggregate_alias,
maint_level,
add_same_as,
remove_invalid=True,
expand_names=True,
add_alias=True,
aggregate_alias=True,
maint_level=True,
add_same_as=True,
):
logging.info("Number of configuration entries before removing invalid ones: %s", len(config))
# Remove printers without write_key or without read_key
@ -360,7 +360,7 @@ def normalize_config(
return config
def generate_config_from_toml(
config, printer_model, full,
config, printer_model=None, full=False,
):
# Generate "read_key" values
@ -650,8 +650,6 @@ def main():
if args.pickle:
pickle.dump(normalized_config, args.pickle[0]) # serialize the list
args.pickle[0].close()
from epson_print_conf import EpsonPrinter
ep = EpsonPrinter(conf_dict=normalized_config, replace_conf=True)
logging.info("Number of expanded configuration entries: %s", len(ep.PRINTER_CONFIG))
quit()

388
ui.py
View file

@ -5,6 +5,7 @@
Epson Printer Configuration via SNMP (TCP/IP) - GUI
"""
import os
import sys
import re
import threading
@ -15,6 +16,7 @@ import socket
import traceback
import logging
import webbrowser
import pickle
import black
import tkinter as tk
@ -22,14 +24,15 @@ from tkinter import ttk, Menu
from tkinter.scrolledtext import ScrolledText
import tkinter.font as tkfont
from tkcalendar import DateEntry # Ensure you have: pip install tkcalendar
from tkinter import simpledialog, messagebox
from tkinter import simpledialog, messagebox, filedialog
import pyperclip
from epson_print_conf import EpsonPrinter
from epson_print_conf import EpsonPrinter, get_printer_models
from parse_devices import generate_config_from_toml, generate_config_from_xml, normalize_config
from find_printers import PrinterScanner
VERSION = "4.0"
VERSION = "5.0"
NO_CONF_ERROR = (
"[ERROR] Please select a printer model and a valid IP address,"
@ -44,40 +47,6 @@ CONFIRM_MESSAGE = (
"Are you sure you want to proceed?"
)
def get_printer_models(input_string):
# Tokenize the string
tokens = re.split(" |/", input_string)
if not len(tokens):
return []
# Define the words to remove (uppercase, then case insensitive)
remove_tokens = {"EPSON", "SERIES"}
# Process tokens
processed_tokens = []
non_numeric_part = ""
pre_model = ""
for token in tokens:
upper_token = token.upper()
# Remove tokens that match remove_tokens
if any(word == upper_token for word in remove_tokens):
continue
if not any(char.isdigit() for char in token): # no alphanum inside
pre_model = pre_model + token + " "
continue
# Identify the non-numeric part of the first token
if not token.isnumeric() and not non_numeric_part:
non_numeric_part = "".join(c for c in token if not c.isdigit())
# if token is numeric, prepend the non-numeric part
if token.isnumeric():
processed_tokens.append(f"{pre_model}{non_numeric_part}{token}")
else:
processed_tokens.append(f"{pre_model}{token}")
if not processed_tokens and pre_model:
processed_tokens.append(pre_model.strip())
return processed_tokens
class MultiLineInputDialog(simpledialog.Dialog):
def __init__(self, parent, title=None, text=""):
@ -205,7 +174,7 @@ class EpsonPrinterUI(tk.Tk):
self,
model: str = None,
hostname: str = None,
conf_dict={},
conf_dict = {},
replace_conf=False
):
super().__init__()
@ -225,6 +194,89 @@ class EpsonPrinterUI(tk.Tk):
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
# Setup the menu
menubar = tk.Menu(self)
self.config(menu=menubar)
# Create File menu
file_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="File", menu=file_menu)
LOAD_LABEL_NAME = "%s printer configuration file or web URL..."
LOAD_LABEL_TITLE = "Select a %s printer configuration file, or enter a Web URL"
LOAD_LABEL_TYPE = "%s files"
file_menu.add_command(
label=LOAD_LABEL_NAME % "Load a PICKLE",
command=lambda: self.load_from_file(
file_type={
"title": LOAD_LABEL_TITLE % "PICKLE",
"filetypes": [
(LOAD_LABEL_TYPE % "PICKLE", "*.pickle"),
("All files", "*.*")
]
},
type=0
)
)
file_menu.add_command(
label=LOAD_LABEL_NAME % "Import a XML",
command=lambda: self.load_from_file(
file_type={
"title": LOAD_LABEL_TITLE % "XML",
"filetypes": [
(LOAD_LABEL_TYPE % "XML", "*.xml"),
("All files", "*.*")
]
},
type=1
)
)
file_menu.add_command(
label=LOAD_LABEL_NAME % "Import a TOML",
command=lambda: self.load_from_file(
file_type={
"title": LOAD_LABEL_TITLE % "TOML",
"filetypes": [
(LOAD_LABEL_TYPE % "TOML", "*.toml"),
("All files", "*.*")
]
},
type=2
)
)
file_menu.add_command(
label="Save the selected printer configuration to a PICKLE file...",
command=self.save_to_file
)
# Create Help menu
help_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Settings", menu=help_menu)
help_menu.add_command(label="Show printer parameters of the selected model", command=self.printer_config)
help_menu.entryconfig("Show printer parameters of the selected model", accelerator="F2")
help_menu.add_command(label="Show printer keys of the selected model", command=self.key_values)
help_menu.entryconfig("Show printer keys of the selected model", accelerator="F3")
help_menu.add_command(label="Remove selected printer configuration", command=self.remove_printer_conf)
help_menu.entryconfig("Remove selected printer configuration", accelerator="F4")
help_menu.add_command(label="Keep only selected printer configuration", command=self.keep_printer_conf)
help_menu.entryconfig("Keep only selected printer configuration", accelerator="F5")
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="Get next local IP addresss", command=lambda: self.next_ip(0))
help_menu.entryconfig("Get next local IP addresss", accelerator="F9")
# Create Help menu
help_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Help", menu=help_menu)
help_menu.add_command(label="Help", command=self.open_help_browser)
help_menu.add_command(label="Program Information", command=self.show_program_info)
# Setup frames
FRAME_PAD = 10
PAD = (3, 0)
PADX = 4
@ -277,12 +329,14 @@ class EpsonPrinterUI(tk.Tk):
)
ToolTip(
self.model_dropdown,
"Select the model of the printer, or press 'Detect Printers'.\n"
"Press F2 to dump the parameters associated to the printer model."
" Press F3 to get the values of the keys from the configuration.",
"Select the model of the printer, or press 'Detect Printers'."
" Special features are allowed via F2, F3, F4, F5, or F6.\n"
)
self.model_dropdown.bind("<F2>", self.printer_config)
self.model_dropdown.bind("<F3>", self.key_values)
self.model_dropdown.bind("<F4>", lambda event: self.remove_printer_conf())
self.model_dropdown.bind("<F5>", lambda event: self.keep_printer_conf())
self.model_dropdown.bind("<F6>", lambda event: self.clear_printer_list())
# BOX IP address
ip_frame = ttk.LabelFrame(
@ -310,13 +364,13 @@ class EpsonPrinterUI(tk.Tk):
self.ip_entry.grid(
row=0, column=1, pady=PADY, padx=PADX, sticky=(tk.W, tk.E)
)
self.ip_entry.bind("<F2>", self.next_ip)
self.ip_entry.bind("<F9>", self.next_ip)
ToolTip(
self.ip_entry,
"Enter the IP address, or press 'Detect Printers'"
" (you can also enter part of the IP address"
" to speed up the detection),"
" or press F2 more times to get the next local IP address,"
" or press F9 more times to get the next local IP address,"
" which can then be edited"
" (by removing the last part before pressing 'Detect Printers').",
)
@ -779,6 +833,219 @@ class EpsonPrinterUI(tk.Tk):
self.ip_var.trace('w', self.change_widget_states)
self.change_widget_states()
def save_to_file(self):
if not self.model_var.get():
self.show_status_text_view()
self.status_text.insert(
tk.END,
'[ERROR]: Unknown printer model.'
)
return
if not self.printer:
self.printer = EpsonPrinter(
conf_dict=self.conf_dict,
model=self.model_var.get(),
)
if not self.printer or not self.printer.parm:
self.show_status_text_view()
self.status_text.insert(
tk.END,
'[ERROR]: No printer configuration defined.'
)
return
# Open file dialog to enter the file
file_path = filedialog.asksaveasfilename(
defaultextension=".pickle",
title="PICKLE file name",
initialfile=self.model_var.get(),
filetypes=[("PICKLE files", "*.pickle")]
)
if not file_path:
self.show_status_text_view()
self.status_text.insert(
tk.END,
f"[WARNING] File save operation aborted.\n"
)
return
# Ensure the file has the desired extension
if "." not in file_path and not file_path.endswith(".pickle"):
file_path += ".pickle"
normalized_config = { self.model_var.get(): self.printer.parm.copy() }
normalized_config["internal_data"] = {}
normalized_config["internal_data"]["default_model"] = self.model_var.get()
if self.ip_var.get():
normalized_config["internal_data"]["hostname"] = self.ip_var.get()
try:
with open(file_path, "wb") as file:
pickle.dump(normalized_config, file) # serialize the list
except Exception:
self.show_status_text_view()
self.status_text.insert(
tk.END,
f"[ERROR] File save operation failed.\n"
)
return
self.status_text.insert(
tk.END,
f'[INFO] "{os.path.basename(file_path)}" file save operation completed.\n'
)
def load_from_file(self, file_type, type):
# Open file dialog to select the file
file_path = filedialog.askopenfilename(**file_type)
if not file_path:
self.show_status_text_view()
self.status_text.insert(
tk.END,
f"[WARNING] File load operation aborted.\n"
)
return
if type == 0:
try:
with open(file_path, 'rb') as pickle_file:
self.conf_dict = pickle.load(pickle_file)
except Exception as e:
self.show_status_text_view()
if not file_path.tell():
self.status_text.insert(
tk.END,
f"[ERROR] Empty PICKLE FILE {file_path}.\n"
)
else:
self.status_text.insert(
tk.END,
f"[ERROR] Cannot load PICKLE file {file_path}. {e}\n"
)
return
if (
"internal_data" in self.conf_dict
and "hostname" in self.conf_dict["internal_data"]
):
self.ip_var.set(self.conf_dict["internal_data"]["hostname"])
if (
"internal_data" in self.conf_dict
and "default_model" in self.conf_dict["internal_data"]
):
self.model_var.set(self.conf_dict["internal_data"]["default_model"])
else:
self.status_text.insert(
tk.END,
f"[INFO] Converting file, please wait...\n"
)
self.update_idletasks()
if type == 1:
printer_config = generate_config_from_xml(config=file_path)
if type == 2:
printer_config = generate_config_from_toml(config=file_path)
if not printer_config:
self.show_status_text_view()
self.status_text.insert(
tk.END,
f"[ERROR] Cannot load file {file_path}\n"
)
return
self.conf_dict = normalize_config(config=printer_config)
self.model_dropdown["values"] = sorted(EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf
).valid_printers)
if file_path:
self.show_status_text_view()
self.status_text.insert(
tk.END,
f"[INFO] Loaded file {os.path.basename(file_path)}.\n"
)
def keep_printer_conf(self):
self.show_status_text_view()
if not self.model_var.get():
self.status_text.insert(
tk.END,
'[ERROR]: Select a valid printer model.\n'
)
return
keep_model = self.model_var.get()
self.model_dropdown["values"] = tuple(
model for model in self.model_dropdown["values"] if model == keep_model
)
self.replace_conf = True
self.show_status_text_view()
self.update_idletasks()
self.status_text.insert(
tk.END,
f"[INFO] Printer {keep_model} is the only one in the list.\n"
)
def remove_printer_conf(self):
self.show_status_text_view()
if not self.model_var.get():
self.status_text.insert(
tk.END,
'[ERROR]: Select a valid printer model.\n'
)
return
remove_model = self.model_var.get()
self.model_var.set("")
self.model_dropdown["values"] = tuple(
model for model in self.model_dropdown["values"] if model != remove_model
)
self.replace_conf = True
self.show_status_text_view()
self.update_idletasks()
self.status_text.insert(
tk.END,
f"[INFO] Configuation of printer {remove_model} removed.\n"
)
def clear_printer_list(self):
self.conf_dict = {}
self.model_var.set("")
self.model_dropdown["values"] = {}
self.replace_conf = True
self.show_status_text_view()
self.update_idletasks()
self.status_text.insert(
tk.END,
f"[INFO] Printer list cleared.\n"
)
def open_help_browser(self):
# Opens a web browser to a help URL
url = "https://github.com/Ircama/epson_print_conf/?tab=readme-ov-file#epson_print_conf"
self.show_status_text_view()
try:
ret = webbrowser.open(url)
if ret:
self.status_text.insert(
tk.END, f"[INFO] The browser is being opened.\n"
)
else:
self.status_text.insert(
tk.END, f"[ERROR] Cannot open browser.\n"
)
except Exception as e:
self.status_text.insert(
tk.END, f"[ERROR] Cannot open web browser: {e}\n"
)
finally:
self.config(cursor="")
self.update_idletasks()
def show_program_info(self):
# Show program information in a popup
program_version = "1.0.0" # Specify your program version
description = """
Epson Printer Configuration tool via SNMP (TCP/IP).
A tool for managing settings of Epson printers connected via Wi-Fi over the SNMP protocol.
Web site: https://github.com/Ircama/epson_print_conf
"""
self.title("Epson Printer Configuration - v" + VERSION)
messagebox.showinfo("Program Information",
f"Version: {VERSION}\n{description}"
)
def focus_next(self, event):
event.widget.tk_focusNext().focus()
return("break")
@ -1783,6 +2050,7 @@ class EpsonPrinterUI(tk.Tk):
return
if not self.printer:
self.printer = EpsonPrinter(
conf_dict=self.conf_dict,
hostname=self.ip_var.get()
)
self.printer.parm = {'read_key': None}
@ -1796,16 +2064,17 @@ class EpsonPrinterUI(tk.Tk):
read_key = None
try:
read_key = self.printer.brute_force_read_key()
self.status_text.insert(
tk.END, f"[INFO] Detected read_key: {read_key}.\n"
)
except Exception as e:
self.handle_printer_error(e)
logging.getLogger().setLevel(current_log_level)
self.config(cursor="")
self.update_idletasks()
return
if not read_key:
if read_key:
self.status_text.insert(
tk.END, f"[INFO] Detected read_key: {read_key}.\n"
)
else:
self.status_text.insert(
tk.END, f"[ERROR] Could not detect read_key.\n"
)
@ -2163,13 +2432,14 @@ class EpsonPrinterUI(tk.Tk):
try:
addr = range(0, 2048)
eeprom = {
k: int(v, 16) for k, v in zip(
addr,self.printer.read_eeprom_many(
k: None if v == None else int(v, 16) for k, v in zip(
addr,
self.printer.read_eeprom_many(
addr, label="dump_EEPROM"
)
)
}
if not eeprom:
if not eeprom or eeprom == {0: None}:
self.status_text.insert(
tk.END,
'[ERROR] Cannot read EEPROM values'
@ -2658,6 +2928,10 @@ class EpsonPrinterUI(tk.Tk):
ip_address = self.ip_var.get()
if not self._is_valid_ip(ip_address):
self.show_status_text_view()
self.status_text.insert(
tk.END, f"[ERROR] Missing IP address or printer host name.\n"
)
return
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
@ -2670,7 +2944,10 @@ class EpsonPrinterUI(tk.Tk):
+ form_feed
)
except Exception as e:
self.handle_printer_error(e)
self.show_status_text_view()
self.status_text.insert(
tk.END, f"[ERROR] Printer is unreachable or offline.\n"
)
def main():
@ -2726,7 +3003,14 @@ def main():
logging.getLogger().setLevel(logging.DEBUG)
conf_dict = {}
if args.pickle:
conf_dict = pickle.load(args.pickle[0])
try:
conf_dict = pickle.load(args.pickle[0])
except Exception as e:
if not args.pickle[0].tell():
print("Error. Empty PICKLE FILE.")
else:
print("Error. Cannot load PICKLE FILE:", e)
quit()
return EpsonPrinterUI(
model=args.model,