news 2026/7/8 23:17:55

Managers/WebServer.cs

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 (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>

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/8 23:11:19

Stable Diffusion WebUI 扩展管理:5 个高效技巧与 2 个目录结构解析

Stable Diffusion WebUI 扩展管理&#xff1a;5 个高效技巧与 2 个目录结构解析 对于深度使用 Stable Diffusion WebUI 的创作者来说&#xff0c;扩展管理是提升工作效率的关键环节。本文将带您深入探索 WebUI 扩展系统的底层逻辑&#xff0c;分享实用管理技巧&#xff0c;并解…

作者头像 李华
网站建设 2026/7/8 23:10:41

工业级MCU与智能高边开关的负载控制方案

1. 项目背景与核心需求在工业自动化控制系统中&#xff0c;精确控制电感和电阻负载是常见但极具挑战性的任务。TPD2017FN&#xff08;智能高边开关&#xff09;与PIC18F4610&#xff08;工业级MCU&#xff09;的组合方案&#xff0c;特别适合需要高可靠性、强抗干扰能力的工业场…

作者头像 李华
网站建设 2026/7/8 23:09:30

昇腾CANN 6.0.1 算子开发实战:TBE DSL vs TIK vs AICPU 3种方式性能对比

昇腾CANN 6.0.1算子开发实战&#xff1a;TBE DSL、TIK与AICPU深度性能对比在昇腾AI处理器的生态中&#xff0c;算子开发是模型性能优化的核心环节。面对TBE DSL、TBE TIK和AICPU三种开发方式&#xff0c;开发者常陷入选择困境&#xff1a;哪种方式能最大限度发挥硬件潜力&#…

作者头像 李华
网站建设 2026/7/8 23:08:40

DALL-E 3 API 集成实战:3步调用实现电商平台自动商品图生成

DALL-E 3 API 集成实战&#xff1a;3步调用实现电商平台自动商品图生成在电商行业&#xff0c;商品图的视觉吸引力直接影响转化率。传统拍摄流程需要摄影师、模特、场地和后期处理&#xff0c;成本高且周期长。而借助DALL-E 3的API能力&#xff0c;开发者可以构建自动化图像生成…

作者头像 李华