雷鸟兼容EG810的配置,cat1固件选择w9的固件,并更新cat1Service.py
author孙春阳 <snickersun@163.com>
Thu, 18 Sep 2025 13:57:24 +0000 (21:57 +0800)
committer孙春阳 <snickersun@163.com>
Thu, 18 Sep 2025 13:57:24 +0000 (21:57 +0800)
优化ppp协议响应速度

14 files changed:
cat1modem/src/LeiNiao/cat1Service.py [new file with mode: 0644]
code/sdk/build/config/target_config/brandy/config.py
code/sdk/zhihui/4g/cat1Service/Service/cat1_ctl.c
code/sdk/zhihui/4g/cat1Service/include/cat1_ctl.h
code/sdk/zhihui/CMakeLists.txt
code/sdk/zhihui/ai_stub/CMakeLists.txt [new file with mode: 0644]
code/sdk/zhihui/ai_stub/src/ppp_stub_functions.c [moved from code/sdk/zhihui/ppp/src/ppp_stub_functions.c with 72% similarity]
code/sdk/zhihui/ppp/CMakeLists.txt
code/sdk/zhihui/ppp/include/ppp_performance_config.h [new file with mode: 0644]
code/sdk/zhihui/ppp/src/ppp_api.c
code/sdk/zhihui/ppp/src/ppp_lwip.c
code/sdk/zhihui/ppp/src/ppp_power_ctl.c
code/sdk/zhihui/ppp/src/ppp_serial.c
code/sdk/zhihui/utils/custom_utils.c

