/* * L505.c * * Created on: Apr 1, 2021 * Author: wushufeng */ #include "drv_ec800k.h" #include #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; 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 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; } } 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_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; } 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; 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++; 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"); } } 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); } 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----------------------------