#include "mySystem.h"
#include "myLog.h"
#include "myIcp67.h"
#include "method.h"
#include "self_ptl.h"

typedef struct
{
    uint16_t rptr;
    uint16_t wptr;
    uint16_t size;
    uint16_t cnt;
    uint8_t buf[2048];
}stru_self_rx;

typedef struct
{
    uint32_t interface;
    stru_icp67 icp67;
    stru_genneral_method method;
    stru_self_rx icp67_rx;
    stru_self_rx iec_rx;
    uint8_t temp_buf[2048];
}stru_self_ptl;

stru_self_ptl g_self_ptl = 
{
    .method = 
    {
        .ao_get_cb = NULL,
        .ao_pop_out_cb = ao_pop_out,
        .ao_set_cb = NULL,
        .iec_point_tbl_get_cb = NULL,
        .iec_point_tbl_pop_out_cb = iec_point_tbl_pop_out,
        .time_set_cb = NULL,
        .self_check_get_cb = NULL,
        .self_check_pop_out_cb = self_check_pop_out,
        .upgrade_start_cb = NULL,
        
        .dir_read_cb = NULL,
        .dir_pop_out_cb = dir_pop_out,
        .file_read_act_cb = NULL,
        .file_read_act_confirm_cb = file_read_act_confirm,
        .file_read_cb = file_read,
        .file_read_confirm_cb = NULL,
        .file_write_act_cb = NULL,
        .file_write_act_confirm_cb = file_write_act_confirm,
        .file_write_cb = NULL,
        .file_write_confirm_cb = file_write_confirm,
        .file_write_end_cb = file_write_end,
        .file_write_end_confirm_cb = NULL,

        .zip_dir_pop_out_cb = zip_dir_pop_out,
        .zip_file_pop_out_cb = zip_file_pop_out,

        .mx_trans_cb = mx_trans,
        .st_trans_cb = st_trans,
        .dd_trans_cb = dd_trans,
        .soe_trans_cb = soe_trans,
        .fault_trans_cb = fault_trans,
        .mx_change_cb = mx_change,
    },
    .icp67_rx = 
    {
        .rptr = 0,
        .wptr = 0,
        .size = 2048,
        .cnt = 0,
    },
    .iec_rx = 
    {
        .rptr = 0,
        .wptr = 0,
        .size = 2048,
        .cnt = 0,
    },
};

stru_self_ptl_cfg_data g_self_ptl_cfg_data = {};


stru_genneral_method *self_ptl_method_ptr_get()
{
    return &g_self_ptl.method;
}

stru_icp67 *self_ptl_icp67_ptr_get()
{
    return &g_self_ptl.icp67;
}

stru_self_ptl_cfg_data *self_ptl_cfg_data_ptr_get()
{
    return &g_self_ptl_cfg_data;
}

LOCAL void put_rx_data(stru_self_rx *p_slef_rx, uint8_t *p_rx, uint16_t len)
{
    if(NULL == p_slef_rx || NULL == p_rx || 0 == len)
    {
        LOG_E("put_rx_data p_slef_rx NULL or p_rx NULL or len 0");
        return;
    }

    for(uint16_t i = 0; i < len; i++)
    {
        p_slef_rx->buf[p_slef_rx->wptr] = p_rx[i];
        p_slef_rx->wptr = (p_slef_rx->wptr + 1) % p_slef_rx->size;
        p_slef_rx->cnt++;

        if(p_slef_rx->cnt > p_slef_rx->size)
        {
            p_slef_rx->cnt--;
            p_slef_rx->rptr = (p_slef_rx->rptr + 1) % p_slef_rx->size;

            // LOG_E("put_rx_data cnt %d, rptr %d, wptr %d", p_slef_rx->cnt, p_slef_rx->rptr, p_slef_rx->wptr);
        }
    }
}

LOCAL void get_rx_data(stru_self_rx *p_slef_rx, uint8_t *p_data, uint16_t *p_data_len)
{
    if(NULL == p_slef_rx || NULL == p_data || NULL == p_data_len)
    {
        LOG_E("get_rx_data p_slef_rx NULL or p_data NULL or p_data_len NULL");
        return;
    }

    uint16_t pos = p_slef_rx->rptr;

    for(uint16_t i = 0; i < p_slef_rx->cnt; i++)
    {
        p_data[i] = p_slef_rx->buf[pos];
        pos = (pos + 1) % p_slef_rx->size;
    }
    
    (*p_data_len) = p_slef_rx->cnt;
}

