#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/syslog.h>
#include <sys/time.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <pthread.h>
#include "adapter/pe_adapter.h"
#include "define.h"
#include "log_module.h"
#include "pub_fun.h"
#include "lnxall_hal.h"
#include <mntent.h>
#include <sys/statvfs.h>
#include <sys/sysmacros.h>
#include "hardware_monitor.h"
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <inttypes.h>

const char* monitor_network[] = {"eth0", "eth1", "usb0"};

static int init_harddisk_monitor(hardware_monitor_t* hwmon);
static int init_cpu_monitor(hardware_monitor_t* hwmon);
static int init_network_monitor_task(hardware_monitor_t* hwmon);
static int update_ems_disk_status_task(hardware_monitor_t* hwmon);
static int update_ems_cpus_status_task(hardware_monitor_t* hwmon);
static int update_ems_memory_status_task(hardware_monitor_t* hwmon);
static int update_ems_network_monitor_task(hardware_monitor_t* hwmon);


static void* update_ems_hardware_status_task(void* arg)
{
    // 电源状态
    dev_set_dev_tag_int(DEV_NO_EMS, EMS_POWER, 0);

    lnxhal_power_detect_t powerd;
    enum lnxhal_hwtype    hwtype;
    powerd = NULL;
    hwtype = lnxhal_hw_gettype();
    if (!lnxhal_hw_has(LNXHAL_HWCAP_POWER_DETECT))
        return NULL;
    powerd = lnxhal_powerd_get(hwtype);
    if (powerd == NULL)
    {
        return NULL;
    }
    int power_down, ret;

    // 硬件监控
    hardware_monitor_t* hwmon = malloc(sizeof(hardware_monitor_t));
    if (hwmon == NULL)
    {
        return NULL;
    }
    memset(hwmon, 0, sizeof(hardware_monitor_t));

    init_harddisk_monitor(hwmon);
    init_cpu_monitor(hwmon);
    init_network_monitor_task(hwmon);
    while (1)
    {
        ret = lnxhal_powerd_poll(powerd, CHECK_INTERVAL, &power_down);
        if (ret != -1)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, EMS_POWER, power_down);
        }
        if (power_down == 1)
        {
            usleep(1000 * CHECK_INTERVAL);
        }
        // 硬盘
        update_ems_disk_status_task(hwmon);
        // CPU
        update_ems_cpus_status_task(hwmon);
        // 内存
        update_ems_memory_status_task(hwmon);
        // 网络
        update_ems_network_monitor_task(hwmon);
    }
    return NULL;
}

void print_hardware_monitor(hardware_monitor_t* hwmon)
{
    for (int i = 0; i < hwmon->harddisk_num; i++)
    {
        float total = (float)hwmon->harddisk_list[i].total / 1024.0 / 1024.0 / 1024.0;
        float used  = (float)hwmon->harddisk_list[i].used / 1024.0 / 1024.0 / 1024.0;
        ems_syslog(LOG_ERR, "disk[%d]: %s %s %lf %lf %lf", i, hwmon->harddisk_list[i].device, hwmon->harddisk_list[i].mountpoint, total, used, hwmon->harddisk_list[i].usage);
    }
    ems_syslog(LOG_ERR, "cpu: %.2lf%%", hwmon->cpu_usage.usage * 100);
    ems_syslog(LOG_ERR, "memory: %.2lf%%", hwmon->mem_info.usage * 100);
    for (int i = 0; i < hwmon->net_num; i++)
    {
        ems_syslog(LOG_ERR, "net[%d]: %s %ld", i, hwmon->net_infos[i].ifname, hwmon->net_infos[i].lost_time);
    }
}

void init_update_ems_hardware_status_task(void)
{
    pthread_t tid = {0};
    if (pthread_create(&tid, NULL, update_ems_hardware_status_task, NULL) != 0)
    {
        ems_syslog(LOG_ERR, "Failed to create hardware_monitor thread!");
    }
    else
    {
        pthread_setname_np(tid, "hardware_monitor");
    }
}

