在现场抓取的报文中,时常会发现会收到【+QIURC: "pdpdeact",1..】的问题,这实际上是运营商主动断开了socket连接,但是此时4G模组依然是在网的,大部分场景下只需要重新打开连接即可
操作:
【rt-thread / components / net / at / include / at.h 增加枚举、结构体】
enum at_client_err_type
{
AT_CLIENT_NORMAL = 0,
AT_CLIENT_PDPDEACT,
};
typedef void (*at_client_callback_fn )(struct at_client *netdev, enum at_client_err_type type);
struct at_client
{
rt_device_t device;
at_status_t status;
char end_sign;
char *recv_line_buf;
rt_size_t recv_line_len;
rt_size_t recv_bufsz;
rt_sem_t rx_notice;
rt_mutex_t lock;
at_response_t resp;
rt_sem_t resp_notice;
at_resp_status_t resp_status;
struct at_urc_table *urc_table;
rt_size_t urc_table_size;
rt_thread_t parser;
at_client_callback_fn status_callback;
};
typedef struct at_client *at_client_t;
【packages / at_device-v2.0.4 / class / ec20 / at_socket_ec20.c 增加回调函数设置、调用回调函数的逻辑】
void at_client_set_status_callback(struct at_client *client, at_client_callback_fn status_callback)
{
client->status_callback = status_callback;
}
static void urc_pdpdeact_func(struct at_client *client, const char *data, rt_size_t size)
{
int connectID = 0;
RT_ASSERT(data && size);
sscanf(data, "+QIURC: \"pdpdeact\",%d", &connectID);
LOG_E("context (%d) is deactivated.", connectID);
if (client->status_callback)
{
client->status_callback(client, AT_CLIENT_PDPDEACT);
}
}
【net.c 注册回调函数、实现回调函数】
at_client_set_status_callback(s_ec20_at_device->client, ec20_at_client_set_status_callback);
void ec20_at_client_set_status_callback(struct at_client *netdev, enum at_client_err_type type)
{
if (AT_CLIENT_PDPDEACT == type)
{
ec20_reconnect_type = RECONNECT_PDPDEACT;
LOG_E("callback EC20 pdpdeact");
}
}
【pdpdeact后的重连操作】
void qideact_qiact()
{
rt_err_t result = RT_EOK;
at_response_t resp = RT_NULL;
resp = at_create_resp(256, 0, rt_tick_from_millisecond(600));
AT_SEND_CMD(resp, 0, 40 * 1000, "AT+QIDEACT=1"); // 在激活GPRS场景之前先关闭GPRS场景,确保连接正确
AT_SEND_CMD(resp, 0, 150 * 1000, "AT+QIACT=1"); // 激活PDP连接,为接下来的TCP/IP连接做准备
if (result != RT_EOK)
{
rt_thread_mdelay(10);
// 在激活GPRS场景之前先关闭GPRS场景,确保连接正确
AT_SEND_CMD(resp, 0, 150 * 1000, "AT+QIDEACT=1");
rt_thread_mdelay(10);
AT_SEND_CMD(resp, 0, 150 * 1000, "AT+QIACT=1");
}
if (resp)
{
at_delete_resp(resp);
}
}
int reconnect_ec20_device(uint8_t type)
{
static uint8_t first_in = 1;
if (first_in)
{
return init_ec20_device(); // 首次初始化不需要关机
}
if (if_enable_network_4g())
{
switch (type)
{
case RECONNECT_PDPDEACT: // pdpdeact的回调函数会将type置为RECONNECT_PDPDEACT
{
uint8_t ip[4] = {0};
if (get_dev_ip(ip) == DONE)
{
LOG_I("IP is %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
qideact_qiact();
LOG_E("Detected pdpdeact, Execute QIDEACT and QIACT");
break;
}
else
{
LOG_E("Detected pdpdeact, But no IP was detected, Execute the normal process");
}
}
case RECONNECT_NORMAL: // 正常的开机初始化
{
power_off();
clear_ec20_recv();
init_ec20_at_ctrl();
ADD_DELAY_COUNT;
break;
}
default:
break;
}
return 1;
}
else
return 1;
}