Now that Patrick has so kindly added hooks for calling external programs to
get sync/waitend/pagecount information from a printer, I've found it's not
that bad to deal with a Xerox Phaser 5400 printer. From what I've been told
about the geneology of the Phaser 5400 by some of the more friendly Xerox
support personel, this likely will work with the DocuPrint N??25 series
printers, too.
Attached is a perl script check_printer_status.pl, along with a config file
check_printer_status.xml containing printer-specific information. I only use
this program with a Phaser 5400; your mileage may vary with a DocuPrint.
To use this program, do the following:
0. you need perl with Net::SNMP installed; go get if if you don't
have it already
1. install check_printer_status.pl and config file somewhere
2. create symbolic links to it titled "check_printer_waitend.pl"
and "check_printer_pagecount.pl", likely in the same directory
3. edit check_printer_status.pl:
- change perl path to your perl installation path
- change path to default XML config file to wherever you put yours
4. the entry for "phaser5400" in ifhp.conf should look like this:
[ phaser5400 ]
tc=hp4000_pcl
appsocket
sync=|/s/lprng-3.8/sbin/check_printer_status.pl
#sync
pagecount=|/s/lprng-3.8/sbin/check_printer_pagecount.pl
#pagecount
waitend=|/s/lprng-3.8/sbin/check_printer_waitend.pl
#waitend
(Again, change paths to your installation path for this script.)
For large jobs, you may need to increase the lpd timeout for the printer; I
haven't been able to stress-test this printer with lots of large jobs yet.
If anyone uses this program for other printer models, please report back any
config file changes you needed to make to get it to work...
My first impression of this printer, despite Xerox support staff that won't
talk to you if you have questions about anything beyond how to use their
Windows printer driver, is this is a nice printer. Supports PS version 3.
Looks like it is a PostScript engine with PCL 5e/6 emulator, not the other way
around. Renders pages fast, too. Documents that would not print on our HP
LaserJet 8000/8100's print on this printer. Time will tell how it holds up.
The duplexing mechanism is interesting on this printer, much like that of the
Tektronix Phaser 850: the printer will print one side of the page, send it to
the output tray, then pull it back in after the paper was pushed half-way out.
If the printer can render pages fast enough, it will keep 2 pages moving
through the paper mechanism (two half-printed pages followed by two completed
pages when in duplex mode).
--
============================================================================
John Perkins | University of Wisconsin-Madison
Associate Researcher | Department of Computer Science
[EMAIL PROTECTED] | 1210 W. Dayton St.
608-262-0438/608-262-9997 FAX | Madison, WI 53706-1685
============================================================================
<config>
<snmp_params
community="public"
timeout="5"
retries="3" >
</snmp_params>
<printerdata
name="phaser850"
pagecount_oid=".1.3.6.1.2.1.43.10.2.1.4.1"
jobstatus_oid=".1.3.6.1.4.1.253.8.59.6.1.1.9"
display_oid=".1.3.6.1.2.1.43.16.5.1.2.1.1"
status_ok="17">
<status> </status>
</printerdata>
<printerdata
name="phaser5400"
pagecount_oid=".1.3.6.1.2.1.43.10.2.1.4.1.1"
jobstatus_oid=".1.3.6.1.4.1.253.8.59.6.1.1.9"
display_oid=".1.3.6.1.2.1.43.16.5.1.2.1.1"
status_ok="17">
<status
Canceling.Job = "10007"
Clear.Paper.Path = "40022"
Close.Covers = "40105"
Close.Stacker.Door = "40105"
Close.Tray = "40104"
Disk.Error = "32000"
Disk.Full = "32002"
Duplex.Jam = "40093"
Duplex.Unit.Fail = "40124"
Exit.Jam = "40022"
Fan.Failure = "50006"
Flash.Error = "40053"
Flash.Full = "30036"
Flushing = "10007"
Format.Failed = "40083"
Fuser.Failure = "50011"
Initializing... = "10011"
Insert.MBF = "40026"
Insert.Tray = "40026"
Install.Print = "40046"
IOT.NVM.Fail = "40053"
Laser.Failure = "50013"
Open.Extend.MBF = "40053"
Load.Tray = "41200"
Low.Paper = "41200"
Maintenance.Kit = "35075"
Manual.Feed = "41100"
Memory.Failure = "40063"
Motor.Failure = "50023"
NV.Memory.Fail = "40053"
Offline = "10001"
Open.Rear.Tray.Dr = "40022"
Open.Stacker.Door = "30105"
PCL.Out.of.Memory = "30016"
Paper.Jam = "42100"
Paper.Size.Jam = "42100"
Please.Wait = "10024"
Power.Saver.On = "10000"
Print.Cartridge.OEM.ID = "40005"
Print.Using = "10023"
Processing = "10023"
Ready = "10001"
Remove.Output.From = "40019"
Remove.Print.Cart = "40047"
Replace.Print.Cartridge = "40046"
Stacker.Bin.Fail = "30107"
Stacker.Jam = "42100"
Toner.Low = "10006"
Tray...Jam = "42100"
Tray.1.Failure = "50020"
Tray.2.Failure = "50021"
Tray.3.Failure = "50022"
Tray...Empty = "41200"
Waiting = "10024"
Warming.Up = "10003"></status>
</printerdata>
</config>
#! /s/perl-5.6.1/bin/perl -w
#
# usage:
# check_printer_status
#
#
# Do SNMP query of printer; return PJL-style information for ifhp
# (must have ifhp-3.5.8a3 or newer)
#
# Originally written to deal with Xerox appsocket printers, but could
# easily work with other printers, too.
#
# Symlink this printer as 3 separate names. I've used the following:
# check_printer_status (status check)
# check_printer_waitend (EOJ check--will spin until EOJ comes back)
# check_printer_pagecount (pagecount query)
#
#BEGIN {
# if ($0 =~ m/^(.*?)[\/\\]([^\/\\]+)$/) {
# $runtimedir = $1;
# $PROGNAME = $2;
# }
#}
use strict;
use Net::SNMP;
use XML::Simple;
use Data::Dumper;
# XML config file containing printer-specific information
my $xml_config="/s/lprng-3.8/common/sbin/check_printer_status.xml";
# other variables
my $printcap;
my $host;
my $model;
my $ifhp;
my $error;
my $response;
my $status;
my $pagecount;
my $complete=0;
my $verbose=0;
my $pjl_status_code;
my $display;
if ($ENV{PRINTCAP_ENTRY}) {
# get PRINTCAP_ENTRY
$printcap = $ENV{PRINTCAP_ENTRY};
# get host from :lp PRINTCAP_ENTRY
foreach (split (/:/, $printcap)) {
if (/^lp=/) {
$host = $_;
$host =~ s/lp=//;
$host =~ s/\%\S*\s*//;
}
if (/^ifhp=/) {
$ifhp = $_;
$ifhp =~ s/ifhp=//;
foreach (split(/,\s/, $ifhp)) {
if (/model=/) {
$model = $_;
$model =~ s/model=//;
}
}
$model =~ s/\s*//g;
}
}
} else {
die("No host or model defined!\n");
}
print "Host: $host\tModel: $model\n" if $verbose;
# parse XML config file
# slurp in all printer-specific OID info,
my $ref = XMLin($xml_config, forcearray => 0);
# SNMP parameters
# Not sure why the following line doesn't work...I suspect something
# strange in XML::Simple...Nate thinks it's in XML::Parser called from
# XML::Simple.
#my $community=$ref->{snmp_params}->{community};
my $community=substr($ref->{snmp_params}->{community}, 0);
my $timeout=$ref->{snmp_params}->{timeout};
my $retries=$ref->{snmp_params}->{retries};
my $session;
if ( $host eq "" ) {
die "No printer name defined or \$PRINTER set\n";
}
#print "progname: $0\n";
print Dumper($ref) if $verbose;
print "SNMP params: host $host, community $community, timeout $timeout, retries
$retries\n" if $verbose;
($session, $error) = Net::SNMP->session(-hostname => $host,
-community => $community,
-timeout => $timeout,
-retries => $retries);
# check status
if ($0 =~ /waitend/) {
if ($ref->{printerdata}->{$model}->{jobstatus_oid}) {
my $jobstatus_oid=$ref->{printerdata}->{$model}->{jobstatus_oid};
my $status_ok=$ref->{printerdata}->{$model}->{status_ok};
do {
if ($response) {
# be nice to the network
sleep 3;
}
print "Running get_table ($jobstatus_oid)\n" if $verbose;
($response) = $session->get_table(($jobstatus_oid));
print "jobstatus response: $response\n" if $verbose;
# if we get an answer back, assume the printer job is complete and change
# the flag if it is still printing; otherwise, assume the job is not done
if ($response) {
$complete=1;
foreach (sort keys (%$response)) {
print "response for $_: $response->{$_}\n" if $verbose;
# Get "ok" status from XML config file
if ($response->{$_} != $status_ok) {
$complete=0;
}
}
}
} until ($complete);
print "RESULT=OK\n";
print "waitend=1\n";
}
}
# check pagecount
if ($0 =~ /pagecount/) {
print "Running pagecount\n" if $verbose;
if ($ref->{printerdata}->{$model}->{pagecount_oid} &&
$ref->{printerdata}->{$model}->{jobstatus_oid} ) {
my $pagecount_oid=$ref->{printerdata}->{$model}->{pagecount_oid};
print "Running get_request $pagecount_oid\n" if $verbose;
($response) = $session->get_request(($pagecount_oid));
$pagecount = $response->{$pagecount_oid};
print "pagecount response: $response\tpagecount: $pagecount\n" if $verbose;
print "Error: $error\n" if $verbose;
if ($pagecount) {
print "PAGECOUNT=$pagecount\n";
}
}
}
# check display status
if ($0 =~ /status/ && $ref->{printerdata}->{$model}->{display_oid}) {
my $display_oid=$ref->{printerdata}->{$model}->{display_oid};
print "Running get_table $display_oid\n" if $verbose;
$display = $session->get_request($display_oid);
print "Display status fetched: $display->{$display_oid}" if $verbose;
my $status = $ref->{printerdata}->{$model}->{status};
if ($status) {
foreach (keys %$status) {
print "Checking for $_\n" if $verbose;
if ($display->{$display_oid} =~ /$_/) {
$pjl_status_code = $status->{$_};
print "CODE=$pjl_status_code\n";
last;
}
}
print "sync=1\n";
} else {
print "sync=0\n";
}
}
# all done
$session->close;
# exit with JSUCC
$status = 0;
print "Exit status: 0\n" if $verbose;
exit $status;