1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3# 4# (c) Copyright 2003-2015 HP Development Company, L.P. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program; if not, write to the Free Software 18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19# 20# Author: Don Welch, Naga Samrat Chowdary Narla 21# 22 23# Std Lib 24import socket 25import re 26import gzip 27import os.path 28import time 29from .sixext.moves import urllib_request, urllib_parse, urllib_error 30import io 31from io import BytesIO 32from .sixext.moves import http_client 33import struct 34import string 35import time 36# Local 37from .g import * 38from .codes import * 39from . import utils 40from . import services 41from . import os_utils 42from . import status 43from . import pml 44from . import status 45from prnt import pcl, ldl, cups 46from . import models, mdns, slp, avahi 47from .strings import * 48from .sixext import PY3, to_bytes_utf8, to_unicode, to_string_latin, to_string_utf8, xStringIO 49 50http_result_pat = re.compile("""HTTP/\d.\d\s(\d+)""", re.I) 51 52HTTP_OK = 200 53HTTP_ERROR = 500 54 55try: 56 import hpmudext 57except ImportError: 58 if not os.getenv("HPLIP_BUILD"): 59 log.error("HPMUDEXT could not be loaded. Please check HPLIP installation.") 60 sys.exit(1) 61else: 62 # Workaround for build machine 63 try: 64 MAX_BUFFER = hpmudext.HPMUD_BUFFER_SIZE 65 except AttributeError: 66 MAX_BUFFER = 8192 67 68dbus_avail = False 69dbus_disabled = False 70try: 71 import dbus 72 from dbus import lowlevel, SessionBus 73 dbus_avail = True 74except ImportError: 75 log.warn("python-dbus not installed.") 76 77import warnings 78# Ignore: .../dbus/connection.py:242: DeprecationWarning: object.__init__() takes no parameters 79# (occurring on Python 2.6/dBus 0.83/Ubuntu 9.04) 80warnings.simplefilter("ignore", DeprecationWarning) 81 82 83DEFAULT_PROBE_BUS = ['usb', 'par', 'cups'] 84VALID_BUSES = ('par', 'net', 'cups', 'usb') #, 'bt', 'fw') 85VALID_BUSES_WO_CUPS = ('par', 'net', 'usb') 86DEFAULT_FILTER = None 87VALID_FILTERS = ('print', 'scan', 'fax', 'pcard', 'copy') 88DEFAULT_BE_FILTER = ('hp',) 89 90pat_deviceuri = re.compile(r"""(.*):/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*)|ip=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[^&]*)|zc=(\S+)|hostname=(\S+))(?:&port=(\d))?""", re.IGNORECASE) 91http_pat_url = re.compile(r"""/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*))&loc=(\S*)""", re.IGNORECASE) 92direct_pat = re.compile(r'direct (.*?) "(.*?)" "(.*?)" "(.*?)"', re.IGNORECASE) 93 94# Pattern to check for ; at end of CTR fields 95# Note: If ; not present, CTR value is invalid 96pat_dynamic_ctr = re.compile(r"""CTR:\d*\s.*;""", re.IGNORECASE) 97 98# Cache for model data 99model_dat = models.ModelData() 100 101ip_pat = re.compile(r"""\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b""", re.IGNORECASE) 102dev_pat = re.compile(r"""/dev/.+""", re.IGNORECASE) 103usb_pat = re.compile(r"""(\d+):(\d+)""", re.IGNORECASE) 104 105 106class Event(object): 107 def __init__(self, device_uri, printer_name, event_code, 108 username=prop.username, job_id=0, title='', 109 timedate=0): 110 111 self.device_uri = to_unicode(device_uri) 112 self.printer_name = to_unicode(printer_name) 113 self.event_code = int(event_code) 114 self.username = to_unicode(username) 115 self.job_id = int(job_id) 116 self.title = to_unicode(title) 117 118 if timedate: 119 self.timedate = float(timedate) 120 else: 121 self.timedate = time.time() 122 123 self.pipe_fmt = "80s80sI32sI80sf" 124 self.dbus_fmt = "ssisisd" 125 126 127 def debug(self): 128 log.debug(" device_uri=%s" % self.device_uri) 129 log.debug(" printer_name=%s" % self.printer_name) 130 log.debug(" event_code=%d" % self.event_code) 131 log.debug(" username=%s" % self.username) 132 log.debug(" job_id=%d" % self.job_id) 133 log.debug(" title=%s" % self.title) 134 log.debug(" timedate=%s" % self.timedate) 135 136 137 def pack_for_pipe(self): 138 return struct.pack(self.pipe_fmt, self.device_uri.encode('utf-8'), self.printer_name.encode('utf-8'), 139 self.event_code, self.username.encode('utf-8'), self.job_id, self.title.encode('utf-8'), 140 self.timedate) 141 142 143 def send_via_pipe(self, fd, recipient='hpssd'): 144 if fd is not None: 145 log.debug("Sending event %d to %s (via pipe %d)..." % (self.event_code, recipient, fd)) 146 try: 147 os.write(fd, self.pack_for_pipe()) 148 return True 149 except OSError: 150 log.debug("Failed.") 151 return False 152 153 154 def send_via_dbus(self, session_bus, interface='com.hplip.StatusService'): 155 if session_bus is not None and dbus_avail: 156 log.debug("Sending event %d to %s (via dbus)..." % (self.event_code, interface)) 157 msg = lowlevel.SignalMessage('/', interface, 'Event') 158 msg.append(signature=self.dbus_fmt, *self.as_tuple()) 159 session_bus.send_message(msg) 160 161 162 def copy(self): 163 return Event(*self.as_tuple()) 164 165 166 def __str__(self): 167 return "<Event('%s', '%s', %d, '%s', %d, '%s', %f)>" % self.as_tuple() 168 169 170 def as_tuple(self): 171 return (self.device_uri, self.printer_name, self.event_code, 172 self.username, self.job_id, self.title, self.timedate) 173 174 175class FaxEvent(Event): 176 def __init__(self, temp_file, event): 177 Event.__init__(self, *event.as_tuple()) 178 self.temp_file = temp_file 179 self.pipe_fmt = "80s80sI32sI80sfs" 180 self.dbus_fmt = "ssisisfs" 181 182 183 def debug(self): 184 log.debug("FAX:") 185 Event.debug(self) 186 log.debug(" temp_file=%s" % self.temp_file) 187 188 189 def __str__(self): 190 return "<FaxEvent('%s', '%s', %d, '%s', %d, '%s', %f, '%s')>" % self.as_tuple() 191 192 193 def as_tuple(self): 194 return (self.device_uri, self.printer_name, self.event_code, 195 self.username, self.job_id, self.title, self.timedate, 196 self.temp_file) 197 198 199 200class DeviceIOEvent(Event): 201 def __init__(self, bytes_written, event): 202 Event.__init__(self, *event.as_tuple()) 203 self.bytes_written = bytes_written 204 self.pipe_fmt = "80s80sI32sI80sfI" 205 self.dbus_fmt = "ssisisfi" 206 207 208 def debug(self): 209 log.debug("DEVIO:") 210 Event.debug(self) 211 log.debug(" bytes_written=%d" % self.bytes_written) 212 213 214 def __str__(self): 215 return "<DeviceIOEvent('%s', '%s', %d, '%s', %d, '%s', %f, '%d')>" % self.as_tuple() 216 217 218 def as_tuple(self): 219 return (self.device_uri, self.printer_name, self.event_code, 220 self.username, self.job_id, self.title, self.timedate, 221 self.bytes_written) 222 223 224# 225# DBus Support 226# 227 228def init_dbus(dbus_loop=None): 229 global dbus_avail 230 service = None 231 session_bus = None 232 233 if not prop.gui_build: 234 dbus_avail = False 235 return dbus_avail, None, None 236 237 if dbus_avail and not dbus_disabled: 238 if os.getuid() == 0: 239 log.debug("Not starting dbus: running as root.") 240 dbus_avail = False 241 return dbus_avail, None, None 242 243 try: 244 if dbus_loop is None: 245 session_bus = dbus.SessionBus() 246 else: 247 session_bus = dbus.SessionBus(dbus_loop) 248 except dbus.exceptions.DBusException as e: 249 if os.getuid() != 0: 250 log.error("Unable to connect to dbus session bus. %s "%e) 251 else: 252 log.debug("Unable to connect to dbus session bus (running as root?). %s "%e) 253 254 dbus_avail = False 255 return dbus_avail, None, None 256 257 try: 258 log.debug("Connecting to com.hplip.StatusService (try #1)...") 259 service = session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService") 260 dbus_avail = True 261 except dbus.exceptions.DBusException as e: 262 try: 263 os.waitpid(-1, os.WNOHANG) 264 except OSError: 265 pass 266 267 path = utils.which('hp-systray') 268 if path: 269 path = os.path.join(path, 'hp-systray') 270 else: 271 path = os.path.join(prop.home_dir, 'systray.py') 272 if not os.path.exists(path): 273 log.warn("Unable to start hp-systray") 274 return False, None, None 275 276 log.debug("Running hp-systray: %s --force-startup" % path) 277 278 os.spawnlp(os.P_NOWAIT, path, 'hp-systray', '--force-startup') 279 280 log.debug("Waiting for hp-systray to start...") 281 time.sleep(1) 282 283 t = 2 284 while True: 285 try: 286 log.debug("Connecting to com.hplip.StatusService (try #%d)..." % t) 287 service = session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService") 288 289 except dbus.exceptions.DBusException as e: 290 log.debug("Unable to connect to dbus. Is hp-systray running?") 291 t += 1 292 293 if t > 5: 294 log.warn("Unable to connect to dbus. Is hp-systray running?") 295 return False, None, None 296 297 time.sleep(1) 298 299 else: 300 log.debug("Connected.") 301 dbus_avail = True 302 break 303 304 return dbus_avail, service, session_bus 305 306 307# 308# Make URI from parameter (bus ID, IP address, etc) 309# 310 311def makeURI(param, port=1): 312 cups_uri, sane_uri, fax_uri = '', '', '' 313 found = False 314 315 if dev_pat.search(param) is not None: # parallel 316 log.debug("Trying parallel with %s" % param) 317 318 result_code, uri = hpmudext.make_par_uri(param) 319 320 if result_code == hpmudext.HPMUD_R_OK and uri: 321 uri = to_string_utf8(uri) 322 log.debug("Found: %s" % uri) 323 found = True 324 cups_uri = uri 325 else: 326 log.debug("Not found.") 327 328 elif usb_pat.search(param) is not None: # USB 329 match_obj = usb_pat.search(param) 330 usb_bus_id = match_obj.group(1) 331 usb_dev_id = match_obj.group(2) 332 333 log.debug("Trying USB with bus=%s dev=%s..." % (usb_bus_id, usb_dev_id)) 334 result_code, uri = hpmudext.make_usb_uri(usb_bus_id, usb_dev_id) 335 336 if result_code == ERROR_SUCCESS and uri: 337 uri = to_string_utf8(uri) 338 log.debug("Found: %s" % uri) 339 found = True 340 cups_uri = uri 341 else: 342 log.debug("Not found.") 343 344 elif ip_pat.search(param) is not None: # IPv4 dotted quad 345 log.debug("Trying IP address %s" % param) 346 347 result_code, uri = hpmudext.make_net_uri(param, port) 348 349 if result_code == hpmudext.HPMUD_R_OK and uri: 350 uri = to_string_utf8(uri) 351 log.debug("Found: %s" % uri) 352 found = True 353 cups_uri = uri 354 else: 355 log.debug("Not found.") 356 357 else: # Try Zeroconf hostname 358 log.debug("Trying ZC hostname %s" % param) 359 360 result_code, uri = hpmudext.make_zc_uri(param, port) 361 362 if result_code == hpmudext.HPMUD_R_OK and uri: 363 uri = to_string_utf8(uri) 364 log.debug("Found: %s" % uri) 365 found = True 366 cups_uri = uri 367 368 else: # Try DNS hostname 369 log.debug("Device not found using mDNS hostname. Trying with DNS hostname %s" % param) 370 371 result_code, uri = hpmudext.make_net_uri(param, port) 372 373 if result_code == hpmudext.HPMUD_R_OK and uri: 374 uri = to_string_utf8(uri) 375 uri = uri.replace("ip=","hostname=") 376 log.debug("Found: %s" % uri) 377 found = True 378 cups_uri = uri 379 else: 380 log.debug("Not found.") 381 382 if not found: 383 log.debug("Trying serial number %s" % param) 384 devices = probeDevices(bus=['usb', 'par']) 385 386 for d in devices: 387 log.debug(d) 388 389 # usb has serial in URI... 390 try: 391 back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ 392 parseDeviceURI(d) 393 except Error: 394 continue 395 396 if bus == 'par': # ...parallel does not. Must get Device ID to obtain it... 397 mq = queryModelByURI(d) 398 399 result_code, device_id = \ 400 hpmudext.open_device(d, mq.get('io-mode', hpmudext.HPMUD_UNI_MODE)) 401 402 if result_code == hpmudext.HPMUD_R_OK: 403 result_code, data = hpmudext.get_device_id(device_id) 404 serial = parseDeviceID(data).get('SN', '') 405 hpmudext.close_device(device_id) 406 407 if serial.lower() == param.lower(): 408 log.debug("Found: %s" % d) 409 found = True 410 cups_uri = d 411 break 412 else: 413 log.debug("Not found.") 414 415 if found: 416 try: 417 mq = queryModelByURI(cups_uri) 418 except Error as e: 419 log.error("Error: %s" % e.msg) 420 cups_uri, sane_uri, fax_uri = '', '', '' 421 else: 422 if mq.get('support-type', SUPPORT_TYPE_NONE) > SUPPORT_TYPE_NONE: 423 if mq.get('scan-type', 0): 424 sane_uri = cups_uri.replace("hp:", "hpaio:") 425 426 if mq.get('fax-type', 0): 427 fax_uri = cups_uri.replace("hp:", "hpfax:") 428 429 else: 430 cups_uri, sane_uri, fax_uri = '', '', '' 431 432 else: 433 scan_uri, fax_uri = '', '' 434 435 if cups_uri: 436 user_conf.set('last_used', 'device_uri', cups_uri) 437 438 return cups_uri, sane_uri, fax_uri 439 440 441# 442# Model Queries 443# 444 445def queryModelByModel(model): 446 model = models.normalizeModelName(model).lower() 447 return model_dat[model] 448 449 450def queryModelByURI(device_uri): 451 try: 452 back_end, is_hp, bus, model, \ 453 serial, dev_file, host, zc, port = \ 454 parseDeviceURI(device_uri) 455 except Error: 456 raise Error(ERROR_INVALID_DEVICE_URI) 457 else: 458 return queryModelByModel(model) 459 460 461# 462# Device Discovery 463# 464 465def probeDevices(bus=DEFAULT_PROBE_BUS, timeout=10, 466 ttl=4, filter=DEFAULT_FILTER, search='', net_search='slp', 467 back_end_filter=('hp',)): 468 469 num_devices, ret_devices = 0, {} 470 471 if search: 472 try: 473 search_pat = re.compile(search, re.IGNORECASE) 474 except: 475 log.error("Invalid search pattern. Search uses standard regular expressions. For more info, see: http://www.amk.ca/python/howto/regex/") 476 search = '' 477 478 for b in bus: 479 log.debug("Probing bus: %s" % b) 480 if b not in VALID_BUSES: 481 log.error("Invalid bus: %s" % b) 482 continue 483 484 if b == 'net': 485 if net_search == 'slp': 486 try: 487 detected_devices = slp.detectNetworkDevices(ttl, timeout) 488 except Error as socket_error: 489 socket.error = socket_error 490 log.error("An error occured during network probe.[%s]"%socket_error) 491 raise ERROR_INTERNAL 492 elif net_search == 'avahi': 493 try: 494 detected_devices = avahi.detectNetworkDevices(ttl, timeout) 495 except Error as socket_error: 496 socket.error = socket_error 497 log.error("An error occured during network probe.[%s]"%socket_error) 498 raise ERROR_INTERNAL 499 else :#if net_search = 'mdns' 500 try: 501 detected_devices = mdns.detectNetworkDevices(ttl, timeout) 502 except Error as socket_error: 503 socket.error = socket_error 504 log.error("An error occured during network probe.[%s]"%socket_error) 505 raise ERROR_INTERNAL 506 507 for ip in detected_devices: 508 update_spinner() 509 hn = detected_devices[ip].get('hn', '?UNKNOWN?') 510 num_devices_on_jd = detected_devices[ip].get('num_devices', 0) 511 num_ports_on_jd = detected_devices[ip].get('num_ports', 1) 512 513 if num_devices_on_jd > 0: 514 for port in range(num_ports_on_jd): 515 dev = detected_devices[ip].get('device%d' % (port+1), '0') 516 517 if dev is not None and dev != '0': 518 device_id = parseDeviceID(dev) 519 model = models.normalizeModelName(device_id.get('MDL', '?UNKNOWN?')) 520 521 if num_ports_on_jd == 1: 522 if net_search == 'slp': 523 device_uri = 'hp:/net/%s?ip=%s' % (model, ip) 524 else: 525 device_uri = 'hp:/net/%s?zc=%s' % (model, hn) 526 else: 527 if net_search == 'slp': 528 device_uri = 'hp:/net/%s?ip=%s&port=%d' % (model, ip, (port + 1)) 529 else: 530 device_uri = 'hp:/net/%s?zc=%s&port=%d' % (model, hn, (port + 1)) 531 532 include = True 533 mq = queryModelByModel(model) 534 535 if not mq: 536 log.debug("Not found.") 537 include = False 538 539 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE: 540 log.debug("Not supported.") 541 include = False 542 543 elif filter not in (None, 'print', 'print-type'): 544 include = __checkFilter(filter, mq) 545 546 if include: 547 ret_devices[device_uri] = (model, model, hn) 548 549 elif b in ('usb', 'par'): 550 if b == 'par': 551 bn = hpmudext.HPMUD_BUS_PARALLEL 552 else: 553 bn = hpmudext.HPMUD_BUS_USB 554 555 result_code, data = hpmudext.probe_devices(bn) 556 if result_code == hpmudext.HPMUD_R_OK: 557 for x in data.splitlines(): 558 m = direct_pat.match(x) 559 560 uri = m.group(1) or '' 561 mdl = m.group(2) or '' 562 desc = m.group(3) or '' 563 devid = m.group(4) or '' 564 565 log.debug(uri) 566 #if("scanjet" in mdl.lower()): 567 # continue # Do not include HP Scanjets 568 569 try: 570 back_end, is_hp, bb, model, serial, dev_file, host, zc, port = \ 571 parseDeviceURI(uri) 572 except Error: 573 continue 574 575 include = True 576 577 if mdl and uri and is_hp: 578 mq = queryModelByModel(model) 579 580 if not mq: 581 log.debug("Not found.") 582 include = False 583 584 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE: 585 log.debug("Not supported.") 586 include = False 587 588 elif filter not in (None, 'print', 'print-type'): 589 include = __checkFilter(filter, mq) 590 591 if include: 592 ret_devices[uri] = (mdl, desc, devid) # model w/ _'s, mdl w/o 593 594 elif b == 'cups': 595 cups_printers = cups.getPrinters() 596 x = len(cups_printers) 597 598 for p in cups_printers: 599 device_uri = p.device_uri 600 log.debug("%s: %s" % (device_uri, p.name)) 601 602 if device_uri != '': 603 try: 604 back_end, is_hp, bs, model, serial, dev_file, host, zc, port = \ 605 parseDeviceURI(device_uri) 606 except Error: 607 log.debug("Unrecognized URI: %s" % device_uri) 608 continue 609 610 if not is_hp: 611 continue 612 613 include = True 614 mq = queryModelByModel(model) 615 616 if not mq: 617 include = False 618 log.debug("Not found.") 619 620 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE: 621 log.debug("Not supported.") 622 include = False 623 624 elif filter not in (None, 'print', 'print-type'): 625 include = __checkFilter(filter, mq) 626 627 if include: 628 ret_devices[device_uri] = (model, model, '') 629 630 probed_devices = {} 631 for uri in ret_devices: 632 num_devices += 1 633 mdl, model, devid_or_hn = ret_devices[uri] 634 635 include = True 636 if search: 637 match_obj = search_pat.search("%s %s %s %s" % (mdl, model, devid_or_hn, uri)) 638 639 if match_obj is None: 640 log.debug("%s %s %s %s: Does not match search '%s'." % (mdl, model, devid_or_hn, uri, search)) 641 include = False 642 643 if include: 644 probed_devices[uri] = ret_devices[uri] 645 646 cleanup_spinner() 647 return probed_devices 648 649# 650# CUPS Devices 651# 652 653def getSupportedCUPSDevices(back_end_filter=['hp'], filter=DEFAULT_FILTER): 654 devices = {} 655 printers = cups.getPrinters() 656 log.debug(printers) 657 658 for p in printers: 659 try: 660 back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ 661 parseDeviceURI(p.device_uri) 662 663 except Error: 664 continue 665 666 if (back_end_filter == '*' or back_end in back_end_filter or \ 667 ('hpaio' in back_end_filter and back_end == 'hp')) and \ 668 model and is_hp: 669 670 include = True 671 mq = queryModelByModel(model) 672 673 if not mq: 674 log.debug("Not found.") 675 include = False 676 677 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE: 678 log.debug("Not supported.") 679 include = False 680 681 elif filter not in (None, 'print', 'print-type'): 682 include = __checkFilter(filter, mq) 683 684 if include: 685 if 'hpaio' in back_end_filter: 686 d = p.device_uri.replace('hp:', 'hpaio:') 687 else: 688 d = p.device_uri 689 690 try: 691 devices[d] 692 except KeyError: 693 devices[d] = [p.name] 694 else: 695 devices[d].append(p.name) 696 697 return devices # { 'device_uri' : [ CUPS printer list ], ... } 698 699 700def getSupportedCUPSPrinters(back_end_filter=['hp'], filter=DEFAULT_FILTER): 701 printer_list = [] 702 printers = cups.getPrinters() 703 704 for p in printers: 705 try: 706 back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ 707 parseDeviceURI(p.device_uri) 708 709 except Error: 710 continue 711 712 if (back_end_filter == '*' or back_end in back_end_filter) and model and is_hp: 713 include = True 714 mq = queryModelByModel(model) 715 716 if not mq: 717 log.debug("Not found.") 718 include = False 719 720 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE: 721 log.debug("Not supported.") 722 include = False 723 724 elif filter not in (None, 'print', 'print-type'): 725 include = __checkFilter(filter, mq) 726 727 if include: 728 printer_list.append(p) 729 730 731 return printer_list # [ cupsext.Printer, ... ] 732 733 734def getSupportedCUPSPrinterNames(back_end_filter=['hp'], filter=DEFAULT_FILTER): 735 printers = getSupportedCUPSPrinters(back_end_filter, filter) 736 return [p.name for p in printers] 737 738 739def getDeviceURIByPrinterName(printer_name, scan_uri_flag=False): 740 if printer_name is None: 741 return None 742 743 device_uri = None 744 printers = cups.getPrinters() 745 746 for p in printers: 747 try: 748 back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ 749 parseDeviceURI(p.device_uri) 750 751 except Error: 752 continue 753 754 if is_hp and p.name == printer_name: 755 if scan_uri_flag: 756 device_uri = p.device_uri.replace('hp:', 'hpaio:') 757 else: 758 device_uri = p.device_uri 759 break 760 761 return device_uri 762 763# 764# IEEE-1284 Device ID parsing 765# 766 767def parseDeviceID(device_id): 768 d= {} 769 x = [y.strip() for y in device_id.strip().split(';') if y] 770 771 for z in x: 772 y = z.split(':') 773 try: 774 d.setdefault(y[0].strip(), y[1]) 775 except IndexError: 776 d.setdefault(y[0].strip(), None) 777 778 d.setdefault('MDL', '') 779 d.setdefault('SN', '') 780 781 if 'MODEL' in d: 782 d['MDL'] = d['MODEL'] 783 del d['MODEL'] 784 785 if 'SERIAL' in d: 786 d['SN'] = d['SERIAL'] 787 del d['SERIAL'] 788 789 elif 'SERN' in d: 790 d['SN'] = d['SERN'] 791 del d['SERN'] 792 793 if d['SN'].startswith('X'): 794 d['SN'] = '' 795 796 return d 797 798# 799# IEEE-1284 Device ID Dynamic Counter Parsing 800# 801 802def parseDynamicCounter(ctr_field, convert_to_int=True): 803 counter, value = ctr_field.split(' ') 804 try: 805 counter = int(utils.xlstrip(str(counter), '0') or '0') 806 807 if convert_to_int: 808 value = int(utils.xlstrip(str(value), '0') or '0') 809 except ValueError: 810 if convert_to_int: 811 counter, value = 0, 0 812 else: 813 counter, value = 0, '' 814 815 return counter, value 816 817 818# 819# Parse Device URI Strings 820# 821 822def parseDeviceURI(device_uri): 823 m = pat_deviceuri.match(device_uri) 824 if m is None: 825 log.debug("Device URI %s is invalid/unknown" % device_uri) 826 raise Error(ERROR_INVALID_DEVICE_URI) 827 828 back_end = m.group(1).lower() or '' 829 is_hp = (back_end in ('hp', 'hpfax', 'hpaio')) 830 bus = m.group(2).lower() or '' 831 832 if bus not in ('usb', 'net', 'bt', 'fw', 'par'): 833 log.debug("Device URI %s is invalid/unknown" % device_uri) 834 raise Error(ERROR_INVALID_DEVICE_URI) 835 836 model = m.group(3) or '' 837 serial = m.group(4) or '' 838 dev_file = m.group(5) or '' 839 host = m.group(6) or '' 840 zc = m.group(7) or '' 841 hostname = m.group(8) or '' 842 843 if hostname: 844 host = hostname 845 elif zc: 846 host = zc 847 848 port = m.group(8) or 1 849 850 if bus == 'net': 851 try: 852 port = int(port) 853 except (ValueError, TypeError): 854 port = 1 855 856 if port == 0: 857 port = 1 858 859 log.debug("%s: back_end:%s is_hp:%s bus:%s model:%s serial:%s dev_file:%s host:%s zc:%s port:%s" % 860 (device_uri, back_end, is_hp, bus, model, serial, dev_file, host, zc, port)) 861 862 return back_end, is_hp, bus, model, serial, dev_file, host, zc, port 863 864 865def isLocal(bus): 866 return bus in ('par', 'usb', 'fw', 'bt') 867 868 869def isNetwork(bus): 870 return bus in ('net',) 871 872 873# 874# Misc 875# 876 877def __checkFilter(filter, mq): 878 for f, p in list(filter.items()): 879 if f is not None: 880 op, val = p 881 if not op(mq[f], val): 882 return False 883 884 return True 885 886 887def validateBusList(bus, allow_cups=True): 888 for b in bus: 889 if allow_cups: 890 vb = VALID_BUSES 891 else: 892 vb = VALID_BUSES_WO_CUPS 893 894 if b not in vb: 895 log.error("Invalid bus name: %s" %b) 896 return False 897 898 return True 899 900 901def validateFilterList(filter): 902 if filter is None: 903 return True 904 905 for f in filter: 906 if f not in VALID_FILTERS: 907 log.error("Invalid term '%s' in filter list" % f) 908 return False 909 910 return True 911 912 913AGENT_types = { AGENT_TYPE_NONE : 'invalid', 914 AGENT_TYPE_BLACK : 'black', 915 AGENT_TYPE_BLACK_B8800 : 'black', 916 AGENT_TYPE_CMY : 'cmy', 917 AGENT_TYPE_KCM : 'kcm', 918 AGENT_TYPE_CYAN : 'cyan', 919 AGENT_TYPE_MAGENTA : 'magenta', 920 AGENT_TYPE_YELLOW : 'yellow', 921 AGENT_TYPE_CYAN_LOW : 'photo_cyan', 922 AGENT_TYPE_MAGENTA_LOW : 'photo_magenta', 923 AGENT_TYPE_YELLOW_LOW : 'photo_yellow', 924 AGENT_TYPE_GGK : 'photo_gray', 925 AGENT_TYPE_BLUE : 'photo_blue', 926 AGENT_TYPE_KCMY_CM : 'kcmy_cm', 927 AGENT_TYPE_LC_LM : 'photo_cyan_and_photo_magenta', 928 #AGENT_TYPE_Y_M : 'yellow_and_magenta', 929 #AGENT_TYPE_C_K : 'cyan_and_black', 930 AGENT_TYPE_LG_PK : 'light_gray_and_photo_black', 931 AGENT_TYPE_LG : 'light_gray', 932 AGENT_TYPE_G : 'medium_gray', 933 AGENT_TYPE_PG : 'photo_gray', 934 AGENT_TYPE_C_M : 'cyan_and_magenta', 935 AGENT_TYPE_K_Y : 'black_and_yellow', 936 AGENT_TYPE_PHOTO_BLACK : 'photo_black', 937 AGENT_TYPE_MATTE_BLACK : 'matte_black', 938 AGENT_TYPE_UNSPECIFIED : 'unspecified', # Kind=5,6 939 } 940 941AGENT_kinds = {AGENT_KIND_NONE : 'invalid', 942 AGENT_KIND_HEAD : 'head', 943 AGENT_KIND_SUPPLY : 'supply', 944 AGENT_KIND_HEAD_AND_SUPPLY : 'cartridge', 945 AGENT_KIND_TONER_CARTRIDGE : 'toner', 946 AGENT_KIND_MAINT_KIT : 'maint_kit', # fuser 947 AGENT_KIND_ADF_KIT : 'adf_kit', 948 AGENT_KIND_DRUM_KIT : 'drum_kit', 949 AGENT_KIND_TRANSFER_KIT : 'transfer_kit', 950 AGENT_KIND_INT_BATTERY : 'battery', 951 AGENT_KIND_UNKNOWN : 'unknown', 952 } 953 954AGENT_healths = {AGENT_HEALTH_OK : 'ok', 955 AGENT_HEALTH_MISINSTALLED : 'misinstalled', # supply/cart 956 #AGENT_HEALTH_FAIR_MODERATE : '', 957 AGENT_HEALTH_INCORRECT : 'incorrect', 958 AGENT_HEALTH_FAILED : 'failed', 959 AGENT_HEALTH_OVERTEMP : 'overtemp', # battery 960 AGENT_HEALTH_CHARGING : 'charging', # battery 961 AGENT_HEALTH_DISCHARGING : 'discharging', # battery 962 AGENT_HEALTH_UNKNOWN : 'unknown', 963 } 964 965 966AGENT_levels = {AGENT_LEVEL_TRIGGER_MAY_BE_LOW : 'low', 967 AGENT_LEVEL_TRIGGER_PROBABLY_OUT : 'low', 968 AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT : 'out', 969 } 970 971 972 973 974# **************************************************************************** # 975 976string_cache = {} 977 978class Device(object): 979 def __init__(self, device_uri, printer_name=None, 980 service=None, callback=None, disable_dbus=False): 981 982 log.debug("Device URI: %s" % device_uri) 983 log.debug("Printer: %s" % printer_name) 984 985 global dbus_disabled 986 dbus_disabled = disable_dbus 987 988 if not disable_dbus: 989 if service is None: 990 self.dbus_avail, self.service, session_bus = init_dbus() 991 else: 992 self.dbus_avail = True 993 self.service = service 994 else: 995 self.dbus_avail = False 996 self.service = None 997 998 self.last_event = None # Used in devmgr if dbus is disabled 999 1000 printers = cups.getPrinters() 1001 1002 if device_uri is None and printer_name is not None: 1003 for p in printers: 1004 if p.name.lower() == printer_name.lower(): 1005 device_uri = p.device_uri 1006 log.debug("Device URI: %s" % device_uri) 1007 break 1008 else: 1009 raise Error(ERROR_DEVICE_NOT_FOUND) 1010 1011 self.device_uri = device_uri 1012 self.callback = callback 1013 self.device_type = DEVICE_TYPE_UNKNOWN 1014 1015 if self.device_uri is None: 1016 raise Error(ERROR_DEVICE_NOT_FOUND) 1017 1018 if self.device_uri.startswith('hp:'): 1019 self.device_type = DEVICE_TYPE_PRINTER 1020 1021 elif self.device_uri.startswith('hpaio:'): 1022 self.device_type = DEVICE_TYPE_SCANNER 1023 1024 elif self.device_uri.startswith('hpfax:'): 1025 self.device_type = DEVICE_TYPE_FAX 1026 1027 try: 1028 self.back_end, self.is_hp, self.bus, self.model, \ 1029 self.serial, self.dev_file, self.host, self.zc, self.port = \ 1030 parseDeviceURI(self.device_uri) 1031 except Error: 1032 self.io_state = IO_STATE_NON_HP 1033 raise Error(ERROR_INVALID_DEVICE_URI) 1034 1035 log.debug("URI: backend=%s, is_hp=%s, bus=%s, model=%s, serial=%s, dev=%s, host=%s, port=%d" % \ 1036 (self.back_end, self.is_hp, self.bus, self.model, self.serial, self.dev_file, self.host, self.port)) 1037 1038 self.model_ui = models.normalizeModelUIName(self.model) 1039 self.model = models.normalizeModelName(self.model) 1040 1041 log.debug("Model/UI model: %s/%s" % (self.model, self.model_ui)) 1042 1043 if self.bus == 'net': 1044 self.http_host = self.host 1045 else: 1046 self.http_host = 'localhost' 1047 1048 # TODO: 1049 #service.setAlertsEx(self.hpssd_sock) 1050 1051 self.mq = {} # Model query 1052 self.dq = {} # Device query 1053 self.icon = "default_printer" 1054 self.cups_printers = [] 1055 self.channels = {} # { 'SERVICENAME' : channel_id, ... } 1056 self.device_id = -1 1057 self.r_values = None # ( r_value, r_value_str, rg, rr ) 1058 self.deviceID = '' 1059 self.panel_check = True 1060 self.io_state = IO_STATE_HP_READY 1061 self.is_local = isLocal(self.bus) 1062 self.hist = [] 1063 1064 self.supported = False 1065 1066 self.queryModel() 1067 if not self.supported: 1068 log.error("Unsupported model: %s" % self.model) 1069 self.error_code = STATUS_DEVICE_UNSUPPORTED 1070 self.sendEvent(self.error_code) 1071 else: 1072 self.supported = True 1073 1074 1075 self.mq.update({'model' : self.model, 1076 'model-ui' : self.model_ui}) 1077 1078 self.error_state = ERROR_STATE_ERROR 1079 self.device_state = DEVICE_STATE_NOT_FOUND 1080 self.status_code = EVENT_ERROR_DEVICE_NOT_FOUND 1081 1082 self.updateCUPSPrinters() 1083 1084 if self.mq.get('fax-type', FAX_TYPE_NONE) != FAX_TYPE_NONE: 1085 self.dq.update({ 'fax-uri' : self.device_uri.replace('hp:/', 'hpfax:/').replace('hpaio:/', 'hpfax:/')}) 1086 1087 if self.mq.get('scan-type', SCAN_TYPE_NONE) != SCAN_TYPE_NONE: 1088 self.dq.update({ 'scan-uri' : self.device_uri.replace('hp:/', 'hpaio:/').replace('hpfax:/', 'hpaio:/')}) 1089 1090 self.dq.update({ 1091 'back-end' : self.back_end, 1092 'is-hp' : self.is_hp, 1093 'serial' : self.serial, 1094 'dev-file' : self.dev_file, 1095 'host' : self.host, 1096 'port' : self.port, 1097 'cups-printers' : self.cups_printers, 1098 'status-code' : self.status_code, 1099 'status-desc' : '', 1100 'deviceid' : '', 1101 'panel' : 0, 1102 'panel-line1' : '', 1103 'panel-line2' : '', 1104 'device-state' : self.device_state, 1105 'error-state' : self.error_state, 1106 'device-uri' : self.device_uri, 1107 'cups-uri' : self.device_uri.replace('hpfax:/', 'hp:/').replace('hpaio:/', 'hp:/'), 1108 }) 1109 1110 self.device_vars = { 1111 'URI' : self.device_uri, 1112 'DEVICE_URI' : self.device_uri, 1113 'SCAN_URI' : self.device_uri.replace('hp:', 'hpaio:'), 1114 'SANE_URI' : self.device_uri.replace('hp:', 'hpaio:'), 1115 'FAX_URI' : self.device_uri.replace('hp:', 'hpfax:'), 1116 'PRINTER' : self.first_cups_printer, 1117 'HOME' : prop.home_dir, 1118 } 1119 1120 1121 1122 1123 def sendEvent(self, event_code, printer_name='', job_id=0, title=''): 1124 if self.dbus_avail and self.service is not None: 1125 try: 1126 log.debug("Sending event %d to hpssd..." % event_code) 1127 self.service.SendEvent(self.device_uri, printer_name, event_code, prop.username, job_id, title) 1128 except dbus.exceptions.DBusException as e: 1129 log.debug("dbus call to SendEvent() failed.") 1130 1131 1132 def quit(self): 1133 pass 1134 1135 1136 def queryModel(self): 1137 if not self.mq: 1138 self.mq = queryModelByURI(self.device_uri) 1139 1140 self.supported = bool(self.mq) 1141 1142 if self.supported: 1143 for m in self.mq: 1144 self.__dict__[m.replace('-','_')] = self.mq[m] 1145 1146 1147 def queryString(self, string_id): 1148 return queryString(string_id) 1149 1150 1151 def open(self, open_for_printing=False): 1152 if self.supported and self.io_state in (IO_STATE_HP_READY, IO_STATE_HP_NOT_AVAIL): 1153 prev_device_state = self.device_state 1154 self.io_state = IO_STATE_HP_NOT_AVAIL 1155 self.device_state = DEVICE_STATE_NOT_FOUND 1156 self.error_state = ERROR_STATE_ERROR 1157 self.status_code = EVENT_ERROR_DEVICE_NOT_FOUND 1158 self.device_id = -1 1159 self.open_for_printing = open_for_printing 1160 1161 if open_for_printing: 1162 log.debug("Opening device: %s (for printing)" % self.device_uri) 1163 self.io_mode = self.mq.get('io-mode', hpmudext.HPMUD_UNI_MODE) 1164 else: 1165 log.debug("Opening device: %s (not for printing)" % self.device_uri) 1166 self.io_mode = self.mq.get('io-mfp-mode', hpmudext.HPMUD_UNI_MODE) 1167 1168 log.debug("I/O mode=%d" % self.io_mode) 1169 result_code, self.device_id = \ 1170 hpmudext.open_device(self.device_uri, self.io_mode) 1171 1172 if result_code != hpmudext.HPMUD_R_OK: 1173 self.error_state = ERROR_STATE_ERROR 1174 self.error_code = result_code+ERROR_CODE_BASE 1175 self.sendEvent(self.error_code) 1176 1177 if result_code == hpmudext.HPMUD_R_DEVICE_BUSY: 1178 log.error("Device busy: %s" % self.device_uri) 1179 else: 1180 log.error("Unable to communicate with device (code=%d): %s" % (result_code, self.device_uri)) 1181 1182 self.last_event = Event(self.device_uri, '', EVENT_ERROR_DEVICE_NOT_FOUND, 1183 prop.username, 0, '', time.time()) 1184 1185 raise Error(ERROR_DEVICE_NOT_FOUND) 1186 1187 else: 1188 log.debug("device-id=%d" % self.device_id) 1189 self.io_state = IO_STATE_HP_OPEN 1190 self.error_state = ERROR_STATE_CLEAR 1191 log.debug("Opened device: %s (backend=%s, is_hp=%s, bus=%s, model=%s, dev=%s, serial=%s, host=%s, port=%d)" % 1192 (self.back_end, self.device_uri, self.is_hp, self.bus, self.model, 1193 self.dev_file, self.serial, self.host, self.port)) 1194 1195 if prev_device_state == DEVICE_STATE_NOT_FOUND: 1196 self.device_state = DEVICE_STATE_JUST_FOUND 1197 else: 1198 self.device_state = DEVICE_STATE_FOUND 1199 1200 self.getDeviceID() 1201 self.getSerialNumber() 1202 return self.device_id 1203 1204 1205 def close(self): 1206 if self.io_state == IO_STATE_HP_OPEN: 1207 log.debug("Closing device...") 1208 1209 if len(self.channels) > 0: 1210 1211 for c in list(self.channels.keys()): 1212 self.__closeChannel(c) 1213 1214 result_code = hpmudext.close_device(self.device_id) 1215 log.debug("Result-code = %d" % result_code) 1216 1217 self.channels.clear() 1218 self.io_state = IO_STATE_HP_READY 1219 1220 1221 def __openChannel(self, service_name): 1222 try: 1223 if self.io_state == IO_STATE_HP_OPEN: 1224 if service_name == hpmudext.HPMUD_S_PRINT_CHANNEL and not self.open_for_printing: 1225 self.close() 1226 self.open(True) 1227 elif service_name != hpmudext.HPMUD_S_PRINT_CHANNEL and self.open_for_printing: 1228 self.close() 1229 self.open(False) 1230 else: 1231 self.open(service_name == hpmudext.HPMUD_S_PRINT_CHANNEL) 1232 except: 1233 log.error("unable to open channel") 1234 return -1 1235 1236 #if not self.mq['io-mode'] == IO_MODE_UNI: 1237 if 1: 1238 service_name = service_name.upper() 1239 1240 if service_name not in self.channels: 1241 log.debug("Opening %s channel..." % service_name) 1242 1243 result_code, channel_id = hpmudext.open_channel(self.device_id, service_name) 1244 1245 self.channels[service_name] = channel_id 1246 log.debug("channel-id=%d" % channel_id) 1247 return channel_id 1248 else: 1249 return self.channels[service_name] 1250 else: 1251 return -1 1252 1253 1254 def openChannel(self, service_name): 1255 return self.__openChannel(service_name) 1256 1257 def openPrint(self): 1258 return self.__openChannel(hpmudext.HPMUD_S_PRINT_CHANNEL) 1259 1260 def openFax(self): 1261 return self.__openChannel(hpmudext.HPMUD_S_FAX_SEND_CHANNEL) 1262 1263 def openPCard(self): 1264 return self.__openChannel(hpmudext.HPMUD_S_MEMORY_CARD_CHANNEL) 1265 1266 def openEWS(self): 1267 return self.__openChannel(hpmudext.HPMUD_S_EWS_CHANNEL) 1268 1269 def openEWS_LEDM(self): 1270 return self.__openChannel(hpmudext.HPMUD_S_EWS_LEDM_CHANNEL) 1271 1272 def openLEDM(self): 1273 return self.__openChannel(hpmudext.HPMUD_S_LEDM_SCAN) 1274 1275 def openMarvell_EWS(self): 1276 return self.__openChannel(hpmudext.HPMUD_S_MARVELL_EWS_CHANNEL) 1277 1278 def closePrint(self): 1279 return self.__closeChannel(hpmudext.HPMUD_S_PRINT_CHANNEL) 1280 1281 def closePCard(self): 1282 return self.__closeChannel(hpmudext.HPMUD_S_MEMORY_CARD_CHANNEL) 1283 1284 def closeFax(self): 1285 return self.__closeChannel(hpmudext.HPMUD_S_FAX_SEND_CHANNEL) 1286 1287 def openPML(self): 1288 return self.__openChannel(hpmudext.HPMUD_S_PML_CHANNEL) 1289 1290 def openWifiConfig(self): 1291 return self.__openChannel(hpmudext.HPMUD_S_WIFI_CHANNEL) 1292 1293 def closePML(self): 1294 return self.__closeChannel(hpmudext.HPMUD_S_PML_CHANNEL) 1295 1296 def closeEWS(self): 1297 return self.__closeChannel(hpmudext.HPMUD_S_EWS_CHANNEL) 1298 1299 def closeEWS_LEDM(self): 1300 return self.__closeChannel(hpmudext.HPMUD_S_EWS_LEDM_CHANNEL) 1301 1302 def closeLEDM(self): 1303 return self.__closeChannel(hpmudext.HPMUD_S_LEDM_SCAN) 1304 1305 def closeMarvell_EWS(self): 1306 return self.__closeChannel(hpmudext.HPMUD_S_MARVELL_EWS_CHANNEL) 1307 1308 def openCfgUpload(self): 1309 return self.__openChannel(hpmudext.HPMUD_S_CONFIG_UPLOAD_CHANNEL) 1310 1311 def closeCfgUpload(self): 1312 return self.__closeChannel(hpmudext.HPMUD_S_CONFIG_UPLOAD_CHANNEL) 1313 1314 def openCfgDownload(self): 1315 return self.__openChannel(hpmudext.HPMUD_S_CONFIG_DOWNLOAD_CHANNEL) 1316 1317 def closeCfgDownload(self): 1318 return self.__closeChannel(hpmudext.HPMUD_S_CONFIG_DOWNLOAD_CHANNEL) 1319 1320 def openSoapFax(self): 1321 return self.__openChannel(hpmudext.HPMUD_S_SOAP_FAX) 1322 1323 def openMarvellFax(self): 1324 return self.__openChannel(hpmudext.HPMUD_S_MARVELL_FAX_CHANNEL) 1325 1326 def closeSoapFax(self): 1327 return self.__closeChannel(hpmudext.HPMUD_S_SOAP_FAX) 1328 1329 def closeMarvellFax(self): 1330 return self.__closeChannel(hpmudext.HPMUD_S_MARVELL_FAX_CHANNEL) 1331 1332 def closeWifiConfig(self): 1333 return self.__closeChannel(hpmudext.HPMUD_S_WIFI_CHANNEL) 1334 1335 def __closeChannel(self, service_name): 1336 #if not self.mq['io-mode'] == IO_MODE_UNI and \ 1337 if self.io_state == IO_STATE_HP_OPEN: 1338 1339 service_name = service_name.upper() 1340 1341 if service_name in self.channels: 1342 log.debug("Closing %s channel..." % service_name) 1343 1344 result_code = hpmudext.close_channel(self.device_id, 1345 self.channels[service_name]) 1346 1347 del self.channels[service_name] 1348 1349 1350 def closeChannel(self, service_name): 1351 return self.__closeChannel(service_name) 1352 1353 1354 def getDeviceID(self): 1355 needs_close = False 1356 self.raw_deviceID = '' 1357 self.deviceID = {} 1358 1359 if self.io_state != IO_STATE_HP_OPEN: 1360 try: 1361 self.open() 1362 except: 1363 return -1 1364 needs_close = True 1365 1366 result_code, data = hpmudext.get_device_id(self.device_id) 1367 1368 if result_code == hpmudext.HPMUD_R_OK: 1369 self.raw_deviceID = data 1370 self.deviceID = parseDeviceID(data) 1371 1372 if needs_close: 1373 self.close() 1374 1375 return self.deviceID 1376 1377 1378 def getSerialNumber(self): 1379 if self.serial: 1380 return 1381 1382 try: 1383 self.serial = self.deviceID['SN'] 1384 except KeyError: 1385 pass 1386 else: 1387 if self.serial: 1388 return 1389 1390 if self.mq.get('status-type', STATUS_TYPE_NONE) != STATUS_TYPE_NONE: # and \ 1391 #not self.mq.get('io-mode', IO_MODE_UNI) == IO_MODE_UNI: 1392 1393 try: 1394 try: 1395 error_code, self.serial = self.getPML(pml.OID_SERIAL_NUMBER) 1396 except Error: 1397 self.serial = '' 1398 finally: 1399 self.closePML() 1400 1401 if self.serial is None: 1402 self.serial = '' 1403 1404 1405 def getThreeBitStatus(self): 1406 pass 1407 1408 1409 def getStatusFromDeviceID(self): 1410 self.getDeviceID() 1411 return status.parseStatus(parseDeviceID(self.raw_deviceID)) 1412 1413 1414 def __parseRValues(self, r_value): 1415 r_value_str = str(r_value) 1416 r_value_str = ''.join(['0'*(9 - len(r_value_str)), r_value_str]) 1417 rg, rr = r_value_str[:3], r_value_str[3:] 1418 r_value = int(rr) 1419 self.r_values = r_value, r_value_str, rg, rr 1420 return r_value, r_value_str, rg, rr 1421 1422 1423 def getRValues(self, r_type, status_type, dynamic_counters): 1424 r_value, r_value_str, rg, rr = 0, '000000000', '000', '000000' 1425 1426 if r_type > 0 and \ 1427 dynamic_counters != STATUS_DYNAMIC_COUNTERS_NONE: 1428 1429 if self.r_values is None: 1430 if self.dbus_avail: 1431 try: 1432 r_value = int(self.service.GetCachedIntValue(self.device_uri, 'r_value')) 1433 except dbus.exceptions.DBusException as e: 1434 log.debug("dbus call to GetCachedIntValue() failed.") 1435 r_value = -1 1436 1437 if r_value != -1: 1438 log.debug("r_value=%d" % r_value) 1439 r_value, r_value_str, rg, rr = self.__parseRValues(r_value) 1440 1441 return r_value, r_value_str, rg, rr 1442 1443 if self.r_values is None: 1444 1445 if status_type == STATUS_TYPE_S and \ 1446 self.is_local and \ 1447 dynamic_counters != STATUS_DYNAMIC_COUNTERS_PML_SNMP: 1448 1449 try: 1450 try: 1451 r_value = self.getDynamicCounter(140) 1452 1453 if r_value is not None: 1454 log.debug("r_value=%d" % r_value) 1455 r_value, r_value_str, rg, rr = self.__parseRValues(r_value) 1456 1457 if self.dbus_avail: 1458 try: 1459 self.service.SetCachedIntValue(self.device_uri, 'r_value', r_value) 1460 except dbus.exceptions.DBusException as e: 1461 log.debug("dbus call to SetCachedIntValue() failed.") 1462 else: 1463 log.error("Error attempting to read r-value (2).") 1464 r_value = 0 1465 except Error: 1466 log.error("Error attempting to read r-value (1).") 1467 r_value = 0 1468 finally: 1469 self.closePrint() 1470 1471 1472 elif (status_type == STATUS_TYPE_S and 1473 dynamic_counters == STATUS_DYNAMIC_COUNTERS_PCL and 1474 not self.is_local) or \ 1475 dynamic_counters == STATUS_DYNAMIC_COUNTERS_PML_SNMP: 1476 1477 try: 1478 result_code, r_value = self.getPML(pml.OID_R_SETTING) 1479 1480 if r_value is not None: 1481 log.debug("r_value=%d" % r_value) 1482 r_value, r_value_str, rg, rr = self.__parseRValues(r_value) 1483 1484 if self.dbus_avail: 1485 try: 1486 self.service.SetCachedIntValue(self.device_uri, 'r_value', r_value) 1487 except dbus.exceptions.DBusException as e: 1488 log.debug("dbus call to SetCachedIntValue() failed.") 1489 1490 else: 1491 r_value = 0 1492 1493 finally: 1494 self.closePML() 1495 1496 else: 1497 r_value, r_value_str, rg, rr = self.r_values 1498 1499 return r_value, r_value_str, rg, rr 1500 1501 1502 def __queryFax(self, quick=False, reread_cups_printers=False): 1503 io_mode = self.mq.get('io-mode', IO_MODE_UNI) 1504 self.status_code = STATUS_PRINTER_IDLE 1505 1506 if io_mode != IO_MODE_UNI: 1507 1508 if self.device_state != DEVICE_STATE_NOT_FOUND: 1509 if self.tech_type in (TECH_TYPE_MONO_INK, TECH_TYPE_COLOR_INK): 1510 try: 1511 self.getDeviceID() 1512 except Error as e: 1513 log.error("Error getting device ID.") 1514 self.last_event = Event(self.device_uri, '', ERROR_DEVICE_IO_ERROR, 1515 prop.username, 0, '', time.time()) 1516 1517 raise Error(ERROR_DEVICE_IO_ERROR) 1518 1519 status_desc = self.queryString(self.status_code) 1520 1521 self.dq.update({ 1522 'serial' : self.serial, 1523 'cups-printers' : self.cups_printers, 1524 'status-code' : self.status_code, 1525 'status-desc' : status_desc, 1526 'deviceid' : self.raw_deviceID, 1527 'panel' : 0, 1528 'panel-line1' : '', 1529 'panel-line2' : '', 1530 'device-state' : self.device_state, 1531 'error-state' : self.error_state, 1532 }) 1533 1534 1535 log.debug("Fax activity check...") 1536 1537 tx_active, rx_active = status.getFaxStatus(self) 1538 1539 if tx_active: 1540 self.status_code = STATUS_FAX_TX_ACTIVE 1541 elif rx_active: 1542 self.status_code = STATUS_FAX_RX_ACTIVE 1543 1544 self.error_state = STATUS_TO_ERROR_STATE_MAP.get(self.status_code, ERROR_STATE_CLEAR) 1545 self.error_code = self.status_code 1546 self.sendEvent(self.error_code) 1547 1548 try: 1549 self.dq.update({'status-desc' : self.queryString(self.status_code), 1550 'error-state' : self.error_state, 1551 }) 1552 1553 except (KeyError, Error): 1554 self.dq.update({'status-desc' : '', 1555 'error-state' : ERROR_STATE_CLEAR, 1556 }) 1557 1558 1559 if self.panel_check: 1560 self.panel_check = bool(self.mq.get('panel-check-type', 0)) 1561 1562 status_type = self.mq.get('status-type', STATUS_TYPE_NONE) 1563 if self.panel_check and \ 1564 status_type in (STATUS_TYPE_LJ, STATUS_TYPE_S, STATUS_TYPE_VSTATUS) and \ 1565 io_mode != IO_MODE_UNI: 1566 1567 log.debug("Panel check...") 1568 try: 1569 self.panel_check, line1, line2 = status.PanelCheck(self) 1570 finally: 1571 self.closePML() 1572 1573 self.dq.update({'panel': int(self.panel_check), 1574 'panel-line1': line1, 1575 'panel-line2': line2,}) 1576 1577 if not quick and reread_cups_printers: 1578 self.updateCUPSPrinters() 1579 1580 for d in self.dq: 1581 self.__dict__[d.replace('-','_')] = self.dq[d] 1582 1583 self.last_event = Event(self.device_uri, '', self.status_code, prop.username, 0, '', time.time()) 1584 1585 log.debug(self.dq) 1586 1587 1588 1589 def updateCUPSPrinters(self): 1590 self.cups_printers = [] 1591 log.debug("Re-reading CUPS printer queue information.") 1592 printers = cups.getPrinters() 1593 for p in printers: 1594 if self.device_uri == p.device_uri: 1595 self.cups_printers.append(p.name) 1596 self.state = p.state # ? 1597 1598 if self.io_state == IO_STATE_NON_HP: 1599 self.model = p.makemodel.split(',')[0] 1600 1601 self.dq.update({'cups-printers' : self.cups_printers}) 1602 1603 try: 1604 self.first_cups_printer = self.cups_printers[0] 1605 except IndexError: 1606 self.first_cups_printer = '' 1607 1608 1609 1610 1611 def queryDevice(self, quick=False, reread_cups_printers=False): 1612 if not self.supported: 1613 self.dq = {} 1614 1615 self.last_event = Event(self.device_uri, '', STATUS_DEVICE_UNSUPPORTED, 1616 prop.username, 0, '', time.time()) 1617 1618 return 1619 1620 if self.device_type == DEVICE_TYPE_FAX: 1621 return self.__queryFax(quick, reread_cups_printers) 1622 1623 r_type = self.mq.get('r-type', 0) 1624 tech_type = self.mq.get('tech-type', TECH_TYPE_NONE) 1625 status_type = self.mq.get('status-type', STATUS_TYPE_NONE) 1626 battery_check = self.mq.get('status-battery-check', STATUS_BATTERY_CHECK_NONE) 1627 dynamic_counters = self.mq.get('status-dynamic-counters', STATUS_DYNAMIC_COUNTERS_NONE) 1628 io_mode = self.mq.get('io-mode', IO_MODE_UNI) 1629 io_mfp_mode = self.mq.get('io-mfp-mode', IO_MODE_UNI) 1630 status_code = STATUS_UNKNOWN 1631 1632 # Turn off status if local connection and bi-di not avail. 1633 #if io_mode == IO_MODE_UNI and self.back_end != 'net': 1634 # status_type = STATUS_TYPE_NONE 1635 1636 agents = [] 1637 1638 if self.device_state != DEVICE_STATE_NOT_FOUND: 1639 if self.tech_type in (TECH_TYPE_MONO_INK, TECH_TYPE_COLOR_INK): 1640 try: 1641 self.getDeviceID() 1642 except Error as e: 1643 log.error("Error getting device ID.") 1644 self.last_event = Event(self.device_uri, '', ERROR_DEVICE_IO_ERROR, 1645 prop.username, 0, '', time.time()) 1646 1647 raise Error(ERROR_DEVICE_IO_ERROR) 1648 1649 status_desc = self.queryString(self.status_code) 1650 1651 self.dq.update({ 1652 'serial' : self.serial, 1653 'cups-printers' : self.cups_printers, 1654 'status-code' : self.status_code, 1655 'status-desc' : status_desc, 1656 'deviceid' : self.raw_deviceID, 1657 'panel' : 0, 1658 'panel-line1' : '', 1659 'panel-line2' : '', 1660 'device-state' : self.device_state, 1661 'error-state' : self.error_state, 1662 }) 1663 1664 status_block = {} 1665 1666 if status_type == STATUS_TYPE_NONE: 1667 log.warn("No status available for device.") 1668 status_block = {'status-code' : STATUS_UNKNOWN} 1669 1670 elif status_type in (STATUS_TYPE_VSTATUS, STATUS_TYPE_S): 1671 log.debug("Type 1/2 (S: or VSTATUS:) status") 1672 status_block = status.parseStatus(self.deviceID) 1673 1674 elif status_type in (STATUS_TYPE_LJ, STATUS_TYPE_PML_AND_PJL): 1675 log.debug("Type 3/9 LaserJet PML(+PJL) status") 1676 status_block = status.StatusType3(self, self.deviceID) 1677 1678 elif status_type == STATUS_TYPE_LJ_XML: 1679 log.debug("Type 6: LJ XML") 1680 status_block = status.StatusType6(self) 1681 1682 elif status_type == STATUS_TYPE_PJL: 1683 log.debug("Type 8: LJ PJL") 1684 status_block = status.StatusType8(self) 1685 1686 elif status_type == STATUS_TYPE_LEDM: 1687 log.debug("Type 10: LEDM") 1688 status_block = status.StatusType10(self.getEWSUrl_LEDM) 1689 1690 elif status_type == STATUS_TYPE_LEDM_FF_CC_0: 1691 log.debug("Type 11: LEDM_FF_CC_0") 1692 status_block = status.StatusType10(self.getUrl_LEDM) 1693 1694 elif status_type == STATUS_TYPE_IPP: 1695 log.debug("Type 12: IPP") 1696 status_block = status.StatusTypeIPP(self.device_uri) 1697 1698 else: 1699 log.error("Unimplemented status type: %d" % status_type) 1700 1701 if battery_check and \ 1702 io_mode != IO_MODE_UNI: 1703 1704 log.debug("Battery check...") 1705 status.BatteryCheck(self, status_block, battery_check) 1706 1707 if status_block: 1708 log.debug(status_block) 1709 self.dq.update(status_block) 1710 try: 1711 status_block['agents'] 1712 except KeyError: 1713 pass 1714 else: 1715 agents = status_block['agents'] 1716 del self.dq['agents'] 1717 1718 1719 status_code = self.dq.get('status-code', STATUS_UNKNOWN) 1720 1721 self.error_state = STATUS_TO_ERROR_STATE_MAP.get(status_code, ERROR_STATE_CLEAR) 1722 self.error_code = status_code 1723 self.sendEvent(self.error_code) 1724 1725 try: 1726 self.dq.update({'status-desc' : self.queryString(status_code), 1727 'error-state' : self.error_state, 1728 }) 1729 1730 except (KeyError, Error): 1731 self.dq.update({'status-desc' : '', 1732 'error-state' : ERROR_STATE_CLEAR, 1733 }) 1734 1735 r_value = 0 1736 1737 if not quick and status_type != STATUS_TYPE_NONE: 1738 if self.panel_check: 1739 self.panel_check = bool(self.mq.get('panel-check-type', 0)) 1740 1741 if self.panel_check and \ 1742 status_type in (STATUS_TYPE_LJ, STATUS_TYPE_S, STATUS_TYPE_VSTATUS) and \ 1743 io_mode != IO_MODE_UNI: 1744 1745 log.debug("Panel check...") 1746 try: 1747 self.panel_check, line1, line2 = status.PanelCheck(self) 1748 finally: 1749 self.closePML() 1750 1751 self.dq.update({'panel': int(self.panel_check), 1752 'panel-line1': line1, 1753 'panel-line2': line2,}) 1754 1755 1756 if dynamic_counters != STATUS_DYNAMIC_COUNTERS_NONE and \ 1757 io_mode != IO_MODE_UNI: 1758 1759 r_value, r_value_str, rg, rr = self.getRValues(r_type, status_type, dynamic_counters) 1760 else: 1761 r_value, r_value_str, rg, rr = 0, '000000000', '000', '000000' 1762 1763 self.dq.update({'r' : r_value, 1764 'rs' : r_value_str, 1765 'rg' : rg, 1766 'rr' : rr, 1767 }) 1768 1769 if not quick and reread_cups_printers: 1770 self.updateCUPSPrinters() 1771 1772 if not quick: 1773 # Make sure there is some valid agent data for this r_value 1774 # If not, fall back to r_value == 0 1775 if r_value > 0 and self.mq.get('r%d-agent1-kind' % r_value, 0) == 0: 1776 r_value = 0 1777 self.dq.update({'r' : r_value, 1778 'rs' : r_value_str, 1779 'rg' : rg, 1780 'rr' : rr, 1781 }) 1782 1783 #Check if device itself is sending the supplies info. If so, then in that case we need not check model.dat static data and 1784 #compare with region, kind and type values. 1785 dynamic_sku_data = False 1786 for agent in agents: 1787 try: 1788 if agent['agent-sku'] != '': 1789 dynamic_sku_data = True 1790 break 1791 except: 1792 pass 1793 1794 a, aa = 1, 1 1795 while True: 1796 if dynamic_sku_data: 1797 if a > len(agents): 1798 break 1799 agent = agents[a-1] 1800 mq_agent_sku = agent['agent-sku'] 1801 agent_kind = agent['kind'] 1802 agent_type = agent['type'] 1803 found = True 1804 else: 1805 mq_agent_kind = self.mq.get('r%d-agent%d-kind' % (r_value, a), -1) 1806 if mq_agent_kind == -1: 1807 break 1808 mq_agent_type = self.mq.get('r%d-agent%d-type' % (r_value, a), 0) 1809 mq_agent_sku = self.mq.get('r%d-agent%d-sku' % (r_value, a), '') 1810 found = False 1811 1812 log.debug("Looking for kind=%d, type=%d..." % (mq_agent_kind, mq_agent_type)) 1813 for agent in agents: 1814 agent_kind = agent['kind'] 1815 agent_type = agent['type'] 1816 1817 if agent_kind == mq_agent_kind and \ 1818 agent_type == mq_agent_type: 1819 found = True 1820 break 1821 1822 if found: 1823 log.debug("found: r%d-kind%d-type%d" % (r_value, agent_kind, agent_type)) 1824 1825 agent_health = agent.get('health', AGENT_HEALTH_OK) 1826 agent_level = agent.get('level', 100) 1827 agent_level_trigger = agent.get('level-trigger', 1828 AGENT_LEVEL_TRIGGER_SUFFICIENT_0) 1829 1830 log.debug("health=%d, level=%d, level_trigger=%d, status_code=%d" % 1831 (agent_health, agent_level, agent_level_trigger, status_code)) 1832 1833 query = 'agent_%s_%s' % (AGENT_types.get(agent_type, 'unknown'), 1834 AGENT_kinds.get(agent_kind, 'unknown')) 1835 1836 agent_desc = self.queryString(query) 1837 query = 'agent_health_ok' 1838 1839 # If printer is not in an error state, and 1840 # if agent health is OK, check for low supplies. If low, use 1841 # the agent level trigger description for the agent description. 1842 # Otherwise, report the agent health. 1843 if (status_code == STATUS_PRINTER_POWER_SAVE or status_code == STATUS_PRINTER_IDLE or status_code == STATUS_PRINTER_OUT_OF_INK) and \ 1844 (agent_health == AGENT_HEALTH_OK or 1845 (agent_health == AGENT_HEALTH_FAIR_MODERATE and agent_kind == AGENT_KIND_HEAD)) and \ 1846 agent_level_trigger >= AGENT_LEVEL_TRIGGER_MAY_BE_LOW: 1847 1848 query = 'agent_level_%s' % AGENT_levels.get(agent_level_trigger, 'unknown') 1849 1850 if tech_type in (TECH_TYPE_MONO_INK, TECH_TYPE_COLOR_INK): 1851 code = agent_type + STATUS_PRINTER_LOW_INK_BASE 1852 else: 1853 code = agent_type + STATUS_PRINTER_LOW_TONER_BASE 1854 1855 self.dq['status-code'] = code 1856 self.dq['status-desc'] = self.queryString(code) 1857 1858 self.dq['error-state'] = STATUS_TO_ERROR_STATE_MAP.get(code, ERROR_STATE_LOW_SUPPLIES) 1859 self.error_code = code 1860 self.sendEvent(self.error_code) 1861 1862 if agent_level_trigger in \ 1863 (AGENT_LEVEL_TRIGGER_PROBABLY_OUT, AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT): 1864 1865 query = 'agent_level_out' 1866 else: 1867 query = 'agent_level_low' 1868 1869 agent_health_desc = self.queryString(query) 1870 1871 self.dq.update( 1872 { 1873 'agent%d-kind' % aa : agent_kind, 1874 'agent%d-type' % aa : agent_type, 1875 'agent%d-known' % aa : agent.get('known', False), 1876 'agent%d-sku' % aa : mq_agent_sku, 1877 'agent%d-level' % aa : agent_level, 1878 'agent%d-level-trigger' % aa : agent_level_trigger, 1879 'agent%d-ack' % aa : agent.get('ack', False), 1880 'agent%d-hp-ink' % aa : agent.get('hp-ink', False), 1881 'agent%d-health' % aa : agent_health, 1882 'agent%d-dvc' % aa : agent.get('dvc', 0), 1883 'agent%d-virgin' % aa : agent.get('virgin', False), 1884 'agent%d-desc' % aa : agent_desc, 1885 'agent%d-id' % aa : agent.get('id', 0), 1886 'agent%d-health-desc' % aa : agent_health_desc, 1887 }) 1888 1889 else: 1890 query = 'agent_health_%s' % AGENT_healths.get(agent_health, AGENT_HEALTH_OK) 1891 agent_health_desc = self.queryString(query) 1892 1893 self.dq.update( 1894 { 1895 'agent%d-kind' % aa : agent_kind, 1896 'agent%d-type' % aa : agent_type, 1897 'agent%d-known' % aa : False, 1898 'agent%d-sku' % aa : mq_agent_sku, 1899 'agent%d-level' % aa : agent_level, 1900 'agent%d-level-trigger' % aa : agent_level_trigger, 1901 'agent%d-ack' % aa : False, 1902 'agent%d-hp-ink' % aa : False, 1903 'agent%d-health' % aa : agent_health, 1904 'agent%d-dvc' % aa : 0, 1905 'agent%d-virgin' % aa : False, 1906 'agent%d-desc' % aa : agent_desc, 1907 'agent%d-id' % aa : 0, 1908 'agent%d-health-desc' % aa : agent_health_desc, 1909 }) 1910 1911 aa += 1 1912 1913 else: 1914 log.debug("Not found: %d" % a) 1915 1916 a += 1 1917 1918 else: # Create agent keys for not-found devices 1919 1920 r_value = 0 1921 if r_type > 0 and self.r_values is not None: 1922 r_value = self.r_values[0] 1923 1924 # Make sure there is some valid agent data for this r_value 1925 # If not, fall back to r_value == 0 1926 if r_value > 0 and self.mq.get('r%d-agent1-kind', 0) == 0: 1927 r_value = 0 1928 1929 a = 1 1930 while True: 1931 mq_agent_kind = self.mq.get('r%d-agent%d-kind' % (r_value, a), 0) 1932 1933 if mq_agent_kind == 0: 1934 break 1935 1936 mq_agent_type = self.mq.get('r%d-agent%d-type' % (r_value, a), 0) 1937 mq_agent_sku = self.mq.get('r%d-agent%d-sku' % (r_value, a), '') 1938 query = 'agent_%s_%s' % (AGENT_types.get(mq_agent_type, 'unknown'), 1939 AGENT_kinds.get(mq_agent_kind, 'unknown')) 1940 1941 agent_desc = self.queryString(query) 1942 1943 self.dq.update( 1944 { 1945 'agent%d-kind' % a : mq_agent_kind, 1946 'agent%d-type' % a : mq_agent_type, 1947 'agent%d-known' % a : False, 1948 'agent%d-sku' % a : mq_agent_sku, 1949 'agent%d-level' % a : 0, 1950 'agent%d-level-trigger' % a : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT, 1951 'agent%d-ack' % a : False, 1952 'agent%d-hp-ink' % a : False, 1953 'agent%d-health' % a : AGENT_HEALTH_MISINSTALLED, 1954 'agent%d-dvc' % a : 0, 1955 'agent%d-virgin' % a : False, 1956 'agent%d-health-desc' % a : self.queryString('agent_health_unknown'), 1957 'agent%d-desc' % a : agent_desc, 1958 'agent%d-id' % a : 0, 1959 }) 1960 1961 a += 1 1962 1963 for d in self.dq: 1964 self.__dict__[d.replace('-','_')] = self.dq[d] 1965 1966 self.last_event = Event(self.device_uri, '', status_code, prop.username, 0, '', time.time()) 1967 log.debug(self.dq) 1968 1969 1970 def isBusyOrInErrorState(self): 1971 try: 1972 self.queryDevice(quick=True) 1973 except Error: 1974 return True 1975 return self.error_state in (ERROR_STATE_ERROR, ERROR_STATE_BUSY) 1976 1977 1978 def isIdleAndNoError(self): 1979 try: 1980 self.queryDevice(quick=True) 1981 except Error: 1982 return False 1983 return self.error_state not in (ERROR_STATE_ERROR, ERROR_STATE_BUSY) 1984 1985 1986 def getPML(self, oid, desired_int_size=pml.INT_SIZE_INT): # oid => ( 'dotted oid value', pml type ) 1987 channel_id = self.openPML() 1988 result_code, data, typ, pml_result_code = \ 1989 hpmudext.get_pml(self.device_id, channel_id, pml.PMLToSNMP(oid[0]), oid[1]) 1990 if pml_result_code > pml.ERROR_MAX_OK: 1991 log.debug("PML/SNMP GET %s failed (result code = 0x%x)" % (oid[0], pml_result_code)) 1992 return pml_result_code, None 1993 1994 converted_data = pml.ConvertFromPMLDataFormat(data, oid[1], desired_int_size) 1995 1996 if log.is_debug(): 1997 if oid[1] in (pml.TYPE_STRING, pml.TYPE_BINARY): 1998 1999 log.debug("PML/SNMP GET %s (result code = 0x%x) returned:" % 2000 (oid[0], pml_result_code)) 2001 log.log_data(data) 2002 else: 2003 log.debug("PML/SNMP GET %s (result code = 0x%x) returned: %s" % 2004 (oid[0], pml_result_code, repr(converted_data))) 2005 return pml_result_code, converted_data 2006 2007 2008 def setPML(self, oid, value): # oid => ( 'dotted oid value', pml type ) 2009 channel_id = self.openPML() 2010 value = pml.ConvertToPMLDataFormat(value, oid[1]) 2011 result_code, pml_result_code = \ 2012 hpmudext.set_pml(self.device_id, channel_id, pml.PMLToSNMP(oid[0]), oid[1], value) 2013 2014 if log.is_debug(): 2015 if oid[1] in (pml.TYPE_STRING, pml.TYPE_BINARY): 2016 2017 log.debug("PML/SNMP SET %s (result code = 0x%x) to:" % 2018 (oid[0], pml_result_code)) 2019 else: 2020 log.debug("PML/SNMP SET %s (result code = 0x%x) to: %s" % 2021 (oid[0], pml_result_code, repr(value.decode('utf-8')))) 2022 2023 return pml_result_code 2024 2025 2026 def getDynamicCounter(self, counter, convert_to_int=True): 2027 dynamic_counters = self.mq.get('status-dynamic-counters', STATUS_DYNAMIC_COUNTERS_NONE) 2028 log.debug("Dynamic counters: %d" % dynamic_counters) 2029 if dynamic_counters != STATUS_DYNAMIC_COUNTERS_NONE: 2030 2031 if dynamic_counters == STATUS_DYNAMIC_COUNTERS_LIDIL_0_5_4: 2032 self.printData(ldl.buildResetPacket(), direct=True) 2033 self.printData(ldl.buildDynamicCountersPacket(counter), direct=True) 2034 else: 2035 self.printData(pcl.buildDynamicCounter(counter), direct=True) 2036 2037 value, tries, times_seen, sleepy_time, max_tries = 0, 0, 0, 0.1, 5 2038 time.sleep(0.1) 2039 2040 while True: 2041 2042 if self.callback: 2043 self.callback() 2044 2045 sleepy_time += 0.1 2046 tries += 1 2047 2048 time.sleep(sleepy_time) 2049 2050 self.getDeviceID() 2051 2052 if 'CTR' in self.deviceID and \ 2053 pat_dynamic_ctr.search(self.raw_deviceID) is not None: 2054 dev_counter, value = parseDynamicCounter(self.deviceID['CTR'], convert_to_int) 2055 2056 if counter == dev_counter: 2057 self.printData(pcl.buildDynamicCounter(0), direct=True) 2058 # protect the value as a string during msg handling 2059 if not convert_to_int: 2060 value = '#' + value 2061 return value 2062 2063 if tries > max_tries: 2064 if dynamic_counters == STATUS_DYNAMIC_COUNTERS_LIDIL_0_5_4: 2065 self.printData(ldl.buildResetPacket()) 2066 self.printData(ldl.buildDynamicCountersPacket(counter), direct=True) 2067 else: 2068 self.printData(pcl.buildDynamicCounter(0), direct=True) 2069 2070 return None 2071 2072 if dynamic_counters == STATUS_DYNAMIC_COUNTERS_LIDIL_0_5_4: 2073 self.printData(ldl.buildResetPacket()) 2074 self.printData(ldl.buildDynamicCountersPacket(counter), direct=True) 2075 else: 2076 self.printData(pcl.buildDynamicCounter(counter), direct=True) 2077 2078 else: 2079 raise Error(ERROR_DEVICE_DOES_NOT_SUPPORT_OPERATION) 2080 2081 2082 def readPrint(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=False): 2083 return self.__readChannel(self.openPrint, bytes_to_read, stream, timeout, allow_short_read) 2084 2085 def readPCard(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=False): 2086 return self.__readChannel(self.openPCard, bytes_to_read, stream, timeout, allow_short_read) 2087 2088 def readFax(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=False): 2089 return self.__readChannel(self.openFax, bytes_to_read, stream, timeout, allow_short_read) 2090 2091 def readCfgUpload(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=False): 2092 return self.__readChannel(self.openCfgUpload, bytes_to_read, stream, timeout, allow_short_read) 2093 2094 def readEWS(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True): 2095 return self.__readChannel(self.openEWS, bytes_to_read, stream, timeout, allow_short_read) 2096 2097 def readEWS_LEDM(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True): 2098 return self.__readChannel(self.openEWS_LEDM, bytes_to_read, stream, timeout, allow_short_read) 2099 2100 def readLEDM(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True): 2101 return self.__readChannel(self.openLEDM, bytes_to_read, stream, timeout, allow_short_read) 2102 2103 def readMarvell_EWS(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True): 2104 return self.__readChannel(self.openMarvell_EWS, bytes_to_read, stream, timeout, allow_short_read) 2105 2106 def readSoapFax(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True): 2107 return self.__readChannel(self.openSoapFax, bytes_to_read, stream, timeout, allow_short_read) 2108 2109 def readMarvellFax(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True): 2110 return self.__readChannel(self.openMarvellFax, bytes_to_read, stream, timeout, allow_short_read) 2111 2112 def readWifiConfig(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True): 2113 return self.__readChannel(self.openWifiConfig, bytes_to_read, stream, timeout, allow_short_read) 2114 2115#Common handling of reading chunked or unchunked data from LEDM devices 2116 def readLEDMData(dev, func, reply, timeout=6): 2117 2118 END_OF_DATA=to_bytes_utf8("0\r\n\r\n") 2119 bytes_requested = 1024 2120 bytes_remaining = 0 2121 chunkedFlag = True 2122 2123 bytes_read = func(bytes_requested, reply, timeout) 2124 2125 for line in reply.getvalue().splitlines(): 2126 if line.lower().find(to_bytes_utf8("content-length")) != -1: 2127 bytes_remaining = int(line.split(to_bytes_utf8(":"))[1]) 2128 chunkedFlag = False 2129 break 2130 2131 xml_data_start = reply.getvalue().find(to_bytes_utf8("<?xml")) 2132 if (xml_data_start != -1): 2133 bytes_remaining = bytes_remaining - (len(reply.getvalue()) - xml_data_start) 2134 2135 while bytes_read > 0: 2136 temp_buf = xStringIO() 2137 bytes_read = func(bytes_requested, temp_buf, timeout) 2138 2139 reply.write(temp_buf.getvalue()) 2140 2141 if not chunkedFlag: # Unchunked data 2142 bytes_remaining = bytes_remaining - bytes_read 2143 if bytes_remaining <= 0: 2144 break 2145 elif END_OF_DATA == temp_buf.getvalue(): # Chunked data end 2146 break 2147 2148 2149 2150 def __readChannel(self, opener, bytes_to_read, stream=None, 2151 timeout=prop.read_timeout, allow_short_read=False): 2152 2153 channel_id = opener() 2154 2155 log.debug("Reading channel %d (device-id=%d, bytes_to_read=%d, allow_short=%s, timeout=%d)..." % 2156 (channel_id, self.device_id, bytes_to_read, allow_short_read, timeout)) 2157 2158 num_bytes = 0 2159 2160 if stream is None: 2161 buffer = to_bytes_utf8('') 2162 2163 while True: 2164 result_code, data = \ 2165 hpmudext.read_channel(self.device_id, channel_id, bytes_to_read, timeout) 2166 2167 log.debug("Result code=%d" % result_code) 2168 2169 l = len(data) 2170 2171 if result_code == hpmudext.HPMUD_R_IO_TIMEOUT: 2172 log.debug("I/O timeout") 2173 break 2174 2175 if result_code != hpmudext.HPMUD_R_OK: 2176 log.error("Channel read error") 2177 raise Error(ERROR_DEVICE_IO_ERROR) 2178 2179 if not l: 2180 log.debug("End of data") 2181 break 2182 2183 if stream is None: 2184 buffer = to_bytes_utf8('').join([buffer, data]) 2185 else: 2186 stream.write(data) 2187 2188 num_bytes += l 2189 2190 if self.callback is not None: 2191 self.callback() 2192 2193 if num_bytes == bytes_to_read: 2194 log.debug("Full read complete.") 2195 break 2196 2197 if allow_short_read and num_bytes < bytes_to_read: 2198 log.debug("Allowed short read of %d of %d bytes complete." % (num_bytes, bytes_to_read)) 2199 break 2200 2201 if stream is None: 2202 log.debug("Returned %d total bytes in buffer." % num_bytes) 2203 return buffer 2204 else: 2205 log.debug("Saved %d total bytes to stream." % num_bytes) 2206 return num_bytes 2207 2208 2209 def writePrint(self, data): 2210 return self.__writeChannel(self.openPrint, data) 2211 2212 def writePCard(self, data): 2213 return self.__writeChannel(self.openPCard, data) 2214 2215 def writeFax(self, data): 2216 return self.__writeChannel(self.openFax, data) 2217 2218 def writeEWS(self, data): 2219 return self.__writeChannel(self.openEWS, data) 2220 2221 def writeEWS_LEDM(self, data): 2222 return self.__writeChannel(self.openEWS_LEDM, data) 2223 2224 def writeLEDM(self, data): 2225 return self.__writeChannel(self.openLEDM, data) 2226 2227 def writeMarvell_EWS(self, data): 2228 return self.__writeChannel(self.openMarvell_EWS, data) 2229 2230 def writeCfgDownload(self, data): 2231 return self.__writeChannel(self.openCfgDownload, data) 2232 2233 def writeSoapFax(self, data): 2234 return self.__writeChannel(self.openSoapFax, data) 2235 2236 def writeMarvellFax(self, data): 2237 if not isinstance(data, bytes) and hasattr(data, 'tobytes'): # hasattr function used for supporting 2.6 2238 data = data.tobytes() 2239 return self.__writeChannel(self.openMarvellFax, data) 2240 2241 def writeWifiConfig(self, data): 2242 return self.__writeChannel(self.openWifiConfig, data) 2243 2244 def __writeChannel(self, opener, data): 2245 channel_id = opener() 2246 buffer, bytes_out, total_bytes_to_write = data, 0, len(data) 2247 log.debug("Writing %d bytes to channel %d (device-id=%d)..." % (total_bytes_to_write, channel_id, self.device_id)) 2248 2249 while len(buffer) > 0: 2250 result_code, bytes_written = \ 2251 hpmudext.write_channel(self.device_id, channel_id, 2252 buffer[:prop.max_message_len]) 2253 2254 log.debug("Result code=%d" % result_code) 2255 2256 if result_code != hpmudext.HPMUD_R_OK: 2257 log.error("Channel write error") 2258 raise Error(ERROR_DEVICE_IO_ERROR) 2259 2260 buffer = buffer[prop.max_message_len:] 2261 bytes_out += bytes_written 2262 2263 if self.callback is not None: 2264 self.callback() 2265 2266 if total_bytes_to_write != bytes_out: 2267 raise Error(ERROR_DEVICE_IO_ERROR) 2268 2269 return bytes_out 2270 2271 2272 def writeEmbeddedPML(self, oid, value, style=1, direct=True): 2273 if style == 1: 2274 func = pcl.buildEmbeddedPML2 2275 else: 2276 func = pcl.buildEmbeddedPML 2277 2278 data = func(pcl.buildPCLCmd('&', 'b', 'W', 2279 pml.buildEmbeddedPMLSetPacket(oid[0], 2280 value, 2281 oid[1]))) 2282 2283 #log.log_data(data) 2284 2285 self.printData(data, direct=direct, raw=True) 2286 2287 def post(self, url, post): 2288 status_type = self.mq.get('status-type', STATUS_TYPE_NONE) 2289 data = """POST %s HTTP/1.1\r 2290Connection: Keep-alive\r 2291User-agent: hplip/2.0\r 2292Host: %s\r 2293Content-type: text/xml\r 2294Content-length: %d\r 2295\r 2296%s""" % (url, self.http_host, len(post), post) 2297 log.log_data(data) 2298 if status_type == STATUS_TYPE_LEDM: 2299 log.debug("status-type: %d" % status_type) 2300 self.writeEWS_LEDM(data) 2301 response = BytesIO() 2302 2303 self.readLEDMData(self.readEWS_LEDM, response) 2304 2305 response = response.getvalue() 2306 log.log_data(response) 2307 self.closeEWS_LEDM() 2308 2309 elif status_type == STATUS_TYPE_LEDM_FF_CC_0: 2310 log.debug("status-type: %d" % status_type) 2311 self.writeLEDM(data) 2312 response = BytesIO() 2313 2314 self.readLEDMData(self.readLEDM, response) 2315 2316 response = response.getvalue() 2317 log.log_data(response) 2318 self.closeLEDM() 2319 2320 else: 2321 log.error("Not an LEDM status-type: %d" % status_type) 2322 2323 match = http_result_pat.match(to_string_utf8(response)) 2324 if match is None: return HTTP_OK 2325 try: 2326 code = int(match.group(1)) 2327 except (ValueError, TypeError): 2328 code = HTTP_ERROR 2329 2330 return code == HTTP_OK 2331 2332 def printGzipFile(self, file_name, printer_name=None, direct=False, raw=True, remove=False): 2333 return self.printFile(file_name, printer_name, direct, raw, remove) 2334 2335 def printParsedGzipPostscript(self, print_file, printer_name=None): 2336 # always: direct=False, raw=False, remove=True 2337 try: 2338 os.stat(print_file) 2339 except OSError: 2340 log.error("File not found: %s" % print_file) 2341 return 2342 2343 temp_file_fd, temp_file_name = utils.make_temp_file() 2344 f = gzip.open(print_file, 'r') 2345 2346 x = f.readline() 2347 while not x.startswith(to_bytes_utf8('%PY_BEGIN')): 2348 os.write(temp_file_fd, x) 2349 x = f.readline() 2350 2351 sub_lines = [] 2352 x = f.readline() 2353 while not x.startswith(to_bytes_utf8('%PY_END')): 2354 sub_lines.append(x) 2355 x = f.readline() 2356 2357 SUBS = {'VERSION' : prop.version, 2358 'MODEL' : self.model_ui, 2359 'URI' : self.device_uri, 2360 'BUS' : self.bus, 2361 'SERIAL' : self.serial, 2362 'IP' : self.host, 2363 'PORT' : self.port, 2364 'DEVNODE' : self.dev_file, 2365 } 2366 2367 if self.bus == 'net' : 2368 SUBS['DEVNODE'] = 'n/a' 2369 else: 2370 SUBS['IP']= 'n/a' 2371 SUBS['PORT'] = 'n/a' 2372 2373 if PY3: 2374 sub_lines = [s.decode('utf-8') for s in sub_lines] 2375 2376 2377 for s in sub_lines: 2378 os.write(temp_file_fd, to_bytes_utf8((s % SUBS))) 2379 2380 2381 os.write(temp_file_fd, f.read()) 2382 f.close() 2383 os.close(temp_file_fd) 2384 2385 self.printFile(temp_file_name, printer_name, direct=False, raw=False, remove=True) 2386 2387 def printFile(self, file_name, printer_name=None, direct=False, raw=True, remove=False): 2388 is_gzip = os.path.splitext(file_name)[-1].lower() == '.gz' 2389 2390 if printer_name is None: 2391 printer_name = self.first_cups_printer 2392 2393 if not printer_name: 2394 raise Error(ERROR_NO_CUPS_QUEUE_FOUND_FOR_DEVICE) 2395 2396 log.debug("Printing file '%s' to queue '%s' (gzip=%s, direct=%s, raw=%s, remove=%s)" % 2397 (file_name, printer_name, is_gzip, direct, raw, remove)) 2398 2399 if direct: # implies raw==True 2400 if is_gzip: 2401 self.writePrint(gzip.open(file_name, 'r').read()) 2402 else: 2403 self.writePrint(open(file_name, 'r').read()) 2404 2405 else: 2406 if not utils.which('lpr'): 2407 lp_opt = '' 2408 2409 if raw: 2410 lp_opt = '-oraw' 2411 2412 if is_gzip: 2413 c = 'gunzip -c %s | lp -c -d%s %s' % (file_name, printer_name, lp_opt) 2414 else: 2415 c = 'lp -c -d%s %s %s' % (printer_name, lp_opt, file_name) 2416 2417 exit_code = os_utils.execute(c) 2418 2419 if exit_code != 0: 2420 log.error("Print command failed with exit code %d!" % exit_code) 2421 2422 if remove: 2423 os.remove(file_name) 2424 2425 else: 2426 raw_str, rem_str = '', '' 2427 if raw: raw_str = '-o raw' 2428 if remove: rem_str = '-r' 2429 2430 if is_gzip: 2431 c = 'gunzip -c %s | lpr %s %s -P%s' % (file_name, raw_str, rem_str, printer_name) 2432 else: 2433 c = 'lpr -P%s %s %s %s' % (printer_name, raw_str, rem_str, file_name) 2434 2435 exit_code = os_utils.execute(c) 2436 2437 if exit_code != 0: 2438 log.error("Print command failed with exit code %d!" % exit_code) 2439 2440 2441 def printTestPage(self, printer_name=None): 2442 return self.printParsedGzipPostscript(os.path.join( prop.home_dir, 'data', 2443 'ps', 'testpage.ps.gz' ), printer_name) 2444 2445 2446 def printData(self, data, printer_name=None, direct=True, raw=True): 2447 if direct: 2448 self.writePrint(data) 2449 else: 2450 temp_file_fd, temp_file_name = utils.make_temp_file() 2451 os.write(temp_file_fd, data) 2452 os.close(temp_file_fd) 2453 2454 self.printFile(temp_file_name, printer_name, False, raw, remove=True) 2455 2456 2457 def cancelJob(self, jobid): 2458 cups.cancelJob(jobid) 2459 self.error_code = STATUS_PRINTER_CANCELING 2460 self.sendEvent(self.error_code) 2461 2462 2463 def queryHistory(self): 2464 result = [] 2465 2466 if self.dbus_avail: 2467 try: 2468 device_uri, history = self.service.GetHistory(self.device_uri) 2469 except dbus.exceptions.DBusException as e: 2470 log.error("dbus call to GetHistory() failed.") 2471 return [] 2472 2473 history.reverse() 2474 2475 for h in history: 2476 result.append(Event(*tuple(h))) 2477 2478 try: 2479 self.error_code = result[0].event_code 2480 except IndexError: 2481 self.error_code = STATUS_UNKNOWN 2482 2483 self.error_state = STATUS_TO_ERROR_STATE_MAP.get(self.error_code, ERROR_STATE_CLEAR) 2484 2485 else: 2486 self.error_code = STATUS_UNKNOWN 2487 self.error_state = ERROR_STATE_CLEAR 2488 2489 self.hist = result 2490 return result 2491 2492 def getEWSUrl(self, url, stream): 2493 try: 2494 if self.is_local: 2495 url2 = "%s&loc=%s" % (self.device_uri.replace('hpfax:', 'hp:'), url) 2496 data = self 2497 else: 2498 url2 = "http://%s%s" % (self.host, url) 2499 if self.zc: 2500 status, ip = hpmudext.get_zc_ip_address(self.zc) 2501 if status == hpmudext.HPMUD_R_OK: 2502 url2 = "http://%s%s" % (ip, url) 2503 data = None 2504 2505 log.debug("Opening: %s" % url2) 2506 opener = LocalOpener({}) 2507 try: 2508 f = opener.open(url2, data) 2509 2510 except Error: 2511 log.error("Status read failed: %s" % url2) 2512 stream.seek(0) 2513 stream.truncate() 2514 else: 2515 try: 2516 stream.write(f.fp.read()) 2517 #stream.write(f) 2518 finally: 2519 f.close() 2520 2521 finally: 2522 self.closeEWS() 2523 2524 def getEWSUrl_LEDM(self, url, stream, footer=""): 2525 try: 2526 url2 = "%s&loc=%s" % (self.device_uri.replace('hpfax:', 'hp:'), url) 2527 data = self 2528 opener = LocalOpenerEWS_LEDM({}) 2529 try: 2530 if footer: 2531 return opener.open_hp(url2, data, footer) 2532 else: 2533 return opener.open_hp(url2, data) 2534 except Error: 2535 log.debug("Status read failed: %s" % url2) 2536 finally: 2537 self.closeEWS_LEDM() 2538 2539 def getUrl_LEDM(self, url, stream, footer=""): 2540 try: 2541 url2 = "%s&loc=%s" % (self.device_uri.replace('hpfax:', 'hp:'), url) 2542 data = self 2543 opener = LocalOpener_LEDM({}) 2544 try: 2545 if footer: 2546 return opener.open_hp(url2, data, footer) 2547 else: 2548 return opener.open_hp(url2, data) 2549 except Error: 2550 log.debug("Status read failed: %s" % url2) 2551 2552 finally: 2553 self.closeLEDM() 2554 2555 def FetchLEDMUrl(self, url, footer=""): 2556 data_fp = BytesIO() 2557 if footer: 2558 data = self.getUrl_LEDM(url, data_fp, footer) 2559 else: 2560 data = self.getUrl_LEDM(url, data_fp) 2561 if data: 2562 data = data.split(to_bytes_utf8('\r\n\r\n'), 1)[1] 2563 if data: 2564 data = status.ExtractXMLData(data) 2565 return data 2566 2567#-------------------------For LEDM SOAP PROTOCOL(FAX) Devices----------------------------------------------------------------------# 2568 2569 def FetchEWS_LEDMUrl(self, url, footer=""): 2570 data_fp = BytesIO() 2571 if footer: 2572 data = self.getEWSUrl_LEDM(url, data_fp, footer) 2573 else: 2574 data = self.getEWSUrl_LEDM(url, data_fp) 2575 if data: 2576 data = data.split(to_bytes_utf8('\r\n\r\n'), 1)[1] 2577 if data: 2578 data = status.ExtractXMLData(data) 2579 return data 2580 2581 def readAttributeFromXml_EWS(self, uri, attribute): 2582 stream = BytesIO() 2583 data = self.FetchEWS_LEDMUrl(uri) 2584 if not data: 2585 log.error("Unable To read the XML data from device") 2586 return "" 2587 xmlDict = utils.XMLToDictParser().parseXML(data) 2588 2589 try: 2590 return xmlDict[attribute] 2591 except: 2592 return str("") 2593 2594#---------------------------------------------------------------------------------------------------# 2595 2596 def readAttributeFromXml(self,uri,attribute): 2597 stream = BytesIO() 2598 data = self.FetchLEDMUrl(uri) 2599 if not data: 2600 log.error("Unable To read the XML data from device") 2601 return "" 2602 xmlDict = utils.XMLToDictParser().parseXML(data ) 2603 try: 2604 return xmlDict[attribute] 2605 except: 2606 return str("") 2607 2608 2609 def downloadFirmware(self, usb_bus_id=None, usb_device_id=None): # Note: IDs not currently used 2610 ok = False 2611 filename = os.path.join(prop.data_dir, "firmware", self.model.lower() + '.fw.gz') 2612 log.debug(filename) 2613 2614 if os.path.exists(filename): 2615 log.debug("Downloading firmware file '%s'..." % filename) 2616 2617 # Write to port directly (no MUD) so that HAL can enumerate the printer 2618 if 0: # this currently doesn't work because usblp is loaded... 2619 #if usb_bus_id is not None and usb_device_id is not None: 2620 try: 2621 p = "/dev/bus/usb/%s/%s" % (usb_bus_id, usb_device_id) 2622 log.debug("Writing to %s..." % p) 2623 f = os.open(p, os.O_RDWR) 2624 x = gzip.open(filename).read() 2625 os.write(f, x) 2626 os.close(f) 2627 ok = True 2628 log.debug("OK") 2629 except (OSError, IOError) as e: 2630 log.error("An error occured: %s" % e) 2631 else: 2632 try: 2633 self.openPrint() 2634 bytes_written = self.writePrint(gzip.open(filename).read()) 2635 log.debug("%s bytes downloaded." % utils.commafy(bytes_written)) 2636 self.closePrint() 2637 ok = True 2638 log.debug("OK") 2639 except Error as e: 2640 log.error("An error occured: %s" % e.msg) 2641 else: 2642 log.error("Firmware file '%s' not found." % filename) 2643 2644 return ok 2645 2646 2647 2648 2649 2650 2651# URLs: hp:/usb/HP_LaserJet_3050?serial=00XXXXXXXXXX&loc=/hp/device/info_device_status.xml 2652class LocalOpener(urllib_request.URLopener): 2653 def open_hp(self, url, dev): 2654 log.debug("open_hp(%s)" % url) 2655 2656 match_obj = http_pat_url.search(url) 2657 bus = match_obj.group(1) or '' 2658 model = match_obj.group(2) or '' 2659 serial = match_obj.group(3) or '' 2660 device = match_obj.group(4) or '' 2661 loc = match_obj.group(5) or '' 2662 2663 dev.openEWS() 2664 dev.writeEWS("""GET %s HTTP/1.0\nContent-Length:0\nHost:localhost\nUser-Agent:hplip\n\n""" % loc) 2665 2666 reply = xStringIO() 2667 while dev.readEWS(8192, reply, timeout=1): 2668 pass 2669 2670 reply.seek(0) 2671 log.log_data(reply.getvalue()) 2672 2673 response = http_client.HTTPResponse(reply) 2674 response.begin() 2675 2676 if response.status != http_client.OK: 2677 raise Error(ERROR_DEVICE_STATUS_NOT_AVAILABLE) 2678 else: 2679 return response#.fp 2680 2681# URLs: hp:/usb/HP_OfficeJet_7500?serial=00XXXXXXXXXX&loc=/hp/device/info_device_status.xml 2682class LocalOpenerEWS_LEDM(urllib_request.URLopener): 2683 def open_hp(self, url, dev, foot=""): 2684 log.debug("open_hp(%s)" % url) 2685 2686 match_obj = http_pat_url.search(url) 2687 loc = url.split("=")[url.count("=")] 2688 2689 dev.openEWS_LEDM() 2690 if foot: 2691 if "PUT" in foot: 2692 dev.writeEWS_LEDM("""%s""" % foot) 2693 else: 2694 dev.writeEWS_LEDM("""POST %s HTTP/1.1\r\nContent-Type:text/xml\r\nContent-Length:%s\r\nAccept-Encoding: UTF-8\r\nHost:localhost\r\nUser-Agent:hplip\r\n\r\n """ % (loc, len(foot))) 2695 dev.writeEWS_LEDM("""%s""" % foot) 2696 else: 2697 dev.writeEWS_LEDM("""GET %s HTTP/1.1\r\nAccept: text/plain\r\nHost:localhost\r\nUser-Agent:hplip\r\n\r\n""" % loc) 2698 2699 reply = xStringIO() 2700 2701 dev.readLEDMData(dev.readEWS_LEDM,reply) 2702 2703 reply.seek(0) 2704 return reply.getvalue() 2705 2706 2707# URLs: hp:/usb/HP_OfficeJet_7500?serial=00XXXXXXXXXX&loc=/hp/device/info_device_status.xml 2708class LocalOpener_LEDM(urllib_request.URLopener): 2709 def open_hp(self, url, dev, foot=""): 2710 log.debug("open_hp(%s)" % url) 2711 2712 match_obj = http_pat_url.search(url) 2713 loc = url.split("=")[url.count("=")] 2714 2715 dev.openLEDM() 2716 if foot: 2717 if "PUT" in foot: 2718 dev.writeLEDM("""%s""" % foot) 2719 else: 2720 dev.writeLEDM("""POST %s HTTP/1.1\r\nContent-Type:text/xml\r\nContent-Length:%s\r\nAccept-Encoding: UTF-8\r\nHost:localhost\r\nUser-Agent:hplip\r\n\r\n """ % (loc, len(foot))) 2721 dev.writeLEDM("""%s""" % foot) 2722 else: 2723 dev.writeLEDM("""GET %s HTTP/1.1\r\nAccept: text/plain\r\nHost:localhost\r\nUser-Agent:hplip\r\n\r\n""" % loc) 2724 2725 reply = xStringIO() 2726 2727 2728 dev.readLEDMData(dev.readLEDM,reply) 2729 2730 reply.seek(0) 2731 return reply.getvalue() 2732