From e03aacd06da89df7d0c030c04b5a47b9aa30e9e7 Mon Sep 17 00:00:00 2001 From: hcj <1224667075@qq.com> Date: Sat, 2 Aug 2025 15:38:42 +0800 Subject: [PATCH] =?utf8?q?=E5=A2=9E=E5=8A=A0N9=20=E8=AE=A4=E8=AF=81cat1ser?= =?utf8?q?vice.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- cat1modem/src/N9/cat1Service.py | 1121 +++++++++++++++++++++++++++++++ 1 file changed, 1121 insertions(+) create mode 100644 cat1modem/src/N9/cat1Service.py diff --git a/cat1modem/src/N9/cat1Service.py b/cat1modem/src/N9/cat1Service.py new file mode 100644 index 000000000..a69f71641 --- /dev/null +++ b/cat1modem/src/N9/cat1Service.py @@ -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.UART4, 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/" + + -- 2.17.1