QS100连接onenet
这里只是把数据手册中使用到的重要部分摘取出来,数据手册可以去官方的qq群获取。项目还未完成后面只展示了连接onenet的代码。
项目源码地址:https://gitee.com/xiao-liu-harbors-dreams/locator.git
AT命令处理是参考:MCU 通用AT指令处理框架_at指令框架-CSDN博客这篇文章
rt-thread环形缓冲区代码:components/drivers/ipc/ringbuffer.c · RT-Thread/rt-thread - Gitee.com
一. 简介
-
QS-100 是一款基于芯翼 XY1100 的工业级 NB-IoT 无线通信模组,具有高性能、低功耗、多频段等多
个产品优势,协议上完全兼容 R13 和 R14,软件升级支持 R15,内嵌 TCP、UDP、MQTT、COAP 等多种通
信协议栈,支持中国移动 OneNET ,中国联通云和中国电信 IoT 物联网云平台,方便客户应用。
-
发射功率:23dBm±2dB
-
灵敏度:Band 3:-116dBm±1dB
Band 5/8:-117dBm±1dB
-
USIM 卡接口:自适应模式,支持 1.8/3.0V USIM 卡
-
主串口: 全功能串口,用于 AT 指令发送,数据传输,自适应波特率:从 4800bps 到 115200bps
二. 关键参数
-
通讯方式:可以通过串口发送AT指令进行相关操作。串口默认波特率9600
-
复位和唤醒:通过GPIO控制RST_WAKE引脚的高低电平实现

-
工作模式:


- 工作指示灯:

- 功耗:

三. 代码
1. uart
串口接收这边用的是DMA+空闲中断+环形缓冲区进行接收的数据,
usart.c
volatile uint8_t uart_rx_flag = UART_RX_IDLE;
/* 串口映射表 */
static UART_HandleTypeDef *s_uartMap[] =
{
[UART_NUM_1] = NULL,
[UART_NUM_2] = NULL,
[UART_NUM_3] = &huart3,
};
struct rt_ringbuffer ringbuffer; /* 接收环形缓冲区 */
static uint8_t rx_buffer[UART_BUFFER_SIZE]; /* 接收缓冲区 */
uint8_t dma_rx_buffer[UART_BUFFER_SIZE]; /* DMA接收缓冲区 */
/**
* @brief 获取串口接收环形缓冲区句柄
*
* @param 无
*
* @retval 环形缓冲区句柄
*/
struct rt_ringbuffer* get_ringbuffer_handler(void)
{
return &ringbuffer;
}
/**
* @brief 串口发送数据
*
* @param uart_num 串口编号
* @param tx_data 发送的数据
* @param tx_data_len 发送的数据长度
*
* @retval 返回是否发送成功
*/
com_status_t uart_send_data(uint8_t uart_num,
const uint8_t* tx_data,
const uint16_t tx_data_len)
{
/* 检查参数 */
if (NULL == tx_data || 0 == tx_data_len)
{
return COM_ERROR;
}
if (UART_MAX_NUM <= uart_num || NULL == s_uartMap[uart_num])
{
return COM_ERROR;
}
/* 发送数据 */
if(HAL_OK == HAL_UART_Transmit(s_uartMap[uart_num],
tx_data,
tx_data_len,
1000))
{
return COM_OK;
}
else
{
return COM_ERROR;
}
}
/**
* @brief 串口接收数据
*
* @param uart_num 串口编号
* @param rx_data 接收数据
* @param rx_data 接收数据长度
*
* @retval 返回是否接收成功
*/
com_status_t uart_recv_data(uint8_t uart_num,
uint8_t* rx_data,
size_t* rx_data_len)
{
static uint16_t rx_buffer_len = 0;
/* 检查参数 */
if (NULL == rx_data || NULL == rx_data_len)
{
return COM_ERROR;
}
if (UART_MAX_NUM <= uart_num || NULL == s_uartMap[uart_num])
{
return COM_ERROR;
}
/* 接收数据 */
if(uart_num == UART_NUM_3 && UART_RX_OK == uart_rx_flag)
{
uart_rx_flag = UART_RX_IDLE;
rx_buffer_len = rt_ringbuffer_data_len(&ringbuffer);
if(rx_buffer_len > 0)
{
rt_ringbuffer_get(&ringbuffer, rx_data, rx_buffer_len);
*rx_data_len = rx_buffer_len;
// debug_println("uart_recv:%s, %d", rx_data, *rx_data_len);
// HAL_Delay(200);
return COM_OK;
}
}
return COM_TIMEOUT;
}
/* 串口中断接收回调函数 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
static uint8_t recv_total_size = 0;
static uint8_t current_recv_size = 0;
if(huart == &huart3)
{
if(__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
uart_rx_flag = UART_RX_OK;
recv_total_size = UART_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
current_recv_size = recv_total_size - last_rx_size;
rt_ringbuffer_put(&ringbuffer,
&dma_rx_buffer[last_rx_size],
current_recv_size);
last_rx_size = recv_total_size;
}
}
}
/* DMA 半满中断回调函数 */
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
static uint8_t recv_total_size = 0;
static uint8_t current_recv_size = 0;
if(huart == &huart3)
{
recv_total_size = UART_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
current_recv_size = recv_total_size - last_rx_size;
rt_ringbuffer_put(&ringbuffer,
&dma_rx_buffer[last_rx_size],
current_recv_size);
last_rx_size = recv_total_size;
}
}
/* DMA 全满中断回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
static uint8_t current_recv_size = 0;
if(huart == &huart3)
{
current_recv_size = UART_BUFFER_SIZE - last_rx_size;
rt_ringbuffer_put(&ringbuffer,
&dma_rx_buffer[last_rx_size],
current_recv_size);
last_rx_size = 0;
}
}
usart.h
#define UART_BUFFER_SIZE 256 /* 缓冲区大小 */
/* 串口号 */
typedef enum
{
UART_NUM_1 = 1, /* 串口1 */
UART_NUM_2 = 2, /* 串口2 */
UART_NUM_3 = 3, /* 串口3 */
UART_MAX_NUM /* 最大串口数量 */
} uart_num_t;
typedef enum
{
UART_RX_OK = 0, /* 接收成功 */
UART_RX_IDLE, /* 未在接收 */
} UART_RxStatus_t;
/**
* @brief 获取串口接收环形缓冲区句柄
*
* @param 无
*
* @retval 环形缓冲区句柄
*/
struct rt_ringbuffer* get_ringbuffer_handler(void);
/**
* @brief 串口发送数据
*
* @param uart_num 串口编号
* @param tx_data 发送的数据
* @param tx_data_len 发送的数据长度
*
* @retval 返回是否发送成功
*/
com_status_t uart_send_data(uint8_t uart_num,
const uint8_t* tx_data,
const uint16_t tx_data_len);
/**
* @brief 串口接收数据
*
* @param uart_num 串口编号
* @param rx_data 接收数据
* @param rx_data 接收数据长度
*
* @retval 返回是否接收成功
*/
com_status_t uart_recv_data(uint8_t uart_num,
uint8_t* rx_data,
size_t* rx_data_len);
2. AT命令处理
freertos和透传部分没有使用也没有进行修改,还未测试,此次用到是裸机处理命令发送,接收以及处理URC。
AT响应的处理流程大概是下图这样

