萤火工场 GD32VW553-IOT-V2 简单的远程控制浇水
分享作者:dh9824
评测品牌:萤火工场
评测型号:GD32VW553-IOT-V2
发布时间:2025-10-21 14:26:31
1 2
视频链接
前言
开源口碑分享内容
纯小白艰难自学,还好有元宝,你值得拥有,
打开GD32EmbeddedBuilder,导入官方提供的演示案例,softap_tcp_ server,
然后我根据我爱小易大佬的代码在元宝里滚了我需要的代码,大概功能是远程控制浇水系统启动关闭,后续还想添加湿度传感器,太阳能供电充电,水位检测,显示器等等,有试过,可惜毛病很多,浪费了半个多月时间,还是不行,只能先实现远程控制,配合内网穿透,就能实现外网访问控制网站了
基于您的代码框架,我将修改为完整的智能浇水系统,添加远程定时浇水、湿度检测、手动控制等功能。以下是完整的修改后代码:
/*!
\file main.c
\brief GD32VW553 智能浇水系统 - SoftAP + 远程控制
\author 我爱小易
\company 萤火工场
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "gd32vw55x.h"
#include "app_cfg.h"
#include "gd32vw55x_platform.h"
#include "lwip/sockets.h"
#include "lwip/priv/sockets_priv.h"
#include "wifi_management.h"
#include "wifi_init.h"
#include "gd32vw55x_adc.h"
/* 硬件引脚定义 - 请根据实际硬件调整 */
#define WATER_PUMP_PORT GPIOB
#define WATER_PUMP_PIN GPIO_PIN_2
#define SOIL_MOISTURE_ADC_CHANNEL ADC_CHANNEL_0
#define WATER_LEVEL_PORT GPIOA
#define WATER_LEVEL_PIN GPIO_PIN_1
#define SYSTEM_LED_PORT GPIOB
#define SYSTEM_LED_PIN GPIO_PIN_0
#define AP_SSID "SmartWatering_AP"
#define AP_PASSWORD "12345678"
#define HTTP_PORT 80
/* 系统参数 */
#define MOISTURE_THRESHOLD_LOW 30 /* 自动浇水阈值 */
#define MOISTURE_THRESHOLD_HIGH 60 /* 停止浇水阈值 */
#define WATERING_DURATION 30000 /* 浇水持续时间(ms) */
/* 全局变量 */
volatile uint8_t watering_mode = 0; /* 0:自动 1:定时 2:手动 */
volatile uint8_t watering_status = 0;
volatile uint16_t soil_moisture = 0;
volatile uint8_t water_level = 0;
volatile uint32_t watering_timer = 0;
volatile uint32_t next_watering_time = 0;
/* 硬件初始化 */
void hardware_init(void) {
/* 初始化水泵控制 */
rcu_periph_clock_enable(RCU_GPIOB);
gpio_mode_set(WATER_PUMP_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, WATER_PUMP_PIN);
gpio_output_options_set(WATER_PUMP_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, WATER_PUMP_PIN);
gpio_bit_reset(WATER_PUMP_PORT, WATER_PUMP_PIN);
/* 初始化水位检测 */
rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(WATER_LEVEL_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, WATER_LEVEL_PIN);
/* 初始化系统LED */
gpio_mode_set(SYSTEM_LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SYSTEM_LED_PIN);
gpio_output_options_set(SYSTEM_LED_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, SYSTEM_LED_PIN);
gpio_bit_reset(SYSTEM_LED_PORT, SYSTEM_LED_PIN);
/* 初始化ADC用于土壤湿度检测 */
rcu_periph_clock_enable(RCU_ADC0);
adc_mode_config(ADC_MODE_FREE);
adc_special_function_config(ADC_SCAN_MODE, ENABLE);
adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);
adc_clock_config(ADC_CLK_SYSCLK_DIV6);
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
adc_regular_channel_config(0, SOIL_MOISTURE_ADC_CHANNEL, ADC_SAMPLETIME_55POINT5);
adc_enable();
delay_1ms(1);
adc_calibration_enable();
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}
/* 控制函数 */
void water_pump_on(void) {
gpio_bit_set(WATER_PUMP_PORT, WATER_PUMP_PIN);
watering_status = 1;
printf("水泵开启\n");
}
void water_pump_off(void) {
gpio_bit_reset(WATER_PUMP_PORT, WATER_PUMP_PIN);
watering_status = 0;
printf("水泵关闭\n");
}
void system_led_toggle(void) {
gpio_bit_toggle(SYSTEM_LED_PORT, SYSTEM_LED_PIN);
}
/* 传感器读取函数 */
uint16_t read_soil_moisture(void) {
while(!adc_flag_get(ADC0, ADC_FLAG_EOC));
uint16_t adc_value = adc_regular_data_read(ADC0);
/* 转换为百分比 (需要根据实际传感器校准) */
return (100 - ((adc_value * 100) / 4095));
}
uint8_t check_water_level(void) {
return (gpio_input_bit_get(WATER_LEVEL_PORT, WATER_LEVEL_PIN) == RESET) ? 1 : 0;
}
/* 自动浇水逻辑 */
void auto_watering_task(void) {
soil_moisture = read_soil_moisture();
water_level = check_water_level();
if(watering_mode == 0) { /* 自动模式 */
if(soil_moisture < MOISTURE_THRESHOLD_LOW && !watering_status && !water_level) {
water_pump_on();
watering_timer = WATERING_DURATION;
}
else if((soil_moisture > MOISTURE_THRESHOLD_HIGH && watering_status) || water_level) {
water_pump_off();
watering_timer = 0;
}
}
/* 处理浇水定时器 */
if(watering_timer > 0) {
if(--watering_timer == 0) {
water_pump_off();
}
}
}
// 解析 URL 参数
int get_query_param(const char* request, const char* key, char* value, size_t val_size) {
const char* query_start = strchr(request, '?');
if (!query_start) return 0;
const char* key_pos = strstr(query_start, key);
if (!key_pos) return 0;
const char* eq = strchr(key_pos, '=');
if (!eq) return 0;
eq++;
const char* end = eq;
while (*end && *end != ' ' && *end != '\r' && *end != '&' && *end != '\n') {
end++;
}
size_t len = (end - eq) < (val_size - 1) ? (end - eq) : (val_size - 1);
memcpy(value, eq, len);
value[len] = '\0';
return 1;
}
// 发送 HTTP 响应
void send_response(int fd, const char* content_type, const char* body) {
char header[256];
int len = strlen(body);
snprintf(header, sizeof(header),
"HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Content-Length: %d\r\n"
"Connection: close\r\n"
"\r\n", content_type, len);
write(fd, header, strlen(header));
write(fd, body, len);
}
static void http_server_serve(int conn_fd) {
char buffer[1024];
int len = read(conn_fd, buffer, sizeof(buffer) - 1);
if (len <= 0) {
close(conn_fd);
return;
}
buffer[len] = '\0';
printf("请求: %.100s\n", buffer);
// API 接口处理
if (strncmp(buffer, "GET /api/", 8) == 0) {
char action[16] = {0};
char value[16] = {0};
if (strncmp(buffer, "GET /api/control", 16) == 0) {
if (get_query_param(buffer, "action", action, sizeof(action))) {
if (strcmp(action, "on") == 0) {
watering_mode = 2; /* 手动模式 */
water_pump_on();
watering_timer = WATERING_DURATION;
} else if (strcmp(action, "off") == 0) {
water_pump_off();
} else if (strcmp(action, "auto") == 0) {
watering_mode = 0; /* 自动模式 */
} else if (strcmp(action, "timer") == 0) {
watering_mode = 1; /* 定时模式 */
}
}
}
else if (strncmp(buffer, "GET /api/timer", 14) == 0) {
if (get_query_param(buffer, "set", value, sizeof(value))) {
next_watering_time = atoi(value) * 60 * 1000; /* 转换为毫秒 */
printf("定时浇水设置: %s分钟后\n", value);
}
}
/* 返回系统状态JSON */
char json[256];
const char* mode_str[] = {"自动", "定时", "手动"};
const char* pump_status = watering_status ? "开启" : "关闭";
const char* water_level_str = water_level ? "低水位" : "正常";
snprintf(json, sizeof(json),
"{\"mode\":\"%s\",\"pump\":\"%s\",\"moisture\":%d,\"water_level\":\"%s\",\"timer\":%lu}",
mode_str[watering_mode], pump_status, soil_moisture, water_level_str,
watering_timer / 1000);
send_response(conn_fd, "application/json", json);
close(conn_fd);
return;
}
// 返回智能浇水系统网页
const char* html =
"<!DOCTYPE html>"
"<html lang=\"zh-CN\">"
"<head>"
" <meta charset=\"UTF-8\">"
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">"
" <title>智能浇水系统 - GD32VW553</title>"
" <style>"
" body {"
" margin: 0; padding: 20px;"
" font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;"
" background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);"
" min-height: 100vh; color: #333;"
" }"
" .container { max-width: 500px; margin: 0 auto; background: rgba(255,255,255,0.95); border-radius: 20px; padding: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); }"
" h1 { text-align: center; color: #2c3e50; margin-bottom: 10px; }"
" .subtitle { text-align: center; color: #7f8c8d; margin-bottom: 30px; }"
" .status-card { background: #ecf0f1; border-radius: 15px; padding: 20px; margin: 15px 0; }"
" .status-item { display: flex; justify-content: space-between; margin: 10px 0; }"
" .moisture-bar { height: 20px; background: #bdc3c7; border-radius: 10px; overflow: hidden; margin: 10px 0; }"
" .moisture-fill { height: 100%; background: linear-gradient(90deg, #e74c3c, #f39c12, #27ae60); transition: width 0.5s; }"
" .btn-group { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 15px 0; }"
" .btn { padding: 12px; border: none; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; transition: all 0.3s; }"
" .btn-primary { background: #3498db; color: white; }"
" .btn-success { background: #27ae60; color: white; }"
" .btn-warning { background: #f39c12; color: white; }"
" .btn-danger { background: #e74c3c; color: white; }"
" .btn:active { transform: scale(0.98); }"
" .timer-set { display: flex; gap: 10px; margin: 15px 0; }"
" .timer-input { flex: 1; padding: 12px; border: 2px solid #bdc3c7; border-radius: 10px; font-size: 16px; }"
" .alert { padding: 10px; border-radius: 5px; margin: 10px 0; text-align: center; }"
" .alert-warning { background: #fff3cd; color: #856404; border: 1px solid #ffeaa7; }"
" .footer { text-align: center; margin-top: 30px; color: #7f8c8d; font-size: 14px; }"
" </style>"
"</head>"
"<body>"
" <div class=\"container\">"
" <h1>🌱 智能浇水系统</h1>"
" <div class=\"subtitle\">GD32VW553 · 萤火工场 · 我爱小易</div>"
" "
" <div class=\"status-card\">"
" <h3>📊 系统状态</h3>"
" <div class=\"status-item\"><span>工作模式:</span><span id=\"mode\">自动</span></div>"
" <div class=\"status-item\"><span>水泵状态:</span><span id=\"pump\">关闭</span></div>"
" <div class=\"status-item\"><span>土壤湿度:</span><span id=\"moisture\">0%</span></div>"
" <div class=\"moisture-bar\"><div id=\"moistureBar\" class=\"moisture-fill\" style=\"width: 0%\"></div></div>"
" <div class=\"status-item\"><span>水位状态:</span><span id=\"waterLevel\">正常</span></div>"
" <div class=\"status-item\"><span>剩余时间:</span><span id=\"timer\">0秒</span></div>"
" </div>"
" "
" <div id=\"waterAlert\" class=\"alert alert-warning\" style=\"display:none;\">⚠️ 水位过低,浇水已停止!</div>"
" "
" <div class=\"btn-group\">"
" <button class=\"btn btn-primary\" onclick=\"setMode('auto')\">🤖 自动模式</button>"
" <button class=\"btn btn-warning\" onclick=\"setMode('timer')\">⏰ 定时模式</button>"
" </div>"
" "
" <div class=\"btn-group\">"
" <button class=\"btn btn-success\" onclick=\"controlPump('on')\">💧 开始浇水</button>"
" <button class=\"btn btn-danger\" onclick=\"controlPump('off')\">🛑 停止浇水</button>"
" </div>"
" "
" <div style=\"margin: 20px 0;\">"
" <h4>定时浇水设置:</h4>"
" <div class=\"timer-set\">"
" <input type=\"number\" id=\"timerInput\" class=\"timer-input\" placeholder=\"分钟后浇水\" min=\"1\" max=\"1440\">"
" <button class=\"btn btn-warning\" onclick=\"setTimer()\">设置定时</button>"
" </div>"
" </div>"
" "
" <div class=\"footer\">"
" 连接开发板 Wi-Fi 即可远程控制<br>"
" 系统将自动监测土壤湿度和水位"
" </div>"
" </div>"
" "
" <script>"
" let updateInterval;"
" "
" function updateStatus() {"
" fetch('/api/control?action=status')"
" .then(res => res.json())"
" .then(data => {"
" document.getElementById('mode').textContent = data.mode;"
" document.getElementById('pump').textContent = data.pump;"
" document.getElementById('moisture').textContent = data.moisture + '%';"
" document.getElementById('waterLevel').textContent = data.water_level;"
" document.getElementById('timer').textContent = data.timer + '秒';"
" "
" document.getElementById('moistureBar').style.width = data.moisture + '%';"
" "
" const alert = document.getElementById('waterAlert');"
" alert.style.display = data.water_level === '低水位' ? 'block' : 'none';"
" "
" // 根据湿度改变颜色"
" const moisture = data.moisture;"
" if(moisture < 30) {"
" document.getElementById('moistureBar').style.background = '#e74c3c';"
" } else if(moisture < 60) {"
" document.getElementById('moistureBar').style.background = '#f39c12';"
" } else {"
" document.getElementById('moistureBar').style.background = '#27ae60';"
" }"
" })"
" .catch(err => console.error('更新状态失败:', err));"
" }"
" "
" function setMode(mode) {"
" fetch('/api/control?action=' + mode)"
" .then(() => updateStatus())"
" .catch(err => console.error('设置模式失败:', err));"
" }"
" "
" function controlPump(action) {"
" fetch('/api/control?action=' + action)"
" .then(() => updateStatus())"
" .catch(err => console.error('控制水泵失败:', err));"
" }"
" "
" function setTimer() {"
" const minutes = document.getElementById('timerInput').value;"
" if(minutes && minutes > 0) {"
" fetch('/api/timer?set=' + minutes)"
" .then(() => {"
" updateStatus();"
" document.getElementById('timerInput').value = '';"
" alert('定时浇水设置成功: ' + minutes + '分钟后');"
" })"
" .catch(err => console.error('设置定时失败:', err));"
" }"
" }"
" "
" // 页面加载时开始定时更新"
" document.addEventListener('DOMContentLoaded', function() {"
" updateStatus();"
" updateInterval = setInterval(updateStatus, 2000); // 每2秒更新一次"
" });"
" "
" // 页面卸载时清除定时器"
" window.addEventListener('beforeunload', function() {"
" clearInterval(updateInterval);"
" });"
" </script>"
"</body>"
"</html>";
send_response(conn_fd, "text/html; charset=utf-8", html);
close(conn_fd);
}
static void http_server_task(void *arg) {
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
printf("创建 Socket 失败!\n");
return;
}
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(HTTP_PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
printf("绑定端口失败!\n");
close(listen_fd);
return;
}
if (listen(listen_fd, 5) < 0) {
printf("监听失败!\n");
close(listen_fd);
return;
}
printf("智能浇水系统已启动!\n");
printf("请连接 Wi-Fi: %s, 密码: %s\n", AP_SSID, AP_PASSWORD);
printf("然后访问: http://192.168.237.1\n");
while (1) {
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int conn_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &len);
if (conn_fd >= 0) {
printf("客户端连接: %s\n", inet_ntoa(client_addr.sin_addr));
http_server_serve(conn_fd);
}
/* 在主循环中处理自动浇水任务 */
auto_watering_task();
system_led_toggle();
delay_1ms(100); /* 短暂延时 */
}
}
static void system_monitor_task(void *param) {
while(1) {
auto_watering_task();
system_led_toggle();
delay_1ms(1000); /* 1秒间隔 */
}
}
static void wifi_ap_task(void *param) {
printf("正在启动智能浇水系统 AP...\n");
int ret = wifi_management_ap_start((char *)AP_SSID, (char *)AP_PASSWORD, 1, AUTH_MODE_WPA_WPA2, 0);
if (ret != 0) {
printf("AP 启动失败!错误码: %d\n", ret);
sys_task_delete(NULL);
return;
}
printf("AP 启动成功: %s\n", AP_SSID);
/* 初始化硬件 */
hardware_init();
/* 创建系统监控任务 */
sys_task_create_dynamic((const uint8_t *)"monitor_task", 2048, OS_TASK_PRIORITY(1), system_monitor_task, NULL);
/* 启动HTTP服务器 */
http_server_task(NULL);
sys_task_delete(NULL);
}
int main(void) {
platform_init();
if (wifi_init()) {
printf("Wi-Fi 初始化失败!\n");
while (1);
}
/* 创建AP任务 */
sys_task_create_dynamic((const uint8_t *)"ap_task", 4096, OS_TASK_PRIORITY(0), wifi_ap_task, NULL);
sys_os_start();
while (1);
}
主要新增功能:
土壤湿度检测 - 实时读取并显示湿度值
水位检测 - 监测水位状态,低水位时自动停止浇水
三种工作模式:
🤖 自动模式:根据湿度自动控制
⏰ 定时模式:设置定时浇水
👆 手动模式:远程手动控制
实时状态显示 - 湿度进度条、水位警告、倒计时等
响应式界面 - 美观的现代化UI设计
使用说明:
编译烧录后,设备会创建WiFi热点 SmartWatering_AP
手机连接该热点,密码 12345678
浏览器访问 http://192.168.237.1
实时监控土壤湿度和系统状态
远程控制浇水模式和定时设置
硬件连接建议:
水泵继电器 → PB2
土壤湿度传感器 → ADC0通道0 (PA0)
水位传感器 → PA1
状态LED → PB0
这个系统具备了您需要的所有功能,界面美观易用,适合实际部署使用!
可惜这不知道哪里有问题,元宝也解决不了。
在画个板子整合的好看点,可惜俺是新人得一点点学,ai给的代码总是有问题,第一次测试的时候是能用的,我后面重新烧录之后就出现通电就掉wifi,继电器持续运行等问题,只能以后有空再解决,简单的功能是勉强实现了
以下是我最后能用的简化版,还有一些调整其他文件,可能这就是造成我第二次无法使用的原因。
/*!
\file main.c
\brief GD32VW553 SoftAP + 中文 Captive Portal + 无刷新 水泵控制
\author 作者我爱小易
\company 萤火工场
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "gd32vw55x.h"
#include "app_cfg.h"
#include "gd32vw55x_platform.h"
#include "lwip/sockets.h"
#include "lwip/priv/sockets_priv.h"
#include "wifi_management.h"
#include "wifi_init.h"
#define PUMP_PORT GPIOB
#define PUMP_PIN GPIO_PIN_2
#define AP_SSID "GD32_PUMP_AP"
#define AP_PASSWORD "12345678"
#define HTTP_PORT 80
void pump_init(void) {
rcu_periph_clock_enable(RCU_GPIOB);
gpio_mode_set(PUMP_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, PUMP_PIN);
gpio_output_options_set(PUMP_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, PUMP_PIN);
gpio_bit_reset(PUMP_PORT, PUMP_PIN); // 初始状态关闭水泵
}
void pump_on(void) {
gpio_bit_set(PUMP_PORT, PUMP_PIN);
printf("水泵开启\n");
}
void pump_off(void) {
gpio_bit_reset(PUMP_PORT, PUMP_PIN);
printf("水泵关闭\n");
}
// 解析 URL 参数
int get_query_param(const char* request, const char* key, char* value, size_t val_size) {
const char* query_start = strchr(request, '?');
if (!query_start) return 0;
const char* key_pos = strstr(query_start, key);
if (!key_pos) return 0;
const char* eq = strchr(key_pos, '=');
if (!eq) return 0;
eq++;
const char* end = eq;
while (*end && *end != ' ' && *end != '\r' && *end != '&' && *end != '\n') {
end++;
}
size_t len = (end - eq) < (val_size - 1) ? (end - eq) : (val_size - 1);
memcpy(value, eq, len);
value[len] = '\0';
return 1;
}
// 发送 HTTP 响应
void send_response(int fd, const char* content_type, const char* body) {
char header[256];
int len = strlen(body);
snprintf(header, sizeof(header),
"HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Content-Length: %d\r\n"
"Connection: close\r\n"
"\r\n", content_type, len);
write(fd, header, strlen(header));
write(fd, body, len);
}
static void http_server_serve(int conn_fd) {
char buffer[1024];
int len = read(conn_fd, buffer, sizeof(buffer) - 1);
if (len <= 0) {
close(conn_fd);
return;
}
buffer[len] = '\0';
printf("请求: %.100s\n", buffer);
// 处理 API:/api/control?action=on/off
if (strncmp(buffer, "GET /api/control", 16) == 0) {
char action[16] = {0};
if (get_query_param(buffer, "action", action, sizeof(action))) {
if (strcmp(action, "on") == 0) {
pump_on();
} else if (strcmp(action, "off") == 0) {
pump_off();
}
}
const char* status = gpio_input_bit_get(PUMP_PORT, PUMP_PIN) ? "on" : "off";
char json[64];
snprintf(json, sizeof(json), "{\"status\":\"%s\"}", status);
send_response(conn_fd, "application/json", json);
close(conn_fd);
return;
}
// 返回中文美化页面(修改后)
const char* html =
"<!DOCTYPE html>"
"<html lang=\"zh-CN\">"
"<head>"
" <meta charset=\"UTF-8\">"
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">"
" <title>GD32VW553 水泵远程控制</title>"
" <style>"
" body {"
" margin: 0; padding: 0;"
" font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;"
" background: #ffffff;"
" height: 100vh; display: flex; flex-direction: column; justify-content: center; align-items: center;"
" color: #2c3e50; text-align: center;"
" }"
" .container { "
" padding: 40px 30px; "
" max-width: 480px; "
" background: #f8f9fa;"
" border-radius: 20px;"
" box-shadow: 0 10px 30px rgba(0,0,0,0.08);"
" }"
" h1 { font-size: 32px; margin: 10px 0; color: #2c3e50; font-weight: 700; }"
" .subtitle { font-size: 16px; opacity: 0.7; margin-bottom: 30px; color: #5a6c7d; }"
" .pump-status { "
" width: 140px; height: 140px; border-radius: 50%; margin: 30px auto; "
" transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); "
" display: flex; align-items: center; justify-content: center; "
" font-size: 60px; border: 3px solid #e9ecef;"
" }"
" .pump-status.on { "
" background: linear-gradient(135deg, #00b894, #00a085); "
" box-shadow: 0 10px 25px rgba(0, 184, 148, 0.3); "
" border-color: #00b894;"
" }"
" .pump-status.off { "
" background: linear-gradient(135deg, #dfe6e9, #b2bec3); "
" box-shadow: 0 10px 25px rgba(0, 0, 0, 0.05); "
" border-color: #dfe6e9;"
" }"
" .status { font-size: 24px; margin: 20px 0; font-weight: 600; color: #2c3e50; }"
" .btn {"
" display: block; width: 100%; padding: 20px;"
" font-size: 20px; font-weight: 600; border: none; border-radius: 15px;"
" background: linear-gradient(135deg, #3498db, #2980b9);"
" color: white; cursor: pointer; margin-top: 25px;"
" transition: all 0.3s ease;"
" box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3);"
" letter-spacing: 1px;"
" }"
" .btn.on { "
" background: linear-gradient(135deg, #00b894, #00a085);"
" box-shadow: 0 5px 15px rgba(0, 184, 148, 0.3);"
" }"
" .btn.off { "
" background: linear-gradient(135deg, #e74c3c, #c0392b);"
" box-shadow: 0 5px 15px rgba(231, 76, 60, 0.3);"
" }"
" .btn:hover { "
" transform: translateY(-2px); "
" box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);"
" }"
" .btn:active { transform: translateY(0); }"
" .footer { margin-top: 25px; font-size: 14px; opacity: 0.6; color: #7f8c8d; }"
" .warning { "
" background: #fff3cd; padding: 12px; border-radius: 10px; "
" margin: 20px 0; font-size: 14px; color: #856404;"
" border-left: 4px solid #ffc107;"
" }"
" @media (max-width: 480px) {"
" .container { padding: 30px 20px; margin: 20px; }"
" h1 { font-size: 28px; }"
" .pump-status { width: 120px; height: 120px; font-size: 50px; }"
" }"
" </style>"
"</head>"
"<body>"
" <div class=\"container\">"
" <h1>GD32VW553 水泵远程控制</h1>"
" <div class=\"subtitle\">作者:我爱小易|出品:萤火工场</div>"
" <div id=\"pumpStatus\" class=\"pump-status off\">💧</div>"
" <div id=\"status\" class=\"status\">水泵状态:关闭</div>"
" <div class=\"warning\">⚠️ 远程控制水泵,请确保安全操作</div>"
" <button id=\"controlBtn\" class=\"btn off\">启动水泵</button>"
" <div class=\"footer\">连接开发板 Wi-Fi 即可远程控制</div>"
" </div>"
""
" <script>"
" let isPumpOn = false;"
""
" function updateUI() {"
" const pumpStatus = document.getElementById('pumpStatus');"
" const status = document.getElementById('status');"
" const btn = document.getElementById('controlBtn');"
" if (isPumpOn) {"
" pumpStatus.className = 'pump-status on';"
" pumpStatus.textContent = '💦';"
" status.textContent = '水泵状态:运行中';"
" btn.textContent = '停止水泵';"
" btn.className = 'btn on';"
" } else {"
" pumpStatus.className = 'pump-status off';"
" pumpStatus.textContent = '💧';"
" status.textContent = '水泵状态:关闭';"
" btn.textContent = '启动水泵';"
" btn.className = 'btn off';"
" }"
" }"
""
" function sendAction(action) {"
" fetch('/api/control?action=' + action)"
" .then(res => res.json())"
" .then(data => {"
" isPumpOn = (data.status === 'on');"
" updateUI();"
" })"
" .catch(err => console.error('请求失败:', err));"
" }"
""
" document.getElementById('controlBtn').addEventListener('click', () => {"
" sendAction(isPumpOn ? 'off' : 'on');"
" });"
""
" // 初始化:获取当前状态"
" fetch('/api/control?action=get')"
" .then(res => res.json())"
" .then(data => {"
" isPumpOn = (data.status === 'on');"
" updateUI();"
" });"
" </script>"
"</body>"
"</html>";
send_response(conn_fd, "text/html; charset=utf-8", html);
close(conn_fd);
}
static void http_server_task(void *arg) {
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
printf("创建 Socket 失败!\n");
return;
}
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(HTTP_PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
printf("绑定端口失败!\n");
close(listen_fd);
return;
}
if (listen(listen_fd, 5) < 0) {
printf("监听失败!\n");
close(listen_fd);
return;
}
printf("HTTP 服务器已启动,请连接 Wi-Fi 后访问 http://192.168.237.1\n");
while (1) {
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int conn_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &len);
if (conn_fd >= 0) {
printf("客户端已连接:%s\n", inet_ntoa(client_addr.sin_addr));
http_server_serve(conn_fd);
}
}
}
static void wifi_ap_task(void *param) {
printf("正在启动 SoftAP:%s ...\n", AP_SSID);
int ret = wifi_management_ap_start((char *)AP_SSID, (char *)AP_PASSWORD, 1, AUTH_MODE_WPA_WPA2, 0);
if (ret != 0) {
printf("SoftAP 启动失败!错误码:%d\n", ret);
sys_task_delete(NULL);
return;
}
printf("SoftAP 已启动,SSID:%s,密码:%s\n", AP_SSID, AP_PASSWORD);
pump_init();
http_server_task(NULL);
sys_task_delete(NULL);
}
int main(void) {
platform_init();
if (wifi_init()) {
printf("Wi-Fi 初始化失败!\n");
while (1);
}
sys_task_create_dynamic((const uint8_t *)"ap_task", 4096, OS_TASK_PRIORITY(0), wifi_ap_task, NULL);
sys_os_start();
while (1);
}
总结,这个板子是一款很适合新人尝试的开发板,可惜成熟的项目还是太少,相对主流板子,希望以后优秀的项目能越来越多,
全部评论

暂无评论

0/144