/**
 * @file tkl_wifi.c
 * @brief this file was auto-generated by tuyaos v&v tools, developer can add implements between BEGIN and END
 * 
 * @warning: changes between user 'BEGIN' and 'END' will be keeped when run tuyaos v&v tools
 *           changes in other place will be overwrited and lost
 *
 * @copyright Copyright 2020-2021 Tuya Inc. All Rights Reserved.
 * 
 */

// --- BEGIN: user defines and implements ---
#include "tkl_wifi.h"
#include "tuya_error_code.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <pthread.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <linux/wireless.h>
#include <errno.h>
#include <dirent.h>
#include <regex.h>
#include <net/if_arp.h>
#include <sys/sysinfo.h>

// --- END: user defines and implements ---


//ym modify 25.08.15
//#define WLAN_DEV    "ens33"
#define WLAN_DEV    "wlan0"
//ym add 25.08.16
#ifdef CHIP_ANYKA
#define MAC_PREV    "HWaddr " 
#else
#define MAC_PREV    "ether " 
#endif
#define IPV4_PREV   "inet addr:"
#define IPV6_PREV   "inet6 addr: "

#define SSID_MAX_LEN 32
#define BSSID_MAX_LEN 18

STATIC WIFI_EVENT_CB wifi_status_cb;

char g_tmp[512] = {0};
char g_mac[MAC_ADDR_LEN] = {0};
WF_WK_MD_E g_work_mode = 0;
NW_IP_S g_ip = {0};
//#define OPRT_OK 0
//#define OPRT_COM_ERROR 1  // 假设的错误码，需替换为实际定义


int get_ip_address(const char *hostname, const char *port);

static int __get_connected_bssid(char *bssid, int max_len);

/**
 * @brief 执行shell命令并获取输出
 * @param g_tmp 要执行的命令
 * @param g_tmp 存储输出的缓冲区
 * @param buf_len 缓冲区长度
 * @return 0成功，-1失败
 */
static int __exec_cmd(const char *cmd, char *buf, int buf_len) {

    printf("%s:%s\r\n", __func__, cmd);

    if (cmd == NULL /*|| g_tmp == NULL || buf_len <= 0*/) {
        return -1;
    }

    // 检查系统内存
    // struct sysinfo info;
    // if (sysinfo(&info) == -1 || info.freeram < (1 << 20)) {
    //     fprintf(stderr, "Insufficient memory\n");
    //     return;
    // }


    FILE *fp = popen(cmd, "r");
    if (fp == NULL) {
        return -1;
    }

    if(buf != NULL &&  buf_len > 0)
    {
        memset(buf, 0, buf_len);
        fread(buf, 1, buf_len - 1, fp);
        if(strlen(buf)>0)
        {
            pclose(fp);
            return 0;
        }
            
    }

    pclose(fp);
    return -1;
}


STATIC VOID_T *wifi_status_event_cb(void *arg)
{
    WF_EVENT_E wf_event;
    WF_STATION_STAT_E stat = 0;
    WF_STATION_STAT_E last_stat = 0;
    int last_state = -1;

#if 1   //仅 wifi链接模式下，使用debug入网激活需要，原因:IOT会判断当前wifi的work_mode，然后再记录event，debug模式下给event太快，非debug模式不用sleep
    sleep(3);  
    tal_wifi_set_work_mode(WWM_STATION);
#endif
    pthread_detach (pthread_self());
    while (1) {
        tkl_wifi_station_get_status(&stat);
        if(stat != WSS_CONN_SUCCESS && stat != WSS_GOT_IP) {
            wf_event = WFE_DISCONNECTED;
        }
        if(stat == WSS_CONN_FAIL) {
            wf_event = WFE_CONNECT_FAILED;
        } else if(stat == WSS_GOT_IP || stat == WSS_CONN_SUCCESS) {
            wf_event = WFE_CONNECTED;
            if (last_stat != stat) {
                last_stat = stat;
                last_state = wf_event;
                printf("%s-%d set wf event[%d]\n",__FUNCTION__, __LINE__, wf_event);
                wifi_status_cb(wf_event,NULL);
                sleep(1);
                continue;
            }
        }

        if(last_state == wf_event) {
            sleep(1);
            continue;
        }

        last_state = wf_event;
        printf("%s-%d set wf event[%d]\n",__FUNCTION__, __LINE__, wf_event);
        wifi_status_cb(wf_event,NULL);
        sleep(1);
    }
}


/**
 * @brief set wifi station work status changed callback
 *
 * @param[in]      cb        the wifi station work status changed callback
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_init(WIFI_EVENT_CB cb)
{
    int iret = 0;
    pthread_t thread;
    printf("%s\r\n", __func__);
    wifi_status_cb = cb;
    iret = pthread_create(&thread,NULL,wifi_status_event_cb,NULL);
    if(iret) {
        printf("create status_cs thread failed");
        return -1;
    }

    return 0;
}

/**
 * @brief scan current environment and obtain the ap
 *        infos in current environment
 * 
 * @param[in]       ssid        the specific ssid
 * @param[out]      ap_ary      current ap info array
 * @param[out]      num         the num of ar_ary
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 *
 * @note if ssid == NULL means scan all ap, otherwise means scan the specific ssid
 */
// OPERATE_RET tkl_wifi_scan_ap(CONST SCHAR_T *ssid, AP_IF_S **ap_ary, UINT_T *num)
// {
//     printf("%s\r\n", __func__);
//     return OPRT_OK;
// }

/**
 * @brief release the memory malloced in <tkl_wifi_ap_scan>
 *        if needed. tuyaos will call this function when the 
 *        ap info is no use.
 * 
 * @param[in]       ap          the ap info
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
// OPERATE_RET tkl_wifi_release_ap(AP_IF_S *ap)
// {//Static variables, no need to tkl_system_free
//     printf("%s\r\n", __func__);
//     return OPRT_OK;
// }

/**
 * @brief start a soft ap
 * 
 * @param[in]       cfg         the soft ap config
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
// OPERATE_RET tkl_wifi_start_ap(CONST WF_AP_CFG_IF_S *cfg)
// {
//     printf("%s\r\n", __func__);
//     if(NULL == cfg){
//         return OPRT_INVALID_PARM;
//     }

//     printf("Start AP SSID:%s \r\n", cfg->ssid);
//     printf("Start AP ip info:[%s-%s-%s] \r\n", cfg->ip.addr.ip4.ip, cfg->ip.addr.ip4.gw, cfg->ip.addr.ip4.mask);
//     //Reserved
//     return OPRT_OK;
// }

/**
 * @brief stop a soft ap
 * 
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
// OPERATE_RET tkl_wifi_stop_ap(VOID_T)
// {
//     printf("Stop AP \r\n");
//     //Reserved
//     return OPRT_OK;
// }



// 常量定义
//#define WLAN_DEV "wlan0"
#define WIFI_SSID_LEN 32
#define WIFI_PASSWD_LEN 64
#define SCAN_g_tmpER_SIZE 16384
#define MAX_SCAN_AP_NUM 32

// // 加密模式映射
// typedef enum {
//     WIFI_AUTH_OPEN = 0,
//     WIFI_AUTH_WEP,
//     WIFI_AUTH_WPA_PSK,
//     WIFI_AUTH_WPA2_PSK,
//     WIFI_AUTH_WPA_WPA2_PSK,
//     WIFI_AUTH_MAX
// } WF_AP_AUTH_MODE_E;
// typedef enum
// {
//     WAAM_OPEN = 0,      ///< open
//     WAAM_WEP,           ///< WEP
//     WAAM_WPA_PSK,       ///< WPA—PSK
//     WAAM_WPA2_PSK,      ///< WPA2—PSK
//     WAAM_WPA_WPA2_PSK,  ///< WPA/WPA2
//     WAAM_WPA_WPA3_SAE,
//     WAAM_UNKNOWN,       //unknown
// }WF_AP_AUTH_MODE_E;
// IP信息结构体
// typedef struct {
//     union {
//         struct {
//             char ip[16];
//             char gw[16];
//             char mask[16];
//         } ip4;
//     } addr;
// } NW_IP_S;

/**
 * @brief 解析扫描结果中的加密模式
 */
static WF_AP_AUTH_MODE_E __parse_security(const char *enc_str)
{
    printf("%s\r\n", __func__);
    if (strstr(enc_str, "WPA2") && strstr(enc_str, "PSK")) {
        return WAAM_WPA2_PSK;
    } else if (strstr(enc_str, "WPA") && strstr(enc_str, "PSK")) {
        return WAAM_WPA_PSK;
    } else if (strstr(enc_str, "WEP")) {
        return WAAM_WEP;
    } else {
        return WAAM_OPEN;
    }
}




/**
 * @brief 扫描当前环境中的AP信息
 */
char* g_scan_buf=NULL;
OPERATE_RET tkl_wifi_scan_ap(CONST SCHAR_T *ssid, AP_IF_S **ap_ary, UINT_T *num)
{
    printf("%s,ssid:%s\r\n", __func__, ssid);
    
    if (!ap_ary || !num) {
        return OPRT_INVALID_PARM;
    }

    *ap_ary = NULL;
    *num = 0;

    // 执行扫描命令
    //static char g_tmp[256];
    snprintf(g_tmp, sizeof(g_tmp), "iwlist %s scan", WLAN_DEV);
    
    //char scan_buf[SCAN_g_tmpER_SIZE];
    if(!g_scan_buf)
    {
        g_scan_buf = tkl_system_malloc(SCAN_g_tmpER_SIZE);
        if(!g_scan_buf)
        {
            printf("!g_scan_buf\n");
            return OPRT_INVALID_PARM;
        }
        memset(g_scan_buf, 0, SCAN_g_tmpER_SIZE);
    }
    int scan_len = __exec_cmd(g_tmp, g_scan_buf, SCAN_g_tmpER_SIZE);
    printf("tkl_wifi_scan_ap 111\r\n");
    if (scan_len != 0) {
        printf("Scan failed\n");
        tkl_system_free(g_scan_buf);
        g_scan_buf = NULL;
        return OPRT_COM_ERROR;
    }

    printf("tkl_wifi_scan_ap 222\r\n");
    // 分配AP数组内存
    AP_IF_S *aps = (AP_IF_S *)tkl_system_malloc(sizeof(AP_IF_S) * MAX_SCAN_AP_NUM);
    if (!aps) {
        tkl_system_free(g_scan_buf);
        g_scan_buf = NULL;
        return OPRT_MALLOC_FAILED;
    }
    memset(aps, 0, sizeof(AP_IF_S) * MAX_SCAN_AP_NUM);

    printf("tkl_wifi_scan_ap 333\r\n");

    // 解析扫描结果
    char *line = strtok(g_scan_buf, "\n");
    AP_IF_S *curr_ap = NULL;
    int ap_count = 0;

    printf("tkl_wifi_scan_ap 444\r\n");

    while (line && ap_count < MAX_SCAN_AP_NUM) {

        printf("line:%s\r\n", line);

        // 查找新的AP
        if (strstr(line, "Cell ") && strstr(line, " - Address:")) {
            curr_ap = &aps[ap_count];
            ap_count++;



            // 解析BSSID
            char bssid_str[18];
            if (sscanf(line, "Cell %*d - Address: %17s", bssid_str) == 1) {

                printf("bssid_str:%s\r\n", bssid_str);

                // 转换为十六进制
                unsigned int b1, b2, b3, b4, b5, b6;
                if (sscanf(bssid_str, "%x:%x:%x:%x:%x:%x", &b1, &b2, &b3, &b4, &b5, &b6) == 6) {
                    curr_ap->bssid[0] = b1;
                    curr_ap->bssid[1] = b2;
                    curr_ap->bssid[2] = b3;
                    curr_ap->bssid[3] = b4;
                    curr_ap->bssid[4] = b5;
                    curr_ap->bssid[5] = b6;
                }
            }
        }
        // 解析SSID
        else if (curr_ap && strstr(line, "ESSID:")) {
            char ssid_str[WIFI_SSID_LEN + 1];
            if (sscanf(line, "ESSID:\"%32[^\"]\"", ssid_str) == 1) {

                printf("ssid_str:%s\r\n", ssid_str);

                curr_ap->s_len = strlen(ssid_str);
                memcpy(curr_ap->ssid, ssid_str, curr_ap->s_len);
            }
        }
        // 解析信号强度
        else if (curr_ap && strstr(line, "Signal level=")) {
            int rssi;
            if (sscanf(line, "Signal level=%d", &rssi) == 1) {
                curr_ap->rssi = rssi;
            }
        }
        // 解析信道
        else if (curr_ap && strstr(line, "Channel:")) {
            int channel;
            if (sscanf(line, "Channel:%d", &channel) == 1) {
                curr_ap->channel = channel;
            }
        }
        // 解析加密模式
        else if (curr_ap && (strstr(line, "Encryption key:on") || strstr(line, "Encryption key:off"))) {
            if (strstr(line, "off")) {
                curr_ap->security = WAAM_OPEN;//WIFI_AUTH_OPEN;
            } else {
                // 后续行包含具体加密类型
                line = strtok(NULL, "\n");
                if (line && (strstr(line, "IE:") || strstr(line, "WPA"))) {
                    curr_ap->security = __parse_security(line);
                } else {
                    curr_ap->security = WAAM_WEP;//WIFI_AUTH_WEP;
                }
            }
        }

        line = strtok(NULL, "\n");
    }
    printf("tkl_wifi_scan_ap 555\r\n");
    // 过滤指定SSID
    if (ssid) {
        AP_IF_S *filtered_aps = (AP_IF_S *)tkl_system_malloc(sizeof(AP_IF_S) * ap_count);

        printf("tkl_wifi_scan_ap 555\r\n");

        if (!filtered_aps) {
            tkl_system_free(aps);
            tkl_system_free(g_scan_buf);
            aps = g_scan_buf = NULL;
            return OPRT_MALLOC_FAILED;
        }
        
        int filtered_count = 0;
        for (int i = 0; i < ap_count; i++) {
            if (strncmp((char *)aps[i].ssid, ssid, aps[i].s_len) == 0) {
                filtered_aps[filtered_count++] = aps[i];
            }
        }
        printf("tkl_wifi_scan_ap filtered_count=%d\r\n",filtered_count);
        tkl_system_free(aps);
        aps = NULL; 
        *ap_ary = filtered_aps;
        *num = filtered_count;
    } else {
        printf("tkl_wifi_scan_ap ap_count=%d\r\n",ap_count);
        *ap_ary = aps;
        *num = ap_count;
    }

    printf("tkl_wifi_scan_ap end\r\n");
    tkl_system_free(g_scan_buf);
    g_scan_buf = NULL;

    return OPRT_OK;
}

