diff --git a/applications/VK_Client.c b/applications/VK_Client.c index dea1879..7fc8022 100644 --- a/applications/VK_Client.c +++ b/applications/VK_Client.c @@ -32,6 +32,8 @@ static char cmd_cmd[128] = {0}; +static void lte_diag_finish_disconnect(void); + no_carrier_match_t _no_carrier_t = {0}; /*关闭TCP连接*/ @@ -39,6 +41,11 @@ 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(); + } 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); @@ -149,6 +156,7 @@ static const char *disconnect_reason_name(lte_disconnect_reason_t reason) { 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"; default: return "UNKNOWN"; } } @@ -167,6 +175,7 @@ void lte_diag_disconnect(lte_disconnect_reason_t reason) { 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, @@ -176,10 +185,13 @@ void lte_diag_disconnect(lte_disconnect_reason_t reason) { 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("[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("[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), @@ -191,13 +203,76 @@ void lte_diag_disconnect(lte_disconnect_reason_t reason) { 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); + 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; + 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] tcp_ack=unavailable mode=transparent"); + + 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) { + classification = "SERVER_POLICY"; + confidence = "HIGH"; + evidence = "no_fmu_hb_30s"; + } else if (lte_diag.last_disconnect_reason == LTE_DISC_SERVER_SILENCE) { + classification = "SERVER_OR_DOWNLINK"; + confidence = "MEDIUM"; + evidence = "server_silence"; + } else if (diag_age(now, lte_diag.last_server_rx_tick) <= 5000) { + classification = "REMOTE_CLOSE"; + confidence = "MEDIUM"; + evidence = "recent_server_rx"; + } + + LOG_I("[CLASS] class=%s confidence=%s evidence=%s", classification, + confidence, evidence); + lte_diag.disconnect_report_pending = false; +} + /*将EC800K软件复位*/ int16_t EC800K_Reset(void) { @@ -372,6 +447,7 @@ static bool client_exit_transparent_mode(CLte_dev_t *pLte_dev) { sizeof(pLte_dev->at_buf) - 1); if (len > 0) { lte_diag_uart2_rx((rt_size_t)len); + lte_diag_modem_text(pLte_dev->at_buf, (rt_size_t)len); pLte_dev->at_buf[len] = '\0'; if (rt_strstr((const char *)pLte_dev->at_buf, DEFAULT_EXPECT) != RT_NULL) { return true; @@ -391,7 +467,7 @@ void client_yield(CLte_dev_t *pLte_dev) { 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; + lte_diag_disconnect(LTE_DISC_SERVER_SILENCE); client_tcp_close(pLte_dev->client1); } else { lte_diag_disconnect(LTE_DISC_AT_TIMEOUT); @@ -408,6 +484,7 @@ void client_yield(CLte_dev_t *pLte_dev) { sizeof(pLte_dev->at_buf)); if (len > 0) { lte_diag_uart2_rx((rt_size_t)len); + lte_diag_modem_text(pLte_dev->at_buf, (rt_size_t)len); /*收到TCP关闭的消息*/ if (strstr((const char *)pLte_dev->at_buf, CLOSED)) { LOG_W("[URC] closed received"); @@ -437,9 +514,7 @@ void client_yield(CLte_dev_t *pLte_dev) { } 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(); + 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); diff --git a/applications/VK_Com.c b/applications/VK_Com.c index 1a68f10..4547347 100644 --- a/applications/VK_Com.c +++ b/applications/VK_Com.c @@ -86,7 +86,7 @@ void com_task(void) { while (1) { len = rt_device_read(fmu_com, 0, buff, sizeof(buff)); if (len > 0) { - lte_diag_fmu_rx(len); + lte_diag_fmu_data(buff, len); if (lte_dev.client1->connect_sta == true && lte_dev.data_tx_paused == false) { /* 仅在客户端2连接时转发 */ diff --git a/applications/drv_ec800k.c b/applications/drv_ec800k.c index ef242a4..066e6b9 100644 --- a/applications/drv_ec800k.c +++ b/applications/drv_ec800k.c @@ -38,6 +38,143 @@ CLte_dev_t lte_dev = { lte_diag_t lte_diag = {0}; static bool lte_log_clock_query_done = false; +static rt_uint8_t pdpdeact_match_position = 0; + +typedef struct { + rt_uint16_t remaining; + rt_uint16_t checksum; + rt_uint16_t received_checksum; + rt_uint8_t magic; + rt_uint8_t phase; + rt_uint8_t position; + rt_uint8_t payload_length; + rt_uint8_t incompat_flags; + bool heartbeat; +} mavlink_diag_parser_t; + +static mavlink_diag_parser_t fmu_mavlink_parser; +static mavlink_diag_parser_t server_mavlink_parser; + +static int parse_decimal(const char **text) { + int value = 0; + bool found = false; + const char *p = *text; + + while (*p == ' ') p++; + while (*p >= '0' && *p <= '9') { + found = true; + value = value * 10 + (*p++ - '0'); + } + *text = p; + return found ? value : -1; +} + +static void copy_csv_token(const char **text, char *output, rt_size_t capacity) { + const char *p = *text; + rt_size_t used = 0; + char terminator = ','; + + if (capacity == 0) return; + while (*p == ' ' || *p == ',') p++; + if (*p == '"') { + terminator = '"'; + p++; + } + while (*p != '\0' && *p != '\r' && *p != '\n' && *p != terminator) { + if (used + 1 < capacity) output[used++] = *p; + p++; + } + while (used > 0 && output[used - 1] == ' ') used--; + output[used] = '\0'; + if (*p == terminator) p++; + *text = p; +} + +static void mavlink_crc_accumulate(uint8_t data, rt_uint16_t *checksum) { + uint8_t tmp = data ^ (uint8_t)(*checksum & 0xff); + tmp ^= tmp << 4; + *checksum = (*checksum >> 8) ^ ((rt_uint16_t)tmp << 8) ^ + ((rt_uint16_t)tmp << 3) ^ ((rt_uint16_t)tmp >> 4); +} + +static void mavlink_diag_start(mavlink_diag_parser_t *parser, uint8_t magic) { + parser->magic = magic; + parser->phase = 1; + parser->position = 0; + parser->remaining = 0; + parser->checksum = 0xffff; + parser->received_checksum = 0; + parser->payload_length = 0; + parser->incompat_flags = 0; + parser->heartbeat = false; +} + +static void mavlink_diag_feed(mavlink_diag_parser_t *parser, + const uint8_t *data, rt_size_t size, + rt_uint32_t *heartbeat_count) { + rt_size_t i; + + for (i = 0; i < size; i++) { + uint8_t ch = data[i]; + + if (parser->phase == 0) { + if (ch == 0xFE || ch == 0xFD) mavlink_diag_start(parser, ch); + continue; + } + if (parser->phase == 5) { + parser->remaining--; + if (parser->remaining == 0) parser->phase = 0; + continue; + } + if (parser->phase == 2) { + mavlink_crc_accumulate(ch, &parser->checksum); + parser->remaining--; + if (parser->remaining == 0) parser->phase = 3; + continue; + } + if (parser->phase == 3) { + parser->received_checksum = ch; + parser->phase = 4; + continue; + } + if (parser->phase == 4) { + parser->received_checksum |= (rt_uint16_t)ch << 8; + mavlink_crc_accumulate(50, &parser->checksum); + if (parser->heartbeat && + parser->checksum == parser->received_checksum) { + (*heartbeat_count)++; + } + if (parser->magic == 0xFD && + (parser->incompat_flags & 0x01) != 0) { + parser->phase = 5; + parser->remaining = 13; + } else { + parser->phase = 0; + } + continue; + } + + mavlink_crc_accumulate(ch, &parser->checksum); + if (parser->position == 0) parser->payload_length = ch; + if (parser->magic == 0xFE && parser->position == 4) { + parser->heartbeat = parser->payload_length == 9 && ch == 0; + parser->remaining = parser->payload_length; + parser->phase = parser->remaining > 0 ? 2 : 3; + } else if (parser->magic == 0xFD) { + if (parser->position == 1) parser->incompat_flags = ch; + if (parser->position == 6) parser->heartbeat = ch == 0; + if (parser->position == 7) + parser->heartbeat = parser->heartbeat && ch == 0; + if (parser->position == 8) { + parser->heartbeat = parser->payload_length == 9 && + parser->heartbeat && ch == 0; + parser->remaining = parser->payload_length; + parser->phase = parser->remaining > 0 ? 2 : 3; + } + } + parser->position++; + } +} void lte_diag_at_begin(const char *cmd) { rt_size_t i; @@ -86,6 +223,42 @@ void lte_diag_fmu_rx(rt_size_t size) { lte_diag.last_fmu_rx_tick = rt_tick_get(); } +void lte_diag_fmu_data(const uint8_t *data, rt_size_t size) { + if (data == RT_NULL || size == 0) return; + lte_diag_fmu_rx(size); + mavlink_diag_feed(&fmu_mavlink_parser, data, size, <e_diag.fmu_heartbeats); +} + +void lte_diag_server_data(const uint8_t *data, rt_size_t size) { + if (data == RT_NULL || size == 0) return; + lte_diag.server_rx_bytes += size; + lte_diag.server_rx_read_events++; + lte_diag.last_server_rx_tick = rt_tick_get(); + mavlink_diag_feed(&server_mavlink_parser, data, size, + <e_diag.server_heartbeats); +} + +void lte_diag_modem_text(const uint8_t *data, rt_size_t size) { + static const char pattern[] = "pdpdeact"; + rt_size_t i; + + if (data == RT_NULL) return; + for (i = 0; i < size; i++) { + char ch = (char)data[i]; + if (ch >= 'A' && ch <= 'Z') ch = (char)(ch - 'A' + 'a'); + if (ch == pattern[pdpdeact_match_position]) { + pdpdeact_match_position++; + if (pdpdeact_match_position == sizeof(pattern) - 1) { + if (!lte_dev.socket_pdpdeact_pending) lte_diag.pdpdeact_count++; + lte_dev.socket_pdpdeact_pending = true; + pdpdeact_match_position = 0; + } + } else { + pdpdeact_match_position = ch == pattern[0] ? 1 : 0; + } + } +} + void lte_diag_fmu_tx(rt_size_t size) { lte_diag.fmu_tx_bytes += size; lte_diag.last_fmu_tx_tick = rt_tick_get(); @@ -101,6 +274,16 @@ void lte_diag_connect_attempt(void) { void lte_diag_connect_success(void) { lte_diag.connect_tick = rt_tick_get(); lte_diag.last_server_rx_tick = lte_diag.connect_tick; + lte_diag.conn_fmu_rx_base = lte_diag.fmu_rx_bytes; + lte_diag.conn_fmu_tx_base = lte_diag.fmu_tx_bytes; + lte_diag.conn_server_rx_base = lte_diag.server_rx_bytes; + lte_diag.conn_server_events_base = lte_diag.server_rx_read_events; + lte_diag.conn_fmu_heartbeat_base = lte_diag.fmu_heartbeats; + lte_diag.conn_server_heartbeat_base = lte_diag.server_heartbeats; + lte_dev.socket_pdpdeact_pending = false; + pdpdeact_match_position = 0; + rt_memset(&fmu_mavlink_parser, 0, sizeof(fmu_mavlink_parser)); + rt_memset(&server_mavlink_parser, 0, sizeof(server_mavlink_parser)); } void lte_diag_module_reset(void) { @@ -151,6 +334,103 @@ void BSP_LTE_InitLogClock(void) { } } +static void parse_cereg_snapshot(const char *response) { + const char *p = rt_strstr(response, "+CEREG:"); + int value; + + if (p == RT_NULL) return; + p += rt_strlen("+CEREG:"); + value = parse_decimal(&p); + if (value < 0 || *p != ',') return; + p++; + value = parse_decimal(&p); + if (value < 0) return; + lte_diag.network.cereg = (int8_t)value; + if (*p == ',') { + copy_csv_token(&p, lte_diag.network.tac, + sizeof(lte_diag.network.tac)); + copy_csv_token(&p, lte_diag.network.cell, + sizeof(lte_diag.network.cell)); + } +} + +static void parse_cgatt_snapshot(const char *response) { + const char *p = rt_strstr(response, "+CGATT:"); + int value; + + if (p == RT_NULL) return; + p += rt_strlen("+CGATT:"); + value = parse_decimal(&p); + if (value >= 0) lte_diag.network.cgatt = (int8_t)value; +} + +static void parse_qiact_snapshot(const char *response) { + const char *p = rt_strstr(response, "+QIACT:"); + int context; + int state; + + if (p == RT_NULL) { + lte_diag.network.pdp = 0; + return; + } + p += rt_strlen("+QIACT:"); + context = parse_decimal(&p); + if (context < 0 || *p != ',') return; + p++; + state = parse_decimal(&p); + if (context == 1 && state >= 0) lte_diag.network.pdp = (int8_t)state; +} + +static void parse_qnwinfo_snapshot(const char *response) { + const char *p = rt_strstr(response, "+QNWINFO:"); + char channel[12]; + + if (p == RT_NULL) return; + p += rt_strlen("+QNWINFO:"); + copy_csv_token(&p, lte_diag.network.rat, sizeof(lte_diag.network.rat)); + copy_csv_token(&p, lte_diag.network.oper, sizeof(lte_diag.network.oper)); + copy_csv_token(&p, lte_diag.network.band, sizeof(lte_diag.network.band)); + copy_csv_token(&p, channel, sizeof(channel)); + p = channel; + { + int value = parse_decimal(&p); + if (value >= 0) lte_diag.network.channel = (rt_uint32_t)value; + } +} + +void BSP_LTE_CollectNetworkSnapshot(void) { + lte_network_snapshot_t *network = <e_diag.network; + + rt_memset(network, 0, sizeof(*network)); + network->cereg = -1; + network->cgatt = -1; + network->pdp = -1; + network->csq = -1; + + BSP_LTE_SendCmd(AT_CEREG2, DEFAULT_EXPECT, DEFAULT_ERROR, + LTE_CMD_WAIT_NORMAL); + if (BSP_LTE_SendCmd(AT_CEREG, DEFAULT_EXPECT, DEFAULT_ERROR, + LTE_CMD_WAIT_NORMAL) == 0) { + parse_cereg_snapshot((const char *)lte_dev.at_buf); + } + BSP_LTE_SendCmd(AT_CEREG0, DEFAULT_EXPECT, DEFAULT_ERROR, + LTE_CMD_WAIT_NORMAL); + if (BSP_LTE_SendCmd(AT_CGATT, DEFAULT_EXPECT, DEFAULT_ERROR, + LTE_CMD_WAIT_NORMAL) == 0) { + parse_cgatt_snapshot((const char *)lte_dev.at_buf); + } + if (BSP_LTE_SendCmd(AT_QIACT, DEFAULT_EXPECT, DEFAULT_ERROR, + LTE_CMD_WAIT_NORMAL) == 0) { + parse_qiact_snapshot((const char *)lte_dev.at_buf); + } + if (BSP_LTE_SendCmd(AT_QNWINFO, DEFAULT_EXPECT, DEFAULT_ERROR, + LTE_CMD_WAIT_NORMAL) == 0) { + parse_qnwinfo_snapshot((const char *)lte_dev.at_buf); + } + network->csq = BSP_LTE_GetCSQ(); + if (network->csq >= 0) lte_dev.csq = network->csq; +} + int16_t BSP_LTE_SendCmd(const char *cmd, const char *expect, const char *error, uint32_t waittime) { lte_diag_at_begin(cmd); @@ -167,6 +447,7 @@ int16_t BSP_LTE_SendCmd(const char *cmd, const char *expect, const char *error, sizeof(lte_dev.at_buf)); if (read_len > 0) { lte_diag_uart2_rx((rt_size_t)read_len); + lte_diag_modem_text(lte_dev.at_buf, (rt_size_t)read_len); } LOG_I("%s\n", lte_dev.at_buf); diff --git a/applications/drv_ec800k.h b/applications/drv_ec800k.h index 4e20fee..8b3708c 100644 --- a/applications/drv_ec800k.h +++ b/applications/drv_ec800k.h @@ -66,7 +66,9 @@ extern "C" { #define AT_CGREG "AT+CGREG?\r\n" // GPRS REG 2G #define AT_CEREG "AT+CEREG?\r\n" // EPS REG 4G #define AT_CEREG0 "AT+CEREG=0\r\n" +#define AT_CEREG2 "AT+CEREG=2\r\n" #define AT_CSQ "AT+CSQ\r\n" +#define AT_QNWINFO "AT+QNWINFO\r\n" #define AT_CPSI "AT+CPSI?\r\n" #define AT_CIPMODE "AT+CIPMODE=1\r\n" @@ -227,8 +229,22 @@ typedef enum { LTE_DISC_AT_TIMEOUT, LTE_DISC_QIOPEN_FAILED, LTE_DISC_MODULE_RESET, + LTE_DISC_SERVER_SILENCE, } lte_disconnect_reason_t; +typedef struct { + int8_t cereg; + int8_t cgatt; + int8_t pdp; + int8_t csq; + char rat[12]; + char oper[16]; + char band[16]; + char tac[9]; + char cell[12]; + rt_uint32_t channel; +} lte_network_snapshot_t; + typedef struct { rt_uint32_t uart2_rx_bytes; rt_uint32_t uart2_tx_bytes; @@ -250,6 +266,15 @@ typedef struct { rt_uint32_t server_rx_bytes; rt_uint32_t server_rx_read_events; rt_uint32_t server_silence_timeout_count; + rt_uint32_t fmu_heartbeats; + rt_uint32_t server_heartbeats; + rt_uint32_t pdpdeact_count; + rt_uint32_t conn_fmu_rx_base; + rt_uint32_t conn_fmu_tx_base; + rt_uint32_t conn_server_rx_base; + rt_uint32_t conn_server_events_base; + rt_uint32_t conn_fmu_heartbeat_base; + rt_uint32_t conn_server_heartbeat_base; rt_tick_t last_uart2_rx_tick; rt_tick_t last_uart2_tx_tick; rt_tick_t last_fmu_rx_tick; @@ -261,6 +286,8 @@ typedef struct { rt_int32_t last_at_result; char last_at_cmd[20]; lte_disconnect_reason_t last_disconnect_reason; + lte_network_snapshot_t network; + bool disconnect_report_pending; } lte_diag_t; extern lte_diag_t lte_diag; @@ -272,6 +299,9 @@ void lte_diag_uart2_tx(rt_size_t size); void lte_diag_uart_error(const char *name, rt_uint32_t error_code); void lte_diag_fmu_rx(rt_size_t size); void lte_diag_fmu_tx(rt_size_t size); +void lte_diag_fmu_data(const uint8_t *data, rt_size_t size); +void lte_diag_server_data(const uint8_t *data, rt_size_t size); +void lte_diag_modem_text(const uint8_t *data, rt_size_t size); void lte_diag_connect_attempt(void); void lte_diag_connect_success(void); void lte_diag_disconnect(lte_disconnect_reason_t reason); @@ -299,6 +329,7 @@ typedef struct { bool reset_flag; bool dev_init_flag; volatile bool data_tx_paused; + volatile bool socket_pdpdeact_pending; } CLte_dev_t; extern CLte_dev_t lte_dev; @@ -320,6 +351,7 @@ void BSP_LTE_SetDataTxPaused(bool paused); void BSP_LTE_Config(void); void BSP_LTE_InitLogClock(void); +void BSP_LTE_CollectNetworkSnapshot(void); int BSP_LTE_GetICCID(char *pICCID);