#include "CONFIG.h" #if BC260Y /** ****************************************************************************** * 版 本 :V1.0.0 * 作 者 :liuyanbin,helomgxiang * 版权所有,盗版必究。 * Copyright(C) All rights reserved ****************************************************************************** * 历史记录 * 序号 版本 变更内容 作者 日期 * 1 V0.0.1 实现4GAT指令 何龙翔 2023/12/10 * 2 V0.0.2 基于4实现NB指令 刘艳斌 2024/1/10 * 3 V0.0.3 整合4g和nb代码 刘艳斌 2024/1/24 * 4 V0.0.4 修改send函数添加sendrai 刘艳斌 2024/2/18 ****************************************************************************** */ #include "stm32f10x.h" #include #include #include #include #include "CONFIG.h" #include "bc260y.h" #include "Log_Module.h" #include "At_Module.h" #include "Common_Util.h" // 方法声明 void bc260y_reset(void); // 重置状态。该文件中的方法共用状态,在使用下面的方法前需要重置一下状态。 enum Result bc260y_exit_sleep(void); // 退出休眠 enum Result bc260y_exit_sleep_sync(void); // 退出休眠 void bc260y_enter_sleep(void); // 进入休眠 /** * 查询休眠模式 * 输入<< * * 输出>> * n 睡眠模式。0 禁用,默认;1 启用。 **/ enum Result bc260y_query_sleep(uint8_t * n); // 查询休眠模式。 enum Result bc260y_query_sleep_sync(uint8_t * n); // 查询休眠模式。同步 /** * 设置休眠模式 * 输入<< * n 参数。0 禁用;1启用。 * 输出>> * **/ enum Result bc260y_set_sleep(uint8_t n); // 设置休眠模式。 enum Result bc260y_set_sleep_sync(uint8_t n); // 设置休眠模式。同步 /** * 设置功能模式 * 输入<< * fun 0 最小功能模式;1 全功能模式。 * 输出>> * **/ enum Result bc260y_query_cfun(uint8_t * n); // 查询功能模式。 enum Result bc260y_query_cfun_sync(uint8_t * n); // 查询功能模式。 enum Result bc260y_set_cfun(uint8_t fun); enum Result bc260y_set_cfun_sync(uint8_t fun); // 同步 /** * 设置ps域网络注册状态 * 输入<< * n 0 禁止上报网络注册;1 允许上报网络注册;2 允许上报网络注册和位置信息 * 输出>> * **/ enum Result bc260y_set_cereg(uint8_t n); enum Result bc260y_set_cereg_sync(uint8_t n); // 同步 /** * 查询ps域网络注册状态 * 输入<< * * 输出>> * n 控制指定URC的上报。0 禁止上报网络注册;1 允许上报网络注册;2 允许上报网络注册和位置信息 * stat 网络注册状态。0 未注册;1 已注册,归属地网络; 2 未注册;3 注册被拒绝;4 未知;5 已注册,漫游。 * lac 基站位置区号。用于基站定位,2个字节。 * ci 基站小区ID。用于基站定位,4个字节。 * **/ enum Result bc260y_query_cereg(uint8_t * n, uint8_t * stat, uint16_t * lac, uint32_t * ci); enum Result bc260y_query_cereg_sync(uint8_t * n, uint8_t * stat, uint16_t * lac, uint32_t * ci); // 同步 /** * 查询socket服务状态 * 输入<< * connectID Socket ID。范围1-11 * * 输出>> * state Socket服务状态。0 未连接;1 正在连接;2 已建立连接;3 服务正在监听;4 连接断开。 * * **/ enum Result bc260y_query_socket_state(uint8_t connectID, uint8_t * state); enum Result bc260y_query_socket_state_sync(uint8_t connectID, uint8_t * state); // 同步 /** * 打开socket服务 * 输入<< * connectID Socket ID。范围1-11 * service_type Socket服务类型。取值为"UDP", "TCP"。 * IP_address 远程服务器地址 * remote_port 远程服务器端口 * access_mode Socket服务的数据访问模式。0 缓存模式;1 直吐模式;2 透传模式。 * * 输出>> * err 操作错误代码。0 表示没有错误;其余参考移远文档。 * **/ enum Result bc260y_open_socket(uint8_t connectID, char * service_type, char * IP_address, uint16_t remote_port, uint8_t access_mode, uint16_t * err); enum Result bc260y_open_socket_sync(uint8_t connectID, char * service_type, char * IP_address, uint16_t remote_port, uint8_t access_mode, uint16_t * err); // 同步 /** * 关闭socket服务 * 输入<< * connectID Socket ID。范围1-11 * * 输出>> * **/ enum Result bc260y_close_socket(uint8_t connectID); enum Result bc260y_close_socket_sync(uint8_t connectID); // 同步 /** * 解释:控制是否回显AT+QISEND要发送的数据 * 为了便于处理返回,发送数据时需要关闭回显。 * 输入<< * echo 是否回显AT+QISEND要发送的数据。0 不回显;1 回显。默认是回显 * * 输出>> * **/ enum Result bc260y_set_qisde(uint8_t echo); enum Result bc260y_set_qisde_sync(uint8_t echo); // 同步 /** * 发送数据 * 输入<< * connectID Socket ID。范围1-11。 * send_length 发送长度。 * data 待发送的数据。 * * **/ enum Result bc260y_send(uint8_t connectID, uint8_t * data, uint16_t data_length); enum Result bc260y_send_rai(uint8_t connectID, uint8_t * data, uint16_t data_length,uint8_t rai); enum Result bc260y_send_sync(uint8_t connectID, uint8_t * data, uint16_t data_length); // 同步 /** * 接收数据 * 输入<< * connectID Socket ID。范围0-11。 * * 输出>> * data 接收的数据。 * data_length 接收的数据长度。 **/ enum Result bc260y_recv(uint8_t connectID, uint8_t * data, uint16_t * data_length); // 接收数据 /** * 接收数据。带计时 * 输入<< * connectID Socket ID。范围0-11。 * * 输出>> * data 接收的数据。 * data_length 接收的数据长度。 * **/ enum Result bc260y_recv_with_time(uint8_t connectID, uint8_t * data, uint16_t * data_length, uint32_t time_out); enum Result bc260y_recv_with_time_sync(uint8_t connectID, uint8_t * data, uint16_t * data_length, uint32_t time_out); // 同步 /** * 解释:关闭模块 * 关闭模块,关闭后会自动重启。 * 输入<< * n 模块关机方式。0 立即关机;1 正常关机。默认是1 * * **/ enum Result bc260y_power_down(uint8_t n); enum Result bc260y_power_down_sync(uint8_t n); // 同步 /** * 模块是否启动成功 * 输入<< * * 输出>> * **/ enum Result bc260y_ready(void); /** * 查询信号质量 * 输入<< * * 输出>> * RSRP * RSRQ * RSSI * SINR **/ enum Result bc260y_qeng_servingcell(int * RSRP, int * RSRQ, int * RSSI, int * SINR); enum Result bc260y_qeng_servingcell_sync(int * RSRP, int * RSRQ, int * RSSI, int * SINR); /** * 查询ICCID * 输入<< * * 输出>> * iccid SIM卡卡号 **/ enum Result bc260y_query_qccid(char * iccid); enum Result bc260y_query_qccid_sync(char * iccid); /** * 配置发送数据格式 * 输入<< *n 0数据格式为文本字符串,1为十六进制字符串 * **/ enum Result bc260y_dataformat(uint8_t n); enum Result bc260y_dataformat_sync(uint8_t n); // // AT指令 static char AT_CMD[256]; // EC800M提供的一些方法 struct BC260Y_Struct bc260y = { .timer = { .time = 0, .flag = 0 }, .reset = bc260y_reset, .exit_sleep = bc260y_exit_sleep, .exit_sleep_sync = bc260y_exit_sleep_sync, .enter_sleep = bc260y_enter_sleep, .query_sleep = bc260y_query_sleep, .query_sleep_sync = bc260y_query_sleep_sync, .set_sleep = bc260y_set_sleep, .set_sleep_sync = bc260y_set_sleep_sync, .query_cfun = bc260y_query_cfun, .query_cfun_sync = bc260y_query_cfun_sync, .set_cfun = bc260y_set_cfun, .set_cfun_sync = bc260y_set_cfun_sync, .set_cereg = bc260y_set_cereg, .set_cereg_sync = bc260y_set_cereg_sync, .query_cereg = bc260y_query_cereg, .query_cereg_sync = bc260y_query_cereg_sync, .query_socket_state = bc260y_query_socket_state, .query_socket_state_sync = bc260y_query_socket_state_sync, .open_socket = bc260y_open_socket, .open_socket_sync = bc260y_open_socket_sync, .close_socket = bc260y_close_socket, .close_socket_sync = bc260y_close_socket_sync, .set_qisde = bc260y_set_qisde, .set_qisde_sync = bc260y_set_qisde_sync, .send = bc260y_send, .send_rai = bc260y_send_rai, .send_sync = bc260y_send_sync, .recv = bc260y_recv, .recv_with_time = bc260y_recv_with_time, .recv_with_time_sync = bc260y_recv_with_time_sync, .power_down = bc260y_power_down, .power_down_sync = bc260y_power_down_sync, .ready = bc260y_ready, .qeng_servingcell = bc260y_qeng_servingcell, .qeng_servingcell_sync = bc260y_qeng_servingcell_sync, .query_qccid = bc260y_query_qccid, .query_qccid_sync = bc260y_query_qccid_sync, .dataformat= bc260y_dataformat, .dataformat_sync= bc260y_dataformat_sync }; // 发送AT指令 static void send_data(uint8_t * data, uint16_t length) { // 发送AT指令 AT_Send_Bytes(data, length); } // 发送AT指令 static uint8_t send_at_string(char * cmd) { uint8_t state = 0; if(AT_Get_Status() == AT_Status_None) { // 发送AT指令 AT_Send_String(cmd); state = 1; } return state; } // 获取状态 static enum STATUS getStatus(void) { return bc260y.status; } // 设置状态 static void setStatus(enum STATUS status) { bc260y.status = status; } // 获取定时 static uint32_t getTimerMs(void) { return time_get_delay(&bc260y.timer); } // 清除定时 static void clearTimer(void) { time_clear(&bc260y.timer); } // 设置定时 //static void setTimerMs(uint32_t time) //{ // bc260y.timer_ms = time; //} // 获取ID static uint8_t getActiveID(void) { return bc260y.activeID; } static void setActiveID(uint8_t activeID) { bc260y.activeID = activeID; } // 验证ID static uint8_t verifyActiveID(uint8_t activeID) { if(getActiveID() == 0 || getActiveID() == activeID){ return 1; } else { Log_Printf_Debug("activeID repetition!\r\n"); return 0; } } // 返回超时结果 static enum Result overtime(void) { setStatus(Status_Overtime); // 超时 return Result_Failed; // 结果 } // 返回成功结果 static enum Result success(void) { // 成功 setStatus(Status_Success); // 结果 return Result_Success; } // 返回失败结果 static enum Result failed(void) { // 失败 setStatus(Status_Failed); // 失败结果 return Result_Failed; } // 重置状态。该文件中的方法共用状态,在使用方法前需要重置一下状态。 void bc260y_reset(void) { setStatus(Status_None); // 重置状态 setActiveID(0); // 重置ID clearTimer(); // 重置计时 AT_Clear(); // 清除AT指令 } // 发送指令并改变状态 enum Result send_at(char * cmd, uint8_t activeID) { Log_Printf_Debug(cmd); // 打印AT指令 if(send_at_string(cmd)) // 发送AT指令 { setActiveID(activeID); // 活动ID setStatus(Status_Sending); // 设置已发送 clearTimer(); // 重置计时 return Result_None; // 未知结果 } else { Log_Printf_Debug("AT指令发送失败\r\n"); // 打印日志 return Result_Failed; // 失败结果 } } // 退出休眠 enum Result bc260y_exit_sleep(void) { //GPIO_SetBits(WAKE_GPIO, WAKE_GPIO_Pin);// nb拉高io口,唤醒模组 enum Result result = Result_None; int activeID = 1, time = 500; // 活动ID, 超时时间 if(!verifyActiveID(activeID)){ return Result_Failed; } // 校验ID // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT\r\n"); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期1,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 Log_SendArray_Debug(AT_result(), AT_result_length()); result = overtime(); // 超时 } if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "+QNBIOTEVENT:") != NULL) { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } enum Result bc260y_exit_sleep_sync() { enum Result result = Result_None; while(1) { result = bc260y_exit_sleep(); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } // 进入休眠 void bc260y_enter_sleep(void) { // GPIO_ResetBits(WAKE_GPIO, WAKE_GPIO_Pin); // nb拉低io口,进入睡眠 } /** * 查询休眠模式 * 输入<< * * 输出>> * n 睡眠模式。0 禁用,默认;1 启用。 * **/ enum Result bc260y_query_sleep(uint8_t * n) { enum Result result = Result_None; int activeID = 1, time = 500; // 活动ID, 超时时间 if(!verifyActiveID(activeID)){ return Result_Failed; } // 校验ID // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QSCLK?\r\n"); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期1,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 Log_SendArray_Debug(AT_result(), AT_result_length()); } if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // 处理返回结果 char * saveptr = NULL; char * split = "\r\n"; // 第一行 char * Line1 = strtok_r((char * )AT_result(), split, &saveptr); // 第二行 char * Line2 = strtok_r(NULL, split, &saveptr); // 拆解第二行 char * saveptr_inner = NULL; char * split_inner = ": "; strtok_r(Line2, split_inner, &saveptr_inner); // 获取mode * n = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 查询休眠模式。同步方法 * 输入<< * * 输出>> * n 睡眠模式。0 禁用,默认;1 启用。 * **/ enum Result bc260y_query_sleep_sync(uint8_t * n) { enum Result result = Result_None; while(1) { result = bc260y_query_sleep(n); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 设置休眠模式 * n 参数。0 禁用;1启用允许进入Deep Sleep 模式,2允许模块进入入Light Sleep 模式。 **/ enum Result bc260y_set_sleep(uint8_t n) { enum Result result = Result_None; int activeID = 2, time = 500; // 活动ID, 超时时间 if(!verifyActiveID(activeID)){ return Result_Failed; } // 校验ID // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QSCLK=%d\r\n", n); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 设置休眠模式。同步 * n 参数。0 禁用;1启用。 **/ enum Result bc260y_set_sleep_sync(uint8_t n) { enum Result result = Result_None; while(1) { result = bc260y_set_sleep(n); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 查询功能模式 * 输入<< * * 输出>> * n 功能模式。0 最小功能模式,默认;1 全功能模式。 * **/ enum Result bc260y_query_cfun(uint8_t * n) { enum Result result = Result_None; int activeID = 100, time = 500; // 活动ID, 超时时间 if(!verifyActiveID(activeID)){ return Result_Failed; } // 校验ID // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+CFUN?\r\n"); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期1,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 Log_SendArray_Debug(AT_result(), AT_result_length()); } if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // 处理返回结果 char * saveptr = NULL; char * split = "\r\n"; // 第一行 strtok_r((char * )AT_result(), split, &saveptr); // 第二行 char * Line2 = strtok_r(NULL, split, &saveptr); // 拆解第二行 char * saveptr_inner = NULL; char * split_inner = ": "; strtok_r(Line2, split_inner, &saveptr_inner); // 获取mode * n = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } enum Result bc260y_query_cfun_sync(uint8_t * n) { enum Result result = Result_None; while(1) { result = bc260y_query_cfun(n); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 设置功能模式 * fun 0 最小功能模式;1 全功能模式。 **/ enum Result bc260y_set_cfun(uint8_t fun) { enum Result result = Result_None; int activeID = 4, time; // 活动ID, 超时时间 // 校验参数 if(fun == 0){ time = 3000; } else if(fun == 1){ time = 7000; } else { Log_Printf_Debug("set_cfun params error!\r\n"); return Result_Failed; } // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+CFUN=%d\r\n", fun); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 Log_SendArray_Debug(AT_result(), AT_result_length()); result = overtime(); // 超时 } else if(fun == 1 && strstr((char * )AT_result(), "+IP:") != NULL) // 查询是否返回 { // 防止接收不完整 if(AT_wait_time() > 10) // 过10ms之后再取数据,避免数据截断。 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } } else if(fun == 0 && strstr((char * )AT_result(), "+CPIN: NOT READY") != NULL) // 查询是否返回 { // 防止接收不完整 if(AT_wait_time() > 10) // 过10ms之后再取数据,避免数据截断。 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 设置功能模式 * 输入<< * fun 0 最小功能模式;1 全功能模式。 * 输出>> * **/ enum Result bc260y_set_cfun_sync(uint8_t fun) { enum Result result = Result_None; while(1) { result = bc260y_set_cfun(fun); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 设置ps域网络注册状态 * n 0 禁止上报网络注册;1 允许上报网络注册;2 允许上报网络注册和位置信息 **/ enum Result bc260y_set_cereg(uint8_t n) { enum Result result = Result_None; int activeID = 6, time = 500; // 活动ID, 超时时间 // 校验参数 if(n > 2) { Log_Printf_Debug("set_cgreg params error!\r\n"); return Result_Failed; } // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+CEREG=%d\r\n", n); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 设置ps域网络注册状态 * 输入<< * n 0 禁止上报网络注册;1 允许上报网络注册;2 允许上报网络注册和位置信息 * 输出>> * **/ enum Result bc260y_set_cereg_sync(uint8_t n) { enum Result result = Result_None; while(1) { result = bc260y_set_cereg(n); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 查询ps域网络注册状态 * 输入<< * * 输出>> * n 控制指定URC的上报。0 禁止上报网络注册;1 允许上报网络注册;2 允许上报网络注册和位置信息 * stat 网络注册状态。0 未注册;1 已注册,归属地网络; 2 未注册;3 注册被拒绝;4 未知;5 已注册,漫游。 * lac 基站位置区号。用于基站定位,2个字节。 * ci 基站小区ID。用于基站定位,4个字节。 * **/ enum Result bc260y_query_cereg(uint8_t * n, uint8_t * stat, uint16_t * lac, uint32_t * ci) { enum Result result = Result_None; int activeID = 9, time = 500; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+CEREG?\r\n"); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 setStatus(Status_Overtime); // 超时 result = Result_Failed; // 结果 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // 处理返回结果 char * saveptr = NULL; char * split = "\r\n"; // 第一行 strtok_r((char * )AT_result(), split, &saveptr); // 第二行 char * Line2 = strtok_r(NULL, split, &saveptr); char * saveptr_inner = NULL; char * split_inner = ": ,\""; strtok_r(Line2, split_inner, &saveptr_inner); * n = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); * stat = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); // Log_Printf_Debug("saveptr_inner: %s\r\n", Line2); * lac = strtoul(strtok_r(NULL, split_inner, &saveptr_inner), NULL, 16); * ci = strtoul(strtok_r(NULL, split_inner, &saveptr_inner), NULL, 16); // 打印 Log_Printf_Debug("mode: %d, stat: %d, lac: %d, ci: %d\r\n", * n, * stat, * lac, * ci); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 查询ps域网络注册状态 * 输入<< * * 输出>> * n 控制指定URC的上报。0 禁止上报网络注册;1 允许上报网络注册;2 允许上报网络注册和位置信息 * stat 网络注册状态。0 未注册;1 已注册,归属地网络; 2 未注册;3 注册被拒绝;4 未知;5 已注册,漫游。 * lac 基站位置区号。用于基站定位,2个字节。 * ci 基站小区ID。用于基站定位,4个字节。 * **/ enum Result bc260y_query_cereg_sync(uint8_t * n, uint8_t * stat, uint16_t * lac, uint32_t * ci) { enum Result result = Result_None; while(1) { result = bc260y_query_cereg(n, stat, lac, ci); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 查询socket服务状态 * connectID Socket ID。范围1-11 * state Socket服务状态。0 未连接;1 正在连接;2 已建立连接;3 服务正在监听;4 连接断开。 * * activeID 9 **/ enum Result bc260y_query_socket_state(uint8_t connectID, uint8_t * state) { enum Result result = Result_None; int activeID = 9, time = 500; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QISTATE=1,%d\r\n", connectID); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // 处理返回结果 char * saveptr = NULL; char * split = "\r\n"; // 第一行 strtok_r((char * )AT_result(), split, &saveptr); // 第二行 char * Line2 = strtok_r(NULL, split, &saveptr); // 查询结果为空 if(strcmp(Line2, "OK") == 0){ * state = 0; } else { // 拆解第二行 char * saveptr_inner = NULL; char * split_inner = ": ,\""; strtok_r(Line2, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); * state = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); } // 打印 Log_Printf_Debug("result: %d\r\n", * state); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 查询socket服务状态 * connectID Socket ID。范围1-11 * state Socket服务状态。0 未连接;1 正在连接;2 已建立连接;3 服务正在监听;4 连接断开。 * * activeID 9 **/ enum Result bc260y_query_socket_state_sync(uint8_t connectID, uint8_t * state) { enum Result result = Result_None; while(1) { result = bc260y_query_socket_state(connectID, state); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 打开socket服务 * 输入<< * connectID Socket ID。范围1-11 * service_type Socket服务类型。取值为"UDP", "TCP"。 * IP_address 远程服务器地址 * remote_port 远程服务器端口 * access_mode Socket服务的数据访问模式。0 缓存模式;1 直吐模式;2 透传模式。 * * 输出>> * err 操作错误代码。0 表示没有错误;其余参考移远文档。 * * activeID 19 **/ enum Result bc260y_open_socket(uint8_t connectID, char * service_type, char * IP_address, uint16_t remote_port, uint8_t access_mode, uint16_t * err) { enum Result result = Result_None; int activeID = 19, time = 3000; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QIOPEN=0,%d,\"%s\",\"%s\",%d,%d,%d\r\n", connectID, service_type, IP_address, remote_port, 0, access_mode); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), "+QIOPEN: ") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length());// // 处理返回结果 char * saveptr = NULL; char * split = "\r\n"; // 第一行 strtok_r((char * )AT_result(), split, &saveptr); // 第二行 char * Line2 = strtok_r(NULL, split, &saveptr); // 第三行 char * Line3 = strtok_r(NULL, split, &saveptr); // 查询结果为空 if(strcmp(Line2, "OK") == 0) { // 拆解第三行 char * saveptr_inner = NULL; char * split_inner = ": ,\""; strtok_r(Line3, split_inner, &saveptr_inner); uint8_t connID = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); * err = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); Log_Printf_Debug("result: %d, %d\r\n", connID, * err); } result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 打开socket服务 * 输入<< * connectID Socket ID。范围1-11 * service_type Socket服务类型。取值为"UDP", "TCP"。 * IP_address 远程服务器地址 * remote_port 远程服务器端口 * access_mode Socket服务的数据访问模式。0 缓存模式;1 直吐模式;2 透传模式。 * * 输出>> * err 操作错误代码。0 表示没有错误;其余参考移远文档。 * * activeID 19 **/ enum Result bc260y_open_socket_sync(uint8_t connectID, char * service_type, char * IP_address, uint16_t remote_port, uint8_t access_mode, uint16_t * err) { enum Result result = Result_None; while(1) { result = bc260y_open_socket(connectID, service_type, IP_address, remote_port, access_mode, err); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 关闭socket服务 * 输入<< * connectID Socket ID。范围1-11 * * activeID 29 **/ enum Result bc260y_close_socket(uint8_t connectID) { enum Result result = Result_None; int activeID = 29, time = 500; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QICLOSE=%d\r\n", connectID); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = Result_Failed; } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 关闭socket服务 * 输入<< * connectID Socket ID。范围1-11 * * activeID 29 **/ enum Result bc260y_close_socket_sync(uint8_t connectID) { enum Result result = Result_None; while(1) { result = bc260y_close_socket(connectID); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 解释:控制是否回显AT+QISEND要发送的数据 * 为了便于处理返回,发送数据时需要关闭回显。 * 输入<< * echo 是否回显AT+QISEND要发送的数据。0 不回显;1 回显。默认是回显 * * activeID 45 **/ enum Result bc260y_set_qisde(uint8_t echo) { enum Result result = Result_None; int activeID = 45, time = 1000; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "ATE%d\r\n", echo); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = Result_Failed; } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 解释:控制是否回显AT+QISEND要发送的数据 * 为了便于处理返回,发送数据时需要关闭回显。 * 输入<< * echo 是否回显AT+QISEND要发送的数据。0 不回显;1 回显。默认是回显 * * activeID 45 **/ enum Result bc260y_set_qisde_sync(uint8_t echo) { enum Result result = Result_None; while(1) { result = bc260y_set_qisde(echo); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 发送数据 * 输入<< * connectID Socket ID。范围1-11。 * send_length 发送长度。 * data 待发送的数据。 * * activeID 49 **/ enum Result bc260y_send(uint8_t connectID, uint8_t * data, uint16_t data_length) { enum Result result = Result_None; int activeID = 49, time = 10000; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QISEND=%d,%d\r\n", connectID, data_length); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = Result_Failed; } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), ">") != NULL) // 有响应 { // 发送日志 Log_Printf_Debug("AT6返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // Log_Printf_Debug("coap:\r\n"); // Log_SendHex(data, data_length); // Log_Printf_Debug("\r\n"); // 发送数据 send_data(data, data_length); // 清理一下AT返回结果缓存 AT_Clear_Result(); } else if(strstr((char * )AT_result(), "SEND OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "SEND FALL\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 发送数据 * 输入<< * connectID Socket ID。范围1-11。 * send_length 发送长度。 * data 待发送的数据。 *rai 发送模式,0发送不释放RRC,1发送立即释放RRC,2发送返回释放RRC * activeID 49 **/ enum Result bc260y_send_rai(uint8_t connectID, uint8_t * data, uint16_t data_length,uint8_t rai) { enum Result result = Result_None; int activeID = 50, time = 10000; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { // memset(hexData,0, sizeof(hexData)); // byteToHexStr(data,hexData, data_length);//nb需要转16进制 // sprintf(AT_CMD, "AT+QISEND=%d,%d,%s,%d\r\n", connectID, data_length,hexData,rai); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = Result_Failed; } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), "SEND OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "SEND FALL\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 发送数据 * 输入<< * connectID Socket ID。范围1-11。 * send_length 发送长度。 * data 待发送的数据。 * * activeID 49 **/ enum Result bc260y_send_sync(uint8_t connectID, uint8_t * data, uint16_t data_length) { enum Result result = Result_None; while(1) { result = bc260y_send(connectID, data, data_length); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 接收数据 * 输入<< * connectID Socket ID。范围0-11。 * * 输出>> * data 接收的数据。 * data_length 接收的数据长度。 * **/ enum Result bc260y_recv(uint8_t connectID, uint8_t * data, uint16_t * data_length) { // 设置AT为使用中,防止被其他程序占用 AT_Set_Status(AT_Status_Using); enum Result result = Result_None; // 校验参数 if(connectID > 11) { Log_Printf_Debug("recv params error!\r\n"); return Result_Failed; } char cmp[20]; sprintf(cmp, "+QIURC: \"recv\",%d", connectID); // 拼接AT指令 // 判断是否接收到 if(strstr((char * )AT_result(), cmp) != NULL) { // 防止接收不完整 uint32_t last_time = AT_wait_time(); if(last_time > 10) // 过10ms之后再取数据,避免数据截断。 { // 发送日志 Log_Printf_Debug("AT返回: %d, time_diff: %d\r\n", AT_result_length(), last_time); // Log_SendArray_Debug(AT_result(), AT_result_length()); char * saveptr = NULL; char * split = "\r";//删除\n,这个会改变解析的值 char * Line1 = strtok_r((char * )AT_result(), split, &saveptr); uint8_t Line1_Len = strlen(Line1); // Log_Printf_Debug("Line1(%d): %s\r\n",Line1_Len ,Line1); // 分割Line1,获取报文长度 char * saveptr_inner = NULL; char * split_inner = ","; strtok_r(Line1, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); //Log_Printf_Debug("saveptr_inner: %s####\r\n",saveptr_inner); * data_length = strtoul(strtok_r(NULL, split_inner, &saveptr_inner), NULL, 10); // uint16_t line_length = Line1_Len+4 ; // 内存拷贝 memcpy(data,saveptr_inner+1, *data_length); //memcpy(data,AT_result(), *data_length); // for(int i =0;i<*data_length;i++) // { // Log_Printf_Debug("%02x",data[i]); // } // Log_Printf_Debug("\r\n ####data: %s\r\n",data); // 成功 result = Result_Success; // 清理一下AT返回结果缓存 AT_Clear_Result(); } } return result; } /** * 接收数据。带计时 * 输入<< * connectID Socket ID。范围0-11。 * * 输出>> * data 接收的数据。 * data_length 接收的数据长度。 * **/ enum Result bc260y_recv_with_time(uint8_t connectID, uint8_t * data, uint16_t * data_length, uint32_t time_out) { enum Result result = Result_None; int activeID = 59, time = time_out; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { setStatus(Status_Sending); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = Result_Failed; } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("等待时间超时\r\n"); // 打印日志 result = overtime(); // 超时 Log_SendArray_Debug(AT_result(), AT_result_length()); } else { // 接收数据 result = bc260y.recv(connectID, data, data_length); if(result == Result_Success) { result = success(); // 成功 } } return result; } /** * 接收数据。带计时 * 输入<< * connectID Socket ID。范围0-11。 * * 输出>> * data 接收的数据。 * data_length 接收的数据长度。 * **/ enum Result bc260y_recv_with_time_sync(uint8_t connectID, uint8_t * data, uint16_t * data_length, uint32_t time_out) { enum Result result = Result_None; while(1) { result = bc260y_recv_with_time(connectID, data, data_length, time_out); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 解释:关闭模块 * 关闭模块,关闭后会自动重启。 * 输入<< * n 模块关机方式。0 立即关机;1 正常关机。默认是1 * * activeID 69 **/ enum Result bc260y_power_down(uint8_t n) { enum Result result = Result_None; int activeID = 69, time = 3000; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QPOWD=%d\r\n", n); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = Result_Failed; } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); } else if(strstr((char * )AT_result(), "POWERED DOWN\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // 成功结果 result = success(); } return result; } /** * 解释:关闭模块。同步 * 关闭模块,关闭后会自动重启。 * 输入<< * n 模块关机方式。0 立即关机;1 正常关机。默认是1 * * activeID 69 **/ enum Result bc260y_power_down_sync(uint8_t n) { enum Result result = Result_None; while(1) { result = bc260y_power_down(n); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 模块是否启动成功 * 输入<< * * 输出>> * **/ enum Result bc260y_ready(void) { if(AT_Get_Status() != AT_Status_None) { return Result_None; } enum Result result = Result_None; // 判断是否接收到 uint8_t RDY[5]="RDY"; if(memmem(AT_result(),AT_result_length(),RDY,strlen((char *)RDY)) != 0) { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // 成功结果 result = Result_Success; // 清理一下AT返回结果缓存 AT_Clear_Result(); } return result; } /** * 查询信号质量 * 输入<< * * 输出>> * RSRP * RSRQ * RSSI * SINR **/ enum Result bc260y_qeng_servingcell(int * RSRP, int * RSRQ, int * RSSI, int * SINR) { enum Result result = Result_None; int activeID = 71, time = 500; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { //sprintf(AT_CMD, "AT+QENG=\"servingcell\"\r\n"); // 拼接AT指令 sprintf(AT_CMD, "AT+QENG=0\r\n"); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 setStatus(Status_Overtime); // 超时 result = Result_Failed; // 结果 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // 处理返回结果 // char * saveptr = NULL; // char * split = "\r\n"; char * saveptr_inner = NULL; char * split_inner = ",\""; strtok_r((char * )AT_result(), split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); strtok_r(NULL, split_inner, &saveptr_inner); * RSRP = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); * RSRQ = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); * RSSI = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); * SINR = atoi(strtok_r(NULL, split_inner, &saveptr_inner)); // 打印 Log_Printf_Debug("RSRP: %d, RSRQ: %d, RSSI: %d, SINR: %d\r\n", * RSRP, * RSRQ, * RSSI, * SINR); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } enum Result bc260y_qeng_servingcell_sync(int * RSRP, int * RSRQ, int * RSSI, int * SINR) { enum Result result = Result_None; while(1) { result = bc260y_qeng_servingcell(RSRP, RSRQ, RSSI, SINR); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 查询ICCID * 输入<< * * 输出>> * iccid SIM卡卡号 **/ enum Result bc260y_query_qccid(char * iccid) { enum Result result = Result_None; int activeID = 75, time = 500; // 活动ID, 超时时间 // 校验ID if(!verifyActiveID(activeID)){ return Result_Failed; } // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QCCID\r\n"); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 setStatus(Status_Overtime); // 超时 result = Result_Failed; // 结果 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); // 处理返回结果 char * saveptr = NULL; char * split = "\r\n"; // 第一行 char * Line1 =strtok_r((char * )AT_result(), split, &saveptr); // // 第二行 // char * Line2 = strtok_r(NULL, split, &saveptr); // 拆解第二行 char * saveptr_inner = NULL; char * split_inner = ": ,\""; strtok_r(Line1, split_inner, &saveptr_inner); // 字符串拷贝 strcpy(iccid, strtok_r(NULL, split_inner, &saveptr_inner)); // 打印 Log_Printf_Debug("ICCID: %s\r\n", iccid); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } enum Result bc260y_query_qccid_sync(char * iccid) { enum Result result = Result_None; while(1) { result = bc260y_query_qccid(iccid); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } /** * 配置发送数据格式 * 输入<< *n 0数据格式为文本字符串,1为十六进制字符串 * **/ enum Result bc260y_dataformat(uint8_t n) { enum Result result = Result_None; int activeID = 2, time = 500; // 活动ID, 超时时间 if(!verifyActiveID(activeID)){ return Result_Failed; } // 校验ID // 判断状态 if(getStatus() == Status_None) // 空闲状态 { sprintf(AT_CMD, "AT+QICFG=dataformat,%d,%d\r\n", n,0); // 拼接AT指令 result = send_at(AT_CMD, activeID); } else if(getStatus() != Status_Sending) // 上一次的结果没有清除,返回错误,为了保证时效性,需要重置状态。重新调用 { Log_Printf_Debug("返回结果过期,请重置状态\r\n"); // 打印日志 result = failed(); // 失败 } else if(getTimerMs() > time) // 正在发送状态。判断超时 { Log_Printf_Debug("AT指令返回超时\r\n"); // 打印日志 result = overtime(); // 超时 } else if(strstr((char * )AT_result(), "OK\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = success(); // 成功 } else if(strstr((char * )AT_result(), "ERROR\r\n") != NULL) // 查询是否返回 { // 发送日志 Log_Printf_Debug("AT返回: %d\r\n", AT_result_length()); Log_SendArray_Debug(AT_result(), AT_result_length()); result = failed(); // 失败 } return result; } /** * 配置发送数据格式 * 输入<< *n 0数据格式为文本字符串,1为十六进制字符串 * **/ enum Result bc260y_dataformat_sync(uint8_t n) { enum Result result = Result_None; while(1) { result =bc260y_dataformat(n); if(result != Result_None) { // 重置 bc260y.reset(); break; } } return result; } #endif