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_arrayif __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 refrom tools.extract import ExtractMultilineclass 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_listif __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 refrom tools.extract import ExtractMultilineclass 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_listif __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 refrom tools.extract import ExtractMultilineclass 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