home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / hplip / base / status.py < prev    next >
Encoding:
Python Source  |  2006-08-30  |  38.6 KB  |  1,017 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2006 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Don Welch
  20. #
  21.  
  22. from __future__ import division
  23.  
  24. # StdLib
  25. import struct, xml.parsers.expat, cStringIO
  26.  
  27. # Local
  28. from g import *
  29. from codes import *
  30. import pml, utils
  31.  
  32.  
  33. """
  34. status dict structure:
  35.     { 'revision' :     STATUS_REV_00 .. STATUS_REV_04,
  36.       'agents' :       [ list of pens/agents/supplies (dicts) ],
  37.       'top-door' :     TOP_DOOR_NOT_PRESENT | TOP_DOOR_CLOSED | TOP_DOOR_OPEN,
  38.       'status-code' :  STATUS_...,
  39.       'supply-door' :  SUPPLY_DOOR_NOT_PRESENT | SUPPLY_DOOR_CLOSED | SUPPLY_DOOR_OPEN.
  40.       'duplexer' :     DUPLEXER_NOT_PRESENT | DUPLEXER_DOOR_CLOSED | DUPLEXER_DOOR_OPEN,
  41.       'photo_tray' :   PHOTO_TRAY_NOT_PRESENT | PHOTO_TRAY_ENGAGED | PHOTO_TRAY_NOT_ENGAGED,
  42.       'in-tray1' :     IN_TRAY_NOT_PRESENT | IN_TRAY_CLOSED | IN_TRAY_OPEN (| IN_TRAY_DEFAULT | IN_TRAY_LOCKED)*,
  43.       'in-tray2' :     IN_TRAY_NOT_PRESENT | IN_TRAY_CLOSED | IN_TRAY_OPEN (| IN_TRAY_DEFAULT | IN_TRAY_LOCKED)*,
  44.       'media-path' :   MEDIA_PATH_NOT_PRESENT | MEDIA_PATH_CUT_SHEET | MEDIA_PATH_BANNER | MEDIA_PATH_PHOTO,
  45.     }
  46.  
  47.     * S:02 only
  48.  
  49. agent dict structure: (pens/supplies/agents/etc)
  50.     { 'kind' :           AGENT_KIND_NONE ... AGENT_KIND_ADF_KIT,
  51.       'type' :           TYPE_BLACK ... AGENT_TYPE_UNSPECIFIED,      # aka color
  52.       'health' :         AGENT_HEALTH_OK ... AGENT_HEALTH_UNKNOWN,
  53.       'level' :          0 ... 100,
  54.       'level-trigger' :  AGENT_LEVEL_TRIGGER_SUFFICIENT_0 ... AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT,
  55.     }
  56. """
  57.  
  58.  
  59.  
  60. # 'revision'
  61. STATUS_REV_00 = 0x00
  62. STATUS_REV_01 = 0x01
  63. STATUS_REV_02 = 0x02
  64. STATUS_REV_03 = 0x03
  65. STATUS_REV_04 = 0x04
  66. STATUS_REV_V  = 0xff
  67. STATUS_REV_UNKNOWN = 0xfe
  68.  
  69. vstatus_xlate  = {'busy' : STATUS_PRINTER_BUSY,
  70.                    'idle' : STATUS_PRINTER_IDLE,
  71.                    'prnt' : STATUS_PRINTER_PRINTING,
  72.                    'offf' : STATUS_PRINTER_TURNING_OFF,
  73.                    'rprt' : STATUS_PRINTER_REPORT_PRINTING,
  74.                    'cncl' : STATUS_PRINTER_CANCELING,
  75.                    'iost' : STATUS_PRINTER_IO_STALL,
  76.                    'dryw' : STATUS_PRINTER_DRY_WAIT_TIME,
  77.                    'penc' : STATUS_PRINTER_PEN_CHANGE,
  78.                    'oopa' : STATUS_PRINTER_OUT_OF_PAPER,
  79.                    'bnej' : STATUS_PRINTER_BANNER_EJECT,
  80.                    'bnmz' : STATUS_PRINTER_BANNER_MISMATCH,
  81.                    'phmz' : STATUS_PRINTER_PHOTO_MISMATCH,
  82.                    'dpmz' : STATUS_PRINTER_DUPLEX_MISMATCH,
  83.                    'pajm' : STATUS_PRINTER_MEDIA_JAM,
  84.                    'cars' : STATUS_PRINTER_CARRIAGE_STALL,
  85.                    'paps' : STATUS_PRINTER_PAPER_STALL,
  86.                    'penf' : STATUS_PRINTER_PEN_FAILURE,
  87.                    'erro' : STATUS_PRINTER_HARD_ERROR,
  88.                    'pwdn' : STATUS_PRINTER_POWER_DOWN,
  89.                    'fpts' : STATUS_PRINTER_FRONT_PANEL_TEST,
  90.                    'clno' : STATUS_PRINTER_CLEAN_OUT_TRAY_MISSING}
  91.  
  92. REVISION_2_TYPE_MAP = {0 : AGENT_TYPE_NONE,
  93.                         1 : AGENT_TYPE_BLACK,
  94.                         2 : AGENT_TYPE_CYAN,
  95.                         3 : AGENT_TYPE_MAGENTA,
  96.                         4 : AGENT_TYPE_YELLOW,
  97.                         5 : AGENT_TYPE_BLACK,
  98.                         6 : AGENT_TYPE_CYAN,
  99.                         7 : AGENT_TYPE_MAGENTA,
  100.                         8 : AGENT_TYPE_YELLOW,
  101.                        }
  102.  
  103. STATUS_BLOCK_UNKNOWN = {'revision' : STATUS_REV_UNKNOWN,
  104.                          'agents' : [],
  105.                          'status-code' : STATUS_UNKNOWN,
  106.                        }
  107.  
  108. NUM_PEN_POS = {STATUS_REV_00 : 16,
  109.                 STATUS_REV_01 : 16,
  110.                 STATUS_REV_02 : 16,
  111.                 STATUS_REV_03 : 18,
  112.                 STATUS_REV_04 : 22}
  113.  
  114. PEN_DATA_SIZE = {STATUS_REV_00 : 8,
  115.                   STATUS_REV_01 : 8,
  116.                   STATUS_REV_02 : 4,
  117.                   STATUS_REV_03 : 8,
  118.                   STATUS_REV_04 : 8}
  119.  
  120. STATUS_POS = {STATUS_REV_00 : 14,
  121.                STATUS_REV_01 : 14,
  122.                STATUS_REV_02 : 14,
  123.                STATUS_REV_03 : 16,
  124.                STATUS_REV_04 : 20}
  125.  
  126. def parseSStatus(s, z=''):
  127.     Z_SIZE = 6
  128.  
  129.     z1 = []
  130.     if len(z) > 0:
  131.         z_fields = z.split(',')
  132.  
  133.         for z_field in z_fields:
  134.  
  135.             if len(z_field) > 2 and z_field[:2] == '05':
  136.                 z1s = z_field[2:]
  137.                 z1 = [int(x, 16) for x in z1s]
  138.  
  139.     s1 = [int(x, 16) for x in s]
  140.  
  141.     revision = s1[1]
  142.  
  143.     assert STATUS_REV_00 <= revision <= STATUS_REV_04
  144.  
  145.     top_door = bool(s1[2] & 0x8L) + s1[2] & 0x1L
  146.     supply_door = bool(s1[3] & 0x8L) + s1[3] & 0x1L
  147.     duplexer = bool(s1[4] & 0xcL) +  s1[4] & 0x1L
  148.     photo_tray = bool(s1[5] & 0x8L) + s1[5] & 0x1L
  149.  
  150.     if revision == STATUS_REV_02:
  151.         in_tray1 = bool(s1[6] & 0x8L) + s1[6] & 0x1L
  152.         in_tray2 = bool(s1[7] & 0x8L) + s1[7] & 0x1L
  153.     else:
  154.         in_tray1 = bool(s1[6] & 0x8L)
  155.         in_tray2 = bool(s1[7] & 0x8L)
  156.  
  157.     media_path = bool(s1[8] & 0x8L) + (s1[8] & 0x1L) + ((bool(s1[18] & 0x2L))<<1)
  158.     status_pos = STATUS_POS[revision]
  159.     status_byte = (s1[status_pos]<<4) + s1[status_pos + 1]
  160.     stat = status_byte + STATUS_PRINTER_BASE
  161.  
  162.     pens, pen, c, d = [], {}, NUM_PEN_POS[revision]+1, 0
  163.     num_pens = s1[NUM_PEN_POS[revision]]
  164.     log.debug("Num pens=%d" % num_pens)
  165.     index = 0
  166.     pen_data_size = PEN_DATA_SIZE[revision]
  167.  
  168.     for p in range(num_pens):
  169.         info = long(s[c : c + pen_data_size], 16)
  170.  
  171.         pen['index'] = index
  172.  
  173.         if pen_data_size == 4:
  174.             pen['type'] = REVISION_2_TYPE_MAP.get(int((info & 0xf000L) >> 12L), 0)
  175.             if index < (num_pens / 2):
  176.                 pen['kind'] = AGENT_KIND_HEAD
  177.             else:
  178.                 pen['kind'] = AGENT_KIND_SUPPLY
  179.  
  180.             pen['level-trigger'] = int ((info & 0x0e00L) >> 9L)
  181.             pen['health'] = int((info & 0x0180L) >> 7L)
  182.             pen['level'] = int(info & 0x007fL)
  183.             pen['id'] = 0x1f
  184.  
  185.         elif pen_data_size == 8:
  186.             pen['kind'] = bool(info & 0x80000000L) + ((bool(info & 0x40000000L))<<1L)
  187.             pen['type'] = int((info & 0x3f000000L) >> 24L)
  188.             pen['id'] = int((info & 0xf80000) >> 19L)
  189.             pen['level-trigger'] = int((info & 0x70000L) >> 16L)
  190.             pen['health'] = int((info & 0xc000L) >> 14L)
  191.             pen['level'] = int(info & 0xffL)
  192.  
  193.         else:
  194.             log.error("Pen data size error")
  195.  
  196.         if len(z1) > 0:
  197.             pen['dvc'] = long(z1s[d+1:d+5], 16)
  198.             pen['virgin'] = bool(z1[d+5] & 0x8L)
  199.             pen['hp-ink'] = bool(z1[d+5] & 0x4L)
  200.             pen['known'] = bool(z1[d+5] & 0x2L)
  201.             pen['ack'] = bool(z1[d+5] & 0x1L)
  202.  
  203.         index += 1
  204.         pens.append(pen)
  205.         pen = {}
  206.         c += pen_data_size
  207.         d += Z_SIZE
  208.  
  209.     return {'revision' :    revision,
  210.              'agents' :      pens,
  211.              'top-door' :    top_door,
  212.              'status-code' : stat,
  213.              'supply-door' : supply_door,
  214.              'duplexer' :    duplexer,
  215.              'photo-tray' :  photo_tray,
  216.              'in-tray1' :    in_tray1,
  217.              'in-tray2' :    in_tray2,
  218.              'media-path' :  media_path,
  219.            }
  220.  
  221.  
  222.  
  223. # $HB0$NC0,ff,DN,IDLE,CUT,K0,C0,DP,NR,KP092,CP041
  224. #     0    1  2  3    4   5  6  7  8  9     10
  225. def parseVStatus(s):
  226.     pens, pen, c = [], {}, 0
  227.     fields = s.split(',')
  228.     f0 = fields[0]
  229.     
  230.     if len(f0) == 20:
  231.         # TODO: $H00000000$M00000000 style (OJ Pro 1150/70)
  232.         # Need spec
  233.         pass
  234.     elif len(f0) == 8:
  235.         for p in f0:
  236.             if c == 0:
  237.                 #assert p == '$'
  238.                 c += 1
  239.             elif c == 1:
  240.                 if p in ('a', 'A'):
  241.                     pen['type'], pen['kind'] = AGENT_TYPE_NONE, AGENT_KIND_NONE
  242.                 c += 1
  243.             elif c == 2:
  244.                 pen['health'] = AGENT_HEALTH_OK
  245.                 pen['kind'] = AGENT_KIND_HEAD_AND_SUPPLY
  246.                 if   p in ('b', 'B'): pen['type'] = AGENT_TYPE_BLACK
  247.                 elif p in ('c', 'C'): pen['type'] = AGENT_TYPE_CMY
  248.                 elif p in ('d', 'D'): pen['type'] = AGENT_TYPE_KCM
  249.                 elif p in ('u', 'U'): pen['type'], pen['health'] = AGENT_TYPE_NONE, AGENT_HEALTH_MISINSTALLED
  250.                 c += 1
  251.             elif c == 3:
  252.                 if p == '0': pen['state'] = 1
  253.                 else: pen['state'] = 0
  254.     
  255.                 pen['level'] = 0
  256.                 i = 8
  257.     
  258.                 while True:
  259.                     try:
  260.                         f = fields[i]
  261.                     except IndexError:
  262.                         break
  263.                     else:
  264.                         if f[:2] == 'KP' and pen['type'] == AGENT_TYPE_BLACK:
  265.                             pen['level'] = int(f[2:])
  266.                         elif f[:2] == 'CP' and pen['type'] == AGENT_TYPE_CMY:
  267.                             pen['level'] = int(f[2:])
  268.                     i += 1
  269.     
  270.                 pens.append(pen)
  271.                 pen = {}
  272.                 c = 0
  273.     else:
  274.         pass
  275.         
  276.     if fields[2] == 'DN':
  277.         top_lid = 1
  278.     else:
  279.         top_lid = 2
  280.  
  281.     stat = vstatus_xlate.get(fields[3].lower(), STATUS_PRINTER_IDLE)
  282.  
  283.     return {'revision' :   STATUS_REV_V,
  284.              'agents' :     pens,
  285.              'top-lid' :    top_lid,
  286.              'status-code': stat,
  287.              'supply-lid' : SUPPLY_DOOR_NOT_PRESENT,
  288.              'duplexer' :   DUPLEXER_NOT_PRESENT,
  289.              'photo-tray' : PHOTO_TRAY_NOT_PRESENT,
  290.              'in-tray1' :   IN_TRAY_NOT_PRESENT,
  291.              'in-tray2' :   IN_TRAY_NOT_PRESENT,
  292.              'media-path' : MEDIA_PATH_CUT_SHEET, # ?
  293.            }
  294.  
  295. def parseStatus(DeviceID):
  296.     if 'VSTATUS' in DeviceID:
  297.          return parseVStatus(DeviceID['VSTATUS'])
  298.     elif 'S' in DeviceID:
  299.         return parseSStatus(DeviceID['S'], DeviceID.get('Z', ''))
  300.     else:
  301.         return STATUS_BLOCK_UNKNOWN
  302.  
  303.  
  304.  
  305. def LaserJetDeviceStatusToPrinterStatus(device_status, printer_status, detected_error_state):
  306.     stat = STATUS_PRINTER_IDLE
  307.  
  308.     if device_status in (pml.DEVICE_STATUS_WARNING, pml.DEVICE_STATUS_DOWN):
  309.  
  310.         if detected_error_state & pml.DETECTED_ERROR_STATE_LOW_PAPER_MASK and \
  311.             not (detected_error_state & pml.DETECTED_ERROR_STATE_NO_PAPER_MASK):
  312.             stat = STATUS_PRINTER_LOW_PAPER
  313.  
  314.         elif detected_error_state & pml.DETECTED_ERROR_STATE_NO_PAPER_MASK:
  315.             stat = STATUS_PRINTER_OUT_OF_PAPER
  316.  
  317.         elif detected_error_state & pml.DETECTED_ERROR_STATE_DOOR_OPEN_MASK:
  318.             stat = STATUS_PRINTER_DOOR_OPEN
  319.  
  320.         elif detected_error_state & pml.DETECTED_ERROR_STATE_JAMMED_MASK:
  321.             stat = STATUS_PRINTER_MEDIA_JAM
  322.  
  323.         elif detected_error_state & pml.DETECTED_ERROR_STATE_OUT_CART_MASK:
  324.             stat = STATUS_PRINTER_NO_TONER
  325.  
  326.         elif detected_error_state & pml.DETECTED_ERROR_STATE_LOW_CART_MASK:
  327.             stat = STATUS_PRINTER_LOW_TONER
  328.  
  329.         elif detected_error_state == pml.DETECTED_ERROR_STATE_SERVICE_REQUEST_MASK:
  330.             stat = STATUS_PRINTER_SERVICE_REQUEST
  331.  
  332.         elif detected_error_state & pml.DETECTED_ERROR_STATE_OFFLINE_MASK:
  333.             stat = STATUS_PRINTER_OFFLINE
  334.  
  335.     else:
  336.  
  337.         if printer_status == pml.PRINTER_STATUS_IDLE:
  338.             stat = STATUS_PRINTER_IDLE
  339.  
  340.         elif printer_status == pml.PRINTER_STATUS_PRINTING:
  341.             stat = STATUS_PRINTER_PRINTING
  342.  
  343.         elif printer_status == pml.PRINTER_STATUS_WARMUP:
  344.             stat = STATUS_PRINTER_WARMING_UP
  345.  
  346.     return stat
  347.  
  348. # Map from ISO 10175/10180 to HPLIP types
  349. COLORANT_INDEX_TO_AGENT_TYPE_MAP = {
  350.                                     'other' :   AGENT_TYPE_UNSPECIFIED,
  351.                                     'unknown' : AGENT_TYPE_UNSPECIFIED,
  352.                                     'blue' :    AGENT_TYPE_BLUE,
  353.                                     'cyan' :    AGENT_TYPE_CYAN,
  354.                                     'magenta':  AGENT_TYPE_MAGENTA,
  355.                                     'yellow' :  AGENT_TYPE_YELLOW,
  356.                                     'black' :   AGENT_TYPE_BLACK,
  357.                                    }
  358.  
  359. MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP = {
  360.     pml.OID_MARKER_SUPPLIES_TYPE_OTHER :              AGENT_KIND_UNKNOWN,
  361.     pml.OID_MARKER_SUPPLIES_TYPE_UNKNOWN :            AGENT_KIND_UNKNOWN,
  362.     pml.OID_MARKER_SUPPLIES_TYPE_TONER :              AGENT_KIND_TONER_CARTRIDGE,
  363.     pml.OID_MARKER_SUPPLIES_TYPE_WASTE_TONER :        AGENT_KIND_UNKNOWN,
  364.     pml.OID_MARKER_SUPPLIES_TYPE_INK :                AGENT_KIND_SUPPLY,
  365.     pml.OID_MARKER_SUPPLIES_TYPE_INK_CART :           AGENT_KIND_HEAD_AND_SUPPLY,
  366.     pml.OID_MARKER_SUPPLIES_TYPE_INK_RIBBON :         AGENT_KIND_HEAD_AND_SUPPLY,
  367.     pml.OID_MARKER_SUPPLIES_TYPE_WASTE_INK :          AGENT_KIND_UNKNOWN,
  368.     pml.OID_MARKER_SUPPLIES_TYPE_OPC :                AGENT_KIND_DRUM_KIT,
  369.     pml.OID_MARKER_SUPPLIES_TYPE_DEVELOPER :          AGENT_KIND_UNKNOWN,
  370.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OIL :          AGENT_KIND_UNKNOWN,
  371.     pml.OID_MARKER_SUPPLIES_TYPE_SOLID_WAX :          AGENT_KIND_UNKNOWN,
  372.     pml.OID_MARKER_SUPPLIES_TYPE_RIBBON_WAX :         AGENT_KIND_UNKNOWN,
  373.     pml.OID_MARKER_SUPPLIES_TYPE_WASTE_WAX :          AGENT_KIND_UNKNOWN,
  374.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER :              AGENT_KIND_MAINT_KIT,
  375.     pml.OID_MARKER_SUPPLIES_TYPE_CORONA_WIRE :        AGENT_KIND_UNKNOWN,
  376.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OIL_WICK :     AGENT_KIND_UNKNOWN,
  377.     pml.OID_MARKER_SUPPLIES_TYPE_CLEANER_UNIT :       AGENT_KIND_UNKNOWN,
  378.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER_CLEANING_PAD : AGENT_KIND_UNKNOWN,
  379.     pml.OID_MARKER_SUPPLIES_TYPE_TRANSFER_UNIT :      AGENT_KIND_TRANSFER_KIT,
  380.     pml.OID_MARKER_SUPPLIES_TYPE_TONER_CART :         AGENT_KIND_TONER_CARTRIDGE,
  381.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OILER :        AGENT_KIND_UNKNOWN,
  382.     pml.OID_MARKER_SUPPLIES_TYPE_ADF_MAINT_KIT :      AGENT_KIND_ADF_KIT,
  383. }
  384.  
  385.  
  386. def StatusType3( dev, parsedID ): # LaserJet Status (PML/SNMP)
  387.     dev.openPML()
  388.     result_code, on_off_line = dev.getPML( pml.OID_ON_OFF_LINE, pml.INT_SIZE_BYTE )
  389.     result_code, sleep_mode = dev.getPML( pml.OID_SLEEP_MODE, pml.INT_SIZE_BYTE )
  390.     result_code, printer_status = dev.getPML( pml.OID_PRINTER_STATUS, pml.INT_SIZE_BYTE )
  391.     result_code, device_status = dev.getPML( pml.OID_DEVICE_STATUS, pml.INT_SIZE_BYTE )
  392.     result_code, cover_status = dev.getPML( pml.OID_COVER_STATUS, pml.INT_SIZE_BYTE )
  393.     result_code,  value = dev.getPML( pml.OID_DETECTED_ERROR_STATE )
  394.     
  395.     try:
  396.         detected_error_state = struct.unpack( 'B', value[0])[0]
  397.     except IndexError:
  398.         detected_error_state = pml.DETECTED_ERROR_STATE_OFFLINE_MASK
  399.     
  400.     agents, x = [], 1
  401.  
  402.     while True:
  403.         log.debug( "%s Agent: %d %s" % ("*"*10, x, "*"*10))
  404.         log.debug("OID_MARKER_SUPPLIES_TYPE_%d:" % x)
  405.         oid = ( pml.OID_MARKER_SUPPLIES_TYPE_x % x, pml.OID_MARKER_SUPPLIES_TYPE_x_TYPE )
  406.         result_code, value = dev.getPML( oid, pml.INT_SIZE_BYTE )
  407.  
  408.         if result_code != ERROR_SUCCESS or value is None:
  409.             log.debug("End of supply information.")
  410.             break
  411.  
  412.         for a in MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP:
  413.             if value == a:
  414.                 agent_kind = MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP[a]
  415.                 break
  416.         else:
  417.             agent_kind = AGENT_KIND_UNKNOWN
  418.  
  419.         # TODO: Deal with printers that return -1 and -2 for level and max (LJ3380)
  420.         
  421.         log.debug("OID_MARKER_SUPPLIES_LEVEL_%d:" % x)
  422.         oid = ( pml.OID_MARKER_SUPPLIES_LEVEL_x % x, pml.OID_MARKER_SUPPLIES_LEVEL_x_TYPE )
  423.         result_code, agent_level = dev.getPML( oid )
  424.  
  425.         if result_code != ERROR_SUCCESS:
  426.             log.debug("Failed")
  427.             break
  428.             
  429.         log.debug( 'agent%d-level: %d' % ( x, agent_level ) )
  430.         log.debug("OID_MARKER_SUPPLIES_MAX_%d:" % x)
  431.         oid = ( pml.OID_MARKER_SUPPLIES_MAX_x % x, pml.OID_MARKER_SUPPLIES_MAX_x_TYPE )
  432.         result_code, agent_max = dev.getPML( oid )
  433.         
  434.         if agent_max == 0: agent_max = 1
  435.  
  436.         if result_code != ERROR_SUCCESS:
  437.             log.debug("Failed")
  438.             break
  439.  
  440.         log.debug( 'agent%d-max: %d' % ( x, agent_max ) )
  441.         log.debug("OID_MARKER_SUPPLIES_COLORANT_INDEX_%d:" % x)
  442.         oid = ( pml.OID_MARKER_SUPPLIES_COLORANT_INDEX_x % x, pml.OID_MARKER_SUPPLIES_COLORANT_INDEX_x_TYPE )
  443.         result_code, colorant_index = dev.getPML( oid )
  444.  
  445.         if result_code != ERROR_SUCCESS: # 3080, 3055 will fail here
  446.             log.debug("Failed")
  447.             agent_type = AGENT_TYPE_BLACK
  448.             #break
  449.         else:
  450.             log.debug("Colorant index: %d" % colorant_index)
  451.  
  452.             log.debug("OID_MARKER_COLORANT_VALUE_%d" % x)
  453.             oid = ( pml.OID_MARKER_COLORANT_VALUE_x % colorant_index, pml.OID_MARKER_COLORANT_VALUE_x_TYPE )
  454.             result_code, colorant_value = dev.getPML( oid )
  455.     
  456.             if result_code != ERROR_SUCCESS:
  457.                 log.debug("Failed. Defaulting to black.")
  458.                 agent_type = AGENT_TYPE_BLACK
  459.             #else:
  460.             if 1:
  461.                 if agent_kind in (AGENT_KIND_MAINT_KIT, AGENT_KIND_ADF_KIT,
  462.                                   AGENT_KIND_DRUM_KIT, AGENT_KIND_TRANSFER_KIT):
  463.         
  464.                     agent_type = AGENT_TYPE_UNSPECIFIED
  465.         
  466.                 else:
  467.                     agent_type = AGENT_TYPE_BLACK
  468.         
  469.                     if result_code != ERROR_SUCCESS:
  470.                         log.debug("OID_MARKER_SUPPLIES_DESCRIPTION_%d:" % x)
  471.                         oid = (pml.OID_MARKER_SUPPLIES_DESCRIPTION_x % x, pml.OID_MARKER_SUPPLIES_DESCRIPTION_x_TYPE)
  472.                         result_code, colorant_value = dev.getPML( oid )
  473.                         
  474.                         if result_code != ERROR_SUCCESS:
  475.                             log.debug("Failed")
  476.                             break
  477.         
  478.                         if colorant_value is not None:
  479.                             log.debug("colorant value: %s" % colorant_value)
  480.                             colorant_value = colorant_value.lower().strip()
  481.         
  482.                             for c in COLORANT_INDEX_TO_AGENT_TYPE_MAP:
  483.                                 if colorant_value.find(c) >= 0:
  484.                                     agent_type = COLORANT_INDEX_TO_AGENT_TYPE_MAP[c]
  485.                                     break
  486.                             else:
  487.                                 agent_type = AGENT_TYPE_BLACK
  488.         
  489.                     else: # SUCCESS
  490.                         if colorant_value is not None:
  491.                             log.debug("colorant value: %s" % colorant_value)
  492.                             agent_type = COLORANT_INDEX_TO_AGENT_TYPE_MAP.get( colorant_value, None )
  493.         
  494.                         if agent_type == AGENT_TYPE_NONE:
  495.                             if agent_kind == AGENT_KIND_TONER_CARTRIDGE:
  496.                                 agent_type = AGENT_TYPE_BLACK
  497.                             else:
  498.                                 agent_type = AGENT_TYPE_UNSPECIFIED
  499.     
  500.         log.debug("OID_MARKER_STATUS_%d:" % x)
  501.         oid = ( pml.OID_MARKER_STATUS_x % x, pml.OID_MARKER_STATUS_x_TYPE )
  502.         result_code, agent_status = dev.getPML( oid )
  503.  
  504.         if result_code != ERROR_SUCCESS:
  505.             log.debug("Failed")
  506.             agent_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0
  507.             agent_health = AGENT_HEALTH_OK
  508.         else:
  509.             agent_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0
  510.  
  511.             if agent_status is None:
  512.                 agent_health = AGENT_HEALTH_OK
  513.  
  514.             elif agent_status == pml.OID_MARKER_STATUS_OK:
  515.                 agent_health = AGENT_HEALTH_OK
  516.  
  517.             elif agent_status == pml.OID_MARKER_STATUS_MISINSTALLED:
  518.                 agent_health = AGENT_HEALTH_MISINSTALLED
  519.  
  520.             elif agent_status in ( pml.OID_MARKER_STATUS_LOW_TONER_CONT,
  521.                                    pml.OID_MARKER_STATUS_LOW_TONER_STOP ):
  522.  
  523.                 agent_health = AGENT_HEALTH_OK
  524.                 agent_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW
  525.  
  526.             else:
  527.                 agent_health = AGENT_HEALTH_OK
  528.  
  529.         agent_level = int(agent_level/agent_max * 100)
  530.  
  531.         log.debug("agent%d: kind=%d, type=%d, health=%d, level=%d, level-trigger=%d" % \
  532.             (x, agent_kind, agent_type, agent_health, agent_level, agent_trigger))
  533.  
  534.  
  535.         agents.append({'kind' : agent_kind,
  536.                        'type' : agent_type,
  537.                        'health' : agent_health,
  538.                        'level' : agent_level,
  539.                        'level-trigger' : agent_trigger,})
  540.  
  541.         x += 1
  542.     
  543.  
  544.     log.debug("on_off_line=%d" % on_off_line)
  545.     log.debug("sleep_mode=%d" % sleep_mode)
  546.     log.debug("printer_status=%d" % printer_status)
  547.     log.debug("device_status=%d" % device_status)
  548.     log.debug("cover_status=%d" % cover_status)
  549.     log.debug("detected_error_state=%d (0x%x)" % (detected_error_state, detected_error_state))
  550.  
  551.     stat = LaserJetDeviceStatusToPrinterStatus(device_status, printer_status, detected_error_state)
  552.  
  553.     log.debug("Printer status=%d" % stat)
  554.  
  555.     if stat == STATUS_PRINTER_DOOR_OPEN:
  556.         supply_door = 0
  557.     else:
  558.         supply_door = 1
  559.  
  560.     return {'revision' :    STATUS_REV_UNKNOWN,
  561.              'agents' :      agents,
  562.              'top-door' :    cover_status,
  563.              'status-code' : stat,
  564.              'supply-door' : supply_door,
  565.              'duplexer' :    1,
  566.              'photo-tray' :  0,
  567.              'in-tray1' :    1,
  568.              'in-tray2' :    1,
  569.              'media-path' :  1,
  570.            }
  571.  
  572. def setup_panel_translator():
  573.     printables = list(
  574. """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
  575. !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~""")
  576.  
  577.     map = {}
  578.     for x in [chr(x) for x in range(0,256)]:
  579.         if x in printables:
  580.             map[x] = x
  581.         else:
  582.             map[x] = '\x20'
  583.  
  584.     map.update({'\x10' : '\xab',
  585.                     '\x11' : '\xbb',
  586.                     '\x12' : '\xa3',
  587.                     '\x13' : '\xbb',
  588.                     '\x80' : '\xab',
  589.                     '\x81' : '\xbb',
  590.                     '\x82' : '\x2a',
  591.                     '\x83' : '\x2a',
  592.                     '\x85' : '\x2a',
  593.                     '\xa0' : '\xab',
  594.                     '\x1f' : '\x3f',
  595.                     '='    : '\x20',
  596.                 })
  597.  
  598.     frm, to = '', ''
  599.     map_keys = map.keys()
  600.     map_keys.sort()
  601.     for x in map_keys:
  602.         frm = ''.join([frm, x])
  603.         to = ''.join([to, map[x]])
  604.  
  605.     global PANEL_TRANSLATOR_FUNC
  606.     PANEL_TRANSLATOR_FUNC = utils.Translator(frm, to)
  607.  
  608. PANEL_TRANSLATOR_FUNC = None
  609. setup_panel_translator()
  610.  
  611.  
  612. def PanelCheck(dev):
  613.     line1, line2 = '', ''
  614.     try:
  615.         dev.openPML()
  616.     except Error:
  617.         pass
  618.     else:
  619.  
  620.         oids = [(pml.OID_HP_LINE1, pml.OID_HP_LINE2),
  621.                  (pml.OID_SPM_LINE1, pml.OID_SPM_LINE2)]
  622.  
  623.         for oid1, oid2 in oids:
  624.             result, line1 = dev.getPML(oid1)
  625.  
  626.             if result < pml.ERROR_MAX_OK:
  627.                 line1 = PANEL_TRANSLATOR_FUNC(line1).rstrip()
  628.  
  629.                 if '\x0a' in line1:
  630.                     line1, line2 = line1.split('\x0a', 1)
  631.                     break
  632.  
  633.                 result, line2 = dev.getPML(oid2)
  634.  
  635.                 if result < pml.ERROR_MAX_OK:
  636.                     line2 = PANEL_TRANSLATOR_FUNC(line2).rstrip()
  637.                     break
  638.  
  639.         #dev.closePML()
  640.  
  641.     return bool(line1 or line2), line1 or '', line2 or ''
  642.  
  643.  
  644. BATTERY_HEALTH_MAP = {0 : AGENT_HEALTH_OK,
  645.                        1 : AGENT_HEALTH_OVERTEMP,
  646.                        2 : AGENT_HEALTH_CHARGING,
  647.                        3 : AGENT_HEALTH_MISINSTALLED,
  648.                        4 : AGENT_HEALTH_FAILED,
  649.                       }
  650.  
  651.  
  652. BATTERY_TRIGGER_MAP = {0 : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  653.                         1 : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT,
  654.                         2 : AGENT_LEVEL_TRIGGER_PROBABLY_OUT,
  655.                         3 : AGENT_LEVEL_TRIGGER_SUFFICIENT_4,
  656.                         4 : AGENT_LEVEL_TRIGGER_SUFFICIENT_2,
  657.                         5 : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  658.                        }
  659.  
  660. BATTERY_PML_TRIGGER_MAP = {
  661.         (100, 80)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  662.         (79,  60)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_1,
  663.         (59,  40)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_2,
  664.         (39,  30)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_3,
  665.         (29,  20)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_4,
  666.         (19,  10)  : AGENT_LEVEL_TRIGGER_MAY_BE_LOW,
  667.         (9,    5)  : AGENT_LEVEL_TRIGGER_PROBABLY_OUT,
  668.         (4,   -1)  : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT,
  669.         }
  670.  
  671.         
  672. def BatteryCheck(dev, status_block):
  673.     try_dynamic_counters = False
  674.     
  675.     try:
  676.         try:
  677.             dev.openPML()
  678.         except Error:
  679.             log.error("PML channel open failed.")
  680.             try_dynamic_counters = True
  681.         else:
  682.             result, battery_level = dev.getPML(pml.OID_BATTERY_LEVEL)
  683.             result, power_mode =  dev.getPML(pml.OID_POWER_MODE)
  684.     
  685.             if battery_level is not None and \
  686.                 power_mode is not None:
  687.     
  688.                 if power_mode & pml.POWER_MODE_BATTERY_LEVEL_KNOWN and \
  689.                     battery_level >= 0:
  690.     
  691.                     for x in BATTERY_PML_TRIGGER_MAP:
  692.                         if x[0] >= battery_level > x[1]:
  693.                             battery_trigger_level = BATTERY_PML_TRIGGER_MAP[x]
  694.                             break
  695.     
  696.                     if power_mode & pml.POWER_MODE_CHARGING:
  697.                         agent_health = AGENT_HEALTH_CHARGING
  698.     
  699.                     elif power_mode & pml.POWER_MODE_DISCHARGING:
  700.                         agent_health = AGENT_HEALTH_DISCHARGING
  701.     
  702.                     else:
  703.                         agent_health = AGENT_HEALTH_OK
  704.     
  705.                     status_block['agents'].append({
  706.                                                     'kind'   : AGENT_KIND_INT_BATTERY,
  707.                                                     'type'   : AGENT_TYPE_UNSPECIFIED,
  708.                                                     'health' : agent_health,
  709.                                                     'level'  : battery_level,
  710.                                                     'level-trigger' : battery_trigger_level,
  711.                                                     })
  712.                 else:
  713.                     status_block['agents'].append({
  714.                                                     'kind'   : AGENT_KIND_INT_BATTERY,
  715.                                                     'type'   : AGENT_TYPE_UNSPECIFIED,
  716.                                                     'health' : AGENT_HEALTH_UNKNOWN,
  717.                                                     'level'  : 0,
  718.                                                     'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  719.                                                     })
  720.     
  721.             else:
  722.                 try_dynamic_counters = True
  723.  
  724.     finally:
  725.         dev.closePML()
  726.  
  727.     if try_dynamic_counters:
  728.  
  729.         try:
  730.             try:
  731.                 battery_health = dev.getDynamicCounter(200)
  732.                 battery_trigger_level = dev.getDynamicCounter(201)
  733.                 battery_level = dev.getDynamicCounter(202)
  734.  
  735.                 status_block['agents'].append({
  736.                                                 'kind'   : AGENT_KIND_INT_BATTERY,
  737.                                                 'type'   : AGENT_TYPE_UNSPECIFIED,
  738.                                                 'health' : BATTERY_HEALTH_MAP[battery_health],
  739.                                                 'level'  : battery_level,
  740.                                                 'level-trigger' : BATTERY_TRIGGER_MAP[battery_trigger_level],
  741.                                                 })
  742.             except Error:
  743.                 status_block['agents'].append({
  744.                                                 'kind'   : AGENT_KIND_INT_BATTERY,
  745.                                                 'type'   : AGENT_TYPE_UNSPECIFIED,
  746.                                                 'health' : AGENT_HEALTH_UNKNOWN,
  747.                                                 'level'  : 0,
  748.                                                 'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  749.                                                 })
  750.         finally:
  751.             dev.closePrint()
  752.             
  753.  
  754. # this works for 2 pen products that allow 1 or 2 pens inserted
  755. # from: k, kcm, cmy, ggk
  756. def getPenConfiguration(s): # s=status dict from parsed device ID
  757.     pens = [p['type'] for p in s['agents']]
  758.  
  759.     if utils.all(pens, lambda x : x==AGENT_TYPE_NONE):
  760.         return AGENT_CONFIG_NONE
  761.  
  762.     if AGENT_TYPE_NONE in pens:
  763.  
  764.         if AGENT_TYPE_BLACK in pens:
  765.             return AGENT_CONFIG_BLACK_ONLY
  766.  
  767.         elif AGENT_TYPE_CMY in pens:
  768.             return AGENT_CONFIG_COLOR_ONLY
  769.  
  770.         elif AGENT_TYPE_KCM in pens:
  771.             return AGENT_CONFIG_PHOTO_ONLY
  772.  
  773.         elif AGENT_TYPE_GGK in pens:
  774.             return AGENT_CONFIG_GREY_ONLY
  775.  
  776.         else:
  777.             return AGENT_CONFIG_INVALID
  778.  
  779.     else:
  780.         if AGENT_TYPE_BLACK in pens and AGENT_TYPE_CMY in pens:
  781.             return AGENT_CONFIG_COLOR_AND_BLACK
  782.  
  783.         elif AGENT_TYPE_CMY in pens and AGENT_TYPE_KCM in pens:
  784.             return AGENT_CONFIG_COLOR_AND_PHOTO
  785.  
  786.         elif AGENT_TYPE_CMY in pens and AGENT_TYPE_GGK in pens:
  787.             return AGENT_CONFIG_COLOR_AND_GREY
  788.  
  789.         else:
  790.             return AGENT_CONFIG_INVALID
  791.  
  792.  
  793. def getFaxStatus(dev):
  794.     tx_active, rx_active = False, False
  795.     
  796.     try:
  797.         dev.openPML()
  798.     
  799.         result_code, tx_state = dev.getPML(pml.OID_FAXJOB_TX_STATUS)
  800.         
  801.         if result_code == ERROR_SUCCESS:
  802.             if tx_state not in (pml.FAXJOB_TX_STATUS_IDLE, pml.FAXJOB_TX_STATUS_DONE):
  803.                 tx_active = True
  804.         
  805.         result_code, rx_state = dev.getPML(pml.OID_FAXJOB_RX_STATUS)
  806.  
  807.         if result_code == ERROR_SUCCESS:
  808.             if rx_state not in (pml.FAXJOB_RX_STATUS_IDLE, pml.FAXJOB_RX_STATUS_DONE):
  809.                 rx_active = True
  810.     
  811.     finally:
  812.         dev.closePML()
  813.         
  814.     return tx_active, rx_active
  815.     
  816.     
  817. TYPE6_STATUS_CODE_MAP = {
  818.     -19928: STATUS_PRINTER_IDLE,
  819.     -18995: STATUS_PRINTER_CANCELING,
  820.     -17974: STATUS_PRINTER_WARMING_UP,
  821.     -17973: STATUS_PRINTER_PEN_CLEANING, # sic
  822.     -18993: STATUS_PRINTER_BUSY,
  823.     -17949: STATUS_PRINTER_BUSY,
  824.     -19720: STATUS_PRINTER_MANUAL_DUPLEX_BLOCK,
  825.     -19678: STATUS_PRINTER_BUSY,
  826.     -19695: STATUS_PRINTER_OUT_OF_PAPER,
  827.     -17985: STATUS_PRINTER_MEDIA_JAM,
  828.     -19731: STATUS_PRINTER_OUT_OF_PAPER,
  829.     -18974: STATUS_PRINTER_BUSY, #?
  830.     -19730: STATUS_PRINTER_OUT_OF_PAPER,
  831.     -19729: STATUS_PRINTER_OUT_OF_PAPER,
  832.     -19933: STATUS_PRINTER_HARD_ERROR, # out of memory
  833.     -17984: STATUS_PRINTER_DOOR_OPEN, 
  834.     -19694: STATUS_PRINTER_DOOR_OPEN,
  835.     -18992: STATUS_PRINTER_MANUAL_FEED_BLOCKED, # ?
  836.     -19690: STATUS_PRINTER_MEDIA_JAM, # tray 1
  837.     -19689: STATUS_PRINTER_MEDIA_JAM, # tray 2
  838.     -19611: STATUS_PRINTER_MEDIA_JAM, # tray 3
  839.     -19686: STATUS_PRINTER_MEDIA_JAM,
  840.     -19688: STATUS_PRINTER_MEDIA_JAM, # paper path
  841.     -19685: STATUS_PRINTER_MEDIA_JAM, # cart area
  842.     -19684: STATUS_PRINTER_MEDIA_JAM, # output bin
  843.     -18848: STATUS_PRINTER_MEDIA_JAM, # duplexer
  844.     -18847: STATUS_PRINTER_MEDIA_JAM, # door open
  845.     -18846: STATUS_PRINTER_MEDIA_JAM, # tray 2
  846.     -19687: STATUS_PRINTER_MEDIA_JAM, # open door
  847.     -17992: STATUS_PRINTER_MEDIA_JAM, # mispick
  848.     -19700: STATUS_PRINTER_HARD_ERROR, # invalid driver
  849.     -17996: STATUS_PRINTER_FUSER_ERROR, # fuser error
  850.     -17983: STATUS_PRINTER_FUSER_ERROR,
  851.     -17982: STATUS_PRINTER_FUSER_ERROR,
  852.     -17981: STATUS_PRINTER_FUSER_ERROR,
  853.     -17971: STATUS_PRINTER_FUSER_ERROR,
  854.     -17995: STATUS_PRINTER_HARD_ERROR, # beam error
  855.     -17994: STATUS_PRINTER_HARD_ERROR, # scanner error
  856.     -17993: STATUS_PRINTER_HARD_ERROR, # fan error
  857.     -18994: STATUS_PRINTER_HARD_ERROR,
  858.     -17986: STATUS_PRINTER_HARD_ERROR,
  859.     -19904: STATUS_PRINTER_HARD_ERROR,
  860.     -19701: STATUS_PRINTER_NON_HP_INK, # [sic]
  861.     -19613: STATUS_PRINTER_IDLE, # HP
  862.     -19654: STATUS_PRINTER_NON_HP_INK, # [sic]
  863.     -19682: STATUS_PRINTER_HARD_ERROR, # resinstall
  864.     -19693: STATUS_PRINTER_IDLE, # ?? To Accept
  865.     -19752: STATUS_PRINTER_LOW_TONER,
  866.     -19723: STATUS_PRINTER_BUSY,
  867.     -19703: STATUS_PRINTER_BUSY,
  868.     -19739: STATUS_PRINTER_NO_TONER,
  869.     -19927: STATUS_PRINTER_BUSY,
  870.     -19932: STATUS_PRINTER_BUSY,
  871.     -19931: STATUS_PRINTER_BUSY,
  872.     -11989: STATUS_PRINTER_BUSY,
  873.     -11995: STATUS_PRINTER_BUSY, # ADF loaded
  874.     -19954: STATUS_PRINTER_CANCELING,
  875.     -19955: STATUS_PRINTER_REPORT_PRINTING,
  876.     -19956: STATUS_PRINTER_REPORT_PRINTING,
  877.     -19934: STATUS_PRINTER_HARD_ERROR,
  878.     -19930: STATUS_PRINTER_BUSY,
  879.     -11990: STATUS_PRINTER_DOOR_OPEN,
  880.     -11999: STATUS_PRINTER_MEDIA_JAM, # ADF
  881.     -12000: STATUS_PRINTER_MEDIA_JAM, # ADF
  882.     -11998: STATUS_PRINTER_MEDIA_JAM, # ADF
  883.     -11986: STATUS_PRINTER_HARD_ERROR, # scanner
  884.     -11994: STATUS_PRINTER_BUSY,
  885.     -14967: STATUS_PRINTER_BUSY,
  886.     -19912: STATUS_PRINTER_HARD_ERROR,
  887.     -14962: STATUS_PRINTER_BUSY, # copy pending
  888.     -14971: STATUS_PRINTER_BUSY, # copying
  889.     -14973: STATUS_PRINTER_BUSY, # copying being canceled
  890.     -14972: STATUS_PRINTER_BUSY, # copying canceled
  891.     -14966: STATUS_PRINTER_DOOR_OPEN,
  892.     -14974: STATUS_PRINTER_MEDIA_JAM,
  893.     -14969: STATUS_PRINTER_HARD_ERROR,
  894.     -14968: STATUS_PRINTER_HARD_ERROR,
  895.     -12996: STATUS_PRINTER_BUSY, # scan
  896.     -12994: STATUS_PRINTER_BUSY, # scan
  897.     -12993: STATUS_PRINTER_BUSY, # scan
  898.     -12991: STATUS_PRINTER_BUSY, # scan
  899.     -12995: STATUS_PRINTER_BUSY, # scan
  900.     -12997: STATUS_PRINTER_HARD_ERROR, # scan
  901.     -12990: STATUS_PRINTER_BUSY,
  902.     -12998: STATUS_PRINTER_BUSY,
  903.     -13000: STATUS_PRINTER_DOOR_OPEN,
  904.     -12999: STATUS_PRINTER_MEDIA_JAM,
  905.     -13859: STATUS_PRINTER_BUSY,
  906.     -13858: STATUS_PRINTER_BUSY, #</DevStatusDialingOut>
  907.     -13868: STATUS_PRINTER_BUSY, #</DevStatusRedialPending>
  908.     -13867: STATUS_PRINTER_BUSY, #</DevStatusFaxSendCanceled>
  909.     -13857: STATUS_PRINTER_BUSY, #</DevStatusConnecting>
  910.     -13856: STATUS_PRINTER_BUSY, #</DevStatusSendingPage>
  911.     -13855: STATUS_PRINTER_BUSY, #</DevStatusOnePageSend>
  912.     -13854: STATUS_PRINTER_BUSY, #</DevStatusMultiplePagesSent>
  913.     -13853: STATUS_PRINTER_BUSY, #</DevStatusSenderCancelingFax>
  914.     -13839: STATUS_PRINTER_BUSY, #</DevStatusIncomingCall>
  915.     -13842: STATUS_PRINTER_BUSY, #</DevStatusBlockingFax>
  916.     -13838: STATUS_PRINTER_BUSY, #</DevStatusReceivingFax>
  917.     -13847: STATUS_PRINTER_BUSY, #</DevStatusSinglePageReceived>
  918.     -13846: STATUS_PRINTER_BUSY, #</DevStatusDoublePagesReceived>
  919.     -13845: STATUS_PRINTER_BUSY, #</DevStatusTriplePagesReceived>
  920.     -13844: STATUS_PRINTER_BUSY, #</DevStatusPrintingFax>
  921.     -13840: STATUS_PRINTER_BUSY, #</DevStatusCancelingFaxPrint>
  922.     -13843: STATUS_PRINTER_BUSY, #</DevStatusFaxCancelingReceive>
  923.     -13850: STATUS_PRINTER_BUSY, #</DevStatusFaxCanceledReceive>
  924.     -13851: STATUS_PRINTER_BUSY, #</DevStatusFaxDelayedSendMemoryFull>
  925.     -13836: STATUS_PRINTER_BUSY, #</DevStatusNoDialTone>
  926.     -13864: STATUS_PRINTER_BUSY, #</DevStatusNoFaxAnswer>
  927.     -13863: STATUS_PRINTER_BUSY, #</DevStatusFaxBusy>
  928.     -13865: STATUS_PRINTER_BUSY, #</DevStatusNoDocumentSent>
  929.     -13862: STATUS_PRINTER_BUSY, #</DevStatusFaxSendError>
  930.     -13837: STATUS_PRINTER_BUSY, #</DevStatusT30Error>
  931.     -13861: STATUS_PRINTER_BUSY, #</DevStatusFaxMemoryFullSend>
  932.     -13866: STATUS_PRINTER_BUSY, #</DevStatusADFNotCleared>
  933.     -13841: STATUS_PRINTER_BUSY, #</DevStatusNoFaxDetected>
  934.     -13848: STATUS_PRINTER_BUSY, #</DevStatusFaxMemoryFullReceive>
  935.     -13849: STATUS_PRINTER_BUSY, #</DevStatusFaxReceiveError>
  936.     0: STATUS_UNKNOWN, #</DevStatusUnknown>
  937. }    
  938.  
  939. def StatusType6(dev): #  LaserJet Status (XML)
  940.     info_device_status = cStringIO.StringIO()
  941.     info_ssp = cStringIO.StringIO()
  942.     
  943.     dev.getEWSUrl("/hp/device/info_device_status.xml", info_device_status)
  944.     dev.getEWSUrl("/hp/device/info_ssp.xml", info_ssp)
  945.     
  946.     info_device_status = info_device_status.getvalue()
  947.     info_ssp = info_ssp.getvalue()
  948.     
  949.     device_status = {}
  950.     ssp = {}
  951.     
  952.     if info_device_status:
  953.         device_status = utils.XMLToDictParser().parseXML(info_device_status)
  954.         log.debug_block("info_device_status", info_device_status)
  955.         log.debug(device_status)
  956.  
  957.     if info_ssp:
  958.         ssp = utils.XMLToDictParser().parseXML(info_ssp)
  959.         log.debug_block("info_spp", info_ssp)
  960.         log.debug(ssp)
  961.     
  962.     status_code = device_status.get('devicestatuspage-devicestatus-statuslist-status-code-0', 0)
  963.     black_supply_level = device_status.get('devicestatuspage-suppliesstatus-blacksupply-percentremaining', 0)
  964.     black_supply_low = ssp.get('suppliesstatuspage-blacksupply-lowreached', 0)
  965.     agents = []
  966.     
  967.     agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  968.                      'type' : AGENT_TYPE_BLACK,
  969.                      'health' : 0,
  970.                      'level' : black_supply_level,
  971.                      'level-trigger' : 0,
  972.                   })
  973.     
  974.     if dev.tech_type == TECH_TYPE_COLOR_LASER:
  975.         cyan_supply_level = device_status.get('devicestatuspage-suppliesstatus-cyansupply-percentremaining', 0)
  976.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  977.                          'type' : AGENT_TYPE_CYAN,
  978.                          'health' : 0,
  979.                          'level' : cyan_supply_level,
  980.                          'level-trigger' : 0,
  981.                       })
  982.  
  983.         magenta_supply_level = device_status.get('devicestatuspage-suppliesstatus-magentasupply-percentremaining', 0)
  984.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  985.                          'type' : AGENT_TYPE_MAGENTA,
  986.                          'health' : 0,
  987.                          'level' : magenta_supply_level,
  988.                          'level-trigger' : 0,
  989.                       })
  990.  
  991.         yellow_supply_level = device_status.get('devicestatuspage-suppliesstatus-yellowsupply-percentremaining', 0)
  992.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  993.                          'type' : AGENT_TYPE_YELLOW,
  994.                          'health' : 0,
  995.                          'level' : yellow_supply_level,
  996.                          'level-trigger' : 0,
  997.                       })
  998.  
  999.     return {'revision' :    STATUS_REV_UNKNOWN,
  1000.              'agents' :      agents,
  1001.              'top-door' :    0,
  1002.              'status-code' : 0,
  1003.              'supply-door' : 0,
  1004.              'duplexer' :    1,
  1005.              'photo-tray' :  0,
  1006.              'in-tray1' :    1,
  1007.              'in-tray2' :    1,
  1008.              'media-path' :  1,
  1009.              'status-code' : TYPE6_STATUS_CODE_MAP.get(status_code, STATUS_PRINTER_IDLE),
  1010.            }     
  1011.     
  1012.         
  1013.     
  1014.     
  1015.     
  1016.     
  1017.