1. 3GPP的文本格式
3GPP OTA的二进制数据,通过Wireshark(tshark)解析后能够生成文本格式,该文本格式的缩进是4空格。针对此4空格的格局,应用Python脚本能够获取感兴趣的数据段落。
对于数据段落能够依据本人的需要,应用正则表达式提取局部字段以不便查看。
2. 源码
2.1 提取感兴趣的字段
extract.py:
class ExtractMultiline(object): ''' 3GPP Decoder工具对OTA二进制数据解析,生成文本,该文本格式是4个空格的文本格式。 为不便解析该文本中的数据,咱们须要对感兴趣的数据段落进行提取。 该类用于提取这些数据段落。 ''' def get_filecontent_lines(self, multilines_file): ''' Parameters ---------- multilines_file : string 文件名称 Returns ------- lines : string 文件内容 ''' f = open(multilines_file, 'r', encoding='UTF-8', errors='ignore') lines = f.readlines() f.close() return lines def get_multilines(self, entry_string, tag_string, lines): ''' Parameters ---------- entry_string : string 如果该字符串蕴含在某行中,该行作为启动捕捉冀望获取的多行字符串的开始。该标记为防止(缩小)间接应用tag_string引起的抵触。 tag_string : string 冀望获取的多行字符串的标记 lines : string 输出的多行文本 Returns ------- multilines_array : array 冀望获取的多行字符串,有可能有多个,这里用array返回 ''' entry_flag = False entry_nest_count = 0 nest_count = 0 multilines = [] multilines_array = [] tag_state = 'IDLE' tag_count = 0 for line in lines: spaceNum = len(line.rstrip()) - len(line.strip()) nest_count = int(spaceNum/4) if entry_string == line.strip(): entry_flag = True entry_nest_count = nest_count elif entry_flag and nest_count <= entry_nest_count: entry_flag = False if entry_flag: if tag_string in line: tag_state = 'START' tag_count = nest_count elif tag_state == 'START' and nest_count <= tag_count: tag_state = 'END' if tag_state == 'START': multilines.append(line) if tag_state == 'END': tag_state = 'IDLE' multilines_array.append(multilines) multilines = [] # 文件完结还处于START状态的非凡解决,示意该最初一段multilines也须要记录下来 if tag_state == 'START': tag_state = 'IDLE' multilines_array.append(multilines) return multilines_array if __name__ == '__main__': extract_multiline = ExtractMultiline() lines = extract_multiline.get_filecontent_lines(r'nr-ueCapabilityEnquiry.txt') multilines_array = extract_multiline.get_multilines('ue-CapabilityRAT-RequestList:', 'UE-CapabilityRAT-Request', lines) print(multilines_array)
2.2 例子
2.2.1 获取LTE能力申请信息中的Band信息
get_capability_enquiry_for_lte.py:
import re from tools.extract import ExtractMultiline class UeCapabilityEnquiryForLTE(object): # 获取RAT类型列表 def get_rat(self, multilines): re_rat_type = '\s*RAT-Type: (\S+) .+' rat_type_list = [] for line in multilines: m_rat_type = re.match(re_rat_type, line) if m_rat_type: rat_type_list.append(m_rat_type.group(1)) return rat_type_list def analyse_ota(self, ota_file): extract_multiline = ExtractMultiline() lines = extract_multiline.get_filecontent_lines(ota_file) multilines_array = extract_multiline.get_multilines('ueCapabilityEnquiry-r8', 'ue-CapabilityRequest:', lines) rat_type_list = [] if len(multilines_array) >= 1: rat_type_list = self.get_rat(multilines_array[0]) return rat_type_list if __name__ == '__main__': ue_capability_enquiry_for_lte = UeCapabilityEnquiryForLTE() rat_type_list = ue_capability_enquiry_for_lte.analyse_ota(r'lte-ueCapabilityEnquiry.txt') print(rat_type_list)
2.2.2 获取NR能力申请信息中的Band信息
get_capability_enquiry_for_nr.py:
import re from tools.extract import ExtractMultiline class UeCapabilityEnquiryForNR(object): # 获取RAT类型列表 def get_rat(self, multilines_array): re_rat_type = '\s*rat-Type: (\S+) .+' rat_type_list = [] for multilines in multilines_array: for line in multilines: m_rat_type = re.match(re_rat_type, line) if m_rat_type: rat_type_list.append(m_rat_type.group(1)) return rat_type_list def analyse_ota(self, ota_file): extract_multiline = ExtractMultiline() lines = extract_multiline.get_filecontent_lines(ota_file) multilines_array = extract_multiline.get_multilines('ue-CapabilityRAT-RequestList:', 'UE-CapabilityRAT-Request', lines) rat_type_list = self.get_rat(multilines_array) return rat_type_list if __name__ == '__main__': ue_capability_enquiry_for_nr = UeCapabilityEnquiryForNR() rat_type_list = ue_capability_enquiry_for_nr.analyse_ota(r'nr-ueCapabilityEnquiry.txt') print(rat_type_list)
2.2.3 获取能力上报信息中的Band信息(包含CA和EN-DC信息)
get_capability_information.py:
import re from tools.extract import ExtractMultiline class UeCapabilityInformation(object): # LTE Band list def supported_band_list_eutra(self, multilines): re_bandEUTRA = '\s*bandEUTRA: (\d*)' bandlist = [] for line in multilines: m_bandEUTRA = re.match(re_bandEUTRA, line) if m_bandEUTRA: bandlist.append(m_bandEUTRA.group(1)) return bandlist # LTE Band list extend(v9e0) def supported_band_list_eutra_v9e0(self, multilines): re_bandEUTRA_v9e0 = '\s*bandEUTRA-v9e0: (\d*)' bandlist_v9e0_str = '' bandlist_v9e0 = [] for line in multilines: if 'SupportedBandEUTRA-v9e0' in line: bandlist_v9e0_str = bandlist_v9e0_str + ':B' m_bandEUTRA_v9e0 = re.match(re_bandEUTRA_v9e0, line) if m_bandEUTRA_v9e0: bandlist_v9e0_str = bandlist_v9e0_str + m_bandEUTRA_v9e0.group(1) if len(bandlist_v9e0_str) > 1: bandlist_v9e0 = bandlist_v9e0_str[1:].split(':') bandlist_v9e0 = [item.replace('B','') for item in bandlist_v9e0] return bandlist_v9e0 # LTE CA band combination def supported_band_combination_r10(self, multilines): ca_array = [] ca_str = '' re_bandEUTRA_r10 = '\s*bandEUTRA-r10: (\d*)' re_ca_BandwidthClassUL_r10 = '\s*ca-BandwidthClassUL-r10: ([abcde]{1}) .+' re_ca_BandwidthClassDL_r10 = '\s*ca-BandwidthClassDL-r10: ([abcde]{1}) .+' for line in multilines: m_bandEUTRA_r10 = re.match(re_bandEUTRA_r10, line) m_ca_BandwidthClassUL_r10 = re.match(re_ca_BandwidthClassUL_r10, line) m_ca_BandwidthClassDL_r10 = re.match(re_ca_BandwidthClassDL_r10, line) if 'BandCombinationParameters-r10' in line: ca_str = ca_str + ':' if m_bandEUTRA_r10: ca_str = ca_str + ';B' + m_bandEUTRA_r10.group(1) if m_ca_BandwidthClassUL_r10: ca_str = ca_str + '-UL' + m_ca_BandwidthClassUL_r10.group(1) if m_ca_BandwidthClassDL_r10: ca_str = ca_str + '-DL' + m_ca_BandwidthClassDL_r10.group(1) if len(ca_str) > 1: ca_array = ca_str[1:].split(':') ca_array = [item[1:] for item in ca_array] # or item.replace(';','',1) return ca_array # LTE CA band extend def supported_band_combination_v1090(self, multilines): ca_extend_str = '' ca_extend_array = [] re_bandEUTRA_v1090 = '\s*bandEUTRA-v1090: (\d*)' for line in multilines: m_bandEUTRA_v1090 = re.match(re_bandEUTRA_v1090, line) if 'BandCombinationParameters-v1090' in line: ca_extend_str = ca_extend_str + ':' if 'BandParameters-v1090' in line: ca_extend_str = ca_extend_str + ';' if m_bandEUTRA_v1090: ca_extend_str = ca_extend_str + m_bandEUTRA_v1090.group(1) if len(ca_extend_str) > 1: ca_extend_array = ca_extend_str[1:].split(':') return ca_extend_array # LTE CA set def supported_band_combination_ext_r10(self, multilines): ca_set_str = '' ca_set_array = [] for line in multilines: m = re.match('\s*supportedBandwidthCombinationSet-r10: ([0-9abcdefABCDEF]*) .*', line) if 'BandCombinationParametersExt-r10' in line: ca_set_str = ca_set_str + ':' if m: ca_set_str = ca_set_str + m.group(1) if len(ca_set_str) > 1: ca_set_array = ca_set_str[1:].split(':') for index in range(0, len(ca_set_array)): if ca_set_array[index] != '': ca_set_array[index] = (bin(int(ca_set_array[index],16))).replace('0b', '').replace('0', '') return ca_set_array # NR Band list def supported_band_list_nr(self, multilines): re_bandNR = '\s*bandNR: (\d*)' bandlist = [] for line in multilines: m_bandNR= re.match(re_bandNR, line) if m_bandNR: bandlist.append(m_bandNR.group(1)) return bandlist # NR CA band combination def supported_band_combination_list_nr(self, multilines): ca_array = [] ca_str = '' re_bandNR = '\s*bandNR: (\d*)' re_ca_BandwidthClassUL_NR = '\s*ca-BandwidthClassUL-NR: ([abcde]{1}) .+' re_ca_BandwidthClassDL_NR = '\s*ca-BandwidthClassDL-NR: ([abcde]{1}) .+' for line in multilines: m_bandNR = re.match(re_bandNR, line) m_ca_BandwidthClassUL_NR = re.match(re_ca_BandwidthClassUL_NR, line) m_ca_BandwidthClassDL_NR = re.match(re_ca_BandwidthClassDL_NR, line) if 'BandCombination' == line.strip(): ca_str = ca_str + ':' if m_bandNR: ca_str = ca_str + ';N' + m_bandNR.group(1) if m_ca_BandwidthClassUL_NR: ca_str = ca_str + '-UL' + m_ca_BandwidthClassUL_NR.group(1) if m_ca_BandwidthClassDL_NR: ca_str = ca_str + '-DL' + m_ca_BandwidthClassDL_NR.group(1) if len(ca_str) > 1: ca_array = ca_str[1:].split(':') ca_array = [item[1:] for item in ca_array] # or item.replace(';','',1) return ca_array # MRDC CA band combination def supported_band_combination_list_mrdc(self, multilines): mrdc_array = [] mrdc_str = '' re_bandEUTRA = '\s*bandEUTRA: (\d*)' re_ca_BandwidthClassUL_EUTRA = '\s*ca-BandwidthClassUL-EUTRA: ([abcde]{1}) .+' re_ca_BandwidthClassDL_EUTRA = '\s*ca-BandwidthClassDL-EUTRA: ([abcde]{1}) .+' re_bandNR = '\s*bandNR: (\d*)' re_ca_BandwidthClassUL_NR = '\s*ca-BandwidthClassUL-NR: ([abcde]{1}) .+' re_ca_BandwidthClassDL_NR = '\s*ca-BandwidthClassDL-NR: ([abcde]{1}) .+' for line in multilines: m_bandEUTRA = re.match(re_bandEUTRA, line) m_ca_BandwidthClassUL_EUTRA = re.match(re_ca_BandwidthClassUL_EUTRA, line) m_ca_BandwidthClassDL_EUTRA = re.match(re_ca_BandwidthClassDL_EUTRA, line) m_bandNR = re.match(re_bandNR, line) m_ca_BandwidthClassUL_NR = re.match(re_ca_BandwidthClassUL_NR, line) m_ca_BandwidthClassDL_NR = re.match(re_ca_BandwidthClassDL_NR, line) if 'BandCombination' == line.strip(): mrdc_str = mrdc_str + ':' if m_bandNR: mrdc_str = mrdc_str + ';N' + m_bandNR.group(1) if m_ca_BandwidthClassUL_NR: mrdc_str = mrdc_str + '-UL' + m_ca_BandwidthClassUL_NR.group(1) if m_ca_BandwidthClassDL_NR: mrdc_str = mrdc_str + '-DL' + m_ca_BandwidthClassDL_NR.group(1) if m_bandEUTRA: mrdc_str = mrdc_str + ';B' + m_bandEUTRA.group(1) if m_ca_BandwidthClassUL_EUTRA: mrdc_str = mrdc_str + '-UL' + m_ca_BandwidthClassUL_EUTRA.group(1) if m_ca_BandwidthClassDL_EUTRA: mrdc_str = mrdc_str + '-DL' + m_ca_BandwidthClassDL_EUTRA.group(1) #print('MRDC str', mrdc_str) if len(mrdc_str) > 1: mrdc_array = mrdc_str[1:].split(':') mrdc_array = [item[1:] for item in mrdc_array] # or item.replace(';','',1) return mrdc_array # all information def output_ue_information(self, ota_file): lte_band = [] lte_ca = [] nr_band = [] nr_ca = [] mrdc = [] extract_multiline = ExtractMultiline() lines = extract_multiline.get_filecontent_lines(ota_file) bandlist = [] bandlist_v9e0 = [] ca_array = [] ca_extend_array = [] ca_set_array = [] # LTE Band list multilines_array = extract_multiline.get_multilines('UE-EUTRA-Capability', 'supportedBandListEUTRA:', lines) if len(multilines_array) >= 1: bandlist = self.supported_band_list_eutra(multilines_array[0]) # LTE Band list extend(v9e0) multilines_array = extract_multiline.get_multilines('UE-EUTRA-Capability', 'supportedBandListEUTRA-v9e0:', lines) if len(multilines_array) >= 1: bandlist_v9e0 = self.supported_band_list_eutra_v9e0(multilines_array[0]) # LTE CA band combination multilines_array = extract_multiline.get_multilines('UE-EUTRA-Capability', 'supportedBandCombination-r10:', lines) if len(multilines_array) >= 1: ca_array = self.supported_band_combination_r10(multilines_array[0]) # LTE CA band extend multilines_array = extract_multiline.get_multilines('UE-EUTRA-Capability', 'supportedBandCombination-v1090:', lines) if len(multilines_array) >= 1: ca_extend_array = self.supported_band_combination_v1090(multilines_array[0]) # LTE CA set multilines_array = extract_multiline.get_multilines('UE-EUTRA-Capability', 'supportedBandCombinationExt-r10:', lines) if len(multilines_array) >= 1: ca_set_array = self.supported_band_combination_ext_r10(multilines_array[0]) #print('bandlist: ', bandlist) #print('bandlist_v9e0: ', bandlist_v9e0) #print('ca_array: ', ca_array) #print('ca_extend_array: ', ca_extend_array) #print('ca_set_array: ', ca_set_array) # LTE Band and CA for index in range(0, len(bandlist)): if bandlist[index] != '64': lte_band.append(bandlist[index]) else: lte_band.append(bandlist_v9e0[index]) for index in range(0, len(ca_array)): ca = ca_array[index] if len(ca_extend_array) >= 1: for band_extend in ca_extend_array[index].split(';')[1:]: if band_extend != '': ca = ca.replace('B64', 'B'+band_extend, 1) lte_ca.append(ca + '; BW comb set: ' + ca_set_array[index]) print('LTE Band: ', lte_band) print('LTE CA: ', lte_ca) #for item in lte_ca: # print(item) # NR Band list multilines_array = extract_multiline.get_multilines('UE-NR-Capability', 'supportedBandListNR:', lines) if len(multilines_array) >= 1: nr_band = self.supported_band_list_nr(multilines_array[0]) print('NR Band:', nr_band) # NR CA band combination multilines_array = extract_multiline.get_multilines('UE-NR-Capability', 'supportedBandCombinationList:', lines) if len(multilines_array) >= 1: nr_ca = self.supported_band_combination_list_nr(multilines_array[0]) print('NR CA:', nr_ca) # MRDC multilines_array = extract_multiline.get_multilines('UE-MRDC-Capability', 'supportedBandCombinationList:', lines) if len(multilines_array) >= 1: mrdc = self.supported_band_combination_list_mrdc(multilines_array[0]) print('MRDC:', mrdc) return [lte_band, lte_ca, nr_band, nr_ca, mrdc] if __name__ == '__main__': ue_capability_information = UeCapabilityInformation() #[lte_band, lte_ca, nr_band, nr_ca, mrdc] = ue_capability_information.output_ue_information(r'nr-ueCapabilityInformation.txt') [lte_band, lte_ca, nr_band, nr_ca, mrdc] = ue_capability_information.output_ue_information(r'lte-ueCapabilityInformation.txt')
3. 测试数据
测试数据EN-DC ueCapabilityInformation:
38 03 08 13 ad d9 a0 4b 00 10 40 c1 c9 99 36 7d 2a 75 02 e5 ff f9 1f f9 7f fe 47 fe 5f ff 91 ff 97 ff e4 7f e5 ff f9 1f f9 7f fe 47 fe 5f ff 91 ff 97 ff e4 7f e5 ff f9 1f f9 7f fe 47 fe 5f ff 91 ff 97 ff e4 7f ff f3 ff af a2 08 00 8c 87 0c a7 4a 93 bb f1 59 c0 80 00 00 7d bf f0 00 00 00 78 d4 00 c0 0a 00 40 00 34 05 af aa dc bf ff 1a 06 38 00 20 01 80 00 08 20 61 00 02 08 18 80 00 80 06 30 00 20 81 a6 00 08 00 6c 80 02 00 1b 60 00 80 02 f8 40 03 94 00 10 00 e7 00 04 00 3a 00 01 00 1c 00 00 40 47 08 00 e3 80 02 02 00 40 1b 2f ff c8 ff cb ff f2 3f f2 ff fc 8f fc bf ff 23 ff 2f ff c8 ff cb ff f2 3f f2 ff fc 8f fc bf ff 23 ff 2f ff c8 ff cb ff f2 3f f2 ff fc 8f fc bf ff 23 ff 2f ff c8 ff cb ff f2 3f ff fe c0 00 19 8d 00 08 bc 5d 98 a2 27 38 10 70 0c f6 91 84 92 5f ff ff fe ef 73 5e 08 04 cc 11 99 41 24 30 00 80 05 09 08 25 cf 01 80 00 08 06 01 c1 b0 9c 4d 78 08 00 00 08 51 90 00 00 00 cd 07 ff 20 00 70 c1 96 03 80 00 10 08 03 00 e0 d8 4e 26 d8 05 83 15 e1 a0 3f a0 47 4e 7a ef ff ff af 01 40 78 2e 02 03 c1 27 be 7f ff ff 80 07 03 1b ef 80 01 40 dc 04 07 e3 80 f5 17 c0 0f f8 bc 21 d8 be 08 21 fd 50 08 83 d9 51 d2 20 62 4f ac 41 e4 20 f0 81 42 5b e7 e4 ff e3 f8 00 3f f8 fe 00 00 d8 05 00 07 42 a2 f8 05 ff 17 84 3b 17 c1 04 3f aa 01 10 7b 2a 3a 44 0c 49 f5 88 3c 84 1e 10 28 4b 7c fc 9f f8 7e 00 07 fe 1f 80 00 1b 00 a0 00 e8 54 5f 01 3f e2 f0 87 62 f8 20 87 f5 40 22 0f 65 47 48 81 89 3e b1 07 90 83 c2 05 09 6f 9f 93 f8 0e 00 00 fe 03 80 00 03 60 14 00 1d 0a 8b e0 37 fc 5e 10 ec 5f 04 10 fe a8 04 41 ec a8 e9 10 31 27 d6 20 f2 10 78 40 a1 2d f3 f2 7f f1 fc 00 1f fc 7f 00 00 6c 02 80 03 a1 51 7c 07 ff 8b c2 1d 8b e0 82 1f d5 00 88 3d 95 1d 22 06 24 fa c4 1e 42 0f 08 14 25 be 7e 42 00 08 00 0d 80 50 00 74 2a 2f 83 7f f1 78 43 b1 7c 10 43 fa a0 11 07 b2 a3 a4 40 c4 9f 58 83 c8 41 e1 02 84 b7 cf c9 fd 07 40 00 7f 41 d0 00 01 b0 0a 00 0e 85 45 f0 9f fe 2f 08 76 2f 82 08 7f 54 02 20 f6 54 74 88 18 93 eb 10 79 08 3c 20 50 96 f9 f9 08 00 20 00 36 01 40 01 d0 a8 be 26 ff c5 e1 0e c5 f0 41 0f ea 80 44 1e ca 8e 91 03 12 7d 62 0f 21 07 84 0a 12 df 3f 27 7f 1f f0 01 df c7 fc 00 06 e0 28 00 3a 00 d9 40 00 14 00 00 00 4a 0f 00 00 03 09 a0 00 03 d0 2a 0e 00 00 e2 68 00 00 13 d0 20 0e 00 04 04 d0 0e 00 01 50 d8 0a 14 e9 db 24 f8 10 a7 4e d9 27 c0 00 38 10 c6 0f ff f8 00 02 e0 3e 00 28 00 30 1c 04 07 03 10 5c 07 00 07 00 06 03 e0 40 82 00 00 00 41 00 00 02 20 80 00 02 10 40 00 01 88 20 00 01 04 10 00 00 a2 08 00 00 61 04 00 00 38 82 00 00 20 08 60 6d 60 ed 64 ed 60 cd 64 cd 64 6d 65 0d 65 2d e5 4d 02 01 00 00 09 65 94 04 00 00 65 96 50 10 00 02 96 59 40 40 00 0e 59 65 01 00 00 49 65 94 04 00 01 65 96 50 10 00 06 96 59 40 40 00 1e 59 65 01 00 00 89 65 94 02 14 0e 2a 83 c5 52 78 aa 0d 15 49 a2 a9 1c 55 28 8a a5 31 74 aa 28 18 d2 01 1e 6f c0 70 1c 01 e6 fc 07 01 c0 1e 6f c0 70 1c 01 e6 fc 07 01 c0 1e 6f c0 70 1c 01 e6 fc 07 01 c0 1e 6f c0 70 1c 01 e6 fc 07 01 c0 1e 6f c0 70 1c 00 00 01 08 98 01 00 30 04 00 a0 0c 01 c0 18 03 80 40 09 00 a0 16 01 40 2c 00 80 18 06 00 d0 0c 01 84 c0 10 00 80 70 01 00 40 02 01 c0 04 04 00 08 02 00 10 10 00 20 24 00 40 10 00 80 90 00 11 30 02 00 20 08 00 40 18 00 80 30 01 00 80 02 01 40 04 02 80 08 01 00 10 0c 00 20 18 00 09 80 20 05 00 e0 1e 00 80 14 03 80 78 08 01 10 04 00 a0 20 04 40 48 09 80 20 05 01 20 24 6a c2 c0 00 81 01 81 c4 c6 46 c7 c9 49 ca 1d c0 00 00 00 d0 4a 65 3a 18 ff 02 f0 58 38 07 00 00 00 00 10 3d 19 03 e0 b0 00 0e 26 80 00 01 20 7a 32 04 01 c0 00 80 9a 01 c0 00 2a 1a 81 42 9d 3b 64 9f 02 14 e9 db 24 f8 00 07 01 0c 60 e0 04 20 40 10 08 02 01 03 00 40 0a 00 c0 18 40 80 40 10 08 02 06 00 80 14 04 80 9c 00 00