From: 孙春阳 Date: Thu, 18 Sep 2025 14:26:55 +0000 (+0800) Subject: 添加雷鸟EG810 固件 X-Git-Tag: leiniao_debug_1.0.0_20250922_020716~50 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=8ade8f970bf35e15deeeac486af4933d7df628b9;p=mirrors%2FFD230.git 添加雷鸟EG810 固件 --- diff --git a/cat1modem/leiniao/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0725_LN_PY_SRV_V23_20250918-2225.zip b/cat1modem/leiniao/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0725_LN_PY_SRV_V23_20250918-2225.zip new file mode 100644 index 000000000..87eb19b0a Binary files /dev/null and b/cat1modem/leiniao/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0725_LN_PY_SRV_V23_20250918-2225.zip differ diff --git a/cat1modem/src/LeiNiao/EventMesh.py b/cat1modem/src/LeiNiao/EventMesh.py new file mode 100644 index 000000000..7951835b2 --- /dev/null +++ b/cat1modem/src/LeiNiao/EventMesh.py @@ -0,0 +1,86 @@ +import _thread +import usys +import ql_fs +CHINA_TELECOM_DM_FUN_ENABLE = 1 #是否开启电信入库的功能 +CHINA_MOBILE_DM_FUN_ENABLE = 1 #开启移动入库功能 +class EventStore(object): + def __init__(self): + self.map = dict() + self.log = None + self.__filters = [] + + def add_filter(self, flt): + self.__filters.append(flt) + + def append(self, event, cb): + self.map[event] = cb + + def fire_async(self, event, msg,thread_size): + if event in self.map: + #print("fire_async:thread_size:{}".format(thread_size)) + if thread_size != None: + _thread.stack_size(thread_size) + #print("fire_async:thread_size:{}".format(thread_size)) + _thread.start_new_thread(self.map[event], (event, msg)) + if thread_size != None: + _thread.stack_size(8*1024) + if self.log: + self.log.info("ASYNC executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, None)) + + def fire_sync(self, event, msg): + res = None + try: + if event in self.map: + res = self.map[event](event, msg) + except Exception as e: + usys.print_exception(e) + if self.log: + self.log.info("ERROR executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, res)) + if event not in self.__filters: + if self.log: + self.log.info("SYNC executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, res)) + return res + + def subscribe(self,event, cb): + """ + subscribe event and cb + """ + return self.append(event, cb) + + + def publish(self,event, msg=None): + """ + publish event and msg + """ + return self.publish_sync(event, msg) + + + def publish_async(self,event, msg=None,thread_size = None): + """ + 异步发送 + """ + return self.fire_async(event, msg,thread_size) + + + def publish_sync(self,event, msg=None): + """ + 同步发送 + """ + return self.fire_sync(event, msg) + + + def set_log(self,log_adapter): + self,log = log_adapter + + + def add_filter(self,flt): + self.add_filter(flt) + +eventMesh = EventStore() + + + + + + + diff --git a/cat1modem/src/LeiNiao/cat1Service.py b/cat1modem/src/LeiNiao/cat1Service.py index 476be0ea2..3f2f47af2 100644 --- a/cat1modem/src/LeiNiao/cat1Service.py +++ b/cat1modem/src/LeiNiao/cat1Service.py @@ -81,7 +81,7 @@ sms.setCallback(msg_cb)#sms注册回调 CAT1_SERVICE_HEAD = 'FE' #固定head PROJECT_NAME = "Cat1SlipUDPService" -PROJECT_VERSION = "PY_SRV_V21" +PROJECT_VERSION = "PY_SRV_V23" CONFIG_JSON="/usr/system_config.json" CURRENT_APP_TYPE="pysrv" @@ -275,6 +275,7 @@ class Cat1Service: modem_ver = modem.getDevFwVersion() self.reply_cmd('0F',"BOOTUP@pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver)) self.reply_cmd('0F',"VOLUME:{}".format(voiceCall.getVolume())) + self.reply_cmd('0F',"PRODUCT:LEINIAO") def btmcu_cmd_handler(self,cmd,parm): diff --git a/cat1modem/src/LeiNiao/checkota.py b/cat1modem/src/LeiNiao/checkota.py new file mode 100644 index 000000000..e5ef1f1ae --- /dev/null +++ b/cat1modem/src/LeiNiao/checkota.py @@ -0,0 +1,150 @@ +import app_fota +from misc import Power +import modem +import ujson +import request +import ql_fs +import checkNet +import sys + +#远程升级 + +import fota +import utime +import log +import uos + +PROJECT_VERSION="PY_OTA_V14" +CONFIG_JSON="/usr/system_config.json" +CURRENT_APP_TYPE="pyota" +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +fota_log = log.getLogger("Fota") + + +def get_versionkeyname_by_py(app_type): + return str("{}version".format(app_type)) + +def get_default_versionvalue_by_py(app_type): + if (app_type == "pyota"): + return "PY_OTA_V13" + + +#如果没有configfile则创建它 +if not ql_fs.path_exists(CONFIG_JSON): + data = {str(get_versionkeyname_by_py(CURRENT_APP_TYPE)):get_default_versionvalue_by_py(CURRENT_APP_TYPE)} + try: + ql_fs.touch(CONFIG_JSON,data) + except Exception as e: + print("checkota 创建出错 {}".format(e)) + +def set_version_to_json_config(app_type,keyvalue): + try: + config_data = ql_fs.read_json(CONFIG_JSON) + config_data.update( {str(get_versionkeyname_by_py(app_type)):keyvalue}) + + ql_fs.touch(CONFIG_JSON, config_data) + print("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue)) + print("{}".format(config_data)) + except Exception as e: + print("checkota 创建出错 {}".format(e)) + +def get_version_from_json_config(app_type): + try: + config_data = ql_fs.read_json(CONFIG_JSON) + keyvalue = config_data.get( get_versionkeyname_by_py(app_type),get_default_versionvalue_by_py(app_type)) + print("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue)) + return keyvalue + except Exception as e: + print("get_version_from_json_config出错 {}".format(e)) + return "" + +def result(args): + print('download status:',args[0],'download process:',args[1]) + +def check_fota(): + modem_ver = modem.getDevFwVersion() + imei = modem.getDevImei() + url = "http://icfota.snicker.com.cn:8089/fd230ota.jsp?product=FD230&pkgver={0}&imei={1}".format(modem_ver,imei) + response = request.get(url) + print(url) + data = response.json() + if(data['UptoDate'] == False): + print("Need update python application") + fota_obj = fota() # 创建Fota对象 + print("httpDownload...") + srcurl = data['url'] + #差分升级方式 + # res = fota_obj.httpDownload(url1="http://www.example.com/fota.bin",callback=result) + # mini fota方式 + print("{},{}".format("{}/dfota_1.bin".format(srcurl),"{}/dfota_2.bin".format(srcurl))) + res = fota_obj.httpDownload(url1="{}/dfota_1.bin".format(srcurl),url2="{}/dfota_2.bin".format(srcurl),callback=result) + #差分升级FTP方式 + #res = fota_obj.httpDownload(url1="ftp://user:password@ip:port/fota.bin",callback=result) #其中user,password,ip,port需要填写具体使用的FTP服务器信息 + if res != 0: + print("httpDownload error") + return + print("wait httpDownload update...") + else: + print("No need update python application") + +def do_app_update_internal(app_type): + fota = app_fota.new() + imei = modem.getDevImei() + pythonversion=get_version_from_json_config(app_type) + url = "http://icfota.snicker.com.cn:8089/fd230ota.jsp?product=FD230&pkgver={0}&imei={1}".format(pythonversion,imei) + try: + response = request.get(url) + print(url) + data = response.json() + if data['UptoDate'] == False: + print("Need update python application {}".format(data["appcount"])) + for app_update in data["apps"]: + srcurl = app_update['url'] + print("run start...") + targetpyname = app_update['OtaPackageName'] + version = app_update['OtaPackageVersion'] + tmpfile_path = "/usr/.updater/{}".format(targetpyname) + targetfile_path = "/usr/{}".format(targetpyname) + print("download {0} to {1}".format(srcurl,targetfile_path)) + if ql_fs.path_exists(tmpfile_path): + try: + uos.remove(tmpfile_path) + except Exception as e: + print("update remove出错 {}".format(e)) + ret = fota.download(srcurl,targetpyname) + if ret == 0 : + try: + ql_fs.file_copy(targetfile_path, tmpfile_path) + set_version_to_json_config(app_type,version) + print("ota success") + if ql_fs.path_exists(tmpfile_path): + try: + uos.remove(tmpfile_path) + except Exception as e: + print("update remove出错 {}".format(e)) + except Exception as e: + print("ota failed!") + else: + print("ota failed") + # 升级后重启 + Power.powerRestart() + else: + print("No need update python application") + except Exception as e: + print("nonetwork:{}".format(e)) + +if __name__ == '__main__': + print("check ota start!!!!!!!!!!") + set_version_to_json_config(CURRENT_APP_TYPE,PROJECT_VERSION) + stage, state = checkNet.waitNetworkReady(1) + if stage == 3 and state == 1: + print('Network connection successful.') + do_app_update_internal("pyota") + # check_fota() + else: + print('Network connection failed, stage={}, state={}'.format(stage, state)) + +# res = uos.statvfs("/usr") +# res = list(res) +# print('总ext空间:{} MB,剩余空间:{} MB'.format((((res[0] * res[2]) / 1024 / 1024)),((res[0] * res[3]) / 1024 / 1024))) \ No newline at end of file diff --git a/cat1modem/src/LeiNiao/china_mobile_ai_regulation.py b/cat1modem/src/LeiNiao/china_mobile_ai_regulation.py new file mode 100644 index 000000000..9cd4bf9a8 --- /dev/null +++ b/cat1modem/src/LeiNiao/china_mobile_ai_regulation.py @@ -0,0 +1,416 @@ +#AI 纳管对接文件 +import modem +import request +import utime +import osTimer +import ql_fs +from machine import RTC +from misc import Power +import uos +import ujson +import urandom +from usr.EventMesh import eventMesh +HEARBEAT_REPORT_TIMER_CONFIG = 60*60*12#60*60*12 #心跳上报时间间隔12小时可更改做测试 +REALY_TIME_COUNT = 60*60# #开启1小时实时定时器 +HEART_REPORT_ERROR_TIMER = 60 #心率上报错误定时器检测 按照1分钟检查 +PRODUCTID = "1927646275585744898" #产品ID +PRODUCTKEY = "iijgiGiTolCblSFE" #产品KEY 平台创建产品是生成的 +HEART_REPORT_ERR_MAX_NUM = 30 #连续上报错误次数最大值 30 网络异常或者哪里报错了 重启设备 可根据实际的用户的需求更改次数 +REPORT_MODE = 1 #上报方式 1 24小时内一定上报一次 2 12小时后上报一次 +class AIRegulation: + #定义全局变量 + def __init__(self): + self.timerStart = osTimer() + self.timerStartReportHr = osTimer() + self.productId = PRODUCTID + self.productKey = PRODUCTKEY + self.deviceId = "" #设备ID + self.deviceSecret = "" #设备私钥 + self.config_data = {} + self.getDevInforErrCount = 0 #获取设备信息错误次数累计 + self.report_state = 0 #超过24小时清0 + self.TimeSec = 0 #上报的时间戳 + self.startTimerState = 0 + self.software_version = "" + self.imei_new = "" + self.init_flag = 0 + self.net_work_state = 0 + self.dev_mac = "" + eventMesh.subscribe("get_dev_version",self.get_dev_version) + eventMesh.subscribe("set_dev_version",self.set_dev_version) + eventMesh.subscribe("get_dev_mac",self.get_dev_mac) + eventMesh.subscribe("set_dev_mac",self.set_dev_mac) + eventMesh.subscribe("get_network_state",self.get_network_state)#订阅消息 + eventMesh.subscribe("set_network_state",self.set_network_state)#订阅消息 + self.report_err_count = 0 #上报错误次数 30次 + + def set_network_state(self,event,msg): + self.net_work_state=int(msg) + + def get_network_state(self,event,msg): + return self.net_work_state + + def set_dev_version(self,event,msg): + self.software_version=str(msg) + + def get_dev_version(self,event,msg): + return self.software_version + def get_dev_mac(self,event,msg): + return self.dev_mac + def set_dev_mac(self,event,msg): + self.dev_mac = str(msg) + #要或者设备的mac 和设备的固件版本号 + + #读取存储设备的设备参数 包含设备imei 设备ID和设备私钥 同一个设备设备ID和设备私钥不变 + def read_dev_storage_param(self): + + IMEI = modem.getDevImei() #获取IMEI号 + result_ok = 0 #返回结果状态 + IFEXIST = ql_fs.path_exists("/usr/cm_ai_regulation.json") # + if IFEXIST == True: #文件存在 + fileSize = ql_fs.path_getsize('usr/cm_ai_regulation.json') + if fileSize == 0: + result_ok = 0 + print("设备信息配置文件不存在\r\n") + return result_ok + else: + try: + with open("/usr/cm_ai_regulation.json","r",encoding='utf-8') as fd: + try: + self.config_data = ujson.load(fd) #转换成json格式 + if len(self.config_data) != 0: + if "deviceId" in self.config_data:# + self.deviceId = str(self.config_data["deviceId"]) #设备ID + + #存在 + if "deviceSecret" in self.config_data: + self.deviceSecret = str(self.config_data["deviceSecret"]) + #存在 + if "TimeSec" in self.config_data: + self.TimeSec = self.config_data["TimeSec"] + if "IMEI" in self.config_data: + self.imei_new = self.config_data["IMEI"] + if str(self.imei_new) != str(IMEI): #设备IMEI不一样也要重新获取 + self.config_data["IMEI"] = str(IMEI) + self.write_config_msg_file(self.config_data) + result_ok = 0 + return result_ok + + if len(str(self.deviceId)) != 0 or len(str(self.deviceSecret)) != 0: + result_ok = 1 + else: #m没有存储数据 需要从平台上获取设备信息 + result_ok = 0 + except Exception as error: + print("配置文件的内容不是json格式 保存数据的时候格式不对\r\n") + result_ok = 0 + except Exception as error: + print("打开配置文件失败\r\n") + result_ok = 0 + else: + print("配置文件不存在!!!!\r\n") + result_ok = 0 + + print("cm_ai_regulation result_ok: {} self.config_data:{}\r\n".format(result_ok,self.config_data)) + return result_ok + #写文件信息 + def write_config_msg_file(self,msg): + + print("cm_ai_regulation msg:{}\r\n".format(msg)) + with open("/usr/cm_ai_regulation.json",'w+',encoding="utf-8") as fd: + ujson.dump(msg,fd) + def get_dev_info(self): #是否需要获取设备信息 + request_result = 0 + netWorkState = eventMesh.publish("get_network_state") + if netWorkState == 0: #网络异常 + request_result = 0 + return request_result + url = "https://ivs.chinamobiledevice.com:11443/v2/customer/device/secret/info" + #获取设备ID和设备私钥 + get_dev_storage = self.read_dev_storage_param() #返回1说明已经获取过设备信息 不需要再重新获取了只有 + if get_dev_storage == 0: #还没有获取设备信息需要获取一遍 + #获取设备设备信息地址 + IMEI = modem.getDevImei() #获取IMEI号 + + headers_T ={"Content-Type":"application/json"} + config_data ={ + "deviceNoType":"IMEI", + "deviceNo":str(IMEI), + "productKey":str(self.productKey), + "productId":str(self.productId), + } + print("ujson.dumps(config_data):{}".format(ujson.dumps(config_data))) + + result_json = "" + response = 0 + try: + response = request.post(url, data=ujson.dumps(config_data),headers =headers_T) + if response.status_code == 200: #服务器响应成功并返回数据 + try: + content = response.content + c = next(content) + result_json = ujson.loads(c) + print("response.json:{}".format(ujson.loads(c))) + code = "" + message = "" + success = False + if "code" in result_json: + code = result_json["code"] + if "message" in result_json: + message = result_json["message"] + if "success" in result_json: + success = result_json["success"] + if code == "200" and message == "成功" and success == True: + if "data" in result_json: + data_json = result_json["data"] + if "deviceId" in data_json: + self.deviceId = data_json["deviceId"] + if "deviceSecret" in data_json: + self.deviceSecret = data_json["deviceSecret"] + + if len(self.deviceId) != 0 or len(self.deviceSecret) != 0: #获取设备信息成功 保存数据 用做心跳上报 + request_result = 1 + self.config_data["deviceId"] = str(self.deviceId) + self.config_data["deviceSecret"] = str(self.deviceSecret) + IMEI = modem.getDevImei() #获取IMEI号 + self.config_data["IMEI"] = str(IMEI) + self.write_config_msg_file(self.config_data) + # { + # "code":"200", + # "message":"成功", + # "success": true, + # "data":{ + # "deviceId":"xxx", + # "deviceNo":"xxx", + # "productId":"xxx", + # "deviceSecret":"xxx" + # } + # } + else: + request_result = 0 + print("后台返回数据json字段里面没有data字段\r\n") + else: + request_result = 0 + print("后台返回数据失败 可能是设备没有加入产品或者产品私钥或者产品ID对不上\r\n") + except Exception as e: #不是json格式 + print("not json data:{}".format(e)) + request_result = 0 + else: + print("未响应 或者网络异常连接不上后台\r\n") + request_result = 0 + except Exception as e: + print("response error:{}".format(e)) + request_result = 0 + else: + request_result = 1 + return request_result + + #上报心跳数据 + def report_hr_data(self): #设备ID 设备私钥不为空才可以上报 + result_s = 0 + netWorkState = eventMesh.publish("get_network_state") + if netWorkState == 0: #网络异常 + result_s = 0 + return result_s + if len(str(self.deviceId)) != 0 and len(str(self.deviceSecret)) != 0: + + ######################################################### + # { + # "deviceId":"1927659130106658817", + # "deviceSecret":"xmvlRHbEaKPtCqHt", + # "productId":"1927646275585744898", + # "productKey":"iijgiGiTolCblSFE", + # "params": { + # "innerIp": [ + # "127.0.0.1" + # ], + # "netSpeed": "0Mbps", + # "netType": "4G", + # "platform": "RTOS", + # "sdkVersion": "ai_http_1.0", + # "firmwareVersion": "0.0.5.2", + # "imei": "860132060564184", + # "cmei": "", + # "mac": "" + # } + # } + IMEI = modem.getDevImei() #获取IMEI号 + tmp_mac = "" + if len(self.dev_mac) != 0: + tmp_mac = self.dev_mac.replace(':', '-') #将传过来的字符里面的:转换成- + #数据格式内容 + data_json = { + "deviceId":str(self.deviceId), #设备ID + "deviceSecret":str(self.deviceSecret), #设备私钥 + "productId":str(self.productId), #产品ID + "productKey":str(self.productKey), #产品私钥 + "params": { + "innerIp": [ + "127.0.0.1" + ], + "netSpeed": "0Mbps", + "netType": "4G", + "platform": "RTOS", + "sdkVersion": "ai_http_1.0", + "firmwareVersion":str(self.software_version), #设备固件版本号 + "imei": str(IMEI), #设备IMEI号 + "cmei": "", + "mac": str(tmp_mac) #设备MAC地址 + } + } + url = "https://ivs.chinamobiledevice.com:11443/v2/customer/device/report" #post请求上报数据心跳地址 + #获取设备ID和设备私钥 + try: + headers_T ={"Content-Type":"application/json"} #应用是json格式 + response = request.post(url, data=ujson.dumps(data_json),headers =headers_T) #post请求数据 + if response.status_code == 200: #服务器响应成功并返回数据 + try: + content = response.content + c = next(content) + result_json = ujson.loads(c) #将字符串转换成json格式 + print("response.json:{}".format(result_json)) + code = "" + message = "" + success = False + if "code" in result_json: + code = result_json["code"] + if "message" in result_json: + message = result_json["message"] + if "success" in result_json: + success = result_json["success"] + if code == "200" and message == "成功" and success == True: #上报成功返回 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp) #获取当前时间戳 用于下次时间判断上报心跳数据 + print("date_tmp :{} time_tmp:{}\r\n".format(date_tmp,time_tmp)) + self.report_state = 1 #表示上报成功 置标志1 12小时之内不清0 12小时之后再次上报清零 + self.TimeSec = str(time_tmp) + self.config_data["TimeSec"] = str(time_tmp) + IMEI = modem.getDevImei() #获取IMEI号 + self.config_data["IMEI"] = str(IMEI) + self.write_config_msg_file(self.config_data) + # { + # "code":"200", + # "message":"成功", + # "success": true, + # "data":{ + # "deviceId":"xxx", + # "protocolTypeTime":"xxx" + # } + # } + result_s = 1 + else: + result_s = 0 + except Exception as e: #不是json格式 + print("response:{}".format(e)) + result_s = 0 + else: + result_s = 0 + except Exception as e: + print("response:{}".format(e)) + result_s = 0 + if REPORT_MODE == 1: #上报方式1 + if result_s == 1: #当前上报数据成功 开启下一个上报心跳数据定时器 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp) + random_integer = urandom.randint(-15, 15) #两个时间戳相减大于24小时啧清0 + timerStart_init = HEARBEAT_REPORT_TIMER_CONFIG*1000+random_integer*1000*60 + print("timerStart_init {} random_integer:{}\r\n".format(timerStart_init,random_integer)) + self.timerStartReportHr.start(timerStart_init,0,self.timerStartReportHrCbOne)#重新开始 单次定时器 + else: #上报方式2 + if self.startTimerState == 0: + self.startTimerState = 1 + self.open_report_start_timer() + else: + result_s = 2 + self.AIRegulation_init() #重新初始化 + return result_s + return result_s + def timerStartReportHrCbOne(self,*argc): + reportStatus = self.report_hr_data() #上报心跳数据接口函数 + print("timerStartReportHrCbOne {}\r\n".format(reportStatus)) + if reportStatus == 0: #当前上报失败 开启1分钟的定时器检测 + self.timerStart.stop() + self.report_err_count = 0 + self.timerStart.start(HEART_REPORT_ERROR_TIMER*1000,1,self.oneMinTimerStartCb)#重新开始 + else: + self.timerStart.stop() + + def oneMinTimerStartCb(self,*argc): + reportStatus = self.report_hr_data() + print("oneMinTimerStartCb {}\r\n".format(reportStatus)) + if reportStatus != 0: # + self.timerStart.stop() + else: + self.report_err_count+=1 + if self.report_err_count >= HEART_REPORT_ERR_MAX_NUM: + self.report_err_count = 0 + self.timerStart.stop() + Power.powerRestart() #重启设备 可能网络异常或者哪里出错了 + + def timerStartReportHrCb(self,*argc): #上报心跳定时器回调 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp) + random_integer = urandom.randint(-15, 15) #-15 - +15上报时间随机值分钟单位 *60*1000 + data = RTC().datetime() + year = data[0] + month = data[1] + day = data[2] + + if self.report_state == 1: #上报过一次 就等下一个12小时再上报一次 + #当前时间大于上次记录时间加上12小时就上报一次 + next_alarm_time = utime.localtime(int(self.TimeSec)) + old_month = next_alarm_time[1] + old_day = next_alarm_time[2] + old_year = next_alarm_time[0] + # if 1: + # if old_year != year or old_month != month or old_day != day: + # self.report_state = 0 + # self.report_hr_data() + + # else: + if (time_tmp >= self.TimeSec + HEARBEAT_REPORT_TIMER_CONFIG*1000 + random_integer*60*1000) or (old_year != year or old_month != month or old_day != day): #or old_year != year or old_month != month or old_day != day: #上次上报时间戳+12小时时间戳 大于当前时间戳 上报一次 或者年 月 日不一致也上报一次 + self.report_state = 0 + self.report_hr_data() + else: #确保12小时之内上报一次 每一个小时上 + self.report_hr_data()#上报一次心跳数据 + + def open_report_start_timer(self): #1小时的定时器 + self.timerStartReportHr.start(REALY_TIME_COUNT*1000,1,self.timerStartReportHrCb)#1小时定时 + + def timerStartCb(self,*argc):#获取设备信息定时器回调 + getDevInfoState = self.get_dev_info() + if getDevInfoState == 0:# + self.getDevInforErrCount+=1 + if self.getDevInforErrCount >= 20: + self.getDevInforErrCount = 0 + self.timerStart.stop() + else: + self.getDevInforErrCount = 0 + self.timerStart.stop() + self.report_hr_data()#上报一次心跳数据 + + def AIRegulation_init(self):#AI 纳管 初始化 获取完设备数据后立马上报心跳数据 + status = eventMesh.publish("get_factory_status") + if status == None: + status = 0 + print("get_factory_status:{}\r\n".format(status)) + if status == 0:#恢复出厂或者新的机器需要清空不必要的数据 + if self.init_flag == 0:#只初始化一次 + IFEXIST = ql_fs.path_exists("/usr/cm_ai_regulation.json") + if IFEXIST == True: + uos.remove("/usr/cm_ai_regulation.json") + self.init_flag = 1 + self.report_state = 0 + self.getDevInforErrCount = 0 + self.report_err_count = 0 + self.timerStartReportHr.stop() + + self.startTimerState = 0 + getDevInfoState = self.get_dev_info() + if getDevInfoState == 0:#开机获取失败了再等30s重新获取 获取二十次都失败就等下次重启设备获取 + self.timerStart.stop() + self.timerStart.start(30*1000,1,self.timerStartCb)#重新开始 开机10分钟内没有获取到设备信息就不获取了需要手动重启设备 + else: #设备开机获取设备信息成功 立马上报一次心跳数据 + self.report_hr_data()#上报一次心跳数据 + +aiRegulation = AIRegulation() + diff --git a/cat1modem/src/LeiNiao/china_mobile_dmp.py b/cat1modem/src/LeiNiao/china_mobile_dmp.py new file mode 100644 index 000000000..8128328bd --- /dev/null +++ b/cat1modem/src/LeiNiao/china_mobile_dmp.py @@ -0,0 +1,842 @@ +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 +import sim + +BLOCK_SIZE = 16 +NEED_SAVE_CONFIG_FILE = 0 #是否需要保存上报次数 异常重试次数 时间戳到配置文件 0不保存 1保存 +#中国移动入库 +class chinamobile: + def __init__(self): + 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.config_data = {} + + self.__net_connected = 0 + self.regist_timeSec = 0 + self.iccid_data = "" + self.software_version = "" + self.mac_data ="" + self.address = "a.fxltsbl.com" + + self.new_address = "a.fxltsbl.com" + + self.retryInterval = 10 + self.retryNum = 1#异常重试最大次数 + self.heartBeatTime = 1440#心跳上报频率 单位分钟 + self.reportTime = 1440#最大上报频率 自注册+心跳上报的频率次数不能大于最大上报频率次数 + self.reportNum = 8 #最大上报次数 + + + self.reportTime_Sec = 0 #保存本地 保存时间戳下一次开机使用 + self.report_Num_old = 0#保存本地 + self.retryNum_old = 0#保存本地 + self.init_flag = 0#初始化状态指初始化一次 + self.retryTimer = osTimer()#异常重试定时器 + self.retpoertTimerC = osTimer()#上报次数大于下一个周期再触发 + self.heartreportTimer = osTimer()#心跳上报定时器 + + 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)#订阅消息 + + eventMesh.subscribe("set_dmp_cm_address",self.set_dmp_cm_address)#订阅消息 + eventMesh.subscribe("get_dmp_cm_address",self.get_dmp_cm_address)#订阅消息 + + pass + + def set_dmp_cm_address(self,event,msg):#设置网络是否正常 + self.address = str(msg) + self.new_address = str(msg) + + def get_dmp_cm_address(self,event,msg):#获取网络是否正常 + return self.address + + 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 write_config_msg_file(self,msg): + + print("write_config_msg_file msg:{}\r\n".format(msg)) + with open("/usr/china_mobie_config.json",'w+',encoding="utf-8") as fd: + ujson.dump(msg,fd) + #读文件信息 + def read_config_msg_file(self): + IFEXIST = ql_fs.path_exists("/usr/china_mobie_config.json") #不存在 + if IFEXIST == True: + with open("/usr/china_mobie_config.json","r",encoding='utf-8') as fd: + self.config_data = ujson.load(fd) + print("read_config_msg_file self.config_data:{}\r\n".format(self.config_data)) + + def china_mobile_first_get_config(self,url): + ##############第一步#######获取采集规则配置####### + # brand = "KUMI"#品牌 + # model = "Watch Soar"#型号 + # NWO N9 + brand = "NWO"#品牌 + model = "NWO N9"#型号 + + + 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://{}//dm-multi-accept/multi/getMultiTerminalConfig".format(self.address) + headers_T ={"Content-Type":"application/json"} + print("ujson.dumps(config_data):{}".format(ujson.dumps(config_data))) + request_result = 0 + result_json = "" + try: + response = request.post(url, data=ujson.dumps(config_data),headers =headers_T) + request_result = 1 + if response.status_code == 200:#服务器响应成功并返回数据 + content = response.content + c = next(content) + result_json = ujson.loads(c) + print("response.json:{}".format(ujson.loads(c))) + except Exception as e: + print("response:{}".format(e)) + request_result = 0 + + + if request_result == 0: #请求出错了 + return "" + + + return result_json + + + def first_get_config_json(self):#开机上电获取配置信息 + getresult = 0 + print("first_get_config_json false",self.__net_connected) + network_state = eventMesh.publish("get_network_state") + if network_state != 1:#网络不正常 + print("网络不正常") + return getresult + url = "https://{}//dm-multi-accept/multi/getMultiTerminalConfig".format(self.address) + result_json = self.china_mobile_first_get_config(url) + + if result_json == "": + print("result_json == NULL") + return 0 + # { + # "reportTime":1440, + # "reportNum":8, + # "heartBeatTime":1440, + # "retryInterval":10, + # "retryNum":1 + # }#默认采集规则配置 + #默认参数 + + retryInterval = self.retryInterval + heartBeatTime = self.heartBeatTime + reportTime = self.reportTime + reportNum = self.reportNum + retryNum = self.retryNum + new_address = self.address + print("get_config_json old:{} {} {} {} {} {}\r\n".format(reportTime,heartBeatTime,reportNum,retryInterval,retryNum,new_address)) + 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"]) + if "address" in msg_data: + self.address = str(msg_data["address"]) + print("get_config_json new:{} {} {} {} {}\r\n".format(self.reportTime,self.heartBeatTime,self.reportNum,self.retryInterval,self.retryNum,self.address)) + + print("true") + else: + print("false") + + if getresult == 1:#请求配置文件成功 + if (self.retryInterval != retryInterval) or (self.retryNum != retryNum) or (self.heartBeatTime != heartBeatTime) or\ + (self.reportTime != reportTime) or (self.reportNum != reportNum) or (self.address != new_address): + #重新走注册流程 清空报错次数 记录当前时间戳 + print("new config not old config!!!\r\n")#拉取的配置文件和保存本地的不一致 + self.config_data["reportTime"] = self.reportTime + self.config_data["heartBeatTime"] = self.heartBeatTime + self.config_data["reportNum"] = self.reportNum + self.config_data["retryNum"] = self.retryNum + self.config_data["retryInterval"] = self.retryInterval + # self.config_data["address"] = str(self.address) + if new_address != self.address : #服务器下发和本地不一致需要用服务器下发的最新的IP 并把这个IP发送到BLE保存 + eventMesh.publish("send_dmp_cm_address_toBLE",str(self.address)) + + self.write_config_msg_file(self.config_data) #保存新的配置文件 + return 2 + return getresult #1 获取成功 0 获取失败 + + + def china_mobile_autoregist_infor(self,url,configType_data): + #########################第二步############自注册上报################### + #设备自注册上报 + dev_autoregist_result = 0 #默认是1成功 0是失败 + network_state = eventMesh.publish("get_network_state") + if network_state != 1:#网络不正常 + return dev_autoregist_result + #密钥 + key = "03816c12b6d24182981325e57670e478" + + brand = "{}".format("NWO")#品牌 + + # model = "Watch Soar"#型号 + model = "NWO N9"#型号 + + # -*- coding: UTF-8 -*- +#示例 + + + appKey = "M100001188"#不需要就填***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 + + + batteryCapacityCurr="***" + + + #不需要加密 #||分隔符不能超过11个 否则平台会解析出错 + config_data = "{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}".format(brand,model,appKey,sdkVersion,apiVersion,apiType,templateId,imei1,imei2,configType,preField1,preField2) + + #需要加密的数据明文 + mac_data="***"#eventMesh.publish("get_dev_mac") + + if (len(mac_data) == 0):#获取失败了 + mac_data = "***" + + imsi = sim.getImsi() + print("Get IMSI : {}".format(imsi)) + + MAC = mac_data + # base64_MAC = sha256_encode(key,MAC) + RAM = "***" + # base64_RAM = sha256_encode(key,RAM) + ROM = "***" + # base64_ROM = sha256_encode(key,ROM) + CPU = "***" + # base64_CPU = sha256_encode(key,CPU) + GPU = "***" + + imsi2="***" + + sysVersion = "***" + + board = "***" + + # base64_sysVersion = sha256_encode(key,sysVersion) + if (len(self.software_version) == 0):#获取失败了 + # self.software_version = "Watch Soar V1.0" + self.software_version = "NWO N9 V1.0" + + softwareVer = "NWO N9 V1.0" + # base64_softwareVer = sha256_encode(key,softwareVer) + # softwareName ="FD230" + softwareName ="***" + + sn="***" + + batteryCapacity="***" + + phoneNumber="***" + # base64_softwareName = sha256_encode(key,softwareName) + volte="***" #0:开;1:关;-1:不支持 + # base64_volte = sha256_encode(key,volte) + netType="***" + # 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 ="***"#1:连接;0:未连接;-1:不支持 + + routerMac = "***" + + wifiMac = "***" + # base64_networkStatus = sha256_encode(key,networkStatus) + encyr_data = [MAC,RAM,ROM,CPU,sysVersion,softwareVer,softwareName,volte,netType,resolution,screenSize,wearingStatus,networkStatus,routerMac,wifiMac,imsi,GPU,imsi2,board,sn,batteryCapacity,phoneNumber,batteryCapacityCurr] + print(len(encyr_data)) + encyr_new_data=[] + for i in range(len(encyr_data)): + tmp_data = self.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)#网络状态 + + # } + if configType_data=="keepAlive": + print("keepAlive :") + 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]),#网络状态 + "routerMac":"{}".format(encyr_new_data[13]), #路由mac地址 *** + "mac":"{}".format(encyr_new_data[14]), #wifi mac + "imsi":"{}".format(encyr_new_data[15]), #imsi + "gpu":"{}".format(encyr_new_data[16]), #GPU + "imsi2":"{}".format(encyr_new_data[17]), #imsi2 + "board":"{}".format(encyr_new_data[18]), #board + "sn":"{}".format(encyr_new_data[19]), #board + "batteryCapacity":"{}".format(encyr_new_data[20]), #board + "phoneNumber":"{}".format(encyr_new_data[21]), #board + "batteryCapacityCurr":"{}".format(encyr_new_data[22]), #board + } + else : + 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]),#网络状态 + "routerMac":"{}".format(encyr_new_data[13]), #路由mac地址 *** + "mac":"{}".format(encyr_new_data[14]), #wifi mac + "imsi":"{}".format(encyr_new_data[15]), #imsi + "gpu":"{}".format(encyr_new_data[16]), #GPU + "imsi2":"{}".format(encyr_new_data[17]), #imsi2 + "board":"{}".format(encyr_new_data[18]), #board + "sn":"{}".format(encyr_new_data[19]), #board + "batteryCapacity":"{}".format(encyr_new_data[20]), #board + "phoneNumber":"{}".format(encyr_new_data[21]), #board + + } + 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"} + request_result = 0 + print("shangbao address:{}\r\n".format(url)) + try: + response = request.post(url, data=ujson.dumps(send_autoregist),headers =headers_T) + request_result = 1 + result_json = "" + print("response success:response.status_code{}\r\n".format(response.status_code)) + if response.status_code == 200: + dev_autoregist_result = 1 + content = response.content + c = next(content) + result_json = ujson.loads(c)#解析成json格式 + else: + dev_autoregist_result = 0 + + + if "rspCode" in result_json: + rspCode = result_json["rspCode"] + rspMsg = result_json["rspMsg"] + print("response success:rspCode{} {}\r\n".format(rspMsg,rspCode)) + if rspCode == "0000" or rspMsg == "成功": + dev_autoregist_result = 1 + else: + dev_autoregist_result = 0 + else: + dev_autoregist_result = 0 + print("response success:\r\n") + return dev_autoregist_result + + except Exception as e: + print("response:{}".format(e)) + request_result = 0 + + if request_result == 0:#请求出错了 + dev_autoregist_result = 0 + return dev_autoregist_result + + + def read_config_file(self):#获取配置文件,一开机是没有配置文件的 + + self.read_config_msg_file()#读文件信息 + if self.config_data != {}: + if "retryInterval" in self.config_data: + self.retryInterval = int(self.config_data["retryInterval"]) + if "retryNum" in self.config_data: + self.retryNum = int(self.config_data["retryNum"]) + if "heartBeatTime" in self.config_data: + self.heartBeatTime = int(self.config_data["heartBeatTime"]) + if "reportTime" in self.config_data: + self.reportTime = int(self.config_data["reportTime"]) + if "reportNum" in self.config_data: + self.reportNum = int(self.config_data["reportNum"]) + if "address" in self.config_data: + self.address = str(self.config_data["address"]) + + #终端本地需要保存本地的数据 + # self.reportTime_Sec = 0 #保存本地 保存时间戳下一次开机使用 + # self.report_Num_old = 0#保存本地 + # self.retryNum_old = 3#保存本地 + if NEED_SAVE_CONFIG_FILE == 1: + if "reportTime_Sec" in self.config_data: + self.reportTime_Sec = int(self.config_data["reportTime_Sec"]) + if "report_Num_old" in self.config_data: + self.report_Num_old = int(self.config_data["report_Num_old"]) + if "retryNum_old" in self.config_data: + self.retryNum_old = int(self.config_data["retryNum_old"]) + + print("read_config_file self.config_data:{} ".format(self.config_data)) + def retryTimerCb(self,*argc):#异常重试机制定时器回调 + #保存本地 + self.retryNum_old+=1 #1 self.reportNum = 1 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["retryNum_old"] = self.retryNum_old + self.write_config_msg_file(self.config_data) + print("retryTimerCb self.retryNum_old:{}\r\n".format(self.retryNum_old)) + self.search_report_num_step() + pass + def reportTimerIntervalError(self): + self.retryNum_old = 0#保存 + self.report_Num_old = 0#保存 定时清空数据 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + self.reportTime_Sec = time_tmp+self.reportTime*60 #(记录时间+reportTime)标识旧的时间 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["reportTime_Sec"] = self.reportTime_Sec + self.config_data["retryNum_old"] = self.retryNum_old + self.config_data["report_Num_old"] = self.report_Num_old + self.write_config_msg_file(self.config_data) + self.search_report_num_step()#重新查询 + pass + def error_retryNum_step(self):#判读报错次数是否大于self.retryNum 步骤 + print("error_retryNum_step:self.retryNum_oldd:{} self.retryNum:{} self.reportTime:{}\r\n".format(self.retryNum_old,self.retryNum,self.reportTime)) + + if self.retryNum_old >= self.retryNum and self.retryNum_old != 0:#self.retryNum_old > 10#结束HTPP下一个最大频率周期时间间隔流程 + print("error_retryNum_step:self.retryNum_old >= self.retryNum\r\n") + self.reportTimerIntervalError() + # self.retpoertTimerC.start(self.reportTime*60*1000,0,self.reportTimerIntervalError)#重新开始 需要清空数据 + else: + get_result = self.first_get_config_json()#发起向服务端请求配置信息下发到设备端 + if get_result == 0:#获取失败或者没有网络 走异常重试机制 + self.report_Num_old+=1#请求错误请求失败都要保存上报次数 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["report_Num_old"] = self.report_Num_old + self.write_config_msg_file(self.config_data) + print("error_retryNum_step:self.retryTimer.start :{} {} {}\r\n".format(self.retryInterval,self.report_Num_old,self.reportNum)) + self.checkMaxReportNum()#检查上报最大次数 + self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb) + pass + else:# + + #第一步触发自注册 + if get_result == 2:#请求的配置文件和本地不一致重启 + self.retryNum_old = 0#保存本地 配置文件不同重启模组 清空异常重试的报错次数 + # self.report_Num_old+=1#请求错误请求失败都要保存上报次数 + # if NEED_SAVE_CONFIG_FILE == 1: + # self.config_data["report_Num_old"] = self.report_Num_old + # self.config_data["retryNum_old"] = self.retryNum_old + # self.write_config_msg_file(self.config_data) + + self.china_mobile_init_param()#重新走流程读配置文件->判断上报总数->判断报错次数->获取配置文件 + self.search_report_num_step() + return + + self.report_Num_old+=1#请求错误请求失败都要保存上报次数 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["report_Num_old"] = self.report_Num_old + self.write_config_msg_file(self.config_data) + print("error_retryNum_step self.report_Num_old:{}\r\n".format(self.report_Num_old)) + if self.checkMaxReportNum() == 1:#检查上报最大次数 + self.search_report_num_step()#重新查询 + return + report_result = self.onself_regist_report_cb()#注册 + + #第二步触发心跳上报次数 + if report_result == 1:#注册完成之后根据服务端下发的配置 间隔上报心跳 + self.heartreportTimer.stop() + self.heartreportTimer.start(self.heartBeatTime*60*1000,1,self.heartreportTimerCb) + + def heartreportTimerCb(self,*argc): + self.heart_report_cb() + + def retpoertTimerClear(self): + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + print("retpoertTimerCB time_tmp -self.reportTime_Sec:{} time_tmp :{} self.reportTime_Sec:{}\r\n".format(self.reportTime_Sec-time_tmp,time_tmp,self.reportTime_Sec)) + self.report_Num_old = 0#清空上报总次数 #保存本地 + self.retryNum_old = 0#清空上报错误次数 #保存本地 + self.reportTime_Sec = time_tmp+self.reportTime*60#记录当前时间+reportTime的时间用于下次错判断 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["reportTime_Sec"] = self.reportTime_Sec + self.config_data["retryNum_old"] = self.retryNum_old + self.config_data["report_Num_old"] = self.report_Num_old + self.write_config_msg_file(self.config_data) + self.retpoertTimerC.stop()#关闭定时器 + self.error_retryNum_step()#清空报错次数重新走判断报错次数 + pass + def check_current_time(self):#检测当前时间是否超过self.reportTime 超过清空报错次数 清空上报总次数 + # + date_tmp = utime.localtime() + currentTime = utime.mktime(date_tmp)#获取时间戳 + reportTime = self.reportTime_Sec + print("check_current_time:time_tmp - self.reportTime_Sec:{} currentTime:{} self.reportTime*60:{}".format(reportTime, currentTime,self.reportTime*60)) + if currentTime >= reportTime:#当前时间是否大于上次记录的时间 currentTime >= reportTime 直接清空 不超过定时清空数据不再上报数据 + #在规定时间内上报次数大于8次就要等下一个10分钟 或者1440分了开个定时器 + print("currentTime >= reportTime:\r\n") + self.retpoertTimerClear() + else:#否则次数置零,记录一下(当前时间+reportTime)时间 + time_count = (reportTime - currentTime) #self.reportTime_Sec永远比time_tmp大 + print("time_count:{}".format(time_count)) + print("currentTime < reportTime:\r\n") + self.retpoertTimerC.start(time_count*1000,0,self.retpoertTimerCB) + + + # 第一次请求的时候,记录一下(当前时间+reportTime)时间与次数,如果次数小于最大次数,直接返回true。 + # 如果次数大于最大次数,则判断一下当前时间是否超过上次设置的时间,如果超过了,则表示超过最大次数;否则次数置零,记录一下(当前时间+reportTime)时间。 + def retpoertTimerCB(self,*argc):#按照剩余的时间做定时器 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + print("retpoertTimerCB time_tmp -self.reportTime_Sec:{} time_tmp :{} self.reportTime_Sec:{}\r\n".format(self.reportTime_Sec-time_tmp,time_tmp,self.reportTime_Sec)) + self.report_Num_old = 0#清空上报总次数 #保存本地 + self.retryNum_old = 0#清空上报错误次数 #保存本地 + self.reportTime_Sec = time_tmp+self.reportTime*60#记录当前时间+reportTime的时间用于下次错判断 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["reportTime_Sec"] = self.reportTime_Sec + self.config_data["retryNum_old"] = self.retryNum_old + self.config_data["report_Num_old"] = self.report_Num_old + self.write_config_msg_file(self.config_data) + self.error_retryNum_step()#清空报错次数重新走判断报错次数 + + + 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 and self.report_Num_old != 0:#查询上报的总次数是否大于存储上报总次数 + self.check_current_time()#检测当前时间是否超过self.reportTime 超过清空报错次数 清空上报总次数 + else:# + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + self.reportTime_Sec = time_tmp+self.reportTime*60 #(记录时间+reportTime)标识旧的时间 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["reportTime_Sec"] = self.reportTime_Sec + self.write_config_msg_file(self.config_data) + self.error_retryNum_step()#查询上报错误次数 + + def search_report_num_step_init(self):#查询上报总数步骤 + print("search_report_num_step:self.retryInterval:{} self.retryNum:{} self.reportTime_Sec:{}\r\n".format(self.report_Num_old,self.reportNum,self.reportTime_Sec)) + if self.report_Num_old >= self.reportNum and self.report_Num_old != 0:#查询上报的总次数是否大于存储上报总次数 + self.check_current_time()#检测当前时间是否超过self.reportTime 超过清空报错次数 清空上报总次数 + else:# + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + if self.reportTime_Sec == 0: + self.reportTime_Sec = time_tmp+self.reportTime*60 #(记录时间+reportTime)标识旧的时间 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["reportTime_Sec"] = self.reportTime_Sec + self.write_config_msg_file(self.config_data) + self.error_retryNum_step()#查询上报错误次数 + + + def reportTimerIntervalCb(self,*argc):#最大上报频率时间间隔定时器 要清空数据 + print("reportTimerIntervalCb\r\n") + self.search_report_num_step()#重新查询 + + def onself_regist_report_cb(self):#自注册上报信息 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + print("onself_regist_report_cb:self.report_Num_old:{} self.reportNum:{} self.reportTime_Sec:{}\r\n".format(self.report_Num_old,self.reportNum,self.reportTime_Sec)) + self.report_Num_old+=1 ##保存本地 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["report_Num_old"] = self.report_Num_old + self.write_config_msg_file(self.config_data) + #设备自注册上报信息 + print("onself_regist_report_cb:self.china_mobile_autoregist_infor") + url = "https://{}//dm-multi-accept/multi/acceptMultiTerminalRegInfo".format(self.address)#上报地址 + confing_type = "autoRegist"#上报传输配置 + result = self.china_mobile_autoregist_infor(url,confing_type) + + + if result != 1: + #触发异常重试进制 + self.checkMaxReportNum()#检查上报最大次数 + if self.checkMaxRetryNum() == 1: + print("retryTimerCb timer22")#异常重试过多重新间隔reportTime注册流程 关闭所有的定时器 + self.search_report_num_step()#重新查询 + return 0 + self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb) + return 0 + else: + if self.checkMaxReportNum() == 1: + self.search_report_num_step()#重新查询 + # self.retpoertTimerC.start(self.reportTime*60*1000,0,self.reportTimerIntervalCb) + return 0 + else: + return 1 + def checkMaxReportNum(self):#检查上报次数最大值 + print("checkMaxReportNum :self.reportNum :{} self.report_Num_old:{}\r\n".format(self.reportNum,self.report_Num_old)) + if self.report_Num_old >= self.reportNum and self.report_Num_old != 0: + self.retryTimer.stop()#关定时器 + self.retpoertTimerC.stop() + self.heartreportTimer.stop() + return 1 + else: + return 0 + + def checkMaxRetryNum(self):#检查上报错误次数 + print("checkMaxRetryNum :self.retryNum:{} self.retryNum_old:{}\r\n".format(self.retryNum_old,self.retryNum)) + if self.retryNum_old >= self.retryNum and self.retryNum_old != 0:#异常重试过多重新间隔reportTime注册流程 + self.retryTimer.stop()#关定时器 + self.retpoertTimerC.stop() + self.heartreportTimer.stop()#关闭心跳定时器 + return 1 + else: + return 0 + + def heart_report_cb(self):#心跳上报信息 + + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + self.report_Num_old+=1#保存本地 + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["report_Num_old"] = self.report_Num_old + self.write_config_msg_file(self.config_data) + print("heart_report_cb:self.report_Num_old:{} self.reportNum:{} self.reportTime:{} self.reportTime_Sec:{}\r\n".format(self.report_Num_old,self.reportNum,self.reportTime,self.reportTime_Sec)) + + url = "https://{}//dm-multi-accept/multi/acceptMultiTerminalHeartbeatInfo".format(self.address)#上报地址 + confing_type = "keepAlive"#上报传输配置 + print("heart_report_cb:self.china_mobile_autoregist_infor") + result = self.china_mobile_autoregist_infor(url,confing_type) + if result != 1: + #触发异常重试进制 + self.checkMaxReportNum() + if self.checkMaxRetryNum() == 1:#异常重试过多重新间隔reportTime注册流程 + self.search_report_num_step()#重新查询 + return + self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb) + return + if self.checkMaxReportNum() == 1:#上报次数大于8次 + self.search_report_num_step()#重新查询 + return + + def china_mobile_init_param(self):#初始化 + + status = eventMesh.publish("get_factory_status") + if status == None: + status = 0 + print("get_factory_status:{}\r\n".format(status)) + if status == 0:#恢复出厂或者新的机器需要清空不必要的数据 + if self.init_flag == 0:#只初始化一次 + IFEXIST = ql_fs.path_exists("/usr/telecom_config.json") #不存在 + if IFEXIST == True: + uos.remove("/usr/telecom_config.json") + isStorage = ql_fs.path_exists("/usr/china_mobie_config.json")#移动入库的配置文件移除 + if isStorage == True: + uos.remove("/usr/china_mobie_config.json") + #先清空再写入默认参数 + self.init_flag = 1 + self.retryInterval = 10 + self.retryNum = 1#异常重试最大次数 + self.heartBeatTime = 1440#心跳上报频率 单位分钟 + self.reportTime = 1440#最大上报频率 自注册+心跳上报的频率次数不能大于最大上报频率次数 + self.reportNum = 8 #最大上报次数 + + self.reportTime_Sec = 0 #保存本地 保存时间戳下一次开机使用 + self.report_Num_old = 0#保存本地 + self.retryNum_old = 0#保存本地 + get_address = eventMesh.publish("get_dmp_cm_address") + if get_address == None:#获取出来地址是空的使用适配地址 + self.address = "a.fxltsbl.com"#默认 + else: #恢复出厂使用BLE传送过来的地址 + self.address = str(eventMesh.publish("get_dmp_cm_address")) + + self.config_data["retryInterval"] = self.retryInterval + self.config_data["retryNum"] = self.retryNum + self.config_data["heartBeatTime"] = self.heartBeatTime + self.config_data["reportTime"] = self.reportTime + self.config_data["reportNum"] = self.reportNum + # self.config_data["address"] = self.address + if NEED_SAVE_CONFIG_FILE == 1: + self.config_data["reportTime_Sec"] = self.reportTime_Sec + self.config_data["report_Num_old"] = self.report_Num_old + self.config_data["retryNum_old"] = self.retryNum_old + + self.write_config_msg_file(self.config_data) + #读配置文件 + self.read_config_file()#只读一下配置文件 + + self.retryTimer.stop()#关定时器 + self.retpoertTimerC.stop() + self.heartreportTimer.stop() + def china_mobile_init(self): + self.china_mobile_init_param() + #查询上报总数流程 + self.search_report_num_step_init() + + + + +chinamobileCb = chinamobile() + + + + + + + + + + + + diff --git a/cat1modem/src/LeiNiao/httpota.py b/cat1modem/src/LeiNiao/httpota.py new file mode 100644 index 000000000..1f7ff897c --- /dev/null +++ b/cat1modem/src/LeiNiao/httpota.py @@ -0,0 +1,43 @@ +#远程升级 + +import fota +import utime +import log +import checkNet + +import app_fota +from misc import Power +import modem +import ujson +import request +import ql_fs +import checkNet +import sys + +#远程升级 +import uos + + +# 设置日志输出级别 + +class httpota: + def __init__(self): + print("httpota init") + + + def run(url_1,url_2): + print("httpDownload...{}".format(url_1)) + print("httpDownload...{}".format(url_2)) + # format(str(url_2))) + fota_obj = fota() # 创建Fota对象 + # res = fota_obj.httpDownload(str(url_1),str(url_2)) + res = fota_obj.httpDownload(url1="{}".format(url_1),url2="{}".format(url_2)) + if res != 0: + print.error("httpDownload error") + return + print("wait httpDownload update...") + utime.sleep(2) + # Power.powerRestart() + +# httpota = httpota() +# httpota.run("http://snicker.com.cn:8089/FD230/V18-V19OTA") \ No newline at end of file diff --git a/cat1modem/src/LeiNiao/main.py b/cat1modem/src/LeiNiao/main.py new file mode 100644 index 000000000..a5bea573d --- /dev/null +++ b/cat1modem/src/LeiNiao/main.py @@ -0,0 +1,27 @@ +import example +import log +from machine import UART + +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +# 设置输出到debug口 +uart = UART(UART.UART0, 115200, 8, 0, 1, 0) +# log.set_output(uart) +clog = log.getLogger("cat1") + +main_flag = 1 + + +try: + example.exec('/usr/main_init.py') + clog.info("启动main_init成功!!!!!\r\n") +except Exception as e: + main_flag = 0 + clog.error("启动失败!!!!!\r\n".format(e)) + +try: + example.exec('/usr/tcpserver.py') + clog.info("启动tcpserver成功!!!!!\r\n") +except Exception as e: + clog.error("启动失败!!!!!\r\n".format(e)) + diff --git a/cat1modem/src/LeiNiao/main_init.py b/cat1modem/src/LeiNiao/main_init.py new file mode 100644 index 000000000..4eb63593f --- /dev/null +++ b/cat1modem/src/LeiNiao/main_init.py @@ -0,0 +1,101 @@ +import example +import osTimer +import ql_fs +import log +import sms +from misc import Power +ota_flag = 0 +try: + try: + from usr.EventMesh import eventMesh + print("检测文件成功!!!!!!!\r\n",'eventMesh') + except Exception as e: + print("检测文件失败!!!!!!!{}\r\n",'eventMesh') + + try: + from usr.telecom_dmp import telecomDmpCb + print("检测文件成功!!!!!!!\r\n",'telecomDmpCb') + except Exception as e: + print("检测文件失败!!!!!!!{}\r\n",'telecomDmpCb') + + try: + from usr.china_mobile_dmp import chinamobileCb + print("检测文件成功!!!!!!!\r\n",'chinamobileCb') + except Exception as e: + print("检测文件失败!!!!!!!{}\r\n",'chinamobileCb') + try: + from usr.china_mobile_ai_regulation import aiRegulation + print("检测文件成功!!!!!!!\r\n",'aiRegulation') + except Exception as e: + print("检测文件失败!!!!!!!{}\r\n",'aiRegulation') + try: + from usr.cat1Service import cat1service + print("检测文件成功!!!!!!!\r\n",'cat1service') + except Exception as e: + print("检测文件失败!!!!!!!{}\r\n",'cat1service') + + ota_flag = 1 + print("检测文件成功!!!!!!!\r\n") +except Exception as e: + print("检测文件失败!!!!!!!{}\r\n".format(e)) + ota_flag = 0 +tmp_dir = ql_fs.path_exists("/usr/TmpPyFile") #临时存放的文件夹 +if tmp_dir == True: + try: + ql_fs.rmdirs("/usr/TmpPyFile") + print("移除 TmpPyFile 成功!!!!!!!\r\n") + except Exception as e: + print("移除 TmpPyFile 失败!!!!!!!{}\r\n".format(e)) + +sms_get = sms.getSaveLoc() +if(sms_get != -1): + sms_lacv = sms_get[0][0] + if sms_lacv != 'SM': #每次开机设置一下短信的存储位置 + sms.setSaveLoc('SM', 'SM', 'SM') + +PROJECT_VERSION = "PY_MAIN_V3" +CONFIG_JSON="/usr/system_config.json" +CURRENT_APP_TYPE="pymain" + + +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +cat1service_log = log.getLogger("pymain") + + +def get_versionkeyname_by_py(app_type): + return str("{}version".format(app_type)) + +def get_default_versionvalue_by_py(app_type): + if (app_type == "pymain"): + return "PY_MAIN_V2" + elif (app_type == "pyota"): + return "PY_OTA_V2" + elif (app_type == "pysrv"): + return "PY_SRV_V2" + +#如果没有configfile则创建它 +if not ql_fs.path_exists(CONFIG_JSON): + data = {str(get_versionkeyname_by_py(CURRENT_APP_TYPE)):get_default_versionvalue_by_py(CURRENT_APP_TYPE)} + ql_fs.touch(CONFIG_JSON,data) + +def set_version_to_json_config(app_type,keyvalue): + config_data = ql_fs.read_json(CONFIG_JSON) + config_data.update( {str(get_versionkeyname_by_py(app_type)):keyvalue}) + ql_fs.touch(CONFIG_JSON, config_data) + cat1service_log.info("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue)) + cat1service_log.info("{}".format(config_data)) + +set_version_to_json_config(CURRENT_APP_TYPE,PROJECT_VERSION) + + +def checkota_cb(arg): + print("start checkota!!") + example.exec('/usr/checkota.py') +# 创建os定时器 + +timer = osTimer() +# 启动定时器,参数依次为时间、是否循环、回调函数 定时器超时的时间(单位ms) +# 开机delay 20秒后执行一次ota升级 +timer.start(20000,0,checkota_cb) +print("checkota py end!!") diff --git a/cat1modem/src/LeiNiao/tcpserver.py b/cat1modem/src/LeiNiao/tcpserver.py new file mode 100644 index 000000000..afe23b2c1 --- /dev/null +++ b/cat1modem/src/LeiNiao/tcpserver.py @@ -0,0 +1,602 @@ +from misc import Power +import usocket +import log +import utime +from machine import UART +import _thread +from queue import Queue +from machine import Pin +from machine import ExtInt +import osTimer +import utime +import ql_fs +import binascii +import ujson +import uos + + +log.basicConfig(level=log.INFO) +clog = log.getLogger("cat1") + +USR_FILE_PATH = "/usr" # +BAK_FILE_PATH = "{}/TmpPyFile".format(USR_FILE_PATH) +BAK_FILE_TMP = "_bak" +CAT1_SERVICE_HEAD = "FE" +CAT1_FILE_DATA_HEAD = "FF" +CAT1_REPLAY_STATE="00" +CAT1_CREAT_DIR_FAILE= "01" +CAT1_CREAT_DIR_OK= "02" +CAT1_NO_REPLAY_OTA_OK= "03" +CAT1_WRITE_FILE_SUCC= "04" +CAT1_WRITE_FILE_ERROR = "05" +CAT1_CRC_ERROR = "06" +CAT1_SEND_HEAD_ERR = "07" +CAT1_OTA_TIMEOUT_BLE_NO_REPLAY = "08" +CAT1_CREAT_FILE_ERROR = "09" +CAT1_CREAT_FILE_SUCC = "0A" +CAT1_ALLPY_FILE_TRANSFER_END = "0B" +CAT1_REPLAY_OTA_SUCC = "0C" +CAT1_REPLAY_OTA_FALIE = "0D" +CAT1_REPLAY_FILE_SIZE_OK = "0E" +CAT1_REPLAY_FILE_SIZE_ERR = "0F" +CAT1_REPLAY_OTA_END_FAILE = "10" +CAT1_NEED_UPDATE_OTA = "11" +CAT1_TCP_STOP_OTA = 0 +CAT1_TCP_START_OTA = 1 +CAT1_TCP_START_SEND_SINGLE_FILE_INFO= 2 +CAT1_TCP_START_SEND_FILE_DATA= 3 +CAT1_TCP_START_OTA_FAILE = 4 +CAT1_TCP_START_OTA_SUCC = 5 +CAT1_TCP_START_SEND_ALLFILE_FINESH = 6 +CAT1_TCP_SEND_SINGLE_FINESH = 7 +CAT1_TCP_START_ERROR_INFO = 255 + +gpioWakeBT = Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_DISABLE, 1) +gpioWakeBT.set_dir(Pin.OUT) +gpioWakeBT.write(0) +FILE_TRANSFER_TIMEOUT=60 +class TcpServiceInit: + AP = 0 + STA = 1 + + def __init__(self, uart=UART.UART4, mode=AP): + self.__uart = uart + self.__mode = mode + self.Cat1FileState = 0 + self.Cat1FileReplayBle = 0 + self.Cat1TimeCount = 0 + self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT + self.Cat1FileTransTimer = osTimer() + self.Cat1OtaTimeOut = osTimer() + self.crc_err = 0 + self.allPyRecvFlag = 0 + self.ota_state =0 + self.ota_bstate =0 + self.fileNameTmp = "" + self.fileNameList = [] + self.fileSizeList = [] + self.fileSize = 0 + self.updateTimer = osTimer() + self.updateTimerCount = 0 + self.updateTimerFlag = 0 + self.sock = None + self.bakFlag = "0" + self.conn= None + self.__sock_file = None + self.__sock_file = self.__socket_file_init() + self.__thread_file = _thread.start_new_thread(self.__Socket_File_Thread, ()) + self.conn_thread=_thread.start_new_thread(self._client_conn_proc, ()) + + def __pack_tlv_format(self, head, content): + head1 = head + content1 = content + if len(content1) == 0 or len(content1) > 9999 or len(head1) != 2: + return -1 + len_str ='%04d' % len(content1) + tlv_pack = CAT1_SERVICE_HEAD+head1+len_str+content1 + return tlv_pack + + def __unpack_tlv_format(self, msg): + msg_tmp = str(msg)[2:] + tag = msg_tmp[0:2] + length = msg_tmp[2:6] + value = msg_tmp[6:] + len_str ='%04d' % len(value) + if len(value) == 0 or len(value) > 9999 or len(tag) != 2 or len_str != msg_tmp[2:6]: + return -1 + unpack = (tag,length,value) + return unpack + + def __socket_file_init(self): + self.sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM, usocket.IPPROTO_TCP_SER) + self.sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1) + bind_addr = ('172.16.1.2', 5001) + self.sock.bind(bind_addr) + self.sock.listen(10) + return self.sock + + def __Socket_TCP_file_noreply(self, head, content): + head1 = head + content1 = content + gpioWakeBT.write(1) + utime.sleep_ms(2) + gpioWakeBT.write(0) + utime.sleep_ms(20) + msg = self.__pack_tlv_format(head1,content1) + if msg == -1: + return 0 + try: + self.conn.send(msg) + except Exception as e: + clog.info("self.__sock_file error {}".format(e)) + return 0 + + def _client_conn_proc(self): + while True: + if self.conn==None: + utime.sleep_ms(20) + continue + try: + data = self.conn.recv(1024) + if not data: + clog.info("__Socket_File_Thread data null:\r\n") + else: + self.src_data(data.decode('uft-8')) + except: + self.conn.close() + break + + def __Socket_File_Thread(self): + while True: + try : + cli_conn, cli_ip_addr, cli_port = self.__sock_file.accept() + self.conn=cli_conn + clog.info('[serveice] accept a client: %s, %s' % (cli_ip_addr, cli_port)) + except : + utime.sleep_ms(20) + + def cat1FileTimerCb(self,*argc): + clog.info("timer test\r\n") + if self.Cat1PyFileTimout > 0: + self.Cat1PyFileTimout-=1 + if self.Cat1PyFileTimout == 0: + self.Cat1PyFileTimout = 0 + self.Cat1FileState = 0 + self.deleteTmpFile() + self.deleteUsrTmpFile() + self.__Socket_TCP_file_noreply(CAT1_OTA_TIMEOUT_BLE_NO_REPLAY,"ota error") #结束文件接收不完整的 + self.Cat1FileTransTimer.stop() + pass + + def crc_cal(self,msg): + bytes_data = msg.encode('utf-8') + hex_data = binascii.hexlify(bytes_data) + hex_data = hex_data.decode() + data = hex_data + crcValue = 0 + j = 0 + i = 0 + json_state = 0 + crcbuf = 0 + data_len = len(str(data)) + try: + if data_len % 2 != 0: + json_state = 0 + return [json_state,crcbuf] + except Exception as e: + json_state = 0 + for i in range(data_len): + if j >= data_len: + break + try: + decimal_number = int(str(data[j:j+2]), 16) + crcValue=crcValue+decimal_number + crcValue = crcValue&0xff + except Exception as e: + clog.info("crc_cal") + j+=2 + crcbuf = crcValue%256 + crcbuf = 256-crcbuf + crcbuf = crcbuf%256 + return [json_state,"%02x"%(crcbuf)] + def deleteTmpFile(self): + tmp_dir = ql_fs.path_exists(BAK_FILE_PATH) + if tmp_dir == True: + ql_fs.rmdirs(BAK_FILE_PATH) + + def deleteUsrTmpFile(self): + return + + def src_data(self,data): + if self.updateTimerFlag == 0: + self.updateTimerFlag = 1 + self.updateTimer.stop() + msg = "" + json_state = 0 + try: + msg = ujson.loads(data) + json_state = 1 + except Exception as e: + json_state = 0 + if json_state == 0: + value = self.__unpack_tlv_format(data) + self.cmd_data(value[0],value[2]) + return + else: + self.file_data(msg) + pass + def cmd_data(self,cmd,parm): + if cmd == "01": + self.bakFlag = str(parm) + pass + def file_data(self,msg): + if "Code" in msg: + Code = int(msg["Code"]) + if Code == CAT1_TCP_STOP_OTA: + self.allPyRecvFlag = 0 + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.deleteTmpFile() + self.deleteUsrTmpFile() + pass + elif Code == CAT1_TCP_START_OTA: + self.ota_state =0 + self.ota_bstate =0 + self.allPyRecvFlag = 0 + self.fileNameList = [] + self.fileSizeList = [] + self.allPyRecvFlag = 0 + self.Cat1FileState = 0 + self.deleteUsrTmpFile() + self.Cat1OtaTimeOut.stop() + check_dir = ql_fs.path_exists(BAK_FILE_PATH) + mk_dir_state = 0 + if check_dir == True: + try: + self.deleteTmpFile() + except Exception as e: + clog.info("移除失败\r\n") + check_dir = ql_fs.path_exists(BAK_FILE_PATH) + if check_dir == False: + try: + ql_fs.mkdirs(BAK_FILE_PATH) + mk_dir_state = 1 + except Exception as e: + mk_dir_state = 0 + else: + mk_dir_state = 1 + if mk_dir_state == 0: + self.__Socket_TCP_file_noreply(CAT1_CREAT_DIR_FAILE,"creat dir error!") + else: + self.Cat1FileState = 1 + self.fileNameList = [] + self.fileSizeList = [] + self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT + self.Cat1FileTransTimer.stop() + self.Cat1FileTransTimer.start(1000,1,self.cat1FileTimerCb) + self.__Socket_TCP_file_noreply(CAT1_CREAT_DIR_OK,"creat dir success!") + + elif Code == CAT1_TCP_START_SEND_SINGLE_FILE_INFO and self.Cat1FileState == 1: + self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT + self.fileNameTmp = str(msg["fileName"]) + self.fileSize = msg["fileSize"] + self.fileNameList = msg["fileNameList"] + path = "{}/{}".format(BAK_FILE_PATH,self.fileNameTmp) + check_touch = ql_fs.path_exists("{}/{}".format(BAK_FILE_PATH,self.fileNameTmp)) + if check_touch == True: + try: + uos.remove("{}/{}".format(BAK_FILE_PATH,self.fileNameTmp)) + except Exception as e: + clog.info("移除文件失败\r\n") + try: + with open(path,"w+") as fd: + fd.write("") + fd.close() + self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_SUCC,"1creat file or dir success!") + except Exception as e: + self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_ERROR,"1creat file or dir err!") + else: + try: + with open(path,"w+") as fd: + fd.write("") + fd.close() + self.crc_err = 0 + + self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_SUCC,"2creat file or dir success!") + except Exception as e: + self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_ERROR,"2creat file or dir err!") + + + elif Code == CAT1_TCP_START_SEND_FILE_DATA and self.Cat1FileState == 1: + self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT + if len(self.fileNameTmp) == 0: + return + data = msg["data"] + if len(data) == 0: + return + tmpdata = str(data) + head = tmpdata[0:2] + if head != CAT1_FILE_DATA_HEAD or len(tmpdata) <= 8: + clog.info("head {}\r\n".format(head)) + self.__Socket_TCP_file_noreply(CAT1_SEND_HEAD_ERR,"head error!") + return + datalen = str(tmpdata[2:6]) + datalen = int("0x" + datalen, 16) + data_buf = tmpdata[6:] + data_buf = data_buf[:-2] + crc = tmpdata[-2:] + if len(str(data_buf)) == 0 or len(str(data_buf)) != datalen: + self.__Socket_TCP_file_noreply(CAT1_WRITE_FILE_ERROR,"crc error or data null!") + return + data = str(data_buf) + path = "{}/{}".format(BAK_FILE_PATH,str(self.fileNameTmp)) + try: + with open(path,"a") as fd: + fd.write(data) + fd.close() + self.__Socket_TCP_file_noreply(CAT1_WRITE_FILE_SUCC,"write file success!") + + except Exception as e: + self.__Socket_TCP_file_noreply(CAT1_WRITE_FILE_ERROR,"write file error!") + + elif Code == CAT1_TCP_START_OTA_FAILE and self.Cat1FileState == 1: + self.allPyRecvFlag = 0 + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"OTA FAILE") + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.deleteTmpFile() + self.deleteUsrTmpFile() + pass + elif Code == CAT1_TCP_START_SEND_ALLFILE_FINESH and self.Cat1FileState == 1: + if self.bakFlag == "0": + if self.allPyRecvFlag == 1: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!") + else: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!") + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.Cat1OtaTimeOut.stop() + self.Cat1TimeCount = 0 + self.ota_state = 1 + self.allPyRecvFlag = 1 + self.Cat1OtaTimeOut.start(5000,0,self.otaTimeOut) + return + tmp_dir = ql_fs.path_exists(BAK_FILE_PATH) + if tmp_dir == True: + filenamesList = uos.listdir(BAK_FILE_PATH) + list1 = sorted(filenamesList) + list2 = sorted(self.fileNameList) + if list1 != list2: + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.deleteUsrTmpFile() + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!") + return + try: + copy_state = 1 + compare_flag = 1 + copy_flag = 0 + filenamesList = uos.listdir(BAK_FILE_PATH) + for tmp in filenamesList: + dst_path = "{}/{}".format(USR_FILE_PATH,tmp) + src_path = "{}/{}".format(BAK_FILE_PATH,tmp) + ret = False + file_size = 0 + try: + ret = ql_fs.file_copy(dst_path,src_path) + + if ret == True: + dstfile_size = ql_fs.path_getsize(dst_path) + srcfile_size = ql_fs.path_getsize(src_path) + if dstfile_size != srcfile_size: + compare_flag = 0 + break + else: + try: + compare_flag = 1 + uos.remove(src_path) + filenamesList = uos.listdir(BAK_FILE_PATH) + except Exception as e: + clog.info("copy file \r\n") + else: + compare_flag = 0 + break + except Exception as e: + clog.info("copy file \r\n") + + if copy_state == 0 or compare_flag == 0 : + self.deleteUsrTmpFile() + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota faile!22") + return + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!") + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.Cat1OtaTimeOut.stop() + self.Cat1TimeCount = 0 + self.ota_state = 1 + self.allPyRecvFlag = 1 + self.Cat1OtaTimeOut.start(5000,0,self.otaTimeOut) + except Exception as e: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota faile!33") + self.deleteUsrTmpFile() + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + else: + if self.ota_state == 1: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!") + pass + else: + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.deleteUsrTmpFile() + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!") + + elif Code == CAT1_TCP_START_OTA_SUCC and self.Cat1FileState == 1: + if self.bakFlag == "0": + self.deleteUsrTmpFile() + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + if self.allPyRecvFlag == 1: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!") + else: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!") + return + + if self.allPyRecvFlag == 0: + self.deleteTmpFile() + self.deleteUsrTmpFile() + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!") + return + tmp_dir = ql_fs.path_exists(BAK_FILE_PATH) + if tmp_dir == True: + filenamesList = uos.listdir(BAK_FILE_PATH) + list1 = sorted(filenamesList) + list2 = sorted(self.fileNameList) + if list1 != list2: + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.deleteUsrTmpFile() + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!") + return + + try: + copy_state = 1 + compare_flag = 1 + filenamesList = uos.listdir(BAK_FILE_PATH) + for tmp in filenamesList: + dst_path = "{}/{}".format(USR_FILE_PATH,tmp) + src_path = "{}/{}".format(BAK_FILE_PATH,tmp) + ret = False + file_size = 0 + try: + ret = ql_fs.file_copy(dst_path,src_path) + if ret == True: + dstfile_size = ql_fs.path_getsize(dst_path) + srcfile_size = ql_fs.path_getsize(src_path) + if dstfile_size != srcfile_size: + compare_flag = 0 + break + else: + try: + compare_flag = 1 + uos.remove(src_path) + filenamesList = uos.listdir(BAK_FILE_PATH) + except Exception as e: + clog.info("file\r\n") + else: + compare_flag = 0 + break + + except Exception as e: + clog.info("file\r\n") + if copy_state == 0 or compare_flag == 0 : + self.deleteUsrTmpFile() + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota faile!22") + return + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!") + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.Cat1OtaTimeOut.stop() + self.Cat1TimeCount = 0 + self.ota_bstate = 1 + self.conn.close() + self.Cat1OtaTimeOut.start(10000,0,self.otaTimeOut) + except Exception as e: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota faile!33") + self.deleteUsrTmpFile() + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + else: + if self.ota_bstate == 1: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!") + pass + else: + self.deleteTmpFile() + self.Cat1FileState = 0 + self.Cat1FileTransTimer.stop() + self.deleteUsrTmpFile() + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!") + + elif Code == CAT1_TCP_SEND_SINGLE_FINESH and self.Cat1FileState == 1: + self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT + tmp_dir = ql_fs.path_exists(BAK_FILE_PATH) + if tmp_dir == True: + tmp_file = ql_fs.path_exists("{}/{}".format(BAK_FILE_PATH,self.fileNameTmp)) + if tmp_file == True: + file_size = ql_fs.path_getsize("{}/{}".format(BAK_FILE_PATH,self.fileNameTmp)) + if self.fileSize != file_size: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_ERR,"file size err") + else: + if self.bakFlag == "0": + dst_path = "{}/{}".format(USR_FILE_PATH,self.fileNameTmp) + src_path = "{}/{}".format(BAK_FILE_PATH,self.fileNameTmp) + ret = False + try: + ret = ql_fs.file_copy(dst_path,src_path) + if ret == True: + dstfile_size = ql_fs.path_getsize(dst_path) + srcfile_size = ql_fs.path_getsize(src_path) + if dstfile_size != srcfile_size: + src_file = ql_fs.path_exists(src_path) + if src_file == True: + try: + uos.remove(src_path) + except Exception as e: + clog.info("copy 文件异常出错 yichu!{}:\r\n".format(e)) + self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_ERR,"file size err") + return + else: + src_file = ql_fs.path_exists(src_path) + if src_file == True: + try: + uos.remove(src_path) + except Exception as e: + clog.info("copy 文件异常出错!!!!!!!!!!{}:\r\n".format(e)) + self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_OK,"file size ok") + return + else: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_ERR,"file copy err") + except Exception as e: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_ERR,"file copy err") + else: + self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_OK,"file copy ok") + else: + self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_ERROR,"creat file or dir err!") + pass + else: + self.__Socket_TCP_file_noreply(CAT1_CREAT_DIR_FAILE,"creat file or dir error!") + pass + else: + if self.Cat1FileState == 0: + if self.Cat1FileReplayBle == 1: + return + self.Cat1FileReplayBle = 1 + self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"reset start!") + self.Cat1FileState == 0 + self.Cat1FileTransTimer.stop() + self.Cat1PyFileTimout = 0 + self.fileNameList=[] + self.deleteTmpFile() + self.deleteUsrTmpFile() + + def otaTimeOut(self,*argc): + clog.info("重启成功!!!!!!!!\r\n") + +TcpService = TcpServiceInit() + + diff --git a/cat1modem/src/LeiNiao/telecom_dmp.py b/cat1modem/src/LeiNiao/telecom_dmp.py new file mode 100644 index 000000000..289ba2b79 --- /dev/null +++ b/cat1modem/src/LeiNiao/telecom_dmp.py @@ -0,0 +1,438 @@ +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 usr.EventMesh import eventMesh,CHINA_TELECOM_DM_FUN_ENABLE +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +fota_log = log.getLogger("telecom_dmp") +import modem +import base64 +import request +import ujson +REGIST_MAX_NUM=10 #自注册的最大次数 现在是默认是10次 +REGIST_INTERVAL_TIMER=60*60 #自注册失败的间隔时间 1小时 +REGIST_POWER_ON_TIME=5*60 #开机5分钟内就必须自注册触发 +MULTI_DAY_RESEND_T = 30*24*60*60-12*60*60#多日重发的机制的周期T 30天 +MULTI_DAY_RESEND_t = 12*60*60#多日重发的机制的周期t 0.5天 +def get_report_url_website(mode = None):#获取上报网址 + url = "https://zzhc.vnet.cn/pi/"#上报网址 + return url + +class telecomDmp: + def __init__(self): + self.config_data = {} + self.check_timer = osTimer()#1小时定时器 + self.multiDayResend_timer = osTimer()#12小时定时器 多日重发的机制 + self.telecomTimer = osTimer() + 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#注册成功 + eventMesh.subscribe("get_telecom_init_state",self.get_telecom_init_state) + eventMesh.subscribe("set_telecom_init_state",self.set_telecom_init_state) + + eventMesh.subscribe("set_dmp_power_num",self.set_dmp_power_num) + eventMesh.subscribe("get_dmp_power_num",self.get_dmp_power_num) + + eventMesh.subscribe("get_dmp_power_timer_count",self.get_dmp_power_timer_count) + + 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("save_iccid_data",self.save_iccid_data)#订阅消息 保存ICCID + eventMesh.subscribe("get_iccid_data",self.get_iccid_data)#订阅消息 保存ICCID + + eventMesh.subscribe("set_regist_time",self.set_regist_time)#订阅消息 保存ICCID + eventMesh.subscribe("get_regist_time",self.get_regist_time)#订阅消息 保存ICCID + + self.regist_timeSec = 0 + self.iccid_data = "" + self.software_version = "" + self.mulit_day_timesec = 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 save_iccid_data(self,event,msg): + self.iccid_data = str(msg)[6:]#ICCID: + print("write_config_msg_file msg:{}\r\n".format(msg)) + self.config_data["ICCID"]=self.iccid_data + with open("/usr/telecom_config.json",'w+',encoding="utf-8") as fd: + ujson.dump(self.config_data,fd) + #读文件信息 + def get_iccid_data(self,event,msg): + + IFEXIST = ql_fs.path_exists("/usr/telecom_config.json") #不存在 + if IFEXIST == True: + with open("/usr/telecom_config.json","r",encoding='utf-8') as fd: + self.config_data = ujson.load(fd) + print("get_iccid_data self.config_data:{}\r\n".format(self.config_data)) + if self.config_data != {}: + if "ICCID" in self.config_data: + value = self.config_data["ICCID"] + self.iccid_data = str(value) + else: + self.iccid_data = "" + print("get_iccid_data self.config_data end:{}\r\n".format(self.config_data)) + return self.iccid_data + + def set_regist_time(self,event,msg):# + self.regist_timeSec = str(msg)[7:]#REGIST: + print("set_regist_time msg:{}\r\n".format(msg)) + self.config_data["REGIST"]=self.regist_timeSec + with open("/usr/telecom_config.json",'w+',encoding="utf-8") as fd: + ujson.dump(self.config_data,fd) + + def get_regist_time(self,event,msg):# + IFEXIST = ql_fs.path_exists("/usr/telecom_config.json") #不存在 + if IFEXIST == True: + with open("/usr/telecom_config.json","r",encoding='utf-8') as fd: + self.config_data = ujson.load(fd) + print("get_regist_time self.config_data:{}\r\n".format(self.config_data)) + if self.config_data != {}: + if "REGIST" in self.config_data: + value = self.config_data["REGIST"] + self.regist_timeSec = int(value) + else: + self.regist_timeSec = 0 + return self.regist_timeSec + + + def get_sim_state(self):#获取sim状态 不为1是sim异常 + return sim.getStatus() + + def get_sim_iccid(self):#获取sim的iccid + return sim.getIccid() + + def get_sim_imsi(self):#获取sim的imsi + return sim.getImsi() + def get_dev_imei(self):#获取设备的imei号 + return modem.getDevImei() + + def telecom_regeist_infor(self):#自注册信息 可变更 + network_state = eventMesh.publish("get_network_state") + print("telecom_regeist_infor :",network_state,self.isRegistOk,REGIST_INTERVAL_TIMER,MULTI_DAY_RESEND_T,MULTI_DAY_RESEND_t,REGIST_POWER_ON_TIME) + if network_state == 0:# 第一次进入网络不正常就需要开启1小时定时器 等待下一个周期判断网络是否正常 需要判断网络是否正常 不正常就不去触发自注册了 就等待下一次 如果10次都不成功 就等一下次开机再去自注册 + self.timer_count+=1 + print("self.timer_count:{}".format(self.timer_count)) + if self.timer_count < REGIST_MAX_NUM:#总共是10次 10次结束还没有自注册成功就等下一次开机自注册 + self.check_timer.start(REGIST_INTERVAL_TIMER*1000,0,self.publish_regist_event_cb)#不需要循环定时器 + else: + self.multiple_day_resend() + return + iccid = self.get_sim_iccid() + read_iccid = eventMesh.publish("get_iccid_data") + if read_iccid == None: + read_iccid = "" + + print("iccid!!!!!!!!!!iccid {} read_iccid:{}".format(iccid,read_iccid)) + if read_iccid != "": + if str(read_iccid) == str(iccid):#两者相同 并且本地有保存 不再自注册了 说明已经自注册过了 + print("already registed!!!!!!") #已自注册过 + self.isRegistOk = 1 + + if self.isRegistOk == 1: + print("multiple_day_resend!!!!!!\r\n") + self.multiple_day_resend() + return + self.telecom_regist_infor_init()#自注册初始化函数 + if self.isRegistOk == 0: + self.timer_count+=1 + print("self.timer_count:{}".format(self.timer_count)) + if self.timer_count < REGIST_MAX_NUM:#总共是10次 10次结束还没有自注册成功就等下一次开机自注册 + self.check_timer.start(REGIST_INTERVAL_TIMER*1000,0,self.publish_regist_event_cb)#不需要循环定时器 + else: + self.multiple_day_resend() + + def telecom_regist_infor_init(self):#自注册的数据部分 + iccid = self.get_sim_iccid() + read_iccid = eventMesh.publish("get_iccid_data") + if read_iccid == None: + read_iccid = "" + url = get_report_url_website(None)#上报网址 根据需要更改上报网址 + if iccid == -1: + iccid = str("FF")#为空就填写FF + + IMSI = self.get_sim_imsi() + if IMSI == -1:#没有卡 则填FF + IMSI = str("FF") + imei = self.get_dev_imei() + if imei == -1: + imei = str("FF") + + data_tmp = net.getCellInfo() #会适当卡个3-5s + i = 0 + cell_data = 0 + if(len(data_tmp) >= 1): + for cell in data_tmp: + if i == 2:#在list里面最多就三个元素 最后一个是LTE的数据 + if cell != []: + for tup in cell: + print("tup:{}".format(tup)) + if tup[0] == 0 and len(tup) > 0:#第0个代表当前服务的小区CELLID 7位16进制数 + cell_data = tup[1]#这个是十进制数需要自行转换成十六进制数 + print(cell_data) + break + i+=1 + # cell_data = 0 + cell_data = "%07x"%(cell_data)#7位16进制数不够前面补0 + print(cell_data) + sendCellid = "{}".format(cell_data) + REGVER = "12.0"#当前数据域协议版本号 + + # MODEL = "TXB-Watch Soar"#机型字段 -前面是厂商名 -后面是设备名 + + MODEL = "KNZ-NWO N9"#机型字段 -前面是厂商名 -后面是设备名 + + get_dev_version = eventMesh.publish("get_dev_version")#订阅消息 + if get_dev_version == None: + get_dev_version = "" + SWVER = "NWO N9 V1.0"#get_dev_version #软件版本号 + UETYPE = "12"#终端类型 12是智能手表 11是儿童手表 + SIM1ICCID = iccid + SIM1LTEIMSI = IMSI + MACID = ""#可用WALN的地址 终端布支持WLAN 就是不可上网 + OSVER = "OHOS 5.0"#操作系统版本号 + IMEI1 = imei#"876226002021717"#imei + SIM1CELLID = sendCellid#下发的小区ID + data = { + "REGVER":REGVER, + "MODEL":MODEL, + "SWVER":SWVER, + "UETYPE":UETYPE, + "SIM1ICCID":SIM1ICCID, + "SIM1LTEIMSI":IMSI, + "MACID":MACID, + "OSVER":OSVER, + "IMEI1":IMEI1, + "SIM1CELLID":SIM1CELLID, + # "NETWORKTYPE":4 + "NWTYPE1":4, + } + data_infor=ujson.dumps(data)#将字典转换成json格式 + json_bytes = bytes(data_infor, 'utf-8')#转换成字节数 + data_encode = base64.b64encode(json_bytes)#再转换成base64的编码格式 密文 + print("data_infor:{} data:{}".format(data_encode,data)) + headers_T = {'Content-Type':'application/encrypted-json'} #请求头信息 按照实际要求填写 + request_result = 0 + try: + # https://zzhc.vnet.cn/pi + response = request.post("https://zzhc.vnet.cn/pi/", data=data_encode,headers =headers_T) + request_result = 1 + if response.status_code == 200 : #返回状态码 200服务器正常解析数据 + content = response.content#后台返回的结果 + c = next(content) + + jsload_data = ujson.loads(c) + print("jsload_data:{}".format(ujson.loads(c))) #{"resultCode": "0","resultDesc": "Success"} + if "resultCode" in jsload_data or "resultDesc" in jsload_data:#返回结果码值 + resultCode = jsload_data["resultCode"]#结果解析 "0" 成功 "1" 解码错误 "2" 校验错误 + resultDesc = jsload_data["resultDesc"]#Success 表示自注册成功 + + if resultCode == "0" or resultDesc == "Success":#注册成功退出当前注册 保存当前的ICCID 不在进行自注册了 + iccid = self.get_sim_iccid()#获取当前SIM的ICCID + if iccid != -1:#读到ICCID + self.timer_count = 0 + self.check_timer.stop() + self.isRegistOk = 1#已完成自注册的标识 + iccid_buf =str("ICCID:")+str(str(iccid)) + eventMesh.publish("save_iccid_data",iccid_buf) + self.multiple_day_resend() + #上报成功后 需要29.5或者30.5天后重发 初始值为0.5也就是12小时 30天后再重发一次也是一个月后重发数据自注册域 + print("regist success:!!!!!") + return 1 + if resultCode == "1": + print("Decode error")#解码错误 设备编码不正确 + return 0 + + if resultCode == "2":# + print("Check error")#校验错误 设备里面数据不正确 有些数据不应该为空 + return 0 + + except Exception as e: + print("response:{}".format(e)) + request_result = 0 + return 0 + + def timer_cb(self,data):#定时器回调 + self.telecom_regeist_infor()#重新进行自注册 + pass + # 多日重发功能要求: + # 1) 多日重发是指:在重发周期 T 内,如果没有功能性触发数据域自注册(触发发送且发送成功), + # 则终端应根据当前终端实时信息组织数据域自注册(不能直接拿上一周期的内容不变而重发)内容 + # 并发送的过程; + # 2) 多日重发的时间间隔周期 T 设置为 30 天; + # 3) 多日重发的过程应设置为:功能性(比如换卡等)触发数据域自注册后,立即启动定时器 t(t + # 的初始值应设为 0.5 天)开始重发计时,以后每当 t 时间等于 T 的整数倍(t=N*T)时,终端就进 + # 行数据域自注册发送,发送后 t 不要清零不要初始化,只有当功能性触发数据域自注册后,t 才初 + # 始化,t 的初始化值为 0.5 天。 + # Multiple day resend + def multiple_day_resend(self):#多日重发机制函数 没有发送数据域或者发送成功 + + t = 12 #计时周期 按照0.5天 也就是12小时来计算 + T = 30*24 #周期为30天 计算30天的总共小时数 + # t = N*T#只有t为T的整数倍就需要重发数据域自注册 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)#获取时间戳 + if self.multimer_init == 1:#已注册过或者开机5分钟之内没有注册 或者注册成功就开始出发多日重发机制 + self.mulit_day_timesec = time_tmp+MULTI_DAY_RESEND_t#初始值多加12小时 #初始化t = 0.5天 + REGIST_buf = str("REGIST:")+str(self.mulit_day_timesec) + eventMesh.publish("set_regist_time",REGIST_buf) + return + self.multimer_init = 1 + #设置开始时间戳 + get_timesec = eventMesh.publish("get_regist_time")#一开机初始化为0 没有保存过数据 如果保存过就用保存的时间 + if get_timesec == 0: + self.mulit_day_timesec = time_tmp+MULTI_DAY_RESEND_t + REGIST_buf = str("REGIST:")+str(self.mulit_day_timesec) + eventMesh.publish("set_regist_time",REGIST_buf) + else: + self.mulit_day_timesec = get_timesec + self.multiDayResend_timer.start(60*60*1000,1,self.multiDayResendTimer_Cb)#一分钟计时 + + def multiDayResendTimer_Cb(self,*argc):#多日重发机制定时器回调函数 + T = 30*24*60*60 + date_tmp = utime.localtime() + time_tmp = utime.mktime(date_tmp)+MULTI_DAY_RESEND_t#获取时间戳 + + if time_tmp < self.mulit_day_timesec:#如果当前时间戳小于保存的时间戳 + self.mulit_day_timesec = time_tmp + print("time_tmp: self.mulit_day_timesec:\r\n",time_tmp,self.mulit_day_timesec) + + if time_tmp - self.mulit_day_timesec >= MULTI_DAY_RESEND_T:#一个周期的时间到了重发注册一次 + network_state = eventMesh.publish("get_network_state") + print("get_network_state:\r\n",network_state) + if network_state == 0:#网络不正常就不需要重发了等下一个周期 + return + result = self.telecom_regist_infor_init()#要自注册数据域信息发送完才初始化t + if result == 0: #上报出错了 + return + self.mulit_day_timesec = time_tmp+MULTI_DAY_RESEND_t # 重发后 初始化t = 0.5天 + REGIST_buf = str("REGIST:")+str(self.mulit_day_timesec) + eventMesh.publish("set_regist_time",REGIST_buf) + + + def set_telecom_init_state(self,event,msg):#开机5分钟内检查是否有联网 有一次联网就关闭检查 + self.telecom_init_state = msg + + def get_telecom_init_state(self,event,msg): + return self.telecom_init_state + + def get_dmp_power_timer_count(self,event,msg):#开机后限定5分钟内完成自注册 + return REGIST_POWER_ON_TIME + + def get_dmp_power_num(self,event,msg):#开机限定次数最多十次 十次不成功就等下一次开机 或者多日重发机制 + print("get_dmp_power_num:{}".format(self.timerPowerNum)) + return self.timerPowerNum + + def set_dmp_power_num(self,event,msg): + print("set_dmp_power_num:{}".format(msg)) + self.timerPowerNum = msg + def clear_storage_data(self): + IFEXIST = ql_fs.path_exists("/usr/telecom_config.json") #不存在 + if IFEXIST == True: + uos.remove("/usr/telecom_config.json") + isStorage = ql_fs.path_exists("/usr/china_mobie_config.json")#移动入库的配置文件移除 + if isStorage == True: + uos.remove("/usr/china_mobie_config.json") + print("clear_storage_data;{} {}".format(IFEXIST,isStorage)) + + + def telecom_dmp_power_on_init(self):#开机初始化一次检测 + if eventMesh.publish("get_telecom_init_state") == 1:#发送消息获取对应的值 + return + if eventMesh.publish("get_dmp_power_num") < (eventMesh.publish("get_dmp_power_timer_count")*1000)/30000:#开机检查 + if eventMesh.publish("get_telecom_init_state") == 0:#开机初始化一次 + status = eventMesh.publish("get_factory_status") + if status == None: + status = 0 + if status == 0:#恢复出厂过需要清空存储数据 + self.clear_storage_data() + pass + self.telecomTimer.start(1*1000,0,self.fun_cb) + eventMesh.publish("set_telecom_init_state",1) + + def fun_cb(self,*argc): + self.telecom_regeist_infor()#开机初始一次自注册信息 + pass + def telecom_dmp_power_on_count(self):#开机计时判断最多十次 + if eventMesh.publish("get_telecom_init_state") != 1:#在开机五分钟之内只要一次联网正常就不需要再检查是否网络正常去自注册了 + if eventMesh.publish("get_dmp_power_num") < (eventMesh.publish("get_dmp_power_timer_count")*1000)/30000:#10+1 + num = eventMesh.publish("get_dmp_power_num") #开机计时 如果开机5分钟内没有一次网络正常的话 当前开机自注册不生效 等待下一次开机自注册触发 或者触发多日重发机制 + num+=1 + eventMesh.publish("set_dmp_power_num",num)#次数累计加一 + else: + if self.power_on_multiflag == 1: + return + self.power_on_multiflag = 1 + self.multiple_day_resend() + pass + +telecomDmpCb = telecomDmp() + + + + + + + + + + + + diff --git a/cat1modem/src/LeiNiao/vfsstat.py b/cat1modem/src/LeiNiao/vfsstat.py new file mode 100644 index 000000000..0951d5a8f --- /dev/null +++ b/cat1modem/src/LeiNiao/vfsstat.py @@ -0,0 +1,23 @@ +import gc +import uos + +usr = uos.statvfs("/usr") + +print('获取usr目录状态信息:', usr) +print('f_bsize – 文件系统块大小,单位字节:', usr[0]) +print('f_bfree – 可用块数:', usr[3]) +print('usr剩下总空间 {} 字节'.format(usr[0] * usr[3])) +print('usr剩下总空间 {} KB'.format((usr[0] * usr[3])/1024)) +print('usr剩下总空间 {} MB'.format((usr[0] * usr[3]) / 1024 / 1024)) + +bak = uos.statvfs("/bak") + +print('获取bak目录状态信息:', bak) +print('f_bsize – 文件系统块大小,单位字节:', bak[0]) +print('f_bfree – 可用块数:', bak[3]) +print('bak剩下总空间 {} 字节'.format(bak[0] * bak[3])) +print('bak剩下总空间 {} KB'.format((bak[0] * bak[3])/1024)) +print('bak剩下总空间 {} MB'.format((bak[0] * bak[3]) / 1024 / 1024)) + +mem = gc.mem_free() +print('剩余可用RAM空间:{}KB'.format(mem / 1024)) \ No newline at end of file