树莓派centos 第十八章 C语言自建web服务器,网页控制RGB灯

1 .开发文 件夹,先建立几个文

index.html 是前端网页控制文件,用户界面,用户控制RGB灯

main.c是 后端web服务器代码,用于控制硬件RGB灯

2.编辑前端网页界面 index.html

网页的界面有三个按钮

HTTP/1.1 200 OK
Content-Type: text/html
Connection: close
Refresh: 300

<!DOCTYPE HTML>
<html>
<head>
<title>Rpi Car</title>
<style>
body {background-color: white}
button {
color: red;
height: 150px;
width: 150px;
background:white;
border: 3px solid #4CAF50; 
border-radius: 50%;
font-size: 250%;
position: center;}
</style>
<link rel="icon" href="data:image/ico;base64,aWNv">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
</head>
<center>
<div><button name="CMD" value="left"  onclick="SetRGB(1,0,0);">Red</button>
<button name="CMD" value="stop"  onclick="SetRGB(0,1,0);">Green</button>
<button name="CMD" value="right"  onclick="SetRGB(0,0,1);">Blue</button></div>
</center>

<script type="text/javascript">
function ajax() 
{
    var ajaxData = 
    {
        type: arguments[0].type || "GET",
        url: arguments[0].url || "",
        async: arguments[0].async || "true",
        data: arguments[0].data || null,
        dataType: arguments[0].dataType || "text",
        contentType: arguments[0].contentType || "application/x-www-form-urlencoded",
        beforeSend: arguments[0].beforeSend || function () { },
        success: arguments[0].success || function () { },
        error: arguments[0].error || function () { }
    }
    ajaxData.beforeSend()
    var xhr = createxmlHttpRequest();
    xhr.responseType = ajaxData.dataType;
    xhr.open(ajaxData.type, ajaxData.url, ajaxData.async);
    xhr.setRequestHeader("Content-Type", ajaxData.contentType);
    xhr.send(convertData(ajaxData.data));
    xhr.onreadystatechange = function () 
    {
        if (xhr.readyState == 4) 
        {
            if (xhr.status == 200) 
            {
                ajaxData.success(xhr.response)
            }
            else 
            {
                ajaxData.error()
            }
        }
    }
}

function createxmlHttpRequest() 
{
    if (window.ActiveXObject) 
    {
        return new ActiveXObject("Microsoft.XMLHTTP");
    }
    else if (window.XMLHttpRequest) 
    {
        return new XMLHttpRequest();
    }
}

function convertData(data) 
{
    if (typeof data === 'object') 
    {
        var convertResult = "";
        for (var c in data) 
        {
            convertResult += c + "=" + data[c] + "&";
        }
        convertResult = convertResult.substring(0, convertResult.length - 1)
        return convertResult;
    } 
    else 
    {
        return data;
    }
}




function SetRGB( R,  G,  B)
{
    var url1 = "api.php?SetRGB="+R+","+G+","+B;
    
    ajax({
        type: "GET",
        url: url1,
        dataType: "json",
        data: { 'scommon': 'SetRGB', 'Reg':R, 'Green':G,'Blue':B },
        beforeSend: function () 
        {
            //some js code 
        },
        success: function (msg) 
        {
            //console.log(msg) 
        },
        error: function () 
        {
            // console.log("error") 
        }
    });
}
</script>
</html>

3.编辑后台控制程序 main.c

/************************************************************************* 
> File Path: /var/www/develop/20201217/
> File Name: main.c
> Author: Mee 
> QQ: 11345612
> Date: 2020-12-17
>  g++ main.c -o test -lwiringPi -lwiringPiDev -lpthread
************************************************************************/  

 
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <wiringPi.h> 

#define PORT 8848
#define BACKLOG 5
#define MAXDATASIZE 1000
//#define DEBUG 0

#define LEDR 29
#define LEDG 28
#define LEDB 27

void process_cli(int connectfd, sockaddr_in client);
int sendobj(int connectfd,char* serverfilepath);
int IsDIR(char* fpath);
int fileordirExist(char* fpath);
char* getextname(char*);
int writehead(FILE* cfp, char* extname);
void* start_routine(void* arg);
void msg404(int connectfd);
void writeLED(int r, int g, int b);
char* splitGetValue(char* strsrc, char* strStart, char* strEnd);
int StringFind( char* string1, char* find,int number);
void DealWith(char* requeststring);


void writeLED(int r, int g, int b)
{
    digitalWrite(LEDR, r ==1?HIGH:LOW); 
    digitalWrite(LEDG, g ==1?HIGH:LOW); 
    digitalWrite(LEDB, b ==1?HIGH:LOW); 
}




struct ARG {
       int connfd;
       sockaddr_in client;
       };


