Changeset 3025
- Timestamp:
- 10/04/06 00:21:34 (18 years ago)
- Location:
- pykota/trunk
- Files:
-
- 6 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/conf/pykota.conf.sample
r3012 r3025 1143 1143 1144 1144 1145 # Sets the maximum number of seconds to wait for the printer 1146 # being in 'printing' mode once the job has been sent to it. 1147 # Once this delay is expired, PyKota will consider this job 1148 # will never be printed, aborts the hardware accounting 1149 # process, and uses the latest internal page counter value seen. 1150 # 1151 # Increasing this value, or setting it to 0, may help with some 1152 # printers which don't conform to RFC3805. Problem reported on a 1153 # Samsung ML2551n gave a way for clever students to bypass 1154 # hardware accounting entirely by removing the paper from 1155 # the paper tray before the job had begun to print, then 1156 # waiting 60 seconds, and putting the paper back in the tray... 1157 # 1158 # IMPORTANT : always ensure that your printers' firmware is up 1159 # to date. 1160 # 1161 # This directive can be set either globally or on a per printer 1162 # basis. 1163 # 1164 # When not set, an hardcoded value of 60 seconds is used. 1165 # When set to 0, PyKota will wait indefinitely until the 1166 # printer switches to the 'printing' status. 1167 noprintingmaxdelay : 60 -
pykota/trunk/NEWS
r3018 r3025 22 22 PyKota NEWS : 23 23 24 - 1.25alpha13 (2006-10-04) : 25 26 - Introduced the 'noprintingmaxdelay' directive to workaround 27 some buggy printers when hardware accounting is used. 28 29 - Improved the reliability of hardware accounting. 30 24 31 - 1.25alpha12 (2006-09-15) : 25 32 -
pykota/trunk/pykota/accounters/pjl.py
r2830 r3025 131 131 def waitPrinting(self) : 132 132 """Waits for printer status being 'printing'.""" 133 try : 134 noprintingmaxdelay = int(self.parent.filter.config.getNoPrintingMaxDelay(self.parent.filter.PrinterName)) 135 except (TypeError, AttributeError) : # NB : AttributeError in testing mode because I'm lazy ! 136 noprintingmaxdelay = NOPRINTINGMAXDELAY 137 self.parent.filter.logdebug("No max delay defined for printer %s, using %i seconds." % (self.parent.filter.PrinterName, noprintingmaxdelay)) 138 if not noprintingmaxdelay : 139 self.parent.filter.logdebug("Will wait indefinitely until printer %s is in 'printing' state." % self.parent.filter.PrinterName) 140 else : 141 self.parent.filter.logdebug("Will wait until printer %s is in 'printing' state or %i seconds have elapsed." % (self.parent.filter.PrinterName, noprintingmaxdelay)) 133 142 previousValue = self.parent.getLastPageCounter() 134 143 timebefore = time.time() … … 151 160 self.parent.filter.printInfo("Printer %s is lying to us !!!" % self.parent.filter.PrinterName, "warn") 152 161 break 153 elif (time.time() - timebefore) > NOPRINTINGMAXDELAY:162 elif noprintingmaxdelay and ((time.time() - timebefore) > noprintingmaxdelay) : 154 163 # More than X seconds without the printer being in 'printing' mode 155 164 # We can safely assume this won't change if printer is now 'idle' -
pykota/trunk/pykota/accounters/snmp.py
r2877 r3025 22 22 # 23 23 # 24 25 """This module is used to extract printer's internal page counter 26 and status informations using SNMP queries. 27 28 The values extracted are defined at least in RFC3805 and RFC2970. 29 """ 24 30 25 31 ITERATIONDELAY = 1.5 # 1.5 Second … … 65 71 } 66 72 hrPrinterDetectedErrorStateOID = "1.3.6.1.2.1.25.3.5.1.2.1" # SNMPv2-SMI::mib-2.25.3.5.1.2.1 73 printerDetectedErrorStateValues = [ { 128 : 'Low Paper', 74 64 : 'No Paper', 75 32 : 'Low Toner', 76 16 : 'No Toner', 77 8 : 'Door Open', 78 4 : 'Jammed', 79 2 : 'Offline', 80 1 : 'Service Requested', 81 }, 82 { 128 : 'Input Tray Missing', 83 64 : 'Output Tray Missing', 84 32 : 'Marker Supply Missing', 85 16 : 'Output Near Full', 86 8 : 'Output Full', 87 4 : 'Input Tray Empty', 88 2 : 'Overdue Preventive Maintainance', 89 1 : 'Not Assigned in RFC3805', 90 }, 91 ] 92 errorConditions = [ 'No Paper', 93 # 'No Toner', 94 'Door Open', 95 'Jammed', 96 'Offline', 97 'Service Requested', 98 'Input Tray Missing', 99 'Output Tray Missing', 100 # 'Marker Supply Missing', 101 'Output Full', 102 'Input Tray Empty', 103 ] 67 104 prtConsoleDisplayBufferTextOID = "1.3.6.1.2.1.43.16.5.1.2.1.1" # SNMPv2-SMI::mib-2.43.16.5.1.2.1.1 105 68 106 class BaseHandler : 69 107 """A class for SNMP print accounting.""" … … 76 114 self.community = "public" 77 115 self.port = 161 116 self.initValues() 117 118 def initValues(self) : 119 """Initializes SNMP values.""" 78 120 self.printerInternalPageCounter = None 79 121 self.printerStatus = None 80 122 self.deviceStatus = None 123 self.printerDetectedErrorState = None 124 self.consoleDisplayBufferText = None 125 self.timebefore = time.time() # resets timer also in case of error 81 126 82 127 def retrieveSNMPValues(self) : … … 84 129 raise RuntimeError, "You have to overload this method." 85 130 131 def extractErrorStates(self, value) : 132 """Returns a list of textual error states from a binary value.""" 133 states = [] 134 for i in range(min(len(value), len(printerDetectedErrorStateValues))) : 135 byte = ord(value[i]) 136 bytedescription = printerDetectedErrorStateValues[i] 137 for (k, v) in bytedescription.items() : 138 if byte & k : 139 states.append(v) 140 return states 141 142 def checkIfError(self, errorstates) : 143 """Checks if any error state is fatal or not.""" 144 for err in errorstates : 145 if err in errorConditions : 146 return True 147 return False 148 86 149 def waitPrinting(self) : 87 150 """Waits for printer status being 'printing'.""" 151 try : 152 noprintingmaxdelay = int(self.parent.filter.config.getNoPrintingMaxDelay(self.parent.filter.PrinterName)) 153 except (TypeError, AttributeError) : # NB : AttributeError in testing mode because I'm lazy ! 154 noprintingmaxdelay = NOPRINTINGMAXDELAY 155 self.parent.filter.logdebug("No max delay defined for printer %s, using %i seconds." % (self.parent.filter.PrinterName, noprintingmaxdelay)) 156 if not noprintingmaxdelay : 157 self.parent.filter.logdebug("Will wait indefinitely until printer %s is in 'printing' state." % self.parent.filter.PrinterName) 158 else : 159 self.parent.filter.logdebug("Will wait until printer %s is in 'printing' state or %i seconds have elapsed." % (self.parent.filter.PrinterName, noprintingmaxdelay)) 88 160 previousValue = self.parent.getLastPageCounter() 89 timebefore = time.time()90 161 firstvalue = None 91 162 while 1: … … 107 178 self.parent.filter.printInfo("Printer %s is lying to us !!!" % self.parent.filter.PrinterName, "warn") 108 179 break 109 elif (time.time() - timebefore) > NOPRINTINGMAXDELAY : 180 elif noprintingmaxdelay \ 181 and ((time.time() - self.timebefore) > noprintingmaxdelay) \ 182 and not self.checkIfError(self.printerDetectedErrorState) : 110 183 # More than X seconds without the printer being in 'printing' mode 111 184 # We can safely assume this won't change if printer is now 'idle' … … 135 208 dstatusAsString = deviceStatusValues.get(self.deviceStatus) 136 209 idle_flag = 0 137 if (pstatusAsString == 'idle') or \ 138 ((pstatusAsString == 'other') and \ 139 (dstatusAsString == 'running')) : 210 if (not self.checkIfError(self.printerDetectedErrorState)) \ 211 and ((pstatusAsString == 'idle') or \ 212 ((pstatusAsString == 'other') and \ 213 (dstatusAsString == 'running'))) : 140 214 idle_flag = 1 # Standby / Powersave is considered idle 141 215 if idle_flag : … … 173 247 tuple([int(i) for i in pageCounterOID.split('.')]), \ 174 248 tuple([int(i) for i in hrPrinterStatusOID.split('.')]), \ 175 tuple([int(i) for i in hrDeviceStatusOID.split('.')])) 249 tuple([int(i) for i in hrDeviceStatusOID.split('.')]), \ 250 tuple([int(i) for i in hrPrinterDetectedErrorStateOID.split('.')]), \ 251 tuple([int(i) for i in prtConsoleDisplayBufferTextOID.split('.')])) 176 252 if errorIndication : 177 253 self.parent.filter.printInfo("SNMP Error : %s" % errorIndication, "error") 254 self.initValues() 178 255 elif errorStatus : 179 256 self.parent.filter.printInfo("SNMP Error : %s at %s" % (errorStatus.prettyPrint(), \ … … 184 261 self.printerStatus = int(varBinds[1][1].prettyPrint()) 185 262 self.deviceStatus = int(varBinds[2][1].prettyPrint()) 186 self.parent.filter.logdebug("SNMP answer decoded : PageCounter : %s PrinterStatus : '%s' DeviceStatus : '%s'" \ 263 self.printerDetectedErrorState = self.extractErrorStates(str(varBinds[3][1])) 264 self.consoleDisplayBufferText = varBinds[4][1].prettyPrint() 265 self.parent.filter.logdebug("SNMP answer decoded : PageCounter : %s PrinterStatus : '%s' DeviceStatus : '%s' PrinterErrorState : '%s' ConsoleDisplayBuffer : '%s'" \ 187 266 % (self.printerInternalPageCounter, \ 188 267 printerStatusValues.get(self.printerStatus), \ 189 deviceStatusValues.get(self.deviceStatus))) 268 deviceStatusValues.get(self.deviceStatus), \ 269 self.printerDetectedErrorState, \ 270 self.consoleDisplayBufferText)) 190 271 else : 191 272 class Handler(BaseHandler) : … … 199 280 req.apiAlphaGetPdu().apiAlphaSetVarBindList((pageCounterOID, ver.Null()), \ 200 281 (hrPrinterStatusOID, ver.Null()), \ 201 (hrDeviceStatusOID, ver.Null())) 282 (hrDeviceStatusOID, ver.Null()), \ 283 (hrPrinterDetectedErrorStateOID, ver.Null()), \ 284 (prtConsoleDisplayBufferTextOID, ver.Null())) 202 285 tsp = Manager() 203 286 try : … … 211 294 def handleAnswer(self, wholeMsg, notusedhere, req): 212 295 """Decodes and handles the SNMP answer.""" 213 self.parent.filter.logdebug("SNMP answer : '%s'" % repr(wholeMsg))214 296 ver = alpha.protoVersions[alpha.protoVersionId1] 215 297 rsp = ver.Message() … … 232 314 self.printerStatus = self.values[1] 233 315 self.deviceStatus = self.values[2] 234 self.parent.filter.logdebug("SNMP answer decoded : PageCounter : %s PrinterStatus : '%s' DeviceStatus : '%s'" \ 316 self.printerDetectedErrorState = self.extractErrorStates(self.values[3]) 317 self.consoleDisplayBufferText = self.values[4] 318 self.parent.filter.logdebug("SNMP answer decoded : PageCounter : %s PrinterStatus : '%s' DeviceStatus : '%s' PrinterErrorState : '%s' ConsoleDisplayBuffer : '%s'" \ 235 319 % (self.printerInternalPageCounter, \ 236 320 printerStatusValues.get(self.printerStatus), \ 237 deviceStatusValues.get(self.deviceStatus))) 321 deviceStatusValues.get(self.deviceStatus), \ 322 self.printerDetectedErrorState, \ 323 self.consoleDisplayBufferText)) 238 324 except IndexError : 239 325 self.parent.filter.logdebug("SNMP answer is incomplete : %s" % str(self.values)) -
pykota/trunk/pykota/config.py
r2909 r3025 557 557 raise PyKotaConfigError, _("Incorrect value %s for the duplicatesdelay directive in section %s") % (str(duplicatesdelay), printername) 558 558 559 def getNoPrintingMaxDelay(self, printername) : 560 """Returns the max number of seconds to wait for the printer to be in 'printing' mode.""" 561 try : 562 maxdelay = self.getPrinterOption(printername, "noprintingmaxdelay") 563 except PyKotaConfigError : 564 return None # tells to use hardcoded value 565 else : 566 try : 567 maxdelay = int(maxdelay) 568 if maxdelay < 0 : 569 raise ValueError 570 except (TypeError, ValueError) : 571 raise PyKotaConfigError, _("Incorrect value %s for the noprintingmaxdelay directive in section %s") % (str(maxdelay), printername) 572 else : 573 return maxdelay 574 559 575 def getWinbindSeparator(self) : 560 576 """Returns the winbind separator's value if it is set, else None.""" -
pykota/trunk/pykota/version.py
r3018 r3025 22 22 # 23 23 24 __version__ = "1.25alpha1 2_unofficial"24 __version__ = "1.25alpha13_unofficial" 25 25 26 26 __doc__ = "PyKota : a complete Printing Quota Solution for CUPS."