mirror of
https://github.com/Ircama/epson_print_conf.git
synced 2025-05-15 07:34:40 -04:00
Improvements
This commit is contained in:
parent
4b3cdfc7e3
commit
096e9487e4
3 changed files with 125 additions and 24 deletions
15
README.md
15
README.md
|
@ -4,7 +4,7 @@ Epson Printer Configuration tool via SNMP (TCP/IP)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Access the Epson printer via SNMP (TCP/IP; printer connected over Wi-Fi)
|
- Interface Epson printers via SNMP (TCP/IP, with printers connected over Wi-Fi)
|
||||||
- Print the advanced status of the printer, with the possibility to restrict the query to specific information
|
- Print the advanced status of the printer, with the possibility to restrict the query to specific information
|
||||||
- Other inspection features:
|
- Other inspection features:
|
||||||
- Reset ink waste
|
- Reset ink waste
|
||||||
|
@ -12,12 +12,12 @@ Epson Printer Configuration tool via SNMP (TCP/IP)
|
||||||
- Other admin stuffs and debug options
|
- Other admin stuffs and debug options
|
||||||
- Read and write EEPROM addresses
|
- Read and write EEPROM addresses
|
||||||
- Dump a set of EEPROM addresses
|
- Dump a set of EEPROM addresses
|
||||||
- both a GUI and a command line tool
|
- Both a GUI and a command line tool
|
||||||
- Python API interface
|
- Python API interface
|
||||||
|
|
||||||
The GUI has an autodiscovery function which finds the printer IP addresses and their model names. The GUI can be used to get the printer status, to set the "Power-off timer", to set the "TI Received Time" and to reset the ink waste counter.
|
The GUI has an autodiscovery function which finds the printer IP addresses and their model names; it can be used to get the printer status, to set the "Power-off timer", to set the "TI Received Time" and to reset the ink waste counter.
|
||||||
|
|
||||||
The software provides a configurable printer dictionary, which can be easily extended. There is also a tool to import an extensive Epson printer configuration DB.
|
The software provides a configurable printer dictionary, which can be easily extended. There is also a tool to import and convert an extensive Epson printer configuration DB.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@ -218,8 +218,8 @@ The `-m` option is optional and is used to filter the printer model in scope. If
|
||||||
Program usage:
|
Program usage:
|
||||||
|
|
||||||
```
|
```
|
||||||
parse_devices.py [-h] [-m PRINTER_MODEL] [-l LINE_LENGTH] [-i] [-d] [-t] [-v] [-f] [-e] [-c CONFIG_FILE]
|
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]
|
||||||
[-s DEFAULT_MODEL] [-a HOSTNAME] [-p PICKLE_FILE] [-I] [-N] [-A] [-S]
|
[-N] [-A] [-G] [-S] [-M]
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
|
@ -244,7 +244,10 @@ optional arguments:
|
||||||
-I, --keep_invalid Do not remove printers without write_key or without read_key
|
-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
|
-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
|
-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
|
-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
|
||||||
```
|
```
|
||||||
|
|
|
@ -300,6 +300,52 @@ class EpsonPrinter:
|
||||||
"Maintenance required level of 2nd waste ink counter": [55],
|
"Maintenance required level of 2nd waste ink counter": [55],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"ET-2810": {
|
||||||
|
"read_key": [74, 54],
|
||||||
|
"write_key": b"Maribaya",
|
||||||
|
"main_waste": {"oids": [48, 49, 47], "divider": 63.46},
|
||||||
|
"borderless_waste": {"oids": [50, 51, 47], "divider": 34.16},
|
||||||
|
"third_waste": {"oids": [252, 253, 254], "divider": 13.0},
|
||||||
|
"raw_waste_reset": {
|
||||||
|
48: 0, 49: 0, 47: 0, 52: 0, 53: 0, 54: 94, 50: 0, 51: 0,
|
||||||
|
55: 94, 28: 0, 252: 0, 253: 0, 254: 0, 255: 94
|
||||||
|
},
|
||||||
|
"stats": {
|
||||||
|
"Maintenance required level of 1st waste ink counter": [54],
|
||||||
|
"Maintenance required level of 2nd waste ink counter": [55],
|
||||||
|
"Manual cleaning counter": [90],
|
||||||
|
"Timer cleaning counter": [89],
|
||||||
|
"Power cleaning counter": [91],
|
||||||
|
"Total print pass counter": [133, 132, 131, 130],
|
||||||
|
"Total print page counter": [776, 775, 774, 773],
|
||||||
|
"Total scan counter": [1843, 1842, 1841, 1840],
|
||||||
|
},
|
||||||
|
"serial_number": range(1604, 1614),
|
||||||
|
"alias": ["ET-2811", "ET-2813", "ET-2815"],
|
||||||
|
},
|
||||||
|
"ET-2812": {
|
||||||
|
"read_key": [74, 54],
|
||||||
|
"write_key": b"Maribaya",
|
||||||
|
"main_waste": {"oids": [48, 49, 47], "divider": 63.46},
|
||||||
|
"borderless_waste": {"oids": [50, 51, 47], "divider": 34.16},
|
||||||
|
"third_waste": {"oids": [252, 253, 254], "divider": 13.0},
|
||||||
|
"raw_waste_reset": {
|
||||||
|
48: 0, 49: 0, 47: 0, 52: 0, 53: 0, 54: 94, 50: 0, 51: 0,
|
||||||
|
55: 94, 28: 0, 252: 0, 253: 0, 254: 0, 255: 94
|
||||||
|
},
|
||||||
|
"stats": {
|
||||||
|
"Maintenance required level of 1st waste ink counter": [54],
|
||||||
|
"Maintenance required level of 2nd waste ink counter": [55],
|
||||||
|
"Manual cleaning counter": [90],
|
||||||
|
"Timer cleaning counter": [89],
|
||||||
|
"Power cleaning counter": [91],
|
||||||
|
"Total print pass counter": [133, 132, 131, 130],
|
||||||
|
"Total print page counter": [776, 775, 774, 773],
|
||||||
|
"Total scan counter": [1843, 1842, 1841, 1840],
|
||||||
|
},
|
||||||
|
"serial_number": range(1604, 1614),
|
||||||
|
"alias": ["ET-2814", "ET-2816", "ET-2818"],
|
||||||
|
},
|
||||||
"L3160": {
|
"L3160": {
|
||||||
"read_key": [151, 7],
|
"read_key": [151, 7],
|
||||||
"write_key": b'Maribaya',
|
"write_key": b'Maribaya',
|
||||||
|
@ -325,6 +371,7 @@ class EpsonPrinter:
|
||||||
"main_waste": {"oids": [24, 25, 30], "divider": 62.07},
|
"main_waste": {"oids": [24, 25, 30], "divider": 62.07},
|
||||||
"raw_waste_reset": {24: 0, 25: 0, 30: 0, 28: 0, 29: 0, 46: 94},
|
"raw_waste_reset": {24: 0, 25: 0, 30: 0, 28: 0, 29: 0, 46: 94},
|
||||||
"stats": {
|
"stats": {
|
||||||
|
"Maintenance required level of waste ink counter": [46],
|
||||||
"Manual cleaning counter": [147],
|
"Manual cleaning counter": [147],
|
||||||
"Timer cleaning counter": [149],
|
"Timer cleaning counter": [149],
|
||||||
"Power cleaning counter": [148],
|
"Power cleaning counter": [148],
|
||||||
|
@ -548,7 +595,7 @@ class EpsonPrinter:
|
||||||
"ET-2550": { # Epson EcoTank ET-2550
|
"ET-2550": { # Epson EcoTank ET-2550
|
||||||
"read_key": [0x44, 0x01],
|
"read_key": [0x44, 0x01],
|
||||||
"write_key": b'Gazania*',
|
"write_key": b'Gazania*',
|
||||||
"main_waste": {"oids": [24, 25], "divider": 62.06},
|
"main_waste": {"oids": [24, 25, 30], "divider": 62.06},
|
||||||
"serial_number": range(192, 202),
|
"serial_number": range(192, 202),
|
||||||
"stats": {
|
"stats": {
|
||||||
"Maintenance required level of waste ink counter": [46]
|
"Maintenance required level of waste ink counter": [46]
|
||||||
|
@ -561,17 +608,18 @@ class EpsonPrinter:
|
||||||
# uncompleted
|
# uncompleted
|
||||||
},
|
},
|
||||||
"ET-2700": { # Epson EcoTank ET-2700 Series
|
"ET-2700": { # Epson EcoTank ET-2700 Series
|
||||||
|
"alias": ["ET-2701", "ET-2703", "ET-2705"],
|
||||||
"read_key": [73, 8],
|
"read_key": [73, 8],
|
||||||
"write_key": b'Arantifo',
|
"write_key": b'Arantifo',
|
||||||
"serial_number": range(1604, 1614),
|
"serial_number": range(1604, 1614),
|
||||||
"main_waste": {"oids": [48, 49], "divider": 109.125},
|
"main_waste": {"oids": [48, 49, 47], "divider": 109.13},
|
||||||
"second_waste": {"oids": [50, 51], "divider": 16.31},
|
"borderless_waste": {"oids": [50, 51, 47], "divider": 16.31},
|
||||||
"stats": {
|
"stats": {
|
||||||
"Maintenance required level of 1st waste ink counter": [54],
|
"Maintenance required level of 1st waste ink counter": [54],
|
||||||
"Maintenance required level of 2nd waste ink counter": [55],
|
"Maintenance required level of 2nd waste ink counter": [55],
|
||||||
"First TI received time": [9, 8],
|
"First TI received time": [9, 8],
|
||||||
"Total print pass counter": [133, 132, 131, 130],
|
"Total print pass counter": [133, 132, 131, 130],
|
||||||
"Total print page counter": [776, 775, 774, 773],
|
"Total print page counter - rear feed": [755, 754, 753, 752],
|
||||||
"Total scan counter": [1843, 1842, 1841, 1840],
|
"Total scan counter": [1843, 1842, 1841, 1840],
|
||||||
"Ink replacement counter - Black": [554],
|
"Ink replacement counter - Black": [554],
|
||||||
"Ink replacement counter - Cyan": [555],
|
"Ink replacement counter - Cyan": [555],
|
||||||
|
@ -1685,26 +1733,34 @@ class EpsonPrinter:
|
||||||
j.rjust(4), i[j].rjust(4), value.rjust(4)
|
j.rjust(4), i[j].rjust(4), value.rjust(4)
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
|
missing = "Not available"
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
k: v for k, v in
|
k: v for k, v in
|
||||||
{
|
{
|
||||||
# items which must exist
|
"ink_color": self.ink_color(int(i['IC1'], 16))
|
||||||
"ink_color": self.ink_color(int(i['IC1'], 16)),
|
if 'IC1' in i else missing,
|
||||||
"ink_quantity": int(i['IQT'], 16),
|
"ink_quantity": int(i['IQT'], 16)
|
||||||
|
if 'IQT' in i else missing,
|
||||||
"production_year": int(i['PDY'], 16) + (
|
"production_year": int(i['PDY'], 16) + (
|
||||||
1900 if int(i['PDY'], 16) > 80 else 2000),
|
1900 if int(i['PDY'], 16) > 80 else 2000)
|
||||||
"production_month": int(i['PDM'], 16),
|
if 'PDY' in i else missing,
|
||||||
# items which can be excluded
|
"production_month": int(i['PDM'], 16)
|
||||||
"data": i.get('SID').strip(),
|
if 'PDM' in i else missing,
|
||||||
"manufacturer": i.get('LOG').strip(),
|
"data": i.get('SID').strip()
|
||||||
|
if 'SID' in i else missing,
|
||||||
|
"manufacturer": i.get('LOG').strip()
|
||||||
|
if 'LOG' in i else missing,
|
||||||
}.items()
|
}.items()
|
||||||
if v # exclude items without value
|
if v # exclude items without value
|
||||||
|
} if 'II' in i and i['II'] == '03' else {
|
||||||
|
"Ink Information": f"Unknown {i['II']}"
|
||||||
|
if 'II' in i and i['II'] != '00' else missing
|
||||||
}
|
}
|
||||||
for i in cartridges
|
for i in cartridges
|
||||||
]
|
]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("Cartridge value error: %s", e)
|
logging.error("Cartridge value error: %s.\n%s", e, cartridges)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def dump_eeprom(self, start: int = 0, end: int = 0xFF):
|
def dump_eeprom(self, start: int = 0, end: int = 0xFF):
|
||||||
|
@ -2329,13 +2385,13 @@ if __name__ == "__main__":
|
||||||
args.query[0] in printer.parm["stats"]):
|
args.query[0] in printer.parm["stats"]):
|
||||||
ret = printer.get_stats(args.query[0])
|
ret = printer.get_stats(args.query[0])
|
||||||
if ret:
|
if ret:
|
||||||
pprint(ret)
|
pprint(ret, width=100, compact=True)
|
||||||
else:
|
else:
|
||||||
print("No information returned. Check printer definition.")
|
print("No information returned. Check printer definition.")
|
||||||
elif args.query[0] in printer.MIB_INFO.keys():
|
elif args.query[0] in printer.MIB_INFO.keys():
|
||||||
ret = printer.get_snmp_info(args.query[0])
|
ret = printer.get_snmp_info(args.query[0])
|
||||||
if ret:
|
if ret:
|
||||||
pprint(ret)
|
pprint(ret, width=100, compact=True)
|
||||||
else:
|
else:
|
||||||
print("No information returned. Check printer definition.")
|
print("No information returned. Check printer definition.")
|
||||||
else:
|
else:
|
||||||
|
@ -2346,7 +2402,7 @@ if __name__ == "__main__":
|
||||||
if method in printer.list_methods:
|
if method in printer.list_methods:
|
||||||
ret = printer.__getattribute__(method)()
|
ret = printer.__getattribute__(method)()
|
||||||
if ret:
|
if ret:
|
||||||
pprint(ret)
|
pprint(ret, width=100, compact=True)
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
"No information returned."
|
"No information returned."
|
||||||
|
@ -2412,7 +2468,7 @@ if __name__ == "__main__":
|
||||||
if args.info or not print_opt:
|
if args.info or not print_opt:
|
||||||
ret = printer.stats()
|
ret = printer.stats()
|
||||||
if ret:
|
if ret:
|
||||||
pprint(ret)
|
pprint(ret, width=100, compact=True)
|
||||||
else:
|
else:
|
||||||
print("No information returned. Check printer definition.")
|
print("No information returned. Check printer definition.")
|
||||||
except TimeoutError as e:
|
except TimeoutError as e:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
@ -225,6 +226,7 @@ def normalize_config(
|
||||||
expand_names,
|
expand_names,
|
||||||
add_alias,
|
add_alias,
|
||||||
aggregate_alias,
|
aggregate_alias,
|
||||||
|
maint_level,
|
||||||
add_same_as,
|
add_same_as,
|
||||||
):
|
):
|
||||||
logging.info("Number of configuration entries before removing invalid ones: %s", len(config))
|
logging.info("Number of configuration entries before removing invalid ones: %s", len(config))
|
||||||
|
@ -330,15 +332,37 @@ def normalize_config(
|
||||||
)))
|
)))
|
||||||
del config[key]
|
del config[key]
|
||||||
|
|
||||||
|
if maint_level:
|
||||||
|
for key, items in config.copy().items():
|
||||||
|
if "raw_waste_reset" in items:
|
||||||
|
n = 1
|
||||||
|
for k, v in items["raw_waste_reset"].items():
|
||||||
|
if v == 94:
|
||||||
|
if "stats" not in items:
|
||||||
|
items["stats"] = {}
|
||||||
|
m_key = f"Maintenance required level of {ordinal(n)} waste ink counter"
|
||||||
|
if m_key in items["stats"]:
|
||||||
|
print("ERROR key", key, m_key)
|
||||||
|
quit()
|
||||||
|
items["stats"][m_key] = [k]
|
||||||
|
n += 1
|
||||||
|
|
||||||
logging.info("Number of obtained configuration entries: %s", len(config))
|
logging.info("Number of obtained configuration entries: %s", len(config))
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
def ordinal(n: int):
|
||||||
|
if 11 <= (n % 100) <= 13:
|
||||||
|
suffix = 'th'
|
||||||
|
else:
|
||||||
|
suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)]
|
||||||
|
return str(n) + suffix
|
||||||
|
|
||||||
def equal_dicts(a, b, ignore_keys):
|
def equal_dicts(a, b, ignore_keys):
|
||||||
ka = set(a).difference(ignore_keys)
|
ka = set(a).difference(ignore_keys)
|
||||||
kb = set(b).difference(ignore_keys)
|
kb = set(b).difference(ignore_keys)
|
||||||
return ka == kb and all(a[k] == b[k] for k in ka)
|
return ka == kb and all(a[k] == b[k] for k in ka)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def main():
|
||||||
import argparse
|
import argparse
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
|
@ -472,6 +496,13 @@ if __name__ == "__main__":
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Do not add "same-as" for similar printers with different names'
|
help='Do not add "same-as" for similar printers with different names'
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-M',
|
||||||
|
'--no_maint_level',
|
||||||
|
dest='no_maint_level',
|
||||||
|
action='store_true',
|
||||||
|
help='Do not add "Maintenance required levelas" in "stats"'
|
||||||
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.debug:
|
if args.debug:
|
||||||
|
@ -501,6 +532,7 @@ if __name__ == "__main__":
|
||||||
expand_names=not args.keep_names,
|
expand_names=not args.keep_names,
|
||||||
add_alias=not args.no_alias,
|
add_alias=not args.no_alias,
|
||||||
aggregate_alias=not args.no_aggregate_alias,
|
aggregate_alias=not args.no_aggregate_alias,
|
||||||
|
maint_level=not args.no_maint_level,
|
||||||
add_same_as=not args.no_same_as,
|
add_same_as=not args.no_same_as,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -532,3 +564,13 @@ if __name__ == "__main__":
|
||||||
if args.indent:
|
if args.indent:
|
||||||
dict_str = textwrap.indent(dict_str, ' ')
|
dict_str = textwrap.indent(dict_str, ' ')
|
||||||
print(dict_str)
|
print(dict_str)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print('\nInterrupted.')
|
||||||
|
try:
|
||||||
|
sys.exit(130)
|
||||||
|
except SystemExit:
|
||||||
|
os._exit(130)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue