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.
979 lines
28 KiB
979 lines
28 KiB
/*
|
|
* L505.c
|
|
*
|
|
* Created on: Apr 1, 2021
|
|
* Author: wushufeng
|
|
*/
|
|
|
|
#include "drv_ec800k.h"
|
|
#include <stdint.h>
|
|
#include "VK_Com.h"
|
|
#include "VK_Log.h"
|
|
#include "rtdef.h"
|
|
#include "rtthread.h"
|
|
#include "rttypes.h"
|
|
|
|
#define DBG_TAG "DTU_LOG"
|
|
#define DBG_LVL DBG_INFO
|
|
#include "rtdbg.h"
|
|
|
|
|
|
Cclient_t client1 = {
|
|
.mode = "TCP",
|
|
/*教培IP和PORT*/
|
|
.ip = "uavedu.jiagutech.com",
|
|
.port = "19763",
|
|
.connect_ID = 0,
|
|
.connect_sta = false,
|
|
.error_cnt = 0,
|
|
};
|
|
|
|
CLte_dev_t lte_dev = {
|
|
.client1 = (Cclient_t *)&client1,
|
|
.config_sta = false,
|
|
.reset_flag = DTU_CF_NEED_RESET,
|
|
.dev_init_flag = true,
|
|
.data_tx_paused = false,
|
|
};
|
|
|
|
lte_diag_t lte_diag = {0};
|
|
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) {
|
|
rt_size_t i;
|
|
|
|
lte_diag.at_commands++;
|
|
lte_diag.last_at_elapsed = rt_tick_get();
|
|
lte_diag.last_at_result = -2;
|
|
for (i = 0; i < sizeof(lte_diag.last_at_cmd) - 1 && cmd[i] != '\0'; i++) {
|
|
lte_diag.last_at_cmd[i] = (cmd[i] == '\r' || cmd[i] == '\n') ? '_' : cmd[i];
|
|
}
|
|
lte_diag.last_at_cmd[i] = '\0';
|
|
}
|
|
|
|
void lte_diag_at_end(rt_int32_t result) {
|
|
rt_tick_t now = rt_tick_get();
|
|
lte_diag.last_at_elapsed = now - lte_diag.last_at_elapsed;
|
|
lte_diag.last_at_result = result;
|
|
if (result == -1) {
|
|
lte_diag.at_timeouts++;
|
|
} else if (result != 0) {
|
|
lte_diag.at_errors++;
|
|
}
|
|
}
|
|
|
|
void lte_diag_uart2_rx(rt_size_t size) {
|
|
lte_diag.uart2_rx_bytes += size;
|
|
lte_diag.last_uart2_rx_tick = rt_tick_get();
|
|
}
|
|
|
|
void lte_diag_uart2_tx(rt_size_t size) {
|
|
lte_diag.uart2_tx_bytes += size;
|
|
lte_diag.last_uart2_tx_tick = rt_tick_get();
|
|
}
|
|
|
|
void lte_diag_uart_error(const char *name, rt_uint32_t error_code) {
|
|
lte_diag.last_uart_error_code = error_code;
|
|
if (name != RT_NULL && rt_strcmp(name, "uart2") == 0) {
|
|
lte_diag.uart2_error_count++;
|
|
} else if (name != RT_NULL && rt_strcmp(name, "uart3") == 0) {
|
|
lte_diag.uart3_error_count++;
|
|
}
|
|
}
|
|
|
|
void lte_diag_fmu_rx(rt_size_t size) {
|
|
lte_diag.fmu_rx_bytes += 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_fmu_tx(rt_size_t size) {
|
|
lte_diag.fmu_tx_bytes += size;
|
|
lte_diag.last_fmu_tx_tick = rt_tick_get();
|
|
}
|
|
|
|
void lte_diag_connect_attempt(void) {
|
|
lte_diag.connect_attempts++;
|
|
if (lte_diag.connect_attempts > 1) {
|
|
lte_diag.reconnect_count++;
|
|
}
|
|
}
|
|
|
|
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.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) {
|
|
lte_diag.reset_count++;
|
|
}
|
|
|
|
void BSP_LTE_SendData(uint8_t *pdata, uint32_t length) {
|
|
if (lte_dev.com_dev != RT_NULL) {
|
|
if (lte_dev.data_tx_mutex != RT_NULL) {
|
|
rt_mutex_take(lte_dev.data_tx_mutex, RT_WAITING_FOREVER);
|
|
}
|
|
rt_ssize_t written = rt_device_write(lte_dev.com_dev, 0, pdata, length);
|
|
if (written > 0) {
|
|
lte_diag_uart2_tx((rt_size_t)written);
|
|
}
|
|
if (written != (rt_ssize_t)length) {
|
|
lte_diag.uart2_write_failures++;
|
|
}
|
|
if (lte_dev.data_tx_mutex != RT_NULL) {
|
|
rt_mutex_release(lte_dev.data_tx_mutex);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BSP_LTE_SetDataTxPaused(bool paused) {
|
|
if (lte_dev.data_tx_mutex != RT_NULL) {
|
|
rt_mutex_take(lte_dev.data_tx_mutex, RT_WAITING_FOREVER);
|
|
}
|
|
lte_dev.data_tx_paused = paused;
|
|
if (lte_dev.data_tx_mutex != RT_NULL) {
|
|
rt_mutex_release(lte_dev.data_tx_mutex);
|
|
}
|
|
}
|
|
|
|
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) {
|
|
if (lte_log_clock_query_done) {
|
|
return;
|
|
}
|
|
|
|
lte_log_clock_query_done = true;
|
|
if (BSP_LTE_SendCmd(AT_QLTS, DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
LTE_CMD_WAIT_NORMAL) == 0) {
|
|
if (dev_log_time_set_from_at((const char *)lte_dev.at_buf) != 0) {
|
|
LOG_W("EC800K clock is not synchronized; using untimestamped logs\n");
|
|
}
|
|
} else {
|
|
LOG_W("EC800K clock query failed; using untimestamped logs\n");
|
|
}
|
|
}
|
|
|
|
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);
|
|
LOG_I("%s\n", cmd);
|
|
BSP_LTE_SendData((uint8_t *)cmd, rt_strlen(cmd));
|
|
|
|
rt_err_t ret = rt_sem_take(lte_dev.com_dev_rx_sem, waittime);
|
|
if (ret == RT_EOK) {
|
|
rt_thread_mdelay(500);
|
|
|
|
rt_memset(lte_dev.at_buf, 0, sizeof(lte_dev.at_buf));
|
|
|
|
rt_ssize_t read_len = rt_device_read(lte_dev.com_dev, 0, lte_dev.at_buf,
|
|
sizeof(lte_dev.at_buf));
|
|
if (read_len > 0) {
|
|
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);
|
|
/* 清空缓存 */
|
|
uint8_t c;
|
|
while (rt_device_read(lte_dev.com_dev, 0, &c, 1) == 1) {
|
|
}
|
|
|
|
if (expect != NULL && NULL != rt_strstr((char *)lte_dev.at_buf, expect)) {
|
|
lte_diag_at_end(0);
|
|
return 0;
|
|
} else if (error != NULL && NULL != rt_strstr((char *)lte_dev.at_buf, error)) {
|
|
lte_diag_at_end(1);
|
|
return 1;
|
|
} else {
|
|
lte_diag_at_end(2);
|
|
return 2;
|
|
}
|
|
} else {
|
|
lte_diag_at_end(-1);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int16_t BSP_LTE_SendATE(int16_t retry) {
|
|
do {
|
|
if (0 == BSP_LTE_SendCmd(AT_ATE0, DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
LTE_CMD_WAIT_NORMAL)) {
|
|
return 0;
|
|
}
|
|
retry--;
|
|
} while (retry);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int extract_number(const char *src, char *dest) {
|
|
if(src == RT_NULL || dest == RT_NULL){
|
|
return -1;
|
|
}
|
|
char *start = NULL;
|
|
char *end = NULL;
|
|
if (strchr(src, '\n') != NULL) {
|
|
start = strchr(src, '\n') + 1;
|
|
if (start != NULL) {
|
|
end = strchr(start, '\r');
|
|
}
|
|
}
|
|
if (start != NULL && end != NULL) {
|
|
int length = end - start;
|
|
if(length >= 30){
|
|
return -1;
|
|
}
|
|
strncpy(dest, start, length);
|
|
dest[length] = '\0';
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int BSP_LTE_GetIMEI(char *pIMEI) {
|
|
int ret = 0;
|
|
// while (0 != BSP_LTE_SendCmd(AT_IMEI, DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
// LTE_CMD_WAIT_NORMAL));
|
|
ret = BSP_LTE_SendCmd(AT_IMEI, DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
LTE_CMD_WAIT_NORMAL);
|
|
if (ret != 0) {
|
|
return -1;
|
|
}
|
|
if (extract_number((const char *)lte_dev.at_buf, pIMEI) == -1) {
|
|
return -1;
|
|
}
|
|
if (strlen(pIMEI) < 10) {
|
|
ret = -1;
|
|
}
|
|
if (pIMEI[15] == '\"')
|
|
pIMEI[15] = 0;
|
|
return ret;
|
|
}
|
|
|
|
int BSP_LTE_GetICCID(char *pICCID) {
|
|
char *start = NULL;
|
|
char *end = NULL;
|
|
int ret = 0;
|
|
// while (0 != BSP_LTE_SendCmd(AT_ICCID, DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
// LTE_CMD_WAIT_LONG));
|
|
ret = BSP_LTE_SendCmd(AT_ICCID, DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
LTE_CMD_WAIT_LONG);
|
|
if(ret != 0){
|
|
return -1;
|
|
}
|
|
if(rt_strstr((const char *)lte_dev.at_buf, "+ICCID:") != NULL){
|
|
start =
|
|
rt_strstr((const char *)lte_dev.at_buf, "+ICCID:") + rt_strlen("+ICCID:") + 1;
|
|
}
|
|
if(start == RT_NULL){
|
|
return -1;
|
|
}
|
|
end = start;
|
|
while (*end != '\0' && *end != '\r' && *end != '\n') end++;
|
|
rt_size_t len = end - start;
|
|
if(len >= 30){
|
|
return -1;
|
|
}
|
|
rt_memcpy(pICCID, start, len);
|
|
pICCID[len] = '\0';
|
|
|
|
if (strlen(pICCID) < 10) {
|
|
ret = -1;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#define CSQ_CMD_RESP "+CSQ:"
|
|
int8_t BSP_LTE_GetCSQ(void) {
|
|
int8_t ret = 0;
|
|
char *start;
|
|
|
|
if (0 != BSP_LTE_SendCmd(AT_CSQ, DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
LTE_CMD_WAIT_LONG)) {
|
|
return -1;
|
|
}
|
|
|
|
start = rt_strstr((const char *)lte_dev.at_buf, CSQ_CMD_RESP);
|
|
if (start == RT_NULL) {
|
|
return -1;
|
|
}
|
|
|
|
start += rt_strlen(CSQ_CMD_RESP) + 1;
|
|
|
|
while (*start >= '0' && *start <= '9') {
|
|
ret = ret * 10 + (*start - '0');
|
|
start++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int16_t BSP_LTE_SendATCPIN(int16_t retry) {
|
|
do {
|
|
if (0 ==
|
|
BSP_LTE_SendCmd(AT_CPIN, "READY", DEFAULT_ERROR, LTE_CMD_WAIT_NORMAL)) {
|
|
return 0;
|
|
} else if (NULL != strstr((char *)lte_dev.at_buf, "ERROR: 10")) {
|
|
// No SimCard
|
|
return 1;
|
|
}
|
|
|
|
retry--;
|
|
} while (retry);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int16_t BSP_LTE_GetCEREG(int16_t retry) {
|
|
do {
|
|
if (0 ==
|
|
BSP_LTE_SendCmd(AT_CEREG, CEREG_OK, DEFAULT_ERROR, LTE_CMD_WAIT_LONG)) {
|
|
return 0;
|
|
} else if (0 == BSP_LTE_SendCmd(AT_CEREG, "+CEREG: 0,5\r\n\r\nOK",
|
|
DEFAULT_ERROR, LTE_CMD_WAIT_LONG)) {
|
|
return 0;
|
|
} else if (0 == BSP_LTE_SendCmd(AT_CEREG, CEREG_OK_2, DEFAULT_ERROR,
|
|
LTE_CMD_WAIT_LONG)) {
|
|
return 0;
|
|
} else if (0 == BSP_LTE_SendCmd(AT_CEREG, DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
LTE_CMD_WAIT_LONG)) {
|
|
return 0;
|
|
}
|
|
retry--;
|
|
} while (retry);
|
|
return -1;
|
|
}
|
|
|
|
static rt_err_t lte_com_rx_cb(rt_device_t dev, rt_size_t size) {
|
|
lte_diag.uart2_rx_events++;
|
|
if (lte_dev.com_dev_rx_sem != RT_NULL) {
|
|
rt_sem_release(lte_dev.com_dev_rx_sem);
|
|
}
|
|
return RT_EOK;
|
|
}
|
|
|
|
void BSP_LET_Register_Com(rt_device_t com_dev) {
|
|
if (lte_dev.com_dev_rx_sem == RT_NULL) {
|
|
lte_dev.com_dev_rx_sem = rt_sem_create("lteRx", 0, RT_IPC_FLAG_PRIO);
|
|
}
|
|
|
|
lte_dev.com_dev = com_dev;
|
|
if (lte_dev.data_tx_mutex == RT_NULL) {
|
|
lte_dev.data_tx_mutex = rt_mutex_create("lteTx", RT_IPC_FLAG_PRIO);
|
|
}
|
|
BSP_LTE_SetDataTxPaused(false);
|
|
}
|
|
|
|
/*
|
|
函数功能:配置EC800K
|
|
*/
|
|
void BSP_LTE_Config(void) {
|
|
int res = 0;
|
|
|
|
rt_device_set_rx_indicate(lte_dev.com_dev, lte_com_rx_cb);
|
|
|
|
uint8_t c = 0;
|
|
|
|
//rt_thread_mdelay(3000);
|
|
BSP_LTE_SendData((uint8_t *)"+++", 3);
|
|
rt_thread_mdelay(2000);
|
|
BSP_LTE_SendData((uint8_t *)"+++", 3);
|
|
rt_thread_mdelay(2000);
|
|
while (rt_device_read(lte_dev.com_dev, 0, &c, 1) == 1);
|
|
|
|
while (0 != BSP_LTE_SendATE(3)) {
|
|
rt_thread_mdelay(500);
|
|
LOG_I("BSP_LTE_SendATE error\n");
|
|
}
|
|
|
|
/* Allow the network to update the module clock after registration. */
|
|
BSP_LTE_SendCmd(AT_CTZU, DEFAULT_EXPECT, DEFAULT_ERROR, LTE_CMD_WAIT_NORMAL);
|
|
|
|
/*查询模块信息*/
|
|
if (lte_dev.dev_init_flag == true) {
|
|
BSP_LTE_SendCmd(AT_ATI, DEFAULT_EXPECT, DEFAULT_ERROR, LTE_CMD_WAIT_NORMAL);
|
|
}
|
|
/*查询SIM卡是否存在*/
|
|
res = BSP_LTE_SendATCPIN(3);
|
|
if (res == 1) {
|
|
return;
|
|
}
|
|
|
|
/*请求移动设备的识别码*/
|
|
if (lte_dev.dev_init_flag == true) {
|
|
if (BSP_LTE_GetIMEI(lte_dev.imei) == -1) {
|
|
return;
|
|
}
|
|
|
|
/*请求sim卡号码*/
|
|
if (BSP_LTE_GetICCID(lte_dev.iccid) == -1) {
|
|
return;
|
|
}
|
|
}
|
|
/*查询信号强度*/
|
|
res = BSP_LTE_GetCSQ();
|
|
if (res != -1) lte_dev.csq = res;
|
|
|
|
/*查询网络注册状态*/
|
|
res = BSP_LTE_GetCEREG(3);
|
|
if(res == -1){
|
|
return;
|
|
}
|
|
/*配置应用场景*/
|
|
BSP_LTE_SendCmd(AT_QICSGP, DEFAULT_EXPECT, DEFAULT_ERROR, LTE_CMD_WAIT_LONG);
|
|
//BSP_LTE_SendCmd(AT_QICSGP_CTIOT, DEFAULT_EXPECT, DEFAULT_ERROR, LTE_CMD_WAIT_LONG);
|
|
//BSP_LTE_SendCmd(AT_QICSGP_CMTDS, DEFAULT_EXPECT, DEFAULT_ERROR, LTE_CMD_WAIT_LONG);
|
|
/*定义 PDP 上下文*/
|
|
BSP_LTE_SendCmd("AT+CGDCONT?\r\n", DEFAULT_EXPECT, DEFAULT_ERROR,
|
|
LTE_CMD_WAIT_NORMAL);
|
|
//+CGDCONT: 1,"IP","cmiot","0.0.0.0",0,0,0,0,0,0....OK
|
|
|
|
lte_dev.config_sta = true;
|
|
lte_dev.dev_init_flag = false;
|
|
}
|
|
//------------------End of File----------------------------
|
|
|