#include "ws_method.h"
#include "myLog.h"
#include "cJSON.h"
#include "mySystem.h"

typedef struct
{
    std::string saddr;
    std::string desc;
    uint8_t data_type;
    uint8_t ctrl_type;
    // void *p_data;
    std::vector<void *> vec_p_data;
    std::vector<void *> vec_p_default_data;
    stru_signal_ctrl *p_ctrl;
    stru_signal_param *p_param;
}stru_ws_signal;

LOCAL std::vector<stru_ws_signal> g_ws_out_signals;
LOCAL std::vector<stru_ws_signal> g_ws_in_signals;
LOCAL std::vector<stru_ws_signal> g_ws_yk_signals;
LOCAL std::vector<stru_ws_signal> g_ws_ao_signals;
LOCAL std::vector<stru_ws_signal> g_ws_param_signals;



int signal_is_exist(const std::string& saddr, const std::vector<stru_ws_signal>& signals)
{
    for(uint32_t i = 0; i < signals.size(); i++)
    {
        if(signals[i].saddr == saddr)
        {
            return 0;
        }
    }
    return -1;
}

void add_signal(const std::string& saddr, const std::string& signal_type)
{
    std::vector<stru_ws_signal> *p_signals = nullptr;
    stru_ws_signal *p = nullptr;

    if(signal_type == "out")
    {
        p_signals = &g_ws_out_signals;

        if(0 == signal_is_exist(saddr, g_ws_out_signals))
        {
            LOG_E("add_signals: signal is already exist, saddr = %s", saddr.c_str());
            return;
        }

        p_signals->reserve(p_signals->size() + 1);
        p_signals->push_back({saddr, "", 0, 0});
        p = &p_signals->back();

        if(0 != dc_get_out_signal_info(saddr, p->desc, p->data_type, p->vec_p_data))
        {
            LOG_E("add_signals: dc_get_out_signal_info failed, saddr = %s", saddr.c_str());

            p->vec_p_data.clear();
            p->vec_p_default_data.clear();
            p_signals->pop_back();
            return;
        }
    }
    else if(signal_type == "in")
    {
        p_signals = &g_ws_in_signals;

        if(0 == signal_is_exist(saddr, g_ws_in_signals))
        {
            LOG_E("add_signals: signal is already exist, saddr = %s", saddr.c_str());
            return;
        }

        p_signals->push_back({saddr, "", 0, 0});
        p = &p_signals->back();

        if(0 != dc_get_in_signal_info(saddr, p->desc, p->data_type, p->vec_p_data))
        {
            LOG_E("add_signals: dc_get_in_signal_info failed, saddr = %s", saddr.c_str());

            p->vec_p_data.clear();
            p->vec_p_default_data.clear();
            p_signals->pop_back();
            return;
        }
        
    }
    else if(signal_type == "yk")
    {
        p_signals = &g_ws_yk_signals;

        if(0 == signal_is_exist(saddr, g_ws_yk_signals))
        {
            LOG_E("add_signals: signal is already exist, saddr = %s", saddr.c_str());
            return;
        }   

        p_signals->push_back({saddr, "", 0, 0});
        p_signals->back().p_ctrl = new stru_signal_ctrl;
        p = &p_signals->back();

        if(0 != dc_get_yk_signal_info(saddr, p->desc, p->data_type, p->ctrl_type, p->vec_p_data))
        {
            LOG_E("add_signals: dc_get_yk_signal_info failed, saddr = %s", saddr.c_str());

            delete p->p_ctrl;
            p->vec_p_data.clear();
            p->vec_p_default_data.clear();
            p_signals->pop_back();
            return;
        }

        p->p_ctrl->type = p->ctrl_type;
        p->p_ctrl->step = SIGNAL_CTRL_STEP::READY;
        p->p_ctrl->data_type = p->data_type;
        p->p_ctrl->p_data = dc_create_data_ptr_by_type(p->data_type);
        if(nullptr == p->p_ctrl->p_data)
        {
            LOG_E("add_signals: dc_create_data_ptr_by_type failed, saddr = %s, data_type = %d", saddr.c_str(), p->data_type);

            delete p->p_ctrl;
            p->vec_p_data.clear();
            p->vec_p_default_data.clear();
            p_signals->pop_back();
            return;
        }
    }
    else if(signal_type == "ao")
    {
        p_signals = &g_ws_ao_signals;

        if(0 == signal_is_exist(saddr, g_ws_ao_signals))
        {
            LOG_E("add_signals: signal is already exist, saddr = %s", saddr.c_str());
            return;
        }

        p_signals->push_back({saddr, "", 0, 0});
        p_signals->back().p_ctrl = new stru_signal_ctrl;
        p_signals->back().p_param = new stru_signal_param;
        p = &p_signals->back();

        if(0 != dc_get_ao_siganl_info(saddr, p->desc, p->data_type, *p->p_param, p->ctrl_type, p->vec_p_data, p->vec_p_default_data))
        {
            LOG_E("add_signals: dc_get_ao_siganl_info failed, saddr = %s", saddr.c_str());

            delete p->p_ctrl;
            delete p->p_param;
            p->vec_p_data.clear();
            p->vec_p_default_data.clear();
            p_signals->pop_back();
            return;
        }
        
        p->p_ctrl->type = p->ctrl_type;
        p->p_ctrl->step = SIGNAL_CTRL_STEP::READY;
        p->p_ctrl->data_type = p->data_type;
        p->p_ctrl->p_data = dc_create_data_ptr_by_type(p->data_type);
        if(nullptr == p->p_ctrl->p_data)
        {
            LOG_E("add_signals: dc_create_data_ptr_by_type failed, saddr = %s, data_type = %d", saddr.c_str(), p->data_type);

            delete p->p_ctrl;
            delete p->p_param;
            p->vec_p_data.clear();
            p->vec_p_default_data.clear();
            p_signals->pop_back();
            return;
        }
    }
    else if(signal_type == "param")
    {
        p_signals = &g_ws_param_signals;

        if(0 == signal_is_exist(saddr, g_ws_param_signals))
        {
            LOG_E("add_signals: signal is already exist, saddr = %s", saddr.c_str());
            return;
        }
        p_signals->push_back({saddr, "", 0, 0});
        p_signals->back().p_ctrl = new stru_signal_ctrl;
        p_signals->back().p_param = new stru_signal_param;
        p = &p_signals->back();
        
        if(0 != dc_get_param_signal_info(saddr, p->desc, p->data_type, *p->p_param, p->ctrl_type, p->vec_p_data, p->vec_p_default_data))
        {
            LOG_E("add_signals: dc_get_param_signal_info failed, saddr = %s", saddr.c_str());

            delete p->p_ctrl;
            delete p->p_param;
            p->vec_p_data.clear();
            p->vec_p_default_data.clear();
            p_signals->pop_back();
            return;
        }

        p->p_ctrl->type = p->ctrl_type;
        p->p_ctrl->step = SIGNAL_CTRL_STEP::READY;
        p->p_ctrl->data_type = p->data_type;
        p->p_ctrl->p_data = dc_create_data_ptr_by_type(p->data_type);
        if(nullptr == p->p_ctrl->p_data)
        {
            LOG_E("add_signals: dc_create_data_ptr_by_type failed, saddr = %s, data_type = %d", saddr.c_str(), p->data_type);

            delete p->p_ctrl;
            delete p->p_param;
            p->vec_p_data.clear();
            p->vec_p_default_data.clear();
            p_signals->pop_back();
            return;
        }
    }
    else
    {
        LOG_E("add_signals: invalid signal_type = %s", signal_type.c_str());
        return;
    }
}