Com_at.c
#include "Com_at.h"
/**
* @brief 处理命令响应
*
* @param client AT客户端
*
* @return com_status_t 命令处理结果
*/
static com_status_t at_process_command_response(at_client_t* client,
uint8_t* response_line)
{
/* 获取互斥锁 */
#ifdef USE_FREERTOS
xSemaphoreTake(client->xATControlMutex, pdMAX_DELAY);
#endif
/* 检查期望响应 */
if (NULL != strstr((const char*)response_line,
(const char*)client->cmd_param.expect))
{
// debug_println("接收响应成功");
client->cmd_in_progress = false;
return client->cmd_param.handler(response_line,
client->cmd_param.output);
}
else if (NULL != strstr((const char*)response_line,
"OK"))
{
client->cmd_in_progress = false;
// debug_println("接收响应成功");
return COM_OK;
}
/* 检查错误响应 */
else if (NULL != strstr((const char*)response_line,
"ERROR"))
{
debug_println("接收响应失败");
client->cmd_in_progress = false;
client->error_handler(response_line);
return COM_ERROR;
}
else
return COM_TIMEOUT;
}
/**
* @brief 处理URC
*
* @param client AT客户端
*
* @return com_status_t URC处理结果
*/
static com_status_t at_process_urc(at_client_t* client,
uint8_t* response_line)
{
urc_entry_t* entry = NULL; /* URC条目 */
debug_println("开始处理URC %s", response_line);
for (size_t i = 0; i < client->urc_count; i++)
{
entry = &client->urc_table[i];
if (NULL == strstr((const char*)response_line,
(const char*)entry->prefix))
{
continue;
}
if(COM_OK == entry->handler(entry->context,
response_line))
{
// debug_println("URC请求处理完成");
return COM_OK;
}
else
{
debug_println("URC请求处理失败");
return COM_ERROR;
}
}
debug_println("接收URC超时 :%s", response_line);
return COM_TIMEOUT;
}
/**
* @brief 处理普通模式命令
*
* @param client AT客户端实例
*
* @return com_status_t 命令处理结果
*/
static com_status_t at_process_general(at_client_t* client)
{
static uint8_t* response_start = NULL; /* 响应起始 */
static uint8_t* response_end = NULL; /* 响应结束 */
com_status_t com_status = COM_OK;
/* 获取互斥锁 */
#ifdef USE_FREERTOS
xSemaphoreTake(client->xATControlMutex, pdMAX_DELAY);
#endif
/* 检查参数 */
if(NULL == client)
return COM_ERROR;
if(AT_MODE_GENERAL != client->at_mode)
return COM_ERROR;
/* 获取响应起始 */
response_start = client->uart_config.rx_buf;
do
{
/* 查找是否有多个响应 */
response_end = (uint8_t*)strstr((const char*)response_start,
"\r\n\r\n");
/* 每次只处理一条响应 */
if(NULL != response_end)
{
*response_end = '\0';
}
/* 1. 检查是否有正在发送的命令 */
if (true == client->cmd_in_progress)
{
com_status = at_process_command_response(client, response_start);
/* 没有处理完继续检查urc */
if(true == client->cmd_in_progress)
{
at_process_urc(client, response_start);
}
}
/* 2. 检查URC */
else
{
at_process_urc(client, response_start);
}
/* 没有响应退出 */
if(response_end == NULL)
break;
/* 恢复原数据 */
*response_end = '\r';
/* 移动响应指针 */
response_start = response_end + 2;
response_end = NULL;
}while(1);
if(true == client->cmd_in_progress)
{
debug_println("接收响应超时");
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_TIMEOUT;
}
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return com_status;
}
/**
* @brief AT服务任务
*
* @param arg 创建任务时传递的参数
*
* @return 无
*/
void at_service_task(void* arg)
{
at_client_t* client = (at_client_t*)arg;
// while(1)
// {
memset(client->uart_config.rx_buf,
0,
client->uart_config.rx_buf_size);
client->uart_config.rx_len = 0;
#ifdef USE_FREERTOS
/* 等待数据接收完成 */
xSemaphoreTake(client->xBinarySemaphorRecvMsg, pdMAX_DELAY);
#endif
/* 接收数据 */
if(COM_OK != client->uart_recv_data(client->uart_config.uart_port,
client->uart_config.rx_buf,
&client->uart_config.rx_len))
{
// continue;
return;
}
// debug_println("uart_recv_data: %s", client->uart_config.rx_buf);
if (AT_MODE_GENERAL == client->at_mode)
{
/* 普通模式处理 */
at_process_general(client);
client->cmd_in_progress = false;
}
else
{
/* 透传模式处理 */
if (client->pass_through_param.data_cb)
{
client->pass_through_param.data_cb(client);
}
}
// }
}
/**
* @brief AT命令发送
*
* @param client AT客户端实例
* @param at_cmd_param_t AT命令参数
* @param retries 重试次数
*
* @return 是否发送成功
*/
com_status_t at_cmd_send(at_client_t* client)
{
#ifdef USE_FREERTOS
/* 获取互斥锁 */
xSemaphoreTake(client->xATControlMutex, pdMAX_DELAY);
#endif
/* 检查参数 */
if(NULL == client)
{
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_ERROR;
}
if(AT_MODE_GENERAL != client->at_mode)
return COM_ERROR;
/* 检查是否已有命令在执行 */
if (true == client->cmd_in_progress)
{
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_BUSY;
}
client->cmd_in_progress = true;
/* 清空接收缓存 */
client->uart_config.rx_len = 0;
memset(client->uart_config.rx_buf,
0,
client->uart_config.rx_buf_size);
do
{
#ifdef USE_FREERTOS
vTaskDelay(300);
#else
Com_delay_ms(300);
#endif
/* 发送命令 */
if(COM_OK != client->uart_send_data(client->uart_config.uart_port,
(const uint8_t*)client->cmd_param.cmd,
strlen((const char*)client->cmd_param.cmd)))
{
continue;
}
/* 等待响应 */
#ifdef USE_FREERTOS
if(pdTRUE != xSemaphoreTake(client->xBinarySemaphorRecvMsg,
client->cmd_param.timeout))
{
vTaskDelay(300);
continue;
}
#endif
Com_delay_ms(client->cmd_param.timeout);
/* 接收响应 */
if(COM_OK != client->uart_recv_data(client->uart_config.uart_port,
client->uart_config.rx_buf,
&client->uart_config.rx_len))
{
continue;
}
/* 处理响应 */
if(COM_OK == at_process_general(client))
{
break;
}
debug_println("retry...%d", client->cmd_param.retries);
} while (--client->cmd_param.retries);
/* 命令处理完成 */
client->cmd_in_progress = false;
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
if(client->cmd_param.retries > 0)
return COM_OK;
else
return COM_ERROR;
}
/**
* @brief 注册URC实现
*
* @param client AT客户端实例
* @param entry URC条目
*
* @return 是否注册成功
*/
com_status_t at_register_urc(at_client_t* client,
urc_entry_t *entry)
{
urc_entry_t* urc_entry = NULL;
#ifdef USE_FREERTOS
/* 获取互斥锁 */
xSemaphoreTake(client->xATControlMutex, pdMAX_DELAY);
#endif
/* 检查参数 */
if (NULL == client
|| NULL == entry
|| NULL == entry->prefix
|| NULL == entry->handler)
return COM_ERROR;
/* 检查是否已存在 */
for (size_t i = 0; i < client->urc_count; i++)
{
if (0 == memcmp(client->urc_table[i].prefix,
entry->prefix,
strlen((const char*)client->urc_table[i].prefix)))
{
/* 存在则更新 */
client->urc_table[i].handler = entry->handler;
client->urc_table[i].context = entry->context;
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_OK;
}
}
/* 不存在则添加 */
if (client->urc_count < client->urc_table_size)
{
urc_entry = &client->urc_table[client->urc_count++];
urc_entry->prefix = entry->prefix;
urc_entry->handler = entry->handler;
urc_entry->context = entry->context;
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_OK;
}
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_ERROR;
}
/**
* @brief 进入透传模式实现
*
* @param client AT客户端实例
* @param param 透传参数
*
* @return 返回是否进入成功
*/
com_status_t at_enter_pass_through_mode(at_client_t* client,
at_pass_through_param_t* paramt)
{
#ifdef USE_FREERTOS
xSemaphoreTake(client->xATControlMutex, portMAX_DELAY);
#endif
/* 检查参数 */
if (NULL == client
|| NULL == paramt
|| NULL == paramt->data_cb
|| NULL == paramt->data_context)
{
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_ERROR;
}
client->at_mode = AT_MODE_PassThrough;
client->pass_through_param.data_cb = paramt->data_cb;
client->pass_through_param.data_context = paramt->data_context;
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_OK;
}
/**
* @brief 退出透传模式实现
*
* @param client AT客户端实例
*
* @return 无
*/
com_status_t at_exit_pass_through_mode(at_client_t* client)
{
#ifdef USE_FREERTOS
xSemaphoreTake(client->xATControlMutex, portMAX_DELAY);
#endif
/* 检查参数 */
if(NULL == client)
{
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_ERROR;
}
client->at_mode = AT_MODE_GENERAL;
client->pass_through_param.data_cb = NULL;
client->pass_through_param.data_context = NULL;
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_OK;
}
/**
* @brief 透传模式发送数据实现
*
* @param client AT客户端实例
* @param data 数据
* @param len 数据长度
*
* @return 返回是否发送成功
*/
com_status_t at_send_data(at_client_t* client,
const uint8_t* data,
size_t len)
{
com_status_t com_status = COM_ERROR;
#ifdef USE_FREERTOS
xSemaphoreTake(client->xATControlMutex, portMAX_DELAY);
#endif
/* 检查参数 */
if (NULL == client
|| NULL == data
|| 0 == len)
{
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return COM_ERROR;
}
/* 发送数据 */
if (AT_MODE_PassThrough == client->at_mode)
com_status = client->uart_send_data(client->uart_config.uart_port,
data,
strlen((const char*)data));
#ifdef USE_FREERTOS
xSemaphoreGive(client->xATControlMutex);
#endif
return com_status;
}
/**
* @brief 创建AT客户端实例
*
* @param uart_port UART端口
* @param default_timeout 默认超时时间
* @param rx_buf_size 接收缓冲区大小
* @param urc_table_size URC条目数量
*
* @return 返回AT客户端实例
*/
at_client_t* at_client_create(uint8_t uart_port,
size_t rx_buf_size,
size_t urc_table_size)
{
at_client_t* client = calloc(1, sizeof(at_client_t));
if (NULL == client)
return NULL;
/* 串口配置 */
client->uart_config.uart_port = uart_port;
client->uart_config.rx_buf_size = rx_buf_size;
client->uart_config.rx_buf = calloc(1, rx_buf_size);
/* 串口发送和接收方法 */
client->uart_send_data = NULL;
client->uart_recv_data = NULL;
/* 错误处理方法 */
client->error_handler = NULL;
/* 状态变量初始化 */
client->cmd_in_progress = false;
client->at_mode = AT_MODE_GENERAL;
/* 创建URC表 */
client->urc_table_size = urc_table_size;
client->urc_table = calloc(1,
client->urc_table_size * sizeof(urc_entry_t));
if (NULL == client->urc_table)
{
free(client->uart_config.rx_buf);
free(client);
return NULL;
}
client->urc_count = 0;
#ifdef USE_FREERTOS
/* 创建RTOS资源 */
client->xATControlMutex = xSemaphoreCreateMutex(); /* AT控制互斥锁 */
client->xBinarySemaphorRecvMsg = xSemaphoreCreateBinary(); /* 串口接收二值信号量 */
if (NULL == client->xATControlMutex)
{
free(client->uart_config.rx_buf);
free(client->urc_table);
free(client);
return NULL;
}
if (NULL == client->xBinarySemaphorRecvMsg)
{
vSemaphoreDelete(client->xMutexSendMsg);
free(client->uart_config.rx_buf);
free(client->urc_table);
free(client);
return NULL;
}
#endif
return client;
}
/**
* @brief 销毁AT客户端实例
*
* @param client AT客户端实例
*
* @return void
*/
void at_client_destroy(at_client_t* client)
{
#ifdef USE_FREERTOS
xSemaphoreTake(client->xATControlMutex, pdMAX_DELAY);
#endif
if (NULL == client)
return;
#ifdef USE_FREERTOS
/* 停止服务任务 */
if (NULL != client->task_handle)
{
vTaskDelete(client->task_handle);
client->task_handle = NULL;
}
#endif
#ifdef USE_FREERTOS
/* 释放RTOS资源 */
if(NULL != xATCotrolMutex)
vSemaphoreDelete(client->xATCotrolMutex);
if(NULL != xBinarySemaphorRecvMsg)
vSemaphoreDelete(client->xBinarySemaphorRecvMsg);
#endif
/* 释放接收缓冲区 */
if (NULL != client->uart_config.rx_buf)
free(client->uart_config.rx_buf);
/* 释放URC表 */
if (NULL != client->urc_table)
free(client->urc_table);
/* 释放实例 */
free(client);
}
/**
* @brief 启动AT服务任务
*
* @param client AT客户端实例
*
* @return 是否启动成功
*/
com_status_t at_client_start(at_client_t* client)
{
#ifdef USE_FREERTOS
BaseType_t result = pdFAIL;
xSemaphoreTake(client->xATControlMutex, pdMAX_DELAY);
if(NULL == client)
return COM_ERROR;
/* 创建服务任务 */
result = xTaskCreate(
at_service_task, /* 任务函数 */
"AT_Service", /* 任务名 */
configMINIMAL_STACK_SIZE * 4, /* 栈大小 */
client, /* 参数 */
tskIDLE_PRIORITY + 2, /* 优先级 */
&client->task_handle /* 任务句柄 */
);
if(pdPASS == result)
{
xSemaphoreGive(client->xATControlMutex);
return COM_OK;
}
else
{
xSemaphoreGive(client->xATControlMutex);
return COM_ERROR;
}
#endif
return COM_OK;
}
Com_at.h
#ifndef COM_AT_H
#define COM_AT_H
/* 用来启用匿名结构体 */
#pragma anon_unions
#ifdef USE_FREERTOS
#include "FreeRTOS.h"
#include "semphr.h"
#endif
#include "string.h"
#include "stdlib.h"
#include "stm32f1xx_hal.h"
#include "Com_Debug.h"
#include "com_config.h"
#include "Com_tool.h"
struct at_client;
/* 串口发送数据函数据 */
typedef com_status_t (*uart_send_data_t)(uint8_t uart_num,
const uint8_t* tx_data,
const uint16_t tx_data_len);
/* 串口接收数据函数据 */
typedef com_status_t (*uart_recv_data_t)(uint8_t uart_num,
uint8_t* rx_data,
size_t* rx_data_len);
/* 错误处理函数类型 */
typedef void (*error_handler_t)(uint8_t* response_line);
/* 响应解析函数类型 */
typedef com_status_t (*response_handler_t)(uint8_t* response_line,
void* output_param);
/* URC处理函数类型 */
typedef com_status_t (*urc_handler_t)(void* context,
const uint8_t* urc);
/* 透传数据接收回调类型 */
typedef void (*data_receive_cb_t)(void* context);
typedef enum
{
false = 0,
true = 1
} bool;
/* at接收模式 */
typedef enum
{
AT_MODE_GENERAL, /* 普通模式 */
AT_MODE_PassThrough /* 透传模式 */
} at_mode_t;
/* URC注册项 */
typedef struct
{
uint8_t* prefix; /* URC前缀 */
urc_handler_t handler; /* 处理函数 */
void* context; /* 上下文指针 */
} urc_entry_t;
/* UART配置参数 */
typedef struct
{
uint8_t uart_port; /* UART端口号 */
uint8_t* rx_buf; /* UART接收缓冲区 */
size_t rx_buf_size; /* UART接收缓冲区大小 */
size_t rx_len; /* 已接收长度 */
} uart_config_t;
/* AT命令参数 */
typedef struct
{
const uint8_t* cmd; /* 命令 */
const uint8_t* expect; /* 期望响应 */
uint32_t timeout; /* 接收超时时间 */
uint8_t retries; /* 重试次数 */
void* output; /* 输出参数 */
response_handler_t handler; /* 响应处理函数 */
} at_cmd_param_t;
/* AT 透传参数 */
typedef struct
{
data_receive_cb_t data_cb; /* 数据接收回调 */
void* data_context; /* 数据回调上下文 */
} at_pass_through_param_t;
/* AT客户端对象 */
typedef struct at_client
{
/* 串口配置参数 */
uart_config_t uart_config;
/* at 模式 */
at_mode_t at_mode;
/* 命令执行中标志 */
bool cmd_in_progress;
union
{
/* 命令参数 */
at_cmd_param_t cmd_param;
/* 透传参数 */
at_pass_through_param_t pass_through_param;
} ;
/* URC处理 */
urc_entry_t* urc_table; /* URC注册表 */
size_t urc_table_size; /* URC表大小 */
size_t urc_count; /* 已注册URC数量 */
/* RTOS资源 */
#ifdef USE_FREERTOS
SemaphoreHandle_t xATControlMutex; /* AT控制互斥锁 */
SemaphoreHandle_t xBinarySemaphorRecvMsg; /* 串口接收二值信号量 */
TaskHandle_t task_handle; /* 任务句柄 */
#endif
/* 串口发送数据 */
uart_send_data_t uart_send_data;
/* 串口接收数据 */
uart_recv_data_t uart_recv_data;
/* 错误处理 */
error_handler_t error_handler;
} at_client_t;
/**
* @brief AT命令发送
*
* @param client AT客户端实例
* @param at_cmd_param_t AT命令参数
* @param retries 重试次数
*
* @return 是否发送成功
*/
com_status_t at_cmd_send(at_client_t* client);
/**
* @brief 注册URC实现
*
* @param client AT客户端实例
* @param entry URC条目
*
* @return 是否注册成功
*/
com_status_t at_register_urc(at_client_t* client,
urc_entry_t *entry);
/**
* @brief 进入透传模式实现
*
* @param client AT客户端实例
* @param param 透传参数
*
* @return 返回是否进入成功
*/
com_status_t at_enter_pass_through_mode(at_client_t* client,
at_pass_through_param_t* paramt);
/**
* @brief 退出透传模式实现
*
* @param client AT客户端实例
*
* @return 无
*/
com_status_t at_exit_pass_through_mode(at_client_t* client);
/**
* @brief 透传模式发送数据实现
*
* @param client AT客户端实例
* @param data 数据
* @param len 数据长度
*
* @return 返回是否发送成功
*/
com_status_t at_send_data(at_client_t* client,
const uint8_t* data,
size_t len);
/**
* @brief 创建AT客户端实例
*
* @param uart_port UART端口
* @param default_timeout 默认超时时间
* @param rx_buf_size 接收缓冲区大小
* @param urc_table_size URC条目数量
*
* @return 返回AT客户端实例
*/
at_client_t* at_client_create(uint8_t uart_port,
size_t rx_buf_size,
size_t urc_table_size);
/**
* @brief 销毁AT客户端实例
*
* @param client AT客户端实例
*
* @return void
*/
void at_client_destroy(at_client_t* client);
/**
* @brief 启动AT服务任务
*
* @param client AT客户端实例
*
* @return 是否启动成功
*/
com_status_t at_client_start(at_client_t* client);
/**
* @brief AT服务任务
*
* @param arg 创建任务时传递的参数
*
* @return 无
*/
void at_service_task(void* arg);
#endif
3. Int_QS100.c
#include "Int_QS100.h"
/* onenet 网络通信套件实例标识 */
static uint8_t onenet_instance = 0xFF;
/* AT 命令表 */
static const at_cmd_t g_at_cmd_table[] =
{
// 索引 测试命令 设置命令 查询命令 执行命令 响应前缀 说明
{AT_CMD_RB, NULL, NULL, NULL, "AT+RB\r\n", "REBOOTING", "设备软重启" },
{AT_CMD_CGATT, "AT+CGATT=?\r\n", "AT+CGATT=%d\r\n", "AT+CGATT?\r\n", NULL, "+CGATT:", "PS附着/去附着" },
{AT_CMD_CSQ, "AT+CSQ=?\r\n", NULL, "AT+CSQ\r\n", NULL, "+CSQ:", "获得信号强度指示" },
{AT_CMD_ATE, NULL, "ATE1\r\n", NULL, NULL, "OK", "开启串口回显" },
{AT_CMD_COPS, "AT+COPS=?\r\n", "AT+COPS=%d,%d,\"%s\",%d\r\n", "AT+COPS?\r\n", NULL, "+COPS:", "运营商选择" },
{AT_CMD_CGDCONT, "AT+CGDCONT=?\r\n", "AT+CGDCONT=%d,\"%s\",\"%s\"\r\n", "AT+CGDCONT?\r\n" , NULL, "+CGDCONT:", "定义PDP上下文" },
{AT_CMD_CGACT, "AT+CGACT=?\r\n", "AT+CGACT=%d,%d\r\n", "AT+CGACT?\r\n", NULL, "+CGACT", "PDP上下文激活/去激活" },
{AT_CMD_CPIN, "AT+CPIN=?\r\n", "AT+CPIN=\"%s\"\r\n", "AT+CPIN?\r\n", NULL, "+CPIN:", "PIN码输入与管理" },
{AT_CMD_CEREG, "AT+CEREG=?\r\n", "AT+CEREG=%d\r\n", "AT+CEREG?\r\n", NULL, "+CEREG:", "EPS网络注册状态" },
{AT_CMD_NTSETID, NULL, "AT+NTSETID=1,%s\r\n", NULL, NULL, "OK", "设置IMEI号" },
{AT_CMD_NCCID, NULL, NULL, "AT+NCCID?\r\n", NULL, "+NCCID:", "查询SIM卡ID" },
{AT_CMD_CGSN, "AT+CGSN=?\r\n", NULL, "AT+CGSN=%d\r\n", NULL, "+CGSN:", "获取产品序列号" },
{AT_CMD_CIMI, NULL, NULL, "AT+CIMI\r\n", NULL, "+CIMI:", "获取IMSI号" },
{AT_CMD_NV, "AT+NV=?\r\n", "AT+NV=SET,%s,%s\r\n", "AT+NV=GET,%s\r\n", "AT+NV=SAVE\r\n", "REBOOTING", "NV参数动态配置" },
{AT_CMD_FASTOFF, "AT+FASTOFF=?\r\n", "AT+FASTOFF=%d\r\n", NULL, NULL, "OK", "快速断电" },
{AT_CMD_WORKLOCK, NULL, "AT+WORKLOCK=%d\r\n", "AT+WORKLOCK?\r\n", NULL, "+WORKLOCK:", "省电锁" },
{AT_CMD_CEDRXRDP, NULL, NULL, "AT+CEDRXRDP\r\n", NULL, "+CEDRXRDP:", "读取扩展DRX动态参数" },
{AT_CMD_NPTWEDRXS, "AT+NPTWEDRXS=?\r\n", "AT+NPTWEDRXS=%hhu,%hhu,%s,%s\r\n", "AT+NPTWEDRXS?\r\n", NULL, "+NPTWEDRXS:", "寻呼时间窗及eDRX设置" },
{AT_CMD_CPSMS, "AT+CPSMS=?\r\n", "AT+CPSMS=%d,,,%s,%s\r\n", "AT+CPSMS?\r\n", NULL, "+CPSMS:", "省电模式PSM设置" },
{AT_CMD_CRTDCP, "AT+CRTDCP=?\r\n", "AT+CRTDCP=%d\r\n", "AT+CRTDCP?\r\n", NULL, "+CRTDCP:", "下行数据主动上报设置" },
{AT_CMD_XNTP, NULL, "AT+XNTP=%s\r\n", NULL, NULL, "+XNTP:", "查询NTP时间" },
};
/* QS100 请求回调函数 */
static QS100_DISCOVER_callback gs_qs100_discover_callback = NULL;
static QS100_OBSERVE_callback gs_qs100_observe_callback = NULL;
static QS100_READ_callback gs_qs100_read_callback = NULL;
static QS100_WRITE_callback gs_qs100_write_callback = NULL;
static QS100_EXECUTE_callback gs_qs100_execute_callback = NULL;
static QS100_PARAMETER_callback gs_qs100_parameter_callback = NULL;
static QS100_EVENT_callback gs_qs100_event_callback = NULL;
static QS100_NPTWEDRXP_callback gs_qs100_nptwedrxp_callback = NULL;
static QS100_POWERON_callback gs_qs100_poweron_callback = NULL;
static QS100_SIMST_callback gs_qs100_simst_callback = NULL;
/**
* @brief 获取命令字符串
*
* @param cmd_index 命令索引
* @param cmd_type 命令类型
*
* @return 返回命令
*/
const uint8_t *get_at_cmd_string(at_cmd_index_t cmd_index, at_cmd_type_t cmd_type)
{
/* 超出命令范围退出 */
if(AT_CMD_MAX < cmd_index)
return NULL;
/* 根据命令类型返回相应的命令 */
switch (cmd_type)
{
case AT_CMD_TEST:
return g_at_cmd_table[cmd_index].testCmd;
case AT_CMD_SET:
return g_at_cmd_table[cmd_index].setCmd;
case AT_CMD_READ:
return g_at_cmd_table[cmd_index].readCmd;
case AT_CMD_EXECUTE:
return g_at_cmd_table[cmd_index].executeCmd;
default:
return NULL;
}
}
/**
* @brief 获取命令前缀
*
* @param cmd_index 命令索引
*
* @return 命令前缀
*/
const uint8_t *get_at_response_prefix(at_cmd_index_t cmd_index)
{
/* 超出命令范围退出 */
if(AT_CMD_MAX < cmd_index)
return NULL;
/* 返回命令前缀 */
return NULL;
}
/**
* @brief QS100 错误处理函数
*
* @param response_line 错误响应行
*
* @retval 无
*/
static void error_handler(uint8_t* response_line)
{
debug_println("err: %s", response_line);
}
/**
* @brief QS100 将PTW转换为二进制字符串
*
* @param PTW 寻呼时间窗口
*
* @retval 返回ptw字符串
*/
const uint8_t* PTW_to_bin_str(PTW_t ptw)
{
static const uint8_t* bin_strings[] =
{
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
};
return bin_strings[ptw];
}
/**
* @brief QS100 将eDRX转换为二进制字符串
*
* @param cycle eDRX周期
*
* @retval 返回eDRX字符串
*/
const uint8_t* eDRX_to_bin_str(eDRX_cycle_t cycle)
{
static const uint8_t* bin_strings[] =
{
[EDRX_CYCLE_20_48_S] = "0010",
[EDRX_CYCLE_40_96_S] = "0011",
[EDRX_CYCLE_81_92_S] = "0101",
[EDRX_CYCLE_163_84_S] = "1001",
[EDRX_CYCLE_327_68_S] = "1010",
[EDRX_CYCLE_655_36_S] = "1011",
[EDRX_CYCLE_1310_72_S] = "1100",
[EDRX_CYCLE_2621_44_S] = "1101",
[EDRX_CYCLE_5242_88_S] = "1110",
[EDRX_CYCLE_10485_76_S] = "1111"
};
return bin_strings[cycle];
}
/**
* @brief QS100 获取onenet 实例标识
*
* @param 无
*
* @retval 返回实例标识
*/
uint8_t QS100_get_onenet_instance(void)
{
return onenet_instance;
}
/**
* @brief QS100 通用响应解析
*
* @param response_line 响应行
* @param output_param 返回响应参数
*
* @retval 返回处理结果
*/
static com_status_t general_response_handler(uint8_t* response_line,
void* output_param)
{
if(NULL != strstr((char*)response_line,
QS100_RESPONSE_OK))
{
debug_println("接收:%s.", response_line);
return COM_OK;
}
else if(NULL != strstr((char*)response_line,
QS100_RESPONSE_ERROR))
{
debug_println("响应错误:%s", response_line);
return COM_ERROR;
}
else
{
debug_println("正在接收:%s", response_line);
return COM_TIMEOUT;
}
}
/**
* @brief QS100 打印响应处理
*
* @param response_line 响应行
* @param output_param 返回响应参数
*
* @retval 返回处理结果
*/
static com_status_t print_response_handler(uint8_t* response_line,
void* output_param)
{
if(NULL != response_line)
debug_println("响应:%s", response_line);
return COM_OK;
}
/**
* @brief QS100 处理重启命令响应
*
* @param response 响应行
* @param output_param 返回响应参数
*
* @retval 返回处理结果
*/
static com_status_t REBOOTING_response_handler(uint8_t* response_line,
void* output_param)
{
debug_println("重启成功");
return COM_OK;
}
/**
* @brief QS100 处理保存命令响应
*
* @param response_line 响应行
* @param output_param 返回响应参数
*
* @retval 返回处理结果
*/
static com_status_t NV_SAVE_response_handler(uint8_t* response_line,
void* output_param)
{
debug_println("保存成功");
return COM_OK;
}
/**
* @brief QS100 处理查询信号强度命令响应
*
* @param response_line 响应行
* @param output_param 返回响应参数
*
* @retval 返回查询结果
*/
static com_status_t CSQ_response_handler(uint8_t* response_line,
void* output_param)
{
if(NULL == output_param)
return COM_ERROR;
debug_println("信号强度:%s", response_line);
/* 信号强度为99说明没有信号 */
if(1 == sscanf((char*)response_line,
QS100_RESPONSE_CSQ, (uint8_t*)output_param))
return COM_OK;
else
return COM_TIMEOUT;
}
/**
* @brief QS100 处理查询是否有网络
*
* @param response_line 响应行
* @param output_param 返回响应参数
*
* @retval 返回处理结果
*/
static com_status_t CGATT_response_handler(uint8_t* response_line,
void* output_param)
{
if(NULL == output_param)
return COM_ERROR;
debug_println("网络附着:%s", response_line);
if(1 == sscanf((const char*)response_line,
QS100_RESPONSE_CGATT,
(uint8_t*)output_param))
{
// debug_println("已连接网络 %d", *(uint8_t*)output_param);
return COM_OK;
}
else
return COM_ERROR;
}
/**
* @brief QS100 处理创建onenet通信套件响应
*
* @param response_line 响应行
* @param output_param 返回响应参数
*
* @retval 返回处理结果
*/
static com_status_t MIPLCREATE_response_handler(uint8_t* response_line,
void* output_param)
{
debug_println("网络通信套件:%s", response_line);
if(1 != sscanf((const char*)response_line,
QS100_RESPONSE_MIPLCREATE,
&onenet_instance))
return COM_TIMEOUT;
debug_println("onenet_instance:%d", onenet_instance);
return COM_OK;
}
/**
* @brief QS100 处理 LIFETIME 命令响应
*
* @param response_line 响应行
* @param output_param 返回响应参数
*
* @retval 返回处理结果
*/
static com_status_t LIFETIME_response_handler(uint8_t* response_line,
void* output_param)
{
uint32_t* lifetime = NULL;
if(NULL == output_param)
{
return COM_ERROR;
}
lifetime = (uint32_t*)output_param;
if(1 != sscanf((const char*)response_line,
QS100_RESPONSE_ONETRMLFT,
lifetime))
return COM_ERROR;
debug_println("lifetime:%d ", *lifetime);
return COM_OK;
}
/**
* @brief QS100 处理 DISCOVER URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t MIPLDISCOVER_request_handler(void* context,
const uint8_t* urc)
{
discover_response_t discover_response;
debug_println("DISCOVER URC:%s", urc);
if(3 != sscanf((const char*)urc,
QS100_RESPONSE_MIPLDISCOVER,
&discover_response.base.ref,
&discover_response.base.msgid,
&discover_response.base.path.objectid))
return COM_ERROR;
if(discover_response.base.ref == onenet_instance)
{
debug_println("instance:%d, "
"msgid:%d, "
"objectid:%d",
discover_response.base.ref,
discover_response.base.msgid,
discover_response.base.path.objectid);
}
if(NULL != gs_qs100_discover_callback)
gs_qs100_discover_callback(&discover_response);
return COM_OK;
}
/**
* @brief QS100 处理 OBSERVE URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t MIPLOBSERVE_request_handler(void* context,
const uint8_t* urc)
{
observe_response_t observe_response;
debug_println("OBSERVE URC:%s", urc);
if(6 != sscanf((const char*)urc,
QS100_RESPONSE_MIPLOBSERVE,
&observe_response.base.ref,
&observe_response.base.msgid,
&observe_response.flag,
&observe_response.base.path.objectid,
&observe_response.base.path.instanceid,
&observe_response.base.path.resourceid))
return COM_ERROR;
if(observe_response.base.ref == onenet_instance)
{
debug_println("instance:%d, "
"msgid:%d, "
"falg:%d, "
"objectid:%d, "
"instanceid:%d, "
"resourceid:%d",
observe_response.base.ref,
observe_response.base.msgid,
observe_response.flag,
observe_response.base.path.objectid,
observe_response.base.path.instanceid,
observe_response.base.path.resourceid);
}
if(NULL != gs_qs100_observe_callback)
gs_qs100_observe_callback(&observe_response);
return COM_OK;
}
/**
* @brief QS100 处理 READ URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t MIPLREAD_request_handler(void* context,
const uint8_t* urc)
{
read_response_t read_response;
debug_println("READ URC:%s", urc);
if(5 != sscanf((const char*)urc,
QS100_RESPONSE_MIPLREAD,
&read_response.base.ref,
&read_response.base.msgid,
&read_response.base.path.objectid,
&read_response.base.path.instanceid,
&read_response.base.path.resourceid))
return COM_ERROR;
if(read_response.base.ref == onenet_instance)
{
debug_println("instance:%d, "
"msgid:%d, "
"objectid:%d, "
"instanceid:%d, "
"resourceid:%d",
read_response.base.ref,
read_response.base.msgid,
read_response.base.path.objectid,
read_response.base.path.instanceid,
read_response.base.path.resourceid);
}
if(NULL != gs_qs100_read_callback)
gs_qs100_read_callback(&read_response);
return COM_OK;
}
/**
* @brief QS100 处理 WRITE URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t MIPLWRITE_request_handler(void* context,
const uint8_t* urc)
{
write_response_t write_response;
void* response_data = NULL;
uint8_t* filling_str = NULL; /* 填充字符串 */
/* 获取数据类型和数据长度 */
if(1 != sscanf((const char*)urc,
"%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%hhu,%hu",
&write_response.valuetype,
&write_response.len))
return COM_ERROR;
/* 根据发送类型选择填充字符串和发送数据 */
switch (write_response.valuetype)
{
case LWM2M_TYPE_STRING:
response_data = calloc(1, write_response.len + 1);
write_response.data_t.str_type = response_data;
if(NULL == write_response.data_t.str_type)
filling_str = QS100_RESPONSE_MIPLWRITE_STR_IGNORE;
else
filling_str = QS100_RESPONSE_MIPLWRITE_STR_CAPTURE;
break;
case LWM2M_TYPE_OPAQUE:
response_data = calloc(1, write_response.len * 2 + 1);
write_response.data_t.opaque_type = response_data;
if(NULL == write_response.data_t.opaque_type)
filling_str = QS100_RESPONSE_MIPLWRITE_OPAQUE_IGNORE;
else
filling_str = QS100_RESPONSE_MIPLWRITE_OPAQUE_CAPTURE;
break;
case LWM2M_TYPE_INTEGER:
response_data = calloc(1, write_response.len + 1);
filling_str = QS100_CMD_MIPLREADRSP_INT;
write_response.data_t.int_type = response_data;
break;
case LWM2M_TYPE_FLOAT:
response_data = calloc(1, write_response.len + 1);
filling_str = QS100_CMD_MIPLREADRSP_FLOAT;
write_response.data_t.float_type = response_data;
break;
case LWM2M_TYPE_BOOL:
response_data = calloc(1, write_response.len + 1);
filling_str = QS100_CMD_MIPLREADRSP_BOOL;
write_response.data_t.bool_type = response_data;
break;
default:
free(response_data);
response_data = NULL;
debug_println("数据类型错误:%d", write_response.valuetype);
return COM_ERROR;
}
if(NULL == response_data
&& 9 != sscanf((const char*)urc,
(const char*)filling_str,
&write_response.base.ref,
&write_response.base.msgid,
&write_response.base.path.objectid,
&write_response.base.path.instanceid,
&write_response.base.path.resourceid,
&write_response.valuetype,
&write_response.len,
&write_response.flag,
&write_response.index))
{
free(response_data);
response_data = NULL;
return COM_ERROR;
}
else if(NULL != response_data
&& 10 != sscanf((const char*)urc,
(const char*)filling_str,
&write_response.base.ref,
&write_response.base.msgid,
&write_response.base.path.objectid,
&write_response.base.path.instanceid,
&write_response.base.path.resourceid,
&write_response.valuetype,
&write_response.len,
(char*)response_data,
&write_response.flag,
&write_response.index))
{
free(response_data);
response_data = NULL;
return COM_ERROR;
}
if(write_response.base.ref == onenet_instance)
{
debug_println("instance:%d, "
"msgid:%d, "
"objectid:%d, "
"instanceid:%d, "
"resourceid:%d, "
"valuetype:%d, "
"len:%d, "
// "value:%s, "
"flag:%d, "
"index:%d",
write_response.base.ref,
write_response.base.msgid,
write_response.base.path.objectid,
write_response.base.path.instanceid,
write_response.base.path.resourceid,
write_response.valuetype,
write_response.len,
// write_response.data_t.str_t,
write_response.flag,
write_response.index);
}
if(NULL != gs_qs100_write_callback)
{
free(response_data);
response_data = NULL;
gs_qs100_write_callback(&write_response);
return COM_OK;
}
else
{
free(response_data);
response_data = NULL;
return COM_OK;
}
}
/**
* @brief QS100 处理 EXECUTE URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t EXECUTE_request_handler(void* context,
const uint8_t* urc)
{
execute_response_t execute_response;
debug_println("EXECUTE URC:%s", urc);
if(NULL == execute_response.arguments
&& 6 != sscanf((const char*)urc,
QS100_RESPONSE_MIPLEXECUTE_IGNORE,
&execute_response.base.ref,
&execute_response.base.msgid,
&execute_response.base.path.objectid,
&execute_response.base.path.instanceid,
&execute_response.base.path.resourceid,
&execute_response.len))
return COM_ERROR;
else if(NULL != execute_response.arguments
&& 7 != sscanf((const char*)urc,
QS100_RESPONSE_MIPLEXECUTE_CAPTURE,
&execute_response.base.ref,
&execute_response.base.msgid,
&execute_response.base.path.objectid,
&execute_response.base.path.instanceid,
&execute_response.base.path.resourceid,
&execute_response.len,
execute_response.arguments))
return COM_ERROR;
if(execute_response.base.ref == onenet_instance)
{
debug_println("instance:%d, "
"msgid:%d, "
"objectid:%d, "
"instanceid:%d, "
"resourceid:%d"
"len:%d",
// "arguments:%s"
execute_response.base.ref,
execute_response.base.msgid,
execute_response.base.path.objectid,
execute_response.base.path.instanceid,
execute_response.base.path.resourceid,
execute_response.len);
}
if(NULL != gs_qs100_execute_callback)
gs_qs100_execute_callback(&execute_response);
return COM_OK;
}
/**
* @brief QS100 处理 PARAMETER URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t PARAMETER_request_handler(void* context,
const uint8_t* urc)
{
parameter_response_t parameter_response;
debug_println("PARAMETER URC:%s", urc);
if(NULL == parameter_response.parameter
&& 6 != sscanf((const char*)urc,
QS100_RESPONSE_MIPLPARAMETER_IGNORE,
¶meter_response.base.ref,
¶meter_response.base.msgid,
¶meter_response.base.path.objectid,
¶meter_response.base.path.instanceid,
¶meter_response.base.path.resourceid,
¶meter_response.len))
return COM_ERROR;
if(NULL != parameter_response.parameter
&& 7 != sscanf((const char*)urc,
QS100_RESPONSE_MIPLPARAMETER_CAPTURE,
¶meter_response.base.ref,
¶meter_response.base.msgid,
¶meter_response.base.path.objectid,
¶meter_response.base.path.instanceid,
¶meter_response.base.path.resourceid,
¶meter_response.len,
parameter_response.parameter))
return COM_ERROR;
if(parameter_response.base.ref == onenet_instance)
{
debug_println("instance:%d, "
"msgid:%d, "
"objectid:%d, "
"instanceid:%d, "
"resourceid:%d"
"len:%d",
// "parameter:%s"
parameter_response.base.ref,
parameter_response.base.msgid,
parameter_response.base.path.objectid,
parameter_response.base.path.instanceid,
parameter_response.base.path.resourceid,
parameter_response.len);
}
if(NULL != gs_qs100_parameter_callback)
gs_qs100_parameter_callback(¶meter_response);
return COM_OK;
}
/**
* @brief QS100 处理 EVENT URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t EVENT_request_handler(void* context,
const uint8_t* urc)
{
event_response_t event_response;
debug_println("EVENT URC:%s", urc);
if(2 != sscanf((const char*)urc,
QS100_RESPONSE_MIPLEVENT,
&event_response.ref,
&event_response.evtid))
return COM_ERROR;
if(event_response.ref == onenet_instance)
{
debug_println("instance:%d, "
"evtid:%d, ",
event_response.ref,
event_response.evtid);
}
if(NULL != gs_qs100_event_callback)
gs_qs100_event_callback(&event_response);
return COM_OK;
}
/**
* @brief QS100 处理 NPTWEDRXP URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t NPTWEDRXP_response_handler(void* context,
const uint8_t* urc)
{
nptwedrxp_response_t nptwedrxp_response;
debug_println("NPTWEDRXP URC:%s", urc);
if(5 != sscanf((const char*)urc,
QS100_RESPONSE_NPTWEDRXP,
&nptwedrxp_response.AcT_type,
(char*)nptwedrxp_response.requested_PTW,
(char*)nptwedrxp_response.requested_eDRX_value,
(char*)nptwedrxp_response.eDRX_value,
(char*)nptwedrxp_response.PTW))
return COM_ERROR;
debug_println("AcT_type:%d, "
"requested_PTW:%s, "
"requested_eDRX_value:%s, "
"eDRX_value:%s, "
"PTW:%s",
nptwedrxp_response.AcT_type,
nptwedrxp_response.requested_PTW,
nptwedrxp_response.requested_eDRX_value,
nptwedrxp_response.eDRX_value,
nptwedrxp_response.PTW
);
if(NULL != gs_qs100_nptwedrxp_callback)
gs_qs100_nptwedrxp_callback(&nptwedrxp_response);
return COM_OK;
}
/**
* @brief QS100 处理 POWERON URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t POWERON_response_handler(void* context,
const uint8_t* urc)
{
uint8_t status = 0;
debug_println("POWERON URC:%s", urc);
if(1 != sscanf((const char*)urc,
QS100_RESPONSE_POWERON,
&status))
return COM_ERROR;
debug_println("status:%d, ", status);
if(NULL != gs_qs100_poweron_callback)
gs_qs100_poweron_callback(status);
return COM_OK;
}
/**
* @brief QS100 处理 SIMST URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t SIMST_response_handler(void* context,
const uint8_t* urc)
{
uint8_t status = 0;
debug_println("SIMST URC:%s", urc);
if(1 != sscanf((const char*)urc,
QS100_RESPONSE_SIMST,
&status))
return COM_ERROR;
debug_println("status:%d, ", status);
if(NULL != gs_qs100_simst_callback)
gs_qs100_simst_callback(status);
return COM_OK;
}
/**
* @brief QS100 处理串口回显 URC
*
* @param context 上下文指针
* @param urc 设备主动上报的消息
*
* @retval 返回处理结果
*/
static com_status_t ECHO_response_handler(void* context,
const uint8_t* urc)
{
debug_println("串口回显:%s", urc);
return COM_OK;
}
/**
* @brief QS100 唤醒
*
* @param 无
*
* @retval 无
*/
void Int_QS100_wakeup(void)
{
QS100_WAKEUP_H;
Com_delay_s(1);
QS100_WAKEUP_L;
Com_delay_s(1);
}
/**
* @brief QS100 重启
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_reset(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_RB, AT_CMD_EXECUTE);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_RB);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = REBOOTING_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 打开串口回显
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_ATE(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_ATE, AT_CMD_SET);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_ATE);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = general_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 设置IMEI
*
* @param imei IMEI
* @param imei IMEI 号
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_set_IMEI(at_client_t* client,
uint8_t *imei)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
if(NULL == imei)
return COM_ERROR;
snprintf((char*)cmd,
sizeof(cmd),
(const char*)get_at_cmd_string(AT_CMD_NTSETID, AT_CMD_SET),
imei);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = get_at_response_prefix(AT_CMD_NTSETID);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = general_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询信号强度
*
* @param client at 客户端句柄
* @param rssi 返回信号强度
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CSQ(at_client_t* client,
uint8_t* rssi)
{
if(NULL == rssi)
return COM_ERROR;
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CSQ, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CSQ);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = rssi;
client->cmd_param.handler = CSQ_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询运营商
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_COPS(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_COPS, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_COPS);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询 PDP 上下文
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CGDCONT(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CGDCONT, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CGDCONT);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 设置 PDP 上下文
*
* @param client at 客户端句柄
* @param pdp PDP 参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_set_CGDCONT(at_client_t* client,
PDP_t *pdp)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
if(NULL == pdp)
return COM_ERROR;
snprintf((char*)cmd,
sizeof(cmd),
(const char*)get_at_cmd_string(AT_CMD_CGDCONT, AT_CMD_SET),
pdp->cid,
pdp->PDP_type,
pdp->APN);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 激活/断开 PDP 上下文
*
* @param client at 客户端句柄
* @param pdp pdp 参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_set_CGACT(at_client_t* client,
PDP_t *pdp)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
if(NULL == pdp)
return COM_ERROR;
snprintf((char*)cmd,
sizeof(cmd),
(const char*)get_at_cmd_string(AT_CMD_CGACT, AT_CMD_SET),
pdp->status,
pdp->cid);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询是否需要输入pin码
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CPIN(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CPIN, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CPIN);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询网络注册状态
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CEREG(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CEREG, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CEREG);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询SIM卡ID
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_NCCID(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_NCCID, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_NCCID);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询IMEI号
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_IMEI(at_client_t* client)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
(const char*)get_at_cmd_string(AT_CMD_CGSN, AT_CMD_READ),
1);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CGSN);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询IMSI号
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_IMSI(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CIMI, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CIMI);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 保存NV
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_execute_NV_SAVE(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_NV, AT_CMD_EXECUTE);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_NV);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = NV_SAVE_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询是否有网络
*
* @param client at 客户端句柄
* @param attach 返回网络附着状态
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CGATT(at_client_t* client,
uint8_t* attach)
{
if(NULL == attach)
return COM_ERROR;
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CGATT, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CGATT);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = attach;
client->cmd_param.handler = CGATT_response_handler;
return at_cmd_send(client);
}
/**
* @brief 查询省电锁
*
* @param client at 客户端句柄
*
* @retval 返回查询结果
*/
com_status_t Int_QS100_query_WORKLOCK(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_WORKLOCK, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_WORKLOCK);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief 设置省电锁
*
* @param client at 客户端句柄
* @param switch_mode 省电锁状态
*
* @retval 返回查询结果
*/
com_status_t Int_QS100_set_WORKLOCK(at_client_t* client,
uint8_t switch_mode)
{
uint8_t cmd[32];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
(const char*)get_at_cmd_string(AT_CMD_WORKLOCK, AT_CMD_SET),
switch_mode);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief 查询扩展 DRX 动态参数
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CEDRXRDP(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CEDRXRDP, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CEDRXRDP);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief 查询寻呼时间窗及 eDRX
*
* @param client at 客户端句柄
*
* @retval 返回查询结果
*/
com_status_t Int_QS100_query_NPTWEDRXS(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_NPTWEDRXS, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_NPTWEDRXS);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief 设置寻呼时间窗及 eDRX
*
* @param client at 客户端句柄
*
* @retval 返回设置结果
*/
com_status_t Int_QS100_set_eDRX(at_client_t* client,
eDRX_t eDRX)
{
uint8_t cmd[32];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
(const char*)get_at_cmd_string(AT_CMD_NPTWEDRXS, AT_CMD_SET),
eDRX.mode,
QS100_EDRX_NB_S1_MODE,
eDRX.PTW,
eDRX.eDRX_value);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
if(COM_OK == at_cmd_send(client))
{
return Int_QS100_execute_NV_SAVE(client);
}
return COM_ERROR;
}
/**
* @brief 查询 PSM 参数
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CPSMS(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CPSMS, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CPSMS);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief 设置 PSM
*
* @param client at 客户端句柄
*
* @retval 返回设置结果
*/
com_status_t Int_QS100_set_PSM(at_client_t* client,
PSM_t PSM)
{
uint8_t cmd[32];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
(const char*)get_at_cmd_string(AT_CMD_CPSMS, AT_CMD_SET),
PSM.mode,
PSM.T3412_time,
PSM.T3324_time);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
if(COM_OK == at_cmd_send(client))
{
debug_println("Int_QS100_NV_SAVE");
return Int_QS100_execute_NV_SAVE(client);
}
debug_println("Int_QS100_PSM_CONFIG failed");
return COM_ERROR;
}
/**
* @brief QS100 查询主动上报下行数据
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CRTDCP(at_client_t* client)
{
client->cmd_param.cmd = get_at_cmd_string(AT_CMD_CRTDCP, AT_CMD_READ);
client->cmd_param.expect = get_at_response_prefix(AT_CMD_CRTDCP);
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 设置主动上报下行数据
*
* @param client at 客户端句柄
* @param reporting 是否主动上报下行数据
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_set_CRTDCP(at_client_t* client,
uint8_t reporting)
{
uint8_t cmd[32];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
(const char*)get_at_cmd_string(AT_CMD_CRTDCP, AT_CMD_SET),
reporting);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询onenet通讯套件版本号
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_NV_MIPLVER(at_client_t* client)
{
client->cmd_param.cmd = QS100_CMD_NV_MIPLVER;
client->cmd_param.expect = QS100_RESPONSE_PREFIX_MIPLVER;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 创建onenet通讯套件
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLCREATE(at_client_t* client)
{
client->cmd_param.cmd = QS100_CMD_MIPLSTART;
client->cmd_param.expect = QS100_RESPONSE_PREFIX_MIPLCREATE;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = MIPLCREATE_response_handler;
if(COM_OK != at_cmd_send(client))
{
uint8_t cmd[512];
memset(cmd, 0, sizeof(cmd));
/* 命令参数:
配置文件总长度
配置文件
配置文件序号(可以将配置文件分为多次发送)
当前指令配置文件长度
消息标志 0: 最后一条消息 1: 第一条消息 2: 中间消息 */
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLCREATE,
strlen(QS100_CONFIG) / 2,
QS100_CONFIG,
0,
strlen(QS100_CONFIG) / 2,
0);
// debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_PREFIX_MIPLCREATE;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = MIPLCREATE_response_handler;
return at_cmd_send(client);
}
return COM_OK;
}
/**
* @brief QS100 删除onenet通讯套件
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLDELETE(at_client_t* client)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
/* 命令参数:
实例标识 */
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLDELETE,
onenet_instance);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 增加 LwM2M 实例
*
* @param client at 客户端句柄
* @param mipladdob_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLADDOB(at_client_t* client,
mipladdob_cmd_t mipladdob_cmd)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLADDOB,
onenet_instance,
mipladdob_cmd.objectid,
mipladdob_cmd.instancecount,
mipladdob_cmd.instancebitmap,
mipladdob_cmd.attributecount,
mipladdob_cmd.actioncount);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = general_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 删除 LwM2M 实例
*
* @param client at 客户端句柄
* @param objectid 对象id
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLDELOBJ(at_client_t* client,
uint16_t objectid)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLDELOBJ,
onenet_instance,
objectid);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 发起注册请求
*
* @param client at 客户端句柄
* @param lifetime 生命周期
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLOPEN(at_client_t* client,
uint16_t lifetime)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
/* 命令参数:
实例标识
生命周期 最少120s*/
if(lifetime < 120)
lifetime = 3000;
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLOPEN,
onenet_instance,
lifetime);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 发送注销请求
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLCLOSE(at_client_t* client)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
/* 命令参数:
实例标识 */
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLCLOSE,
onenet_instance);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 Discover请求的响应
*
* @param client at 客户端句柄
* @param discover_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLDISCOVERRSP(at_client_t* client,
discoverrsp_cmd_t discover_cmd)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLDISCOVERRSP,
onenet_instance,
discover_cmd.msgid,
discover_cmd.result,
discover_cmd.length,
discover_cmd.valuestring);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 Observe请求的响应
*
* @param client at 客户端句柄
* @param observersp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLOBSERVERSP(at_client_t* client,
observersp_cmd_t observersp_cmd)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLOBSERVERSP,
onenet_instance,
observersp_cmd.msgid,
observersp_cmd.result);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 Read 请求的响应
*
* @param client at 客户端句柄
* @param readrsp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLREADRSP(at_client_t* client,
readrsp_cmd_t readrsp_cmd)
{
uint8_t cmd[380];
uint8_t* filling_str = NULL; /* 填充字符串 */
void* value = NULL; /* 数据指针 */
uint16_t len = 0; /* 数据长度 */
memset(cmd, 0, sizeof(cmd));
/* 最多发送160字节数据 */
if(LWM2M_READ_DATA_MAX_LEN < readrsp_cmd.len)
return COM_ERROR;
/* 根据发送类型选择填充字符串和发送数据 */
switch (readrsp_cmd.valuetype)
{
case LWM2M_TYPE_STRING:
filling_str = QS100_CMD_MIPLREADRSP_STR;
value = readrsp_cmd.data_t.str_type;
len = readrsp_cmd.len;
break;
case LWM2M_TYPE_OPAQUE:
filling_str = QS100_CMD_MIPLREADRSP_OPAQUE;
value = readrsp_cmd.data_t.opaque_type;
len = readrsp_cmd.len * 2;
break;
case LWM2M_TYPE_INTEGER:
filling_str = QS100_CMD_MIPLREADRSP_INT;
value = (void*)&readrsp_cmd.data_t.int_type;
len = readrsp_cmd.len;
break;
case LWM2M_TYPE_FLOAT:
filling_str = QS100_CMD_MIPLREADRSP_FLOAT;
value = (void*)&readrsp_cmd.data_t.float_type;
len = readrsp_cmd.len;
break;
case LWM2M_TYPE_BOOL:
filling_str = QS100_CMD_MIPLREADRSP_BOOL;
value = (void*)&readrsp_cmd.data_t.bool_type;
len = readrsp_cmd.len;
break;
default:
debug_println("数据类型错误:%d", readrsp_cmd.valuetype);
return COM_ERROR;
}
snprintf((char*)cmd,
sizeof(cmd),
(const char*)filling_str,
onenet_instance,
readrsp_cmd.base.msgid,
readrsp_cmd.result,
readrsp_cmd.base.path.objectid,
readrsp_cmd.base.path.instanceid,
readrsp_cmd.base.path.resourceid,
readrsp_cmd.valuetype,
readrsp_cmd.len,
len,
(uint8_t*)value,
0,
MSG_FLAG_LAST);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 Write请求的响应
*
* @param client at 客户端句柄
* @param writersp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLWRITERSP(at_client_t* client,
writersp_cmd_t writersp_cmd)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLWRITERSP,
onenet_instance,
writersp_cmd.msgid,
writersp_cmd.result);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 Execute 请求的响应
*
* @param client at 客户端句柄
* @param executersp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLEXECUTERSP(at_client_t* client,
executersp_cmd_t executersp_cmd)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLEXECUTERSP,
onenet_instance,
executersp_cmd.msgid,
executersp_cmd.result);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 PARAMETERRSP 请求的响应
*
* @param client at 客户端句柄
* @param parameterrsp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLPARAMETERRSP(at_client_t* client,
parameterrsp_cmd_t parameterrsp_cmd)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLPARAMETERRSP,
onenet_instance,
parameterrsp_cmd.msgid,
parameterrsp_cmd.result);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 Notify 数据到 ONENET 云端
*
* @param client at 客户端句柄
* @param notify_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLNOTIFY(at_client_t* client,
notify_cmd_t notify_cmd)
{
/* QS100 notify ackid */
static uint16_t ackid = 100;
uint8_t cmd[350];
uint8_t* filling_str = NULL; /* 填充字符串 */
void* value = NULL; /* 数据指针 */
uint16_t data_len = 0; /* 数据长度 */
uint8_t cmd_index = 0; /* 指令序号 */
uint8_t cmd_flag = 0; /* 数据标志 */
uint16_t notify_max_len = 0; /* 最大数据长度 */
uint8_t i = 1;
memset(cmd, 0, sizeof(cmd));
switch (notify_cmd.valuetype)
{
case LWM2M_TYPE_STRING:
filling_str = QS100_CMD_MIPLNOTIFY_STR;
value = notify_cmd.data_t.str_type;
notify_max_len = LWM2M_NOTIFY_DATA_MAX_LEN;
data_len = notify_cmd.len;
break;
case LWM2M_TYPE_OPAQUE:
filling_str = QS100_CMD_MIPLNOTIFY_OPAQUE;
value = notify_cmd.data_t.opaque_type;
notify_max_len = LWM2M_NOTIFY_DATA_MAX_LEN * 2;
data_len = notify_cmd.len * 2;
break;
case LWM2M_TYPE_INTEGER:
filling_str = QS100_CMD_MIPLNOTIFY_INT;
value = (void*)¬ify_cmd.data_t.int_type;
notify_max_len = LWM2M_NOTIFY_DATA_MAX_LEN;
data_len = notify_cmd.len;
break;
case LWM2M_TYPE_FLOAT:
filling_str = QS100_CMD_MIPLNOTIFY_FLOAT;
value = (void*)¬ify_cmd.data_t.float_type;
notify_max_len = LWM2M_NOTIFY_DATA_MAX_LEN;
data_len = notify_cmd.len;
break;
case LWM2M_TYPE_BOOL:
filling_str = QS100_CMD_MIPLNOTIFY_BOOL;
value = (void*)¬ify_cmd.data_t.bool_type;
notify_max_len = LWM2M_NOTIFY_DATA_MAX_LEN;
data_len = notify_cmd.len;
break;
default:
debug_println("数据类型错误:%d", notify_cmd.valuetype);
return COM_ERROR;
}
/* 获取指令序号 */
cmd_index = (data_len > notify_max_len) ? (data_len / notify_max_len) : 0;
cmd_flag = MSG_FLAG_FIRST;
for(i = 0; i < cmd_index; i++)
{
snprintf((char*)cmd,
sizeof(cmd),
(const char*)filling_str,
onenet_instance,
notify_cmd.base.msgid,
notify_cmd.base.path.objectid,
notify_cmd.base.path.instanceid,
notify_cmd.base.path.resourceid,
notify_cmd.valuetype,
LWM2M_NOTIFY_DATA_MAX_LEN,
notify_max_len,
(uint8_t*)value + i * notify_max_len,
cmd_index - i,
cmd_flag,
ackid);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = general_response_handler;
if(COM_OK != at_cmd_send(client))
return COM_ERROR;
memset(cmd, 0, sizeof(cmd));
cmd_flag = MSG_FLAG_MIDDLE;
data_len -= notify_max_len;
}
cmd_flag = MSG_FLAG_LAST;
snprintf((char*)cmd,
sizeof(cmd),
(const char*)filling_str,
onenet_instance,
notify_cmd.base.msgid,
notify_cmd.base.path.objectid,
notify_cmd.base.path.instanceid,
notify_cmd.base.path.resourceid,
notify_cmd.valuetype,
notify_cmd.len - i * LWM2M_NOTIFY_DATA_MAX_LEN,
notify_max_len - i * notify_max_len,
(uint8_t*)value + i * notify_max_len,
0,
MSG_FLAG_LAST,
ackid);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = general_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 发送更新请求
*
* @param client at 客户端句柄
* @param lifetime 更新的 lifetime 值(0:为默认24小时,最短120s)
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLUPDATE(at_client_t* client,
uint16_t lifetime)
{
uint8_t cmd[64];
memset(cmd, 0, sizeof(cmd));
snprintf((char*)cmd,
sizeof(cmd),
QS100_CMD_MIPLUPDATE,
onenet_instance,
lifetime,
0);
debug_println("%s", cmd);
client->cmd_param.cmd = cmd;
client->cmd_param.expect = QS100_RESPONSE_OK;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = NULL;
client->cmd_param.handler = print_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 查询当前 ONENET 剩余 LIFETIME 时间
*
* @param client at 客户端句柄
* @param lifetime 返回剩余时间
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_ONETRMLFT(at_client_t* client,
uint32_t *lifetime)
{
client->cmd_param.cmd = QS100_CMD_ONETRMLFT;
client->cmd_param.expect = QS100_RESPONSE_ONETRMLFT;
client->cmd_param.retries = 10;
client->cmd_param.timeout = 500;
client->cmd_param.output = lifetime;
client->cmd_param.handler = LIFETIME_response_handler;
return at_cmd_send(client);
}
/**
* @brief QS100 注册 URC
*
* @param client at 客户端句柄
*
* @retval 无
*/
static com_status_t Int_QS100_reg_urc(at_client_t* client)
{
urc_entry_t entry ;
com_status_t com_status = COM_ERROR;
entry.handler = MIPLDISCOVER_request_handler;
entry.prefix = QS100_URC_MIPLDISCOVER;
entry.context = NULL;
com_status = at_register_urc(client, &entry);
if(COM_OK == com_status)
{
entry.handler = MIPLOBSERVE_request_handler;
entry.prefix = QS100_URC_MIPLOBSERVE;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = MIPLREAD_request_handler;
entry.prefix = QS100_URC_MIPLREAD;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = MIPLWRITE_request_handler;
entry.prefix = QS100_URC_MIPLWRITE;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = EXECUTE_request_handler;
entry.prefix = QS100_URC_MIPLEXECUTE;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = PARAMETER_request_handler;
entry.prefix = QS100_URC_MIPLPARAMETER;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = EVENT_request_handler;
entry.prefix = QS100_URC_MIPLEVENT;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = NPTWEDRXP_response_handler;
entry.prefix = QS100_URC_NPTWEDRXP;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = POWERON_response_handler;
entry.prefix = QS100_URC_POWERON;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = SIMST_response_handler;
entry.prefix = QS100_URC_SIMST;
com_status = at_register_urc(client, &entry);
}
if(COM_OK == com_status)
{
entry.handler = ECHO_response_handler;
entry.prefix = QS100_URC_ECHO;
com_status = at_register_urc(client, &entry);
}
return com_status;
}
/**
* @brief QS100 初始化
*
* @param 无
*
* @retval 无
*/
at_client_t* Int_QS100_init(void)
{
at_client_t* client = NULL;
/* 创建串口客户端 */
client = at_client_create(
QS100_UART_NUM,
QS100_RX_BUF_SIZE,
AT_URC_TABLE_LEN);
if(NULL == client)
debug_println("QS100 创建失败");
/* 串口数据发送和接收函数注册 */
client->uart_send_data = uart_send_data;
client->uart_recv_data = uart_recv_data;
/* 错误处理函数注册 */
client->error_handler = error_handler;
/* 注册 URC */
Int_QS100_reg_urc(client);
/* 重启 */
if(COM_OK != Int_QS100_reset(client))
debug_println("QS100 重启失败");
/* 打开串口回显 */
// if(COM_OK != Int_QS100_ATE(client))
// debug_println("QS100 串口回显打开失败");
return client;
}
/**
* @brief QS100 模块任务
*
* @param client at 客户端句柄
*
* @retval 无
*/
void Int_QS100_task(at_client_t* client)
{
at_service_task(client);
}
/**
* @brief QS100 基础命令测试
*
* @param client at 客户端句柄
*
* @retval 无
*/
void Int_QS100_test(at_client_t* client)
{
uint8_t rssi = 0;
uint8_t attach = 0;
/* QS100 设置IMEI测试 */
// if(COM_OK != Int_QS100_set_IMEI(client, QS100_IMEI))
// debug_println("QS100 设置IMEI失败");
Com_delay_s(1);
/* QS100 查询信号强度测试 */
if(COM_OK != Int_QS100_query_CSQ(client, &rssi))
debug_println("QS100 查询信号强度失败");
Com_delay_s(1);
/* QS100 查询运营商测试 */
if(COM_OK != Int_QS100_query_COPS(client))
debug_println("QS100 查询运营商失败");
Com_delay_s(1);
/* QS100 查询APN设置测试 */
if(COM_OK != Int_QS100_query_CGDCONT(client))
debug_println("QS100 查询APN设置失败");
Com_delay_s(1);
/* QS100 查询是否需要输入pin码测试 */
if(COM_OK != Int_QS100_query_CPIN(client))
debug_println("QS100 查询PIN码状态失败");
Com_delay_s(1);
/* QS100 查询网络注册状态测试 */
if(COM_OK != Int_QS100_query_CEREG(client))
debug_println("QS100 查询网络注册状态失败");
Com_delay_s(1);
/* QS100 查询SIM卡ID测试 */
if(COM_OK != Int_QS100_query_NCCID(client))
debug_println("QS100 查询SIM卡ID失败");
Com_delay_s(1);
/* QS100 获取IMEI号测试 */
if(COM_OK != Int_QS100_query_IMEI(client))
debug_println("QS100 获取IMEI号失败");
Com_delay_s(1);
/* QS100 获取IMSI号测试 */
if(COM_OK != Int_QS100_query_IMSI(client))
debug_println("QS100 获取IMSI号失败");
Com_delay_s(1);
/* QS100 查询onenet通讯套件版本号测试 */
if(COM_OK != Int_QS100_query_NV_MIPLVER(client))
debug_println("QS100 查询onenet通讯套件版本号失败");
Com_delay_s(1);
// /* QS100 保存NV测试 */
// // if(COM_OK != Int_QS100_NV_SAVE(client))
// // debug_println("QS100 保存NV失败");
// // Com_delay_s(1);
/* QS100 查看使用有网络测试 */
if(COM_OK != Int_QS100_query_CGATT(client, &attach))
debug_println("QS100 查询网络附着状态失败");
Com_delay_s(1);
}
/**
* @brief 注册QS100 DISCOVER 事件回调函数
*
* @param callback DISCOVER 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_DISCOVER_callback(QS100_DISCOVER_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_discover_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 OBSERVE 事件回调函数
*
* @param callback OBSERVE 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_OBSERVE_callback(QS100_OBSERVE_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_observe_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 READ 事件回调函数
*
* @param callback READ 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_READ_callback(QS100_READ_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_read_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 WRITE 事件回调函数
*
* @param callback WRITE 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_WRITE_callback(QS100_WRITE_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_write_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 EXECUTE 事件回调函数
*
* @param callback EXECUTE 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_EXECUTE_callback(QS100_EXECUTE_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_execute_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 PARAMETER 事件回调函数
*
* @param callback PARAMETER 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_PARAMETER_callback(QS100_PARAMETER_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_parameter_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 EVENT 事件回调函数
*
* @param callback EVENT 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_EVENT_callback(QS100_EVENT_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_event_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 NPTWEDRXP 事件回调函数
*
* @param callback NPTWEDRXP事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_NPTWEDRXP_callback(QS100_NPTWEDRXP_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_nptwedrxp_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 POWERON 事件回调函数
*
* @param callback POWERON 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_POWERON_callback(QS100_POWERON_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_poweron_callback = callback;
return COM_OK;
}
/**
* @brief 注册QS100 SIMST 事件回调函数
*
* @param callback SIMST 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_SIMST_callback(QS100_SIMST_callback callback)
{
if (callback == NULL)
return COM_ERROR;
gs_qs100_simst_callback = callback;
return COM_OK;
}
Int_QS100.h
#ifndef INT_QS100_H
#define INT_QS100_H
#include <stdio.h>
#include "stdlib.h"
#include "stm32f1xx_hal.h"
#include "usart.h"
#include "gpio.h"
#include "dma.h"
#include "Com_at.h"
#include "Int_QS100_cmd_def.h"
/* QS100串口接收缓冲区大小 */
#define QS100_RX_BUF_SIZE UART_BUFFER_SIZE
/* QS100串口号 */
#define QS100_UART_NUM UART_NUM_3
/* URC表大小 */
#define AT_URC_TABLE_LEN 20
/* QS100 IMEI */
#define QS100_IMEI "13245678912344"
/* QS100 onenet配置文件 */
#define QS100_CONFIG "130040f10003f2003204001100000000"\
"00000000123138332e3233302e34302e"\
"34303a35363833000f41757468436f64"\
"653a3b50534b3a3bf30008e400c80000"
/* 发送最大重试次数 */
#define QS100_TX_MAX_RETRIES 10
/* 接收最大重试次数 */
#define QS100_RX_MAX_RETRIES 10
/* LwM2M read 数据最大长度 */
#define LWM2M_READ_DATA_MAX_LEN 150
/* LwM2M notify 数据最大长度 */
#define LWM2M_NOTIFY_DATA_MAX_LEN 500
/* EDRX 接入技术类型 */
#define QS100_EDRX_NB_S1_MODE 5
/* wakeup引脚操作 */
#define QS100_WAKEUP_L HAL_GPIO_WritePin(QS100_WAKEUP_GPIO_Port, QS100_WAKEUP_Pin, GPIO_PIN_RESET)
#define QS100_WAKEUP_H HAL_GPIO_WritePin(QS100_WAKEUP_GPIO_Port, QS100_WAKEUP_Pin, GPIO_PIN_SET)
/* AT命令表大小 */
#define AT_CMD_TABLE_SIZE (sizeof(g_at_cmd_table) / sizeof(g_at_cmd_table[0]))
/* onenet 相关命令 */
#define QS100_CMD_NV_MIPLVER "AT+MIPLVER?\r\n" /* 查询onenet通讯套件版本号 */
#define QS100_CMD_MIPLCREATE "AT+MIPLCREATE=%d,%s,%d,%d,%d\r\n" /* 创建onenet通讯套件 */
#define QS100_CMD_MIPLSTART "AT+MIPLCREATE\r\n" /* 启动onenet通讯套件 */
#define QS100_CMD_MIPLDELETE "AT+MIPLDELETE=%d\r\n" /* 删除onenet通讯套件 */
#define QS100_CMD_MIPLADDOB "AT+MIPLADDOBJ=%d,%d,%d,\"%s\",%d,%d\r\n" /* 增加 LwM2M 实例 */
#define QS100_CMD_MIPLDELOBJ "AT+MIPLDELOBJ=%d,%d\r\n" /* 删除 LwM2M 实例 */
#define QS100_CMD_MIPLOPEN "AT+MIPLOPEN=%d,%d\r\n" /* 发起注册请求 */
#define QS100_CMD_MIPLCLOSE "AT+MIPLCLOSE=%d\r\n" /* 发送注销请求 */
#define QS100_CMD_MIPLDISCOVERRSP "AT+MIPLDISCOVERRSP=%d,%d,%d,%d,\"%s\"\r\n" /* Discover请求的响应 */
#define QS100_CMD_MIPLOBSERVERSP "AT+MIPLOBSERVERSP=%d,%d,%d\r\n" /* Observe请求的响应 */
#define QS100_CMD_MIPLREADRSP_STR "AT+MIPLREADRSP=%d,%d,%d,%d,%d,%d,%d,%d,\"%.*s\",%d,%d\r\n" /* Read str请求的响应 */
#define QS100_CMD_MIPLREADRSP_OPAQUE "AT+MIPLREADRSP=%d,%d,%d,%d,%d,%d,%d,%d,%.*s,%d,%d\r\n" /* Read opaque请求的响应 */
#define QS100_CMD_MIPLREADRSP_INT "AT+MIPLREADRSP=%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n" /* Read int请求的响应 */
#define QS100_CMD_MIPLREADRSP_FLOAT "AT+MIPLREADRSP=%d,%d,%d,%d,%d,%d,%d,%d,%f,%d,%d\r\n" /* Read float请求的响应 */
#define QS100_CMD_MIPLREADRSP_BOOL "AT+MIPLREADRSP=%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n" /* Read bool请求的响应 */
#define QS100_CMD_MIPLWRITERSP "AT+MIPLWRITERSP=%d,%d,%d\r\n" /* Write请求的响应 */
#define QS100_CMD_MIPLEXECUTERSP "AT+MIPLEXECUTERSP=%d,%d,%d\r\n" /* Execute 请求的响应 */
#define QS100_CMD_MIPLPARAMETERRSP "AT+MIPLPARAMETERRSP=%d,%d,%d\r\n" /* Write 属性请求的响应 */
#define QS100_CMD_MIPLNOTIFY_STR "AT+MIPLNOTIFY=%d,%d,%d,%d,%d,%d,%d,\"%.*s\",%d,%d,%d\r\n" /* Notify 数据到 ONENET 云端 */
#define QS100_CMD_MIPLNOTIFY_OPAQUE "AT+MIPLNOTIFY=%d,%d,%d,%d,%d,%d,%d,%.*s,%d,%d,%d\r\n" /* Notify 数据到 ONENET 云端 */
#define QS100_CMD_MIPLNOTIFY_INT "AT+MIPLNOTIFY=%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n" /* Notify 数据到 ONENET 云端 */
#define QS100_CMD_MIPLNOTIFY_FLOAT "AT+MIPLNOTIFY=%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n" /* Notify 数据到 ONENET 云端 */
#define QS100_CMD_MIPLNOTIFY_BOOL "AT+MIPLNOTIFY=%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n" /* Notify 数据到 ONENET 云端 */
#define QS100_CMD_MIPLUPDATE "AT+MIPLUPDATE=%d,%d,%d\r\n" /* 发送更新请求 */
#define QS100_CMD_ONETRMLFT "AT+ONETRMLFT\r\n" /* 查询当前 ONENET 剩余 LIFETIME 时间 */
/* 通用响应解析 */
#define QS100_RESPONSE_CSQ "%*[^:]:%hhu" /* 查询信号强度 响应 */
#define QS100_RESPONSE_MIPLCREATE "%*[^:]:%hhu" /* 创建网络通信套件 响应 */
#define QS100_RESPONSE_NPTWEDRXP "%*[^:]:%hhu,\"%[^\"]\",\"%[^\"]\",\"%[^\"]\",\"%[^\"]\"" /* NPTWEDRXP 事件通知 */
#define QS100_RESPONSE_CGATT "%*[^:]:%hhu\r\n" /* 网络注册状态主动上报 */
#define QS100_RESPONSE_POWERON "%*[^:]:%hhu\r\n" /* 上电完成主动上报 */
#define QS100_RESPONSE_SIMST "%*[^:]:%hhu\r\n" /* SIM卡状态主动上报 */
/* onenet 响应格式 */
#define QS100_RESPONSE_ONETRMLFT "%*[^:]:%u\r\n" /* 查询当前 ONENET 剩余 LIFETIME 时间 */
#define QS100_RESPONSE_MIPLDISCOVER "%*[^:]:%hhu,%u,%hd\r\n" /* 主动上报Discover 请求 */
#define QS100_RESPONSE_MIPLOBSERVE "%*[^:]:%hhu,%u,%hhu,%hd,%hd,%hd\r\n" /* 主动上报 Observe 请求 */
#define QS100_RESPONSE_MIPLREAD "%*[^:]:%hhu,%u,%hd,%hd,%hd\r\n" /* 主动上报 Read 请求 */
#define QS100_RESPONSE_MIPLWRITE_STR_CAPTURE "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%hu,\"%s\",%hhu,%hhu\r\n" /* 主动上报 Write str请求 */
#define QS100_RESPONSE_MIPLWRITE_STR_IGNORE "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%hu,\"%*s\",%hhu,%hhu\r\n" /* 主动上报 Write str请求 获取数据长度 */
#define QS100_RESPONSE_MIPLWRITE_OPAQUE_CAPTURE "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%hu,%s,%hhu,%hhu\r\n" /* 主动上报 Write opaque请求 */
#define QS100_RESPONSE_MIPLWRITE_OPAQUE_IGNORE "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%hu,%*s,%hhu,%hhu\r\n" /* 主动上报 Write opaque请求 获取数据长度 */
#define QS100_RESPONSE_MIPLWRITE_INT "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%hu,%lld,%hhu,%hhu\r\n" /* 主动上报 Write int 获取数据长度 */
#define QS100_RESPONSE_MIPLWRITE_FLAOT "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%hu,%f,%hhu,%hhu\r\n" /* 主动上报 Write float 请求 */
#define QS100_RESPONSE_MIPLWRITE_BOOL "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%hu,%hhu,%hhu,%hhu\r\n" /* 主动上报 Write bool 请求 获取数据长度 */
#define QS100_RESPONSE_MIPLEXECUTE_CAPTURE "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%s\r\n" /* 主动上报 Execute 请求 */
#define QS100_RESPONSE_MIPLEXECUTE_IGNORE "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%*s\r\n" /* 主动上报 Execute 请求 获取数据长度 */
#define QS100_RESPONSE_MIPLPARAMETER_CAPTURE "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%s\r\n" /* 主动上报 Write 属性请求 */
#define QS100_RESPONSE_MIPLPARAMETER_IGNORE "%*[^:]:%hhu,%u,%hd,%hd,%hd,%hhu,%*s\r\n" /* 主动上报 Write 属性请求 获取数据长度 */
#define QS100_RESPONSE_MIPLEVENT "%*[^:]:%hhu,%hhu" /* 主动上报 EVENT 事件通知 */
/* 响应前缀 */
#define QS100_RESPONSE_OK "OK" /* 响应成功 */
#define QS100_RESPONSE_ERROR "ERROR" /* 响应失败 */
#define QS100_RESPONSE_PREFIX_MIPLCREATE "+MIPLCREATE:" /* 创创建 ONENET 通信套件实例 */
#define QS100_RESPONSE_PREFIX_MIPLVER "+MIPLVER:" /* 查询当前 ONENET 通信套件版本 */
/* 主动上报 URC */
#define QS100_URC_ECHO "AT+" /* 串口回显 */
#define QS100_URC_POWERON "+POWERON:" /* 上电完成主动上报 */
#define QS100_URC_SIMST "SIMST:" /* SIM卡状态主动上报 */
#define QS100_URC_MIPLDISCOVER "+MIPLDISCOVER:" /* 主动上报Discover */
#define QS100_URC_MIPLOBSERVE "+MIPLOBSERVE:" /* 主动上报 Observe */
#define QS100_URC_MIPLREAD "+MIPLREAD:" /* 主动上报 Read */
#define QS100_URC_MIPLWRITE "+MIPLWRITE:" /* 主动上报 Write */
#define QS100_URC_MIPLEXECUTE "+MIPLEXECUTE:" /* 主动上报 Execute */
#define QS100_URC_MIPLPARAMETER "+MIPLPARAMETER:" /* 主动上报 Write */
#define QS100_URC_MIPLEVENT "+MIPLEVENT:" /* 主动上报 EVENT */
#define QS100_URC_NPTWEDRXP "+NPTWEDRXP:" /* 主动上报 NPTWEDRXP */
/* AT命令结构体类型 */
typedef struct
{
uint16_t index; /* 命令在列表中的序号 */
const uint8_t *testCmd; /* 测试命令 AT+<X>=? */
const uint8_t *setCmd; /* 设置命令 AT+<X>=<...> */
const uint8_t *readCmd; /* 查询命令 AT+<X>? */
const uint8_t *executeCmd; /* 执行命令 AT+<X> */
const uint8_t *responsePrefix; /* 期望的响应前缀 */
const uint8_t *cmdInfor; /* 命令注释说明 */
} at_cmd_t;
/* AT命令类型 */
typedef enum
{
AT_CMD_TEST = 0, /* 测试命令 */
AT_CMD_SET, /* 设置命令 */
AT_CMD_READ, /* 查询命令 */
AT_CMD_EXECUTE /* 执行命令 */
} at_cmd_type_t;
/* AT命令索引 */
typedef enum
{
AT_CMD_RB = 0, /* 设备软重启 */
AT_CMD_CGATT, /* PS附着/去附着 */
AT_CMD_CSQ, /* 获得信号强度指示 */
AT_CMD_ATE, /* 开启串口回显 */
AT_CMD_COPS, /* 运营商选择 */
AT_CMD_CGDCONT, /* 定义PDP上下文 */
AT_CMD_CGACT, /* PDP上下文激活/去激活 */
AT_CMD_CPIN, /* PIN码输入与管理 */
AT_CMD_CEREG, /* EPS网络注册状态 */
AT_CMD_NTSETID, /* 设置IMEI号 */
AT_CMD_NCCID, /* 查询SIM卡ID */
AT_CMD_CGSN, /* 获取产品序列号 */
AT_CMD_CIMI, /* 获取IMSI号 */
AT_CMD_NV, /* NV参数动态配置 */
AT_CMD_FASTOFF, /* 快速断电 */
AT_CMD_WORKLOCK, /* 省电锁 */
AT_CMD_CEDRXRDP, /* 读取扩展DRX动态参数 */
AT_CMD_NPTWEDRXS, /* 寻呼时间窗及eDRX设置 */
AT_CMD_CPSMS, /* 省电模式PSM设置 */
AT_CMD_CRTDCP, /* 下行数据主动上报设置 */
AT_CMD_XNTP, /* 查询NTP时间 */
AT_CMD_MAX /* 命令总数,用于边界检查 */
} at_cmd_index_t;
/* onenet 事件类型 */
typedef enum
{
ONENET_EVENT_BOOTSTRAP_START = 1, /* 引导启动事件 */
ONENET_EVENT_BOOTSTRAP_SUCCESS, /* 引导成功 */
ONENET_EVENT_BOOTSTRAP_FAILED, /* 引导失败 */
ONENET_EVENT_CONNECT_SUCCESS, /* 连接成功 */
ONENET_EVENT_CONNECT_FAILED, /* 连接失败 */
ONENET_EVENT_REG_SUCCESS, /* 注册成功 */
ONENET_EVENT_REG_FAILED, /* 注册失败 */
ONENET_EVENT_REG_TIMEOUT, /* 注册超时 */
ONENET_EVENT_LIFETIME_TIMEOUT, /* 生命周期超时 */
ONENET_EVENT_STATUS_HALT, /* 状态停止 */
ONENET_EVENT_UPDATE_SUCCESS, /* 更新成功 */
ONENET_EVENT_UPDATE_FAILED, /* 更新失败 */
ONENET_EVENT_UPDATE_TIMEOUT, /* 更新超时 */
ONENET_EVENT_UPDATE_NEED, /* 需要更新 */
ONENET_EVENT_UNREG_DONE, /* 注销完成 */
ONENET_EVENT_RESPONSE_FAILED = 20, /* 响应失败 */
ONENET_EVENT_RESPONSE_SUCCESS, /* 响应成功 */
ONENET_EVENT_NOTIFY_FAILED = 25, /* 通知失败 */
ONENET_EVENT_NOTIFY_SUCCESS, /* 通知成功 */
ONENET_EVENT_MAX, /* 事件最大值 */
} onenet_event_t;
// /* 响应解析函数类型 */
// typedef com_status_t (*response_handler)(uint8_t* response,
// void* output_param);
/* 消息标识 */
typedef enum {
MSG_FLAG_LAST = 0, /* 最后一条消息 */
MSG_FLAG_FIRST = 1, /* 第一条消息 */
MSG_FLAG_MIDDLE = 2 /* 中间消息 */
} message_flag_t;
/* eDRX模式 */
typedef enum
{
EDRX_DISABLED = 0, /* 不使用eDRX */
EDRX_ENABLED = 1, /* 使用eDRX */
EDRX_ENABLED_WITH_REPORT = 2, /* 使用eDRX,当网络参数发生变化时主动上报 */
EDRX_DISABLED_WITH_RESET = 3 /* 不使用eDRX,且指令中其他参数值无效,
如果可以则直接将其他参数值恢复出厂值 */
} eDRX_mode_t;
/* PSM 模式 */
typedef enum
{
PSM_DISABLED = 0, /* 不使用PSM */
PSM_ENABLED = 1, /* 使用PSM */
PSM_RESTORE_DEFAULT = 2 /* 不使用PSM,且设置指令中其他参数值无效,
如果可以则直接将其他参数值恢复出厂值 */
} psm_mode_t;
/* PTW时间 */
typedef enum
{
PTW_2_56S = 0x00, /* 0000 */
PTW_5_12S = 0x01, /* 0001 */
PTW_7_68S = 0x02, /* 0010 */
PTW_10_24S = 0x03, /* 0011 */
PTW_12_80S = 0x04, /* 0100 */
PTW_15_36S = 0x05, /* 0101 */
PTW_17_92S = 0x06, /* 0110 */
PTW_20_48S = 0x07, /* 0111 */
PTW_23_04S = 0x08, /* 1000 */
PTW_25_60S = 0x09, /* 1001 */
PTW_28_16S = 0x0A, /* 1010 */
PTW_30_72S = 0x0B, /* 1011 */
PTW_33_28S = 0x0C, /* 1100 */
PTW_35_84S = 0x0D, /* 1101 */
PTW_38_40S = 0x0E, /* 1110 */
PTW_40_96S = 0x0F /* 1111 */
} PTW_t;
/* eDRX周期 */
typedef enum {
EDRX_CYCLE_20_48_S = 0x02, /* 0010 */
EDRX_CYCLE_40_96_S = 0x03, /* 0011 */
EDRX_CYCLE_81_92_S = 0x05, /* 0101 */
EDRX_CYCLE_163_84_S = 0x09, /* 1001 */
EDRX_CYCLE_327_68_S = 0x0A, /* 1010 */
EDRX_CYCLE_655_36_S = 0x0B, /* 1011 */
EDRX_CYCLE_1310_72_S = 0x0C, /* 1100 */
EDRX_CYCLE_2621_44_S = 0x0D, /* 1101 */
EDRX_CYCLE_5242_88_S = 0x0E, /* 1110 */
EDRX_CYCLE_10485_76_S= 0x0F /* 1111 */
} eDRX_cycle_t;
/* eDRX参数 */
typedef struct
{
eDRX_mode_t mode; /* eDRX模式 */
const uint8_t* PTW; /* PTW时间 */
const uint8_t* eDRX_value; /* eDRX周期 */
} eDRX_t;
/* PSM参数 */
typedef struct
{
psm_mode_t mode; /* PSM模式 */
const uint8_t* T3412_time; /* T3412时间 */
const uint8_t* T3324_time; /* T3324时间 */
} PSM_t;
/* PDP参数 */
typedef struct
{
uint8_t cid; /* PDP实例ID */
const uint8_t* PDP_type; /* 数据包交换协议类型 */
const uint8_t* APN; /* APN */
uint8_t status; /* PDP状态 */
} PDP_t;
/* LwM2M 增加实例 */
typedef struct
{
uint16_t objectid; /* 对象id */
uint8_t instancecount; /* 实例个数 */
uint8_t* instancebitmap; /* 实例位图 */
uint8_t attributecount; /* 属性个数 */
uint8_t actioncount; /* 操作个数 */
} mipladdob_cmd_t;
/* LwM2M 资源路径 */
typedef struct
{
int16_t objectid; /* 对象id */
int16_t instanceid; /* 实例id */
int16_t resourceid; /* 资源id */
} lwm2m_path_t;
/* 基础命令 */
typedef struct
{
uint8_t ref; /* 实例标识 */
uint32_t msgid; /* 消息id */
lwm2m_path_t path; /* lwm2m2m 资源路径 */
} cmd_base_t;
/* DISCOVERRSP 命令参数 */
typedef struct
{
uint32_t msgid; /* 消息id */
uint8_t result; /* 操作结果 */
uint8_t length; /* 返回 valuestring 的长度 */
uint8_t* valuestring; /* object 的属性要求,多个属性放置
双引号“”中,使用分号“;”隔开 */
} discoverrsp_cmd_t;
/* DISCOVER 命令参数 */
typedef struct
{
cmd_base_t base; /* 基础命令参数 */
} discover_response_t;
/* OBSERVERSP 命令参数 */
typedef struct
{
uint32_t msgid; /* 消息id */
uint8_t result; /* 操作结果 */
} observersp_cmd_t;
/* OBSERVE 命令参数 */
typedef struct
{
cmd_base_t base; /* 基础命令参数 */
uint8_t flag; /* 操作标志 */
} observe_response_t;
/* READRSP 命令参数 */
typedef struct
{
cmd_base_t base; /* 基础命令参数 */
uint8_t result; /* 操作结果 */
uint8_t valuetype; /* 发送的数据类型 */
uint16_t len; /* 发送的数据长度 */
union
{
int64_t int_type; /* 写入整型 */
uint8_t * opaque_type; /* 写入16进制数据 */
uint8_t* str_type; /* 写入字符串 */
float float_type; /* 写入浮点型 */
uint8_t bool_type; /* 写入布尔型 */
} data_t;
message_flag_t flag; /* 消息标志 */
uint8_t index; /* 指令序号(可以将一条消息分为多次发送)
则 index 从 N-1 至 0,
index 编号为 0 时表示本次指令结束 */
} readrsp_cmd_t;
/* READ 命令参数 */
typedef struct
{
cmd_base_t base; /* 基础命令参数 */
} read_response_t;
/* WRITERSP 命令参数 */
typedef struct
{
uint32_t msgid; /* 消息id */
uint8_t result; /* 操作结果 */
} writersp_cmd_t;
/* WRITE 命令参数 */
typedef struct
{
cmd_base_t base; /* 基础命令参数 */
uint8_t result; /* 操作结果 */
uint8_t valuetype; /* 写入的数据类型 */
uint16_t len; /* 写入的数据长度 */
union
{
int64_t* int_type; /* 写入整型 */
uint8_t * opaque_type; /* 写入16进制数据 */
uint8_t* str_type; /* 写入字符串 */
float* float_type; /* 写入浮点型 */
uint8_t* bool_type; /* 写入布尔型 */
} data_t;
message_flag_t flag; /* 消息标志 */
uint8_t index; /* 指令序号(可以将一条消息分为多次发送)
则 index 从 N-1 至 0,
index 编号为 0 时表示本次指令结束 */
} write_response_t;
/* EXECUTERSP 命令参数 */
typedef struct
{
uint32_t msgid; /* 消息id */
uint8_t result; /* 操作结果 */
} executersp_cmd_t;
/* EXECUTE 命令参数 */
typedef struct
{
cmd_base_t base; /* 基础命令参数 */
uint8_t len; /* 参数的字符长度 */
uint8_t* arguments; /* 执行的字符串格式参数 */
} execute_response_t;
/* PARAMETERRSP 命令参数 */
typedef struct
{
uint32_t msgid; /* 消息id */
uint8_t result; /* 操作结果 */
} parameterrsp_cmd_t;
/* PARAMETER 命令参数 */
typedef struct
{
cmd_base_t base; /* 基础命令参数 */
uint8_t len; /* 参数的字符长度 */
uint8_t* parameter; /* 策略参数 */
} parameter_response_t;
/* NOTIFY 命令参数 */
typedef struct
{
cmd_base_t base; /* 基础命令参数 */
uint8_t valuetype; /* 发送的数据类型 */
uint8_t len; /* 发送的数据长度 */
union
{
uint32_t int_type; /* 发送整型 */
uint8_t * opaque_type; /* 发送16进制数据 */
uint8_t* str_type; /* 发送字符串 */
float float_type; /* 发送浮点型 */
uint8_t bool_type; /* 发送布尔型 */
} data_t;
message_flag_t flag; /* 消息标志 */
uint8_t index; /* 指令序号(可以将一条消息分为多次发送)
则 index 从 N-1 至 0,
index 编号为 0 时表示本次指令结束 */
uint8_t ackid; /* 确认id */
} notify_cmd_t;
/* EVENT 命令参数 */
typedef struct
{
uint8_t ref; /* 实例标识 */
uint8_t evtid; /* 事件id */
uint16_t params; /* 参数 */
} event_response_t;
/* NPTWEDRXP 命令参数 */
typedef struct
{
uint8_t AcT_type; /* 接入技术类型 */
uint8_t requested_PTW[5]; /* 请求的PTW */
uint8_t requested_eDRX_value[5]; /* 请求的eDRX值 */
uint8_t PTW[5]; /* 实际的PTW */
uint8_t eDRX_value[5]; /* 实际的eDRX值 */
} nptwedrxp_response_t;
/* LWM2M 状态码 */
typedef enum
{
LWM2M_STATUS_OK_1 = 1, /* 2.05 Content - 操作正确完成 */
LWM2M_STATUS_OK_2 = 2, /* 2.04 Content - 操作正确完成 */
LWM2M_STATUS_BAD_REQUEST = 11, /* 4.00 Bad Request */
LWM2M_STATUS_UNAUTHORIZED = 12, /* 4.01 Unauthorized */
LWM2M_STATUS_NOT_FOUND = 13, /* 4.04 Not Found */
LWM2M_STATUS_METHOD_NOT_ALLOWED = 14, /* 4.05 Method Not Allowed */
LWM2M_STATUS_NOT_ACCEPTABLE = 15, /* 4.06 Not Acceptable */
} lwm2m_status_code_t;
/* LWM2M 数据类型 */
typedef enum
{
LWM2M_TYPE_STRING = 1, /* 字符串类型 */
LWM2M_TYPE_OPAQUE = 2, /* 不透明的二进制数据 */
LWM2M_TYPE_INTEGER = 3, /* 整数类型 */
LWM2M_TYPE_FLOAT = 4, /* 浮点数类型 */
LWM2M_TYPE_BOOL = 5, /* 布尔类型 */
} lwm2m_data_type_t;
/* 重启原因枚举 */
typedef enum
{
RESET_REASON_POWER_ON = 0, /* 正常的上电动作 */
RESET_REASON_PIN_RESET = 1, /* PIN 复位,供外部进行芯片的硬复位 */
RESET_REASON_SOFT_RESET = 2, /* 软重启功能 */
RESET_REASON_UTC_WAKEUP = 3, /* UTC 唤醒动作 */
RESET_REASON_EXT_PIN_WAKEUP = 4, /* 外部 PIN 唤醒,常与数据通信绑定 */
RESET_REASON_WDT_RESET = 5, /* 硬件看门狗重启 */
RESET_REASON_UNKNOWN = 6 /* 未知的异常重启,如电容放电不充分等 */
} reset_reason_t;
/* 卡状态枚举 */
typedef enum
{
CARD_STATUS_NO_CARD = 0, /* 无卡 */
CARD_STATUS_INIT_SUCCESS = 1, /* 开机上电或深睡唤醒,卡初始化成功 */
CARD_STATUS_DEEP_SLEEP_WAKE = 2 /* 深睡唤醒,未做卡初始化,
保持深睡前卡状态,
不支持深睡期间热插拔 */
} card_status_t;
/* QS100 DISCOVER 请求回调函数 */
typedef void (*QS100_DISCOVER_callback)(discover_response_t* discover_response);
/* QS100 OBSERVE 请求回调函数 */
typedef void (*QS100_OBSERVE_callback)(observe_response_t* observe_response);
/* QS100 READ 请求回调函数 */
typedef void (*QS100_READ_callback)(read_response_t* read_response);
/* QS100 WRITE 请求回调函数 */
typedef void (*QS100_WRITE_callback)(write_response_t* write_response);
/* QS100 EXECUTE 请求回调函数 */
typedef void (*QS100_EXECUTE_callback)(execute_response_t* execute_response);
/* QS100 PARAMETER 请求回调函数 */
typedef void (*QS100_PARAMETER_callback)(parameter_response_t* parameter_response);
/* QS100 EVENT 请求回调函数 */
typedef void (*QS100_EVENT_callback)(event_response_t* event_response);
/* QS100 NPTWEDRXP 请求回调函数 */
typedef void (*QS100_NPTWEDRXP_callback)(nptwedrxp_response_t* nptwedrxp_response);
/* QS100 POWERON 请求回调函数 */
typedef void (*QS100_POWERON_callback)(uint8_t status);
/* QS100 SIMST 请求回调函数 */
typedef void (*QS100_SIMST_callback)(uint8_t status);
/**
* @brief 获取命令字符串
*
* @param cmd_index 命令索引
* @param cmd_type 命令类型
*
* @return 返回命令
*/
const uint8_t *get_at_cmd_string(at_cmd_index_t cmd_index,
at_cmd_type_t cmd_type);
/**
* @brief 获取命令前缀
*
* @param cmd_index 命令索引
*
* @return 命令前缀
*/
const uint8_t *get_at_response_prefix(at_cmd_index_t cmd_index);
/**
* @brief QS100 将PTW转换为二进制字符串
*
* @param PTW 寻呼时间窗口
*
* @retval 返回ptw字符串
*/
const uint8_t* PTW_to_bin_str(PTW_t ptw);
/**
* @brief QS100 将eDRX转换为二进制字符串
*
* @param cycle eDRX周期
*
* @retval 返回eDRX字符串
*/
const uint8_t* eDRX_to_bin_str(eDRX_cycle_t cycle);
/**
* @brief QS100 获取onenet 实例标识
*
* @param 无
*
* @retval 返回实例标识
*/
uint8_t QS100_get_onenet_instance(void);
/**
* @brief QS100 唤醒
*
* @param 无
*
* @retval 无
*/
void Int_QS100_wakeup(void);
/**
* @brief QS100 重启
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_reset(at_client_t* client);
/**
* @brief QS100 打开串口回显
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_ATE(at_client_t* client);
/**
* @brief QS100 设置IMEI
*
* @param imei IMEI
* @param imei IMEI 号
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_set_IMEI(at_client_t* client,
uint8_t *imei);
/**
* @brief QS100 查询信号强度
*
* @param client at 客户端句柄
* @param rssi 返回信号强度
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CSQ(at_client_t* client,
uint8_t* rssi);
/**
* @brief QS100 查询运营商
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_COPS(at_client_t* client);
/**
* @brief QS100 查询 PDP 上下文
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CGDCONT(at_client_t* client);
/**
* @brief QS100 设置 PDP 上下文
*
* @param client at 客户端句柄
* @param pdp PDP 参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_set_CGDCONT(at_client_t* client,
PDP_t *pdp);
/**
* @brief QS100 激活/断开 PDP 上下文
*
* @param client at 客户端句柄
* @param pdp pdp 参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_set_CGACT(at_client_t* client,
PDP_t *pdp);
/**
* @brief QS100 查询是否需要输入pin码
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CPIN(at_client_t* client);
/**
* @brief QS100 查询网络注册状态
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CEREG(at_client_t* client);
/**
* @brief QS100 查询SIM卡ID
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_NCCID(at_client_t* client);
/**
* @brief QS100 查询IMEI号
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_IMEI(at_client_t* client);
/**
* @brief QS100 查询IMSI号
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_IMSI(at_client_t* client);
/**
* @brief QS100 保存NV
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_execute_NV_SAVE(at_client_t* client);
/**
* @brief QS100 查询是否有网络
*
* @param client at 客户端句柄
* @param attach 返回网络附着状态
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CGATT(at_client_t* client,
uint8_t* attach);
/**
* @brief 查询省电锁
*
* @param client at 客户端句柄
*
* @retval 返回查询结果
*/
com_status_t Int_QS100_query_WORKLOCK(at_client_t* client);
/**
* @brief 设置省电锁
*
* @param client at 客户端句柄
* @param switch_mode 省电锁状态
*
* @retval 返回查询结果
*/
com_status_t Int_QS100_set_WORKLOCK(at_client_t* client,
uint8_t switch_mode);
/**
* @brief 查询扩展 DRX 动态参数
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CEDRXRDP(at_client_t* client);
/**
* @brief 查询寻呼时间窗及 eDRX
*
* @param client at 客户端句柄
*
* @retval 返回查询结果
*/
com_status_t Int_QS100_query_NPTWEDRXS(at_client_t* client);
/**
* @brief 设置寻呼时间窗及 eDRX
*
* @param client at 客户端句柄
*
* @retval 返回设置结果
*/
com_status_t Int_QS100_set_eDRX(at_client_t* client,
eDRX_t eDRX);
/**
* @brief 查询 PSM 参数
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CPSMS(at_client_t* client);
/**
* @brief 设置 PSM
*
* @param client at 客户端句柄
*
* @retval 返回设置结果
*/
com_status_t Int_QS100_set_PSM(at_client_t* client,
PSM_t PSM);
/**
* @brief QS100 查询主动上报下行数据
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_CRTDCP(at_client_t* client);
/**
* @brief QS100 设置主动上报下行数据
*
* @param client at 客户端句柄
* @param reporting 是否主动上报下行数据
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_set_CRTDCP(at_client_t* client,
uint8_t reporting);
/**
* @brief QS100 查询onenet通讯套件版本号
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_query_NV_MIPLVER(at_client_t* client);
/**
* @brief QS100 创建onenet通讯套件
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLCREATE(at_client_t* client);
/**
* @brief QS100 删除onenet通讯套件
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLDELETE(at_client_t* client);
/**
* @brief QS100 增加 LwM2M 实例
*
* @param client at 客户端句柄
* @param mipladdob_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLADDOB(at_client_t* client,
mipladdob_cmd_t mipladdob_cmd);
/**
* @brief QS100 删除 LwM2M 实例
*
* @param client at 客户端句柄
* @param objectid 对象id
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLDELOBJ(at_client_t* client,
uint16_t objectid);
/**
* @brief QS100 发起注册请求
*
* @param client at 客户端句柄
* @param lifetime 生命周期
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLOPEN(at_client_t* client,
uint16_t lifetime);
/**
* @brief QS100 发送注销请求
*
* @param client at 客户端句柄
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLCLOSE(at_client_t* client);
/**
* @brief QS100 Discover请求的响应
*
* @param client at 客户端句柄
* @param discover_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLDISCOVERRSP(at_client_t* client,
discoverrsp_cmd_t discover_cmd);
/**
* @brief QS100 Observe请求的响应
*
* @param client at 客户端句柄
* @param observersp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLOBSERVERSP(at_client_t* client,
observersp_cmd_t observersp_cmd);
/**
* @brief QS100 Read 请求的响应
*
* @param client at 客户端句柄
* @param readrsp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLREADRSP(at_client_t* client,
readrsp_cmd_t readrsp_cmd);
/**
* @brief QS100 Write请求的响应
*
* @param client at 客户端句柄
* @param writersp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLWRITERSP(at_client_t* client,
writersp_cmd_t writersp_cmd);
/**
* @brief QS100 Execute 请求的响应
*
* @param client at 客户端句柄
* @param executersp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLEXECUTERSP(at_client_t* client,
executersp_cmd_t executersp_cmd);
/**
* @brief QS100 PARAMETERRSP 请求的响应
*
* @param client at 客户端句柄
* @param parameterrsp_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLPARAMETERRSP(at_client_t* client,
parameterrsp_cmd_t parameterrsp_cmd);
/**
* @brief QS100 Notify 数据到 ONENET 云端
*
* @param client at 客户端句柄
* @param notify_cmd 命令参数
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLNOTIFY(at_client_t* client,
notify_cmd_t notify_cmd);
/**
* @brief QS100 发送更新请求
*
* @param client at 客户端句柄
* @param lifetime 更新的 lifetime 值(0:为默认24小时,最短120s)
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_MIPLUPDATE(at_client_t* client,
uint16_t lifetime);
/**
* @brief QS100 查询当前 ONENET 剩余 LIFETIME 时间
*
* @param client at 客户端句柄
* @param lifetime 返回剩余时间
*
* @retval 返回执行结果
*/
com_status_t Int_QS100_ONETRMLFT(at_client_t* client,
uint32_t *lifetime);
/**
* @brief QS100 初始化
*
* @param 无
*
* @retval 无
*/
at_client_t* Int_QS100_init(void);
/**
* @brief QS100 模块任务
*
* @param client at 客户端句柄
*
* @retval 无
*/
void Int_QS100_task(at_client_t* client);
/**
* @brief QS100 基础命令测试
*
* @param client at 客户端句柄
*
* @retval 无
*/
void Int_QS100_test(at_client_t* client);
/**
* @brief 注册QS100 DISCOVER 事件回调函数
*
* @param callback DISCOVER 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_DISCOVER_callback(QS100_DISCOVER_callback callback);
/**
* @brief 注册QS100 OBSERVE 事件回调函数
*
* @param callback OBSERVE 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_OBSERVE_callback(QS100_OBSERVE_callback callback);
/**
* @brief 注册QS100 READ 事件回调函数
*
* @param callback READ 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_READ_callback(QS100_READ_callback callback);
/**
* @brief 注册QS100 WRITE 事件回调函数
*
* @param callback WRITE 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_WRITE_callback(QS100_WRITE_callback callback);
/**
* @brief 注册QS100 EXECUTE 事件回调函数
*
* @param callback EXECUTE 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_EXECUTE_callback(QS100_EXECUTE_callback callback);
/**
* @brief 注册QS100 PARAMETER 事件回调函数
*
* @param callback PARAMETER 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_PARAMETER_callback(QS100_PARAMETER_callback callback);
/**
* @brief 注册QS100 EVENT 事件回调函数
*
* @param callback EVENT 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_EVENT_callback(QS100_EVENT_callback callback);
/**
* @brief 注册QS100 NPTWEDRXP 事件回调函数
*
* @param callback NPTWEDRXP事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_NPTWEDRXP_callback(QS100_NPTWEDRXP_callback callback);
/**
* @brief 注册QS100 POWERON 事件回调函数
*
* @param callback POWERON 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_POWERON_callback(QS100_POWERON_callback callback);
/**
* @brief 注册QS100 SIMST 事件回调函数
*
* @param callback SIMST 事件处理函数
*
* @retval 注册是否成功
*/
com_status_t QS100_register_SIMST_callback(QS100_SIMST_callback callback);
#endif
4. 连接onenet
#define LWM2M_OBJECT_COUNT 1 /* 对象个数 */
#define LWM2M_INSTANCE_COUNT 1 /* 实例个数 */
#define LWM2M_RESOURCE_COUNT 2 /* 资源个数 */
#define LWM2M_OBJECT_UPLOAD_DATA 3300 /* 上传数据对象 */
#define LMM2M_RESOURCES_READ 5750 /* 读资源 id */
#define LMM2M_RESOURCES_WRITE 5701 /* 写资源 id */
/**
* @brief 连接onenet
*
* @param 无
*
* @retval 返回执行结果
*/
com_status_t App_connect_onenet(void)
{
uint8_t attach = 0;
do
{
if(COM_OK != Int_QS100_query_CGATT(client, &attach))
{
debug_println("QS100 网络附着失败");
return COM_ERROR;
}
Com_delay_ms(300);
} while (0 == attach);
/* 创建onenet通信套件 */
if(COM_OK != Int_QS100_MIPLCREATE(client))
{
debug_println("QS100 创建onenet通信套件失败");
return COM_ERROR;
}
/* 添加LwM2M实例 */
mipladdob_cmd_t mipladdob_cmd;
mipladdob_cmd.objectid = LWM2M_OBJECT_UPLOAD_DATA;
mipladdob_cmd.instancecount = LWM2M_INSTANCE_COUNT;
mipladdob_cmd.instancebitmap = instance_bitmap;
mipladdob_cmd.attributecount = LWM2M_RESOURCE_COUNT;
mipladdob_cmd.actioncount = 0;
if(COM_OK != Int_QS100_MIPLADDOB(client, mipladdob_cmd))
{
debug_println("QS100 添加LwM2M实例失败");
return COM_ERROR;
}
/* 发起注册请求 */
if(COM_OK != Int_QS100_MIPLOPEN(client, 3000))
{
debug_println("QS100 发起注册请求失败");
return COM_ERROR;
}
return COM_OK;
}
/**
* @brief 处理响应
*
* @param 无
*
* @retval 返回执行结果
*/
void App_response_handler(void)
{
extern volatile uint8_t timer_flag;
while(1)
{
if(timer_flag == 1)
{
timer_flag = 0;
App_locator_upload_data();
}
Int_QS100_task(client);
}
}
四. 遇到的问题及解决办法
1. QS100上必须插物联卡
2. 出现,发送AT+CGATT指令,显示未附着,没有网络连接。
发送AT+CSQ接收到+CSQ:99,0说明没有信号,可能是SIM卡不能使用或者模组刚上电需等待一会。
如果信号正常发送:
-
AT+CPIN?:查询是否需要输入pin码,如果接收不为READY,则SIM卡需要输入密码解锁,可根据命令手册5.1解锁 -
AT+COPS?: 查询运营商,查看是否和物联卡的运营商信息相同,查看卡是否正常PLMN 运营商 46000 中国移动 (GSM) 46001 中国联通 (GSM) 46002 中国移动 (TD-S) 46003 中国电信 (CDMA) 46005 中国电信 (CDMA) 46006 中国联通 (WCDMA) 46007 中国移动 (TD-S) 46008 中国移动 46009 中国联通 46011 中国电信 (FDD-LTE) -
AT+CEREG?: 查询网络注册状态,结果+CEREG:0,1第二位是否为1,如果为0说明没有网络连接,查看物联卡是否能使用 -
AT+NCCID?: 查询SIM卡ID,查看是否和SIM卡标识相同,如果识别不到,把卡拿出清理一下SIM卡接触点,如果还是识别不到换张卡再试试。
3. IMEI 查询全是0
使用这两个命令设置IMEI
/* QS100 设置IMEI */
if(COM_OK != Int_QS100_set_IMEI(client, QS100_IMEI))
debug_println("QS100 设置IMEI失败");
/* QS100 保存NV */
if(COM_OK != Int_QS100_execute_NV_SAVE(client))
debug_println("QS100 保存NV失败");
/* 重启 */
if(COM_OK != Int_QS100_reset(client))
debug_println("QS100 重启失败");
4. 创建onenet通信套件
第一次创建需要将先将配置文件写入NV中,可以直接使用代码中的配置文件无需修改。也可通过官方qq群中的这个文件夹生成配置文件,具体查看文件夹中readme文件,生成后替换掉代码中的配置文件。

/* QS100 onenet配置文件 */
#define QS100_CONFIG "130040f10003f2003204001100000000"\
"00000000123138332e3233302e34302e"\
"34303a35363833000f41757468436f64"\
"653a3b50534b3a3bf30008e400c80000"
if(COM_OK == Int_QS100_MIPLCREATE(client))
debug_println("QS100 创建onenet通信套件失败");
if(COM_OK != Int_QS100_execute_NV_SAVE(client))
debug_println("QS100 保存NV失败");
if(COM_OK != Int_QS100_reset(client))
debug_println("QS100 重启失败");
5.进入不了eDRX模式

可以问问卖卡的这个卡支不支持eDRX,换张支持的卡。
6. 上报数据错误
上报数据太长可能会发生平台收到数据而模式响应上报失败。所以notifi时要加上ackid,这样当上报成功或失败时平台也会下发一个event事件。
7. 平台下发数据是asscii码


浙公网安备 33010602011771号