832d554bf82a35ea2385aef968bdc37b60a78849
[snmp-json.git] / printer-callbacks.pl
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4
5 use Net::SNMP;
6 use Data::Dump qw(dump);
7
8 my $community = 'public';
9 my @printers = qw(
10 10.60.0.20
11
12 10.60.0.40
13
14 10.60.3.15
15 10.60.3.17
16 );
17
18 @printers = @ARGV if @ARGV;
19
20 my %vars = qw[
21 info                            iso.3.6.1.2.1.1.1.0
22 hostname                        iso.3.6.1.2.1.43.5.1.1.16.1
23 serial                          iso.3.6.1.2.1.43.5.1.1.17.1
24 pages                           iso.3.6.1.2.1.43.10.2.1.4.1
25 @message                        iso.3.6.1.2.1.43.18.1.1.8
26 @consumable.name        iso.3.6.1.2.1.43.11.1.1.6.1
27 @consumable.max         iso.3.6.1.2.1.43.11.1.1.8.1
28 @consumable.curr        iso.3.6.1.2.1.43.11.1.1.9.1
29 @tray.dim_x                     iso.3.6.1.2.1.43.8.2.1.4.1
30 @tray.dim_y                     iso.3.6.1.2.1.43.8.2.1.5.1
31 @tray.max                       iso.3.6.1.2.1.43.8.2.1.9.1
32 @tray.capacity          iso.3.6.1.2.1.43.8.2.1.10.1
33 @tray.name                      iso.3.6.1.2.1.43.8.2.1.13.1
34 ];
35
36 our $response;
37
38 sub columns_cb {
39         my ( $session, $oid2name ) = @_;
40
41         my $ip = $session->hostname;
42
43         if ( ! defined $session->var_bind_list ) {
44                 warn "ERROR: $ip ", $session->error, "\n";
45                 warn dump($session);
46                 return;
47         }
48
49
50         warn "# $ip var_bind_list ", dump( $session->var_bind_list );
51         my $results = $session->var_bind_list;
52         $response->{$ip} = { ip => $ip, utime => time() };
53         # oid_lex_sort would be wonderfull to use here, but it doesn't work
54         foreach my $r_oid ( sort {
55                         my ($af,$bf) = ($a,$b);
56                         $af =~ s{\.(\d+)$}{sprintf("%03d",$1)}eg;
57                         $bf =~ s{\.(\d+)$}{sprintf("%03d",$1)}eg;
58                         $af cmp $bf
59         } keys %$results ) {
60                 my $var = $results->{$r_oid};
61                 my $oid = (grep {
62                         substr($r_oid,0,length($_)) eq $_
63                 } keys %$oid2name)[0] || die "no name for $r_oid in ",dump($oid2name);
64                 my $name = $oid2name->{$oid};
65 warn "++ $oid $name $var\n";
66                 if ( $name =~ m{^\@} ) {
67                         my $no_prefix = $name;
68                         $no_prefix =~ s{^\@}{};
69                         push @{ $response->{$ip}->{ $no_prefix } }, $var;
70                 } else {
71                         $response->{$ip}->{ $name } = $var;
72                 }
73         }
74
75         warn "## $ip response ",dump($response->{$ip});
76 }
77
78 foreach my $host ( @printers ) {
79
80         my ( $snmp, $err ) = Net::SNMP->session(
81                 -hostname => $host,
82                 -version => 1,
83                 -community => $community,
84                 -timeout => 2,
85                 -retries => 0,
86                 -nonblocking => 1,
87         );
88
89         if ( ! $snmp ) {
90                 warn "ERROR: $host $err\n";
91                 next;
92         }
93
94         my @columns;
95         my @vars;
96         my $oid2name;
97         while ( my ($name,$oid) = each %vars ) {
98                 warn "# $name $oid\n";
99                 $oid =~ s{^iso}{.1};
100                 if ( $name =~ m/^\@/ ) {
101                         push @columns, $oid;
102                 } else {
103                         push @vars, $oid;
104                 }
105                 $oid2name->{$oid} = $name;
106         }
107         $snmp->get_request( -varbindlist => [ @vars ], -callback => [ \&columns_cb, $oid2name ] );
108         $snmp->get_entries( -columns =>  [ @columns ], -callback => [ \&columns_cb, $oid2name ] );
109
110 }
111
112 warn "# dispatch requests for ",dump(@printers);
113 snmp_dispatcher;
114
115 foreach my $ip ( keys %$response ) {
116
117         my $status = $response->{$ip};
118         foreach my $group ( grep { /\w+\.\w+/ } keys %$status ) {
119                 my ( $prefix,$name ) = split(/\./,$group,2);
120                 if ( ref $status->{$group} eq 'ARRAY' ) { # some consumables are non-repeatable on low-end devices
121                         foreach my $i ( 0 .. $#{ $status->{$group} } ) {
122                                 $status->{$prefix}->[$i]->{$name} = $status->{$group}->[$i];
123                         }
124                 } else {
125                         $status->{$prefix}->[0]->{$name} = $status->{$group};
126                 }
127                 delete $status->{$group};
128         }
129
130         print "$ip ",dump($status);
131 }