398 lines
9.8 KiB
C
398 lines
9.8 KiB
C
|
|
/*
|
|||
|
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
|||
|
|
*
|
|||
|
|
* SPDX-License-Identifier: Apache-2.0
|
|||
|
|
*
|
|||
|
|
* Change Logs:
|
|||
|
|
* Date Author Notes
|
|||
|
|
* 2024-05-06 lijian the first version
|
|||
|
|
*/
|
|||
|
|
#include <LTE.h>
|
|||
|
|
|
|||
|
|
#define AT_UART_NAME "uart3"
|
|||
|
|
|
|||
|
|
LTE_t LTE;
|
|||
|
|
|
|||
|
|
static rt_device_t AT_serial; /* 串口设备句柄 */
|
|||
|
|
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
|
|||
|
|
|
|||
|
|
/* 串口接收消息结构*/
|
|||
|
|
struct rx_msg
|
|||
|
|
{
|
|||
|
|
rt_device_t dev;
|
|||
|
|
rt_size_t size;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/* 消息队列控制块 */
|
|||
|
|
static struct rt_messagequeue rx_mq;
|
|||
|
|
|
|||
|
|
rt_uint8_t rx_length;
|
|||
|
|
rt_uint8_t check_flag;
|
|||
|
|
rt_err_t result;
|
|||
|
|
static char line_buffer[60];
|
|||
|
|
|
|||
|
|
void set_check_flag(rt_uint8_t flag){
|
|||
|
|
check_flag = flag;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//AT指令发送
|
|||
|
|
void AT_send(const char * cmd)
|
|||
|
|
{
|
|||
|
|
rt_device_write(AT_serial, 0, cmd, rt_strlen(cmd));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 接收数据回调函数 */
|
|||
|
|
static rt_err_t uart_callback(rt_device_t dev, rt_size_t size)
|
|||
|
|
{
|
|||
|
|
struct rx_msg msg;
|
|||
|
|
rt_err_t result;
|
|||
|
|
msg.dev = dev;
|
|||
|
|
msg.size = size;
|
|||
|
|
|
|||
|
|
//rt_kprintf("in uart_callback\n");
|
|||
|
|
|
|||
|
|
result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
|
|||
|
|
if (result == -RT_EFULL)
|
|||
|
|
{
|
|||
|
|
/* 消息队列满 */
|
|||
|
|
rt_kprintf("message queue full!\n");
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//接收数据线程
|
|||
|
|
static void rx_serial_thread_entry(void *parameter)
|
|||
|
|
{
|
|||
|
|
struct rx_msg msg;
|
|||
|
|
static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1];
|
|||
|
|
rt_uint8_t line_pos = 0;
|
|||
|
|
|
|||
|
|
while (1)
|
|||
|
|
{
|
|||
|
|
rt_memset(&msg, 0, sizeof(msg));
|
|||
|
|
/* 从消息队列中读取消息*/
|
|||
|
|
result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
|
|||
|
|
if (result > 0)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
// rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
|
|||
|
|
// rx_buffer[rx_length] = '\0';
|
|||
|
|
// /* 打印数据 */
|
|||
|
|
// rt_kprintf("%s\n", rx_buffer);
|
|||
|
|
|
|||
|
|
rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
|
|||
|
|
|
|||
|
|
for (int i = 0; i < rx_length; i++)
|
|||
|
|
{
|
|||
|
|
// 如果收到了换行符或回车符,就认为是一行的结束
|
|||
|
|
if (rx_buffer[i] == '\n' || rx_buffer[i] == '\r')
|
|||
|
|
{
|
|||
|
|
line_buffer[line_pos] = '\0'; // 添加字符串结束符
|
|||
|
|
if (line_pos > 0) // 如果这一行至少有一个字符
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
if (check_flag == 1) //1检测MQTT
|
|||
|
|
{
|
|||
|
|
//+MQTTSTATU :0 离线 1 已经登陆认证过 2 还没认证,需要发送 MCONNECT
|
|||
|
|
char * ch_pos = rt_strstr(line_buffer, "+MQTTSTATU :");
|
|||
|
|
// rt_kprintf("ch_pos c: %s\n", ch_pos);
|
|||
|
|
if (ch_pos != RT_NULL)
|
|||
|
|
{
|
|||
|
|
ch_pos = ch_pos + 12;
|
|||
|
|
set_MQTT_STATUS((rt_uint8_t) *ch_pos - '0');
|
|||
|
|
//break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
else if (check_flag == 2) //2检测LTE
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
//判断两个.为有IP,即联网成功
|
|||
|
|
char *ch_pos2 = strchr(line_buffer, '.');
|
|||
|
|
|
|||
|
|
if (ch_pos2 != NULL) {
|
|||
|
|
// 计算点字符的位置
|
|||
|
|
rt_uint8_t position = ch_pos2 - line_buffer; // 指针减法得到索引
|
|||
|
|
|
|||
|
|
if (line_buffer[position+2] == '.' || line_buffer[position+3] == '.' || line_buffer[position+4] == '.') {
|
|||
|
|
set_LTE_Status(1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//+CME ERROR:联网失败
|
|||
|
|
ch_pos2 = rt_strstr(line_buffer, "+CME ERROR:");
|
|||
|
|
if (ch_pos2 != RT_NULL)
|
|||
|
|
{
|
|||
|
|
set_LTE_Status(0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (LTE.log) {
|
|||
|
|
rt_kprintf("Received line: %s\n", line_buffer);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// rt_kprintf("Received line: %s , %d\n", line_buffer, line_pos);
|
|||
|
|
}
|
|||
|
|
line_pos = 0; // 重置行缓冲区位置
|
|||
|
|
}
|
|||
|
|
else if (line_pos < sizeof(line_buffer) - 1)
|
|||
|
|
{
|
|||
|
|
// 否则,将字符添加到行缓冲区
|
|||
|
|
line_buffer[line_pos++] = rx_buffer[i];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//AT串口初始化
|
|||
|
|
rt_uint8_t AT_device_init()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
// rt_pin_mode(WAK, PIN_MODE_OUTPUT);
|
|||
|
|
// // 默认为高电平
|
|||
|
|
// rt_pin_write(WAK, PIN_HIGH);
|
|||
|
|
// rt_pin_mode(GPS, PIN_MODE_OUTPUT);
|
|||
|
|
// // 默认为高电平
|
|||
|
|
// rt_pin_write(GPS, PIN_LOW);
|
|||
|
|
rt_pin_mode(RST, PIN_MODE_OUTPUT);
|
|||
|
|
// 默认为高电平
|
|||
|
|
rt_pin_write(RST, PIN_HIGH);
|
|||
|
|
rt_thread_mdelay(200);
|
|||
|
|
rt_pin_write(RST, PIN_LOW);
|
|||
|
|
|
|||
|
|
rt_err_t ret = RT_EOK;
|
|||
|
|
|
|||
|
|
static char msg_pool[256];
|
|||
|
|
|
|||
|
|
// char str[] = "AT\r\n";
|
|||
|
|
|
|||
|
|
AT_serial = rt_device_find(AT_UART_NAME);
|
|||
|
|
if (!AT_serial)
|
|||
|
|
{
|
|||
|
|
rt_kprintf("find %s failed!\n", AT_UART_NAME);
|
|||
|
|
return RT_ERROR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
config.baud_rate = BAUD_RATE_115200; //修改波特率为 115200
|
|||
|
|
config.data_bits = DATA_BITS_8; //数据位 8
|
|||
|
|
config.stop_bits = STOP_BITS_1; //停止位 1
|
|||
|
|
config.bufsz = 128; //修改缓冲区 buff size 为 128
|
|||
|
|
config.parity = PARITY_NONE; //无奇偶校验位
|
|||
|
|
|
|||
|
|
/* 初始化消息队列 */
|
|||
|
|
rt_mq_init(&rx_mq, "rx_mq", msg_pool, /* 存放消息的缓冲区 */
|
|||
|
|
sizeof(struct rx_msg), /* 一条消息的最大长度 */
|
|||
|
|
sizeof(msg_pool), /* 存放消息的缓冲区大小 */
|
|||
|
|
RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */
|
|||
|
|
|
|||
|
|
/* 串口设备控制参数 */
|
|||
|
|
rt_device_control(AT_serial, RT_DEVICE_CTRL_CONFIG, &config);
|
|||
|
|
|
|||
|
|
/* 打开串口设备。 DMA 接收及轮询发送模式打开串口设备 RT_DEVICE_FLAG_DMA_RX */
|
|||
|
|
ret = rt_device_open(AT_serial, RT_DEVICE_FLAG_DMA_RX);
|
|||
|
|
if (ret != RT_EOK)
|
|||
|
|
{
|
|||
|
|
rt_kprintf("open AT_serial fail!\n");
|
|||
|
|
return RT_ERROR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// AT_send("ATE0\r\n");
|
|||
|
|
|
|||
|
|
/* 设置接收回调函数 */
|
|||
|
|
rt_device_set_rx_indicate(AT_serial, uart_callback);
|
|||
|
|
/* 发送字符串 */
|
|||
|
|
|
|||
|
|
/* 创建 serial 线程 */
|
|||
|
|
rt_thread_t rx_thread = rt_thread_create("rx_serial", rx_serial_thread_entry, RT_NULL, 1024, 25, 10);
|
|||
|
|
/* 创建成功则启动线程 */
|
|||
|
|
if (rx_thread != RT_NULL)
|
|||
|
|
{
|
|||
|
|
rt_thread_startup(rx_thread);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = RT_ERROR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rt_kprintf("open AT_serial ok!\n");
|
|||
|
|
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//LTE初始化
|
|||
|
|
rt_uint8_t LTE_init()
|
|||
|
|
{
|
|||
|
|
AT_send("AT\r\n");
|
|||
|
|
AT_send("ATE0\r\n");
|
|||
|
|
rt_thread_mdelay(1000);
|
|||
|
|
// AT_send("AT+CGMI\r\n"); //模块厂商信息
|
|||
|
|
// rt_thread_mdelay(500);
|
|||
|
|
//
|
|||
|
|
// AT_send("AT+CPIN?\r\n"); //查询卡是否插好
|
|||
|
|
// rt_thread_mdelay(500);
|
|||
|
|
//
|
|||
|
|
// AT_send("AT+CSQ\r\n"); //信号质量
|
|||
|
|
// rt_thread_mdelay(500);
|
|||
|
|
//
|
|||
|
|
// AT_send("AT+CREG?\r\n"); //网络注册状态
|
|||
|
|
// rt_thread_mdelay(500);
|
|||
|
|
//
|
|||
|
|
// AT_send("AT+CGATT?\r\n"); //附着GPRS
|
|||
|
|
// rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
AT_send("AT+CSTT=\"\",\"\",\"\"\r\n"); //自动APN
|
|||
|
|
rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
// AT_send("AT+CSTT?\r\n");
|
|||
|
|
// rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
AT_send("AT+CIICR\r\n"); //激活移动场景
|
|||
|
|
rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
AT_send("AT+CIFSR\r\n"); //查询IP
|
|||
|
|
rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
// AT_send("ATI\r\n");
|
|||
|
|
// rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
//AT_send("ATD15612696324;\r\n");
|
|||
|
|
|
|||
|
|
return RT_EOK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//获取LTE状态
|
|||
|
|
rt_uint8_t get_LTE_status_flag()
|
|||
|
|
{
|
|||
|
|
set_check_flag(2);
|
|||
|
|
rt_uint8_t i = 0;
|
|||
|
|
AT_send("AT+CIFSR\r\n");
|
|||
|
|
while (!get_LTE_Status())
|
|||
|
|
{
|
|||
|
|
rt_thread_mdelay(200);
|
|||
|
|
if (i > 3)
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
i++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (LTE.log) {
|
|||
|
|
rt_kprintf("LTE status:%d\n" , get_LTE_Status());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
return get_LTE_Status();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void set_LTE_log(rt_uint8_t log){
|
|||
|
|
LTE.log = log;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//LTE重新初始化
|
|||
|
|
void LTE_Re_Init()
|
|||
|
|
{
|
|||
|
|
rt_pin_write(RST, PIN_HIGH);
|
|||
|
|
rt_thread_mdelay(500);
|
|||
|
|
rt_pin_write(RST, PIN_LOW);
|
|||
|
|
|
|||
|
|
AT_send("AT+CSTT=\"\",\"\",\"\"\r\n"); //自动APN
|
|||
|
|
rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
// AT_send("AT+CSTT?\r\n");
|
|||
|
|
// rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
AT_send("AT+CIICR\r\n"); //激活移动场景
|
|||
|
|
rt_thread_mdelay(500);
|
|||
|
|
|
|||
|
|
AT_send("AT+CIFSR\r\n"); //查询IP
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//检测MQTT与LTE联网状态
|
|||
|
|
void check_LTE_MQTT(){
|
|||
|
|
if (LTE.toggle)
|
|||
|
|
{
|
|||
|
|
if (get_LTE_status_flag() != 1)
|
|||
|
|
{
|
|||
|
|
LTE.LTE_re++;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
LTE.LTE_re = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (LTE.LTE_re == 3)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
LTE_Re_Init();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
LTE.toggle = 0;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
if (get_MQTT_Status_flag() != 1)
|
|||
|
|
{
|
|||
|
|
LTE.MQTT_re++;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
LTE.MQTT_re = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (LTE.LTE_re == 0 && LTE.MQTT_re == 3)
|
|||
|
|
{
|
|||
|
|
MQTT_RE_init();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
LTE.toggle = 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置/获取LTE使用键值
|
|||
|
|
* @param rt_uint8_t key 要设置的Key值
|
|||
|
|
* @return rt_uint8_t 返回当前的Key值
|
|||
|
|
*/
|
|||
|
|
void set_LTE_Key(rt_uint8_t key)
|
|||
|
|
{
|
|||
|
|
LTE.Key = key;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rt_uint8_t get_LTE_Key()
|
|||
|
|
{
|
|||
|
|
return LTE.Key;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置/获取LTE状态键值
|
|||
|
|
* @param rt_uint8_t key 要设置的Key值
|
|||
|
|
* @return rt_uint8_t 返回当前的Key值
|
|||
|
|
*/
|
|||
|
|
void set_LTE_Status(rt_uint8_t Status_t)
|
|||
|
|
{
|
|||
|
|
LTE.Status = Status_t;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rt_uint8_t get_LTE_Status()
|
|||
|
|
{
|
|||
|
|
return LTE.Status;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rt_uint8_t get_LTE_re()
|
|||
|
|
{
|
|||
|
|
return LTE.LTE_re;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rt_uint8_t get_L_MQTT_re()
|
|||
|
|
{
|
|||
|
|
return LTE.MQTT_re;
|
|||
|
|
}
|