diff --git a/cat1modem/src/LeiNiao/cat1Service.py b/cat1modem/src/LeiNiao/cat1Service.py
new file mode 100644 (file)
index 0000000..476be0e
--- /dev/null
@@ -0,0 +1,1121 @@
+# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.
+#  
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#  
+#     http://www.apache.org/licenses/LICENSE-2.0
+#  
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+# net.getNetMode()
+# (0, '460', '11', 7)
+
+# net.getSignal(1)
+# ([99, 99, 255, 255], [-84, -117, -15, 255, -3])
+
+# net.nitzTime()
+# ('24/02/26 11:17:42 8 0', 1708946262, 0)
+
+
+import usocket
+import log
+import utime
+import slip
+import audio
+from machine import UART
+import _thread
+from queue import Queue
+from machine import Pin
+from machine import ExtInt
+import dataCall
+import voiceCall
+import net
+import uping
+import example
+import osTimer
+import sim
+import modem
+import utime
+import checkNet
+import atcmd
+import fota
+import request
+import ql_fs
+import pm
+import sms
+import ujson
+
+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")
+
+def msg_cb(args):
+    index = args[1]
+    storage = args[2]
+    sms_data = sms.getSaveLoc()
+    if sms_data == -1:
+        return
+    sms_max = sms_data[0][2]
+    if index != -1:
+        eventMesh.publish("send_singal_data_toBle",index)
+        
+    if index >= sms_max-1:#删除短信
+        eventMesh.publish("delete_sms_event")#删除短信
+
+sms.setCallback(msg_cb)#sms注册回调
+
+CAT1_SERVICE_HEAD = 'FE' #固定head 
+
+PROJECT_NAME = "Cat1SlipUDPService"
+PROJECT_VERSION = "PY_SRV_V21"
+CONFIG_JSON="/usr/system_config.json"
+CURRENT_APP_TYPE="pysrv"
+
+
+
+
+
+
+#设置通话音量
+voiceCall.setVolume(10)
+clog.info("voice call volume {}".format(voiceCall.getVolume()))
+lpm_fd = pm.create_wakelock("system_lock", len("system_lock"))
+# pm.autosleep(1)
+pm.wakelock_lock(lpm_fd)
+clog.info("create_wakelock {}".format(pm.get_wakelock_num()))
+telecomTimerCount = 0
+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_V14"
+    elif (app_type == "pysrv"):
+        return  "PY_SRV_V16"
+
+#如果没有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):
+    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)
+        clog.info("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue))
+        clog.info("{}".format(config_data))
+    except Exception as e:
+        clog.error("set_version_to_json_config")
+
+def get_version_from_json_config(app_type):
+    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))
+    clog.info("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue))
+    return keyvalue
+
+set_version_to_json_config(CURRENT_APP_TYPE,PROJECT_VERSION)
+    
+
+audio.set_qdai_cfg(1,0,0,1,0,0,1,1)
+
+# GPIO21 - 引脚 86   KP_MKOUT1   唤醒主控
+# GPIO22 - 引脚 87   KP_MKIN     被主控唤醒
+
+# GPIOn - GPIO号,int类型,点此查看GPIO引脚编号与物理引脚的映射关系。
+
+# direction - 输入输出模式,int类型,IN - 输入模式,OUT - 输出模式。
+
+# pullMode - 上下拉模式,int类型,说明如下:
+# PULL_DISABLE - 浮空模式
+# PULL_PU - 上拉模式
+# PULL_PD - 下拉模式
+
+# level - 引脚电平,int类型,0 - 设置引脚为低电平, 1- 设置引脚为高电平。
+# recvDataPin = Pin(Pin.GPIO22, Pin.IN, Pin.PULL_PU, 0)
+def ExtIntfun(args):
+        # clog.info('### interrupt  {} ###'.format(args)) # args[0]:gpio号 args[1]:上升沿或下降沿
+        if args[1] == 0:
+            clog.info("disable autosleep")
+            # pm.autosleep(0)
+            pm.wakelock_lock(lpm_fd)
+        elif args[1] == 1:
+            clog.info("enable autosleep")
+            pm.wakelock_unlock(lpm_fd)
+            # pm.autosleep(1)
+        # clog.info("recvDataPin={}".format(recvDataPin.read()))
+extint = ExtInt(ExtInt.GPIO22, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_DISABLE, ExtIntfun)
+extint.enable()
+
+
+# 创建gpio对象
+gpioWakeBT = Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_DISABLE, 1)
+# 设置输入输出模式
+gpioWakeBT.set_dir(Pin.OUT)
+
+# 设置引脚电平
+gpioWakeBT.write(0)
+
+UDP_CMD_GET_CAT1VER = '0'  #获取 Cat1 版本号
+UDP_CMD_DIAL_NUMB = '1'              #拨打电话
+UDP_CMD_HUNGUP = '2'               #挂断电话
+UDP_CMD_ANSWER = '3'            #接听电话
+UDP_CMD_CAT1_OTA_UPDATE = '4'       #触发Cat1 OTA升级,mcu提供url
+UDP_CMD_SEND_SMS = '5'         #发送SMS短信,mcu提供电话号及短信内容
+UDP_CMD_GET_TIME = '6'               #获取Cat1 时间 ,YYYYMMDD HHmmss zone
+UDP_CMD_GET_RECV_NETWORKSTAT = '7'      #获取Cat1 信号信息,VOLTE信息,信号强度,SIM卡状态  // 内容同UDP_CMD_GET_NETWORKSTAT,CAT主动发给MCU
+UDP_MSG_SMS = '8'           #  CAT1接收到的SMS信息给MCU,包含电话号及短信内容
+UDP_CMD_ATCMD = '9'           # 执行AT指令
+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
+    STA = 1 # SLIP_OUTER
+
+    def __init__(self, uart=UART.UART2, mode=AP):
+        
+        self.__uart = uart
+        self.__mode = mode
+        self.__message = ''
+        self.__err = 0
+        self.__net_connected = 0
+        # self.__value = None
+        self.__wait_resp = 0
+        self.__waiting_netstat = 0
+        slip.destroy()
+        clog.info('slip uart={0}'.format (self.__uart))
+
+        ret = slip.construct(self.__uart, self.__mode, 0)
+        if ret != 0:
+            clog.error('slip netif construct fail')
+            return None
+        clog.info('slip network card create success')
+        # self.__queue = Queue(1)
+        self.__sock = self.__socket_init()
+        self.__threadid = _thread.start_new_thread(self.__Socket_Thread, ())
+        self.telecom_init_flag = 0
+        self.telecomTimer = osTimer()
+        eventMesh.subscribe("cat1_reply_iccid_to_ble",self.cat1_reply_iccid_to_ble)
+        eventMesh.subscribe("cat1_reply_timesec_to_ble",self.cat1_reply_timesec_to_ble)
+        
+        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)
+        eventMesh.subscribe("delete_sms_event",self.delete_sms_event)
+        eventMesh.subscribe("remove_all_sms_cb", self.remove_all_sms_cb)#
+        eventMesh.subscribe("send_sms_max_to_Ble",self.send_sms_max_to_Ble)
+        eventMesh.subscribe("get_all_sms_data",self.get_all_sms_data) #获取所有的短信内容
+        eventMesh.subscribe("send_singal_data_toBle",self.send_singal_data_toBle)
+        eventMesh.subscribe("delete_sms_single_data",self.delete_sms_single_data)
+
+        eventMesh.subscribe("get_factory_status",self.get_factory_status)
+        eventMesh.subscribe("set_factory_status",self.set_factory_status)
+        eventMesh.subscribe("send_dmp_cm_address_toBLE",self.send_dmp_cm_address_toBLE)
+        eventMesh.subscribe("set_volte_switch",self.set_volte_switch)
+        eventMesh.subscribe("get_volte_switch",self.get_volte_switch)
+        eventMesh.publish("delete_sms_event")
+
+       
+        self.telecom_dmp_switch = 0
+
+        self.send_data = []
+        self.code_old = 0
+        self.code_old_num = 1
+        self.tmp_data = []
+        self.total_num = 0
+        #
+        self.msg_nums = 0
+        self.msg_nums_old = 0
+        self.china_mobile_init = 0
+        self.factory_status = 0
+        self.send_data_q = Queue(100)
+        self.ack_sem=0
+        _thread.start_new_thread(self.Socket_SEND_Thread,())
+        # 发数据线程
+        return None
+
+    def __socket_init(self):
+        # 创建一个socket实例
+        sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM, usocket.TCP_CUSTOMIZE_PORT)
+        sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1)
+        # 绑定IP
+        bind_addr = ('172.16.1.2', 5000)
+        sock.bind(bind_addr)
+        sock.settimeout(None)
+        return sock
+
+    def __socket_reinit(self):
+        return self.__socket_init()
+    
+    def bootup_msg_to_bt(self):
+        modem_ver = modem.getDevFwVersion() 
+        self.reply_cmd('0F',"BOOTUP@pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver))
+        self.reply_cmd('0F',"VOLUME:{}".format(voiceCall.getVolume()))
+
+    def btmcu_cmd_handler(self,cmd,parm):
+        
+        # cmd = ""
+        # cmd_tmp= int(cmd_data)#将十进制数转换成int 再转换成十六进制
+        # cell_data = hex(cmd_tmp)
+        # decimal_number = int(cell_data, 16)
+        # cmd = "%02x"%(decimal_number)  # 使用两位表示,不足前面补0
+        clog.info(cmd)  # 输出: 07
+        clog.info("btmcu_cmd_handler cmd {0} , args {1}".format(cmd,parm))
+        if cmd == "00":
+            clog.info(cmd)
+            # UDP_CMD_GET_CAT1VER
+            modem_ver = modem.getDevFwVersion() 
+            self.reply_cmd('00',"pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver))
+        elif cmd == "01":
+            # UDP_CMD_DIAL_NUMB
+            if eventMesh.publish("get_volte_switch") == 1: #只有BLE开了VOLTE才允许打电话
+                ret = voiceCall.callStart(str(parm))
+                # if ret != 0:
+                #     ret = voiceCall.callStart(str(parm))
+                clog.info("ret={} {} {}".format(ret,cmd,parm))
+                if ret != 0:
+                    self.reply_cmd('0F',"callcmd_fail")
+                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)
+            # UDP_CMD_HUNGUP
+            ret = voiceCall.callEnd()
+            if ret != 0:
+                ret = voiceCall.callEnd()
+            if ret != 0:
+                self.reply_cmd('0F',"callend_fail")
+            else:
+                self.reply_cmd('0F',"callend_success")
+        elif cmd == "03":
+            clog.info(cmd)
+            # UDP_CMD_ANSWER
+            ret = voiceCall.callAnswer()
+            if ret != 0:
+                ret = voiceCall.callAnswer()
+            if ret != 0:
+                self.reply_cmd('0F',"callanswer_fail")
+            else:
+                self.reply_cmd('0F',"callanswer_success")
+        elif cmd == "04":
+            clog.info(cmd)
+        elif cmd == "05":
+            clog.info(cmd)
+            # UDP_CMD_SEND_SMS
+        elif cmd == "06":
+            clog.info(cmd)
+            # UDP_CMD_GET_TIME
+            time=utime.localtime()
+            zone=utime.getTimeZone()
+            #(2024, 3, 2, 18, 31, 32, 5, 62),8
+            # 返回当前时间戳,参数为元组
+            # timestamp = utime.mktime(time)
+            # clog.info(timestamp)
+            self.reply_cmd('06',"{0}@{1}".format(time,zone))
+        elif cmd == "07":
+            clog.info("cmd ==== 07!")
+            # UDP_CMD_GET_RECV_NETWORKSTAT
+            simstat = sim.getStatus()
+            imei = modem.getDevImei()
+            netstat = "0,10,0,10"
+            netstat_ = net.getState()
+            if netstat_ != -1 :
+                netstat = "{},{},{},{}".format(netstat_[0][0],netstat_[0][3],netstat_[1][0],netstat_[1][3])
+            # ([voice_state, voice_lac, voice_cid, voice_rat, voice_reject_cause, voice_psc], [data_state, data_lac, data_cid, data_rat, data_reject_cause, data_psc])
+            operator =  net.operatorName()
+            signal = net.csqQueryPoll()
+            clog.info("imei:{0},sim:{1},oper:{2},signal:{3},net:{4}".format(imei,simstat,operator,signal,netstat))
+            self.reply_cmd('07',"imei:{0}@sim:{1}@oper:{2}@signal:{3}@net:{4}".format(imei,simstat,operator,signal,netstat))
+        elif cmd == "09":
+            clog.info("{},{}".format(cmd,parm))
+            # UDP_CMD_ATCMD
+            # net.setModemFun(0)
+            # net.setModemFun(1)
+            resp=bytearray(50)
+            ret=atcmd.sendSync("{}\r\n".format(parm),resp,'',10)
+            if ret == 0:
+                clog.info("reply:{},ret:{}".format(resp.decode(),ret))
+                self.reply_cmd('09',"{}".format(resp.decode()))
+            else:
+                clog.info("cmd error ret:{}".format(ret))
+                self.reply_cmd('09',"{}".format("at error"))
+        
+        elif cmd == "10" or cmd == "12" or cmd == "14": #获取固件版本号或者获取BT保存的SIM卡的ICCID BLE那边是否开启电信入库功能
+            if 1: #CHINA_TELECOM_DM_FUN_ENABLE == 1 :
+                if eventMesh.publish("get_dmp_change_mode") == 1:
+                    self.telecom_recv_cmd(cmd,parm)
+            else:
+                pass
+
+            if 1:#CHINA_MOBILE_DM_FUN_ENABLE == 1:
+                if eventMesh.publish("get_dmp_change_mode") > 1:
+                    self.china_mobile_recv_cmd(cmd,parm)
+            else:
+                pass
+            pass
+        elif cmd == "13":
+            on = int(parm)
+            clog.info("set_dmp_change_mode on:{}".format(on))
+            eventMesh.publish("set_dmp_change_mode",on)
+
+        elif cmd == "16":
+            if 1: #CHINA_MOBILE_DM_FUN_ENABLE == 1:
+                if eventMesh.publish("get_dmp_change_mode") > 1:
+                    self.china_mobile_recv_cmd(cmd,parm)
+            else:
+                pass
+        elif cmd == "17": #用于CAT1恢复出厂需要清空数据的标识通用
+            eventMesh.publish("set_factory_status",int(parm))
+        elif cmd == "18":
+            eventMesh.publish("set_dmp_cm_address",str(parm))
+        elif cmd == "19": #DTMF功能
+            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 == "1C":# 
+            self.read_dev_ai_id()
+        elif cmd == "AC":#
+            if self.ack_sem==1:
+                self.ack_sem=0
+      
+               
+
+    def telecom_recv_cmd(self,cmd,parm): 
+        if cmd == "10":
+            self.software_version = str(parm)
+            eventMesh.publish("set_dev_version",self.software_version)
+            clog.info("software_version:{},{}".format(self.software_version,parm))
+        elif cmd == "12":
+            pass
+        elif cmd == "14":#
+            pass
+        pass
+
+    def set_volte_switch(self,event,msg): #设置VOLTE开关
+        self.volte_switch = int(msg)
+        
+
+    def get_volte_switch(self,event,msg): #获取VOLTE开关
+
+        return self.volte_switch
+        
+
+    def china_mobile_recv_cmd(self,cmd,parm): #移动入库相关指令
+        if cmd == "10":
+            self.software_version = str(parm)
+            eventMesh.publish("set_dev_version",self.software_version)
+            clog.info("software_version:{},{}".format(self.software_version,parm))
+        elif cmd == "16": #获取BLE mac地址
+            eventMesh.publish("set_dev_mac",str(parm))
+            clog.info("parm:{}\r\n".format(parm))
+                
+        pass
+    def get_factory_status(self,event,msg):
+        return self.factory_status
+    def set_factory_status(self,event,msg):
+        self.factory_status = int(msg)
+        if self.factory_status == 0: #只有为的时候才设置进去 1不再设置
+            self.reply_cmd('17',"{}".format(1))
+
+    def send_dmp_cm_address_toBLE(self,event,msg):
+        buf_tmp = "address:"+str(msg)
+        self.reply_cmd('18',"{}".format(buf_tmp))
+        
+    def set_dmp_change_mode(self,event,msg):
+        self.telecom_dmp_switch = msg
+    def delete_sms_single_data(self,event,msg): #删除单条信息
+        sms.deleteMsg(int(msg))
+
+    def get_dmp_change_mode(self,event,msg):
+        return self.telecom_dmp_switch
+    def delete_sms_event(self,event,msg):
+        self.deletSmsTimer.start(2*1000,0,self.delete_sms_cb)
+    def delete_sms_cb(self,*argc):
+        eventMesh.publish_async("remove_all_sms_cb","",1*1024)
+    def remove_all_sms_cb(self, event, msg):
+        clog.info("remove_all_sms_cb\r\n")
+        msg_nums = sms.getMsgNums() #短信数量
+        if msg_nums == -1:
+            msg_nums = 0
+        sms_data = sms.getSaveLoc()
+        clog.info("{}\r\n".format(sms_data))
+        if sms_data == -1:
+            return
+        sms_max = sms_data[0][2] #最大存储短信数量
+        if sms_max >= msg_nums and sms_max > 0:
+            sms.deleteMsg(1,4) #删除所有的sms信息
+
+    def send_singal_data_toBle(self,event,msg):
+        msg_nums = sms.getMsgNums() #短信数量
+        if msg_nums == -1:
+            msg_nums = 0
+        sms_data = sms.getSaveLoc()
+        if sms_data == -1:
+            return
+        sms_max = sms_data[0][2] #最大存储短信数量
+        clog.info("recv:{}".format(int(msg)))
+        message=self.sms_get_message_info(int(msg))
+        if message == -1: #说明没有这条短信
+            return
+        message_pdu = sms.decodePdu(message[5],20)
+        
+        if message_pdu != -1: #解码出来的内容
+
+            message_ref = message[0] #编码
+            message_total_num = message[1] #总共条数
+            message_seq = message[2] #当前第几条
+            data = message[5] #内容
+            data_len = len(data) #内容长度
+            # ref        :短信参考标识,同一个标识表明为同一条短信 
+            # total_num  :此条长短信总条数 大于1属于长短信
+            # seq        :此条短信在长短信中的序号
+            # print("message:{} {}\r\n".format(message,message_pdu))
+            msg_total = "ref:"+str(message_ref)+"@total_num:"+str(message_total_num)+"@seq:"+str(message_seq)+"@data:"+str(message[5])
+            self.reply_cmd('15',msg_total)
+        
+        eventMesh.publish("delete_sms_single_data",int(msg))
+
+    def sms_deal_phone_number(self,args):
+        data=enumerate(args)
+        data_str1=""
+        data_str2=""
+        data_str3=""
+        for index,value in data:
+            if index % 2 == 0:
+                data_str1=data_str1+value
+            else:
+                data_str2=data_str2+value
+        for i in range(0,len(data_str1)):
+            data_str3=data_str3+data_str2[i]
+            data_str3=data_str3+data_str1[i]
+        return data_str3
+    def sms_get_message_info(self,index):
+        """
+        :param index    :短信索引值
+        :tyoe  index    :整形
+        
+        :return         :元组类型
+        元组内容:
+        (message_ref,message_total_num,message_seq,sub_message_data,pdu_tye,sub_message_len)
+        
+        :message_ref        :短信参考标识,同一个标识表明为同一条短信
+        :message_total_num  :此条长短信总条数
+        :message_seq        :此条短信在长短信中的序号
+        :sub_message_data   :词条短信的内容
+        :pdu_tye            :PDU类型,bit 6标记是否包含用户报文头,长短信需要
+        :sub_message_len    :此条短信内容长度
+        
+        """
+
+        message0=sms.searchPduMsg(index)  
+        #print("sms_get_message_info:message0:{}".format(message0))
+        if message0 == -1:
+            return -1
+        
+        sca_num  = int(message0[0:2],16) - 1
+        data_len = 2
+        addr_type= message0[data_len:data_len+1*2]
+        data_len = data_len+1*2
+        
+        sca      = message0[data_len:data_len+sca_num*2]
+        # 电话号码高低位需要转换
+        sca = self.sms_deal_phone_number(sca)
+
+        # if sca_num % 2 == 1:
+        #      print("Get SCA phone {}".format(sca[:-1]))
+        # else:
+        #      print("Get SCA phone {}".format(sca))
+
+        data_len = data_len+sca_num*2
+
+        pdu_tye   = int(message0[data_len:data_len+1*2],16)
+        data_len = data_len+1*2
+
+        oa_num   = int(message0[data_len:data_len+1*2],16)
+        data_len = data_len+1*2
+        oa_addr_type   = message0[data_len:data_len+1*2]
+        data_len = data_len+1*2
+
+        if oa_num % 2 == 1:
+             oa_num_t   = int((oa_num + 1)/2)
+        else:
+             oa_num_t   = int((oa_num )/2)
+
+        oa       = message0[data_len:data_len+oa_num_t*2]
+        # 电话号码高低位需要转换
+        oa       = self.sms_deal_phone_number(oa)
+
+        # if oa_num % 2 == 1:
+        #      print("Get OA phone {}".format(oa[:-1]))
+        # else:
+        #      print("get OA phone {}".format(oa))
+
+        data_len = data_len+oa_num_t*2
+        pid      = message0[data_len:data_len+1*2]
+        
+        data_len = data_len+1*2
+        dcs      = message0[data_len:data_len+1*2]
+        data_len = data_len+1*2
+        scts     = message0[data_len:data_len+7*2] 
+        data_len = data_len+7*2
+        sub_message_len = int(message0[data_len:data_len+1*2],16)
+        data_len = data_len+1*2
+        sub_message_head = message0[data_len:data_len+6*2]
+        data_len = data_len+6*2
+
+        # 或短信用户数据
+        sub_message_data = message0[data_len:data_len+sub_message_len*2]
+
+        #长短信
+        if ((pdu_tye & 0x40 ) >> 6) == 1:
+            #长短信,处理长短信用户报文头
+            message_ref = int(sub_message_head[6:8],16)
+            message_total_num = int(sub_message_head[8:10],16)
+            message_seq = int(sub_message_head[10:12],16)
+            return [message_ref,message_total_num,message_seq,pdu_tye,sub_message_len,message0]
+        else:
+             # 短短信
+            return [0,1,1,pdu_tye,sub_message_len,message0]
+
+
+
+    def send_sms_max_to_Ble(self,event,msg):
+        msg_nums = sms.getMsgNums()#短信数量
+        if msg_nums == -1:
+            msg_nums = 0
+        sms_data = sms.getSaveLoc()
+        if sms_data != -1:
+            sms_max = sms_data[0][2]#最大存储短信数量
+            self.reply_cmd('15',"@sms_max:"+str(sms_max)+"@current_num:"+str(msg_nums))
+        pass
+    
+    def get_all_sms_data(self,event,msg):
+        msg_total = ""
+        SMS_lis={}
+        SMS_lis_count = 0
+        sms_data = sms.getSaveLoc()
+        clog.info(sms_data)
+        if sms_data == -1:
+            return
+        sms_max = sms_data[0][2]#最大存储短信数量
+        clog.info(sms_max)
+        self.msg_nums = sms.getMsgNums() 
+        if self.msg_nums_old != self.msg_nums:
+            self.send_data = []
+        self.msg_nums_old = self.msg_nums
+        if self.send_data == [] :
+            for i in range(self.msg_nums):
+                phonenum = ""
+                data =""
+                time = ""
+                data_len = 0
+                message=self.sms_get_message_info(self.msg_nums-i-1)
+                if message == -1:
+                    break
+                data = message[5]
+                sms_data = []
+                code = message[0]#编码
+                num = message[1]#总共条数
+                curren_num = message[2]#当前第几条
+                data_len = message[4]
+                sms_data.append(code)#编码 编码相同是同一条短信的内容
+                sms_data.append(num)
+                sms_data.append(curren_num)
+                sms_data.append(data)
+                sms_data.append(data_len)
+                self.send_data.append(sms_data)
+        count = len(self.send_data)
+        for i in range(count):
+            text = self.send_data[i]
+            clog.info("text:{} {} {}\r\n".format(text[0],text[1],text[2]))
+
+            msg_total = "@code:"+str(text[0])+"@totalcodenum:"+str(text[1])+"@currcodeid:"+str(text[2])+"@data:"+str(text[3])
+            self.reply_cmd('17',msg_total)
+
+    # 来电提醒
+    def notifyIncomingcall(self, incomming_numb):
+        self.clear_remain()
+        __head = '0C'
+        __message = str(incomming_numb)
+        self.__Socket_UDP(__head, __message)
+        # if self.__err == 1 or self.__value[2] != 'OK':
+        #     return -1
+        return 0
+
+    # 电话接听消息
+    def notifyConnecteCall(self, phone_numb):
+        self.clear_remain()
+        __head = '0A'
+        __message = str(phone_numb)       
+        self.__Socket_UDP(__head, __message)
+        # if self.__err == 1 or self.__value[2] != 'OK':
+        #     return -1
+        return 0
+
+    # 电话拒接消息
+    def notifyDisconnectCall(self, phone_numb):
+        self.clear_remain()
+        __head = '0B'
+        __message = str(phone_numb)            
+        self.__Socket_UDP(__head, __message)
+        # if self.__err == 1 or self.__value[2] != 'OK':
+        #     return -1
+        return 0
+    
+    def wait_network_ready(self):
+        if(self.__waiting_netstat == 1):
+            return 0
+        self.__waiting_netstat = 1
+        stage, state = checkNet.waitNetworkReady(30)
+        pm.wakelock_unlock(lpm_fd)
+        if stage == 3 and state == 1:
+            clog.info('Network connection successful.')
+            self.set_network_config()
+            self.__net_connected = 1
+            eventMesh.publish("set_network_state",self.__net_connected)
+            self.__waiting_netstat = 0
+            return 0
+        else:
+            clog.info('Network connection failed, stage={}, state={}'.format(stage, state))
+            self.reset_network_config()
+            self.__net_connected = 0
+            eventMesh.publish("set_network_state",self.__net_connected)
+
+            self.__waiting_netstat = 0
+            return -1
+
+    # 查询网卡状态
+    def timesync(self,_timesync):
+        self.clear_remain()
+        message = str(_timesync)
+        self.__Socket_UDP('0D', message)
+        return 0
+    
+    def reply_timesync(self,_timesync):
+        self.clear_remain()
+        message = str(_timesync)
+        self.__Socket_UDP_noreply('0D', message)
+        return 0
+
+    def reply_cmd(self,cmd,_timesync):
+        try :
+            clog.info('reply_cmd 1')
+            self.clear_remain()
+            message = str(_timesync)
+            clog.info('reply_cmd 2')
+            self.__Socket_UDP_noreply(cmd, message)
+        except:
+            clog.info('reply_cmd')
+        return 0
+    
+    def clear_remain(self):
+        # if self.__queue.empty() == False:
+        #     self.__queue.get()
+        self.__err = 0
+        # self.__value = None
+    #添加路由信息
+    def router_add(self, ip='192.168.4.1', mask='255.255.255.0'):
+        self.ip = ip
+        self.mask = mask
+        
+        return slip.router_add(self.ip, self.mask)
+
+    # 获取slip的网络配置
+    def ipconfig(self):
+        return slip.ipconfig()
+
+       # 设置dns服务器
+    def set_dns(self, pri_dns='8.8.8.8', sec_dns='114.114.114.114'):
+        self.pri_dns = pri_dns
+        self.sec_dns = sec_dns
+        return slip.set_dns(self.pri_dns,self.sec_dns)
+    
+       # 设置默认网卡
+    def set_default_NIC(self, ip_str):
+        self.ip_str = ip_str
+        return slip.set_default_netif(self.ip_str)
+    
+    def reset_network_config(self):
+        if (self.__net_connected == 0):
+            clog.info("skip reset_network_config")
+            return 0
+        Info = dataCall.getInfo(1,0)
+        clog.info("Info{}".format(Info))
+        default_NIC_ip = Info[2][2]    # 假设默认网卡ip地址为10.10.1.1,请根据实际情况更改
+        segment_ip = '172.16.4.0'      # 假设ap模式网段范围是[192.168.4.0 ~ 192.168.4.255],请根据实际情况更改
+        mask = '255.255.255.0'          # 假设子网掩码为255.255.255.0,请根据实际情况更改
+        # 配置默认网卡,通过默认网卡进行网络转发
+        cat1service.set_default_NIC(default_NIC_ip)
+        clog.info("default_NIC_ip {0} segment_ip {1}".format(default_NIC_ip,segment_ip))
+        #添加路由规则,只有该网段IP才进行转发
+        cat1service.router_add(segment_ip, mask)
+
+        pri_dns = '8.8.8.8'             # 假设DNS首选地址为8.8.8.8,请根据实际情况更改
+        sec_dns = '114.114.114.114'     # 假设DNS备选地址为114.114.114.114,请根据实际情况更改
+        # 配置网卡DNS服务器
+        cat1service.set_dns(pri_dns, sec_dns)
+        # 网卡IP信息查询
+        cat1service.ipconfig()
+
+    def set_network_config(self):
+        
+
+        if (self.__net_connected == 1) :
+            clog.info("skip set_network_config")
+            return 0
+        Info = dataCall.getInfo(1,0)
+        clog.info("Info{}".format(Info))
+        default_NIC_ip = Info[2][2]    # 假设默认网卡ip地址为10.10.1.1,请根据实际情况更改
+        segment_ip = '172.16.1.0'      # 假设ap模式网段范围是[192.168.4.0 ~ 192.168.4.255],请根据实际情况更改
+        mask = '255.255.255.0'          # 假设子网掩码为255.255.255.0,请根据实际情况更改
+        # 配置默认网卡,通过默认网卡进行网络转发
+        cat1service.set_default_NIC(default_NIC_ip)
+        clog.info("default_NIC_ip {0} segment_ip {1}".format(default_NIC_ip,segment_ip))
+        #添加路由规则,只有该网段IP才进行转发
+        cat1service.router_add(segment_ip, mask)
+
+        pri_dns = '8.8.8.8'             # 假设DNS首选地址为8.8.8.8,请根据实际情况更改
+        sec_dns = '114.114.114.114'     # 假设DNS备选地址为114.114.114.114,请根据实际情况更改
+        # 配置网卡DNS服务器
+        cat1service.set_dns(pri_dns, sec_dns)
+        # 网卡IP信息查询
+        cat1service.ipconfig()
+        if eventMesh.publish("get_dmp_change_mode") == 0:#入库功能关闭
+            return
+        if 1: #CHINA_TELECOM_DM_FUN_ENABLE == 1:#电信入库功能 不使用设置 0 防止两边不同步修改
+            if eventMesh.publish("get_dmp_change_mode") == 1:
+                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") == 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)
+        self.reply_cmd('11',"{}".format(ICCID_DATA))
+        pass
+    def cat1_reply_timesec_to_ble(self,event,msg):
+       
+        self.reply_cmd('14',"REGIST_TIME:{}".format(msg))
+        pass
+    # 释放slip网卡
+    def stop(self):
+        slip.destroy()
+        return 0
+    
+    def read_dev_ai_id(self):
+        
+        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:
+    
+                print("设备信息配置文件不存在\r\n")
+            else:
+                try:
+                    with open("/usr/cm_ai_regulation.json","r",encoding='utf-8') as fd:
+                        try:
+                            config_data = ujson.load(fd) #转换成json格式
+                            if len(config_data) != 0:
+                                if "deviceId" in config_data:# 
+                                    deviceId = str(config_data["deviceId"]) #设备ID
+                                    self.reply_cmd('1C',"{}".format(deviceId))
+                        except Exception as error:
+                            print("配置文件的内容不是json格式 保存数据的时候格式不对\r\n")
+                except Exception as error:
+                    print("打开配置文件失败\r\n")
+
+    
+
+
+    # 封装tlv数据包
+    def __pack_tlv_format(self, head, content):
+        # self.head = head
+        # self.content = content
+        if len(content) == 0 or len(content) > 9999 or len(head) != 2:
+            clog.error('illegal pack tlv content')
+            return -1
+        len_str ='%04d' % len(content)
+        tlv_pack = CAT1_SERVICE_HEAD+head+len_str+content
+        return tlv_pack
+    # 解码tlv数据包
+    def __unpack_tlv_format(self, msg):
+        clog.info('__unpack_tlv_format  {}\r\n'.format(msg))
+        self.msg = str(msg)[2:]#这是去除head FE
+        tag = self.msg[0:2]
+        length = self.msg[2:6]
+        value = self.msg[6:]
+        len_str ='%04d' % len(value)
+        if len(value) == 0 or len(value) > 9999 or len(tag) != 2 or len_str != self.msg[2:6]:
+            clog.error('__unpack_tlv_format err')
+            return -1
+        clog.info('__unpack_tlv_format: {} {} {}\r\n'.format(tag,length,value))
+        unpack = (tag,length,value)
+        return unpack
+    # socket通信(UDP)模块
+    def __Socket_UDP(self, head, content):
+         # 0 则  __Socket_UDP_write
+        self.send_data_q.put([head,content])
+    def Socket_SEND_Thread(self):
+        while True:
+            try:
+                clog.info("send====")
+                data=self.send_data_q.get()
+                self.ack_sem=1
+                # # if data[2]:
+                #     self.__Socket_UDP_noreply_write( data[0], data[1])
+                # else :
+                self.__Socket_UDP_write( data[0], data[1])
+                
+                
+                clog.info("Socket_SEND_Thread data:{} {}".format(data[0],data[1]))
+                count=20
+                
+                while count & self.ack_sem :
+                    utime.sleep_ms(1)
+                    count=count-1
+                    # if data[2]:
+                    #     self.__Socket_UDP_noreply_write( data[0], data[1])
+                    # else :
+                    self.__Socket_UDP_write( data[0], data[1])
+                        
+                    clog.info("Socket_SEND_Thread  while data:{} {}".format(data[0],data[1]))
+                
+                if data:
+                        clog.info("data ok!!")
+                else:
+                        clog.error("data error!!")
+            except Exception :
+                clog.error("sned Socket >>>")
+   
+    def __Socket_UDP_write(self, head, content):
+        try:
+            ##self.head = head
+            # self.content = content
+            gpioWakeBT.write(1)
+            utime.sleep_ms(2)
+            gpioWakeBT.write(0)
+            utime.sleep_ms(20)
+            # 消息处理
+            msg = self.__pack_tlv_format(head, content)
+
+            # 向服务端发送消息
+            server_addr = ('172.16.1.5',1000)
+            clog.info("__Socket_UDP send msg {}".format(msg))
+            self.__err = 0
+            self.__sock.sendto(msg,server_addr)
+            clog.info("__Socket_UDP send 2")
+            self.__wait_resp = 1
+            # data = self.__queue.get()
+            self.__wait_resp = 0
+            # return data
+            return 1
+        except Exception as error:
+            clog.error(error)
+        return 0
+   
+    def __Socket_UDP_noreply(self, head, content):
+         # 1 则  __Socket_UDP_noreply_write
+         self.send_data_q.put([head,content])
+         
+    def __Socket_UDP_noreply_write(self, head, content):    
+        # self.head = head
+        # self.content = content
+        gpioWakeBT.write(1)
+        utime.sleep_ms(2)
+        gpioWakeBT.write(0)
+        utime.sleep_ms(20)
+        # 消息处理
+        msg = self.__pack_tlv_format(head, content)
+
+        # 向服务端发送消息
+        server_addr = ('172.16.1.5',1000)
+        
+        clog.info("__Socket_UDP_noreply send msg {}".format(msg))
+        self.__err = 0
+        data_size = self.__sock.sendto(msg,server_addr)
+        clog.info("self.__sock data_size {}".format(data_size))
+        self.__wait_resp = 0
+        return 0
+
+    # socket通信(UDP)模块
+    def __Socket_Thread(self):
+        while True:
+            try:
+                clog.info("recv====")
+                data=self.__sock.recv(1024)
+                clog.info("data:{}".format(data))
+                if data:
+                    value = self.__unpack_tlv_format(data.decode())
+                    if value != -1:
+                        clog.info('mode: {0}, recv {1} bytes, Data: {2}'.format (value[0],len(data), value[2]))
+                        if value[1] == 'FF':
+                            self.btmcu_cmd_handler(value[0],value[2])
+                        else:
+                            # self.__value = value
+                            # self.__queue.put('1')
+                            self.btmcu_cmd_handler(value[0],value[2])
+                        clog.info("End else Thread")
+                    else:
+                        clog.error("data error!!")
+            except Exception as recverr:
+                clog.error("recverr:{}\r\n".format(recverr))
+                if "110" in str(recverr):
+                    self.__err = 1
+                    # if self.__wait_resp == 1:
+                    #     self.__queue.put('0')
+                else:
+                    utime.sleep(1)
+                    self.__sock = self.__socket_reinit()
+                
+            
+
+        clog.info("End Socket Thread")
+
+
+
+
+# UDP_CMD_GET_CAT1VER = '0',  // 获取 Cat1 版本号
+# UDP_CMD_DIAL_NUMB = '1',               //  拨打电话
+# UDP_CMD_HUNGUP = '2',                 //  挂断电话
+# UDP_CMD_ANSWER = '3',            //  接听电话
+# UDP_CMD_CAT1_OTA_UPDATE = '4',       // 触发Cat1 OTA升级,mcu提供url
+# UDP_CMD_SEND_SMS = '5',               // 发送SMS短信,mcu提供电话号及短信内容
+# UDP_CMD_GET_TIME = '6',               // 获取Cat1 时间 ,YYYYMMDD HHmmss zone
+# UDP_CMD_GET_NETWORKSTAT = '7',               //获取Cat1 信号信息,VOLTE信息,信号强度,SIM卡状态
+# 下文进行系统配置
+clog.info("Cat1Service start")
+
+cat1service = Cat1Service()
+
+#send_data_q = Queue(100)
+
+#voice call callback function
+def voice_callback(args):
+    if args[0] == 10:
+        if eventMesh.publish("get_volte_switch") == 0: #关闭VOLTE功能
+            clog.info('voicecall auto end:')
+            voiceCall.callEnd()
+        else:     
+            # gpioWakeBT.write(1)
+            cat1service.notifyIncomingcall(args[6])
+    elif args[0] == 11:
+        if eventMesh.publish("get_volte_switch") == 1: #开启VOLTE功能
+            clog.info('voicecall connected, PhoneNO: \n'.format(args[6]))
+            cat1service.notifyConnecteCall(args[6])
+    elif args[0] == 12:
+        clog.info('voicecall disconnect')
+        if eventMesh.publish("get_volte_switch") == 1: #开启VOLTE功能
+            clog.info('voicecall disconnected, PhoneNO: \n'.format(args[6]))
+            cat1service.notifyDisconnectCall(args[6])
+    elif args[0] == 13:
+        clog.info('voicecall is waiting, PhoneNO: \n'.format(args[6]))
+    elif args[0] == 14:
+        clog.info('voicecall dialing, PhoneNO: \n'.format(args[6]))
+    elif args[0] == 15:
+        clog.info('voicecall alerting, PhoneNO: \n'.format(args[6]))
+    elif args[0] == 16:
+        clog.info('voicecall holding, PhoneNO: \n'.format(args[6]))
+    else:
+        clog.info('voice_callback , args[0]: \n'.format(args[6]))
+
+#电话消息反馈
+voiceCall.setCallback(voice_callback)
+
+
+def checknet_cb(arg):
+    clog.info("start checktime!!")
+    # if 1: #CHINA_TELECOM_DM_FUN_ENABLE == 1:#这是手表每30s检查一次
+        # if eventMesh.publish("get_dmp_change_mode") == 1:
+            # telecomDmpCb.telecom_dmp_power_on_count()
+
+    _thread.start_new_thread(cat1service.wait_network_ready, ())
+    # time=utime.localtime()
+    # zone=utime.getTimeZone()
+    #(2024, 3, 2, 18, 31, 32, 5, 62),8
+    # cat1service.timesync("{0},{1}".format(time,zone))
+# _thread.start_new_thread(cat1service.wait_network_ready, ())
+timer = osTimer()
+# checknet_cb(())
+timer.start(30000,1,checknet_cb)  
+
+def bootupmsg_cb(arg):
+    cat1service.bootup_msg_to_bt()
+    
+
+delaybootupmsg_timer = osTimer()
+delaybootupmsg_timer.start(1000,0,bootupmsg_cb)
+
+# def checkpin_cb(arg):
+#     clog.info("recvDataPin={}".format(recvDataPin.read()))
+
+# timerCheckRevPin = osTimer()
+# timerCheckRevPin.start(1000,1,checkpin_cb)  
+
+
+
+    
+
+
+# while True:
+#     utime.sleep(5)
+
+
+# uping.ping("172.16.1.5")
+   # 获取网卡当前工作状态
+
+# gpioWakeBT.write(1)
+# utime.sleep(1)
+
+# timesync = net.nitzTime()
+# cat1service.timesync(timesync)
+
+
+#url = "http://zzhc.vnet.cn:9998/"
+
+
index dff9169..0650693 100644 (file)
@@ -463,6 +463,8 @@ target = {
                             "zhihui_ai_old",
                             #音频相关配置
                             "audio_manager",
+                            #AI桩函数
+                            "ai_stub",
                             
                            "producttest",
                             "ppg_hal",
@@ -1229,9 +1231,6 @@ target = {
             'BOARD_LEINIAO',
             # cat1 相关配置
             'FT_SINGLE_UART',
-            # 'ENABLE_SLIP',
-            # 'SUPPORT_CAT1_SERVICE',
-            'SUPPORT_TCPIP',           
             
             'CONFIG_EFUSE_READ_TO_RAM',
              'CUSTOM_UTILS',
@@ -1297,7 +1296,13 @@ target = {
                           "thunderbird_toys",#雷鸟
                           "leiniaoMediaService",
                          #cat1 相关配置
+                         #有方需要开启  PPP
                           "ppp",
+
+                        #EG810 需要开启 cat1Service 和 cat1Test
+                        # "cat1Service",
+                        # "cat1Test",
+
                         #websocket 相关配置
                         "zhihui_websocket",
                         #ai 相关配置
@@ -1305,6 +1310,8 @@ target = {
                         "aiService",
                         #ai_old相关配置
                         "zhihui_ai_old",
+                        #ai_stub 专门解决ai_old和ai_service的依赖问题
+                        "ai_stub",
                         #音频相关配置
                         "audio_manager",
                         #   "CustomUIcomponentTool",
index d57dc28..d968838 100644 (file)
@@ -73,10 +73,10 @@ static ctl_pin_4g_t g_cat1_ctl_pins={
     S_AGPIO_L23, // pwr_pin
     1,
     S_AGPIO_L24,//reset_pin
-    0,
-    PIN_NONE,//ring_pin
-    0,
-    PIN_NONE,//wakemodem_pin
+    1, //电路中 控制gpio拉高,reset才拉低
+    S_MGPIO21,//ring_pin
+    2,
+    S_MGPIO22,//wakemodem_pin
     0,
     #else
     PIN_NONE, //bat_pin
@@ -112,14 +112,14 @@ errcode_t cat1_register_ctl_pin(ctl_pin_4g_t ctl_pin)
     return ERRCODE_SUCC;
 }
 
-uint32_t cat1_api_cat1_bat_on(uint32_t pwron)
+uint32_t cat1_api_bat_pin(uint32_t pwron)
 {
     pin_t en_pin =  g_cat1_ctl_pins.bat_pin;
     uint8_t en_value = g_cat1_ctl_pins.bat_pin_en_value;
 
     if (en_pin == PIN_NONE)   
     {
-        printf("cat1_api_cat1_bat_on en_pin is none\r\n");
+        printf("cat1_api_bat_pin en_pin is none\r\n");
         return 0xff;
     }
 
@@ -147,14 +147,14 @@ uint32_t cat1_api_cat1_bat_on(uint32_t pwron)
     }
     return 0;
 }
-uint32_t cat1_api_cat1_pwrkey_on(uint32_t pwron)
+uint32_t cat1_api_power_pin(uint32_t pwron)
 {
 
     pin_t en_pin =  g_cat1_ctl_pins.pwr_pin;
     uint8_t en_value = g_cat1_ctl_pins.pwr_pin_en_value;
     if (en_pin == PIN_NONE)   
     {
-        printf("cat1_api_cat1_pwrkey_on en_pin is none\r\n");
+        printf("cat1_api_power_pin en_pin is none\r\n");
         return 0xff;
     }
     if( pwron == 0)
@@ -181,7 +181,7 @@ uint32_t cat1_api_cat1_pwrkey_on(uint32_t pwron)
     }
     return 0;
 }
-uint32_t cat1_api_cat1_reset(uint32_t pwron)
+uint32_t cat1_api_reset_pin(uint32_t pwron)
 {
 
     pin_t en_pin =  g_cat1_ctl_pins.reset_pin;
@@ -189,7 +189,7 @@ uint32_t cat1_api_cat1_reset(uint32_t pwron)
 
     if (en_pin == PIN_NONE)   
     {
-        printf("cat1_api_cat1_reset en_pin is none\r\n");
+        printf("cat1_api_reset_pin en_pin is none\r\n");
         return 0xff;
     }
 
@@ -235,10 +235,10 @@ bool cat1_api_is_cat1_enabled(void)
     }
     if ( en_value == uapi_gpio_get_output_val(en_pin))
     {
-        printf("cat1_api_is_cat1_enabled en_value is %d\r\n",en_value);
+        // printf("cat1_api_is_cat1_enabled en_value is %d\r\n",en_value);
         return true;
     }else{
-        printf("cat1_api_is_cat1_enabled en_value is %d\r\n",en_value);
+        // printf("cat1_api_is_cat1_enabled en_value is %d\r\n",en_value);
         return false;
     }
 }
@@ -246,14 +246,20 @@ bool cat1_api_is_cat1_enabled(void)
 void cat1_api_power_on_cat1(void)
 {
     #if defined(BOARD_FD230)
-    cat1_api_cat1_pwrkey_on(1);    
-    cat1_api_cat1_reset(0);
-    #elif (defined(BOARD_W9) || defined(BOARD_N9) || defined(BOARD_LEINIAO))
-    cat1_api_cat1_reset(0);
-    cat1_api_cat1_pwrkey_on(1);  
-    cat1_api_cat1_bat_on(1);
+    cat1_api_power_pin(1);    
+    cat1_api_reset_pin(0);
+    #elif (defined(BOARD_W9) || defined(BOARD_N9) )
+    cat1_api_reset_pin(0);
+    cat1_api_power_pin(1);  
+    cat1_api_bat_pin(1);
     osDelay(900);
-    cat1_api_cat1_pwrkey_on(0);  
+    cat1_api_power_pin(0);  
+    #elif defined(BOARD_LEINIAO)
+    cat1_api_reset_pin(0);
+    cat1_api_power_pin(1);    
+    cat1_api_bat_pin(1);
+    osDelay(900);
+    cat1_api_power_pin(0);  
     #endif
  
 }
@@ -261,12 +267,16 @@ void cat1_api_power_on_cat1(void)
 void cat1_api_power_off_cat1(void)
 {
     #if defined(BOARD_FD230)
-    cat1_api_cat1_reset(1);
-    cat1_api_cat1_pwrkey_on(0); 
-    #elif (defined(BOARD_W9) || defined(BOARD_N9) || defined(BOARD_LEINIAO))
-    cat1_api_cat1_bat_on(0);
-    cat1_api_cat1_reset(1);
-    cat1_api_cat1_pwrkey_on(1); 
+    cat1_api_reset_pin(1);
+    cat1_api_power_pin(0); 
+    #elif (defined(BOARD_W9) || defined(BOARD_N9) )
+    cat1_api_bat_pin(0);
+    cat1_api_reset_pin(1);
+    cat1_api_power_pin(1); 
+    #elif defined(BOARD_LEINIAO)
+    cat1_api_bat_pin(0);
+    cat1_api_reset_pin(1);
+    cat1_api_power_pin(1); 
     #endif
 }
 
index cb38508..b79bbf8 100644 (file)
@@ -23,11 +23,11 @@ extern "C" {
 void cat1_api_uart_init(void);\r
 \r
 /**set powerpin 1/0*/\r
-uint32_t cat1_api_cat1_pwrkey_on(uint32_t pwron);\r
+uint32_t cat1_api_power_pin(uint32_t pwron);\r
 /**set resetpin 0/1*/\r
-uint32_t cat1_api_cat1_reset(uint32_t pwron);\r
+uint32_t cat1_api_reset_pin(uint32_t pwron);\r
 \r
-uint32_t cat1_api_cat1_bat_on(uint32_t pwron);\r
+uint32_t cat1_api_bat_pin(uint32_t pwron);\r
 \r
 /**set powerpin 1 ,set resetpin 0*/\r
 void cat1_api_power_on_cat1(void);\r
index ba5faf9..39e2cc5 100644 (file)
@@ -21,6 +21,7 @@ endif()
 add_subdirectory_if_exist(4gTest)
 add_subdirectory_if_exist(ai)
 add_subdirectory_if_exist(ai_old)
+add_subdirectory_if_exist(ai_stub)
 add_subdirectory_if_exist(ai/media)
 add_subdirectory_if_exist(websocket)
 add_subdirectory_if_exist(4gTestcpp)
diff --git a/code/sdk/zhihui/ai_stub/CMakeLists.txt b/code/sdk/zhihui/ai_stub/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3cadb1d
--- /dev/null
@@ -0,0 +1,59 @@
+#===============================================================================
+# @brief    AI Stub Functions CMakeLists
+# Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved.
+#===============================================================================
+
+# 设置模块名称
+set(COMPONENT_NAME "ai_stub")
+
+# 源文件列表
+set(SOURCES
+    src/ppp_stub_functions.c
+)
+
+# 头文件目录
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+set(PRIVATE_HEADER
+)
+
+# 包含目录
+set(INCLUDE_DIRS
+    include
+)
+
+# AI桩函数编译时配置
+set(PUBLIC_DEFINES
+    SUPPORT_AI_STUB
+)
+
+set(PRIVATE_DEFINES
+)
+
+# 编译选项
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+set(COMPONENT_CCFLAGS
+    -Wall
+    -Wextra
+    -Werror
+    -O2
+    -ffunction-sections
+    -fdata-sections
+)
+
+# 是否整体链接
+set(WHOLE_LINK
+    true
+)
+
+# 是否为主组件
+set(MAIN_COMPONENT
+    false
+)
+
+# 构建组件
+build_component() 
\ No newline at end of file
@@ -9,6 +9,8 @@
 #include <stdbool.h>
 #include <stddef.h>
 
+#ifndef SUPPORT_CAT1_SERVICE
+
 /**
  * @brief HTTP客户端文件下载桩函数
  * @param url 下载URL
@@ -25,7 +27,7 @@ int httpc_get_file_dns_to_disk(const char *url, const char *file_path, int timeo
     // 桩函数 - 不实现实际功能
     return -1;
 }
-
+#endif
 /**
  * @brief AI流式录音发送桩函数
  * @param data 音频数据
@@ -47,12 +49,14 @@ int streamingRecordAndSend_AI(void *data, int len, const char *session_id)
  * @brief AI消息队列发送桩函数
  * @param msg_data 消息数据
  * @param data_len 数据长度
+ * @param type 消息类型
  * @return 总是返回失败(-1)
  */
-int send_msg_data_into_Ai_msg_queue(void *msg_data, int data_len)
+int send_msg_data_into_Ai_msg_queue(void *msg_data, uint16_t data_len, uint16_t type)
 {
     (void)msg_data;
     (void)data_len;
+    (void)type;
     
     // 桩函数 - 不实现实际功能
     return -1;
@@ -61,29 +65,41 @@ int send_msg_data_into_Ai_msg_queue(void *msg_data, int data_len)
 /**
  * @brief 蓝牙设置AI回答字符串桩函数
  * @param answer_str AI回答字符串
- * @return 总是返回失败(-1)
+ * @param type 消息类型
  */
-int ble_set_ai_Answer_str(const char *answer_str)
+void ble_set_ai_Answer_str(char *answer_str, uint8_t type)
 {
     (void)answer_str;
+    (void)type;
     
     // 桩函数 - 不实现实际功能
-    return -1;
 }
 
 /**
  * @brief 蓝牙设置AI问题字符串桩函数
  * @param question_str AI问题字符串
- * @return 总是返回失败(-1)
  */
-int ble_set_ai_Question_str(const char *question_str)
+void ble_set_ai_Question_str(char *question_str)
 {
     (void)question_str;
     
     // 桩函数 - 不实现实际功能
-    return -1;
 }
 
+#ifdef SUPPORT_CAT1_SERVICE
+
+/**
+ * @brief PPP环境初始化桩函数
+ * @return 总是返回成功(0)
+ */
+int ppp_env_init(void)
+{
+    // 桩函数 - 简单返回成功
+    // 注意:实际的ppp_env_init实现在ppp_example.c中
+    // 如果需要完整功能,请确保ppp_example.c被正确编译和链接
+    return 0;
+}
+#endif
 /* 
  * 注意:这些桩函数仅用于解决链接问题,不提供实际功能
  * 如果需要使用相关功能,请实现对应的真实函数
index 4e83333..48f198d 100644 (file)
@@ -23,7 +23,6 @@ set(SOURCES
     src/ppp_debug_manager.c
     src/ppp_power_ctl.c
     src/ppp_cat1_api.c
-    src/ppp_stub_functions.c
     ${PPP_AT_CMD_SOURCE}
 )
 
diff --git a/code/sdk/zhihui/ppp/include/ppp_performance_config.h b/code/sdk/zhihui/ppp/include/ppp_performance_config.h
new file mode 100644 (file)
index 0000000..1a52d23
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * @file ppp_performance_config.h
+ * @brief PPP性能优化配置
+ * 
+ * 本文件包含针对PPP协商性能问题的优化配置参数
+ * 主要解决LCP协商缓慢、Magic Number冲突、超时参数不当等问题
+ * 
+ * 注意:当前这些宏定义主要用作参考和文档说明
+ * 实际的优化参数已直接在相关源文件中定义和使用:
+ * - ppp_lwip.c: PPP协商超时参数和Magic Number生成
+ * - ppp_serial.c: UART通信超时参数
+ */
+
+#ifndef PPP_PERFORMANCE_CONFIG_H
+#define PPP_PERFORMANCE_CONFIG_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ================================ PPP协商超时优化 ================================ */
+
+/**
+ * @brief PPP FSM超时时间优化 (秒)
+ * 默认值: 6秒 -> 优化值: 3秒
+ * 说明: 减少LCP/IPCP协商的单次超时时间,提高协商响应速度
+ */
+#define PPP_OPTIMIZED_FSM_TIMEOUT           3
+
+/**
+ * @brief PPP最大Configure-Request重传次数优化
+ * 默认值: 10次 -> 优化值: 6次  
+ * 说明: 减少不必要的重传,避免过长的协商时间
+ */
+#define PPP_OPTIMIZED_MAX_CONF_REQ          6
+
+/**
+ * @brief PPP最大NAK循环次数优化
+ * 默认值: 5次 -> 优化值: 3次
+ * 说明: 减少NAK循环,加快协商收敛
+ */
+#define PPP_OPTIMIZED_MAX_NAK_LOOPS         3
+
+/**
+ * @brief PPP Terminate-Request重传次数
+ * 默认值: 2次 -> 保持: 2次
+ * 说明: 连接终止重传次数保持不变
+ */
+#define PPP_OPTIMIZED_MAX_TERM_REQ          2
+
+/* ================================ UART通信优化 ================================ */
+
+/**
+ * @brief UART写操作超时优化 (毫秒)
+ * 默认值: 1000ms -> 优化值: 200ms
+ * 说明: 减少UART写操作超时,提高PPP帧传输效率
+ */
+#define PPP_OPTIMIZED_UART_WRITE_TIMEOUT    200
+
+/**
+ * @brief UART读操作超时优化 (毫秒)  
+ * 默认值: 200ms -> 优化值: 100ms
+ * 说明: 减少PPP数据模式下的读取超时,提高协商响应速度
+ */
+#define PPP_OPTIMIZED_UART_READ_TIMEOUT     100
+
+/* ================================ Magic Number优化 ================================ */
+
+/**
+ * @brief Magic Number基础种子值
+ * 说明: 用于生成唯一Magic Number的基础种子
+ */
+#define PPP_MAGIC_NUMBER_SEED               0x12345678
+
+/**
+ * @brief Magic Number异或掩码
+ * 说明: 增加Magic Number随机性的固定异或值
+ */
+#define PPP_MAGIC_NUMBER_XOR_MASK           0xDEADBEEF
+
+/**
+ * @brief Magic Number备用值
+ * 说明: 当生成的Magic Number为0时使用的备用值
+ */
+#define PPP_MAGIC_NUMBER_FALLBACK           0xCAFEBABE
+
+/* ================================ 性能监控配置 ================================ */
+
+/**
+ * @brief PPP阶段切换超时阈值 (毫秒)
+ * 说明: 超过此时间的阶段切换将被标记为性能问题
+ */
+#define PPP_PHASE_TIMEOUT_THRESHOLD         5000
+
+/**
+ * @brief PPP协商总超时阈值 (毫秒)
+ * 说明: PPP完整协商过程的最大允许时间
+ */
+#define PPP_NEGOTIATION_TOTAL_TIMEOUT       30000
+
+/* ================================ 调试配置 ================================ */
+
+/**
+ * @brief 启用PPP性能监控
+ * 说明: 启用后会监控PPP阶段切换时间和性能指标
+ */
+#define PPP_ENABLE_PERFORMANCE_MONITORING   1
+
+/**
+ * @brief 启用Magic Number增强随机性
+ * 说明: 启用后使用多重随机源生成Magic Number
+ */
+#define PPP_ENABLE_ENHANCED_MAGIC_NUMBER     1
+
+/* ================================ 性能优化函数声明 ================================ */
+
+/**
+ * @brief 应用PPP性能优化配置
+ * @param ppp_pcb PPP控制块指针
+ * @return 0成功,非0失败
+ */
+int ppp_apply_performance_config(void *ppp_pcb);
+
+/**
+ * @brief 生成优化的Magic Number
+ * @param base_counter 基础计数器值
+ * @param pcb_addr PCB地址用于增加随机性
+ * @return 生成的Magic Number
+ */
+uint32_t ppp_generate_optimized_magic_number(uint32_t base_counter, void *pcb_addr);
+
+/**
+ * @brief 检查PPP性能指标
+ * @param phase_duration 阶段持续时间(毫秒)
+ * @param phase_id 阶段ID
+ * @return 1表示性能正常,0表示性能异常
+ */
+int ppp_check_performance_metrics(uint32_t phase_duration, int phase_id);
+
+/* ================================ 性能优化建议 ================================ */
+
+/*
+ * PPP协商性能优化建议:
+ * 
+ * 1. Magic Number冲突解决:
+ *    - 使用多重随机源(时间戳、PCB地址、栈地址)
+ *    - 避免Magic Number为0
+ *    - 增加位旋转和异或操作
+ * 
+ * 2. 超时参数优化:
+ *    - FSM超时从6秒减少到3秒
+ *    - 最大重传次数从10减少到6
+ *    - NAK循环从5减少到3
+ * 
+ * 3. UART通信优化:
+ *    - 写超时从1000ms减少到200ms
+ *    - 读超时从200ms减少到100ms
+ * 
+ * 4. 性能监控:
+ *    - 监控阶段切换时间
+ *    - 检测异常缓慢的协商过程
+ *    - 提供性能诊断信息
+ * 
+ * 5. 预期效果:
+ *    - LCP协商时间从30秒减少到5-10秒
+ *    - 减少Magic Number冲突导致的重协商
+ *    - 提高整体PPP连接建立速度
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PPP_PERFORMANCE_CONFIG_H */ 
\ No newline at end of file
index a4130d2..5c2335f 100644 (file)
@@ -58,7 +58,8 @@ errcode_t ppp_api_power_init(void)
         .pwr_pin_en_value = 1,
         .reset_pin = S_AGPIO_L24,
         .reset_pin_en_value = 1, //电路中 控制gpio拉高,reset才拉低
-        .ring_pin = S_MGPIO21, //CTS cat1 wakeup mcu
+        .ring_pin = PIN_NONE, //CTS cat1 wakeup mcu modem还没实现,暂时不使用
+        // .ring_pin = S_MGPIO21, //CTS cat1 wakeup mcu
         .ring_pin_en_value = 2, //2 双边沿中断 , 1 上升沿中断 , 0 下降沿中断
         .wakemodem_pin = S_MGPIO22, //RTS mcu wakeup cat1
         .wakemodem_pin_en_value = 0 //0 唤醒cat1 , 1 休眠cat1
@@ -139,10 +140,8 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config)
     ppp_api_power_init();
 
     ppp_api_power_control(true);
-    
-    // 额外等待时间,让调制解调器完全稳定(特别是在硬件复位后)
-    PPP_DEBUG_PRINT("Waiting for modem stabilization after power control...\n");
-    osal_msleep(5000);  // 等待5秒让调制解调器完全稳定
+#define PPP_SERIAL_INIT 1 //外接串口调试模组时,串口要设置input防止干扰。
+#if PPP_SERIAL_INIT
     
     // 3. UART初始化
     PPP_DEBUG_PRINT("Step 3: Initializing UART for AT mode\n");
@@ -157,7 +156,6 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config)
         .rx_callback = NULL,
         .rx_callback_arg = NULL
     };  
-
     ppp_error_t ret = ppp_serial_init(&serial_config);
     if (ret != PPP_ERR_OK) {
         PPP_DEBUG_PRINT("Failed to initialize serial for AT mode: %d\n", ret);
@@ -207,15 +205,21 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config)
     } else {
         PPP_DEBUG_PRINT("AT communication test succeeded\n");
     }