void del_signal(const std::string& saddr, const std::string& signal_type)
{
    std::vector<stru_ws_signal> *p_signals = nullptr;

    if(signal_type == "out")
    {
        p_signals = &g_ws_out_signals;
    }
    else if(signal_type == "in")
    {
        p_signals = &g_ws_in_signals;
    }
    else if(signal_type == "yk")
    {
        p_signals = &g_ws_yk_signals;
    }
    else if(signal_type == "ao")
    {
        p_signals = &g_ws_ao_signals;
    }
    else if(signal_type == "param")
    {
        p_signals = &g_ws_param_signals;
    }
    else
    {
        LOG_E("del_signal: invalid signal_type = %s", signal_type.c_str());
        return;
    }

    for(uint32_t i = 0; i < p_signals->size(); i++)
    {
        stru_ws_signal *p_signal = &p_signals->at(i);
        if(p_signal->saddr == saddr)
        {
            if(p_signal->p_ctrl)
            {
                delete p_signal->p_ctrl;
            }
            if(p_signal->p_param)
            {
                delete p_signal->p_param;
            }

            p_signal->vec_p_data.clear();
            p_signal->vec_p_default_data.clear();
            
            p_signals->erase(p_signals->begin() + i);
            return;
        }
    }

    LOG_E("del_signal: not found saddr = %s", saddr.c_str());
}

