From lprng@astart2.astart.com Mon May  6 15:26:55 2002
Return-Path: <lprng@astart2.astart.com>
Received: from astart2.astart.com (fw.private [10.0.0.1])
	by h110.private (8.11.6/8.11.6) with ESMTP id g46MQt937597
	for <papowell@h110.private>; Mon, 6 May 2002 15:26:55 -0700 (PDT)
	(envelope-from lprng@astart2.astart.com)
Received: (from majordom@localhost)
	by astart2.astart.com (8.11.6/8.11.6) id g46LgnH32721;
	Mon, 6 May 2002 14:42:49 -0700 (PDT)
	(envelope-from owner-lprng@lprng.com)
Received: from thugbert.cs.wisc.edu (thugbert.cs.wisc.edu [128.105.175.114])
	by astart2.astart.com (8.11.6/8.11.6) with ESMTP id g46LglJ32716
	for <lprng@lprng.com>; Mon, 6 May 2002 14:42:47 -0700 (PDT)
	(envelope-from john@thugbert.cs.wisc.edu)
Received: from thugbert.cs.wisc.edu (localhost [127.0.0.1])
	by thugbert.cs.wisc.edu (8.9.2/8.9.2) with ESMTP id QAA23563
	for <lprng@lprng.com>; Mon, 6 May 2002 16:42:45 -0500 (CDT)
Message-Id: <200205062142.QAA23563@thugbert.cs.wisc.edu>
X-Mailer: exmh version 2.5 07/13/2001 with nmh-1.0.4
To: lprng@lprng.com
Subject: LPRng: Xerox Phaser 5400 and ifhp-3.5.8
Mime-Version: 1.0
Content-Type: multipart/mixed ;
	boundary="==_Exmh_-5061626320"
Date: Mon, 06 May 2002 16:42:45 -0500
From: John Perkins <john@cs.wisc.edu>
Sender: owner-lprng@lprng.com
Precedence: bulk
Reply-To: lprng@lprng.com

This is a multipart MIME message.

--==_Exmh_-5061626320
Content-Type: text/plain; charset=us-ascii

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
   john@cs.wisc.edu		  |   1210 W. Dayton St.
   608-262-0438/608-262-9997 FAX  |   Madison, WI  53706-1685
============================================================================



--==_Exmh_-5061626320
Content-Type: text/plain ; name="check_printer_status.xml"; charset=us-ascii
Content-Description: check_printer_status.xml
Content-Disposition: attachment; filename="check_printer_status.xml"

<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>



--==_Exmh_-5061626320
Content-Type: text/plain ; name="check_printer_status.pl"; charset=us-ascii
Content-Description: check_printer_status.pl
Content-Disposition: attachment; filename="check_printer_status.pl"

#! /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;



--==_Exmh_-5061626320--



-----------------------------------------------------------------------------
YOU MUST BE A LIST MEMBER IN ORDER TO POST TO THE LPRNG MAILING LIST
The address you post from MUST be your subscription address

If you need help, send email to majordomo@lprng.com (or lprng-requests
or lprng-digest-requests) with the word 'help' in the body.  For the impatient,
to subscribe to a list with name LIST,  send mail to majordomo@lprng.com
with:                           | example:
subscribe LIST <mailaddr>       |  subscribe lprng-digest myname@host.org
unsubscribe LIST <mailaddr>     |  unsubscribe lprng myname@host.org

If you have major problems,  send email to papowell@astart.com with the word
LPRNGLIST in the SUBJECT line.
-----------------------------------------------------------------------------

