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.
 
 
 

441 lines
17 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
namespace LTEMvcApp.Models
{
/// <summary>
/// LTE能力解析器
/// </summary>
public class LTECapabilities
{
public string UEId { get; set; }
public List<BandInfo> Bands { get; set; } = new List<BandInfo>();
public int? Category { get; set; }
public int? CategoryDL { get; set; }
public int? CategoryUL { get; set; }
public List<Dictionary<string, object>> ASN1Data { get; set; } = new List<Dictionary<string, object>>();
public Dictionary<string, object> BandCombinations { get; set; } = new Dictionary<string, object>();
public List<List<BandCombinationInfo>> CA { get; set; }
public List<BandInfo> NRBands { get; set; }
public string VoNR { get; set; }
public List<List<BandCombinationInfo>> MRDC { get; set; }
private List<string[]> _pendingData = new List<string[]>();
private int _count = 0;
public static readonly Dictionary<string, int> UE_CAPS_MIMO = new Dictionary<string, int>
{
["twoLayers"] = 2,
["fourLayers"] = 4,
["eightLayers"] = 8
};
/// <summary>
/// 获取类别信息
/// </summary>
public string GetCategory()
{
var cat = new List<string>();
if (CategoryDL.HasValue)
cat.Add($"DL={CategoryDL}");
if (CategoryUL.HasValue)
cat.Add($"UL={CategoryUL}");
if (cat.Count > 0)
return string.Join(", ", cat);
if (Category.HasValue)
return Category.ToString();
return "?";
}
/// <summary>
/// 添加待解析数据
/// </summary>
public void Add(string[] data)
{
if (data != null && data.Length > 0)
{
_pendingData.Add(data);
}
}
/// <summary>
/// 解析所有待处理数据
/// </summary>
public LTECapabilities Parse()
{
while (_pendingData.Count > 0)
{
_count++;
ParseASN1(ASN1Parser.FromGSER(_pendingData[0]));
_pendingData.RemoveAt(0);
}
return _count > 0 ? this : null;
}
/// <summary>
/// 解析ASN1数据
/// </summary>
private void ParseASN1(Dictionary<string, object> asn1)
{
if (asn1 == null) return;
ASN1Data.Add(asn1);
var ratList = ASN1Parser.Dig(asn1, "ueCapabilityInformation", "ueCapabilityInformation-r8", "ue-CapabilityRAT-ContainerList") as List<object> ?? new List<object>();
var ratList1 = ASN1Parser.Dig(asn1, "ueCapabilityInformation", "ueCapabilityInformation", "ue-CapabilityRAT-ContainerList") as List<object>;
if (ratList1 != null)
{
ratList.AddRange(ratList1);
}
foreach (var rat in ratList)
{
if (rat is Dictionary<string, object> ratDict)
{
var ratType = ratDict.GetValueOrDefault("rat-Type")?.ToString();
var container = ratDict.GetValueOrDefault("ueCapabilityRAT-Container") ?? ratDict.GetValueOrDefault("ue-CapabilityRAT-Container");
switch (ratType)
{
case "eutra":
ParseRatEUTRA(container as Dictionary<string, object>);
break;
case "nr":
ParseRatNR(container as Dictionary<string, object>);
break;
case "eutra-nr":
ParseRatEUTRA_NR(container as Dictionary<string, object>);
break;
}
}
}
if (Category == null)
{
ParseR13(asn1);
}
}
/// <summary>
/// 解析R13版本
/// </summary>
private void ParseR13(Dictionary<string, object> asn1)
{
var root = ASN1Parser.Dig(asn1, "ueCapabilityInformation-r13", "ueCapabilityInformation-r13", "ue-Capability-Container-r13") as Dictionary<string, object>;
if (root != null)
{
// Category
if (root.ContainsKey("ue-Category-NB-r13"))
{
Category = Convert.ToInt32(root["ue-Category-NB-r13"]);
}
var bands = ASN1Parser.Dig(root, "rf-Parameters-r13", "supportedBandList-r13") as List<object>;
if (bands != null)
{
var mappedBands = ASN1Parser.Map<BandInfo>(bands, b =>
{
if (b is Dictionary<string, object> bandDict)
{
return new BandInfo { Band = Convert.ToInt32(bandDict["band-r13"]) };
}
return new BandInfo();
});
if (mappedBands != null && mappedBands.Count > 0)
{
//Bands = mappedBands.Cast<BandInfo>().ToList();
}
}
}
}
/// <summary>
/// 解析EUTRA RAT
/// </summary>
private void ParseRatEUTRA(Dictionary<string, object> asn1)
{
if (asn1 == null) return;
if (asn1.ContainsKey("ue-Category"))
{
Category = Convert.ToInt32(asn1["ue-Category"]);
}
var mimo = 1;
if (Category >= 5)
{
mimo = 4;
}
else if (Category >= 2)
{
mimo = 2;
}
// Bands
var extBands = new List<int>();
var bands = ASN1Parser.Dig(asn1, "rf-Parameters", "supportedBandListEUTRA") as List<object>;
if (bands != null)
{
var mappedBands = ASN1Parser.Map<BandInfo>(bands, (b, i) =>
{
if (b is Dictionary<string, object> bandDict)
{
var band = Convert.ToInt32(bandDict["bandEUTRA"]);
if (band == 64)
{
extBands.Add(i);
}
return new BandInfo { Band = band };
}
return new BandInfo();
});
if (mappedBands != null && mappedBands.Count > 0)
{
//Bands = mappedBands.Cast<BandInfo>().ToList();
var ext = ASN1Parser.Dig(asn1, 2, "nonCriticalExtension", "lateNonCriticalExtension", 3, "nonCriticalExtension", "rf-Parameters-v9e0", "supportedBandListEUTRA-v9e0") as List<object>;
if (ext != null)
{
foreach (var b in extBands)
{
if (b < ext.Count && ext[b] is Dictionary<string, object> extBand)
{
Bands[b].Band = Convert.ToInt32(extBand["bandEUTRA-v9e0"]);
}
}
}
}
}
// CA
var ca = ASN1Parser.Dig(asn1, 2, "nonCriticalExtension") as Dictionary<string, object>;
if (ca != null)
{
try
{
extBands.Clear();
var ca1 = ca.GetValueOrDefault("nonCriticalExtension") as Dictionary<string, object>;
if (ca1 != null)
{
if (ca1.ContainsKey("ue-Category-v1020"))
{
Category = Convert.ToInt32(ca1["ue-Category-v1020"]);
}
var rfParams = ca1.GetValueOrDefault("rf-Parameters-v1020") as Dictionary<string, object>;
if (rfParams != null)
{
var supportedBandComb = rfParams.GetValueOrDefault("supportedBandCombination-r10") as List<object>;
if (supportedBandComb != null)
{
CA = ASN1Parser.Map<List<BandCombinationInfo>>(supportedBandComb, (c0, i0) =>
{
if (c0 is List<object> c0List)
{
return ASN1Parser.Map<BandCombinationInfo>(c0List, (c1, i1) =>
{
if (c1 is Dictionary<string, object> c1Dict)
{
var band = Convert.ToInt32(c1Dict["bandEUTRA-r10"]);
if (band == 64)
{
//extBands.Add(new[] { i0, i1 });
}
var dl = c1Dict.GetValueOrDefault("bandParametersDL-r10") as List<object>;
var ul = c1Dict.GetValueOrDefault("bandParametersUL-r10") as List<object>;
var result = new BandCombinationInfo
{
Band = band,
MIMO = mimo
};
if (dl != null && dl.Count > 0 && dl[0] is Dictionary<string, object> dlDict)
{
result.DL = dlDict.GetValueOrDefault("ca-BandwidthClassDL-r10")?.ToString();
if (dlDict.ContainsKey("supportedMIMO-CapabilityDL-r10"))
{
var mimoCap = dlDict["supportedMIMO-CapabilityDL-r10"].ToString();
result.MIMO_9_10 = UE_CAPS_MIMO.GetValueOrDefault(mimoCap, mimo);
}
}
if (ul != null && ul.Count > 0 && ul[0] is Dictionary<string, object> ulDict)
{
result.UL = ulDict.GetValueOrDefault("ca-BandwidthClassUL-r10")?.ToString();
}
return result;
}
return new BandCombinationInfo();
});
}
return new List<BandCombinationInfo>();
});
}
}
}
}
catch (Exception) { }
}
if (Bands != null && Bands.Count > 0)
{
//Bands = Bands.OrderBy(b => b.Band).ToList();
}
}
/// <summary>
/// 解析NR RAT
/// </summary>
private void ParseRatNR(Dictionary<string, object> asn1)
{
if (asn1 == null) return;
// Bands
var bands = ASN1Parser.Dig(asn1, "rf-Parameters", "supportedBandListNR") as List<object>;
if (bands != null)
{
var mappedBands = ASN1Parser.Map<BandInfo>(bands, b =>
{
if (b is Dictionary<string, object> bandDict)
{
return new BandInfo { Band = Convert.ToInt32(bandDict["bandNR"]) };
}
return new BandInfo();
});
if (mappedBands != null && mappedBands.Count > 0)
{
NRBands = mappedBands;
}
}
// VoNR
var v1540 = ASN1Parser.Dig(asn1, 2, "nonCriticalExtension") as Dictionary<string, object>;
if (v1540 != null)
{
var vonr = new List<string>();
if (ASN1Parser.Dig(v1540, "ims-Parameters", "ims-ParametersFRX-Diff", "voiceOverNR")?.ToString() == "supported")
{
vonr.AddRange(new[] { "FR1", "FR2" });
}
else
{
if (ASN1Parser.Dig(v1540, "fr1-Add-UE-NR-Capabilities-v1540", "ims-ParametersFRX-Diff", "voiceOverNR")?.ToString() == "supported")
vonr.Add("FR1");
if (ASN1Parser.Dig(v1540, "fr2-Add-UE-NR-Capabilities-v1540", "ims-ParametersFRX-Diff", "voiceOverNR")?.ToString() == "supported")
vonr.Add("FR2");
}
if (vonr.Count > 0)
{
VoNR = string.Join(", ", vonr);
}
}
}
/// <summary>
/// 解析EUTRA-NR RAT
/// </summary>
private void ParseRatEUTRA_NR(Dictionary<string, object> asn1)
{
if (asn1 == null) return;
var bands = ASN1Parser.Dig(asn1, "rf-ParametersMRDC", "supportedBandCombinationList") as List<object>;
if (bands != null)
{
MRDC = ASN1Parser.Map<List<BandCombinationInfo>>(bands, band =>
{
if (band is Dictionary<string, object> bandDict)
{
var bl = bandDict.GetValueOrDefault("bandList") as Dictionary<string, object>;
if (bl != null)
{
var result = new List<BandCombinationInfo>();
var nr = bl.GetValueOrDefault("nr") as List<object>;
if (nr != null)
{
result.AddRange(ASN1Parser.Map<BandCombinationInfo>(nr, b =>
{
if (b is Dictionary<string, object> bDict)
{
return new BandCombinationInfo
{
Band = Convert.ToInt32(bDict["bandNR"]),
BandType = "NR",
DL = bDict.GetValueOrDefault("ca-BandwidthClassDL-NR")?.ToString(),
UL = bDict.GetValueOrDefault("ca-BandwidthClassUL-NR")?.ToString()
};
}
return new BandCombinationInfo();
}));
}
var eutra = bl.GetValueOrDefault("eutra") as List<object>;
if (eutra != null)
{
result.AddRange(ASN1Parser.Map<BandCombinationInfo>(eutra, b =>
{
if (b is Dictionary<string, object> bDict)
{
return new BandCombinationInfo
{
Band = Convert.ToInt32(bDict["bandEUTRA"]),
DL = bDict.GetValueOrDefault("ca-BandwidthClassDL-EUTRA")?.ToString(),
UL = bDict.GetValueOrDefault("ca-BandwidthClassUL-EUTRA")?.ToString()
};
}
return new BandCombinationInfo();
}));
}
return result;
}
}
return new List<BandCombinationInfo>();
});
}
}
/// <summary>
/// 设置频段组合
/// </summary>
public void SetBandComb(Dictionary<string, object> json, string ratType)
{
BandCombinations[ratType] = json;
}
}
/// <summary>
/// 频段信息
/// </summary>
public class BandInfo
{
public int Band { get; set; }
public bool DL256QAM { get; set; }
public string BandType { get; set; } = "LTE";
}
/// <summary>
/// 频段组合信息
/// </summary>
public class BandCombinationInfo
{
public int Band { get; set; }
public string DL { get; set; }
public string UL { get; set; }
public int MIMO { get; set; }
public int? MIMO_9_10 { get; set; }
public bool MIMO4_3_4 { get; set; }
public string BandType { get; set; } = "LTE";
}
}