void set_signal_data(const std::string& saddr, const std::string& signal_type, const uint8_t setting_zone, const std::string& signal_data)
{
    std::vector<stru_ws_signal> *p_signals = nullptr;
    
    if(signal_data.empty())
    {
        LOG_E("set_signal_data: signal_data is empty, saddr = %s", saddr.c_str());
        return;
    }

    if(signal_type == "out")
    {
        p_signals = &g_ws_out_signals;
        for(uint32_t i = 0; i < p_signals->size(); i++)
        {
            stru_ws_signal *p_signal = &p_signals->at(i);
            if(p_signal->saddr == saddr)
            {
                if(0 != dc_set_out_signal_val(saddr, (void *)signal_data.c_str()))
                {
                    LOG_E("set_signal_data: dc_set_signal_val failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                    return;
                }
            }
        }
    }
    else if(signal_type == "in")
    {
        LOG_E("signal_type is in, not support set_signal_data, saddr = %s");
        return;
    }
    else if(signal_type == "yk")
    {
        p_signals = &g_ws_yk_signals;

        uint8_t ctrl_status = atoi(signal_data.c_str());

        for(uint32_t i = 0; i < p_signals->size(); i++)
        {
            stru_ws_signal *p_signal = &p_signals->at(i);
            if(p_signal->saddr == saddr)
            {
                if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::DIRECT_NORMAL)
                {
                    if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)&ctrl_status))
                    {
                        LOG_E("set_signal_data: dc_signal_yk_set_status direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    LOG_I("saddr %s, direct, value %d success !!!", saddr.c_str(), ctrl_status);
                    return;
                }
                else if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::SBO_NORMAL)
                {
                    if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, (void *)&ctrl_status))
                    {
                        LOG_E("set_signal_data: dc_signal_yk_set_status select failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    task_sleep_ms(1000);
                    MY_LOG_I("saddr %s, select value %d success !!!", saddr.c_str(), ctrl_status);

                    if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)&ctrl_status))
                    {
                        LOG_E("set_signal_data: dc_signal_yk_set_status direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    MY_LOG_I("saddr %s, direct value %d success", saddr.c_str(), ctrl_status);
                    return;
                }
                else
                {
                    LOG_E("p_signal->ctrl_type is invalid, p_signal->ctrl_type = %d");
                    return;
                }
            }
        }
    }
    else if(signal_type == "ao")
    {
        p_signals = &g_ws_ao_signals;

        for(uint32_t i = 0; i < p_signals->size(); i++)
        {
            stru_ws_signal *p_signal = &p_signals->at(i);
            if(p_signal->saddr == saddr)
            {
                if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::DIRECT_NORMAL)
                {
                    if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)signal_data.c_str()))
                    {
                        LOG_E("set_signal_data: dc_signal_ao_set_val direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    LOG_I("saddr %s, direct, value %s success !!!", saddr.c_str(), signal_data.c_str());
                    return;
                }
                else if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::SBO_NORMAL)
                {
                    if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, (void *)signal_data.c_str()))
                    {
                        LOG_E("set_signal_data: dc_signal_ao_set_val select failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    LOG_I("saddr %s, select, value %s success !!!", saddr.c_str(), signal_data.c_str());
                    
                    if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)signal_data.c_str()))
                    {
                        LOG_E("set_signal_data: dc_signal_ao_set_val direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    LOG_I("saddr %s, direct, value %s success !!!", saddr.c_str(), signal_data.c_str());
                    return;
                }
                else
                {
                    LOG_E("p_signal->ctrl_type is invalid, p_signal->ctrl_type = %d");
                    return;
                }
            }
        }
    }
    else if(signal_type == "param")
    {
        p_signals = &g_ws_param_signals;

        for(uint32_t i = 0; i < p_signals->size(); i++)
        {
            stru_ws_signal *p_signal = &p_signals->at(i);
            if(p_signal->saddr == saddr)
            {
                if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::DIRECT_NORMAL)
                {
                    if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, setting_zone, (void *)signal_data.c_str()))
                    {
                        LOG_E("set_signal_data: dc_signal_param_set_val direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    LOG_I("saddr %s, direct, value %s success !!!", saddr.c_str(), signal_data.c_str());
                    return;
                }
                else if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::SBO_NORMAL)
                {
                    if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, setting_zone, (void *)signal_data.c_str()))
                    {
                        LOG_E("set_signal_data: dc_signal_param_set_val select failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    LOG_I("saddr %s, select, value %s success !!!", saddr.c_str(), signal_data.c_str());

                    if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, setting_zone, (void *)signal_data.c_str()))
                    {
                        LOG_E("set_signal_data: dc_signal_param_set_val direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str());
                        return;
                    }

                    LOG_I("saddr %s, direct, value %s success", saddr.c_str(), signal_data.c_str());
                    return;
                }
                else
                {
                    LOG_E("p_signal->ctrl_type is invalid, p_signal->ctrl_type = %d");
                    return;
                }
            }
        }
    }
    else
    {
        LOG_E("set_signal_data: invalid signal_type = %s", signal_type.c_str());
        return;
    }


    LOG_E("set_signal_data: not found saddr = %s", saddr.c_str());
}


