Process TOML format

Ref #32

Example:

Input file epson.toml

```
[[EPSON]]
rkey = 0x364A
wkey = "Bsboujgp"
wkey1 = "Arantifo"
models = ["ET-2850", "ET-2851", "ET-2853", "ET-2855", "L4260", "L4261", "L4263", "L4265", "L4266", "L4267", "L4268", "L4269", "Workforce ST-C2100"]
mem = [
{ addr = [0x1C,0x34,0x35,0x36,0x37,0xFF] , desc = "Waste counters (?)" , reset = [0x00,0x00,0x00,0x5E,0x5E,0x5E] },
{ addr = [0x2F] , desc = "Waste counter" },
{ addr = [0x30,0x31] , desc = "Waste counter" },
{ addr = [0x32,0x33] , desc = "Waste counter" },
{ addr = [0xFC,0xFD] , desc = "Waste counter" },
{ addr = [0xFE] , desc = "Waste counter" },
]
rlen = 2
wlen = 2
mem_high = 0x7FF
```

Command:

```
python3 parse_devices.py -T -c epson.toml -i -l 200
```

Conversion:
```
    PRINTER_CONFIG = {
        "ET-2850": {
            "read_key": [74, 54],
            "write_key": b"Arantifo",
            "raw_waste_reset": {28: 0, 52: 0, 53: 0, 54: 94, 55: 94, 255: 94, 47: 0, 48: 0, 49: 0, 50: 0, 51: 0, 252: 0, 253: 0, 254: 0},
            "alias": ["ET-2851", "ET-2853", "ET-2855", "L4260", "L4261", "L4263", "L4265", "L4266", "L4267", "L4268", "L4269", "Workforce ST-C2100"],
            "stats": {
                "Maintenance required level of 1st waste ink counter": [54],
                "Maintenance required level of 2nd waste ink counter": [55],
                "Maintenance required level of 3rd waste ink counter": [255],
            },
        }
    }
```
This commit is contained in:
Ircama 2024-10-21 06:45:53 +02:00
parent adcbffd72b
commit 4a65352c89
4 changed files with 83 additions and 18 deletions

1
.gitignore vendored
View file

@ -159,3 +159,4 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
devices.xml
*.toml

View file