void destory_hardware_monitor(hardware_monitor_t* hwmon)
{
    if (hwmon == NULL) return;
    if (hwmon->harddisk_list)
    {
        for (int i = 0; i < hwmon->harddisk_num; i++)
        {
            free(hwmon->harddisk_list[i].device);
            free(hwmon->harddisk_list[i].mountpoint);
            free(hwmon->harddisk_list[i].vfs);
        }

        free(hwmon->harddisk_list);
    }
    if (hwmon->net_infos)
    {
        free(hwmon->net_infos);
    }
    free(hwmon);
}

// 监控硬盘使用情况
static int init_harddisk_monitor(hardware_monitor_t* hwmon)
{
    const char* excluded_types[] = {"tmpfs", "proc", "sysfs", "devtmpfs", "devpts", "cgroup", "cgroup2", "overlay", "squashfs", "autofs", "debugfs", "securityfs", "configfs", "mqueue", "hugetlbfs", NULL};

    FILE* fp = setmntent("/proc/mounts", "r");
    if (!fp)
    {
        ems_syslog(LOG_ERR, "无法打开/proc/mounts, %s", strerror(errno));
        return 1;
    }
    harddisk_t     dev[100] = {0};
    int            count    = 0;
    struct mntent* ent;
    while ((ent = getmntent(fp)) != NULL)
    {
        const char* device      = ent->mnt_fsname;
        const char* mount_point = ent->mnt_dir;

        // 跳过黑名单中的文件系统类型
        int skip = 0;
        for (const char** type = excluded_types; *type != NULL; type++)
        {
            if (strcmp(ent->mnt_type, *type) == 0)
            {
                skip = 1;
                break;
            }
        }
        if (skip) continue;

        // 获取文件系统统计信息
        struct statvfs* vfs = malloc(sizeof(struct statvfs));
        if (statvfs(ent->mnt_dir, vfs) == -1)
        {
            ems_syslog(LOG_ERR, "%s statvfs失败, %s", device, strerror(errno));
            continue;
        }
        if (vfs->f_blocks == 0)
        {
            free(vfs);
            continue;
        }

        dev[count].device     = strdup(device);
        dev[count].mountpoint = strdup(mount_point);
        dev[count++].vfs      = vfs;

        // 计算空间
        dev[count].total = vfs->f_blocks * vfs->f_frsize;
        dev[count].used  = dev[count].total - vfs->f_bavail * vfs->f_frsize;
        dev[count].usage = (double)dev[count].used / dev[count].total;
    }
    endmntent(fp);
    hwmon->harddisk_num  = count;
    hwmon->harddisk_list = malloc(count * sizeof(harddisk_t));
    memcpy(hwmon->harddisk_list, dev, count * sizeof(harddisk_t));
    return 0;
}

static int update_ems_disk_status_task(hardware_monitor_t* hwmon)
{
    for (int i = 0; i < hwmon->harddisk_num; i++)
    {
        harddisk_t*     disk = &hwmon->harddisk_list[i];
        struct statvfs* vfs  = disk->vfs;
        if (statvfs(disk->mountpoint, vfs) == -1)
        {
            ems_syslog(LOG_ERR, "%s statvfs失败, %s", disk->mountpoint, strerror(errno));
            continue;
        }
        disk->total = vfs->f_blocks * vfs->f_frsize;
        disk->used  = disk->total - vfs->f_bavail * vfs->f_frsize;
        disk->usage = (double)disk->used / (double)disk->total;
        ems_syslog(LOG_DEBUG, "硬盘: %s, 总大小: %"PRIu64", 已使用: %"PRIu64", 使用率: %.2f%%", disk->mountpoint, disk->total, disk->used, disk->usage * 100);
        if (disk->usage > DISK_USAGE_ALARM_THRESHOLD)
        {
            if (disk->duration == 0)
            {
                disk->duration = time(0);
            }
            else if (time(0) - disk->duration > DISK_USAGE_ALARM)
            {
                if (strcmp(disk->mountpoint, EMMC_DEVICE) == 0)
                {
                    dev_set_dev_tag_int(DEV_NO_EMS, EMMC_DISK_HIGH, 1);
                }
                else if (strcmp(disk->mountpoint, SSD_DEVICE) == 0)
                {
                    dev_set_dev_tag_int(DEV_NO_EMS, SSD_DISK_HIGH, 1);
                }
                else
                {
                    ems_syslog(LOG_WARNING, "硬盘: %s, 总大小: %"PRIu64", 已使用: %"PRIu64", 使用率: %.2f%%", disk->mountpoint, disk->total, disk->used, disk->usage * 100);
                }
            }
        }
        else if (disk->usage > DISK_USAGE_ALARM_URGENCY)
        {
            if (strcmp(disk->mountpoint, EMMC_DEVICE) == 0)
            {
                dev_set_dev_tag_int(DEV_NO_EMS, EMMC_DISK_HIGH, 1);
            }
            else if (strcmp(disk->mountpoint, SSD_DEVICE) == 0)
            {
                dev_set_dev_tag_int(DEV_NO_EMS, SSD_DISK_HIGH, 1);
            }
        }
        else
        {
            disk->duration = 0;
        }
    }
    return 0;
}

