The Arduinos are out collecting data and at some point that data needs to be sent to HCA, either for record-keeping or to take some action, like sending me an email. This posting provides an overview of how I accomplish this.
For the geeks: there are two basic techniques to do this, called synchronous and asynchronous. After screwing around with both I ended up simplifying it greatly by designing the interaction to always be asynchronous. I use UDP packets, which have no mechanism to detect missing or duplicate packets. The simplicity is that I can send and receive packets to/from either end without regard for what else is going on. The tradeoff is simplicity vs reliability. As a practical matter, as far as I know, the reliability has been rock-solid over my wired network. Wireless networks may present more of a problem.
The basic components include:
- The Arduino with an ethernet shield, programmed to send a UDP packet to HCA’s IP address.
- A continually-running Perl program that is constantly looking for incoming packets. When it detects one it reads it, optionally parses it, and places the result into a text file. The records in this text file are in the form of HCA flags.
- A continually-running program in HCA that reads all the flags in the text file (in my case, currently every 30 seconds) and sets them inside HCA.
- Other HCA programs that either record or take some action as the flags change.
The Arduino
As an example, an Arduino detects a fire alarm has triggered. The Arduino program to send HCA would contain the following lines:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x69 };
IPAddress ip(192, 168, 0, 69); // local IP address
IPAddress IP_Remote(192, 168, 0, 10); // IP address for HCA
unsigned int Port_Remote = 5000; // perl pgms port
EthernetUDP Udp;
void setup()
{
Ethernet.begin(mac,ip);
Udp.begin(localPort);
}
void loop()
{
Udp.beginPacket(IP_Remote, Port_Remote);
Udp.write(“ardfirealarm=yes”);
Udp.endPacket();
}
As you might guess, IP_Remote is HCA’s IP address and Port_Remote is the IP port that the Perl program is listening on. The ardfirealarm=yes is an HCA flag, in just the form that HCA expects to see it.
The Perl Program
The operational part of the Perl program looks like:
my ($socket,$received_data);
my $outln = “”;
my $outfile = “minutely.txt”; #picked up by hca
$socket = new IO::Socket::INET (
LocalPort => ‘5000’,
Proto => ‘udp’, )
while(1) # run forever
{
#read operation on the socket
$socket->recv($received_data,1024);
$outln = $received_data . “\n”;
open OUTPUT, “>> $outfile” or die “Output file open error: $!”;
print OUTPUT $outln;
close OUTPUT;
}
See how the Arduino’s remote port agrees with Perl’s local port? Doesn’t work so well if it doesn’t. First hand experience… Also note outfile’s value of “minutely.txt”. That becomes important shortly.
The HCA Read File Program
Meanwhile HCA has a program that is also continually running. The operational part of it looks like:
This picture gives you an idea of how easy programming HCA can be. The little boxes are the different functions HCA provides. You drag them into the program and connect them. Each box, depending upon its function, contains more instructions. In this case, the box at the upper left is a loop. When you click on this box’s properties you get the following window:
Note the “repeat forever” box is checked.
Immediately below the loop box is a “delay” box. Click on its properties and as you can guess the window is set for, in my case, 30 seconds.
Immediately below the delay box is the “read file” box. If you click on its properties it shows the location of the file to be read. In 30 seconds there might be more than one flag in the file. No matter. HCA will read all of them in turn and set its flags accordingly. Note that the name of the file, “minutely.exe”, must agree with the output of the Perl program above.
In my case I have two input files, one for Arduinos and one for other stuff. Finally, the two boxes at the bottom are “execute external” functions. I found that it was cleanest to rewrite the file to nulls to clean it out, as opposed to deleting it. Here’s the properties’ window:
This function is an important one, so I’ll take some time with it. It allows you to execute any external program or batch file on the computer. In this case I’m executing the Perl interpreter, perl.exe. The working directory is set so that all the necessary files are accessible – in this case just the file used to transfer the flags. The command line argument is the name of the Perl program I wrote to clear the file. One of these days I guess I’ll get rid of the “test” nomenclature. That Perl program is rather small. Here it is, in its entirety.
my $outfile = “minutely.txt”; #picked up by hca
my $outln = “”;
open OUTPUT, “> $outfile” or die “Output file open error: $!”;
print OUTPUT $outln;
close OUTPUT;
HCA Takes Action
FINALLY, you can set up HCA programs to start upon a number of conditions. One of these is when a flag changes. Here’s what it looks like inside HCA.
Note how the “ardfirealarm” agrees with what was created by the Arduino way back up at the start? And what does this program do? Here’s the flow diagram for it:
In order, the boxes do the following. First I log the event to one of HCA’s three logs. In the next two boxes I send an email and an sms message to let me know something is going on. Finally, the box in red is an “execute internal” function that starts another HCA program. In this case that other program asks the appropriate Arduinos to send back their temperature readings so maybe the nature of the fire can be determined.