F1CTL/Core/Src/http_server.c

293 lines
8.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "http_server.h"
// HTML页面模板
#include "html_files.h"
// 解析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响应
static int send_all(uint8_t sn, const uint8_t* data, uint16_t length)
{
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";
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);
}
static void send_chunk_end(uint8_t sn)
{
send_all(sn, (uint8_t*)"0\r\n\r\n", 5);
}
#define CHUNK_SIZE 512
// 处理配置页面请求
static void handle_index_page(uint8_t sn)
{
// 发送分块传输的响应头
send_chunked_response_header(sn);
// 分段发送HTML内容
// const int CHUNK_SIZE = 512; // 每个块的大小
int total_len = strlen(index_html);
int sent = 0;
while (sent < total_len) {
// 计算当前块的大小
int chunk_len = ((total_len - sent) > CHUNK_SIZE) ?
CHUNK_SIZE : (total_len - sent);
// 发送数据块
send_chunk(sn, index_html + sent, chunk_len);
sent += chunk_len;
}
// 发送结束块
send_chunk_end(sn);
// 等待数据发送完成
HAL_Delay(1);
// 关闭连接
disconnect(sn);
}
// 解析并更新网络配置
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);
}
// 发送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);
printf("send status success!\r\n");
}
// 处理网络配置请求
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);
// 发送完成后主动关闭连接
disconnect(sn);
}
void http_server_task(void)
{
uint8_t buffer[256];
uint16_t size;
uint8_t status = getSn_SR(HTTP_SERVER_SOCKET);
switch(status)
{
case SOCK_INIT:
listen(HTTP_SERVER_SOCKET);
break;
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) {
if(strcmp(req.uri, "/status") == 0) {
handle_status_request(HTTP_SERVER_SOCKET);
}
else if(strcmp(req.uri, "/netconfig") == 0) {
handle_netconfig_request(HTTP_SERVER_SOCKET);
}
else {
handle_index_page(HTTP_SERVER_SOCKET);
}
}
else if(req.method == HTTP_POST && strcmp(req.uri, "/config") == 0) {
update_network_config((char*)req.body);
send_chunked_response_header(HTTP_SERVER_SOCKET);
send_chunk(HTTP_SERVER_SOCKET,
"<html><head><meta http-equiv='refresh' content='0;url=/'></head></html>",
strlen("<html><head><meta http-equiv='refresh' content='0;url=/'></head></html>"));
send_chunk_end(HTTP_SERVER_SOCKET);
}
}
}
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;
}
}