命令下发--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;
				
		}
	}

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hinzer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值