2024-12-15 02:41:36 +00:00
|
|
|
|
#include "http_server.h"
|
|
|
|
|
|
|
|
|
|
// HTML页面模板
|
2024-12-15 06:07:02 +00:00
|
|
|
|
#include "html_files.h"
|
2024-12-15 02:41:36 +00:00
|
|
|
|
|
|
|
|
|
// 解析HTTP请求
|
|
|
|
|
static void parse_http_request(uint8_t* buffer, uint16_t length, http_request* req)
|
|
|
|
|
{
|
|
|
|
|
char* method = strtok((char*)buffer, " ");
|
|
|
|
|
char* uri = strtok(NULL, " ");
|
|
|
|
|
|
|
|
|
|
if(strcmp(method, "GET") == 0) {
|
|
|
|
|
req->method = HTTP_GET;
|
|
|
|
|
} else if(strcmp(method, "POST") == 0) {
|
|
|
|
|
req->method = HTTP_POST;
|
|
|
|
|
} else {
|
|
|
|
|
req->method = HTTP_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strncpy(req->uri, uri, MAX_URI_SIZE);
|
|
|
|
|
|
|
|
|
|
// 如果是POST请求,查找请求体
|
|
|
|
|
if(req->method == HTTP_POST) {
|
|
|
|
|
char* body = strstr((char*)buffer, "\r\n\r\n");
|
|
|
|
|
if(body) {
|
|
|
|
|
body += 4;
|
|
|
|
|
req->body = (uint8_t*)body;
|
|
|
|
|
req->body_length = length - (body - (char*)buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 发送HTTP响应
|
2024-12-15 06:07:02 +00:00
|
|
|
|
static int send_all(uint8_t sn, const uint8_t* data, uint16_t length)
|
2024-12-15 02:41:36 +00:00
|
|
|
|
{
|
2024-12-15 06:07:02 +00:00
|
|
|
|
int total_sent = 0;
|
|
|
|
|
while (total_sent < length) {
|
|
|
|
|
int sent = send(sn, data + total_sent, length - total_sent);
|
|
|
|
|
if (sent <= 0) {
|
|
|
|
|
return -1; // 发送错误
|
|
|
|
|
}
|
|
|
|
|
total_sent += sent;
|
|
|
|
|
}
|
|
|
|
|
return total_sent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void send_chunked_response_header(uint8_t sn)
|
|
|
|
|
{
|
|
|
|
|
const char* header =
|
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
|
"Transfer-Encoding: chunked\r\n"
|
|
|
|
|
"\r\n";
|
2024-12-15 02:41:36 +00:00
|
|
|
|
|
2024-12-15 06:07:02 +00:00
|
|
|
|
send_all(sn, (uint8_t*)header, strlen(header));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void send_chunk(uint8_t sn, const char* data, uint16_t length)
|
|
|
|
|
{
|
|
|
|
|
char chunk_header[10];
|
|
|
|
|
sprintf(chunk_header, "%X\r\n", length);
|
|
|
|
|
send_all(sn, (uint8_t*)chunk_header, strlen(chunk_header));
|
|
|
|
|
send_all(sn, (uint8_t*)data, length);
|
|
|
|
|
send_all(sn, (uint8_t*)"\r\n", 2);
|
2024-12-15 02:41:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-15 06:07:02 +00:00
|
|
|
|
static void send_chunk_end(uint8_t sn)
|
|
|
|
|
{
|
|
|
|
|
send_all(sn, (uint8_t*)"0\r\n\r\n", 5);
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-17 14:53:56 +00:00
|
|
|
|
#define CHUNK_SIZE 512
|
2024-12-15 06:07:02 +00:00
|
|
|
|
|
2024-12-15 02:41:36 +00:00
|
|
|
|
// 处理配置页面请求
|
2024-12-17 15:26:13 +00:00
|
|
|
|
static void handle_index_page(uint8_t sn)
|
2024-12-15 02:41:36 +00:00
|
|
|
|
{
|
2024-12-17 15:26:13 +00:00
|
|
|
|
// 发送分块传输的响应头
|
2024-12-15 06:07:02 +00:00
|
|
|
|
send_chunked_response_header(sn);
|
|
|
|
|
|
2024-12-17 15:26:13 +00:00
|
|
|
|
// 分段发送HTML内容
|
|
|
|
|
// const int CHUNK_SIZE = 512; // 每个块的大小
|
|
|
|
|
int total_len = strlen(index_html);
|
2024-12-15 06:07:02 +00:00
|
|
|
|
int sent = 0;
|
2024-12-17 15:26:13 +00:00
|
|
|
|
|
2024-12-15 06:07:02 +00:00
|
|
|
|
while (sent < total_len) {
|
2024-12-17 15:26:13 +00:00
|
|
|
|
// 计算当前块的大小
|
|
|
|
|
int chunk_len = ((total_len - sent) > CHUNK_SIZE) ?
|
|
|
|
|
CHUNK_SIZE : (total_len - sent);
|
|
|
|
|
|
|
|
|
|
// 发送数据块
|
|
|
|
|
send_chunk(sn, index_html + sent, chunk_len);
|
|
|
|
|
|
2024-12-15 06:07:02 +00:00
|
|
|
|
sent += chunk_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 发送结束块
|
|
|
|
|
send_chunk_end(sn);
|
2024-12-17 15:26:13 +00:00
|
|
|
|
|
|
|
|
|
// 等待数据发送完成
|
|
|
|
|
HAL_Delay(1);
|
|
|
|
|
|
|
|
|
|
// 关闭连接
|
|
|
|
|
disconnect(sn);
|
2024-12-15 02:41:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析并更新网络配置
|
|
|
|
|
static void update_network_config(const char* body)
|
|
|
|
|
{
|
|
|
|
|
char mac[18], ip[16], subnet[16], gateway[16];
|
|
|
|
|
uint32_t mac_values[6], ip_values[4], subnet_values[4], gateway_values[4];
|
|
|
|
|
|
|
|
|
|
if(sscanf(body, "mac=%02X%%3A%02X%%3A%02X%%3A%02X%%3A%02X%%3A%02X&"
|
|
|
|
|
"ip=%d.%d.%d.%d&"
|
|
|
|
|
"subnet=%d.%d.%d.%d&"
|
|
|
|
|
"gateway=%d.%d.%d.%d",
|
|
|
|
|
&mac_values[0], &mac_values[1], &mac_values[2],
|
|
|
|
|
&mac_values[3], &mac_values[4], &mac_values[5],
|
|
|
|
|
&ip_values[0], &ip_values[1], &ip_values[2], &ip_values[3],
|
|
|
|
|
&subnet_values[0], &subnet_values[1], &subnet_values[2], &subnet_values[3],
|
|
|
|
|
&gateway_values[0], &gateway_values[1], &gateway_values[2], &gateway_values[3]) == 18)
|
|
|
|
|
{
|
|
|
|
|
// 更新MAC地址
|
|
|
|
|
for(int i = 0; i < 6; i++) {
|
|
|
|
|
gWIZNETINFO.mac[i] = (uint8_t)mac_values[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新IP地址
|
|
|
|
|
for(int i = 0; i < 4; i++) {
|
|
|
|
|
gWIZNETINFO.ip[i] = (uint8_t)ip_values[i];
|
|
|
|
|
gWIZNETINFO.sn[i] = (uint8_t)subnet_values[i];
|
|
|
|
|
gWIZNETINFO.gw[i] = (uint8_t)gateway_values[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 应用新的网络配置
|
|
|
|
|
wizchip_setnetinfo(&gWIZNETINFO);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void http_server_init(void)
|
|
|
|
|
{
|
|
|
|
|
// 创建服务器socket
|
|
|
|
|
socket(HTTP_SERVER_SOCKET, Sn_MR_TCP, HTTP_SERVER_PORT, 0);
|
|
|
|
|
listen(HTTP_SERVER_SOCKET);
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-15 08:14:52 +00:00
|
|
|
|
// 发送JSON响应头
|
|
|
|
|
static void send_json_response_header(uint8_t sn)
|
|
|
|
|
{
|
|
|
|
|
const char* header =
|
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
|
"Content-Type: application/json\r\n"
|
|
|
|
|
"Access-Control-Allow-Origin: *\r\n"
|
|
|
|
|
"Connection: close\r\n" // 明确指示关闭连接
|
|
|
|
|
"Cache-Control: no-cache, no-store\r\n" // 禁止缓存
|
|
|
|
|
"\r\n";
|
|
|
|
|
|
|
|
|
|
send_all(sn, (uint8_t*)header, strlen(header));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理状态请求
|
|
|
|
|
static void handle_status_request(uint8_t sn)
|
|
|
|
|
{
|
|
|
|
|
char json_buffer[512];
|
|
|
|
|
// DeviceStatus deviceStatus; // 确保能访问到deviceStatus变量
|
|
|
|
|
|
|
|
|
|
// 构建JSON响应
|
|
|
|
|
int len = sprintf(json_buffer,
|
|
|
|
|
"{"
|
|
|
|
|
"\"deviceStatus\":%d,"
|
|
|
|
|
"\"valves\":{"
|
|
|
|
|
"\"angle1\":%d,"
|
|
|
|
|
"\"angle2\":%d"
|
|
|
|
|
"},"
|
|
|
|
|
"\"pumps\":{"
|
|
|
|
|
"\"status1\":%d,"
|
|
|
|
|
"\"status2\":%d,"
|
|
|
|
|
"\"speed1\":%d,"
|
|
|
|
|
"\"speed2\":%d"
|
|
|
|
|
"},"
|
|
|
|
|
"\"bubbleStatus\":%d,"
|
|
|
|
|
"\"stopStatus\":%d,"
|
|
|
|
|
"\"errorCode\":%d,"
|
|
|
|
|
"\"initStatus\":%d"
|
|
|
|
|
"}",
|
|
|
|
|
deviceStatus.deviceStatus,
|
|
|
|
|
deviceStatus.valves.angle1,
|
|
|
|
|
deviceStatus.valves.angle2,
|
|
|
|
|
deviceStatus.pumps.status1,
|
|
|
|
|
deviceStatus.pumps.status2,
|
|
|
|
|
deviceStatus.pumps.speed1,
|
|
|
|
|
deviceStatus.pumps.speed2,
|
|
|
|
|
deviceStatus.bubbleStatus,
|
|
|
|
|
deviceStatus.stopStatus,
|
|
|
|
|
deviceStatus.errorCode,
|
|
|
|
|
deviceStatus.initStatus
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 发送响应
|
|
|
|
|
send_json_response_header(sn);
|
|
|
|
|
send_all(sn, (uint8_t*)json_buffer, len);
|
|
|
|
|
|
|
|
|
|
// 发送完成后主动关闭连接
|
|
|
|
|
disconnect(sn);
|
2024-12-15 08:35:35 +00:00
|
|
|
|
printf("send status success!\r\n");
|
2024-12-15 08:14:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-17 08:25:23 +00:00
|
|
|
|
// 处理网络配置请求
|
|
|
|
|
static void handle_netconfig_request(uint8_t sn)
|
|
|
|
|
{
|
|
|
|
|
char json_buffer[256];
|
|
|
|
|
|
|
|
|
|
// 构建JSON响应
|
|
|
|
|
int len = sprintf(json_buffer,
|
|
|
|
|
"{"
|
|
|
|
|
"\"mac\":[%d,%d,%d,%d,%d,%d],"
|
|
|
|
|
"\"ip\":[%d,%d,%d,%d],"
|
|
|
|
|
"\"sn\":[%d,%d,%d,%d],"
|
|
|
|
|
"\"gw\":[%d,%d,%d,%d]"
|
|
|
|
|
"}",
|
|
|
|
|
gWIZNETINFO.mac[0], gWIZNETINFO.mac[1], gWIZNETINFO.mac[2],
|
|
|
|
|
gWIZNETINFO.mac[3], gWIZNETINFO.mac[4], gWIZNETINFO.mac[5],
|
|
|
|
|
gWIZNETINFO.ip[0], gWIZNETINFO.ip[1], gWIZNETINFO.ip[2], gWIZNETINFO.ip[3],
|
|
|
|
|
gWIZNETINFO.sn[0], gWIZNETINFO.sn[1], gWIZNETINFO.sn[2], gWIZNETINFO.sn[3],
|
|
|
|
|
gWIZNETINFO.gw[0], gWIZNETINFO.gw[1], gWIZNETINFO.gw[2], gWIZNETINFO.gw[3]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 发送响应
|
|
|
|
|
send_json_response_header(sn);
|
|
|
|
|
send_all(sn, (uint8_t*)json_buffer, len);
|
2024-12-17 14:53:56 +00:00
|
|
|
|
|
|
|
|
|
// 发送完成后主动关闭连接
|
|
|
|
|
disconnect(sn);
|
2024-12-17 08:25:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-12-15 02:41:36 +00:00
|
|
|
|
void http_server_task(void)
|
|
|
|
|
{
|
2024-12-19 14:59:33 +00:00
|
|
|
|
uint8_t buffer[256];
|
2024-12-15 02:41:36 +00:00
|
|
|
|
uint16_t size;
|
|
|
|
|
uint8_t status = getSn_SR(HTTP_SERVER_SOCKET);
|
|
|
|
|
|
|
|
|
|
switch(status)
|
|
|
|
|
{
|
2024-12-15 08:14:52 +00:00
|
|
|
|
case SOCK_INIT:
|
|
|
|
|
listen(HTTP_SERVER_SOCKET);
|
|
|
|
|
break;
|
|
|
|
|
|
2024-12-15 02:41:36 +00:00
|
|
|
|
case SOCK_LISTEN:
|
|
|
|
|
// 等待连接
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SOCK_ESTABLISHED:
|
|
|
|
|
{
|
|
|
|
|
if((size = getSn_RX_RSR(HTTP_SERVER_SOCKET)) > 0)
|
|
|
|
|
{
|
|
|
|
|
size = recv(HTTP_SERVER_SOCKET, buffer, sizeof(buffer));
|
|
|
|
|
if(size > 0)
|
|
|
|
|
{
|
|
|
|
|
http_request req;
|
|
|
|
|
parse_http_request(buffer, size, &req);
|
|
|
|
|
|
|
|
|
|
if(req.method == HTTP_GET) {
|
2024-12-15 08:14:52 +00:00
|
|
|
|
if(strcmp(req.uri, "/status") == 0) {
|
|
|
|
|
handle_status_request(HTTP_SERVER_SOCKET);
|
2024-12-17 08:25:23 +00:00
|
|
|
|
}
|
|
|
|
|
else if(strcmp(req.uri, "/netconfig") == 0) {
|
2024-12-17 14:53:56 +00:00
|
|
|
|
handle_netconfig_request(HTTP_SERVER_SOCKET);
|
2024-12-17 08:25:23 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2024-12-17 15:26:13 +00:00
|
|
|
|
handle_index_page(HTTP_SERVER_SOCKET);
|
2024-12-15 08:14:52 +00:00
|
|
|
|
}
|
2024-12-15 02:41:36 +00:00
|
|
|
|
}
|
|
|
|
|
else if(req.method == HTTP_POST && strcmp(req.uri, "/config") == 0) {
|
|
|
|
|
update_network_config((char*)req.body);
|
2024-12-15 06:07:02 +00:00
|
|
|
|
send_chunked_response_header(HTTP_SERVER_SOCKET);
|
|
|
|
|
send_chunk(HTTP_SERVER_SOCKET,
|
2024-12-15 02:41:36 +00:00
|
|
|
|
"<html><head><meta http-equiv='refresh' content='0;url=/'></head></html>",
|
|
|
|
|
strlen("<html><head><meta http-equiv='refresh' content='0;url=/'></head></html>"));
|
2024-12-15 06:07:02 +00:00
|
|
|
|
send_chunk_end(HTTP_SERVER_SOCKET);
|
2024-12-15 02:41:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case SOCK_CLOSE_WAIT:
|
|
|
|
|
disconnect(HTTP_SERVER_SOCKET);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SOCK_CLOSED:
|
|
|
|
|
socket(HTTP_SERVER_SOCKET, Sn_MR_TCP, HTTP_SERVER_PORT, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|