index previous next

Software Structure

 You have to make two files to CGI.
  • HTML file included Form script
  • Load module
Illustlate this structure. This CGI must have five functions.
  • Get command strings from standard input(stdin)
  • Analyze command strings
  • Put control signals
  • Get sensor states
  • Generate HTML script
After define system functions, write source code step by step.

Get command strings from standard input(stdin)

Get string length from 'Environment Variable' CONTENT_LENGTH in order to get 'POST' formated strings. When you will store these strings temporarily, apply malloc system call. Apply fread system call to store strings. char *pcCL = getenv("CONTENT_LENGTH"); char *pcQS = NULL ; int nCL ; if ( pcCL != NULL ) { nCL = 0 ; sscanf( pcCL , "%d" , &nCL ); if ( nCL > 0 ) { pcQS = malloc( nCL + 1 ); if ( pcQS == NULL ) { fprintf( stderr , "No memory <%d> \n",nCL ); exit(1); } fread( pcQS , 1 , nCL , stdin ); pcQS[nCL] = 0 ; } } if ( pcQS == NULL ) pcQS = "" ;

Analyze command strings

The following strings is to be put from 'stdin' (standard input). b0=1&b1=0&b2=1&b3=0 Actuator control signal informations are placed in fixed location. Get bit informations (1 or 0) from strings and concatenate them to be 4 bits control signal. I have written the following source code. int i ; UBYTE result ; result = 0 ; for ( i = 0 ; i < 4 ; i++ ) { result |= (pcQS[18-5*i] - '0') ; if ( i < 3 ) result <<= 1 ; }

Put control signals

Refer the following GPIO bit assignment and put control word to fd_dr (file discriptor).
  • GPIO_3 : control compressor
  • GPIO_2 : control lamp
  • GPIO_1 : close door
  • GPIO_0 : open door
Lower 4 bits are avairable because this system has four actuators. #define MASK0F 0x0f void put_actuator(UBYTE x) { UBYTE tmp ; tmp = x & MASK0F ; write( fd_dr , &tmp , sizeof(UBYTE) ); }

Get sensor states

Refer the following GPIO bit assignment and get sensor states from fd_dr (file discriptor).
  • GPIO_7 : spare input
  • GPIO_6 : spare input
  • GPIO_5 : detect objects
  • GPIO_4 : door micro switch
Upper 4 bits are avairable. UBYTE get_sensor(void) { UBYTE tmp ; read( fd_dr , &tmp , sizeof(UBYTE) ); tmp >>= 4 ; tmp &= MASK0F ; return tmp ; }

Generate HTML script

Make sequence and structure to show table and Form.
  1. header to indicate context
  2. title
  3. make table
  4. make form
  5. post processing