-   
+#else
+    ppp_api_leiniao_serial_pin_to_gpio_input();
+#endif
+    PPP_DEBUG_PRINT("Waiting for modem stabilization after power control...\n");
+    // 额外等待时间,让调制解调器完全稳定(特别是在硬件复位后)
+    osal_msleep(5000);  // 等待5秒让调制解调器完全稳定
     
     g_ppp_state = PPP_STATE_INITIALIZED;
     
     PPP_DEBUG_PRINT("PPP module initialized successfully\n");
 
     return ERRCODE_SUCC;
-
+#if PPP_SERIAL_INIT
 init_failed:
+#endif
     // 初始化失败,关闭4G电源
     // ppp_api_power_control(false);
     return ERRCODE_FAIL;
index c474d2a..6f5b61e 100644 (file)
@@ -6,6 +6,7 @@
 #include "ppp_power_ctl.h"  // 添加电源控制头文件
 #include "securec.h"
 #include "osal_addr.h"      // 添加OSAL内存管理头文件
+#include "osal_timer.h"     // 添加OSAL时间函数头文件
 #include <string.h>
 
 /* lwIP相关头文件 - 需要在编译时确保PPP支持已启用 */
@@ -41,6 +42,13 @@ typedef struct {
 static ppp_lwip_context_t g_lwip_ctx = {0};
 
 /* 内部函数声明 */
+static uint32_t ppp_lwip_get_time_ms(void);
+static uint32_t ppp_lwip_get_time_ms(void)
+{
+    osal_timeval tv = {0};
+    osal_gettimeofday(&tv);
+    return (uint32_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
 #ifdef LWIP_PPP_SUPPORT
 static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx);
 static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx);
@@ -130,6 +138,19 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config)
     
     PPP_DEBUG_DEBUG("IPCP configuration completed with standard options");
 