LOCAL int self_ptl_iec104_check_ctrl(stru_iec104_apci *p)
{
    if(NULL == p)
    {
        return ERR_FRAME;
    }

    if(p->len > 4)
    {
        if((p->ctrl1 & 0x01) == 0 && (p->ctrl3 & 0x01) == 0)
        {
            return I_FRAME;
        }
    }
    else
    {   
        if((p->ctrl1 == 1) && (p->ctrl2 == 0) && (p->ctrl3 & 0x01) == 0)
        {
            return S_FRAME;
        }

        if((p->ctrl1 & 0x03) == 0x03 && (p->ctrl2 == 0) && (p->ctrl3 == 0) && (p->ctrl4 == 0))
        {
            return U_FRAME;
        }
    }
    return ERR_FRAME;
}

LOCAL int self_ptl_iec104_chech_asdu(stru_iec104_apci *p)
{
    if(NULL == p)
    {   
        return -1;
    }

    if(p->len < 4 + sizeof(stru_iec104_asdu))
    {
        return -1;
    }

    stru_iec104_asdu *p_asdu = (stru_iec104_asdu *)(p->data);

    if(p_asdu->ti == 0)
    {
        return -1;
    }

    if((p_asdu->vsq & 0x7f) == 0)
    {
        return -1;
    }

    if((p_asdu->cot & 0xFF00) != 0)
    {
        return -1;
    }

    uint8_t cot = p_asdu->cot & 0x00FF;
    if(cot == 0 || cot == 11 || cot == 12 || (cot >= 14 && cot <= 19) || (cot >= 37 && cot <= 43) || cot >= 51)
    {
        return -1;
    }

    return 0;
}

LOCAL int self_ptl_search_iec_frame(uint8_t *p_data, uint16_t len, uint16_t *p_pos, uint16_t *p_valid_len)
{
    if(NULL == p_data || 0 == len || NULL == p_pos || NULL == p_valid_len)
    {
        // LOG_E("self_ptl_search_iec_frame p_data NULL or len 0 or p_pos NULL or p_valid_len NULL");
        return -1;  
    }

    for(uint16_t i = 0; i < len; i++)
    {
        if(i + sizeof(stru_iec104_apci) > len)
        {
            break;
        }

        stru_iec104_apci *p_apci = (stru_iec104_apci *)&p_data[i];

        if(p_apci->start != IEC_START)
        {
            continue;
        }

        if(p_apci->len + 2 + i > len)
        {
            break;
        }

        int ret = self_ptl_iec104_check_ctrl(p_apci);
        if(ret == ERR_FRAME)
        {
            continue;
        }

        if(ret == I_FRAME && 0 != self_ptl_iec104_chech_asdu(p_apci))
        {
            continue;
        }

        *p_pos = i;
        *p_valid_len = p_apci->len + 2;
        return 0;
    }

    return -1;
}

LOCAL void self_ptl_search_first_head(uint8_t *p_data, uint16_t len, uint8_t head, uint16_t *p_pos)
{
    if(NULL == p_data || 0 == len || NULL == p_pos)
    {
        return;
    }

    uint16_t i = 0;

    (*p_pos) = 0;
    for(i = 0; i < len; i++)
    {
        if(p_data[i] == head)
        {
            *p_pos = i;
            return;
        }
    }

    if((*p_pos) == 0)
    {
        (*p_pos) = len;
    }
}

void self_ptl_data_tx(uint8_t *p_tx, uint16_t len, void *arg)
{
    if(NULL == p_tx || 0 == len || NULL == arg)
    {
        LOG_E("self_ptl_data_tx p_tx NULL or len 0 or arg NULL");
        return;
    }

    if(len + sizeof(stru_msg_head) > MSG_SIZE)
    {
        LOG_E("self_ptl_data_tx len %d too long", len);
        return;
    }
    
    uint32_t interface = *(uint32_t *)arg;
    stru_rtx_data *p_rtx = NULL;
    stru_app *p_app = NULL;
    stru_app_msg_queue *p_mq = NULL;

    if(NULL == (p_app = app_get_ptr(ENUM_APP_SELF_PTL)))
    {
        LOG_E("self_ptl_data_tx app_get_ptr failed");
        return;
    }

    p_rtx = &p_app->rtx;
    stru_msg_head *p_head = (stru_msg_head *)p_rtx->tx;

    p_head->interface = interface;
    p_head->len = len;
    memcpy(p_head->data, p_tx, len);

    if(NULL == (p_mq = app_get_msg_queue_ptr(ENUM_MQ_SELF_PTL_TO_COM)))
    {
        LOG_E("self_ptl_data_tx app_get_msg_queue_ptr failed");
        return;
    }

    if(0 != task_msg_queue_send(p_mq->p_msg_queue, p_rtx->tx, p_mq->msg_size))
    {
        LOG_E("self_ptl_data_tx task_msg_queue_send failed");
        return;
    }

    if(NULL == (p_app = app_get_ptr(ENUM_APP_COM_SCAN)) || 0 != task_event_send(p_app->p_event, EV_COM_RX_SELF_PTL))
    {
        LOG_E("self_ptl_data_tx task_event_send failed");
        task_msg_queue_try_recv(p_mq->p_msg_queue, p_rtx->rx, p_mq->msg_size);

        return;
    }
}

