The old saying is that there's always more than one way to skin a cat. One of the original GP3EZ demos took an LM34 temperature sensor and posted the result to a web page using some off the shelf tools from the Cygwin toolkit.

The GP3EZ software is very flexible, so naturally there is more than one way to accomplish this goal. In this article, I'll show you yet another way, this time using the GP3EZ's file logging capability and some custom code designed for the task.

Here's the simple GP3EZ script:

Step # Tag Condition Action Next Notes
1 Start (wait) Analog 0>=0 V External New File: c:\daq.txt
  This is going to read a temperature to the web using the gp3ezweb helper program. This step always triggers. But the step value will be the analog value which we will use to start off the output file
2 digital (wait) Input: XXXXXXXX External Add File: c:\daq.txt
  Now we will get the digital input values and log them as line 2
3   (wait) Always External program: c:\gp3ezweb c:\daqtemplate.htm c:\daq.txt c:\daq.htm
  Now we run the gp3ezweb program. You'll need to adjust the paths. Note you might just as well have started a batch file or script that would run the program and then upload the daq.htm file to your server if you wanted to. Or you could make that the next step. Of course, if you are running on the web server, you can just arrange for the file to wind up in the server directory.
4   (wait) After 1/22/2008 9:44:06 AM Repeat 00:05:00   Start This step waits for 5 minutes. You could plug in an "after" delay if you prefer. Note that the after time resets itself on each trigger. So if it triggers at 09:44 the new trigger will be set for 09:49 (5 minutes later). The condition is that the time is simply "after" so to start with you can set the date/time to any time before now (which it should already be set that way) and that "primes" the pump.

Note you might want to change the paths in steps 1-3. I put everything in c:\ to keep it simple. Let's look at it step by step.

1. The analog input will always be >=0V! So this step always occurs but sets the step value to the analog 0 value (the temperature sensor is connected to this port). The External New File action creates a new file (deletinging any old one) and writes the value (among other things). We'll examine this file shortly.

2. This step is similar but it reads the digital I/O. Perhaps this is a freezer controller and the digital inputs are showing door switches. Here, the external file is the same, but the "Add" tells it to append it to the file, not create a new file.

3. Step 3 calls an external program we'll examine shortly. It takes a template file, the data file, and produces an output file.

4. This step waits for 5 minutes before going back to Start.

Obviously, you could insert a step between 3 and 4 to copy the file to a web server, if you wanted to. Or, as the comments indicate, you could have started a batch file to do the file transformation and copy the file to a web server. Like I said, there are lots of ways to skin a cat.

The daq.txt file has a simple format:
1/22/2008 9:39:06 AM,0.7519531,Start,{none}
1/22/2008 9:39:06 AM,57,digital,{none}


The first field is the time and date of the sample, the next field is the value. After that is the name or number of the step that generated the line (Start or digital, in this case). The final field is the GP3's current state which we are not using in this example.

The LM34 has an output of 10mV/degree so the temperature is actually about 75.2 degrees. The digital input is 57 which is 39 in hex or 00111001 in binary.

The template file is just a text file. However, the gp3ezweb program replaces special character sequences in the template with values from the data file to produce the output file. The names of the fields are in curly braces (so {Start} and {digital} are the two fields. You can also get the time and date of a field by prefixing it with @ (so {@Start} would give you the time and date of the Start line. You can also use {$state} to get the last state value (meaningless in this case) and {{} will write out an actual curly brace. The field names are case sensitive. Here's a simple template file:

 

<HTML>
<HEAD><TITLE>GP3 Web Demo</TITLE></HEAD>
<BODY BGCOLOR=#C1C0C6>
<H1>GP3 Web Demo #2</H1>
<H3>{@Start}</H3>
<P>Raw

counts={Start}
<P>Raw digital={digital}
<hr>
<P>Temp=
<SCRIPT language=javascript>
<!--
t={Start};
dio={digital};
t1=Math.round(t*1000)/10;
document.write(t1);
//-->
</SCRIPT>
<BR>
<P>Status:<BR>
<SCRIPT language=javascript>
<!--
  for (i=128;i>=1;i=i>>=1)    if (dio & i)       document.write("<img src=led-on.jpg>"); else
      document.write("<img src=led-off.jpg>");
//-->
</SCRIPT>
<P>
</BODY>
</HTML>

The variables are highlighted in red. Note that the most useful part of the page just sets the values into a Javascript that does calculations with the values.

The result is a page that looks like this:




Here's a zip file with all the files (including gp3ezweb): zip file

If you are curious, here's the source code for the program:

/* GP3EZWEB by AWC - http://www.awce.com */

#include 
#include 

// format of the GP3EZ output lines (conservatively spaced)
typedef struct 
{
  char timedate[64];
  char value[64];
  char id[64];
} record;

// last state
char state[64];
// Maximum #of different values
record records[128];
// high water mark in array
int recordmax=0;


int main(int argc, char *argv[])
{
  FILE *in=stdin;
  FILE *out=stdout;
  FILE *template;
  char line[1025];
  char lineout[1025];
  char *token;
  // set up file handles
  if (argc<=1)
    {
      fprintf(stderr,"Usage: gp3ezweb template [in|-] [out|-]\nUse dashes for standard input or output\n");
      return 2;
    }
  template=fopen(argv[1],"r");
  if (!template) return 4;
  if (argc>2 && *argv[2]!='-') in=fopen(argv[2],"r");
  if (!in) { perror(argv[2]); return 1; }
  if (argc>3 && *argv[3]!='-') out=fopen(argv[3],"w");
  if (!out) { perror(argv[2]); return 3; }
  // read input -- take last value and last state only
  while (!feof(in)&&fgets(line,sizeof(line),in))
    {
      int i;
      token=strtok(line,",");
      if (!token) continue; // huh?
      // tenatively record this line
      strcpy(records[recordmax].timedate,token);
      token=strtok(NULL,",");
      if (!token) continue;
      strcpy(records[recordmax].value,token);
      token=strtok(NULL,",");
      if (!token) continue;
      strcpy(records[recordmax].id,token);
      // look to see if we can replace an old one
      for (i=0;i=recordmax)
	{
	  recordmax++;
	}
      // get state
      token=strtok(NULL,"\n");
      strcpy(state,token);
    }
  if (in!=stdin) fclose(in);

  // now copy the template to the output
  while (!feof(template) && fgets(line,sizeof(line),template))
    {
      char *p1,*p2;
      int offset=0, i, tokenoffset=0;
      *lineout='\0';

      // find {}
      while (p1=strchr(line+offset,'{'))
	{
	  *p1='\0';
	  strcat(lineout,line+offset);
	  p2=strchr(p1+1,'}');
	  if (!p2) break;
	  offset=(p2+1)-line;
	  *p2='\0';
	  token=p1+1;
	  if (!strcmp(token,"{"))  // literal {
	    {
	      strcat(lineout,"{");
	      continue;
	    }
	  if (!strcmp(token,"$state"))  // state
	    {
	      strcat(lineout,state);
	      continue;
	    }
	  if (*token=='@') tokenoffset=1;  // time stamp
	  for (i=0;i