#include "VK_Client.h" #include #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; static void lte_diag_finish_disconnect(void); 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); if (lte_diag.disconnect_report_pending) { BSP_LTE_CollectNetworkSnapshot(); lte_diag_finish_disconnect(); } 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; lte_diag.disconnect_report_pending = true; 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("[CONN] fmu_rx=%u fmu_tx=%u fmu_hb=%u server_rx=%u server_hb=%u events=%u", lte_diag.fmu_rx_bytes - lte_diag.conn_fmu_rx_base, lte_diag.fmu_tx_bytes - lte_diag.conn_fmu_tx_base, lte_diag.fmu_heartbeats - lte_diag.conn_fmu_heartbeat_base, lte_diag.server_rx_bytes - lte_diag.conn_server_rx_base, lte_diag.server_heartbeats - lte_diag.conn_server_heartbeat_base, lte_diag.server_rx_read_events - lte_diag.conn_server_events_base); LOG_I("[CONN] socket_tx=%u send_ok=%u send_fail=%u prompt_timeout=%u read_errors=%u", lte_diag.socket_tx_bytes - lte_diag.conn_socket_tx_base, lte_diag.socket_send_ok - lte_diag.conn_send_ok_base, lte_diag.socket_send_fail - lte_diag.conn_send_fail_base, 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] heap=%u/%u min_free=%u", heap_used, heap_total, heap_total - heap_max); if (reason == LTE_DISC_AT_TIMEOUT || reason == LTE_DISC_QIOPEN_FAILED || reason == LTE_DISC_MODULE_RESET) { const char *classification = reason == LTE_DISC_QIOPEN_FAILED ? "SOCKET_OPEN" : "MODEM_OR_DEVICE"; LOG_I("[CLASS] class=%s confidence=MEDIUM net_snapshot=unavailable", classification); lte_diag.disconnect_report_pending = false; } lte_dev.client1->connect_sta = false; } static const char *diag_text_or_unknown(const char *text) { return text[0] == '\0' ? "?" : text; } static void lte_diag_finish_disconnect(void) { const lte_network_snapshot_t *network = <e_diag.network; rt_tick_t now = lte_diag.last_disconnect_tick; rt_uint32_t connected_ms = now - lte_diag.connect_tick; rt_uint32_t fmu_hb = lte_diag.fmu_heartbeats - lte_diag.conn_fmu_heartbeat_base; rt_uint32_t server_hb = lte_diag.server_heartbeats - lte_diag.conn_server_heartbeat_base; rt_uint32_t ack_queries = lte_diag.socket_ack_queries - lte_diag.conn_ack_queries_base; const char *classification = "UNKNOWN"; const char *confidence = "LOW"; const char *evidence = "insufficient"; bool registration_bad = network->cereg >= 0 && network->cereg != 1 && network->cereg != 5; LOG_I("[NET] oper=%s rat=%s band=%s channel=%u tac=%s cell=%s", diag_text_or_unknown(network->oper), diag_text_or_unknown(network->rat), diag_text_or_unknown(network->band), network->channel, diag_text_or_unknown(network->tac), diag_text_or_unknown(network->cell)); LOG_I("[NET] cereg=%d cgatt=%d pdp=%d csq=%d pdpdeact=%u", network->cereg, network->cgatt, network->pdp, network->csq, lte_dev.socket_pdpdeact_pending ? 1 : 0); LOG_I("[PATH] acked=%u unacked=%u ack_queries=%u last_ack_age_ms=%u queue_drops=%u", lte_diag.socket_acked_bytes, lte_diag.socket_unacked_bytes, ack_queries, diag_age(now, lte_diag.last_socket_ack_tick), lte_diag.tx_queue_drops - lte_diag.conn_queue_drops_base); if (lte_dev.socket_pdpdeact_pending || registration_bad || network->cgatt == 0 || network->pdp == 0) { classification = "CELLULAR"; confidence = "HIGH"; evidence = lte_dev.socket_pdpdeact_pending ? "pdpdeact" : "registration"; } else if (connected_ms >= 25000 && connected_ms <= 40000 && fmu_hb == 0 && server_hb >= 5 && lte_diag.socket_unacked_bytes == 0) { classification = "SERVER_POLICY"; confidence = "HIGH"; evidence = "no_fmu_hb_30s"; } else if (lte_diag.socket_unacked_bytes > 0) { classification = "IP_PATH"; confidence = "MEDIUM"; evidence = "tcp_unacked"; } else if (lte_diag.last_disconnect_reason == LTE_DISC_SERVER_SILENCE) { classification = "SERVER_OR_DOWNLINK"; confidence = "MEDIUM"; evidence = "server_silence"; } else if (lte_diag.last_disconnect_reason == LTE_DISC_SOCKET_SEND) { classification = "MODEM_OR_SOCKET"; confidence = "MEDIUM"; evidence = "socket_send_fail"; } else if (ack_queries > 0 && lte_diag.socket_unacked_bytes == 0 && diag_age(now, lte_diag.last_server_rx_tick) <= 5000) { classification = "REMOTE_CLOSE"; confidence = "MEDIUM"; evidence = "recent_rx_all_acked"; } LOG_I("[CLASS] class=%s confidence=%s evidence=%s", classification, confidence, evidence); lte_diag.disconnect_report_pending = 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_data(pLte_dev->at_buf, len); 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_data(socket_rx_buffer, read_length); #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(<e_dev); } //------------------End of File----------------------------