LOCAL void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp67)
{
    if(NULL == p_rx || 0 == len || NULL == p_icp67)
    {
        LOG_E("self_ptl_search_frame p_rx NULL or len 0 or p_icp67 NULL or p_data NULL or p_data_len NULL");
        return;
    }

    put_rx_data(&g_self_ptl.icp67_rx, p_rx, len);
    put_rx_data(&g_self_ptl.iec_rx, p_rx, len);

    uint16_t data_len = 0;
    uint16_t pos = 0;
    uint16_t valid_len = 0;
    int ret = -1;

    if(p_icp67->search_frame_cb)
    {
        do
        {
            pos = 0;
            valid_len = 0;
            get_rx_data(&g_self_ptl.icp67_rx, g_self_ptl.temp_buf, &data_len);
            ret = p_icp67->search_frame_cb(g_self_ptl.temp_buf, data_len, &pos, &valid_len);

            if(0 == ret)
            {
                g_self_ptl.icp67_rx.rptr += (pos + valid_len);
                g_self_ptl.icp67_rx.rptr %= g_self_ptl.icp67_rx.size;
                g_self_ptl.icp67_rx.cnt -= (pos + valid_len);
                
                stru_head *p_head = (stru_head *)&g_self_ptl.temp_buf[pos];

                if(p_head->dev_addr == DEV_MAINTENANCE_ADDR)
                {
                    uint32_t interface = com_channel_interface_get(ENUM_COMM_TCP_S_0);
                    self_ptl_data_tx(g_self_ptl.temp_buf + pos, valid_len, (void *)&interface);
                }
                else
                {
                    if(p_icp67->decode_cb)
                    {
                        p_icp67->decode_cb(p_icp67, g_self_ptl.temp_buf + pos, valid_len);
                    }
                }
            }
        }while(ret == 0);
    }

    get_rx_data(&g_self_ptl.icp67_rx, g_self_ptl.temp_buf, &data_len);
    self_ptl_search_first_head(g_self_ptl.temp_buf, data_len, 0x67, &pos);
    g_self_ptl.icp67_rx.rptr += pos;
    g_self_ptl.icp67_rx.rptr %= g_self_ptl.icp67_rx.size;
    g_self_ptl.icp67_rx.cnt -= pos;
    
    do
    {
        pos = 0;
        valid_len = 0;
        get_rx_data(&g_self_ptl.iec_rx, g_self_ptl.temp_buf, &data_len);
        ret = self_ptl_search_iec_frame(g_self_ptl.temp_buf, data_len, &pos, &valid_len);
        if(0 == ret)
        {
            g_self_ptl.iec_rx.rptr += (pos + valid_len);
            g_self_ptl.iec_rx.rptr %= g_self_ptl.iec_rx.size;
            g_self_ptl.iec_rx.cnt -= (pos + valid_len);

            uint32_t interface = com_channel_interface_get(ENUM_COMM_TCP_S_0);
            self_ptl_data_tx(g_self_ptl.temp_buf + pos, valid_len, (void *)&interface);
        }
    } while (ret == 0);
    
    get_rx_data(&g_self_ptl.iec_rx, g_self_ptl.temp_buf, &data_len);
    self_ptl_search_first_head(g_self_ptl.temp_buf, data_len, IEC_START, &pos);
    g_self_ptl.iec_rx.rptr += pos;
    g_self_ptl.iec_rx.rptr %= g_self_ptl.iec_rx.size;
    g_self_ptl.iec_rx.cnt -= pos;
}

