|
|
@ -38,6 +38,247 @@ CLte_dev_t lte_dev = { |
|
|
|
|
|
|
|
|
lte_diag_t lte_diag = {0}; |
|
|
lte_diag_t lte_diag = {0}; |
|
|
static bool lte_log_clock_query_done = false; |
|
|
static bool lte_log_clock_query_done = false; |
|
|
|
|
|
static char socket_urc_line[80]; |
|
|
|
|
|
static rt_size_t socket_urc_line_len = 0; |
|
|
|
|
|
static volatile bool socket_open_seen = false; |
|
|
|
|
|
static volatile int16_t socket_open_result = -1; |
|
|
|
|
|
|
|
|
|
|
|
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++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void lte_process_urc_line(const char *line) { |
|
|
|
|
|
const char *p; |
|
|
|
|
|
|
|
|
|
|
|
if (rt_strstr(line, "+QIURC:") != RT_NULL) { |
|
|
|
|
|
if (rt_strstr(line, "\"recv\"") != RT_NULL) { |
|
|
|
|
|
lte_dev.socket_recv_pending = true; |
|
|
|
|
|
} else if (rt_strstr(line, "\"closed\"") != RT_NULL) { |
|
|
|
|
|
lte_dev.socket_closed_pending = true; |
|
|
|
|
|
} else if (rt_strstr(line, "\"pdpdeact\"") != RT_NULL) { |
|
|
|
|
|
lte_dev.socket_pdpdeact_pending = true; |
|
|
|
|
|
lte_diag.pdpdeact_count++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
p = rt_strstr(line, "+QIOPEN:"); |
|
|
|
|
|
if (p != RT_NULL) { |
|
|
|
|
|
int connect_id; |
|
|
|
|
|
int error; |
|
|
|
|
|
p += rt_strlen("+QIOPEN:"); |
|
|
|
|
|
connect_id = parse_decimal(&p); |
|
|
|
|
|
if (*p == ',') p++; |
|
|
|
|
|
error = parse_decimal(&p); |
|
|
|
|
|
if (connect_id == lte_dev.client1->connect_ID && error >= 0) { |
|
|
|
|
|
socket_open_result = (int16_t)error; |
|
|
|
|
|
socket_open_seen = true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void lte_process_text(const uint8_t *data, rt_size_t length) { |
|
|
|
|
|
rt_size_t i; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++) { |
|
|
|
|
|
uint8_t ch = data[i]; |
|
|
|
|
|
if (ch == '\r') continue; |
|
|
|
|
|
if (ch == '\n') { |
|
|
|
|
|
if (socket_urc_line_len > 0) { |
|
|
|
|
|
socket_urc_line[socket_urc_line_len] = '\0'; |
|
|
|
|
|
lte_process_urc_line(socket_urc_line); |
|
|
|
|
|
socket_urc_line_len = 0; |
|
|
|
|
|
} |
|
|
|
|
|
} else if (ch >= 0x20 && ch <= 0x7e) { |
|
|
|
|
|
if (socket_urc_line_len < sizeof(socket_urc_line) - 1) { |
|
|
|
|
|
socket_urc_line[socket_urc_line_len++] = (char)ch; |
|
|
|
|
|
} else { |
|
|
|
|
|
socket_urc_line_len = 0; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static rt_ssize_t lte_read_available(uint8_t *buffer, rt_size_t capacity) { |
|
|
|
|
|
rt_ssize_t length = rt_device_read(lte_dev.com_dev, 0, buffer, capacity); |
|
|
|
|
|
if (length > 0) lte_diag_uart2_rx((rt_size_t)length); |
|
|
|
|
|
return length; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void lte_drain_socket_input(void) { |
|
|
|
|
|
rt_ssize_t length; |
|
|
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
|
length = lte_read_available(lte_dev.at_buf, sizeof(lte_dev.at_buf)); |
|
|
|
|
|
if (length > 0) lte_process_text(lte_dev.at_buf, (rt_size_t)length); |
|
|
|
|
|
} while (length > 0); |
|
|
|
|
|
while (rt_sem_take(lte_dev.com_dev_rx_sem, 0) == RT_EOK) { } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int lte_wait_text(const char *success, const char *failure, |
|
|
|
|
|
rt_tick_t timeout) { |
|
|
|
|
|
rt_tick_t deadline = rt_tick_get() + timeout; |
|
|
|
|
|
rt_size_t used = 0; |
|
|
|
|
|
|
|
|
|
|
|
rt_memset(lte_dev.at_buf, 0, sizeof(lte_dev.at_buf)); |
|
|
|
|
|
while ((rt_int32_t)(rt_tick_get() - deadline) < 0) { |
|
|
|
|
|
rt_ssize_t length; |
|
|
|
|
|
rt_sem_take(lte_dev.com_dev_rx_sem, 50); |
|
|
|
|
|
length = lte_read_available(lte_dev.at_buf + used, |
|
|
|
|
|
sizeof(lte_dev.at_buf) - 1 - used); |
|
|
|
|
|
if (length <= 0) continue; |
|
|
|
|
|
lte_process_text(lte_dev.at_buf + used, (rt_size_t)length); |
|
|
|
|
|
used += (rt_size_t)length; |
|
|
|
|
|
lte_dev.at_buf[used] = '\0'; |
|
|
|
|
|
if (lte_dev.socket_closed_pending) return 1; |
|
|
|
|
|
if (success != RT_NULL && rt_strstr((char *)lte_dev.at_buf, success)) return 0; |
|
|
|
|
|
if ((failure != RT_NULL && rt_strstr((char *)lte_dev.at_buf, failure)) || |
|
|
|
|
|
rt_strstr((char *)lte_dev.at_buf, DEFAULT_ERROR)) return 1; |
|
|
|
|
|
if (used >= sizeof(lte_dev.at_buf) - 1) { |
|
|
|
|
|
rt_memcpy(lte_dev.at_buf, lte_dev.at_buf + used - 32, 32); |
|
|
|
|
|
used = 32; |
|
|
|
|
|
lte_dev.at_buf[used] = '\0'; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void lte_diag_at_begin(const char *cmd) { |
|
|
void lte_diag_at_begin(const char *cmd) { |
|
|
rt_size_t i; |
|
|
rt_size_t i; |
|
|
@ -86,6 +327,21 @@ void lte_diag_fmu_rx(rt_size_t size) { |
|
|
lte_diag.last_fmu_rx_tick = rt_tick_get(); |
|
|
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_fmu_tx(rt_size_t size) { |
|
|
void lte_diag_fmu_tx(rt_size_t size) { |
|
|
lte_diag.fmu_tx_bytes += size; |
|
|
lte_diag.fmu_tx_bytes += size; |
|
|
lte_diag.last_fmu_tx_tick = rt_tick_get(); |
|
|
lte_diag.last_fmu_tx_tick = rt_tick_get(); |
|
|
@ -101,6 +357,26 @@ void lte_diag_connect_attempt(void) { |
|
|
void lte_diag_connect_success(void) { |
|
|
void lte_diag_connect_success(void) { |
|
|
lte_diag.connect_tick = rt_tick_get(); |
|
|
lte_diag.connect_tick = rt_tick_get(); |
|
|
lte_diag.last_server_rx_tick = lte_diag.connect_tick; |
|
|
lte_diag.last_server_rx_tick = lte_diag.connect_tick; |
|
|
|
|
|
lte_diag.last_socket_ack_tick = 0; |
|
|
|
|
|
lte_diag.socket_acked_bytes = 0; |
|
|
|
|
|
lte_diag.socket_unacked_bytes = 0; |
|
|
|
|
|
lte_diag.socket_prompt_timeouts = 0; |
|
|
|
|
|
lte_diag.socket_read_errors = 0; |
|
|
|
|
|
lte_diag.socket_ack_errors = 0; |
|
|
|
|
|
lte_diag.tx_queue_high_water = 0; |
|
|
|
|
|
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_socket_tx_base = lte_diag.socket_tx_bytes; |
|
|
|
|
|
lte_diag.conn_send_ok_base = lte_diag.socket_send_ok; |
|
|
|
|
|
lte_diag.conn_send_fail_base = lte_diag.socket_send_fail; |
|
|
|
|
|
lte_diag.conn_ack_queries_base = lte_diag.socket_ack_queries; |
|
|
|
|
|
lte_diag.conn_queue_drops_base = lte_diag.tx_queue_drops; |
|
|
|
|
|
lte_diag.conn_fmu_heartbeat_base = lte_diag.fmu_heartbeats; |
|
|
|
|
|
lte_diag.conn_server_heartbeat_base = lte_diag.server_heartbeats; |
|
|
|
|
|
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) { |
|
|
void lte_diag_module_reset(void) { |
|
|
@ -135,6 +411,180 @@ void BSP_LTE_SetDataTxPaused(bool paused) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BSP_LTE_ClearSocketEvents(void) { |
|
|
|
|
|
lte_dev.socket_recv_pending = false; |
|
|
|
|
|
lte_dev.socket_closed_pending = false; |
|
|
|
|
|
lte_dev.socket_pdpdeact_pending = false; |
|
|
|
|
|
socket_open_seen = false; |
|
|
|
|
|
socket_open_result = -1; |
|
|
|
|
|
socket_urc_line_len = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int16_t BSP_LTE_OpenSocket(const char *cmd, uint8_t connect_id) { |
|
|
|
|
|
rt_tick_t deadline; |
|
|
|
|
|
|
|
|
|
|
|
(void)connect_id; |
|
|
|
|
|
lte_drain_socket_input(); |
|
|
|
|
|
socket_open_seen = false; |
|
|
|
|
|
socket_open_result = -1; |
|
|
|
|
|
lte_diag_at_begin(cmd); |
|
|
|
|
|
LOG_I("%s", cmd); |
|
|
|
|
|
BSP_LTE_SendData((uint8_t *)cmd, rt_strlen(cmd)); |
|
|
|
|
|
deadline = rt_tick_get() + LTE_CMD_WAIT_QIOPEN; |
|
|
|
|
|
while ((rt_int32_t)(rt_tick_get() - deadline) < 0) { |
|
|
|
|
|
rt_ssize_t length; |
|
|
|
|
|
rt_sem_take(lte_dev.com_dev_rx_sem, 100); |
|
|
|
|
|
length = lte_read_available(lte_dev.at_buf, sizeof(lte_dev.at_buf) - 1); |
|
|
|
|
|
if (length > 0) { |
|
|
|
|
|
lte_dev.at_buf[length] = '\0'; |
|
|
|
|
|
lte_process_text(lte_dev.at_buf, (rt_size_t)length); |
|
|
|
|
|
if (rt_strstr((char *)lte_dev.at_buf, DEFAULT_ERROR)) { |
|
|
|
|
|
lte_diag_at_end(1); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (socket_open_seen) { |
|
|
|
|
|
LOG_I("[SOCKET] open result=%d", socket_open_result); |
|
|
|
|
|
lte_diag_at_end(socket_open_result == 0 ? 0 : 1); |
|
|
|
|
|
return socket_open_result == 0 ? 0 : 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
lte_diag_at_end(-1); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int16_t BSP_LTE_SendSocketData(uint8_t connect_id, const uint8_t *data, |
|
|
|
|
|
uint16_t length) { |
|
|
|
|
|
char command[32]; |
|
|
|
|
|
int result; |
|
|
|
|
|
|
|
|
|
|
|
if (data == RT_NULL || length == 0 || length > 1460) return -1; |
|
|
|
|
|
lte_drain_socket_input(); |
|
|
|
|
|
rt_snprintf(command, sizeof(command), AT_QISEND, connect_id, length); |
|
|
|
|
|
BSP_LTE_SendData((uint8_t *)command, rt_strlen(command)); |
|
|
|
|
|
result = lte_wait_text(TPOK, DEFAULT_ERROR, LTE_CMD_WAIT_PROMPT); |
|
|
|
|
|
if (result != 0) { |
|
|
|
|
|
if (result < 0) lte_diag.socket_prompt_timeouts++; |
|
|
|
|
|
lte_diag.socket_send_fail++; |
|
|
|
|
|
return result < 0 ? -1 : 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
BSP_LTE_SendData((uint8_t *)data, length); |
|
|
|
|
|
result = lte_wait_text(QI_SEND_OK, QI_SEND_FAIL, LTE_CMD_WAIT_SEND); |
|
|
|
|
|
if (result == 0) { |
|
|
|
|
|
lte_diag.socket_tx_bytes += length; |
|
|
|
|
|
lte_diag.socket_send_ok++; |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
lte_diag.socket_send_fail++; |
|
|
|
|
|
return result < 0 ? -1 : 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int16_t BSP_LTE_QuerySocketSendStatus(uint8_t connect_id) { |
|
|
|
|
|
char command[24]; |
|
|
|
|
|
const char *p; |
|
|
|
|
|
int total; |
|
|
|
|
|
int acked; |
|
|
|
|
|
int unacked; |
|
|
|
|
|
|
|
|
|
|
|
lte_drain_socket_input(); |
|
|
|
|
|
rt_snprintf(command, sizeof(command), AT_QISEND, connect_id, 0); |
|
|
|
|
|
BSP_LTE_SendData((uint8_t *)command, rt_strlen(command)); |
|
|
|
|
|
if (lte_wait_text("\r\nOK\r\n", DEFAULT_ERROR, LTE_CMD_WAIT_SEND) != 0) { |
|
|
|
|
|
lte_diag.socket_ack_errors++; |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
p = rt_strstr((char *)lte_dev.at_buf, "+QISEND:"); |
|
|
|
|
|
if (p == RT_NULL) { |
|
|
|
|
|
lte_diag.socket_ack_errors++; |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
p += rt_strlen("+QISEND:"); |
|
|
|
|
|
total = parse_decimal(&p); |
|
|
|
|
|
if (*p == ',') p++; |
|
|
|
|
|
acked = parse_decimal(&p); |
|
|
|
|
|
if (*p == ',') p++; |
|
|
|
|
|
unacked = parse_decimal(&p); |
|
|
|
|
|
if (total < 0 || acked < 0 || unacked < 0) { |
|
|
|
|
|
lte_diag.socket_ack_errors++; |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
(void)total; |
|
|
|
|
|
lte_diag.socket_acked_bytes = (rt_uint32_t)acked; |
|
|
|
|
|
lte_diag.socket_unacked_bytes = (rt_uint32_t)unacked; |
|
|
|
|
|
lte_diag.socket_ack_queries++; |
|
|
|
|
|
lte_diag.last_socket_ack_tick = rt_tick_get(); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int16_t BSP_LTE_ReadSocketData(uint8_t connect_id, uint8_t *data, |
|
|
|
|
|
uint16_t capacity) { |
|
|
|
|
|
char command[32]; |
|
|
|
|
|
rt_tick_t deadline; |
|
|
|
|
|
rt_size_t used = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (data == RT_NULL || capacity == 0 || capacity > LTE_SOCKET_RX_CHUNK_SIZE) |
|
|
|
|
|
return -1; |
|
|
|
|
|
lte_drain_socket_input(); |
|
|
|
|
|
lte_dev.socket_recv_pending = false; |
|
|
|
|
|
rt_snprintf(command, sizeof(command), "AT+QIRD=%u,%u\r\n", |
|
|
|
|
|
connect_id, capacity); |
|
|
|
|
|
BSP_LTE_SendData((uint8_t *)command, rt_strlen(command)); |
|
|
|
|
|
rt_memset(lte_dev.at_buf, 0, sizeof(lte_dev.at_buf)); |
|
|
|
|
|
deadline = rt_tick_get() + LTE_CMD_WAIT_SEND; |
|
|
|
|
|
while ((rt_int32_t)(rt_tick_get() - deadline) < 0) { |
|
|
|
|
|
rt_ssize_t length; |
|
|
|
|
|
char *header; |
|
|
|
|
|
char *payload; |
|
|
|
|
|
const char *number; |
|
|
|
|
|
int payload_length; |
|
|
|
|
|
|
|
|
|
|
|
rt_sem_take(lte_dev.com_dev_rx_sem, 50); |
|
|
|
|
|
length = lte_read_available(lte_dev.at_buf + used, |
|
|
|
|
|
sizeof(lte_dev.at_buf) - 1 - used); |
|
|
|
|
|
if (length <= 0) continue; |
|
|
|
|
|
used += (rt_size_t)length; |
|
|
|
|
|
lte_dev.at_buf[used] = '\0'; |
|
|
|
|
|
header = rt_strstr((char *)lte_dev.at_buf, "+QIRD:"); |
|
|
|
|
|
if (header == RT_NULL) { |
|
|
|
|
|
if (rt_strstr((char *)lte_dev.at_buf, "\"closed\"") != RT_NULL) { |
|
|
|
|
|
lte_dev.socket_closed_pending = true; |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
number = header + rt_strlen("+QIRD:"); |
|
|
|
|
|
payload_length = parse_decimal(&number); |
|
|
|
|
|
payload = rt_strstr((char *)number, "\r\n"); |
|
|
|
|
|
if (payload_length < 0 || payload == RT_NULL) continue; |
|
|
|
|
|
payload += 2; |
|
|
|
|
|
if ((rt_size_t)(payload - (char *)lte_dev.at_buf) + payload_length + 6 > used) |
|
|
|
|
|
continue; |
|
|
|
|
|
if (payload_length > capacity) { |
|
|
|
|
|
lte_diag.socket_read_errors++; |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
if (header > (char *)lte_dev.at_buf) |
|
|
|
|
|
lte_process_text(lte_dev.at_buf, (rt_size_t)(header - (char *)lte_dev.at_buf)); |
|
|
|
|
|
if (payload_length > 0) rt_memcpy(data, payload, payload_length); |
|
|
|
|
|
lte_process_text((uint8_t *)payload + payload_length, 6); |
|
|
|
|
|
return (int16_t)payload_length; |
|
|
|
|
|
} |
|
|
|
|
|
lte_diag.socket_read_errors++; |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BSP_LTE_PollSocketUrc(uint32_t waittime) { |
|
|
|
|
|
rt_ssize_t length; |
|
|
|
|
|
|
|
|
|
|
|
if (rt_sem_take(lte_dev.com_dev_rx_sem, waittime) != RT_EOK) return; |
|
|
|
|
|
do { |
|
|
|
|
|
length = lte_read_available(lte_dev.at_buf, sizeof(lte_dev.at_buf)); |
|
|
|
|
|
if (length > 0) lte_process_text(lte_dev.at_buf, (rt_size_t)length); |
|
|
|
|
|
} while (length > 0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void BSP_LTE_InitLogClock(void) { |
|
|
void BSP_LTE_InitLogClock(void) { |
|
|
if (lte_log_clock_query_done) { |
|
|
if (lte_log_clock_query_done) { |
|
|
return; |
|
|
return; |
|
|
@ -151,6 +601,104 @@ 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, |
|
|
int16_t BSP_LTE_SendCmd(const char *cmd, const char *expect, const char *error, |
|
|
uint32_t waittime) { |
|
|
uint32_t waittime) { |
|
|
lte_diag_at_begin(cmd); |
|
|
lte_diag_at_begin(cmd); |
|
|
@ -167,6 +715,7 @@ int16_t BSP_LTE_SendCmd(const char *cmd, const char *expect, const char *error, |
|
|
sizeof(lte_dev.at_buf)); |
|
|
sizeof(lte_dev.at_buf)); |
|
|
if (read_len > 0) { |
|
|
if (read_len > 0) { |
|
|
lte_diag_uart2_rx((rt_size_t)read_len); |
|
|
lte_diag_uart2_rx((rt_size_t)read_len); |
|
|
|
|
|
lte_process_text(lte_dev.at_buf, (rt_size_t)read_len); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
LOG_I("%s\n", lte_dev.at_buf); |
|
|
LOG_I("%s\n", lte_dev.at_buf); |
|
|
|