+    /* 优化PPP协商超时参数 - 运行时覆盖编译时默认值以获得更好性能 */
+    g_lwip_ctx.ppp_pcb->settings.fsm_timeout_time = 3;        /* 减少FSM超时从6秒到3秒 */
+    g_lwip_ctx.ppp_pcb->settings.fsm_max_conf_req_transmits = 6;  /* 减少最大重传次数从10到6 */
+    g_lwip_ctx.ppp_pcb->settings.fsm_max_term_transmits = 2;   /* 保持terminate重传为2 */
+    g_lwip_ctx.ppp_pcb->settings.fsm_max_nak_loops = 3;       /* 减少NAK循环从5到3 */
+    
+    /* 优化LCP相关参数以提高连接稳定性 */
+    g_lwip_ctx.ppp_pcb->settings.lcp_loopbackfail = 5;        /* 减少loopback检测次数从10到5 */
+    g_lwip_ctx.ppp_pcb->settings.lcp_echo_interval = 0;       /* 禁用LCP echo请求以减少开销 */
+    g_lwip_ctx.ppp_pcb->settings.lcp_echo_fails = 3;          /* 保持echo失败容忍度为3 */
+    
+    PPP_DEBUG_INFO("PPP parameters optimized: FSM(timeout=3s, max_conf_req=6, max_nak_loops=3), LCP(loopback_fail=5, echo_interval=0)");
+    
     /* 设置状态回调 */
     ppp_set_notify_phase_callback(g_lwip_ctx.ppp_pcb, ppp_lwip_status_callback);
     
