增加 modem 升级方式
authorhcj <1224667075@qq.com>
Thu, 10 Jul 2025 06:44:09 +0000 (14:44 +0800)
committerhcj <1224667075@qq.com>
Thu, 10 Jul 2025 06:44:09 +0000 (14:44 +0800)
19 files changed:
cat1modem/fd230/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250710-1429.zip [new file with mode: 0644]
cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944.zip [moved from cat1modem/fd230/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944.zip with 100% similarity]
cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944.zip:Zone.Identifier [new file with mode: 0644]
cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250709-1731.zip [new file with mode: 0644]
cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250710-1429.zip [new file with mode: 0644]
cat1modem/src/cat1Service.py
cat1modem/src/httpota.py [new file with mode: 0644]
cat1modem/src/main.py
code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/system/cat1ota/cat1Service.py
code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/system/cat1ota/china_mobile_ai_regulation.py [new file with mode: 0644]
code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/system/cat1ota/httpota.py [new file with mode: 0644]
code/sdk/drivers/peripheral/slip/cat1Service/CMakeLists.txt
code/sdk/drivers/peripheral/slip/cat1Service/cat1_at_cmd.cpp
code/sdk/drivers/peripheral/slip/cat1Service/cat1_server.cpp
code/sdk/drivers/peripheral/slip/cat1Service/cat1_server.h
code/sdk/drivers/peripheral/slip/cat1Service/cat1_tcpServer.cpp
code/sdk/drivers/peripheral/slip/cat1Service/cat1_ws.cpp
code/sdk/drivers/peripheral/slip/cat1Service/dev_authentication.h
code/sdk/drivers/peripheral/slip/cat1Service/http_cat1_ota.cpp [new file with mode: 0644]

diff --git a/cat1modem/fd230/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250710-1429.zip b/cat1modem/fd230/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250710-1429.zip
new file mode 100644 (file)
index 0000000..f153a28
--- /dev/null
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7b98532e83e5f83c7b86d43e923091987eb3517bacf6fc5bc24c3ed9d88ad4d9
+size 11630097
diff --git a/cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944.zip:Zone.Identifier b/cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944.zip:Zone.Identifier
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250709-1731.zip b/cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250709-1731.zip
new file mode 100644 (file)
index 0000000..065abd4
--- /dev/null
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:82324c00dd851ace1c45e65886849fe39d7d356573b965ce90b66ff123b0c6d7
+size 11630066
diff --git a/cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250710-1429.zip b/cat1modem/fd230/bak/EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_TEST0630_20250630-1944_20250710-1429.zip
new file mode 100644 (file)
index 0000000..f153a28
--- /dev/null
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7b98532e83e5f83c7b86d43e923091987eb3517bacf6fc5bc24c3ed9d88ad4d9
+size 11630097
index b8f0a8b..deed269 100644 (file)
@@ -53,6 +53,7 @@ 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
@@ -78,7 +79,7 @@ sms.setCallback(msg_cb)#sms注册回调
 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"
 
@@ -183,7 +184,7 @@ UDP_MSG_CALL_CONNECTED = 'A'       #  CAT1 电话接听消息
 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
@@ -299,6 +300,7 @@ class Cat1Service:
                 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)
@@ -395,6 +397,13 @@ class Cat1Service:
             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
diff --git a/cat1modem/src/httpota.py b/cat1modem/src/httpota.py
new file mode 100644 (file)
index 0000000..1f7ff89
--- /dev/null
@@ -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
index ab14d8b..a5bea57 100644 (file)
@@ -6,7 +6,7 @@ from machine import UART
 log.basicConfig(level=log.INFO)
 # 设置输出到debug口
 uart = UART(UART.UART0, 115200, 8, 0, 1, 0)
-log.set_output(uart)
+# log.set_output(uart)
 clog = log.getLogger("cat1")
 
 main_flag = 1
index c631c75..d0b7271 100755 (executable)
@@ -52,10 +52,10 @@ import pm
 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")
@@ -78,7 +78,7 @@ sms.setCallback(msg_cb)#sms注册回调
 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"
 
@@ -183,7 +183,7 @@ UDP_MSG_CALL_CONNECTED = 'A'       #  CAT1 电话接听消息
 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
@@ -218,7 +218,7 @@ class Cat1Service:
         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)
@@ -299,6 +299,7 @@ class Cat1Service:
                 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)
@@ -395,6 +396,13 @@ class Cat1Service:
             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
@@ -408,8 +416,6 @@ class Cat1Service:
             pass
         elif cmd == "14":#
             pass
-        
-                
         pass
 
     def set_volte_switch(self,event,msg): #设置VOLTE开关
