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

14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use 5.10.0;
  5. use Device::SerialPort;
  6. use POSIX qw(setsid);
  7. use File::Slurp;
  8. use Getopt::Long;
  9. use LWP::UserAgent;
  10. my $remote;
  11. my $refresh_rate = 10;
  12. my $daemon = 0;
  13. my $cpucount = 2; # default to 2 CPUs
  14. my $device = '/dev/ttyUSB0';
  15. my $getopt_result = GetOptions (
  16. "device=s" => \$device, # string
  17. "refresh=i" => \$refresh_rate, # numeric
  18. "remote=s" => \$remote, # string
  19. "daemon" => \$daemon, # flag
  20. "cores=i" => \$cpucount # numeric
  21. );
  22. say "Talking to Arduino on $device";
  23. if ($daemon) {
  24. daemonize();
  25. }
  26. # set a count explicitly - need this for remotes
  27. if ($remote && $cpucount) {
  28. countcpus($cpucount);
  29. }
  30. # connect to the arduino
  31. my $port = Device::SerialPort->new($device)
  32. or die "Couldn't connect to $device";
  33. $port->databits(8);
  34. $port->baudrate(9600);
  35. $port->parity('none');
  36. $port->stopbits(1);
  37. # ^C
  38. $SIG{INT} = "cleanup";
  39. while (1) {
  40. my $degrees = getdegrees();
  41. # pack into a 16 bit int (i think) and send to the arduino
  42. my $count_out = $port->write(pack 's', $degrees)
  43. or die "Unable to write to $device";
  44. say "$degrees degrees, $count_out bytes sent" unless $daemon;
  45. sleep $refresh_rate;
  46. }
  47. sub getdegrees {
  48. my $loadstring;
  49. if ($remote) {
  50. $loadstring = getremoteload($remote);
  51. } else {
  52. $loadstring = read_file('/proc/loadavg');
  53. }
  54. my ($load) = split / /, $loadstring;
  55. say "Load: $load" unless $daemon;
  56. return 1 if $load >= countcpus();
  57. return int(($load / countcpus()) * 180);
  58. }
  59. # sometimes i miss writing a language that's too clever for its own good
  60. { my $count;
  61. sub countcpus {
  62. my ($setcount) = @_;
  63. if ($setcount) {
  64. say "CPUs explicitly set to $setcount" unless $daemon;
  65. $count = $setcount;
  66. }
  67. $count //= grep { /^processor\s+: [0-9]/ } read_file('/proc/cpuinfo');
  68. }
  69. }
  70. sub getremoteload {
  71. my ($remote) = @_;
  72. # Create a user agent object
  73. my $ua = LWP::UserAgent->new;
  74. $ua->agent("loaduino/0.1 ");
  75. # Create a request
  76. my $req = HTTP::Request->new(GET => $remote);
  77. # Pass request to the user agent and get a response back
  78. my $res = $ua->request($req);
  79. # Check the outcome of the response
  80. my $loadstring;
  81. if ($res->is_success) {
  82. $loadstring = $res->content;
  83. } else {
  84. say $res->status_line;
  85. $loadstring = '0.0';
  86. }
  87. say "Load string: $loadstring";
  88. return $loadstring;
  89. }
  90. sub daemonize {
  91. chdir '/';
  92. umask 0;
  93. open STDIN, '/dev/null';
  94. open STDOUT, '>', '/dev/null';
  95. open STDERR, '>', '/dev/null';
  96. defined(my $pid = fork)
  97. or die "Can't fork: $!";
  98. exit if $pid;
  99. setsid
  100. or die "Can't start a new sesssion: $!";
  101. }
  102. sub cleanup {
  103. say "cleaning up";
  104. $port->close() || warn "close failed";
  105. undef $port;
  106. die "murdered!";
  107. }
  108. END {
  109. if (defined $port) {
  110. cleanup();
  111. }
  112. }