@@ -140,14 +161,30 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config)
     PPP_DEBUG_DEBUG("Using standard PPP/LCP configuration...");
 
     /* 配置LCP Magic Number以避免loopback检测问题 */
-    /* 使用简单的随机数生成唯一的Magic Number */
-    static uint32_t magic_counter = 0x12345678;
+    /* 使用增强的随机数生成算法确保唯一性 */
+    #define PPP_MAGIC_NUMBER_SEED      0x12345678
+    #define PPP_MAGIC_NUMBER_XOR_MASK  0xDEADBEEF
+    #define PPP_MAGIC_NUMBER_FALLBACK  0xCAFEBABE
+    
+    static uint32_t magic_counter = PPP_MAGIC_NUMBER_SEED;
     uint32_t magic_number = magic_counter++;
-    magic_number ^= (uint32_t)g_lwip_ctx.ppp_pcb;  /* 使用PCB地址增加随机性 */
+    
+    /* 增加多重随机性源 */
+    magic_number ^= (uint32_t)g_lwip_ctx.ppp_pcb;      /* PCB地址 */
+    magic_number ^= (uint32_t)ppp_lwip_get_time_ms();  /* 当前时间戳 */
+    magic_number ^= (uint32_t)&magic_number;           /* 栈地址 */
+    magic_number = (magic_number << 16) | (magic_number >> 16);  /* 位旋转 */
+    magic_number ^= PPP_MAGIC_NUMBER_XOR_MASK;         /* 使用配置的异或掩码 */
+    
+    /* 确保Magic Number不为0(避免协商问题) */
+    if (magic_number == 0) {
+        magic_number = PPP_MAGIC_NUMBER_FALLBACK;      /* 使用配置的备用值 */
+    }
+    
     g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_magicnumber = 1;
     g_lwip_ctx.ppp_pcb->lcp_wantoptions.magicnumber = magic_number;
     g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_magicnumber = 1;
