LWIP应用开发|Web点灯二

Web点灯二

在了解了HTML实现、交互功能实现以及HTTP请求和响应的相关内容后,本章主要实现通过网页对STM32F429开发板LED进行开关控制的功能

该实例实现的功能:在浏览器中输入开发板IP(192.168.1.10)可以访问Web点灯的html界面,点击打开和关闭按钮,可以控制开发板上LED的亮灭

1. Web点灯框架设计

TCP服务器开发
主页请求响应
LED控制&请求响应

2. Web点灯编程

  • 参考Socket API编程优化一文,在该文的工程源码基础上进行修改
  • DNS宏开关:将opt.h文件中的LWIP_DNS宏定义开启
//opt.h文件中使能LWIP_DNS
#if !defined LWIP_DNS || defined __DOXYGEN__
#define LWIP_DNS         		1
#endif

参考DNS域名解析一文配置DNS服务器以及修改相关代码

  • IGMP宏开关:将opt.h文件中的LWIP_IGMP宏定义开启
//opt.h文件中使能LWIP_IGMP
#if !defined LWIP_IGMP || defined __DOXYGEN__
#define LWIP_IGMP                       1
#endif
  • 在工程中创建http_server.c和对应的头文件;将SERVER_PORT端口改为80端口
/***********http_server.c***********/
#include "socket_tcp_server.h"
#include "socket_wrap.h"
#include "ctype.h"
#include "http_server.h"
#include "string.h"

static char ReadBuff[BUFF_SIZE];
char SendBuff[128];
char *HtmlPage = 
"<html>"
"<head>"
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\" />"
"<title>web 点灯</title>"
"<script defer=\"defer\">"
"	function ledSwitch(string) {"
"   	var xmlhttp;"
"       if (window.XMLHttpRequest) {"
"       	xmlhttp = new XMLHttpRequest();"
"       } else {"
"           xmlhttp = new ActiveXObject(\"Microsoft.XMLHTTP\");"
"       }"
"       xmlhttp.onreadystatechange = function () {"
"       	if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {"
"           	document.getElementById(\"txtState\").style.backgroundColor = xmlhttp.responseText;"
"				console.log(xmlhttp.responseText);"
"			}"
"		};"
"       xmlhttp.open(\"GET\", string, true);"
"       xmlhttp.send(); "
"	}"
"</script>"
"</head>"
"<body style=\"background-color:gray\">"
"<font size=\"12\" color=\"yellow\">"
"<b>"
"<div class=\"text\" style=\" text-align:center;\"><big>Web 点灯</big></div>"
"</b>"
"</font>"
"<br> </br>     "
"<div align=\"center\" id=\"txtState\"style=\"margin:auto;width:160px;height:160px;border-radius:50%;background:white;\"></div>"
"<br> </br>"
"<div style=\" text-align:center;\">"
"<input type=\"button\" value=\"打开\" style=\"width:160px;height:80px;background:green;\" οnclick=\"ledSwitch(\'on\')\" />"
"<input type=\"button\" value=\"关闭\" style=\"width:160px;height:80px;background:red;\" οnclick=\"ledSwitch(\'off\')\" />"
"</div>"
"</body>"
"</html>";

void HttpParResponse(int cfd, char *Buff){
    
    
	//是否为请求主页
	if(strstr(Buff, "GET / HTTP/1.1") != NULL){
    
    	
		//响应头
		sprintf(SendBuff, "HTTP/1.1 200 OK\r\n");
		Write(cfd, SendBuff, strlen(SendBuff));
		//响应首部
		sprintf(SendBuff, "Content-Type: text/html\r\n");
		Write(cfd, SendBuff, strlen(SendBuff));
		sprintf(SendBuff, "Connection: Keep-Alive\r\n");
		Write(cfd, SendBuff, strlen(SendBuff));
		sprintf(SendBuff, "Content-Length: %d\r\n", strlen(HtmlPage));
		Write(cfd, SendBuff, strlen(SendBuff));
		sprintf(SendBuff, "\r\n");
		Write(cfd, SendBuff, strlen(SendBuff));
		//响应主题
		Write(cfd, HtmlPage, strlen(HtmlPage));	
	//是否为 打开led
	}else if(strstr(Buff, "GET /on HTTP/1.1") != NULL){
    
    
		Write(cfd, "green", strlen("green"));
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
	//是否为 关闭led
	}else if(strstr(Buff, "GET /off HTTP/1.1") != NULL){
    
    
		Write(cfd, "red", strlen("red"));
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
	//请求资源无效, 就是404
	}else{
    
    
		printf("GET Method Error\r\n");
		close(cfd);	
	}
}
//http服务器任务
void vHttpServerTask(void){
    
    
	int sfd, cfd, n;
	struct sockaddr_in server_addr, client_addr;
	socklen_t	client_addr_len;	
	//创建socket
	sfd = Socket(AF_INET, SOCK_STREAM, 0);
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SERVER_PORT);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//绑定socket
	Bind(sfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	//监听socket
	Listen(sfd, 5);
	//等待客户端连接
	client_addr_len = sizeof(client_addr);
again:
	cfd = Accept(sfd, (struct sockaddr *)&client_addr, &client_addr_len);
	printf("client is connect cfd = %d\r\n",cfd);
	while(1){
    
    
		//等待客户端发送数据
		n = Read(cfd, ReadBuff, BUFF_SIZE);
		if(n <= 0){
    
    
			goto again;
		}
		//解析响应http协议
		HttpParResponse(cfd, ReadBuff);
		//http响应后要关闭fd
		close(cfd);
		goto again;
	}
}

如何在C语言文件中存储网页?

  • 若有文件系统,可直接读文件写到socket中
  • 将网页转化成一个完整的字符串
    HTML文件转字符串工具 https://www.html.cn/tool/html2js/
  • 在freertos.c文件中的默认任务里面添加代码
void StartDefaultTask(void const * argument){
    
    
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN StartDefaultTask */
  printf("Web LED test!\r\n");
  /* Infinite loop */
  for(;;){
    
    
    vHttpServerTask();
	osDelay(100);
  }
  /* USER CODE END StartDefaultTask */
}

3. Web点灯测试

编译无误下载到开发板,用网线将PC和STM32开发板连接起来,在PC端配置好网卡IP地址,使用ping命令可以ping通IP地址:192.168.1.10;在浏览器中输入192.168.1.10可以访问到Web点灯网页,点击网页上的打开和关闭按钮可以控制开发板上LED灯的亮灭

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Chuangke_Andy/article/details/114320965