You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
422 lines
8.8 KiB
422 lines
8.8 KiB
using System.Collections.Immutable;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace LTEMvcApp.Models;
|
|
|
|
/// <summary>
|
|
/// LTE客户端类 - 对应JavaScript中的lte.client对象
|
|
/// </summary>
|
|
public class LTEClient
|
|
{
|
|
#region 基础属性
|
|
|
|
/// <summary>
|
|
/// 客户端ID
|
|
/// </summary>
|
|
public int ClientId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 客户端名称
|
|
/// </summary>
|
|
public string Name { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 客户端配置
|
|
/// </summary>
|
|
public ClientConfig Config { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// 客户端状态
|
|
/// </summary>
|
|
public ClientState State { get; set; } = ClientState.Stop;
|
|
|
|
/// <summary>
|
|
/// 版本信息
|
|
/// </summary>
|
|
public string? Version { get; set; }
|
|
|
|
/// <summary>
|
|
/// 许可证信息
|
|
/// </summary>
|
|
public string? License { get; set; }
|
|
|
|
/// <summary>
|
|
/// 模型类型
|
|
/// </summary>
|
|
public string? Model { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region 日志相关属性
|
|
|
|
/// <summary>
|
|
/// 日志列表
|
|
/// </summary>
|
|
public List<LTELog> Logs { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// 日志数量
|
|
/// </summary>
|
|
public int LogCount => Logs.Count;
|
|
|
|
/// <summary>
|
|
/// 是否已过滤
|
|
/// </summary>
|
|
public bool Filtered { get; set; }
|
|
|
|
/// <summary>
|
|
/// 重置标志
|
|
/// </summary>
|
|
public bool ResetFlag { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region 解析器状态
|
|
|
|
/// <summary>
|
|
/// 最后HARQ信息
|
|
/// </summary>
|
|
public Dictionary<int, Dictionary<int, LTELog>> LastHarq { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// 最后NB HARQ信息
|
|
/// </summary>
|
|
public Dictionary<int, Dictionary<int, List<LTELog>>> LastNbHarq { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// 帧信息
|
|
/// </summary>
|
|
public FrameInfo Frame { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// TMSI到UE ID的映射
|
|
/// </summary>
|
|
public Dictionary<int, int> TmsiToUeId { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// RNTI到UE ID的映射
|
|
/// </summary>
|
|
public Dictionary<int, int> RntiToUeId { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// UE列表
|
|
/// </summary>
|
|
public Dictionary<int, UEInfo> UeList { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// 最后时间戳
|
|
/// </summary>
|
|
public long LastTimestamp { get; set; }
|
|
|
|
/// <summary>
|
|
/// 时间戳偏移
|
|
/// </summary>
|
|
public long TimestampOffset { get; set; }
|
|
|
|
/// <summary>
|
|
/// 最后小区
|
|
/// </summary>
|
|
public int? LastCell { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region 功能标志
|
|
|
|
/// <summary>
|
|
/// 是否有小区信息
|
|
/// </summary>
|
|
public bool HasCell { get; set; }
|
|
|
|
/// <summary>
|
|
/// 是否有物理层信息
|
|
/// </summary>
|
|
public bool HasPhy { get; set; }
|
|
|
|
/// <summary>
|
|
/// 是否有数据
|
|
/// </summary>
|
|
public bool HasData { get; set; }
|
|
|
|
/// <summary>
|
|
/// 是否有RNTI
|
|
/// </summary>
|
|
public bool HasRnti { get; set; }
|
|
|
|
/// <summary>
|
|
/// 是否有资源块
|
|
/// </summary>
|
|
public bool HasRb { get; set; }
|
|
|
|
/// <summary>
|
|
/// 是否有信号记录
|
|
/// </summary>
|
|
public bool HasSignalRecord { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region 参数和组件
|
|
|
|
/// <summary>
|
|
/// 参数信息
|
|
/// </summary>
|
|
public Dictionary<string, object> Parameters { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// 组件列表
|
|
/// </summary>
|
|
public Dictionary<string, object> Components { get; set; } = new();
|
|
|
|
#endregion
|
|
|
|
#region 构造函数
|
|
|
|
public LTEClient(ClientConfig config)
|
|
{
|
|
Config = config;
|
|
Name = config.Name;
|
|
ClientId = GenerateClientId();
|
|
ResetParserState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 使用名称创建客户端
|
|
/// </summary>
|
|
/// <param name="name">客户端名称</param>
|
|
public LTEClient(string name)
|
|
{
|
|
Config = new ClientConfig { Name = name, Enabled = true };
|
|
Name = name;
|
|
ClientId = GenerateClientId();
|
|
ResetParserState();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 公共方法
|
|
|
|
/// <summary>
|
|
/// 启动客户端
|
|
/// </summary>
|
|
public void Start()
|
|
{
|
|
SetState(ClientState.Start);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止客户端
|
|
/// </summary>
|
|
public void Stop()
|
|
{
|
|
SetState(ClientState.Stop);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 销毁客户端
|
|
/// </summary>
|
|
public void Destroy()
|
|
{
|
|
SetState(ClientState.Destroy);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 重置日志
|
|
/// </summary>
|
|
public void ResetLogs()
|
|
{
|
|
if (LogCount > 0)
|
|
{
|
|
ResetFlag = true;
|
|
Logs.Clear();
|
|
ResetParserState();
|
|
HasCell = false;
|
|
HasPhy = false;
|
|
HasData = false;
|
|
HasRnti = false;
|
|
HasRb = false;
|
|
HasSignalRecord = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加日志
|
|
/// </summary>
|
|
public void AddLog(LTELog log)
|
|
{
|
|
// 检查时间戳回绕
|
|
var timestamp = log.Timestamp + TimestampOffset;
|
|
if (timestamp < LastTimestamp - 100)
|
|
{
|
|
Console.WriteLine($"Log wrap by {LastTimestamp - timestamp}");
|
|
timestamp += 86400000; // 24小时
|
|
TimestampOffset += 86400000;
|
|
}
|
|
LastTimestamp = log.Timestamp = timestamp;
|
|
|
|
log.Client = this;
|
|
log.Id = GenerateLogId();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置头信息
|
|
/// </summary>
|
|
public void SetHeaders(string[] headers)
|
|
{
|
|
// 实现头信息设置逻辑
|
|
}
|
|
|
|
/// <summary>
|
|
/// 初始化模型猜测
|
|
/// </summary>
|
|
public void LogModelGuessInit()
|
|
{
|
|
// 实现模型猜测初始化逻辑
|
|
}
|
|
|
|
/// <summary>
|
|
/// 模型猜测
|
|
/// </summary>
|
|
public void LogModelGuess(List<Dictionary<string, object>> logs)
|
|
{
|
|
// 实现模型猜测逻辑
|
|
}
|
|
|
|
/// <summary>
|
|
/// 方向转换
|
|
/// </summary>
|
|
public int DirConvert(LTELog log)
|
|
{
|
|
// 实现方向转换逻辑
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 字符串转ID
|
|
/// </summary>
|
|
public int StringToId(string str)
|
|
{
|
|
// 实现字符串转ID逻辑
|
|
return 0;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 私有方法
|
|
|
|
/// <summary>
|
|
/// 设置状态
|
|
/// </summary>
|
|
private void SetState(ClientState state)
|
|
{
|
|
if (State != state)
|
|
{
|
|
State = state;
|
|
switch (state)
|
|
{
|
|
case ClientState.Stop:
|
|
ResetLogs();
|
|
break;
|
|
case ClientState.Start:
|
|
case ClientState.Connected:
|
|
break;
|
|
case ClientState.Destroy:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 重置解析器状态
|
|
/// </summary>
|
|
private void ResetParserState()
|
|
{
|
|
LastHarq.Clear();
|
|
LastNbHarq.Clear();
|
|
Frame = new FrameInfo();
|
|
TmsiToUeId.Clear();
|
|
RntiToUeId.Clear();
|
|
UeList.Clear();
|
|
LastTimestamp = 0;
|
|
TimestampOffset = 0;
|
|
LastCell = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成客户端ID
|
|
/// </summary>
|
|
private static int GenerateClientId()
|
|
{
|
|
return Interlocked.Increment(ref _clientIdCounter);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成日志ID
|
|
/// </summary>
|
|
private static int GenerateLogId()
|
|
{
|
|
return Interlocked.Increment(ref _logIdCounter);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 静态字段
|
|
|
|
private static int _clientIdCounter = 0;
|
|
private static int _logIdCounter = 0;
|
|
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// 客户端配置
|
|
/// </summary>
|
|
public class ClientConfig
|
|
{
|
|
public string Name { get; set; } = string.Empty;
|
|
public bool Enabled { get; set; } = true;
|
|
public string? Model { get; set; }
|
|
public string? Address { get; set; }
|
|
public bool Ssl { get; set; }
|
|
public int ReconnectDelay { get; set; } = 15000;
|
|
public bool Pause { get; set; }
|
|
public bool Readonly { get; set; }
|
|
public bool SkipLogMenu { get; set; }
|
|
public bool Locked { get; set; }
|
|
public bool Active { get; set; }
|
|
public string? Password { get; set; }
|
|
public Dictionary<string, object> Logs { get; set; } = new();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 客户端状态
|
|
/// </summary>
|
|
public enum ClientState
|
|
{
|
|
Stop,
|
|
Start,
|
|
Loading,
|
|
Connecting,
|
|
Connected,
|
|
Error,
|
|
Destroy
|
|
}
|
|
|
|
/// <summary>
|
|
/// 帧信息
|
|
/// </summary>
|
|
public class FrameInfo
|
|
{
|
|
public int Last { get; set; }
|
|
public int Hfn { get; set; }
|
|
public long Timestamp { get; set; } = -1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// UE信息
|
|
/// </summary>
|
|
public class UEInfo
|
|
{
|
|
public int UeId { get; set; }
|
|
public string? Imsi { get; set; }
|
|
public string? Imei { get; set; }
|
|
public object? Caps { get; set; }
|
|
}
|