static int init_cpu_monitor(hardware_monitor_t* hardware)
{
    FILE* fp = fopen("/proc/stat", "r");
    if (!fp)
    {
        ems_syslog(LOG_ERR, "无法打开/proc/stat: %s", strerror(errno));
        return -1;
    }

    char line[512];
    int  core_count = 0;
    while (fgets(line, sizeof(line), fp) && core_count < CPU_CORES)
    {
        // 只处理以"cpu"开头的行（如cpu, cpu0, cpu1）
        if (strncmp(line, "cpu ", 3) == 0 && line[3] == ' ')
        {
            cpu_times_t* cpu = &hardware->cpu_usage.prev;
            sscanf(line, "%s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"", cpu->name, &cpu->user, &cpu->nice, &cpu->system, &cpu->idle, &cpu->iowait, &cpu->irq, &cpu->softirq);
            break;
        }
    }
    hardware->cpu_usage.usage    = 0;
    hardware->cpu_usage.duration = 0;

    fclose(fp);
    return core_count;
}

static inline float calculate_cpu_usage(const cpu_times_t* prev, const cpu_times_t* curr)
{
    const uint64_t prev_total = prev->user + prev->nice + prev->system + prev->idle + prev->iowait + prev->irq + prev->softirq;
    const uint64_t curr_total = curr->user + curr->nice + curr->system + curr->idle + curr->iowait + curr->irq + curr->softirq;
    const uint64_t prev_idle  = prev->idle + prev->iowait;
    const uint64_t curr_idle  = curr->idle + curr->iowait;
    const uint64_t total_diff = curr_total - prev_total;
    const uint64_t idle_diff  = curr_idle - prev_idle;

    if (total_diff == 0) return 0.0; // 避免除以零

    return (double)(total_diff - idle_diff) / (double)total_diff;
}

static int update_ems_cpus_status_task(hardware_monitor_t* hardware)
{
    FILE* fp = fopen("/proc/stat", "r");
    if (!fp)
    {
        ems_syslog(LOG_ERR, "无法打开/proc/stat: %s", strerror(errno));
        return -1;
    }

    char         line[512];
    int          core_count = 0;
    cpu_usage_t* cpu        = &hardware->cpu_usage;
    cpu_times_t  now        = {0};

    while (fgets(line, sizeof(line), fp))
    {
        if (strncmp(line, cpu->prev.name, strlen(cpu->prev.name)) != 0) continue;

        sscanf(line, "%s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"", now.name, &now.user, &now.nice, &now.system, &now.idle, &now.iowait, &now.irq, &now.softirq);
        cpu->usage = calculate_cpu_usage(&cpu->prev, &now);
        cpu->prev  = now;
        ems_syslog(LOG_DEBUG, "Cpu usage: %.2f%%", cpu->usage);

        if (cpu->usage > CPU_USAGE_ALARM_THRESHOLD)
        {
            if (cpu->duration == 0)
            {
                cpu->duration = time(0);
            }
            else if (time(0) - cpu->duration > CPU_USAGE_ALARM)
            {
                dev_set_dev_tag_int(DEV_NO_EMS, EMS_CPU_HIGH, 1);
            }
        }
        else
        {
            if (cpu->duration != 0)
            {
                dev_set_dev_tag_int(DEV_NO_EMS, EMS_CPU_HIGH, 0);
                cpu->duration = 0;
            }
        }
        break;
    }
    fclose(fp);
    return core_count;

    return 0;
}

// 监控内存使用情况
static double calculate_mem_usage(mem_info_t* mem_info)
{
    if (mem_info->total == 0) return 0.0;
    uint64_t used = mem_info->total - mem_info->free;
    return (double)used / mem_info->total;
}
// 读取内存信息
static int read_mem_info(mem_info_t* mem_info)
{
    FILE*    fp;
    char     line[256];
    uint64_t value;

    fp = fopen("/proc/meminfo", "r");
    if (!fp)
    {
        ems_syslog(LOG_ERR, "read /proc/meminfo failed, %s", strerror(errno));
        return -1;
    }

    while (fgets(line, sizeof(line), fp))
    {
        if (sscanf(line, "MemTotal: %"PRIu64" kB", &value) == 1)
        {
            mem_info->total = value * 1024; // 转换为字节
        }
        else if (sscanf(line, "MemAvailable: %"PRIu64" kB", &value) == 1)
        {
            mem_info->free = value * 1024; // 转换为字节
        }
    }
    mem_info->duration = 0;
    mem_info->usage    = calculate_mem_usage(mem_info);

    fclose(fp);
    return 0;
}

// 计算内存使用率


static int update_ems_memory_status_task(hardware_monitor_t* hardware)
{
    mem_info_t* mem_info = &hardware->mem_info;
    if (read_mem_info(mem_info) < 0)
    {
        return -1;
    }
    mem_info->usage = calculate_mem_usage(mem_info);
    ems_syslog(LOG_DEBUG, "Memory usage: %.2f%%", mem_info->usage);

    if (mem_info->usage > MEMORY_USAGE_ALARM_THRESHOLD)
    {
        if (mem_info->duration == 0)
        {
            mem_info->duration = time(0);
        }
        else if (time(0) - mem_info->duration > MEMORY_USAGE_ALARM)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, EMS_MEM_HIGH, 1);
        }
    }
    else
    {
        if (mem_info->duration != 0)
        {
            mem_info->duration = 0;
            dev_set_dev_tag_int(DEV_NO_EMS, EMS_MEM_HIGH, 0);
        }
    }
    return 0;
}

