11124fe83a2d9bbc864893149c519eff6293c0f2
[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 $dir = 'public/json/monitor/printers/';
9 $dir = "/tmp/printers-" unless -d $dir;
10
11 use JSON;
12 sub save_json {
13         my ( $ip, $json ) = @_;
14         my $path = $dir . $ip;
15         open(my $fh, '>', $path) || die "$path: $!";
16         print $fh encode_json $json;
17         close($fh);
18         warn "# $path ", -s $path, " bytes\n";
19 }
20
21 sub iso_datetime {
22         my ($ss,$mm,$hh,$d,$m,$y) = localtime(time);
23         return sprintf "%04d-%02d-%02dT%02d:%02d:%02d", $y+1900, $m, $d, $hh, $mm, $ss;
24 }
25
26 my $log_path = join('.', $dir, (split(/T/,iso_datetime,2))[0], 'json');
27 open(my $log, '>>', $log_path) || die "$log_path: $!";
28
29 my $community = 'public';
30 my @printers = qw(
31 10.60.0.20
32
33 10.60.0.40
34
35 10.60.3.15
36 10.60.3.17
37 );
38
39 @printers = @ARGV if @ARGV;
40
41 my %vars = qw[
42 info                            iso.3.6.1.2.1.1.1.0
43 hostname                        iso.3.6.1.2.1.43.5.1.1.16.1
44 serial                          iso.3.6.1.2.1.43.5.1.1.17.1
45 pages                           iso.3.6.1.2.1.43.10.2.1.4.1
46 @message                        iso.3.6.1.2.1.43.18.1.1.8
47 @consumable.name        iso.3.6.1.2.1.43.11.1.1.6.1
48 @consumable.max         iso.3.6.1.2.1.43.11.1.1.8.1
49 @consumable.curr        iso.3.6.1.2.1.43.11.1.1.9.1
50 @tray.dim_x                     iso.3.6.1.2.1.43.8.2.1.4.1
51 @tray.dim_y                     iso.3.6.1.2.1.43.8.2.1.5.1
52 @tray.max                       iso.3.6.1.2.1.43.8.2.1.9.1
53 @tray.capacity          iso.3.6.1.2.1.43.8.2.1.10.1
54 @tray.name                      iso.3.6.1.2.1.43.8.2.1.13.1
55 ];
56
57 our $response;
58
59 sub columns_cb {
60         my ( $session, $oid2name ) = @_;
61
62         my $ip = $session->hostname;
63
64         if ( ! defined $session->var_bind_list ) {
65                 warn "ERROR: $ip ", $session->error, "\n";
66                 warn dump($session);
67                 return;
68         }
69
70
71         warn "# $ip var_bind_list ", dump( $session->var_bind_list );
72         my $results = $session->var_bind_list;
73         $response->{$ip} = { ip => $ip, utime => time() };
74         # oid_lex_sort would be wonderfull to use here, but it doesn't work
75         foreach my $r_oid ( sort {
76                         my ($af,$bf) = ($a,$b);
77                         $af =~ s{\.(\d+)$}{sprintf("%03d",$1)}eg;
78                         $bf =~ s{\.(\d+)$}{sprintf("%03d",$1)}eg;
79                         $af cmp $bf
80         } keys %$results ) {
81                 my $var = $results->{$r_oid};
82                 my $oid = (grep {
83                         substr($r_oid,0,length($_)) eq $_
84                 } keys %$oid2name)[0] || die "no name for $r_oid in ",dump($oid2name);
85                 my $name = $oid2name->{$oid};
86 warn "++ $oid $name $var\n";
87                 if ( $name =~ m{^\@} ) {
88                         my $no_prefix = $name;
89                         $no_prefix =~ s{^\@}{};
90                         push @{ $response->{$ip}->{ $no_prefix } }, $var;
91                 } else {
92                         $response->{$ip}->{ $name } = $var;
93                 }
94         }
95
96         warn "## $ip response ",dump($response->{$ip});
97         save_json $ip => $response->{$ip};
98         print $log encode_json($response->{$ip}),"\n";
99 }
100
101 foreach my $host ( @printers ) {
102
103         my ( $snmp, $err ) = Net::SNMP->session(
104                 -hostname => $host,
105                 -version => 1,
106                 -community => $community,
107                 -timeout => 2,
108                 -retries => 0,
109                 -nonblocking => 1,
110         );
111
112         if ( ! $snmp ) {
113                 warn "ERROR: $host $err\n";
114                 next;
115         }
116
117         my @columns;
118         my @vars;
119         my $oid2name;
120         while ( my ($name,$oid) = each %vars ) {
121                 warn "# $name $oid\n";
122                 $oid =~ s{^iso}{.1};
123                 if ( $name =~ m/^\@/ ) {
124                         push @columns, $oid;
125                 } else {
126                         push @vars, $oid;
127                 }
128                 $oid2name->{$oid} = $name;
129         }
130         $snmp->get_request( -varbindlist => [ @vars ], -callback => [ \&columns_cb, $oid2name ] );
131         $snmp->get_entries( -columns =>  [ @columns ], -callback => [ \&columns_cb, $oid2name ] );
132
133 }
134
135 warn "# dispatch requests for ",dump(@printers);
136 snmp_dispatcher;
137
138 foreach my $ip ( keys %$response ) {
139
140         my $status = $response->{$ip};
141         foreach my $group ( grep { /\w+\.\w+/ } keys %$status ) {
142                 my ( $prefix,$name ) = split(/\./,$group,2);
143                 if ( ref $status->{$group} eq 'ARRAY' ) { # some consumables are non-repeatable on low-end devices
144                         foreach my $i ( 0 .. $#{ $status->{$group} } ) {
145                                 $status->{$prefix}->[$i]->{$name} = $status->{$group}->[$i];
146                         }
147                 } else {
148                         $status->{$prefix}->[0]->{$name} = $status->{$group};
149                 }
150                 delete $status->{$group};
151         }
152
153         print "$ip ",dump($status);
154 }
155
156 close($log);
157 warn "# log $log_path ", -s $log_path, " bytes\n";
158