/**
 * @brief 释放扫描得到的AP信息内存
 */
OPERATE_RET tkl_wifi_release_ap(AP_IF_S *ap)
{
    printf("%s\r\n", __func__);
	#if 1
    if (ap) {
        tkl_system_free(ap);
        ap = NULL;
    }
    printf("%s  222\r\n", __func__);
	#endif
    return OPRT_OK;
}

/**
 * @brief 启动软AP
 */
OPERATE_RET tkl_wifi_start_ap(CONST WF_AP_CFG_IF_S *cfg)
{
    printf("%s\r\n", __func__);
    
    if (NULL == cfg) {
        return OPRT_INVALID_PARM;
    }
	
#if 1	
	printf("Start AP SSID:%s \r\n", cfg->ssid);
    printf("Start AP ip info:[%s-%s-%s] \r\n", cfg->ip.addr.ip4.ip, cfg->ip.addr.ip4.gw, cfg->ip.addr.ip4.mask);
    //Reserved
    return OPRT_OK;
#else
    // 验证参数
    if (cfg->s_len <= 0 || cfg->s_len > WIFI_SSID_LEN) {
        return OPRT_INVALID_PARM;
    }
    
    if (cfg->md != WAAM_OPEN/*WIFI_AUTH_OPEN*/ && (cfg->p_len < 8 || cfg->p_len > WIFI_PASSWD_LEN)) {
        return OPRT_INVALID_PARM;
    }

    printf("Start AP SSID:%s \r\n", cfg->ssid);
    printf("Start AP ip info:[%s-%s-%s] \r\n", 
           cfg->ip.addr.ip4.ip, 
           cfg->ip.addr.ip4.gw, 
           cfg->ip.addr.ip4.mask);

    // 1. 配置网络接口
    static char g_tmp[256];
    snprintf(g_tmp, sizeof(g_tmp), "ifconfig %s %s netmask %s up",
             WLAN_DEV, cfg->ip.addr.ip4.ip, cfg->ip.addr.ip4.mask);
    __exec_cmd(g_tmp, NULL, 0);

    // 2. 创建hostapd配置文件
    FILE *fp = fopen("/tmp/hostapd.conf", "w");
    if (!fp) {
        return OPRT_COM_ERROR;
    }

    fprintf(fp, "interface=%s\n", WLAN_DEV);
    fprintf(fp, "driver=nl80211\n");
    fprintf(fp, "ssid=%s\n", cfg->ssid);
    fprintf(fp, "channel=%d\n", cfg->chan ? cfg->chan : 6);
    fprintf(fp, "max_num_sta=%d\n", cfg->max_conn ? cfg->max_conn : 1);
    fprintf(fp, "beacon_int=%d\n", cfg->ms_interval ? cfg->ms_interval : 100);
    
    /*
    // typedef enum {
//     WIFI_AUTH_OPEN = 0,
//     WIFI_AUTH_WEP,
//     WIFI_AUTH_WPA_PSK,
//     WIFI_AUTH_WPA2_PSK,
//     WIFI_AUTH_WPA_WPA2_PSK,
//     WIFI_AUTH_MAX
// } WF_AP_AUTH_MODE_E;
// typedef enum
// {
//     WAAM_OPEN = 0,      ///< open
//     WAAM_WEP,           ///< WEP
//     WAAM_WPA_PSK,       ///< WPA—PSK
//     WAAM_WPA2_PSK,      ///< WPA2—PSK
//     WAAM_WPA_WPA2_PSK,  ///< WPA/WPA2
//     WAAM_WPA_WPA3_SAE,
//     WAAM_UNKNOWN,       //unknown
// }WF_AP_AUTH_MODE_E;
*/
    // 配置加密方式
    switch (cfg->md) {
        case WAAM_OPEN://WIFI_AUTH_OPEN:
            fprintf(fp, "auth_algs=1\n");
            fprintf(fp, "wmm_enabled=0\n");
            break;
        case WAAM_WPA2_PSK://WIFI_AUTH_WPA2_PSK:
            fprintf(fp, "wmm_enabled=0\n");
            fprintf(fp, "wpa=2\n");
            fprintf(fp, "wpa_passphrase=%s\n", cfg->passwd);
            fprintf(fp, "wpa_key_mgmt=WPA-PSK\n");
            fprintf(fp, "wpa_pairwise=TKIP\n");
            fprintf(fp, "rsn_pairwise=CCMP\n");
            break;
        case WAAM_WPA_PSK://WIFI_AUTH_WPA_PSK:
            fprintf(fp, "wmm_enabled=0\n");
            fprintf(fp, "wpa=1\n");
            fprintf(fp, "wpa_passphrase=%s\n", cfg->passwd);
            fprintf(fp, "wpa_key_mgmt=WPA-PSK\n");
            fprintf(fp, "wpa_pairwise=TKIP\n");
            break;
        case WAAM_WPA_WPA2_PSK://WIFI_AUTH_WPA_WPA2_PSK:
            fprintf(fp, "wmm_enabled=0\n");
            fprintf(fp, "wpa=3\n");
            fprintf(fp, "wpa_passphrase=%s\n", cfg->passwd);
            fprintf(fp, "wpa_key_mgmt=WPA-PSK\n");
            fprintf(fp, "wpa_pairwise=TKIP\n");
            fprintf(fp, "rsn_pairwise=CCMP\n");
            break;
        default:
            fclose(fp);
            return OPRT_NOT_SUPPORTED;
    }

    fclose(fp);

    // 3. 启动hostapd
    pid_t pid = fork();
    if (pid == 0) {
        printf("Start AP exit(1); \r\n");
        execl("/usr/sbin/hostapd", "hostapd", "/tmp/hostapd.conf", (char *)NULL);
        exit(1);
    } else if (pid < 0) {
        return OPRT_COM_ERROR;
    }

    // 4. 启动DHCP服务
    // snprintf(g_tmp, sizeof(g_tmp), 
    //          "udhcpd -f -S -i %s -s %s -r %s -m %s &",
    //          WLAN_DEV,
    //          cfg->ip.addr.ip4.gw,
    //          cfg->ip.addr.ip4.ip,
    //          cfg->ip.addr.ip4.mask);
    snprintf(g_tmp, sizeof(g_tmp), 
             "udhcpd -f -S -i %s&",
             WLAN_DEV);

    __exec_cmd(g_tmp, NULL, 0);

    // system("echo 'interface eth0\nstart 192.168.1.100\nend 192.168.1.200\noption subnet 255.255.255.0' > /tmp/udhcpd.conf");

    // // 启动udhcpd
    // execlp("udhcpd", "udhcpd", "-f", "/tmp/udhcpd.conf", NULL);

    // printf("Start udhcpd\r\n");

    return OPRT_OK;
#endif	
}

/**
 * @brief 停止软AP
 */
OPERATE_RET tkl_wifi_stop_ap(VOID_T)
{
    printf("%s\r\n", __func__);

    printf("Stop AP \r\n");

#if 0
    // 停止hostapd
    //system("killall hostapd");
    __exec_cmd("killall hostapd", NULL, 0);
    
    // 停止DHCP服务
    //system("killall udhcpd");
    __exec_cmd("killall udhcpd", NULL, 0);
    
    // 关闭网络接口
    static char g_tmp[256];
    snprintf(g_tmp, sizeof(g_tmp), "ifconfig %s down", WLAN_DEV);
    __exec_cmd(g_tmp, NULL, 0);
#endif
    return OPRT_OK;
}


// static void exec_cmd(char *pCmd)
// {
//     int secs = 0;
//     // static char g_tmp[512] = {0};
//     // int len = sizeof(g_tmp)-1;
//     printf("%s\r\n", __func__);
//     // memset(g_tmp, 0, sizeof(g_tmp));

//     printf("Exec Cmd:%s \r\n", pCmd);
//     //system(pCmd);

//     //sys_cmd_run(pCmd, NULL, NULL);

//     // sys_cmd_run(pCmd, g_tmp, &len);

//     __exec_cmd(pCmd, NULL, 0);

//     // printf("exec_cmd result:%s\r\n", g_tmp);

//     // while(secs++<10)
//     // {
//     //     sleep(1);
//     // }
//     printf("exec_cmd end\n");
// }

