1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3# 4# (c) Copyright 2003-2015 HP Development Company, L.P. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program; if not, write to the Free Software 18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19# 20# Author: Don Welch 21# 22 23__version__ = '2.0' 24__title__ = 'Supply Levels Utility' 25__mod__ = 'hp-levels' 26__doc__ = "Display bar graphs of current supply levels for supported HPLIP printers." 27 28# Std Lib 29import sys 30import getopt 31import time 32import operator 33import os 34 35# Local 36from base.g import * 37from base import device, status, utils, tui, module 38from prnt import cups 39 40DEFAULT_BAR_GRAPH_SIZE = 8*(tui.ttysize()[1])/10 41 42 43def logBarGraph(agent_level, agent_type, size=DEFAULT_BAR_GRAPH_SIZE, use_colors=True, bar_char='/'): 44 #print agent_level, agent_type, size, use_colors, bar_char 45 46 adj = 100.0/size 47 if adj==0.0: adj=100.0 48 bar = int(agent_level/adj) 49 size = int(size) 50 if bar > (size-2): bar = size-2 51 52 if use_colors: 53 if agent_type in (AGENT_TYPE_CMY, AGENT_TYPE_KCM, AGENT_TYPE_CYAN, AGENT_TYPE_CYAN_LOW): 54 log.info(log.codes['teal']) 55 elif agent_type in (AGENT_TYPE_MAGENTA, AGENT_TYPE_MAGENTA_LOW): 56 log.info(log.codes['fuscia']) 57 elif agent_type in (AGENT_TYPE_YELLOW, AGENT_TYPE_YELLOW_LOW): 58 log.info(log.codes['yellow']) 59 elif agent_type == AGENT_TYPE_BLUE: 60 log.info(log.codes['blue']) 61 elif agent_type in (AGENT_TYPE_BLACK, AGENT_TYPE_BLACK_B8800): 62 log.info(log.codes['bold']) 63 elif agent_type in (AGENT_TYPE_LG, AGENT_TYPE_G, AGENT_TYPE_PG): 64 pass 65 66 color = '' 67 if use_colors: 68 if agent_type in (AGENT_TYPE_CMY, AGENT_TYPE_KCM): 69 color = log.codes['fuscia'] 70 71 log.info(("-"*(size))+color) 72 73 color = '' 74 if use_colors: 75 if agent_type in (AGENT_TYPE_CMY, AGENT_TYPE_KCM): 76 color = log.codes['yellow'] 77 78 log.info("%s%s%s%s (approx. %d%%)%s" % ("|", bar_char*bar, 79 " "*((size)-bar-2), "|", agent_level, color)) 80 81 82 color = '' 83 if use_colors: 84 color = log.codes['reset'] 85 86 log.info(("-"*int(size))+color) 87 #log.info(("-"*(size))+color) 88 89 90log.set_module('hp-levels') 91 92try: 93 mod = module.Module(__mod__, __title__, __version__, __doc__, None, 94 (INTERACTIVE_MODE,)) 95 96 mod.setUsage(module.USAGE_FLAG_DEVICE_ARGS, 97 extra_options=[ 98 ("Bar graph size:", "-s<size> or --size=<size> (current default=%d)" % DEFAULT_BAR_GRAPH_SIZE, "option", False), 99 ("Use colored bar graphs:", "-c or --color (default is colorized)", "option", False), 100 ("Bar graph character:", "-a<char> or --char=<char> (default is '/')", "option", False)]) 101 102 103 opts, device_uri, printer_name, mode, ui_toolkit, lang = \ 104 mod.parseStdOpts('s:ca:', ['size=', 'color', 'char=']) 105 106 device_uri = mod.getDeviceUri(device_uri, printer_name) 107 if not device_uri: 108 sys.exit(1) 109 log.info("Using device : %s\n" % device_uri) 110 size = DEFAULT_BAR_GRAPH_SIZE 111 color = True 112 bar_char = '/' 113 114 for o, a in opts: 115 if o in ('-s', '--size'): 116 try: 117 size = int(a.strip()) 118 except (TypeError, ValueError): 119 log.warn("Invalid size specified. Using the default of %d" % DEFAULT_BAR_GRAPH_SIZE) 120 size = DEFAULT_BAR_GRAPH_SIZE 121 122 if size < 1 or size > DEFAULT_BAR_GRAPH_SIZE: 123 log.warn("Invalid size specified. Using the default of %d" % DEFAULT_BAR_GRAPH_SIZE) 124 size = DEFAULT_BAR_GRAPH_SIZE 125 126 elif o in ('-c', '--color'): 127 color = True 128 129 elif o in ('-a', '--char'): 130 try: 131 bar_char = a[0] 132 except KeyError: 133 bar_char = '/' 134 135 136 try: 137 d = device.Device(device_uri, printer_name) 138 except Error: 139 log.error("Error opening device. Exiting.") 140 sys.exit(1) 141 142 try: 143 try: 144 d.open() 145 d.queryDevice() 146 except Error as e: 147 log.error("Error opening device (%s). Exiting." % e.msg) 148 sys.exit(1) 149 150 if d.mq['status-type'] != STATUS_TYPE_NONE: 151 log.info("") 152 153 sorted_supplies = [] 154 a = 1 155 while True: 156 try: 157 agent_type = int(d.dq['agent%d-type' % a]) 158 agent_kind = int(d.dq['agent%d-kind' % a]) 159 agent_sku = d.dq['agent%d-sku' % a] 160 log.debug("%d: agent_type %d agent_kind %d agent_sku '%s'" % (a, agent_type, agent_kind, agent_sku)) 161 except KeyError: 162 break 163 else: 164 sorted_supplies.append((a, agent_kind, agent_type, agent_sku)) 165 a += 1 166 sorted_supplies.sort(key=utils.cmp_to_key(utils.levelsCmp)) 167 168 for x in sorted_supplies: 169 a, agent_kind, agent_type, agent_sku = x 170 agent_health = d.dq['agent%d-health' % a] 171 agent_level = d.dq['agent%d-level' % a] 172 agent_desc = d.dq['agent%d-desc' % a] 173 agent_health_desc = d.dq['agent%d-health-desc' % a] 174 175 if agent_health in (AGENT_HEALTH_OK, AGENT_HEALTH_UNKNOWN) and \ 176 agent_kind in (AGENT_KIND_SUPPLY, 177 AGENT_KIND_HEAD_AND_SUPPLY, 178 AGENT_KIND_TONER_CARTRIDGE, 179 AGENT_KIND_MAINT_KIT, 180 AGENT_KIND_ADF_KIT, 181 AGENT_KIND_INT_BATTERY, 182 AGENT_KIND_DRUM_KIT,): 183 184 log.info(log.bold(agent_desc)) 185 log.info("Part No.: %s" % agent_sku) 186 log.info("Health: %s" % agent_health_desc) 187 logBarGraph(agent_level, agent_type, size, color, bar_char) 188 log.info("") 189 190 else: 191 log.info(log.bold(agent_desc)) 192 log.info("Part No.: %s" % agent_sku) 193 log.info("Health: %s" % agent_health_desc) 194 log.info("") 195 196 197 else: 198 log.error("Status not supported for selected device.") 199 sys.exit(1) 200 finally: 201 d.close() 202 203except KeyboardInterrupt: 204 log.error("User exit") 205 206log.info("") 207log.info("Done.") 208 209 210 211