void ws_recv(const char* p_rx, uint16_t rx_len)
{
    if(nullptr == p_rx || 0 == rx_len)
    {
        LOG_E("ws_recv: invalid parameter, p_rx = %p, rx_len = %d", p_rx, rx_len);
        return;
    }

    cJSON* root = cJSON_Parse(p_rx);
    if(nullptr == root)
    {
        LOG_E("ws_recv: cJSON_Parse failed, p_rx = %s", p_rx);
        return;
    }
    
    if(!cJSON_IsObject(root))
    {
        LOG_E("ws_recv: root is not an object, p_rx = %s", p_rx);
        cJSON_Delete(root);
        return;
    }
    
    cJSON *saddr = cJSON_GetObjectItem(root, "saddr");
    cJSON *signal_type = cJSON_GetObjectItem(root, "signal_type");
    cJSON *signal_data = cJSON_GetObjectItem(root, "signal_data");
    cJSON *setting_zone = cJSON_GetObjectItem(root, "setting_zone");
    cJSON *curd = cJSON_GetObjectItem(root, "curd");


    std::string saddr_str = "", signal_type_str = "", signal_data_str = "", setting_zone_str = "", curd_str = "";

    if(saddr && cJSON_IsString(saddr) && saddr->valuestring)
    {
        saddr_str = saddr->valuestring;
    }

    if(signal_type && cJSON_IsString(signal_type) && signal_type->valuestring)
    {
        signal_type_str = signal_type->valuestring;
    }

    if(signal_data && cJSON_IsString(signal_data) && signal_data->valuestring)
    {
        signal_data_str = signal_data->valuestring;
    }

    if(setting_zone && cJSON_IsString(setting_zone) && setting_zone->valuestring)
    {
        setting_zone_str = setting_zone->valuestring;
    }

    if(curd && cJSON_IsString(curd) && curd->valuestring)
    {
        curd_str = curd->valuestring;
    }

    cJSON_Delete(root);
    if(saddr_str.empty())
    {
        LOG_E("ws_recv: saddr is empty, p_rx = %s", p_rx);
        return;
    }
    
    if(signal_type_str.empty())
    {
        LOG_E("ws_recv: signal_type is empty, p_rx = %s", p_rx);
        return;
    }

    if(curd_str.empty())
    {
        LOG_E("ws_recv: curd is empty, p_rx = %s", p_rx);
        return;
    }

    if(0 == curd_str.compare("add"))
    {
        add_signal(saddr_str, signal_type_str);
    }
    else if(0 == curd_str.compare("del"))
    {
        del_signal(saddr_str, signal_type_str);
    }
    else if(0 == curd_str.compare("set"))
    {
        set_signal_data(saddr_str, signal_type_str, atoi(setting_zone_str.c_str()), signal_data_str);
    }
    
}


