|
|
@ -1,5 +1,6 @@ |
|
|
|
using System.Collections.Immutable; |
|
|
|
using System.Text.RegularExpressions; |
|
|
|
using System.Threading; |
|
|
|
using Newtonsoft.Json; |
|
|
|
|
|
|
|
namespace LTEMvcApp.Models; |
|
|
@ -21,6 +22,13 @@ public class LTEClient |
|
|
|
/// </summary>
|
|
|
|
private const int LOGS_MAX = 2000000; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// BSR表 - 对应JavaScript中的_bsr_table
|
|
|
|
/// </summary>
|
|
|
|
private static readonly int[] BsrTable = { |
|
|
|
0, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132, 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4677, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304, 42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125, 150000, 500000 |
|
|
|
}; |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region 正则表达式
|
|
|
@ -768,47 +776,34 @@ public class LTEClient |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
var infoMatch = RegExpInfo1.Match(log.Message); |
|
|
|
if (infoMatch.Success) |
|
|
|
var rrcInfoMatch = RegExpInfo1.Match(log.Message); |
|
|
|
if (rrcInfoMatch.Success) |
|
|
|
{ |
|
|
|
if (!SetLogInfo(log, infoMatch.Groups[1].Value)) continue; |
|
|
|
log.Message = infoMatch.Groups[2].Value; |
|
|
|
if (!SetLogInfo(log, rrcInfoMatch.Groups[1].Value)) continue; |
|
|
|
log.Message = rrcInfoMatch.Groups[2].Value; |
|
|
|
ProcessRrcLog(log); |
|
|
|
} |
|
|
|
|
|
|
|
var bcMatch = RegExpRRC_BC.Match(log.Message); |
|
|
|
if (bcMatch.Success) |
|
|
|
var rrcBcMatch = RegExpRRC_BC.Match(log.Message); |
|
|
|
if (rrcBcMatch.Success) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
var data = log.GetDataString(); |
|
|
|
var jsonData = JsonConvert.DeserializeObject<object>(data); |
|
|
|
// 处理频段组合信息
|
|
|
|
// 这里需要调用getUECaps(log.ue_id).setBandComb(data, info[1].toLowerCase());
|
|
|
|
// 暂时注释掉,因为还没有实现getUECaps方法
|
|
|
|
// GetUECaps(log.UeId ?? 0).SetBandComb(jsonData, rrcBcMatch.Groups[1].Value.ToLower());
|
|
|
|
} |
|
|
|
catch |
|
|
|
catch (Exception e) |
|
|
|
{ |
|
|
|
// 忽略JSON解析错误
|
|
|
|
Console.WriteLine($"Band combination parsing error: {e.Message}"); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "NAS": |
|
|
|
ParseCellId(log, isWebSocket); |
|
|
|
var nasTmsiMatch = RegExpNAS_TMSI.Match(log.Message); |
|
|
|
if (nasTmsiMatch.Success) |
|
|
|
{ |
|
|
|
SetTmsi(log, nasTmsiMatch.Groups[1].Value); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
var nas5gTmsiMatch = RegExpNAS_5GTMSI.Match(log.Message); |
|
|
|
if (nas5gTmsiMatch.Success) |
|
|
|
{ |
|
|
|
SetTmsi(log, nas5gTmsiMatch.Groups[1].Value); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
var nasInfoMatch = RegExpInfo2.Match(log.Message); |
|
|
|
var nasInfoMatch = RegExpInfo1.Match(log.Message); |
|
|
|
if (nasInfoMatch.Success) |
|
|
|
{ |
|
|
|
if (!SetLogInfo(log, nasInfoMatch.Groups[1].Value)) continue; |
|
|
@ -817,11 +812,31 @@ public class LTEClient |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "MON": |
|
|
|
case "OTS": |
|
|
|
var monOtsInfoMatch = RegExpInfo1.Match(log.Message); |
|
|
|
if (monOtsInfoMatch.Success) |
|
|
|
{ |
|
|
|
if (!SetLogInfo(log, monOtsInfoMatch.Groups[1].Value)) continue; |
|
|
|
log.Message = monOtsInfoMatch.Groups[2].Value; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "MAC": |
|
|
|
ParseCellId(log, isWebSocket); |
|
|
|
ParseMacLog(log); |
|
|
|
break; |
|
|
|
|
|
|
|
case "RLC": |
|
|
|
case "PDCP": |
|
|
|
var rlcPdcpInfoMatch = RegExpInfo2.Match(log.Message); |
|
|
|
if (rlcPdcpInfoMatch.Success) |
|
|
|
{ |
|
|
|
if (!SetLogInfo(log, rlcPdcpInfoMatch.Groups[1].Value)) continue; |
|
|
|
log.Message = rlcPdcpInfoMatch.Groups[2].Value; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "IP": |
|
|
|
var ipMatch = RegExpIP.Match(log.Message); |
|
|
|
if (ipMatch.Success) |
|
|
@ -853,6 +868,15 @@ public class LTEClient |
|
|
|
var ranId = int.TryParse(s1ngMatch.Groups[2].Value, System.Globalization.NumberStyles.HexNumber, null, out var ran) ? ran : (int?)null; |
|
|
|
|
|
|
|
log.LinkIds = new LinkIds { Core = coreId, Ran = ranId }; |
|
|
|
// 根据模型类型决定 UeId 赋值
|
|
|
|
if ((Config.Model?.ToUpper() ?? "") == "MME") |
|
|
|
{ |
|
|
|
if (coreId.HasValue) log.UeId = coreId.Value; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
if (ranId.HasValue) log.UeId = ranId.Value; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
@ -861,11 +885,26 @@ public class LTEClient |
|
|
|
if (sipMatch.Success) |
|
|
|
{ |
|
|
|
if (!SetLogInfo(log, sipMatch.Groups[2].Value)) continue; |
|
|
|
log.Message = sipMatch.Groups[3].Value; |
|
|
|
log.Msg0 = log.Message; |
|
|
|
// 替换 ue_id 并调用 SetSameUe
|
|
|
|
var msg = sipMatch.Groups[3].Value; |
|
|
|
var ueIdMatch = System.Text.RegularExpressions.Regex.Match(msg, @" ue_id=(\d+)"); |
|
|
|
if (ueIdMatch.Success) |
|
|
|
{ |
|
|
|
if (int.TryParse(ueIdMatch.Groups[1].Value, out var ueId)) |
|
|
|
{ |
|
|
|
SetSameUe(log, ueId); |
|
|
|
} |
|
|
|
msg = System.Text.RegularExpressions.Regex.Replace(msg, @" ue_id=\d+", ""); |
|
|
|
} |
|
|
|
// 拼接 from/to 和 info[1]
|
|
|
|
var dirStr = log.Direction == 1 ? " from " : " to "; // 1=UL, 2=DL
|
|
|
|
log.Message = msg + dirStr + sipMatch.Groups[1].Value; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "MEDIA": |
|
|
|
case "RTP": |
|
|
|
var mediaMatch = RegExpMediaReq.Match(log.Message); |
|
|
|
if (mediaMatch.Success) |
|
|
|
{ |
|
|
@ -875,11 +914,60 @@ public class LTEClient |
|
|
|
break; |
|
|
|
|
|
|
|
case "IPsec": |
|
|
|
var ipsecMatch = RegExpIPsec.Match(log.Message); |
|
|
|
if (ipsecMatch.Success) |
|
|
|
var ipsecInfoMatch = RegExpInfo1.Match(log.Message); |
|
|
|
if (ipsecInfoMatch.Success) |
|
|
|
{ |
|
|
|
if (!SetLogInfo(log, ipsecInfoMatch.Groups[1].Value)) continue; |
|
|
|
log.Message = ipsecInfoMatch.Groups[2].Value; |
|
|
|
} |
|
|
|
var ipsecPacketMatch = RegExpIPsec.Match(log.Message); |
|
|
|
if (ipsecPacketMatch.Success) |
|
|
|
{ |
|
|
|
log.IpLen = int.Parse(ipsecPacketMatch.Groups[1].Value); |
|
|
|
HasData = true; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "SWU": |
|
|
|
case "NWU": |
|
|
|
var swuNwuInfoMatch = RegExpInfo1.Match(log.Message); |
|
|
|
if (swuNwuInfoMatch.Success) |
|
|
|
{ |
|
|
|
if (!SetLogInfo(log, swuNwuInfoMatch.Groups[1].Value)) continue; |
|
|
|
log.Message = swuNwuInfoMatch.Groups[2].Value; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "IMS": |
|
|
|
var imsInfoMatch = RegExpInfo1.Match(log.Message); |
|
|
|
if (imsInfoMatch.Success) |
|
|
|
{ |
|
|
|
if (!SetLogInfo(log, imsInfoMatch.Groups[1].Value)) continue; |
|
|
|
log.Message = imsInfoMatch.Groups[2].Value; |
|
|
|
|
|
|
|
var hints = ParseHints(log, new Dictionary<string, object> { { "rid", 0 }, { "aid", 0 } }); |
|
|
|
if (hints != null) |
|
|
|
{ |
|
|
|
if (hints.ContainsKey("rid") && hints["rid"] != null) |
|
|
|
{ |
|
|
|
SetSameUeId(log.UeId ?? 0, Convert.ToInt32(hints["rid"])); |
|
|
|
} |
|
|
|
if (hints.ContainsKey("aid") && hints["aid"] != null) |
|
|
|
{ |
|
|
|
SetSameUeId(log.UeId ?? 0, Convert.ToInt32(hints["aid"])); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case "EPDG": |
|
|
|
case "PROD": |
|
|
|
case "COM": |
|
|
|
var comInfoMatch = RegExpInfo1.Match(log.Message); |
|
|
|
if (comInfoMatch.Success) |
|
|
|
{ |
|
|
|
log.IpLen = int.Parse(ipsecMatch.Groups[1].Value); |
|
|
|
log.Message = ipsecMatch.Groups[2].Value; |
|
|
|
if (!SetLogInfo(log, comInfoMatch.Groups[1].Value)) continue; |
|
|
|
log.Message = comInfoMatch.Groups[2].Value; |
|
|
|
var hints = ParseHints(log); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
@ -1158,15 +1246,163 @@ public class LTEClient |
|
|
|
/// </summary>
|
|
|
|
private void ProcessNasLog(LTELog log) |
|
|
|
{ |
|
|
|
// NAS日志处理逻辑
|
|
|
|
// 根据消息类型处理不同的NAS消息
|
|
|
|
switch (log.Message.ToLower()) |
|
|
|
{ |
|
|
|
case "attach accept": |
|
|
|
var tmsiMatch = log.FindData(RegExpNAS_TMSI); |
|
|
|
if (tmsiMatch != null) |
|
|
|
{ |
|
|
|
SetTmsi(log, tmsiMatch.Groups[1].Value); |
|
|
|
} |
|
|
|
break; |
|
|
|
case "registration accept": |
|
|
|
var tmsi5gMatch = log.FindData(RegExpNAS_5GTMSI); |
|
|
|
if (tmsi5gMatch != null) |
|
|
|
{ |
|
|
|
SetTmsi(log, tmsi5gMatch.Groups[1].Value); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
// 解析提示信息
|
|
|
|
var hints = ParseHints(log, new Dictionary<string, object> |
|
|
|
{ |
|
|
|
{ "ran_ue_id", 0 }, |
|
|
|
{ "ran_address", "" } |
|
|
|
}); |
|
|
|
|
|
|
|
// 处理RAN ID
|
|
|
|
if (hints != null && hints.TryGetValue("ran_ue_id", out var ranUeIdObj)) |
|
|
|
{ |
|
|
|
var ranUeId = Convert.ToInt32(ranUeIdObj); |
|
|
|
if (ranUeId > 0) |
|
|
|
{ |
|
|
|
// 获取RAN ID
|
|
|
|
string? ranId = null; |
|
|
|
if (hints.TryGetValue("global_ran_node_id", out var globalRanNodeId)) |
|
|
|
{ |
|
|
|
ranId = globalRanNodeId.ToString(); |
|
|
|
} |
|
|
|
else if (hints.TryGetValue("global_enb_id", out var globalEnbId)) |
|
|
|
{ |
|
|
|
ranId = globalEnbId.ToString(); |
|
|
|
} |
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(ranId)) |
|
|
|
{ |
|
|
|
AddUERanID(log, ranUeId, ranId); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 解析MAC日志
|
|
|
|
/// 解析MAC日志 - 对应JavaScript中的_logParseMac方法
|
|
|
|
/// </summary>
|
|
|
|
private void ParseMacLog(LTELog log) |
|
|
|
{ |
|
|
|
// MAC日志解析逻辑
|
|
|
|
var type = ""; |
|
|
|
var args = log.Message.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); |
|
|
|
|
|
|
|
for (int m = 0; m < args.Length; m++) |
|
|
|
{ |
|
|
|
var param = args[m]; |
|
|
|
string? value = null; |
|
|
|
|
|
|
|
// 检查是否有等号分隔符
|
|
|
|
var equalIndex = param.IndexOf('='); |
|
|
|
if (equalIndex >= 0) |
|
|
|
{ |
|
|
|
value = param.Substring(equalIndex + 1); |
|
|
|
param = param.Substring(0, equalIndex); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// 检查是否有冒号分隔符
|
|
|
|
var colonIndex = param.IndexOf(':'); |
|
|
|
if (colonIndex >= 0) |
|
|
|
{ |
|
|
|
value = param.Substring(colonIndex + 1); |
|
|
|
param = param.Substring(0, colonIndex); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
switch (param.ToLower()) |
|
|
|
{ |
|
|
|
case "ph": |
|
|
|
if (value != null && int.TryParse(value, out var phr)) |
|
|
|
{ |
|
|
|
log.Phr = phr - 23; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "b": |
|
|
|
if (value != null && int.TryParse(value, out var bValue)) |
|
|
|
{ |
|
|
|
switch (type) |
|
|
|
{ |
|
|
|
case "SBSR": |
|
|
|
if (bValue >= 0 && bValue < BsrTable.Length) |
|
|
|
{ |
|
|
|
log.UlBufferSize = BsrTable[bValue]; |
|
|
|
} |
|
|
|
break; |
|
|
|
case "LBSR": |
|
|
|
if (bValue >= 0 && bValue < BsrTable.Length && |
|
|
|
m + 3 < args.Length) |
|
|
|
{ |
|
|
|
var b1 = int.TryParse(args[++m], out var b1Val) ? b1Val : 0; |
|
|
|
var b2 = int.TryParse(args[++m], out var b2Val) ? b2Val : 0; |
|
|
|
var b3 = int.TryParse(args[++m], out var b3Val) ? b3Val : 0; |
|
|
|
|
|
|
|
var total = 0; |
|
|
|
if (bValue < BsrTable.Length) total += BsrTable[bValue]; |
|
|
|
if (b1 < BsrTable.Length) total += BsrTable[b1]; |
|
|
|
if (b2 < BsrTable.Length) total += BsrTable[b2]; |
|
|
|
if (b3 < BsrTable.Length) total += BsrTable[b3]; |
|
|
|
|
|
|
|
log.UlBufferSize = total; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "len": |
|
|
|
if (value != null && int.TryParse(value, out var len)) |
|
|
|
{ |
|
|
|
switch (type) |
|
|
|
{ |
|
|
|
case "PAD": |
|
|
|
log.MacPad = (log.MacPad ?? 0) + len; |
|
|
|
break; |
|
|
|
case "LCID": |
|
|
|
log.MacLen = (log.MacLen ?? 0) + len; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case "lcid": |
|
|
|
type = param; |
|
|
|
break; |
|
|
|
|
|
|
|
case "ta": |
|
|
|
if (value != null && int.TryParse(value, out var ta)) |
|
|
|
{ |
|
|
|
log.Ta = ta - 31; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
if (value == "") |
|
|
|
{ |
|
|
|
type = param; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
@ -1201,6 +1437,147 @@ public class LTEClient |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 获取UE信息
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="ueId">UE ID</param>
|
|
|
|
/// <returns>UE信息</returns>
|
|
|
|
public UEInfo? GetUE(int ueId) |
|
|
|
{ |
|
|
|
return UeList.TryGetValue(ueId, out var ue) ? ue : null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 创建UE信息
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="ueId">UE ID</param>
|
|
|
|
/// <returns>UE信息</returns>
|
|
|
|
public UEInfo CreateUE(int ueId) |
|
|
|
{ |
|
|
|
if (!UeList.TryGetValue(ueId, out var ue)) |
|
|
|
{ |
|
|
|
ue = new UEInfo { UeId = ueId }; |
|
|
|
UeList[ueId] = ue; |
|
|
|
} |
|
|
|
return ue; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 根据参数获取UE
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="name">参数名</param>
|
|
|
|
/// <param name="value">参数值</param>
|
|
|
|
/// <returns>UE信息</returns>
|
|
|
|
public UEInfo? GetUEByParam(string name, object value) |
|
|
|
{ |
|
|
|
foreach (var ue in UeList.Values) |
|
|
|
{ |
|
|
|
var property = typeof(UEInfo).GetProperty(name); |
|
|
|
if (property?.GetValue(ue)?.Equals(value) == true) |
|
|
|
return ue; |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 获取UE能力信息
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="ueId">UE ID</param>
|
|
|
|
/// <returns>UE能力信息</returns>
|
|
|
|
public object GetUECaps(int ueId) |
|
|
|
{ |
|
|
|
var ue = CreateUE(ueId); |
|
|
|
if (ue.Caps == null) |
|
|
|
{ |
|
|
|
// 这里可以创建一个LTECaps对象
|
|
|
|
// ue.Caps = new LTECaps(ueId);
|
|
|
|
ue.Caps = new object(); // 临时实现
|
|
|
|
} |
|
|
|
return ue.Caps; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 添加UE RAN ID
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="log">日志</param>
|
|
|
|
/// <param name="ranUeId">RAN UE ID</param>
|
|
|
|
/// <param name="ranId">RAN ID</param>
|
|
|
|
private void AddUERanID(LTELog log, int ranUeId, string ranId) |
|
|
|
{ |
|
|
|
// 简化实现,实际可能需要更复杂的逻辑
|
|
|
|
var ue = CreateUE(log.UeId ?? 0); |
|
|
|
// 这里可以添加RAN ID相关的处理逻辑
|
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 解析提示信息
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="log">日志</param>
|
|
|
|
/// <param name="config">配置</param>
|
|
|
|
/// <returns>提示信息字典</returns>
|
|
|
|
private Dictionary<string, object>? ParseHints(LTELog log, Dictionary<string, object>? config = null) |
|
|
|
{ |
|
|
|
if (log.Info != ID_HINTS) return null; |
|
|
|
|
|
|
|
var hints = new Dictionary<string, object>(config ?? new Dictionary<string, object>()); |
|
|
|
|
|
|
|
// 解析消息中的参数
|
|
|
|
var args = log.Message.Split(' ', StringSplitOptions.RemoveEmptyEntries); |
|
|
|
foreach (var arg in args) |
|
|
|
{ |
|
|
|
var parts = arg.Split('='); |
|
|
|
if (parts.Length == 2) |
|
|
|
{ |
|
|
|
hints[parts[0]] = parts[1]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 处理IMEI/IMEISV
|
|
|
|
if (hints.TryGetValue("imei", out var imeiObj)) |
|
|
|
{ |
|
|
|
var imei = imeiObj.ToString(); |
|
|
|
var ue = GetUEByParam("Imei", imei); |
|
|
|
if (ue != null) |
|
|
|
{ |
|
|
|
SetSameUe(log, ue.UeId); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
ue = CreateUE(log.UeId ?? 0); |
|
|
|
ue.Imei = imei; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (hints.TryGetValue("imeisv", out var imeisvObj)) |
|
|
|
{ |
|
|
|
var imeisv = imeisvObj.ToString(); |
|
|
|
var imei = imeisv.Length > 2 ? imeisv[..^2] : imeisv; // 移除最后两个字符
|
|
|
|
var ue = GetUEByParam("Imei", imei); |
|
|
|
if (ue != null) |
|
|
|
{ |
|
|
|
SetSameUe(log, ue.UeId); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
ue = CreateUE(log.UeId ?? 0); |
|
|
|
ue.Imei = imei; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 处理IMSI
|
|
|
|
if (hints.TryGetValue("imsi", out var imsiObj)) |
|
|
|
{ |
|
|
|
var imsi = imsiObj.ToString(); |
|
|
|
var ue = GetUEByParam("Imsi", imsi); |
|
|
|
if (ue == null) |
|
|
|
{ |
|
|
|
ue = CreateUE(log.UeId ?? 0); |
|
|
|
ue.Imsi = imsi; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return hints; |
|
|
|
} |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region 私有辅助方法
|
|
|
@ -1527,6 +1904,46 @@ public class LTEClient |
|
|
|
}; |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 设置两个UE ID为同一UE(合并UE信息)
|
|
|
|
/// </summary>
|
|
|
|
private void SetSameUeId(int id0, int id1) |
|
|
|
{ |
|
|
|
if (id0 == id1) return; |
|
|
|
var ue0 = UeList.ContainsKey(id0) ? UeList[id0] : null; |
|
|
|
var ue1 = UeList.ContainsKey(id1) ? UeList[id1] : null; |
|
|
|
|
|
|
|
if (ue0 == ue1) |
|
|
|
{ |
|
|
|
if (ue1 == null) |
|
|
|
{ |
|
|
|
ue1 = CreateUE(id1); |
|
|
|
UeList[id0] = ue1; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (ue0 == null) |
|
|
|
{ |
|
|
|
UeList[id0] = ue1; |
|
|
|
} |
|
|
|
else if (ue1 == null) |
|
|
|
{ |
|
|
|
UeList[id1] = ue0; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// 合并所有指向id1的UE为ue0
|
|
|
|
var keysToUpdate = UeList.Where(kv => kv.Value == ue1).Select(kv => kv.Key).ToList(); |
|
|
|
foreach (var key in keysToUpdate) |
|
|
|
{ |
|
|
|
UeList[key] = ue0; |
|
|
|
} |
|
|
|
// 合并属性
|
|
|
|
if (string.IsNullOrEmpty(ue0.Imsi)) ue0.Imsi = ue1.Imsi; |
|
|
|
if (string.IsNullOrEmpty(ue0.Imei)) ue0.Imei = ue1.Imei; |
|
|
|
if (ue0.Caps == null) ue0.Caps = ue1.Caps; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|