@@ -808,12 +814,19 @@ class Cat1Service:
                 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)
diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/system/cat1ota/china_mobile_ai_regulation.py b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/system/cat1ota/china_mobile_ai_regulation.py
new file mode 100644 (file)
index 0000000..9cd4bf9
--- /dev/null
@@ -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/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/system/cat1ota/httpota.py b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/system/cat1ota/httpota.py
new file mode 100644 (file)
index 0000000..1f7ff89
--- /dev/null
@@ -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
index b4b5f30..f6c4c68 100644 (file)
@@ -19,6 +19,7 @@ set(PRIVATE_HEADER
 set(SOURCES
 ${CMAKE_CURRENT_SOURCE_DIR}/dev_authentication.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/http_cat1.cpp
+${CMAKE_CURRENT_SOURCE_DIR}/http_cat1_ota.cpp
 
 ${CMAKE_CURRENT_SOURCE_DIR}/cat1_at_cmd.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/cat1_server_hal.cpp
@@ -30,6 +31,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/cat1_ws.cpp
 
 
 
+
 )
 
 set(COMPONENT_PUBLIC_CCFLAGS
index d184439..8256686 100644 (file)
@@ -653,6 +653,36 @@ static uint32_t stopwstest(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
 }
 
 
+// static uint32_t sendfotaurl(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+// {
+//     UNUSED(strCommonCmd);
+//     uint8_t argv[PPG_MAX_ARGC][PPG_MAX_ARGV_LEN] = { 0 };
+//     uint32_t argc = 0;
+//     printf("ai_msg\n");
+//     int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+//     if (ret != PPG_SUCCESS) {
+//         printf("CAT1TEST ATCMD Convert Command Failed\n");
+//         return ERRCODE_FAIL;
+//     }
+//     // send_fota_url(" and ");
+//     return 0;
+// }
+
+static uint32_t sendfotaurl(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    uint8_t argv[PPG_MAX_ARGC][PPG_MAX_ARGV_LEN] = { 0 };
+    uint32_t argc = 0;
+    printf("ai_msg\n");
+    int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (ret != PPG_SUCCESS) {
+        printf("CAT1TEST ATCMD Convert Command Failed\n");
+        return ERRCODE_FAIL;
+    }
+    star_http_ota_updata();
+    return 0;
+}
+
 
 
 static const at_cmd_table_t g_cat1_cmd[] = {
@@ -689,6 +719,8 @@ static const at_cmd_table_t g_cat1_cmd[] = {
     { (char *)"AT^STARTTTS",      starttts, (char *)"1" },
     { (char *)"AT^SENDTTTS",      sendttstxt, (char *)"1" },
     { (char *)"AT^STOPTEST",      stopwstest, (char *)"1" },
+    { (char *)"AT^OTAHTTP",      sendfotaurl, (char *)"1" },
+
         
 };
 
index ea949f9..0c50a3e 100644 (file)
@@ -95,6 +95,8 @@ enum UDP_COMMAND_HEAD {
 
     UDP_MSG_SEND_VOLTE_SWITCH = 0x1A,//VOLTE开关
 
+     UDP_MSG_SEND_OTA= 0x1B,//OTA 升级
+
     UDP_MSG_WATCH_REPLY_ACK = 0xAC,//
     // UDP_MSG_WATCH_REPLY_HANGUP = 0x21,//
 };
@@ -395,11 +397,11 @@ void udp_send_msg_toCat1(uint8_t cmd,char *content)
         osal_msleep(50);
     }
 
-    if (g_skip_cat1_service_udp_transfer == 1)
-    {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP," g_skip_cat1_service_udp_transfer \n");
-        return ;
-    }
+    // if (g_skip_cat1_service_udp_transfer == 1)
+    // {
+    //     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP," g_skip_cat1_service_udp_transfer \n");
+    //     return ;
+    // }
     char station_tx_buffer[MAX_TCP_MSG_BUFFER_LEN] = {0};
     if( sourceAddr.sin_port != 0 ) {
         
@@ -1402,6 +1404,21 @@ void send_volte_switch_toCat1(void)//发送VOLTE->CAT1
     sprintf_s((char *)send_str,5, "%d", volte);
     udp_send_msg_toCat1(UDP_MSG_SEND_VOLTE_SWITCH,send_str);
 }
+
+void send_fota_url(char *buf)//发送VOLTE->CAT1
+{
+    // if(strlen(buf)>128)
+    // {
+    //     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"strlen(buf)>128\n");
+    // }
+    // char send_str[128] = {0};
+    // sprintf_s((char *)send_str,128, "%s", buf);
+
+    udp_send_msg_toCat1(UDP_MSG_SEND_OTA,buf);
+
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ok!\n");
+}
+
 bool get_volte_switch(void)//
 {
     bool volte = OHOS::ConfigModel::GetInstance()->GetVoLTE_Call();
index 8d7ece8..f2963d3 100644 (file)
@@ -64,6 +64,10 @@ uint8_t set_call_hungup_flag(uint8_t data);
 
 void cat1_call_hungup_timer(void);
 
+void send_fota_url(char *buf);
+
+void star_http_ota_updata(void);
+
 #ifdef __cplusplus
 #if __cplusplus
 }
index a21c3d6..708637e 100644 (file)
@@ -442,7 +442,7 @@ static void stop_cat1_ota(void){ //停止 CAT1 ota 清标识
         }
     }
     if(fp != NULL){ //防止打开文件没有关闭
-        printf("file is not close!\r\n");
+        printf("file is not lwip_close!\r\n");
         fclose(fp);
         fp = NULL;
     }
