命令下發--html通過CGI與使用者程序互動
寫在最前面
華清遠見教育集團
15年專注高階IT培訓
做良心教育,做專業教育,做受人尊敬的職業教育創客學院官網:http://www.makeru.com.cn/
華清遠見創客學院嵌入式課程連結:http://www.makeru.com.cn/emb
華清遠見創客學院物聯網課程連結:http://www.makeru.com.cn/iot
正文
在本文介紹的倉儲專案中,使用者通過客戶端的一些控制元件實現對向底層硬體傳送指令,這一過程是命令資料的下發;使用者還可以實時檢視到倉庫的環境資料,這是資料的上報。總體上分為三個的物件和兩條資料流向,網頁端-伺服器-底層實現命令資料的下發和環境資料的上報,也就實現了人機互動的過程。下面是命令下發部分框圖:
目的:完成html 和 CGI 和 使用者程序 的互動,實現命令下發並接受到返回結果。隨便從程式上加以分析這一過程。
- HTML(超文字標記語言):就是一種標籤語言,用來描述資源的。加上CSS渲染,就可以通過瀏覽器看到成精美的頁面了。
- CGI:簡單理解是使用者程序對html實現的一組介面。
- 使用者程序:使用者程式在系統上的的執行結果。
實現步驟
1.實現html檔案,放在boa伺服器的www目錄下
2.實現.cgi程式,放在boa伺服器的www目錄下
3.編寫應用程式訊息佇列處理部分,實現與cgi進行互動
4.在開發板上執行boa伺服器,執行應用程式
5.測試結果
關於訊息佇列的使用,我之前寫過一篇介紹:https://mp.csdn.net/postedit/81412616
原始碼分析
1.html main.html
在瀏覽器中右鍵檢視原始碼,顯示如下內容。程式碼的意思是使用者點選提交按鈕,即提交表單資料到boa伺服器目錄的cgi-bin/setEnv.cgi處理。
<form action="cgi-bin/setEnv.cgi" method="get"><input name="store" type="hidden" value="1" /> <tr> <th height="55"><div align="center"> <label>最高溫度: <input type="text" name="temMAX" id="textfield" width="50" maxlength="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='50' /> </label> </div></th> <th><div align="center"> <label>最高溼度: <input type="text" name="humMAX" id="textfield3" width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='50'/> </label> </div></th> <th><div align="center"> <label>最高光度: <input type="text" name="illMAX" id="textfield5" width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='500'/> </label> </div></th> </tr> <tr> <th height="55"><div align="center"> <label>最低溫度: <input type="text" name="temMIN" id="textfield2" width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='5'/> </label> </div></th> <th><div align="center"> <label>最低溼度: <input type="text" name="humMIN" id="textfield4" width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='10'/> </label> </div></th> <th><div align="center"> <label>最低光度: <input type="text" name="illMIN" id="textfield6" width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='10'/> </label> </div></th> </tr> <tr> <th height="50" colspan="3"><div align="center"> <input type="reset" name="button7" style="background-color:transparent" id="button7" value="重置" /> <input type="submit" name="button8" id="button8" value="提交" style="background-color:transparent"/> </div></th> </tr> </form>
2.cgic setenv.c
使用者提交表單,執行到這個介面。cgic使用c語言進行實現,一方面從使用者提交的表單資料中提取到有效的命令資料,將資料內容放在一個訊息結構體msg_buf中;另一方面通過訊息佇列實現與使用者程序/執行緒間的互動。最後將結果一html檔案的形式返回瀏覽器。
#define N 32
struct msg
{
long type;
long msgtype;
unsigned char text[N];
};
struct setEnv
{
int temMAX;
int temMIN;
int humMAX;
int humMIN;
int illMAX;
int illMIN;
};
int cgiMain()
{
key_t key;
char sto_no[2];
char buf[20];
struct setEnv new;
int msgid;
struct msg msg_buf;
memset(&msg_buf,0,sizeof(msg_buf));
cgiFormString("store", sto_no, 2);
cgiFormString("temMAX", buf, 20); //通過cgic.c提供的介面函式 提取表單資料
new.temMAX = atoi (buf);
cgiFormString("temMIN", buf, 20);
new.temMIN = atoi (buf);
cgiFormString("humMAX", buf, 20);
new.humMAX = atoi (buf);
cgiFormString("humMIN", buf, 20);
new.humMIN = atoi (buf);
cgiFormString("illMAX", buf, 20);
new.illMAX = atoi (buf);
cgiFormString("illMIN", buf, 20);
new.illMIN = atoi (buf);
if((key = ftok("/app", 'g')) < 0)
{
perror("ftok");
exit(1);
}
if((msgid = msgget(key, 0666)) < 0)
{
perror("msgget");
exit(1);
}
memcpy (msg_buf.text+1, &new, 24);
msg_buf.type = 1L;
msg_buf.msgtype = 5L;
msg_buf.text[0] = sto_no[0];
msgsnd(msgid, &msg_buf,sizeof(msg_buf)-sizeof(long),0); //訊息佇列與應用程序/執行緒互動
sto_no[0] -= 48;
cgiHeaderContentType("text/html\n\n"); //成功結果通過html檔案的形式返回
fprintf(cgiOut, "<HTML><HEAD>\n");
fprintf(cgiOut, "<TITLE>My CGI</TITLE></HEAD>\n");
fprintf(cgiOut, "<BODY>");
fprintf(cgiOut, "<H2>send sucess</H2>");
//fprintf(cgiOut, "<a href='.html'>返回</a>");
fprintf(cgiOut, "<meta http-equiv=\"refresh\" content=\"1;url=../main%d.html\">", sto_no[0]);
fprintf(cgiOut, "</BODY>\n");
fprintf(cgiOut, "</HTML>\n");
return 0;
}
3.使用者處理程式
下面是使用者主程序中排程的一個執行緒,處理訊息佇列中的請求執行緒。執行緒中一直阻塞等待請求,當從佇列中接收到訊息,表示“我收到了”,然後進行命令的型別判斷,做相應的處理。由於底層還沒有實現,這裡就僅簡單的列印處理
void *pthread_client_request (void *arg)
{
printf("pthread_client_request\n");
if((key = ftok("/tmp",'g')) < 0){
perror("ftok failed .\n");
exit(-1);
}
msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);
if(msgid == -1) {
if(errno == EEXIST){
msgid = msgget(key,0777);
}else{
perror("fail to msgget");
exit(1);
}
}
printf("pthread_client_request\n");
while(1){
bzero(&msgbuf,sizeof(msgbuf));
printf("wait form client request...\n");
msgrcv (msgid, &msgbuf, sizeof (msgbuf) - sizeof (long), 1L, 0);
printf ("Get %ldL msg\n", msgbuf.msgtype);
printf ("text[0] = %#x\n", msgbuf.text[0]);
//1L - 5L為執行緒分類的訊息型別
switch(msgbuf.msgtype){
case 1L:
printf("hello led\n");
break;
case 2L:
printf("hello beep\n");
break;
case 3L:
printf("hello seg\n");
break;
case 4L:
printf("hello fan\n");
break;
case 5L:
printf("set env data\n");
printf("temMAX: %d\n",*((int *)&msgbuf.text[1]));
printf("temMIN: %d\n",*((int *)&msgbuf.text[5]));
printf("humMAX: %d\n",*((int *)&msgbuf.text[9]));
printf("humMAX: %d\n",*((int *)&msgbuf.text[13]));
printf("illMAX: %d\n",*((int *)&msgbuf.text[17]));
printf("illMAX: %d\n",*((int *)&msgbuf.text[21]));
break;
case 6L:
pthread_mutex_lock(&mutex_led);
pthread_cond_wait(&cond_led,&mutex_led);
printf("hello led\n");
pthread_mutex_unlock(&mutex_led);
pthread_cond_broadcast(&cond_led);
break;
case 10L:
{
int i = 0 , j = 0 ;
for(i = 0 ; i < 11; i++){
recive_phone[i] = msgbuf.text[i];
}
recive_phone[i] = '\0';
printf("recive:%s\n",recive_phone);
for(j = 0 ;msgbuf.text[i] != '\0' && j < 12; i++, j++)
{
center_phone[j] = msgbuf.text[i];
}
center_phone[j] = '\0';
printf("center:%s\n",center_phone);
}
break;
default:
break;
}
}
}