void self_ptl_data_rx(uint8_t *p_data)
{
    if(NULL == p_data)
    {
        LOG_E("self_ptl_data_rx p_data NULL");
        return;
    }
    
    stru_msg_head *p_head = (stru_msg_head *)p_data;
    uint32_t interface = p_head->interface;
    uint16_t len = p_head->len;
    uint8_t *p_rx = p_head->data;

    stru_icp67 *p_icp67 = &g_self_ptl.icp67;

    self_ptl_search_frame(p_rx, len, p_icp67);

    // if(p_rx[0] == 0x67)
    // {
    //     stru_head *p_67_head = (stru_head *)p_rx;

    //     if(p_67_head->dev_addr == DEV_MAINTENANCE_ADDR)
    //     {
    //         uint32_t interface = com_channel_interface_get(ENUM_COMM_TCP_S_0);
    //         self_ptl_data_tx(p_rx, len, (void *)&interface);
    //     }
    //     else
    //     {
    //         if(p_icp67->decode_cb)
    //         {
    //             p_icp67->decode_cb(p_icp67, p_rx, len);
    //         }
    //     }
    // }
    // else if(p_rx[0] == IEC_START)
    // {
    //     uint32_t interface = com_channel_interface_get(ENUM_COMM_TCP_S_0);
    //     self_ptl_data_tx(p_rx, len, (void *)&interface);
    // }

}

void self_ptl_task()
{
    if(g_self_ptl.icp67.timer_handler_cb)
    {
        g_self_ptl.icp67.timer_handler_cb(&g_self_ptl.icp67);
    }
}

void self_ptl_set_interface(uint32_t interface)
{
    g_self_ptl.interface = interface;

    LOG_I("self_ptl_init interface %d, %x", g_self_ptl.interface, g_self_ptl.interface);
}


