萤火工场 GD32VW553-IOT-V2 简单的远程控制浇水
分享作者:dh9824
评测品牌:萤火工场
评测型号:GD32VW553-IOT-V2
发布时间:2025-10-21 14:26:31
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