SNMP::NPAdmin - high-level API to query printers via SNMP


  # object-oriented
  $p= SNMP::NPAdmin->new(
        printer         => 'porky',
        community       => 'corpslp'
  printf "Your printer, %s, does%s support PCL.\n",
        $printer, ( $p->pcl() ? "" : " not");

  # procedural
  $p= npa_connect(
        printer         => 'porky',
        community       => 'corpslp'
  printf "Your printer, %s, does%s support PCL.\n",
        $printer, ( npa_pcl( $p) ? "" : " not");


The SNMP::NPAdmin package is a complete port of a SNMP/printer utility called npadmin that provides a high-level interface to query printers via SNMP without specific knowledge of SNMP MIBs or the printer's vendor-specific configuration.

The original npadmin was written in C++ by Ben Woodard who continues to maintain it on SourceForge.

The primary objective in this port is to have a maintainable and extensible version of the same functionality that the original npadmin provides.

It is not optimized for performance at all; it is optimized for extensibility and maintainability. The original npadmin is very much extremely performance, the idea being to query many printers very quickly, especially since SNMP can be quite slow.

To be fair, SNMP::NPAdmin might even be slow by Perl standards due to the extensive use of run-time compilation through the AUTOLOAD subroutine. I don't necessarily believe this since a programmer/sys-admin frequently will not use all of the available methods/subroutines which would typically be compiled during startup; given that only a few methods/subroutines will be called, then only a few will be compiled during the process's lifetime. Probably the difference in speed due to this will be insignificant either way.

The design was chosen in order to get as much information into a maintainable table format and make the logic as generic as possible; not for speed.

So this is your choice. If you have some unsupported printers and you want to be able to modify the code to support them then use SNMP::NPAdmin. If you need to support a lot of printers continuously with this kind of utility then you should use Ben Woodard's npadmin.


The SNMP::NPAdmin package is composed of a module, SNMP::NPAdmin, and a script, The heart of this package is the SNMP::NPAdmin module. Everything happens in the module. All that the script does is parse command-line arguments, call the SNMP::NPAdmin module and report the results. Actually, two modules are provided; but only one is publicly available. I will not even tell you its name; you can find it yourself if you're so curious.

The script is provide for two reasons. The first is to fulfill the original objective of writing a Perl-version of npadmin which is a command-line utility. The second is to provide an example script.


While writing this module, I received a lot a negative feedback about using OO techniques. Therefore I decided to ensure that it could be used by using both OO and procedural techniques.

It is probably true that most modules/classes are similarly Janus-faced since Perl always passes the object-reference (or class name) as the first argument. That is not so different from the way many procedural libraries work, particularly those that establish some kind of state such as network connections: initiate a connection and pass the returned struct to future library calls as the first argument.


The procedural API is not been fully implemented yet. But it is the current task and should be complete soon.




This is the constructor (duh!). It returns an SNMP::NPAdmin object which can then be queried with the object methods that are described below. For arguments, a hash is used which can include values for five keys: printer, community, port, timeout and retries. The printer key is required; the constructor will fail without it.

        $P= SNMP::NPAdmin->new(
                printer         => 'mega-print',
                community       => 'myhouse',

This is the procedural call to start a SNMP::NPAdmin session for a specific printer. It accepts the same arguments and returns the same results as the constructor. I didn't bother not blessing the reference just for a procedural call. It will still work when it is passed to the query subroutines.

        $P= npa_connect(
                printer         => 'mega-print',
                community       => 'myhouse',
SNMP::NPAdmin->version() or npa_version()

This method returns the version of SNMP::NPAdmin that is being used.

SNMP::NPAdmin->verbose() or npa_verbose()

This method toggles the 'verbose' flag for the entire class. All objects will verbosely report its progress during execution of any methods. The previous value of the 'verbose' flag is returned. Currently, the 'verbose' flag is ineffectual.

SNMP::NPAdmin->debug() or npa_debug()

This method toggles the 'debug' flag for the entire class. All objects will report in painful detail everything that is happening during a SNMP::NPAdmin method call. The previous value of the 'debug' flag is returned. Currently, the 'debug' flag is ineffectual.

SNMP::NPAdmin->debugsnmp() or npa_debugsnmp()

This method toggles the 'debugsnmp' flag for all objects/sessions. All objects will report in excruciating detail everything that happens during all actual SNMP transactions. This flag is actually used by the underlying SNMP module. It does work and very well.


MIB queries

The MIB queries determine whether or not the queried printer supports the MIB in question. Currently, SNMP::NPAdmin only asks about the Printer-MIB and the Host-Resources-MIB.

$P->printmib() or npa_printmib( $P)
 Answers the question, "Does the printer support the Printer-MIB?"
$P->hostmib() or npa_hostmib( $P)
 Answers the question, "Does the printer support the Host-Resources-MIB?"

Information queries

The information queries provide information that requires additional processing in addition to merely querying the printer for data. For most of these, this does involve simply querying the printer and reporting the results. The ones that do require this kind of heuristics are vendor(), model(), netconfig(), enginespeed(), maxpapersize(), minpapersize().

$P->contact() or npa_contact( $P)

Retrieves contact and location information as contained in system.sysDescr and system.sysLocation.

$P->vendor() or npa_vendor( $P)

Attempts to determine the vendor/manufacturer of the printer. Currently, only a few vendors can be reliably detected: HP, Tektronix, Lexmark, IBM, Xerox, EFI, Fuji and QMS. If a device can be determined to not be a printer then 'not_a_printer' is returned. If the vendor cannot be determined then 'unknown is returned. If you are able to determine an unsupported vendor then please send the information to me (see below).

$P->model() or npa_model( $P)

Attempts to determine the model of the printer. The vendor is determined as the first step. So, this will only work for printers that are supported by the vendor() method. Even then, the module only guarantees its best-effort. If you are able to determine an unsupported model then please send the information to me (see below).

$P->cfgsrc() or npa_cfgsrc( $P)

The configuration source or method is determined as given by the HP private MIB OID

$P->status() or npa_status( $P)

Attempts to determine the status of the printer from the Host-Resources-MID OID hrPrinterStatus.

$P->memory() or npa_memory( $P)

Attempts to determine the amount memory in the printer from the Host-Resources-MID OID hrMemorySize.

$P->netconfig() or npa_netconfig( $P)

Attempts to determine the network configuration of the printer from these MIB-2 OIDs: ipPhysAddress, ipAdEntAddr, ipAdEntNetMask, ipRouteNextHop.

$P->pagecount() or npa_pagecount( $P)

Attempts to number of pages printed by the printer from the Printer-MIB OIDs prtMarkerLifeCount and prtMarkerCounterUnit.

$P->colors() or npa_colors( $P)

Attempts to determine the number of colors supported by the printer from the Printer-MIB OID prtMarkerProcessColorants.

$P->resolution() or npa_resolution( $P)

This returns the values for the Printer-MIB OIDs prtMarkerAddressabilityFeedDir and prtMarkerAddressabilityXFeedDir.

??? I am not sure what they mean.

$P->minmargin() or npa_minmargin( $P)

This really should be just margin since it is determined from the prtMarkerTable and most printers in use only have one marker. Nonetheless, this merely returns the margins for all of the markers in the printer from the Printer-MIB OIDs prtMarkerNorthMargin, prtMarkerSouthMargin, prtMarkerEastMargin and prtMarkerWestMargin.

$P->enginespeed() or npa_enginespeed( $P)

Determines the maximum speed that one of the media-paths provides from the Printer-MIB OID prtMediaPathSpeed.

$P->maxpapersize() or npa_maxpapersize( $P)

Determines the largest paper-size that is supported by the printer. This does not reflect the largest size paper that is actually in the printer. By "largest" and "max", we mean the paper-size with the most area, as determined from the Printer-MIB OIDs prtMediaPathMaxMediaFeedDir and prtMediaPathMaxMediaXFeedDir.

$P->minpapersize() or npa_minpapersize( $P)

Determines the smallest paper-size that is supported by the printer. This does not reflect the smallest size paper that is actually in the printer. By "smallest" and "min", we mean the paper-size with the least area, as determined from the Printer-MIB OIDs prtMediaPathMinMediaFeedDir and prtMediaPathMinMediaXFeedDir.

SNMP table queries

The next set of queries merely return the contents of the Printer-MIB tables. Just for brevity, I will only list the method/subroutine names and the respective table OIDs.

$P->display() or npa_display( $P)
$P->languages() or npa_languages( $P)
$P->covers() or npa_covers( $P)
$P->inputtray() or npa_inputtray( $P)
$P->marker() or npa_marker( $P)
$P->protocol() or npa_protocol( $P)
$P->supplies() or npa_supplies( $P)
$P->mediapath() or npa_mediapath( $P)
$P->alerts() or npa_alerts( $P)

Truth queries

The truth queries answer a "Yes or No" question about the capabilities of the printer. The questions fall into one of several categories: languages (prtInterpreter), paper-size (prtMediaPath) or protocol (prtChannel).

$P->pjl() or npa_pjl( $P)
        supports PJL printer language?
$P->pcl() or npa_pcl( $P)
        supports PCL printer language?
$P->hpgl() or npa_hpgl( $P)
        supports HPGL printer language?
$P->psprint() or npa_psprint( $P)
        supports PSPRINT printer language?
$P->postscript() or npa_postscript( $P)
        supports Postscript printer language?
$P->autolang() or npa_autolang( $P)
        automatically selects the appropriate language?
$P->duplex() or npa_duplex( $P)
        supports duplex printing?
$P->letter() or npa_letter( $P)
        supports letter papersize?
$P->legal() or npa_legal( $P)
        supports legal papersize?
$P->executive() or npa_executive( $P)
        supports executive papersize?
$P->tabloid() or npa_tabloid( $P)
        supports tabloid papersize?
$P->a3() or npa_a3( $P)
        supports a3 papersize?
$P->a4() or npa_a4( $P)
        supports a4 papersize?
$P->b3() or npa_b3( $P)
        supports b4 papersize?
$P->b5() or npa_alerts( $P)
        supports b5 papersize?
$P->appletalk() or npa_appletalk( $P)
        supports Appletalk protocol?
$P->lpd() or npa_lpd( $P)
        supports LPD protocol?
$P->netware() or npa_netware( $P)
        supports Netware protocol?
$P->port9100() or npa_port9100( $P)
        supports port 9100 bidirectional connections?


Robert Lehr,

I certainly would appreciate any feedback from people that use it, including complaints, suggestions or patches. Even people that don't use it are welcome to send comments.


Copyright (c) 2001 Robert Lehr. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

Caveat emptor. Use this module at your own risk. I will accept no responsibility for any loss of any kind that is the direct or indirect result of the use of this module.


the SNMP module v3.1.0; the UCD SNMP library v4.2.0 at; RFC 1759 - The Printer MIB

7 POD Errors

The following errors were encountered while parsing the POD:

Around line 318:

You forgot a '=back' before '=head2'

Around line 324:

'=item' outside of any '=over'

Around line 403:

You forgot a '=back' before '=head2'

Around line 408:

'=item' outside of any '=over'

Around line 449:

You forgot a '=back' before '=head2'

Around line 454:

'=item' outside of any '=over'

Around line 641:

You forgot a '=back' before '=head1'

You forgot a '=back' before '=head1'