@ -52,6 +52,8 @@ The software provides a configurable printer dictionary, which can be easily ext
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
@ -251,7 +253,7 @@ This repository includes a Windows *epson_print_conf.exe* executable file which
Within a [report](https://codeberg.org/atufi/reinkpy/issues/12#issue-716809) in repo https://codeberg.org/atufi/reinkpy there is an interesting [attachment](https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25bac4495a1d) which includes an extensive XML database of Epson model features.
The program *parse_devices.py* transforms this XML DB into the dictionary that *epson_print_conf.py* can use.
The program *parse_devices.py* transforms this XML DB into the dictionary that *epson_print_conf.py* can use. It is also able to accept the TOML input format, if the `-T` option is used.
Here is a simple procedure to download that DB and run *parse_devices.py* to search for the XP-205 model and produce the related PRINTER_CONFIG dictionary to the standard output:
@ -267,13 +269,15 @@ The `-m` option is optional and is used to filter the printer model in scope. If
Program usage:
```
parse_devices.py [-h] [-m PRINTER_MODEL] [-l LINE_LENGTH] [-i] [-d] [-t] [-v] [-f] [-e] [-c CONFIG_FILE] [-s DEFAULT_MODEL] [-a HOSTNAME] [-p PICKLE_FILE] [-I]
[-N] [-A] [-G] [-S] [-M]
usage: parse_devices.py [-h] [-m PRINTER_MODEL] [-T] [-l LINE_LENGTH] [-i] [-d] [-t] [-v] [-f] [-e]
[-c CONFIG_FILE] [-s DEFAULT_MODEL] [-a HOSTNAME] [-p PICKLE_FILE] [-I] [-N]
[-A] [-G] [-S] [-M]
optional arguments:
-h, --help show this help message and exit
-m PRINTER_MODEL, --model PRINTER_MODEL
Printer model. Example: -m XP-205
Filter printer model. Example: -m XP-205
-T, --toml Use TOML input format instead of XML
-l LINE_LENGTH, --line LINE_LENGTH
Set line length of the output (default: 120)
-i, --indent Indent output of 4 spaces
@ -283,7 +287,8 @@ optional arguments:
-f, --full Generate additional tags
-e, --errors Add last_printer_fatal_errors
-c CONFIG_FILE, --config CONFIG_FILE
use the XML configuration file to generate the configuration
use the XML or TOML configuration file to generate the configuration; default
is 'devices.xml'
-s DEFAULT_MODEL, --default_model DEFAULT_MODEL
Default printer model. Example: -s XP-205
-a HOSTNAME, --address HOSTNAME
@ -291,14 +296,16 @@ optional arguments:
-p PICKLE_FILE, --pickle PICKLE_FILE
Save a pickle archive for subsequent load by ui.py and epson_print_conf.py
-I, --keep_invalid Do not remove printers without write_key or without read_key
-N, --keep_names Do not replace original names with converted names and add printers for all optional names
-A, --no_alias Do not add aliases for same printer with different names and remove aliased printers
-N, --keep_names Do not replace original names with converted names and add printers for all
optional names
-A, --no_alias Do not add aliases for same printer with different names and remove aliased
printers
-G, --no_aggregate_alias
Do not aggregate aliases of printers with same configuration
-S, --no_same_as Do not add "same-as" for similar printers with different names
-M, --no_maint_level Do not add "Maintenance required levelas" in "stats"
Generate printer configuration from devices.xml
Generate printer configuration from devices.xml or from TOML
```
The program does not provide *printer_head_id* and *Power off timer*.

View file

@ -5,6 +5,7 @@ import re
import xml.etree.ElementTree as ET
import itertools
import textwrap
import tomli
from ui import get_printer_models
@ -351,6 +352,50 @@ def normalize_config(
logging.info("Number of obtained configuration entries: %s", len(config))
return config
def convert_toml(config):
def hex_to_bytes(hex_value):
byte1 = (hex_value >> 8) & 0xFF
byte2 = hex_value & 0xFF
return [byte2, byte1]
with open(config, mode="rb") as fp:
parsed_toml = tomli.load(fp)
# Parse mem entries to create raw_waste_reset
def parse_mem_entries(mem):
raw_waste_reset = {}
for entry in mem:
addr = entry.get('addr', [])
reset = entry.get('reset', [0] * len(addr))
for addr_val, reset_val in zip(addr, reset):
raw_waste_reset[addr_val] = reset_val
return raw_waste_reset
output_data = {}
for section_name, section_val in parsed_toml.items():
# Convert rkey and extract mem data
section_data = section_val[0]
read_key = hex_to_bytes(section_data["rkey"])
raw_waste_reset = parse_mem_entries(section_data["mem"])
main_model = section_data["models"][0]
alias = section_data["models"][1:]
if main_model in ["EPSON"] and alias:
main_model = alias.pop(0)
# Structure the section data in the desired format
output_data[main_model] = {
"read_key": read_key,
"write_key": section_data["wkey1"].encode(), # Write key in bytes
"raw_waste_reset": raw_waste_reset, # Raw waste reset dictionary
"alias": alias # Remaining models as aliases
}
return output_data
def ordinal(n: int):
if 11 <= (n % 100) <= 13:
suffix = 'th'
@ -368,7 +413,7 @@ def main():
import pickle
parser = argparse.ArgumentParser(
epilog='Generate printer configuration from devices.xml'
epilog='Generate printer configuration from devices.xml or from TOML'
)
parser.add_argument(
'-m',
@ -376,7 +421,14 @@ def main():
dest='printer_model',
default=False,
action="store",
help='Printer model. Example: -m XP-205'
help='Filter printer model. Example: -m XP-205'
)
parser.add_argument(
'-T',
'--toml',
dest='toml',
action='store_true',
help='Use TOML input format instead of XML'
)
parser.add_argument(
'-l',
@ -433,7 +485,8 @@ def main():
"--config",
dest='config_file',
type=argparse.FileType('r'),
help="use the XML configuration file to generate the configuration",
help="use the XML or TOML configuration file to generate"
" the configuration; default is 'devices.xml'",
default=0,
nargs=1,
metavar='CONFIG_FILE'
@ -520,6 +573,9 @@ def main():
else:
config = "devices.xml"
if args.toml:
printer_config = convert_toml(config)
else:
printer_config = generate_config(
config=config,
traverse=args.traverse,

View file

@ -5,3 +5,4 @@ pyasyncore;python_version>="3.12"
tkcalendar
pyperclip
black
tomli