-    PPP_DEBUG_DEBUG("LCP Magic Number configured: 0x%08X", magic_number);
+    PPP_DEBUG_INFO("LCP Magic Number configured: 0x%08X (enhanced randomness)", magic_number);
 
     /* 使用标准PPP/LCP配置 */
     PPP_DEBUG_DEBUG("Using standard PPP/LCP configuration...");
@@ -399,6 +436,9 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
 {
     (void)pcb;
     (void)ctx;
+    
+    static int last_phase = -1;
+    static uint32_t phase_start_time = 0;
 
     PPP_DEBUG_DEBUG("PPP status callback: err_code=%d", err_code);
 
@@ -420,6 +460,27 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
         case PPP_PHASE_DISCONNECT: phase_str = "DISCONNECT"; break;
         default: phase_str = "OTHER"; break;
     }
+    
+    /* 监控阶段切换时间以诊断性能问题 */
+    uint32_t current_time = ppp_lwip_get_time_ms();
+    if (last_phase != err_code) {
+        if (last_phase != -1) {
+            uint32_t phase_duration = current_time - phase_start_time;
+            PPP_DEBUG_INFO("PPP Phase transition: %d -> %s (%d) [duration: %ums]", 
+                          last_phase, phase_str, err_code, phase_duration);
+            
+            /* 检测异常缓慢的阶段 */
+            if (phase_duration > 5000) {  /* 超过5秒 */
+                PPP_DEBUG_WARN("PPP Phase %d took too long: %ums (potential performance issue)", 
+                              last_phase, phase_duration);
+            }
+        } else {
+            PPP_DEBUG_INFO("PPP Phase: %s (%d) [initial]", phase_str, err_code);
+        }
+        last_phase = err_code;
+        phase_start_time = current_time;
+    }
+    
     PPP_DEBUG_DEBUG("PPP Phase: %s (%d)", phase_str, err_code);
 
     ppp_lwip_event_t event;
