home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / hplip / base / status.py < prev    next >
Encoding:
Python Source  |  2007-04-04  |  39.5 KB  |  1,055 lines

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