// 网络事件
static int init_network_monitor_task(hardware_monitor_t* hardware)
{
    hardware->sfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (hardware->sfd < 0)
    {
        ems_syslog(LOG_ERR, "create socket failed, %s", strerror(errno));
        goto ERROR;
    }

    struct sockaddr_nl addr;
    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE;

    if (bind(hardware->sfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        ems_syslog(LOG_ERR, "bind socket failed, %s", strerror(errno));
        goto ERROR;
    }

    if (fcntl(hardware->sfd, F_SETFL, O_NONBLOCK) < 0)
    {
        ems_syslog(LOG_ERR, "fcntl failed, %s", strerror(errno));
        goto ERROR;
    }

    hardware->net_num   = sizeof(monitor_network) / sizeof(monitor_network[0]);
    hardware->net_infos = (net_info_t*)malloc(sizeof(net_info_t) * hardware->net_num);
    memset(hardware->net_infos, 0, sizeof(net_info_t) * hardware->net_num);

    if (!hardware->net_infos)
    {
        ems_syslog(LOG_ERR, "malloc failed, %s", strerror(errno));
        goto ERROR;
    }

    for (int i = 0; i < hardware->net_num; i++)
    {
        strncpy(hardware->net_infos[i].ifname, monitor_network[i], IFNAMSIZ - 1);
    }

    return 0;
ERROR:
    if (hardware->sfd > 0)
    {
        close(hardware->sfd);
        hardware->sfd = -1;
    }
    if (hardware->net_infos)
        free(hardware->net_infos);
    return -1;
}
static void handle_route_event(struct nlmsghdr* nlh, hardware_monitor_t* hardware);
static void handle_link_event(struct nlmsghdr* nlh, hardware_monitor_t* hardware);

int update_ems_network_monitor_task(hardware_monitor_t* hardware)
{
    if (hardware->sfd < 0)
    {
        return 1;
    }

    char    buffer[8192];
    ssize_t len = 0;
    ;
    while ((len = recv(hardware->sfd, buffer, sizeof(buffer), 0)) > 0)
    {
        for (struct nlmsghdr* nlh = (struct nlmsghdr*)buffer; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len))
        {
            switch (nlh->nlmsg_type)
            {
                case RTM_NEWROUTE:
                case RTM_DELROUTE:
                    handle_route_event(nlh, hardware);
                    break;

                case RTM_NEWLINK:
                case RTM_DELLINK:
                    handle_link_event(nlh, hardware);
                    break;

                case NLMSG_ERROR:
                    ems_syslog(LOG_ERR, "Netlink error message");
                    break;

                case NLMSG_DONE:
                    break;
            }
        }
    }
    for (int i = 0; i < hardware->net_num && hardware->net_infos != NULL; i++)
    {
        if (hardware->net_infos[i].lost_time != 0 &&
            time(NULL) - hardware->net_infos[i].lost_time > NETWORK_DISCONNECT_ALARM_THRESHOLD)
        {
            server_add_new_log(LOG_CODE_NET_MONITOR, "EMS", LOG_MODE_TRIG, 1, hardware->net_infos[i].ifname);
            ems_syslog(LOG_WARNING, "Interface %s: Network disconnected.", hardware->net_infos[i].ifname);
            hardware->net_infos[i].lost_time = 0;
        }
    }

    return 0;
}

