| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- /*
- * YM310 Module Initialization - STABLE v5.3 (No Network Check)
- *
- * Core principles:
- * - AT core init only once, no re-init on retries
- * - Init thread created once, never restart
- * - After init complete, enter idle state, network maintenance by maintain thread
- * - Do not modify at_core.c to keep stability
- */
- #define DBG_TAG "Y-INT"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include "ym310_mqtt.h"
- #include <string.h>
- #include <stdio.h>
- /*=============================================================================
- * Global Variables
- *=============================================================================*/
- rt_thread_t g_init_thread = RT_NULL;
- static volatile rt_bool_t s_init_thread_running = RT_FALSE;
- static volatile rt_bool_t s_module_initialized = RT_FALSE;
- static volatile rt_bool_t s_network_ready = RT_FALSE;
- static volatile rt_bool_t s_at_core_initialized = RT_FALSE;
- /* Retry state machine */
- typedef enum
- {
- INIT_STATE_STARTING = 0, /* Starting */
- INIT_STATE_POWER_ON, /* Power on */
- INIT_STATE_BASIC_CONFIG, /* Basic config (including SIM detection) */
- INIT_STATE_WAIT_NETWORK, /* Wait for network registration */
- INIT_STATE_ACTIVATE_PDP, /* Activate PDP */
- INIT_STATE_COMPLETE, /* Init complete */
- INIT_STATE_RETRY_WAIT /* Wait for retry */
- } init_state_t;
- static init_state_t s_init_state = INIT_STATE_STARTING;
- static int s_retry_count = 0;
- static rt_tick_t s_retry_start_tick = 0;
- /* 配置参数 */
- #define RETRY_DELAY_MS 30000 /* 重试间隔30秒 */
- #define SIM_WAIT_MAX 30 /* SIM等待最多30秒 */
- #define NETWORK_WAIT_MAX 60 /* 网络等待最多60秒 */
- /* 日志记录阈值 */
- #define FAIL_THRESHOLD 3 /* 连续失败3次才记录 */
- #define LOG_INTERVAL_MS (10 * 60 * 1000) /* 日志记录间隔10分钟 */
- /* 故障类型枚举 - 细化原因 */
- typedef enum
- {
- FAIL_TYPE_SIM_NOT_INSERT = 1, /* SIM未插入 */
- FAIL_TYPE_SIM_INVALID, /* SIM失效/损坏 */
- FAIL_TYPE_SIM_UNKNOWN, /* SIM其他错误 */
- FAIL_TYPE_NETWORK_REG, /* 网络注册失败 */
- FAIL_TYPE_PDP_ACT /* PDP激活失败 */
- } fail_type_t;
- /* 各故障类型的记录状态 */
- typedef struct
- {
- fail_type_t type;
- const char *desc;
- int consecutive_count; /* 当前连续失败次数 */
- rt_tick_t last_log_tick; /* 上次记录时间 */
- } fail_status_t;
- static fail_status_t s_fail_status[] = {
- {FAIL_TYPE_SIM_NOT_INSERT, "SIM未插入", 0, 0},
- {FAIL_TYPE_SIM_INVALID, "SIM失效", 0, 0},
- {FAIL_TYPE_SIM_UNKNOWN, "SIM错误", 0, 0},
- {FAIL_TYPE_NETWORK_REG, "网络注册", 0, 0},
- {FAIL_TYPE_PDP_ACT, "PDP激活", 0, 0}};
- /* 外部函数声明 */
- #include "ecode.h"
- extern void Recode_e_code(ecode_list code, uint16_t para, char *detail);
- extern int ym310_at_core_init(void);
- /*=============================================================================
- * SIM Card Status Detection
- *=============================================================================*/
- static int check_sim_status(char *error_detail, int detail_size)
- {
- at_resp_type_t resp;
- char resp_buf[128];
- resp = ym310_at_exec_cmd("AT+CPIN?", resp_buf, sizeof(resp_buf), YM310_AT_CMD_TIMEOUT_MS);
- if (resp != AT_RESP_OK)
- {
- rt_snprintf(error_detail, detail_size, "Query failed");
- return -1;
- }
- if (rt_strstr(resp_buf, "READY") != RT_NULL)
- {
- return 0;
- }
- else if (rt_strstr(resp_buf, "SIM NOT INSERTED") != RT_NULL ||
- rt_strstr(resp_buf, "NOT INSERTED") != RT_NULL)
- {
- rt_snprintf(error_detail, detail_size, "SIM not inserted");
- return FAIL_TYPE_SIM_NOT_INSERT;
- }
- else if (rt_strstr(resp_buf, "SIM PIN") != RT_NULL)
- {
- rt_snprintf(error_detail, detail_size, "PIN required");
- return FAIL_TYPE_SIM_INVALID;
- }
- else if (rt_strstr(resp_buf, "SIM PUK") != RT_NULL)
- {
- rt_snprintf(error_detail, detail_size, "PUK required");
- return FAIL_TYPE_SIM_INVALID;
- }
- else if (rt_strstr(resp_buf, "SIM ERROR") != RT_NULL ||
- rt_strstr(resp_buf, "ERROR") != RT_NULL)
- {
- rt_snprintf(error_detail, detail_size, "SIM card error");
- return FAIL_TYPE_SIM_INVALID;
- }
- else
- {
- rt_snprintf(error_detail, detail_size, "Unknown status");
- return FAIL_TYPE_SIM_UNKNOWN;
- }
- }
- /*=============================================================================
- * Smart Log Recording - 10 minute interval
- *=============================================================================*/
- static void log_persistent_failure(fail_type_t type, int fail_count, const char *extra_info)
- {
- char detail[128];
- rt_tick_t now = rt_tick_get();
- rt_tick_t log_interval = rt_tick_from_millisecond(LOG_INTERVAL_MS);
- for (int i = 0; i < sizeof(s_fail_status) / sizeof(s_fail_status[0]); i++)
- {
- if (s_fail_status[i].type == type)
- {
- if (now - s_fail_status[i].last_log_tick < log_interval)
- {
- LOG_D("Skip logging %s: within %d min",
- s_fail_status[i].desc, LOG_INTERVAL_MS / 60000);
- return;
- }
- s_fail_status[i].last_log_tick = now;
- if (extra_info && extra_info[0] != '\0')
- {
- rt_snprintf(detail, sizeof(detail), "%s(%d次) %s",
- s_fail_status[i].desc, fail_count, extra_info);
- }
- else
- {
- rt_snprintf(detail, sizeof(detail), "%s(%d次)",
- s_fail_status[i].desc, fail_count);
- }
- LOG_W("%s", detail);
- Recode_e_code(e_NET_INIT_FAIL, fail_count, detail);
- return;
- }
- }
- }
- static void reset_fail_counter(fail_type_t type)
- {
- for (int i = 0; i < sizeof(s_fail_status) / sizeof(s_fail_status[0]); i++)
- {
- if (s_fail_status[i].type == type)
- {
- s_fail_status[i].consecutive_count = 0;
- break;
- }
- }
- }
- static void increment_fail_counter(fail_type_t type, const char *extra_info)
- {
- for (int i = 0; i < sizeof(s_fail_status) / sizeof(s_fail_status[0]); i++)
- {
- if (s_fail_status[i].type == type)
- {
- s_fail_status[i].consecutive_count++;
- if (s_fail_status[i].consecutive_count >= FAIL_THRESHOLD)
- {
- log_persistent_failure(type, s_fail_status[i].consecutive_count, extra_info);
- s_fail_status[i].consecutive_count = 0;
- }
- break;
- }
- }
- }
- extern void gpio_lte_ctrl(rt_bool_t on);
- /*=============================================================================
- * Module Power Control
- *=============================================================================*/
- static int ym310_power_on(void)
- {
- LOG_I("Powering on YM310 module...");
- gpio_lte_ctrl(1);
- rt_thread_mdelay(1000);
- int retry = 0;
- while (retry < 10)
- {
- at_resp_type_t resp;
- char buf[64];
- resp = ym310_at_exec_cmd("AT", buf, sizeof(buf), 3000);
- if (resp == AT_RESP_OK)
- {
- LOG_I("Module responded to AT");
- rt_thread_mdelay(500);
- return RT_EOK;
- }
- retry++;
- rt_thread_mdelay(500);
- }
- LOG_W("Module may not be fully ready, continuing anyway");
- return RT_EOK;
- }
- /*=============================================================================
- * Module Basic Configuration
- *=============================================================================*/
- static int ym310_basic_config(void)
- {
- at_resp_type_t resp;
- char resp_buf[128];
- int sim_retry = 0;
- char sim_error[32];
- ym310_at_exec_cmd_with_retry("ATE0", RT_NULL, 0, YM310_AT_CMD_TIMEOUT_MS, 3);
- ym310_at_exec_cmd_with_retry("AT+CMEE=2", RT_NULL, 0, YM310_AT_CMD_TIMEOUT_MS, 3);
- while (sim_retry < SIM_WAIT_MAX)
- {
- resp = ym310_at_exec_cmd("AT+CPIN?", resp_buf, sizeof(resp_buf), YM310_AT_CMD_TIMEOUT_MS);
- if (resp == AT_RESP_OK && rt_strstr(resp_buf, "READY") != RT_NULL)
- {
- LOG_I("SIM card ready");
- reset_fail_counter(FAIL_TYPE_SIM_NOT_INSERT);
- reset_fail_counter(FAIL_TYPE_SIM_INVALID);
- reset_fail_counter(FAIL_TYPE_SIM_UNKNOWN);
- return RT_EOK;
- }
- sim_retry++;
- rt_thread_mdelay(1000);
- }
- int sim_status = check_sim_status(sim_error, sizeof(sim_error));
- if (sim_status > 0)
- {
- increment_fail_counter((fail_type_t)sim_status, sim_error);
- }
- else
- {
- increment_fail_counter(FAIL_TYPE_SIM_UNKNOWN, "SIM not ready");
- }
- LOG_W("SIM not ready after %d retries >>>%s<<<", SIM_WAIT_MAX, resp_buf);
- return -RT_ERROR;
- }
- /*=============================================================================
- * Network Registration
- *=============================================================================*/
- static int ym310_wait_for_network(void)
- {
- int retry_count = 0;
- LOG_D("Waiting for network registration...");
- while (retry_count < NETWORK_WAIT_MAX)
- {
- if (ym310_check_network_connected() == RT_TRUE)
- {
- LOG_D("Network registered and GPRS attached");
- reset_fail_counter(FAIL_TYPE_NETWORK_REG);
- return RT_EOK;
- }
- retry_count++;
- if (retry_count % 10 == 0)
- {
- LOG_D("Waiting for network... (%d/%d)", retry_count, NETWORK_WAIT_MAX);
- }
- rt_thread_mdelay(1000);
- }
- LOG_W("Network registration timeout");
- increment_fail_counter(FAIL_TYPE_NETWORK_REG, NULL);
- return -RT_ERROR;
- }
- /*=============================================================================
- * PDP Context Activation
- *=============================================================================*/
- static int ym310_activate_pdp(void)
- {
- at_resp_type_t resp;
- LOG_D("Activating PDP context...");
- if (ym310_check_network_connected() == RT_TRUE)
- {
- LOG_D("PDP already active");
- reset_fail_counter(FAIL_TYPE_PDP_ACT);
- return RT_EOK;
- }
- resp = ym310_at_exec_cmd("AT+QIPACT=1", RT_NULL, 0, YM310_AT_LONG_TIMEOUT_MS);
- if (resp != AT_RESP_OK)
- {
- rt_thread_mdelay(2000);
- if (ym310_check_network_connected() == RT_TRUE)
- {
- LOG_I("PDP activated successfully (verified)");
- reset_fail_counter(FAIL_TYPE_PDP_ACT);
- return RT_EOK;
- }
- LOG_W("PDP activation failed");
- increment_fail_counter(FAIL_TYPE_PDP_ACT, NULL);
- return -RT_ERROR;
- }
- rt_thread_mdelay(2000);
- if (ym310_check_network_connected() == RT_TRUE)
- {
- LOG_I("PDP activated");
- reset_fail_counter(FAIL_TYPE_PDP_ACT);
- return RT_EOK;
- }
- increment_fail_counter(FAIL_TYPE_PDP_ACT, NULL);
- return -RT_ERROR;
- }
- /*=============================================================================
- * Init Thread - Only handles init, enters idle state after completion
- *=============================================================================*/
- static void ym310_init_thread_entry(void *param)
- {
- int ret;
- // LOG_I("========================================");
- // LOG_I("INITIALIZATION THREAD STARTED");
- // LOG_I("========================================");
- s_init_thread_running = RT_TRUE;
- s_init_state = INIT_STATE_STARTING;
- /* Main loop - only handles init, enters idle sleep after completion */
- while (s_init_thread_running)
- {
- switch (s_init_state)
- {
- case INIT_STATE_STARTING:
- if (!s_at_core_initialized)
- {
- LOG_I("Initializing AT core...");
- if (ym310_at_core_init() == RT_EOK)
- {
- s_at_core_initialized = RT_TRUE;
- // LOG_I("AT core initialized");
- s_init_state = INIT_STATE_POWER_ON;
- }
- else
- {
- LOG_E("AT core init failed, will retry later");
- s_init_state = INIT_STATE_RETRY_WAIT;
- s_retry_start_tick = rt_tick_get();
- }
- }
- else
- {
- s_init_state = INIT_STATE_POWER_ON;
- }
- rt_thread_mdelay(100);
- break;
- case INIT_STATE_RETRY_WAIT:
- if ((rt_tick_get() - s_retry_start_tick) >= rt_tick_from_millisecond(RETRY_DELAY_MS))
- {
- s_retry_count++;
- LOG_I("Retry configuration (%d)...", s_retry_count + 1);
- if (s_at_core_initialized)
- {
- s_init_state = INIT_STATE_POWER_ON;
- }
- else
- {
- if (ym310_at_core_init() == RT_EOK)
- {
- s_at_core_initialized = RT_TRUE;
- s_init_state = INIT_STATE_POWER_ON;
- }
- else
- {
- LOG_E("AT core init failed again");
- s_retry_start_tick = rt_tick_get();
- }
- }
- }
- rt_thread_mdelay(1000);
- break;
- case INIT_STATE_POWER_ON:
- ret = ym310_power_on();
- if (ret == RT_EOK)
- {
- s_init_state = INIT_STATE_BASIC_CONFIG;
- }
- else
- {
- LOG_W("Power on failed, retry later");
- s_init_state = INIT_STATE_RETRY_WAIT;
- s_retry_start_tick = rt_tick_get();
- }
- rt_thread_mdelay(100);
- break;
- case INIT_STATE_BASIC_CONFIG:
- ret = ym310_basic_config();
- if (ret == RT_EOK)
- {
- s_init_state = INIT_STATE_WAIT_NETWORK;
- }
- else
- {
- LOG_W("Basic config failed (SIM issue), will retry later");
- s_init_state = INIT_STATE_RETRY_WAIT;
- s_retry_start_tick = rt_tick_get();
- }
- rt_thread_mdelay(100);
- break;
- case INIT_STATE_WAIT_NETWORK:
- ret = ym310_wait_for_network();
- if (ret == RT_EOK)
- {
- s_init_state = INIT_STATE_ACTIVATE_PDP;
- }
- else
- {
- LOG_W("Network not ready, will retry later");
- s_init_state = INIT_STATE_RETRY_WAIT;
- s_retry_start_tick = rt_tick_get();
- }
- rt_thread_mdelay(100);
- break;
- case INIT_STATE_ACTIVATE_PDP:
- ret = ym310_activate_pdp();
- if (ret == RT_EOK)
- {
- /* ===== 新增:PDP激活成功后立即同步NTP时间 ===== */
- LOG_I("PDP activated, syncing NTP time...");
- if (ym310_ntp_sync_time() == RT_EOK)
- {
- LOG_I("NTP sync successful during init");
- }
- else
- {
- LOG_W("NTP sync failed during init, will retry later");
- }
- /* ============================================= */
- s_init_state = INIT_STATE_COMPLETE;
- s_module_initialized = RT_TRUE;
- s_network_ready = RT_TRUE;
- s_retry_count = 0;
- LOG_D("========================================");
- LOG_D("MODULE INITIALIZATION COMPLETE");
- LOG_D("========================================");
- /* Start MQTT thread (only once) */
- if (g_mqtt_thread == RT_NULL)
- {
- g_mqtt_thread = ym310_start_mqtt_thread();
- if (g_mqtt_thread == RT_NULL)
- {
- LOG_E("Failed to start MQTT thread!");
- }
- }
- /* Start maintenance thread (only once) */
- if (g_maintain_thread == RT_NULL)
- {
- g_maintain_thread = ym310_start_maintain_thread();
- if (g_maintain_thread == RT_NULL)
- {
- LOG_E("Failed to start maintenance thread!");
- }
- }
- /* Init complete, enter idle state, no more checks (maintain thread handles) */
- s_init_state = INIT_STATE_COMPLETE;
- }
- else
- {
- LOG_W("PDP activation failed, will retry later");
- s_init_state = INIT_STATE_RETRY_WAIT;
- s_retry_start_tick = rt_tick_get();
- }
- rt_thread_mdelay(100);
- break;
- case INIT_STATE_COMPLETE:
- /* Init complete, thread sleeps, no more work */
- rt_thread_mdelay(1000); /* Wake once per minute, do nothing, keep thread alive */
- s_init_thread_running = RT_FALSE;
- break;
- default:
- break;
- }
- }
- LOG_I("Initialization thread exit");
- }
- /*=============================================================================
- * Public API
- *=============================================================================*/
- rt_thread_t ym310_start_init_thread(void)
- {
- if (g_init_thread != RT_NULL)
- {
- LOG_D("Init thread already running");
- return g_init_thread;
- }
- if (ym310_mqtt_init() != RT_EOK)
- {
- LOG_E("MQTT init failed!");
- return RT_NULL;
- }
- g_init_thread = rt_thread_create("ym310_init", ym310_init_thread_entry,
- RT_NULL, INIT_THREAD_STACK_SIZE,
- INIT_THREAD_PRIORITY, 10);
- if (g_init_thread == RT_NULL)
- {
- LOG_E("Failed to create init thread!");
- return RT_NULL;
- }
- rt_thread_startup(g_init_thread);
- LOG_D("Initialization thread created");
- return g_init_thread;
- }
- void ym310_init_thread_stop(void)
- {
- s_init_thread_running = RT_FALSE;
- }
- rt_bool_t ym310_is_module_initialized(void)
- {
- return s_module_initialized;
- }
- rt_bool_t ym310_is_network_ready(void)
- {
- return s_network_ready;
- }
|