static int s_curr_channel = 1;
/**
 * @brief set wifi interface work channel
 * 
 * @param[in]       chan        the channel to set
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_set_cur_channel(CONST UCHAR_T chan)
{
    //static char g_tmp[100] = {0};

    printf("%s\r\n", __func__);

    snprintf(g_tmp, 100, "iwconfig %s channel %d", WLAN_DEV, chan);
    __exec_cmd(g_tmp, NULL, 0);
    s_curr_channel = chan;

    printf("WIFI Set Channel:%d \r\n", chan);

    return OPRT_OK;
}

/**
 * @brief get wifi interface work channel
 * 
 * @param[out]      chan        the channel wifi works
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_get_cur_channel(UCHAR_T *chan)
{
    printf("%s\r\n", __func__);

    if(NULL == chan) {
        return OPRT_INVALID_PARM;
    }

    FILE *pp = popen("iwlist "WLAN_DEV" channel", "r");
    if(pp == NULL){
       return OPRT_COM_ERROR;
    }

    //static char g_tmp[256] = {0};
    memset(g_tmp, 0, sizeof(g_tmp));
    while (fgets(g_tmp, sizeof(g_tmp)-1, pp) != NULL){
        char *pIPStart = strstr(g_tmp, " (Channel ");
        if(pIPStart != NULL){
            break;
        }
        memset(g_tmp, 0, sizeof(g_tmp));
    }

    /* find the channel	*/
    char *pCHANNELStart = strstr(g_tmp, " (Channel ");
    if(pCHANNELStart != NULL){
        int x = 0;
        sscanf(pCHANNELStart + strlen(" (Channel "), "%d", &x);
        *chan = x;
    }else{
        *chan = s_curr_channel;
    }

    pclose(pp);

    printf("WIFI Get Curr Channel:%d \r\n", *chan);

    return OPRT_OK;
}

OPERATE_RET tkl_wifi_set_sniffer(CONST BOOL_T en, CONST SNIFFER_CALLBACK cb)
{
    printf("%s\r\n", __func__);
    return OPRT_OK;
}

// #include <stdio.h>
// #include <stdlib.h>
// #include <string.h>
// #include <sys/ioctl.h>
// #include <net/if.h>
// #include <netinet/in.h>
// #include <arpa/inet.h>
// #include <unistd.h>

// // 错误码定义
// #define OPRT_OK          0
// #define OPRT_COM_ERROR   -1
// #define OPRT_INVALID_PARM -2

// // 网络信息结构体
// typedef struct {
//     char ip[16];       // IP地址
//     char gateway[16];  // 网关地址
//     char netmask[16];  // 子网掩码
// } NETWORK_INFO_T;

// /**
//  * @brief 获取指定接口的IP地址和子网掩码
//  * @param ifname 网络接口名（如"wlan0"）
//  * @param info 存储IP和子网掩码的结构体指针
//  * @return OPRT_OK 成功，其他值失败
//  */
// static OPERATE_RET get_ip_and_netmask(const char *ifname, NETWORK_INFO_T *info) {
//     int fd;
//     struct ifreq ifr;

//     if (!ifname || !info) {
//         return OPRT_INVALID_PARM;
//     }

//     // 创建socket
//     fd = socket(AF_INET, SOCK_DGRAM, 0);
//     if (fd < 0) {
//         perror("socket failed");
//         return OPRT_COM_ERROR;
//     }

//     // 获取IP地址 (SIOCGIFADDR)
//     memset(&ifr, 0, sizeof(ifr));
//     strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
//     ifr.ifr_addr.sa_family = AF_INET;

//     if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
//         perror("ioctl(SIOCGIFADDR) failed");
//         close(fd);
//         return OPRT_COM_ERROR;
//     }
//     inet_ntop(AF_INET, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, 
//               info->ip, sizeof(info->ip));

//     // 获取子网掩码 (SIOCGIFNETMASK)
//     memset(&ifr, 0, sizeof(ifr));
//     strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
//     ifr.ifr_netmask.sa_family = AF_INET;

//     if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0) {
//         perror("ioctl(SIOCGIFNETMASK) failed");
//         close(fd);
//         return OPRT_COM_ERROR;
//     }
//     inet_ntop(AF_INET, &((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr,
//               info->netmask, sizeof(info->netmask));

//     close(fd);
//     return OPRT_OK;
// }

// /**
//  * @brief 获取指定接口的网关地址
//  * @param ifname 网络接口名（如"wlan0"）
//  * @param gateway 存储网关地址的缓冲区
//  * @param len 缓冲区长度
//  * @return OPRT_OK 成功，其他值失败
//  */
// static OPERATE_RET get_gateway(const char *ifname, char *gateway, int len) {
//     FILE *fp;
//     char line[256];
//     char iface[16];
//     unsigned long dest, gw, flags;
//     struct in_addr addr;

//     if (!ifname || !gateway || len <= 0) {
//         return OPRT_INVALID_PARM;
//     }

//     // 打开路由表文件
//     fp = fopen("/proc/net/route", "r");
//     if (!fp) {
//         perror("fopen(/proc/net/route) failed");
//         return OPRT_COM_ERROR;
//     }

//     // 跳过表头
//     if (!fgets(line, sizeof(line), fp)) {
//         fclose(fp);
//         return OPRT_COM_ERROR;
//     }

//     // 查找指定接口的默认路由
//     while (fgets(line, sizeof(line), fp)) {
//         // 解析路由表项：接口名 目的地址 网关 标志...
//         if (sscanf(line, "%s %lx %lx %lx", iface, &dest, &gw, &flags) != 4) {
//             continue;
//         }

//         // 匹配接口名且是默认路由（目的地址为0）
//         if (strcmp(iface, ifname) == 0 && dest == 0) {
//             addr.s_addr = gw;  // 转换网关地址
//             inet_ntop(AF_INET, &addr, gateway, len);
//             fclose(fp);
//             return OPRT_OK;
//         }
//     }

//     // 未找到网关
//     fclose(fp);
//     snprintf(gateway, len, "0.0.0.0");
//     return OPRT_COM_ERROR;
// }

// /**
//  * @brief 同时获取IP、网关和子网掩码
//  * @param ifname 网络接口名（如"wlan0"）
//  * @param info 存储网络信息的结构体指针
//  * @return OPRT_OK 成功，其他值失败
//  */
// OPERATE_RET get_network_info(const char *ifname, NETWORK_INFO_T *info) {
//     if (!ifname || !info) {
//         return OPRT_INVALID_PARM;
//     }

//     // 初始化结构体
//     memset(info, 0, sizeof(NETWORK_INFO_T));

//     // 获取IP和子网掩码
//     if (get_ip_and_netmask(ifname, info) != OPRT_OK) {
//         printf("Failed to get IP and netmask\n");
//         return OPRT_COM_ERROR;
//     }

//     // 获取网关
//     if (get_gateway(ifname, info->gateway, sizeof(info->gateway)) != OPRT_OK) {
//         printf("Warning: Failed to get gateway\n");
//         // 网关获取失败不影响整体，仅作警告
//     }

//     return OPRT_OK;
// }

// 使用示例
// int main() {
//     NETWORK_INFO_T info;
//     const char *ifname = "wlan0";  // 可替换为"eth0"等接口名

//     if (get_network_info(ifname, &info) == OPRT_OK) {
//         printf("Network information for %s:\n", ifname);
//         printf("  IP Address:   %s\n", info.ip);
//         printf("  Netmask:      %s\n", info.netmask);
//         printf("  Gateway:      %s\n", info.gateway);
//     } else {
//         printf("Failed to get network information\n");
//     }

//     return 0;
// }


#if 1
STATIC OPERATE_RET hwl_get_local_ip_info(char *interface,OUT NW_IP_S *ip)
{
    int fd;
    struct ifreq ifr;
    FILE *fp;
    //static char g_tmp[256];
    char iface[16];
    unsigned long dest, gw, flags;
    struct in_addr addr;

    printf("%s\r\n", __func__);

#if 1

    // memset(ip->addr.ip4.ip, 0, 16);
    // memset(ip->addr.ip4.mask, 0, 16);
    // memset(ip->addr.ip4.gw, 0, 16);

    // strcpy(ip->addr.ip4.ip, "192.168.31.92");
    // strcpy(ip->addr.ip4.mask, "255.255.255.0");
    // strcpy(ip->addr.ip4.gw, "192.168.31.1");
    // ip->addr.ip4.islinklocal = 1;
    

    const char *ifname = "wlan0";  // 可替换为"eth0"等接口名

    // 创建socket
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        perror("socket failed");
        return OPRT_COM_ERROR;
    }

    // 获取IP地址 (SIOCGIFADDR)
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
    ifr.ifr_addr.sa_family = AF_INET;

    if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
        perror("ioctl(SIOCGIFADDR) failed");
        close(fd);
        return OPRT_COM_ERROR;
    }
    inet_ntop(AF_INET, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, 
              ip->addr.ip4.ip, sizeof(ip->addr.ip4.ip));
    printf("ip->addr.ip4.ip %s\r\n", ip->addr.ip4.ip);
    // 获取子网掩码 (SIOCGIFNETMASK)
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
    ifr.ifr_netmask.sa_family = AF_INET;

    if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0) {
        perror("ioctl(SIOCGIFNETMASK) failed");
        close(fd);
        return OPRT_COM_ERROR;
    }
    inet_ntop(AF_INET, &((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr,
              ip->addr.ip4.mask, sizeof(ip->addr.ip4.mask));
    printf("ip->addr.ip4.mask %s\r\n", ip->addr.ip4.mask);
    close(fd);


    // 打开路由表文件
    fp = fopen("/proc/net/route", "r");
    if (!fp) {
        perror("fopen(/proc/net/route) failed");
        return OPRT_COM_ERROR;
    }

    // 跳过表头
    memset(g_tmp, 0, sizeof(g_tmp));
    if (!fgets(g_tmp, sizeof(g_tmp), fp)) {
        fclose(fp);
        return OPRT_COM_ERROR;
    }

    // 查找指定接口的默认路由
    memset(g_tmp, 0, sizeof(g_tmp));
    while (fgets(g_tmp, sizeof(g_tmp), fp)) {
        // 解析路由表项：接口名 目的地址 网关 标志...
        if (sscanf(g_tmp, "%s %lx %lx %lx", iface, &dest, &gw, &flags) != 4) {
            continue;
        }

        // 匹配接口名且是默认路由（目的地址为0）
        if (strcmp(iface, ifname) == 0 && dest == 0) {
            addr.s_addr = gw;  // 转换网关地址
            inet_ntop(AF_INET, &addr, ip->addr.ip4.gw, sizeof(ip->addr.ip4.gw));
            printf("ip->addr.ip4.gw %s\r\n", ip->addr.ip4.gw);
            break;
        }

        memset(g_tmp, 0, sizeof(g_tmp));
    }

    // 未找到网关
    fclose(fp);

    // //get_ip_address("www.baidu.com", NULL);

    // // snprintf(g_tmp, sizeof(g_tmp), 
    // //          "udhcpd -f -S -i %s&",
    // //          WLAN_DEV);

    // // __exec_cmd(g_tmp, NULL, 0);

    // printf("===========================\r\n");

    return OPRT_OK;
#else

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        printf("hwl_get_local_ip_info fd < 0\r\n");
        return 0;
    }

    
    strncpy(ifr.ifr_name, WLAN_DEV, IFNAMSIZ-1);
    ifr.ifr_name[IFNAMSIZ-1] = '\0';
    printf("hwl_get_local_ip_info ifr_name:%s\r\n",ifr.ifr_name);
    // 获取IP地址
    if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
        struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr;
        close(fd);

        printf("hwl_get_local_ip_info s_addr:%s\r\n",inet_ntoa(addr->sin_addr));

        strcpy(ip->addr.ip4.ip, inet_ntoa(addr->sin_addr));
        strcpy(ip->addr.ip4.mask, "255.255.255.0");
        strcpy(ip->addr.ip4.gw, "192.168.31.1");

        // 检查是否为有效IP（非0.0.0.0）
        return (addr->sin_addr.s_addr != INADDR_ANY);
    }

    close(fd);