static void handle_link_event(struct nlmsghdr* nlh, hardware_monitor_t* hardware)
{
    struct ifinfomsg* ifi                 = NLMSG_DATA(nlh);
    char              ifname[IF_NAMESIZE] = {0};

    // 获取接口名称
    struct rtattr* attr      = IFLA_RTA(ifi);
    int            remaining = NLMSG_PAYLOAD(nlh, sizeof(*ifi));
    for (; RTA_OK(attr, remaining); attr = RTA_NEXT(attr, remaining))
    {
        if (attr->rta_type == IFLA_IFNAME)
        {
            strncpy(ifname, (char*)RTA_DATA(attr), IF_NAMESIZE - 1);
            break;
        }
    }
    net_info_t* net_info = NULL;
    for (int i = 0; i < hardware->net_num && hardware->net_infos != NULL; i++)
    {
        if (strcmp(ifname, hardware->net_infos[i].ifname) == 0)
        {
            net_info = &hardware->net_infos[i];
            break;
        }
    }
    if (net_info == NULL)
    {
        return;
    }
    if(nlh->nlmsg_type == RTM_NEWLINK)
    {
        if (ifi->ifi_flags & IFF_RUNNING)
        {
            ems_syslog(LOG_DEBUG, "Interface %s: Link detected.", ifname);
            net_info->lost_time = 0;
        }
        else
        {
            ems_syslog(LOG_DEBUG, "Interface %s: Link lost.", ifname);
            net_info->lost_time = time(NULL);
        }
    }
}

static void handle_route_event(struct nlmsghdr* nlh, hardware_monitor_t* hardware)
{
    struct rtmsg*  rt      = NLMSG_DATA(nlh);
    int            len     = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*rt));
    struct rtattr* attr    = RTM_RTA(rt);
    int            ifindex = 0;

    char log[512]              = {0};
    char ifname[IF_NAMESIZE]   = {0};
    char dst[INET6_ADDRSTRLEN] = {0};
    char gw[INET6_ADDRSTRLEN]  = {0};
    int  metric                = -1;
    for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len))
    {
        switch (attr->rta_type)
        {
            case RTA_DST:
                inet_ntop(rt->rtm_family, RTA_DATA(attr), dst, sizeof(dst));
                break;
            case RTA_GATEWAY:
                inet_ntop(rt->rtm_family, RTA_DATA(attr), gw, sizeof(gw));
                break;
            case RTA_OIF:
                ifindex = *(int*)RTA_DATA(attr);
                if_indextoname(ifindex, ifname);
                break;
            case RTA_PRIORITY:
                metric = *(int*)RTA_DATA(attr);
                break;
        }
    }

    net_info_t* net_info = NULL;
    for (int i = 0; i < hardware->net_num && hardware->net_infos != NULL; i++)
    {
        if (strcmp(ifname, hardware->net_infos[i].ifname) == 0)
        {
            net_info = &hardware->net_infos[i];
            break;
        }
    }
    if (net_info == NULL)
    {
        return;
    }

    const char* action = "Unknown";
    switch (nlh->nlmsg_type)
    {
        case RTM_NEWROUTE: action = "Added"; break;
        case RTM_DELROUTE: action = "Removed"; break;
    }
    if (dst[0] == '\0')
    {
        snprintf(dst, sizeof(dst), "default");
    }
    if (gw[0] == '\0')
    {
        snprintf(gw, sizeof(gw), "default");
    }

    snprintf(log, sizeof(log), "%s,%s,%s,%s,%d", action, dst, gw, ifname, metric);
    server_add_new_log(LOG_CODE_NET_MONITOR, "EMS", LOG_MODE_TRIG, 2, log);
    ems_syslog(LOG_ERR, "Route event: %s", log);
}

