Code for a Linux + Arduino CPU load monitor
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

137 lines
2.7 KiB

#!/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();
}
}