
using Microsoft.Extensions.Logging;using nanoFramework.Logging;using nanoFramework.WebServer;using System;using System.Net;using System.Threading;namespace YeFanIoTTest.Managers{// AP配网状态枚举public enum APConfigState{Idle, // 空闲APConfiguring, // 正在配网Connecting, // 正在连接Configured, // 配网成功Failed // 配网失败}// 配网完成事件参数public class APConfigResultEventArgs : EventArgs{public bool Success { get; set; }public string SSID { get; set; }public string Message { get; set; }}internal class APConfigManager{// 日志记录器private ILogger _logger;// WIFI管理器外部注入不内部创建private WifiManager _wifiManager;// Web服务器实例private WebServer _webServer;// 当前配网状态public APConfigState CurrentState { get; private set; } APConfigState.Idle;// 配网完成事件通知外部配网结果public event APConfigResultEventHandler OnConfigCompleted;public delegate void APConfigResultEventHandler(object sender, APConfigResultEventArgs e);// AP配网参数private const string AP_SSID YF3300_ESP32S3; // 热点名称private const string AP_PASSWORD yf123456; // 热点密码WPA2需8private const string AP_IP 192.168.4.1; // AP网关IP// Web服务器参数private const int WEB_PORT 80; // Web服务器端口private const int CONFIG_TIMEOUT 600000; // 配网超时时间10分钟// 配网任务取消令牌private CancellationTokenSource _configCts;// 配网超时定时器private Timer _timeoutTimer;// 当前配网的SSID和密码用于传递给WebServerControllerpublic static string PendingSSID { get; set; }public static string PendingPassword { get; set; }public static bool ConfigSubmitted { get; set; } false;// WifiManager实例供WebServerController访问private static WifiManager _staticWifiManager;// 获取WifiManager实例public static WifiManager GetWifiManager(){return _staticWifiManager;}// 触发配网完成事件由外部调用public void RaiseConfigCompleted(bool success, string ssid, string message){if (OnConfigCompleted ! null){OnConfigCompleted(this, new APConfigResultEventArgs(){Success success,SSID ssid,Message message});}}// 构造函数注入WIFI管理器实例public APConfigManager(WifiManager wifiManager){if (wifiManager null){throw new ArgumentNullException(nameof(wifiManager));}_wifiManager wifiManager;_staticWifiManager wifiManager; // 保存到静态字段_logger LogDispatcher.LoggerFactory.CreateLogger(APConfigManager);}#region 公共API// 检查是否已有保存的WIFI配置public bool HasSavedWifiConfig(){return _wifiManager.HasSavedConfig();}// 尝试使用已保存的配置连接WIFIpublic bool TryConnectSavedWifiConfig(){if (_wifiManager.LoadCredentials(out string ssid, out string password)){_logger.LogInformation($[APConfigManager] 尝试使用已保存的WIFI配置进行连接: {ssid});return _wifiManager.ConnectSTA(ssid, password, enableReconnect: true);}return false;}// 开始配网public bool StartAPConfig(){if (CurrentState ! APConfigState.Idle){_logger.LogWarning([APConfigManager] 当前AP状态不是空闲状态无法开始配网);return false;}_logger.LogInformation([APConfigManager] 开始配网);// 步骤一启动AP热点bool apStarted _wifiManager.StartAP(AP_SSID, AP_PASSWORD, AP_IP);if (!apStarted){_logger.LogError([APConfigManager] 启动AP热点失败);CurrentState APConfigState.Failed;return false;}CurrentState APConfigState.APConfiguring;_logger.LogInformation($[APConfigManager] AP热点已启动热点名称{AP_SSID}, IP{AP_IP});// 步骤二启动Web服务器// 【重要】等待网络接口完全初始化后再启动Web服务器Thread.Sleep(1000);try{// 重置配网提交标志ConfigSubmitted false;// 创建Web服务器实例// 【重要】在AP模式下必须显式指定绑定的IP地址否则会绑定到错误的网络接口_webServer new WebServer(WEB_PORT, HttpProtocol.Http, IPAddress.Parse(AP_IP), new Type[] { typeof(WebServerController) });_webServer.Start();_logger.LogInformation($[APConfigManager] Web服务器已启动端口{WEB_PORT}绑定IP{AP_IP});// 诊断信息验证网络接口状态 try{var interfaces System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();foreach (var ni in interfaces){if (ni.NetworkInterfaceType System.Net.NetworkInformation.NetworkInterfaceType.WirelessAP){_logger.LogInformation($[APConfigManager] AP接口状态: {ni.IPv4Address});_logger.LogInformation($[APConfigManager] AP接口类型: {ni.NetworkInterfaceType});}}}catch (Exception ex){_logger.LogWarning($[APConfigManager] 获取网络接口信息失败: {ex.Message});}}catch (Exception e){_logger.LogError($[APConfigManager] 启动Web服务器失败: {e.Message});StopAPConfig();return false;}// 步骤三启动配网超时定时器_configCts new CancellationTokenSource();_timeoutTimer new Timer(OnTimeoutCallback, null, CONFIG_TIMEOUT, Timeout.Infinite);_logger.LogInformation($[APConfigManager] 请连接WIFI {AP_SSID}并访问 http://{AP_IP});_logger.LogInformation($[APConfigManager] 配网超时定时器已启动超时时间{CONFIG_TIMEOUT / 1000} 秒);return true;}// 停止AP配网清理资源public void StopAPConfig(){_logger.LogInformation([APConfigManager] 停止AP配网);// 停止超时定时器if (_timeoutTimer ! null){_timeoutTimer.Dispose();_timeoutTimer null;}// 取消配网任务if (_configCts ! null){_configCts.Cancel();_configCts.Dispose();_configCts null;}// 关闭Web服务器if (_webServer ! null){_webServer.Stop();_webServer.Dispose();_webServer null;}// 关闭AP热点_wifiManager.StopAP();CurrentState APConfigState.Idle;_logger.LogInformation([APConfigManager] AP配网已停止);}// 处理配网提交由WebServerController调用public void HandleConfigSubmit(string ssid, string password){_logger.LogInformation($[APConfigManager] 收到配网请求{ssid});// 停止超时定时器if (_timeoutTimer ! null){_timeoutTimer.Change(Timeout.Infinite, Timeout.Infinite);}// 停止Web服务器if (_webServer ! null){_webServer.Stop();}CurrentState APConfigState.Connecting;// 尝试连接WIFIbool connected _wifiManager.ConnectSTA(ssid, password, enableReconnect: true);if (connected){// 验证网络可达性 // 检查WiFi是否真的可以上网通过DNS解析验证_logger.LogInformation([APConfigManager] 正在验证网络可达性...);bool networkReachable _wifiManager.IsNetworkReachable();if (!networkReachable){_logger.LogWarning([APConfigManager] WiFi已连接但网络不可达请检查路由器是否连接外网);// 仍然保存凭证但提示用户网络可能不可用}else{_logger.LogInformation([APConfigManager] 网络可达性验证成功可以正常上网);}// 保存WIFI凭证到Flash // 【测试时可注释以下2行关闭持久化存储功能】// _wifiManager.SaveCredentials(ssid, password);_logger.LogInformation($[APConfigManager] 已保存WIFI凭证{ssid});CurrentState APConfigState.Configured;_logger.LogInformation($[APConfigManager] 配网成功SSID{ssid});// 触发配网完成事件if (OnConfigCompleted ! null){OnConfigCompleted(this, new APConfigResultEventArgs(){Success true,SSID ssid,Message networkReachable ? 配网成功网络可达 : 配网成功但网络不可达请检查路由器});}}else{CurrentState APConfigState.Failed;_logger.LogError($[APConfigManager] 配网失败SSID{ssid});// 触发配网失败事件if (OnConfigCompleted ! null){OnConfigCompleted(this, new APConfigResultEventArgs(){Success false,SSID ssid,Message 配网失败});}// 重新启动AP配网Thread.Sleep(2000);CurrentState APConfigState.Idle;StartAPConfig();}}#endregion#region 私有方法// 超时回调private void OnTimeoutCallback(object state){_logger.LogWarning([APConfigManager] 配网超时);// 触发配网超时事件if (OnConfigCompleted ! null){OnConfigCompleted(this, new APConfigResultEventArgs(){Success false,SSID null,Message 配网超时});}// 停止AP配网StopAPConfig();}#endregion}}