LOCAL int self_ptl_cfg_init()
{
    stru_self_ptl_cfg *p_cfg = self_ptl_cfg_get();
    if(nullptr == p_cfg)
    {   
        MY_LOG_E("self_ptl_cfg_init self_ptl_cfg_get failed");
        return -1;
    }

    stru_self_ptl_cfg_data *p_cfg_data = &g_self_ptl_cfg_data;

    p_cfg_data->st_vec.reserve(p_cfg->st_vec.size() + 1);

    for(uint32_t i = 0; i < p_cfg->st_vec.size(); i++)
    {
        uint8_t *p_u8 = new uint8_t;
        (*p_u8) = 0;

        p_cfg_data->st_vec.push_back({&p_cfg->st_vec[i], p_u8});
    }

    p_cfg_data->mx_vec.reserve(p_cfg->mx_vec.size() + 1);
    for(uint32_t i = 0; i < p_cfg->mx_vec.size(); i++)
    {
        float *p_f = new float;
        (*p_f) = 0.0;

        p_cfg_data->mx_vec.push_back({&p_cfg->mx_vec[i], p_f});
    }

    p_cfg_data->co_vec.reserve(p_cfg->co_vec.size() + 1);
    for(uint32_t i = 0; i < p_cfg->co_vec.size(); i++)
    {
        uint8_t *p_u8 = new uint8_t;
        (*p_u8) = 0;

        stru_signal_ctrl *p_ctrl = new stru_signal_ctrl;
        if(nullptr == p_ctrl)        
        {
            MY_LOG_E("self_ptl_cfg_init new stru_signal_ctrl failed");
            return -1;
        }

        p_ctrl->type = SIGNAL_CTRL_TYPE::SBO_NORMAL;
        p_ctrl->step = SIGNAL_CTRL_STEP::READY;
        p_ctrl->data_type = DATA_TYPE_U8;
        p_ctrl->p_data = dc_create_data_ptr_by_type(DATA_TYPE_U8);
        if(nullptr == p_ctrl->p_data)
        {
            MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d", DATA_TYPE_U8);
            return -1;
        }

        p_cfg_data->co_vec.push_back({&p_cfg->co_vec[i], p_u8, p_ctrl});
    }

    p_cfg_data->dd_vec.reserve(p_cfg->dd_vec.size() + 1);
    for(uint32_t i = 0; i < p_cfg->dd_vec.size(); i++)
    {
        float *p_f = new float;
        (*p_f) = 0.0;

        p_cfg_data->dd_vec.push_back({&p_cfg->dd_vec[i], p_f});
    }

    p_cfg_data->ao_vec.reserve(p_cfg->ao_vec.size() + 1);
    for(uint32_t i = 0; i < p_cfg->ao_vec.size(); i++)
    {
        stru_self_ptl_cfg_param *p_ao = &p_cfg->ao_vec[i];

        stru_signal_ctrl *p_ctrl = new stru_signal_ctrl;
        if(nullptr == p_ctrl)
        {
            MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d", p_ao->type);
            return -1;
        }

        p_ctrl->type = SIGNAL_CTRL_TYPE::SBO_NORMAL;
        p_ctrl->step = SIGNAL_CTRL_STEP::READY;
        p_ctrl->data_type = p_ao->type;
        p_ctrl->p_data = dc_create_data_ptr_by_type(p_ao->type);
        if(nullptr == p_ctrl->p_data)
        {
            MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d, saddr %s, desc %s",
                 p_ao->type, p_ao->base.saddr.c_str(), p_ao->base.desc.c_str());
            return -1;
        }

        p_cfg_data->ao_vec.push_back({p_ao, p_ctrl});

        void *p_data = dc_create_data_ptr_by_type(p_ao->type);
        if(nullptr == p_data)
        {
            MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d", p_ao->type);
            return -1;
        }
        p_cfg_data->ao_vec.back().vec_p_data.push_back(p_data);

        void *p_default_data = dc_create_data_ptr_by_type(p_ao->type);
        if(nullptr == p_default_data)
        {
            MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d", p_ao->type);
            return -1;
        }
        p_cfg_data->ao_vec.back().vec_p_default_data.push_back(p_default_data);
    }

    p_cfg_data->param_vec.reserve(p_cfg->param_vec.size() + 1);
    for(uint32_t i = 0; i < p_cfg->param_vec.size(); i++)
    {
        stru_self_ptl_cfg_param *p_param = &p_cfg->param_vec[i];

        stru_signal_ctrl *p_ctrl = new stru_signal_ctrl;
        if(nullptr == p_ctrl)
        {
            MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d", p_param->type);
            return -1;
        }

        p_ctrl->type = SIGNAL_CTRL_TYPE::SBO_NORMAL;
        p_ctrl->step = SIGNAL_CTRL_STEP::READY;
        p_ctrl->data_type = p_param->type;
        p_ctrl->p_data = dc_create_data_ptr_by_type(p_param->type);
        if(nullptr == p_ctrl->p_data)
        {
            MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d", p_param->type);
            return -1;
        }

        p_cfg_data->param_vec.push_back({p_param, p_ctrl});

        for(uint8_t i = 0; i < p_param->num; i++)
        {
            void *p_val_data = dc_create_data_ptr_by_type(p_param->type);
            if(nullptr == p_val_data)
            {
                MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d", p_param->type);
                return -1;
            }
            p_cfg_data->param_vec.back().vec_p_data.push_back(p_val_data);

            void *p_default_val_data = dc_create_data_ptr_by_type(p_param->type);
            if(nullptr == p_default_val_data)
            {
                MY_LOG_E("self_ptl_cfg_init dc_create_data_ptr_by_type failed, type:%d", p_param->type);
                return -1;
            }
            p_cfg_data->param_vec.back().vec_p_default_data.push_back(p_default_val_data);
        }
    }

    return 0;
}