#endif
    return 0;
}    
#else
STATIC OPERATE_RET hwl_get_local_ip_info(char *interface,OUT NW_IP_S *ip)
{
    OPERATE_RET ret = OPRT_COM_ERROR;
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_in *sa4;
    struct sockaddr_in6 *sa6;

    printf("%s, ip->type=%d\r\n", __func__,ip->type);

    #if 1 //ym modify 25.08.18, 原来获取IP代码崩溃

    /*
    struct addrinfo hints;
    struct addrinfo *res, *p;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC; // 同时获取IPv4和IPv6
    hints.ai_socktype = SOCK_STREAM;

    int status = getaddrinfo(interface, NULL, &hints, &res);
    if (status != 0) {
        printf("getaddrinfo error: %s\n", gai_strerror(status));
        return 2;
    }
    printf("%s 22222222222222\r\n", __func__); 
    */
   #if 0
    memset(ip->addr.ip4.ip, 0, 16);
    memset(ip->addr.ip4.mask, 0, 16);
    memset(ip->addr.ip4.gw, 0, 16);

    strcpy(ip->addr.ip4.ip, "192.168.31.92");
    strcpy(ip->addr.ip4.mask, "255.255.255.0");
    strcpy(ip->addr.ip4.gw, "192.168.31.1");
    ip->addr.ip4.islinklocal = 1;



    //get_ip_address("www.baidu.com", NULL);

    //sleep(1);

    //printf("%s 333333358888888\r\n", __func__); 
    ret = OPRT_OK;
   #else
    if(ip == NULL)
    {
        printf("ip == NULL\r\n");
        return OPRT_COM_ERROR;
    }

    if(strlen(g_ip.addr.ip4.ip)>0)
    {
        memcpy(ip, &g_ip, sizeof(NW_IP_S));

        printf("use last ip:%s\r\n",g_ip.addr.ip4.ip);
        return OPRT_OK;
    }

    memset(&g_ip, 0, sizeof(g_ip));

    FILE *pp = popen("ifconfig "WLAN_DEV, "r");
    printf("tkl_wifi_get_ip  22\r\n");
    if(pp == NULL){
        printf("pp == NULL\n");
       return OPRT_COM_ERROR;
    }

    memset(g_tmp, 0, sizeof(g_tmp));
    printf("tkl_wifi_get_ip  33\r\n");
    /*
    wlan0     Link encap:Ethernet  HWaddr 5C:4E:EE:24:4D:8F  
          inet addr:192.168.31.92  Bcast:192.168.31.255  Mask:255.255.255.0
          inet6 addr: 240e:3b3:30c2:21d0:5e4e:eeff:fe24:4d8f/64 Scope:Global
          inet6 addr: fe80::5e4e:eeff:fe24:4d8f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:13 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:2986 (2.9 KiB)  TX bytes:3464 (3.3 KiB)*/
    while (fgets(g_tmp, sizeof(g_tmp)-1, pp) != NULL){
        //ym modify 25.08.16
        printf("g_tmp=%s\n", g_tmp);
        char *pMACStart = strstr(g_tmp, IPV4_PREV);
        if(pMACStart != NULL && TY_AF_INET == ip->type){
            char bcast[16] = {0};

            memset(ip->addr.ip4.ip, 0, 16);
            memset(ip->addr.ip4.mask, 0, 16);
            memset(ip->addr.ip4.gw, 0, 16);

            sscanf(pMACStart + strlen(IPV4_PREV), "%s  Bcast:%s  Mask:%s",ip->addr.ip4.ip, bcast, ip->addr.ip4.mask);
            
            printf("ip:%s,bcast:%s,mask:%s\r\n", ip->addr.ip4.ip, bcast, ip->addr.ip4.mask);
            ret = OPRT_OK;
            break;
        }
        pMACStart = strstr(g_tmp, IPV6_PREV);
        if(pMACStart != NULL && TY_AF_INET6 == ip->type){
            char Scope[16] = {0};

            memset(ip->addr.ip6.ip, 0, 40);

            sscanf(pMACStart + strlen(IPV6_PREV), "%s Scope:%s",ip->addr.ip6.ip, Scope);
            
            if(!strcmp(Scope, "Link"))
                ip->addr.ip6.islinklocal = 1;
            else
                ip->addr.ip6.islinklocal = 0;

            printf("ip6:%s,islinklocal:%d, Scope:%s\r\n", ip->addr.ip6.ip, ip->addr.ip6.islinklocal, Scope);
            ret = OPRT_OK;
            break;
        }

        memset(g_tmp, 0, sizeof(g_tmp));
    }
    pclose(pp);

    pp = popen("ip route | grep default", "r");
    printf("tkl_wifi_get_ip  get gateway\r\n");
    if(pp == NULL){
        printf("pp == NULL\n");
       return OPRT_COM_ERROR;
    }

    memset(g_tmp, 0, sizeof(g_tmp));
    printf("tkl_wifi_get_ip  get gateway 33\r\n");
    /*
    default via 192.168.31.1 dev wlan0*/
    while (fgets(g_tmp, sizeof(g_tmp)-1, pp) != NULL){
        //ym modify 25.08.16
        printf("g_tmp=%s\n", g_tmp);
        char *pMACStart = strstr(g_tmp, WLAN_DEV);
        if(pMACStart != NULL){
            char dev[16] = {0};
            sscanf(g_tmp, "default via %s dev %s",ip->addr.ip4.gw, dev);
            
            printf("gateway:%s,dev:%s\r\n", ip->addr.ip4.gw, dev);
            break;
        }
        memset(g_tmp, 0, sizeof(g_tmp));
    }
    pclose(pp);

    if(ret == OPRT_OK)
        memcpy(&g_ip, ip, sizeof(g_ip));  //下次直接读取，不再耗时查询
    #endif

    #else
    if (getifaddrs(&ifap) == -1) {
        printf("getifaddrs\n");
        return OPRT_COM_ERROR;
    }
    printf("%s  22222222\r\n", __func__);
    for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == NULL) continue;
        printf("ifa->ifa_name %s \r\n", ifa->ifa_name);
        if (strcmp(ifa->ifa_name, interface) == 0) {
            if ((ifa->ifa_addr->sa_family == AF_INET)&&(TY_AF_INET == ip->type)) {
                sa4 = (struct sockaddr_in *) ifa->ifa_addr;
                printf("sa4 %d \r\n", sa4);
                if (inet_ntop(AF_INET, &sa4->sin_addr, ip->addr.ip4.ip, sizeof(ip->addr.ip4.ip))) {
                    printf("Interface: %s\n", ifa->ifa_name);
                    printf("IP Address: %s\n", ip->addr.ip4.ip);
                }
                sa4 = (struct sockaddr_in *)ifa->ifa_netmask;
                if (inet_ntop(AF_INET, &sa4->sin_addr, ip->addr.ip4.mask, sizeof(ip->addr.ip4.mask))) {
                    printf("Netmask: %s\n", ip->addr.ip4.mask);
                }
                sa4 = (struct sockaddr_in *)ifa->ifa_ifu.ifu_broadaddr;
                if (inet_ntop(AF_INET, &sa4->sin_addr, ip->addr.ip4.gw, sizeof(ip->addr.ip4.gw))) {
                    printf("Gateway: %s\n", ip->addr.ip4.gw);
                }
                ret = OPRT_OK;
                break;
            } else if ((ifa->ifa_addr->sa_family == AF_INET6)&&(TY_AF_INET6 == ip->type)) {
                sa6 = (struct sockaddr_in6 *) ifa->ifa_addr;
                inet_ntop(AF_INET6, &(sa6->sin6_addr), ip->addr.ip6.ip, sizeof(ip->addr.ip6.ip));
                printf("Interface Name: %s\n", ifa->ifa_name);
                printf("IPv6 Address: %s\n", ip->addr.ip6.ip);
                ret = OPRT_OK;
                break;
            }else{
                ret = OPRT_COM_ERROR;
            }
        }else{
            ret = OPRT_COM_ERROR;
        }
    }
    printf("%s  4444444\r\n", __func__);
    freeifaddrs(ifap);
    #endif
    return ret;
}
#endif
/**
 * @brief get wifi ip info.when wifi works in
 *        ap+station mode, wifi has two ips.
 * 
 * @param[in]       wf          wifi function type
 * @param[out]      ip          the ip addr info
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_get_ip(CONST WF_IF_E wf, NW_IP_S *ip)
{
    printf("%s\r\n", __func__);

    if(NULL == ip){
        return OPRT_INVALID_PARM;
    }
    OPERATE_RET ret = OPRT_OK;

    //get the ip of ethernet
    if (TY_AF_INET == ip->type){
        ret = hwl_get_local_ip_info(WLAN_DEV,ip);
    }else if (TY_AF_INET6 == ip->type){
        ret = hwl_get_local_ip_info(WLAN_DEV,ip);    
    }else{
        printf("not support ip type[%d]\n",ip->type);
        ret = OPRT_NOT_SUPPORTED;
    }
    if (OPRT_OK == ret){
        printf("WIFI mode[%d] Get IP:%s\r\n", wf, ip->type == TY_AF_INET? ip->addr.ip4.ip:ip->addr.ip6.ip);
    }else {
        printf("WIFI mode[%d] Get IP failed\r\n", wf);     
    }
    return ret;
}

/**
 * @brief get wifi ipv6 info.when wifi works in
 *        ap+station mode, wifi has two ips.
 * 
 * @param[in]       wf          wifi function type
 * @param[out]      type          the ip type
 * @param[out]      ip          the ip addr info
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_get_ipv6(CONST WF_IF_E wf, NW_IP_TYPE type, NW_IP_S *ip)
{
    printf("%s\r\n", __func__);

    OPERATE_RET ret = OPRT_OK;
    ret = hwl_get_local_ip_info(WLAN_DEV,ip); 
    if (OPRT_OK == ret){
        printf("WIFI mode[%d] Get IPV6:%s\r\n", wf, ip->addr.ip6.ip);
    }else {
        printf("WIFI mode[%d] Get IPV6 failed\r\n", wf);     
    }
    return ret;    
}

/**
 * @brief set wifi mac info.when wifi works in
 *        ap+station mode, wifi has two macs.
 * 
 * @param[in]       wf          wifi function type
 * @param[in]       mac         the mac info
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_set_mac(CONST WF_IF_E wf, CONST NW_MAC_S *mac)
{
    printf("%s\r\n", __func__);

    if(NULL == mac){
        return OPRT_INVALID_PARM;
    }
    printf("WIFI Set MAC\r\n");
    //reserved
    return OPRT_OK;
}

/**
 * @brief get wifi mac info.when wifi works in
 *        ap+station mode, wifi has two macs.
 * 
 * @param[in]       wf          wifi function type
 * @param[out]      mac         the mac info
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_get_mac(CONST WF_IF_E wf, NW_MAC_S *mac)
{
    printf("%s\r\n", __func__);

    if(NULL == mac){
        printf("OPRT_INVALID_PARM\r\n");
        return OPRT_INVALID_PARM;
    }

    if(strlen(g_mac)>0)
    {
        memcpy(mac->mac, g_mac, sizeof(g_mac));
        printf("use last g_mac, WIFI Get MAC %02X-%02X-%02X-%02X-%02X-%02X\r\n",
           mac->mac[0],mac->mac[1],mac->mac[2],mac->mac[3],mac->mac[4],mac->mac[5]);
        return OPRT_OK;
    }

    FILE *pp = popen("ifconfig "WLAN_DEV, "r");
    printf("tkl_wifi_get_mac  22\r\n");
    if(pp == NULL){
        printf("pp == NULL\n");
       return OPRT_COM_ERROR;
    }

    memset(g_tmp, 0, sizeof(g_tmp));
    printf("tkl_wifi_get_mac  33\r\n");
    while (fgets(g_tmp, sizeof(g_tmp)-1, pp) != NULL){
        //ym modify 25.08.16
        printf("g_tmp=%s\n", g_tmp);
        char *pMACStart = strstr(g_tmp, MAC_PREV);
        if(pMACStart != NULL){
            int x1,x2,x3,x4,x5,x6;
            sscanf(pMACStart + strlen(MAC_PREV), "%x:%x:%x:%x:%x:%x",&x1,&x2,&x3,&x4,&x5,&x6);
            mac->mac[0] = x1 & 0xFF;
            mac->mac[1] = x2 & 0xFF;
            mac->mac[2] = x3 & 0xFF;
            mac->mac[3] = x4 & 0xFF;
            mac->mac[4] = x5 & 0xFF;
            mac->mac[5] = x6 & 0xFF;
            
            memcpy(g_mac, mac->mac,  sizeof(g_mac));

            break;
        }
        memset(g_tmp, 0, sizeof(g_tmp));
    }
    pclose(pp);
    printf("WIFI Get MAC %02X-%02X-%02X-%02X-%02X-%02X\r\n",
           mac->mac[0],mac->mac[1],mac->mac[2],mac->mac[3],mac->mac[4],mac->mac[5]);

    return OPRT_OK;
}

/**
 * @brief set wifi work mode
 * 
 * @param[in]       mode        wifi work mode
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_set_work_mode(CONST WF_WK_MD_E mode)
{
    OPERATE_RET ret = OPRT_OK;

    printf("%s, mode=%d\r\n", __func__, mode);

    if(mode == g_work_mode)
    {
        printf("mode not change,return\r\n");
        return OPRT_OK;
    }

#if 0 //ym删除，次命令 崩溃
    snprintf(g_tmp, 100, "ifconfig %s up", WLAN_DEV);
    __exec_cmd(g_tmp, NULL, 0);
#endif

    switch (mode)
    {
        case WWM_POWERDOWN:
        {
            //Linux system does not care about low power 
            break;
        }
        case WWM_SNIFFER:
        {
            snprintf(g_tmp, 100, "iwconfig %s mode Monitor", WLAN_DEV);
            __exec_cmd(g_tmp, NULL, 0);
            break;
        }
        case WWM_STATION:
        {
            #if 1//def CHIP_ANYKA
    //         __exec_cmd("killall wpa_supplicant\n\
    // killall udhcpc\n\
    // killall udhcpd\n\
    // killall hostapd\n\
    // killall nimble_linux\n\
    // sleep 2\n\
    // rmmod atbm6012bx\n\
    // sleep 2\n\
    // rmmod ak_hcd\n\
    // rmmod usbcore\n\
    // rmmod usb-common\n\
    // rmmod cfg80211\n\
    // modprobe firmware_class path=/usr/sbin\n\
    // modprobe cfg80211\n\
    // modprobe usb-common\n\
    // modprobe nls_base\n\
    // modprobe usbcore\n\
    // insmod /usr/modules/ak_hcd.ko\n\
    // modprobe libarc4\n\
    // insmod /usr/modules/atbm6012bx.ko\n\
    // sleep 3\n\
    // udhcpc -i wlan0\n\
    //     ;;", NULL, 0);
            g_work_mode = mode;
            //__exec_cmd("/usr/sbin/wifi_driver.sh sta &", NULL, 0);
            ret = OPRT_OK;
            #else
            snprintf(g_tmp, 100, "iwconfig %s mode Managed", WLAN_DEV);
            __exec_cmd(g_tmp, NULL, 0);
            #endif
            break;
        }
        case WWM_SOFTAP:
        {
            #ifdef CHIP_ANYKA
			/*
            __exec_cmd("killall wpa_supplicant\n\
    killall udhcpc\n\
    killall udhcpd\n\
    killall hostapd\n\
    killall nimble_linux\n\
    sleep 2\n\
    rmmod atbm6012bx\n\
    sleep 2\n\
    rmmod ak_hcd\n\
    rmmod usbcore\n\
    rmmod usb-common\n\
    rmmod cfg80211\n\
    modprobe firmware_class path=/usr/sbin\n\
    modprobe cfg80211\n\
    modprobe usb-common\n\
    modprobe nls_base\n\
    modprobe usbcore\n\
    insmod /usr/modules/ak_hcd.ko\n\
    modprobe libarc4\n\
    insmod /usr/modules/atbm6012bx.ko\n\
    sleep 3ifconfig wlan0  172.14.10.1\n\
        mkdir -p /var/lib/misc/\n\
        touch /var/lib/misc/udhcpd.leases\n\
	rm -f /dev/random\n\
	ln -s  /dev/urandom  /dev/random\n\
        udhcpd -S /etc/config/udhcpd.conf &\n\
        hostapd -dd -S -B /etc/config/hostapd.conf\n\
        ;;", NULL, 0);*/
            g_work_mode = mode;
			//__exec_cmd("/usr/sbin/wifi_driver.sh ap &", NULL, 0);
            ret = OPRT_OK;
            #else
            //snprintf(g_tmp, 100, "iwconfig %s mode Master", WLAN_DEV);
            //__exec_cmd(g_tmp, NULL, 0);
            ret = OPRT_COM_ERROR;
            #endif
            break;
        }
        case WWM_STATIONAP:
        {//reserved
            break;
        }
        default:
        {
            break;
        }
    }
    printf("WIFI Set Mode %d\r\n", mode);

    //ym add 25.08.18 ,尽量减少查询，耗时操作导致崩溃
    // if(ret != OPRT_OK)
    //     g_work_mode = WWM_POWERDOWN;
    return ret;
}