main()
{
      int listenfd, connectfd;
      pthread_t thread;         //id of thread
      ARG *arg;            //pass this var to the thread
      struct sockaddr_in server; //server's address info
      struct sockaddr_in client; //client's
      int sin_size;

      //wiringPi
        wiringPiSetup() ; 
        pinMode (LEDR, OUTPUT); 
        pinMode (LEDG, OUTPUT); 
        pinMode (LEDB, OUTPUT); 


      //create tcp socket
#ifdef DEBUG
      printf("socket.... ");
#endif
     if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
                    perror("creating socket failed.");
                    exit(1);
      }
      
      int opt = SO_REUSEADDR;
      setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
      
      bzero(&server,sizeof(server));
      server.sin_family = AF_INET;
      server.sin_port = htons(PORT);
      server.sin_addr.s_addr = htonl(INADDR_ANY);
      printf("bind....\n");
      if(bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
          perror("bind error.");
          exit(1);
      }

      printf("listen.... \n");
      if(listen(listenfd,BACKLOG) == -1) {
          perror("listen() error ");
          exit(1);
      }



      sin_size = sizeof(struct sockaddr_in);
      while(1)
      {

          //accept() using main thread
          printf("accepting.... \n");
          if((connectfd = accept(listenfd,
                     (struct sockaddr *)&client,
                     (socklen_t*)&sin_size)) == -1) {
              printf("accept() error ");
          }

          arg = new ARG;
          arg->connfd = connectfd;
          memcpy((void *)&arg->client, &client, sizeof(client));
        
          //invoke start_routine to handle this thread

#ifdef DEBUG
          printf("thread_creating....");
#endif

          if(pthread_create(&thread, NULL, start_routine, (void*)arg)){
              perror("pthread_create() error");
              exit(1);
          }          
      }
      close(listenfd);      
}




void DealWith(char* requeststring1)
{
    
    char requeststring[MAXDATASIZE];
    memset(requeststring,0,MAXDATASIZE);
    memcpy(requeststring, requeststring1+4, strlen(requeststring1)-6);

    char requestrgbvalue[MAXDATASIZE];
    memset(requestrgbvalue,0,MAXDATASIZE);

    strcpy(requestrgbvalue, splitGetValue(requeststring,"SetRGB="," HTTP"));
    
    if(strcmp("0,1,0", requestrgbvalue)==0)
    {
        printf("RGB Light[Green] \n");
        writeLED(0,1,0);
    }
    else if(strcmp("0,0,1", requestrgbvalue)==0)
    {
        printf("RGB Light[Blue] \n");
        writeLED(0,0,1);
    }
    else
    {
        printf("RGB Light[Red] \n");
        writeLED(1,0,0);
    }

}

//handle the request of the client
void process_cli(int connectfd, sockaddr_in client)
{
    int num;
    char requestline[MAXDATASIZE], filepath[MAXDATASIZE], cmd[MAXDATASIZE],extname[MAXDATASIZE];
    int c;
    FILE *fp;
    FILE *cfp;
    fp = fdopen(connectfd,"r");    
    
#ifdef DEBUG
    printf("the host is:%s  ",inet_ntoa(client.sin_addr) );
#endif
    fgets(requestline,MAXDATASIZE,fp);
#ifdef DEBUG
    printf("[A01] THE REQUEST IS :%s \n",requestline);
#endif



    char* ch;

    if((ch=strstr(requestline,"?"))!=NULL)
    {
        DealWith(requestline);
    }


    strcpy(filepath,"./");
    sscanf(requestline,"%s%s",cmd,filepath+2);
    strcpy(extname, getextname(filepath));
#ifdef DEBUG
    printf("cmd:%s filepath:%s extname:%s ",cmd,filepath,extname);
    
    printf("string comparing :::::::::::::start::::::::::::::: ");    
#endif
    if(strcmp(cmd,"GET") == 0)
    {
    //the command is get
#ifdef DEBUG
        printf("cmd(%s)==GET ",cmd);
#endif
        //is this a file or dir or notexist?
        if(fileordirExist(filepath)){
        //is a file or dir or none
            //is this a dir 
            if(IsDIR(filepath)){
                //is a dir
#ifdef DEBUG
            printf("%s is a DIR ",filepath);
#endif
                if( fileordirExist( strcat(filepath,"index.html") ))
                {
                    sendobj(connectfd,"index.html");
                }
                else if(fileordirExist(strcat(filepath,"index.html")))
                {
                    sendobj(connectfd,"index.html");
                }
                else
                {
                    msg404(connectfd);
                }
            }
            else
            {
                    //is a file
#ifdef DEBUG
                    printf("%s is a file",filepath);
#endif
                    sendobj(connectfd,filepath);
            }
        }
        else
        {
#ifdef DEBUG
            printf("404 ");
#endif
            msg404(connectfd);
        }
    }
    else
    {
#ifdef DEBUG
        printf("cmd(%s)!=GET ",cmd);

#endif
    }
#ifdef DEBUG
    printf(":::::::::::::end::::::::::::::: ");    
#endif
    close(connectfd);
}