@@ -1162,7 +1162,7 @@ static int tcp_socket_file_init()
 void re_connect(void)
 {
     // socklen_t addrLen = sizeof(filesourceAddr);
-    // close(g_listen_sock);
+    // lwip_close(g_listen_sock);
     // // while (1)
     // {
     //     int connret=connect(g_listen_sock, (struct sockaddr *)&filesourceAddr,addrLen);
@@ -1200,8 +1200,8 @@ void cat1_server_file_task(void *pvParameters)
         }
         if( g_listen_sock > 0 ) 
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"close(g_listen_sock)\n");
-            close(g_listen_sock);
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"lwip_close(g_listen_sock)\n");
+            lwip_close(g_listen_sock);
         }
 
         if(is_need_udp_updata==0)
@@ -1271,7 +1271,7 @@ void cat1_server_file_task(void *pvParameters)
                 break;
                 // continue;
             } else if (len == 0) {
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Connection closed\n");
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Connection lwip_closed\n");
                 break;
                 // continue;
             }
index 4da61b1..e293a59 100644 (file)
@@ -1082,8 +1082,21 @@ bool chat_result_analysis(char *buf)
             // }
            
         }
+    }
+     if(strcmp("end",type_str)==0)
+    {   
+        char end_str_chat[128]={0};
+
+        if(strlen(content_str)>0) 
+        {
+            memset_s(end_str_chat,128,0,128); 
+            memcpy_s(end_str_chat,128,end_str_chat,strlen(end_str_chat)); 
+            ble_set_ai_Answer_str(end_str_chat,2);
+        }
 
     }
+
+
     cJSON_Delete(root);
     return true;
 }
@@ -1907,7 +1920,9 @@ void bk_websocket_tts(void *data) {
             // uapi_start_asr();
             // uapi_start_tts_single_txt("2025英超夏季转会窗分阶段开启第一阶段2025年6月1日至2025年6月11日凌晨2:00北京时间第二阶段常规夏窗2025年6月16日至2025年9月2日凌晨2:00北京时间本贴将持续更新2025年夏窗以曼联转会相关为主的新闻和消息。");
         }
+
         tts_break=0;
+        
 //    uapi_start_tts_single();
        
         char* tts_recv_buf=(char *)malloc(1024*4);
@@ -2028,6 +2043,10 @@ int32_t uapi_tts_paly_stop(void)
 {
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"uapi_tts_paly_init\n");
 
+    tts_break=1;
+    AIStreamFlush();
+    send_msg_data_into_Ai_msg_queue((uint8_t *)"tts_recv_buf",13,201);
+
     int32_t ret = ERRCODE_FAIL;
     int32_t argc = 1;
     uint8_t *argv = (uint8_t *)"stop";
@@ -2035,6 +2054,7 @@ int32_t uapi_tts_paly_stop(void)
         ret = VoiceCallVolteSample(argc, (const char **)&argv);
     }
     
+   
  
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ret  %d ",ret);
     
@@ -2057,6 +2077,8 @@ void chat_server_deinit(void)
 void tts_server_deinit(void)
 {
     send_websocket_message(tts_client,(uint8_t *)"WS_CLOSE",strlen("WS_CLOSE"),WS_CLOSE);
+
+    
 }
 
 
index 6d91265..8252252 100644 (file)
@@ -33,6 +33,9 @@ void dev_authentication_MSG_put(const char *data,uint32_t len,dev_authentication
 void aut_active(void);//设备激活;\r
 void aut_login(void);//设备激活;\r
 \r
+void system_init(void);\r
+\r
+\r
 #ifdef __cplusplus\r
 }\r
 #endif /* __cplusplus */\r
diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/http_cat1_ota.cpp b/code/sdk/drivers/peripheral/slip/cat1Service/http_cat1_ota.cpp
new file mode 100644 (file)
index 0000000..4f176d3
--- /dev/null
@@ -0,0 +1,253 @@
+#include "lwip/apps/http_client.h"
+
+
+#include <sys/time.h>
+
+#include "bletest.h"
+#include "custom_utils.h"
+#include "custom_runtime.h"
+#include "bleANCS.h"
+#include "cat1_tcpServer.h"
+#include "custom_utils.h"
+#include "broadcast_feature.h"
+#include "cmsis_os2.h"
+#include "cat1_ctl.h"
+#include "wearable_log.h"
+#include "lwip/apps/httpd.h"
+#include "dev_authentication.h"
+#include "SystemUpdateModel.h"
+
+#include "bts_br_gap.h"
+#include "custom_utils.h"
+#include "cat1_server.h"
+
+
+// http://iot.api.thisiot.com/ota/task?deviceId=281106010103&sourceVersion=PY19_1
+// http://iot.api.thisiot.com/ota/task?deviceId=281106010103&sourceVersion=PY19_2
+#if 1
+#define CAT1_HTTP_JSON_SERVER_NAME "iot.api.thisiot.com"//"test.app.api.thisiot.com"//获取升级服务器
+#define CAT1_PORT (80)//(443)//http端口号
+// #define POST_URL "http://test.iot.api.thisiot.com/ota/update-result"//上报url
+#define CAT1_JSON_URL "http://iot.api.thisiot.com/ota/task?deviceId=%s&sourceVersion=%s"//获取升级url
+#else
+
+#define CAT1_HTTP_JSON_SERVER_NAME "snicker.com.cn"//"test.app.api.thisiot.com"//获取升级服务器
+#define CAT1_PORT "snicker.com.cn"//"//升级包服务器
+#define PORT (8089)//(443)//http端口号
+#define CAT1_JSON_URL "http://snicker.com.cn:8089/fd230otanew.jsp?product=FD230&imei=%s&pkgver=%s"//获取升级url
+#endif
+
+#ifdef SINGLE_USER_PARTITION
+#define UPDATAJSONPATH "/user/update/cat1_ota.json"//获取升级的得到的json
+#else
+#define UPDATAJSONPATH "/update/ota_start_.json"//获取升级的得到的json
+#endif
+
+osSemaphoreId_t get_done_sem;
+
+static uint32_t  put_srv_res=0;
+
+static void  read_http_get_ota_url_file(char *out_put_url);
+
+
+static httpc_connection_t settings = {0};
+
+
+    static err_t httpc_download_headers_done_ui(httpc_state_t *connection, void *arg, struct pbuf *hdr, u16_t hdr_len, u32_t content_len)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "httpc_download_headers_done_ui hdrlen %d, file len %d\r\n",hdr_len,content_len); 
+        // file_total_len = content_len;
+        return 0;
+    }
+    static err_t httpc_download_file_recv_ui(httpc_state_t *connection, u32_t rx_len,u32_t rx_total_len)
+    {
+        // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "httpc_download_file_recv_ui recv %d bytes total received %d filelen %d\r\n",rx_len,rx_total_len,file_total_len);
+        return 0;
+    }
+
+    static void httpc_download_result_data_put(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, u32_t srv_res, err_t err)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "httpc_download_result_ui");
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"httpc_download_result , httpc_result_t %d, rx_content_len %d , srv_res %d, err %d\n",
+            httpc_result,rx_content_len,srv_res,err);
+        // if(srv_res==200)
+        {
+            put_srv_res=srv_res;
+
+            (void)osSemaphoreRelease(get_done_sem);
+            //激活成功
+        }
+        return ;
+    }
+
+
+uint32_t  http_get_ota_url(char *out_put_url,char *pkgver)
+{
+   
+    memset_s(&settings,sizeof(settings),0,sizeof(settings));
+    settings.use_proxy=0;
+    
+    uint8_t *otadatapath =(uint8_t *)UPDATAJSONPATH;
+
+    settings.result_fn=httpc_download_result_data_put;
+    settings.file_rx_fn = httpc_download_file_recv_ui;
+    settings.headers_done_fn = httpc_download_headers_done_ui;
+   
+    unsigned char deviceId[20] = {0};
+    memset(deviceId,0,6);    
+    bluetooth_get_local_addr(&deviceId[0],6);
+    char deviceId_temp[20] = {0};
+    sprintf(deviceId_temp,"%02X%02x%02X%02x%02X%02x",deviceId[5],deviceId[4],deviceId[3],deviceId[2],deviceId[1],deviceId[0]);
+
+     char CAT1_JSON_URL_BUF[256]={0};
+    sprintf(CAT1_JSON_URL_BUF,CAT1_JSON_URL,deviceId_temp,pkgver);
+
+    httpc_state_t* connection=NULL;
+    err_t rett= httpc_get_file_dns_to_disk(
+        CAT1_HTTP_JSON_SERVER_NAME,
+        CAT1_PORT,
+        CAT1_JSON_URL_BUF,
+        &settings, 
+        NULL, 
+        (const char*) otadatapath, 
+            &connection);
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"custom_start_ota_download %d \r\n",rett);
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "use_put");
+
+    if(rett==0)
+    {
+        get_done_sem = osSemaphoreNew(1, 0, NULL);
+    
+        osSemaphoreAcquire(get_done_sem, 1000*30);
+        
+        if(put_srv_res==200)
+        {
+            read_http_get_ota_url_file(out_put_url);
+        }
+       
+
+        osSemaphoreDelete(get_done_sem);
+
+
+        return put_srv_res;
+    }
+    else
+    {
+        return rett;
+    }   
+}
+
+
+static void  read_http_get_ota_url_file(char *out_put_url)
+{
+
+    FILE * fp = fopen(UPDATAJSONPATH,"rb+");
+    if(fp==NULL)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "open fail");
+        return;
+    }
+    char *buf=(char *)malloc(1024);
+    memset((void*)buf,0,1024);
+    int ret =fread(buf,1,1024,fp);
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "httpc_download_result_ui %d %s\r\n",ret,buf);
+    if(ret==0)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "fread %d",ret);
+        fclose(fp);
+        free(buf);
+        return;
+    }
+    fclose(fp);
+
+    char *p=buf;
+
+    while (*p!='{' && *p !='\0')
+    {
+        p++;
+    }
+    cJSON *root = cJSON_Parse(p);
+    //  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " %s",new_buf);
+    free(buf);
+
+    if(root==NULL)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "httpc_download_result_ui JSON_parse_fail");
+    }
+    else if(root!=NULL)
+    {
+        
+        int code=cJSON_GetObjectItem(root, "code")->valueint;
+        char *msg_json = cJSON_GetObjectItem(root, "msg")->valuestring;
+
+        int success=cJSON_GetObjectItem(root, "success")->valueint;
+
+        if(code==20007)
+        {
+            cJSON *data=cJSON_GetObjectItem(root, "data");
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "");
+
+            if(data!=NULL)
+            {
+                cJSON *downloadFileVo=cJSON_GetObjectItem(data, "downloadFileVo");
+
+                if(downloadFileVo!=NULL)
+                {
+                    char *uri = cJSON_GetObjectItem(downloadFileVo, "url")->valuestring;
+                    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "uri %s",uri);
+                    sprintf((char *)out_put_url,"%s",uri);
+                }
+                char* targetVersion=cJSON_GetObjectItem(data,"targetVersion")->valuestring;
+            }
+
+    }
+    cJSON_Delete(root);
+    }
+}
+
+
+// 
+// http://snicker.com.cn:8089/FD230/PY_SRV_V19/dfota_2.bin
+
+void star_http_ota_updata(void)
+{
+    int ret=0;
+    char buf_1[256]={0};
+    ret = http_get_ota_url(buf_1,"PY19_1");
+    for (int i = 0;  i <3; i++)
+    {
+        ret = http_get_ota_url(buf_1,"PY19_1");
+        if(ret==200)
+        break;
+    }
+    if(ret!=200)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ret!=200 PY19_1");
+        return;
+    }
+    char buf_2[256]={0};
+    http_get_ota_url(buf_2,"PY19_2");
+    for (int i = 0;  i <3; i++)
+    {
+        ret = http_get_ota_url(buf_2,"PY19_2");
+        if(ret==200)
+        break;
+    }
+    if(ret!=200)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ret!=200 PY19_2");
+        return;
+    }
+
+    char * send_buf=(char *) malloc(strlen(buf_1)+strlen(buf_2)+40);
+    memset(send_buf,0,strlen(buf_1)+strlen(buf_2)+40);
+    
+    sprintf(send_buf,"%s and %s",buf_1,buf_2);
+    // sprintf(send_buf,"%s and %s","http://snicker.com.cn:8089/FD230/PY_SRV_V19/dfota_1.bin","http://snicker.com.cn:8089/FD230/PY_SRV_V19/dfota_2.bin");
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s ",send_buf);
+
+    send_fota_url(send_buf);
+
+    free(send_buf);
+}
+// http_get_ota_url()
\ No newline at end of file