From: DXY <1731678236@qq.com> Date: Thu, 30 May 2024 07:57:23 +0000 (+0800) Subject: 添加中国移动入库.py文件 china_mobile_dmp.py X-Git-Url: http://git.snicker.com.cn/Users/apple/Desktop/static/gitweb.css?a=commitdiff_plain;h=07a4673939b3f4a0c71fc2204ddb38c706ac94df;p=mirrors%2FFD230.git 添加中国移动入库.py文件 china_mobile_dmp.py --- diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/pyscript/china_mobile_dmp.py b/code/sdk/drivers/peripheral/slip/cat1Service/pyscript/china_mobile_dmp.py new file mode 100644 index 000000000..c79ae78f7 --- /dev/null +++ b/code/sdk/drivers/peripheral/slip/cat1Service/pyscript/china_mobile_dmp.py @@ -0,0 +1,548 @@ +import app_fota +from misc import Power +import modem +import ujson +import request +import ql_fs +import checkNet +import sys +import sim + +from queue import Queue +import usys +import _thread +import fota +import utime +import log +import uos +import osTimer +import net +import ql_fs +from ucryptolib import aes +import hashlib +from usr.EventMesh import eventMesh +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +fota_log = log.getLogger("china_mobile") +import modem +import base64 +import request +import ujson + +#中国移动入库 +class chinamobile: + def __init__(self): + self.retryIntervalTimer = osTimer()#异常重试定时器 + self.multiDayResend_timer = osTimer()#12小时定时器 多日重发的机制 + + self.multimer_count = 0#多日重发机制周期Count + self.multimer_init = 0 + self.power_on_multiflag = 0 + self.timer_count = 0 + self.timerPowerNum = 0 + self.telecom_init_state = 0#初始化状态开机检查标识 + self.isRegistOk = 0#注册成功 + + self.regist_queue = Queue() + _thread.stack_size(10*1024) + _thread.start_new_thread(self.regist_queue_thread, ()) + _thread.stack_size(8*1024) + + eventMesh.subscribe("publish_message_event_registinfor",self.publish_message_event_registinfor) + self.__net_connected = 0 + eventMesh.subscribe("get_network_state",self.get_network_state)#订阅消息 + eventMesh.subscribe("set_network_state",self.set_network_state)#订阅消息 + + eventMesh.subscribe("set_dev_version",self.set_dev_version)#订阅消息 + eventMesh.subscribe("get_dev_version",self.get_dev_version)#订阅消息 + + eventMesh.subscribe("set_dev_mac",self.set_dev_mac)#订阅消息 + eventMesh.subscribe("get_dev_mac",self.get_dev_mac)#订阅消息 + + self.regist_timeSec = 0 + self.iccid_data = "" + self.software_version = "" + self.mac_data ="" + + + self.retryInterval = 0#异常重试间隔时间 单位分钟 + self.retryNum = 0#异常重试最大次数 + self.heartBeatTime = 0#心跳上报频率 单位分钟 + self.reportTime = 0#最大上报频率 自注册+心跳上报的频率次数不能大于最大上报频率次数 + self.reportNum = 0 #最大上报次数 + + self.reportTime_old = 0 #保存本地 保存时间戳下一次开机使用 + self.report_Num_old = 0#保存本地 + self.retryNum_old = 0#保存本地 + self.init_flag = 0#初始化状态指初始化一次 + self.retryTimer = osTimer()#异常重试定时器 + self.retpoertTimerC = osTimer()#上报次数大于下一个周期再触发 + self.heartreportTimer = osTimer()#心跳上报定时器 + self.reportTime_Sec = 0 + + pass + def regist_queue_thread(self): + while True: + data = self.regist_queue.get() + #EventMesh.debug_log("regist_queue:data = {}".format(data)) + if data != None: + try: + data["func"](data["data"]) + except Exception as e: + print("regist_queue:ERROR:{}".format(e)) + usys.print_exception(e) + def publish_message_event_registinfor(self,event,msg): + self.regist_queue.put(msg) + + def publish_regist_event_cb(self, *args, **kwargs): + eventMesh.publish("publish_message_event_registinfor",{"func":self.timer_cb,"data":0}) + + def set_network_state(self,event,msg):#设置网络是否正常 + self.__net_connected = int(msg) + + def get_network_state(self,event,msg):#获取网络是否正常 + return self.__net_connected + + def set_dev_version(self,event,msg):#获取固件版本号 + self.software_version = str(msg) + + def get_dev_version(self,event,msg):#获取固件版本号 + return self.software_version + + def set_dev_mac(self,event,msg):#设置BLE MAC地址 + self.mac_data = str(msg) + + def get_dev_mac(self,event,msg):#获取BLE MAC地址 + return self.mac_data + + def sha256_encode(self,key,data):#对数据进行AES256加密 + h = hashlib.sha256() + h.update(key) + crypto_key = h.digest() + #IV是偏移量 默认16个十六进制00 + IV = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + crypto = aes(crypto_key, 2, IV) + + #进行PKCS7Padding填充。 + block_num = len(data) // BLOCK_SIZE+1 + k = len(data) % BLOCK_SIZE + j = len(data) // BLOCK_SIZE + padding = BLOCK_SIZE - k + i = 0 + szDataIn = bytearray(data) + # print(szDataIn) + szDataIn = szDataIn+bytearray(block_num * BLOCK_SIZE -len(data)) + # print(szDataIn) + + for i in range(padding): + szDataIn[j * BLOCK_SIZE + k + i] = padding + # print("szDataIn:{} {} {}\r\n".format(szDataIn,j * BLOCK_SIZE + k + i,padding)) + + indata = bytes(szDataIn) + enc = crypto.encrypt(indata) + #最后将加密AES256的数据转换成base64的编码格式 + msg_tmp = base64.b64encode(enc) + data_encode = msg_tmp.decode('ascii')#转换成字符串 + return data_encode + + + + def china_mobile_first_get_config(self,url): + ##############第一步#######获取采集规则配置####### + brand = "KUMI"#品牌 + + model = "Watch Soar"#型号 + appKey = "M100001131"#不需要就填***appKey 厂商标识 + sdkVersion = "***"#非SDK传输 + apiVersion = "4.0.1"#接口定义 固定4.0.1 + apiType = "I"#非Android + templateId = "TY000014"#根据产品分类在平台查询 + IMEI = modem.getDevImei() + imei1 = IMEI#IMEI1或者CMEI + imei2 = "***" + configType = "autoRegist"#自注册填autoRegist 心跳配置传输 keepAlive + preField1 = "***"#预留字段1 + preField2 = "***"#预留字段2 + preField3 = "***"#预留字段3 + + + + #配置拉取数据格式 + config_data = {"endpoint":"{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}".format(brand,model,appKey,sdkVersion,apiVersion,apiType,templateId,imei1,imei2,preField1,preField2,preField3),"configType":"{}".format(configType)} + + #配置拉取数据上报地址 + url = "https://b.fxltsbl.com//dm-multi-accept/multi/getMultiTerminalConfig" + headers_T ={"Content-Type":"application/json"} + print("ujson.dumps(config_data):{}".format(ujson.dumps(config_data))) + response = request.post(url, data=ujson.dumps(config_data),headers =headers_T) + result_json = "" + if response.status_code == 200:#服务器响应成功并返回数据 + content = response.content + c = next(content) + result_json = ujson.loads(c) + print("response.json:{}".format(ujson.loads(c))) + return result_json + + + def first_get_config_json(self):#开机上电获取配置信息 + getresult = 0 + if self.__net_connected != 1:#网络不正常 + return getresult + url = "https://b.fxltsbl.com//dm-multi-accept/multi/getMultiTerminalConfig" + result_json = self.china_mobile_first_get_config(url) + # { + # "reportTime":1440, + # "reportNum":8, + # "heartBeatTime":1440, + # "retryInterval":10, + # "retryNum":1 + # }#默认采集规则配置 + #默认参数 + + + if "rspCode" in result_json:#返回结课code 0000成功 其他参考文档 + rspCode = result_json["rspCode"] + rspCode_zh = result_json["rspMsg"] + if rspCode == "0000" or rspCode_zh == "成功": + getresult = 1 + if "result" in result_json: + msg_data = result_json["result"] #采集规则配置信息 + if "ruleConfig" in msg_data:#不存在就是空 + msg_data = msg_data["ruleConfig"] + + msg_data = ujson.loads(msg_data)#转换成json格式 + if "reportTime" in msg_data: + self.reportTime = int(msg_data["reportTime"]) + if "heartBeatTime" in msg_data: + self.heartBeatTime = int(msg_data["heartBeatTime"]) + if "reportNum" in msg_data: + self.reportNum = int(msg_data["reportNum"]) + if "retryInterval" in msg_data: + self.retryInterval = int(msg_data["retryInterval"]) + if "retryNum" in msg_data: + self.retryNum = int(msg_data["retryNum"]) + print(self.reportTime,self.heartBeatTime,self.reportNum,self.retryInterval,self.retryNum) + + print("true") + else: + print("false") + return getresult #1 获取成功 0 获取失败 + + + def china_mobile_autoregist_infor(self,url,configType_data): + #########################第二步############自注册上报################### + #设备自注册上报 + dev_autoregist_result = 0 #默认是1成功 0是失败 + if self.__net_connected != 1:#网络不正常 + return dev_autoregist_result + #密钥 + key = "f74c005251dc40c4b64a283827da3812" + + brand = "{}".format("KUMI")#品牌 + + model = "Watch Soar"#型号 + appKey = "M100001131"#不需要就填***appKey 厂商标识 + sdkVersion = "***"#非SDK传输 + apiVersion = "4.0.1"#接口定义 固定4.0.1 + apiType = "I"#非Android + templateId = "TY000014"#根据产品分类在平台查询 + IMEI = modem.getDevImei() + imei1 = IMEI#IMEI1或者CMEI + imei2 = "***" + configType = configType_data#自注册填autoRegist 心跳配置传输 keepAlive 暂时不用 + preField1 = "***"#预留字段1 + preField2 = "***"#预留字段2 + preField3 = "***"#预留字段3 + + #不需要加密 #||分隔符不能超过11个 否则平台会解析出错 + config_data = "{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}".format(brand,model,appKey,sdkVersion,apiVersion,apiType,templateId,imei1,imei2,configType,preField1,preField2) + + + #需要加密的数据明文 + if (len(self.mac_data) == 0)#获取失败了 + self.mac_data = "28:09:78:56:01:06" + + MAC = self.mac_data + # base64_MAC = sha256_encode(key,MAC) + RAM = "35MB" + # base64_RAM = sha256_encode(key,RAM) + ROM = "144MB" + # base64_ROM = sha256_encode(key,ROM) + CPU = "YH601S" + # base64_CPU = sha256_encode(key,CPU) + sysVersion = "OpenHarmony 3.2" + # base64_sysVersion = sha256_encode(key,sysVersion) + if (len(self.software_version) == 0)#获取失败了 + self.software_version = "Watch Soar V1.0" + softwareVer = self.software_version + # base64_softwareVer = sha256_encode(key,softwareVer) + softwareName ="FD230" + # base64_softwareName = sha256_encode(key,softwareName) + volte="0" #0:开;1:关;-1:不支持 + # base64_volte = sha256_encode(key,volte) + netType="4G" + # base64_netType = sha256_encode(key,netType) + + resolution="466*466" + # base64_resolution = sha256_encode(key,resolution) + + screenSize = "1.43" + # base64_screenSize = sha256_encode(key,screenSize) + wearingStatus ="***" + # base64_wearingStatus = sha256_encode(key,wearingStatus) + + networkStatus ="0"#1:连接;0:未连接;-1:不支持 + # base64_networkStatus = sha256_encode(key,networkStatus) + encyr_data = [MAC,RAM,ROM,CPU,sysVersion,softwareVer,softwareName,volte,netType,resolution,screenSize,wearingStatus,networkStatus] + print(len(encyr_data)) + encyr_new_data=[] + for i in range(len(encyr_data)): + tmp_data = sha256_encode(key,encyr_data[i]) + encyr_new_data.append(tmp_data) + + # deviceInfo_tmp = { + # "bluetoothMac":"{}".format(base64_MAC),#mac地址可填可不填 + # "ram":"{}".format(base64_RAM),#ram信息 + # "rom":"{}".format(base64_ROM),#rom信息 + # "cpu":"{}".format(base64_CPU),#cpu信息 + # "sysVersion":"{}".format(base64_sysVersion),#操作系统版本号 + # "softwareVer":"{}".format(base64_softwareVer),#固件版本号 + # "softwareName":"{}".format(base64_softwareName),#固件名称 + # "volte":"{}".format(base64_volte),#volte开关 默认是开 + # "netType":"{}".format(base64_netType),#当前网络类型4G + # "resolution":"{}".format(base64_resolution),#屏幕分辨率466*466 + # "screenSize":"{}".format(base64_screenSize),#屏幕尺寸默认1.43 + # "wearingStatus":"{}".format(base64_wearingStatus),#佩戴状态不支持 + # "networkStatus":"{}".format(base64_networkStatus)#网络状态 + + # } + deviceInfo_tmp = { + "bluetoothMac":"{}".format(encyr_new_data[0]),#mac地址可填可不填 + "ram":"{}".format(encyr_new_data[1]),#ram信息 + "rom":"{}".format(encyr_new_data[2]),#rom信息 + "cpu":"{}".format(encyr_new_data[3]),#cpu信息 + "sysVersion":"{}".format(encyr_new_data[4]),#操作系统版本号 + "softwareVer":"{}".format(encyr_new_data[5]),#固件版本号 + "softwareName":"{}".format(encyr_new_data[6]),#固件名称 + "volte":"{}".format(encyr_new_data[7]),#volte开关 默认是开 + "netType":"{}".format(encyr_new_data[8]),#当前网络类型4G + "resolution":"{}".format(encyr_new_data[9]),#屏幕分辨率466*466 + "screenSize":"{}".format(encyr_new_data[10]),#屏幕尺寸默认1.43 + "wearingStatus":"{}".format(encyr_new_data[11]),#佩戴状态不支持 + "networkStatus":"{}".format(encyr_new_data[12])#网络状态 + } + json_data = ujson.dumps(deviceInfo_tmp)#需要转义的字符串 + + send_autoregist = { + "endpoint":config_data, + "deviceInfo":"{}".format(json_data) + } + + test_data = ujson.dumps(send_autoregist)#需要转义的字符串 + print("test_data:{}".format(test_data)) + headers_T ={"Content-Type":"application/json"} + response = request.post(url, data=ujson.dumps(send_autoregist),headers =headers_T) + result_json = "" + + if response.status_code == 200: + dev_autoregist_result = 1 + content = response.content + c = next(content) + result_json = ujson.loads(c)#解析成json格式 + else: + + + if "rspCode" in result_json: + rspCode = result_json["rspCode"] + rspMsg = result_json["rspMsg"] + if rspCode == "0000" or rspMsg == "成功": + dev_autoregist_result = 1 + else: + dev_autoregist_result = 0 + else: + dev_autoregist_result = 0 + + return dev_autoregist_result + + def read_config_file(self):#获取配置文件,一开机是没有配置文件的 + self.retryInterval = 10 + self.retryNum = 1#异常重试最大次数 + self.heartBeatTime = 1440#心跳上报频率 单位分钟 + self.reportTime = 1440#最大上报频率 自注册+心跳上报的频率次数不能大于最大上报频率次数 + self.reportNum = 8 #最大上报次数 + msg = None + IFEXIST = ql_fs.path_exists("/usr/config_msg.json") #不存在 + if IFEXIST == True: + with open("/usr/config_msg.json","r",encoding='utf-8') as fd: + msg = ujson.loads(fd) + + if msg != None: + if "retryInterval" in msg: + self.retryInterval = int(msg["retryInterval"]) + if "retryNum" in msg: + self.retryNum = int(msg["retryNum"]) + if "heartBeatTime" in msg: + self.heartBeatTime = int(msg["heartBeatTime"]) + if "reportTime" in msg: + self.reportTime = int(msg["reportTime"]) + if "reportNum" in msg: + self.reportNum = int(msg["reportNum"]) + print("read_config_file:self.retryInterval:{} self.retryNum:{} self.heartBeatTime:{} self.reportTime:{} self.reportNum:{}".format(self.retryInterval,self.retryNum,self.heartBeatTime,self.reportTime,self.reportNum)) + def retryTimerCb(self,*argc):#异常重试机制定时器回调 + self.retryNum_old+=1 #保存本地 + + if self.retryNum_old > self.retryNum: + self.retryTimer.stop() + return + #触发查询上报总数流程 + self.search_report_num_step() + pass + + def error_retryNum_step(self):#判读报错次数是否大于self.retryNum 步骤 + print("error_retryNum_step:self.retryNum_oldd:{} self.retryNum:{}".format(self.retryNum_old,self.retryNum)) + if self.retryNum_old > self.retryNum:#self.retryNum_old > 10 + self.retpoertTimerC.start(self.reportTime*60*1000,0,self.reportTimerIntervalCb) + else: + get_result = self.first_get_config_json()#发起向服务端请求配置信息下发到设备端 + if get_result != 1:#获取失败或者没有网络 走异常重试机制 + self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb) + pass + else:#清空报错次数 + self.retryNum_old = 0#保存本地 + data = { + "retryInterval":self.retryInterval, + "retryNum":self.retryNum, + "reportTime":self.reportTime, + "reportTime":self.reportTime, + "reportNum":self.reportNum + } + with open("/usr/config_msg.json", 'w+',encoding='utf-8') as fd:#写文件数据 + ujson.dump(data,fd) + #服务端注册返回成功 + #第一步触发自注册 + report_result = self.self_regis_report_cb() + + #第二步触发心跳上报次数 + if report_result == 1:#注册完成之后根据服务端下发的配置 间隔上报心跳 + self.heart_report_cb() + self.heartreportTimer.start(self.heartBeatTime*60*1000,1,self.heartreportTimerCb) + + self.heartreportTimerCb(self,*argc): + self.heart_report_cb() + + def check_current_time(self):#检测当前时间是否超过self.reportTime 超过清空报错次数 清空上报总次数 + # + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + if time_tmp < self.reportTime_old: + time_tmp = self.reportTime_old + if self.reportTime_old == 0: + self.reportTime_old = time_tmp + #self.reportTime = 20*60 + print("check_current_time:time_tmp - self.reportTime_old:{} self.reportTime*60:{}".format(time_tmp - self.reportTime_old,self.reportTime*60)) + if (time_tmp - self.reportTime_old) >= self.reportTime*60:#是否大于上报的时间self.reportTime 清空保存的上报总数 self.report_Num_old = 0 上报错误次数 self.retryNum_old = 0 + #大于一个周期时间需要等下一个周期触发 不能立马去检查 需要定时reportTime之后再去清空数据 + self.reportTime_Sec = time_tmp + self.retpoertTimerC.start(10*60*1000,1,self.retpoertTimerCB) + + else:#当前时间-旧的保存时间 小于reportTime 判断报错次数是否大于retryNum=10 + self.error_retryNum_step() + + def retpoertTimerCB(self,*argc): + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + if time_tmp - self.reportTime_Sec >= self.reportTime*60: + self.report_Num_old = 0#清空上报总次数 #保存本地 + self.retryNum_old = 0#清空上报错误次数 #保存本地 + + self.retpoertTimerC.stop()#关闭定时器 + self.error_retryNum_step()#清空报错次数重新走判断报错次数 + pass + + def search_report_num_step(self):#查询上报总数步骤 + print("search_report_num_step:self.retryInterval:{} self.retryNum:{}".format(self.report_Num_old,self.reportNum)) + if self.report_Num_old > self.reportNum:#查询上报的总次数是否大于存储上报总次数 + #答:报错次数过多,结束LWM2M是结束这次会话,ruleConfig有最大上报时间频率, + # reportTime字段,有最大上报次数,reportNum字段。表示最大上报时间频率内,不能超过最大上报次数, + # 如reportTime=10,reportNum=3表示10分钟内最大上报3次,如果超过3次,则需要等待10分钟之后再重新发起注册流程。 + #检查当前时间是否大于reportTimer 1440分钟之内最多上报8次 需要自注册上报或者心跳上报成功后保存当前的时间戳 如果下一个心跳间隔时间到了次数加1大于上报最大次数 + #用时间戳相减 大于 reportTimer就不上报了 就等下一个14440分钟了 + # + self.check_current_time()#检测当前时间是否超过self.reportTime 超过清空报错次数 清空上报总次数 + else:#读取报错次数 + self.error_retryNum_step() + + def reportTimerIntervalCb(self,*argc):#最大上报频率时间间隔定时器 + self.search_report_num_step()#重新查询 + + def self_regis_report_cb(self):#自注册上报信息 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + print("self_regis_report_cb:self.report_Num_old:{} self.reportNum:{}".format(self.report_Num_old,self.reportNum)) + self.report_Num_old+=1 ##保存本地 + if report_Num_old > self.reportNum: + + self.retryTimer.stop()#关定时器 + self.retpoertTimerC.stop() + self.heartreportTimer.stop() + self.reportTime_old = time_tmp #需要保存本地 + self.retpoertTimerC.start(self.reportTime*60*1000,0,self.reportTimerIntervalCb) + return 0 + self.reportTime_old = time_tmp #需要保存本地 + #设备自注册上报信息 + url = "https://b.fxltsbl.com//dm-multi-accept/multi/acceptMultiTerminalRegInfo"#上报地址 + confing_type = "autoRegist"#上报传输配置 + result = self.china_mobile_autoregist_infor(url,confing_type) + if result != 1: + #触发异常重试进制 + self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb) + return 0 + else: + return 1 + + def heart_report_cb(self):#心跳上报信息 + #设备心跳上报信息 + print("heart_report_cb:self.report_Num_old:{} self.reportNum:{}".format(self.report_Num_old,self.reportNum)) + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + self.report_Num_old+=1#保存本地 + if report_Num_old > self.reportNum: + self.retryTimer.stop()#关定时器 + self.retpoertTimerC.stop() + self.heartreportTimer.stop() + self.reportTime_old = time_tmp#需要保存本地 + + self.retpoertTimerC.start(self.reportTime*60*1000,0,self.reportTimerIntervalCb) + return + + url = "https://b.fxltsbl.com//dm-multi-accept/multi/acceptMultiTerminalHeartbeatInfo"#上报地址 + confing_type = "keepAlive"#上报传输配置 + result = self.china_mobile_autoregist_infor(url,confing_type) + if result != 1: + #触发异常重试进制 + self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb) + return + + def china_mobile_init(self):#初始化 + #读配置文件 + self.read_config_file()#只读一下配置文件 + #查询上报总数流程 + self.search_report_num_step() + + + + +chinamobileCb = chinamobile() + + + + + + + + + + + +