void self_ptl_init()
{
    // g_self_ptl.interface = com_channel_interface_get(ENUM_COMM_TCP_C_0);
    

    stru_icp67 *p_icp67 = &g_self_ptl.icp67;
    icp67_init(p_icp67, self_ptl_data_tx, (void *)&g_self_ptl.interface);

    stru_self_ptl_cfg *p_self_cfg = self_ptl_cfg_get();
    if(nullptr == p_self_cfg)
    {
        LOG_E("self_ptl_init self_ptl_cfg_get failed");
        return;
    }

    icp67_set_ao_cfg_md5(p_icp67, p_self_cfg->ao_md5);

    stru_genneral_method *p_method = &g_self_ptl.method;

    icp67_set_ao_get_cb(&p_method->ao_get_cb);
    icp67_set_ao_pop_out_cb(p_method->ao_pop_out_cb);
    icp67_set_ao_set_cb(&p_method->ao_set_cb);
    icp67_set_iec_point_tbl_get_cb(&p_method->iec_point_tbl_get_cb);
    icp67_set_iec_point_tbl_pop_out_cb(p_method->iec_point_tbl_pop_out_cb);
    icp67_set_time_set_cb(&p_method->time_set_cb);
    icp67_set_self_check_get_cb(&p_method->self_check_get_cb);
    icp67_set_self_check_pop_out_cb(p_method->self_check_pop_out_cb);
    icp67_set_upgrade_start_cb(&p_method->upgrade_start_cb);

    icp67_set_dir_read_cb(&p_method->dir_read_cb);
    icp67_set_dir_pop_out_cb(p_method->dir_pop_out_cb);
    icp67_set_file_read_act_cb(&p_method->file_read_act_cb);
    icp67_set_file_read_act_confirm_cb(p_method->file_read_act_confirm_cb);
    icp67_set_file_read_cb(p_method->file_read_cb);
    icp67_set_file_read_confirm_cb(&p_method->file_read_confirm_cb);
    icp67_set_file_write_act_cb(&p_method->file_write_act_cb);
    icp67_set_file_write_act_confirm_cb(p_method->file_write_act_confirm_cb);
    icp67_set_file_write_cb(&p_method->file_write_cb);
    icp67_set_file_write_confirm_cb(p_method->file_write_confirm_cb);
    icp67_set_file_write_end_cb(p_method->file_write_end_cb);
    icp67_set_file_write_end_confirm_cb(&p_method->file_write_end_confirm_cb);

    icp67_set_zip_dir_pop_out_cb(p_method->zip_dir_pop_out_cb);
    icp67_set_zip_file_pop_out_cb(p_method->zip_file_pop_out_cb);

    icp67_set_mx_trans_cb(p_method->mx_trans_cb);
    icp67_set_st_trans_cb(p_method->st_trans_cb);
    icp67_set_dd_trans_cb(p_method->dd_trans_cb);
    icp67_set_soe_trans_cb(p_method->soe_trans_cb);
    icp67_set_fault_trans_cb(p_method->fault_trans_cb);
    icp67_set_mx_change_cb(p_method->mx_change_cb);
}

// 你原有的分割函数，完全不动
std::vector<std::string> split(const std::string &s, char delimiter) 
{
    std::vector<std::string> tokens;
    std::string token;
    for (char c : s) 
    {
        if (c == delimiter) 
        {
            tokens.push_back(token);
            token.clear();
        } 
        else 
        {
            token += c;
        }
    }
    tokens.push_back(token);
    return tokens;
}

// 改造后的提取函数：提取 param 和 TERM_ID
void extract_saddr(const std::string &str, std::string &param, std::string &term_id) 
{
    // 按 . 分割：self_ptl | param | TERM_ID
    auto parts = split(str, '.');
    
    // 必须至少 3 段才有效
    if (parts.size() >= 3) 
    {
        param = parts[1];    // 第二段：param
        term_id = parts[2];  // 第三段：TERM_ID
    }
}

