diff --git a/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_ble_main.c b/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_ble_main.c index dbc4c4e..7da71bc 100755 --- a/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_ble_main.c +++ b/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_ble_main.c @@ -665,8 +665,9 @@ int hilink_ble_main(void) #endif /* 启动Hilink SDK */ - if (HILINK_Main() != 0) { - HILINK_SAL_NOTICE("HILINK_Main start error"); + ret = HILINK_Main(); + if (ret != 0) { + HILINK_SAL_NOTICE("HILINK_Main start error:%d\r\n", ret); return -1; } e_printf("HILINK_Main start success\r\n"); diff --git a/application/samples/wifi/ohos_connect/hilink_adapt/product/hilink_device.c b/application/samples/wifi/ohos_connect/hilink_adapt/product/hilink_device.c index 75e2cae..b87a3dd 100755 --- a/application/samples/wifi/ohos_connect/hilink_adapt/product/hilink_device.c +++ b/application/samples/wifi/ohos_connect/hilink_adapt/product/hilink_device.c @@ -20,9 +20,9 @@ #include "hilink_entry.h" #endif -extern void handle_device_online(void); extern void handle_device_unbind(void); -extern void handle_device_offline(void); +extern void handle_device_register(void); +extern void handle_device_unregister(void); extern int myhandle_put_brightness(const char* svc_id, const char* payload, unsigned int len); extern int myhandle_put_cct(const char* svc_id, const char* payload, unsigned int len); @@ -598,7 +598,6 @@ void HILINK_NotifyDevStatus(int status) BLE_CfgNetAdvCtrl(0); (void)BLE_CfgNetAdvCtrl(0xFFFFFFFF); #endif - handle_device_offline(); break; case HILINK_M2M_CLOUD_ONLINE: /* 设备连接云端成功,请在此处添加实现 */ @@ -607,8 +606,6 @@ void HILINK_NotifyDevStatus(int status) BLE_CfgNetAdvCtrl(0); (void)BLE_CfgNetAdvCtrl(0xFFFFFFFF); #endif - /* 设备连接云端成功,请在此处添加实现 */ - handle_device_online(); // 处理设备上线 break; case HILINK_M2M_LONG_OFFLINE: /* 设备与云端连接长时间断开,请在此处添加实现 */ @@ -632,7 +629,6 @@ void HILINK_NotifyDevStatus(int status) case HILINK_LINK_CONNECTED_WIFI: /* 设备已经连上路由器,请在此处添加实现 */ hf_set_wifi_state(1); - handle_device_online(); break; case HILINK_M2M_CONNECTTING_CLOUD: /* 设备正在连接云端,请在此处添加实现 */ @@ -642,14 +638,17 @@ void HILINK_NotifyDevStatus(int status) hf_set_wifi_state(0); break; case HILINK_DEVICE_REGISTERED: - /* 设备被注册,请在此处添加实现 */ + /* 设备被注册:退出配网逻辑并完成绑定后的处理 */ + handle_device_register(); break; case HILINK_DEVICE_UNREGISTER: - /* 设备被解绑,请在此处添加实现 */ - handle_device_unbind(); + /* 设备被解绑:先执行解绑/下线处理,再做解绑清理 */ + handle_device_unregister(); + handle_device_unbind(); break; case HILINK_REVOKE_FLAG_SET: /* 设备被复位标记置位,请在此处添加实现 */ + handle_device_unregister(); handle_device_unbind(); break; case HILINK_NEGO_REG_INFO_FAIL: diff --git a/application/ws63/user_main/CMakeLists.txt b/application/ws63/user_main/CMakeLists.txt index d61d981..0e3b0e2 100755 --- a/application/ws63/user_main/CMakeLists.txt +++ b/application/ws63/user_main/CMakeLists.txt @@ -9,6 +9,13 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/spotlight/spotlight_main.c ${CMAKE_CURRENT_SOURCE_DIR}/spotlight/device_module.c ${CMAKE_CURRENT_SOURCE_DIR}/spotlight/factory_test.c + ${CMAKE_CURRENT_SOURCE_DIR}/debug_kit/core/dk_service.c + ${CMAKE_CURRENT_SOURCE_DIR}/debug_kit/core/dk_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/debug_kit/core/dk_wifi_scanner.c + ${CMAKE_CURRENT_SOURCE_DIR}/debug_kit/core/dk_tcp_console.c + ${CMAKE_CURRENT_SOURCE_DIR}/debug_kit/core/dk_http_ota.c + ${CMAKE_CURRENT_SOURCE_DIR}/debug_kit/core/dk_udp_announce.c + ${CMAKE_CURRENT_SOURCE_DIR}/debug_kit/core/dk_ring.c ) if (DEFINES MATCHES "CONFIG_SPOTLIGHT_UT") list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/spotlight/spotlight_ut.c) @@ -20,6 +27,7 @@ endif() set(PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/spotlight/ + ${CMAKE_CURRENT_SOURCE_DIR}/debug_kit/include ) set(PRIVATE_HEADER diff --git a/application/ws63/user_main/app_main.c b/application/ws63/user_main/app_main.c index 61f4313..861c71b 100755 --- a/application/ws63/user_main/app_main.c +++ b/application/ws63/user_main/app_main.c @@ -7,10 +7,26 @@ */ #include "hsf.h" +#include "errcode.h" +#include "systick.h" +#include "debug_kit/include/debug_kit.h" #include "spotlight.h" #ifdef HF_MCU_OTA #include "mcu_update.h" #endif + +static void *dk_delayed_start(const char *arg) +{ + (void)arg; + unsigned int wait_ms = 0; + while (!hf_hilink_main_is_runing()) { + msleep(100); + if ((wait_ms += 100) > 10000) { break; } + } + msleep(300); + debug_kit_init(); + return NULL; +} int g_module_id = HFM_TYPE_LPT262; const int hf_lpt_262_gpio_fid_to_pid_map_table[HFM_MAX_FUNC_CODE]= { @@ -223,12 +239,14 @@ int USER_FUNC user_app_main(void) HF_Debug(DEBUG_WARN,"start uart fail!\r\n"); } spotlight_main(); + // 延后启动 debug kit:等待 HiLink Main 运行后再启动,避免启动期资源竞争 + // dk_delayed_start(NULL); #ifdef HF_MCU_OTA if(hf_mcu_init() != HF_SUCCESS) HF_Debug(DEBUG_WARN,"init mcu ota fail!\r\n"); #endif //See Wi-Fi Config tools APP for detailed usage of this thread, only debug mode open - if(hfdbg_get_level()) + if(hfdbg_get_level()) { while(!hfnet_wifi_is_active()) { diff --git a/application/ws63/user_main/debug_kit/adapters/.keep b/application/ws63/user_main/debug_kit/adapters/.keep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/application/ws63/user_main/debug_kit/adapters/.keep @@ -0,0 +1 @@ + diff --git a/application/ws63/user_main/debug_kit/core/dk_config.h b/application/ws63/user_main/debug_kit/core/dk_config.h new file mode 100644 index 0000000..5efc0dd --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_config.h @@ -0,0 +1,50 @@ +#ifndef DK_CONFIG_H +#define DK_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DBG_SCAN_PERIOD_S +#define DBG_SCAN_PERIOD_S 10 +#endif +#ifndef DBG_SCAN_DWELL_MS +#define DBG_SCAN_DWELL_MS 100 +#endif +#ifndef DBG_CPU_BUSY_PCT +#define DBG_CPU_BUSY_PCT 60 +#endif +#ifndef DBG_LWIP_Q_BUSY_PCT +#define DBG_LWIP_Q_BUSY_PCT 80 +#endif +#ifndef DBG_CONSOLE_PORT +#define DBG_CONSOLE_PORT 2323 +#endif +#ifndef DBG_OTA_PORT +#define DBG_OTA_PORT 8070 +#endif +#ifndef DBG_BROADCAST_PORT +#define DBG_BROADCAST_PORT 37501 +#endif +#ifndef DBG_RING_KB +#define DBG_RING_KB 16 +#endif +#ifndef DBG_CONSOLE_RATE_KBPS +#define DBG_CONSOLE_RATE_KBPS 100 +#endif +#ifndef DBG_FIRST_CONN_TIMEOUT_S +#define DBG_FIRST_CONN_TIMEOUT_S 300 +#endif + +#define DBG_TRIGGER_SSID "EK_HF_DEBUG" + +typedef enum { + DBG_STATE_CLOSED = 0, + DBG_STATE_DEBUG = 1, +} dbg_state_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/application/ws63/user_main/debug_kit/core/dk_http_ota.c b/application/ws63/user_main/debug_kit/core/dk_http_ota.c new file mode 100644 index 0000000..c95ea78 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_http_ota.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include "securec.h" +#include "soc_osal.h" +#include "lwip/sockets.h" +#include "lwip/inet.h" +#include "dk_config.h" +#include "debug_kit.h" +#include "errcode.h" +#include "upg_definitions.h" +#include "upg_common.h" +#include "upg_verify.h" +#include "upg_alloc.h" + +static volatile bool g_http_running = false; +static bool g_upg_ready = false; + +static bool ensure_upg_ready(void) +{ + if (g_upg_ready) return true; + extern errcode_t ws63_upg_init(void); + errcode_t rc = ws63_upg_init(); + if (rc == ERRCODE_SUCC) { g_upg_ready = true; return true; } + return false; +} + +static int send_text(int fd, int code, const char *status, const char *body) +{ + char hdr[256]; + int n = snprintf(hdr, sizeof(hdr), + "HTTP/1.1 %d %s\r\nContent-Type: text/plain\r\nContent-Length: %u\r\nConnection: close\r\n\r\n", + code, status, (unsigned)strlen(body)); + (void)lwip_send(fd, hdr, n, 0); + (void)lwip_send(fd, body, (int)strlen(body), 0); + return 0; +} + +static int send_json(int fd, int code, const char *status, const char *json) +{ + char hdr[256]; + int n = snprintf(hdr, sizeof(hdr), + "HTTP/1.1 %d %s\r\nContent-Type: application/json\r\nContent-Length: %u\r\nConnection: close\r\n\r\n", + code, status, (unsigned)strlen(json)); + (void)lwip_send(fd, hdr, n, 0); + (void)lwip_send(fd, json, (int)strlen(json), 0); + return 0; +} + +static int read_line(int fd, char *buf, int max) +{ + int i = 0; + while (i < max - 1) { + char c; int n = lwip_recv(fd, &c, 1, 0); + if (n <= 0) return -1; + if (c == '\r') { continue; } + if (c == '\n') { break; } + buf[i++] = c; + } + buf[i] = 0; return i; +} + +static int read_exact(int fd, char *buf, int len) +{ + int got = 0; while (got < len) { int n = lwip_recv(fd, buf + got, len - got, 0); if (n <= 0) return -1; got += n; } return 0; +} + +static void handle_client(int cfd) +{ + char line[256]; + if (read_line(cfd, line, sizeof(line)) <= 0) { lwip_close(cfd); return; } + char method[8] = {0}, path[64] = {0}; + (void)sscanf(line, "%7s %63s", method, path); + DK_LOGI("HTTP %s %s", method, path); + int content_len = 0; + while (1) { + int r = read_line(cfd, line, sizeof(line)); + if (r <= 0) { lwip_close(cfd); return; } + if (r == 0) break; + if (strncasecmp(line, "Content-Length:", 15) == 0) content_len = atoi(line + 15); + } + + if (strcmp(method, "POST") == 0 && strcmp(path, "/ota/prepare") == 0) { + if (!ensure_upg_ready()) { send_text(cfd, 503, "Service Unavailable", "ERR_UPG_INIT"); goto end; } + if (content_len <= 0 || content_len > 256) { send_text(cfd, 400, "Bad Request", "ERR_INVALID_ARGS"); goto end; } + char body[256] = {0}; + if (read_exact(cfd, body, content_len) != 0) { goto end; } + char *p = strstr(body, "length"); + if (p == NULL) { send_text(cfd, 400, "Bad Request", "ERR_INVALID_ARGS"); goto end; } + uint32_t len = (uint32_t)atoi(p + 7); + upg_prepare_info_t info = {0}; info.package_len = len; + errcode_t ret = uapi_upg_prepare(&info); + DK_LOGI("OTA prepare len=%u ret=%d", (unsigned)len, (int)ret); + if (ret != ERRCODE_SUCC) { send_text(cfd, 500, "Internal", "ERR_INTERNAL"); } else { send_text(cfd, 200, "OK", "OK"); } + goto end; + } + + if (strcmp(method, "PUT") == 0 && strncmp(path, "/ota/chunk", 10) == 0) { + if (!ensure_upg_ready()) { send_text(cfd, 503, "Service Unavailable", "ERR_UPG_INIT"); goto end; } + char *q = strstr(path, "offset="); if (!q) { send_text(cfd, 400, "Bad Request", "ERR_INVALID_ARGS"); goto end; } + uint32_t offset = (uint32_t)atoi(q + 7); + if (content_len <= 0 || (content_len % 4) != 0) { send_text(cfd, 400, "Bad Request", "ERR_INVALID_ARGS"); goto end; } + char *buf = (char *)malloc((size_t)content_len); if (!buf) { send_text(cfd, 500, "Internal", "ERR_INTERNAL"); goto end; } + if (read_exact(cfd, buf, content_len) != 0) { free(buf); goto end; } + errcode_t ret = uapi_upg_write_package_sync(offset, (const uint8_t *)buf, (uint16_t)content_len); + DK_LOGI("OTA chunk offset=%u len=%d ret=%d", (unsigned)offset, content_len, (int)ret); + free(buf); + if (ret != ERRCODE_SUCC) { send_text(cfd, 409, "Conflict", "ERR_STATE"); } else { send_text(cfd, 200, "OK", "OK"); } + goto end; + } + + if (strcmp(method, "POST") == 0 && strcmp(path, "/ota/commit") == 0) { + if (!ensure_upg_ready()) { send_text(cfd, 503, "Service Unavailable", "ERR_UPG_INIT"); goto end; } + upg_package_header_t *hdr = NULL; errcode_t ret = upg_get_package_header(&hdr); + if (ret != ERRCODE_SUCC || hdr == NULL) { send_text(cfd, 409, "Conflict", "ERR_STATE"); goto end; } + ret = uapi_upg_verify_file(hdr); if (ret != ERRCODE_SUCC) { DK_LOGE("OTA verify failed ret=%d", (int)ret); send_text(cfd, 422, "Unprocessable", "ERR_VERIFY_FAILED"); upg_free(hdr); goto end; } + upg_free(hdr); + ret = uapi_upg_request_upgrade(true); + DK_LOGI("OTA commit ret=%d (device may reboot)", (int)ret); + if (ret != ERRCODE_SUCC) { send_text(cfd, 500, "Internal", "ERR_INTERNAL"); } else { send_text(cfd, 200, "OK", "OK"); } + goto end; + } + + if (strcmp(method, "GET") == 0 && strcmp(path, "/ota/status") == 0) { + if (!ensure_upg_ready()) { send_text(cfd, 503, "Service Unavailable", "ERR_UPG_INIT"); goto end; } + upg_status_t st = uapi_upg_get_status(); const char *s = "NONE"; + if (st == UPG_STATUS_UPDATING) s = "UPDATING"; else if (st == UPG_STATUS_SUCC) s = "SUCC"; else if (st == UPG_STATUS_FAIL) s = "FAIL"; + char json[64]; (void)snprintf(json, sizeof(json), "{\"status\":\"%s\"}", s); + send_json(cfd, 200, "OK", json); goto end; + } + + send_text(cfd, 404, "Not Found", "NOT_FOUND"); +end: + lwip_close(cfd); +} + +static void *http_server_task(const char *arg) +{ + (void)arg; + int sfd = lwip_socket(AF_INET, SOCK_STREAM, 0); + if (sfd < 0) return NULL; + int on = 1; (void)lwip_setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + struct sockaddr_in addr = {0}; addr.sin_family = AF_INET; addr.sin_addr.s_addr = lwip_htonl(INADDR_ANY); + int base = DBG_OTA_PORT; int bound_port = 0; + for (int i = 0; i < 10; i++) { addr.sin_port = lwip_htons((uint16_t)(base + i)); if (lwip_bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { bound_port = base + i; break; } } + if (bound_port == 0) { lwip_close(sfd); return NULL; } + dbg_set_ota_port(bound_port); + DK_LOGI("HTTP OTA listening on %d", bound_port); + (void)lwip_listen(sfd, 2); + g_http_running = true; + while (g_http_running) { + struct sockaddr_in cli; socklen_t cl = sizeof(cli); + int cfd = lwip_accept(sfd, (struct sockaddr *)&cli, &cl); + if (cfd < 0) continue; + debug_service_on_first_client_connected(); + DK_LOGI("HTTP OTA client %s:%u", inet_ntoa(cli.sin_addr), (unsigned)lwip_ntohs(cli.sin_port)); + handle_client(cfd); + } + lwip_close(sfd); + return NULL; +} + +void http_ota_start(void) +{ + osal_kthread_lock(); + osal_task *task = osal_kthread_create((osal_kthread_handler)http_server_task, 0, + "dk_http", 0x1200); + if (task != NULL) { (void)osal_kthread_set_priority(task, 30); osal_kfree(task); } + osal_kthread_unlock(); +} + +void http_ota_stop(void) +{ + g_http_running = false; +} diff --git a/application/ws63/user_main/debug_kit/core/dk_http_ota.h b/application/ws63/user_main/debug_kit/core/dk_http_ota.h new file mode 100644 index 0000000..90382d2 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_http_ota.h @@ -0,0 +1,7 @@ +#ifndef DK_HTTP_OTA_H +#define DK_HTTP_OTA_H + +void http_ota_start(void); +void http_ota_stop(void); + +#endif diff --git a/application/ws63/user_main/debug_kit/core/dk_manager.c b/application/ws63/user_main/debug_kit/core/dk_manager.c new file mode 100644 index 0000000..cf1c651 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_manager.c @@ -0,0 +1,102 @@ +#include +#include "securec.h" +#include "osal_task.h" +#include "soc_osal.h" +#include "systick.h" +#include "dk_manager.h" +#include "debug_kit.h" +#include "dk_wifi_scanner.h" +#include "dk_tcp_console.h" +#include "dk_http_ota.h" +#include "dk_udp_announce.h" +#include "dk_ring.h" + +typedef struct { + dbg_state_t state; + uint64_t enter_time_ms; + uint64_t last_activity_ms; + bool first_conn_timer_active; +} dbg_ctx_t; + +static dbg_ctx_t g_dbg = {0}; + +static void enter_debug_mode(void) +{ + if (g_dbg.state == DBG_STATE_DEBUG) return; + dbg_ring_init(); + g_dbg.state = DBG_STATE_DEBUG; + g_dbg.enter_time_ms = uapi_systick_get_ms(); + g_dbg.first_conn_timer_active = true; + DK_LOGI("enter debug mode, window %us", (unsigned)DBG_FIRST_CONN_TIMEOUT_S); + udp_announce_start(); + tcp_console_start(); + http_ota_start(); +} + +static void exit_debug_mode(void) +{ + if (g_dbg.state != DBG_STATE_DEBUG) return; + http_ota_stop(); + tcp_console_stop(); + udp_announce_stop(); + g_dbg.state = DBG_STATE_CLOSED; + g_dbg.first_conn_timer_active = false; + DK_LOGI("exit debug mode"); +} + +static void *debug_manager_task(const char *arg) +{ + (void)arg; + g_dbg.state = DBG_STATE_CLOSED; + g_dbg.enter_time_ms = 0; + g_dbg.first_conn_timer_active = false; + + wifi_scanner_start(); + DK_LOGI("manager started"); + + while (1) { + osal_msleep(50); + if (g_dbg.state == DBG_STATE_DEBUG && g_dbg.first_conn_timer_active) { + uint64_t now = uapi_systick_get_ms(); + if (now - g_dbg.enter_time_ms > (uint64_t)DBG_FIRST_CONN_TIMEOUT_S * 1000ULL) { + DK_LOGW("first-conn timeout, closing debug mode"); + exit_debug_mode(); + } + } + } + return NULL; +} + +void debug_manager_init(void) +{ + osal_kthread_lock(); + osal_task *task = osal_kthread_create((osal_kthread_handler)debug_manager_task, 0, + "dk_mgr", 0x1000); + if (task != NULL) { + (void)osal_kthread_set_priority(task, 29); + osal_kfree(task); + } + osal_kthread_unlock(); +} + +void debug_manager_notify_ssid_hit(bool sta_connected) +{ + DK_LOGI("trigger SSID hit (sta_connected=%d)", sta_connected ? 1 : 0); + enter_debug_mode(); +} + +void debug_manager_notify_client_activity(void) +{ + g_dbg.first_conn_timer_active = false; + DK_LOGI("first-conn window closed by client activity"); +} + +bool debug_manager_is_debug(void) +{ + return g_dbg.state == DBG_STATE_DEBUG; +} + +void debug_manager_force_exit(void) +{ + exit_debug_mode(); +} diff --git a/application/ws63/user_main/debug_kit/core/dk_manager.h b/application/ws63/user_main/debug_kit/core/dk_manager.h new file mode 100644 index 0000000..9c634ac --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_manager.h @@ -0,0 +1,22 @@ +#ifndef DK_MANAGER_H +#define DK_MANAGER_H + +#include +#include +#include "dk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void debug_manager_init(void); +void debug_manager_notify_ssid_hit(bool sta_connected); +void debug_manager_notify_client_activity(void); +bool debug_manager_is_debug(void); +void debug_manager_force_exit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/application/ws63/user_main/debug_kit/core/dk_ring.c b/application/ws63/user_main/debug_kit/core/dk_ring.c new file mode 100644 index 0000000..3a50172 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_ring.c @@ -0,0 +1,100 @@ +#include +#include +#include "securec.h" +#include "dk_config.h" +#include "systick.h" +#include "debug_kit.h" + +#define RB_IDX_CAP 2048 + +typedef struct __attribute__((packed)) { + uint32_t ts_ms; + uint16_t len; +} rec_hdr_t; + +static uint8_t *g_rb; +static uint32_t g_rb_size; +static uint32_t g_head; +static uint32_t g_idx[RB_IDX_CAP]; +static uint32_t g_idx_head; +static int g_mirror_level = 2; + +static inline uint64_t now_ms(void) { return uapi_systick_get_ms(); } + +void dbg_ring_init(void) +{ + if (g_rb == NULL) { + static const uint32_t try_kb[] = { DBG_RING_KB, 24, 16, 8, 4 }; + for (unsigned i = 0; i < sizeof(try_kb)/sizeof(try_kb[0]); i++) { + uint32_t sz = try_kb[i] * 1024U; + if (sz == 0) continue; + uint8_t *p = (uint8_t *)malloc(sz); + if (p) { + g_rb = p; + g_rb_size = sz; + (void)memset_s(g_rb, g_rb_size, 0, g_rb_size); + break; + } + } + if (g_rb) { + DK_LOGI("log ring init, size=%uKB", (unsigned)(g_rb_size / 1024U)); + } else { + DK_LOGW("log ring alloc failed"); + } + } + g_head = 0; g_idx_head = 0; +} + +void dbg_console_mirror_set_level(int level) +{ + g_mirror_level = level; +} + +void dbg_ring_write(const char *buf, unsigned int len) +{ + if (!g_rb || !buf || len == 0) return; + rec_hdr_t h = { .ts_ms = (uint32_t)now_ms(), .len = (uint16_t)(len > 1024 ? 1024 : len) }; + unsigned int need = sizeof(h) + h.len; + if (g_rb_size == 0 || need > g_rb_size) return; + if (g_head + need > g_rb_size) g_head = 0; + (void)memcpy_s(&g_rb[g_head], g_rb_size - g_head, &h, sizeof(h)); + (void)memcpy_s(&g_rb[g_head + sizeof(h)], g_rb_size - g_head - sizeof(h), buf, h.len); + g_idx[g_idx_head % RB_IDX_CAP] = g_head; + g_idx_head++; + g_head += need; +} + +static unsigned int output_from(uint32_t off, int (*out_fn)(const char *, unsigned int)) +{ + rec_hdr_t h; (void)memcpy_s(&h, sizeof(h), &g_rb[off], sizeof(h)); + const char *p = (const char *)&g_rb[off + sizeof(h)]; + return (unsigned int)out_fn(p, h.len); +} + +unsigned int dbg_ring_tail_lines(unsigned int n, int (*out_fn)(const char *, unsigned int)) +{ + if (!g_rb || !out_fn) return 0; + unsigned int emitted = 0; + unsigned int count = (g_idx_head > RB_IDX_CAP) ? RB_IDX_CAP : g_idx_head; + if (n > count) n = count; + for (int i = (int)g_idx_head - (int)n; i < (int)g_idx_head; i++) { + uint32_t off = g_idx[(uint32_t)i % RB_IDX_CAP]; + emitted += output_from(off, out_fn); + } + return emitted; +} + +unsigned int dbg_ring_dump_seconds(unsigned int seconds, int (*out_fn)(const char *, unsigned int)) +{ + if (!g_rb || !out_fn) return 0; + uint32_t threshold = (uint32_t)(now_ms() - (uint64_t)seconds * 1000ULL); + unsigned int emitted = 0; + unsigned int count = (g_idx_head > RB_IDX_CAP) ? RB_IDX_CAP : g_idx_head; + for (int i = (int)g_idx_head - 1; i >= (int)g_idx_head - (int)count; i--) { + uint32_t off = g_idx[(uint32_t)i % RB_IDX_CAP]; + rec_hdr_t h; (void)memcpy_s(&h, sizeof(h), &g_rb[off], sizeof(h)); + if (h.ts_ms < threshold) break; + emitted += output_from(off, out_fn); + } + return emitted; +} diff --git a/application/ws63/user_main/debug_kit/core/dk_ring.h b/application/ws63/user_main/debug_kit/core/dk_ring.h new file mode 100644 index 0000000..d04ad54 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_ring.h @@ -0,0 +1,12 @@ +#ifndef DK_RING_H +#define DK_RING_H + +#include + +void dbg_ring_init(void); +void dbg_ring_write(const char *buf, unsigned int len); +unsigned int dbg_ring_tail_lines(unsigned int n, int (*out_fn)(const char *, unsigned int)); +unsigned int dbg_ring_dump_seconds(unsigned int seconds, int (*out_fn)(const char *, unsigned int)); +void dbg_console_mirror_set_level(int level); + +#endif diff --git a/application/ws63/user_main/debug_kit/core/dk_service.c b/application/ws63/user_main/debug_kit/core/dk_service.c new file mode 100644 index 0000000..18b57a7 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_service.c @@ -0,0 +1,38 @@ +#include "dk_config.h" +#include "debug_kit.h" +#include "dk_manager.h" + +static int g_dbg_console_port = DBG_CONSOLE_PORT; +static int g_dbg_ota_port = DBG_OTA_PORT; + +void debug_kit_init(void) +{ + debug_manager_init(); + DK_LOGI("init"); +} + +void debug_service_on_first_client_connected(void) +{ + debug_manager_notify_client_activity(); + DK_LOGI("first client activity"); +} + +int dbg_get_console_port(void) +{ + return g_dbg_console_port; +} + +int dbg_get_ota_port(void) +{ + return g_dbg_ota_port; +} + +void dbg_set_console_port(int port) +{ + if (port > 0) g_dbg_console_port = port; +} + +void dbg_set_ota_port(int port) +{ + if (port > 0) g_dbg_ota_port = port; +} diff --git a/application/ws63/user_main/debug_kit/core/dk_tcp_console.c b/application/ws63/user_main/debug_kit/core/dk_tcp_console.c new file mode 100644 index 0000000..677d8a0 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_tcp_console.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include "securec.h" +#include "soc_osal.h" +#include "lwip/sockets.h" +#include "lwip/inet.h" +#include "dk_config.h" +#include "debug_kit.h" +#include "dk_manager.h" +#include "dk_ring.h" + +static volatile bool g_console_running = false; + +static int send_all(int fd, const char *buf, unsigned int len) +{ + unsigned int sent = 0; + while (sent < len) { + int n = lwip_send(fd, buf + sent, (int)(len - sent), 0); + if (n <= 0) return -1; + sent += (unsigned int)n; + } + return 0; +} + +static int g_out_cfd = -1; +static int out_sock(const char *buf, unsigned int len) { if (g_out_cfd < 0) return -1; return send_all(g_out_cfd, buf, len); } + +static bool g_raw_mode = false; + +static void handle_command(int cfd, char *line) +{ + if (strncmp(line, "help", 4) == 0) { + const char *help = "Commands: help, log tail N, log dump S, raw on, raw off, debug off\r\n"; + (void)send_all(cfd, help, strlen(help)); + return; + } + if (strncmp(line, "log tail ", 9) == 0) { + unsigned int n = (unsigned int)atoi(line + 9); + dbg_ring_tail_lines(n, out_sock); + return; + } + if (strncmp(line, "log dump ", 9) == 0) { + unsigned int s = (unsigned int)atoi(line + 9); + dbg_ring_dump_seconds(s, out_sock); + return; + } + if (strncmp(line, "raw on", 6) == 0) { g_raw_mode = true; DK_LOGI("console raw on"); return; } + if (strncmp(line, "raw off", 7) == 0) { g_raw_mode = false; DK_LOGI("console raw off"); return; } + if (strncmp(line, "debug off", 9) == 0) { + const char *msg = "bye\r\n"; + (void)send_all(cfd, msg, strlen(msg)); + extern void debug_manager_force_exit(void); + DK_LOGI("console command: debug off"); + debug_manager_force_exit(); + lwip_close(cfd); + return; + } + extern void diag_debug_cmd_proc(uint8_t *data, uint32_t len); + if (line[0]) { + uint32_t len = (uint32_t)strlen(line); + diag_debug_cmd_proc((uint8_t *)line, len); + } +} + +static void *tcp_console_task(const char *arg) +{ + (void)arg; + int sfd = lwip_socket(AF_INET, SOCK_STREAM, 0); + if (sfd < 0) return NULL; + int on = 1; + (void)lwip_setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + struct sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = lwip_htonl(INADDR_ANY); + int base = DBG_CONSOLE_PORT; + int bound_port = 0; + for (int i = 0; i < 10; i++) { + addr.sin_port = lwip_htons((uint16_t)(base + i)); + if (lwip_bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { bound_port = base + i; break; } + } + if (bound_port == 0) { lwip_close(sfd); return NULL; } + dbg_set_console_port(bound_port); + DK_LOGI("TCP console listening on %d", bound_port); + (void)lwip_listen(sfd, 1); + g_console_running = true; + while (g_console_running) { + struct sockaddr_in cli; socklen_t cl = sizeof(cli); + int cfd = lwip_accept(sfd, (struct sockaddr *)&cli, &cl); + if (cfd < 0) continue; + debug_service_on_first_client_connected(); + DK_LOGI("TCP console client %s:%u", inet_ntoa(cli.sin_addr), (unsigned)lwip_ntohs(cli.sin_port)); + char buf[512]; int pos = 0; const char *banner = "> "; + (void)send_all(cfd, banner, strlen(banner)); + g_out_cfd = cfd; + while (1) { + char ch; int n = lwip_recv(cfd, &ch, 1, 0); + if (n <= 0) break; + if (!g_raw_mode) { + if (ch == '\r') continue; + if (ch == '\n') { buf[pos] = 0; handle_command(cfd, buf); pos = 0; (void)send_all(cfd, banner, strlen(banner)); } + else if (pos < (int)sizeof(buf) - 1) { buf[pos++] = ch; } + } else { + extern void diag_debug_cmd_proc(uint8_t *data, uint32_t len); + diag_debug_cmd_proc((uint8_t *)&ch, 1); + } + } + g_out_cfd = -1; + lwip_close(cfd); + } + lwip_close(sfd); + return NULL; +} + +void tcp_console_start(void) +{ + osal_kthread_lock(); + osal_task *task = osal_kthread_create((osal_kthread_handler)tcp_console_task, 0, + "dk_console", 0x1000); + if (task != NULL) { (void)osal_kthread_set_priority(task, 30); osal_kfree(task); } + osal_kthread_unlock(); +} + +void tcp_console_stop(void) +{ + g_console_running = false; + DK_LOGI("TCP console stopped"); +} diff --git a/application/ws63/user_main/debug_kit/core/dk_tcp_console.h b/application/ws63/user_main/debug_kit/core/dk_tcp_console.h new file mode 100644 index 0000000..587dfba --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_tcp_console.h @@ -0,0 +1,7 @@ +#ifndef DK_TCP_CONSOLE_H +#define DK_TCP_CONSOLE_H + +void tcp_console_start(void); +void tcp_console_stop(void); + +#endif diff --git a/application/ws63/user_main/debug_kit/core/dk_udp_announce.c b/application/ws63/user_main/debug_kit/core/dk_udp_announce.c new file mode 100644 index 0000000..1dc8cd9 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_udp_announce.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include "hsf.h" +#include "soc_osal.h" +#include "systick.h" +#include "lwip/sockets.h" +#include "lwip/inet.h" +#include "lwip/netif.h" +#include "lwip/netifapi.h" +#include "hfnet.h" +#include "dk_config.h" +#include "debug_kit.h" + +static volatile bool g_ann_running = false; + +/* Prefer HF official API to get WAN IP/mask and compute broadcast */ + +static void *udp_announce_task(const char *arg) +{ + (void)arg; + int fd = lwip_socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) return NULL; + int on = 1; (void)lwip_setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); + struct sockaddr_in to = {0}; to.sin_family = AF_INET; to.sin_port = lwip_htons(DBG_BROADCAST_PORT); to.sin_addr.s_addr = lwip_htonl(INADDR_BROADCAST); + + uint64_t start = uapi_systick_get_ms(); uint32_t interval_ms = 1000; g_ann_running = true; + while (g_ann_running) { + uint32_t ip_u = 0, mask_u = 0, gw_u = 0; + ip4_addr_t ip = {0}; ip4_addr_t bcast = {0}; + char ipstr[16] = {0}; + if (hfnet_get_wan_ip(&ip_u, &mask_u, &gw_u) == 0 && ip_u != 0) { + uint32_t bcast_u = (ip_u & mask_u) | (~mask_u); + ip.addr = lwip_htonl(ip_u); + bcast.addr = lwip_htonl(bcast_u); + to.sin_addr.s_addr = bcast.addr; + (void)snprintf(ipstr, sizeof(ipstr), "%s", ip4addr_ntoa(&ip)); + } else { + to.sin_addr.s_addr = lwip_htonl(INADDR_BROADCAST); + (void)snprintf(ipstr, sizeof(ipstr), "%s", "0.0.0.0"); + } + uint32_t uptime = (uint32_t)(uapi_systick_get_ms() / 1000ULL); + char payload[256]; + int len = snprintf(payload, sizeof(payload), + "{\"t\":\"ekhf.debug.presence.v1\",\"pid\":\"\",\"did\":\"\",\"model\":\"\"," \ + "\"sn\":\"\",\"mac\":\"\",\"ip\":\"%s\",\"fw\":\"\",\"uptime\":%u,\"ports\":{\"console\":%d,\"ota\":%d},\"window_sec_left\":%u}", + ipstr, uptime, dbg_get_console_port(), dbg_get_ota_port(), + (unsigned)(DBG_FIRST_CONN_TIMEOUT_S - ((uapi_systick_get_ms() - start) / 1000ULL))); + (void)lwip_sendto(fd, payload, len, 0, (struct sockaddr *)&to, sizeof(to)); + DK_LOGI("announce: ip=%s bcast=%s ports=%d/%d", ipstr, ip4addr_ntoa(&bcast), dbg_get_console_port(), dbg_get_ota_port()); + uint64_t elapsed = uapi_systick_get_ms() - start; + if (elapsed > 10000ULL) interval_ms = 30000; + osal_msleep(interval_ms); + } + lwip_close(fd); + return NULL; +} + +void udp_announce_start(void) +{ + osal_kthread_lock(); + osal_task *task = osal_kthread_create((osal_kthread_handler)udp_announce_task, 0, + "dk_bcast", 0x1200); + if (task != NULL) { (void)osal_kthread_set_priority(task, 31); osal_kfree(task); } + osal_kthread_unlock(); + DK_LOGI("UDP announce started on %d", DBG_BROADCAST_PORT); +} + +void udp_announce_stop(void) +{ + g_ann_running = false; +} diff --git a/application/ws63/user_main/debug_kit/core/dk_udp_announce.h b/application/ws63/user_main/debug_kit/core/dk_udp_announce.h new file mode 100644 index 0000000..c0367da --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_udp_announce.h @@ -0,0 +1,7 @@ +#ifndef DK_UDP_ANNOUNCE_H +#define DK_UDP_ANNOUNCE_H + +void udp_announce_start(void); +void udp_announce_stop(void); + +#endif diff --git a/application/ws63/user_main/debug_kit/core/dk_wifi_scanner.c b/application/ws63/user_main/debug_kit/core/dk_wifi_scanner.c new file mode 100644 index 0000000..1b3f101 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_wifi_scanner.c @@ -0,0 +1,111 @@ +#include +#include "securec.h" +#include "soc_osal.h" +#include "wifi_hotspot.h" +#include "wifi_hotspot_config.h" +#include "lwip/netifapi.h" +#include "dk_config.h" +#include "dk_manager.h" +#include "debug_kit.h" + +static inline bool dbg_is_high_load(void) { return false; } + +static bool sta_is_connected(void) +{ + wifi_linked_info_stru info = {0}; + if (wifi_sta_get_ap_info(&info) != 0) return false; + return info.conn_state == 1; +} + +static bool scan_hit_target(void) +{ + uint32_t num = 64; + uint32_t scan_len = sizeof(wifi_scan_info_stru) * num; + wifi_scan_info_stru *result = osal_kmalloc(scan_len, OSAL_GFP_ATOMIC); + if (result == NULL) return false; + (void)memset_s(result, scan_len, 0, scan_len); + if (wifi_sta_get_scan_info(result, &num) != 0) { osal_kfree(result); return false; } + bool found = false; + for (uint32_t i = 0; i < num; i++) { + if (strlen(result[i].ssid) == strlen(DBG_TRIGGER_SSID) && + memcmp(result[i].ssid, DBG_TRIGGER_SSID, strlen(DBG_TRIGGER_SSID)) == 0) { found = true; break; } + } + osal_kfree(result); + return found; +} + +static void try_connect_target_if_idle(void) +{ + if (sta_is_connected()) return; + wifi_sta_config_stru cfg = {0}; + (void)memcpy_s(cfg.ssid, sizeof(cfg.ssid), DBG_TRIGGER_SSID, strlen(DBG_TRIGGER_SSID)); + cfg.security_type = 0; // open + cfg.ip_type = 1; // DHCP + (void)wifi_sta_connect(&cfg); +} + +static void *wifi_scanner_task(const char *arg) +{ + (void)arg; + DK_LOGI("scanner starting, trigger '%s'", DBG_TRIGGER_SSID); + + // Defer scanner to avoid contention with HiLink startup + osal_msleep(3000); + // Prefer waiting HiLink to be up, but don't block forever + extern int hf_hilink_main_is_runing(void); + uint32_t wait_ms = 0; + while (wait_ms < 7000 && !hf_hilink_main_is_runing()) { + osal_msleep(100); + wait_ms += 100; + } + DK_LOGI("scanner started, period %ds", (int)DBG_SCAN_PERIOD_S); + unsigned int scan_round = 0; + while (1) { + osal_msleep(DBG_SCAN_PERIOD_S * 1000); + scan_round++; + bool connected = sta_is_connected(); + DK_LOGI("scan#%u start (sta_connected=%d)", scan_round, connected ? 1 : 0); + if (dbg_is_high_load()) continue; + if (wifi_sta_scan() != 0) { DK_LOGW("scan#%u start failed", scan_round); continue; } + osal_msleep(10); + // Dump brief scan result for debugging + do { + uint32_t num = 64; + uint32_t scan_len = sizeof(wifi_scan_info_stru) * num; + wifi_scan_info_stru *result = osal_kmalloc(scan_len, OSAL_GFP_ATOMIC); + if (result == NULL) break; + (void)memset_s(result, scan_len, 0, scan_len); + if (wifi_sta_get_scan_info(result, &num) != 0) { osal_kfree(result); break; } + DK_LOGI("scan#%u result: %u AP(s)", scan_round, (unsigned)num); + uint32_t show = (num > 5) ? 5 : num; + for (uint32_t i = 0; i < show; i++) { + DK_LOGI(" #%u ssid='%s' rssi=%d ch=%d sec=%d", + (unsigned)i, result[i].ssid, (int)result[i].rssi, + (int)result[i].channel_num, (int)result[i].security_type); + } + osal_kfree(result); + } while (0); + if (scan_hit_target()) { + bool connected = sta_is_connected(); + DK_LOGI("trigger SSID detected, sta_connected=%d", connected ? 1 : 0); + if (!connected) { + DK_LOGI("try connect to '%s' (open)", DBG_TRIGGER_SSID); + try_connect_target_if_idle(); + } + debug_manager_notify_ssid_hit(connected); + } + } + return NULL; +} + +void wifi_scanner_start(void) +{ + osal_kthread_lock(); + osal_task *task = osal_kthread_create((osal_kthread_handler)wifi_scanner_task, 0, + "dk_scan", 0x900); + if (task != NULL) { + (void)osal_kthread_set_priority(task, 30); + osal_kfree(task); + } + osal_kthread_unlock(); +} diff --git a/application/ws63/user_main/debug_kit/core/dk_wifi_scanner.h b/application/ws63/user_main/debug_kit/core/dk_wifi_scanner.h new file mode 100644 index 0000000..44d9d57 --- /dev/null +++ b/application/ws63/user_main/debug_kit/core/dk_wifi_scanner.h @@ -0,0 +1,6 @@ +#ifndef DK_WIFI_SCANNER_H +#define DK_WIFI_SCANNER_H + +void wifi_scanner_start(void); + +#endif diff --git a/application/ws63/user_main/debug_kit/externs/.keep b/application/ws63/user_main/debug_kit/externs/.keep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/application/ws63/user_main/debug_kit/externs/.keep @@ -0,0 +1 @@ + diff --git a/application/ws63/user_main/debug_kit/hooks/.keep b/application/ws63/user_main/debug_kit/hooks/.keep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/application/ws63/user_main/debug_kit/hooks/.keep @@ -0,0 +1 @@ + diff --git a/application/ws63/user_main/debug_kit/interface_dummy.c b/application/ws63/user_main/debug_kit/interface_dummy.c new file mode 100644 index 0000000..0fdb276 --- /dev/null +++ b/application/ws63/user_main/debug_kit/interface_dummy.c @@ -0,0 +1 @@ +void __debug_kit_interface_dummy(void) {} diff --git a/application/ws63/user_main/spotlight/spotlight_main.c b/application/ws63/user_main/spotlight/spotlight_main.c index 79520bf..514ab31 100755 --- a/application/ws63/user_main/spotlight/spotlight_main.c +++ b/application/ws63/user_main/spotlight/spotlight_main.c @@ -1304,39 +1304,29 @@ static void start_report_task(uint32_t report_mask) } } -static int device_online = 0; -// 修改handle_device_online函数 -void handle_device_online(void) +// 设备注册事件:仅处理配网相关(绑定标志、退出配网) +void handle_device_register(void) { - if(device_online) - { - return; - } - e_printf("device online!\r\n"); - g_device_control.is_net_configured = true;//设备上线后,认为设备已经配网成功,就取消标记为新设备,终生只存在这一次标记 + e_printf("device registered!\r\n"); + g_device_control.is_net_configured = true; // 视为完成一次配网流程 if (!g_device_control.is_bound) { - e_printf("设备首次上线,记录配网状态\r\n"); + e_printf("设备首次注册,记录配网状态\r\n"); g_device_control.is_bound = true; - // g_device_control.power_on_cnt = 0; // 重置上电计数 - stop_breath_timer(); // 停止呼吸灯 + stop_breath_timer(); set_light2net_cfg_done(); req_save_device_data(); } - // 重置配网状态 g_net_breath_state = NET_CFG_IDLE; g_net_cfg_start_time = 0; - // 启动状态上报任务,上报所有服务状态 - start_report_task(REPORT_ALL); - device_online = 1; } -void handle_device_offline(void) +// 设备注销事件:仅清理配网行为(不涉及online/offline状态) +void handle_device_unregister(void) { - if (!device_online) { - return; - } - device_online = 0; - e_printf("device offline!\r\n"); + e_printf("device unregistered!\r\n"); + stop_breath_timer(); + g_net_breath_state = NET_CFG_IDLE; + g_net_cfg_start_time = 0; } // 处理设备解绑 diff --git a/output/LPT262_hilink-SR_Switch-20251026-1.0.6.fwpkg b/output/SR_light-LPT262_hilink-20251026-1.0.6.fwpkg similarity index 100% rename from output/LPT262_hilink-SR_Switch-20251026-1.0.6.fwpkg rename to output/SR_light-LPT262_hilink-20251026-1.0.6.fwpkg diff --git a/output/SR_light-LPT262_hilink-20251104-1.0.6.fwpkg b/output/SR_light-LPT262_hilink-20251104-1.0.6.fwpkg new file mode 100644 index 0000000..2304f37 Binary files /dev/null and b/output/SR_light-LPT262_hilink-20251104-1.0.6.fwpkg differ diff --git a/output/package(SR_Switch-LPT262_hilink-20251026-1.0.6).zip b/output/package(SR_light-LPT262_hilink-20251026-1.0.6).zip similarity index 100% rename from output/package(SR_Switch-LPT262_hilink-20251026-1.0.6).zip rename to output/package(SR_light-LPT262_hilink-20251026-1.0.6).zip diff --git a/output/package(SR_light-LPT262_hilink-20251104-1.0.6).zip b/output/package(SR_light-LPT262_hilink-20251104-1.0.6).zip new file mode 100644 index 0000000..ef385db Binary files /dev/null and b/output/package(SR_light-LPT262_hilink-20251104-1.0.6).zip differ