/**
 * @brief get wifi work mode
 * 
 * @param[out]      mode        wifi work mode
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_get_work_mode(WF_WK_MD_E *mode)
{
    printf("%s, g_work_mode=%d\r\n", __func__, g_work_mode);

    if(NULL == mode){
        printf("NULL == mode\r\n");
        return OPRT_INVALID_PARM;
    }

    //ym add 25.08.18 ,尽量减少查询，耗时操作导致崩溃
    if (g_work_mode != WWM_POWERDOWN)
    {
        *mode = g_work_mode;
        printf("use last mode val:%d", *mode);
        return OPRT_OK;
    }

    FILE *pp = popen("iwconfig "WLAN_DEV, "r");
    if(pp == NULL){
        printf("WIFI Get Mode Fail. Force Set Station \r\n");
        *mode = WWM_STATION;
        return OPRT_OK;
    }

    char scan_mode[10] = {0};
    memset(g_tmp, 0, sizeof(g_tmp));
    while (fgets(g_tmp, sizeof(g_tmp)-1, pp) != NULL){
        char *pModeStart = strstr(g_tmp, "Mode:");
        if(pModeStart != NULL){
            int x1,x2,x3,x4,x5,x6;
            sscanf(pModeStart + strlen("Mode:"), "%s ", scan_mode);
            break;
        }
        memset(g_tmp, 0, sizeof(g_tmp));
    }
    pclose(pp);

    *mode = WWM_STATION;
    if(strncasecmp(scan_mode, "Managed", strlen("Managed")) == 0){
        *mode = WWM_STATION;
    }
    if(strncasecmp(scan_mode, "Master", strlen("Master")) == 0){
        *mode = WWM_SOFTAP;
    }
    if(strncasecmp(scan_mode, "Monitor", strlen("Monitor")) == 0){
        *mode = WWM_SNIFFER;
    }
    printf("WIFI Get Mode [%s] %d\r\n", scan_mode, *mode);

    //ym add 25.08.18 ,尽量减少查询，耗时操作导致崩溃
    g_work_mode = *mode;

    return OPRT_OK;
}

/**
 * @brief : get ap info for fast connect
 * @param[out]      fast_ap_info
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
// OPERATE_RET tkl_wifi_get_connected_ap_info(FAST_WF_CONNECTED_AP_INFO_T **fast_ap_info)
// {
//     printf("%s-%d not support\n",__FUNCTION__,__LINE__);
//     return OPRT_NOT_SUPPORTED;
// }


// 内部函数声明
static WF_STATION_STAT_E get_wifi_status(void);
static void notify_wifi_event(WF_EVENT_E event);
static int get_dhcp_info(FAST_DHCP_INFO_T *dhcp_info);

/**
 * @brief 获取当前WiFi状态
 * 
 * @return 当前WiFi状态
 */
static WF_STATION_STAT_E get_wifi_status(void)
{
    struct iwreq wreq;
    int sockfd;


    printf("%s\r\n", __func__);

    // 尝试打开socket获取WiFi状态
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        return WSS_CONN_FAIL;
    }
    printf("%s 222\r\n", __func__);
    memset(&wreq, 0, sizeof(wreq));
    strncpy(wreq.ifr_name, "wlan0", IFNAMSIZ);

    // 检查是否已关联到AP
    if (ioctl(sockfd, SIOCGIWSTATS, &wreq) == 0) {
        close(sockfd);
        
        
        memset(g_tmp, 0, sizeof(g_tmp));
        // 检查是否获取到IP地址
        if (__exec_cmd("ip -4 addr show wlan0 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}'", g_tmp, sizeof(g_tmp)) == 0) {
            return WSS_GOT_IP;
        } else {
            return WSS_CONN_SUCCESS;
        }
    }

    close(sockfd);

    // 检查是否正在连接
    if (__exec_cmd("wpa_cli -i wlan0 status | grep 'wpa_state=SCANNING\\|wpa_state=ASSOCIATING\\|wpa_state=ASSOCIATED\\|wpa_state=4WAY_HANDSHAKE\\|wpa_state=GROUP_HANDSHAKE'", g_tmp, sizeof(g_tmp)) == 0) {
        return WSS_CONNECTING;
    }

    // 检查密码是否错误
    if (__exec_cmd("dmesg | grep 'wlan0: failed to authenticate with' | tail -n 1", g_tmp, sizeof(g_tmp)) == 0) {
        return WSS_PASSWD_WRONG;
    }

    // 检查AP是否不存在
    if (__exec_cmd("dmesg | grep 'wlan0: AP .* not found' | tail -n 1", g_tmp, sizeof(g_tmp)) == 0) {
        return WSS_NO_AP_FOUND;
    }

    return WSS_IDLE;
}

/**
 * @brief 通知WiFi事件
 * 
 * @param event 要通知的事件
 */
static void notify_wifi_event(WF_EVENT_E event)
{
    // 这里应该实现实际的事件通知机制
    // 例如调用涂鸦SDK提供的回调函数
    printf("WiFi event notified: %d\n", event);
}

/**
 * @brief 获取DHCP信息
 * 
 * @param dhcp_info 存储DHCP信息的结构体指针
 * @return 0 成功, -1 失败
 */
static int get_dhcp_info(FAST_DHCP_INFO_T *dhcp_info)
{
    printf("%s\r\n", __func__);
    if (dhcp_info == NULL) {
        return -1;
    }

    memset(g_tmp, 0, sizeof(g_tmp));
    // 获取IP地址
    if (__exec_cmd("ip -4 addr show wlan0 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}'", g_tmp, sizeof(g_tmp)) != 0) {
        return -1;
    }
    strncpy(dhcp_info->ip, g_tmp, sizeof(dhcp_info->ip) - 1);

    // 获取子网掩码
    if (__exec_cmd("ip -4 addr show wlan0 | grep -oP '(?<=netmask\\s)\\d+(\\.\\d+){3}'", g_tmp, sizeof(g_tmp)) != 0) {
        return -1;
    }
    strncpy(dhcp_info->mask, g_tmp, sizeof(dhcp_info->mask) - 1);

    // 获取网关
    if (__exec_cmd("ip route show default | grep -oP '(?<=via\\s)\\d+(\\.\\d+){3}'", g_tmp, sizeof(g_tmp)) != 0) {
        return -1;
    }
    strncpy(dhcp_info->gw, g_tmp, sizeof(dhcp_info->gw) - 1);

    // 获取DNS服务器
    if (__exec_cmd("grep nameserver /etc/resolv.conf | head -n 1 | awk '{print $2}'", g_tmp, sizeof(g_tmp)) != 0) {
        return -1;
    }
    strncpy(dhcp_info->dns, g_tmp, sizeof(dhcp_info->dns) - 1);

    return 0;
}



