diff --git a/LTEMvcApp/Models/LTEClient.cs b/LTEMvcApp/Models/LTEClient.cs index f46cc12..957de92 100644 --- a/LTEMvcApp/Models/LTEClient.cs +++ b/LTEMvcApp/Models/LTEClient.cs @@ -559,7 +559,7 @@ public class LTEClient /// 小区ID /// 小区配置 /// 小区对象 - private LTECell AddCell(int id, Dictionary config) + public LTECell AddCell(int id, Dictionary config) { var cell = new LTECell(id, config); diff --git a/LTEMvcApp/Services/LTEClientWebSocket.cs b/LTEMvcApp/Services/LTEClientWebSocket.cs index 2131035..2429199 100644 --- a/LTEMvcApp/Services/LTEClientWebSocket.cs +++ b/LTEMvcApp/Services/LTEClientWebSocket.cs @@ -39,6 +39,13 @@ namespace LTEMvcApp.Services private const int ServerMessageCacheLimit = 1000; private readonly ConcurrentQueue _sentMessages = new ConcurrentQueue(); private readonly ConcurrentQueue _receivedMessages = new ConcurrentQueue(); + + // 统计更新相关字段 + private int _statsPollDelay = 1000; // 默认1秒,对应JavaScript版本的_statsPolldelay + private bool _isFirstStatsUpdate = true; + + // 防止重复调用的标志 + private bool _isSocketReady = false; #endregion #region 事件 @@ -191,6 +198,7 @@ namespace LTEMvcApp.Services { SetState(ClientState.Stop); StopTimers(); + _isSocketReady = false; // 重置连接状态标志 } /// @@ -394,6 +402,31 @@ namespace LTEMvcApp.Services _logGetId = SendMessage(message, LogGetParse); } + /// + /// 手动触发统计更新 + /// + public void TriggerStatsUpdate() + { + UpdateStats(); + } + + /// + /// 重置统计信息 + /// + public void ResetStatistics() + { + ResetStats(); + } + + /// + /// 获取当前统计更新间隔 + /// + /// 统计更新间隔(毫秒) + public int GetStatsUpdateInterval() + { + return _statsPollDelay; + } + #endregion #region 私有方法 @@ -419,6 +452,9 @@ namespace LTEMvcApp.Services StopTimers(); CloseComponents(); + + // 重置连接状态标志 + _isSocketReady = false; if (State == ClientState.Connected) { @@ -504,7 +540,14 @@ namespace LTEMvcApp.Services /// private void OnSocketReady() { - if (_webSocket == null) return; + if (_webSocket == null || _isSocketReady) + { + _logger.LogDebug($"[{_config.Name}] OnSocketReady被跳过: WebSocket={_webSocket != null}, IsSocketReady={_isSocketReady}"); + return; // 防止重复调用 + } + + _logger.LogInformation($"[{_config.Name}] WebSocket准备就绪,开始初始化"); + _isSocketReady = true; // 设置标志 // 切换到正常的消息处理函数 _webSocket.MessageReceived -= OnSocketMessage0; @@ -516,9 +559,11 @@ namespace LTEMvcApp.Services var firstCon = _config.Logs.Layers.Count == 0; // 获取配置 + _logger.LogDebug($"[{_config.Name}] 发送config_get请求"); SendMessage(new JObject { ["message"] = "config_get" }, config => { Console.WriteLine("配置已接收"); + _logger.LogInformation($"[{_config.Name}] 配置已接收"); _client.ResetLogs(); @@ -552,6 +597,8 @@ namespace LTEMvcApp.Services foreach (var cell in cells) { // 添加小区配置 + + _client.AddCell(Convert.ToInt32(cell.Key), cells); } } } @@ -571,6 +618,9 @@ namespace LTEMvcApp.Services { SetLogsConfig(_config.Logs); } + + // 启动统计更新(对应JavaScript版本的_updateStats(true)) + UpdateStats(true); }); } @@ -693,58 +743,73 @@ namespace LTEMvcApp.Services { if (logItem is JObject logObj) { - //var logData = logObj.ToObject>() ?? new Dictionary(); - - // 创建LTELog对象 - var log = JsonConvert.DeserializeObject(logObj.ToString()); //new LTELog(logData); - - // 处理消息和数据 - if (log.Data is List dataList && dataList.Count > 0) + try { - log.Message = dataList[0]; - dataList.RemoveAt(0); - } + // 使用JsonConvert反序列化创建LTELog对象 + var log = JsonConvert.DeserializeObject(logObj.ToString()); + if (log == null) continue; - // 设置方向 - log.Direction = _client.DirConvert(log); + // 处理消息和数据 - 从data中提取第一条作为Message(与JavaScript版本保持一致) + if (log.Data is List dataList && dataList.Count > 0) + { + log.Message = dataList[0]; + dataList.RemoveAt(0); + } - // 处理信息字段 - if (log.Info != null) - { - log.Info = _client.StringToId(log.Info.ToString()); - } + // 设置方向(与JavaScript版本保持一致) + log.Direction = _client.DirConvert(log); - // 处理PHY层的信号记录 - if (log.Layer == "PHY" && log.Data is List data) - { - var signalRecord = new Dictionary(); - for (int j = data.Count - 1; j >= 0; j--) + // 处理信息字段(与JavaScript版本保持一致) + if (log.Info != null) { - var line = data[j]; - var match = Regex.Match(line, @"Link:\s([\w\d]+)@(\d+)"); - if (match.Success) - { - var linkName = match.Groups[1].Value; - var offset = uint.Parse(match.Groups[2].Value); - signalRecord[linkName] = new { offset = offset }; - data.RemoveAt(j); - } + log.Info = _client.StringToId(log.Info.ToString()); } - if (signalRecord.Count > 0) + // 处理PHY层的信号记录(与JavaScript版本保持一致) + if (log.Layer == "PHY" && log.Data is List data) { - //log.SignalRecord = signalRecord; - _client.HasSignalRecord = true; + var signalRecord = new Dictionary(); + for (int j = data.Count - 1; j >= 0; j--) + { + var line = data[j]; + var match = Regex.Match(line, @"Link:\s([\w\d]+)@(\d+)"); + if (match.Success) + { + var linkName = match.Groups[1].Value; + var offset = uint.Parse(match.Groups[2].Value); + signalRecord[linkName] = new { offset = offset }; + data.RemoveAt(j); + } + } + + if (signalRecord.Count > 0) + { + log.SignalRecord = signalRecord; // 修复:正确设置信号记录 + _client.HasSignalRecord = true; + } } - } - log.Client = _client; - logList.Add(log); + log.Client = _client; + logList.Add(log); + } + catch (Exception ex) + { + _logger.LogError(ex, $"[{_config.Name}] 解析日志项时出错: {ex.Message}"); + // 继续处理下一个日志项,不中断整个流程 + } } } - _client.ParseLogList(logList, true); - //_client.ParseLogList(logList, true); - LogsReceived?.Invoke(this, logList); + + // 调用日志解析(与JavaScript版本保持一致) + if (logList.Count > 0) + { + _client.ParseLogList(logList, true); + + // 更新日志管理器(对应JavaScript版本的lteLogs.updateLogs()) + _client.LogsManager.UpdateLogs(); + + LogsReceived?.Invoke(this, logList); + } } } @@ -811,8 +876,8 @@ namespace LTEMvcApp.Services _reconnectTimer?.Dispose(); _reconnectTimer = null; - _statsTimer?.Dispose(); - _statsTimer = null; + StopStatsTimer(); // 使用专门的统计定时器停止方法 + ResetStats(); // 重置统计信息 _messageDeferTimer?.Dispose(); _messageDeferTimer = null; @@ -886,6 +951,129 @@ namespace LTEMvcApp.Services Console.WriteLine("需要认证,请输入密码"); } + #region 统计更新相关方法 + + /// + /// 设置刷新延迟时间 + /// + /// 延迟时间(毫秒) + public void SetRefreshDelay(int delay) + { + _statsPollDelay = delay; + } + + /// + /// 获取刷新延迟时间 + /// + /// 延迟时间(毫秒) + public int GetRefreshDelay() + { + return _statsPollDelay; + } + + /// + /// 更新统计信息(对应JavaScript版本的_updateStats) + /// + /// 是否为第一次更新 + private void UpdateStats(bool first = false) + { + if (_disposed || _webSocket?.State != WebSocketState.Open) return; + + var msg = new JObject { ["message"] = "stats" }; + + // 准备统计消息(对应JavaScript版本的tab.statsPrepare) + PrepareStatsMessage(msg); + + SendMessage(msg, response => + { + if (_disposed) return; + + // 第一次调用会重置统计 + if (first || _isFirstStatsUpdate) + { + ResetStats(); + _isFirstStatsUpdate = false; + + // 第一次调用后启动定时器循环 + StartStatsTimer(); + return; + } + + // 发送统计事件(对应JavaScript版本的sendEvent) + StatsReceived?.Invoke(this, response); + + // 添加统计到统计面板(对应JavaScript版本的lteStatsTab.add) + AddStatsToPanel(response); + + // 设置下一次统计更新(对应JavaScript版本的定时器循环) + StartStatsTimer(); + }); + } + + /// + /// 准备统计消息 + /// + /// 统计消息 + private void PrepareStatsMessage(JObject msg) + { + // 这里可以添加统计消息的准备工作 + // 对应JavaScript版本中的tab.statsPrepare(msg) + _logger.LogDebug($"[{_config.Name}] 准备统计消息: {msg}"); + } + + /// + /// 重置统计信息(对应JavaScript版本的_resetStats) + /// + private void ResetStats() + { + // 重置统计信息,对应JavaScript版本的lteStatsTab.add(this.getName(), {cpu: {global: 0}}) + var resetStats = new JObject + { + ["cpu"] = new JObject { ["global"] = 0 } + }; + + AddStatsToPanel(resetStats); + _logger.LogDebug($"[{_config.Name}] 重置统计信息"); + } + + /// + /// 添加统计到面板 + /// + /// 统计信息 + private void AddStatsToPanel(JObject stats) + { + // 这里应该将统计信息添加到统计面板 + // 对应JavaScript版本中的lteStatsTab.add(this.getName(), resp) + _logger.LogDebug($"[{_config.Name}] 添加统计到面板: {stats}"); + + // 可以在这里实现具体的统计面板更新逻辑 + // 或者通过事件通知其他组件更新统计信息 + } + + /// + /// 启动统计更新定时器 + /// + private void StartStatsTimer() + { + if (_statsTimer != null) + { + _statsTimer.Dispose(); + } + + _statsTimer = new Timer(_ => UpdateStats(), null, _statsPollDelay, Timeout.Infinite); + } + + /// + /// 停止统计更新定时器 + /// + private void StopStatsTimer() + { + _statsTimer?.Dispose(); + _statsTimer = null; + } + + #endregion + #endregion #region IDisposable