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通讯