// #include "tuya_hal_wifi.h"
// #include "tuya_error_code.h"

// // 假设WiFi接口名称为wlan0，实际应用中可能需要修改
// #define WLAN_DEV "wlan0"

/**
 * @brief 从/proc/net/wireless获取WiFi连接状态
 * @return 1表示已连接，0表示未连接
 */
static int __is_wifi_connected(void)
{
    FILE *fp = fopen("/proc/net/wireless", "r");

    // char face[16] = {0};
    // int tus,link,level,noise,nwid,crypt,frag,retry,misc,beacon;


    printf("%s\r\n", __func__);

    if (fp == NULL) {
        return 0;
    }

    //char g_tmp[256];
    int connected = 0;
	int count = 0;

    // __exec_cmd("tkl_system_free -h", g_tmp, sizeof(g_tmp));
    // printf("mem:\n", g_tmp);
    {
        FILE *file = fopen("/proc/meminfo", "r");
        if (file) {
            while (fgets(g_tmp, sizeof(g_tmp), file)) {
                printf("%s", g_tmp); // 输出内存信息（如MemTotal、MemFree等）
                memset(g_tmp, 0, sizeof(g_tmp));
				if(count++>4)
				{
					break;
				}
            }
            fclose(file);
        }
    }

    memset(g_tmp, 0, sizeof(g_tmp));
    // 跳过前两行标题
    fgets(g_tmp, sizeof(g_tmp), fp);
    //printf("%s 0 g_tmp:%s\r\n", __func__, g_tmp);
    fgets(g_tmp, sizeof(g_tmp), fp);
    //printf("%s 1 g_tmp:%s\r\n", __func__, g_tmp);
    
    // 查找WiFi接口状态
    while (fgets(g_tmp, sizeof(g_tmp), fp)) {
        //printf("%s 3 g_tmp:%s\r\n", __func__, g_tmp);
        
        #if 1
        // wlan0: 0000    0     0     0        0      0      0      0      0        0
        if(strstr(g_tmp, WLAN_DEV) != NULL && strstr(g_tmp, WLAN_DEV": 0000    0     0     0")== NULL)
        {
            connected = 1;
            printf("connected = 1\r\n");
            break;
        }
        #else
        //
        if (sscanf(g_tmp, " %s: %d    %d     %d     %d        %d      %d      %d      %d      %d        %d", face,&tus,&link,&level,&noise,&nwid,&crypt,&frag,&retry,&misc,&beacon) == 11)
        {
            printf("sscanf succ\r\n");
        }

        printf("parser: %s: %d    %d     %d     %d        %d      %d      %d      %d      %d        %d\r\n", face,&tus,&link,&level,&noise,&nwid,&crypt,&frag,&retry,&misc,&beacon);
        
        if (strstr(g_tmp, WLAN_DEV) != NULL && level>0) 
        {
            // 找到接口，检查状态
            printf("connected = 1\r\n");
            connected = 1;
            break;
        }
        #endif
    }
    
    fclose(fp);
    return connected;
}

/**
 * @brief 检查是否获取到IP地址
 * @return 1表示已获取，0表示未获取
 */
static int __has_ip_address(void)
{
    int fd;
    struct ifreq ifr;

    printf("%s\r\n", __func__);

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        printf("__has_ip_address fd < 0\r\n");
        return 0;
    }

    
    strncpy(ifr.ifr_name, WLAN_DEV, IFNAMSIZ-1);
    ifr.ifr_name[IFNAMSIZ-1] = '\0';
    printf("__has_ip_address ifr_name:%s\r\n",ifr.ifr_name);
    // 获取IP地址
    if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
        struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr;
        close(fd);

        printf("__has_ip_address s_addr:%s\r\n",inet_ntoa(addr->sin_addr));


        // 检查是否为有效IP（非0.0.0.0）
        return (addr->sin_addr.s_addr != INADDR_ANY);
    }

    close(fd);
    return 0;
}

/**
 * @brief 获取当前连接的SSID
 * @param ssid 存储SSID的缓冲区
 * @param max_len 缓冲区最大长度
 * @return 成功返回0，失败返回-1
 */
static int __get_connected_ssid(char *ssid, int max_len)
{
    printf("%s\r\n", __func__);

    // FILE *fp;
    //  = fopen("/proc/net/wireless", "r");
    // if (fp == NULL) {
    //     printf("fp == NULL\r\n");
    //     return -1;
    // }

#if 1
    char cmd[32]={0};
    memset(g_tmp, 0, sizeof(g_tmp));
    snprintf(cmd, sizeof(cmd), "iwconfig %s | grep ESSID", WLAN_DEV);
    __exec_cmd(cmd, g_tmp, sizeof(g_tmp)-1);
    printf("%s  g_tmp=%s \r\n", __func__,g_tmp);
    //wlan0     IEEE 802.11  ESSID:"HHO" 
    char *p,*q;
    char* essid = "ESSID:\"";
    p = strstr(g_tmp, essid);
    if(p)
    {
        q = strstr(p+strlen(essid), "\"");
        p += strlen(essid);
        if(q)
        {
            
            if(q-p>max_len)
            {
                printf("%s error: max_len<q-p \r\n",__func__);

                return -1;
            }
                
            memset(ssid, 0, max_len);
            strncpy(ssid, p, q-p);

            printf("%s %s\r\n", __func__,ssid);
            return 0; //success
        }
    }
    
    return -1;
#else

    fp = popen(g_tmp, "r");
    printf("__get_connected_ssid 22 0000\r\n");
    if (fp == NULL) {
        printf("__get_connected_ssid 33\r\n");
        return -1;
    }
    printf("__get_connected_ssid 22  1111\r\n");
    //char g_tmp[256] = {0};
    memset(g_tmp, 0, sizeof(g_tmp));
    if (fgets(g_tmp, sizeof(g_tmp), fp) == NULL) {
        printf("__get_connected_ssid 44\r\n");
        pclose(fp);
        return -1;
    }
    pclose(fp);
    printf("__get_connected_ssid g_tmp:%s\r\n", g_tmp);
    // 解析ESSID
    regex_t regex;
    regmatch_t pmatch[2];
    const char *pattern = "ESSID:\"([^\"]+)\"";
    
    if (regcomp(&regex, pattern, REG_EXTENDED) != 0) {
        return -1;
    }

    printf("__get_connected_ssid 55\r\n");
    int ret = regexec(&regex, g_tmp, 2, pmatch, 0);
    printf("__get_connected_ssid 66 ret=%d\r\n", ret);
    if (ret == 0 && pmatch[1].rm_so != -1) {
        int len = pmatch[1].rm_eo - pmatch[1].rm_so;
        if (len >= max_len) {
            len = max_len - 1;
        }

        printf("__get_connected_ssid 55 000\r\n");


        strncpy(ssid, g_tmp + pmatch[1].rm_so, len);
        ssid[len] = '\0';
        regfree(&regex);
        return 0;
    }

    printf("__get_connected_ssid 66\r\n");
    regfree(&regex);
    printf("__get_connected_ssid 77\r\n");
    return -1;
#endif    
}

/**
 * @brief 获取当前连接的BSSID
 * @param bssid 存储BSSID的缓冲区
 * @param max_len 缓冲区最大长度
 * @return 成功返回0，失败返回-1
 */
static int __get_connected_bssid(char *bssid, int max_len)
{
    printf("%s\r\n", __func__);

#if 1
    char cmd[64]={0};
    
    memset(g_tmp, 0, sizeof(g_tmp));
    snprintf(cmd, sizeof(cmd), "iwconfig %s | grep Access", WLAN_DEV);
    __exec_cmd(cmd, g_tmp, sizeof(g_tmp)-1);
    printf("%s  g_tmp=%s \r\n", __func__,g_tmp);
    //          Mode:Managed  Frequency:2.412 GHz  Access Point: 44:F7:70:B6:F1:92   
    char *p,*q;
    char* essid = "Access Point: ";
    p = strstr(g_tmp, essid);
    if(p)
    {
        q = strstr(p+strlen(essid), " ");
        p += strlen(essid);
        if(q)
        {
            
            if(q-p>max_len)
            {
                printf("%s error: max_len<q-p \r\n",__func__);

                return -1;
            }
                
            memset(bssid, 0, max_len);
            strncpy(bssid, p, q-p);

            printf("%s %s\r\n", __func__,bssid);
            return 0; //success
        }
    }
    
    return -1;

#else

    snprintf(g_tmp, sizeof(g_tmp), "iwconfig %s | grep Access Point", WLAN_DEV);
    
    FILE *fp = popen(g_tmp, "r");
    if (fp == NULL) {
        return -1;
    }

    char g_tmp[256] = {0};
    if (fgets(g_tmp, sizeof(g_tmp), fp) == NULL) {
        pclose(fp);
        return -1;
    }
    pclose(fp);

    // 解析BSSID
    regex_t regex;
    regmatch_t pmatch[2];
    const char *pattern = "Access Point: ([0-9A-Fa-f:]+)";
    
    if (regcomp(&regex, pattern, REG_EXTENDED) != 0) {
        return -1;
    }

    int ret = regexec(&regex, g_tmp, 2, pmatch, 0);
    if (ret == 0 && pmatch[1].rm_so != -1) {
        int len = pmatch[1].rm_eo - pmatch[1].rm_so;
        if (len >= max_len) {
            len = max_len - 1;
        }
        strncpy(bssid, g_tmp + pmatch[1].rm_so, len);
        bssid[len] = '\0';
        regfree(&regex);
        return 0;
    }

    regfree(&regex);
    return -1;
#endif    
}


/**
 * @brief : get ap info for fast connect
 * @param[out]      fast_ap_info
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_get_connected_ap_info(FAST_WF_CONNECTED_AP_INFO_T **fast_ap_info)
{
    printf("%s\r\n", __func__);
	
	
	return OPRT_COM_ERROR;
    
    // if (fast_ap_info == NULL) {
    //     printf("fast_ap_info == NULL\r\n");
    //     return OPRT_INVALID_PARM;
    // }
    // printf("%s  11\r\n", __func__);
    // // 先检查WiFi状态
    // WF_STATION_STAT_E stat;
    // OPERATE_RET ret = tkl_wifi_station_get_status(&stat);
    // if (ret != OPRT_OK) {
    //     return ret;
    // }
    // printf("%s  22\r\n", __func__);
    // // 只有在已连接状态下才返回AP信息
    // if (stat != WSS_CONN_SUCCESS && stat != WSS_GOT_IP) {
    //     *fast_ap_info = NULL;
    //     return OPRT_COM_ERROR;
    // }
    // printf("%s  33\r\n", __func__);
    // // 收集AP信息：SSID(32字节) + BSSID(18字节)
    // // #define SSID_MAX_LEN 32
    // // #define BSSID_MAX_LEN 18
    // UINT_T data_len = SSID_MAX_LEN + BSSID_MAX_LEN;
    // UINT_T total_len = sizeof(FAST_WF_CONNECTED_AP_INFO_T) + data_len;
    // printf("%s  44\r\n", __func__);
    // // 分配内存
    // *fast_ap_info = (FAST_WF_CONNECTED_AP_INFO_T *)tkl_system_malloc(total_len);
    // if (*fast_ap_info == NULL) {
    //     return OPRT_MALLOC_FAILED;
    // }
    // printf("%s  55\r\n", __func__);
    // // 初始化数据
    // memset(*fast_ap_info, 0, total_len);
    // (*fast_ap_info)->len = data_len;
    // printf("%s  66\r\n", __func__);
    // // 获取并填充SSID
    // char ssid[SSID_MAX_LEN + 1] = {0};
    // if (__get_connected_ssid(ssid, SSID_MAX_LEN) != 0) {
    //     tkl_system_free(*fast_ap_info);
    //        *fast_ap_info= NULL;
    //     return OPRT_COM_ERROR;
    // }
    // printf("%s  77\r\n", __func__);
    // memcpy((*fast_ap_info)->data, ssid, SSID_MAX_LEN);

    // 获取并填充BSSID
    // char bssid[BSSID_MAX_LEN + 1] = {0};
    // if (__get_connected_bssid(bssid, BSSID_MAX_LEN) != 0) {
    //     return OPRT_COM_ERROR;
    // }
    // memcpy((*fast_ap_info)->data + SSID_MAX_LEN, bssid, BSSID_MAX_LEN);
    
    // printf("%s  88\r\n", __func__);
    // return OPRT_OK;
}

/**
 * @brief get wifi bssid
 * 
 * @param[out]      mac         uplink mac
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_get_bssid(UCHAR_T *mac)
{
    printf("%s,%s\r\n", __func__, mac);

    // 获取并填充BSSID
    char bssid[BSSID_MAX_LEN + 1] = {0};
    if (__get_connected_bssid(bssid, BSSID_MAX_LEN) != 0) {
        return OPRT_COM_ERROR;
    }
    strcpy(mac, bssid);

    return OPRT_OK;
}

/**
 * @brief 设置WiFi国家代码
 * 
 * @param[in] ccode 国家代码
 * @return OPRT_OK 成功, 其他值 失败
 */