//
// static int init_module_4g_status_task(hardware_monitor_t* hardware)
// {
//     char* m4g_path = read_file_data("/tmp/4g_modem_tty");
//     if (m4g_path == NULL || strlen(m4g_path) == 0)
//     {
//         ems_syslog(LOG_ERR, "Failed to get 4G modem device path");
//         hardware->m4g_info.fd = -1;
//         return -1;
//     }
//     if (m4g_path[strlen(m4g_path) - 1] == '\n')
//     {
//         m4g_path[strlen(m4g_path) - 1] = '\0';
//     }
//     hardware->m4g_info.fd = open(m4g_path, O_RDWR | O_NOCTTY | O_NDELAY);
//     if (hardware->m4g_info.fd < 0)
//     {
//         ems_syslog(LOG_ERR, "Failed to open 4G modem device: %s, err:%s\n", m4g_path, strerror(errno));
//         return -1;
//     }
//     free(m4g_path);
//     struct termios options = {0};
//     tcgetattr(hardware->m4g_info.fd, &options);
//     cfsetispeed(&options, B115200);
//     cfsetospeed(&options, B115200);
//     options.c_cflag |= (CLOCAL | CREAD);
//     options.c_cflag &= ~PARENB;
//     options.c_cflag &= ~CSTOPB;
//     options.c_cflag &= ~CSIZE;
//     options.c_cflag |= CS8;
//     options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
//     tcsetattr(hardware->m4g_info.fd, TCSANOW, &options);
//     return 0;
// }
//
// static int write_to_module_4g(hardware_monitor_t* hardware)
// {
//     if (hardware->m4g_info.rw == 0 || time(0) - hardware->m4g_info.write_time > 2)
//     {
//         char* cmd = "AT+CPIN?\r\n";
//         int   n   = write(hardware->m4g_info.fd, cmd, strlen(cmd));
//         if (n < 0)
//         {
//             ems_syslog(LOG_ERR, "Failed to Write 4G modem device, err:%s\n", strerror(errno));
//             return -1;
//         }
//         hardware->m4g_info.write_time = time(0);
//         hardware->m4g_info.rw         = 1;
//     }
//     return 0;
// }
//
//
// static int update_module_4g_status_task(hardware_monitor_t* hardware)
// {
//     if (hardware->m4g_info.fd < 0)
//     {
//         return -1;
//     }
//     if (hardware->m4g_info.rw == 1)
//     {
//         char buffer[256];
//         memset(buffer, 0, sizeof(buffer));
//         fd_set         read_fds;
//         struct timeval timeout;
//
//         FD_ZERO(&read_fds);
//         FD_SET(hardware->m4g_info.fd, &read_fds);
//
//         timeout.tv_sec  = 0;
//         timeout.tv_usec = 500;
//
//         int select_ret = select(hardware->m4g_info.fd + 1, &read_fds, NULL, NULL, &timeout);
//         if (select_ret > 0)
//         {
//             int n = read(hardware->m4g_info.fd, buffer, sizeof(buffer) - 1);
//             if (n > 0)
//             {
//                 // 处理 4G 回复
//                 hardware->m4g_info.rw = 0;
//                 if(strstr(buffer, "CPIN: READY") != NULL)
//                 {
//                     hardware->m4g_info.status = 1;
//                     hardware->m4g_info.lost_time = 0;
//                 }
//                 else
//                 {
//                     hardware->m4g_info.status = 0;
//                     if( hardware->m4g_info.lost_time == 0)
//                     {
//                         hardware->m4g_info.lost_time = time(NULL);
//                     }
//                     else if (time(NULL) - hardware->m4g_info.lost_time >= NETWORK_DISCONNECT_ALARM)
//                     {
//                         //todo alarm
//                     }
//                 }
//             }
//         }
//     }
//
//     return 0;
// }
