using nanoFramework.WebServer;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
namespace YeFanIoTTest.Managers
{
// Web服务器控制器
// 处理AP配网的HTTP请求
// 【重要】必须是public类,否则WebServer无法实例化
public class WebServerController
{
// 静态APConfigManager实例引用
private static APConfigManager _apConfigManager;
// 设置APConfigManager实例(internal,因为APConfigManager是internal)
internal static void SetAPConfigManager(APConfigManager apConfigManager)
{
_apConfigManager = apConfigManager;
}
// ========== 配网页面路由 ==========
// GET / - 配网主页
[Route("")]
[Method("GET")]
public void GetIndex(WebServerEventArgs e)
{
Debug.WriteLine("[WebServer] ========== Received GET request ==========");
Debug.WriteLine($"[WebServer] Remote endpoint: {e.Context.Request.RemoteEndPoint}");
Debug.WriteLine($"[WebServer] Request URL: {e.Context.Request.RawUrl}");
// 直接输出HTML,不进行任何检查
string html = GetConfigPageHtml();
e.Context.Response.ContentType = "text/html";
WebServer.OutputAsStream(e.Context.Response, html);
Debug.WriteLine("[WebServer] Response sent successfully");
}
// POST /config - 处理配网表单提交
[Route("config")]
[Method("POST")]
public void PostConfig(WebServerEventArgs e)
{
try
{
// 解析表单数据
string body = GetRequestBody(e);
// 解析SSID和密码
string ssid = ParseFormField(body, "ssid");
string password = ParseFormField(body, "password");
if (string.IsNullOrEmpty(ssid) || string.IsNullOrEmpty(password))
{
string errorHtml = GetErrorPageHtml("SSID和密码不能为空!");
e.Context.Response.ContentType = "text/html";
WebServer.OutputAsStream(e.Context.Response, errorHtml);
return;
}
// ========== 调用APConfigManager处理配网 ==========
if (_apConfigManager == null)
{
string errorHtml = GetErrorPageHtml("系统错误:APConfigManager未初始化");
e.Context.Response.ContentType = "text/html";
WebServer.OutputAsStream(e.Context.Response, errorHtml);
return;
}
// 调用HandleConfigSubmit方法处理配网
// 该方法会:连接WiFi、检查网络可达性、触发OnConfigCompleted事件
_apConfigManager.HandleConfigSubmit(ssid, password);
// 根据配网结果显示页面
// 注意:HandleConfigSubmit已经处理了所有逻辑,这里只需要显示结果页面
// 由于HandleConfigSubmit是同步的,我们可以直接检查CurrentState
// 等待配网完成(最多等待10秒)
int waitCount = 0;
while (_apConfigManager.CurrentState == APConfigState.Connecting && waitCount < 100)
{
System.Threading.Thread.Sleep(100);
waitCount++;
}
// 根据配网结果显示页面
if (_apConfigManager.CurrentState == APConfigState.Configured)
{
// 配网成功
string successHtml = GetSuccessPageHtml(ssid);
e.Context.Response.ContentType = "text/html";
WebServer.OutputAsStream(e.Context.Response, successHtml);
}
else if (_apConfigManager.CurrentState == APConfigState.Failed)
{
// 配网失败
string errorHtml = GetErrorPageHtml("WiFi连接失败,请检查SSID和密码是否正确");
e.Context.Response.ContentType = "text/html";
WebServer.OutputAsStream(e.Context.Response, errorHtml);
}
else
{
// 其他状态(超时等)
string errorHtml = GetErrorPageHtml("配网超时,请重试");
e.Context.Response.ContentType = "text/html";
WebServer.OutputAsStream(e.Context.Response, errorHtml);
}
}
catch (Exception ex)
{
string errorHtml = GetErrorPageHtml("配网失败:" + ex.Message);
e.Context.Response.ContentType = "text/html";
WebServer.OutputAsStream(e.Context.Response, errorHtml);
}
}
// GET /scan - 扫描WiFi网络(AP模式下不支持)
[Route("scan")]
[Method("GET")]
public void GetScan(WebServerEventArgs e)
{
// AP模式下无法扫描WiFi网络
string jsonResult = "{\"success\":false,\"message\":\"AP模式下不支持WiFi扫描,请手动输入WiFi名称\"}";
e.Context.Response.ContentType = "application/json";
WebServer.OutputAsStream(e.Context.Response, jsonResult);
}
// ========== 辅助方法 ==========
// 获取请求体
private string GetRequestBody(WebServerEventArgs e)
{
try
{
var request = e.Context.Request;
// 获取请求体长度
long contentLength = request.ContentLength64;
if (contentLength == 0)
{
return string.Empty;
}
// 读取请求体
byte[] buffer = new byte[(int)contentLength];
request.InputStream.Read(buffer, 0, (int)contentLength);
return Encoding.UTF8.GetString(buffer, 0, (int)contentLength);
}
catch (Exception)
{
return string.Empty;
}
}
// 解析表单字段
private static string ParseFormField(string body, string fieldName)
{
try
{
// 格式: ssid=MyWiFi&password=12345678
string searchPattern = fieldName + "=";
int startIndex = body.IndexOf(searchPattern);
if (startIndex < 0)
{
return string.Empty;
}
startIndex += searchPattern.Length;
int endIndex = body.IndexOf('&', startIndex);
if (endIndex < 0)
{
endIndex = body.Length;
}
string value = body.Substring(startIndex, endIndex - startIndex);
// URL解码
return UrlDecode(value);
}
catch
{
return string.Empty;
}
}
// URL解码
private static string UrlDecode(string value)
{
// 处理 %XX 格式的编码和 + 号
StringBuilder result = new StringBuilder();
for (int i = 0; i < value.Length; i++)
{
if (value[i] == '+')
{
// + 号转换为空格
result.Append(' ');
}
else if (value[i] == '%' && i + 2 < value.Length)
{
// 解析十六进制值
string hex = value.Substring(i + 1, 2);
byte b = HexToByte(hex);
if (b > 0)
{
result.Append((char)b);
i += 2;
}
else
{
result.Append(value[i]);
}
}
else
{
result.Append(value[i]);
}
}
return result.ToString();
}
// 十六进制字符串转字节
private static byte HexToByte(string hex)
{
try
{
byte high = HexCharToValue(hex[0]);
byte low = HexCharToValue(hex[1]);
return (byte)((high << 4) | low);
}
catch
{
return 0;
}
}
// 十六进制字符转数值
private static byte HexCharToValue(char c)
{
if (c >= '0' && c <= '9')
{
return (byte)(c - '0');
}
else if (c >= 'A' && c <= 'F')
{
return (byte)(c - 'A' + 10);
}
else if (c >= 'a' && c <= 'f')
{
return (byte)(c - 'a' + 10);
}
return 0;
}
// ========== HTML页面模板 ==========
// 配网主页HTML
private static string GetConfigPageHtml()
{
string html = "<!DOCTYPE html>";
html += "<html><head>";
html += "<meta charset=\"UTF-8\">";
html += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">";
html += "<title>YF3300-ESP32S3 WiFi配网</title>";
html += "<style>";
html += "body{font-family:Arial;margin:20px;background:#f0f0f0;}";
html += ".container{max-width:400px;margin:0 auto;background:white;padding:20px;border-radius:10px;}";
html += "h1{color:#333;text-align:center;}";
html += ".form-group{margin-bottom:15px;}";
html += "label{display:block;margin-bottom:5px;color:#666;}";
html += "input{width:100%;padding:10px;border:1px solid #ddd;border-radius:5px;box-sizing:border-box;}";
html += "button{width:100%;padding:12px;background:#007bff;color:white;border:none;border-radius:5px;font-size:16px;cursor:pointer;}";
html += ".footer{text-align:center;margin-top:20px;color:#999;font-size:12px;}";
html += ".tip{background:#fff3cd;border:1px solid #ffc107;padding:10px;border-radius:5px;margin-bottom:15px;font-size:14px;}";
html += "</style></head><body>";
html += "<div class=\"container\">";
html += "<h1>YF3300-ESP32S3 WiFi配网</h1>";
html += "<div class=\"tip\">请输入您要连接的WiFi名称和密码</div>";
html += "<form action=\"/config\" method=\"POST\">";
html += "<div class=\"form-group\">";
html += "<label>WiFi名称 (SSID)</label>";
html += "<input type=\"text\" name=\"ssid\" placeholder=\"请输入WiFi名称\" required>";
html += "</div>";
html += "<div class=\"form-group\">";
html += "<label>WiFi密码</label>";
html += "<input type=\"password\" name=\"password\" placeholder=\"请输入WiFi密码\" required>";
html += "</div>";
html += "<button type=\"submit\">开始配网</button>";
html += "</form>";
html += "<div class=\"footer\">YF3300-ESP32S3 v1.0</div>";
html += "</div></body></html>
Managers/WebServer.cs
张小明
前端开发工程师
Stable Diffusion WebUI 扩展管理:5 个高效技巧与 2 个目录结构解析
Stable Diffusion WebUI 扩展管理:5 个高效技巧与 2 个目录结构解析 对于深度使用 Stable Diffusion WebUI 的创作者来说,扩展管理是提升工作效率的关键环节。本文将带您深入探索 WebUI 扩展系统的底层逻辑,分享实用管理技巧,并解…
工业级MCU与智能高边开关的负载控制方案
1. 项目背景与核心需求在工业自动化控制系统中,精确控制电感和电阻负载是常见但极具挑战性的任务。TPD2017FN(智能高边开关)与PIC18F4610(工业级MCU)的组合方案,特别适合需要高可靠性、强抗干扰能力的工业场…
昇腾CANN 6.0.1 算子开发实战:TBE DSL vs TIK vs AICPU 3种方式性能对比
昇腾CANN 6.0.1算子开发实战:TBE DSL、TIK与AICPU深度性能对比在昇腾AI处理器的生态中,算子开发是模型性能优化的核心环节。面对TBE DSL、TBE TIK和AICPU三种开发方式,开发者常陷入选择困境:哪种方式能最大限度发挥硬件潜力&#…
DALL-E 3 API 集成实战:3步调用实现电商平台自动商品图生成
DALL-E 3 API 集成实战:3步调用实现电商平台自动商品图生成在电商行业,商品图的视觉吸引力直接影响转化率。传统拍摄流程需要摄影师、模特、场地和后期处理,成本高且周期长。而借助DALL-E 3的API能力,开发者可以构建自动化图像生成…
开源项目的自动化发版工具链:ChangeLog 生成与语义化版本的工程实践
开源项目的自动化发版工具链:ChangeLog 生成与语义化版本的工程实践 一、发版的负担:手工整理 Release Notes 为什么是一种工程浪费 开源项目的发布流程通常涉及:整理 commit log → 编写 ChangeLog → 确定版本号 → 打 tag → 创建 GitHu…
深度剖析RevokeMsgPatcher:Windows平台即时通讯防撤回的二进制修改技术解析
深度剖析RevokeMsgPatcher:Windows平台即时通讯防撤回的二进制修改技术解析 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了) 项目地址…