void self_ptl_signal_change_callback(std::string saddr, SIGNAL_CTRL_STEP step, uint8_t data_type, uint8_t setting_zone, void *p_data)
{
    std::string value = "";
    if(p_data)
    {   
        value = dc_get_signal_val(p_data, data_type);
    }

    std::string step_str = "";
    switch(step)
    {
        case SIGNAL_CTRL_STEP::READY:
            step_str = "READY";
            break;
        case SIGNAL_CTRL_STEP::SELECT:
            step_str = "SELECT";
            break;
        case SIGNAL_CTRL_STEP::DIRECT:
            step_str = "DIRECT";
            break;
        case SIGNAL_CTRL_STEP::CANCEL:
            step_str = "CANCEL";
            break;
    }

    std::string data_type_str = "";
    data_type_str = dc_get_data_type_str_by_id(data_type);

    LOG_I("self_ptl_signal_change_callback saddr %s, step %s, data_type %s, value %s", saddr.c_str(), step_str.c_str(), data_type_str.c_str(), value.c_str());

    std::string signal_type = "", no = "";

    extract_saddr(saddr, signal_type, no);

    LOG_I("signal_type %s, no %s", signal_type.c_str(), no.c_str());

    stru_icp67 *p_icp67 = &g_self_ptl.icp67;
    stru_self_ptl_cfg_data *p_self_cfg_data = &g_self_ptl_cfg_data;

    if(signal_type == "co")
    {

    }
    else if(signal_type == "ao")
    {
        if(step == SIGNAL_CTRL_STEP::DIRECT)
        {
            if(g_self_ptl.method.ao_set_cb)
            {
                for(uint32_t i = 0; i < p_self_cfg_data->ao_vec.size(); i++)
                {
                    stru_self_ptl_cfg_param_data *p = &p_self_cfg_data->ao_vec.at(i);
                    if(p->p_param && p->p_param->base.saddr == saddr)
                    {
                        uint8_t temp[256] = {0};
                        stru_ti_1_2_data_info *p_data_info = (stru_ti_1_2_data_info *)temp;
                        p_data_info->data_addr = p->p_param->base.inf;
                        p_data_info->data_type = p->p_param->type;
                        p_data_info->data_len = dc_get_data_type_len(p->p_param->type);
                        std::string val = dc_get_signal_val(p->vec_p_data[0], p->p_param->type);
                        strcpy((char *)p_data_info->data, val.c_str());
                        g_self_ptl.method.ao_set_cb(p_icp67, temp, 1);
                        break;
                    }
                }
            }
        }
    }
    else if(signal_type == "param")
    {
        if(step == SIGNAL_CTRL_STEP::DIRECT)
        {
            // if(g_self_ptl.method.param_set_cb)
            // {
            //     for(uint32_t i = 0; i < p_self_cfg_data->param_vec.size(); i++)
            //     {
            //         stru_self_ptl_cfg_param_data *p = &p_self_cfg_data->param_vec.at(i);
            //         if(p->p_param && p->p_param->base.saddr == saddr)
            //         {
            //             uint8_t temp[256] = {0};
            //             stru_ti_1_2_data_info *p_data_info = (stru_ti_1_2_data_info *)temp;
            //             p_data_info->data_addr = p->p_param->base.inf;
            //             p_data_info->data_type = p->p_param->type;
            //             p_data_info->data_len = dc_get_data_type_len(p->p_param->type);
            //             std::string val = dc_get_signal_val(p->vec_p_data[setting_zone], p->p_param->type);
            //             strcpy((char *)p_data_info->data, val.c_str());
            //             g_self_ptl.method.param_set_cb(p_icp67, temp, 1);
            //             break;
            //         }
            //     }
            // }
        }
    }
}

LOCAL float safeStringToFloat(const std::string& str)
{
    float f = 0.0f;
    try {
        // 能转就转
        f = std::stof(str);
    }
    catch (const std::exception& e) {
        // 转不了就返回0.0
        // LOG_E("safeStringToFloat failed to convert '%s' to float: %s", str.c_str(), e.what());
        return 0.0f;
    }
    return f;
}

