当前位置:   article > 正文

【笔记】【开发方案】APN 配置参数 bitmask 数据转换(Android & KaiOS)_t-mobile mms配置

t-mobile mms配置

一、参数说明

(一)APN配置结构对比

平台AndroidKaiOS
文件类型xmljson
结构每个<apn>标签是一条APN,包含完成的信息层级数组结构,使用JSON格式的数据。最外层是mcc,其次mnc,最后APN用数组形式配置(每个APN都是一个对象,不含mccmnc属性)。

Android: apns-conf.xml

  1. <!-- Android: apns-conf.xml -->
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <apns version="8">
  4. <apn carrier="T-Mobile US" mcc="001" mnc="01" apn="fast.t-mobile.com" user="" password="" server="" proxy="" port="" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" mmsproxy="" mmsport="" type="default,mms,supl,hipri,xcap,rcs" protocol="IPV6" roaming_protocol="IP" bearer_bitmask="" mvno_type="ecid" mvno_match_data="[4]4310260" class="" user_visible="true" user_editable="true" authtype="0"/>
  5. </apns>

KaiOS: apns.json

特别需要注意格式(很容易出错),数组最后不用加逗号,注意大/中括号的首位一致性。

  1. {
  2. "202": {
  3. "10": [
  4. {"carrier":"Wind Internet","apn":"gint.b-online.gr","type":["default","supl"]},
  5. {"voicemail":"122","type":["operatorvariant"]},
  6. {"carrier":"Wind MMS","apn":"mnet.b-online.gr","mmsc":"http://192.168.200.95/servlets/mms","mmsproxy":"192.168.200.11","mmsport":"9401","type":["mms"]}
  7. ],
  8. "01": [
  9. {"carrier":"Cosmote Wireless Internet","apn":"","type":["ia"]},
  10. {"voicemail":"123","type":["operatorvariant"]},
  11. {"carrier":"Cosmote Wireless Internet","apn":"internet","type":["default","supl"]},
  12. {"carrier":"Cosmote Mms","apn":"mms","mmsc":"http://mmsc.cosmote.gr:8002","mmsproxy":"10.10.10.20","mmsport":"8080","type":["mms"]}
  13. ],
  14. "09": [
  15. {"carrier":"Q Internet","apn":"myq","type":["default","supl"]},
  16. {"voicemail":"122","type":["operatorvariant"]},
  17. {"carrier":"Q-Telecom MMS GPRS","apn":"q-mms.myq.gr","mmsc":"http://mms.myq.gr","mmsproxy":"192.168.80.134","mmsport":"8080","type":["mms"]}
  18. ]
  19. },
  20. "001": {
  21. "01": [
  22. {"carrier":"Testing SIM default","apn":"test","type":["default"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true"},
  23. {"carrier":"IMS","apn":"ims","type":["ims"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true"},
  24. {"carrier":"XCAP","apn":"xcap","type":["xcap"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true","authtype":"0"}
  25. ]
  26. }
  27. }

(二)bearer配置值对比

  • 1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20 (The original bearer value in Android,位运算)
  • 1048575(The original bearer value in KaiOS using decimalism)

二、代码解析

(一)Android

待完善

(二)KaiOS

  • DataCallManager.jsm
  • apn_editor_const.js

1、bitmask的进制转换

可以参考PDN建立逻辑,gecko/dom/system/gonk/radio/DataCallManager.jsm

  1. //DataCallManager.jsm
  2. //检查对应的rat是否包含在此APN bearer 配置中
  3. // Check rat value include in the bit map or not.
  4. function bitmaskHasTech(aBearerBitmask, aRadioTech) {
  5. if (aBearerBitmask == 0) {
  6. return true;
  7. } else if (aRadioTech > 0) {
  8. return (aBearerBitmask & (1 << (aRadioTech - 1))) != 0;
  9. }
  10. return false;
  11. }
  12. //bearer十进制转成二进制
  13. // Show the detail rat type.
  14. function bitmaskToString(aBearerBitmask) {
  15. if (aBearerBitmask == 0 || aBearerBitmask === undefined) {
  16. return 0;
  17. }
  18. let val = "";
  19. for (let i = 1; i < RIL.GECKO_RADIO_TECH.length; i++) {
  20. if ((aBearerBitmask & (1 << (i - 1))) != 0) {
  21. val = val.concat(i + "|");
  22. }
  23. }
  24. return val;
  25. }
  26. function bearerBitmapHasCdma(aBearerBitmask) {
  27. return (RIL_RADIO_CDMA_TECHNOLOGY_BITMASK & aBearerBitmask) != 0;
  28. }

bitmaskToString接口中,将bitmask转化成String时,循环RIL.GECKO_RADIO_TECH的长度次,经过位运算转换成与Android原始配置的bearer_bitmask相同格式的bearer位符,用“|”间隔rat类型位。

是如何通过RIL调用ril_consts.js内的GECKO_RADIO_TECH?

DataCallManager.jsm 中定义RIL对象,并使用XPCOMUtils.defineLazyGetter()方法来实现懒加载,即在要使用时才加载和初始化对象(只有在第一次访问该对象时才会进行初始化和加载),避免不必要的性能开销和资源浪费。
RIL对象是通过ChromeUtils.import 方法从ril_consts.js文件中导入的,该对象由ril_consts.js文件中的代码创建和初始化的。

  1. //DataCallManaer.jsm
  2. "use strict";
  3. //XPCOM 是一个用于 实现跨语言组件的技术框架。
  4. //导入XPCOMUtils对象(工具库),简化和封装XPCOM组件的开发和使用。
  5. //使用常量const来定义 XPCOMUtils 对象,以确保在运行时不会发生对象被重新赋值的情况。
  6. const { XPCOMUtils } = ChromeUtils.import(
  7. "resource://gre/modules/XPCOMUtils.jsm"
  8. );
  9. //定义RIL对象,后续调用 RIL.GECKO_RADIO_TECH
  10. XPCOMUtils.defineLazyGetter(this, "RIL", function() {
  11. return ChromeUtils.import("resource://gre/modules/ril_consts.js");
  12. });
  13. //ref RIL.GECKO_RADIO_TECH
  14. const TCP_BUFFER_SIZES = [
  15. null,
  16. "4092,8760,48000,4096,8760,48000", // gprs
  17. "4093,26280,70800,4096,16384,70800", // edge
  18. "58254,349525,1048576,58254,349525,1048576", // umts
  19. "16384,32768,131072,4096,16384,102400", // is95a = 1xrtt
  20. "16384,32768,131072,4096,16384,102400", // is95b = 1xrtt
  21. "16384,32768,131072,4096,16384,102400", // 1xrtt
  22. "4094,87380,262144,4096,16384,262144", // evdo0
  23. "4094,87380,262144,4096,16384,262144", // evdoa
  24. "61167,367002,1101005,8738,52429,262114", // hsdpa
  25. "40778,244668,734003,16777,100663,301990", // hsupa = hspa
  26. "40778,244668,734003,16777,100663,301990", // hspa
  27. "4094,87380,262144,4096,16384,262144", // evdob
  28. "131072,262144,1048576,4096,16384,524288", // ehrpd
  29. "524288,1048576,2097152,262144,524288,1048576", // lte
  30. "122334,734003,2202010,32040,192239,576717", // hspa+
  31. "4096,87380,110208,4096,16384,110208", // gsm (using default value)
  32. "4096,87380,110208,4096,16384,110208", // tdscdma (using default value)
  33. "122334,734003,2202010,32040,192239,576717", // iwlan
  34. "122334,734003,2202010,32040,192239,576717", // ca
  35. ];
  36. //定义了一个常量RIL_RADIO_CDMA_TECHNOLOGY_BITMASK,用于表示CDMA射频技术类型的掩码值。
  37. //RIL.GECKO_RADIO_TECH.indexOf 查找各个CDMA技术类型在GECKO_RADIO_TECH数组中的下标值,
  38. //-1 的目的是得到对应的掩码位数,并将此转换成掩码值,
  39. //使用按位左移(<<)运算符得到掩码值,
  40. //各个掩码值按位或(|)操作得到最终的掩码值。
  41. const RIL_RADIO_CDMA_TECHNOLOGY_BITMASK =
  42. (1 << (RIL.GECKO_RADIO_TECH.indexOf("is95a") - 1)) |
  43. (1 << (RIL.GECKO_RADIO_TECH.indexOf("is95b") - 1)) |
  44. (1 << (RIL.GECKO_RADIO_TECH.indexOf("1xrtt") - 1)) |
  45. (1 << (RIL.GECKO_RADIO_TECH.indexOf("evdo0") - 1)) |
  46. (1 << (RIL.GECKO_RADIO_TECH.indexOf("evdoa") - 1)) |
  47. (1 << (RIL.GECKO_RADIO_TECH.indexOf("evdob") - 1)) |
  48. (1 << (RIL.GECKO_RADIO_TECH.indexOf("ehrpd") - 1));
  49. // set to true in ril_consts.js to see debug messages
  50. var DEBUG = RIL_DEBUG.DEBUG_RIL; //调试用的log打印标识符

如上代码,CDMA技术类型对应的掩码值RIL_RADIO_CDMA_TECHNO如下:

is95a: 1 << (5-1) = 0x10
is95b: 1 << (6-1) = 0x20
1xrtt: 1 << (7-1) = 0x40
evdo0: 1 << (8-1) = 0x80
evdoa: 1 << (9-1) = 0x100
evdob: 1 << (14-1) = 0x2000
ehrpd: 1 << (15-1) = 0x4000

2、GECKO_RADIO_TECH 定义网络制式 (ril_consts.js)

在KaiOS中,RIL.GECKO_RADIO_TECH数组是在Gecko内核的代码中定义的,其实现位于Gecko代码库的"gecko/dom/system/gonk/radio/ril_consts.js"文件中。该文件定义了一系列RIL层的常量,包括射频技术类型、消息ID等。在该文件中,可以找到以下代码片段,其中定义了RIL.GECKO_RADIO_TECH数组的元素和顺序:

  1. //GECKO_RADIO_TECH 数组定义射频技术(网络连接)
  2. this.GECKO_RADIO_TECH = [
  3. null,
  4. "gprs", //1 GPRS
  5. "edge", //2 EDGE
  6. "umts", //3 UMTS
  7. "is95a", //4 IS-95A
  8. "is95b", //5 IS-95B
  9. "1xrtt", //6 cdma1x?一种CDMA2000射频技术,是CDMAOne技术的升级版(1x Radio Transmission Technology)
  10. "evdo0", //7 EVDO-0
  11. "evdoa", //8 EVDO-A
  12. "hsdpa", //9
  13. "hsupa", //10
  14. "hspa", //11
  15. "evdob", //12 EVDO-B
  16. "ehrpd", //13 EVDO-D
  17. "lte", //14 LTE
  18. "hspa+", //15 HSPA+
  19. "gsm", //16 GSM
  20. "tdscdma", //17 TD-SCDMA
  21. "iwlan", //18 iWLAN(wifi)
  22. "lte_ca", //19 LTE_CA
  23. ];
  24. //定义遵循的协议类型
  25. this.GECKO_PROFILE_INFO_TYPE_COMMON = 0;
  26. this.GECKO_PROFILE_INFO_TYPE_3GPP = 1;
  27. this.GECKO_PROFILE_INFO_TYPE_3GPP2 = 2;

3、DataCall 对 rat 的使用案例

  1. dataRegistrationChanged(aRadioTech) {
  2. let targetBearer;
  3. if (this.apnSetting.bearer === undefined) {
  4. targetBearer = 0;
  5. } else {
  6. targetBearer = this.apnSetting.bearer;
  7. }
  8. if (DEBUG) {
  9. this.debug(
  10. "dataRegistrationChanged: targetBearer: " +
  11. bitmaskToString(targetBearer)
  12. );
  13. }
  14. if (bitmaskHasTech(targetBearer, aRadioTech)) {
  15. // Ignore same rat type. Let handler process the retry.
  16. } else {
  17. if (DEBUG) {
  18. this.debug(
  19. "dataRegistrationChanged: current APN do not support this rat reset DC. APN:" +
  20. JSON.stringify(this.apnSetting)
  21. );
  22. // Clean the requestedNetworkInterfaces due to current DC can not support this rat under DC retrying state.
  23. // Let handler process the retry.
  24. let targetRequestedNetworkInterfaces = this.requestedNetworkInterfaces.slice();
  25. for (let networkInterface of targetRequestedNetworkInterfaces) {
  26. this.disconnect(networkInterface);
  27. }
  28. }
  29. },

gecko/koost/telephony/TelephonyBinderService.h

  1. // Cover the GECKO_RADIO_TECH to NETWORK_TYPE_*
  2. int32_t convertRadioTech(const nsAString& rat);

4、apn_editor_const.js 原始数据和 UI显示转换

KaiOS 基线提供了VALUE_CONVERTERS 常量对象,包含两个属性:TO_STRING和TO_DATA,每个属性包含了转换方法。

  • TO_STRING:将一个字符串数组转换成一个用逗号分隔的字符串
    • apn_editor.js 界面显示用
  • TO_DATA :将一个用逗号分隔的字符串转换为一个字符串数组
    • apn_editor_session.js 保存数据库用

源码如下,可参考APN Type显示的内容,对数组进行显示和配置数据存储。

  1. /**
  2. * The apn editor const
  3. */
  4. define([],() => {
  5. const APN_PROPERTY_DEFAULTS = {
  6. //省略大部分原生属性
  7. apn: '',
  8. types: ['default'],
  9. roaming_protocol: 'notDefined',
  10. //自定义
  11. mvno_type: 'notDefined',
  12. mvno_match_data: '',
  13. bearer:['unspecified']
  14. };
  15. const APN_PROPERTIES = Object.keys(APN_PROPERTY_DEFAULTS);
  16. //数据转换工具接口
  17. const VALUE_CONVERTERS = {
  18. TO_STRING: { //TO_STRING属性
  19. types(types) {
  20. //判断 types参数存在、是一个数组、且数组非空,就将字符串数组转换成用逗号分隔的字符串
  21. // types :参数是否存在
  22. // Array.isArray(types):是否为一个数组
  23. // types.length:数组是否非空
  24. if (types && Array.isArray(types) && types.length) {
  25. return types.join(', ');
  26. }
  27. return 'default'; //默认返回“default”
  28. }
  29. },
  30. TO_DATA: { //TO_DATA属性
  31. types(string) {
  32. //将用逗号分隔的字符串转换为字符串数组
  33. return string.split(',').map(str => str.trim());
  34. }
  35. }
  36. };
  37. //在apn_editor.js中定义了常量调用方法,APN_PROPERTIES、APN_PROPERTY_DEFAULTS、VALUE_CONVERTERS
  38. return { //一个对象,三个只读get属性?外部访问但不能修改他们的值?
  39. get APN_PROPERTIES() {
  40. return APN_PROPERTIES;
  41. },
  42. get APN_PROPERTY_DEFAULTS() {
  43. return APN_PROPERTY_DEFAULTS;
  44. },
  45. get VALUE_CONVERTERS() {
  46. return VALUE_CONVERTERS;
  47. }
  48. };
  49. });
(1)测试代码

 对以上接口VALUE_CONVERTERS的测试代码和解析,输出案例 :

  1. const types = ['gprs', 'edge', 'umts'];
  2. const str = VALUE_CONVERTERS.TO_STRING.types(types);
  3. console.log(str); // 输出 'gprs, edge, umts'
  4. const str = 'gprs, edge, umts';
  5. const types = VALUE_CONVERTERS.TO_DATA.types(str);
  6. console.log(types); // 输出 ['gprs', 'edge', 'umts']
(2)apn_editor.js 调用TO_STRING 界面显示

外部模块调用源码实现

  1. /**
  2. * The apn editor module
  3. */
  4. 'use strict';
  5. define(function(require) { //eslint-disable-line
  6. const ApnEditorConst = require('panels/apn_editor/apn_editor_const');
  7. const ApnEditorSession = require('panels/apn_editor/apn_editor_session');
  8. //引用apn_editor_const.js 定义常量
  9. const { APN_PROPERTIES } = ApnEditorConst;
  10. const { APN_PROPERTY_DEFAULTS } = ApnEditorConst;
  11. const { VALUE_CONVERTERS } = ApnEditorConst;
  12. ApnEditor.prototype = {
  13. convertValue(value, converter) {
  14. if (converter) {
  15. return converter(value);
  16. }
  17. return value;
  18. },
  19. fillInputElements(inputElements, apn) {
  20. APN_PROPERTIES.forEach(function input(name) {
  21. const inputElement = inputElements[name];
  22. if (inputElement) {
  23. //数据处理,调用VALUE_CONVERTERS 转成字符串
  24. inputElement.value = this.convertValue(
  25. value,
  26. VALUE_CONVERTERS.TO_STRING[name]
  27. );
  28. } //if inputElement
  29. }, this);
  30. },
  31. });
(3)apn_editor_session.js 保存信息到APN数据库

在commit 中保存APN到,通过apn manager执行addApn或 updateApn

  1. /**
  2. * The apn editor session module
  3. */
  4. define(['require','modules/apn/apn_settings_manager','panels/apn_editor/apn_editor_const','modules/apn/apn_utils'],function(require) { //eslint-disable-line
  5. const ApnSettingsManager = require('modules/apn/apn_settings_manager');
  6. const ApnEditorConst = require('panels/apn_editor/apn_editor_const');
  7. const ApnUtils = require('modules/apn/apn_utils');
  8. const { APN_PROPERTIES } = ApnEditorConst;
  9. const { VALUE_CONVERTERS } = ApnEditorConst;
  10. function ApnEditorSession(obj, inputElements, apnItem) {
  11. this.serviceId = obj.serviceId;
  12. this.apnMode = obj.mode;
  13. this.inputElements = inputElements;
  14. this.apnItem = apnItem;
  15. }
  16. ApnEditorSession.prototype = {
  17. convertValue(value, converter) {
  18. if (converter) {
  19. return converter(value);
  20. }
  21. return value;
  22. },
  23. exportApnSetting(inputElements) {
  24. const newApnSetting = {};
  25. APN_PROPERTIES.forEach(function input(name) {
  26. const inputElement = inputElements[name];
  27. if (inputElement && !inputElement.hidden) {
  28. newApnSetting[name.toLowerCase()] = this.convertValue(
  29. inputElement.value,
  30. VALUE_CONVERTERS.TO_DATA[name]
  31. );
  32. }
  33. }, this);
  34. return newApnSetting;
  35. },
  36. //保存新增APN数据,调用addApn
  37. commitNew() {
  38. const promises = [];
  39. const newApnSetting = this.exportApnSetting(this.inputElements);
  40. promises.push(ApnSettingsManager.addApn(this.serviceId, newApnSetting));
  41. return Promise.all(promises);
  42. },
  43. //保存编辑APN数据,调用updateApn
  44. commitEdit() {
  45. const promises = [];
  46. const newApnSetting = this.exportApnSetting(this.inputElements);
  47. promises.push(ApnSettingsManager.updateApn(this.serviceId,
  48. this.apnItem.id, newApnSetting));
  49. return Promise.all(promises);
  50. },
  51. //在apn_editor.js中传递 new/edit选择执行新增/编辑APN
  52. commit() {
  53. switch (this.apnMode) {
  54. case 'new':
  55. return this.commitNew();
  56. case 'edit':
  57. return this.commitEdit();
  58. default:
  59. console.error('invalid mode');
  60. return Promise.resolve();
  61. }
  62. },
  63. //取消,不保存任何数据
  64. cancel() {
  65. APN_PROPERTIES.forEach(function input(name) {
  66. this.inputElements[name].value = '';
  67. }, this);
  68. this.apnItem = null;
  69. },
  70. //还没找到mode的用法
  71. get mode() {
  72. return this.apnMode;
  73. }
  74. };
  75. return function apnEditorSession(obj, inputElements, apnItem) {
  76. return new ApnEditorSession(obj, inputElements, apnItem);
  77. };
  78. });

三、日志分析

追溯在PDN建立过程中,读取apn配置的bearer参数到DataCall使用的radio类型的bearer值变化情况。

四、方案开发

相关介绍:KaiOS 新增APN信息字段的代码实现-CSDN博客

在 APN Editor中实现bearer显示

代码模块:gaia/apps/settings/js/panels/apn_editor/apn_editor.js

  1. /**
  2. * The apn editor module
  3. */
  4. 'use strict';
  5. define(function(require) { //eslint-disable-line
  6. const ApnEditorConst = require('panels/apn_editor_tct/apn_editor_const');
  7. const ApnEditorSession = require('panels/apn_editor_tct/apn_editor_session');
  8. const ApnUtils = require('modules/apn_tct/apn_utils');
  9. //以下三个常量都是从ApnEditorConst模块中导入的
  10. const { APN_PROPERTIES } = ApnEditorConst;
  11. const { APN_PROPERTY_DEFAULTS } = ApnEditorConst;
  12. const { VALUE_CONVERTERS } = ApnEditorConst;
  13. return function apnEditor(rootElement) {
  14. return new ApnEditor(rootElement);
  15. };
  16. });

(一)KaiOS

1、十进制bearer -> bitmask位码 & networkType字符

将kaios中十进制的bearer转换同Android原始配置的bitmask及映射网络类型字符串

  1. // 功能:将十进制bearer转换成1-20字符串(同Android)
  2. function bitmaskToString(aBearerBitmask) {
  3. if (aBearerBitmask == 0 || aBearerBitmask === undefined) {
  4. return 0;
  5. }
  6. let val = "";
  7. for (let i = 1; i < 20; i++) {
  8. if ((aBearerBitmask & (1 << (i - 1))) != 0) {
  9. val = val.concat(i + "|");
  10. }
  11. }
  12. return val;
  13. }
  14. //常量数组,定义rat。
  15. //最后一个数据到底要不要逗号?源码有,参考代码可以不用 —— 兼容性问题,新的会支持 ,
  16. const GECKO_RADIO_TECH = [
  17. null,
  18. "gprs",
  19. "edge",
  20. "umts",
  21. "is95a",
  22. "is95b",
  23. "1xrtt",
  24. "evdo0",
  25. "evdoa",
  26. "hsdpa",
  27. "hsupa",
  28. "hspa",
  29. "evdob",
  30. "ehrpd",
  31. "lte",
  32. "hspa+",
  33. "gsm",
  34. "tdscdma",
  35. "iwlan",
  36. "lte_ca",
  37. ];
  38. //将1-20的bitmask转换成对应的网络制式
  39. function bitmaskToRatString(aBitmask) {
  40. if (aBitmask == 0 || aBitmask === undefined) {
  41. return "unspecified";
  42. }
  43. let rat = "";
  44. let splitResult = aBitmask.split("|");
  45. console.log('splitResult = '+ splitResult);
  46. rat = splitResult.map(x => GECKO_RADIO_TECH[x]).join(",").slice(0,-1);
  47. //slice(startIndex,endIndex) 用于去掉最后一个逗号
  48. return rat;
  49. }
  50. // 测试代码
  51. let apnBearer = '312312'; //apn.json原始配置值
  52. let targetBearer; //1-20转换目标值
  53. let bearerString = '';
  54. if (apnBearer === undefined) {
  55. targetBearer = 0;
  56. } else {
  57. targetBearer = apnBearer;
  58. }
  59. bearerString = bitmaskToString(targetBearer);
  60. let ratString = bitmaskToRatString(bearerString);
  61. // 输出结果
  62. console.log('targetBearer = ' + targetBearer);
  63. console.log('bearerString = '+ bearerString);
  64. console.log('ratString = ' + ratString);

存在一个问题 ,在UI显示了rat的字符串,那么 commitEdit() 的时候会保存bearer为字符串,应该需要在apn_editor_session.js 中处理ApnSettings内容。

难点在于如何将gprs,edge,is95b,1xrtt 转换成bearer数值 ( bitmask=1|2|5|6 甚至是 十进制原文)

2、networktype字符 -> bitmask 位码

convertNetworkTypeToBitmask,将networktype字符串转换成bitmask(1|18|20格式)

  1. //映射表,包含了不同的网络类型和对应的数字码。
  2. const networkTypeMap = {
  3. "unspecified": "0",
  4. "gprs": "1",
  5. "edge": "2",
  6. "umts": "3",
  7. "is95a": "4",
  8. "is95b": "5",
  9. "1xrtt": "6",
  10. "evdo0": "7",
  11. "evdoa": "8",
  12. "hsdpa": "9",
  13. "hsupa": "10",
  14. "hspa": "11",
  15. "evdob": "12",
  16. "ehrpd": "13",
  17. "lte": "14",
  18. "hspa+": "15",
  19. "gsm": "16",
  20. "tdscdma": "17",
  21. "iwlan": "18",
  22. "lte_ca": "19"
  23. };
  24. //测试代码
  25. //一、简单程序
  26. let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"; //界面显示字符串包含多个网络类型,使用逗号分隔
  27. let networkTypes = bearerString.split(","); //string转换成字符串数组
  28. let bitCode = Array.from(networkTypes, bearerString => networkTypeMap[bearerString]); //将字符串数组转换成数字码数组
  29. let bitmask = bitCode.join("|");
  30. console.log("networkTypes = " + networkTypes);
  31. console.log("bitCode = " + bitCode);
  32. //二、改善,封装成接口调用
  33. //参数类型:字符串 "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"
  34. //let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+";
  35. function convertNetworkTypeToBitmask(aNetworkTypes) {
  36. let bitmask = '0'; //初始化为0和"0"的区别?
  37. if (aNetworkTypes == 0 || aNetworkTypes === undefined) {
  38. return 0;
  39. }
  40. //networkTypesArray是一个字符串数组,存储着多个网络类型的字符串,例如 ['gprs', 'edge']
  41. let networkTypesArray = aNetworkTypes.split(","); //字符串转成字符串数组
  42. //networkTypesBitCode是一个数字码数组,如[ '1', '2', '3' ]
  43. //映射函数对每个字符串进行转换,函数参数是每个字符串,它在映射表中对应的值就是所需bit位数字码
  44. //映射函数的代码为 aNetworkTypes => networkTypeMap[aNetworkTypes]
  45. let networkTypesBitCode = Array.from(networkTypesArray, aNetworkTypes => networkTypeMap[aNetworkTypes]); //字符串数组转换成功数字码
  46. bitmask = networkTypesBitCode.join("|");
  47. return bitmask;
  48. }
  49. console.log("bitmask(api) = " + convertNetworkTypeToBitmask(bearerString));

  1. //如果传参是数组,就更简单的封装接口了
  2. //接受一个包含网络类型的数组作为参数,并将这个数组中的每种网络类型转换为对应的数字码,
  3. //返回一个由数字码组成的字符串,使用"|"符号分隔,即bitmask
  4. //通过map()方法遍历这个数组,将每种网络类型转换为对应的数字码,存在codes数组
  5. //通过join()方法将codes数字码连接成字符串 ,用“|”符号分隔。
  6. function convertNetworkTypes(networkTypes) {
  7. const codes = networkTypes.map(type => networkTypeMap[type]);
  8. return codes.join("|");
  9. }
  10. const types = ["gprs", "edge", "is95b", "1xrtt"];
  11. const codeString = convertNetworkTypes(types); // "1|2|5|6"

3、networktype字符 -> 十进制bearer

用如下bitcode数组能便于转换成 bitmask位码和十进制,不能直接通过bitmask转换成十进制,即bitmask 位码 -> 十进制bearer

 bitcode = 1,2,3,9,10,11,14,15

  1. const NETWORK_TYPE_MAP = {
  2. "unspecified": "0",
  3. "gprs": "1",
  4. "edge": "2",
  5. "umts": "3",
  6. "is95a": "4",
  7. "is95b": "5",
  8. "1xrtt": "6",
  9. "evdo0": "7",
  10. "evdoa": "8",
  11. "hsdpa": "9",
  12. "hsupa": "10",
  13. "hspa": "11",
  14. "evdob": "12",
  15. "ehrpd": "13",
  16. "lte": "14",
  17. "hspa+": "15",
  18. "gsm": "16",
  19. "tdscdma": "17",
  20. "iwlan": "18",
  21. "lte_ca": "19"
  22. };
  23. //参数类型:字符串 "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"
  24. //let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+";
  25. function convertNetworkTypeToBitCode(aNetworkTypes) {
  26. console.log("convertBitcodeToBearer: aNetworkTypes = " + aNetworkTypes);
  27. let bitcode = '0';
  28. if (aNetworkTypes == 0 || aNetworkTypes === undefined) {
  29. return 0;
  30. }
  31. let networkTypesArray = aNetworkTypes.split(","); //字符串转成字符串数组
  32. bitcode = Array.from(networkTypesArray, aNetworkTypes => NETWORK_TYPE_MAP[aNetworkTypes]); //
  33. console.log("convertNetworkTypeToBitCode: bitcode = " + bitcode);
  34. return bitcode;
  35. }
  36. function convertBitCodeToBitmask(aBitCode) {
  37. let bitmask = aBitCode.join("|");
  38. console.log("convertBitCodeToBitmask: bitmask = " + bitmask);
  39. return bitmask;
  40. }
  41. function convertBitcodeToBearer(aBitCode) {
  42. let bearerDec = 0;
  43. let bearerBin =0;
  44. if (aBitCode == 0 || aBitCode === undefined) {
  45. return 0;
  46. }
  47. //parseInt((code).toString(2)) 是将数字 code转成二进制字符串
  48. bearerBin = aBitCode.map(code => parseInt(code).toString(2)).join(""); //转成二进制
  49. console.log("convertBitcodeToBearer: bearerBin = " + bearerBin);
  50. bearerDec = parseInt(bearerBin,2);//将二进制转换成十进制 。
  51. console.log("convertBitcodeToBearer: bearerDec = " + bearerDec);
  52. return bearerDec;
  53. }
  54. let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"; //界面显示字符串包含多个网络类型,使用逗号分隔
  55. convertBitCodeToBitmask(convertNetworkTypeToBitCode(bearerString));
  56. convertBitcodeToBearer(convertNetworkTypeToBitCode(bearerString));

bearerBin  存在问题,在bitcode 转成20位二进制数的时候,输出的bearerBin 不正确

优化以上代码:

  1. function convertNetworkTypeToBearer(aNetworkTypes) {
  2. dump('apn_editor_session: StringToBearer aNetworkTypes = ' + aNetworkTypes);
  3. if (aNetworkTypes == 0 || aNetworkTypes === undefined) {
  4. return 0;
  5. }
  6. let bitcode = '0';
  7. let bearerBin = "";
  8. let bearer = 0;
  9. let networkTypesArray = aNetworkTypes.split(",");
  10. bitcode = Array.from(networkTypesArray, aNetworkTypes => NETWORK_TYPE_MAP[aNetworkTypes]); //bitcode array like [18,14]
  11. bitcode = bitcode.sort(function(a, b) {
  12. return a - b;
  13. });
  14. dump('apn_editor_session: StringToBearer bitcode = ' + bitcode);
  15. let bearerArray = new Array(20).fill(0);
  16. for (let i = 0; i < bitcode.length; i++) {
  17. bearerArray[bitcode[i]-1] = 1;
  18. dump('apn_editor: StringToBearer bitcode[i] = ' + bitcode[i]);
  19. }
  20. dump('apn_editor_session: StringToBearer bearerArray = ' + bearerArray);
  21. bearerBin = bearerArray.reverse().join("");
  22. bearer = parseInt(bearerBin,2);
  23. dump('apn_editor_session: StringToBearer bearer = ' + bearer);
  24. return bearer;
  25. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/138935
推荐阅读
相关标签
  

闽ICP备14008679号