|
|
- #!/usr/bin/perl
-
- use strict;
- use warnings;
- use 5.10.0;
-
- use Device::SerialPort;
- use POSIX qw(setsid);
- use File::Slurp;
- use Getopt::Long;
- use LWP::UserAgent;
-
- my $remote;
- my $refresh_rate = 10;
- my $daemon = 0;
- my $cpucount = 2; # default to 2 CPUs
- my $device = '/dev/ttyUSB0';
-
- my $getopt_result = GetOptions (
- "device=s" => \$device, # string
- "refresh=i" => \$refresh_rate, # numeric
- "remote=s" => \$remote, # string
- "daemon" => \$daemon, # flag
- "cores=i" => \$cpucount # numeric
- );
-
- say "Talking to Arduino on $device";
-
- if ($daemon) {
- daemonize();
- }
-
- # set a count explicitly - need this for remotes
- if ($remote && $cpucount) {
- countcpus($cpucount);
- }
-
- # connect to the arduino
- my $port = Device::SerialPort->new($device)
- or die "Couldn't connect to $device";
-
- $port->databits(8);
- $port->baudrate(9600);
- $port->parity('none');
- $port->stopbits(1);
-
- # ^C
- $SIG{INT} = "cleanup";
-
- while (1) {
- my $degrees = getdegrees();
-
- # pack into a 16 bit int (i think) and send to the arduino
- my $count_out = $port->write(pack 's', $degrees)
- or die "Unable to write to $device";
-
- say "$degrees degrees, $count_out bytes sent" unless $daemon;
- sleep $refresh_rate;
- }
-
- sub getdegrees {
- my $loadstring;
- if ($remote) {
- $loadstring = getremoteload($remote);
- } else {
- $loadstring = read_file('/proc/loadavg');
- }
-
- my ($load) = split / /, $loadstring;
- say "Load: $load" unless $daemon;
- return 1 if $load >= countcpus();
- return int(($load / countcpus()) * 180);
- }
-
- # sometimes i miss writing a language that's too clever for its own good
- { my $count;
- sub countcpus {
- my ($setcount) = @_;
- if ($setcount) {
- say "CPUs explicitly set to $setcount" unless $daemon;
- $count = $setcount;
- }
- $count //= grep { /^processor\s+: [0-9]/ } read_file('/proc/cpuinfo');
- }
- }
-
- sub getremoteload {
- my ($remote) = @_;
- # Create a user agent object
- my $ua = LWP::UserAgent->new;
- $ua->agent("loaduino/0.1 ");
-
- # Create a request
- my $req = HTTP::Request->new(GET => $remote);
-
- # Pass request to the user agent and get a response back
- my $res = $ua->request($req);
-
- # Check the outcome of the response
- my $loadstring;
- if ($res->is_success) {
- $loadstring = $res->content;
- } else {
- say $res->status_line;
- $loadstring = '0.0';
- }
-
- say "Load string: $loadstring";
- return $loadstring;
- }
-
- sub daemonize {
- chdir '/';
- umask 0;
- open STDIN, '/dev/null';
- open STDOUT, '>', '/dev/null';
- open STDERR, '>', '/dev/null';
- defined(my $pid = fork)
- or die "Can't fork: $!";
- exit if $pid;
- setsid
- or die "Can't start a new sesssion: $!";
- }
-
- sub cleanup {
- say "cleaning up";
- $port->close() || warn "close failed";
- undef $port;
- die "murdered!";
- }
-
- END {
- if (defined $port) {
- cleanup();
- }
- }
-
|