void ws_task()
{
    if(g_ws_out_signals.empty() && g_ws_in_signals.empty() && g_ws_yk_signals.empty() && g_ws_ao_signals.empty() && g_ws_param_signals.empty())
    {
        return;
    }

    const char ctrl_type_str[][16] = {"0", "1", "2"};

    cJSON *root = cJSON_CreateObject();
    if(nullptr == root)
    {
        LOG_E("ws_task: cJSON_CreateObject failed");
        return;
    }

    cJSON *out_arr = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "out", out_arr);

    for(uint32_t i = 0; i < g_ws_out_signals.size(); i++)
    {
        stru_ws_signal *p_signal = &g_ws_out_signals.at(i);
        cJSON *item = cJSON_CreateObject();
        if(nullptr == item)
        {
            LOG_E("ws_task: cJSON_CreateObject failed");
            cJSON_Delete(root);
            return;
        }

        cJSON_AddItemToObject(item, "saddr", cJSON_CreateString(p_signal->saddr.c_str()));
        cJSON_AddItemToObject(item, "desc", cJSON_CreateString(p_signal->desc.c_str()));
        cJSON_AddItemToObject(item, "type", cJSON_CreateString(dc_get_data_type_str_by_id(p_signal->data_type).c_str()));

        std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type);
        cJSON_AddItemToObject(item, "val", cJSON_CreateString(val.c_str()));
        cJSON_AddItemToArray(out_arr, item);
    }

    cJSON *in_arr = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "in", in_arr);

    for(uint32_t i = 0; i < g_ws_in_signals.size(); i++)
    {
        stru_ws_signal *p_signal = &g_ws_in_signals.at(i);
        cJSON *item = cJSON_CreateObject();
        if(nullptr == item)
        {
            LOG_E("ws_task: cJSON_CreateObject failed");
            cJSON_Delete(root);
            return;
        }

        cJSON_AddItemToObject(item, "saddr", cJSON_CreateString(p_signal->saddr.c_str()));
        cJSON_AddItemToObject(item, "desc", cJSON_CreateString(p_signal->desc.c_str()));
        cJSON_AddItemToObject(item, "type", cJSON_CreateString(dc_get_data_type_str_by_id(p_signal->data_type).c_str()));
        std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type);
        cJSON_AddItemToObject(item, "val", cJSON_CreateString(val.c_str()));
        cJSON_AddItemToArray(in_arr, item);
    }

    cJSON *yk_arr = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "yk", yk_arr);
    for(uint32_t i = 0; i < g_ws_yk_signals.size(); i++)
    {
        stru_ws_signal *p_signal = &g_ws_yk_signals.at(i);
        cJSON *item = cJSON_CreateObject();
        if(nullptr == item)
        {
            LOG_E("ws_task: cJSON_CreateObject failed");
            cJSON_Delete(root);
            return;
        }

        cJSON_AddItemToObject(item, "saddr", cJSON_CreateString(p_signal->saddr.c_str()));
        cJSON_AddItemToObject(item, "desc", cJSON_CreateString(p_signal->desc.c_str()));
        cJSON_AddItemToObject(item, "type", cJSON_CreateString(dc_get_data_type_str_by_id(p_signal->data_type).c_str()));
        std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type);
        cJSON_AddItemToObject(item, "val", cJSON_CreateString(val.c_str()));
        cJSON_AddItemToObject(item, "ctrl_type", cJSON_CreateNumber(p_signal->ctrl_type));
        cJSON_AddItemToArray(yk_arr, item);
    }

    cJSON *ao_arr = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "ao", ao_arr);
    
    for(uint32_t i = 0; i < g_ws_ao_signals.size(); i++)
    {
        stru_ws_signal *p_signal = &g_ws_ao_signals.at(i);
        cJSON *item = cJSON_CreateObject();
        if(nullptr == item)
        {
            LOG_E("ws_task: cJSON_CreateObject failed");
            cJSON_Delete(root);
            return;
        }

        cJSON_AddItemToObject(item, "saddr", cJSON_CreateString(p_signal->saddr.c_str()));
        cJSON_AddItemToObject(item, "desc", cJSON_CreateString(p_signal->desc.c_str()));
        cJSON_AddItemToObject(item, "type", cJSON_CreateString(dc_get_data_type_str_by_id(p_signal->data_type).c_str()));
        // std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type);
        // cJSON_AddItemToObject(item, "val", cJSON_CreateString(val.c_str()));
        cJSON_AddItemToObject(item, "ctrl_type", cJSON_CreateNumber(p_signal->ctrl_type));
        if(p_signal->p_param)
        {
            cJSON_AddItemToObject(item, "min", cJSON_CreateString(std::to_string(p_signal->p_param->min).c_str()));
            cJSON_AddItemToObject(item, "max", cJSON_CreateString(std::to_string(p_signal->p_param->max).c_str()));
            cJSON_AddItemToObject(item, "step", cJSON_CreateString(std::to_string(p_signal->p_param->step).c_str()));
            cJSON_AddItemToObject(item, "unit", cJSON_CreateString(p_signal->p_param->unit.c_str()));
            // cJSON_AddItemToObject(item, "default", cJSON_CreateString(p_signal->p_param->default_value.c_str()));
        }

        std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type);
        cJSON_AddItemToObject(item, "val", cJSON_CreateString(val.c_str()));
        std::string default_val = dc_get_signal_val(p_signal->vec_p_default_data[0], p_signal->data_type);
        cJSON_AddItemToObject(item, "default_val", cJSON_CreateString(default_val.c_str()));

        cJSON_AddItemToArray(ao_arr, item);
    }


    cJSON *param_arr = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "param", param_arr);

    for(uint32_t i = 0; i < g_ws_param_signals.size(); i++)
    {
        stru_ws_signal *p_signal = &g_ws_param_signals.at(i);
        cJSON *item = cJSON_CreateObject();
        if(nullptr == item)
        {
            LOG_E("ws_task: cJSON_CreateObject failed");
            cJSON_Delete(root);
            return;
        }

        cJSON_AddItemToObject(item, "saddr", cJSON_CreateString(p_signal->saddr.c_str()));
        cJSON_AddItemToObject(item, "desc", cJSON_CreateString(p_signal->desc.c_str()));
        cJSON_AddItemToObject(item, "type", cJSON_CreateString(dc_get_data_type_str_by_id(p_signal->data_type).c_str()));
        // std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type);
        // cJSON_AddItemToObject(item, "val", cJSON_CreateString(val.c_str()));
        cJSON_AddItemToObject(item, "ctrl_type", cJSON_CreateNumber(p_signal->ctrl_type));
        if(p_signal->p_param)
        {
            cJSON_AddItemToObject(item, "min", cJSON_CreateString(std::to_string(p_signal->p_param->min).c_str()));
            cJSON_AddItemToObject(item, "max", cJSON_CreateString(std::to_string(p_signal->p_param->max).c_str()));
            cJSON_AddItemToObject(item, "step", cJSON_CreateString(std::to_string(p_signal->p_param->step).c_str()));
            cJSON_AddItemToObject(item, "unit", cJSON_CreateString(p_signal->p_param->unit.c_str()));
            // cJSON_AddItemToObject(item, "default", cJSON_CreateString(p_signal->p_param->default_value.c_str()));
        }

        for(uint32_t j = 0; j < p_signal->vec_p_data.size(); j++)
        {
           cJSON *setting_zone_item = cJSON_CreateObject();
            if(nullptr == setting_zone_item)
            {
                LOG_E("ws_task: cJSON_CreateObject failed");
                cJSON_Delete(root);
                return;
            }

            std::string setting_zone_str = std::to_string(j);
            cJSON_AddItemToObject(setting_zone_item, "setting_zone", cJSON_CreateString(setting_zone_str.c_str()));
            std::string val = dc_get_signal_val(p_signal->vec_p_data[j], p_signal->data_type);
            cJSON_AddItemToObject(setting_zone_item, "val", cJSON_CreateString(val.c_str()));
            std::string default_val = dc_get_signal_val(p_signal->vec_p_default_data[j], p_signal->data_type);
            cJSON_AddItemToObject(setting_zone_item, "default_val", cJSON_CreateString(default_val.c_str()));

            cJSON_AddItemToArray(item, setting_zone_item);
        }

        cJSON_AddItemToArray(param_arr, item);
    }

    char *p_tx = cJSON_Print(root);
    if(nullptr == p_tx)
    {
        LOG_E("ws_task: cJSON_Print failed");
        cJSON_Delete(root);
        return;
    }

    ws_send(p_tx, strlen(p_tx));

    cJSON_Delete(root);
    free(p_tx);

}