更新网页,11k

This commit is contained in:
murmur 2024-12-15 16:14:52 +08:00
parent 4e79f700dc
commit b110c919bc
2 changed files with 350 additions and 18 deletions

View File

@ -1,5 +1,6 @@
R"(<!DOCTYPE html> R"(<!DOCTYPE html>
<html><head> <html><head>
<meta charset="UTF-8">
<title>W5500 Configuration</title> <title>W5500 Configuration</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<style> <style>
@ -13,9 +14,6 @@ R"(<!DOCTYPE html>
h2 { h2 {
color: #333; color: #333;
text-align: center; text-align: center;
padding-bottom: 10px;
border-bottom: 2px solid #ddd;
font-size: clamp(1.5rem, 4vw, 2rem);
} }
form { form {
background: white; background: white;
@ -46,7 +44,7 @@ R"(<!DOCTYPE html>
padding: 8px; padding: 8px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
font-family: monospace; font-family: consolas;
box-sizing: border-box; box-sizing: border-box;
} }
input[type='submit'] { input[type='submit'] {
@ -140,6 +138,104 @@ R"(<!DOCTYPE html>
background-color: #cccccc; background-color: #cccccc;
cursor: not-allowed; cursor: not-allowed;
} }
.device-status,.network-config {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
width: 100%;
max-width: 600px;
margin: 20px auto;
}
.status-group {
display: flex;
flex-direction: column;
gap: 15px;
}
.status-row {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.status-item {
flex: 1;
min-width: 200px;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #fff;
}
.status-item.full-width {
flex-basis: 100%;
min-width: 100%;
}
.status-item h3 {
margin: 0 0 10px 0;
color: #333;
font-size: 1.1em;
}
.status-value {
display: flex;
justify-content: space-between;
align-items: center;
margin: 5px 0;
}
.status-label {
font-weight: bold;
color: #555;
}
.error {
color: #dc3545;
}
.success {
color: #28a745;
}
.warning {
color: #ffc107;
}
@media screen and (max-width: 768px) {
.status-item {
flex-basis: 100%;
}
}
.status-row.device-running {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.status-row.device-running .status-item {
flex: 1;
min-width: 200px;
}
@media screen and (min-width: 900px) {
.status-row.device-running .status-item {
flex: 1;
min-width: 0;
width: calc(33.33% - 10px);
}
}
@media screen and (max-width: 899px) {
.status-row.device-running .status-item {
flex: 1 1 100%;
width: 100%;
}
}
</style> </style>
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
@ -160,10 +256,134 @@ document.addEventListener('DOMContentLoaded', function() {
} }
}, 5000); }, 5000);
}); });
function updateDeviceStatus() {
fetch('/status')
.then(response => {
return response.json();
})
.then(data => {
const deviceElement = document.getElementById('device-status');
deviceElement.textContent = data.deviceStatus ? '正常' : '异常';
deviceElement.className = data.deviceStatus ? 'success' : 'error';
const initStatus = ['等待', '成功', '失败'];
const initElement = document.getElementById('init-status');
initElement.textContent = initStatus[data.initStatus];
initElement.className = data.initStatus === 0 ? 'warning' : (data.initStatus === 1 ? 'success' : 'error');
const errorElement = document.getElementById('error-status');
errorElement.textContent = data.errorCode ? `Error: ${data.errorCode}` : '正常';
errorElement.className = data.errorCode ? 'error' : 'success';
const stopElement = document.getElementById('stop-status');
stopElement.textContent = data.stopStatus ? '停止' : '正常';
stopElement.className = data.stopStatus ? 'error' : 'success';
document.getElementById('valve1-angle').textContent = `${data.valves.angle1}°`;
document.getElementById('valve2-angle').textContent = `${data.valves.angle2}°`;
const pumpStatus = ['停止', '顺时针', '逆时针'];
document.getElementById('pump1-status').textContent =
`${pumpStatus[data.pumps.status1] || '#'} (${data.pumps.speed1}%)`;
document.getElementById('pump2-status').textContent =
`${pumpStatus[data.pumps.status2] || '#'} (${data.pumps.speed2}%)`;
const bubbleElement = document.getElementById('bubble-status');
bubbleElement.textContent = data.bubbleStatus ? '有' : '无';
bubbleElement.className = data.bubbleStatus ? 'error' : 'success';
})
.catch(error => {
console.error('Status update failed:', error);
});
}
setInterval(updateDeviceStatus, 1000);
}); });
</script> </script>
</head><body> </head><body>
<h2>W5500 Network Configuration</h2> <div class='device-status'>
<h2>状态信息</h2>
<div class='status-group'>
<!-- 设备信息行 -->
<div class='status-row'>
<div class='status-item full-width'>
<h3>Device Information</h3>
<div class='status-value'>
<span class='status-label'>Device Status:</span>
<span id='device-status'>#</span>
</div>
<div class='status-value'>
<span class='status-label'>Init Status:</span>
<span id='init-status'>#</span>
</div>
</div>
</div>
<!-- 设备运行状态行 -->
<div class='status-row device-running'>
<div class='status-item'>
<h3>Valve Status</h3>
<div class='status-value'>
<span class='status-label'>Valve 1 Angle:</span>
<span id='valve1-angle'>#</span>
</div>
<div class='status-value'>
<span class='status-label'>Valve 2 Angle:</span>
<span id='valve2-angle'>#</span>
</div>
</div>
<div class='status-item'>
<h3>Pump Status</h3>
<div class='status-value'>
<span class='status-label'>Pump 1:</span>
<span id='pump1-status'>#</span>
</div>
<div class='status-value'>
<span class='status-label'>Pump 2:</span>
<span id='pump2-status'>#</span>
</div>
</div>
<div class='status-item'>
<h3>Sensor Status</h3>
<div class='status-value'>
<span class='status-label'>Bubble Status:</span>
<span id='bubble-status'>#</span>
</div>
</div>
</div>
<!-- 急停状态 -->
<div class='status-row'>
<div class='status-item full-width'>
<h3>Emergency Stop</h3>
<div class='status-value'>
<span class='status-label'>Stop Status:</span>
<span id='stop-status'>#</span>
</div>
</div>
</div>
<!-- 错误状态行 -->
<div class='status-row'>
<div class='status-item full-width'>
<h3>Error Status</h3>
<div class='status-value'>
<span class='status-label'>Error Code:</span>
<span id='error-status'>#</span>
</div>
</div>
</div>
</div>
</div>
<div class='network-config'>
<h2>参数设置</h2>
<form method='post' action='/config'> <form method='post' action='/config'>
<div class='form-group'> <div class='form-group'>
<label>MAC:</label> <label>MAC:</label>
@ -183,7 +403,6 @@ document.addEventListener('DOMContentLoaded', function() {
</div> </div>
<input type='submit' value='Save Configuration'> <input type='submit' value='Save Configuration'>
</form> </form>
<div class='status %s'>
Network Status: %s
</div> </div>
</body></html>)" </body></html>)"

View File

@ -75,19 +75,15 @@ static void send_chunk_end(uint8_t sn)
static void handle_config_page(uint8_t sn) static void handle_config_page(uint8_t sn)
{ {
char buffer[CHUNK_SIZE]; char buffer[CHUNK_SIZE];
bool is_connected = (wizphy_getphylink() == PHY_LINK_ON);
char* link_status = is_connected ? "Connected" : "Disconnected";
char* status_class = is_connected ? "connected" : "disconnected";
// 先将完整的HTML内容格式化到一个临时缓冲区 // 先将完整的HTML内容格式化到一个临时缓冲区
char full_page[8192]; // 确保足够大 char full_page[1024*15]; // 确保足够大
int total_len = sprintf(full_page, index_html, int total_len = sprintf(full_page, index_html,0,
gWIZNETINFO.mac[0], gWIZNETINFO.mac[1], gWIZNETINFO.mac[2], gWIZNETINFO.mac[0], gWIZNETINFO.mac[1], gWIZNETINFO.mac[2],
gWIZNETINFO.mac[3], gWIZNETINFO.mac[4], gWIZNETINFO.mac[5], gWIZNETINFO.mac[3], gWIZNETINFO.mac[4], gWIZNETINFO.mac[5],
gWIZNETINFO.ip[0], gWIZNETINFO.ip[1], gWIZNETINFO.ip[2], gWIZNETINFO.ip[3], 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.sn[0], gWIZNETINFO.sn[1], gWIZNETINFO.sn[2], gWIZNETINFO.sn[3],
gWIZNETINFO.gw[0], gWIZNETINFO.gw[1], gWIZNETINFO.gw[2], gWIZNETINFO.gw[3], gWIZNETINFO.gw[0], gWIZNETINFO.gw[1], gWIZNETINFO.gw[2], gWIZNETINFO.gw[3]);
status_class, link_status);
// 发送响应头 // 发送响应头
send_chunked_response_header(sn); send_chunked_response_header(sn);
@ -145,6 +141,118 @@ void http_server_init(void)
listen(HTTP_SERVER_SOCKET); listen(HTTP_SERVER_SOCKET);
} }
// 三通阀结构体
typedef struct {
uint8_t angle1; // 阀门1角度 (120/210)
uint8_t angle2; // 阀门2角度 (120/210)
} ValveStatus;
// 泵结构体
typedef struct {
uint8_t status1; // 泵1运行状态 (停止/顺时针/逆时针)
uint8_t status2; // 泵2运行状态 (停止/顺时针/逆时针)
uint8_t speed1; // 泵1速度百分比 (0-100)
uint8_t speed2; // 泵2速度百分比 (0-100)
} PumpStatus;
// 设备状态结构体
// 1.下挂设备在位状态在位为1否则为0当前为气泡感应器1个字节
// 2.两个三通阀实时角度每个角度占用1个字节只能为210或120
// 3.泵状态1表示泵顺时针转动中2表示泵逆时针转动中0表示停止两个泵共2个字节
// 4.泵速度2个字节每个泵的速度占用一个字节表示当前泵设定的速度百分比
// 5.气泡感应器读值1表示监测到气泡0表示没有气泡共1个字节
// 6.急停按键状态1个字节1为按下0为正常。
// 7.错误码1个字节用于监控当前系统总体状态如通信异常、控制异常等等具体错误码待定
// 8.初始化状态1个字节 0表示初始化执行中1表示初始化执行成功2表示初始化执行失败。
typedef struct {
uint8_t deviceStatus; // 下挂设备状态
ValveStatus valves; // 两个三通阀状态
PumpStatus pumps; // 两个泵状态
uint8_t bubbleStatus; // 气泡状态
uint8_t stopStatus; // 急停状态
uint8_t errorCode; // 错误码
uint8_t initStatus; // 初始化状态
} DeviceStatus;
DeviceStatus deviceStatus={
.deviceStatus=1,
.valves={
.angle1=0,
.angle2=0
},
.pumps={
.status1=0,
.status2=0,
.speed1=60,
.speed2=70
},
.bubbleStatus=0,
.stopStatus=0,
.errorCode=0,
.initStatus=1
};
// 发送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);
}
void http_server_task(void) void http_server_task(void)
{ {
uint8_t buffer[2048]; uint8_t buffer[2048];
@ -153,13 +261,16 @@ void http_server_task(void)
switch(status) switch(status)
{ {
case SOCK_INIT:
listen(HTTP_SERVER_SOCKET);
break;
case SOCK_LISTEN: case SOCK_LISTEN:
// 等待连接 // 等待连接
break; break;
case SOCK_ESTABLISHED: case SOCK_ESTABLISHED:
{ {
// 接收数据
if((size = getSn_RX_RSR(HTTP_SERVER_SOCKET)) > 0) if((size = getSn_RX_RSR(HTTP_SERVER_SOCKET)) > 0)
{ {
size = recv(HTTP_SERVER_SOCKET, buffer, sizeof(buffer)); size = recv(HTTP_SERVER_SOCKET, buffer, sizeof(buffer));
@ -169,11 +280,14 @@ void http_server_task(void)
parse_http_request(buffer, size, &req); parse_http_request(buffer, size, &req);
if(req.method == HTTP_GET) { if(req.method == HTTP_GET) {
handle_config_page(HTTP_SERVER_SOCKET); if(strcmp(req.uri, "/status") == 0) {
handle_status_request(HTTP_SERVER_SOCKET);
} else {
handle_config_page(HTTP_SERVER_SOCKET);
}
} }
else if(req.method == HTTP_POST && strcmp(req.uri, "/config") == 0) { else if(req.method == HTTP_POST && strcmp(req.uri, "/config") == 0) {
update_network_config((char*)req.body); update_network_config((char*)req.body);
// 重定向回配置页面
send_chunked_response_header(HTTP_SERVER_SOCKET); send_chunked_response_header(HTTP_SERVER_SOCKET);
send_chunk(HTTP_SERVER_SOCKET, send_chunk(HTTP_SERVER_SOCKET,
"<html><head><meta http-equiv='refresh' content='0;url=/'></head></html>", "<html><head><meta http-equiv='refresh' content='0;url=/'></head></html>",
@ -191,7 +305,6 @@ void http_server_task(void)
case SOCK_CLOSED: case SOCK_CLOSED:
socket(HTTP_SERVER_SOCKET, Sn_MR_TCP, HTTP_SERVER_PORT, 0); socket(HTTP_SERVER_SOCKET, Sn_MR_TCP, HTTP_SERVER_PORT, 0);
listen(HTTP_SERVER_SOCKET);
break; break;
} }
} }