#include "microgridtopology.h"
#include "collector-api.h"
#include "deviceLayer.h" 
#include "emsctrlProc.h"
#include "discover.h"
#include "./jsonct.h"
#include <sys/syslog.h>
#include <time.h>
#include <unistd.h>
#include <stdatomic.h>
#include <float.h>

#define PV_KM 1
#define SOC_KM 0.2
static micro_abnormal_msg_t micro_abnormal_tab[] =
{
	{LCB_SIGN_ON, "waring abnormal: 负载断路器合闸异常"},
	{LCB_SIGN_OFF, "waring abnormal: 负载断路器分闸异常"},
	{ICB_SIGN_ON,  "waring abnormal: 并离网断路器合闸异常"},
	{ICB_SIGN_OFF, "waring abnormal: 并离网断路器分闸异常"},
	{DG_SIGN_ON,   "waring abnormal: 柴发启动异常"},
	{DG_SIGN_OFF,  "waring abnormal: 柴发关机异常"},
};

static void print_abnormal_result(ABNORMAL code){
    char *abnormal_msg = NULL;
    int i;
    for (i = 0; i < sizeof(micro_abnormal_tab) / sizeof(micro_abnormal_tab[0]); i++)
    {
        if (micro_abnormal_tab[i].code == code)
        {
            abnormal_msg = micro_abnormal_tab[i].msg;
            break;
        }
    }
    ems_syslog(LOG_WARNING, "~~: %s ", abnormal_msg);
}

static time_t startTime = -1;
static void check_action_timeout(int *p, char *tag, int value, ABNORMAL code){
    time_t currentTime = -1;
    time(&currentTime);

    double elapsedTime = difftime(currentTime, startTime);
    if (elapsedTime >= microgrid_ctrl.action_timeout) {
        dev_set_dev_tag_int(DEV_NO_EMS, tag, value);
        *p = value;
        print_abnormal_result(code);
    }
}

// bit_set(microgrid_ctrl.cut_flag, BIT_STATE_OFF_GRID, 1);  

static battery_flag_t battery_flag[CABINET_NUM_MAX] = {0};

static current_stat_t ac_state_machine;
static current_stat_t *get_ac_state_machine(void)
{
    return &ac_state_machine;
}

static bool offgrid_condition_with_sts(dev_info_all_t *var, int value, unsigned int pos){
    if (microgrid_cfg.en_mains && microgrid_cfg.en_diesel_generator){ 
        if (microgrid_cfg.en_ats){
            if (microgrid_cfg.en_sts == 1 && microgrid_cfg.en_icb == 0){
                if (microgrid_data.offgrid_statu == 1)
                    return true;
            }
        }else{
            ems_syslog(LOG_WARNING, "ATS must be opened!!!");
            return false;
        }
    }
    else if (microgrid_cfg.en_mains){
        if (microgrid_cfg.en_sts == 1 && microgrid_cfg.en_icb == 0){
            if (microgrid_data.offgrid_statu == 1)
                return true;
        }
    }
    else if (microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_sts == 1 && microgrid_cfg.en_icb == 0){
            if (microgrid_data.offgrid_statu == 1)
                return true;
        }   
    }
    else //>>柴发和市电都未使能，纯离网
        return true;
    return false;
}

static bool offgrid_condition_with_cirbreak(dev_info_all_t *var, int value, unsigned int pos){
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_mains && microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_ats){// 柴发和市电都使能，必须开启ATS，电操断路器和STS可选任意一个
            if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 1){
                if (_dido->info.dido_data.conn_sign == 0 && _dido->info.dido_data.icb_sign == 0)
                    return true;
            }
        }else{
            ems_syslog(LOG_WARNING, "ATS must be opened!!!");
            return false;
        }
    }
    else if (microgrid_cfg.en_mains){
        if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 1){
            if (_dido->info.dido_data.conn_sign == 0 && _dido->info.dido_data.icb_sign == 0)
                return true;
        }
    }
    else if (microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 1){
            if (_dido->info.dido_data.conn_sign == 0 && _dido->info.dido_data.icb_sign == 0)
                return true;
        }    
    }
    else //>>柴发和市电都未使能，纯离网
        return true;
    return false;
}

static bool offgrid_condition_with_none(dev_info_all_t *var, int value, unsigned int pos){ // ***
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_mains && microgrid_cfg.en_diesel_generator){
        return false;
    }
    else if (microgrid_cfg.en_mains){
        return false;
    }
    else if (microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 0){
            if ((bit_get(microgrid_ctrl.cut_flag, BIT_STATE_CF_CONNECT_GRID) == 0) && _dido->info.dido_data.conn_sign == 0){ // 防止柴发并网init过程中，柴发开机较慢，导致意外进入离网
                return true;
            }
        }    
    }
    else //>>柴发和市电都未使能，纯离网
        return true;
    return false;
}

static bool offgrid_condition_with_force(dev_info_all_t *var, int value, unsigned int pos){
    if (bit_get(microgrid_ctrl.cut_flag, pos)){
        return true;
    }
    return false;
}
/***********************************/
static bool cfgrid_condition_with_sts(dev_info_all_t *var, int value, unsigned int pos){
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_mains && microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_ats){
            if (microgrid_cfg.en_sts == 1 && microgrid_cfg.en_icb == 0){
                if (microgrid_data.grid_statu == 1 && _dido->info.dido_data.ats_sign == 0)
                    return true;
            }
        }else{
            ems_syslog(LOG_WARNING, "ATS must be opened!!!");
            return false;
        }
    }
    else if (microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_sts == 1 && microgrid_cfg.en_icb == 0){
            if (microgrid_data.grid_statu == 1)
                return true;
        }
    }
    return false;
}

static bool cfgrid_condition_with_cirbreak(dev_info_all_t *var, int value, unsigned int pos){
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_mains && microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_ats){// 柴发和市电都使能，必须开启ATS，电操断路器和STS可选任意一个
            if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 1){
                if (_dido->info.dido_data.conn_sign == 1 && _dido->info.dido_data.ats_sign == 0) // 1. 主->备电源切换、断路器自动分闸 2. 离网->备电源、断路器保持分闸状态
                    return true;
            }
        }else{
            ems_syslog(LOG_WARNING, "ATS must be opened!!!");
            return false;
        }
    }
    else if (microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 1){
            if (_dido->info.dido_data.conn_sign == 1)
                return true;
        }  
    }
    return false;
}

static bool cfgrid_condition_with_none(dev_info_all_t *var, int value, unsigned int pos){ // ***
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_mains == 0 && microgrid_cfg.en_diesel_generator == 1){
        if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 0){
            if ((bit_get(microgrid_ctrl.cut_flag, BIT_STATE_OFF_GRID) == 0) && _dido->info.dido_data.conn_sign == 1){ // 防止离网init过程中，柴发关机较慢，导致意外进入柴发并网
                return true;
            }
        }
    }
    return false;
}

static bool cfgrid_condition_with_force(dev_info_all_t *var, int value, unsigned int pos){ // 状态机支持强切功能
    if (bit_get(microgrid_ctrl.cut_flag, pos)){
        return true;
    }
    return false;
}
/*****************************************/
static bool grid_condition_with_sts(dev_info_all_t *var, int value, unsigned int pos){
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_mains && microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_ats){
            if (microgrid_cfg.en_sts == 1 && microgrid_cfg.en_icb == 0){
                if (microgrid_data.grid_statu == 1 && _dido->info.dido_data.ats_sign == 1)
                    return true;
            }
        }else{
            ems_syslog(LOG_WARNING, "ATS must be opened!!!");
            return false;
        }
    }
    else if (microgrid_cfg.en_mains){
        if (microgrid_cfg.en_sts == 1 && microgrid_cfg.en_icb == 0){
            if (microgrid_data.grid_statu == 1)
                return true;
        }
    }
    return false;
}

static bool grid_condition_with_cirbreak(dev_info_all_t *var, int value, unsigned int pos){
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_mains && microgrid_cfg.en_diesel_generator){
        if (microgrid_cfg.en_ats){// 柴发和市电都使能，必须开启ATS，电操断路器和STS可选任意一个
            if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 1){
                if (_dido->info.dido_data.conn_sign == 1 && _dido->info.dido_data.ats_sign == 1) // 1. 备->主电源切换、断路器自动分闸 2. 离网->主电源、断路器保持分闸状态
                    return true;
            }
        }else{
            ems_syslog(LOG_WARNING, "ATS must be opened!!!");
            return false;
        }
    }
    else if (microgrid_cfg.en_mains){
        if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 1){
            if (_dido->info.dido_data.conn_sign == 1)
                return true;
        }  
    }
    return false;
}

static bool grid_condition_with_none(dev_info_all_t *var, int value, unsigned int pos){ // 此方案：一定是纯市电并网，(市电不可控制)
    // struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_mains == 1 && microgrid_cfg.en_diesel_generator == 0){
        if (microgrid_cfg.en_sts == 0 && microgrid_cfg.en_icb == 0){
            return true;
        }
    }
    return false;
}

static bool grid_condition_with_force(dev_info_all_t *var, int value, unsigned int pos){
    if (bit_get(microgrid_ctrl.cut_flag, pos)){
        return true;
    }
    return false;
}
/*****************************************/
static bool abnormal_condition(dev_info_all_t *var, int value, unsigned int pos){ // 异常状态切入条件，系统异常
    if(dev_get_dev_tag_int(DEV_NO_EMS, SYSTEM_STATUS)){ 
        return true; 
    }
    return false;
}

static bool await_condition(dev_info_all_t *var, int value, unsigned int pos){ 	
    return true;
}

static bool grid_abnormal_condition(dev_info_all_t *var, int value, unsigned int pos){
    if (abnormal_condition(var, value, pos) == true) { return true; }
    if (microgrid_abnormal.icb_abnormal == 1){ return true; }
    for (int i = 0 ; i < var->cabinet_info.num; i++)  //所有柜子都不能用 
	{
	    cabinet_inside_t *_cabinet_inside  = var->cabinet_info.cabinet_inside[i];
        if (_cabinet_inside->cab_data.en == 0)
            return false; 
	}	
    return true;
}

static bool offgrid_abnormal_condition(dev_info_all_t *var, int value, unsigned int pos){
    if (abnormal_condition(var, value, pos) == true) { return true; }
    if (microgrid_abnormal.lcb_abnormal == 2){ return true; }
    for (int i = 0 ; i < var->cabinet_info.num; i++)
	{
	    cabinet_inside_t *_cabinet_inside  = var->cabinet_info.cabinet_inside[i];
        if (_cabinet_inside->cab_data.en == 0)
            return false; 
	}	
    return true;
}

static bool cf_grid_abnormal_condition(dev_info_all_t *var, int value, unsigned int pos){
    if (abnormal_condition(var, value, pos) == true) { return true; }
    if (microgrid_abnormal.DG_abnormal == 1|| microgrid_abnormal.icb_abnormal == 1){ return true; }
    for (int i = 0 ; i < var->cabinet_info.num; i++)
	{
	    cabinet_inside_t *_cabinet_inside  = var->cabinet_info.cabinet_inside[i];
        if (_cabinet_inside->cab_data.en == 0)
            return false; 
	}	
    return true;
}

static bool init_grid_abnormal_condition(dev_info_all_t *var, int value, unsigned int pos){
    if (abnormal_condition(var, value, pos) == true) { return true; }
    if (microgrid_abnormal.DG_abnormal == 1 || microgrid_abnormal.icb_abnormal == 1 || microgrid_abnormal.lcb_abnormal == 2){ return true; }
    for (int i = 0 ; i < var->cabinet_info.num; i++)
	{
	    cabinet_inside_t *_cabinet_inside  = var->cabinet_info.cabinet_inside[i];
        if (_cabinet_inside->cab_data.en == 0)
            return false; 
	}	
    return true;
}

static bool abnormal_grid_condition_perp(void){
    if (microgrid_abnormal.icb_abnormal == 1){ 
        return false; 
    }	
    return true;
}

static bool abnormal_cfgrid_condition_perp(void){
    if (microgrid_abnormal.DG_abnormal == 1 || microgrid_abnormal.icb_abnormal == 1){
        return false; 
    }	
    return true;
}

static bool abnormal_offgrid_condition_perp(void){
    if (microgrid_abnormal.DG_abnormal == 1 || microgrid_abnormal.lcb_abnormal == 2){ 
        return false; 
    }
    return true;
}

// 实际场景中，不存在市电并网直接切柴发并网，
// 带STS，柴发并网-->离网"短暂"-->市电并网
// 不带STS，柴发并网-->离网-->市电并网
/* ****************************************** "状态机"，状态切出，条件可添加 *****************start**********************/
static micr_condition_and_check_t grid_handover_detect[] = {
    {"异常状态",  STATE_ABNORMAL,  BIT_STATE_ABNORMAL,  LOGIC_OR, { {grid_abnormal_condition, 0}, 
                                                                    {NULL, 0} }, NULL }, // {NULL, 0} 结束符
    {"待机",     STATE_AWAIT,     BIT_STATE_OFF_GRID,   LOGIC_OR, {    {offgrid_condition_with_sts, 0}, 
                                                                        {offgrid_condition_with_cirbreak, 0}, 
                                                                        {offgrid_condition_with_none, 0},
                                                                        {offgrid_condition_with_force, 0}, 
                                                                        {NULL, 0} }, NULL },
    {"待机",     STATE_AWAIT,     BIT_STATE_CF_CONNECT_GRID,  LOGIC_OR, {   {cfgrid_condition_with_sts, 0}, 
                                                                            {cfgrid_condition_with_cirbreak, 0}, 
                                                                            {cfgrid_condition_with_none, 0}, 
                                                                            {cfgrid_condition_with_force, 0}, 
                                                                            {NULL, 0} }, NULL  },
};

static micr_condition_and_check_t offgrid_handover_detect[] = {
    {"异常状态", STATE_ABNORMAL, BIT_STATE_ABNORMAL, LOGIC_OR, { {offgrid_abnormal_condition, 0}, 
                                                                {NULL, 0} }, NULL  },
    {"待机",     STATE_AWAIT,   BIT_STATE_CONNECT_GRID,  LOGIC_OR, { {grid_condition_with_sts, 0}, 
                                                                    {grid_condition_with_cirbreak, 0}, 
                                                                    {grid_condition_with_none, 0}, 
                                                                    {grid_condition_with_force, 0}, 
                                                                    {NULL, 0} }, NULL  },
    {"待机",     STATE_AWAIT,   BIT_STATE_CF_CONNECT_GRID,  LOGIC_OR, { {cfgrid_condition_with_sts, 0}, 
                                                                        {cfgrid_condition_with_cirbreak, 0}, 
                                                                        {cfgrid_condition_with_none, 0},
                                                                        {cfgrid_condition_with_force, 0}, 
                                                                        {NULL, 0} }, NULL  },
};