Define a function to put header information and execute some sequences. void make_html(PROP *x) { /* send content type */ out_header(); /* send header */ fprintf(stdout,"<html>"); crlf(); fprintf(stdout,"<title>Automatic Door</title>"); crlf(); fprintf(stdout,"<h3>"); crlf(); fprintf(stdout,"<body>"); crlf(); fprintf(stdout,"<blockquote>"); crlf(); /* update table script */ generate_table(x); /* update form script */ generate_form(x); /* send trailer */ fprintf(stdout,"</blockquote>"); crlf(); fprintf(stdout,"</body>"); crlf(); fprintf(stdout,"</h3>"); crlf(); fprintf(stdout,"</html>"); crlf(); /* flush buffer */ fflush(stdout); } After make top level control function, define some functions. *Make a function to send 'carriage return' and 'new line'. void crlf(void) { fprintf(stdout,"\r\n"); } *Make a function to send content type. void out_header(void) { fprintf( stdout , "Content-type: text/html"); crlf(); crlf(); } Define table format to show the state of sensors and actuators. void generate_table(PROP *x) { int up_index,low_index ; /* get parameters */ up_index = x->inf ; low_index = x->outf ; /* send top */ fprintf(stdout,"<pre>");crlf(); fprintf(stdout,"<table border>");crlf(); fprintf(stdout,"<tr><th colspan=\"2\">INPUT</th><th colspan=\"2\">OUTPUT</th></tr>"); crlf(); fprintf(stdout,"<tr>");crlf(); /* send first row */ fprintf(stdout,"<td align=middle>detect</td><td align=middle>"); if ( up_index & 2 ) fprintf(stdout,"yes"); else fprintf(stdout,"no"); fprintf(stdout,"</td>");crlf(); fprintf(stdout,"<td align=left>open</td><td align=right>"); if ( low_index & 1 ) fprintf(stdout,"enable"); else fprintf(stdout,"disable"); fprintf(stdout,"</td></tr>");crlf(); /* send second row */ fprintf(stdout,"<td align=middle>opened</td><td align=middle>"); if ( up_index & 1 ) fprintf(stdout,"yes"); else fprintf(stdout,"no"); fprintf(stdout,"</td>");crlf(); fprintf(stdout,"<td align=left>close</td><td align=right>"); if ( low_index & 2 ) fprintf(stdout,"enable"); else fprintf(stdout,"disable"); fprintf(stdout,"</td></tr>");crlf(); /* third row */ fprintf(stdout,"<tr>");crlf(); fprintf(stdout,"<td></td><td></td>");crlf(); fprintf(stdout,"<td align=left>light</td><td align=right>"); if ( low_index & 4 ) fprintf(stdout,"enable"); else fprintf(stdout,"disable"); fprintf(stdout,"</td></tr>");crlf(); /* last row */ fprintf(stdout,"<tr>");crlf(); fprintf(stdout,"<td></td><td></td>");crlf(); fprintf(stdout,"<td align=left>pump</td><td align=right>"); if ( low_index & 8 ) fprintf(stdout,"enable"); else fprintf(stdout,"disable"); fprintf(stdout,"</td></tr>");crlf(); /* send bottom */ fprintf(stdout,"</pre>");crlf(); fprintf(stdout,"<hr>");crlf(); } Form area indicates 'check' boxes and 'submit' buttons. void generate_radio(int x,int y) { /* check range */ if ( x < 0 || 3 < x ) return ; if ( y < 0 || 1 < y ) return ; /* send item string */ switch ( x ) { case 0 : fprintf(stdout,"<li>open" ) ; crlf(); break; case 1 : fprintf(stdout,"<li>close" ); crlf(); break; case 2 : fprintf(stdout,"<li>light" ); crlf(); break; case 3 : fprintf(stdout,"<li>pump" ) ; crlf(); break; } /* first line */ fprintf(stdout,"<input type=\"radio\" name=\"b%d\" value=\"0\" ",x); if ( y == 0 ) fprintf(stdout,"checked"); fprintf(stdout, ">OFF");crlf(); /* second line */ fprintf(stdout,"<input type=\"radio\" name=\"b%d\" value=\"1\" ",x); if ( y == 1 ) fprintf(stdout,"checked"); fprintf(stdout,">ON");crlf(); }

main function

After define primitive functions, write control sequence in main function.
  1. Get strings length from 'Environment Variable'
  2. Get command strings from 'stdin'
  3. Analyze command strings
  4. Put control signals to actuators according to information
  5. Get sensor states
  6. Generate HTML script
  7. Send HTML script to network
Convert the above sequence to source code. int main(void) { char *pcCL = getenv("CONTENT_LENGTH"); char *pcQS = NULL ; int i,nCL ; UBYTE result ; PROP profile ; /* set initial values */ profile.inf = 0 ; profile.outf = 0 ; /* show parameter strings */ if ( pcCL != NULL ) { nCL = 0 ; sscanf( pcCL , "%d" , &nCL ); if ( nCL > 0 ) { pcQS = malloc( nCL + 1 ); if ( pcQS == NULL ) { fprintf( stderr , "No memory <%d> \n",nCL ); exit(1); } fread( pcQS , 1 , nCL , stdin ); pcQS[nCL] = 0 ; } } if ( pcQS == NULL ) pcQS = "" ; result = 0 ; for ( i = 0 ; i < 4 ; i++ ) { result |= (pcQS[18-5*i] - '0') ; if ( i < 3 ) result <<= 1 ; } /* check control code */ if ( check_double_booking(result) == TRUE ) { send_err_msg("Can't set both OPEN and CLOSE !"); return -1 ; } /* actual perform */ profile.outf = result ; if ( initialize() == 0 ) { /* output information */ put_actuator(profile.outf); /* wait */ sleep(3) ; /* input information */ profile.inf = get_sensor(); set_close(); } /* update html context */ make_html(&profile); return 0; }

Define structure

I have defined structure to manage some informations simultaneously. typedef struct { UBYTE inf ; /* input information */ UBYTE outf ; /* output information */ } PROP ;

Set permission of device files

You must set permmision of device files in CGI controlling. Set permission in 'root' mode. # chmod 666 /dev/pbddr # chmod 666 /dev/pbdr I could not run this system at first. Because I didn't change permmision of device files.

index previous next

inserted by FC2 system