Managers/WebServer.cs

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 (valuei == '+')

{

// + 号转换为空格

result.Append(' ');

}

else if (valuei == '%' && 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(valuei);

}

}

else

{

result.Append(valuei);

}

}

return result.ToString();

}

// 十六进制字符串转字节

private static byte HexToByte(string hex)

{

try

{

byte high = HexCharToValue(hex0);

byte low = HexCharToValue(hex1);

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>

相关推荐
LL34363818 小时前
撰写周报、整理会议纪要、制作PPT适配的各类办公效率工具分析
powerpoint
沉默的云朵2 天前
NET平台下不借助Office实现Word、Powerpoint等文件的解析(一)
word·powerpoint
神奇的代码在哪里2 天前
AI编程时代,PPT已成为过去,单个HTML文件创造无限可能
javascript·html·powerpoint·ai编程·ppt
开开心心_Every4 天前
带OCR识别的电子发票打印工具
运维·自动化·ocr·电脑·powerpoint·音视频·lua
绎奇PPT4 天前
青拔申报全套服务丨文案逻辑梳理+高端PPT设计
信息可视化·powerpoint·ppt
Ar-Sr-Na5 天前
工作路演PPT处理,交给Workbuddy
人工智能·powerpoint·workbuddy开发者分享季
RZhLyRaHv5 天前
LangChain教程-4、构建简易智能 PPT 生成器
人工智能·langchain·powerpoint
SpaceAIGlobal22 天前
AI 生成 PPT 工具深度评测与选型指南
人工智能·powerpoint
一头爱吃肉的牛22 天前
2026年10款AI PPT工具横向评测:内容准确性、生成速度、模板丰富度对比
人工智能·powerpoint