static micr_condition_and_check_t cf_grid_handover_detect[] = {
    {"异常状态", STATE_ABNORMAL,  BIT_STATE_ABNORMAL,  LOGIC_OR, { {cf_grid_abnormal_condition, 0}, 
                                                                    {NULL, 0} }, NULL  },
    {"待机",     STATE_AWAIT,    BIT_STATE_CONNECT_GRID,   LOGIC_OR, {  {grid_condition_with_sts, 0}, 
                                                                        {grid_condition_with_cirbreak, 0}, 
                                                                        {grid_condition_with_none, 0}, 
                                                                        {grid_condition_with_force, 0}, 
                                                                        {NULL, 0} }, NULL  },
    {"待机",     STATE_AWAIT,   BIT_STATE_OFF_GRID,    LOGIC_OR, {  {offgrid_condition_with_sts, 0}, 
                                                                    {offgrid_condition_with_cirbreak, 0},
                                                                    {offgrid_condition_with_none, 0},
                                                                    {offgrid_condition_with_force, 0}, 
                                                                    {NULL, 0} }, NULL  },
};

static micr_condition_and_check_t await_handover_detect[] = { // 若所有状态都不满足，且没有异常，则待机等待 ~~"中间态"
    {"异常状态", STATE_ABNORMAL,  BIT_STATE_ABNORMAL,   LOGIC_OR, { {abnormal_condition, 0}, 
                                                                    {NULL, 0} }, NULL  },
    {"市电并网", STATE_CONNECT_GRID,  BIT_STATE_CONNECT_GRID,  LOGIC_OR, {  {grid_condition_with_sts, 0}, 
                                                                            {grid_condition_with_cirbreak, 0}, 
                                                                            {grid_condition_with_none, 0},
                                                                            {grid_condition_with_force, 0}, 
                                                                            {NULL, 0} }, NULL  },
    {"柴发并网", STATE_CF_CONNECT_GRID, BIT_STATE_CF_CONNECT_GRID, LOGIC_OR, {  {cfgrid_condition_with_sts, 0}, 
                                                                                {cfgrid_condition_with_cirbreak, 0},  
                                                                                {cfgrid_condition_with_none, 0},
                                                                                {cfgrid_condition_with_force, 0},  
                                                                                {NULL, 0} }, NULL  },
    {"离网",     STATE_OFF_GRID,   BIT_STATE_OFF_GRID, LOGIC_OR, {  {offgrid_condition_with_sts, 0}, 
                                                                    {offgrid_condition_with_cirbreak, 0}, 
                                                                    {offgrid_condition_with_none, 0},
                                                                    {offgrid_condition_with_force, 0},
                                                                    {NULL, 0} }, NULL  },
};

static micr_condition_and_check_t abnormal_handover_detect[] = {
    {"市电并网", STATE_CONNECT_GRID,  BIT_STATE_CONNECT_GRID,  LOGIC_OR, {  {grid_condition_with_sts, 0}, 
                                                                            {grid_condition_with_cirbreak, 0},  
                                                                            {grid_condition_with_none, 0},
                                                                            {grid_condition_with_force, 0}, 
                                                                            {NULL, 0} },  abnormal_grid_condition_perp },
    {"柴发并网", STATE_CF_CONNECT_GRID, BIT_STATE_CF_CONNECT_GRID,  LOGIC_OR, { {cfgrid_condition_with_sts, 0}, 
                                                                                {cfgrid_condition_with_cirbreak, 0}, 
                                                                                {cfgrid_condition_with_none, 0},
                                                                                {cfgrid_condition_with_force, 0}, 
                                                                                {NULL, 0} },   abnormal_cfgrid_condition_perp},
    {"离网",     STATE_OFF_GRID,   BIT_STATE_OFF_GRID,     LOGIC_OR, { {offgrid_condition_with_sts, 0}, 
                                                                        {offgrid_condition_with_cirbreak, 0}, 
                                                                        {offgrid_condition_with_none, 0},
                                                                        {offgrid_condition_with_force, 0},
                                                                        {NULL, 0} },  abnormal_offgrid_condition_perp},
};

static micr_condition_and_check_t init_handover_detect[] = {
    {"异常状态",  STATE_ABNORMAL,    BIT_STATE_ABNORMAL,      LOGIC_OR, { {init_grid_abnormal_condition, 0}, 
                                                                    {NULL, 0} }, NULL  },
    {"市电并网", STATE_CONNECT_GRID,  BIT_STATE_CONNECT_GRID,  LOGIC_OR, { {grid_condition_with_sts, 0}, 
                                                                            {grid_condition_with_cirbreak, 0},  
                                                                            {grid_condition_with_none, 0}, 
                                                                            {grid_condition_with_force, 0}, 
                                                                            {NULL, 0} }, NULL  },
    {"柴发并网", STATE_CF_CONNECT_GRID, BIT_STATE_CF_CONNECT_GRID,  LOGIC_OR, { {cfgrid_condition_with_sts, 0}, 
                                                                                {cfgrid_condition_with_cirbreak, 0}, 
                                                                                {cfgrid_condition_with_none, 0}, 
                                                                                {cfgrid_condition_with_force, 0}, 
                                                                                {NULL, 0} }, NULL  },
    {"离网",    STATE_OFF_GRID,    BIT_STATE_OFF_GRID,     LOGIC_OR, { {offgrid_condition_with_sts, 0}, 
                                                                        {offgrid_condition_with_cirbreak, 0},
                                                                        {offgrid_condition_with_none, 0}, 
                                                                        {offgrid_condition_with_force, 0},
                                                                        {NULL, 0} }, NULL  },
    {"待机",    STATE_AWAIT,     BIT_STATE_AWAIT,       LOGIC_OR, { {await_condition, 0}, 
                                                                    {NULL, 0} }, NULL  }  //上述条件都不满足，进入待机状态
};
/* *******************************************************************************************end**********************/
static bool check_conditions(micr_condition_and_check_t *check) {
    dev_info_all_t *var = get_dev_info_all_var();
    if (check->check_condi_perp == NULL) // 前置条件perp = NULL，直接判断切出条件即可
        CHECK_CONDITIONS(check, check->relation, check->pos);
    else{
        if (check->check_condi_perp())
            CHECK_CONDITIONS(check, check->relation, check->pos);
        else
            return false;
    }
}

static RELEVANCE_STATE micr_condition_check(micr_condition_and_check_t *micr_condition_and_check, int size, RELEVANCE_STATE state){
    Relevant_data_refresh();
    for (int i = 0; i < size; i++) { // 按顺序检测，返回切出状态"标识"，若未满足切出状态，则返回当前状态
        if (check_conditions(&micr_condition_and_check[i]) == true){
            ems_syslog(LOG_NOTICE, "cute out state: %s", micr_condition_and_check[i].desc);
            return  micr_condition_and_check[i].state;
        }
    }
    return state;
}
/******************************************************** */
static void update_cf_switch(dev_info_all_t *var, int value)
{
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_diesel_generator)
        _dido->info.dido_ctrl.DG_ctrl = value;
}

