diff --git a/check_snmp_printer b/check_snmp_printer
new file mode 100644
index 0000000000000000000000000000000000000000..6540f2b21df60464f28355ff14a1fac51700d42e
--- /dev/null
+++ b/check_snmp_printer
@@ -0,0 +1,1016 @@
+#!/usr/bin/perl
+#########################################################
+#                                                       #
+#                                                       #
+#      SNMP Printer Check Plugin for Icinga             #
+#            Version 1.2.3 (October 14, 2020)           #
+#                by Rob McLoughlin                      #
+#         E-mail: rmcloughlin@outlook.com               #
+#                                                       #
+#                                                       #
+# Based on:                                             #
+# check_snmp_printer (Perl)                             #
+#       Version 1.6 (September 08, 2014)                #
+# ( by Franky Van Liedekerke                            #
+#       E-mail: liedekef@telenet.be )                   #
+#                                                       #
+# Which was further based on:                           #
+# check_snmp_printer.sh                                 #
+#       Version 1.5 (January 15, 2010)                  #
+# ( by Jason Leonard                                    #
+#       E-mail: jason_leonard@yahoo.com )               #
+#                                                       #
+# Version History                                       #
+#   - Refer to CHANGELOG.md                             #
+#                                                       #
+#       Like the original, this plugin is distributed   #
+# under the GNU GPL license. You may re-destribute only #
+# according to the terms of the GNU GPL.                #
+#                                                       #
+#########################################################
+#########################################################
+#                                                       #
+# DEPENDS On                                            #
+# Net::SNMP perl module                                 #
+# Nagios plugins installed and located in lib64         #
+#                                                       #
+#########################################################
+
+use strict;
+use lib qw( /usr/lib/nagios/plugins /usr/lib64/nagios/plugins );
+use utils qw( %ERRORS $TIMEOUT &print_revision &support &usage );
+use Net::SNMP;
+use Getopt::Long;
+use Data::Dumper;
+
+
+# globals
+use vars qw(
+  $PROGNAME $VERSION %procs $snmp $errstr $oid
+  $opt_version $opt_help $opt_timeout $opt_retries $opt_host
+  $opt_community $opt_snmpver $opt_warning $opt_critical
+  $opt_messages $opt_model $opt_consum $opt_tray $opt_pagecount
+  $opt_metric $opt_nofeeder
+);
+my (@consumables,@status,@trays,@strays,@percentages,@mresults,@message,@measurables);
+my ($state,$statuscode,$EXITSTRING);
+my ($i,$tcount,$scount,$traynumber,$cnumber,$mnumber,$critcount,$warncount) = 0;
+
+my %STATUS_CODE =
+  ( 'UNKNOWN' => '3', 'OK' => '0', 'WARNING' => '1', 'CRITICAL' => '2' );
+
+# config
+$PROGNAME    = $0;
+$VERSION     = '1.2.3';
+
+# init options
+$opt_version    = undef;
+$opt_help       = undef;
+$opt_timeout    = $TIMEOUT;
+$opt_retries    = 3;
+$opt_host       = undef;
+$opt_community  = 'public';
+$opt_snmpver    = 1;
+$opt_warning    = 20; # warning percentage: if lower: warning
+$opt_critical   = 5;  # critical percentage: if lower: critical
+$opt_messages   = undef;
+$opt_model      = undef;
+$opt_consum     = undef;
+$opt_tray       = undef;
+$opt_pagecount  = undef;
+$opt_metric     = undef;
+
+# get options
+Getopt::Long::Configure('bundling');
+GetOptions(
+  'V|version'           => \$opt_version,
+  'h|help'              => \$opt_help,
+  't|timeout=i'         => \$opt_timeout,
+  'r|retries=i'         => \$opt_retries,
+  'H|host=s'            => \$opt_host,
+  'C|community=s'       => \$opt_community,
+  'v|snmpver=s'         => \$opt_snmpver,
+  'w|warning=i'         => \$opt_warning,
+  'c|critical=i'        => \$opt_critical,
+  'messages'            => \$opt_messages,
+  'model'               => \$opt_model,
+  'consum'              => \$opt_consum,
+  'trays'               => \$opt_tray,
+  'pagecount'           => \$opt_pagecount,
+  'nofeeder'            => \$opt_nofeeder,
+  'metric'              => \$opt_metric
+) or do {
+  print_usage();
+  exit($ERRORS{'UNKNOWN'});
+};
+
+if($opt_version) {
+  print_version();
+  exit($ERRORS{'UNKNOWN'});
+}
+
+if($opt_help) {
+  print_help();
+  exit($ERRORS{'UNKNOWN'});
+}
+
+if(!$opt_host) {
+  print "Host option not given\n";
+  print_usage();
+  exit($ERRORS{'UNKNOWN'});
+}
+
+# only use one of messages|model|consum|tray|pagecount options
+my $count=0;
+($opt_messages) && ($count++);
+($opt_model) && ($count++);
+($opt_consum) && ($count++);
+(defined($opt_tray)) && ($count++);
+($opt_pagecount) && ($count++);
+if ($count>1) {
+  print "Only use one of messages|model|consum|trays|pagecount options\n";
+  print_help();
+  exit($ERRORS{'UNKNOWN'});
+}
+if ($count<1) {
+  print "Only use one of messages|model|consum|trays|pagecount options\n";
+  print_help();
+  exit($ERRORS{'UNKNOWN'});
+}
+
+sub print_usage {
+  my $tab = ' ' x length($PROGNAME);
+  print <<EOB
+Usage:
+ $PROGNAME -H host
+ $tab [-C snmp_community] [-v snmp_version] [-t timeout]
+ $PROGNAME --version
+ $PROGNAME --help
+EOB
+}
+
+sub print_version {
+  print_revision($PROGNAME, $VERSION);
+}
+
+sub print_help {
+  print_version();
+  print <<EOB;
+
+Check a printer through SNMP.
+
+EOB
+
+  print_usage();
+  print <<EOB;
+
+Required Arguments:
+ -H, --host=HOST
+    The name or address of the host running SNMP.
+ --messages
+    Print the messages of the printer
+ --model
+    Prints the model of the printer
+ --pagecount
+    Prints the number of pages printed
+ --trays
+    Checks trays for paper status.
+ --consum
+    Checks consumables for status.
+
+Optional Arguments:
+ -C, --community=STRING
+    The community string of the SNMP agent. Default: public
+ -v, --snmpver=STRING
+    The version of snmp to use.  1 and 2 are supported. Default: 1
+ -w, --warning=INTEGER
+    The warning limit level to alert on.  0 to disable tray alerting.
+ -c, --critical=INTEGER
+    The critical limit level to alert on.  0 to disable tray alerting.
+ -t, --timeout=INTEGER
+    Number of seconds to wait for a response.
+ -r, --retries=INTEGER
+    Number of retries to try before timing out. Default: 3
+ --metric
+    Converts output to metric.  Default: imperial
+ --nofeeder
+    Disables checking of the manual feeder tray
+EOB
+}
+
+sub check_model {
+        my ($pcheck) = @_;
+        my ($oid,$result);
+        my $MODEL="Uknown model";
+        my $SERIAL="";
+
+        if ($pcheck == 1 || $pcheck == 2) {
+                $oid=".1.3.6.1.2.1.25.3.2.1.3.1";
+                $result=$snmp->get_request(-varbindlist => [$oid]);
+                ($result) && ($MODEL=$result->{$oid});
+                if ($pcheck == 2) { return lc $MODEL; }
+        }
+        if ($pcheck == 1) {
+                $oid=".1.3.6.1.2.1.43.5.1.1.17.1";
+                $result=$snmp->get_request(-varbindlist => [$oid]);
+                ($result) && ($SERIAL=$result->{$oid});
+                $SERIAL =~ s/\"//g;
+
+                print "$MODEL, Serial # $SERIAL\n";
+        }
+}
+
+sub check_messages {
+        my ($mcheck) = @_;
+        my ($oid,$result,$model);
+        my $MESSAGES="";
+
+        $model = check_model(2);
+        if ($model =~ m/hp/) {
+                $oid=".1.3.6.1.4.1.11.2.3.9.1.1.3";
+        } else {
+                $oid=".1.3.6.1.2.1.43.16";
+        }
+
+        $result = $snmp->get_entries(-columns => [$oid]);
+
+        foreach my $key (keys(%$result)) {
+                $result->{$key} =~ s/\"//g;
+                $result->{$key} =~ s/\n/\!/g;
+                $MESSAGES .= $result->{$key}."\n";
+        }
+        chomp $MESSAGES;
+        if ($MESSAGES eq "") {
+                $MESSAGES= "(Can't determine messages)";
+        }
+        if ($mcheck == 2) { return $MESSAGES; }
+        my @messages = split('\n',$MESSAGES);
+        foreach my $message (@messages) {
+                $message = lc $message;
+                if ($message =~ m/toner low|wenig toner|cartridge low|niedrig|attention/) {
+                        $state = "WARNING";
+                }
+                elsif ($message =~ m/replace toner|toner ersetzen|error|paper is out/) {
+                        $state = "CRITICAL";
+                } else { $state = "OK"; }
+                push @{ $status[$mnumber] }, $state;
+                $mnumber++;
+        }
+        print "$MESSAGES\n";
+}
+
+sub check_page_count {
+        my ($oid,$result,$model,$t_oid,$c_oid,$m_oid,
+            $m_a3_oid,$m_a4_oid,$c_a3_oid,$c_a4_oid,
+            $m_a3,$m_a4,$c_a3,$c_a4,$MonoPagecount,$ColorPagecount,$TotalPagecount);
+        my (%ttmpprs,%ctmpprs,%mtmpprs) = ();
+
+        $model = check_model(2);
+        if ($model =~ m/hp/) {
+                $c_oid='.1.3.6.1.4.1.11.2.3.9.4.2.1.4.1.2.7.0';
+                $m_oid='.1.3.6.1.4.1.11.2.3.9.4.2.1.4.1.2.6.0';
+        }
+        if ($model =~ m/canon/) {
+                $t_oid='.1.3.6.1.4.1.1602.1.11.1.3.1.4.101';
+                $c_oid='.1.3.6.1.4.1.1602.1.11.1.3.1.4.105';
+                $m_oid='.1.3.6.1.4.1.1602.1.11.1.3.1.4.108';
+                $m_a3_oid='.1.3.6.1.4.1.1602.1.11.1.3.1.4.112';
+                $m_a4_oid='.1.3.6.1.4.1.1602.1.11.1.3.1.4.113';
+                $c_a3_oid='.1.3.6.1.4.1.1602.1.11.1.3.1.4.222';
+                $c_a4_oid='.1.3.6.1.4.1.1602.1.11.1.3.1.4.223';
+        }
+        if ($model =~ m/xerox/) {
+                $c_oid='.1.3.6.1.4.1.253.8.53.13.2.1.6.1.20.33';
+                $m_oid='.1.3.6.1.4.1.253.8.53.13.2.1.6.1.20.34';
+        }
+        if ($model =~ m/lexmark/) {
+                $c_oid='.1.3.6.1.4.1.641.6.4.2.2.1.7.1.1';
+                $m_oid='.1.3.6.1.4.1.641.6.4.2.2.1.6.1.1';
+        }
+        if ($model =~ m/ricoh/) {
+                $c_oid='.1.3.6.1.4.1.367.3.2.1.2.19.5.1.9.21';
+                $m_oid='.1.3.6.1.4.1.367.3.2.1.2.19.5.1.9.22';
+        }
+        if ($model =~ m/kyocera|ecosys|taskalfa|4200dn/) {
+                $t_oid='.1.3.6.1.4.1.1347.42.2.1.1.1.6.1';
+                $c_oid='.1.3.6.1.4.1.1347.42.2.1.1.1.8.1';
+                $m_oid='.1.3.6.1.4.1.1347.42.2.1.1.1.7.1';
+        }
+
+        $oid=".1.3.6.1.2.1.43.10.2.1.4.1.1";
+
+
+        if (defined($snmp->get_request(-varbindlist => [$m_a3_oid]))) { $m_a3 = $snmp->get_request(-varbindlist => [$m_a3_oid]) }
+        if (defined($snmp->get_request(-varbindlist => [$m_a4_oid]))) { $m_a4 = $snmp->get_request(-varbindlist => [$m_a4_oid]) }
+        if (defined($snmp->get_request(-varbindlist => [$c_a3_oid]))) { $c_a3 = $snmp->get_request(-varbindlist => [$c_a3_oid]) }
+        if (defined($snmp->get_request(-varbindlist => [$c_a4_oid]))) { $c_a4 = $snmp->get_request(-varbindlist => [$c_a4_oid]) }
+
+        if (($m_a3 || $m_a4) > 0) {
+                $MonoPagecount = $m_a3 + $m_a4;
+        } elsif ($model =~ m/kyocera|ecosys|taskalfa|4200dn/) {
+                my $tresult = $snmp->get_entries(-columns => [$t_oid]);
+                my $cresult = $snmp->get_entries(-columns => [$c_oid]);
+                my $mresult = $snmp->get_entries(-columns => [$m_oid]);
+                foreach my $tkey (keys(%$tresult)) {
+                        my($tindex) = ($tkey =~ /($t_oid\.\d+)/);
+                        $tresult->{$tkey} =~ s/[^\w\s]//g;
+                        $ttmpprs{$tindex}{t_count} = $tresult->{$tkey};
+                }
+                foreach my $tkey (keys(%ttmpprs)) {
+                        my $t_count=$ttmpprs{$tkey}{t_count};
+                        $TotalPagecount = $TotalPagecount+$t_count;
+                }
+                foreach my $ckey (keys(%$cresult)) {
+                        my($cindex) = ($ckey =~ /($c_oid\.\d+)/);
+                        $cresult->{$ckey} =~ s/[^\w\s]//g;
+                        $ctmpprs{$cindex}{c_count} = $cresult->{$ckey};
+                }
+                foreach my $ckey (keys(%ctmpprs)) {
+                        my $c_count=$ctmpprs{$ckey}{c_count};
+                        $ColorPagecount = $ColorPagecount+$c_count;
+                }
+                foreach my $mkey (keys(%$mresult)) {
+                        my($mindex) = ($mkey =~ /($m_oid\.\d+)/);
+                        $mresult->{$mkey} =~ s/[^\w\s]//g;
+                        $mtmpprs{$mindex}{m_count} = $mresult->{$mkey};
+                }
+                foreach my $mkey (keys(%mtmpprs)) {
+                        my $m_count=$mtmpprs{$mkey}{m_count};
+                        $MonoPagecount = $MonoPagecount+$m_count;
+                }
+        } else {
+                $result=$snmp->get_request(-varbindlist => [$m_oid]);
+                if((not defined($result)) || ($result->{$m_oid} eq 'noSuchInstance')) {
+                        $result=$snmp->get_request(-varbindlist => [$t_oid]);
+                                if((not defined($result)) || ($result->{$m_oid} eq 'noSuchInstance')) {
+                                        $result=$snmp->get_request(-varbindlist => [$oid]);
+                                        if ($snmp->error() =~ m/genError/) {
+                                                $result = retry_snmp($oid,undef,undef,undef,undef,undef,undef,undef);
+                                        }
+                                        if(not defined($result)) {
+                                                print "CRITICAL - snmp error: " . $snmp->error() . "\n";
+                                                exit($ERRORS{'CRITICAL'});
+                                        } else { $TotalPagecount=$result->{$oid}; }
+                                } else { $TotalPagecount=$result->{$t_oid}; }
+                } else { $MonoPagecount=$result->{$m_oid}; }
+        }
+        if (($c_a3 || $c_a4) > 0) {
+                $ColorPagecount = $c_a3 + $c_a4;
+        } else {
+                $result=$snmp->get_request(-varbindlist => [$c_oid]);
+                if(not defined($result)) {
+                } else { $ColorPagecount=$result->{$c_oid}; }
+        }
+        if (($TotalPagecount) or (($model =~ m/kyocera|ecosys|taskalfa|4200dn/))) {
+                $EXITSTRING = "Pagecount is $TotalPagecount";
+                        if ($model =~ m/kyocera|ecosys|taskalfa|4200dn/) {
+                                $EXITSTRING.= " Total, $MonoPagecount Black-and-White";
+                        }
+        } else { $EXITSTRING = "Pagecount is $MonoPagecount Black-and-White"; }
+        if ($ColorPagecount > 0) {
+                $EXITSTRING.= ", $ColorPagecount Color";
+        }
+        $EXITSTRING.= "\n";
+        if (($TotalPagecount) or ($model =~ m/kyocera|ecosys|taskalfa|4200dn/)) {
+                $EXITSTRING.= "|Total=$TotalPagecount;;;;";
+                if ($model =~ m/kyocera|ecosys|taskalfa|4200dn/) {
+                        $EXITSTRING.= " Black-and-White=$MonoPagecount;;;;";
+                }
+        } else { $EXITSTRING.= "|Black-and-White=$MonoPagecount;;;;"; }
+        if ($ColorPagecount > 0) {
+                $EXITSTRING.= " Color=$ColorPagecount;;;;";
+        }
+
+}
+
+sub get_consumables {
+        my ($result,$Table,$Names,$CurCap,$MaxCap) = @_;
+        my %tmpprs = ();
+        my ($consumable, $curcap_pct);
+        my ($puncher, $found) = 0;
+
+        foreach my $key (keys(%$result)) {
+                my($base, $index) = ($key =~ /($Table\.\d+\.\d+)\.(\d+)/);
+                if($base eq $Names ) {
+                        $result->{$key} =~ s/[^\w\s]//g;
+                        $tmpprs{$index}{name} = $result->{$key};
+                }
+                if($base eq $CurCap) { $tmpprs{$index}{curcap} = $result->{$key}; }
+                if($base eq $MaxCap) { $tmpprs{$index}{maxcap} = $result->{$key}; }
+        }
+
+        foreach my $key (keys(%tmpprs)) {
+                my $name=$tmpprs{$key}{name};
+                if ($name =~ m/Imaging Unit|Imaging Kit/) { $consumable = $name; }
+                else { ($consumable = $name) =~ s/(\w+).*/$1/; }
+                if ($consumable eq "Canon") {
+                        my @split = split(' ',$consumable = $name);
+                        foreach my $cconsumable (@split) {
+                                if ($cconsumable =~ m/Black|Yellow|Magenta|Cyan/) { $consumable = $cconsumable; }
+                                else { next; }
+                        }
+                }
+                if ($consumable eq "Image") {
+                        my @split = split(' ',$consumable = $name);
+                        foreach my $iconsumable (@split) {
+                                if ($iconsumable =~ m/Transfer|Fuser/) { $consumable = $iconsumable. " Kit"; }
+                                else { next; }
+                        }
+                }
+                if (check_model(2) =~ m/generic 30c-9/) {
+                        my @split = split(' ',$consumable = $name);
+                        foreach my $gconsumable (@split) {
+                                if ($gconsumable =~ m/Toner/) {
+                                        ($consumable) = $name =~ /\((.*)\)/;
+                                } elsif ($gconsumable =~ m/Image|Fusing/) {
+                                        $consumable = $name;
+                                } else {
+                                        next;
+                                }
+                        }
+                }
+                if (check_model(2) =~ m/ricoh/) {
+                        my @split = split(' ',$consumable = $name);
+                        foreach my $rconsumable (@split) {
+                                if ($rconsumable =~ m/Toner/) {
+                                        ($consumable) = $name =~ /(?<=Toner )(\w+)/;
+                                } else {
+                                        next;
+                                }
+                        }
+                }
+
+                my $curcap=$tmpprs{$key}{curcap};
+                my $maxcap=$tmpprs{$key}{maxcap};
+
+                if ($name =~ m/Drum|Resttoner|Waste Toner|Belt|Developer/) {
+                        next;
+                }
+
+                if ($consumable =~ m/Imaging Unit/) { }
+                elsif ($consumable =~ m/Black|Yellow|Magenta|Cyan/) { $consumable = $consumable." Toner"; }
+                elsif ($consumable =~ m/Schwarz|Gelb/) { $consumable = $consumable." Toner"; } # German
+                # Kyocera reports toner as model number so we need to convert that to something human readable
+                if ($consumable =~ m/TK/) {
+                        if ($consumable =~ /CS$|C$/) { $consumable = "Cyan Toner"; }
+                        elsif ($consumable =~ /MS$|M$/) { $consumable = "Magenta Toner"; }
+                        elsif ($consumable =~ /YS$|Y$/) { $consumable = "Yellow Toner"; }
+                        elsif ($consumable =~ /KS$|K$/) { $consumable = "Black Toner"; }
+                        else { $consumable = "Black Toner"; }
+                }
+                if ($consumable eq 'Magneta') { $consumable = "Magenta Toner"; }  # New HP OID has a typo
+                if ($consumable eq 'Clean') { $consumable = $consumable." Rollers"; }
+                if ($consumable eq 'Document') { $consumable = $consumable." Feeder Kit"; }
+                if ($consumable eq 'Maintenance') { $consumable = $consumable." Kit"; }
+                if ($consumable eq 'Transfer') { $consumable = $consumable." Unit"; }
+                if ($consumable eq 'Stapler') { }
+                if ($consumable eq 'Staples') { }
+                if ($consumable eq 'Saddle') { $consumable = $consumable." Staples"; }
+                if ($consumable eq 'Puncher') { $puncher = 1; $consumable = $consumable. " Waste"; }
+
+                push (@consumables, $consumable);
+
+                $found=1;
+                if ($puncher == 1) {
+                        if ($curcap > 99) {
+                                $state = "CRITICAL";
+                        } elsif ($curcap >= 96) {
+                                $state = "WARNING";
+                        } else {
+                                $state = "OK";
+                        }
+                        push (@measurables, '1');
+                        push (@percentages, $curcap);
+                } else {
+                        if ($maxcap>0 && $curcap>0) {
+                                $curcap_pct=sprintf("%.2f",$curcap*100/$maxcap);
+                                if ($curcap_pct<=$opt_critical) {
+                                        # critical messages come first
+                                        $state = "CRITICAL";
+                                } elsif ($curcap_pct<=$opt_warning) {
+                                        $state = "WARNING";
+                                } else {
+                                        $state = "OK";
+                                }
+                                push (@measurables, '1');
+                                push (@percentages, $curcap_pct);
+                        } elsif ($maxcap == 100 && $curcap == 0) {
+                                $state = "CRITICAL";
+                                push (@measurables, '1');
+                                push (@percentages, 0);
+                        } else {
+                                if (check_model(2) =~ m/brother/) {
+                                        my ($bresult,$bstatus,$boid);
+                                        if ($consumable =~ m/Black|Schwarz/) {
+                                                $boid = ".1.3.6.1.4.1.2435.2.3.9.1.1.2.10.1";
+                                        }
+                                        if ($consumable =~ m/Cyan/) {
+                                                $boid = ".1.3.6.1.4.1.2435.2.3.9.1.1.2.10.2";
+                                        }
+                                        if ($consumable =~ m/Magenta/) {
+                                                $boid = ".1.3.6.1.4.1.2435.2.3.9.1.1.2.10.3";
+                                        }
+                                        if ($consumable =~ m/Yellow|Gelb/) {
+                                                $boid = ".1.3.6.1.4.1.2435.2.3.9.1.1.2.10.4";
+                                        }
+                                        if (defined($snmp->get_request(-varbindlist => [$boid]))) {
+                                                $bstatus = $bresult->{$oid};
+                                                if ($bstatus == 0) { $state = "OK"; push (@measurables, 'b0'); $curcap = 100; }
+                                                if ($bstatus == 1) { $state = "WARNING"; push (@measurables, 'b1'); $curcap = 10; }
+                                                if ($bstatus == 2) { $state = "CRITICAL"; push (@measurables, 'b2'); $curcap = 0; }
+                                                if ($bstatus == 3) { $state = "CRITICAL"; push (@measurables, 'b3'); $curcap = 0; }
+                                        } else { ($state,$curcap) = nonmeasurable($curcap,$maxcap,$name); }
+                                } else {
+                                        $state = nonmeasurable($curcap,$maxcap,$name);
+                                }
+                                push (@percentages, $curcap);
+                        }
+                }
+                $puncher = 0;
+                push @{ $status[$cnumber] }, $state;
+                $cnumber++;
+        }
+}
+
+sub nonmeasurable {
+        my ($curcap,$maxcap,$name) = @_;
+
+        # Our object is not measurable - it's either FULL or EMPTY (such as a punch dust box)
+        # Let's report on it's status using appropriate terminology
+        if (check_model(2) =~ m/brother/) {
+                if ($curcap == -3) { $state = "OK"; push (@measurables, 'b0'); }
+                else {
+                        my $smessage = check_messages(2);
+                        my @messages = split('\n',$smessage);
+                        foreach my $message (@messages) {
+                                $message = lc $message;
+                                if ($message =~ m/toner low|wenig toner/) {
+                                        $state = "WARNING";
+                                        push (@measurables, 'b1');
+                                        $curcap = 10;
+                                }
+                                elsif ($message =~ m/replace toner|toner ersetzen/) {
+                                        $state = "CRITICAL";
+                                        push (@measurables, 'b3');
+                                        $curcap = 0;
+                                }
+                        }
+                }
+                push (@measurables, '1');
+                return $state, $curcap;
+        } elsif ($curcap==-3) {
+                if ($maxcap>0) { $state = "WARNING"; push (@measurables, 'lt'); }
+                else { $state = "OK"; (@measurables, 'gt'); }
+        } elsif ($curcap==-2) {
+                # The value (-2) means unknown
+                if ($name =~ m/W2020A|W2021A|W2022A|W2023A/) { # HP Color LaserJet Pro M454dw Toner
+                        $state = "CRITICAL";
+                        push (@measurables, '1');
+                 } else { $state = "WARNING"; push (@measurables, '0'); }
+        } elsif ($curcap==0) {
+                # Something is empty!
+                $state = "CRITICAL";
+        }
+        return $state;
+}
+
+sub prioritize_results {
+        my ($metric) = @_;
+        my ($mcount,$scode);
+
+        if ((scalar @consumables) > 0) { $mcount = (scalar @consumables); }
+        if ((scalar @strays) > 0) { $mcount = (scalar @strays); }
+
+        $i = 0;
+
+        while ($mcount > 0) {
+
+                if ($status[$i][0] eq 'CRITICAL') { $scode = 1; }
+                if ($status[$i][0] eq 'WARNING') { $scode = 2; }
+                if ($status[$i][0] eq 'OK') { $scode = 3; }
+
+                if ($metric eq "consumables") {
+                        push @{ $mresults[$i] }, $scode, $status[$i][0], $consumables[$i], $message[$i];
+                }
+                if ($metric eq "trays") {
+                        push @{ $mresults[$i] }, $scode, $status[$i][0], $strays[$i][0], $message[$i];
+                }
+                $mcount--;
+                $i++;
+        }
+
+        @mresults = sort { $a->[0] cmp $b->[0] } @mresults;
+
+        $i = 0;
+        $mcount = (scalar @mresults);
+        while ($mcount > 0) {
+                print "$mresults[$i][1]: $mresults[$i][2]$mresults[$i][3]\n";
+                $mcount--;
+                $i++;
+        }
+}
+
+sub check_consumables {
+        my %pr_oids = (
+                'Table'         => '.1.3.6.1.2.1.43.11.1.1',
+                'Names'         => '.1.3.6.1.2.1.43.11.1.1.6.1',
+                'CurCap'        => '.1.3.6.1.2.1.43.11.1.1.9.1',
+                'MaxCap'        => '.1.3.6.1.2.1.43.11.1.1.8.1',
+                'CTable'        => '.1.3.6.1.2.1.43.31.1.1',
+                'CNames'        => '.1.3.6.1.2.1.43.31.1.1.5.1',
+                'CCurCap'       => '.1.3.6.1.2.1.43.31.1.1.8.1',
+                'CMaxCap'       => '.1.3.6.1.2.1.43.31.1.1.7.1'
+        );
+        my ($consumable,$measurable,$perfcount);
+        my $pct_remaining = "";
+
+        my $result = $snmp->get_entries(-columns => [$pr_oids{Names}, $pr_oids{CurCap}, $pr_oids{MaxCap}]);
+        if ($snmp->error() =~ m/genError/) {
+                $result = retry_snmp($pr_oids{Names}, $pr_oids{CurCap}, $pr_oids{MaxCap},undef,undef,undef,undef,undef);
+        }
+        if(not defined($result)) {
+                print "CRITICAL - snmp error: " . $snmp->error() . "\n";
+                exit($ERRORS{'CRITICAL'});
+        }
+        my $cresult = $snmp->get_entries(-columns => [$pr_oids{CNames}, $pr_oids{CCurCap}, $pr_oids{CMaxCap}]);
+
+        get_consumables($result, $pr_oids{Table}, $pr_oids{Names}, $pr_oids{CurCap}, $pr_oids{MaxCap});
+        get_consumables($cresult, $pr_oids{CTable}, $pr_oids{CNames}, $pr_oids{CCurCap}, $pr_oids{CMaxCap});
+
+        $tcount = (scalar @consumables);
+        if (@percentages != 0 ) { $measurable = 1; }
+        if ($measurable) {
+                if ($consumables[0] eq "Puncher Waste") {
+                        $pct_remaining = " is ".$percentages[0]. "% full.";
+                } elsif ($consumables[0] eq "Stapler") {
+                        $pct_remaining = "";
+                } elsif (check_model(2) =~ m/brother/) {
+                        if ($measurables[$i] eq "b0") {
+                                $pct_remaining = " levels are OK.";
+                        }
+                        if ($measurables[$i] eq "b1") {
+                                $pct_remaining = " levels are LOW.";
+                        }
+                        if ($measurables[$i] eq "b2") {
+                                $pct_remaining = " has no toner installed.";
+                        }
+                        if ($measurables[$i] eq "b3") {
+                                $pct_remaining = " levels are EMPTY.";
+                        }
+                } elsif ($percentages[$i] eq "-2") {
+                        if ($measurables[$i] eq "0") {
+                                $pct_remaining = " levels cannot be measured.";
+                        } else { $pct_remaining = " is at 0% remaining."; }
+                } else {
+                        $pct_remaining = " is at ".$percentages[0]. "% remaining.";
+                }
+                push (@message, $pct_remaining);
+        }
+        my $perfcount = $tcount;
+        if ($tcount > 1) {
+                $tcount--;
+                while ($tcount > 0) {
+                        $i++;
+                        if ($consumables[$i] eq "Waste") {
+                                $tcount--;
+                                next;
+                        }
+                        if ($measurable) {
+                                if ($consumables[$i] eq "Puncher Waste") {
+                                        $pct_remaining = " is ".$percentages[$i]. "% full.";
+                                } elsif ($consumables[$i] eq "Stapler") {
+                                        $pct_remaining = "";
+                                } elsif (check_model(2) =~ m/brother/) {
+                                        if ($measurables[$i] eq "b0") {
+                                                $pct_remaining = " levels are OK.";
+                                        }
+                                        if ($measurables[$i] eq "b1") {
+                                                $pct_remaining = " levels are LOW.";
+                                        }
+                                        if ($measurables[$i] eq "b2") {
+                                                $pct_remaining = " has no toner installed.";
+                                        }
+                                        if ($measurables[$i] eq "b3") {
+                                                $pct_remaining = " levels are EMPTY.";
+                                        }
+                                } elsif ($percentages[$i] eq "-2") {
+                                        if ($measurables[$i] eq "0") {
+                                                $pct_remaining = " levels cannot be measured.";
+                                        } else { $pct_remaining = " is at 0% remaining."; }
+                                } elsif ($percentages[$i] eq "-3") {
+                                        if ($measurables[$i] eq "lt") {
+                                                $pct_remaining = " levels are LOW.";
+                                        }
+                                        if ($measurables[$i] eq "gt") {
+                                                $pct_remaining = " levels are OK.";
+                                        }
+                                } else {
+                                        $pct_remaining = " is at ".$percentages[$i]. "% remaining.";
+                                }
+                        }
+                        push (@message, $pct_remaining);
+                        $tcount--;
+                }
+        }
+        prioritize_results('consumables');
+        $i = 0;
+        $EXITSTRING.= "|";
+        while ($perfcount > 0) {
+                if ($consumables[$i] eq "Waste") {
+                        $i++;
+                        $perfcount--;
+                        next;
+                }
+                ($consumable = $consumables[$i]) =~ s/ /_/g;
+                if ($measurable) {
+                        if ($consumable eq "Stapler") {
+                                if ($status[$i] eq 'CRITICAL') { $EXITSTRING.= $consumable."=0"; }
+                                elsif ($status[$i] eq 'OK') { $EXITSTRING.= $consumable."=100"; }
+                        } elsif ($percentages[$i] eq "-2") {
+                                if ($measurables[$i] eq "0") { }
+                                else { $EXITSTRING.= "$consumable=0"; }
+                        } else {
+                                $EXITSTRING.= $consumable."=".$percentages[$i];
+                        }
+                } else {
+                        if ($status[$i] == "CRITICAL") {
+                                $EXITSTRING.= $consumable."=0";
+                        } else {
+                                $EXITSTRING.= $consumable."=1";
+                        }
+                }
+                $i++;
+                $perfcount--;
+                if ($perfcount == 0) { $EXITSTRING.= ";;;;"; } else { $EXITSTRING.=";;;; "; }
+        }
+}
+
+sub check_paper_trays {
+        my $found=0;
+        my %tmpprs = ();
+        my ($name,$lcname,$feeder,$cap,$tstatus,$traymessage,$maxcap,$feeddim,$xfeeddim,$cap_pct);
+        my %tray_oids = (
+                'Table'         => '.1.3.6.1.2.1.43.8.2.1',
+                'Cap'           => '.1.3.6.1.2.1.43.8.2.1.10.1',
+                'Status'        => '.1.3.6.1.2.1.43.8.2.1.11.1',
+                'MaxCap'        => '.1.3.6.1.2.1.43.8.2.1.9.1',
+                'Name'          => '.1.3.6.1.2.1.43.8.2.1.13.1',
+                'FeedDim'       => '.1.3.6.1.2.1.43.8.2.1.4.1',
+                'FeedDimUnits'  => '.1.3.6.1.2.1.43.8.2.1.2.1',
+                'XFeedDim'      => '.1.3.6.1.2.1.43.8.2.1.5.1',
+                'XFeedDimUnits' => '.1.3.6.1.2.1.43.8.2.1.3.1'
+        );
+        my $result = $snmp->get_entries(-columns => [$tray_oids{Name},$tray_oids{Cap},$tray_oids{MaxCap},$tray_oids{FeedDim},$tray_oids{FeedDimUnits},$tray_oids{XFeedDim},$tray_oids{XFeedDimUnits},$tray_oids{Status}]);
+        my $model = "Unknown Model";
+        my $mresult = $snmp->get_request(-varbindlist => [".1.3.6.1.2.1.25.3.2.1.3.1"]);
+        ($mresult) && ($model=$mresult->{".1.3.6.1.2.1.25.3.2.1.3.1"});
+
+        if ($snmp->error() =~ m/genError/) {
+                $result = retry_snmp($tray_oids{Name},$tray_oids{Cap},$tray_oids{MaxCap},$tray_oids{FeedDim},$tray_oids{FeedDimUnits},$tray_oids{XFeedDim},$tray_oids{XFeedDimUnits},$tray_oids{Status});
+        }
+
+        if(not defined($result)) {
+                print "CRITICAL - snmp error: " . $snmp->error() . "\n";
+                exit($ERRORS{'CRITICAL'});
+        }
+        foreach my $key (keys(%$result)) {
+                my($base, $index) = ($key =~ /($tray_oids{Table}\.\d+\.\d+)\.(\d+)/);
+                $result->{$key} =~ s/\"//g;
+                if($base eq $tray_oids{Cap}) { $tmpprs{$index}{cap}  = $result->{$key}; }
+                if($base eq $tray_oids{Status}) { $tmpprs{$index}{tstatus}  = $result->{$key}; }
+                if($base eq $tray_oids{MaxCap}) { $tmpprs{$index}{maxcap}  = $result->{$key}; }
+                if($base eq $tray_oids{Name}) { $tmpprs{$index}{name} = $result->{$key}; }
+                if($base eq $tray_oids{FeedDim}) { $tmpprs{$index}{feeddim} = $result->{$key}; }
+                if($base eq $tray_oids{XFeedDim}) { $tmpprs{$index}{xfeeddim} = $result->{$key}; }
+        }
+
+        foreach my $key (keys(%tmpprs)) {
+                $name=$tmpprs{$key}{name};
+                $cap=$tmpprs{$key}{cap};
+                $tstatus=$tmpprs{$key}{tstatus};
+                $maxcap=$tmpprs{$key}{maxcap};
+                $feeddim=$tmpprs{$key}{feeddim};
+                $xfeeddim=$tmpprs{$key}{xfeeddim};
+
+                # if name is empty, make one with the number
+                if ($name eq "") {
+                        $name="Tray $key";
+                }
+                if ($name =~ m/(MPT)/) {
+                        $name =~ s/ \(MPT\)//g;
+                }
+                if ($name =~ m/Paper Tray/) {
+                        ($name) = $name =~ /[^ ]* (.*)/;
+                }
+                $name =~ s/\n/\!/g;
+                if ($name =~ m/TRAY/) {
+                        if ($name =~ /(?<=TRAY)[0-9]/) {
+                                my @split = split(/(?<=\d)(?=\D)|(?<=\D)(?=\d)/, $name);
+                                        $name = @split[0]." ".@split[1];
+                        }
+                        $name = (ucfirst(lc($name)));
+                }
+                $lcname = lc($name);
+                if (($lcname =~ m/stack bypass|mp tray|manual paper|manual envelope|multi-purpose_tray/) and ($opt_nofeeder)) { $feeder=1; next; }
+                if (($lcname =~ m/tray 1/) and ($opt_nofeeder) and (scalar(keys(%tmpprs) > 1)) and $feeder != 1) { next; }
+                $found=1;
+                push @{ $trays[$traynumber] }, $name, $cap, $maxcap, $feeddim, $xfeeddim, $tstatus;
+                $traynumber++;
+        }
+
+        $traynumber = 0;
+        @strays = sort { $a->[0] cmp $b->[0] } @trays;
+        $tcount = scalar(@strays);
+        my $perfcount = $tcount;
+
+        while  ($tcount > 0) {
+                $name           = $strays[$i][0];
+                $cap            = $strays[$i][1];
+                $maxcap         = $strays[$i][2];
+                $feeddim        = $strays[$i][3];
+                $xfeeddim       = $strays[$i][4];
+                $tstatus        = $strays[$i][5];
+                $lcname         = lc($name);
+
+                if ($feeddim eq '-2') { $feeddim = "Any"; }
+                if ($xfeeddim eq '-2') { $xfeeddim = "Any"; }
+
+                $model = check_model(2);
+                if (($feeddim || $xfeeddim) ne 'Any') {
+                        if ($model =~ m/canon|xerox|ricoh|brother/) {
+                                if ($opt_metric) {
+                                        $feeddim = sprintf("%.0f", $feeddim * .001)."mm";
+                                        $xfeeddim = sprintf("%.0f", $xfeeddim * .001)."mm";
+                                } else {
+                                        $feeddim = sprintf("%.2f", (($feeddim / 2.54) * .0001))."in";
+                                        $xfeeddim = sprintf("%.2f", (($xfeeddim / 2.54) * .0001))."in";
+                                }
+                        } else {
+                                if ($opt_metric) {
+                                        $feeddim = sprintf("%.0f", (($feeddim * 2.54) * .001))."mm";
+                                        $xfeeddim = sprintf("%.0f", (($xfeeddim * 2.54) * .001))."mm";
+                                } else {
+                                        $feeddim = sprintf("%.2f", $feeddim * .0001)."in";
+                                        $xfeeddim = sprintf("%.2f", $xfeeddim  * .0001)."in";
+                                }
+                        }
+                }
+
+                if ($cap == -3) {
+                        # The value (-3) means that the printer knows that at least one unit remains.
+                        if ($model =~ m/lexmark/) { # When -3, Lexmark is really low status.
+                                if (($opt_critical == 0) or ($opt_warning == 0 )) {
+                                        $state = "OK";
+                                } else {
+                                        $state = "WARNING";
+                                }
+                                $traymessage = " is LOW. ($xfeeddim x $feeddim)";
+                        } else {
+                                $state = "OK";
+                                $traymessage = " ($xfeeddim x $feeddim)";
+                        }
+                } elsif ($cap == -2) {
+                        # The value (-2) means unknown
+                        # so lets check the tray status instead
+                        if ($tstatus eq '0') {
+                                if ($model =~ m/canon|hp|ricoh/) {
+                                        $state = "OK";
+                                        $traymessage = " ($xfeeddim x $feeddim)";
+                                } else {
+                                        $state = "WARNING";
+                                        $traymessage = " is in an UNKNOWN state.";
+                                }
+                                if (($lcname =~ m/tray 1|stack bypass|mp tray|manual paper|manual envelope|multi-purpose_tray/) and ($state ne 'WARNING')) {
+                                        $traymessage = "";
+                                }
+                        } elsif ($tstatus eq '4') {
+                                if ($model =~ m/lexmark/) {
+                                        $state = "OK";
+                                        $traymessage = " ($xfeeddim x $feeddim)";
+                                }
+                        } elsif ($tstatus eq '9') {
+                                if ($model =~ m/hp/) {
+                                        $state = "OK";
+                                        $traymessage = " ($xfeeddim x $feeddim)";
+                                }
+                        } else {
+                                # still unknown so we'll mark it warning because we just don't know
+                                $state = "WARNING";
+                                $traymessage = " is in UNKNOWN status.";
+                        }
+                } elsif ($cap == 0) {
+                        # 0 means there is no paper left! This is our only critical value.
+                        # first lets check to see if it's a bypass tray, we'll always assume Tray 1 is such.
+                        if ($lcname =~ m/tray 1|stack bypass|mp tray|manual paper|manual envelope|multi-purpose_tray/) {
+                                        $state = "CRITICAL";
+                                        if (($xfeeddim || $feeddim) ne 'Any') {
+                                                $traymessage = " ($xfeeddim x $feeddim)";
+                                        } else { $traymessage = " is empty."; }
+                                } else {
+                                        if ($opt_critical > 0) {
+                                                $state = "CRITICAL";
+                                        } else {
+                                                $state = "OK";
+                                        }
+                                        $traymessage = " ($xfeeddim x $feeddim) is at 0% paper remaining.";
+                                }
+                        $cap_pct=sprintf("%.2f",$cap*100/$maxcap);
+                } else {
+                        ($maxcap==0) && ($maxcap=1);
+                        $cap_pct=sprintf("%.2f",$cap*100/$maxcap);
+                        if (($cap_pct <= $opt_warning) and ($opt_warning > 0 )) {
+                                $state = "WARNING";
+                        } else {
+                                $state = "OK";
+                        }
+                        $traymessage = " ($xfeeddim x $feeddim) is at $cap_pct% paper remaining.";
+                }
+                push @{ $status[$traynumber] }, $state, $cap_pct;
+                push (@message, $traymessage);
+                $traynumber++;
+                $tcount--;
+                $i++;
+        }
+        prioritize_results('trays');
+        $i = 0;
+        $EXITSTRING.= "|";
+        while ($perfcount > 0) {
+                (my $tray = $strays[$i][0]) =~ s/ /_/g;
+                if ($status[$i][0] eq 'CRITICAL') {
+                        if ($status[$i][1] != "") {
+                                $EXITSTRING.= $tray."=$status[$i][1]";
+                        } else { $EXITSTRING.= $tray."=0"; }
+                }
+                if ($status[$i][0] eq 'WARNING') {
+                        if ($status[$i][1] != "") {
+                                $EXITSTRING.= $tray."=$status[$i][1]";
+                        } else { $EXITSTRING.= $tray."=10"; }
+                }
+                if ($status[$i][0] eq 'OK') {
+                        if ($status[$i][1] != "") {
+                                $EXITSTRING.= $tray."=$status[$i][1]";
+                        } else { $EXITSTRING.= $tray."=100"; }
+                }
+                $i++;
+                $perfcount--;
+                if ($perfcount == 0) { $EXITSTRING.= ";;;;"; } else { $EXITSTRING.=";;;; "; }
+        }
+}
+sub retry_snmp {
+        my ($sr1,$sr2,$sr3,$sr4,$sr5,$sr6,$sr7,$sr8) = @_;
+
+        if ($sr8) {
+                return $snmp->get_entries(-columns => [$sr1,$sr2,$sr3,$sr4,$sr5,$sr6,$sr7,$sr8]);
+        } elsif ($sr2) {
+                return $snmp->get_entries(-columns => [$sr1,$sr2,$sr3]);
+        } else {
+                return $snmp->get_request(-varbindlist => [$sr1]);
+        }
+}
+
+# set alarm in case we hang
+$SIG{ALRM} = sub {
+  print "CRITICAL - Timeout after $opt_timeout seconds\n";
+  exit($ERRORS{'CRITICAL'});
+};
+alarm($opt_timeout*$opt_retries);
+
+# connect to the snmp server
+($snmp, $errstr) = Net::SNMP->session(
+  -hostname  => $opt_host,
+  -version   => $opt_snmpver,
+  -community => $opt_community,
+  -timeout   => $opt_timeout,
+  -retries   => $opt_retries,
+);
+if (!$snmp) {
+  print "Could not create SNMP session: $errstr\n";
+  exit($ERRORS{'UNKNOWN'});
+}
+
+if ($opt_messages) {check_messages();}
+if ($opt_model) {check_model(1); exit($ERRORS{'OK'});}
+if ($opt_pagecount) {check_page_count();}
+if ($opt_consum) {check_consumables();}
+if (defined($opt_tray)) {check_paper_trays($opt_tray);}
+
+$i = 0;
+$scount = (scalar @status);
+while ($scount > 0) {
+        if ($status[$i][0] eq "CRITICAL") { $critcount++; }
+        if (($status[$i][0] eq "WARNING") && ($state ne "CRITICAL")) { $warncount++; }
+        $scount--;
+        $i++;
+}
+
+if ($critcount > 0) { $state = "CRITICAL"; }
+elsif ($warncount > 0) { $state = "WARNING"; }
+else { $state = "OK"; }
+
+stop($EXITSTRING, $state);
+sub stop {
+        my $result = shift;
+        my $exit_code = shift;
+        print $result . "\n";
+        exit ( $STATUS_CODE{$exit_code} );
+}