From: SnickerSun Date: Thu, 30 May 2024 04:52:32 +0000 (+0800) Subject: 更新cat1 蓝牙通讯协议解析,同时支持旧版和新版协议。 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=fb8964e1c7ef5eeb131f482351d94f935718475f;p=mirrors%2FFD230.git 更新cat1 蓝牙通讯协议解析,同时支持旧版和新版协议。 --- diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/cat1_server.cpp b/code/sdk/drivers/peripheral/slip/cat1Service/cat1_server.cpp index 5f60e4b2a..fbd35c6fa 100644 --- a/code/sdk/drivers/peripheral/slip/cat1Service/cat1_server.cpp +++ b/code/sdk/drivers/peripheral/slip/cat1Service/cat1_server.cpp @@ -83,80 +83,99 @@ enum UDP_COMMAND_HEAD { UDP_MSG_GET_TELECON_DMP_TIMESEC = 0x14,//获取本地保存的注册的时间戳 UDP_MSG_RECV_CAT1_SMS_CONTENT = 0x15,//接收信息内容数据 }; +static uint8_t g_msg_format_type = 0;// 0: old format , 1: new format - -static uint8_t get_header_cmd_from_uint16_hexstr(uint16_t value) +static uint8_t get_int8_from_ascii_char( uint8_t ascii) { - uint8_t *p_value = (uint8_t *)&value; - uint16_t intvalue = 0; - uint8_t * p_intvalue = (uint8_t *)&intvalue; - for (int i= 0 ; i<2;i++) - { + char* tmpt =NULL; uint8_t tmp=0; - switch (p_value[i]) + switch (ascii) { case '0': tmp = 0; + tmpt="0"; break; case '1': tmp = 1; + tmpt="1"; break; case '2': tmp = 2; + tmpt="2"; break; case '3': tmp = 3; + tmpt="3"; break; case '4': tmp = 4; + tmpt="4"; break; case '5': tmp = 5; + tmpt="5"; break; case '6': tmp = 6; + tmpt="6"; break; case '7': tmp = 7; + tmpt="7"; break; case '8': tmp = 8; + tmpt="8"; break; case '9': tmp = 9; + tmpt="9"; break; case 'A': case 'a': tmp = 0xA; + tmpt="A"; break; case 'B': case 'b': tmp = 0xB; + tmpt="B"; break; case 'C': case 'c': tmp = 0xC; + tmpt="C"; break; case 'D': case 'd': tmp = 0xD; + tmpt="D"; break; case 'E': case 'e': tmp = 0xE; + tmpt="E"; break; case 'F': case 'f': tmp = 0xF; + tmpt="F"; break; default: tmp = 0x0; + tmpt="0"; break; } - p_intvalue[i] = tmp; - } - uint8_t ret = (p_intvalue[1]&0x0F) | ((p_intvalue[0]&0x0F)<<4); + // printf("%s\n",tmpt); + return tmp; +} +static uint8_t get_header_cmd_from_uint16_hexstr(char* int16_value) +{ + uint8_t * p_intvalue = (uint8_t *)int16_value; + uint8_t low = get_int8_from_ascii_char(p_intvalue[1]); + uint8_t high = get_int8_from_ascii_char(p_intvalue[0]); + uint8_t ret = ((low&0x0F) | (high&0x0F)<<4); return ret; } @@ -173,14 +192,21 @@ static uint8_t get_header_cmd_from_uint16_hexstr(uint16_t value) // "6", // smart config mode // }; #define RESP_STATUS_OFSET 2 -#define MAX_TCP_MSG_BUFFER_LEN (512+8) +#define MAX_CMD_MSG_BUFFER_LEN 512 +#define MAX_TCP_MSG_BUFFER_LEN (MAX_CMD_MSG_BUFFER_LEN+8) #pragma pack(push) #pragma pack(1) struct tcp_msg_t { uint16_t head; uint16_t cmd; - int length; - char buffer[512]; + uint32_t length; + char buffer[MAX_CMD_MSG_BUFFER_LEN]; +}; +struct tcp_msg_old_t { + uint8_t head; + uint8_t cmd; + uint32_t length; + char buffer[MAX_CMD_MSG_BUFFER_LEN]; }; #pragma pack(pop) @@ -203,6 +229,43 @@ static uint8_t g_time_sync_retry_time = 0; static uint8_t g_py_ver = 4; +static struct tcp_msg_old_t *unpack_tlv_format_old(char *rx_buffer, int length) +{ + char temp[8]={0}; + struct tcp_msg_old_t *msg = (struct tcp_msg_old_t *)rx_buffer; + strncpy(temp, (char *)&msg->length, 4); + temp[4] = '\0'; + msg->length = atoi(temp); + + if( length != msg->length+6 ) return NULL; + return msg; +} + +static int pack_tlv_format_old(char *tx_buffer, uint8_t cmd, char *content) +{ + int content_length = (int)strlen(content); + if( content == NULL || content_length > MAX_CMD_MSG_BUFFER_LEN) { + return -1; + } + // sprintf_s(tx_buffer,1,"%1X", 0xF); + // sprintf_s(tx_buffer+1,1,"%1X", cmd&0xF); + // sprintf_s(tx_buffer+4,4,"%04d", content_length); + // sprintf_s(tx_buffer+6,MAX_CMD_MSG_BUFFER_LEN,"%s",content); + // printf("pack_tlv_format_old %04d , %s\n",content_length,content); + sprintf(tx_buffer,"%1X", 0xF); + sprintf(tx_buffer+1,"%1X", cmd&0xF); + sprintf(tx_buffer+2,"%04d", content_length); + sprintf(tx_buffer+6,"%s",content); + + // for (int i = 0 ; i MAX_TCP_MSG_BUFFER_LEN ) { + if( content == NULL || content_length > MAX_CMD_MSG_BUFFER_LEN ) { return -1; } - struct tcp_msg_t *msg = (struct tcp_msg_t *)tx_buffer; - sprintf((char*)(&msg->head), "%02X", 0xFE); - sprintf((char*)(&msg->cmd), "%02X", cmd); - sprintf((char*)(&msg->length), "%04d", (unsigned char)content_length); - sprintf(&tx_buffer[4], "%04d", content_length); - strcpy(msg->buffer, content); - return strlen(content)+8; + // printf("pack_tlv_format %04d , %s\n",content_length,content); + // sprintf_s(tx_buffer,2,"%02X", 0xFE); + // sprintf_s(tx_buffer+2,2,"%02X", cmd); + // sprintf_s(tx_buffer+4,4,"%04d", content_length); + // sprintf_s(tx_buffer+8,MAX_CMD_MSG_BUFFER_LEN,"%s",content); + sprintf(tx_buffer,"%02X", 0xFE); + sprintf(tx_buffer+2,"%02X", cmd); + sprintf(tx_buffer+4,"%04d", content_length); + sprintf(tx_buffer+8,"%s",content); + // for (int i = 0 ; i 0 ) { err = sendto(g_listen_sock, tx_buffer, len, 0, (struct sockaddr *)&sourceAddr, sizeof(sourceAddr)); @@ -607,30 +685,34 @@ void cat1_call_sms_send(char* phonenum,char* sms_txtdata) memset_s(msg_tmp,len_smstxt,0,len_smstxt); sprintf_s(msg_tmp,len_smstxt,"%s,%s",phonenum,sms_txtdata); udp_send_msg_toCat1(UDP_CMD_SEND_SMS,msg_tmp); + free(msg_tmp); } } static char* phonenum =NULL; //来电 -int cat1_handle_call_incomming(struct tcp_msg_t *msg) +int cat1_handle_call_incomming(char * msg) { if(phonenum!=NULL) { free(phonenum); phonenum=NULL; } - phonenum = (char*)malloc(strlen(msg->buffer)); + int phonenumlen = strlen(msg)+1; + phonenum = (char*)malloc(phonenumlen); if(phonenum==NULL) return 0; - strcpy(phonenum,msg->buffer); + strncpy(phonenum,msg,phonenumlen-1); + phonenum[phonenumlen-1]='\0'; WEARABLE_LOGI(WEARABLE_LOG_MODULE_MAIN_SERVICE,"cat1 incomming call %s\n",phonenum); incomingcall_event_sendmsg_toUI(phonenum); //声音 //uapi_cat1_start_volte_voice(); - + //由于incomingcall_event_sendmsg_toUI中的参数是char* 在其他地方会使用。因此要保留内存存在,只能在更新时刷新。 + // free(phonenum); return 1; @@ -638,15 +720,13 @@ int cat1_handle_call_incomming(struct tcp_msg_t *msg) void test_call_incomming(void) { - struct tcp_msg_t msg; - strcpy(msg.buffer,"10086"); - cat1_handle_call_incomming(&msg); + cat1_handle_call_incomming("10086"); } -int cat1_handle_networ_msg(struct tcp_msg_t *msg) +int cat1_handle_networ_msg(char *msg) { // WEARABLE_LOGI(WEARABLE_LOG_MODULE_MAIN_SERVICE,"cat1 cat1_handle_networ_msg %s\n",msg->buffer); - if(decodeNetStat(msg->buffer) == 0) + if(decodeNetStat(msg) == 0) { runtime_status_t * runtime = get_device_runtime_status(); OHOS::ConfigModel::GetInstance()->Setimei(runtime->cat1_runtime.imei); @@ -656,7 +736,7 @@ int cat1_handle_networ_msg(struct tcp_msg_t *msg) return 1; } -int cat1_handle_version_msg(struct tcp_msg_t *msg) +int cat1_handle_version_msg(char *msg) { // WEARABLE_LOGI(WEARABLE_LOG_MODULE_MAIN_SERVICE,"cat1 cat1_handle_networ_msg %s\n",msg->buffer); @@ -666,7 +746,7 @@ int cat1_handle_version_msg(struct tcp_msg_t *msg) // pyVer,PY_SRV_V4,modemVer,EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_BETA0312 // imei:860132060352796,sim:0,oper:-1,signal:99,net:([99, 0, 0, 0], [0, 0, 0, 0, 0]) - if(decodeVersion(msg->buffer) == 0) + if(decodeVersion(msg) == 0) { runtime_status_t * runtime = get_device_runtime_status(); OHOS::ConfigModel::GetInstance()->SetpyVer(runtime->cat1_runtime.pyVer); @@ -679,20 +759,19 @@ int cat1_handle_version_msg(struct tcp_msg_t *msg) -int cat1_handle_sms(struct tcp_msg_t *msg) +int cat1_handle_sms(char *msg) { - char* smsmsg=msg->buffer; // WEARABLE_LOGI(WEARABLE_LOG_MODULE_MAIN_SERVICE,"cat1 cat1_handle_sms %s\n",smsmsg); - if (decodeSMS(smsmsg) ==0 ) + if (decodeSMS(msg) ==0 ) { //添加到消息列表里 } return 1; } -int cat1_handle_timesync(struct tcp_msg_t *msg) +int cat1_handle_timesync(char *timesync) { - char* timesync=msg->buffer; + // WEARABLE_LOGI(WEARABLE_LOG_MODULE_MAIN_SERVICE,"cat1 cat1_handle_timesync %s\n",timesync); // ('24/03/01 07:15:36 8 0', 1709277336, 0) @@ -806,7 +885,7 @@ void restart_time_sync(void) } } -int cat1_handle_call_connected(struct tcp_msg_t *msg) +int cat1_handle_call_connected(void) { WEARABLE_LOGI(WEARABLE_LOG_MODULE_MAIN_SERVICE,"cat1 call connected\n"); @@ -817,7 +896,7 @@ int cat1_handle_call_connected(struct tcp_msg_t *msg) return 1; } //来电挂断处理 -int cat1_handle_call_disconnected(struct tcp_msg_t *msg) +int cat1_handle_call_disconnected(void) { WEARABLE_LOGI(WEARABLE_LOG_MODULE_MAIN_SERVICE,"cat1 call disconnected\n"); //TODO: 关闭声音 @@ -901,92 +980,108 @@ void get_regist_time_toCat1(void)//设置电信入库功能开关->CAT1 static int udp_packet_parse(char *rx_buffer, int len) { - struct tcp_msg_t *msg = unpack_tlv_format(rx_buffer, len); - int index = 0; - // if( msg->head[1] != UDP_WIFI_STATUS ) { // ota only status check - // return 1; - // } - uint8_t cmd = get_header_cmd_from_uint16_hexstr(msg->cmd); - - uint8_t *p_header = (uint8_t *)&msg->head; - if (( *p_header == 'F' || *p_header == 'f') && (*(p_header+1) == 'E' || *(p_header+1) == 'e')) + int index = 0; + if (len <6 || rx_buffer == NULL) { - - }else{ - printf("msg format error!\n"); + printf("len < 6 , format error !\n"); return -1; } + uint8_t header0 = rx_buffer[0]; + uint8_t header1 = rx_buffer[1]; + if (( header0 == 'F' || header0 == 'f') && (header1== 'E' || header1 == 'e')) + { + g_msg_format_type = 1; + }else{ + // printf("msg format error or old msg format!\n"); + g_msg_format_type = 0; + } + printf("g_msg_format_type %d\n",g_msg_format_type); + char * msg_buffer = NULL; + int msg_buffer_len = 0; + uint16_t cmd = 0; + if (g_msg_format_type == 1) + { + struct tcp_msg_t *msg = unpack_tlv_format(rx_buffer, len); + msg_buffer = msg->buffer; + msg_buffer_len = msg->length; + cmd = get_header_cmd_from_uint16_hexstr(&rx_buffer[2]); - if( msg != NULL ) { - switch (cmd) { - case UDP_MSG_COMMING_CALL: - index = cat1_handle_call_incomming(msg); - break; - case UDP_CMD_GET_RECV_NETWORKSTAT: - index = cat1_handle_networ_msg(msg); - break; - case UDP_CMD_GET_TIME: - index = cat1_handle_timesync(msg); - break; - case UDP_MSG_CALL_CONNECTED: - index = cat1_handle_call_connected(msg); - break; - case UDP_MSG_CALL_DISCONNECTED: - index = cat1_handle_call_disconnected(msg); - break; - case UDP_CMD_CAT1_OTA_UPDATE: - PRINT("CAT1_OTA_UPDATE reply %s\n",msg->buffer); - break; - case UDP_MSG_REPLY: - PRINT("UDP_MSG_REPLY reply %s!!!!!!!\n",msg->buffer); - //"BOOTUP,pyVer,PY_SRV_V4,modemVer,EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_BETA0312" - // VER:xxxxx - // ICCID:xxxxxx - if(strstr(msg->buffer,"BOOTUP")!=NULL) - { - cat1_handle_version_msg(msg); - restart_time_sync(); - cat1_getsignal(); - #ifdef SUPPORT_TELECOM_DMP //是否开启电信入库功能 - set_telecom_dmp_switch_toCat1(1); - get_software_version_toCat1(); - get_sim_iccid_toCat1(); - get_regist_time_toCat1(); - #endif - } - break; - case UDP_MSG_GET_TELECON_DMP_TIMESEC: - #ifdef SUPPORT_TELECOM_DMP - save_regist_time_toBle(msg->buffer); - #endif - break; - case UDP_CMD_GET_CAT1VER: - index = cat1_handle_version_msg(msg); - break; - case UDP_CMD_MSG_ATCMD: - PRINT("ATCMD reply : %s\n", msg->buffer); - break; - case UDP_MSG_SAVE_SIM_ICCID: - #ifdef SUPPORT_TELECOM_DMP - save_sim_iccid_toBle(msg->buffer); + }else{ + struct tcp_msg_old_t *msg = unpack_tlv_format_old(rx_buffer, len); + msg_buffer = msg->buffer; + msg_buffer_len = msg->length; + cmd = get_int8_from_ascii_char(rx_buffer[1]); + } + // printf("cmd %x,bufferlen %d , buffer %s \n",cmd,msg_buffer_len,msg_buffer); + switch (cmd) { + case UDP_MSG_COMMING_CALL: + index = cat1_handle_call_incomming(msg_buffer); + break; + case UDP_CMD_GET_RECV_NETWORKSTAT: + index = cat1_handle_networ_msg(msg_buffer); + break; + case UDP_CMD_GET_TIME: + index = cat1_handle_timesync(msg_buffer); + break; + case UDP_MSG_CALL_CONNECTED: + index = cat1_handle_call_connected(); + break; + case UDP_MSG_CALL_DISCONNECTED: + index = cat1_handle_call_disconnected(); + break; + case UDP_CMD_CAT1_OTA_UPDATE: + PRINT("CAT1_OTA_UPDATE reply %s\n",msg_buffer); + break; + case UDP_MSG_REPLY: + PRINT("UDP_MSG_REPLY reply %s!!!!!!!\n",msg_buffer); + //"BOOTUP,pyVer,PY_SRV_V4,modemVer,EG810MCNLAR06A01M08_VOLTE_OCPU_QPY_BETA0312" + // VER:xxxxx + // ICCID:xxxxxx + if(strstr(msg_buffer,"BOOTUP")!=NULL) + { + cat1_handle_version_msg(msg_buffer); + restart_time_sync(); + cat1_getsignal(); + if(g_msg_format_type == 0) break; + #ifdef SUPPORT_TELECOM_DMP //是否开启电信入库功能 + set_telecom_dmp_switch_toCat1(1); + get_software_version_toCat1(); + get_sim_iccid_toCat1(); + get_regist_time_toCat1(); #endif - break; - case UDP_MSG_RECV_CAT1_SMS_CONTENT://接收单条短信内容 - case UDP_MSG_SMS: - index = cat1_handle_sms(msg); - break; - default: - PRINT("error message: %s\n", rx_buffer); - index = 1; - break; - } - // if (index > 0) //需要反馈的指令才返回OK - // udp_send_msg_toCat1( msg->head[1], "OK"); - } else { - PRINT("wrong format msg and exit\n"); - index = 1; + } + break; + case UDP_MSG_GET_TELECON_DMP_TIMESEC: + #ifdef SUPPORT_TELECOM_DMP + save_regist_time_toBle(msg_buffer); + #endif + break; + case UDP_CMD_GET_CAT1VER: + index = cat1_handle_version_msg(msg_buffer); + break; + case UDP_CMD_MSG_ATCMD: + PRINT("ATCMD reply : %s\n", msg_buffer); + break; + case UDP_MSG_SAVE_SIM_ICCID: + #ifdef SUPPORT_TELECOM_DMP + save_sim_iccid_toBle(msg_buffer); + #endif + break; + case UDP_MSG_RECV_CAT1_SMS_CONTENT://接收单条短信内容 + case UDP_MSG_SMS: + index = cat1_handle_sms(msg_buffer); + break; + default: + PRINT("error message: %s\n", rx_buffer); + index = 1; + break; } + + // if (index > 0) //需要反馈的指令才返回OK + // udp_send_msg_toCat1( msg->head[1], "OK"); + + return index; } @@ -1076,19 +1171,6 @@ void cat1_server_task(void *pvParameters) } - - -#if 0 -void wifi_status() -{ - char tx_buffer[128] = {0}; - int index = resolve_msg_wifi_status(NULL); - char *head = "FF"; - int len = pack_tlv_format(tx_buffer, head, msg_wifi_status[index]); - PRINT("wifi_status len = %d, msg = [%s]\n",len, tx_buffer); -} -#endif - #include "osal_msgqueue.h" #include "thread_init.h" #include "soc_osal.h" diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/pyscript/checkota.pyV3 b/code/sdk/drivers/peripheral/slip/cat1Service/pyscript/V3/checkota.py similarity index 100% rename from code/sdk/drivers/peripheral/slip/cat1Service/pyscript/checkota.pyV3 rename to code/sdk/drivers/peripheral/slip/cat1Service/pyscript/V3/checkota.py diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/pyscript/V6/cat1Service.py b/code/sdk/drivers/peripheral/slip/cat1Service/pyscript/V6/cat1Service.py new file mode 100644 index 000000000..4bd9cd684 --- /dev/null +++ b/code/sdk/drivers/peripheral/slip/cat1Service/pyscript/V6/cat1Service.py @@ -0,0 +1,625 @@ +# 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 +PROJECT_NAME = "Cat1SlipUDPService" +PROJECT_VERSION = "PY_SRV_V6" +CONFIG_JSON="/usr/system_config.json" +CURRENT_APP_TYPE="pysrv" + + +# 设置日志输出级别 +log.basicConfig(level=log.INFO) +cat1service_log = log.getLogger("cat1service") + +lpm_fd = pm.create_wakelock("system_lock", len("system_lock")) +pm.autosleep(1) +pm.wakelock_lock(lpm_fd) +cat1service_log.info("create_wakelock {}".format(pm.get_wakelock_num())) + +def get_versionkeyname_by_py(app_type): + return str("{}version".format(app_type)) + +def get_default_versionvalue_by_py(app_type): + if (app_type == "pymain"): + return "PY_MAIN_V2" + elif (app_type == "pyota"): + return "PY_OTA_V2" + elif (app_type == "pysrv"): + return "PY_SRV_V2" + +#如果没有configfile则创建它 +if not ql_fs.path_exists(CONFIG_JSON): + data = {str(get_versionkeyname_by_py(CURRENT_APP_TYPE)):get_default_versionvalue_by_py(CURRENT_APP_TYPE)} + ql_fs.touch(CONFIG_JSON,data) + +def set_version_to_json_config(app_type,keyvalue): + config_data = ql_fs.read_json(CONFIG_JSON) + config_data.update( {str(get_versionkeyname_by_py(app_type)):keyvalue}) + ql_fs.touch(CONFIG_JSON, config_data) + cat1service_log.info("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue)) + cat1service_log.info("{}".format(config_data)) + +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)) + cat1service_log.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): + # cat1service_log.info('### interrupt {} ###'.format(args)) # args[0]:gpio号 args[1]:上升沿或下降沿 + if args[1] == 0: + cat1service_log.info("disable autosleep") + # pm.autosleep(0) + pm.wakelock_lock(lpm_fd) + elif args[1] == 1: + cat1service_log.info("enable autosleep") + pm.wakelock_unlock(lpm_fd) + # pm.autosleep(1) + # cat1service_log.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' # 返回值 + + + +def result(args): + print('download status:',args[0],'download process:',args[1]) +def download_fota_img( srcurl ): + fota_obj = fota() # 创建Fota对象 + cat1service_log.info("httpDownload... {} , {}".format("{}/dfota_1.bin".format(srcurl),"{}/dfota_2.bin".format(srcurl))) + res = fota_obj.httpDownload(url1="{}/dfota_1.bin".format(srcurl),url2="{}/dfota_2.bin".format(srcurl),callback=result) + #差分升级FTP方式 + #res = fota_obj.httpDownload(url1="ftp://user:password@ip:port/fota.bin",callback=result) #其中user,password,ip,port需要填写具体使用的FTP服务器信息 + if res != 0: + cat1service_log.error("httpDownload error") + +def check_fota(): + modem_ver = modem.getDevFwVersion() + imei = modem.getDevImei() + url = "http://icfota.snicker.com.cn:8089/fd230ota.jsp?product=FD230&pkgver={0}&imei={1}".format(modem_ver,imei) + response = request.get(url) + cat1service_log.info(url) + data = response.json() + if(data['UptoDate'] == False): + cat1service_log.info("Need update python application") + srcurl = data['url'] + #差分升级方式 + # res = fota_obj.httpDownload(url1="http://www.example.com/fota.bin",callback=result) + # mini fota方式 + return srcurl + else: + cat1service_log.info("No need update python application") + return "" + +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() + print('slip uart={0}'.format (self.__uart)) + + ret = slip.construct(self.__uart, self.__mode, 0) + if ret != 0: + print('slip netif construct fail') + return None + print('slip network card create success') + self.__queue = Queue(1) + self.__sock = self.__socket_init() + self.__threadid = _thread.start_new_thread(self.__Socket_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(10) + return sock + + def __socket_reinit(self): + return self.__socket_init() + + def bootup_msg_to_bt(self): + modem_ver = modem.getDevFwVersion() + self.reply_cmd('FF',"BOOTUP@pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver)) + + def btmcu_cmd_handler(self,cmd,parm): + print("btmcu_cmd_handler cmd {0} , args {1}".format(cmd,parm)) + if cmd == "F0": + print(cmd) + # UDP_CMD_GET_CAT1VER + modem_ver = modem.getDevFwVersion() + self.reply_cmd('F0',"pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver)) + elif cmd == "F1": + print("{}{}".format(cmd,parm)) + # UDP_CMD_DIAL_NUMB + voiceCall.callStart(parm) + elif cmd == "F2": + print(cmd) + # UDP_CMD_HUNGUP + voiceCall.callEnd() + elif cmd == "F3": + print(cmd) + # UDP_CMD_ANSWER + voiceCall.callAnswer() + elif cmd == "F4": + print(cmd) + result = check_fota() + if result == "": + self.reply_cmd('F4',"no need update!") + else: + self.reply_cmd('F4',"start ota {} please wait...".format(result)) + download_fota_img(result) + elif cmd == "F5": + print(cmd) + # UDP_CMD_SEND_SMS + elif cmd == "F6": + print(cmd) + # UDP_CMD_GET_TIME + time=utime.localtime() + zone=utime.getTimeZone() + #(2024, 3, 2, 18, 31, 32, 5, 62),8 + # 返回当前时间戳,参数为元组 + # timestamp = utime.mktime(time) + # cat1service_log.info(timestamp) + self.reply_cmd('F6',"{0}@{1}".format(time,zone)) + elif cmd == "F7": + print(cmd) + # 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() + print("imei:{0},sim:{1},oper:{2},signal:{3},net:{4}".format(imei,simstat,operator,signal,netstat)) + self.reply_cmd('F7',"imei:{0}@sim:{1}@oper:{2}@signal:{3}@net:{4}".format(imei,simstat,operator,signal,netstat)) + elif cmd == "F9": + print("{},{}".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: + print("reply:{},ret:{}".format(resp.decode(),ret)) + self.reply_cmd('F9',"{}".format(resp.decode())) + else: + print("cmd error ret:{}".format(ret)) + self.reply_cmd('F9',"{}".format("at error")) + + + # 来电提醒 + def notifyIncomingcall(self, incomming_numb): + self.clear_remain() + __head = 'FC' + self.__message = str(incomming_numb) + self.__Socket_UDP(__head, self.__message) + # if self.__err == 1 or self.__value[2] != 'OK': + # return -1 + return 0 + + # 电话接听消息 + def notifyConnecteCall(self): + self.clear_remain() + __head = 'FA' + self.__message = '0' + self.__Socket_UDP(__head, self.__message) + # if self.__err == 1 or self.__value[2] != 'OK': + # return -1 + return 0 + + # 电话拒接消息 + def notifyDisconnectCall(self): + self.clear_remain() + __head = 'FB' + self.__message = '0' + self.__Socket_UDP(__head, self.__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: + print('Network connection successful.') + self.set_network_config() + self.__net_connected = 1 + self.__waiting_netstat = 0 + return 0 + else: + print('Network connection failed, stage={}, state={}'.format(stage, state)) + self.reset_network_config() + self.__net_connected = 0 + self.__waiting_netstat = 0 + return -1 + + # 查询网卡状态 + def timesync(self,_timesync): + self.clear_remain() + self.__message = str(_timesync) + self.__Socket_UDP('FD', self.__message) + return 0 + + # 查询网卡版本信息 + def version(self): + self.clear_remain() + self.__Socket_UDP('F5', '0') + if self.__err == 1: + return -1 + return self.__value[2] + + def reply_timesync(self,_timesync): + self.clear_remain() + self.__message = str(_timesync) + self.__Socket_UDP_noreply('FD', self.__message) + return 0 + + def reply_cmd(self,cmd,_timesync): + self.clear_remain() + self.__message = str(_timesync) + self.__Socket_UDP_noreply(cmd, self.__message) + 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): + print("skip reset_network_config") + return 0 + Info = dataCall.getInfo(1,0) + print("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) + print("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) : + print("skip set_network_config") + return 0 + Info = dataCall.getInfo(1,0) + print("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) + print("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() + + # 释放slip网卡 + def stop(self): + slip.destroy() + return 0 + + + # 封装tlv数据包 + def __pack_tlv_format(self, head, content): + self.head = head + self.content = content + if len(self.content) == 0 or len(self.content) > 9999 or len(self.head) != 2: + print('illegal pack tlv content') + return -1 + len_str ='%04d' % len(self.content) + tlv_pack = self.head+len_str+self.content + return tlv_pack + + # 解码tlv数据包 + def __unpack_tlv_format(self, msg): + self.msg = str(msg) + 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]: + print('illegal unpack tlv content') + return -1 + unpack = (tag,length,value) + return unpack + + # socket通信(UDP)模块 + def __Socket_UDP(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(self.head, self.content) + + # 向服务端发送消息 + server_addr = ('172.16.1.5',1000) + print("send msg {}".format(msg)) + self.__err = 0 + self.__sock.sendto(msg,server_addr) + self.__wait_resp = 1 + # data = self.__queue.get() + self.__wait_resp = 0 + # return data + return 1 + except Exception as error: + print(error) + return 0 + + def __Socket_UDP_noreply(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(self.head, self.content) + # 向服务端发送消息 + server_addr = ('172.16.1.5',1000) + print("send msg {}".format(msg)) + self.__err = 0 + self.__sock.sendto(msg,server_addr) + self.__wait_resp = 0 + return 0 + + # socket通信(UDP)模块 + def __Socket_Thread(self): + while True: + try: + print("recv====") + data=self.__sock.recv(1024) + print(data) + except Exception as recverr: + print(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() + + else : + value = self.__unpack_tlv_format(data.decode()) + print('mode: {0}, recv {1} bytes, Data: {2}'.format (value[0],len(data), value[2])) + if value[0] == '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]) + print("End else Thread") + + print("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卡状态 +# 下文进行系统配置 +print("Cat1Service start") + +cat1service = Cat1Service() + + + +#voice call callback function +def voice_callback(args): + if args[0] == 10: + print('voicecall incoming call, PhoneNO: ', args[6]) + # gpioWakeBT.write(1) + cat1service.notifyIncomingcall(args[6]) + elif args[0] == 11: + print('voicecall connected, PhoneNO: ', args[6]) + cat1service.notifyConnecteCall() + elif args[0] == 12: + print('voicecall disconnect') + cat1service.notifyDisconnectCall() + elif args[0] == 13: + print('voicecall is waiting, PhoneNO: ', args[6]) + elif args[0] == 14: + print('voicecall dialing, PhoneNO: ', args[6]) + elif args[0] == 15: + print('voicecall alerting, PhoneNO: ', args[6]) + elif args[0] == 16: + print('voicecall holding, PhoneNO: ', args[6]) + +#电话消息反馈 +voiceCall.setCallback(voice_callback) + + +def checknet_cb(arg): + print("start checktime!!") + _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)) + +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): +# cat1service_log.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)