index d332c6b..b1f2538 100644 (file)
@@ -117,18 +117,29 @@ void ppp_api_gpio_init(void)
         {
         case 0:
             uapi_gpio_register_isr_func(gpiopin, GPIO_INTERRUPT_FALLING_EDGE, ppp_ring_isr_callback);
+            PPP_DEBUG_PRINT("PPP: Register ring pin %d falling edge interrupt\n", gpiopin);
             break;
         case 1:
             uapi_gpio_register_isr_func(gpiopin, GPIO_INTERRUPT_RISING_EDGE, ppp_ring_isr_callback);
+            PPP_DEBUG_PRINT("PPP: Register ring pin %d rising edge interrupt\n", gpiopin);
             break;
         case 2:
         default:
             uapi_gpio_register_isr_func(gpiopin, GPIO_INTERRUPT_DEDGE, ppp_ring_isr_callback);
+            PPP_DEBUG_PRINT("PPP: Register ring pin %d both edge interrupt\n", gpiopin);
             break;
         }
     }
 }
 
+void ppp_api_leiniao_serial_pin_to_gpio_input(void)
+{
+    uapi_pin_set_mode(SIO_UART_TX_PIN, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(SIO_UART_TX_PIN, GPIO_DIRECTION_INPUT);
+    uapi_pin_set_mode(SIO_UART_RX_PIN, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(SIO_UART_RX_PIN, GPIO_DIRECTION_INPUT);
+    PPP_DEBUG_PRINT("PPP: Leiniao serial pin to gpio input\n");
+}
 
 /**
  * @brief PPP模块设置电源引脚状态
index d45a765..61123c9 100644 (file)
 #include <string.h>
 #include "arch_port.h"
 
+/* PPP性能优化配置 */
+#define PPP_OPTIMIZED_UART_WRITE_TIMEOUT    200    /* UART写超时优化: 1000ms -> 200ms */
+#define PPP_OPTIMIZED_UART_READ_TIMEOUT     100    /* UART读超时优化: 200ms -> 100ms */
+
 /* 串口上下文结构 - 优化缓存机制 */
 typedef struct {
     bool initialized;
@@ -289,7 +293,7 @@ ppp_error_t ppp_serial_switch_to_ppp_mode(void)
     
     g_serial_ctx.current_mode = PPP_SERIAL_MODE_PPP_DATA;
     PPP_DEBUG_CRITICAL("Serial mode switched to PPP_DATA (%d)", g_serial_ctx.current_mode);
-    PPP_DEBUG_CRITICAL("PPP data mode active - UART will use direct read with 200ms timeout (balanced)");
+    PPP_DEBUG_CRITICAL("PPP data mode active - UART will use direct read with %dms timeout (optimized for fast negotiation)", PPP_OPTIMIZED_UART_READ_TIMEOUT);
     PPP_DEBUG_INFO("=== PPP Data Mode Switch Complete ===");
     return PPP_ERR_OK;
 }
@@ -404,10 +408,11 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length)
             // }
             // PPP_DEBUG_PRINT("\n");
             
-            PPP_DEBUG_INFO("Calling uapi_uart_write(bus=%u, data=%p, len=%u, timeout=1000)...", 
-                          g_serial_ctx.uart_bus, data, length);
+            PPP_DEBUG_DEBUG("Calling uapi_uart_write(bus=%u, data=%p, len=%u, timeout=%d)...", 
+                          g_serial_ctx.uart_bus, data, length, PPP_OPTIMIZED_UART_WRITE_TIMEOUT);
             
-            write_result = uapi_uart_write(g_serial_ctx.uart_bus, data, length, 1000);
+            /* 优化UART写超时:使用配置的优化值以提高PPP协商速度 */
+            write_result = uapi_uart_write(g_serial_ctx.uart_bus, data, length, PPP_OPTIMIZED_UART_WRITE_TIMEOUT);
             PPP_DEBUG_INFO("uapi_uart_write returned: %d (expected: %u)", write_result, length);
             
             if (write_result != (int32_t)length) {
@@ -473,7 +478,8 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt
             {
                 /* 使用适中的超时时间来平衡响应性和帧完整性 */
                 // PPP_DEBUG_DEBUG("PPP mode: Attempting UART read (timeout: 200ms)");
-                int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, 200);
+                /* 优化PPP数据模式读取超时:使用配置的优化值以提高协商响应速度 */
+                int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, PPP_OPTIMIZED_UART_READ_TIMEOUT);
                 if (read_result > 0) {
                     *bytes_read = (uint32_t)read_result;
                     g_serial_ctx.rx_bytes += *bytes_read;
index 6058175..f199806 100644 (file)
@@ -702,10 +702,7 @@ void startup_post_init_task(void)
 
 
     
-#ifdef BOARD_LEINIAO
-    extern int ppp_env_init(void);
-    ppp_env_init();
-#else
+#ifdef SUPPORT_CAT1_SERVICE
 if ( cm_poweron_cat1_on_bootup_flag() )
 {
     PRINT("PowerOn Cat1 !\r\n");
@@ -714,6 +711,13 @@ if ( cm_poweron_cat1_on_bootup_flag() )
     PRINT("PowerOff Cat1 !\r\n");
     uapi_set4GCapability(false);
 }
+#else
+
+#ifdef BOARD_LEINIAO
+    extern int ppp_env_init(void);
+    ppp_env_init();
+#endif
+
 #endif
 
 #ifdef A5133_DEMO_SERVER