%PDF- %PDF-
Direktori : /usr/share/hplip/base/ |
Current File : //usr/share/hplip/base/status.py |
# -*- coding: utf-8 -*- # # (c) Copyright 2003-2015 HP Development Company, L.P. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Don Welch, Narla Naga Samrat Chowdary, Yashwant Kumar Sahu # # Std Lib import json, ast import ssl import sys try: from urllib.request import urlopen except: from urllib import urlopen import struct import io from .sixext import BytesIO, to_bytes_utf8, to_bytes_latin, to_string_latin, to_long from .g import * import xml.parsers.expat as expat import re try: from xml.etree import ElementTree etree_loaded = True except ImportError: try: from elementtree.ElementTree import XML elementtree_loaded = True except ImportError: elementtree_loaded = False etree_loaded = False # Local from .g import * from .codes import * from . import pml, utils cupsext = utils.import_ext('cupsext') hpmudext = utils.import_ext('hpmudext') """ status dict structure: { 'revision' : STATUS_REV_00 .. STATUS_REV_04, 'agents' : [ list of pens/agents/supplies (dicts) ], 'top-door' : TOP_DOOR_NOT_PRESENT | TOP_DOOR_CLOSED | TOP_DOOR_OPEN, 'status-code' : STATUS_..., 'supply-door' : SUPPLY_DOOR_NOT_PRESENT | SUPPLY_DOOR_CLOSED | SUPPLY_DOOR_OPEN. 'duplexer' : DUPLEXER_NOT_PRESENT | DUPLEXER_DOOR_CLOSED | DUPLEXER_DOOR_OPEN, 'photo_tray' : PHOTO_TRAY_NOT_PRESENT | PHOTO_TRAY_ENGAGED | PHOTO_TRAY_NOT_ENGAGED, 'in-tray1' : IN_TRAY_NOT_PRESENT | IN_TRAY_CLOSED | IN_TRAY_OPEN (| IN_TRAY_DEFAULT | IN_TRAY_LOCKED)*, 'in-tray2' : IN_TRAY_NOT_PRESENT | IN_TRAY_CLOSED | IN_TRAY_OPEN (| IN_TRAY_DEFAULT | IN_TRAY_LOCKED)*, 'media-path' : MEDIA_PATH_NOT_PRESENT | MEDIA_PATH_CUT_SHEET | MEDIA_PATH_BANNER | MEDIA_PATH_PHOTO, } * S:02 only agent dict structure: (pens/supplies/agents/etc) { 'kind' : AGENT_KIND_NONE ... AGENT_KIND_ADF_KIT, 'type' : TYPE_BLACK ... AGENT_TYPE_UNSPECIFIED, # aka color 'health' : AGENT_HEALTH_OK ... AGENT_HEALTH_UNKNOWN, 'level' : 0 ... 100, 'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0 ... AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, } """ # 'revision' STATUS_REV_00 = 0x00 STATUS_REV_01 = 0x01 STATUS_REV_02 = 0x02 STATUS_REV_03 = 0x03 STATUS_REV_04 = 0x04 STATUS_REV_V = 0xff STATUS_REV_UNKNOWN = 0xfe vstatus_xlate = {'busy' : STATUS_PRINTER_BUSY, 'idle' : STATUS_PRINTER_IDLE, 'prnt' : STATUS_PRINTER_PRINTING, 'offf' : STATUS_PRINTER_TURNING_OFF, 'rprt' : STATUS_PRINTER_REPORT_PRINTING, 'cncl' : STATUS_PRINTER_CANCELING, 'iost' : STATUS_PRINTER_IO_STALL, 'dryw' : STATUS_PRINTER_DRY_WAIT_TIME, 'penc' : STATUS_PRINTER_PEN_CHANGE, 'oopa' : STATUS_PRINTER_OUT_OF_PAPER, 'bnej' : STATUS_PRINTER_BANNER_EJECT, 'bnmz' : STATUS_PRINTER_BANNER_MISMATCH, 'phmz' : STATUS_PRINTER_PHOTO_MISMATCH, 'dpmz' : STATUS_PRINTER_DUPLEX_MISMATCH, 'pajm' : STATUS_PRINTER_MEDIA_JAM, 'cars' : STATUS_PRINTER_CARRIAGE_STALL, 'paps' : STATUS_PRINTER_PAPER_STALL, 'penf' : STATUS_PRINTER_PEN_FAILURE, 'erro' : STATUS_PRINTER_HARD_ERROR, 'pwdn' : STATUS_PRINTER_POWER_DOWN, 'fpts' : STATUS_PRINTER_FRONT_PANEL_TEST, 'clno' : STATUS_PRINTER_CLEAN_OUT_TRAY_MISSING} REVISION_2_TYPE_MAP = {0 : AGENT_TYPE_NONE, 1 : AGENT_TYPE_BLACK, 2 : AGENT_TYPE_CYAN, 3 : AGENT_TYPE_MAGENTA, 4 : AGENT_TYPE_YELLOW, 5 : AGENT_TYPE_BLACK, 6 : AGENT_TYPE_CYAN, 7 : AGENT_TYPE_MAGENTA, 8 : AGENT_TYPE_YELLOW, } STATUS_BLOCK_UNKNOWN = {'revision' : STATUS_REV_UNKNOWN, 'agents' : [], 'status-code' : STATUS_UNKNOWN, } NUM_PEN_POS = {STATUS_REV_00 : 16, STATUS_REV_01 : 16, STATUS_REV_02 : 16, STATUS_REV_03 : 18, STATUS_REV_04 : 22} PEN_DATA_SIZE = {STATUS_REV_00 : 8, STATUS_REV_01 : 8, STATUS_REV_02 : 4, STATUS_REV_03 : 8, STATUS_REV_04 : 8} STATUS_POS = {STATUS_REV_00 : 14, STATUS_REV_01 : 14, STATUS_REV_02 : 14, STATUS_REV_03 : 16, STATUS_REV_04 : 20} def parseSStatus(s, z=''): revision = '' pens = [] top_door = TOP_DOOR_NOT_PRESENT stat = STATUS_UNKNOWN supply_door = SUPPLY_DOOR_NOT_PRESENT duplexer = DUPLEXER_NOT_PRESENT photo_tray = PHOTO_TRAY_NOT_PRESENT in_tray1 = IN_TRAY_NOT_PRESENT in_tray2 = IN_TRAY_NOT_PRESENT media_path = MEDIA_PATH_NOT_PRESENT Z_SIZE = 6 try: z1 = [] if len(z) > 0: z_fields = z.split(',') for z_field in z_fields: if len(z_field) > 2 and z_field[:2] == '05': z1s = z_field[2:] z1 = [int(x, 16) for x in z1s] s1 = [int(x, 16) for x in s] revision = s1[1] assert STATUS_REV_00 <= revision <= STATUS_REV_04 top_door = bool(s1[2] & to_long(0x8)) + s1[2] & to_long(0x1) supply_door = bool(s1[3] & to_long(0x8)) + s1[3] & to_long(0x1) duplexer = bool(s1[4] & to_long(0xc)) + s1[4] & to_long(0x1) photo_tray = bool(s1[5] & 0x8) + s1[5] & 0x1 if revision == STATUS_REV_02: in_tray1 = bool(s1[6] & to_long(0x8)) + s1[6] & to_long(0x1) in_tray2 = bool(s1[7] & to_long(0x8)) + s1[7] & to_long(0x1) else: in_tray1 = bool(s1[6] & to_long(0x8)) in_tray2 = bool(s1[7] & to_long(0x8)) media_path = bool(s1[8] & to_long(0x8)) + (s1[8] & to_long(0x1)) + ((bool(s1[18] & to_long(0x2)))<<1) status_pos = STATUS_POS[revision] status_byte = s1[status_pos]<<4 if status_byte != 48: status_byte = (s1[status_pos]<<4) + s1[status_pos + 1] stat = status_byte + STATUS_PRINTER_BASE pen, c, d = {}, NUM_PEN_POS[revision]+1, 0 num_pens = s1[NUM_PEN_POS[revision]] index = 0 pen_data_size = PEN_DATA_SIZE[revision] log.debug("num_pens = %d" % num_pens) for p in range(num_pens): info = int(s[c : c + pen_data_size], 16) pen['index'] = index if pen_data_size == 4: pen['type'] = REVISION_2_TYPE_MAP.get(int((info & to_long(0xf000)) >> to_long(12)), 0) if index < (num_pens / 2): pen['kind'] = AGENT_KIND_HEAD else: pen['kind'] = AGENT_KIND_SUPPLY pen['level-trigger'] = int ((info & to_long(0x0e00)) >> to_long(9)) pen['health'] = int((info & to_long(0x0180)) >> to_long(7)) pen['level'] = int(info & to_long(0x007f)) pen['id'] = 0x1f elif pen_data_size == 8: pen['kind'] = bool(info & to_long(0x80000000)) + ((bool(info & to_long(0x40000000)))<<to_long(1)) pen['type'] = int((info & to_long(0x3f000000)) >> to_long(24)) pen['id'] = int((info & 0xf80000) >> to_long(19)) pen['level-trigger'] = int((info & to_long(0x70000)) >> to_long(16)) pen['health'] = int((info & to_long(0xc000)) >> to_long(14)) pen['level'] = int(info & to_long(0xff)) else: log.error("Pen data size error") if len(z1) > 0: # TODO: Determine cause of IndexError for C6100 (defect #1111) try: pen['dvc'] = int(z1s[d+1:d+5], 16) pen['virgin'] = bool(z1[d+5] & to_long(0x8)) pen['hp-ink'] = bool(z1[d+5] & to_long(0x4)) pen['known'] = bool(z1[d+5] & to_long(0x2)) pen['ack'] = bool(z1[d+5] & to_long(0x1)) except IndexError: pen['dvc'] = 0 pen['virgin'] = 0 pen['hp-ink'] = 0 pen['known'] = 0 pen['ack'] = 0 log.debug("pen %d %s" % (index, pen)) index += 1 pens.append(pen) pen = {} c += pen_data_size d += Z_SIZE except (IndexError, ValueError, TypeError) as e: log.warn("Status parsing error: %s" % str(e)) return {'revision' : revision, 'agents' : pens, 'top-door' : top_door, 'status-code' : stat, 'supply-door' : supply_door, 'duplexer' : duplexer, 'photo-tray' : photo_tray, 'in-tray1' : in_tray1, 'in-tray2' : in_tray2, 'media-path' : media_path, } # $HB0$NC0,ff,DN,IDLE,CUT,K0,C0,DP,NR,KP092,CP041 # 0 1 2 3 4 5 6 7 8 9 10 def parseVStatus(s): pens, pen, c = [], {}, 0 fields = s.split(',') log.debug(fields) f0 = fields[0] if len(f0) == 20: # TODO: $H00000000$M00000000 style (OJ Pro 1150/70) # Need spec pass elif len(f0) == 8: for p in f0: if c == 0: #assert p == '$' c += 1 elif c == 1: if p in ('a', 'A'): pen['type'], pen['kind'] = AGENT_TYPE_NONE, AGENT_KIND_NONE c += 1 elif c == 2: pen['health'] = AGENT_HEALTH_OK pen['kind'] = AGENT_KIND_HEAD_AND_SUPPLY if p in ('b', 'B'): pen['type'] = AGENT_TYPE_BLACK elif p in ('c', 'C'): pen['type'] = AGENT_TYPE_CMY elif p in ('d', 'D'): pen['type'] = AGENT_TYPE_KCM elif p in ('u', 'U'): pen['type'], pen['health'] = AGENT_TYPE_NONE, AGENT_HEALTH_MISINSTALLED c += 1 elif c == 3: if p == '0': pen['state'] = 1 else: pen['state'] = 0 pen['level'] = 0 i = 8 while True: try: f = fields[i] except IndexError: break else: if f[:2] == 'KP' and pen['type'] == AGENT_TYPE_BLACK: pen['level'] = int(f[2:]) elif f[:2] == 'CP' and pen['type'] == AGENT_TYPE_CMY: pen['level'] = int(f[2:]) i += 1 pens.append(pen) pen = {} c = 0 else: pass try: fields[2] except IndexError: top_lid = 1 # something went wrong! else: if fields[2] == 'DN': top_lid = 1 else: top_lid = 2 try: stat = vstatus_xlate.get(fields[3].lower(), STATUS_PRINTER_IDLE) except IndexError: stat = STATUS_PRINTER_IDLE # something went wrong! return {'revision' : STATUS_REV_V, 'agents' : pens, 'top-door' : top_lid, 'status-code': stat, 'supply-door': SUPPLY_DOOR_NOT_PRESENT, 'duplexer' : DUPLEXER_NOT_PRESENT, 'photo-tray' : PHOTO_TRAY_NOT_PRESENT, 'in-tray1' : IN_TRAY_NOT_PRESENT, 'in-tray2' : IN_TRAY_NOT_PRESENT, 'media-path' : MEDIA_PATH_CUT_SHEET, # ? } def parseStatus(DeviceID): if 'VSTATUS' in DeviceID: return parseVStatus(DeviceID['VSTATUS']) elif 'S' in DeviceID: return parseSStatus(DeviceID['S'], DeviceID.get('Z', '')) else: return STATUS_BLOCK_UNKNOWN def LaserJetDeviceStatusToPrinterStatus(device_status, printer_status, detected_error_state): stat = STATUS_PRINTER_IDLE if device_status in (pml.DEVICE_STATUS_WARNING, pml.DEVICE_STATUS_DOWN): if detected_error_state & pml.DETECTED_ERROR_STATE_LOW_PAPER_MASK and \ not (detected_error_state & pml.DETECTED_ERROR_STATE_NO_PAPER_MASK): stat = STATUS_PRINTER_LOW_PAPER elif detected_error_state & pml.DETECTED_ERROR_STATE_NO_PAPER_MASK: stat = STATUS_PRINTER_OUT_OF_PAPER elif detected_error_state & pml.DETECTED_ERROR_STATE_DOOR_OPEN_MASK: stat = STATUS_PRINTER_DOOR_OPEN elif detected_error_state & pml.DETECTED_ERROR_STATE_JAMMED_MASK: stat = STATUS_PRINTER_MEDIA_JAM elif detected_error_state & pml.DETECTED_ERROR_STATE_OUT_CART_MASK: stat = STATUS_PRINTER_NO_TONER elif detected_error_state & pml.DETECTED_ERROR_STATE_LOW_CART_MASK: stat = STATUS_PRINTER_LOW_TONER elif detected_error_state == pml.DETECTED_ERROR_STATE_SERVICE_REQUEST_MASK: stat = STATUS_PRINTER_SERVICE_REQUEST elif detected_error_state & pml.DETECTED_ERROR_STATE_OFFLINE_MASK: stat = STATUS_PRINTER_OFFLINE else: if printer_status == pml.PRINTER_STATUS_IDLE: stat = STATUS_PRINTER_IDLE elif printer_status == pml.PRINTER_STATUS_PRINTING: stat = STATUS_PRINTER_PRINTING elif printer_status == pml.PRINTER_STATUS_WARMUP: stat = STATUS_PRINTER_WARMING_UP return stat # Map from ISO 10175/10180 to HPLIP types COLORANT_INDEX_TO_AGENT_TYPE_MAP = { 'other' : AGENT_TYPE_UNSPECIFIED, 'unknown' : AGENT_TYPE_UNSPECIFIED, 'blue' : AGENT_TYPE_BLUE, 'cyan' : AGENT_TYPE_CYAN, 'magenta': AGENT_TYPE_MAGENTA, 'yellow' : AGENT_TYPE_YELLOW, 'black' : AGENT_TYPE_BLACK, 'photoblack': AGENT_TYPE_PHOTO_BLACK, 'matteblack' : AGENT_TYPE_MATTE_BLACK, 'lightgray' : AGENT_TYPE_LG, 'gray': AGENT_TYPE_G, 'darkgray': AGENT_TYPE_DG, 'lightcyan': AGENT_TYPE_LC, 'lightmagenta': AGENT_TYPE_LM, 'red' : AGENT_TYPE_RED, } MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP = { pml.OID_MARKER_SUPPLIES_TYPE_OTHER : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_UNKNOWN : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_TONER : AGENT_KIND_TONER_CARTRIDGE, pml.OID_MARKER_SUPPLIES_TYPE_WASTE_TONER : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_INK : AGENT_KIND_SUPPLY, pml.OID_MARKER_SUPPLIES_TYPE_INK_CART : AGENT_KIND_HEAD_AND_SUPPLY, pml.OID_MARKER_SUPPLIES_TYPE_INK_RIBBON : AGENT_KIND_HEAD_AND_SUPPLY, pml.OID_MARKER_SUPPLIES_TYPE_WASTE_INK : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_OPC : AGENT_KIND_DRUM_KIT, pml.OID_MARKER_SUPPLIES_TYPE_DEVELOPER : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OIL : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_SOLID_WAX : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_RIBBON_WAX : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_WASTE_WAX : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_FUSER : AGENT_KIND_MAINT_KIT, pml.OID_MARKER_SUPPLIES_TYPE_CORONA_WIRE : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OIL_WICK : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_CLEANER_UNIT : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_FUSER_CLEANING_PAD : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_TRANSFER_UNIT : AGENT_KIND_TRANSFER_KIT, pml.OID_MARKER_SUPPLIES_TYPE_TONER_CART : AGENT_KIND_TONER_CARTRIDGE, pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OILER : AGENT_KIND_UNKNOWN, pml.OID_MARKER_SUPPLIES_TYPE_ADF_MAINT_KIT : AGENT_KIND_ADF_KIT, } def StatusType3( dev, parsedID ): # LaserJet Status (PML/SNMP) try: dev.openPML() #result_code, on_off_line = dev.getPML( pml.OID_ON_OFF_LINE, pml.INT_SIZE_BYTE ) #result_code, sleep_mode = dev.getPML( pml.OID_SLEEP_MODE, pml.INT_SIZE_BYTE ) result_code, printer_status = dev.getPML( pml.OID_PRINTER_STATUS, pml.INT_SIZE_BYTE ) result_code, device_status = dev.getPML( pml.OID_DEVICE_STATUS, pml.INT_SIZE_BYTE ) result_code, cover_status = dev.getPML( pml.OID_COVER_STATUS, pml.INT_SIZE_BYTE ) result_code, value = dev.getPML( pml.OID_DETECTED_ERROR_STATE ) except Error: dev.closePML() return {'revision' : STATUS_REV_UNKNOWN, 'agents' : [], 'top-door' : 0, 'status-code' : STATUS_UNKNOWN, 'supply-door' : 0, 'duplexer' : 1, 'photo-tray' : 0, 'in-tray1' : 0, 'in-tray2' : 0, 'media-path' : 0, } try: detected_error_state = struct.unpack( 'B', to_bytes_latin(value[0]))[0] except (IndexError, TypeError): detected_error_state = pml.DETECTED_ERROR_STATE_OFFLINE_MASK agents, x = [], 1 while True: log.debug( "%s Agent: %d %s" % ("*"*10, x, "*"*10)) log.debug("OID_MARKER_SUPPLIES_TYPE_%d:" % x) oid = ( pml.OID_MARKER_SUPPLIES_TYPE_x % x, pml.OID_MARKER_SUPPLIES_TYPE_x_TYPE ) result_code, value = dev.getPML( oid, pml.INT_SIZE_BYTE ) if result_code != ERROR_SUCCESS or value is None: log.debug("End of supply information.") break for a in MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP: if value == a: agent_kind = MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP[a] break else: agent_kind = AGENT_KIND_UNKNOWN # TODO: Deal with printers that return -1 and -2 for level and max (LJ3380) log.debug("OID_MARKER_SUPPLIES_LEVEL_%d:" % x) oid = ( pml.OID_MARKER_SUPPLIES_LEVEL_x % x, pml.OID_MARKER_SUPPLIES_LEVEL_x_TYPE ) result_code, agent_level = dev.getPML( oid ) if result_code != ERROR_SUCCESS: log.debug("Failed") break log.debug( 'agent%d-level: %d' % ( x, agent_level ) ) log.debug("OID_MARKER_SUPPLIES_MAX_%d:" % x) oid = ( pml.OID_MARKER_SUPPLIES_MAX_x % x, pml.OID_MARKER_SUPPLIES_MAX_x_TYPE ) result_code, agent_max = dev.getPML( oid ) if agent_max == 0: agent_max = 1 if result_code != ERROR_SUCCESS: log.debug("Failed") break log.debug( 'agent%d-max: %d' % ( x, agent_max ) ) log.debug("OID_MARKER_SUPPLIES_COLORANT_INDEX_%d:" % x) oid = ( pml.OID_MARKER_SUPPLIES_COLORANT_INDEX_x % x, pml.OID_MARKER_SUPPLIES_COLORANT_INDEX_x_TYPE ) result_code, colorant_index = dev.getPML( oid ) if result_code != ERROR_SUCCESS: # 3080, 3055 will fail here log.debug("Failed") agent_type = AGENT_TYPE_BLACK #break else: log.debug("Colorant index: %d" % colorant_index) log.debug("OID_MARKER_COLORANT_VALUE_%d" % x) oid = ( pml.OID_MARKER_COLORANT_VALUE_x % colorant_index, pml.OID_MARKER_COLORANT_VALUE_x_TYPE ) result_code, colorant_value = dev.getPML( oid ) if result_code != ERROR_SUCCESS: log.debug("Failed. Defaulting to black.") agent_type = AGENT_TYPE_BLACK else: if agent_kind in (AGENT_KIND_MAINT_KIT, AGENT_KIND_ADF_KIT, AGENT_KIND_DRUM_KIT, AGENT_KIND_TRANSFER_KIT): agent_type = AGENT_TYPE_UNSPECIFIED else: agent_type = AGENT_TYPE_BLACK if result_code != ERROR_SUCCESS: log.debug("OID_MARKER_SUPPLIES_DESCRIPTION_%d:" % x) oid = (pml.OID_MARKER_SUPPLIES_DESCRIPTION_x % x, pml.OID_MARKER_SUPPLIES_DESCRIPTION_x_TYPE) result_code, colorant_value = dev.getPML( oid ) if result_code != ERROR_SUCCESS: log.debug("Failed") break if colorant_value is not None: log.debug("colorant value: %s" % colorant_value) colorant_value = colorant_value.lower().strip() for c in COLORANT_INDEX_TO_AGENT_TYPE_MAP: if colorant_value.find(c) >= 0: agent_type = COLORANT_INDEX_TO_AGENT_TYPE_MAP[c] break else: agent_type = AGENT_TYPE_BLACK else: # SUCCESS if colorant_value is not None: log.debug("colorant value: %s" % colorant_value) colorant_value = colorant_value.lower().strip() agent_type = COLORANT_INDEX_TO_AGENT_TYPE_MAP.get( colorant_value, AGENT_TYPE_BLACK ) if agent_type == AGENT_TYPE_NONE: if agent_kind == AGENT_KIND_TONER_CARTRIDGE: agent_type = AGENT_TYPE_BLACK else: agent_type = AGENT_TYPE_UNSPECIFIED log.debug("OID_MARKER_STATUS_%d:" % x) oid = ( pml.OID_MARKER_STATUS_x % x, pml.OID_MARKER_STATUS_x_TYPE ) result_code, agent_status = dev.getPML( oid ) if result_code != ERROR_SUCCESS: log.debug("Failed") agent_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0 agent_health = AGENT_HEALTH_OK else: agent_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0 if agent_status is None: agent_health = AGENT_HEALTH_OK elif agent_status == pml.OID_MARKER_STATUS_OK: agent_health = AGENT_HEALTH_OK elif agent_status == pml.OID_MARKER_STATUS_MISINSTALLED: agent_health = AGENT_HEALTH_MISINSTALLED elif agent_status in ( pml.OID_MARKER_STATUS_LOW_TONER_CONT, pml.OID_MARKER_STATUS_LOW_TONER_STOP ): agent_health = AGENT_HEALTH_OK agent_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW else: agent_health = AGENT_HEALTH_OK agent_level = int(float(agent_level)/agent_max * 100) log.debug("agent%d: kind=%d, type=%d, health=%d, level=%d, level-trigger=%d" % \ (x, agent_kind, agent_type, agent_health, agent_level, agent_trigger)) agents.append({'kind' : agent_kind, 'type' : agent_type, 'health' : agent_health, 'level' : agent_level, 'level-trigger' : agent_trigger,}) x += 1 if x > 20: break printer_status = printer_status or STATUS_PRINTER_IDLE log.debug("printer_status=%d" % printer_status) device_status = device_status or pml.DEVICE_STATUS_RUNNING log.debug("device_status=%d" % device_status) cover_status = cover_status or pml.COVER_STATUS_CLOSED log.debug("cover_status=%d" % cover_status) detected_error_state = detected_error_state or pml.DETECTED_ERROR_STATE_NO_ERROR log.debug("detected_error_state=%d (0x%x)" % (detected_error_state, detected_error_state)) stat = LaserJetDeviceStatusToPrinterStatus(device_status, printer_status, detected_error_state) log.debug("Printer status=%d" % stat) if stat == STATUS_PRINTER_DOOR_OPEN: supply_door = 0 else: supply_door = 1 return {'revision' : STATUS_REV_UNKNOWN, 'agents' : agents, 'top-door' : cover_status, 'status-code' : stat, 'supply-door' : supply_door, 'duplexer' : 1, 'photo-tray' : 0, 'in-tray1' : 1, 'in-tray2' : 1, 'media-path' : 1, } def setup_panel_translator(): printables = list( """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~""") map = {} for x in [chr(x) for x in range(0,256)]: if x in printables: map[x] = x else: map[x] = '\x20' map.update({'\x10' : '\xab', '\x11' : '\xbb', '\x12' : '\xa3', '\x13' : '\xbb', '\x80' : '\xab', '\x81' : '\xbb', '\x82' : '\x2a', '\x83' : '\x2a', '\x85' : '\x2a', '\xa0' : '\xab', '\x1f' : '\x3f', '=' : '\x20', }) frm, to = to_bytes_latin(''), to_bytes_latin('') map_keys = list(map.keys()) map_keys.sort() for x in map_keys: frm = to_bytes_latin('').join([frm, to_bytes_latin(x)]) to = to_bytes_latin('').join([to, to_bytes_latin(map[x])]) global PANEL_TRANSLATOR_FUNC PANEL_TRANSLATOR_FUNC = utils.Translator(frm, to) PANEL_TRANSLATOR_FUNC = None setup_panel_translator() def PanelCheck(dev): line1, line2 = to_bytes_utf8(''), ('') if dev.io_mode not in (IO_MODE_RAW, IO_MODE_UNI): try: dev.openPML() except Error: pass else: oids = [(pml.OID_HP_LINE1, pml.OID_HP_LINE2), (pml.OID_SPM_LINE1, pml.OID_SPM_LINE2)] for oid1, oid2 in oids: result, line1 = dev.getPML(oid1) if result < pml.ERROR_MAX_OK: line1 = PANEL_TRANSLATOR_FUNC(line1.encode('utf-8')).rstrip() if to_bytes_utf8('\x0a') in line1: line1, line2 = line1.split(to_bytes_utf8('\x0a'), 1) break result, line2 = dev.getPML(oid2) if result < pml.ERROR_MAX_OK: line2 = PANEL_TRANSLATOR_FUNC(line2.encode('utf-8')).rstrip() break return bool(line1 or line2), line1 or to_bytes_utf8(''), line2 or to_bytes_utf8('') BATTERY_HEALTH_MAP = {0 : AGENT_HEALTH_OK, 1 : AGENT_HEALTH_OVERTEMP, 2 : AGENT_HEALTH_CHARGING, 3 : AGENT_HEALTH_MISINSTALLED, 4 : AGENT_HEALTH_FAILED, } BATTERY_TRIGGER_MAP = {0 : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, 1 : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, 2 : AGENT_LEVEL_TRIGGER_PROBABLY_OUT, 3 : AGENT_LEVEL_TRIGGER_SUFFICIENT_4, 4 : AGENT_LEVEL_TRIGGER_SUFFICIENT_2, 5 : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, } BATTERY_PML_TRIGGER_MAP = { (100, 80) : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, (79, 60) : AGENT_LEVEL_TRIGGER_SUFFICIENT_1, (59, 40) : AGENT_LEVEL_TRIGGER_SUFFICIENT_2, (39, 30) : AGENT_LEVEL_TRIGGER_SUFFICIENT_3, (29, 20) : AGENT_LEVEL_TRIGGER_SUFFICIENT_4, (19, 10) : AGENT_LEVEL_TRIGGER_MAY_BE_LOW, (9, 5) : AGENT_LEVEL_TRIGGER_PROBABLY_OUT, (4, -1) : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, } def BatteryCheck(dev, status_block, battery_check): try_dynamic_counters = False try: try: dev.openPML() except Error: if battery_check == STATUS_BATTERY_CHECK_STD: log.debug("PML channel open failed. Trying dynamic counters...") try_dynamic_counters = True else: if battery_check == STATUS_BATTERY_CHECK_PML: result, battery_level = dev.getPML(pml.OID_BATTERY_LEVEL_2) if result > pml.ERROR_MAX_OK: status_block['agents'].append({ 'kind' : AGENT_KIND_INT_BATTERY, 'type' : AGENT_TYPE_UNSPECIFIED, 'health' : AGENT_HEALTH_UNKNOWN, 'level' : 0, 'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, }) return else: status_block['agents'].append({ 'kind' : AGENT_KIND_INT_BATTERY, 'type' : AGENT_TYPE_UNSPECIFIED, 'health' : AGENT_HEALTH_OK, 'level' : battery_level, 'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, }) return else: # STATUS_BATTERY_CHECK_STD result, battery_level = dev.getPML(pml.OID_BATTERY_LEVEL) result, power_mode = dev.getPML(pml.OID_POWER_MODE) if battery_level is not None and \ power_mode is not None: if power_mode & pml.POWER_MODE_BATTERY_LEVEL_KNOWN and \ battery_level >= 0: for x in BATTERY_PML_TRIGGER_MAP: if x[0] >= battery_level > x[1]: battery_trigger_level = BATTERY_PML_TRIGGER_MAP[x] break if power_mode & pml.POWER_MODE_CHARGING: agent_health = AGENT_HEALTH_CHARGING elif power_mode & pml.POWER_MODE_DISCHARGING: agent_health = AGENT_HEALTH_DISCHARGING else: agent_health = AGENT_HEALTH_OK status_block['agents'].append({ 'kind' : AGENT_KIND_INT_BATTERY, 'type' : AGENT_TYPE_UNSPECIFIED, 'health' : agent_health, 'level' : battery_level, 'level-trigger' : battery_trigger_level, }) return else: status_block['agents'].append({ 'kind' : AGENT_KIND_INT_BATTERY, 'type' : AGENT_TYPE_UNSPECIFIED, 'health' : AGENT_HEALTH_UNKNOWN, 'level' : 0, 'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, }) return else: try_dynamic_counters = True finally: dev.closePML() if battery_check == STATUS_BATTERY_CHECK_STD and \ try_dynamic_counters: try: try: battery_health = dev.getDynamicCounter(200) battery_trigger_level = dev.getDynamicCounter(201) battery_level = dev.getDynamicCounter(202) status_block['agents'].append({ 'kind' : AGENT_KIND_INT_BATTERY, 'type' : AGENT_TYPE_UNSPECIFIED, 'health' : BATTERY_HEALTH_MAP[battery_health], 'level' : battery_level, 'level-trigger' : BATTERY_TRIGGER_MAP[battery_trigger_level], }) except Error: status_block['agents'].append({ 'kind' : AGENT_KIND_INT_BATTERY, 'type' : AGENT_TYPE_UNSPECIFIED, 'health' : AGENT_HEALTH_UNKNOWN, 'level' : 0, 'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, }) finally: dev.closePrint() else: status_block['agents'].append({ 'kind' : AGENT_KIND_INT_BATTERY, 'type' : AGENT_TYPE_UNSPECIFIED, 'health' : AGENT_HEALTH_UNKNOWN, 'level' : 0, 'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, }) # this works for 2 pen products that allow 1 or 2 pens inserted # from: k, kcm, cmy, ggk def getPenConfiguration(s): # s=status dict from parsed device ID pens = [p['type'] for p in s['agents']] if utils.all(pens, lambda x : x==AGENT_TYPE_NONE): return AGENT_CONFIG_NONE if AGENT_TYPE_NONE in pens: if AGENT_TYPE_BLACK in pens: return AGENT_CONFIG_BLACK_ONLY elif AGENT_TYPE_CMY in pens: return AGENT_CONFIG_COLOR_ONLY elif AGENT_TYPE_KCM in pens: return AGENT_CONFIG_PHOTO_ONLY elif AGENT_TYPE_GGK in pens: return AGENT_CONFIG_GREY_ONLY else: return AGENT_CONFIG_INVALID else: if AGENT_TYPE_BLACK in pens and AGENT_TYPE_CMY in pens: return AGENT_CONFIG_COLOR_AND_BLACK elif AGENT_TYPE_CMY in pens and AGENT_TYPE_KCM in pens: return AGENT_CONFIG_COLOR_AND_PHOTO elif AGENT_TYPE_CMY in pens and AGENT_TYPE_GGK in pens: return AGENT_CONFIG_COLOR_AND_GREY else: return AGENT_CONFIG_INVALID def getFaxStatus(dev): tx_active, rx_active = False, False if dev.io_mode not in (IO_MODE_UNI, IO_MODE_RAW): try: dev.openPML() result_code, tx_state = dev.getPML(pml.OID_FAXJOB_TX_STATUS) if result_code == ERROR_SUCCESS and tx_state: if tx_state not in (pml.FAXJOB_TX_STATUS_IDLE, pml.FAXJOB_TX_STATUS_DONE): tx_active = True result_code, rx_state = dev.getPML(pml.OID_FAXJOB_RX_STATUS) if result_code == ERROR_SUCCESS and rx_state: if rx_state not in (pml.FAXJOB_RX_STATUS_IDLE, pml.FAXJOB_RX_STATUS_DONE): rx_active = True finally: dev.closePML() return tx_active, rx_active TYPE6_STATUS_CODE_MAP = { 0 : STATUS_PRINTER_IDLE, #</DevStatusUnknown> -19928: STATUS_PRINTER_IDLE, -18995: STATUS_PRINTER_CANCELING, -17974: STATUS_PRINTER_WARMING_UP, -17973: STATUS_PRINTER_PEN_CLEANING, # sic -18993: STATUS_PRINTER_BUSY, -17949: STATUS_PRINTER_BUSY, -19720: STATUS_PRINTER_MANUAL_DUPLEX_BLOCK, -19678: STATUS_PRINTER_BUSY, -19695: STATUS_PRINTER_OUT_OF_PAPER, -17985: STATUS_PRINTER_MEDIA_JAM, -19731: STATUS_PRINTER_OUT_OF_PAPER, -18974: STATUS_PRINTER_BUSY, #? -19730: STATUS_PRINTER_OUT_OF_PAPER, -19729: STATUS_PRINTER_OUT_OF_PAPER, -19933: STATUS_PRINTER_HARD_ERROR, # out of memory -17984: STATUS_PRINTER_DOOR_OPEN, -19694: STATUS_PRINTER_DOOR_OPEN, -18992: STATUS_PRINTER_MANUAL_FEED_BLOCKED, # ? -19690: STATUS_PRINTER_MEDIA_JAM, # tray 1 -19689: STATUS_PRINTER_MEDIA_JAM, # tray 2 -19611: STATUS_PRINTER_MEDIA_JAM, # tray 3 -19686: STATUS_PRINTER_MEDIA_JAM, -19688: STATUS_PRINTER_MEDIA_JAM, # paper path -19685: STATUS_PRINTER_MEDIA_JAM, # cart area -19684: STATUS_PRINTER_MEDIA_JAM, # output bin -18848: STATUS_PRINTER_MEDIA_JAM, # duplexer -18847: STATUS_PRINTER_MEDIA_JAM, # door open -18846: STATUS_PRINTER_MEDIA_JAM, # tray 2 -19687: STATUS_PRINTER_MEDIA_JAM, # open door -17992: STATUS_PRINTER_MEDIA_JAM, # mispick -19700: STATUS_PRINTER_HARD_ERROR, # invalid driver -17996: STATUS_PRINTER_FUSER_ERROR, # fuser error -17983: STATUS_PRINTER_FUSER_ERROR, -17982: STATUS_PRINTER_FUSER_ERROR, -17981: STATUS_PRINTER_FUSER_ERROR, -17971: STATUS_PRINTER_FUSER_ERROR, -17995: STATUS_PRINTER_HARD_ERROR, # beam error -17994: STATUS_PRINTER_HARD_ERROR, # scanner error -17993: STATUS_PRINTER_HARD_ERROR, # fan error -18994: STATUS_PRINTER_HARD_ERROR, -17986: STATUS_PRINTER_HARD_ERROR, -19904: STATUS_PRINTER_HARD_ERROR, -19701: STATUS_PRINTER_NON_HP_INK, # [sic] -19613: STATUS_PRINTER_IDLE, # HP -19654: STATUS_PRINTER_NON_HP_INK, # [sic] -19682: STATUS_PRINTER_HARD_ERROR, # resinstall -19693: STATUS_PRINTER_IDLE, # ?? To Accept -19752: STATUS_PRINTER_LOW_TONER, -19723: STATUS_PRINTER_BUSY, -19703: STATUS_PRINTER_BUSY, -19739: STATUS_PRINTER_NO_TONER, -19927: STATUS_PRINTER_BUSY, -19932: STATUS_PRINTER_BUSY, -19931: STATUS_PRINTER_BUSY, -11989: STATUS_PRINTER_BUSY, -11995: STATUS_PRINTER_BUSY, # ADF loaded -19954: STATUS_PRINTER_CANCELING, -19955: STATUS_PRINTER_REPORT_PRINTING, -19956: STATUS_PRINTER_REPORT_PRINTING, -19934: STATUS_PRINTER_HARD_ERROR, -19930: STATUS_PRINTER_BUSY, -11990: STATUS_PRINTER_DOOR_OPEN, -11999: STATUS_PRINTER_MEDIA_JAM, # ADF -12000: STATUS_PRINTER_MEDIA_JAM, # ADF -11998: STATUS_PRINTER_MEDIA_JAM, # ADF -11986: STATUS_PRINTER_HARD_ERROR, # scanner -11994: STATUS_PRINTER_BUSY, -14967: STATUS_PRINTER_BUSY, -19912: STATUS_PRINTER_HARD_ERROR, -14962: STATUS_PRINTER_BUSY, # copy pending -14971: STATUS_PRINTER_BUSY, # copying -14973: STATUS_PRINTER_BUSY, # copying being canceled -14972: STATUS_PRINTER_BUSY, # copying canceled -14966: STATUS_PRINTER_DOOR_OPEN, -14974: STATUS_PRINTER_MEDIA_JAM, -14969: STATUS_PRINTER_HARD_ERROR, -14968: STATUS_PRINTER_HARD_ERROR, -12996: STATUS_PRINTER_BUSY, # scan -12994: STATUS_PRINTER_BUSY, # scan -12993: STATUS_PRINTER_BUSY, # scan -12991: STATUS_PRINTER_BUSY, # scan -12995: STATUS_PRINTER_BUSY, # scan -12997: STATUS_PRINTER_HARD_ERROR, # scan -12990: STATUS_PRINTER_BUSY, -12998: STATUS_PRINTER_BUSY, -13000: STATUS_PRINTER_DOOR_OPEN, -12999: STATUS_PRINTER_MEDIA_JAM, -13859: STATUS_PRINTER_BUSY, -13858: STATUS_PRINTER_BUSY, #</DevStatusDialingOut> -13868: STATUS_PRINTER_BUSY, #</DevStatusRedialPending> -13867: STATUS_PRINTER_BUSY, #</DevStatusFaxSendCanceled> -13857: STATUS_PRINTER_BUSY, #</DevStatusConnecting> -13856: STATUS_PRINTER_BUSY, #</DevStatusSendingPage> -13855: STATUS_PRINTER_BUSY, #</DevStatusOnePageSend> -13854: STATUS_PRINTER_BUSY, #</DevStatusMultiplePagesSent> -13853: STATUS_PRINTER_BUSY, #</DevStatusSenderCancelingFax> -13839: STATUS_PRINTER_BUSY, #</DevStatusIncomingCall> -13842: STATUS_PRINTER_BUSY, #</DevStatusBlockingFax> -13838: STATUS_PRINTER_BUSY, #</DevStatusReceivingFax> -13847: STATUS_PRINTER_BUSY, #</DevStatusSinglePageReceived> -13846: STATUS_PRINTER_BUSY, #</DevStatusDoublePagesReceived> -13845: STATUS_PRINTER_BUSY, #</DevStatusTriplePagesReceived> -13844: STATUS_PRINTER_BUSY, #</DevStatusPrintingFax> -13840: STATUS_PRINTER_BUSY, #</DevStatusCancelingFaxPrint> -13843: STATUS_PRINTER_BUSY, #</DevStatusFaxCancelingReceive> -13850: STATUS_PRINTER_BUSY, #</DevStatusFaxCanceledReceive> -13851: STATUS_PRINTER_BUSY, #</DevStatusFaxDelayedSendMemoryFull> -13836: STATUS_PRINTER_BUSY, #</DevStatusNoDialTone> -13864: STATUS_PRINTER_BUSY, #</DevStatusNoFaxAnswer> -13863: STATUS_PRINTER_BUSY, #</DevStatusFaxBusy> -13865: STATUS_PRINTER_BUSY, #</DevStatusNoDocumentSent> -13862: STATUS_PRINTER_BUSY, #</DevStatusFaxSendError> -13837: STATUS_PRINTER_BUSY, #</DevStatusT30Error> -13861: STATUS_PRINTER_BUSY, #</DevStatusFaxMemoryFullSend> -13866: STATUS_PRINTER_BUSY, #</DevStatusADFNotCleared> -13841: STATUS_PRINTER_BUSY, #</DevStatusNoFaxDetected> -13848: STATUS_PRINTER_BUSY, #</DevStatusFaxMemoryFullReceive> -13849: STATUS_PRINTER_BUSY, #</DevStatusFaxReceiveError> } def StatusType6(dev): # LaserJet Status (XML) info_device_status = BytesIO() info_ssp = BytesIO() try: dev.getEWSUrl("/hp/device/info_device_status.xml", info_device_status) dev.getEWSUrl("/hp/device/info_ssp.xml", info_ssp) except: log.warn("Failed to get Device status information") pass info_device_status = info_device_status.getvalue() info_ssp = info_ssp.getvalue() device_status = {} ssp = {} if info_device_status: try: log.debug_block("info_device_status", to_string_latin(info_device_status)) device_status = utils.XMLToDictParser().parseXML(info_device_status) log.debug(device_status) except expat.ExpatError: log.error("Device Status XML parse error") device_status = {} if info_ssp: try: log.debug_block("info_spp", to_string_latin(info_ssp)) ssp = utils.XMLToDictParser().parseXML(info_ssp) log.debug(ssp) except expat.ExpatError: log.error("SSP XML parse error") ssp = {} status_code = device_status.get('devicestatuspage-devicestatus-statuslist-status-code-0', 0) if not status_code: status_code = ssp.get('devicestatuspage-devicestatus-statuslist-status-code-0', 0) black_supply_level = device_status.get('devicestatuspage-suppliesstatus-blacksupply-percentremaining', 0) black_supply_low = ssp.get('suppliesstatuspage-blacksupply-lowreached', 0) agents = [] agents.append({ 'kind' : AGENT_KIND_TONER_CARTRIDGE, 'type' : AGENT_TYPE_BLACK, 'health' : 0, 'level' : black_supply_level, 'level-trigger' : 0, }) if dev.tech_type == TECH_TYPE_COLOR_LASER: cyan_supply_level = device_status.get('devicestatuspage-suppliesstatus-cyansupply-percentremaining', 0) agents.append({ 'kind' : AGENT_KIND_TONER_CARTRIDGE, 'type' : AGENT_TYPE_CYAN, 'health' : 0, 'level' : cyan_supply_level, 'level-trigger' : 0, }) magenta_supply_level = device_status.get('devicestatuspage-suppliesstatus-magentasupply-percentremaining', 0) agents.append({ 'kind' : AGENT_KIND_TONER_CARTRIDGE, 'type' : AGENT_TYPE_MAGENTA, 'health' : 0, 'level' : magenta_supply_level, 'level-trigger' : 0, }) yellow_supply_level = device_status.get('devicestatuspage-suppliesstatus-yellowsupply-percentremaining', 0) agents.append({ 'kind' : AGENT_KIND_TONER_CARTRIDGE, 'type' : AGENT_TYPE_YELLOW, 'health' : 0, 'level' : yellow_supply_level, 'level-trigger' : 0, }) return {'revision' : STATUS_REV_UNKNOWN, 'agents' : agents, 'top-door' : 0, 'supply-door' : 0, 'duplexer' : 1, 'photo-tray' : 0, 'in-tray1' : 1, 'in-tray2' : 1, 'media-path' : 1, 'status-code' : TYPE6_STATUS_CODE_MAP.get(status_code, STATUS_PRINTER_IDLE), } # PJL status codes PJL_STATUS_MAP = { 10001: STATUS_PRINTER_IDLE, # online 10002: STATUS_PRINTER_OFFLINE, # offline 10003: STATUS_PRINTER_WARMING_UP, 10004: STATUS_PRINTER_BUSY, # self test 10005: STATUS_PRINTER_BUSY, # reset 10006: STATUS_PRINTER_LOW_TONER, 10007: STATUS_PRINTER_CANCELING, 10010: STATUS_PRINTER_SERVICE_REQUEST, 10011: STATUS_PRINTER_OFFLINE, 10013: STATUS_PRINTER_BUSY, 10014: STATUS_PRINTER_REPORT_PRINTING, 10015: STATUS_PRINTER_BUSY, 10016: STATUS_PRINTER_BUSY, 10017: STATUS_PRINTER_REPORT_PRINTING, 10018: STATUS_PRINTER_BUSY, 10019: STATUS_PRINTER_BUSY, 10020: STATUS_PRINTER_BUSY, 10021: STATUS_PRINTER_BUSY, 10022: STATUS_PRINTER_REPORT_PRINTING, 10023: STATUS_PRINTER_PRINTING, 10024: STATUS_PRINTER_SERVICE_REQUEST, 10025: STATUS_PRINTER_SERVICE_REQUEST, 10026: STATUS_PRINTER_BUSY, 10027: STATUS_PRINTER_MEDIA_JAM, 10028: STATUS_PRINTER_REPORT_PRINTING, 10029: STATUS_PRINTER_PRINTING, 10030: STATUS_PRINTER_BUSY, 10031: STATUS_PRINTER_BUSY, 10032: STATUS_PRINTER_BUSY, 10033: STATUS_PRINTER_SERVICE_REQUEST, 10034: STATUS_PRINTER_CANCELING, 10035: STATUS_PRINTER_PRINTING, 10036: STATUS_PRINTER_WARMING_UP, 10200: STATUS_PRINTER_LOW_BLACK_TONER, 10201: STATUS_PRINTER_LOW_CYAN_TONER, 10202: STATUS_PRINTER_LOW_MAGENTA_TONER, 10203: STATUS_PRINTER_LOW_YELLOW_TONER, 10204: STATUS_PRINTER_LOW_TONER, # order image drum 10205: STATUS_PRINTER_LOW_BLACK_TONER, # order black drum 10206: STATUS_PRINTER_LOW_CYAN_TONER, # order cyan drum 10207: STATUS_PRINTER_LOW_MAGENTA_TONER, # order magenta drum 10208: STATUS_PRINTER_LOW_YELLOW_TONER, # order yellow drum 10209: STATUS_PRINTER_LOW_BLACK_TONER, 10210: STATUS_PRINTER_LOW_CYAN_TONER, 10211: STATUS_PRINTER_LOW_MAGENTA_TONER, 10212: STATUS_PRINTER_LOW_YELLOW_TONER, 10213: STATUS_PRINTER_SERVICE_REQUEST, # order transport kit 10214: STATUS_PRINTER_SERVICE_REQUEST, # order cleaning kit 10215: STATUS_PRINTER_SERVICE_REQUEST, # order transfer kit 10216: STATUS_PRINTER_SERVICE_REQUEST, # order fuser kit 10217: STATUS_PRINTER_SERVICE_REQUEST, # maintenance 10218: STATUS_PRINTER_LOW_TONER, 10300: STATUS_PRINTER_LOW_BLACK_TONER, # replace black toner 10301: STATUS_PRINTER_LOW_CYAN_TONER, # replace cyan toner 10302: STATUS_PRINTER_LOW_MAGENTA_TONER, # replace magenta toner 10303: STATUS_PRINTER_LOW_YELLOW_TONER, # replace yellow toner 10304: STATUS_PRINTER_SERVICE_REQUEST, # replace image drum 10305: STATUS_PRINTER_SERVICE_REQUEST, # replace black drum 10306: STATUS_PRINTER_SERVICE_REQUEST, # replace cyan drum 10307: STATUS_PRINTER_SERVICE_REQUEST, # replace magenta drum 10308: STATUS_PRINTER_SERVICE_REQUEST, # replace yellow drum 10309: STATUS_PRINTER_SERVICE_REQUEST, # replace black cart 10310: STATUS_PRINTER_SERVICE_REQUEST, # replace cyan cart 10311: STATUS_PRINTER_SERVICE_REQUEST, # replace magenta cart 10312: STATUS_PRINTER_SERVICE_REQUEST, # replace yellow cart 10313: STATUS_PRINTER_SERVICE_REQUEST, # replace transport kit 10314: STATUS_PRINTER_SERVICE_REQUEST, # replace cleaning kit 10315: STATUS_PRINTER_SERVICE_REQUEST, # replace transfer kit 10316: STATUS_PRINTER_SERVICE_REQUEST, # replace fuser kit 10317: STATUS_PRINTER_SERVICE_REQUEST, 10318: STATUS_PRINTER_SERVICE_REQUEST, # replace supplies 10400: STATUS_PRINTER_NON_HP_INK, # [sic] 10401: STATUS_PRINTER_IDLE, 10402: STATUS_PRINTER_SERVICE_REQUEST, 10403: STATUS_PRINTER_IDLE, # 11xyy - Background paper-loading # 12xyy - Background paper-tray status # 15xxy - Output-bin status # 20xxx - PJL parser errors # 25xxx - PJL parser warnings # 27xxx - PJL semantic errors # 30xxx - Auto continuable conditions 30119: STATUS_PRINTER_MEDIA_JAM, # 32xxx - PJL file system errors # 35xxx - Potential operator intervention conditions # 40xxx - Operator intervention conditions 40021: STATUS_PRINTER_DOOR_OPEN, 40022: STATUS_PRINTER_MEDIA_JAM, 40038: STATUS_PRINTER_LOW_TONER, 40600: STATUS_PRINTER_NO_TONER, # 41xyy - Foreground paper-loading messages # 43xyy - Optional paper handling device messages # 44xyy - LJ 4xxx/5xxx paper jam messages # 50xxx - Hardware errors # 55xxx - Personality errors } MIN_PJL_ERROR_CODE = 10001 DEFAULT_PJL_ERROR_CODE = 10001 def MapPJLErrorCode(error_code, str_code=None): if error_code < MIN_PJL_ERROR_CODE: return STATUS_PRINTER_BUSY if str_code is None: str_code = str(error_code) if len(str_code) < 5: return STATUS_PRINTER_BUSY status_code = PJL_STATUS_MAP.get(error_code, None) if status_code is None: status_code = STATUS_PRINTER_BUSY if 10999 < error_code < 12000: # 11xyy - Background paper-loading # x = tray # # yy = media code tray = int(str_code[2]) media = int(str_code[3:]) log.debug("Background paper loading for tray #%d" % tray) log.debug("Media code = %d" % media) elif 11999 < error_code < 13000: # 12xyy - Background paper-tray status # x = tray # # yy = status code tray = int(str_code[2]) status = int(str_code[3:]) log.debug("Background paper tray status for tray #%d" % tray) log.debug("Status code = %d" % status) elif 14999 < error_code < 16000: # 15xxy - Output-bin status # xx = output bin # y = status code bin = int(str_code[2:4]) status = int(str_code[4]) log.debug("Output bin full for bin #%d" % bin) status_code = STATUS_PRINTER_OUTPUT_BIN_FULL elif 19999 < error_code < 28000: # 20xxx, 25xxx, 27xxx PJL errors status_code = STATUS_PRINTER_SERVICE_REQUEST elif 29999 < error_code < 31000: # 30xxx - Auto continuable conditions log.debug("Auto continuation condition #%d" % error_code) status_code = STATUS_PRINTER_BUSY elif 34999 < error_code < 36000: # 35xxx - Potential operator intervention conditions status_code = STATUS_PRINTER_SERVICE_REQUEST elif 39999 < error_code < 41000: # 40xxx - Operator intervention conditions status_code = STATUS_PRINTER_SERVICE_REQUEST elif 40999 < error_code < 42000: # 41xyy - Foreground paper-loading messages # x = tray # yy = media code tray = int(str_code[2]) media = int(str_code[3:]) log.debug("Foreground paper loading for tray #%d" % tray) log.debug("Media code = %d" % media) status_code = STATUS_PRINTER_OUT_OF_PAPER elif 41999 < error_code < 43000: status_code = STATUS_PRINTER_MEDIA_JAM elif 42999 < error_code < 44000: # 43xyy - Optional paper handling device messages status_code = STATUS_PRINTER_SERVICE_REQUEST elif 43999 < error_code < 45000: # 44xyy - LJ 4xxx/5xxx paper jam messages status_code = STATUS_PRINTER_MEDIA_JAM elif 49999 < error_code < 51000: # 50xxx - Hardware errors status_code = STATUS_PRINTER_HARD_ERROR elif 54999 < error_code < 56000 : # 55xxx - Personality errors status_code = STATUS_PRINTER_HARD_ERROR log.debug("Mapped PJL error code %d to status code %d" % (error_code, status_code)) return status_code pjl_code_pat = re.compile(r"""^CODE\s*=\s*(\d.*)$""", re.IGNORECASE) def StatusType8(dev): # LaserJet PJL (B&W only) try: # Will error if printer is busy printing... dev.openPrint() except Error as e: log.warn(e.msg) status_code = STATUS_PRINTER_BUSY else: try: try: dev.writePrint(to_bytes_utf8("\x1b%-12345X@PJL INFO STATUS \r\n\x1b%-12345X")) pjl_return = dev.readPrint(1024, timeout=5, allow_short_read=True) dev.close() log.debug_block("PJL return:", to_string_latin(pjl_return)) str_code = '10001' for line in pjl_return.splitlines(): line = line.strip() match = pjl_code_pat.match(line.decode('utf-8')) if match is not None: str_code = match.group(1) break log.debug("Code = %s" % str_code) try: error_code = int(str_code) except ValueError: error_code = DEFAULT_PJL_ERROR_CODE log.debug("Error code = %d" % error_code) status_code = MapPJLErrorCode(error_code, str_code) except Error: status_code = STATUS_PRINTER_HARD_ERROR finally: try: dev.closePrint() except Error: pass agents = [] # TODO: Only handles mono lasers... if status_code in (STATUS_PRINTER_LOW_TONER, STATUS_PRINTER_LOW_BLACK_TONER): health = AGENT_HEALTH_OK level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW level = 0 elif status_code == STATUS_PRINTER_NO_TONER: health = AGENT_HEALTH_MISINSTALLED level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW level = 0 else: health = AGENT_HEALTH_OK level_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0 level = 100 log.debug("Agent: health=%d, level=%d, trigger=%d" % (health, level, level_trigger)) agents.append({ 'kind' : AGENT_KIND_TONER_CARTRIDGE, 'type' : AGENT_TYPE_BLACK, 'health' : health, 'level' : level, 'level-trigger' : level_trigger, }) if dev.tech_type == TECH_TYPE_COLOR_LASER: level = 100 level_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0 if status_code == STATUS_PRINTER_LOW_CYAN_TONER: level = 0 level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW log.debug("Agent: health=%d, level=%d, trigger=%d" % (health, level, level_trigger)) agents.append({ 'kind' : AGENT_KIND_TONER_CARTRIDGE, 'type' : AGENT_TYPE_CYAN, 'health' : AGENT_HEALTH_OK, 'level' : level, 'level-trigger' : level_trigger, }) level = 100 level_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0 if status_code == STATUS_PRINTER_LOW_MAGENTA_TONER: level = 0 level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW log.debug("Agent: health=%d, level=%d, trigger=%d" % (health, level, level_trigger)) agents.append({ 'kind' : AGENT_KIND_TONER_CARTRIDGE, 'type' : AGENT_TYPE_MAGENTA, 'health' : AGENT_HEALTH_OK, 'level' : level, 'level-trigger' : level_trigger, }) level = 100 level_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0 if status_code == STATUS_PRINTER_LOW_YELLOW_TONER: level = 0 level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW log.debug("Agent: health=%d, level=%d, trigger=%d" % (health, level, level_trigger)) agents.append({ 'kind' : AGENT_KIND_TONER_CARTRIDGE, 'type' : AGENT_TYPE_YELLOW, 'health' : AGENT_HEALTH_OK, 'level' : level, 'level-trigger' : level_trigger, }) if status_code == 40021: top_door = 0 else: top_door = 1 log.debug("Status code = %d" % status_code) return { 'revision' : STATUS_REV_UNKNOWN, 'agents' : agents, 'top-door' : top_door, 'supply-door' : top_door, 'duplexer' : 0, 'photo-tray' : 0, 'in-tray1' : 1, 'in-tray2' : 1, 'media-path' : 1, 'status-code' : status_code, } element_type10_xlate = { 'ink' : AGENT_KIND_SUPPLY, 'rechargeableToner' : AGENT_KIND_TONER_CARTRIDGE, 'inkTank' : AGENT_KIND_SUPPLY, 'inkCartridge' : AGENT_KIND_HEAD_AND_SUPPLY, 'printhead' : AGENT_KIND_HEAD, 'toner' : AGENT_KIND_TONER_CARTRIDGE, 'tonerCartridge' : AGENT_KIND_TONER_CARTRIDGE, } pen_type10_xlate = { 'pK' : AGENT_TYPE_PHOTO_BLACK, 'CMY' : AGENT_TYPE_CMY, 'M' : AGENT_TYPE_MAGENTA, 'C' : AGENT_TYPE_CYAN, 'Y' : AGENT_TYPE_YELLOW, 'K' : AGENT_TYPE_BLACK, 'G' : AGENT_TYPE_G, 'mK' : AGENT_TYPE_MATTE_BLACK, } pen_level10_xlate = { 'ok' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, 'low' : AGENT_LEVEL_TRIGGER_MAY_BE_LOW, 'out' : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, 'empty' : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, 'missing' : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, 'unknown' : AGENT_LEVEL_UNKNOWN, } pen_health10_xlate = { 'ok' : AGENT_HEALTH_OK, 'misinstalled' : AGENT_HEALTH_MISINSTALLED, 'missing' : AGENT_HEALTH_MISINSTALLED, 'unknown' : AGENT_HEALTH_UNKNOWN, } #ExtractXMLData will extract actual data from http response (Transfer-encoding: chunked). #For unchunked response it will not do anything. def ExtractXMLData(data): if data == '404 Not Found\r\n': return data if data[0:1] != b'<': size = -1 temp = to_bytes_utf8("") while size: index = data.find(to_bytes_utf8('\r\n')) size = int(data[0:index+1], 16) temp = temp + data[index+2:index+2+size] data = data[index+2+size+2:len(data)] data = temp return data def StatusType10FetchUrl(func, url, footer=""): data_fp = BytesIO() if footer: data = func(url, data_fp, footer) else: data = func(url, data_fp) if data: while data.find(to_bytes_utf8('\r\n\r\n')) != -1: data = data.split(to_bytes_utf8('\r\n\r\n'), 1)[1] if not data.startswith(to_bytes_utf8("HTTP")): break if data: data = ExtractXMLData(data) return data def StatusType10(func): # Low End Data Model status_block = { 'revision' : STATUS_REV_UNKNOWN, 'agents' : [], 'top-door' : TOP_DOOR_NOT_PRESENT, 'supply-door' : TOP_DOOR_NOT_PRESENT, 'duplexer' : DUPLEXER_NOT_PRESENT, 'photo-tray' : PHOTO_TRAY_NOT_PRESENT, 'in-tray1' : IN_TRAY_NOT_PRESENT, 'in-tray2' : IN_TRAY_NOT_PRESENT, 'media-path' : MEDIA_PATH_NOT_PRESENT, 'status-code' : STATUS_PRINTER_IDLE, } if not etree_loaded and not elementtree_loaded: log.error("cannot get status for printer. please load ElementTree module") return status_block status_block = StatusType10Agents(func) temp_status_block = {} temp_status_block = StatusType10Media(func) status_block.update(temp_status_block) temp_status_block = {} temp_status_block = StatusType10Status(func) status_block.update(temp_status_block) return status_block def StatusTypeCDMFetchUrl_USB(func, url, footer=""): data = BytesIO() data = func(url,"/cdm/supply/v1/suppliesPublic") return data def StatusTypeCDMFetchUrl_Net(url): response = urlopen(url, context=ssl._create_unverified_context()) data = response.read() return data def StatusTypeCDMStatus(): # CDM status_block = {} # Get the product status status_block['status-code'] = STATUS_PRINTER_IDLE return status_block def StatusTypeCDM_USB(func): # CDM status_block = { 'revision' : STATUS_REV_UNKNOWN, 'agents' : [], 'top-door' : TOP_DOOR_NOT_PRESENT, 'supply-door' : TOP_DOOR_NOT_PRESENT, 'duplexer' : DUPLEXER_NOT_PRESENT, 'photo-tray' : PHOTO_TRAY_NOT_PRESENT, 'in-tray1' : IN_TRAY_NOT_PRESENT, 'in-tray2' : IN_TRAY_NOT_PRESENT, 'media-path' : MEDIA_PATH_NOT_PRESENT, 'status-code' : STATUS_PRINTER_IDLE, } status_block = StatusTypeCDMAgents(func) temp_status_block = {} temp_status_block = StatusTypeCDMStatus() status_block.update(temp_status_block) return status_block def StatusTypeCDM_Net(url): # CDM status_block = { 'revision' : STATUS_REV_UNKNOWN, 'agents' : [], 'top-door' : TOP_DOOR_NOT_PRESENT, 'supply-door' : TOP_DOOR_NOT_PRESENT, 'duplexer' : DUPLEXER_NOT_PRESENT, 'photo-tray' : PHOTO_TRAY_NOT_PRESENT, 'in-tray1' : IN_TRAY_NOT_PRESENT, 'in-tray2' : IN_TRAY_NOT_PRESENT, 'media-path' : MEDIA_PATH_NOT_PRESENT, 'status-code' : STATUS_PRINTER_IDLE, } status_block = StatusTypeCDMAgents_Net(url) temp_status_block = {} temp_status_block = StatusTypeCDMStatus() status_block.update(temp_status_block) return status_block def StatusTypeCDMAgents_Net(url): # CDM status_block = {} data = StatusTypeCDMFetchUrl_Net(url) data = json.loads(data) data = ast.literal_eval(json.dumps(data)) agents = [] for each in data['suppliesList']: health = AGENT_HEALTH_OK ink_level = 0 agent_sku = '' agent_type = each['supplyType'] state = each['supplyState'] if agent_type == "ink" or agent_type == "inkCartridge" or agent_type == "toner" or agent_type == "tonerCartridge" or agent_type == "rechargeableToner" or agent_type == "inkTank": ink_type = each['supplyColorCode'] if state != "missing": try: ink_level = each['percentLifeDisplay'] if ink_level == 0: state = "unknown" elif ink_level <=10: state = "low" agent_sku = 'Unknown' #Initialize to unknown. IN some old devices, ConsumableSelectibilityNumber is not returned by device. except: ink_level = 0 elif agent_type == "printHead" or agent_type == 'imageDrum': continue; #No need of adding this agent. else: ink_type = '' if state == "ok": ink_level = 100 try: agent_sku = each['productNumber'] except: try : agent_sku = each['selectabilityNumber'] except : pass entry = { 'kind' : element_type10_xlate.get(agent_type, AGENT_KIND_NONE), 'type' : pen_type10_xlate.get(ink_type, AGENT_TYPE_NONE), 'health' : pen_health10_xlate.get(state, AGENT_HEALTH_OK), 'level' : int(ink_level), 'level-trigger' : pen_level10_xlate.get(state, AGENT_LEVEL_TRIGGER_SUFFICIENT_0), 'agent-sku' : agent_sku } agents.append(entry) status_block['agents'] = agents return status_block def StatusTypeCDMAgents(func): # CDM status_block = {} data = BytesIO() data = StatusTypeCDMFetchUrl_USB(func,"/cdm/supply/v1/suppliesPublic") data = json.loads(data.strip()) data = ast.literal_eval(json.dumps(data)) agents = [] for each in data['suppliesList']: health = AGENT_HEALTH_OK ink_level = 0 agent_sku = '' agent_type = each['supplyType'] state = each['supplyState'] if agent_type == "ink" or agent_type == "inkCartridge" or agent_type == "toner" or agent_type == "tonerCartridge" or agent_type == "rechargeableToner" or agent_type == "inkTank": ink_type = each['supplyColorCode'] if state != "missing": try: ink_level = each['percentLifeDisplay'] if ink_level == 0: state = "unknown" elif ink_level <=10: state = "low" agent_sku = 'Unknown' #Initialize to unknown. IN some old devices, ConsumableSelectibilityNumber is not returned by device. except: ink_level = 0 elif agent_type == "printhead" or agent_type == 'imageDrum': continue; #No need of adding this agent. else: ink_type = '' if state == "ok": ink_level = 100 try: agent_sku = each['productNumber'] except: try : agent_sku = each['selectabilityNumber'] except : pass entry = { 'kind' : element_type10_xlate.get(agent_type, AGENT_KIND_NONE), 'type' : pen_type10_xlate.get(ink_type, AGENT_TYPE_NONE), 'health' : pen_health10_xlate.get(state, AGENT_HEALTH_OK), 'level' : int(ink_level), 'level-trigger' : pen_level10_xlate.get(state, AGENT_LEVEL_TRIGGER_SUFFICIENT_0), 'agent-sku' : agent_sku } agents.append(entry) status_block['agents'] = agents return status_block def StatusType13Status(func): # CDM status_block = {} # Get the product status data = StatusType10FetchUrl(func, "/DevMgmt/ProductStatusDyn.xml") if not data: return status_block data = data.replace(to_bytes_utf8("psdyn:"), to_bytes_utf8("")).replace(to_bytes_utf8("locid:"), to_bytes_utf8("")) data = data.replace(to_bytes_utf8("pscat:"), to_bytes_utf8("")).replace(to_bytes_utf8("dd:"), to_bytes_utf8("")).replace(to_bytes_utf8("ad:"), to_bytes_utf8("")) # Parse the product status XML try: if etree_loaded: tree = ElementTree.XML(data) if not etree_loaded and elementtree_loaded: tree = XML(data) elements = tree.findall("Status/StatusCategory") except (expat.ExpatError, UnboundLocalError): elements = [] for e in elements: if e.text == "processing": status_block['status-code'] = STATUS_PRINTER_PRINTING elif e.text == "ready": status_block['status-code'] = STATUS_PRINTER_IDLE elif e.text == "closeDoorOrCover": status_block['status-code'] = STATUS_PRINTER_DOOR_OPEN elif e.text == "shuttingDown": status_block['status-code'] = STATUS_PRINTER_TURNING_OFF elif e.text == "cancelJob": status_block['status-code'] = STATUS_PRINTER_CANCELING elif e.text == "trayEmptyOrOpen": status_block['status-code'] = STATUS_PRINTER_OUT_OF_PAPER elif e.text == "jamInPrinter": status_block['status-code'] = STATUS_PRINTER_MEDIA_JAM elif e.text == "hardError": status_block['status-code'] = STATUS_PRINTER_HARD_ERROR elif e.text == "outputBinFull": status_block['status-code'] = STATUS_PRINTER_OUTPUT_BIN_FULL elif e.text == "unexpectedSizeInTray" or e.text == "sizeMismatchInTray": status_block['status-code'] = STATUS_PRINTER_MEDIA_SIZE_MISMATCH elif e.text == "insertOrCloseTray2": status_block['status-code'] = STATUS_PRINTER_TRAY_2_MISSING elif e.text == "scannerError": status_block['status-code'] = EVENT_SCANNER_FAIL elif e.text == "scanProcessing": status_block['status-code'] = EVENT_START_SCAN_JOB elif e.text == "scannerAdfLoaded": status_block['status-code'] = EVENT_SCAN_ADF_LOADED elif e.text == "scanToDestinationNotSet": status_block['status-code'] = EVENT_SCAN_TO_DESTINATION_NOTSET elif e.text == "scanWaitingForPC": status_block['status-code'] = EVENT_SCAN_WAITING_FOR_PC elif e.text == "scannerAdfJam": status_block['status-code'] = EVENT_SCAN_ADF_JAM elif e.text == "scannerAdfDoorOpen": status_block['status-code'] = EVENT_SCAN_ADF_DOOR_OPEN elif e.text == "faxProcessing": status_block['status-code'] = EVENT_START_FAX_JOB elif e.text == "faxSending": status_block['status-code'] = STATUS_FAX_TX_ACTIVE elif e.text == "faxReceiving": status_block['status-code'] = STATUS_FAX_RX_ACTIVE elif e.text == "faxDialing": status_block['status-code'] = EVENT_FAX_DIALING elif e.text == "faxConnecting": status_block['status-code'] = EVENT_FAX_CONNECTING elif e.text == "faxSendError": status_block['status-code'] = EVENT_FAX_SEND_ERROR elif e.text == "faxErrorStorageFull": status_block['status-code'] = EVENT_FAX_ERROR_STORAGE_FULL elif e.text == "faxReceiveError": status_block['status-code'] = EVENT_FAX_RECV_ERROR elif e.text == "faxBlocking": status_block['status-code'] = EVENT_FAX_BLOCKING elif e.text == "inPowerSave": status_block['status-code'] = STATUS_PRINTER_POWER_SAVE elif e.text == "incorrectCartridge": status_block['status-code'] = STATUS_PRINTER_CARTRIDGE_WRONG elif e.text == "cartridgeMissing": status_block['status-code'] = STATUS_PRINTER_CARTRIDGE_MISSING elif e.text == "missingPrintHead": status_block['status-code'] = STATUS_PRINTER_PRINTHEAD_MISSING #Alert messages for Pentane products RQ 8888 elif e.text == "scannerADFMispick": status_block['status-code'] = STATUS_SCANNER_ADF_MISPICK elif e.text == "mediaTooShortToAutoDuplex": status_block['status-code'] = STATUS_PRINTER_PAPER_TOO_SHORT_TO_AUTODUPLEX elif e.text == "insertOrCloseTray": status_block['status-code'] = STATUS_PRINTER_TRAY_2_3_DOOR_OPEN elif e.text == "inkTooLowToPrime": status_block['status-code'] = STATUS_PRINTER_INK_TOO_LOW_TO_PRIME elif e.text == "cartridgeVeryLow": status_block['status-code'] = STATUS_PRINTER_VERY_LOW_ON_INK elif e.text == "wasteMarkerCollectorAlmostFull": status_block['status-code'] = STATUS_PRINTER_SERVICE_INK_CONTAINER_ALMOST_FULL elif e.text == "wasteMarkerCollectorFull": status_block['status-code'] = STATUS_PRINTER_SERVICE_INK_CONTAINER_FULL elif e.text == "wasteMarkerCollectorFullPrompt": status_block['status-code'] = STATUS_PRINTER_SERVICE_INK_CONTAINER_FULL_PROMPT elif e.text == "missingDuplexer": status_block['status-code'] = STATUS_PRINTER_DUPLEX_MODULE_MISSING elif e.text == "printBarStall": status_block['status-code'] = STATUS_PRINTER_PRINTHEAD_JAM elif e.text == "outputBinClosed": status_block['status-code'] = STATUS_PRINTER_CLEAR_OUTPUT_AREA elif e.text == "outputBinOpened": status_block['status-code'] = STATUS_PRINTER_CLEAR_OUTPUT_AREA elif e.text == "reseatDuplexer": status_block['status-code'] = STATUS_PRINTER_RESEAT_DUPLEXER elif e.text == "unexpectedTypeInTray": status_block['status-code'] = STATUS_PRINTER_MEDIA_TYPE_MISMATCH elif e.text == "manuallyFeed": status_block['status-code'] = STATUS_MANUALLY_FEED else: status_block['status-code'] = STATUS_UNKNOWN_CODE return status_block def StatusType10Agents(func): # Low End Data Model status_block = {} # Get the dynamic consumables configuration data = StatusType10FetchUrl(func, "/DevMgmt/ConsumableConfigDyn.xml") if not data: return status_block data = data.replace(to_bytes_utf8("ccdyn:"), to_bytes_utf8("")).replace(to_bytes_utf8("dd:"), to_bytes_utf8("")) # Parse the agent status XML agents = [] try: if etree_loaded: tree = ElementTree.XML(data) if not etree_loaded and elementtree_loaded: tree = XML(data) elements = tree.findall("ConsumableInfo") for e in elements: health = AGENT_HEALTH_OK ink_level = 0 agent_sku = '' try: type = e.find("ConsumableTypeEnum").text state = e.find("ConsumableLifeState/ConsumableState").text quantityState = e.find("ConsumableLifeState/MeasuredQuantityState").text # level if type == "ink" or type == "inkCartridge" or type == "toner" or type == "tonerCartridge" or type == "rechargeableToner" or type == "inkTank": ink_type = e.find("ConsumableLabelCode").text if state != "missing": try: ink_level = int(e.find("ConsumablePercentageLevelRemaining").text) if ink_level == 0 and quantityState == 'unknown': state = "unknown" elif ink_level == 0: state = "empty" elif ink_level <=10: state = "low" agent_sku = 'Unknown' #Initialize to unknown. IN some old devices, ConsumableSelectibilityNumber is not returned by device. except: ink_level = 0 elif type == "printhead" or type == 'imageDrum': continue; #No need of adding this agent. else: ink_type = '' if state == "ok": ink_level = 100 try: agent_sku = e.find("ProductNumber").text except: try : agent_sku = e.find("ConsumableSelectibilityNumber").text except : pass log.debug("type '%s' state '%s' ink_type '%s' ink_level %d agent_sku = %s" % (type, state, ink_type, ink_level,agent_sku)) entry = { 'kind' : element_type10_xlate.get(type, AGENT_KIND_NONE), 'type' : pen_type10_xlate.get(ink_type, AGENT_TYPE_NONE), 'health' : pen_health10_xlate.get(state, AGENT_HEALTH_OK), 'level' : int(ink_level), 'level-trigger' : pen_level10_xlate.get(state, AGENT_LEVEL_TRIGGER_SUFFICIENT_0), 'agent-sku' : agent_sku } log.debug("%s" % entry) agents.append(entry) except AttributeError: log.debug("no value found for attribute") except (expat.ExpatError, UnboundLocalError): agents = [] status_block['agents'] = agents return status_block def StatusType10Media(func): # Low End Data Model status_block = {} # Get the media handling configuration data = StatusType10FetchUrl(func, "/DevMgmt/MediaHandlingDyn.xml") if not data: return status_block data = data.replace(to_bytes_utf8("mhdyn:"), to_bytes_utf8("")).replace(to_bytes_utf8("dd:"), to_bytes_utf8("")) # Parse the media handling XML try: if etree_loaded: tree = ElementTree.XML(data) if not etree_loaded and elementtree_loaded: tree = XML(data) elements = tree.findall("InputTray") except (expat.ExpatError, UnboundLocalError): elements = [] for e in elements: bin_name = e.find("InputBin").text if bin_name == "Tray1": status_block['in-tray1'] = IN_TRAY_PRESENT elif bin_name == "Tray2": status_block['in-tray2'] = IN_TRAY_PRESENT elif bin_name == "PhotoTray": status_block['photo-tray'] = PHOTO_TRAY_ENGAGED try: elements = tree.findall("Accessories/MediaHandlingDeviceFunctionType") except UnboundLocalError: elements = [] for e in elements: if e.text == "autoDuplexor": status_block['duplexer'] = DUPLEXER_DOOR_CLOSED return status_block def StatusType10Status(func): # Low End Data Model status_block = {} # Get the product status data = StatusType10FetchUrl(func, "/DevMgmt/ProductStatusDyn.xml") if not data: return status_block data = data.replace(to_bytes_utf8("psdyn:"), to_bytes_utf8("")).replace(to_bytes_utf8("locid:"), to_bytes_utf8("")) data = data.replace(to_bytes_utf8("pscat:"), to_bytes_utf8("")).replace(to_bytes_utf8("dd:"), to_bytes_utf8("")).replace(to_bytes_utf8("ad:"), to_bytes_utf8("")) # Parse the product status XML try: if etree_loaded: tree = ElementTree.XML(data) if not etree_loaded and elementtree_loaded: tree = XML(data) elements = tree.findall("Status/StatusCategory") except (expat.ExpatError, UnboundLocalError): elements = [] for e in elements: if e.text == "processing": status_block['status-code'] = STATUS_PRINTER_PRINTING elif e.text == "ready": status_block['status-code'] = STATUS_PRINTER_IDLE elif e.text == "closeDoorOrCover": status_block['status-code'] = STATUS_PRINTER_DOOR_OPEN elif e.text == "shuttingDown": status_block['status-code'] = STATUS_PRINTER_TURNING_OFF elif e.text == "cancelJob": status_block['status-code'] = STATUS_PRINTER_CANCELING elif e.text == "trayEmptyOrOpen": status_block['status-code'] = STATUS_PRINTER_OUT_OF_PAPER elif e.text == "jamInPrinter": status_block['status-code'] = STATUS_PRINTER_MEDIA_JAM elif e.text == "hardError": status_block['status-code'] = STATUS_PRINTER_HARD_ERROR elif e.text == "outputBinFull": status_block['status-code'] = STATUS_PRINTER_OUTPUT_BIN_FULL elif e.text == "unexpectedSizeInTray" or e.text == "sizeMismatchInTray": status_block['status-code'] = STATUS_PRINTER_MEDIA_SIZE_MISMATCH elif e.text == "insertOrCloseTray2": status_block['status-code'] = STATUS_PRINTER_TRAY_2_MISSING elif e.text == "scannerError": status_block['status-code'] = EVENT_SCANNER_FAIL elif e.text == "scanProcessing": status_block['status-code'] = EVENT_START_SCAN_JOB elif e.text == "scannerAdfLoaded": status_block['status-code'] = EVENT_SCAN_ADF_LOADED elif e.text == "scanToDestinationNotSet": status_block['status-code'] = EVENT_SCAN_TO_DESTINATION_NOTSET elif e.text == "scanWaitingForPC": status_block['status-code'] = EVENT_SCAN_WAITING_FOR_PC elif e.text == "scannerAdfJam": status_block['status-code'] = EVENT_SCAN_ADF_JAM elif e.text == "scannerAdfDoorOpen": status_block['status-code'] = EVENT_SCAN_ADF_DOOR_OPEN elif e.text == "faxProcessing": status_block['status-code'] = EVENT_START_FAX_JOB elif e.text == "faxSending": status_block['status-code'] = STATUS_FAX_TX_ACTIVE elif e.text == "faxReceiving": status_block['status-code'] = STATUS_FAX_RX_ACTIVE elif e.text == "faxDialing": status_block['status-code'] = EVENT_FAX_DIALING elif e.text == "faxConnecting": status_block['status-code'] = EVENT_FAX_CONNECTING elif e.text == "faxSendError": status_block['status-code'] = EVENT_FAX_SEND_ERROR elif e.text == "faxErrorStorageFull": status_block['status-code'] = EVENT_FAX_ERROR_STORAGE_FULL elif e.text == "faxReceiveError": status_block['status-code'] = EVENT_FAX_RECV_ERROR elif e.text == "faxBlocking": status_block['status-code'] = EVENT_FAX_BLOCKING elif e.text == "inPowerSave": status_block['status-code'] = STATUS_PRINTER_POWER_SAVE elif e.text == "incorrectCartridge": status_block['status-code'] = STATUS_PRINTER_CARTRIDGE_WRONG elif e.text == "cartridgeMissing": status_block['status-code'] = STATUS_PRINTER_CARTRIDGE_MISSING elif e.text == "missingPrintHead": status_block['status-code'] = STATUS_PRINTER_PRINTHEAD_MISSING #Alert messages for Pentane products RQ 8888 elif e.text == "scannerADFMispick": status_block['status-code'] = STATUS_SCANNER_ADF_MISPICK elif e.text == "mediaTooShortToAutoDuplex": status_block['status-code'] = STATUS_PRINTER_PAPER_TOO_SHORT_TO_AUTODUPLEX elif e.text == "insertOrCloseTray": status_block['status-code'] = STATUS_PRINTER_TRAY_2_3_DOOR_OPEN elif e.text == "inkTooLowToPrime": status_block['status-code'] = STATUS_PRINTER_INK_TOO_LOW_TO_PRIME elif e.text == "cartridgeVeryLow": status_block['status-code'] = STATUS_PRINTER_VERY_LOW_ON_INK elif e.text == "wasteMarkerCollectorAlmostFull": status_block['status-code'] = STATUS_PRINTER_SERVICE_INK_CONTAINER_ALMOST_FULL elif e.text == "wasteMarkerCollectorFull": status_block['status-code'] = STATUS_PRINTER_SERVICE_INK_CONTAINER_FULL elif e.text == "wasteMarkerCollectorFullPrompt": status_block['status-code'] = STATUS_PRINTER_SERVICE_INK_CONTAINER_FULL_PROMPT elif e.text == "missingDuplexer": status_block['status-code'] = STATUS_PRINTER_DUPLEX_MODULE_MISSING elif e.text == "printBarStall": status_block['status-code'] = STATUS_PRINTER_PRINTHEAD_JAM elif e.text == "outputBinClosed": status_block['status-code'] = STATUS_PRINTER_CLEAR_OUTPUT_AREA elif e.text == "outputBinOpened": status_block['status-code'] = STATUS_PRINTER_CLEAR_OUTPUT_AREA elif e.text == "reseatDuplexer": status_block['status-code'] = STATUS_PRINTER_RESEAT_DUPLEXER elif e.text == "unexpectedTypeInTray": status_block['status-code'] = STATUS_PRINTER_MEDIA_TYPE_MISMATCH elif e.text == "manuallyFeed": status_block['status-code'] = STATUS_MANUALLY_FEED else: status_block['status-code'] = STATUS_UNKNOWN_CODE return status_block #IPP Status Code IPP_PRINTER_STATE_IDLE = 0x03 IPP_PRINTER_STATE_PROCESSING = 0x04 IPP_PRINTER_STATE_STOPPED = 0x05 marker_kind_xlate = { 'ink' : AGENT_KIND_SUPPLY, 'rechargeableToner' : AGENT_KIND_TONER_CARTRIDGE, 'inkTank' : AGENT_KIND_SUPPLY, 'inkCartridge' : AGENT_KIND_SUPPLY, 'printhead' : AGENT_KIND_HEAD, 'toner' : AGENT_KIND_TONER_CARTRIDGE, 'tonerCartridge' : AGENT_KIND_TONER_CARTRIDGE, 'toner-cartridge' : AGENT_KIND_TONER_CARTRIDGE, 'maintenanceKit' : AGENT_KIND_MAINT_KIT, 'ink-cartridge' : AGENT_KIND_SUPPLY, } marker_type_xlate = {'magenta ink' : AGENT_TYPE_MAGENTA, 'cyan ink' : AGENT_TYPE_CYAN, 'yellow ink' : AGENT_TYPE_YELLOW, 'black ink' : AGENT_TYPE_BLACK, 'Black Cartridge' : AGENT_TYPE_BLACK, 'Magenta Cartridge' : AGENT_TYPE_MAGENTA, 'Cyan Cartridge' : AGENT_TYPE_CYAN, 'Yellow Cartridge' : AGENT_TYPE_YELLOW, 'Maintenance Kit' : AGENT_TYPE_NONE, } marker_leveltrigger_xlate = { 'ok' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0, 'low' : AGENT_LEVEL_TRIGGER_MAY_BE_LOW, 'out' : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, 'empty' : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, 'missing' : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, } marker_state_xlate = { 'ok' : AGENT_HEALTH_OK, 'misinstalled' : AGENT_HEALTH_MISINSTALLED, 'missing' : AGENT_HEALTH_MISINSTALLED, } printer_state_reasons_xlate = { 'none' : STATUS_PRINTER_IDLE, 'media-needed' : STATUS_PRINTER_OUT_OF_PAPER, 'media-jam' : STATUS_PRINTER_MEDIA_JAM, 'shutdown' : STATUS_PRINTER_TURNING_OFF, 'toner-low' : STATUS_PRINTER_LOW_TONER, 'toner-empty' : STATUS_PRINTER_EMPTY_TONER, 'cover-open' : STATUS_PRINTER_DOOR_OPEN, 'door-open' : STATUS_PRINTER_DOOR_OPEN, 'input-tray-missing' : STATUS_PRINTER_TRAY_2_3_DOOR_OPEN, 'media-low' : STATUS_PRINTER_OUT_OF_PAPER, 'media-empty' : STATUS_PRINTER_MEDIA_EMPTY_ERROR, 'output-tray-missing' : STATUS_PRINTER_TRAY_2_MISSING, 'output-area-almost-full' : STATUS_PRINTER_CLEAR_OUTPUT_AREA, 'output-area-full' : STATUS_PRINTER_CLEAR_OUTPUT_AREA, 'marker-supply-low' : STATUS_PRINTER_VERY_LOW_ON_INK, 'marker-supply-empty' : STATUS_PRINTER_VERY_LOW_ON_INK, 'paused' : STATUS_PRINTER_PAUSED, 'other' : STATUS_UNKNOWN_CODE, } def StatusTypeIPPStatus(attrs): status_block = {} if not attrs: return status_block try: printer_state = attrs['printer-state'][0] printer_state_reasons = attrs['printer-state-reasons'][0] if printer_state == IPP_PRINTER_STATE_IDLE: status_block['status-code'] = STATUS_PRINTER_IDLE elif printer_state == IPP_PRINTER_STATE_PROCESSING: status_block['status-code'] = STATUS_PRINTER_PRINTING else: printer_state_reasons = printer_state_reasons.replace("-error", "") printer_state_reasons = printer_state_reasons.replace("-warning", "") printer_state_reasons = printer_state_reasons.replace("-report", "") status_block['status-code'] = printer_state_reasons_xlate.get(printer_state_reasons, STATUS_PRINTER_IDLE) except Exception as e: log.debug("Exception occured while updating printer-state [%s]" %e.args[0]) status_block = {} return status_block def StatusTypeIPPAgents(attrs): status_block = {} agents = [] if not attrs: return status_block loopcntr = 0 while(True ): try: if loopcntr >= len(attrs['marker-names']): break if attrs['marker-types'][loopcntr] == 'maintenanceKit': loopcntr = loopcntr + 1 continue if attrs['marker-levels'][loopcntr] > attrs['marker-low-levels'][loopcntr] : state = 'ok' else: state = 'low' #match the type if marker-type is something like 'Black Cartridge HP XXXX' mtype = [v for k,v in marker_type_xlate.items() if attrs['marker-names'][loopcntr].startswith(k)] entry = { 'kind' : marker_kind_xlate.get(attrs['marker-types'][loopcntr], AGENT_KIND_NONE), 'type' : mtype[0] if len(mtype) > 0 else 0, 'health' : marker_state_xlate.get(state, AGENT_HEALTH_OK), 'level' : attrs['marker-levels'][loopcntr], 'level-trigger' : marker_leveltrigger_xlate.get(state, AGENT_LEVEL_TRIGGER_SUFFICIENT_0), 'agent-sku' : '' } log.debug("%s" % entry) agents.append(entry) except AttributeError: log.error("no value found for attribute") return [] loopcntr = loopcntr + 1 status_block['agents'] = agents return status_block def StatusTypeIPP(device_uri,printer_name): status_block = { 'revision' : STATUS_REV_UNKNOWN, 'agents' : [], 'top-door' : TOP_DOOR_NOT_PRESENT, 'supply-door' : TOP_DOOR_NOT_PRESENT, 'duplexer' : DUPLEXER_NOT_PRESENT, 'photo-tray' : PHOTO_TRAY_NOT_PRESENT, 'in-tray1' : IN_TRAY_NOT_PRESENT, 'in-tray2' : IN_TRAY_NOT_PRESENT, 'media-path' : MEDIA_PATH_NOT_PRESENT, 'status-code' : STATUS_PRINTER_IDLE, } status_attrs = cupsext.getStatusAttributes(device_uri,printer_name) if status_attrs: status_block.update(StatusTypeIPPAgents(status_attrs) ) status_block.update(StatusTypeIPPStatus (status_attrs) ) return status_block def StatusTypeCDMFetchUrl(host): header = "http://" path = "/cdm/supply/v1/suppliesPublic" url = header + host + path response = urlopen(url, context=ssl._create_unverified_context()) data = response.read() return data