You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

554 lines
17 KiB

#include "VK_Client.h"
#include <stdint.h>
#include "VK_Com.h"
#include "drv_ec800k.h"
#include "VK_Log.h"
#include "rtdef.h"
#include "rtthread.h"
#include "rttypes.h"
#ifdef EDU_TRAINING
#if defined(__CC_ARM) && !defined(__clang__)
#define VK_MAVLINK_DO_PRAGMA(x) _Pragma(#x)
#define __pragma(x) VK_MAVLINK_DO_PRAGMA(x)
#pragma anon_unions
#endif
#include "VKFly/mavlink.h"
#include "mavlink_helpers.h"
#if defined(__CC_ARM) && !defined(__clang__)
#undef __pragma
#undef VK_MAVLINK_DO_PRAGMA
#endif
#endif
#define DBG_TAG "LINK_LOG"
#define DBG_LVL DBG_INFO
#include "rtdbg.h"
static char cmd_cmd[128] = {0};
static uint8_t socket_tx_buffer[LTE_SOCKET_TX_CHUNK_SIZE];
static uint8_t socket_rx_buffer[LTE_SOCKET_RX_CHUNK_SIZE];
static rt_size_t socket_tx_pending = 0;
static rt_tick_t last_ack_query_tick = 0;
no_carrier_match_t _no_carrier_t = {0};
/*关闭TCP连接*/
void client_tcp_close(Cclient_t *client) {
char close_cmd[24];
client->connect_sta = false;
BSP_LTE_SetDataTxPaused(true);
BSP_LTE_ClearSocketEvents();
fmu_net_queue_reset();
socket_tx_pending = 0;
rt_snprintf(close_cmd, sizeof(close_cmd), AT_QICLOSE, client->connect_ID);
BSP_LTE_SendCmd(close_cmd, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_QICLOSE);
client->error_cnt = 0;
}
static int no_carrier_char_parser(uint8_t ch){
int ret = 0;
switch(_no_carrier_t.match_stage){
case 0:
if(ch == 0x4E){
_no_carrier_t.match_stage++;
}else {
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 1:
if(ch == 0x4F){
_no_carrier_t.match_stage++;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 2:
if(ch == 0x20){
_no_carrier_t.match_stage++;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 3:
if(ch == 0x43){
_no_carrier_t.match_stage++;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 4:
if(ch == 0x41){
_no_carrier_t.match_stage++;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 5:
if(ch == 0x52){
_no_carrier_t.match_stage++;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 6:
if(ch == 0x52){
_no_carrier_t.match_stage++;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 7:
if(ch == 0x49){
_no_carrier_t.match_stage++;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 8:
if(ch == 0x45){
_no_carrier_t.match_stage++;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
case 9:
if(ch == 0x52){
ret = 1;
_no_carrier_t.match_stage = 0;
}else{
_no_carrier_t.match_stage = 0;
ret = -1;
}
break;
}
return ret;
}
static void no_carrier_match(uint8_t * at_buf,rt_size_t len){
for(int i = 0;i < len;i++){
if(no_carrier_char_parser(at_buf[i]) == 1){
_no_carrier_t.match_flag = COMPLETE_MATCH;
}
}
}
static const char *disconnect_reason_name(lte_disconnect_reason_t reason) {
switch (reason) {
case LTE_DISC_CLOSED: return "CLOSED";
case LTE_DISC_NO_CARRIER: return "NO_CARRIER";
case LTE_DISC_NO_CARRIER_SPLIT: return "NO_CARRIER_SPLIT";
case LTE_DISC_AT_TIMEOUT: return "AT_TIMEOUT";
case LTE_DISC_QIOPEN_FAILED: return "QIOPEN_FAILED";
case LTE_DISC_MODULE_RESET: return "MODULE_RESET";
case LTE_DISC_SERVER_SILENCE: return "SERVER_SILENCE";
case LTE_DISC_SOCKET_SEND: return "SOCKET_SEND";
default: return "UNKNOWN";
}
}
static rt_tick_t diag_age(rt_tick_t now, rt_tick_t tick) {
return tick == 0 ? 0 : now - tick;
}
void lte_diag_disconnect(lte_disconnect_reason_t reason) {
rt_tick_t now = rt_tick_get();
rt_size_t heap_total = 0;
rt_size_t heap_used = 0;
rt_size_t heap_max = 0;
rt_memory_info(&heap_total, &heap_used, &heap_max);
lte_diag.disconnect_count++;
lte_diag.last_disconnect_reason = reason;
lte_diag.last_disconnect_tick = now;
LOG_I("[DISC] reason=%s count=%u connected_ticks=%u",
disconnect_reason_name(reason), lte_diag.disconnect_count,
lte_diag.connect_tick == 0 ? 0 : now - lte_diag.connect_tick);
LOG_I("[DISC] uart2_rx=%u uart2_tx=%u events=%u write_fail=%u errors=%u/%u last_err=0x%X",
lte_diag.uart2_rx_bytes, lte_diag.uart2_tx_bytes,
lte_diag.uart2_rx_events, lte_diag.uart2_write_failures,
lte_diag.uart2_error_count, lte_diag.uart3_error_count,
lte_diag.last_uart_error_code);
LOG_I("[DISC] fmu_rx=%u fmu_tx=%u server_rx=%u read_events=%u silence_timeout=%u",
lte_diag.fmu_rx_bytes, lte_diag.fmu_tx_bytes,
lte_diag.server_rx_bytes, lte_diag.server_rx_read_events,
lte_diag.server_silence_timeout_count);
LOG_I("[DISC] socket_tx=%u send_ok=%u send_fail=%u prompt_timeout=%u read_errors=%u",
lte_diag.socket_tx_bytes, lte_diag.socket_send_ok,
lte_diag.socket_send_fail, lte_diag.socket_prompt_timeouts,
lte_diag.socket_read_errors);
LOG_I("[DISC] acked=%u unacked=%u ack_queries=%u ack_errors=%u",
lte_diag.socket_acked_bytes, lte_diag.socket_unacked_bytes,
lte_diag.socket_ack_queries, lte_diag.socket_ack_errors);
LOG_I("[DISC] tx_queue_high=%u drops=%u",
lte_diag.tx_queue_high_water, lte_diag.tx_queue_drops);
LOG_I("[DISC] age_uart2_rx=%u age_uart2_tx=%u age_fmu_rx=%u age_server_rx=%u",
diag_age(now, lte_diag.last_uart2_rx_tick),
diag_age(now, lte_diag.last_uart2_tx_tick),
diag_age(now, lte_diag.last_fmu_rx_tick),
diag_age(now, lte_diag.last_server_rx_tick));
LOG_I("[DISC] at_cmd=%s result=%d elapsed_ticks=%u timeouts=%u errors=%u",
lte_diag.last_at_cmd, lte_diag.last_at_result,
lte_diag.last_at_elapsed, lte_diag.at_timeouts, lte_diag.at_errors);
LOG_I("[DISC] attempts=%u reconnects=%u qioopen_fail=%u resets=%u",
lte_diag.connect_attempts, lte_diag.reconnect_count,
lte_diag.qioopen_failures, lte_diag.reset_count);
LOG_I("[DISC] csq=%d cereg=%u pdp=%u heap=%u/%u min_free=%u",
lte_dev.csq, lte_dev.eps_sta, lte_dev.reset_flag == DTU_CF_NO_NEED_RESET,
heap_used, heap_total, heap_total - heap_max);
lte_dev.client1->connect_sta = false;
}
/*将EC800K软件复位*/
int16_t EC800K_Reset(void) {
int16_t rst = -1;
lte_diag_module_reset();
BSP_LTE_SetDataTxPaused(true);
lte_dev.config_sta = false;
lte_dev.reset_flag = DTU_CF_NEED_RESET;
lte_dev.client1->connect_sta = false;
//lte_dev.client2->connect_sta = false;
rt_thread_mdelay(1000);
uint8_t try_count = 5;
do {
rt_thread_mdelay(1000);
rst = BSP_LTE_SendCmd(SOFT_RESET, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_LONG);
if (0 == rst) return 0;
try_count--;
} while (try_count > 0);
return rst;
}
int16_t client_tcp_connect(Cclient_t *client) {
int cmd_len;
int16_t rtn = 0;
if (lte_dev.config_sta == false)
return rtn;
if (client->connect_sta == true)
return rtn;
lte_diag_connect_attempt();
if (lte_dev.reset_flag == DTU_CF_NEED_RESET) {
/*查询PDP场景*/
if (0 != BSP_LTE_SendCmd(AT_QIACT, "+QIACT: 1,1,1,", DEFAULT_ERROR,
LTE_CMD_WAIT_QIACT)) {
/*如果查询PDP场景未设置成功,则激活PDP场景模式*/
if (0 != BSP_LTE_SendCmd(AT_QIACT1, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_QIACT)) {
BSP_LTE_SendCmd(AT_QIDEACT, NETCLOSE_SUCCESS, NETCLOSE_FAILURE,
LTE_CMD_WAIT_QIDEACT);
// client->error_cnt++;
return -1;
}
}
/* Query once after PDP is available, so network time has had a chance to sync. */
BSP_LTE_InitLogClock();
//
BSP_LTE_SendCmd(AT_CFG_RECV_IND, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL);
BSP_LTE_SendCmd(AT_QISDE0, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL);
BSP_LTE_SendCmd(AT_CFG_PASSIVE_CLOSED, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL);
BSP_LTE_SendCmd(AT_CFG_TCP_KEEPALIVE, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL);
//
}
// 1. 检查网络信号
lte_dev.csq = BSP_LTE_GetCSQ();
// 2, 打开链接
memset(cmd_cmd, 0, sizeof(cmd_cmd));
cmd_len = rt_snprintf(cmd_cmd, sizeof(cmd_cmd), AT_QIOPEN_BUFFER,
client->connect_ID, client->mode, client->ip,
client->port);
if (cmd_len < 0 || cmd_len >= (int)sizeof(cmd_cmd)) {
LOG_E("QIOPEN command is too long");
lte_diag.qioopen_failures++;
return -1;
}
/* 透传模式成功返回 CONNECT;一次尝试只发送一次 QIOPEN。 */
while (0 != BSP_LTE_OpenSocket(cmd_cmd, client->connect_ID)) {
lte_diag.qioopen_failures++;
client_tcp_close(client);
#ifdef debug_mode
EC800K_Reset();
client->error_cnt = 0;
return 0;
#else
client->error_cnt++;
if (client->error_cnt > 5) {
lte_diag_disconnect(LTE_DISC_QIOPEN_FAILED);
EC800K_Reset();
client->error_cnt = 0;
return 0;
}
rt_thread_mdelay((client->error_cnt < 5 ? client->error_cnt : 5) * 1000);
#endif
}
client->connect_sta = true;
BSP_LTE_ClearSocketEvents();
fmu_net_queue_reset();
socket_tx_pending = 0;
BSP_LTE_SetDataTxPaused(false);
lte_diag_connect_success();
last_ack_query_tick = lte_diag.connect_tick;
client->error_cnt = 0;
lte_dev.reset_flag = DTU_CF_NO_NEED_RESET;
#ifdef EDU_TRAINING
mavlink_message_t msg = {0};
uint8_t mav_buf[MAVLINK_MAX_PACKET_LEN] = {0};
uint16_t mav_len = 0;
mavlink_dtu_status_t _status_t = {0};
_status_t.csq = lte_dev.csq;
rt_memcpy(_status_t.sn, lte_dev.iccid, sizeof(_status_t.sn));
rt_memcpy(_status_t.imei,lte_dev.imei,sizeof(_status_t.imei));
mavlink_msg_dtu_status_encode(1, MAV_COMP_ID_TELEMETRY_RADIO, &msg,
&_status_t);
mav_len = mavlink_msg_to_send_buffer(mav_buf, &msg);
for (int i = 0; i < 3; i++) {
BSP_LTE_SendSocketData(client->connect_ID, mav_buf, mav_len);
}
rt_device_t fmu_com = fmu_com_get();
if (fmu_com != RT_NULL) {
rt_device_write(fmu_com, 0, mav_buf, mav_len);
}
#else
char buf[128] = {0};
rt_sprintf(buf, "{\"sn\":\"%s\",\"client_id\":\"%s\",\"csq\":\"%d\"}\r\n",
lte_dev.iccid, lte_dev.imei, lte_dev.csq);
BSP_LTE_SendSocketData(client->connect_ID, (uint8_t *)buf, sizeof(buf));
BSP_LTE_SendSocketData(client->connect_ID, (uint8_t *)buf, sizeof(buf));
BSP_LTE_SendSocketData(client->connect_ID, (uint8_t *)buf, sizeof(buf));
//hw_printf(buf);
#endif
return rtn;
}
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
static rt_tick_t last_rx_tick = 0;
#endif
#if 0
void client_yield(CLte_dev_t *pLte_dev) {
while (1) {
if (pLte_dev->client1->connect_sta == true) {
rt_err_t ret = rt_sem_take(pLte_dev->com_dev_rx_sem, 1000);
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
if (ret != RT_EOK && rt_tick_get() - last_rx_tick >
RT_TICK_PER_SECOND * LTE_SERVER_SILENCE_TIMEOUT_SEC) {
lte_diag.server_silence_timeout_count++;
LOG_W("server silence timeout, reconnect\n");
if (client_exit_transparent_mode(pLte_dev)) {
pLte_dev->client1->connect_sta = false;
client_tcp_close(pLte_dev->client1);
} else {
lte_diag_disconnect(LTE_DISC_AT_TIMEOUT);
EC800K_Reset();
}
continue;
}
#endif
if (RT_EOK == ret) {
rt_ssize_t len = 0;
while (1) {
rt_memset(pLte_dev->at_buf, 0, sizeof(pLte_dev->at_buf));
len = rt_device_read(pLte_dev->com_dev, 0, pLte_dev->at_buf,
sizeof(pLte_dev->at_buf));
if (len > 0) {
lte_diag_uart2_rx((rt_size_t)len);
/*收到TCP关闭的消息*/
if (strstr((const char *)pLte_dev->at_buf, CLOSED)) {
LOG_W("[URC] closed received");
lte_diag_disconnect(LTE_DISC_CLOSED);
BSP_LTE_SetDataTxPaused(true);
client_tcp_close(pLte_dev->client1);
break;
} else if (strstr((const char *)lte_dev.at_buf, "NO CARRIER")) {
lte_diag_disconnect(LTE_DISC_NO_CARRIER);
BSP_LTE_SetDataTxPaused(true);
client_tcp_close(pLte_dev->client1);
_no_carrier_t.match_flag = NO_MATCH;
break;
} else if(strstr((const char *)lte_dev.at_buf, "\r\n")) {
_no_carrier_t.match_flag = HALF_MATCH;
}
if (_no_carrier_t.match_flag == HALF_MATCH) {
no_carrier_match(pLte_dev->at_buf, len);
if (_no_carrier_t.match_flag == COMPLETE_MATCH) {
lte_diag_disconnect(LTE_DISC_NO_CARRIER_SPLIT);
BSP_LTE_SetDataTxPaused(true);
client_tcp_close(pLte_dev->client1);
_no_carrier_t.match_flag = NO_MATCH;
break;
}
}
rt_device_t fmu_com = fmu_com_get();
lte_diag.server_rx_bytes += len;
lte_diag.server_rx_read_events++;
lte_diag.last_server_rx_tick = rt_tick_get();
if (fmu_com) {
rt_ssize_t written = rt_device_write(fmu_com, 0,
pLte_dev->at_buf, len);
if (written > 0) {
lte_diag_fmu_tx((rt_size_t)written);
}
}
}else{
break;
}
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
last_rx_tick = rt_tick_get();
#endif
}
}
} else {
if(pLte_dev->reset_flag == DTU_CF_NEED_RESET){
BSP_LTE_Config();
}
client_tcp_connect(pLte_dev->client1);
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
last_rx_tick = rt_tick_get();
#endif
}
}
}
#endif
void client_yield(CLte_dev_t *pLte_dev) {
while (1) {
if (pLte_dev->client1->connect_sta == true) {
int16_t socket_result;
BSP_LTE_PollSocketUrc(20);
if (pLte_dev->socket_closed_pending) {
LOG_W("[URC] socket closed received");
lte_diag_disconnect(LTE_DISC_CLOSED);
client_tcp_close(pLte_dev->client1);
continue;
}
while (pLte_dev->socket_recv_pending &&
pLte_dev->client1->connect_sta) {
rt_device_t fmu_com;
int16_t read_length = BSP_LTE_ReadSocketData(
pLte_dev->client1->connect_ID, socket_rx_buffer,
sizeof(socket_rx_buffer));
if (read_length < 0) {
lte_diag_disconnect(pLte_dev->socket_closed_pending
? LTE_DISC_CLOSED
: LTE_DISC_AT_TIMEOUT);
client_tcp_close(pLte_dev->client1);
break;
}
if (read_length == 0) break;
lte_diag.server_rx_bytes += read_length;
lte_diag.server_rx_read_events++;
lte_diag.last_server_rx_tick = rt_tick_get();
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
last_rx_tick = lte_diag.last_server_rx_tick;
#endif
fmu_com = fmu_com_get();
if (fmu_com != RT_NULL) {
rt_ssize_t written = rt_device_write(fmu_com, 0, socket_rx_buffer,
read_length);
if (written > 0) lte_diag_fmu_tx((rt_size_t)written);
}
if (read_length == sizeof(socket_rx_buffer))
pLte_dev->socket_recv_pending = true;
}
if (!pLte_dev->client1->connect_sta) continue;
if (socket_tx_pending == 0) {
socket_tx_pending = fmu_net_queue_get(socket_tx_buffer,
sizeof(socket_tx_buffer));
}
if (socket_tx_pending > 0) {
socket_result = BSP_LTE_SendSocketData(
pLte_dev->client1->connect_ID, socket_tx_buffer,
(uint16_t)socket_tx_pending);
if (socket_result == 0) {
socket_tx_pending = 0;
} else if (socket_result < 0) {
lte_diag_disconnect(LTE_DISC_SOCKET_SEND);
client_tcp_close(pLte_dev->client1);
continue;
} else {
rt_thread_mdelay(50);
}
}
if (rt_tick_get() - last_ack_query_tick >= RT_TICK_PER_SECOND * 5) {
last_ack_query_tick = rt_tick_get();
BSP_LTE_QuerySocketSendStatus(pLte_dev->client1->connect_ID);
}
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
if (rt_tick_get() - last_rx_tick >
RT_TICK_PER_SECOND * LTE_SERVER_SILENCE_TIMEOUT_SEC) {
lte_diag.server_silence_timeout_count++;
LOG_W("server silence timeout, reconnect\n");
lte_diag_disconnect(LTE_DISC_SERVER_SILENCE);
client_tcp_close(pLte_dev->client1);
continue;
}
#endif
} else {
if (pLte_dev->reset_flag == DTU_CF_NEED_RESET) BSP_LTE_Config();
client_tcp_connect(pLte_dev->client1);
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
last_rx_tick = rt_tick_get();
#endif
}
}
}
void client_task(void) {
client_yield(&lte_dev);
}
//------------------End of File----------------------------