Dioda i WWW

W poprzednich artykułach pokazałem jak zapalić diodę z poziomu linuxa używając GPIO oraz jak postawić serwer WWW obsługujący skrypty CGI. W tym momencie mamy wszystko czego potrzeba do sterowania naszymi urządzeniami z drugiego końca świata. Należy się tylko nauczyć przekazywać parametry oraz je odczytywać za pomocą języka C. Przekazywanie parametrów odbywa się za pomocą formularza HTML, a o tym była już mowa w artykule o PHP. Tu robi się to dokładnie tak samo, tylko zamiast PHP używamy języka C. Poczytajcie sobie o tym w tym artykule http://avrkwiat.nstrefa.pl/omnie/index.php?option=com_content&view=article&id=52&Itemid=68.

Stwórzmy najpierw plik HTML o nazwie led.html i wgrywamy go do katalogu /www/pages/ na naszym mini komputerze. Będziemy go odpalać poprzez http://192.168.1.104/led.html. Ten plik ma za zadanie przekazać formularz ze zmienną "a" do pliku param-cgi umieszczonego w katalogu cgi-bin:

<html><body><h1>
<form action="http://192.168.1.104/cgi-bin/param-cgi">
dioda led 3: </br><input type="radio" name="a" value="0" /> ON<br />
<input type="radio" name="a" value="1" /> OFF<br />
<input type="submit" value="Wyślij dane" /><br />
</form>
</h1></body></html>

Gdy otworzymy go za pomocą przeglądarki uzyskamy następujący efekt:

Następnie tworzymy plik param-cgi.c w którym odbierzemy parametr "a" i w zależności od tego jakie wartości przyjął zapalimy lub zgasimy diodę. Po skompilowaniu otrzymamy plik param-cgi, który plik wgrywamy do katalogu www/cgi-bin/:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>


#define DIODA    "164"    

//PROTOTYPY FUNKCJI
int export_GPIO(char gpio_pin[]);            //eksport wyprowadzenia do przesrzeni użytkownika
int unexport_GPIO(char gpio_pin[]);            //odeskportowanie wyprowadzenia do jądra
int direction_GPIO(char gpio_pin[], char direction[]);    //ustawienie kierunku "in"/"out"
int set_GPIO(char gpio_pin[], int value);        //ustawienie stanu wyjścia "0"/"1"
int check_GPIO (char gpio_pin[]);
char *data;
long a,b;

int main (int argc, char *argv[]){
 printf("%s%c%c\n","Content-Type:text/html;charset=iso-8859-1",13,10);
 printf("<TITLE>Zgaszanie diody przez www</TITLE>\n");
 printf("<H2>0 oznacza ON, 1 oznacza OFF</H2>\n");

 data = getenv("QUERY_STRING");
 sscanf(data,"a=%d",&a);

 if(data == NULL)
 printf("<P>Nie przekazano parametrów");
 else
 printf("<P>Dioda 3: %d",a);

 export_GPIO(DIODA);
 direction_GPIO(DIODA,"out");

 if (a==1)
 set_GPIO(DIODA, 1);
 else set_GPIO(DIODA, 0);

 return 0;
}


/* ustawia numer portu GPIO, który będzie można dalej modyfikować i ustawiac jako wejść lub wyjście ------------------------------------------------------------------------------- */
int export_GPIO(char gpio_pin[]){

 FILE *fd;

 fd = fopen("/sys/class/gpio/export", "w");

 if (!fd){
 fprintf (stderr, "Blad otwarcia pliku\n");
 return -1;
 }else{
 fprintf (fd,"%s", gpio_pin);
 }
 fclose (fd);
 return 0;
}

/* zwalnia port GPIO wystarczy podać numer nóżki ------------------------------------------------------------------------------- */
int unexport_GPIO(char gpio_pin[]){    

 FILE *fd;
 
 fd = fopen("/sys/class/gpio/unexport", "w");

 if (!fd){
 fprintf (stderr, "Blad otwarcia pliku\n");
 return -1;
 }else{
 fprintf (fd,"%s", gpio_pin);
 }
 fclose (fd);
 return 0;
}

/* ustawia kierunek pinu in lub out ------------------------------------------------------------------------------- */
int direction_GPIO(char gpio_pin[], char direction[]){

 FILE *fd;
 char path [50] ="";

 strcat(path, "/sys/class/gpio/gpio");
 strcat(path, gpio_pin);
 strcat(path, "/direction");

 fd = fopen(path, "w");
 
 if (!fd){
 fprintf (stderr, "Blad otwarcia pliku\n");
 return -1;
 }else{
 fprintf (fd,"%s",direction);
 }
 fclose (fd);
 return 0;
}

/* ustawia wartość pinu 0 lub 1 ------------------------------------------------------------------------------- */
int set_GPIO(char gpio_pin[], int value){

 FILE *fd;
 char path [50] ="";

 strcat(path, "/sys/class/gpio/gpio");
 strcat(path, gpio_pin);
 strcat(path, "/value");

 fd = fopen(path, "w");
 
 if (!fd){
 fprintf (stderr, "Blad otwarcia pliku\n");
 return -1;
 }else{
 fprintf (fd,"%d", value);

 }
 fclose (fd);
 return 0;
}

/* sprawdza stan pinu i podaje 0 lub 1 ------------------------------------------------------------------------------- */
int check_GPIO(char gpio_pin[]){

 FILE *fd;
 char path [50] ="";
 char bufor [4];
 int temp;

 strcat(path, "/sys/class/gpio/gpio");
 strcat(path, gpio_pin);
 strcat(path, "/value");

 fd = fopen(path, "r");

 if (!fd){
 fprintf (stderr, "Blad otwarcia pliku\n");
 return -1;
 }else{

 if (!fgets(bufor,3,fd)){
 fprintf (stderr, "Blad odczytu danych\n");
 return -1;
 }else{
 temp = atoi (bufor);
 }
 }
 fclose (fd);
 return temp;
}

Gdy naciśniemy przycisk "wyślij" w naszym formularzu, to odpali się program param-cgi, który zapali lub zgasi diodę led3 oraz wyświetli się następujący komunikat ekranie przeglądarki.

Jak widać został przekazany parametr a=1, który jest widoczny także w wyszukiwarce po znaku "?". Można odpalać skrypt param-cgi bezpośrednio wpisując parametry w przeglądarce, tak jak to było możliwe w PHP. Teraz zamiast diody led możecie podczepić przekaźnik i sterować swoim światłem w domu z drugiego końca świata, albo opuszczać rolety w konie. Oczywiście musicie swój serwer udostępnić na świat (jeśli macie router). Należy wejść do konfiguracji routera i stworzyć virtualny serwer z przekierowaniem na wewnętrzny adres IP naszego minikomputera w taki sposób:

Całość można pobrać tu, kliknij , aby pobrać program