OPERATE_RET tkl_wifi_set_country_code(CONST COUNTRY_CODE_E ccode)
{
    printf("%s, Set Country Code:%d \r\n", __func__, ccode);
    
    // char cmd[64] = {0};
    // char *country_str = NULL;

    // // 根据国家代码选择对应的国家代码字符串
    // switch (ccode) {
    //     case COUNTRY_CODE_CN:
    //         country_str = "CN";
    //         break;
    //     case COUNTRY_CODE_US:
    //         country_str = "US";
    //         break;
    //     case COUNTRY_CODE_JP:
    //         country_str = "JP";
    //         break;
    //     case COUNTRY_CODE_EU:
    //         country_str = "DE";  // 以德国代表欧盟地区
    //         break;
    //     default:
    //         printf("Invalid country code: %d\n", ccode);
    //         return OPRT_INVALID_PARM;
    // }

    // // 构造并执行设置国家代码的命令
    // snprintf(cmd, sizeof(cmd), "wpa_cli -i wlan0 set country %s", country_str);
    // memset(g_tmp, 0, sizeof(g_tmp));
    // if (__exec_cmd(cmd, g_tmp, sizeof(g_tmp)) != 0) {
    //     printf("Failed to set country code\n");
    //     return OPRT_COM_ERROR;
    // }

    // // 重新加载配置使设置生效
    // __exec_cmd("wpa_cli -i wlan0 reconfigure", g_tmp, sizeof(g_tmp));
    return OPRT_OK;
}

/**
 * @brief 执行WiFi校准
 *
 * @note 测试WiFi时调用
 *
 * @return OPRT_OK 成功, 其他值 失败
 */
OPERATE_RET tkl_wifi_set_rf_calibrated(VOID_T)
{
    printf("%s\r\n", __func__);
    
    // 在Linux系统中，WiFi校准通常由固件处理
    // 这里可以添加校准相关的命令或操作
    
    // memset(g_tmp, 0, sizeof(g_tmp));
    // // 检查WiFi设备是否存在
    // if (__exec_cmd("iw list", g_tmp, sizeof(g_tmp)) != 0) {
    //     printf("No WiFi interface found\n");
    //     return OPRT_COM_ERROR;
    // }
    
    // // 对于某些设备，可能需要执行校准命令
    // // 这通常是硬件相关的，这里仅作示例
    // __exec_cmd("iw dev wlan0 set txpower fixed 20dBm", g_tmp, sizeof(g_tmp));
    
    return OPRT_OK;
}

/**
 * @brief 设置WiFi低功耗模式
 * 
 * @param[in] enable 是否启用低功耗模式
 * @param[in] dtim DTIM值
 * @return OPRT_OK 成功, 其他值 失败
 */
OPERATE_RET tkl_wifi_set_lp_mode(CONST BOOL_T enable, CONST UCHAR_T dtim)
{
    printf("%s, enable: %d, dtim: %d\r\n", __func__, enable, dtim);
	
    
    // char cmd[80] = {0};
    
    // if (enable) {
    //     // 启用低功耗模式并设置DTIM
    //     snprintf(cmd, sizeof(cmd), "iw dev wlan0 set power_save on; iw dev wlan0 set dtim_period %d", dtim);
    // } else {
    //     // 禁用低功耗模式
    //     snprintf(cmd, sizeof(cmd), "iw dev wlan0 set power_save off");
    // }
    
    // memset(g_tmp, 0, sizeof(g_tmp));
    // if (__exec_cmd(cmd, g_tmp, sizeof(g_tmp)) != 0) {
    //     printf("Failed to set low power mode\n");
    //     return OPRT_COM_ERROR;
    // }
    
    return OPRT_OK;
}


/**
 * @brief 快速连接WiFi
 * @param[in] fast_ap_info 快速连接信息
 * @return OPRT_OK 成功, 其他值 失败
 */
OPERATE_RET tkl_wifi_station_fast_connect(CONST FAST_WF_CONNECTED_AP_INFO_T *fast_ap_info)
{
    printf("%s\r\n", __func__);
	
	return OPRT_COM_ERROR;
    
    if (fast_ap_info == NULL || fast_ap_info->len <= 0) {
        return OPRT_INVALID_PARM;
    }
    
    // 假设fast_ap_info包含SSID和密码信息
    // 实际实现需要根据数据格式解析
    static char ssid[64] = {0};
    static char passwd[64] = {0};
    
    // 这里简化处理，实际应用中需要根据具体数据格式解析
    // 假设前32字节是SSID，后32字节是密码
    if (fast_ap_info->len >= 64) {
        memcpy(ssid, fast_ap_info->data, 32);
        memcpy(passwd, fast_ap_info->data + 32, 32);
    } else {
        memcpy(ssid, fast_ap_info->data, fast_ap_info->len);
        passwd[0] = '\0';
    }

    printf("%s, ssid=%s,passwd=%s\r\n", __func__, ssid, passwd);

    // 调用普通连接函数
    return tkl_wifi_station_connect(ssid, passwd);
}


/**
 * @brief 使用SSID和密码连接WiFi
 * 
 * @param[in] ssid WiFi名称
 * @param[in] passwd WiFi密码
 * @return OPRT_OK 成功, 其他值 失败
 */
OPERATE_RET tkl_wifi_station_connect(CONST SCHAR_T *ssid, CONST SCHAR_T *passwd)
{
    printf("%s, SSID:%s, Password:%s\r\n", __func__, ssid, passwd);
	
	//return OPRT_OK;

    #if 1
    
    if (ssid == NULL) {
        printf("get bind info from ethernet network\n");
        return OPRT_INVALID_PARM;
    }
    
    // 生成wpa_supplicant配置
    static char cmd[512] = {0};
    
    // 先断开当前连接
    tkl_wifi_station_disconnect();
    sleep(1);
    
    // 生成连接命令
    if (passwd && strlen(passwd) > 0) {
        snprintf(cmd, sizeof(cmd), 
                 "wpa_cli -i wlan0 add_network; "
                 "wpa_cli -i wlan0 set_network 0 ssid '\"%s\"'; "
                 "wpa_cli -i wlan0 set_network 0 psk '\"%s\"'; "
                 "wpa_cli -i wlan0 enable_network 0; "
                 "wpa_cli -i wlan0 save_config",
                 ssid, passwd);
    } else {
        // 无密码网络
        snprintf(cmd, sizeof(cmd), 
                 "wpa_cli -i wlan0 add_network; "
                 "wpa_cli -i wlan0 set_network 0 ssid '\"%s\"'; "
                 "wpa_cli -i wlan0 set_network 0 key_mgmt NONE; "
                 "wpa_cli -i wlan0 enable_network 0; "
                 "wpa_cli -i wlan0 save_config",
                 ssid);
    }
    
    // 执行连接命令
    memset(g_tmp, 0, sizeof(g_tmp));
    if (__exec_cmd(cmd, g_tmp, sizeof(g_tmp)) != 0) {
        printf("Failed to connect to WiFi\n");
        notify_wifi_event(WFE_CONNECT_FAILED);
        return OPRT_COM_ERROR;
    }
    
    // 等待连接完成，最多等待15秒
    int timeout = 15;
    WF_STATION_STAT_E status;
    
    while (timeout-- > 0) {
        status = get_wifi_status();
        printf("WiFi connecting... status: %d\n", status);
        
        if (status == WSS_GOT_IP) {
            notify_wifi_event(WFE_CONNECTED);
            return OPRT_OK;
        } else if (status == WSS_PASSWD_WRONG || status == WSS_NO_AP_FOUND || status == WSS_DHCP_FAIL) {
            notify_wifi_event(WFE_CONNECT_FAILED);
            return OPRT_COM_ERROR;
        }
        
        sleep(1);
    }
    
    // 超时未成功连接
    notify_wifi_event(WFE_CONNECT_FAILED);
    return OPRT_COM_ERROR;
    #endif
}


/**
 * @brief 断开与当前AP的连接
 * 
 * @return OPRT_OK 成功, 其他值 失败
 */
OPERATE_RET tkl_wifi_station_disconnect(VOID_T)
{
    printf("%s, STA Disconn AP\r\n", __func__);
	
	
    
    // 断开所有网络连接
    // if (__exec_cmd("wpa_cli -i wlan0 disable_network all", g_tmp, sizeof(g_tmp)) != 0) {
    //     printf("Failed to disable networks\n");
    //     return OPRT_COM_ERROR;
    // }
    
    // // 移除所有网络配置
    // __exec_cmd("wpa_cli -i wlan0 remove_network all", g_tmp, sizeof(g_tmp));
    
    // // 保存配置
    // __exec_cmd("wpa_cli -i wlan0 save_config", g_tmp, sizeof(g_tmp));
    
    // notify_wifi_event(WFE_DISCONNECTED);
    return OPRT_OK;
}

/**
 * @brief get wifi connect rssi
 * 
 * @param[out]      rssi        the return rssi
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_station_get_conn_ap_rssi(SCHAR_T *rssi)
{
    printf("%s\r\n", __func__);
    if(NULL == rssi){
        return OPRT_INVALID_PARM;
    }
    *rssi = 0;

    FILE *pp = popen("iwconfig "WLAN_DEV, "r");
    if(pp == NULL){
       return OPRT_COM_ERROR;
    }

    memset(g_tmp, 0, sizeof(g_tmp));
    while (fgets(g_tmp, sizeof(g_tmp), pp) != NULL){
        /* find signal  */
        char *pSIGNALStart = strstr(g_tmp, "Quality=");
        if(pSIGNALStart != NULL)
        {
            int x = 0;
            int y = 0;
            sscanf(pSIGNALStart + strlen("Quality="), "%d/%d",&x,&y);
            *rssi = x * 100/ (y+1);
            break;
        }
    }
    pclose(pp);
    printf("Get Conn AP RSSI:%d\r\n", *rssi);

    return OPRT_OK;
}

