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

一、参数说明

(一)APN配置结构对比

平台AndroidKaiOS
文件类型xmljson
结构每个<apn>标签是一条APN,包含完成的信息层级数组结构,使用JSON格式的数据。最外层是mcc,其次mnc,最后APN用数组形式配置(每个APN都是一个对象,不含mccmnc属性)。
Android: apns-conf.xml
<!-- Android: apns-conf.xml -->
<?xml version="1.0" encoding="utf-8"?>
<apns version="8"><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"/>
</apns>
KaiOS: apns.json

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

{
"202": {"10": [{"carrier":"Wind Internet","apn":"gint.b-online.gr","type":["default","supl"]},{"voicemail":"122","type":["operatorvariant"]},{"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"]}],"01": [{"carrier":"Cosmote Wireless Internet","apn":"","type":["ia"]},{"voicemail":"123","type":["operatorvariant"]},{"carrier":"Cosmote Wireless Internet","apn":"internet","type":["default","supl"]},{"carrier":"Cosmote Mms","apn":"mms","mmsc":"http://mmsc.cosmote.gr:8002","mmsproxy":"10.10.10.20","mmsport":"8080","type":["mms"]}],"09": [{"carrier":"Q Internet","apn":"myq","type":["default","supl"]},{"voicemail":"122","type":["operatorvariant"]},{"carrier":"Q-Telecom MMS GPRS","apn":"q-mms.myq.gr","mmsc":"http://mms.myq.gr","mmsproxy":"192.168.80.134","mmsport":"8080","type":["mms"]}]
},
"001": {"01": [{"carrier":"Testing SIM default","apn":"test","type":["default"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true"},{"carrier":"IMS","apn":"ims","type":["ims"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true"},{"carrier":"XCAP","apn":"xcap","type":["xcap"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true","authtype":"0"}]
}
}

(二)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

//DataCallManager.jsm//检查对应的rat是否包含在此APN bearer 配置中
// Check rat value include in the bit map or not.
function bitmaskHasTech(aBearerBitmask, aRadioTech) {if (aBearerBitmask == 0) {return true;} else if (aRadioTech > 0) {return (aBearerBitmask & (1 << (aRadioTech - 1))) != 0;}return false;
}//bearer十进制转成二进制
// Show the detail rat type.
function bitmaskToString(aBearerBitmask) {if (aBearerBitmask == 0 || aBearerBitmask === undefined) {return 0;}let val = "";for (let i = 1; i < RIL.GECKO_RADIO_TECH.length; i++) {if ((aBearerBitmask & (1 << (i - 1))) != 0) {val = val.concat(i + "|");}}return val;
}function bearerBitmapHasCdma(aBearerBitmask) {return (RIL_RADIO_CDMA_TECHNOLOGY_BITMASK & aBearerBitmask) != 0;
}

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文件中的代码创建和初始化的。

//DataCallManaer.jsm"use strict";//XPCOM 是一个用于 实现跨语言组件的技术框架。
//导入XPCOMUtils对象(工具库),简化和封装XPCOM组件的开发和使用。
//使用常量const来定义 XPCOMUtils 对象,以确保在运行时不会发生对象被重新赋值的情况。
const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"
);//定义RIL对象,后续调用 RIL.GECKO_RADIO_TECH
XPCOMUtils.defineLazyGetter(this, "RIL", function() {return ChromeUtils.import("resource://gre/modules/ril_consts.js");
});//ref RIL.GECKO_RADIO_TECH
const TCP_BUFFER_SIZES = [null,"4092,8760,48000,4096,8760,48000", // gprs"4093,26280,70800,4096,16384,70800", // edge"58254,349525,1048576,58254,349525,1048576", // umts"16384,32768,131072,4096,16384,102400", // is95a = 1xrtt"16384,32768,131072,4096,16384,102400", // is95b = 1xrtt"16384,32768,131072,4096,16384,102400", // 1xrtt"4094,87380,262144,4096,16384,262144", // evdo0"4094,87380,262144,4096,16384,262144", // evdoa"61167,367002,1101005,8738,52429,262114", // hsdpa"40778,244668,734003,16777,100663,301990", // hsupa = hspa"40778,244668,734003,16777,100663,301990", // hspa"4094,87380,262144,4096,16384,262144", // evdob"131072,262144,1048576,4096,16384,524288", // ehrpd"524288,1048576,2097152,262144,524288,1048576", // lte"122334,734003,2202010,32040,192239,576717", // hspa+"4096,87380,110208,4096,16384,110208", // gsm (using default value)"4096,87380,110208,4096,16384,110208", // tdscdma (using default value)"122334,734003,2202010,32040,192239,576717", // iwlan"122334,734003,2202010,32040,192239,576717", // ca
];//定义了一个常量RIL_RADIO_CDMA_TECHNOLOGY_BITMASK,用于表示CDMA射频技术类型的掩码值。
//RIL.GECKO_RADIO_TECH.indexOf 查找各个CDMA技术类型在GECKO_RADIO_TECH数组中的下标值,
//-1 的目的是得到对应的掩码位数,并将此转换成掩码值,
//使用按位左移(<<)运算符得到掩码值,
//各个掩码值按位或(|)操作得到最终的掩码值。
const RIL_RADIO_CDMA_TECHNOLOGY_BITMASK =(1 << (RIL.GECKO_RADIO_TECH.indexOf("is95a") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("is95b") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("1xrtt") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("evdo0") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("evdoa") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("evdob") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("ehrpd") - 1));// set to true in ril_consts.js to see debug messages
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数组的元素和顺序:

//GECKO_RADIO_TECH 数组定义射频技术(网络连接)
this.GECKO_RADIO_TECH = [null,"gprs",     //1 GPRS"edge",     //2 EDGE"umts",     //3 UMTS"is95a",    //4 IS-95A"is95b",    //5 IS-95B"1xrtt",    //6 cdma1x?一种CDMA2000射频技术,是CDMAOne技术的升级版(1x Radio Transmission Technology)"evdo0",    //7 EVDO-0"evdoa",    //8 EVDO-A"hsdpa",    //9"hsupa",    //10"hspa",     //11"evdob",    //12 EVDO-B"ehrpd",    //13 EVDO-D"lte",      //14 LTE"hspa+",    //15 HSPA+"gsm",      //16 GSM"tdscdma",  //17 TD-SCDMA"iwlan",    //18 iWLAN(wifi)"lte_ca",   //19 LTE_CA
];//定义遵循的协议类型
this.GECKO_PROFILE_INFO_TYPE_COMMON = 0;
this.GECKO_PROFILE_INFO_TYPE_3GPP = 1;
this.GECKO_PROFILE_INFO_TYPE_3GPP2 = 2;
3、DataCall 对 rat 的使用案例
  dataRegistrationChanged(aRadioTech) {let targetBearer;if (this.apnSetting.bearer === undefined) {targetBearer = 0;} else {targetBearer = this.apnSetting.bearer;}if (DEBUG) {this.debug("dataRegistrationChanged: targetBearer: " +bitmaskToString(targetBearer));}if (bitmaskHasTech(targetBearer, aRadioTech)) {// Ignore same rat type. Let handler process the retry.} else {if (DEBUG) {this.debug("dataRegistrationChanged: current APN do not support this rat reset DC. APN:" +JSON.stringify(this.apnSetting));// Clean the requestedNetworkInterfaces due to current DC can not support this rat under DC retrying state.// Let handler process the retry.let targetRequestedNetworkInterfaces = this.requestedNetworkInterfaces.slice();for (let networkInterface of targetRequestedNetworkInterfaces) {this.disconnect(networkInterface);}}},

gecko/koost/telephony/TelephonyBinderService.h

// Cover the GECKO_RADIO_TECH to NETWORK_TYPE_*
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显示的内容,对数组进行显示和配置数据存储。

/*** The apn editor const*/define([],() => {const APN_PROPERTY_DEFAULTS = {//省略大部分原生属性apn: '',types: ['default'],roaming_protocol: 'notDefined',//自定义mvno_type: 'notDefined',mvno_match_data: '',bearer:['unspecified']};const APN_PROPERTIES = Object.keys(APN_PROPERTY_DEFAULTS);//数据转换工具接口const VALUE_CONVERTERS = {TO_STRING: { //TO_STRING属性types(types) {//判断 types参数存在、是一个数组、且数组非空,就将字符串数组转换成用逗号分隔的字符串// types :参数是否存在// Array.isArray(types):是否为一个数组// types.length:数组是否非空if (types && Array.isArray(types) && types.length) {return types.join(', ');}return 'default'; //默认返回“default”}},TO_DATA: { //TO_DATA属性types(string) {//将用逗号分隔的字符串转换为字符串数组return string.split(',').map(str => str.trim());}}};//在apn_editor.js中定义了常量调用方法,APN_PROPERTIES、APN_PROPERTY_DEFAULTS、VALUE_CONVERTERSreturn { //一个对象,三个只读get属性?外部访问但不能修改他们的值?get APN_PROPERTIES() {return APN_PROPERTIES;},get APN_PROPERTY_DEFAULTS() {return APN_PROPERTY_DEFAULTS;},get VALUE_CONVERTERS() {return VALUE_CONVERTERS;}};
});
测试代码

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

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

外部模块调用源码实现

/*** The apn editor module*/
'use strict';
define(function(require) { //eslint-disable-lineconst ApnEditorConst = require('panels/apn_editor/apn_editor_const');const ApnEditorSession = require('panels/apn_editor/apn_editor_session');//引用apn_editor_const.js 定义常量const { APN_PROPERTIES } = ApnEditorConst;const { APN_PROPERTY_DEFAULTS } = ApnEditorConst;const { VALUE_CONVERTERS } = ApnEditorConst;ApnEditor.prototype = {convertValue(value, converter) {if (converter) {return converter(value);}return value;},fillInputElements(inputElements, apn) {APN_PROPERTIES.forEach(function input(name) {const inputElement = inputElements[name];if (inputElement) {//数据处理,调用VALUE_CONVERTERS 转成字符串inputElement.value = this.convertValue(value,VALUE_CONVERTERS.TO_STRING[name]);} //if inputElement}, this);},});

三、日志分析

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

四、方案开发

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

在 APN Editor中实现bearer显示

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

/*** The apn editor module*/
'use strict';
define(function(require) { //eslint-disable-lineconst ApnEditorConst = require('panels/apn_editor_tct/apn_editor_const');const ApnEditorSession = require('panels/apn_editor_tct/apn_editor_session');const ApnUtils = require('modules/apn_tct/apn_utils');//以下三个常量都是从ApnEditorConst模块中导入的const { APN_PROPERTIES } = ApnEditorConst;const { APN_PROPERTY_DEFAULTS } = ApnEditorConst;const { VALUE_CONVERTERS } = ApnEditorConst;return function apnEditor(rootElement) {return new ApnEditor(rootElement);};
});

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

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

// 功能:将十进制bearer转换成1-20字符串(同Android)
function bitmaskToString(aBearerBitmask) {if (aBearerBitmask == 0 || aBearerBitmask === undefined) {return 0;}let val = "";for (let i = 1; i < 20; i++) {if ((aBearerBitmask & (1 << (i - 1))) != 0) {val = val.concat(i + "|");}}return val;
}//常量数组,定义rat。
//最后一个数据到底要不要逗号?源码有,参考代码可以不用 —— 兼容性问题,新的会支持 ,
const GECKO_RADIO_TECH = [null,"gprs","edge","umts","is95a","is95b","1xrtt","evdo0","evdoa","hsdpa","hsupa","hspa","evdob","ehrpd","lte","hspa+","gsm","tdscdma","iwlan","lte_ca",
];//将1-20的bitmask转换成对应的网络制式
function bitmaskToRatString(aBitmask) {if (aBitmask == 0 || aBitmask === undefined) {return "unspecified";}let rat = "";let splitResult = aBitmask.split("|");console.log('splitResult = '+ splitResult);rat = splitResult.map(x => GECKO_RADIO_TECH[x]).join(",").slice(0,-1);//slice(startIndex,endIndex) 用于去掉最后一个逗号return rat;
}// 测试代码
let apnBearer = '312312';  //apn.json原始配置值
let targetBearer;  //1-20转换目标值
let bearerString = '';if (apnBearer === undefined) {targetBearer = 0;
} else {targetBearer = apnBearer;
}bearerString = bitmaskToString(targetBearer);
let ratString = bitmaskToRatString(bearerString);// 输出结果
console.log('targetBearer = ' + targetBearer);
console.log('bearerString = '+ bearerString);
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格式)

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

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

const NETWORK_TYPE_MAP = {"unspecified": "0","gprs": "1","edge": "2","umts": "3","is95a": "4","is95b": "5","1xrtt": "6","evdo0": "7","evdoa": "8","hsdpa": "9","hsupa": "10","hspa": "11","evdob": "12","ehrpd": "13","lte": "14","hspa+": "15","gsm": "16","tdscdma": "17","iwlan": "18","lte_ca": "19"
};//参数类型:字符串 "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"
//let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"; 
function convertNetworkTypeToBitCode(aNetworkTypes) {console.log("convertBitcodeToBearer: aNetworkTypes = " + aNetworkTypes);let bitcode = '0';if (aNetworkTypes == 0 || aNetworkTypes === undefined) {return 0;}let networkTypesArray = aNetworkTypes.split(","); //字符串转成字符串数组bitcode = Array.from(networkTypesArray, aNetworkTypes => NETWORK_TYPE_MAP[aNetworkTypes]); //  console.log("convertNetworkTypeToBitCode: bitcode = " + bitcode);return bitcode;
}function convertBitCodeToBitmask(aBitCode) {let bitmask = aBitCode.join("|");console.log("convertBitCodeToBitmask: bitmask = " + bitmask);return bitmask;
}function convertBitcodeToBearer(aBitCode) {let bearerDec = 0;let bearerBin =0;if (aBitCode == 0 || aBitCode === undefined) {return 0;}bearerBin = aBitCode.map(code => parseInt(code).toString(2)).join(""); //转成二进制console.log("convertBitcodeToBearer: bearerBin = " + bearerBin);bearerDec = parseInt(bearerBin,2);//将二进制转换成十进制 。console.log("convertBitcodeToBearer: bearerDec = " + bearerDec);return bearerDec;
}let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"; //界面显示字符串包含多个网络类型,使用逗号分隔convertBitCodeToBitmask(convertNetworkTypeToBitCode(bearerString));
convertBitcodeToBearer(convertNetworkTypeToBitCode(bearerString));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/693237.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java使用企业邮箱发送预警邮件

前言&#xff1a;最近接到一个需求&#xff0c;需要根据所监控设备的信息&#xff0c;在出现问题时发送企业微信进行预警。 POM依赖 <!-- 邮件 --> <dependency><groupId>com.sun.mail</groupId><artifactId>jakarta.mail</artifactId>…

【C++】C++11下线程库

C11下线程库 1. thread类的简单介绍2.线程函数参数3.原子性操作库(atomic)4.mutex的种类5. RAII风格加锁解锁5.1Lock_guard5.2unique_lock 6.condition_variable 1. thread类的简单介绍 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如wi…

Android | ArcGIS入门

一、概述 ArcGIS是由Esri开发的地理信息系统&#xff08;GIS&#xff09;软件。它用于制图、空间分析和数据可视化。ArcGIS允许用户以各种格式创建、管理、分析和共享地理信息。它通常用于城市规划、环境管理和应急响应等领域。该软件包括一系列工具&#xff0c;用于创建地图、…

新年新方案,制造业数字化经营管理平台方案全新升级

伴随着工业4.0和中国智造2025成为制造业领域的两大重要趋势&#xff0c;“推动制造业智能化改造数字化转型”已经到了“不得不”的阶段。 数字化转型能够为制造企业带来降本增效、扩能提质、优化流程、提升竞争力等优势&#xff0c;是建设现代化产业体系的必经之路。 然而&…

CVE-2016-3088(ActiveMQ任意文件写入漏洞)

漏洞描述 1、漏洞编号&#xff1a;CVE-2016-3088 2、影响版本&#xff1a;Apache ActiveMQ 5.x~5.13.0 在 Apache ActiveMQ 5.12.x~5.13.x 版本中&#xff0c;默认关闭了 fileserver 这个应用&#xff08;不过&#xff0c;可以在conf/jetty.xml 中开启&#xff09;&#xff1b;…

【python】linux系统python报错“ssl module in Python is not available”

一、问题现象 1.1 执行pip命令报错 pip安装时遇到openssl问题&#xff0c;没办法安装第三方库 “WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. ” 1.2 导入import ssl 报错 直接执行python&…

C/C++ BM14 链表的奇偶重排

文章目录 前言题目解决方案一1.1 思路阐述1.2 源码 解决方案二2.1 思路阐述2.2 源码 总结 前言 这道题算是链表思路的一种常规题&#xff0c;看透题目本质做起来还是不难。 题目 描述 给定一个单链表&#xff0c;请设定一个函数&#xff0c;将链表的奇数位节点和偶数位节点分…

电脑开机蓝屏错误代码c000021a怎么办 电脑蓝屏报错c000021a的解决办法

很多小伙伴在电脑开机的时候出现蓝屏代码c000021a都不知道该怎么去解决&#xff0c;所以今天就给你们带来了c000021a蓝屏解救方法&#xff0c;如果你还没解决的话就快来看看吧。 解决办法&#xff1a; 原因&#xff1a; c000021a蓝屏的原因有很多&#xff0c;主要有以下几种…

四非保研之旅

大家好&#xff0c;我是工藤学编程&#xff0c;虽有万分感概&#xff0c;但是话不多说&#xff0c;先直接进入正题&#xff0c;抒情环节最后再说&#xff0c;哈哈哈 写在开头 我的分享是来给大家涨信心的&#xff0c;网上的大佬们都太强了&#xff0c;大家拿我涨涨信心&#…

Spring Framework

Spring Framework Spring 是一款开源的轻量级 Java 开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。 Spring 框架指的都是 Spring Framework&#xff0c;它是很多模块的集合&#xff0c;如下图所示&#xff1a; 一、Core Container Spring 框架的核心模…

Samba是什么?有什么作用?工作流程以及如何搭建

前言&#xff1a; 寒假在家学习Linux近一个月了&#xff0c;最近参加了嘉立创组织的泰山派训练营&#xff0c;从中了解到了现在Linux开发中很方便的一些开发方式和工具。例如&#xff1a;使用MobaXterm终端通过SSH登陆ubuntu服务器进行开发&#xff1b;安装一个FileZilla工具通…

定制线缆厂家推荐:赋能科技互联,精工电联的集成线缆定制服务(小批量、多品类产品高效解决方案)

定制线缆 精工电联&#xff1a;赋能科技互联&#xff0c;精工电联的集成线缆定制服务&#xff08;小批量、多品类产品高效解决方案&#xff09; 随着科技的飞速发展&#xff0c;人们对数据传输速度和稳定性的需求日益增强。精工电联作为高科技智能化产品及自动化设备专用连接线…

第二证券:汽车产业链股爆发,中通客车涨停,星源卓镁等大涨

轿车产业链股21日盘中强势拉升&#xff0c;截至发稿&#xff0c;华阳变速涨超29%&#xff0c;星源卓镁涨超15%&#xff0c;德迈仕涨逾10%&#xff0c;中捷精工、中通客车、合力科技、圣龙股份等涨停。 行业方面&#xff0c;中国轿车工业协会近来公布数据显示&#xff0c;1月&a…

【快速搞定Webpack5】介绍及基本使用(一)

webpack 是一个静态资源打包工具。 他会以一个或多个文件作为打包的入口&#xff0c;将我们整个项目所有文件编译组合成一个或多个文件输出出去。 输出的文件就是编译好的文件&#xff0c;就可以在浏览器端运行了。 我们将 webpack 输出的文件叫做 bundle 。 (将浏览器不识别的…

wo-gradient-card是一款采用uniapp实现的透明辉光动画卡片

采用uniapp-vue3实现&#xff0c;透明辉光动画卡片&#xff0c;卡片内容包含标签、标题、副标题、图片 支持H5、微信小程序&#xff08;其他小程序未测试过&#xff0c;可自行尝试&#xff09; 可用于参考学习 可到插件市场下载尝试&#xff1a; https://ext.dcloud.net.cn/plu…

学习鸿蒙基础(5)

一、honmonyos的page路由界面的路径 新建了一个page,然后删除了。运行模拟器的时候报错了。提示找不到这个界面。原来是在路由界面没有删除这个page。新手刚接触找了半天才找到这个路由。在resources/base/profile/main_pages.json 这个和微信小程序好类似呀。 吐槽&#xf…

力扣精选算法100道——提莫攻击(模拟专题)

目录 &#x1f6a9;题目解析 &#x1f6a9;算法原理 &#x1f6a9;实现代码 &#x1f6a9;题目解析 输入&#xff1a;timeSeries [1,4], duration 2 输出&#xff1a;4 解释&#xff1a;提莫攻击对艾希的影响如下&#xff1a; - 第 1 秒&#xff0c;提莫攻击艾希并使其立即…

图片怎么转换格式jpg?轻松转换图片格式

图片怎么转换格式jpg&#xff1f;在数字化时代&#xff0c;图片作为信息传递的重要载体&#xff0c;其格式转换显得尤为重要。JPG作为一种广泛使用的图片格式&#xff0c;具有压缩比高、兼容性好等特点&#xff0c;深受用户喜爱。那么&#xff0c;如何将其他格式的图片轻松转换…

【41 Pandas+Pyecharts | 全国星巴克门店数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 计算营业时长2.4 营业时长区间 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 各省星巴克门店数量柱状图3.2 各省星巴克门…

【力扣hot100】刷题笔记Day7

前言 身边同学已经陆陆续续回来啦&#xff0c;舍友都开始投简历了&#xff0c;我也要加油啦&#xff01;刷完hot100就投&#xff01; 73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09; 标记数组&#xff1a;空间复杂度O(mn) class Solution:def setZeroes(self, matrix:…