int self_ptl_do_signal_out(stru_app *p_app)
{
    stru_self_ptl_cfg_data *p_app_cfg_data = &g_self_ptl_cfg_data;

    stru_self_ptl_cfg_base_data *p  = nullptr;

    int ret = 0;
    ret |= dc_signal_out("self_ptl.run_cnt", "self_ptl.run_cnt", DATA_TYPE_U32, &p_app->run_cnt);
    if(ret != 0)
    {
        goto ERR;
    }

    for(uint32_t i = 0; i < p_app_cfg_data->st_vec.size(); i++)
    {
        p = &p_app_cfg_data->st_vec.at(i);
        if(p && p->p_base)
        {
            ret |= dc_signal_out(p->p_base->saddr, p->p_base->desc, DATA_TYPE_U8, p->p_data);
        }
    }

    if(ret != 0)
    {
        goto ERR;
    }

    for(uint32_t i = 0; i < p_app_cfg_data->mx_vec.size(); i++)
    {
        p = &p_app_cfg_data->mx_vec.at(i);
        if(p && p->p_base)
        {
            ret |= dc_signal_out(p->p_base->saddr, p->p_base->desc, DATA_TYPE_F32, p->p_data);
        }
    }
    
    if(ret != 0)
    {
        goto ERR;
    }

    for(uint32_t i = 0; i < p_app_cfg_data->co_vec.size(); i++)
    {
        p = &p_app_cfg_data->co_vec.at(i);
        if(p && p->p_base)
        {
            ret |= dc_signal_yk(p->p_base->saddr, p->p_base->desc, DATA_TYPE_U8, SIGNAL_CTRL_TYPE::SBO_NORMAL, p->p_data, self_ptl_signal_change_callback);
        }
    }

    if(ret != 0)
    {
        goto ERR;
    }

    for(uint32_t i = 0; i < p_app_cfg_data->dd_vec.size(); i++)
    {
        p = &p_app_cfg_data->dd_vec.at(i);
        if(p && p->p_base)
        {
            ret |= dc_signal_out(p->p_base->saddr, p->p_base->desc, DATA_TYPE_F32, p->p_data);
        }
    }

    if(ret != 0)
    {
        goto ERR;
    }

    for(uint32_t i = 0; i < p_app_cfg_data->ao_vec.size(); i++)
    {
        stru_self_ptl_cfg_param_data *p_ao = &p_app_cfg_data->ao_vec.at(i);
        if(p_ao && p_ao->p_param)
        {
            stru_signal_param param;
            param.min = safeStringToFloat(p_ao->p_param->min);
            param.max = safeStringToFloat(p_ao->p_param->max);
            param.step = safeStringToFloat(p_ao->p_param->step);
            param.unit = p_ao->p_param->unit;

            ret |= dc_signal_ao(p_ao->p_param->base.saddr, p_ao->p_param->base.desc, p_ao->p_param->type, param, SIGNAL_CTRL_TYPE::SBO_NORMAL, p_ao->vec_p_data[0], p_ao->vec_p_default_data[0], self_ptl_signal_change_callback);
        }
    }

    if(ret != 0)
    {
        goto ERR;
    }

    for(uint32_t i = 0; i < p_app_cfg_data->param_vec.size(); i++)
    {
        stru_self_ptl_cfg_param_data *p_param = &p_app_cfg_data->param_vec.at(i);
        if(p_param && p_param->p_param)
        {
            stru_signal_param param;
            param.min = safeStringToFloat(p_param->p_param->min);
            param.max = safeStringToFloat(p_param->p_param->max);
            param.step = safeStringToFloat(p_param->p_param->step);
            param.unit = p_param->p_param->unit;


            // ret(saddr, p(saddr, p->name, p->type, p->p_data);
            ret |= dc_signal_param(p_param->p_param->base.saddr, p_param->p_param->base.desc, p_param->p_param->type, param, SIGNAL_CTRL_TYPE::SBO_NORMAL, p_param->vec_p_data, p_param->vec_p_default_data, self_ptl_signal_change_callback);
        }
    }

    if(ret != 0)
    {
        goto ERR;
    }

    return 0;

ERR:
    MY_LOG_E("self_ptl_do_signal_out ret %d", ret);
    return ret;
}

int app_self_ptl_init1(void *arg)
{
    stru_app *p_app = (stru_app *)arg;

    if(0 != self_ptl_cfg_init())
    {
        MY_LOG_E("self ptl cfg_init failed");
        return -1;
    }

    self_ptl_init();

    if(0 != self_ptl_do_signal_out(p_app))
    {
        MY_LOG_E("self ptl do_signal_out failed");
        return -1;
    }

    return 0;
}

LOCAL uint32_t *p_iec_run_cnt_in = NULL;

int app_self_ptl_init2(void *arg)
{
    dc_signal_in("self_ptl.iec_run_cnt_in", "self_ptl.iec_run_cnt_in", "iec.run_cnt", DATA_TYPE_U32, (void **)&p_iec_run_cnt_in);

    MY_LOG_I("p_iec_run_cnt_in %p", p_iec_run_cnt_in);
    return 0;
}

void *app_self_ptl(void *arg)
{
    if(NULL == arg)
    {
        LOG_E("app_com_scan arg null");
        return NULL;
    }

    stru_app *p_app = (stru_app *)arg;

    uint32_t event;
    stru_app_msg_queue *p_mq = NULL;
    stru_rtx_data *p_rtx = &p_app->rtx;


    while(1)
    {
        task_event_recv(p_app->p_event, 
            EV_TIMER1 | EV_TIMER2 | EV_TIMER3 | EV_SELF_PTL_RX_COM,
            TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
            TASK_EVENT_WAIT_FOREVER, 
            &event);

        if((event & EV_SELF_PTL_RX_COM) && NULL != (p_mq = app_get_msg_queue_ptr(ENUM_MQ_COM_TO_SELF_PTL)))
        {
            while(1)
            {
                if(0 != task_msg_queue_try_recv(p_mq->p_msg_queue, p_rtx->rx, p_mq->msg_size))
                {
                    break;
                }
                self_ptl_data_rx(p_rtx->rx);
            }
        }

        if(event & EV_TIMER1)
        {
            self_ptl_task();
        }

        if(event & EV_TIMER2)
        {
            self_ptl_method_task();
        }

        if(event & EV_TIMER3)
        {
            p_app->run_cnt++;
        }
    }

    return NULL;
}   