1 # -*- coding: utf-8 -*-
3 # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
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.
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.
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
19 # Author: Don Welch, Naga Samrat Chowdary Narla
28 import urllib # TODO: Replace with urllib2 (urllib is deprecated in Python 3.0)
42 from prnt import pcl, ldl, cups
43 import models, mdns, slp
44 from strings import StringTable
50 if not os.getenv("HPLIP_BUILD"):
51 log.error("HPMUDEXT could not be loaded. Please check HPLIP installation.")
54 # Workaround for build machine
56 MAX_BUFFER = hpmudext.HPMUD_BUFFER_SIZE
57 except AttributeError:
64 from dbus import lowlevel, SessionBus
67 log.warn("python-dbus not installed.")
70 # Ignore: .../dbus/connection.py:242: DeprecationWarning: object.__init__() takes no parameters
71 # (occurring on Python 2.6/dBus 0.83/Ubuntu 9.04)
72 warnings.simplefilter("ignore", DeprecationWarning)
75 DEFAULT_PROBE_BUS = ['usb', 'par', 'cups']
76 VALID_BUSES = ('par', 'net', 'cups', 'usb') #, 'bt', 'fw')
77 VALID_BUSES_WO_CUPS = ('par', 'net', 'usb')
79 VALID_FILTERS = ('print', 'scan', 'fax', 'pcard', 'copy')
80 DEFAULT_BE_FILTER = ('hp',)
82 pat_deviceuri = re.compile(r"""(.*):/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*)|ip=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[^&]*)|zc=(\S+))(?:&port=(\d))?""", re.IGNORECASE)
83 http_pat_url = re.compile(r"""/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*))&loc=(\S*)""", re.IGNORECASE)
84 direct_pat = re.compile(r'direct (.*?) "(.*?)" "(.*?)" "(.*?)"', re.IGNORECASE)
86 # Pattern to check for ; at end of CTR fields
87 # Note: If ; not present, CTR value is invalid
88 pat_dynamic_ctr = re.compile(r"""CTR:\d*\s.*;""", re.IGNORECASE)
90 # Cache for model data
91 model_dat = models.ModelData()
93 ip_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)
94 dev_pat = re.compile(r"""/dev/.+""", re.IGNORECASE)
95 usb_pat = re.compile(r"""(\d+):(\d+)""", re.IGNORECASE)
97 ### **********Lambda Function UniStar for checking type of arguments to constructor of class event*******************************
99 UniStr = lambda title: isinstance(title, str) and utils.xrstrip(title, '\x00')[:128] or utils.xrstrip(title, '\x00')[:128].encode('utf-8')
103 # Event Wrapper Class for pipe IPC
107 def __init__(self, device_uri, printer_name, event_code,
108 username=prop.username, job_id=0, title='',
110 # UniStr = lambda title: isinstance(title, str) and utils.xrstrip(title, '\x00')[:128] or utils.xrstrip(title, '\x00')[:128].encode('utf-8')
111 self.device_uri = UniStr(device_uri)
112 self.printer_name = UniStr(printer_name)
113 self.event_code = int(event_code)
114 self.username = UniStr(username)
115 self.job_id = int(job_id)
116 self.title = UniStr(title)
119 self.timedate = float(timedate)
121 self.timedate = time.time()
123 self.pipe_fmt = "80s80sI32sI80sf"
124 self.dbus_fmt = "ssisisd"
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)
137 def pack_for_pipe(self):
138 return struct.pack(self.pipe_fmt, self.device_uri, self.printer_name,
139 self.event_code, self.username, self.job_id, self.title,
143 def send_via_pipe(self, fd, recipient='hpssd'):
145 log.debug("Sending event %d to %s (via pipe %d)..." % (self.event_code, recipient, fd))
147 os.write(fd, self.pack_for_pipe())
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)
163 return Event(*self.as_tuple())
167 return "<Event('%s', '%s', %d, '%s', %d, '%s', %f)>" % self.as_tuple()
171 return (self.device_uri, self.printer_name, self.event_code,
172 self.username, self.job_id, self.title, self.timedate)
175 class 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"
186 log.debug(" temp_file=%s" % self.temp_file)
190 return "<FaxEvent('%s', '%s', %d, '%s', %d, '%s', %f, '%s')>" % self.as_tuple()
194 return (self.device_uri, self.printer_name, self.event_code,
195 self.username, self.job_id, self.title, self.timedate,
200 class 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"
211 log.debug(" bytes_written=%d" % self.bytes_written)
215 return "<DeviceIOEvent('%s', '%s', %d, '%s', %d, '%s', %f, '%d')>" % self.as_tuple()
219 return (self.device_uri, self.printer_name, self.event_code,
220 self.username, self.job_id, self.title, self.timedate,
228 def init_dbus(dbus_loop=None):
233 if not prop.gui_build:
235 return dbus_avail, None, None
237 if dbus_avail and not dbus_disabled:
239 log.debug("Not starting dbus: running as root.")
241 return dbus_avail, None, None
244 if dbus_loop is None:
245 session_bus = dbus.SessionBus()
247 session_bus = dbus.SessionBus(dbus_loop)
248 except dbus.exceptions.DBusException, e:
250 log.error("Unable to connect to dbus session bus.")
252 log.debug("Unable to connect to dbus session bus (running as root?)")
255 return dbus_avail, None, None
258 log.debug("Connecting to com.hplip.StatusService (try #1)...")
259 service = session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService")
261 except dbus.exceptions.DBusException, e:
263 os.waitpid(-1, os.WNOHANG)
267 path = utils.which('hp-systray')
269 path = os.path.join(path, 'hp-systray')
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
276 log.debug("Running hp-systray: %s --force-startup" % path)
278 os.spawnlp(os.P_NOWAIT, path, 'hp-systray', '--force-startup')
280 log.debug("Waiting for hp-systray to start...")
286 log.debug("Connecting to com.hplip.StatusService (try #%d)..." % t)
287 service = session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService")
289 except dbus.exceptions.DBusException, e:
290 log.debug("Unable to connect to dbus. Is hp-systray running?")
294 log.warn("Unable to connect to dbus. Is hp-systray running?")
295 return False, None, None
300 log.debug("Connected.")
304 return dbus_avail, service, session_bus
308 # Make URI from parameter (bus ID, IP address, etc)
311 def makeURI(param, port=1):
312 cups_uri, sane_uri, fax_uri = '', '', ''
315 if dev_pat.search(param) is not None: # parallel
316 log.debug("Trying parallel with %s" % param)
318 result_code, uri = hpmudext.make_par_uri(param)
320 if result_code == hpmudext.HPMUD_R_OK and uri:
321 log.debug("Found: %s" % uri)
325 log.debug("Not found.")
327 elif usb_pat.search(param) is not None: # USB
328 match_obj = usb_pat.search(param)
329 usb_bus_id = match_obj.group(1)
330 usb_dev_id = match_obj.group(2)
332 log.debug("Trying USB with bus=%s dev=%s..." % (usb_bus_id, usb_dev_id))
333 result_code, uri = hpmudext.make_usb_uri(usb_bus_id, usb_dev_id)
335 if result_code == ERROR_SUCCESS and uri:
336 log.debug("Found: %s" % uri)
340 log.debug("Not found.")
342 elif ip_pat.search(param) is not None: # IPv4 dotted quad
343 log.debug("Trying IP address %s" % param)
345 result_code, uri = hpmudext.make_net_uri(param, port)
347 if result_code == hpmudext.HPMUD_R_OK and uri:
348 log.debug("Found: %s" % uri)
352 log.debug("Not found.")
354 else: # Try Zeroconf hostname
355 log.debug("Trying ZC hostname %s" % param)
357 result_code, uri = hpmudext.make_zc_uri(param, port)
359 if result_code == hpmudext.HPMUD_R_OK and uri:
360 log.debug("Found: %s" % uri)
364 log.debug("Not found.")
367 log.debug("Trying serial number %s" % param)
368 devices = probeDevices(bus=['usb', 'par'])
373 # usb has serial in URI...
375 back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
380 if bus == 'par': # ...parallel does not. Must get Device ID to obtain it...
381 mq = queryModelByURI(d)
383 result_code, device_id = \
384 hpmudext.device_open(d, mq.get('io-mode', hpmudext.HPMUD_UNI_MODE))
386 if result_code == hpmudext.HPMUD_R_OK:
387 result_code, data = hpmudext.get_device_id(device_id)
388 serial = parseDeviceID(data).get('SN', '')
389 hpmudext.close_device(device_id)
391 if serial.lower() == param.lower():
392 log.debug("Found: %s" % d)
397 log.debug("Not found.")
401 mq = queryModelByURI(cups_uri)
403 log.error("Error: %s" % e.msg)
404 cups_uri, sane_uri, fax_uri = '', '', ''
406 if mq.get('support-type', SUPPORT_TYPE_NONE) > SUPPORT_TYPE_NONE:
407 if mq.get('scan-type', 0):
408 sane_uri = cups_uri.replace("hp:", "hpaio:")
410 if mq.get('fax-type', 0):
411 fax_uri = cups_uri.replace("hp:", "hpfax:")
414 cups_uri, sane_uri, fax_uri = '', '', ''
417 scan_uri, fax_uri = '', ''
420 user_conf.set('last_used', 'device_uri', cups_uri)
422 return cups_uri, sane_uri, fax_uri
429 def queryModelByModel(model):
430 model = models.normalizeModelName(model).lower()
431 return model_dat[model]
434 def queryModelByURI(device_uri):
436 back_end, is_hp, bus, model, \
437 serial, dev_file, host, zc, port = \
438 parseDeviceURI(device_uri)
440 raise Error(ERROR_INVALID_DEVICE_URI)
442 return queryModelByModel(model)
449 def probeDevices(bus=DEFAULT_PROBE_BUS, timeout=10,
450 ttl=4, filter=DEFAULT_FILTER, search='', net_search='mdns',
451 back_end_filter=('hp',)):
453 num_devices, ret_devices = 0, {}
457 search_pat = re.compile(search, re.IGNORECASE)
459 log.error("Invalid search pattern. Search uses standard regular expressions. For more info, see: http://www.amk.ca/python/howto/regex/")
463 log.debug("Probing bus: %s" % b)
464 if b not in VALID_BUSES:
465 log.error("Invalid bus: %s" % b)
469 if net_search == 'slp':
471 detected_devices = slp.detectNetworkDevices(ttl, timeout)
472 except Error, socket.error:
473 log.error("An error occured during network probe.")
477 detected_devices = mdns.detectNetworkDevices(ttl, timeout)
478 except Error, socket.error:
479 log.error("An error occured during network probe.")
482 for ip in detected_devices:
484 hn = detected_devices[ip].get('hn', '?UNKNOWN?')
485 num_devices_on_jd = detected_devices[ip].get('num_devices', 0)
486 num_ports_on_jd = detected_devices[ip].get('num_ports', 1)
488 if num_devices_on_jd > 0:
489 for port in range(num_ports_on_jd):
490 dev = detected_devices[ip].get('device%d' % (port+1), '0')
492 if dev is not None and dev != '0':
493 device_id = parseDeviceID(dev)
494 model = models.normalizeModelName(device_id.get('MDL', '?UNKNOWN?'))
496 if num_ports_on_jd == 1:
497 if net_search == 'slp':
498 device_uri = 'hp:/net/%s?ip=%s' % (model, ip)
500 device_uri = 'hp:/net/%s?zc=%s' % (model, hn)
502 if net_search == 'slp':
503 device_uri = 'hp:/net/%s?ip=%s&port=%d' % (model, ip, (port + 1))
505 device_uri = 'hp:/net/%s?zc=%s&port=%d' % (model, hn, (port + 1))
508 mq = queryModelByModel(model)
511 log.debug("Not found.")
514 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE:
515 log.debug("Not supported.")
518 elif filter not in (None, 'print', 'print-type'):
519 include = __checkFilter(filter, mq)
522 ret_devices[device_uri] = (model, model, hn)
524 elif b in ('usb', 'par'):
526 bn = hpmudext.HPMUD_BUS_PARALLEL
528 bn = hpmudext.HPMUD_BUS_USB
530 result_code, data = hpmudext.probe_devices(bn)
532 if result_code == hpmudext.HPMUD_R_OK:
533 for x in data.splitlines():
534 m = direct_pat.match(x)
536 uri = m.group(1) or ''
537 mdl = m.group(2) or ''
538 desc = m.group(3) or ''
539 devid = m.group(4) or ''
544 back_end, is_hp, bb, model, serial, dev_file, host, zc, port = \
551 if mdl and uri and is_hp:
552 mq = queryModelByModel(model)
555 log.debug("Not found.")
558 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE:
559 log.debug("Not supported.")
562 elif filter not in (None, 'print', 'print-type'):
563 include = __checkFilter(filter, mq)
566 ret_devices[uri] = (mdl, desc, devid) # model w/ _'s, mdl w/o
569 cups_printers = cups.getPrinters()
570 x = len(cups_printers)
572 for p in cups_printers:
573 device_uri = p.device_uri
574 log.debug("%s: %s" % (device_uri, p.name))
578 back_end, is_hp, bs, model, serial, dev_file, host, zc, port = \
579 parseDeviceURI(device_uri)
581 log.debug("Unrecognized URI: %s" % device_uri)
588 mq = queryModelByModel(model)
592 log.debug("Not found.")
594 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE:
595 log.debug("Not supported.")
598 elif filter not in (None, 'print', 'print-type'):
599 include = __checkFilter(filter, mq)
602 ret_devices[device_uri] = (model, model, '')
605 for uri in ret_devices:
607 mdl, model, devid_or_hn = ret_devices[uri]
611 match_obj = search_pat.search("%s %s %s %s" % (mdl, model, devid_or_hn, uri))
613 if match_obj is None:
614 log.debug("%s %s %s %s: Does not match search '%s'." % (mdl, model, devid_or_hn, uri, search))
618 probed_devices[uri] = ret_devices[uri]
621 return probed_devices
627 def getSupportedCUPSDevices(back_end_filter=['hp'], filter=DEFAULT_FILTER):
629 printers = cups.getPrinters()
633 back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
634 parseDeviceURI(p.device_uri)
639 if (back_end_filter == '*' or back_end in back_end_filter or \
640 ('hpaio' in back_end_filter and back_end == 'hp')) and \
644 mq = queryModelByModel(model)
647 log.debug("Not found.")
650 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE:
651 log.debug("Not supported.")
654 elif filter not in (None, 'print', 'print-type'):
655 include = __checkFilter(filter, mq)
658 if 'hpaio' in back_end_filter:
659 d = p.device_uri.replace('hp:', 'hpaio:')
666 devices[d] = [p.name]
668 devices[d].append(p.name)
670 return devices # { 'device_uri' : [ CUPS printer list ], ... }
673 def getSupportedCUPSPrinters(back_end_filter=['hp'], filter=DEFAULT_FILTER):
675 printers = cups.getPrinters()
679 back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
680 parseDeviceURI(p.device_uri)
685 if (back_end_filter == '*' or back_end in back_end_filter) and model and is_hp:
687 mq = queryModelByModel(model)
690 log.debug("Not found.")
693 elif int(mq.get('support-type', SUPPORT_TYPE_NONE)) == SUPPORT_TYPE_NONE:
694 log.debug("Not supported.")
697 elif filter not in (None, 'print', 'print-type'):
698 include = __checkFilter(filter, mq)
701 p.name = p.name.decode('utf-8')
702 printer_list.append(p)
703 #printer_list[p.name] = p.device_uri
705 return printer_list # [ cupsext.Printer, ... ]
708 def getSupportedCUPSPrinterNames(back_end_filter=['hp'], filter=DEFAULT_FILTER):
709 printers = getSupportedCUPSPrinters(back_end_filter, filter)
710 return [p.name for p in printers]
713 def getDeviceURIByPrinterName(printer_name, scan_uri_flag=False):
714 if printer_name is None:
718 printers = cups.getPrinters()
722 back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
723 parseDeviceURI(p.device_uri)
728 if is_hp and p.name == printer_name:
730 device_uri = p.device_uri.replace('hp:', 'hpaio:')
732 device_uri = p.device_uri
738 # IEEE-1284 Device ID parsing
741 def parseDeviceID(device_id):
743 x = [y.strip() for y in device_id.strip().split(';') if y]
748 d.setdefault(y[0].strip(), y[1])
750 d.setdefault(y[0].strip(), None)
752 d.setdefault('MDL', '')
753 d.setdefault('SN', '')
756 d['MDL'] = d['MODEL']
760 d['SN'] = d['SERIAL']
767 if d['SN'].startswith('X'):
773 # IEEE-1284 Device ID Dynamic Counter Parsing
776 def parseDynamicCounter(ctr_field, convert_to_int=True):
777 counter, value = ctr_field.split(' ')
779 counter = int(utils.xlstrip(str(counter), '0') or '0')
782 value = int(utils.xlstrip(str(value), '0') or '0')
785 counter, value = 0, 0
787 counter, value = 0, ''
789 return counter, value
793 # Parse Device URI Strings
796 def parseDeviceURI(device_uri):
797 m = pat_deviceuri.match(device_uri)
800 log.debug("Device URI %s is invalid/unknown" % device_uri)
801 raise Error(ERROR_INVALID_DEVICE_URI)
803 back_end = m.group(1).lower() or ''
804 is_hp = (back_end in ('hp', 'hpfax', 'hpaio'))
805 bus = m.group(2).lower() or ''
807 if bus not in ('usb', 'net', 'bt', 'fw', 'par'):
808 log.debug("Device URI %s is invalid/unknown" % device_uri)
809 raise Error(ERROR_INVALID_DEVICE_URI)
811 model = m.group(3) or ''
812 serial = m.group(4) or ''
813 dev_file = m.group(5) or ''
814 host = m.group(6) or ''
817 zc = host = m.group(7) or ''
818 port = m.group(8) or 1
823 except (ValueError, TypeError):
829 log.debug("%s: back_end:%s is_hp:%s bus:%s model:%s serial:%s dev_file:%s host:%s zc:%s port:%s" %
830 (device_uri, back_end, is_hp, bus, model, serial, dev_file, host, zc, port))
832 return back_end, is_hp, bus, model, serial, dev_file, host, zc, port
836 return bus in ('par', 'usb', 'fw', 'bt')
840 return bus in ('net',)
847 def __checkFilter(filter, mq):
848 for f, p in filter.items():
851 if not op(mq[f], val):
857 def validateBusList(bus, allow_cups=True):
862 vb = VALID_BUSES_WO_CUPS
865 log.error("Invalid bus name: %s" %b)
871 def validateFilterList(filter):
876 if f not in VALID_FILTERS:
877 log.error("Invalid term '%s' in filter list" % f)
884 # UI String Queries (why is this here?)
887 inter_pat = re.compile(r"""%(.*)%""", re.IGNORECASE)
893 global strings_init, st
900 for s in st.string_table:
901 short_string, long_string = st.string_table[s]
902 short_replace, long_replace = short_string, long_string
905 short_match = inter_pat.match(short_string).group(1)
906 except (AttributeError, TypeError):
909 if short_match is not None:
913 short_replace, dummy = st.string_table[short_match]
915 log.error("String interpolation error: %s" % short_match)
918 long_match = inter_pat.match(long_string).group(1)
919 except (AttributeError, TypeError):
922 if long_match is not None:
926 dummy, long_replace = st.string_table[long_match]
928 log.error("String interpolation error: %s" % long_match)
931 st.string_table[s] = (short_replace, long_replace)
941 def queryString(string_id, typ=0):
945 #log.debug("queryString(%s)" % string_id)
946 s = st.string_table.get(str(string_id), ('', ''))[typ]
948 if type(s) == type(''):
954 AGENT_types = { AGENT_TYPE_NONE : 'invalid',
955 AGENT_TYPE_BLACK : 'black',
956 AGENT_TYPE_BLACK_B8800 : 'black',
957 AGENT_TYPE_CMY : 'cmy',
958 AGENT_TYPE_KCM : 'kcm',
959 AGENT_TYPE_CYAN : 'cyan',
960 AGENT_TYPE_MAGENTA : 'magenta',
961 AGENT_TYPE_YELLOW : 'yellow',
962 AGENT_TYPE_CYAN_LOW : 'photo_cyan',
963 AGENT_TYPE_MAGENTA_LOW : 'photo_magenta',
964 AGENT_TYPE_YELLOW_LOW : 'photo_yellow',
965 AGENT_TYPE_GGK : 'photo_gray',
966 AGENT_TYPE_BLUE : 'photo_blue',
967 AGENT_TYPE_KCMY_CM : 'kcmy_cm',
968 AGENT_TYPE_LC_LM : 'photo_cyan_and_photo_magenta',
969 #AGENT_TYPE_Y_M : 'yellow_and_magenta',
970 #AGENT_TYPE_C_K : 'cyan_and_black',
971 AGENT_TYPE_LG_PK : 'light_gray_and_photo_black',
972 AGENT_TYPE_LG : 'light_gray',
973 AGENT_TYPE_G : 'medium_gray',
974 AGENT_TYPE_PG : 'photo_gray',
975 AGENT_TYPE_C_M : 'cyan_and_magenta',
976 AGENT_TYPE_K_Y : 'black_and_yellow',
977 AGENT_TYPE_UNSPECIFIED : 'unspecified', # Kind=5,6
980 AGENT_kinds = {AGENT_KIND_NONE : 'invalid',
981 AGENT_KIND_HEAD : 'head',
982 AGENT_KIND_SUPPLY : 'supply',
983 AGENT_KIND_HEAD_AND_SUPPLY : 'cartridge',
984 AGENT_KIND_TONER_CARTRIDGE : 'toner',
985 AGENT_KIND_MAINT_KIT : 'maint_kit', # fuser
986 AGENT_KIND_ADF_KIT : 'adf_kit',
987 AGENT_KIND_DRUM_KIT : 'drum_kit',
988 AGENT_KIND_TRANSFER_KIT : 'transfer_kit',
989 AGENT_KIND_INT_BATTERY : 'battery',
990 AGENT_KIND_UNKNOWN : 'unknown',
993 AGENT_healths = {AGENT_HEALTH_OK : 'ok',
994 AGENT_HEALTH_MISINSTALLED : 'misinstalled', # supply/cart
995 #AGENT_HEALTH_FAIR_MODERATE : '',
996 AGENT_HEALTH_INCORRECT : 'incorrect',
997 AGENT_HEALTH_FAILED : 'failed',
998 AGENT_HEALTH_OVERTEMP : 'overtemp', # battery
999 AGENT_HEALTH_CHARGING : 'charging', # battery
1000 AGENT_HEALTH_DISCHARGING : 'discharging', # battery
1004 AGENT_levels = {AGENT_LEVEL_TRIGGER_MAY_BE_LOW : 'low',
1005 AGENT_LEVEL_TRIGGER_PROBABLY_OUT : 'low',
1006 AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT : 'out',
1014 # **************************************************************************** #
1018 class Device(object):
1019 def __init__(self, device_uri, printer_name=None,
1020 service=None, callback=None, disable_dbus=False):
1022 log.debug("Device URI: %s" % device_uri)
1023 log.debug("Printer: %s" % printer_name)
1025 global dbus_disabled
1026 dbus_disabled = disable_dbus
1028 if not disable_dbus:
1030 self.dbus_avail, self.service, session_bus = init_dbus()
1032 self.dbus_avail = True
1033 self.service = service
1035 self.dbus_avail = False
1038 self.last_event = None # Used in devmgr if dbus is disabled
1040 printers = cups.getPrinters()
1042 if device_uri is None and printer_name is not None:
1044 if p.name.lower() == printer_name.lower():
1045 device_uri = p.device_uri
1046 log.debug("Device URI: %s" % device_uri)
1049 raise Error(ERROR_DEVICE_NOT_FOUND)
1051 self.device_uri = device_uri
1052 self.callback = callback
1053 self.device_type = DEVICE_TYPE_UNKNOWN
1055 if self.device_uri is None:
1056 raise Error(ERROR_DEVICE_NOT_FOUND)
1058 if self.device_uri.startswith('hp:'):
1059 self.device_type = DEVICE_TYPE_PRINTER
1061 elif self.device_uri.startswith('hpaio:'):
1062 self.device_type = DEVICE_TYPE_SCANNER
1064 elif self.device_uri.startswith('hpfax:'):
1065 self.device_type = DEVICE_TYPE_FAX
1068 self.back_end, self.is_hp, self.bus, self.model, \
1069 self.serial, self.dev_file, self.host, self.zc, self.port = \
1070 parseDeviceURI(self.device_uri)
1072 self.io_state = IO_STATE_NON_HP
1073 raise Error(ERROR_INVALID_DEVICE_URI)
1075 log.debug("URI: backend=%s, is_hp=%s, bus=%s, model=%s, serial=%s, dev=%s, host=%s, port=%d" % \
1076 (self.back_end, self.is_hp, self.bus, self.model, self.serial, self.dev_file, self.host, self.port))
1078 self.model_ui = models.normalizeModelUIName(self.model)
1079 self.model = models.normalizeModelName(self.model)
1081 log.debug("Model/UI model: %s/%s" % (self.model, self.model_ui))
1084 #service.setAlertsEx(self.hpssd_sock)
1086 self.mq = {} # Model query
1087 self.dq = {} # Device query
1088 self.icon = "default_printer"
1089 self.cups_printers = []
1090 self.channels = {} # { 'SERVICENAME' : channel_id, ... }
1092 self.r_values = None # ( r_value, r_value_str, rg, rr )
1094 self.panel_check = True
1095 self.io_state = IO_STATE_HP_READY
1096 self.is_local = isLocal(self.bus)
1099 self.supported = False
1102 if not self.supported:
1103 log.error("Unsupported model: %s" % self.model)
1104 self.error_code = STATUS_DEVICE_UNSUPPORTED
1105 self.sendEvent(self.error_code)
1107 self.supported = True
1110 self.mq.update({'model' : self.model,
1111 'model-ui' : self.model_ui})
1113 self.error_state = ERROR_STATE_ERROR
1114 self.device_state = DEVICE_STATE_NOT_FOUND
1115 self.status_code = EVENT_ERROR_DEVICE_NOT_FOUND
1117 self.updateCUPSPrinters()
1119 if self.mq.get('fax-type', FAX_TYPE_NONE) != FAX_TYPE_NONE:
1120 self.dq.update({ 'fax-uri' : self.device_uri.replace('hp:/', 'hpfax:/').replace('hpaio:/', 'hpfax:/')})
1122 if self.mq.get('scan-type', SCAN_TYPE_NONE) != SCAN_TYPE_NONE:
1123 self.dq.update({ 'scan-uri' : self.device_uri.replace('hp:/', 'hpaio:/').replace('hpfax:/', 'hpaio:/')})
1126 'back-end' : self.back_end,
1127 'is-hp' : self.is_hp,
1128 'serial' : self.serial,
1129 'dev-file' : self.dev_file,
1132 'cups-printers' : self.cups_printers,
1133 'status-code' : self.status_code,
1139 'device-state' : self.device_state,
1140 'error-state' : self.error_state,
1141 'device-uri' : self.device_uri,
1142 'cups-uri' : self.device_uri.replace('hpfax:/', 'hp:/').replace('hpaio:/', 'hp:/'),
1145 self.device_vars = {
1146 'URI' : self.device_uri,
1147 'DEVICE_URI' : self.device_uri,
1148 'SCAN_URI' : self.device_uri.replace('hp:', 'hpaio:'),
1149 'SANE_URI' : self.device_uri.replace('hp:', 'hpaio:'),
1150 'FAX_URI' : self.device_uri.replace('hp:', 'hpfax:'),
1151 'PRINTER' : self.first_cups_printer,
1152 'HOME' : prop.home_dir,
1158 def sendEvent(self, event_code, printer_name='', job_id=0, title=''):
1159 if self.dbus_avail and self.service is not None:
1161 log.debug("Sending event %d to hpssd..." % event_code)
1162 self.service.SendEvent(self.device_uri, printer_name, event_code, prop.username, job_id, title)
1163 except dbus.exceptions.DBusException, e:
1164 log.debug("dbus call to SendEvent() failed.")
1171 def queryModel(self):
1173 self.mq = queryModelByURI(self.device_uri)
1175 self.supported = bool(self.mq)
1179 self.__dict__[m.replace('-','_')] = self.mq[m]
1182 def queryString(self, string_id):
1183 return queryString(string_id)
1186 def open(self, open_for_printing=False):
1187 if self.supported and self.io_state in (IO_STATE_HP_READY, IO_STATE_HP_NOT_AVAIL):
1188 prev_device_state = self.device_state
1189 self.io_state = IO_STATE_HP_NOT_AVAIL
1190 self.device_state = DEVICE_STATE_NOT_FOUND
1191 self.error_state = ERROR_STATE_ERROR
1192 self.status_code = EVENT_ERROR_DEVICE_NOT_FOUND
1194 self.open_for_printing = open_for_printing
1196 if open_for_printing:
1197 log.debug("Opening device: %s (for printing)" % self.device_uri)
1198 self.io_mode = self.mq.get('io-mode', hpmudext.HPMUD_UNI_MODE)
1200 log.debug("Opening device: %s (not for printing)" % self.device_uri)
1201 self.io_mode = self.mq.get('io-mfp-mode', hpmudext.HPMUD_UNI_MODE)
1203 log.debug("I/O mode=%d" % self.io_mode)
1204 result_code, self.device_id = \
1205 hpmudext.open_device(self.device_uri, self.io_mode)
1207 if result_code != hpmudext.HPMUD_R_OK:
1208 self.error_state = ERROR_STATE_ERROR
1209 self.error_code = result_code+ERROR_CODE_BASE
1210 self.sendEvent(self.error_code)
1212 if result_code == hpmudext.HPMUD_R_DEVICE_BUSY:
1213 log.error("Device busy: %s" % self.device_uri)
1215 log.error("Unable to communicate with device (code=%d): %s" % (result_code, self.device_uri))
1217 self.last_event = Event(self.device_uri, '', EVENT_ERROR_DEVICE_NOT_FOUND,
1218 prop.username, 0, '', time.time())
1220 raise Error(ERROR_DEVICE_NOT_FOUND)
1223 log.debug("device-id=%d" % self.device_id)
1224 self.io_state = IO_STATE_HP_OPEN
1225 self.error_state = ERROR_STATE_CLEAR
1226 log.debug("Opened device: %s (backend=%s, is_hp=%s, bus=%s, model=%s, dev=%s, serial=%s, host=%s, port=%d)" %
1227 (self.back_end, self.device_uri, self.is_hp, self.bus, self.model,
1228 self.dev_file, self.serial, self.host, self.port))
1230 if prev_device_state == DEVICE_STATE_NOT_FOUND:
1231 self.device_state = DEVICE_STATE_JUST_FOUND
1233 self.device_state = DEVICE_STATE_FOUND
1236 self.getSerialNumber()
1237 return self.device_id
1241 if self.io_state == IO_STATE_HP_OPEN:
1242 log.debug("Closing device...")
1244 if len(self.channels) > 0:
1246 for c in self.channels.keys():
1247 self.__closeChannel(c)
1249 result_code = hpmudext.close_device(self.device_id)
1250 log.debug("Result-code = %d" % result_code)
1252 self.channels.clear()
1253 self.io_state = IO_STATE_HP_READY
1256 def __openChannel(self, service_name):
1258 if self.io_state == IO_STATE_HP_OPEN:
1259 if service_name == hpmudext.HPMUD_S_PRINT_CHANNEL and not self.open_for_printing:
1262 elif service_name != hpmudext.HPMUD_S_PRINT_CHANNEL and self.open_for_printing:
1266 self.open(service_name == hpmudext.HPMUD_S_PRINT_CHANNEL)
1268 log.error("unable to open channel")
1271 #if not self.mq['io-mode'] == IO_MODE_UNI:
1273 service_name = service_name.upper()
1275 if service_name not in self.channels:
1276 log.debug("Opening %s channel..." % service_name)
1278 result_code, channel_id = hpmudext.open_channel(self.device_id, service_name)
1280 self.channels[service_name] = channel_id
1281 log.debug("channel-id=%d" % channel_id)
1284 return self.channels[service_name]
1289 def openChannel(self, service_name):
1290 return self.__openChannel(service_name)
1292 def openPrint(self):
1293 return self.__openChannel(hpmudext.HPMUD_S_PRINT_CHANNEL)
1296 return self.__openChannel(hpmudext.HPMUD_S_FAX_SEND_CHANNEL)
1298 def openPCard(self):
1299 return self.__openChannel(hpmudext.HPMUD_S_MEMORY_CARD_CHANNEL)
1302 return self.__openChannel(hpmudext.HPMUD_S_EWS_CHANNEL)
1304 def openEWS_LEDM(self):
1305 return self.__openChannel(hpmudext.HPMUD_S_EWS_LEDM_CHANNEL)
1308 return self.__openChannel(hpmudext.HPMUD_S_LEDM_SCAN)
1310 def closePrint(self):
1311 return self.__closeChannel(hpmudext.HPMUD_S_PRINT_CHANNEL)
1313 def closePCard(self):
1314 return self.__closeChannel(hpmudext.HPMUD_S_MEMORY_CARD_CHANNEL)
1317 return self.__closeChannel(hpmudext.HPMUD_S_FAX_SEND_CHANNEL)
1320 return self.__openChannel(hpmudext.HPMUD_S_PML_CHANNEL)
1322 def openWifiConfig(self):
1323 return self.__openChannel(hpmudext.HPMUD_S_WIFI_CHANNEL)
1326 return self.__closeChannel(hpmudext.HPMUD_S_PML_CHANNEL)
1329 return self.__closeChannel(hpmudext.HPMUD_S_EWS_CHANNEL)
1331 def closeEWS_LEDM(self):
1332 return self.__closeChannel(hpmudext.HPMUD_S_EWS_LEDM_CHANNEL)
1334 def closeLEDM(self):
1335 return self.__closeChannel(hpmudext.HPMUD_S_LEDM_SCAN)
1337 def openCfgUpload(self):
1338 return self.__openChannel(hpmudext.HPMUD_S_CONFIG_UPLOAD_CHANNEL)
1340 def closeCfgUpload(self):
1341 return self.__closeChannel(hpmudext.HPMUD_S_CONFIG_UPLOAD_CHANNEL)
1343 def openCfgDownload(self):
1344 return self.__openChannel(hpmudext.HPMUD_S_CONFIG_DOWNLOAD_CHANNEL)
1346 def closeCfgDownload(self):
1347 return self.__closeChannel(hpmudext.HPMUD_S_CONFIG_DOWNLOAD_CHANNEL)
1349 def openSoapFax(self):
1350 return self.__openChannel(hpmudext.HPMUD_S_SOAP_FAX)
1352 def openMarvellFax(self):
1353 return self.__openChannel(hpmudext.HPMUD_S_MARVELL_FAX_CHANNEL)
1355 def closeSoapFax(self):
1356 return self.__closeChannel(hpmudext.HPMUD_S_SOAP_FAX)
1358 def closeMarvellFax(self):
1359 return self.__closeChannel(hpmudext.HPMUD_S_MARVELL_FAX_CHANNEL)
1361 def closeWifiConfig(self):
1362 return self.__closeChannel(hpmudext.HPMUD_S_WIFI_CHANNEL)
1364 def __closeChannel(self, service_name):
1365 #if not self.mq['io-mode'] == IO_MODE_UNI and \
1366 if self.io_state == IO_STATE_HP_OPEN:
1368 service_name = service_name.upper()
1370 if service_name in self.channels:
1371 log.debug("Closing %s channel..." % service_name)
1373 result_code = hpmudext.close_channel(self.device_id,
1374 self.channels[service_name])
1376 del self.channels[service_name]
1379 def closeChannel(self, service_name):
1380 return self.__closeChannel(service_name)
1383 def getDeviceID(self):
1385 if self.io_state != IO_STATE_HP_OPEN:
1392 result_code, data = hpmudext.get_device_id(self.device_id)
1394 if result_code != hpmudext.HPMUD_R_OK:
1395 self.raw_deviceID = ''
1398 self.raw_deviceID = data
1399 self.deviceID = parseDeviceID(data)
1404 return self.deviceID
1407 def getSerialNumber(self):
1412 self.serial = self.deviceID['SN']
1419 if self.mq.get('status-type', STATUS_TYPE_NONE) != STATUS_TYPE_NONE: # and \
1420 #not self.mq.get('io-mode', IO_MODE_UNI) == IO_MODE_UNI:
1424 error_code, self.serial = self.getPML(pml.OID_SERIAL_NUMBER)
1430 if self.serial is None:
1434 def getThreeBitStatus(self):
1438 def getStatusFromDeviceID(self):
1440 return status.parseStatus(parseDeviceID(self.raw_deviceID))
1443 def __parseRValues(self, r_value):
1444 r_value_str = str(r_value)
1445 r_value_str = ''.join(['0'*(9 - len(r_value_str)), r_value_str])
1446 rg, rr = r_value_str[:3], r_value_str[3:]
1448 self.r_values = r_value, r_value_str, rg, rr
1449 return r_value, r_value_str, rg, rr
1452 def getRValues(self, r_type, status_type, dynamic_counters):
1453 r_value, r_value_str, rg, rr = 0, '000000000', '000', '000000'
1456 dynamic_counters != STATUS_DYNAMIC_COUNTERS_NONE:
1458 if self.r_values is None:
1461 r_value = int(self.service.GetCachedIntValue(self.device_uri, 'r_value'))
1462 except dbus.exceptions.DBusException, e:
1463 log.debug("dbus call to GetCachedIntValue() failed.")
1467 log.debug("r_value=%d" % r_value)
1468 r_value, r_value_str, rg, rr = self.__parseRValues(r_value)
1470 return r_value, r_value_str, rg, rr
1472 if self.r_values is None:
1474 if status_type == STATUS_TYPE_S and \
1476 dynamic_counters != STATUS_DYNAMIC_COUNTERS_PML_SNMP:
1480 r_value = self.getDynamicCounter(140)
1482 if r_value is not None:
1483 log.debug("r_value=%d" % r_value)
1484 r_value, r_value_str, rg, rr = self.__parseRValues(r_value)
1488 self.service.SetCachedIntValue(self.device_uri, 'r_value', r_value)
1489 except dbus.exceptions.DBusException, e:
1490 log.debug("dbus call to SetCachedIntValue() failed.")
1492 log.error("Error attempting to read r-value (2).")
1495 log.error("Error attempting to read r-value (1).")
1501 elif (status_type == STATUS_TYPE_S and
1502 dynamic_counters == STATUS_DYNAMIC_COUNTERS_PCL and
1503 not self.is_local) or \
1504 dynamic_counters == STATUS_DYNAMIC_COUNTERS_PML_SNMP:
1507 result_code, r_value = self.getPML(pml.OID_R_SETTING)
1509 if r_value is not None:
1510 log.debug("r_value=%d" % r_value)
1511 r_value, r_value_str, rg, rr = self.__parseRValues(r_value)
1515 self.service.SetCachedIntValue(self.device_uri, 'r_value', r_value)
1516 except dbus.exceptions.DBusException, e:
1517 log.debug("dbus call to SetCachedIntValue() failed.")
1526 r_value, r_value_str, rg, rr = self.r_values
1528 return r_value, r_value_str, rg, rr
1531 def __queryFax(self, quick=False, reread_cups_printers=False):
1532 io_mode = self.mq.get('io-mode', IO_MODE_UNI)
1533 self.status_code = STATUS_PRINTER_IDLE
1535 if io_mode != IO_MODE_UNI:
1537 if self.device_state != DEVICE_STATE_NOT_FOUND:
1538 if self.tech_type in (TECH_TYPE_MONO_INK, TECH_TYPE_COLOR_INK):
1542 log.error("Error getting device ID.")
1543 self.last_event = Event(self.device_uri, '', ERROR_DEVICE_IO_ERROR,
1544 prop.username, 0, '', time.time())
1546 raise Error(ERROR_DEVICE_IO_ERROR)
1548 status_desc = self.queryString(self.status_code)
1551 'serial' : self.serial,
1552 'cups-printers' : self.cups_printers,
1553 'status-code' : self.status_code,
1554 'status-desc' : status_desc,
1555 'deviceid' : self.raw_deviceID,
1559 'device-state' : self.device_state,
1560 'error-state' : self.error_state,
1564 log.debug("Fax activity check...")
1566 tx_active, rx_active = status.getFaxStatus(self)
1569 self.status_code = STATUS_FAX_TX_ACTIVE
1571 self.status_code = STATUS_FAX_RX_ACTIVE
1573 self.error_state = STATUS_TO_ERROR_STATE_MAP.get(self.status_code, ERROR_STATE_CLEAR)
1574 self.error_code = self.status_code
1575 self.sendEvent(self.error_code)
1578 self.dq.update({'status-desc' : self.queryString(self.status_code),
1579 'error-state' : self.error_state,
1582 except (KeyError, Error):
1583 self.dq.update({'status-desc' : '',
1584 'error-state' : ERROR_STATE_CLEAR,
1588 if self.panel_check:
1589 self.panel_check = bool(self.mq.get('panel-check-type', 0))
1591 status_type = self.mq.get('status-type', STATUS_TYPE_NONE)
1592 if self.panel_check and \
1593 status_type in (STATUS_TYPE_LJ, STATUS_TYPE_S, STATUS_TYPE_VSTATUS) and \
1594 io_mode != IO_MODE_UNI:
1596 log.debug("Panel check...")
1598 self.panel_check, line1, line2 = status.PanelCheck(self)
1602 self.dq.update({'panel': int(self.panel_check),
1603 'panel-line1': line1,
1604 'panel-line2': line2,})
1606 if not quick and reread_cups_printers:
1607 self.updateCUPSPrinters()
1610 self.__dict__[d.replace('-','_')] = self.dq[d]
1612 self.last_event = Event(self.device_uri, '', self.status_code, prop.username, 0, '', time.time())
1618 def updateCUPSPrinters(self):
1619 self.cups_printers = []
1620 log.debug("Re-reading CUPS printer queue information.")
1621 printers = cups.getPrinters()
1623 if self.device_uri == p.device_uri:
1624 self.cups_printers.append(p.name)
1625 self.state = p.state # ?
1627 if self.io_state == IO_STATE_NON_HP:
1628 self.model = p.makemodel.split(',')[0]
1630 self.dq.update({'cups-printers' : self.cups_printers})
1633 self.first_cups_printer = self.cups_printers[0]
1635 self.first_cups_printer = ''
1640 def queryDevice(self, quick=False, reread_cups_printers=False):
1641 if not self.supported:
1644 self.last_event = Event(self.device_uri, '', STATUS_DEVICE_UNSUPPORTED,
1645 prop.username, 0, '', time.time())
1649 if self.device_type == DEVICE_TYPE_FAX:
1650 return self.__queryFax(quick, reread_cups_printers)
1652 r_type = self.mq.get('r-type', 0)
1653 tech_type = self.mq.get('tech-type', TECH_TYPE_NONE)
1654 status_type = self.mq.get('status-type', STATUS_TYPE_NONE)
1655 battery_check = self.mq.get('status-battery-check', STATUS_BATTERY_CHECK_NONE)
1656 dynamic_counters = self.mq.get('status-dynamic-counters', STATUS_DYNAMIC_COUNTERS_NONE)
1657 io_mode = self.mq.get('io-mode', IO_MODE_UNI)
1658 io_mfp_mode = self.mq.get('io-mfp-mode', IO_MODE_UNI)
1659 status_code = STATUS_UNKNOWN
1661 # Turn off status if local connection and bi-di not avail.
1662 #if io_mode == IO_MODE_UNI and self.back_end != 'net':
1663 # status_type = STATUS_TYPE_NONE
1667 if self.device_state != DEVICE_STATE_NOT_FOUND:
1668 if self.tech_type in (TECH_TYPE_MONO_INK, TECH_TYPE_COLOR_INK):
1672 log.error("Error getting device ID.")
1673 self.last_event = Event(self.device_uri, '', ERROR_DEVICE_IO_ERROR,
1674 prop.username, 0, '', time.time())
1676 raise Error(ERROR_DEVICE_IO_ERROR)
1678 status_desc = self.queryString(self.status_code)
1681 'serial' : self.serial,
1682 'cups-printers' : self.cups_printers,
1683 'status-code' : self.status_code,
1684 'status-desc' : status_desc,
1685 'deviceid' : self.raw_deviceID,
1689 'device-state' : self.device_state,
1690 'error-state' : self.error_state,
1695 if status_type == STATUS_TYPE_NONE:
1696 log.warn("No status available for device.")
1697 status_block = {'status-code' : STATUS_UNKNOWN}
1699 elif status_type in (STATUS_TYPE_VSTATUS, STATUS_TYPE_S):
1700 log.debug("Type 1/2 (S: or VSTATUS:) status")
1701 status_block = status.parseStatus(self.deviceID)
1703 elif status_type in (STATUS_TYPE_LJ, STATUS_TYPE_PML_AND_PJL):
1704 log.debug("Type 3/9 LaserJet PML(+PJL) status")
1705 status_block = status.StatusType3(self, self.deviceID)
1707 elif status_type == STATUS_TYPE_LJ_XML:
1708 log.debug("Type 6: LJ XML")
1709 status_block = status.StatusType6(self)
1711 elif status_type == STATUS_TYPE_PJL:
1712 log.debug("Type 8: LJ PJL")
1713 status_block = status.StatusType8(self)
1715 elif status_type == STATUS_TYPE_LEDM:
1716 log.debug("Type 10: LEDM")
1717 status_block = status.StatusType10(self.getEWSUrl_LEDM)
1719 elif status_type == STATUS_TYPE_LEDM_FF_CC_0:
1720 log.debug("Type 11: LEDM_FF_CC_0")
1721 status_block = status.StatusType10(self.getUrl_LEDM)
1724 log.error("Unimplemented status type: %d" % status_type)
1726 if battery_check and \
1727 io_mode != IO_MODE_UNI:
1729 log.debug("Battery check...")
1730 status.BatteryCheck(self, status_block, battery_check)
1733 log.debug(status_block)
1734 self.dq.update(status_block)
1736 status_block['agents']
1740 agents = status_block['agents']
1741 del self.dq['agents']
1744 status_code = self.dq.get('status-code', STATUS_UNKNOWN)
1746 ## if not quick and \
1747 ## self.mq.get('fax-type', FAX_TYPE_NONE) and \
1748 ## status_code == STATUS_PRINTER_IDLE and \
1749 ## io_mode != IO_MODE_UNI:
1751 ## log.debug("Fax activity check...")
1753 ## tx_active, rx_active = status.getFaxStatus(self)
1756 ## status_code = STATUS_FAX_TX_ACTIVE
1758 ## status_code = STATUS_FAX_RX_ACTIVE
1761 self.error_state = STATUS_TO_ERROR_STATE_MAP.get(status_code, ERROR_STATE_CLEAR)
1762 self.error_code = status_code
1763 self.sendEvent(self.error_code)
1766 self.dq.update({'status-desc' : self.queryString(status_code),
1767 'error-state' : self.error_state,
1770 except (KeyError, Error):
1771 self.dq.update({'status-desc' : '',
1772 'error-state' : ERROR_STATE_CLEAR,
1777 if not quick and status_type != STATUS_TYPE_NONE:
1778 if self.panel_check:
1779 self.panel_check = bool(self.mq.get('panel-check-type', 0))
1781 if self.panel_check and \
1782 status_type in (STATUS_TYPE_LJ, STATUS_TYPE_S, STATUS_TYPE_VSTATUS) and \
1783 io_mode != IO_MODE_UNI:
1785 log.debug("Panel check...")
1787 self.panel_check, line1, line2 = status.PanelCheck(self)
1791 self.dq.update({'panel': int(self.panel_check),
1792 'panel-line1': line1,
1793 'panel-line2': line2,})
1796 if dynamic_counters != STATUS_DYNAMIC_COUNTERS_NONE and \
1797 io_mode != IO_MODE_UNI:
1799 r_value, r_value_str, rg, rr = self.getRValues(r_type, status_type, dynamic_counters)
1801 r_value, r_value_str, rg, rr = 0, '000000000', '000', '000000'
1803 self.dq.update({'r' : r_value,
1809 if not quick and reread_cups_printers:
1810 self.updateCUPSPrinters()
1813 # Make sure there is some valid agent data for this r_value
1814 # If not, fall back to r_value == 0
1815 if r_value > 0 and self.mq.get('r%d-agent1-kind' % r_value, 0) == 0:
1817 self.dq.update({'r' : r_value,
1825 mq_agent_kind = self.mq.get('r%d-agent%d-kind' % (r_value, a), -1)
1827 if mq_agent_kind == -1:
1830 mq_agent_type = self.mq.get('r%d-agent%d-type' % (r_value, a), 0)
1831 mq_agent_sku = self.mq.get('r%d-agent%d-sku' % (r_value, a), '')
1835 log.debug("Looking for kind=%d, type=%d..." % (mq_agent_kind, mq_agent_type))
1836 for agent in agents:
1837 agent_kind = agent['kind']
1838 agent_type = agent['type']
1840 if agent_kind == mq_agent_kind and \
1841 agent_type == mq_agent_type:
1846 log.debug("found: r%d-kind%d-type%d" % (r_value, agent_kind, agent_type))
1848 agent_health = agent.get('health', AGENT_HEALTH_OK)
1849 agent_level = agent.get('level', 100)
1850 agent_level_trigger = agent.get('level-trigger',
1851 AGENT_LEVEL_TRIGGER_SUFFICIENT_0)
1853 log.debug("health=%d, level=%d, level_trigger=%d, status_code=%d" %
1854 (agent_health, agent_level, agent_level_trigger, status_code))
1856 query = 'agent_%s_%s' % (AGENT_types.get(agent_type, 'unknown'),
1857 AGENT_kinds.get(agent_kind, 'unknown'))
1859 agent_desc = self.queryString(query)
1860 query = 'agent_health_ok'
1862 # If printer is not in an error state, and
1863 # if agent health is OK, check for low supplies. If low, use
1864 # the agent level trigger description for the agent description.
1865 # Otherwise, report the agent health.
1866 if (status_code == STATUS_PRINTER_IDLE or status_code == STATUS_PRINTER_OUT_OF_INK) and \
1867 (agent_health == AGENT_HEALTH_OK or
1868 (agent_health == AGENT_HEALTH_FAIR_MODERATE and agent_kind == AGENT_KIND_HEAD)) and \
1869 agent_level_trigger >= AGENT_LEVEL_TRIGGER_MAY_BE_LOW:
1871 query = 'agent_level_%s' % AGENT_levels.get(agent_level_trigger, 'unknown')
1873 if tech_type in (TECH_TYPE_MONO_INK, TECH_TYPE_COLOR_INK):
1874 code = agent_type + STATUS_PRINTER_LOW_INK_BASE
1876 code = agent_type + STATUS_PRINTER_LOW_TONER_BASE
1878 self.dq['status-code'] = code
1879 self.dq['status-desc'] = self.queryString(code)
1881 self.dq['error-state'] = STATUS_TO_ERROR_STATE_MAP.get(code, ERROR_STATE_LOW_SUPPLIES)
1882 self.error_code = code
1883 self.sendEvent(self.error_code)
1885 if agent_level_trigger in \
1886 (AGENT_LEVEL_TRIGGER_PROBABLY_OUT, AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT):
1888 query = 'agent_level_out'
1890 query = 'agent_level_low'
1892 agent_health_desc = self.queryString(query)
1896 'agent%d-kind' % aa : agent_kind,
1897 'agent%d-type' % aa : agent_type,
1898 'agent%d-known' % aa : agent.get('known', False),
1899 'agent%d-sku' % aa : mq_agent_sku,
1900 'agent%d-level' % aa : agent_level,
1901 'agent%d-level-trigger' % aa : agent_level_trigger,
1902 'agent%d-ack' % aa : agent.get('ack', False),
1903 'agent%d-hp-ink' % aa : agent.get('hp-ink', False),
1904 'agent%d-health' % aa : agent_health,
1905 'agent%d-dvc' % aa : agent.get('dvc', 0),
1906 'agent%d-virgin' % aa : agent.get('virgin', False),
1907 'agent%d-desc' % aa : agent_desc,
1908 'agent%d-id' % aa : agent.get('id', 0),
1909 'agent%d-health-desc' % aa : agent_health_desc,
1913 query = 'agent_health_%s' % AGENT_healths.get(agent_health, AGENT_HEALTH_OK)
1914 agent_health_desc = self.queryString(query)
1918 'agent%d-kind' % aa : agent_kind,
1919 'agent%d-type' % aa : agent_type,
1920 'agent%d-known' % aa : False,
1921 'agent%d-sku' % aa : mq_agent_sku,
1922 'agent%d-level' % aa : agent_level,
1923 'agent%d-level-trigger' % aa : agent_level_trigger,
1924 'agent%d-ack' % aa : False,
1925 'agent%d-hp-ink' % aa : False,
1926 'agent%d-health' % aa : agent_health,
1927 'agent%d-dvc' % aa : 0,
1928 'agent%d-virgin' % aa : False,
1929 'agent%d-desc' % aa : agent_desc,
1930 'agent%d-id' % aa : 0,
1931 'agent%d-health-desc' % aa : agent_health_desc,
1937 log.debug("Not found: %d" % a)
1941 else: # Create agent keys for not-found devices
1944 if r_type > 0 and self.r_values is not None:
1945 r_value = self.r_values[0]
1947 # Make sure there is some valid agent data for this r_value
1948 # If not, fall back to r_value == 0
1949 if r_value > 0 and self.mq.get('r%d-agent1-kind', 0) == 0:
1954 mq_agent_kind = self.mq.get('r%d-agent%d-kind' % (r_value, a), 0)
1956 if mq_agent_kind == 0:
1959 mq_agent_type = self.mq.get('r%d-agent%d-type' % (r_value, a), 0)
1960 mq_agent_sku = self.mq.get('r%d-agent%d-sku' % (r_value, a), '')
1961 query = 'agent_%s_%s' % (AGENT_types.get(mq_agent_type, 'unknown'),
1962 AGENT_kinds.get(mq_agent_kind, 'unknown'))
1964 agent_desc = self.queryString(query)
1968 'agent%d-kind' % a : mq_agent_kind,
1969 'agent%d-type' % a : mq_agent_type,
1970 'agent%d-known' % a : False,
1971 'agent%d-sku' % a : mq_agent_sku,
1972 'agent%d-level' % a : 0,
1973 'agent%d-level-trigger' % a : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT,
1974 'agent%d-ack' % a : False,
1975 'agent%d-hp-ink' % a : False,
1976 'agent%d-health' % a : AGENT_HEALTH_MISINSTALLED,
1977 'agent%d-dvc' % a : 0,
1978 'agent%d-virgin' % a : False,
1979 'agent%d-health-desc' % a : self.queryString('agent_health_unknown'),
1980 'agent%d-desc' % a : agent_desc,
1981 'agent%d-id' % a : 0,
1987 self.__dict__[d.replace('-','_')] = self.dq[d]
1989 self.last_event = Event(self.device_uri, '', status_code, prop.username, 0, '', time.time())
1993 def isBusyOrInErrorState(self):
1995 self.queryDevice(quick=True)
1998 return self.error_state in (ERROR_STATE_ERROR, ERROR_STATE_BUSY)
2001 def isIdleAndNoError(self):
2003 self.queryDevice(quick=True)
2006 return self.error_state not in (ERROR_STATE_ERROR, ERROR_STATE_BUSY)
2009 def getPML(self, oid, desired_int_size=pml.INT_SIZE_INT): # oid => ( 'dotted oid value', pml type )
2010 channel_id = self.openPML()
2012 result_code, data, typ, pml_result_code = \
2013 hpmudext.get_pml(self.device_id, channel_id, pml.PMLToSNMP(oid[0]), oid[1])
2015 if pml_result_code > pml.ERROR_MAX_OK:
2016 log.debug("PML/SNMP GET %s failed (result code = 0x%x)" % (oid[0], pml_result_code))
2017 return pml_result_code, None
2019 converted_data = pml.ConvertFromPMLDataFormat(data, oid[1], desired_int_size)
2022 if oid[1] in (pml.TYPE_STRING, pml.TYPE_BINARY):
2024 log.debug("PML/SNMP GET %s (result code = 0x%x) returned:" %
2025 (oid[0], pml_result_code))
2028 log.debug("PML/SNMP GET %s (result code = 0x%x) returned: %s" %
2029 (oid[0], pml_result_code, repr(converted_data)))
2031 return pml_result_code, converted_data
2034 def setPML(self, oid, value): # oid => ( 'dotted oid value', pml type )
2035 channel_id = self.openPML()
2037 value = pml.ConvertToPMLDataFormat(value, oid[1])
2039 result_code, pml_result_code = \
2040 hpmudext.set_pml(self.device_id, channel_id, pml.PMLToSNMP(oid[0]), oid[1], value)
2043 if oid[1] in (pml.TYPE_STRING, pml.TYPE_BINARY):
2045 log.debug("PML/SNMP SET %s (result code = 0x%x) to:" %
2046 (oid[0], pml_result_code))
2049 log.debug("PML/SNMP SET %s (result code = 0x%x) to: %s" %
2050 (oid[0], pml_result_code, repr(value)))
2052 return pml_result_code
2055 def getDynamicCounter(self, counter, convert_to_int=True):
2056 dynamic_counters = self.mq.get('status-dynamic-counters', STATUS_DYNAMIC_COUNTERS_NONE)
2057 log.debug("Dynamic counters: %d" % dynamic_counters)
2058 if dynamic_counters != STATUS_DYNAMIC_COUNTERS_NONE:
2060 if dynamic_counters == STATUS_DYNAMIC_COUNTERS_LIDIL_0_5_4:
2061 self.printData(ldl.buildResetPacket(), direct=True)
2062 self.printData(ldl.buildDynamicCountersPacket(counter), direct=True)
2064 self.printData(pcl.buildDynamicCounter(counter), direct=True)
2066 value, tries, times_seen, sleepy_time, max_tries = 0, 0, 0, 0.1, 5
2077 time.sleep(sleepy_time)
2081 if 'CTR' in self.deviceID and \
2082 pat_dynamic_ctr.search(self.raw_deviceID) is not None:
2083 dev_counter, value = parseDynamicCounter(self.deviceID['CTR'], convert_to_int)
2085 if counter == dev_counter:
2086 self.printData(pcl.buildDynamicCounter(0), direct=True)
2087 # protect the value as a string during msg handling
2088 if not convert_to_int:
2092 if tries > max_tries:
2093 if dynamic_counters == STATUS_DYNAMIC_COUNTERS_LIDIL_0_5_4:
2094 self.printData(ldl.buildResetPacket())
2095 self.printData(ldl.buildDynamicCountersPacket(counter), direct=True)
2097 self.printData(pcl.buildDynamicCounter(0), direct=True)
2101 if dynamic_counters == STATUS_DYNAMIC_COUNTERS_LIDIL_0_5_4:
2102 self.printData(ldl.buildResetPacket())
2103 self.printData(ldl.buildDynamicCountersPacket(counter), direct=True)
2105 self.printData(pcl.buildDynamicCounter(counter), direct=True)
2108 raise Error(ERROR_DEVICE_DOES_NOT_SUPPORT_OPERATION)
2111 def readPrint(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=False):
2112 return self.__readChannel(self.openPrint, bytes_to_read, stream, timeout, allow_short_read)
2114 def readPCard(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=False):
2115 return self.__readChannel(self.openPCard, bytes_to_read, stream, timeout, allow_short_read)
2117 def readFax(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=False):
2118 return self.__readChannel(self.openFax, bytes_to_read, stream, timeout, allow_short_read)
2120 def readCfgUpload(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=False):
2121 return self.__readChannel(self.openCfgUpload, bytes_to_read, stream, timeout, allow_short_read)
2123 def readEWS(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True):
2124 return self.__readChannel(self.openEWS, bytes_to_read, stream, timeout, allow_short_read)
2126 def readEWS_LEDM(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True):
2127 return self.__readChannel(self.openEWS_LEDM, bytes_to_read, stream, timeout, allow_short_read)
2129 def readLEDM(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True):
2130 return self.__readChannel(self.openLEDM, bytes_to_read, stream, timeout, allow_short_read)
2132 def readSoapFax(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True):
2133 return self.__readChannel(self.openSoapFax, bytes_to_read, stream, timeout, allow_short_read)
2135 def readMarvellFax(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True):
2136 return self.__readChannel(self.openMarvellFax, bytes_to_read, stream, timeout, allow_short_read)
2138 def readWifiConfig(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True):
2139 return self.__readChannel(self.openWifiConfig, bytes_to_read, stream, timeout, allow_short_read)
2141 def __readChannel(self, opener, bytes_to_read, stream=None,
2142 timeout=prop.read_timeout, allow_short_read=False):
2144 channel_id = opener()
2146 log.debug("Reading channel %d (device-id=%d, bytes_to_read=%d, allow_short=%s, timeout=%d)..." %
2147 (channel_id, self.device_id, bytes_to_read, allow_short_read, timeout))
2155 result_code, data = \
2156 hpmudext.read_channel(self.device_id, channel_id, bytes_to_read, timeout)
2158 log.debug("Result code=%d" % result_code)
2162 if result_code == hpmudext.HPMUD_R_IO_TIMEOUT:
2163 log.debug("I/O timeout")
2166 if result_code != hpmudext.HPMUD_R_OK:
2167 log.error("Channel read error")
2168 raise Error(ERROR_DEVICE_IO_ERROR)
2171 log.debug("End of data")
2175 buffer = ''.join([buffer, data])
2181 if self.callback is not None:
2184 if num_bytes == bytes_to_read:
2185 log.debug("Full read complete.")
2188 if allow_short_read and num_bytes < bytes_to_read:
2189 log.debug("Allowed short read of %d of %d bytes complete." % (num_bytes, bytes_to_read))
2193 log.debug("Returned %d total bytes in buffer." % num_bytes)
2196 log.debug("Saved %d total bytes to stream." % num_bytes)
2200 def writePrint(self, data):
2201 return self.__writeChannel(self.openPrint, data)
2203 def writePCard(self, data):
2204 return self.__writeChannel(self.openPCard, data)
2206 def writeFax(self, data):
2207 return self.__writeChannel(self.openFax, data)
2209 def writeEWS(self, data):
2210 return self.__writeChannel(self.openEWS, data)
2212 def writeEWS_LEDM(self, data):
2213 return self.__writeChannel(self.openEWS_LEDM, data)
2215 def writeLEDM(self, data):
2216 return self.__writeChannel(self.openLEDM, data)
2218 def writeCfgDownload(self, data):
2219 return self.__writeChannel(self.openCfgDownload, data)
2221 def writeSoapFax(self, data):
2222 return self.__writeChannel(self.openSoapFax, data)
2224 def writeMarvellFax(self, data):
2225 return self.__writeChannel(self.openMarvellFax, data)
2227 def writeWifiConfig(self, data):
2228 return self.__writeChannel(self.openWifiConfig, data)
2230 def __writeChannel(self, opener, data):
2231 channel_id = opener()
2232 buffer, bytes_out, total_bytes_to_write = data, 0, len(data)
2234 log.debug("Writing %d bytes to channel %d (device-id=%d)..." % (total_bytes_to_write, channel_id, self.device_id))
2236 while len(buffer) > 0:
2237 result_code, bytes_written = \
2238 hpmudext.write_channel(self.device_id, channel_id,
2239 buffer[:prop.max_message_len])
2241 log.debug("Result code=%d" % result_code)
2243 if result_code != hpmudext.HPMUD_R_OK:
2244 log.error("Channel write error")
2245 raise Error(ERROR_DEVICE_IO_ERROR)
2247 buffer = buffer[prop.max_message_len:]
2248 bytes_out += bytes_written
2250 if self.callback is not None:
2253 if total_bytes_to_write != bytes_out:
2254 raise Error(ERROR_DEVICE_IO_ERROR)
2259 def writeEmbeddedPML(self, oid, value, style=1, direct=True):
2261 func = pcl.buildEmbeddedPML2
2263 func = pcl.buildEmbeddedPML
2265 data = func(pcl.buildPCLCmd('&', 'b', 'W',
2266 pml.buildEmbeddedPMLSetPacket(oid[0],
2272 self.printData(data, direct=direct, raw=True)
2275 def printGzipFile(self, file_name, printer_name=None, direct=False, raw=True, remove=False):
2276 return self.printFile(file_name, printer_name, direct, raw, remove)
2278 def printParsedGzipPostscript(self, print_file, printer_name=None):
2279 # always: direct=False, raw=False, remove=True
2283 log.error("File not found: %s" % print_file)
2286 temp_file_fd, temp_file_name = utils.make_temp_file()
2287 f = gzip.open(print_file, 'r')
2290 while not x.startswith('%PY_BEGIN'):
2291 os.write(temp_file_fd, x)
2296 while not x.startswith('%PY_END'):
2300 SUBS = {'VERSION' : prop.version,
2301 'MODEL' : self.model_ui,
2302 'URI' : self.device_uri,
2304 'SERIAL' : self.serial,
2307 'DEVNODE' : self.dev_file,
2310 if self.bus == 'net':
2311 SUBS['DEVNODE'] = 'n/a'
2314 SUBS['PORT'] = 'n/a'
2317 os.write(temp_file_fd, s % SUBS)
2319 os.write(temp_file_fd, f.read())
2321 os.close(temp_file_fd)
2323 self.printFile(temp_file_name, printer_name, direct=False, raw=False, remove=True)
2325 def printFile(self, file_name, printer_name=None, direct=False, raw=True, remove=False):
2326 is_gzip = os.path.splitext(file_name)[-1].lower() == '.gz'
2328 if printer_name is None:
2329 printer_name = self.first_cups_printer
2331 if not printer_name:
2332 raise Error(ERROR_NO_CUPS_QUEUE_FOUND_FOR_DEVICE)
2334 log.debug("Printing file '%s' to queue '%s' (gzip=%s, direct=%s, raw=%s, remove=%s)" %
2335 (file_name, printer_name, is_gzip, direct, raw, remove))
2337 if direct: # implies raw==True
2339 self.writePrint(gzip.open(file_name, 'r').read())
2341 self.writePrint(file(file_name, 'r').read())
2344 if not utils.which('lpr'):
2351 c = 'gunzip -c %s | lp -c -d%s %s' % (file_name, printer_name, lp_opt)
2353 c = 'lp -c -d%s %s %s' % (printer_name, lp_opt, file_name)
2356 exit_code = os.system(c)
2359 log.error("Print command failed with exit code %d!" % exit_code)
2362 os.remove(file_name)
2365 raw_str, rem_str = '', ''
2366 if raw: raw_str = '-o raw'
2367 if remove: rem_str = '-r'
2370 c = 'gunzip -c %s | lpr %s %s -P%s' % (file_name, raw_str, rem_str, printer_name)
2372 c = 'lpr -P%s %s %s %s' % (printer_name, raw_str, rem_str, file_name)
2375 exit_code = os.system(c)
2378 log.error("Print command failed with exit code %d!" % exit_code)
2381 def printTestPage(self, printer_name=None):
2382 return self.printParsedGzipPostscript(os.path.join( prop.home_dir, 'data',
2383 'ps', 'testpage.ps.gz' ), printer_name)
2386 def printData(self, data, printer_name=None, direct=True, raw=True):
2388 #log.debug("printData(direct=%s, raw=%s)" % (direct, raw))
2390 self.writePrint(data)
2392 temp_file_fd, temp_file_name = utils.make_temp_file()
2393 os.write(temp_file_fd, data)
2394 os.close(temp_file_fd)
2396 self.printFile(temp_file_name, printer_name, False, raw, remove=True)
2399 def cancelJob(self, jobid):
2400 cups.cancelJob(jobid)
2401 self.error_code = STATUS_PRINTER_CANCELING
2402 self.sendEvent(self.error_code)
2405 def queryHistory(self):
2410 device_uri, history = self.service.GetHistory(self.device_uri)
2411 except dbus.exceptions.DBusException, e:
2412 log.error("dbus call to GetHistory() failed.")
2418 result.append(Event(*tuple(h)))
2421 self.error_code = result[0].event_code
2423 self.error_code = STATUS_UNKNOWN
2425 self.error_state = STATUS_TO_ERROR_STATE_MAP.get(self.error_code, ERROR_STATE_CLEAR)
2428 self.error_code = STATUS_UNKNOWN
2429 self.error_state = ERROR_STATE_CLEAR
2434 def getEWSUrl(self, url, stream):
2437 url2 = "%s&loc=%s" % (self.device_uri.replace('hpfax:', 'hp:'), url)
2440 url2 = "http://%s%s" % (self.host, url)
2442 status, ip = hpmudext.get_zc_ip_address(self.zc)
2443 if status == hpmudext.HPMUD_R_OK:
2444 url2 = "http://%s%s" % (ip, url)
2447 log.debug("Opening: %s" % url2)
2448 opener = LocalOpener({})
2450 f = opener.open(url2, data)
2452 log.error("Status read failed: %s" % url2)
2457 stream.write(f.read())
2464 def getEWSUrl_LEDM(self, url, stream, footer=""):
2466 url2 = "%s&loc=%s" % (self.device_uri.replace('hpfax:', 'hp:'), url)
2468 opener = LocalOpenerEWS_LEDM({})
2471 return opener.open_hp(url2, data, footer)
2473 return opener.open_hp(url2, data)
2475 log.debug("Status read failed: %s" % url2)
2477 self.closeEWS_LEDM()
2479 def getUrl_LEDM(self, url, stream, footer=""):
2481 url2 = "%s&loc=%s" % (self.device_uri.replace('hpfax:', 'hp:'), url)
2483 opener = LocalOpener_LEDM({})
2486 return opener.open_hp(url2, data, footer)
2488 return opener.open_hp(url2, data)
2490 log.debug("Status read failed: %s" % url2)
2495 def FetchLEDMUrl(self, url, footer=""):
2496 data_fp = cStringIO.StringIO()
2498 data = self.getUrl_LEDM(url, data_fp, footer)
2500 data = self.getUrl_LEDM(url, data_fp)
2502 data = data.split('\r\n\r\n', 1)[1]
2504 data = status.clean(data)
2507 #-------------------------For LEDM SOAP PROTOCOL(FAX) Devices----------------------------------------------------------------------#
2509 def FetchEWS_LEDMUrl(self, url, footer=""):
2510 data_fp = cStringIO.StringIO()
2512 data = self.getEWSUrl_LEDM(url, data_fp, footer)
2514 data = self.getEWSUrl_LEDM(url, data_fp)
2516 data = data.split('\r\n\r\n', 1)[1]
2518 data = status.clean(data)
2521 def readAttributeFromXml_EWS(self, uri, attribute):
2522 stream = cStringIO.StringIO()
2523 data = self.FetchEWS_LEDMUrl(uri)
2525 log.error("Unable To read the XML data from device")
2527 xmlDict = utils.XMLToDictParser().parseXML(data)
2529 return str(xmlDict[attribute])
2533 #---------------------------------------------------------------------------------------------------#
2535 def readAttributeFromXml(self,uri,attribute):
2536 stream = cStringIO.StringIO()
2537 data = self.FetchLEDMUrl(uri)
2539 log.error("Unable To read the XML data from device")
2541 xmlDict = utils.XMLToDictParser().parseXML(data)
2543 return str(xmlDict[attribute])
2547 def downloadFirmware(self, usb_bus_id=None, usb_device_id=None): # Note: IDs not currently used
2549 filename = os.path.join(prop.data_dir, "firmware", self.model.lower() + '.fw.gz')
2552 if os.path.exists(filename):
2553 log.debug("Downloading firmware file '%s'..." % filename)
2555 # Write to port directly (no MUD) so that HAL can enumerate the printer
2556 if 0: # this currently doesn't work because usblp is loaded...
2557 #if usb_bus_id is not None and usb_device_id is not None:
2559 p = "/dev/bus/usb/%s/%s" % (usb_bus_id, usb_device_id)
2560 log.debug("Writing to %s..." % p)
2561 f = os.open(p, os.O_RDWR)
2562 x = gzip.open(filename).read()
2567 except (OSError, IOError), e:
2568 log.error("An error occured: %s" % e)
2572 bytes_written = self.writePrint(gzip.open(filename).read())
2573 log.debug("%s bytes downloaded." % utils.commafy(bytes_written))
2578 log.error("An error occured: %s" % e.msg)
2580 log.error("Firmware file '%s' not found." % filename)
2585 # ********************************** Support classes/functions
2588 class xStringIO(StringIO.StringIO):
2589 def makefile(self, x, y):
2592 # URLs: hp:/usb/HP_LaserJet_3050?serial=00XXXXXXXXXX&loc=/hp/device/info_device_status.xml
2593 class LocalOpener(urllib.URLopener):
2594 def open_hp(self, url, dev):
2595 log.debug("open_hp(%s)" % url)
2597 match_obj = http_pat_url.search(url)
2598 bus = match_obj.group(1) or ''
2599 model = match_obj.group(2) or ''
2600 serial = match_obj.group(3) or ''
2601 device = match_obj.group(4) or ''
2602 loc = match_obj.group(5) or ''
2605 dev.writeEWS("""GET %s HTTP/1.0\nContent-Length:0\nHost:localhost\nUser-Agent:hplip\n\n""" % loc)
2609 while dev.readEWS(8192, reply, timeout=1):
2613 log.log_data(reply.getvalue())
2615 response = httplib.HTTPResponse(reply)
2618 if response.status != httplib.OK:
2619 raise Error(ERROR_DEVICE_STATUS_NOT_AVAILABLE)
2623 # URLs: hp:/usb/HP_OfficeJet_7500?serial=00XXXXXXXXXX&loc=/hp/device/info_device_status.xml
2624 class LocalOpenerEWS_LEDM(urllib.URLopener):
2625 def open_hp(self, url, dev, foot=""):
2626 log.debug("open_hp(%s)" % url)
2628 match_obj = http_pat_url.search(url)
2629 loc = url.split("=")[url.count("=")]
2634 dev.writeEWS_LEDM("""%s""" % foot)
2636 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)))
2637 dev.writeEWS_LEDM("""%s""" % foot)
2639 dev.writeEWS_LEDM("""GET %s HTTP/1.1\r\nAccept: text/plain\r\nHost:localhost\r\nUser-Agent:hplip\r\n\r\n""" % loc)
2643 while dev.readEWS_LEDM(512, reply, timeout=3):
2647 return reply.getvalue()
2649 # URLs: hp:/usb/HP_OfficeJet_7500?serial=00XXXXXXXXXX&loc=/hp/device/info_device_status.xml
2650 class LocalOpener_LEDM(urllib.URLopener):
2651 def open_hp(self, url, dev, foot=""):
2652 log.debug("open_hp(%s)" % url)
2654 match_obj = http_pat_url.search(url)
2655 loc = url.split("=")[url.count("=")]
2660 dev.writeLEDM("""%s""" % foot)
2662 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)))
2663 dev.writeLEDM("""%s""" % foot)
2665 dev.writeLEDM("""GET %s HTTP/1.1\r\nAccept: text/plain\r\nHost:localhost\r\nUser-Agent:hplip\r\n\r\n""" % loc)
2669 while dev.readLEDM(512, reply, timeout=3):
2673 return reply.getvalue()