//send the 404 error message to the client

void msg404(int connectfd)
{
    char* msg;
    msg  = "HTTP/1.0 404 Not Found Content-Type: text/plain 404 not found by Manio";
    send(connectfd,msg,strlen(msg),0);
}

//is the filepath a file  or directory

int fileordirExist(char* fpath)
{
    struct stat filestat;
    return (  stat(fpath,&filestat) != -1);
}

// is the filepath a directory
int IsDIR(char* fpath)
{
#ifdef DEBUG
    printf("IN IsDIR ");
#endif
    struct stat filestat;
    return ( stat(fpath,&filestat) != -1 && S_ISDIR(filestat.st_mode));
}

//send the data of the file which the client want
int sendobj(int connectfd,char* serverfilepath)
{
   FILE* sfp,*cfp;
    int c;
    sfp = fopen(serverfilepath,"r");
    cfp = fdopen(connectfd,"w");
    writehead(cfp,getextname(serverfilepath));
    while( (c = getc(sfp)) != EOF)putc(c,cfp);    
    fflush(cfp);
    return 0;
}

//write the packet header to the client

int writehead(FILE* cfp, char* extname)
{
#ifdef DEBUG
    printf("INWRITEHEAD:::::::extname is %s::::::: ",extname);
#endif
    char* content = "text/plain";
    if( strcmp(extname,"html") == 0 || strcmp(extname,"htm") == 0)
        content = "text/html";
    else if ( strcmp(extname,"css") == 0 )
        content = "text/css";
    else if ( strcmp(extname,"gif") == 0 )
        content = "image/gif";
    else if ( strcmp(extname,"jpeg") == 0 || strcmp(extname,"jpg") == 0)
        content = "image/jpeg";
    else if ( strcmp(extname,"png") == 0)
        content = "image/png";

#ifdef DEBUG
    printf("HTTP/1.1 200 OK ");
    printf("Content-Type: %s ",content);
#endif
    fprintf(cfp,"HTTP/1.1 200 OK ");
    fprintf(cfp,"Content-Type: %s ",content);
    return 0;
}



//get the extent name of the file

char* getextname(char* filepath)
{
    char* p;
    if(( p  =  strrchr(filepath,'.')) != NULL)
               return p+1;
    return NULL;           

}

//SetRGB=
char* splitGetValue(char* strsrc, char* strStart, char* strEnd)
{

    char str1[MAXDATASIZE];
    memset(str1,0,MAXDATASIZE);

    int pos1 = StringFind(strsrc, strStart,1);

    if(pos1>0)
    {
        memcpy(str1,  strsrc+ pos1+strlen(strStart)-1, strlen(strsrc)-pos1-strlen(strStart)+1);
    }
    else
    {
        memcpy(str1,strsrc,strlen(strsrc));
    }

    int pos2 = StringFind(str1, strEnd, 1);

    char str2[MAXDATASIZE];
    memset(str2,0,MAXDATASIZE);

    if(pos2>0)
    {
        memcpy(str2,  str1,  pos2-1);
    }
    else
    {
        memcpy(str2,str1,strlen(str1));
    }

    char* p2= str2;
    return p2;
     
}


void* start_routine(void* arg)
{
    ARG *info;
    info = (ARG *)arg;
    //handle client's requirement
    process_cli(info->connfd, info->client);
    delete arg;
    pthread_exit(NULL);
}


/*获取一个指定字符的位置,中文字符作为一个字符计算*/
int StringFind( char* string1, char* find,int number)
{
    char* pos = string1;
    char* p = string1;
    int count = 0;
    while (number > 0)
    {
        /*定义查找到的字符位置的指针,以便临时指针进行遍历*/
        pos = strstr(p,find);
        /*当位置指针为0时,说明没有找到这个字符*/
        if (pos == 0)
            return -1;
        /*当位置指针和临时指针相等说明下一个字符就是要找的字符,如果临时指针小于位置指针,则进行遍历字符串操作,并将count增1*/
        while(p <= pos)
        {
            if(*p > 0x80 || *p < 0)
            {
                p++;
            }
            p++;
            count++;
        }
        /*对要查找的次数减一*/
        number--;
    }
    return count;
}

4.编译程序

g++ main.c -o test -lwiringPi -lwiringPiDev -lpthread

5. 运行后台程序

./test

6. 手机打开网页 树莓派的IP+端口(8848)/index.html

 7. 测试结果Red Green Blue三个按钮,分别控制RGB三个颜色变化

小结:这里使用了多线程,建web服务器,方便 用控制使用,网页前端与后台C++通过socket通讯

源码下载连接:
https://download.csdn.net/download/meekiki/21385111

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

树莓派centos

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值