import sms
from usr.EventMesh import eventMesh
-
+from usr.httpota import httpota
# from usr.telecom_dmp import telecomDmpCb
# from usr.china_mobile_dmp import chinamobileCb
-
+from usr.china_mobile_ai_regulation import aiRegulation
# 设置日志输出级别
log.basicConfig(level=log.INFO)
clog = log.getLogger("cat1")
CAT1_SERVICE_HEAD = 'FE' #固定head
PROJECT_NAME = "Cat1SlipUDPService"
-PROJECT_VERSION = "PY_SRV_V18"
+PROJECT_VERSION = "PY_SRV_V19"
CONFIG_JSON="/usr/system_config.json"
CURRENT_APP_TYPE="pysrv"
UDP_MSG_CALL_DISCONNECTED = 'B' # CAT1 电话挂断消息
UDP_MSG_COMMING_CALL = 'C' # CAT1 来电消息,包含电话号
UDP_MSG_REPLY = 'F' # 返回值
-
+UDP_MSG_OTA = 'D' # 返回值
class Cat1Service:
AP = 0 # SLIP_INNER
self.iccid_data = ""
self.software_version = ""
self.deletSmsTimer = osTimer()
-
+ self.china_mobile_ai_init = 0
self.volte_switch = 1 #默认是开启VOLTE通话功能
eventMesh.subscribe("set_dmp_change_mode",self.set_dmp_change_mode)
eventMesh.subscribe("get_dmp_change_mode",self.get_dmp_change_mode)
else:
self.reply_cmd('0F',"callcmd_success")
else:
+ print("get_volte_switch NO")
self.reply_cmd('0F',"callcmd_fail")
elif cmd == "02":
clog.info(cmd)
voiceCall.startDtmf(str(parm),100) #100ms 持续时间 100-1000
elif cmd == "1A":
eventMesh.publish("set_volte_switch",int(parm))
+ elif cmd == "1B":
+ print("fota {}".format(str(parm).split("and")[0]))
+ print("fota {}".format(str(parm).split("and")[-1]))
+ # httpota = httpota()
+ httpota.run( str(parm).split("and")[0], str(parm).split("and")[-1])
+ # eventMesh.publish("set_volte_switch",int(parm))
+ # UDP_MSG_OTA
elif cmd == "AC":#
if self.ack_sem==1:
self.ack_sem=0
pass
elif cmd == "14":#
pass
-
-
pass
def set_volte_switch(self,event,msg): #设置VOLTE开关
eventMesh.publish("set_network_state",1)
# telecomDmpCb.telecom_dmp_power_on_init()
if 1: #CHINA_MOBILE_DM_FUN_ENABLE == 1:
- if eventMesh.publish("get_dmp_change_mode") > 1:
+ if eventMesh.publish("get_dmp_change_mode") == 2:
eventMesh.publish("set_network_state",1)
if self.china_mobile_init == 1:
return
self.china_mobile_init = 1
+ #移动入库的初始化
# chinamobileCb.china_mobile_init()
+ if eventMesh.publish("get_dmp_change_mode") == 3:
+ if self.china_mobile_ai_init == 1:
+ return
+ self.china_mobile_ai_init = 1
+ eventMesh.publish("set_network_state",1)
+ aiRegulation.AIRegulation_init()
def cat1_reply_iccid_to_ble(self,event,msg):
ICCID_DATA = str("ICCID:")+str(msg)
--- /dev/null
+#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()
+
--- /dev/null
+#远程升级
+
+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
import sms
from usr.EventMesh import eventMesh
-
+from usr.httpota import httpota
# from usr.telecom_dmp import telecomDmpCb
# from usr.china_mobile_dmp import chinamobileCb
-
+from usr.china_mobile_ai_regulation import aiRegulation
# 设置日志输出级别
log.basicConfig(level=log.INFO)
clog = log.getLogger("cat1")
CAT1_SERVICE_HEAD = 'FE' #固定head
PROJECT_NAME = "Cat1SlipUDPService"
-PROJECT_VERSION = "PY_SRV_V18"
+PROJECT_VERSION = "PY_SRV_V19"
CONFIG_JSON="/usr/system_config.json"
CURRENT_APP_TYPE="pysrv"
UDP_MSG_CALL_DISCONNECTED = 'B' # CAT1 电话挂断消息
UDP_MSG_COMMING_CALL = 'C' # CAT1 来电消息,包含电话号
UDP_MSG_REPLY = 'F' # 返回值
-
+UDP_MSG_OTA = 'D' # 返回值
class Cat1Service:
AP = 0 # SLIP_INNER
self.iccid_data = ""
self.software_version = ""
self.deletSmsTimer = osTimer()
-
+ self.china_mobile_ai_init = 0
self.volte_switch = 1 #默认是开启VOLTE通话功能
eventMesh.subscribe("set_dmp_change_mode",self.set_dmp_change_mode)
eventMesh.subscribe("get_dmp_change_mode",self.get_dmp_change_mode)
else:
self.reply_cmd('0F',"callcmd_success")
else:
+ print("get_volte_switch NO")
self.reply_cmd('0F',"callcmd_fail")
elif cmd == "02":
clog.info(cmd)
voiceCall.startDtmf(str(parm),100) #100ms 持续时间 100-1000
elif cmd == "1A":
eventMesh.publish("set_volte_switch",int(parm))
+ elif cmd == "1B":
+ print("fota {}".format(str(parm).split("and")[0]))
+ print("fota {}".format(str(parm).split("and")[-1]))
+ # httpota = httpota()
+ httpota.run( str(parm).split("and")[0], str(parm).split("and")[-1])
+ # eventMesh.publish("set_volte_switch",int(parm))
+ # UDP_MSG_OTA
elif cmd == "AC":#
if self.ack_sem==1:
self.ack_sem=0
pass
elif cmd == "14":#
pass
-
-
pass
def set_volte_switch(self,event,msg): #设置VOLTE开关
eventMesh.publish("set_network_state",1)
# telecomDmpCb.telecom_dmp_power_on_init()
if 1: #CHINA_MOBILE_DM_FUN_ENABLE == 1:
- if eventMesh.publish("get_dmp_change_mode") > 1:
+ if eventMesh.publish("get_dmp_change_mode") == 2:
eventMesh.publish("set_network_state",1)
if self.china_mobile_init == 1:
return
self.china_mobile_init = 1
+ #移动入库的初始化
# chinamobileCb.china_mobile_init()
+ if eventMesh.publish("get_dmp_change_mode") == 3:
+ if self.china_mobile_ai_init == 1:
+ return
+ self.china_mobile_ai_init = 1
+ eventMesh.publish("set_network_state",1)
+ aiRegulation.AIRegulation_init()
def cat1_reply_iccid_to_ble(self,event,msg):
ICCID_DATA = str("ICCID:")+str(msg)
--- /dev/null
+#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()
+
--- /dev/null
+#远程升级
+
+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