/**
 * @brief get wifi station work status
 * 
 * @param[out]      stat        the wifi station work status
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
/**
 * @brief get wifi station work status
 * 
 * @param[out]      stat        the wifi station work status
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_station_get_status(WF_STATION_STAT_E *stat)
{
    static WF_STATION_STAT_E last_stat = WSS_IDLE;


    printf("%s, last_stat=%d\r\n", __func__, last_stat);

    if(NULL == stat){
        return OPRT_INVALID_PARM;
    }

    if(last_stat == WSS_GOT_IP)
    {
        *stat = WSS_GOT_IP;
        printf("last_stat WSS_GOT_IP\r\n");
        return OPRT_OK;
    }

    // char wpa_state[32] = {0};
    // // 解析wpa_supplicant状态获取详细信息
    // if (__get_wpa_state(wpa_state, sizeof(wpa_state)) == 0) {
    //     // 判断连接中状态
    //     if (strcmp(wpa_state, "ASSOCIATING") == 0 || 
    //         strcmp(wpa_state, "ASSOCIATED") == 0 ||
    //         strcmp(wpa_state, "AUTHENTICATING") == 0) {
    //         *stat = WSS_CONNECTING;
    //         return OPRT_OK;
    //     }
    // }

    // 检查是否连接到WiFi
    int connected = __is_wifi_connected();
    if (!connected) {
        *stat = WSS_IDLE;
        return OPRT_OK;
    }

    // 检查是否获取到IP
    int has_ip = __has_ip_address();
    if (has_ip) {
        last_stat = *stat = WSS_GOT_IP;//WSS_CONN_SUCCESS;//WSS_GOT_IP;
        printf("WSS_GOT_IP\r\n");
        //sleep(1);
    } else {
        // 已连接但未获取IP，可能是DHCP失败
        *stat = WSS_DHCP_FAIL;
        printf("WSS_DHCP_FAIL\r\n");
    }

    // 注意：更详细的状态（如连接中、密码错误等）需要解析wpa_supplicant状态
    // 这里为简化实现，只处理了基本状态
    
    return OPRT_OK;
}

/**
 * @brief send wifi management
 * 
 * @param[in]       g_tmp         pointer to g_tmper
 * @param[in]       len         length of g_tmper
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_send_mgnt(CONST UCHAR_T *g_tmp, CONST UINT_T len)
{
    printf("%s\r\n", __func__);
    return OPRT_OK;
}

/**
 * @brief register receive wifi management callback
 * 
 * @param[in]       enable
 * @param[in]       recv_cb     receive callback
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tkl_wifi_register_recv_mgnt_callback(CONST BOOL_T enable, CONST WIFI_REV_MGNT_CB recv_cb)
{
    printf("%s\r\n", __func__);
    return OPRT_OK;
}

#if 1

// #include "tuya_hal_wifi.h"
// #include "tuya_error_code.h"

// 定义WiFi接口名称（根据实际情况修改，如wlan0）
// #define WLAN_DEV "wlan0"

// 定义命令相关的参数结构体（需与调用方约定）
/** WFI_CONNECT_CMD参数：连接WiFi所需信息 */
typedef struct {
    const char *ssid;       // WiFi名称
    const char *passphrase; // WiFi密码（可为NULL，用于开放网络）
    const char *bssid;      // BSSID（可选，指定AP）
} WF_CONNECT_ARGS_T;

/** WFI_GET_LAST_DISCONN_REASON输出参数：断开原因 */
typedef struct {
    INT_T reason_code;      // 断开原因码（映射涂鸦定义）
    char reason_str[64];   // 断开原因描述
} WF_DISCONN_REASON_T;

/** WFI_AP_GET_STALIST_CMD输出参数：客户端列表 */
typedef struct {
    UINT_T max_num;         // 最大支持的客户端数量
    UINT_T actual_num;      // 实际客户端数量
    char *mac_list;         // MAC地址列表（每个MAC占18字节，格式"xx:xx:xx:xx:xx:xx"）
} WF_STA_LIST_T;


/**
 * @brief 处理WFI_CONNECT_CMD：连接指定WiFi
 */
static OPERATE_RET __handle_connect(WF_CONNECT_ARGS_T *args) {

    printf("%s\r\n", __func__);

    if (args == NULL || args->ssid == NULL) {
        return OPRT_INVALID_PARM;
    }

    // // 构建wpa_cli命令（通过wpa_supplicant连接WiFi）
    // // 1. 移除当前网络（若存在）
    // snprintf(g_tmp, sizeof(g_tmp), "wpa_cli -i %s remove_network all", WLAN_DEV);
    // __exec_cmd(g_tmp, NULL, 0);

    // // 2. 添加新网络
    // char g_tmp[64] = {0};
    // snprintf(g_tmp, sizeof(g_tmp), "wpa_cli -i %s add_network", WLAN_DEV);
    // if (__exec_cmd(g_tmp, g_tmp, sizeof(g_tmp)) != 0) {
    //     return OPRT_COM_ERROR;
    // }
    // int net_id = atoi(g_tmp);
    // if (net_id < 0) {
    //     return OPRT_COM_ERROR;
    // }

    // // 3. 设置SSID
    // snprintf(g_tmp, sizeof(g_tmp), "wpa_cli -i %s set_network %d ssid \"%s\"", 
    //          WLAN_DEV, net_id, args->ssid);
    // if (__exec_cmd(g_tmp, g_tmp, sizeof(g_tmp)) != 0 || strstr(g_tmp, "OK") == NULL) {
    //     return OPRT_COM_ERROR;
    // }

    // // 4. 设置密码（若有）
    // if (args->passphrase != NULL && strlen(args->passphrase) > 0) {
    //     snprintf(g_tmp, sizeof(g_tmp), "wpa_cli -i %s set_network %d psk \"%s\"", 
    //              WLAN_DEV, net_id, args->passphrase);
    //     if (__exec_cmd(g_tmp, g_tmp, sizeof(g_tmp)) != 0 || strstr(g_tmp, "OK") == NULL) {
    //         return OPRT_COM_ERROR;
    //     }
    // } else {
    //     // 开放网络（无密码）
    //     snprintf(g_tmp, sizeof(g_tmp), "wpa_cli -i %s set_network %d key_mgmt NONE", 
    //              WLAN_DEV, net_id);
    //     __exec_cmd(g_tmp, g_tmp, sizeof(g_tmp));
    // }

    // // 5. 选择并连接网络
    // snprintf(g_tmp, sizeof(g_tmp), "wpa_cli -i %s select_network %d", WLAN_DEV, net_id);
    // if (__exec_cmd(g_tmp, g_tmp, sizeof(g_tmp)) != 0 || strstr(g_tmp, "OK") == NULL) {
    //     return OPRT_COM_ERROR;
    // }

    return OPRT_OK;
}

/**
 * @brief 处理WFI_GET_LAST_DISCONN_REASON：获取最后断开原因
 */
static OPERATE_RET __handle_get_disconn_reason(WF_DISCONN_REASON_T *reason) {

    printf("%s\r\n", __func__);

    if (reason == NULL) {
        return OPRT_INVALID_PARM;
    }

    // 通过wpa_cli获取最后断开信息（格式："<timestamp> <reason_code> <reason_str>"）
    // char cmd[64] = {0};
    // memset(g_tmp, 0, sizeof(g_tmp));
    // snprintf(cmd, sizeof(cmd), "wpa_cli -i %s last_disconnect", WLAN_DEV);
    // if (__exec_cmd(cmd, g_tmp, sizeof(g_tmp)) != 0) {
    //     return OPRT_COM_ERROR;
    // }
    // printf("%s  111\r\n", __func__);
    // // 解析原因（示例："1620000000 15 4-Way Handshake failed"）
    // int reason_code;
    // //char reason_str[128] = {0};
    // memset(cmd, 0,sizeof(cmd));
    // if (sscanf(g_tmp, "%*d %d %127s", &reason_code, cmd) < 2) {
    //     // 未获取到有效信息（可能从未断开过）
    //     reason->reason_code = 0;
    //     strcpy(reason->reason_str, "No disconnect record");
    //     return OPRT_OK;
    // }
    // printf("%s  222\r\n", __func__);
    // // 映射到涂鸦定义的原因码（示例映射，需根据实际需求调整）
    // reason->reason_code = reason_code;
    // strncpy(reason->reason_str, cmd, sizeof(reason->reason_str)-1);
    return OPRT_OK;
}

/**
 * @brief 处理WFI_AP_GET_STALIST_CMD：获取AP客户端列表
 */
static OPERATE_RET __handle_get_stalist(WF_STA_LIST_T *sta_list) {

    printf("%s\r\n", __func__);

    // if (sta_list == NULL || sta_list->max_num == 0 || sta_list->mac_list == NULL) {
    //     return OPRT_INVALID_PARM;
    // }

    // // 通过iw命令获取客户端列表（AP模式下）
    // char g_tmp[128] = {0};
    // char g_tmp[1024] = {0};
    // snprintf(g_tmp, sizeof(g_tmp), "iw dev %s station dump | grep 'Station ' | awk '{print $2}'", WLAN_DEV);
    // if (__exec_cmd(g_tmp, g_tmp, sizeof(g_tmp)) != 0) {
    //     return OPRT_COM_ERROR;
    // }

    // // 解析MAC地址（每行一个MAC）
    // sta_list->actual_num = 0;
    // char *mac = strtok(g_tmp, "\n");
    // while (mac != NULL && sta_list->actual_num < sta_list->max_num) {
    //     // 复制MAC到列表（格式"xx:xx:xx:xx:xx:xx"）
    //     strncpy(sta_list->mac_list + sta_list->actual_num * 18, mac, 17);
    //     sta_list->actual_num++;
    //     mac = strtok(NULL, "\n");
    // }

    return OPRT_OK;
}

/**
 * @brief 处理WFI_BEACON_CMD：暂不实现（示例）
 */
static OPERATE_RET __handle_beacon(VOID *args) {

    printf("%s\r\n", __func__);

    // 实际应用中需根据需求实现（如设置Beacon间隔、获取Beacon信息等）
    // 可通过iw命令或ioctl操作无线网卡的Beacon相关配置
    return OPRT_NOT_SUPPORTED;
}

/**
 * @brief wifi ioctl 实现入口
 */
OPERATE_RET tkl_wifi_ioctl(WF_IOCTL_CMD_E cmd, VOID *args) {
    printf("%s: cmd=%d\n", __func__, cmd);

    return OPRT_NOT_SUPPORTED;

    // switch (g_tmp) {
    //     case WFI_BEACON_CMD:
    //         return __handle_beacon(args);
    //     case WFI_GET_LAST_DISCONN_REASON:
    //         return __handle_get_disconn_reason((WF_DISCONN_REASON_T *)args);
    //     case WFI_AP_GET_STALIST_CMD:
    //         return __handle_get_stalist((WF_STA_LIST_T *)args);
    //     case WFI_CONNECT_CMD:
    //         return __handle_connect((WF_CONNECT_ARGS_T *)args);
    //     default:
    //         printf("unsupported g_tmp: %d\n", g_tmp);
    //         return OPRT_NOT_SUPPORTED;
    // }
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>

/**
 * 通过域名获取IP地址
 * @param hostname 要解析的域名（如"www.example.com"）
 * @param port 端口号（可以为NULL）
 * @return 0表示成功，非0表示失败
 */
int get_ip_address(const char *hostname, const char *port) 
{
    struct addrinfo hints, *result, *p;
    int status;
    char ipstr[INET6_ADDRSTRLEN];

    printf("%s \n", __func__);

    // 初始化hints结构体
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;   // 支持IPv4和IPv6
    hints.ai_socktype = SOCK_STREAM; // 使用TCP

    printf("IP addresses for 00 %s:\n\n", hostname);

    // 调用getaddrinfo解析域名
    if ((status = getaddrinfo(hostname, port, &hints, &result)) != 0) {
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
        return 1;
    }

    printf("IP addresses for 11 %s:\n\n", hostname);

    // 遍历所有返回的地址结构
    for(p = result; p != NULL; p = p->ai_next) {
        void *addr;
        char *ipver;

        // 判断是IPv4还是IPv6
        if (p->ai_family == AF_INET) { // IPv4
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
            ipver = "IPv4";
        } else { // IPv6
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
            ipver = "IPv6";
        }

        // 将二进制IP转换为字符串
        inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
        printf("  %s: %s\n", ipver, ipstr);
    }

    // 释放内存
    freeaddrinfo(result);
    return 0;
}
#endif