static int chk_cf_switch(dev_info_all_t *var, int value)
{
    struct _dido_t * _dido = &var->dido.dido_param[0];

    if(microgrid_cfg.en_diesel_generator == 0 || value == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
    ems_syslog(LOG_NOTICE, "DG sign :%d", _dido->info.dido_data.DG_sign);
    if(0 == value)//0: 停止  1:启动
    {
        if(_dido->info.dido_data.DG_sign == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        check_action_timeout(&microgrid_abnormal.DG_abnormal, DG_ABNORMAL, 2, DG_SIGN_OFF);
        return (_dido->info.dido_data.DG_sign == 0) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    else if (1 == value)
    {
        if(_dido->info.dido_data.DG_sign == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        check_action_timeout(&microgrid_abnormal.DG_abnormal, DG_ABNORMAL, 1, DG_SIGN_ON);
        return (_dido->info.dido_data.DG_sign == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    return MICR_CONDITION_NO_MATCH;
}

static void update_pv_switch(dev_info_all_t *var, int value){
    if (microgrid_cfg.en_photovoltaic)
        microgrid_ctrl.pv_exp_onoff = value;
}

static int chk_pv_switch(dev_info_all_t *var, int value)
{
    if(microgrid_cfg.en_photovoltaic == 0 || value == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
    ems_syslog(LOG_NOTICE, "pv status pv_on_statu :%d, pv_off_statu :%d", microgrid_data.pv_on_statu, microgrid_data.pv_off_statu);
    if(0 == value)//停机
    {
        if(microgrid_data.pv_off_statu == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        return (microgrid_data.pv_off_statu == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    else if (1 == value) //开机
    {
        if(microgrid_data.pv_on_statu == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        return (microgrid_data.pv_on_statu == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    return MICR_CONDITION_NO_MATCH;
}

static void update_pcs_connect(dev_info_all_t *var, int value)
{
    int index = 0;

    if (microgrid_cfg.en_sts == 0){
        microgrid_ctrl.Grid_offgrid = value;
        for(index = 0; index < var->cabinet_info.num; index++)
        {
            atomic_store(&var->cabinet_info.cabinet_inside[index]->cab_ctrl.connect, value);
        }
    }
}

static int chk_pcs_connect(dev_info_all_t *var, int value)
{
    ems_syslog(LOG_NOTICE, "pcs  grid_statu:%d, offgrid_statu :%d", microgrid_data.grid_statu, microgrid_data.offgrid_statu);
    if(value == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
    if(0 == value)//离网
    {
        if(microgrid_data.offgrid_statu == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        return (microgrid_data.offgrid_statu == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    else if (1 == value) //并网
    {
        if(microgrid_data.grid_statu == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        return (microgrid_data.grid_statu == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    return MICR_CONDITION_NO_MATCH;
}

static void update_pcs_switch(dev_info_all_t *var, int value)
{
    int index = 0;
    microgrid_ctrl.onoff = value;
    for(index = 0; index < var->cabinet_info.num; index++)
    {
        atomic_store(&var->cabinet_info.cabinet_inside[index]->cab_ctrl.onoff, value);
    }
}

static int chk_pcs_switch(dev_info_all_t *var, int value)
{
    ems_syslog(LOG_NOTICE, "pcs status stop :%d, run :%d", microgrid_data.off_statu, microgrid_data.on_statu);
    if(value == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
    if(0 == value)//停机
    {
        if(microgrid_data.off_statu == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        return (microgrid_data.off_statu == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    else if (1 == value) //开机
    {
        if(microgrid_data.on_statu == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        return (microgrid_data.on_statu == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    return MICR_CONDITION_NO_MATCH;
}

static void update_load_switch(dev_info_all_t *var, int value)
{
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_lcb)
        _dido->info.dido_ctrl.lcb_ctrl = value;
}

static int chk_load_switch(dev_info_all_t *var, int value)
{
    struct _dido_t * _dido = &var->dido.dido_param[0];

    if(microgrid_cfg.en_lcb == 0 || value == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
    ems_syslog(LOG_NOTICE, "lcb sign :%d", _dido->info.dido_data.lcb_sign);
    if(0 == value) // 0: 断开  1:闭合
    {
        if(_dido->info.dido_data.lcb_sign == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        check_action_timeout(&microgrid_abnormal.lcb_abnormal, LCB_ABNORMAL, 2, LCB_SIGN_OFF);
        return (_dido->info.dido_data.lcb_sign == 0) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    else if (1 == value)
    {
        if(_dido->info.dido_data.lcb_sign == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        check_action_timeout(&microgrid_abnormal.lcb_abnormal, LCB_ABNORMAL, 1, LCB_SIGN_ON);
        return (_dido->info.dido_data.lcb_sign == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    return MICR_CONDITION_NO_MATCH;
}

static void update_gd_switch(dev_info_all_t *var, int value) // 并离网断路器没有市电/柴发时，会自动分闸，只需确认分闸就行；但合闸需要EMS自己控制，(需确认PCS并网后，再合闸)
{
    struct _dido_t * _dido = &var->dido.dido_param[0];
    if (microgrid_cfg.en_icb)
        _dido->info.dido_ctrl.icb_ctrl = value;
}

static int chk_gd_switch(dev_info_all_t *var, int value)
{
    struct _dido_t * _dido = &var->dido.dido_param[0];

    if(microgrid_cfg.en_icb == 0 || value == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
    ems_syslog(LOG_NOTICE, "icb sign :%d", _dido->info.dido_data.icb_sign);
    if(0 == value)//分闸
    {
        if(_dido->info.dido_data.icb_sign == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        check_action_timeout(&microgrid_abnormal.icb_abnormal, ICB_ABNORMAL, 2, ICB_SIGN_OFF);
        return (_dido->info.dido_data.icb_sign == 0) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    else if (1 == value) //合闸
    {
        if(_dido->info.dido_data.icb_sign == MICR_ACTION_TYPE_INIT) return MICR_CONDITION_SKIP;
        check_action_timeout(&microgrid_abnormal.icb_abnormal, ICB_ABNORMAL, 1, ICB_SIGN_ON);
        return (_dido->info.dido_data.icb_sign == 1) ? MICR_CONDITION_OK : MICR_CONDITION_NO_MATCH;
    }
    return MICR_CONDITION_NO_MATCH;
}

/*grid ****************************************** "状态机"，进入状态执行策略逻辑前必须要执行的动作 按顺序执行，可添加 ********************************start**********************/
static micr_action_and_check_t grid_init_actions[] = {
    //{"确认并离网断路器分闸", update_gd_switch,         0,      chk_gd_switch,                      0},
    //{"PCS关机", update_pcs_switch,                   0,      chk_pcs_switch,                      0},
    {"PCS并网", update_pcs_connect,                  1,      chk_pcs_connect,                     1},
    {"并离网断路器合闸", update_gd_switch,            1,      chk_gd_switch,                       1},
    //{"PCS开机", update_pcs_switch,                   1,      chk_pcs_switch,                      1},
    {"PV开机",  update_pv_switch,                    1,      chk_pv_switch,                       1},
    {"接通负载",update_load_switch,                  1,      chk_load_switch,                     1}
};

static micr_action_and_check_t grid_init_actions_sts[] = {
    {"PCS开机", update_pcs_switch,                   1,      chk_pcs_switch,                      1},
    {"PV开机",  update_pv_switch,                    1,      chk_pv_switch,                       1},
    {"接通负载",update_load_switch,                  1,      chk_load_switch,                     1}
};
/* offgrid ********************************************/
static micr_action_and_check_t offgrid_init_actions[] = {
    {"确认CF关机", update_cf_switch,                   0,      chk_cf_switch,                     0},
    {"确认并离网断路器分闸", update_gd_switch,          0,      chk_gd_switch,                      0}, //参数： -1表示不检查，0表示分闸，1表示合闸，其他值返回NO_MATCH,
    {"PCS关机", update_pcs_switch,                     0,      chk_pcs_switch,                     0},
    {"PCS离网", update_pcs_connect,                    0,      chk_pcs_connect,                    0},
    {"PCS开机", update_pcs_switch,                     1,      chk_pcs_switch,                     1},
    {"PV开机",  update_pv_switch,                      1,      chk_pv_switch,                      1}
};

static micr_action_and_check_t offgrid_init_actions_sts[] = { //确保PCS、PV开机
    {"PCS开机", update_pcs_switch,                     1,      chk_pcs_switch,                     1},
    {"PV开机",  update_pv_switch,                      1,      chk_pv_switch,                      1}
};
/* cf_grid ********************************************/
static micr_action_and_check_t cf_grid_init_actions[] = {
    //{"确认并离网断路器分闸", update_gd_switch,        0,      chk_gd_switch,                     0},
    {"PCS关机", update_pcs_switch,                   0,      chk_pcs_switch,                    0},
    {"PCS并网", update_pcs_connect,                  1,      chk_pcs_connect,                   1},
    {"PV关机", update_pv_switch,                     0,      chk_pv_switch,                     0},
    {"确认CF开机", update_cf_switch,                 1,      chk_cf_switch,                     1}, // 1.使能STS或并离网断路器时，离网行为中可先开启柴发，此处只需确认柴发开机即可 2.不使能STS和并离网断路器时，则需要强切，离网行为中不能开柴发，置位强切标志后，柴发在此处开启
    {"并离网断路器合闸", update_gd_switch,            1,      chk_gd_switch,                     1},
    {"PCS开机", update_pcs_switch,                   1,      chk_pcs_switch,                    1},
    {"接通负载", update_load_switch,                 1,      chk_load_switch,                   1}
};

static micr_action_and_check_t cf_grid_init_actions_sts[] = {
    {"PV关机", update_pv_switch,                     0,      chk_pv_switch,                     0},
    {"确认CF开机", update_cf_switch,                 1,      chk_cf_switch,                     1},
    {"PCS开机", update_pcs_switch,                   1,      chk_pcs_switch,                    1},
    {"接通负载",update_load_switch,                  1,      chk_load_switch,                   1}
};
/* await ********************************************/
static micr_action_and_check_t await_init_actions[] = {
    {"PV关机", update_pv_switch,                     0,      chk_pv_switch,                     0},
    {"PCS关机", update_pcs_switch,                   0,      chk_pcs_switch,                    0},
};

static micr_action_and_check_t await_init_actions_sts[] = {
};
/* abnormal ********************************************/
static micr_action_and_check_t abnormal_init_actions[] = {
    {"PV关机", update_pv_switch,                     0,      chk_pv_switch,                     0},
    //{"PCS关机", update_pcs_switch,                   0,      chk_pcs_switch,                    0},
    {"断开负载", update_load_switch,                 0,      chk_load_switch,                   0}
};
/* init ********************************************/
static micr_action_and_check_t init_actions[] = { // 各个设备准备好，等待进入状态
    //{"PCS开机", update_pcs_switch,                   1,      chk_pcs_switch,                    1},
    {"PV开机",  update_pv_switch,                    1,      chk_pv_switch,                     1},
    {"接通负载",update_load_switch,                  1,      chk_load_switch,                   1}
};
/******************************************* "状态机"，进入状态执行策略逻辑前必须要执行的动作 ****************************************end**********************/
static int excute_action_steps(micr_action_and_check_t *action_steps, int *action_step_idx, int action_steps_max){
    int res = 0;
    if (action_steps == NULL) return res;

    static int idx = -1;
    static micr_action_and_check_t *p = NULL;
    if (p == NULL){
        p = action_steps;
    }
    else{ // 状态切换，idx = -1
        if (action_steps != p){
            p = action_steps;
            idx = -1;
        }
    }

    dev_info_all_t *_dev_info_all = get_dev_info_all_var();
    if(*action_step_idx < action_steps_max)
    {
        if (*action_step_idx != idx){
            idx = *action_step_idx;
            time(&startTime); // action execute time
        }
        micr_action_and_check_t *step = &action_steps[*action_step_idx];
        step->update_cb(_dev_info_all, step->update_param);
        ems_syslog(LOG_NOTICE, "Total steps: %d, current step :%d waiting %s response!!!", action_steps_max, *action_step_idx, step->desc);
        if(Relevant_data_refresh() == 0)//>>> 刷新数据源
        {
            int ret = step->condition_cb(_dev_info_all, step->condition_param);
            //That callback of condition return zero means this check passed and to do next step.
            if(ret == MICR_CONDITION_OK || ret == MICR_CONDITION_SKIP) 
            {
                if(ret == MICR_CONDITION_SKIP)
                    ems_syslog(LOG_NOTICE, "current action: %s, ignore step, invalid feedback data, go to step: [%d]!", step->desc, *action_step_idx);
                (*action_step_idx)++;
                ems_syslog(LOG_NOTICE, "current action: %s, go to step: [%d]...", step->desc, *action_step_idx);
            }
        }
    }else
        res = 1; //符合状态进入条件后，执行后续策略逻辑 return 1;
    return res;
}

static void inf_printf(void){

    dev_set_dev_tag_float(DEV_NO_EMS, TOTAL_PV_POWER, microgrid_data.pv_power);
    dev_set_dev_tag_float(DEV_NO_EMS, TOTAL_PCS_POWER, microgrid_data.pcs_power);
    dev_set_dev_tag_float(DEV_NO_EMS, AVER_SOC, microgrid_data.SOC_average);

    ems_syslog(LOG_NOTICE, "grid_power = %lf, pcs_power = %lf, pv_power = %lf, load_power = %lf, SOC_ceiling = %lf, SOC_average = %lf, SOC_floor = %lf,", microgrid_data.grid_power,
                microgrid_data.pcs_power, microgrid_data.pv_power, microgrid_data.load_power, microgrid_data.SOC_ceiling, microgrid_data.SOC_average, microgrid_data.SOC_floor);

    ems_syslog(LOG_NOTICE, "SOC_max_combin = %lf, SOC_min_combin = %lf, SOC_max_netdead = %lf,  SOC_min_netdead = %lf,  SOCmaxReturnDiff = %lf, SOCminReturnDiff = %lf ", microgrid_ctrl.SOC_max_combin,
                microgrid_ctrl.SOC_min_combin, microgrid_ctrl.SOC_max_netdead, microgrid_ctrl.SOC_min_netdead, microgrid_ctrl.SOCmaxReturnDiff, microgrid_ctrl.SOCminReturnDiff);

    ems_syslog(LOG_NOTICE, "pvMax = %lf, chargeMaxPower = %lf, dischargeMaxPower = %lf", microgrid_ctrl.pvMax,
                microgrid_ctrl.chargeMaxPower, microgrid_ctrl.dischargeMaxPower);

    ems_syslog(LOG_NOTICE, "en_anti_reflux = %d, anti_reflux = %lf, EnProtectTransf = %d, Pmlmax = %lf, K1 = %d, PmlmaxDiff = %lf", microgrid_ctrl.en_anti_reflux, 
                microgrid_ctrl.anti_reflux, microgrid_ctrl.EnProtectTransf, microgrid_ctrl.Pmlmax, microgrid_ctrl.K1, microgrid_ctrl.PmlmaxDiff);

    ems_syslog(LOG_NOTICE, "en_ac_d2c = %d, en_ac_c2d = %d", microgrid_ctrl.en_ac_d2c, microgrid_ctrl.en_ac_c2d);

    ems_syslog(LOG_NOTICE, "dg_rated_power = %lf, dg_boot_soc = %lf, DgDiff = %lf", microgrid_ctrl.dg_rated_power, 
                microgrid_ctrl.dg_boot_soc, microgrid_ctrl.DgDiff);
}

static int chargefull = 0, dischargefull = 0;
/*
static void ac_fush_battery_status_average(double SOC_min_combin, double SOC_max_combin) { // 平均值  刷新总的电池状态，状态：放空、可充可放、满充
    double soc_max_back = SOC_max_combin - microgrid_ctrl.SOCmaxReturnDiff;
    double soc_min_back = SOC_min_combin + microgrid_ctrl.SOCminReturnDiff;

    if (microgrid_data.SOC_average < soc_max_back) {
        chargefull = 0;
        microgrid_data.battery_sta = STATE_OR;
    } else if (microgrid_data.SOC_average >= SOC_max_combin || chargefull == 1) { // 95 90
        chargefull = 1; // 满充
        microgrid_data.battery_sta = STATE_FULL;
        ems_syslog(LOG_NOTICE, "Full charge, battery_sta: %d!!!", microgrid_data.battery_sta);
        return;
    }

    if (microgrid_data.SOC_average > soc_min_back) {
        dischargefull = 0;
        microgrid_data.battery_sta = STATE_OR;
    } else if (microgrid_data.SOC_average <= SOC_min_combin || dischargefull == 1) { // 5 10
        dischargefull = 1; // 放空
        microgrid_data.battery_sta = STATE_EMPTY;
        ems_syslog(LOG_NOTICE, "Empty discharge, battery_sta: %d!!!", microgrid_data.battery_sta);
    }
}
*/
static void ac_fush_battery_status_edge(double SOC_min_combin, double SOC_max_combin) { // 边缘值  刷新总的电池状态，状态：放空、可充可放、满充
    double soc_max_back = SOC_max_combin - microgrid_ctrl.SOCmaxReturnDiff;
    double soc_min_back = SOC_min_combin + microgrid_ctrl.SOCminReturnDiff;

    if (microgrid_data.SOC_ceiling < soc_max_back) {
        chargefull = 0;
        microgrid_data.battery_sta = STATE_OR;
    } else if (microgrid_data.SOC_ceiling >= SOC_max_combin || chargefull == 1) { // 95 90
        chargefull = 1; // 满充
        microgrid_data.battery_sta = STATE_FULL;
        ems_syslog(LOG_NOTICE, "Full charge, battery_sta: %d!!!", microgrid_data.battery_sta);
        return;
    }

    if (microgrid_data.SOC_floor > soc_min_back) {
        dischargefull = 0;
        microgrid_data.battery_sta = STATE_OR;
    } else if (microgrid_data.SOC_floor <= SOC_min_combin || dischargefull == 1) { // 5 10
        dischargefull = 1; // 放空
        microgrid_data.battery_sta = STATE_EMPTY;
        ems_syslog(LOG_NOTICE, "Empty discharge, battery_sta: %d!!!", microgrid_data.battery_sta);
    }
}

static void cabinet_fush_battery_status(double SOC_min, double SOC_max, cabinet_inside_t *cabinet_inside, battery_flag_t *battery_flag) { // 刷新每个柜子的电池状态，状态：放空、可充可放、满充
    double soc_max_back = SOC_max - microgrid_ctrl.SOCmaxReturnDiff;
    double soc_min_back = SOC_min + microgrid_ctrl.SOCminReturnDiff;
    double SOC = cabinet_inside->cab_data.SOC_average;

    if (SOC < soc_max_back) {
        battery_flag->chargefull = 0;
        cabinet_inside->cab_data.battery_sta = STATE_OR;
    } 
    else if (SOC >= SOC_max || battery_flag->chargefull == 1) {  // 95 90 
        battery_flag->chargefull = 1; // 满充
        cabinet_inside->cab_data.battery_sta = STATE_FULL;
        ems_syslog(LOG_NOTICE, "Cab %s, SOC:%lf Full charge, battery_sta: %d!!!", cabinet_inside->no, SOC, cabinet_inside->cab_data.battery_sta);
        return;
    }

    if (SOC > soc_min_back) {
        battery_flag->dischargefull = 0;
        cabinet_inside->cab_data.battery_sta = STATE_OR;
    } 
    else if (SOC <= SOC_min || battery_flag->dischargefull == 1) { // 5 10
        battery_flag->dischargefull = 1; // 放空
        cabinet_inside->cab_data.battery_sta = STATE_EMPTY;
        ems_syslog(LOG_NOTICE, "Cab %s, SOC:%lf Empty discharge, battery_sta: %d!!!", cabinet_inside->no, SOC, cabinet_inside->cab_data.battery_sta);
    }
}

// 根据SOC上下限回差，限制BMS的最大充放电能力，反馈给上层业务逻辑
// "上层"：逻辑上快满充、放空时，'预干预'最大放电功率限制，使调整更加平滑，当储能充满出现断崖式曲线时 防止 光伏来不及调节时导致逆流 "下层"：根据lc反馈的当前最大可充可放功率和柜子状态（是否可用）、柜内电池状态，再次进行功率限制
static int cabinet_accord_soc_cal_power(double SOC_min, double SOC_max, cabinet_inside_t *cabinet_inside, battery_flag_t *battery_flag) {
    
    double char_difference = 1, dischar_difference = 1;
    double SOC = cabinet_inside->cab_data.SOC_average;

    // 并离、离网的SOC回差，公用一套参数 "SOCmaxErr" "SOCminErr"
    cabinet_fush_battery_status(SOC_min, SOC_max, cabinet_inside, battery_flag);
    if (cabinet_inside->cab_data.battery_sta == STATE_EMPTY) {
        dischar_difference = 0;
    }
    else{
        if (SOC <= (SOC_min + microgrid_ctrl.SOCminReturnDiff)) { // 10 <-- 15 ~~'预干预'
            dischar_difference = (SOC - SOC_min) / microgrid_ctrl.SOCminReturnDiff;
            dischar_difference = dischar_difference < 0 ? 0 : dischar_difference;
            ems_syslog(LOG_NOTICE, "Cab %s, SOC过放保护:%lf difference: %f", cabinet_inside->no, cabinet_inside->cab_data.SOC_average, dischar_difference);
        } 
    }
    if (cabinet_inside->cab_data.battery_sta == STATE_FULL) {
        char_difference = 0;
    }
    else{
        if (SOC >= (SOC_max - microgrid_ctrl.SOCmaxReturnDiff)) { // 90 --> 95 ~~'预干预'
            char_difference = (SOC_max - SOC) / microgrid_ctrl.SOCmaxReturnDiff;
            char_difference = char_difference < 0 ? 0 : char_difference;
            ems_syslog(LOG_NOTICE, "Cab %s, SOC过充保护:%lf difference: %f", cabinet_inside->no, cabinet_inside->cab_data.SOC_average, char_difference);
        }
    }

    if (char_difference <= 0.01)  char_difference = 0; // 精度调整
    if (dischar_difference <= 0.01)  dischar_difference = 0;
#if 1
    // 在快"充满放空"时，SOC一般不是线性变化，而是以0.5或者1\1.5为单位减小 或 增加，防止PCS放电或者充电功率出现阶梯式曲线，此处模拟一个衰减过程，使PCS的充放电功率曲线过度更平滑
    double target_power = 0, tmp = 0;
    if (char_difference == 1 || char_difference == 0){
        cabinet_inside->cab_ctrl.pcs_charge_max_set = cabinet_inside->cab_ctrl.charge_max_cfg * char_difference;          // 上层'预干预'BMS最大充电功率限制
    }
    else{
        target_power = cabinet_inside->cab_ctrl.charge_max_cfg * char_difference;
        tmp = (target_power * 100 / 100 - cabinet_inside->cab_ctrl.pcs_charge_max_set) * SOC_KM;
        cabinet_inside->cab_ctrl.pcs_charge_max_set = tmp + cabinet_inside->cab_ctrl.pcs_charge_max_set;        
    }
    if (dischar_difference == 1 || dischar_difference == 0){
        cabinet_inside->cab_ctrl.pcs_discharge_max_set = cabinet_inside->cab_ctrl.discharge_max_cfg * dischar_difference; // 上层'预干预'BMS最大放电功率限制
    }
    else{
        target_power = cabinet_inside->cab_ctrl.discharge_max_cfg * dischar_difference;
        tmp = (target_power * 100 / 100 - cabinet_inside->cab_ctrl.pcs_discharge_max_set) * SOC_KM;
        cabinet_inside->cab_ctrl.pcs_discharge_max_set = tmp + cabinet_inside->cab_ctrl.pcs_discharge_max_set;    
    }
#endif
    ems_syslog(LOG_NOTICE, "Cab %s, pcs_charge_max_set: [%lf, %lf], pcs_discharge_max_set: [%lf, %lf]", cabinet_inside->no, 
                    cabinet_inside->cab_ctrl.pcs_charge_max_set, cabinet_inside->cab_ctrl.charge_max_cfg, 
                    cabinet_inside->cab_ctrl.pcs_discharge_max_set, cabinet_inside->cab_ctrl.discharge_max_cfg);
    return 0;
}

// 根据SOC上下限动态调整BMS的最大可充可放功率，进入回差范围后，根据SOC实际状态来设置衰减值，直至0功率，在解除满充、放空状态后，此值才可恢复
static void accord_soc_cal_supportpower(double SOC_min, double SOC_max){

    double charge_max_set = 0;
    double discharge_max_set = 0;
    dev_info_all_t *var = get_dev_info_all_var();

    // '预干预'最大放电功率限制
    for (int i = 0; i < var->cabinet_info.num; i++) {
        cabinet_inside_t *cabinet_inside = var->cabinet_info.cabinet_inside[i];
        cabinet_accord_soc_cal_power(SOC_min, SOC_max, cabinet_inside, &battery_flag[i]);
    }

    for (int i = 0; i < var->cabinet_info.num; i++) {
        cabinet_inside_t *cabinet_inside = var->cabinet_info.cabinet_inside[i];
        if (cabinet_inside->cab_data.en == 0 && cabinet_inside->cab_data.prohibited_char == 0) {
            charge_max_set += cabinet_inside->cab_ctrl.pcs_charge_max_set;
        }
        if (cabinet_inside->cab_data.en == 0 && cabinet_inside->cab_data.prohibited_dischar == 0) {
            discharge_max_set += cabinet_inside->cab_ctrl.pcs_discharge_max_set;
        }
    }
    microgrid_ctrl.charge_max_set = charge_max_set; // 储能实际能消纳的功率，一般指充电功率，放电功率暂时不用，防止光伏发电太大，储能消纳不了，导致逆流
    microgrid_ctrl.discharge_max_set = discharge_max_set;
    ems_syslog(LOG_NOTICE, "total charge_max_set: %lf discharge_max_set:  %lf", microgrid_ctrl.charge_max_set, microgrid_ctrl.discharge_max_set);

    ac_fush_battery_status_edge(SOC_min, SOC_max);
}

// 功率再分配：根据柜子实际是否可用、以及充满、放空状态，重新计算scale，进而计算每个柜子合理的功率分配值
static void cal_scale_and_set_power(dev_info_all_t *var) {
    double scale = 0;//static
    double pcs_discharge_max_set = 0, pcs_charge_max_set = 0;
    for (int i = 0; i < var->cabinet_info.num; i++) { // 功率再分配：根据柜子实际是否可用、以及充满、放空状态，重新计算scale，进而计算每个柜子合理的功率分配值
        cabinet_inside_t *cabinet_inside = var->cabinet_info.cabinet_inside[i];

        if (microgrid_ctrl.pcs_exp_power > 0){ // 放电
            if (cabinet_inside->cab_data.en == 0 && cabinet_inside->cab_data.prohibited_dischar == 0 && cabinet_inside->cab_data.battery_sta != STATE_EMPTY) {
                scale += cabinet_inside->cab_cfg.scale;
                pcs_discharge_max_set += cabinet_inside->cab_ctrl.pcs_discharge_max_set;
            }
        }else if (microgrid_ctrl.pcs_exp_power < 0){
            if (cabinet_inside->cab_data.en == 0 && cabinet_inside->cab_data.prohibited_char == 0 && cabinet_inside->cab_data.battery_sta != STATE_FULL) {
                scale += cabinet_inside->cab_cfg.scale;
                pcs_charge_max_set += cabinet_inside->cab_ctrl.pcs_charge_max_set;
            }
        }else{
            if (cabinet_inside->cab_data.en == 0) {
                scale += cabinet_inside->cab_cfg.scale;
            }           
        }       
    }
    ems_syslog(LOG_NOTICE, "real static scale sum: %lf, pcs_exp_power: %lf", scale, microgrid_ctrl.pcs_exp_power);

    if (scale == 0 || microgrid_ctrl.pcs_exp_power == 0){
        for (int i = 0 ; i < var->cabinet_info.num; i++){
            atomic_store(&var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power, 0);
        }
    }
    else{
#if 1
        for (int i = 0 ; i < var->cabinet_info.num; i++){ // ~~动态scale计算，在快"充满、放空"时，动态计算功率配比，预计在5~6min内可拉重合从机SOC曲线”~~
            cabinet_inside_t *cabinet_inside = var->cabinet_info.cabinet_inside[i];
            if (microgrid_ctrl.pcs_exp_power > 0){ // 放电
                if (cabinet_inside->cab_data.en == 0 && cabinet_inside->cab_data.prohibited_dischar == 0 && cabinet_inside->cab_data.battery_sta != STATE_EMPTY) {
                    cabinet_inside->cab_ctrl.scale = cabinet_inside->cab_ctrl.pcs_discharge_max_set/pcs_discharge_max_set;
                }
                else{
                    cabinet_inside->cab_ctrl.scale = 0;
                }
            }
            else if (microgrid_ctrl.pcs_exp_power < 0){
                if (cabinet_inside->cab_data.en == 0 && cabinet_inside->cab_data.prohibited_char == 0 && cabinet_inside->cab_data.battery_sta != STATE_FULL) {
                    cabinet_inside->cab_ctrl.scale = cabinet_inside->cab_ctrl.pcs_charge_max_set/pcs_charge_max_set;
                }
                else{
                    cabinet_inside->cab_ctrl.scale = 0;
                }
            }
        }
#endif
        for (int i = 0 ; i < var->cabinet_info.num; i++){
            cabinet_inside_t *cabinet_inside = var->cabinet_info.cabinet_inside[i];
            if (microgrid_ctrl.pcs_exp_power > 0){ // 放电
                if (cabinet_inside->cab_data.en == 0 && cabinet_inside->cab_data.prohibited_dischar == 0 && cabinet_inside->cab_data.battery_sta != STATE_EMPTY) {
                    atomic_store(&var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power, microgrid_ctrl.pcs_exp_power*var->cabinet_info.cabinet_inside[i]->cab_ctrl.scale);
                    LIMIT_RANGE(var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power, 0, var->cabinet_info.cabinet_inside[i]->cab_ctrl.discharge_max_cfg); // 
                }
                else{
                    atomic_store(&var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power, 0);
                }
                ems_syslog(LOG_NOTICE, "discharg cab no: %s, en: %d prohibited_dischar: %d dynamic scale: %f exp_power: %lf ", cabinet_inside->no, cabinet_inside->cab_data.en, cabinet_inside->cab_data.prohibited_dischar, var->cabinet_info.cabinet_inside[i]->cab_ctrl.scale, var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power);
            }
            else if (microgrid_ctrl.pcs_exp_power < 0){
                if (cabinet_inside->cab_data.en == 0 && cabinet_inside->cab_data.prohibited_char == 0 && cabinet_inside->cab_data.battery_sta != STATE_FULL) {
                    atomic_store(&var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power, microgrid_ctrl.pcs_exp_power*var->cabinet_info.cabinet_inside[i]->cab_ctrl.scale);
                    LIMIT_RANGE(var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power, var->cabinet_info.cabinet_inside[i]->cab_ctrl.charge_max_cfg, 0); //
                }
                else{
                    atomic_store(&var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power, 0);
                }
                ems_syslog(LOG_NOTICE, "charg cab no: %s, en: %d prohibited_char: %d dynamic scale: %f exp_power: %lf ", cabinet_inside->no, cabinet_inside->cab_data.en, cabinet_inside->cab_data.prohibited_char, var->cabinet_info.cabinet_inside[i]->cab_ctrl.scale, var->cabinet_info.cabinet_inside[i]->cab_ctrl.pcs_exp_power);
            }
        } 
    }   
}

static void ac_set_power(double pcs_power, double pv_power)
{
    dev_info_all_t *var = get_dev_info_all_var();
#if 1
    atomic_store(&microgrid_ctrl.pv_exp_power, pv_power);
    for (int i = 0 ; i < var->pv.num; i++){
        atomic_store(&var->pv.pv_param[i].info.pv_ctrl.power_set, pv_power*var->pv.pv_param[i].info.pv_cfg.scale);
        ems_syslog(LOG_NOTICE, "pv no: %s, scale: %f, power_set :%lf ", var->pv.pv_param[i].no, var->pv.pv_param[i].info.pv_cfg.scale, var->pv.pv_param[i].info.pv_ctrl.power_set); 
	}
#endif
    atomic_store(&microgrid_ctrl.pcs_exp_power, pcs_power);   // 刷新期望功率
    dev_set_dev_tag_float(DEV_NO_EMS, EXPECT_ACT_POWER, microgrid_ctrl.pcs_exp_power); // 主从模式，DOD保护在lc上，此处  期望功率=LC输入功率
    dev_set_dev_tag_float(DEV_NO_EMS, LOCAL_CTRL_POWER, microgrid_ctrl.pcs_exp_power);
    //
    cal_scale_and_set_power(var);
}

static void peak_cal_char_discharge_limit(double *charge_limit, double *discharge_limit, STRATAGY_TYPE func)
{
    *discharge_limit = microgrid_ctrl.discharge_max_set > microgrid_ctrl.dischargeMaxPower ? microgrid_ctrl.dischargeMaxPower : microgrid_ctrl.discharge_max_set;
    if (func == STRATAGY_TYPE_PERIOD_CTRL){
        *discharge_limit = *discharge_limit > microgrid_ctrl.plan_set_power ? microgrid_ctrl.plan_set_power : *discharge_limit;
    }
    *charge_limit = fabs(microgrid_ctrl.charge_max_set) > fabs(microgrid_ctrl.chargeMaxPower) ? fabs(microgrid_ctrl.chargeMaxPower) : fabs(microgrid_ctrl.charge_max_set);

    ems_syslog(LOG_NOTICE, "limit ~no symbol~ charge_limit: %lf, ~symbol~ discharge_limit: %lf", *charge_limit, *discharge_limit);
}

double last_pcs_exp_power = 0;

// pcs_exp_power 负充正放  算法周期，不建议低于500ms
static int ac_cal_peak_pv_power(double *pcs_exp_power, double *pv_target_power, int en_anti_reflux, int en_ac_d2c, STRATAGY_TYPE func)
{
    int dirction = 0;
    double _ptp = 0, _pcs_power = 0;
    dev_info_all_t *_dev_info_all = get_dev_info_all_var();
    double grid_act_power = _dev_info_all->meter_grid.meter_grid_param[0].info.meter_grid_data.act_power;
    double charge_limit = 0, discharge_limit = 0;

    // limit
    peak_cal_char_discharge_limit(&charge_limit, &discharge_limit, func);
#if 0
    if (en_anti_reflux){
        double exp_power = antiReflux(
            grid_act_power, 
            microgrid_ctrl.anti_reflux,  
            1, 
            microgrid_ctrl.pvMax + discharge_limit, 
            -microgrid_ctrl.anti_reflux,                         // 负载小于防逆流下限时，可返回负值，表示希望PCS多充一点电，保证防逆流余量 
            microgrid_data.pcs_power + microgrid_data.pv_power,  /* 放转充，储能充电功率一定低于光伏 算法自适应，*/
            0);
        ems_syslog(LOG_NOTICE, "antiReflux exp_power: %lf", exp_power);

        //exp_power = exp_power < 0 ? 0 : exp_power;//
        if (en_ac_d2c){ //>>开启放转充，默认关闭
            _ptp = exp_power + charge_limit; // 在储能充电过程中，'预干预'最大充电功率限制，使调整更加平滑，防止储能充满出现"断崖式"曲线，光伏来不及调节时导致逆流
        }
        else
            _ptp = exp_power;

        double tmp = 0 - (microgrid_data.pv_power - exp_power);
        if (tmp < 0 && en_ac_d2c == 1){
            _pcs_power = tmp;  // ~~ PCS充电功率，被动
            ems_syslog(LOG_NOTICE, "启动反流保护，储能充电~~, _pcs_power: %lf", _pcs_power); // 1. 若储能没有满功率充电，在光伏突升、负载突降时，储能可快速消纳逆流部分功率 2. 若储能已满功率充电，只能等待PV慢慢降了
            dirction = CHARGE_DIRECTION;
        }
        else if (tmp > 1){
            if (microgrid_ctrl.discharge_max_set == 0){ 
                _pcs_power = 0;
            }
            else{
                _pcs_power = tmp;
                ems_syslog(LOG_NOTICE, "1. 在光伏上升过程中/ 2.光线不好，光伏不够 -->电池补电~~, _pcs_power: %lf", _pcs_power);
                dirction = DISCHARGE_DIRECTION;
            }
        }               
        else
            _pcs_power = 0;
    }
    else{ // 注意：没有使能防逆流，意味着光伏要上网卖电 "一定不会使能放转充，没有意义，"，光伏直接设置最大 （此处无法核对"光伏上网卖电"还是"电池充电"哪个更符合经济利益，因此暂时不考虑，默认上网卖电）
        if(0 == microgrid_cfg.en_photovoltaic){ // 禁用光伏
            _pcs_power = microgrid_ctrl.plan_set_power;
        }
        else{
            _ptp = microgrid_ctrl.pvMax;

            // 算法忽略光伏的存在，即：逆流就降储能功率，直至PCS 0功率，电网大于0则增加PCS输出功率即可
            double exp_power = antiReflux(
                grid_act_power, 
                0,  
                1, 
                discharge_limit, 
                0, 
                microgrid_data.pcs_power, 
                0);
            exp_power = exp_power < 0 ? 0 : exp_power;

            if (exp_power == 0){
                _pcs_power = 0;
                ems_syslog(LOG_NOTICE, "光伏多余部分上网，pcs 设置0功率!!!, _pcs_power: %lf", _pcs_power);
            }
            else{
                if (microgrid_ctrl.discharge_max_set == 0){ 
                    _pcs_power = 0;
                }
                else{
                    _pcs_power = exp_power;
                    ems_syslog(LOG_NOTICE, "光伏不够, -->电池补电, _pcs_power: %lf", _pcs_power);
                    dirction = DISCHARGE_DIRECTION;
                }
            }
        }
    }
#endif
    last_pcs_exp_power = *pcs_exp_power; // 记录上次的值
    ems_syslog(LOG_NOTICE, "last_pcs_exp_power: %lf", last_pcs_exp_power);

    _pcs_power = *pcs_exp_power;
    if (grid_act_power > microgrid_ctrl.anti_reflux){
        _pcs_power = _pcs_power + (grid_act_power - microgrid_ctrl.anti_reflux);
        ems_syslog(LOG_NOTICE, "over, adjustment, pcs_exp_power: %lf", _pcs_power);
    }
    else if (grid_act_power < 0){
        _pcs_power += grid_act_power;
        ems_syslog(LOG_NOTICE, "under, adjustment, pcs_exp_power: %lf", _pcs_power);
    }
    else{
        // 不调整
        ems_syslog(LOG_NOTICE, "No adjustment, pcs_exp_power: %lf", _pcs_power);
    }

    // 动态调整策略周期，适配PCS启动慢的问题（客户PCS，写0功率自动关机，非0功率自动开机）
    if (last_pcs_exp_power == 0 && _pcs_power != 0){
        dev_set_dev_tag_int(DEV_NO_EMS, EMS_ADJPRERIOD, 60);  // 下个周期延时60秒，等待PCS启机
    }
    else{
        dev_set_dev_tag_int(DEV_NO_EMS, EMS_ADJPRERIOD, 5);
    }
    
    if (_pcs_power < 0){
        dirction = CHARGE_DIRECTION;
        LIMIT_RANGE(_pcs_power, (0-charge_limit), 0);
    }  
    if (_pcs_power > 0){
        dirction = DISCHARGE_DIRECTION;
        LIMIT_RANGE(_pcs_power, 0, discharge_limit); 
    }  

    if (dirction == CHARGE_DIRECTION){
        if (_pcs_power > 0) _pcs_power = 0; 
        _pcs_power = (_pcs_power < microgrid_ctrl.chargeMaxPower) ? microgrid_ctrl.chargeMaxPower : _pcs_power;
    }  
    if (dirction == DISCHARGE_DIRECTION){
        if (_pcs_power < 0) _pcs_power = 0;
        _pcs_power = (_pcs_power > microgrid_ctrl.dischargeMaxPower) ? microgrid_ctrl.dischargeMaxPower : _pcs_power;
        if (func == STRATAGY_TYPE_PERIOD_CTRL){
            _pcs_power = _pcs_power > microgrid_ctrl.plan_set_power ? microgrid_ctrl.plan_set_power : _pcs_power; // 削峰填谷，峰电-->使用计划放电功率，作为放电上限
        }
    }
    *pcs_exp_power = _pcs_power;
#if 1
    if (_ptp < 0) _ptp = 0;
    *pv_target_power = (_ptp > microgrid_ctrl.pvMax) ? microgrid_ctrl.pvMax : _ptp;
#endif
    ems_syslog(LOG_NOTICE, "pcs_exp_power: %lf, pv_target_power: %lf", *pcs_exp_power, *pv_target_power);
    return dirction;
}

static double custom_pcs_exp_power = 0;

static void ac_start_PeakElec_process(int en_ac_d2c, STRATAGY_TYPE func)
{
    //double pcs_exp_power = 0;
    double pv_target_power = 0; //光伏目标功率
    
    int _d2c = 1; //放转充标志， 1：使能 0：失能 默认1
    if (func == STRATAGY_TYPE_PERIOD_CTRL){
        _d2c = en_ac_d2c;
        ems_syslog(LOG_NOTICE, "削峰填谷，放电时间段(尖电)");
    }
    else if(func == STRATAGY_TYPE_PV_STORAGE){
        _d2c = 1;
        ems_syslog(LOG_NOTICE, "光伏消纳");
    }
    ac_cal_peak_pv_power(&custom_pcs_exp_power, &pv_target_power, microgrid_ctrl.en_anti_reflux, _d2c, func);

    double tmp = (pv_target_power * 100 / 100 - microgrid_ctrl.pv_exp_power) * PV_KM;
    if (fabs(tmp) < 1 && fabs(tmp) != 0){
        if(tmp > 0) tmp = 1;
        else  tmp = -1;
    }
    double _pv_exp_power = tmp + microgrid_ctrl.pv_exp_power;
    ems_syslog(LOG_NOTICE, "pv_target_power::: [%lf], _pv_exp_power %f = tmp %f + pv_exp_power %f", pv_target_power, _pv_exp_power, tmp, microgrid_ctrl.pv_exp_power);

    ac_set_power(custom_pcs_exp_power, _pv_exp_power);
}

static void vall_cal_char_discharge_limit(double *charge_limit, double *discharge_limit, STRATAGY_TYPE func)
{
    *charge_limit = microgrid_ctrl.charge_max_set < microgrid_ctrl.chargeMaxPower ? microgrid_ctrl.chargeMaxPower: microgrid_ctrl.charge_max_set;
    if (func == STRATAGY_TYPE_PERIOD_CTRL){
        *charge_limit = *charge_limit < microgrid_ctrl.plan_set_power ? microgrid_ctrl.plan_set_power : *charge_limit;
    }

    *discharge_limit = microgrid_ctrl.discharge_max_set > microgrid_ctrl.dischargeMaxPower ? microgrid_ctrl.dischargeMaxPower : microgrid_ctrl.discharge_max_set;
    ems_syslog(LOG_NOTICE, "limit ~symbol~ charge_limit: %lf, ~symbol~ discharge_limit: %lf", *charge_limit, *discharge_limit);
}

static int ac_cal_vall_pv_power(double *pcs_exp_power, double *pv_target_power, int EnProtectTransf, int en_anti_reflux, int en_ac_c2d, STRATAGY_TYPE func)
{
    int dirction = 0;
    double _ptp = 0, _pcs_power = 0;
    dev_info_all_t *_dev_info_all = get_dev_info_all_var();
    double grid_act_power = _dev_info_all->meter_grid.meter_grid_param[0].info.meter_grid_data.act_power;
    double charge_limit = 0, discharge_limit = 0;

    // limit
    vall_cal_char_discharge_limit(&charge_limit, &discharge_limit, func);

    if (EnProtectTransf){
        double _Pmlmax = (microgrid_ctrl.Pmlmax / 1.0) * ((double)microgrid_ctrl.K1 / 100.0);
        double _exp_power = xl_antiReflux(  // 变压器保护，在保证不超变压器容量的前提下，尽可能靠近充电功率上限，PCS充电功率，主动
            grid_act_power, 
            _Pmlmax,  
            1, 
            discharge_limit, 
            charge_limit, 
            microgrid_data.pcs_power, 
            _Pmlmax,
            0);
        ems_syslog(LOG_NOTICE, "xl_antiReflux _exp_power: %lf", _exp_power);  

        if (en_ac_c2d == 0) _exp_power = _exp_power > 0 ? 0 : _exp_power;//
        if (func == STRATAGY_TYPE_PERIOD_CTRL){
            _exp_power = _exp_power < microgrid_ctrl.plan_set_power ? microgrid_ctrl.plan_set_power : _exp_power; // 削峰填谷，谷电-->使用计划充电功率，作为充电上限
        }
        _pcs_power = _exp_power;
        dirction = _exp_power > 0 ? DISCHARGE_DIRECTION : CHARGE_DIRECTION;
    }
    else{
        _pcs_power = charge_limit;
        dirction = CHARGE_DIRECTION;
    }

    if (en_anti_reflux){
        double exp_power = antiReflux(
            grid_act_power, 
            microgrid_ctrl.anti_reflux,  
            1, 
            microgrid_ctrl.pvMax + discharge_limit, 
            -microgrid_ctrl.anti_reflux,                         // 负载小于防逆流下限时，可返回负值，表示希望光伏少发一点电，保证防逆流余量
            microgrid_data.pcs_power + microgrid_data.pv_power,  /* 如果功率低于0 说明电网在补电 算法自适应，刚好减掉电网上补充的部分，算出实际负载需求 */
            0);
        ems_syslog(LOG_NOTICE, "antiReflux exp_power: %lf", exp_power);

        if (microgrid_data.pcs_power > 0)
            _ptp = exp_power;
        else{
            _ptp = exp_power + fabs(microgrid_data.pcs_power);
        }
    }      
    else{
        _ptp = microgrid_ctrl.pvMax;
    }

    if (dirction == CHARGE_DIRECTION){
        if (_pcs_power > 0) _pcs_power = 0;
        _pcs_power = (_pcs_power < microgrid_ctrl.chargeMaxPower) ? microgrid_ctrl.chargeMaxPower : _pcs_power;
    }  
    if (dirction == DISCHARGE_DIRECTION){
        if (_pcs_power < 0) _pcs_power = 0;
        _pcs_power = (_pcs_power > microgrid_ctrl.dischargeMaxPower) ? microgrid_ctrl.dischargeMaxPower : _pcs_power;
    }
    *pcs_exp_power = _pcs_power;
#if 1
    if (_ptp < 0) _ptp = 0;
    *pv_target_power = _ptp > microgrid_ctrl.pvMax ? microgrid_ctrl.pvMax : _ptp;
#endif
    ems_syslog(LOG_NOTICE, "pcs_exp_power: %lf, pv_target_power: %lf", *pcs_exp_power, *pv_target_power);
    return dirction;
}

static void ac_start_VallElec_process(STRATAGY_TYPE func)
{
    double pcs_exp_power = 0;
    double pv_target_power = 0; //光伏目标功率
    double tmp_power = 0;

    if (func == STRATAGY_TYPE_PERIOD_CTRL){
        ems_syslog(LOG_NOTICE, "削峰填谷，充电时间段(谷电)");
    }
    else if(func == STRATAGY_TYPE_STANDBY){
        ems_syslog(LOG_NOTICE, "应急备电");
    }

    ac_cal_vall_pv_power(&pcs_exp_power, &pv_target_power, microgrid_ctrl.EnProtectTransf, microgrid_ctrl.en_anti_reflux, microgrid_ctrl.en_ac_c2d, func);
    
    tmp_power = (pv_target_power * 100 / 100 - microgrid_ctrl.pv_exp_power) * PV_KM;
    if (fabs(tmp_power) < 1 && fabs(tmp_power) != 0){
        if(tmp_power > 0) tmp_power = 1;
        else  tmp_power = -1;
    }
    double power = tmp_power + microgrid_ctrl.pv_exp_power;
    ems_syslog(LOG_NOTICE, "pv_target_power: [%lf], power %f = tmp_power %f + pv_exp_power %f", pv_target_power, power, tmp_power, microgrid_ctrl.pv_exp_power);
    
    ac_set_power(pcs_exp_power, power);
}

// pcs_exp_power 负充正放，平电禁止储能放电
static int ac_cal_falt_pv_power(double *pcs_exp_power, double *pv_target_power, int en_anti_reflux)
{
    int dirction = 0;
    double _ptp = 0, _pcs_power = 0;
    dev_info_all_t *_dev_info_all = get_dev_info_all_var();
    double grid_act_power = _dev_info_all->meter_grid.meter_grid_param[0].info.meter_grid_data.act_power;

    // limit
    double charge_limit = fabs(microgrid_ctrl.charge_max_set) > fabs(microgrid_ctrl.chargeMaxPower) ? fabs(microgrid_ctrl.chargeMaxPower) : fabs(microgrid_ctrl.charge_max_set);
    ems_syslog(LOG_NOTICE, "limit ~no symbol~ charge_limit: %lf ", charge_limit);

    if (en_anti_reflux){
        if(0 == microgrid_cfg.en_photovoltaic){ // 禁用光伏
            _pcs_power = 0;
        }
        else{
            double exp_power = antiReflux(
                grid_act_power, 
                microgrid_ctrl.anti_reflux,  
                1, 
                microgrid_ctrl.pvMax, 
                -microgrid_ctrl.anti_reflux,                        // 负载小于防逆流下限时，可返回负值，表示希望储能多充一点电，保证防逆流余量 
                microgrid_data.pcs_power + microgrid_data.pv_power, /* 充电，储能充电功率一定低于光伏 算法自适应，*/
                0);
            ems_syslog(LOG_NOTICE, "antiReflux exp_power: %lf", exp_power);

            //exp_power = exp_power < 0 ? 0 : exp_power;// 
            _ptp = exp_power + charge_limit;  

            double tmp = 0 - (microgrid_data.pv_power - exp_power);
            if (tmp < 0){
                _pcs_power = tmp; // ~~ PCS充电功率，被动
                ems_syslog(LOG_NOTICE, "启动反流保护，储能充电~~, _pcs_power: %lf", _pcs_power); // 1. 若储能没有满功率充电，在光伏突升、负载突降时，储能可快速消纳逆流部分的功率 2. 若储能已满功率充电，只能等待PV慢慢降了
                dirction = CHARGE_DIRECTION;
            }
            else {
                _pcs_power = 0;
                ems_syslog(LOG_NOTICE, "1. 在光伏上升过程中/ 2.光线不好，光伏不够 -->电池静置，市电补充~~, _pcs_power: %lf", _pcs_power);
            }
        }             
    }
    else{ // 注意：没有使能防逆流，意味着光伏要上网卖电, 储能不充不放，光伏直接设置最大
        _ptp = microgrid_ctrl.pvMax;
        _pcs_power = 0;
        ems_syslog(LOG_NOTICE, "光伏多余部分上网，pcs 设置0功率，储能不充不放!!!, _pcs_power: %lf", _pcs_power);
    }

    if (dirction == CHARGE_DIRECTION){
        if (_pcs_power > 0) _pcs_power = 0;
        _pcs_power = (_pcs_power < microgrid_ctrl.chargeMaxPower) ? microgrid_ctrl.chargeMaxPower : _pcs_power;
    }  
    if (dirction == DISCHARGE_DIRECTION){
        if (_pcs_power < 0) _pcs_power = 0;
        _pcs_power = (_pcs_power > microgrid_ctrl.dischargeMaxPower) ? microgrid_ctrl.dischargeMaxPower : _pcs_power;
    }
    *pcs_exp_power = _pcs_power;
#if 1
    if (_ptp < 0) _ptp = 0;
    *pv_target_power = (_ptp > microgrid_ctrl.pvMax) ? microgrid_ctrl.pvMax : _ptp;
#endif
    ems_syslog(LOG_NOTICE, "pcs_exp_power: %lf, pv_target_power: %lf", *pcs_exp_power, *pv_target_power);
    return dirction;
}

static void ac_start_FaltElec_process(void)
{
    double pcs_exp_power = 0;
    double pv_target_power = 0; //光伏目标功率
    double tmp_power = 0;

    ems_syslog(LOG_NOTICE, "削峰填谷，静置时间段(平电)");
    ac_cal_falt_pv_power(&pcs_exp_power, &pv_target_power, microgrid_ctrl.en_anti_reflux);

    tmp_power = (pv_target_power * 100 / 100 - microgrid_ctrl.pv_exp_power) * 0.8;
    if (fabs(tmp_power) < 1 && fabs(tmp_power) != 0)
    {
        if(tmp_power > 0) tmp_power = 1;
        else  tmp_power = -1;
    }
    double power = tmp_power + microgrid_ctrl.pv_exp_power;
    ems_syslog(LOG_NOTICE, "pv_target_power: [%lf], power %f = tmp_power %f + pv_exp_power %f", pv_target_power, power, tmp_power, microgrid_ctrl.pv_exp_power);
    
    ac_set_power(pcs_exp_power, power);
}

static void unknow_status_standing(void){
    double pcs_exp_power = 0;
    double pv_target_power = 0; //光伏目标功率

    ems_syslog(LOG_WARNING, "设置PCS，光伏0功率!!!");
    ac_set_power(pcs_exp_power, pv_target_power);
}

int last_paln_statu = -1;
static void ac_Cutpeak_Fillvalley(void)
{
#if 0
    if(0 == microgrid_cfg.en_photovoltaic)   // 光伏失能，返回，设置PCS，光伏0功率
    {
        ems_syslog(LOG_ERR, "当前AC微网模式，必须使能光伏!!! set_power pcs and pv = 0...");
        unknow_status_standing();
        return;
    }
#endif
// 站在交流母线，系统层次上理解算法参数
// 注意：~~~~~~~~ 不使能光伏时，算法兼容，仍可运行削峰填谷策略，pvMax 需设置0 ~~~~~~~~
    switch(microgrid_ctrl.plan_statu) 
    {
        case DISCHARGE_DIRECTION:  /*峰电*/
            ac_start_PeakElec_process(microgrid_ctrl.en_ac_d2c, STRATAGY_TYPE_PERIOD_CTRL);
            break;
        case CHARGE_DIRECTION:     /*谷电*/
            ac_start_VallElec_process(STRATAGY_TYPE_PERIOD_CTRL);
            break;
        case ENERGY_DEFAULT:       /*平电*/
            ac_start_FaltElec_process();
            break;
        default:
            unknow_status_standing(); //you guess...
            break;
    }
    //***** */
    if (microgrid_ctrl.plan_statu != last_paln_statu){
        last_paln_statu = microgrid_ctrl.plan_statu;
        chargefull = 0; dischargefull = 0;
        memset(battery_flag, 0, sizeof(battery_flag));
    }
}

//光伏消纳，一定要开启防逆流，否则此功能无意义
static void ac_Photovol_Absorp(void)
{
    if(0 == microgrid_cfg.en_photovoltaic)
    {
        ems_syslog(LOG_ERR, "当前AC微网模式，必须使能光伏!!! set_power pcs and pv = 0...");
        unknow_status_standing();
        return;
    }
    dev_info_all_t *var = get_dev_info_all_var();
    update_pcs_switch(var, 1);
    ac_start_PeakElec_process(1, STRATAGY_TYPE_PV_STORAGE);
}

static void ac_Meet_Standby(void)
{
    if(0 == microgrid_cfg.en_photovoltaic)
    {
        ems_syslog(LOG_ERR, "当前AC微网模式，必须使能光伏!!! set_power pcs and pv = 0...");
        unknow_status_standing();
        return;
    }

    ac_start_VallElec_process(STRATAGY_TYPE_STANDBY);
}

static int start_ac_connect_grid_strategy(void)
{
    inf_printf();
    accord_soc_cal_supportpower(microgrid_ctrl.SOC_min_combin, microgrid_ctrl.SOC_max_combin);

    switch(microgrid_ctrl.choose_func)
    {
        case STRATAGY_TYPE_PERIOD_CTRL:  /*削峰填谷模式*/
            ac_Cutpeak_Fillvalley();
        break;
        case STRATAGY_TYPE_DEMAND_FIXED: /*变压器增容*/
            return 0;
            // 
        break;
        case STRATAGY_TYPE_PV_STORAGE:  /*光伏消纳*/
            ac_Photovol_Absorp();
        break;
        case STRATAGY_TYPE_STANDBY:     /*应急备电*/
            ac_Meet_Standby();
        break;
        default:
        break;
    }

    return 0;
}

static int ac_cal_off_pv_power(double *pcs_exp_power, double *pv_target_power)
{
    int dirction = 0;
    double _ptp = 0;
    dev_info_all_t *var = get_dev_info_all_var();
    struct _dido_t * _dido = &var->dido.dido_param[0];

    _ptp = fabs(microgrid_ctrl.charge_max_set) > microgrid_ctrl.pvMax ? microgrid_ctrl.pvMax : fabs(microgrid_ctrl.charge_max_set); // PV容量可能过大，加以限制

    if (microgrid_data.battery_sta == STATE_EMPTY || (microgrid_cfg.en_diesel_generator == 1 && microgrid_data.SOC_floor < microgrid_ctrl.dg_boot_soc)) {
#if 1
        if (microgrid_cfg.en_diesel_generator){  // 1.使能柴发则开启柴发，柴发启动后，状态机自动进入柴发充电逻辑
#if 1
            _dido->info.dido_ctrl.DG_ctrl = 1;
            ems_syslog(LOG_NOTICE, "启动柴发");
#endif
#if 0
            bit_set(microgrid_ctrl.cut_flag, BIT_STATE_CF_CONNECT_GRID, 1);
			ems_syslog(LOG_NOTICE, "置位柴发并网标识");
#endif
        }       
        else if (microgrid_cfg.en_lcb){
            _dido->info.dido_ctrl.lcb_ctrl = 0;  // 2.使能负载断路器，则断开负载
        } 
        else{
            microgrid_ctrl.onoff = 0;            // 保护电池，PCS关机，系统将无法运行于离网模式，需要切手动模式对储能充电
        }
#endif
    }
    else if (microgrid_data.battery_sta == STATE_OR)
    {
        if (microgrid_cfg.en_lcb){
            _dido->info.dido_ctrl.lcb_ctrl = 1; // 接通负载
        }
    }
    else if (microgrid_data.battery_sta == STATE_FULL) {
        _ptp = 0; // 储能充满，光伏设置0功率，储能单独带载
    }

    *pv_target_power = (_ptp > microgrid_ctrl.pvMax) ? microgrid_ctrl.pvMax : _ptp;
    if (*pv_target_power < 0) *pv_target_power = 0;

    return dirction;
}

static void ac_start_off_process(void)
{
    double pcs_exp_power = 0;
    double pv_target_power = 0; //光伏目标功率
    double tmp_power = 0;
    
    ems_syslog(LOG_NOTICE, "光储离网");
    ac_cal_off_pv_power(&pcs_exp_power, &pv_target_power);

    tmp_power = (pv_target_power * 100 / 100 - microgrid_ctrl.pv_exp_power) * PV_KM;
    if (fabs(tmp_power) < 1 && fabs(tmp_power) != 0){
        if(tmp_power > 0) tmp_power = 1;
        else  tmp_power = -1;
    }
    double power = tmp_power + microgrid_ctrl.pv_exp_power;
    ems_syslog(LOG_NOTICE, "pv_target_power: [%lf], power %f = tmp_power %f + pv_exp_power %f", pv_target_power, power, tmp_power, microgrid_ctrl.pv_exp_power);

    ac_set_power(pcs_exp_power, power);
}

static void start_ac_off_grid_strategy(void)
{
    inf_printf();
    accord_soc_cal_supportpower(microgrid_ctrl.SOC_min_netdead, microgrid_ctrl.SOC_max_netdead);
    ac_start_off_process();
}

static RELEVANCE_STATE ac_init_init(RELEVANCE_STATE last_state, RELEVANCE_STATE state)
{
    micr_action_and_check_t *action_steps = init_actions;
    int action_steps_max = ARRAY_SIZE(init_actions);

    ems_syslog(LOG_NOTICE, "ac_init actions...");
    return excute_action_steps(action_steps, &ac_state_machine.state[state].action_step_idx, action_steps_max);
}

static RELEVANCE_STATE ac_init_handover_detect(RELEVANCE_STATE state)
{
    if (microgrid_cfg.en_diesel_generator == 0 && \
        microgrid_cfg.en_photovoltaic == 0 && \
        microgrid_cfg.en_mains == 0 && \
        microgrid_cfg.en_charging_pile == 0 && \
        microgrid_cfg.en_esc == 0 && \
        microgrid_cfg.en_sts == 0 && \
        microgrid_cfg.en_icb == 0 && \
        microgrid_cfg.en_lcb == 0 && \
        microgrid_cfg.en_ats == 0)
    return state;
    ems_syslog(LOG_NOTICE, "ac_init_handover_detect");
    micr_condition_and_check_t *micr_condition_and_check = init_handover_detect;
    int size = ARRAY_SIZE(init_handover_detect);
    return micr_condition_check(micr_condition_and_check, size, state);
}

static int ac_init_behaviour_func(RELEVANCE_STATE state_self)
{
    bit_set(microgrid_ctrl.cut_flag, BIT_STATE_INIT, 0); // 
    sleep(1);
    Relevant_data_refresh();
    dev_info_all_t *var = get_dev_info_all_var();
    {
        ac_set_power(0, 0);
        microgrid_ctrl.onoff = 0;
        for(int index = 0; index < var->cabinet_info.num; index++)
        {
            atomic_store(&var->cabinet_info.cabinet_inside[index]->cab_ctrl.onoff, 0);
        }
        if (microgrid_cfg.en_photovoltaic)
            microgrid_ctrl.pv_exp_onoff = 0;
    }
    // 此处可添加一些定制逻辑，用于定义进入初始状态，所需要做的动作
#if 0









#endif
    return 0;
}

static RELEVANCE_STATE ac_await_init(RELEVANCE_STATE last_state, RELEVANCE_STATE state)
{
    micr_action_and_check_t *action_steps = await_init_actions;
    int action_steps_max = 0;
    if (microgrid_cfg.en_sts){
        action_steps = await_init_actions_sts;
        action_steps_max = 0;
    }else{
        action_steps = await_init_actions;
        action_steps_max = ARRAY_SIZE(await_init_actions);
    }
    ems_syslog(LOG_NOTICE, "ac_await actions...");
    return excute_action_steps(action_steps, &ac_state_machine.state[state].action_step_idx, action_steps_max);
}

static RELEVANCE_STATE ac_await_handover_detect(RELEVANCE_STATE state)
{
    ems_syslog(LOG_NOTICE, "ac_await_handover_detect");
    micr_condition_and_check_t *micr_condition_and_check = await_handover_detect;
    int size = ARRAY_SIZE(await_handover_detect);
    return micr_condition_check(micr_condition_and_check, size, state);
}

static int ac_await_behaviour_func(RELEVANCE_STATE state_self)
{
    bit_set(microgrid_ctrl.cut_flag, BIT_STATE_AWAIT, 0); // 
    sleep(1);
    Relevant_data_refresh();
    dev_info_all_t *var = get_dev_info_all_var();
    {
        ac_set_power(0, 0);
        microgrid_ctrl.onoff = 0;
        for(int index = 0; index < var->cabinet_info.num; index++)
        {
            atomic_store(&var->cabinet_info.cabinet_inside[index]->cab_ctrl.onoff, 0);
        }
        if (microgrid_cfg.en_photovoltaic)
            microgrid_ctrl.pv_exp_onoff = 0;
    }
	// 此处可添加一些定制逻辑，用于定义进入待机状态，所需要做的动作
#if 0









#endif

    return 0;
}

static RELEVANCE_STATE ac_abnormal_init(RELEVANCE_STATE last_state, RELEVANCE_STATE state)
{
    micr_action_and_check_t *action_steps = abnormal_init_actions;
    int action_steps_max = ARRAY_SIZE(abnormal_init_actions);
    ems_syslog(LOG_NOTICE, "abnormal_init_actions...");
    return excute_action_steps(action_steps, &ac_state_machine.state[state].action_step_idx, action_steps_max);
}

static RELEVANCE_STATE ac_abnormal_handover_detect(RELEVANCE_STATE state)
{
    int find = 0;
    dev_info_all_t *_dev_info_all = get_dev_info_all_var();
    if(dev_get_dev_tag_int(DEV_NO_EMS, SYSTEM_STATUS)){ 
        return state; 
    }
    for (int i = 0 ; i < _dev_info_all->cabinet_info.num; i++) // 系统状态运行正常，且有一个柜子可以用，就可以检查切出
	{
	    cabinet_inside_t *_cabinet_inside = _dev_info_all->cabinet_info.cabinet_inside[i];
        if (_cabinet_inside->cab_data.en == 0){
            find = 1; 
            break;
        }
	}
    if (find){
        ems_syslog(LOG_NOTICE, "ac_abnormal_handover_detect");
        micr_condition_and_check_t *micr_condition_and_check = abnormal_handover_detect;
        int size = ARRAY_SIZE(abnormal_handover_detect);
        return micr_condition_check(micr_condition_and_check, size, state);
    }else
        return state;
}

static int ac_abnormal_behaviour_func(RELEVANCE_STATE state_self)
{
    bit_clean(microgrid_ctrl.cut_flag);
    //bit_set(microgrid_ctrl.cut_flag, BIT_STATE_ABNORMAL, 0); //
    sleep(1);
    Relevant_data_refresh();
    dev_info_all_t *var = get_dev_info_all_var();
    {
        ac_set_power(0, 0);
        int index = 0;
        microgrid_ctrl.onoff = 0;
        for(index = 0; index < var->cabinet_info.num; index++)
        {
            atomic_store(&var->cabinet_info.cabinet_inside[index]->cab_ctrl.onoff, 0);
        }
        if (microgrid_cfg.en_photovoltaic)
            microgrid_ctrl.pv_exp_onoff = 0;
    }
	// 此处可添加一些定制逻辑，用于定义进入异常状态，所需要做的动作
#if 0









#endif
	
    return 0;
}

static RELEVANCE_STATE ac_grid_init(RELEVANCE_STATE last_state, RELEVANCE_STATE state)
{
    int action_steps_max = 0;
    micr_action_and_check_t *action_steps = NULL;
    if (microgrid_cfg.en_sts){
        action_steps = grid_init_actions_sts;
        action_steps_max = ARRAY_SIZE(grid_init_actions_sts);
    }
    else{
        action_steps = grid_init_actions;
        action_steps_max = ARRAY_SIZE(grid_init_actions);
    }
    ems_syslog(LOG_NOTICE, "grid_init actions...");
    return excute_action_steps(action_steps, &ac_state_machine.state[state].action_step_idx, action_steps_max);
}

static RELEVANCE_STATE ac_grid_handover_detect(RELEVANCE_STATE state)
{
    ems_syslog(LOG_NOTICE, "ac_grid_handover_detect");
    micr_condition_and_check_t *micr_condition_and_check = grid_handover_detect;
    int size = ARRAY_SIZE(grid_handover_detect);
    return micr_condition_check(micr_condition_and_check, size, state);
}

static int ac_grid_behaviour_func(RELEVANCE_STATE state_self)
{
    bit_set(microgrid_ctrl.cut_flag, BIT_STATE_CONNECT_GRID, 0); //
    ems_syslog(LOG_NOTICE, "ac_grid_behaviour_func");

    int sleep_time = dev_get_dev_tag_int(DEV_NO_EMS, EMS_ADJPRERIOD); 
    usleep(1000 * 1000 * sleep_time);  // 由于数采频率及电网表自身采集效率，建议算法周期1秒，电网表、PCS、光伏跟功率相关的poll采集周期500ms.算法周期太短，可能会出现数据刷新不及时导致超调问题

    if(Relevant_data_refresh()){
        return 0;
    }

    if (microgrid_data.grid_statu == 1)
        start_ac_connect_grid_strategy();
    else
        ems_syslog(LOG_ERR, "pcs is not Grid status, waiting...");
    return 0;
}


static RELEVANCE_STATE ac_off_grid_init(RELEVANCE_STATE last_state, RELEVANCE_STATE state)
{
    int action_steps_max = 0;
    micr_action_and_check_t *action_steps = NULL;
    if (microgrid_cfg.en_sts){
        action_steps = offgrid_init_actions_sts;
        action_steps_max = ARRAY_SIZE(offgrid_init_actions_sts);
    }
    else{
        action_steps = offgrid_init_actions;
        action_steps_max = ARRAY_SIZE(offgrid_init_actions);
    }
    ems_syslog(LOG_NOTICE, "off_grid_init actions...");
    return excute_action_steps(action_steps, &ac_state_machine.state[state].action_step_idx, action_steps_max);
}

static RELEVANCE_STATE ac_off_grid_handover_detect(RELEVANCE_STATE state)
{
    ems_syslog(LOG_NOTICE, "ac_off_grid_handover_detect");
    micr_condition_and_check_t *micr_condition_and_check = offgrid_handover_detect;
    int size = ARRAY_SIZE(offgrid_handover_detect);
    return micr_condition_check(micr_condition_and_check, size, state);
}

static int ac_off_grid_behaviour_func(RELEVANCE_STATE state_self)
{
    bit_set(microgrid_ctrl.cut_flag, BIT_STATE_OFF_GRID, 0); //
    ems_syslog(LOG_NOTICE, "ac_off_grid_behaviour_func");
    usleep(1000 * 1000); 

    if(Relevant_data_refresh()){
        return 0;
    }

    if (microgrid_data.offgrid_statu == 1)
        start_ac_off_grid_strategy();
    else
        ems_syslog(LOG_ERR, "pcs is not offgrid status, waiting...");
    return 0;
}

static RELEVANCE_STATE ac_cfgrid_init(RELEVANCE_STATE last_state, RELEVANCE_STATE state)
{
    int action_steps_max = 0;
    micr_action_and_check_t *action_steps = NULL;
    if (microgrid_cfg.en_sts){
        action_steps = cf_grid_init_actions_sts;
        action_steps_max = ARRAY_SIZE(cf_grid_init_actions_sts);
    }
    else{
        action_steps = cf_grid_init_actions;
        action_steps_max = ARRAY_SIZE(cf_grid_init_actions);
    }
    ems_syslog(LOG_NOTICE, "cfgrid_init actions...");
    return excute_action_steps(action_steps, &ac_state_machine.state[state].action_step_idx, action_steps_max);
}

static RELEVANCE_STATE ac_cfgrid_handover_detect(RELEVANCE_STATE state)
{
    ems_syslog(LOG_NOTICE, "ac_cfgrid_handover_detect");
    micr_condition_and_check_t *micr_condition_and_check = cf_grid_handover_detect;
    int size = ARRAY_SIZE(cf_grid_handover_detect);
    return micr_condition_check(micr_condition_and_check, size, state);
}

static int ac_cal_cf_pv_power(double *pcs_exp_power, double *pv_target_power)
{
    int dirction = 0;
    double _ptp = 0;
    dev_info_all_t *_dev_info_all = get_dev_info_all_var();
    double cf_act_power = _dev_info_all->meter_dg.meter_dg_param[0].info.meter_dg_data.act_power;

    double char_limit = microgrid_ctrl.charge_max_set;
    double _Pmlmax = microgrid_ctrl.dg_rated_power;
    double _exp_power = xl_antiReflux(  // 柴发保护，在保证不超柴发额定功率的前提下，尽可能靠近充电功率上限
        cf_act_power, 
        _Pmlmax,  
        1, 
        0, 
        char_limit, 
        microgrid_data.pcs_power, 
        _Pmlmax - microgrid_ctrl.DgDiff,
        0);
    ems_syslog(LOG_NOTICE, "xl_antiReflux _exp_power: %lf", _exp_power);    
    dirction = CHARGE_DIRECTION;
    *pcs_exp_power = _exp_power; // ~~ PCS充电功率，主动

    if (dirction == CHARGE_DIRECTION){
        *pcs_exp_power = *pcs_exp_power > 0 ? 0 : *pcs_exp_power;
    }  
    if (dirction == DISCHARGE_DIRECTION){
        *pcs_exp_power = *pcs_exp_power < 0 ? 0 : *pcs_exp_power;
    }

    *pv_target_power = _ptp > microgrid_ctrl.pvMax ? microgrid_ctrl.pvMax : _ptp;
    if (*pv_target_power < 0) *pv_target_power = 0;

    return dirction;
}

static void ac_start_cf_process(void)
{
    double pcs_exp_power = 0;
    double pv_target_power = 0; //光伏目标功率
    double tmp_power = 0;
    dev_info_all_t *var = get_dev_info_all_var();
    struct _dido_t * _dido = &var->dido.dido_param[0];
    
    ac_cal_cf_pv_power(&pcs_exp_power, &pv_target_power);
    
    tmp_power = (pv_target_power * 100 / 100 - microgrid_ctrl.pv_exp_power) * PV_KM;
    if (fabs(tmp_power) < 1 && fabs(tmp_power) != 0){
        if(tmp_power > 0) tmp_power = 1;
        else  tmp_power = -1;
    }
    double power = tmp_power + microgrid_ctrl.pv_exp_power;
    ems_syslog(LOG_NOTICE, "pv_target_power: [%lf], power %f = tmp_power %f + pv_exp_power %f", pv_target_power, power, tmp_power, microgrid_ctrl.pv_exp_power);
    
    if (microgrid_data.battery_sta == STATE_FULL){
        if (microgrid_cfg.en_diesel_generator){  // 储能满充后，关闭柴发，进入离网状态
#if 1
            _dido->info.dido_ctrl.DG_ctrl = 0;
			ems_syslog(LOG_NOTICE, "关闭柴发");
#endif
#if 0
            bit_set(microgrid_ctrl.cut_flag, BIT_STATE_OFF_GRID, 1); // 适用于无STS和并离网断路器时，需在离网和柴发并网之前切换的场景
			ems_syslog(LOG_NOTICE, "置位离网标识");
#endif
        } 
    }
    ac_set_power(pcs_exp_power, power);
}

// 柴发应急备电
static int ac_cfgrid_behaviour_func(RELEVANCE_STATE state_self)
{
    bit_set(microgrid_ctrl.cut_flag, BIT_STATE_CF_CONNECT_GRID, 0); //
    ems_syslog(LOG_NOTICE, "ac_cfgrid_behaviour_func");
    usleep(1000 * 1000); 

    if(Relevant_data_refresh()){
        return 0;
    }

    inf_printf();
    accord_soc_cal_supportpower(microgrid_ctrl.SOC_min_combin, microgrid_ctrl.SOC_max_combin);
    ac_start_cf_process();
    return 0;
}

static RELEVANCE_STATE states_switch_exev(RELEVANCE_STATE last_state, RELEVANCE_STATE state)
{
    double pcs_exp_power = 0;
    double pv_target_power = 0; //光伏目标功率

    ems_syslog(LOG_NOTICE, "状态切换，设置PCS，光伏0功率!!!");
    ac_set_power(pcs_exp_power, pv_target_power);
    return state;
}

static void states_exit(current_stat_t *state_machine)
{
    if(NULL == state_machine->states_exit)
    {
        return;
    }
    state_machine->states_exit(state_machine->last_state, state_machine->major_state);
}

static void ac_state_machine_Init(current_stat_t *_ac_state_machine)
{
    _ac_state_machine->state[STATE_INIT].handover_detect = ac_init_handover_detect;
    _ac_state_machine->state[STATE_INIT].behaviour_func = ac_init_behaviour_func;
    _ac_state_machine->state[STATE_INIT].init = ac_init_init;
    _ac_state_machine->state[STATE_INIT].state_self = STATE_INIT;
    _ac_state_machine->state[STATE_INIT].action_step_idx = 0;

    _ac_state_machine->state[STATE_AWAIT].handover_detect = ac_await_handover_detect;
    _ac_state_machine->state[STATE_AWAIT].behaviour_func = ac_await_behaviour_func;
    _ac_state_machine->state[STATE_AWAIT].init = ac_await_init;
    _ac_state_machine->state[STATE_AWAIT].state_self = STATE_AWAIT;
    _ac_state_machine->state[STATE_AWAIT].action_step_idx = 0;

    _ac_state_machine->state[STATE_CONNECT_GRID].handover_detect = ac_grid_handover_detect;
    _ac_state_machine->state[STATE_CONNECT_GRID].behaviour_func = ac_grid_behaviour_func;
    _ac_state_machine->state[STATE_CONNECT_GRID].init = ac_grid_init;
    _ac_state_machine->state[STATE_CONNECT_GRID].state_self = STATE_CONNECT_GRID;
    _ac_state_machine->state[STATE_CONNECT_GRID].action_step_idx = 0;

    _ac_state_machine->state[STATE_OFF_GRID].handover_detect = ac_off_grid_handover_detect;
    _ac_state_machine->state[STATE_OFF_GRID].behaviour_func = ac_off_grid_behaviour_func;
    _ac_state_machine->state[STATE_OFF_GRID].init = ac_off_grid_init;
    _ac_state_machine->state[STATE_OFF_GRID].state_self = STATE_OFF_GRID;
    _ac_state_machine->state[STATE_OFF_GRID].action_step_idx = 0;

    _ac_state_machine->state[STATE_CF_CONNECT_GRID].handover_detect = ac_cfgrid_handover_detect;
    _ac_state_machine->state[STATE_CF_CONNECT_GRID].behaviour_func = ac_cfgrid_behaviour_func;
    _ac_state_machine->state[STATE_CF_CONNECT_GRID].init = ac_cfgrid_init;
    _ac_state_machine->state[STATE_CF_CONNECT_GRID].state_self = STATE_CF_CONNECT_GRID;
    _ac_state_machine->state[STATE_CF_CONNECT_GRID].action_step_idx = 0;

    _ac_state_machine->state[STATE_ABNORMAL].handover_detect = ac_abnormal_handover_detect;
    _ac_state_machine->state[STATE_ABNORMAL].behaviour_func = ac_abnormal_behaviour_func;
    _ac_state_machine->state[STATE_ABNORMAL].init = ac_abnormal_init;
    _ac_state_machine->state[STATE_ABNORMAL].state_self = STATE_ABNORMAL; 

    /*未定义状态无法确定逻辑*/
    _ac_state_machine->state[STATE_DEFAULT].handover_detect = NULL;
    _ac_state_machine->state[STATE_DEFAULT].behaviour_func = NULL;
    _ac_state_machine->state[STATE_DEFAULT].init = NULL;
    _ac_state_machine->state[STATE_DEFAULT].state_self = STATE_DEFAULT; 

    _ac_state_machine->states_exit = states_switch_exev;
    state_switch(_ac_state_machine, STATE_INIT); //>> 初始状态，准备 
}

/**控制***************************************************************************************************************************START*********/
static int ac_chk_pcs_connection(dev_info_all_t *var, int idx, int value)
{
    ems_syslog(LOG_NOTICE, "chk cab grp[%d] connection= %d, %d", idx, value, var->cabinet_info.cabinet_inside[idx]->cab_data.connect);
    if(value == MICR_ACTION_TYPE_INIT || var->cabinet_info.cabinet_inside[idx]->cab_data.connect == MICR_ACTION_TYPE_INIT) 
        return MICR_CONDITION_SKIP;
    else 
        return (var->cabinet_info.cabinet_inside[idx]->cab_data.connect == value)? MICR_CONDITION_OK: MICR_CONDITION_NO_MATCH;
}

static void ac_send_pcs_connection(dev_info_all_t *var, int idx, int value)
{
    dev_set_dev_tag_int(DEV_NO_EMS, SET_CONNECT, value);
    dev_set_dev_tag_int(var->cabinet_info.cabinet_inside[idx]->no, SET_CONNECT, value);  // 0:Off-grid;1:On-grid
    ems_syslog(LOG_NOTICE,"Cab: %s :Set grp[%d] connection = %d", var->cabinet_info.cabinet_inside[idx]->no, idx, value);
}

static int ac_chk_pcs_switch(dev_info_all_t *var, int idx, int value)
{
    ems_syslog(LOG_NOTICE, "chk cab grp[%d] status= %d, %d", idx, value, var->cabinet_info.cabinet_inside[idx]->cab_data.onoff);
    if(value == MICR_ACTION_TYPE_INIT || var->cabinet_info.cabinet_inside[idx]->cab_data.onoff == MICR_ACTION_TYPE_INIT) 
        return MICR_CONDITION_SKIP;
    else 
        return (var->cabinet_info.cabinet_inside[idx]->cab_data.onoff == value)? MICR_CONDITION_OK: MICR_CONDITION_NO_MATCH;
}

static void ac_send_pcs_switch(dev_info_all_t *var, int idx, int value)
{
    dev_set_dev_tag_int(DEV_NO_EMS, ON_OFF_STATE, value);
    dev_set_dev_tag_int(var->cabinet_info.cabinet_inside[idx]->no, ON_OFF_STATE, value); // 0:Off;1:On
    ems_syslog(LOG_NOTICE,"Cab: %s :Set grp[%d] status = %d", var->cabinet_info.cabinet_inside[idx]->no, idx, value);
}

static double chk_avail_power_modified(dev_info_all_t *var, int grp_idx, double value, int zero_flag) // 0:Normal;1:Abnormal;
{
    double avail_power = 0;
    double tmp = value;

    if(value > 0){// 放电
        if (microgrid_ctrl.en_bms_power_limit){
            avail_power =  var->cabinet_info.cabinet_inside[grp_idx]->cab_ctrl.pcs_discharge_max_actual;
            ems_syslog(LOG_NOTICE, "discharge, grp[%d] [avail_power, ems_power][%f, %f]", grp_idx, avail_power, tmp);
            tmp = MIN(avail_power, tmp);
        }
        if(zero_flag == 1) tmp = 0;
    }
    else if(value < 0) // 充电
    {
        if (microgrid_ctrl.en_bms_power_limit){
            avail_power =  var->cabinet_info.cabinet_inside[grp_idx]->cab_ctrl.pcs_charge_max_actual;
            ems_syslog(LOG_NOTICE, "charge, grp[%d] [avail_power, ems_power][%f, %f]", grp_idx, avail_power, tmp);
            tmp = MAX(avail_power, tmp);
        }
        if(zero_flag == 1) tmp = 0;
    }
    else { 

    } 
    return tmp;
}

static void *cabinet_loop(void *param)
{
    dev_info_all_t *var = ((ctrl_thread_var_t *)param)->var;
    cabinet_inside_t **grp = ((ctrl_thread_var_t *)param)->grp;
    int grp_idx = ((void*)grp - (void*)&var->cabinet_info.cabinet_inside[0]) / sizeof(void*);

    int i = 0;
    time_t last_update_status = 0, last_update_power = 0;
    time_t last_update_pv_power = 0, last_update_pv_onoff = 0;
    time_t last_update_lcb = 0, last_update_DG = 0;
    // time_t last_update_icb = 0;

    double last_power = -1;
    double last_pv_power = -1;
	int last_pv_onoff = -1;
    int last_lcb = -1, last_DG = -1, last_icb = -1;

    struct _dido_t * _dido = &var->dido.dido_param[0];
    while (1)
    {  
        if (microgrid_ctrl.ControlMode != EMS_AUTO_MODE){ 
            ems_syslog(LOG_NOTICE, "cabinet_loop[%d]: ControlMode is not EMS_AUTO_MODE, sleep!!!", grp_idx);
            sleep(1);
            continue;
        }
        usleep(250 * 1000);
        time_t now = time(NULL);

        if(ac_chk_pcs_switch(var, grp_idx, atomic_load(&(*grp)->cab_ctrl.onoff)) == MICR_CONDITION_NO_MATCH){
            if(now >= last_update_status + 3){
                last_update_status = now;
                ac_send_pcs_switch(var, grp_idx, atomic_load(&(*grp)->cab_ctrl.onoff));
            }
        }  
        else if(microgrid_cfg.en_sts == 0 && ac_chk_pcs_connection(var, grp_idx, atomic_load(&(*grp)->cab_ctrl.connect)) == MICR_CONDITION_NO_MATCH){ // 不使能STS，才开启并离网守护
            if(now >= last_update_status + 3){ //防抖~~
                last_update_status = now;
                ac_send_pcs_connection(var, grp_idx, atomic_load(&(*grp)->cab_ctrl.connect));
            }
        }

        if (grp_idx == 0){ //光伏逆变器统一在第一个柜子(主柜)线程去控制，所以必须使能主从模式，光伏逆变器可挂在任意柜子下
            if(var->pv.num > 0){
                if (last_pv_onoff != atomic_load(&microgrid_ctrl.pv_exp_onoff) || now >= (last_update_pv_onoff + 60)){
                    last_update_pv_onoff = now;
                    last_pv_onoff = atomic_load(&microgrid_ctrl.pv_exp_onoff);
                    for (i = 0; i < var->pv.num; i++){
                        pe_set_onoff(var->pv.pv_param[i].no, atomic_load(&microgrid_ctrl.pv_exp_onoff));
                        ems_syslog(LOG_NOTICE, "Pv：%s: Set grp[%d] pv_exp_onoff: %d ", var->pv.pv_param[i].no, i, atomic_load(&microgrid_ctrl.pv_exp_onoff));
                    }
                }
                if(((last_pv_power - 0.5) > atomic_load(&microgrid_ctrl.pv_exp_power) || (last_pv_power + 0.5) < atomic_load(&microgrid_ctrl.pv_exp_power)) || \
                    now >= (last_update_pv_power + 30)){   //设置光伏 功率/百分比(百分比放到模版里面做，此处全是功率)
                    last_update_pv_power = now;
                    last_pv_power = atomic_load(&microgrid_ctrl.pv_exp_power);
                    for (i = 0; i < var->pv.num; i++){
                        pe_set_power(var->pv.pv_param[i].no, atomic_load(&var->pv.pv_param[i].info.pv_ctrl.power_set));
                        ems_syslog(LOG_NOTICE, "Pv：%s :Set grp[%d] power_set: %.3f ", var->pv.pv_param[i].no, i, atomic_load(&var->pv.pv_param[i].info.pv_ctrl.power_set));
                    }
                } 
            }
            // 负载断路器 0: 断开  1:闭合 \柴发控制 0: 停止  1:启动 \并离网断路器 0: 断开  1:闭合  --底层控制方式：DIDO/modbus协议，但对于EMS上层都是点位，动环xlsx表映射决定控制方式
            if ( microgrid_cfg.en_lcb && (last_lcb != atomic_load(&_dido->info.dido_ctrl.lcb_ctrl) || now >= (last_update_lcb + 60)) ) { 
                last_update_lcb = now;
                last_lcb = atomic_load(&_dido->info.dido_ctrl.lcb_ctrl);
                dev_set_dev_tag_int(DEV_NO_EMS, LCB_CTRL, atomic_load(&_dido->info.dido_ctrl.lcb_ctrl));
            }
            if ( microgrid_cfg.en_diesel_generator && (last_DG != atomic_load(&_dido->info.dido_ctrl.DG_ctrl) || now >= (last_update_DG + 60)) ){
                last_update_DG = now;
                last_DG = atomic_load(&_dido->info.dido_ctrl.DG_ctrl);
                dev_set_dev_tag_int(DEV_NO_EMS, DG_CTRL, atomic_load(&_dido->info.dido_ctrl.DG_ctrl)); 
            }  
            //if ( microgrid_cfg.en_icb && (last_icb != atomic_load(&_dido->info.dido_ctrl.icb_ctrl) || now >= (last_update_icb + 60)) ){
            if ( microgrid_cfg.en_icb && (last_icb != atomic_load(&_dido->info.dido_ctrl.icb_ctrl))){
                // last_update_icb = now;
                last_icb = atomic_load(&_dido->info.dido_ctrl.icb_ctrl);
                dev_set_dev_tag_int(DEV_NO_EMS, ICB_CTRL, atomic_load(&_dido->info.dido_ctrl.icb_ctrl)); 
            }     
        }

        double avail_power = chk_avail_power_modified(var, grp_idx, atomic_load(&(*grp)->cab_ctrl.pcs_exp_power), (*grp)->cab_data.en);
        if(last_power != avail_power || now >= last_update_power + 30)
        {
            last_update_power = now;
            last_power = avail_power;
            dev_set_dev_tag_float((*grp)->no, SET_ACT_POWER, avail_power);
            ems_syslog(LOG_NOTICE,"Cab: %s :Set grp[%d] avail_power = %.3f ", var->cabinet_info.cabinet_inside[grp_idx]->no, grp_idx, avail_power);
        }
    }

    return NULL;
}

static ctrl_thread_var_t threads_var[CABINET_NUM_MAX] = {0};
static int microgrid_cabinet_ctrl_init(dev_info_all_t *var)
{
    int index = 0;

    for(index = 0; index < var->cabinet_info.num; index++)
    {
        cabinet_inside_t **grp = &var->cabinet_info.cabinet_inside[index];
        threads_var[index].var = var;
        threads_var[index].grp = grp;
        /* 创建一个单独的线程 */
        int ret = pthread_create(&((*grp)->action_thread), NULL, cabinet_loop, &threads_var[index]);
        if (ret < 0) {
            ems_syslog(LOG_ERR, "failed to created cabinet_loop %s\n", strerror(errno));
            return -1;
        }
    }
    return 0;
}
/***************************************************************************************************************************************END*****/
static int _state_init(current_stat_t *state_machine)
{
    int ret = 0;
    
    usleep(1000 * 1000);
    if(state_machine->state[state_machine->major_state].init)
        ret = state_machine->state[state_machine->major_state].init(state_machine->last_state, state_machine->major_state);
    else
    {
        ems_syslog(LOG_ERR, "Err state_init: state:%d init unregistered", state_machine->major_state);
        return -1;
    }
    return ret;
}

void *ac_state_machine_pthread(void *args)
{
    int ret = 0, ready = 0, count = 0;
    current_stat_t *state_machine = (current_stat_t *)args;

    if(NULL == state_machine)
    {
        ems_syslog(LOG_ERR, "ac_state_machine is NULL!!!");
        goto END;
    }

    while (1)
    { 
        if (microgrid_ctrl.ControlMode != EMS_AUTO_MODE){
            Relevant_data_refresh();
            ems_syslog(LOG_NOTICE, "ac_state_machine_pthread: ControlMode is not EMS_AUTO_MODE, sleep!!!");
		    bit_clean(microgrid_ctrl.cut_flag);
            //
            chargefull = 0; dischargefull = 0;
            memset(battery_flag, 0, sizeof(battery_flag));
            //
            ready = 0;
            state_switch(state_machine, STATE_INIT); //>> 初始状态，准备 
            for(int i = 0; i < _STATE_MAX; i++)
            {   
                struct STATE_INFO *state = &state_machine->state[i];
                state->action_step_idx = 0;  
            }            
            sleep(1);
            continue;
        }
        if(ready == 0){
            ready = _state_init(state_machine);
            if(-1 == ready){ // init注册异常
                sleep(1);
                continue;
            }
        }
        dev_set_dev_tag_int(DEV_NO_EMS, STATE_MACHINE, state_machine->major_state);
        if (count >= 10) {
            ems_syslog(LOG_NOTICE, "current state :%d !!!", state_machine->major_state);
            count = 0;
        }
        ret = state_check_and_switch(state_machine); // 注意：在执行actions step过程中需要同时进行状态检查，满足条件即可切出
        if(1 == ret){
            ready = 0;
            //
            chargefull = 0; dischargefull = 0;
            memset(battery_flag, 0, sizeof(battery_flag));
            //
            states_exit(state_machine); // 状态切换时PCS、PV写0功率，等ready完毕，执行后续策略逻辑进行功率调度
        }

        if (microgrid_ctrl.ControlMode == EMS_AUTO_MODE){ 
            if (ready == 1){
                if(state_machine->state[state_machine->major_state].behaviour_func){
                    state_machine->state[state_machine->major_state].behaviour_func(state_machine->major_state);
                }
                else
                    ems_syslog(LOG_ERR, "Err:state:%d : behaviour_func unregistered", state_machine->major_state);
            }
        }
        else
            ems_syslog(LOG_NOTICE, "control mode is not auto!!!, ControlMode :%d", microgrid_ctrl.ControlMode);

        count++;
        SocrearlyWarning();
    }
END:
    while (1)
    {
        sleep(1);
        ems_syslog(LOG_ERR, "Err:The state machine thread terminates!!!");
    }
    
    return NULL;
}

static void ac_microgrid_param_Init(void){  //初始化参数
    dev_info_all_t *_dev_info_all = get_dev_info_all_var();

    for (int i = 0 ; i < _dev_info_all->cabinet_info.num; i++){
	    cabinet_inside_t *_cabinet_inside = _dev_info_all->cabinet_info.cabinet_inside[i];
        _cabinet_inside->cab_data.onoff = -1;
        _cabinet_inside->cab_data.connect = -1;
        _cabinet_inside->cab_ctrl.onoff = -1;
        _cabinet_inside->cab_ctrl.connect = -1;
        _cabinet_inside->cab_ctrl.pcs_exp_power = 0;
        _cabinet_inside->cab_ctrl.pcs_discharge_max_actual = 100; // 标准储能柜
        _cabinet_inside->cab_ctrl.pcs_charge_max_actual = -100;
	}

    for (int i = 0 ; i < _dev_info_all->pv.num; i++){
	    struct _pv_t *_pv = &_dev_info_all->pv.pv_param[i];
        _pv->info.pv_ctrl.power_set = 0;
	}

    microgrid_ctrl.Grid_offgrid = -1;
    microgrid_ctrl.onoff = -1;
    microgrid_ctrl.pcs_exp_power = 0;
    microgrid_ctrl.pv_exp_power = 0;
    microgrid_ctrl.pv_exp_onoff = -1;
    microgrid_ctrl.cut_flag = bit_new(128);

    microgrid_data.grid_statu = -1;
    microgrid_data.offgrid_statu = -1;
    microgrid_data.on_statu = -1;
    microgrid_data.off_statu = -1;
    microgrid_data.pv_on_statu = -1;
    microgrid_data.pv_off_statu = -1;

    _dev_info_all->dido.dido_param[0].info.dido_ctrl.icb_ctrl = -1;
    _dev_info_all->dido.dido_param[0].info.dido_ctrl.lcb_ctrl = -1;
    _dev_info_all->dido.dido_param[0].info.dido_ctrl.DG_ctrl = -1;
    _dev_info_all->dido.dido_param[0].info.dido_data.conn_sign = -1;
    _dev_info_all->dido.dido_param[0].info.dido_data.ats_sign = -1;
    _dev_info_all->dido.dido_param[0].info.dido_data.lcb_sign = -1;
    _dev_info_all->dido.dido_param[0].info.dido_data.icb_sign = -1;
    _dev_info_all->dido.dido_param[0].info.dido_data.DG_sign = -1;
}

int start_ac_microgrid(void)
{
	current_stat_t *_ac_state_machine = get_ac_state_machine();
    dev_info_all_t *_dev_info_all = get_dev_info_all_var();

    ac_microgrid_param_Init();

    microgrid_cabinet_ctrl_init(_dev_info_all);
    ac_state_machine_Init(_ac_state_machine); 

    pthread_t tid = {0};
    if (pthread_create(&tid, NULL, ac_state_machine_pthread, _ac_state_machine) != 0){
		ems_syslog(LOG_NOTICE, "Failed to create state_machine_pthread thread!");
		return -1;
	}
	else
	{
		pthread_setname_np(tid, "state_machine_pthread");
	}
	
    return 0;
}

