Skip to content

Commit

Permalink
Process TOML format
Browse files Browse the repository at this point in the history
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],
            },
        }
    }
```
  • Loading branch information
Ircama committed Oct 21, 2024
1 parent adcbffd commit 4a65352
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 18 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,4 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
devices.xml
*.toml
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:

Expand All @@ -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
Expand All @@ -283,22 +287,25 @@ 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
Default printer host name or IP address. (Example: -a 192.168.1.87)
-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*.
Expand Down
76 changes: 66 additions & 10 deletions parse_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import xml.etree.ElementTree as ET
import itertools
import textwrap
import tomli

from ui import get_printer_models

Expand Down Expand Up @@ -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'
Expand All @@ -368,15 +413,22 @@ 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',
'--model',
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',
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -520,13 +573,16 @@ def main():
else:
config = "devices.xml"

printer_config = generate_config(
config=config,
traverse=args.traverse,
add_fatal_errors=args.add_fatal_errors,
full=args.full,
printer_model=args.printer_model
)
if args.toml:
printer_config = convert_toml(config)
else:
printer_config = generate_config(
config=config,
traverse=args.traverse,
add_fatal_errors=args.add_fatal_errors,
full=args.full,
printer_model=args.printer_model
)
normalized_config = normalize_config(
config=printer_config,
remove_invalid=not args.keep_invalid,
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pyasyncore;python_version>="3.12"
tkcalendar
pyperclip
black
tomli

0 comments on commit 4a65352

Please sign in to comment.