#!/usr/bin/perl use warnings; use strict; use threads; package BRscan::Config; our $port = 54925; our $printer = "192.168.4.42"; our $myip = "192.168.4.247"; our $debug = 1; our $work_dir = "/mnt/levant/nfs/tmp"; package BRscan::Listener; use IO::Socket; use feature qw/switch/; #use Data::Dumper; sub run { my $max_len = 2048; our $debug = $BRscan::Config::debug; my $msg; my @processed; my $sock = IO::Socket::INET->new(LocalPort => $BRscan::Config::port, Proto => 'udp') or die "socket: $@"; while ($sock->recv($msg, $max_len)) { my $cport = $sock->peerport(); my $chost = $sock->peerhost(); print STDERR "Client $chost:$cport said: $msg\n" if $debug; # discard first 4 bytes, probably not relevant # TODO: what do they mean? $msg = substr($msg, 4); my %fields; for my $field (split(/;/, $msg)) { my ($key, $value) = split(/=/, $field); next unless defined($key) and defined($value); print STDERR "key: \"$key\"; value: \"$value\"\n" if $debug; $fields{$key} = $value; } # BR likely stands for "brother". use this to determine if it's really a request from a brother device next unless $fields{TYPE} eq "BR"; # ignore multiple requests # TODO: clean up old ids my $id = $fields{REGID}."-".$fields{SEQ}; if ($id ~~ @processed) { print STDERR "already processed $id. skipping...\n" if $debug; next; } # we only handle the scan button next unless $fields{BUTTON} eq "SCAN"; print STDERR "got $fields{FUNC} scan request\n" if $debug; # possible values: FILE, IMAGE, OCR, EMAIL given ($fields{FUNC}) { when (/IMAGE/) { chdir("$BRscan::Config::work_dir"); system("scan-multi"); } when (/FILE/) { chdir("$BRscan::Config::work_dir"); system("scan-multi --pdf"); } } push @processed, $id; print STDERR "finished processing $id\n"; } } package BRscan::RegWatcher; use Net::SNMP; sub run { our $debug = $BRscan::Config::debug; my ($session, $error) = Net::SNMP->session( -community => "internal", -version => 1, -hostname => $BRscan::Config::printer, ); if (!defined $session) { printf STDERR "ERROR: %s.\n", $error; exit 1; } # unhandled are commented out my @apps = ( {appnum => 1, func => "IMAGE"}, #{appnum => 2, func => "EMAIL"}, #{appnum => 3, func => "OCR"}, {appnum => 5, func => "FILE"}, ); my @varbindlist; for my $app (@apps) { push @varbindlist, "1.3.6.1.4.1.2435.2.3.9.2.11.1.1.0"; push @varbindlist, OCTET_STRING; push @varbindlist, "TYPE=BR;BUTTON=SCAN;USER=".$ENV{USER}.";FUNC=".$app->{"func"}.";HOST=".$BRscan::Config::myip.":".$BRscan::Config::port.";APPNUM=".$app->{"appnum"}.";DURATION=360;BRID=;"; } @apps = undef; while (1) { print STDERR "sending snmp set_request\n" if $debug; my $result = $session->set_request(-varbindlist => \@varbindlist); if (!defined $result) { printf "ERROR in set_request: %s.\n", $session->error(); } sleep 60; } } package main; our $debug = $BRscan::Config::debug; threads->new("BRscan::Listener::run"); threads->new("BRscan::RegWatcher::run"); # wait for everyone before exiting foreach my $thr (threads->list) { if ($thr->tid && !threads::equal($thr, threads->self)) { print "waiting for thread ".$thr->tid()." to finish\n" if $debug; $thr->join; } } __END__ =head1 NAME brscan-key.pl - Deamon for brother scanner key =head1 DESCRIPTION This daemon registers itself with a brother scanner and accepts incoming scanning requests. =cut