| Server IP : 182.53.201.61 / Your IP : 216.73.217.175 Web Server : Apache/2.2.15 (Fedora) System : Linux km10.dyndns.org 2.6.31.5-127.fc12.i686.PAE #1 SMP Sat Nov 7 21:25:57 EST 2009 i686 User : apache ( 48) PHP Version : 5.3.3 Disable Function : NONE MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/share/hplip/base/ |
Upload File : |
# -*- coding: utf-8 -*-
#
# (c) Copyright 2003-2007 Hewlett-Packard 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
#
from __future__ import division
# Std Lib
import struct
import cStringIO
import xml.parsers.expat as expat
import re
# Local
from g import *
from codes import *
import pml, utils
"""
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] & 0x8L) + s1[2] & 0x1L
supply_door = bool(s1[3] & 0x8L) + s1[3] & 0x1L
duplexer = bool(s1[4] & 0xcL) + s1[4] & 0x1L
photo_tray = bool(s1[5] & 0x8L) + s1[5] & 0x1L
if revision == STATUS_REV_02:
in_tray1 = bool(s1[6] & 0x8L) + s1[6] & 0x1L
in_tray2 = bool(s1[7] & 0x8L) + s1[7] & 0x1L
else:
in_tray1 = bool(s1[6] & 0x8L)
in_tray2 = bool(s1[7] & 0x8L)
media_path = bool(s1[8] & 0x8L) + (s1[8] & 0x1L) + ((bool(s1[18] & 0x2L))<<1)
status_pos = STATUS_POS[revision]
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]]
log.debug("Num pens=%d" % num_pens)
index = 0
pen_data_size = PEN_DATA_SIZE[revision]
for p in range(num_pens):
info = long(s[c : c + pen_data_size], 16)
pen['index'] = index
if pen_data_size == 4:
pen['type'] = REVISION_2_TYPE_MAP.get(int((info & 0xf000L) >> 12L), 0)
if index < (num_pens / 2):
pen['kind'] = AGENT_KIND_HEAD
else:
pen['kind'] = AGENT_KIND_SUPPLY
pen['level-trigger'] = int ((info & 0x0e00L) >> 9L)
pen['health'] = int((info & 0x0180L) >> 7L)
pen['level'] = int(info & 0x007fL)
pen['id'] = 0x1f
elif pen_data_size == 8:
pen['kind'] = bool(info & 0x80000000L) + ((bool(info & 0x40000000L))<<1L)
pen['type'] = int((info & 0x3f000000L) >> 24L)
pen['id'] = int((info & 0xf80000) >> 19L)
pen['level-trigger'] = int((info & 0x70000L) >> 16L)
pen['health'] = int((info & 0xc000L) >> 14L)
pen['level'] = int(info & 0xffL)
else:
log.error("Pen data size error")
if len(z1) > 0:
# TODO: Determine cause of IndexError for C6100 (defect #1111)
try:
pen['dvc'] = long(z1s[d+1:d+5], 16)
pen['virgin'] = bool(z1[d+5] & 0x8L)
pen['hp-ink'] = bool(z1[d+5] & 0x4L)
pen['known'] = bool(z1[d+5] & 0x2L)
pen['ack'] = bool(z1[d+5] & 0x1L)
except IndexError:
pen['dvc'] = 0
pen['virgin'] = 0
pen['hp-ink'] = 0
pen['known'] = 0
pen['ack'] = 0
index += 1
pens.append(pen)
log.debug("Pen %d: %s" % (p, pen))
pen = {}
c += pen_data_size
d += Z_SIZE
except (IndexError, ValueError, TypeError), 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,
}
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', 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 1:
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)
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(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 = '', ''
map_keys = map.keys()
map_keys.sort()
for x in map_keys:
frm = ''.join([frm, x])
to = ''.join([to, 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 = '', ''
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).rstrip()
if '\x0a' in line1:
line1, line2 = line1.split('\x0a', 1)
break
result, line2 = dev.getPML(oid2)
if result < pml.ERROR_MAX_OK:
line2 = PANEL_TRANSLATOR_FUNC(line2).rstrip()
break
return bool(line1 or line2), line1 or '', line2 or ''
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 = cStringIO.StringIO()
info_ssp = cStringIO.StringIO()
try:
dev.getEWSUrl("/hp/device/info_device_status.xml", info_device_status)
dev.getEWSUrl("/hp/device/info_ssp.xml", info_ssp)
except:
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", 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", 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("""^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, e:
log.warn(e.msg)
status_code = STATUS_PRINTER_BUSY
else:
try:
try:
dev.writePrint("\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:", pjl_return)
str_code = '10001'
for line in pjl_return.splitlines():
line = line.strip()
match = pjl_code_pat.match(line)
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,
}