#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include "define.h"
#include "jsonct.h"
#include "deviceLayer.h"
#include "emsctrlProc.h"
#include "../common.h"
#include "main.h"
#include "../adapter/pe_adapter.h"
#include <math.h>
#include <time.h>
#include "ems_ua.h"
#include "lc_discovery.h"
#include "../proto_forward.h"
#include "automatic.h"
#include "pub_fun.h"
#include "log_module.h"
#include "../multilanguage.h"
#include "microgridtopology.h"
#include "vlc_deviceLater.h"
#include "g100_protect.h"
#include "../virtual_bau.h"
#include "../pcs_business_adapter/pcs_business_adapter.h"
extern double get_ems_lc_power(void);

// static struct hash_intptr *ems_variant_hash;
// static struct hash_intptr *device_variant_hash;
// static void *g_collector = NULL;
// extern usercfg_variant_t g_usercfg_variant;

//配置文件参数 //此处不包含计划参数 计划参数一定会存储
const ems_cfg_info_t ems_config_tab[] = 
{
    {DEV_NO_EMS"."EN_DRAUG_FLOW_POWER   ,offsetof(usercfg_variant_t, EnDraughtFanFlowPower),             EMS_POINT_INT},
    {DEV_NO_EMS"."EN_DRAUG_FLOW_POWER_T ,offsetof(usercfg_variant_t, DraughtFanFlowPowerThreShold),      EMS_POINT_INT},
    {DEV_NO_EMS"."EN_DRAUG_FLOW_TEM     ,offsetof(usercfg_variant_t, EnDraughtFanFlowTem),               EMS_POINT_INT},
    {DEV_NO_EMS"."EN_DRAUG_FLOW_TEM_T   ,offsetof(usercfg_variant_t, DraughtFanFlowTemThreShold),        EMS_POINT_INT},
    {DEV_NO_EMS"."DRAUG_DEAE_TIME       ,offsetof(usercfg_variant_t, DeadTime),                          EMS_POINT_INT}, 
    {DEV_NO_EMS"."EN_TRACELOAD          ,offsetof(usercfg_variant_t, EnTraceLoad),      EMS_POINT_INT}, 
    {DEV_NO_EMS"."EN_PROTECT_REVERSE    ,offsetof(usercfg_variant_t, EnProtectReverse), EMS_POINT_INT}, 
    {DEV_NO_EMS"."PROTECT_REVERSE_WIN    ,offsetof(usercfg_variant_t, ProtectReverseWin), EMS_POINT_INT},
    {DEV_NO_EMS"."DEMAND_WIN             ,offsetof(usercfg_variant_t, DemandWin), EMS_POINT_INT},
    {DEV_NO_EMS"."EN_PROTECT_TRANSF     ,offsetof(usercfg_variant_t, EnProtectTransf),  EMS_POINT_INT}, 
    {DEV_NO_EMS"."STRANTAGY_TYPE        ,offsetof(usercfg_variant_t, StratagyType),     EMS_POINT_INT},
    {DEV_NO_EMS"."EN_PROTECT_DOD        ,offsetof(usercfg_variant_t, EnProtectDOD),      EMS_POINT_INT},
    {DEV_NO_EMS"."CONTROL_MODE          ,offsetof(usercfg_variant_t, ControlMode),      EMS_POINT_INT},
    {DEV_NO_EMS"."EN_BMS_ALARM          ,offsetof(usercfg_variant_t, EnBmsAlarm),      EMS_POINT_INT},

    {DEV_NO_EMS"."EMS_PMLMAX          ,offsetof(usercfg_variant_t, Pmlmax)           ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_K1              ,offsetof(usercfg_variant_t, K1)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_K2              ,offsetof(usercfg_variant_t, K2)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_K3              ,offsetof(usercfg_variant_t, K3)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_SOCMAX          ,offsetof(usercfg_variant_t, SOCmax)           ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."EMS_SOCMIN          ,offsetof(usercfg_variant_t, SOCmin)           ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."EMS_PSET            ,offsetof(usercfg_variant_t, Pset)             ,EMS_POINT_INT},
 
    {DEV_NO_EMS"."CAB_POWER           ,offsetof(usercfg_variant_t, cab_power),        EMS_POINT_INT},
    {DEV_NO_EMS"."CAB_CAPACITY        ,offsetof(usercfg_variant_t, cab_capacity),     EMS_POINT_INT},  
    {DEV_NO_EMS"."EMS_ADJPRERIOD      ,offsetof(usercfg_variant_t, Adjpreriod)       ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_TEMP_THRESHOLD  ,offsetof(usercfg_variant_t, tempThreshold)    ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_TRACKING_LIMIT  ,offsetof(usercfg_variant_t, loadTrackingLimit),EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_NUMPCS          ,offsetof(usercfg_variant_t, numOfPcs)         ,EMS_POINT_INT},
    {DEV_NO_EMS"."METER_INVERT       ,offsetof(usercfg_variant_t, meter_invert)    ,EMS_POINT_INT},
    {DEV_NO_EMS"."BMS_POWER_LIMIT     ,offsetof(usercfg_variant_t, en_bms_power_limit)    ,EMS_POINT_INT},
    {DEV_NO_EMS"."ENPROTECTRASLV       ,offsetof(usercfg_variant_t, EnProtectTrasLV)    ,EMS_POINT_INT},
    {DEV_NO_EMS"."PLVMLMAX          ,offsetof(usercfg_variant_t, PLVmlmax)    ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_K4            ,offsetof(usercfg_variant_t, K4)            ,EMS_POINT_INT},
    {DEV_NO_EMS"."EN_IO_PROTECT       ,offsetof(usercfg_variant_t, EnIoProtect)      ,EMS_POINT_INT},
    {DEV_NO_EMS"."PCS_AUTO_TURN       ,offsetof(usercfg_variant_t, PcsAutoTurn)      ,EMS_POINT_INT},
    {DEV_NO_EMS"."PCS_AUTO_TURN_OFF_TIME,offsetof(usercfg_variant_t, PcsAutoTurnOffTime),EMS_POINT_INT},
    {DEV_NO_EMS"."EN_RP_COMP       ,offsetof(usercfg_variant_t, EnPcsRpComp)      ,EMS_POINT_INT},
    {DEV_NO_EMS"."WORK_SAMPLE_PERIOD,offsetof(usercfg_variant_t, WorkSamplePeriod),EMS_POINT_INT},
    {DEV_NO_EMS"."IDLE_SAMPLE_PERIOD ,offsetof(usercfg_variant_t, IdleSamplePeriod),EMS_POINT_INT},
    {DEV_NO_EMS"."MAX_DEMAND ,offsetof(usercfg_variant_t, MaxDemand),EMS_POINT_INT},
    {DEV_NO_EMS"."DEMAND_MARGIN,offsetof(usercfg_variant_t, DemandMargin),EMS_POINT_INT},
    {DEV_NO_EMS"."DYNAMIC_AUGMENT,offsetof(usercfg_variant_t, DynamicAugmentation),EMS_POINT_INT},
    {DEV_NO_EMS"."PV_MAX_POWER           ,offsetof(usercfg_variant_t, PvMaxPower),        EMS_POINT_INT},
    {DEV_NO_EMS"."INSPOW_COEF           ,offsetof(usercfg_variant_t, Installedcab_coeff),        EMS_POINT_INT},
    {DEV_NO_EMS"."CELL_VOLT_PROTECT_TIME           ,offsetof(usercfg_variant_t, SingleVoltageTime),        EMS_POINT_INT},
    {DEV_NO_EMS"."EN_DYNAMICPOWFA_COR     ,offsetof(usercfg_variant_t, EnDynamicPowerFactorCorrection), EMS_POINT_INT},
    {DEV_NO_EMS"."POWERTARGET_VALUE       ,offsetof(usercfg_variant_t, PowerFactorTargetValue), EMS_POINT_FLOAT},
    {DEV_NO_EMS"."POWERFACTOR_DEVIATION   ,offsetof(usercfg_variant_t, PowerFactorDeviation), EMS_POINT_FLOAT},
    {DEV_NO_EMS"."POWERFACTOR_ADJ_PER     ,offsetof(usercfg_variant_t, PowerFactorAdjustmentPeriod), EMS_POINT_INT},
    {DEV_NO_EMS"."ENABLE_SINGLE_PHASE_REVERSE, offsetof(usercfg_variant_t, EnableSinglePhaseReverse), EMS_POINT_INT},
    {DEV_NO_EMS"."SURPLUS_POWER, offsetof(usercfg_variant_t, SurplusPower), EMS_POINT_INT},


    //热管理
    {DEV_NO_EMS"."AIR_COND_DELAY_TIME, offsetof(usercfg_variant_t,  AirCondDelayTime),EMS_POINT_INT},
    {DEV_NO_EMS"."ENABLE_AIR_COND,      offsetof(usercfg_variant_t, EnableAirCond   ),EMS_POINT_INT},
    {DEV_NO_EMS"."AIR_COND_AHEAD_TIME, offsetof(usercfg_variant_t,  AirCondAheadTime),EMS_POINT_INT},

    {DEV_NO_EMS"."ENABLE_AUTO_COOL, offsetof(usercfg_variant_t, EnableAutoCool),EMS_POINT_INT},
    {DEV_NO_EMS"."START_SELF_LOOP_DIFF, offsetof(usercfg_variant_t, StartSelfLoopDiff),EMS_POINT_INT},
    {DEV_NO_EMS"."END_SELF_LOOP_DIFF, offsetof(usercfg_variant_t, EndSelfLoopDiff),EMS_POINT_INT},
    {DEV_NO_EMS"."EN_SELF_LOOP_DIFF, offsetof(usercfg_variant_t, En_SelfLoopDiff),EMS_POINT_INT},
    {DEV_NO_EMS"."HEAT_CTR_CYCLE, offsetof(usercfg_variant_t, HeatCtrCycle),EMS_POINT_INT},
    
    // {DEV_NO_EMS"."BEFORE_WORK_TIME    , offsetof(usercfg_variant_t,BeforeWorkTime),EMS_POINT_INT},
    {DEV_NO_EMS"."WORK_START_HOT_TEMP , offsetof(usercfg_variant_t,WStartHot),EMS_POINT_INT},
    {DEV_NO_EMS"."WORK_END_HOT_TEMP   , offsetof(usercfg_variant_t,WEndHot),EMS_POINT_INT},
    {DEV_NO_EMS"."WORK_START_COOL_TEMP, offsetof(usercfg_variant_t,WStartCool),EMS_POINT_INT},
    {DEV_NO_EMS"."WORK_END_COOL_TEMP  , offsetof(usercfg_variant_t,WEndCool),EMS_POINT_INT},
    {DEV_NO_EMS"."STOP_START_HOT_TEMP , offsetof(usercfg_variant_t,SStartHot),EMS_POINT_INT},
    {DEV_NO_EMS"."STOP_END_HOT_TEMP   , offsetof(usercfg_variant_t,SEndHot),EMS_POINT_INT},
    {DEV_NO_EMS"."STOP_START_COOL_TEMP, offsetof(usercfg_variant_t,SStartCool),EMS_POINT_INT},
    {DEV_NO_EMS"."STOP_END_COOL_TEMP ,  offsetof(usercfg_variant_t,SEndCool),EMS_POINT_INT},
    // {DEV_NO_EMS"."PREPARE_START_HOT_TEMP , offsetof(usercfg_variant_t,PStartHot),EMS_POINT_INT},
    // {DEV_NO_EMS"."PREPARE_END_HOT_TEMP   , offsetof(usercfg_variant_t,PEndHot),EMS_POINT_INT},
    // {DEV_NO_EMS"."PREPARE_START_COOL_TEMP, offsetof(usercfg_variant_t,PStartCool),EMS_POINT_INT},
    // {DEV_NO_EMS"."PREPARE_END_COOL_TEMP  , offsetof(usercfg_variant_t,PEndCool),EMS_POINT_INT},
    {DEV_NO_EMS"."WORK_DIST_HOT_TEMP  , offsetof(usercfg_variant_t,WDistHot),EMS_POINT_INT},
    {DEV_NO_EMS"."WORK_DIST_COOL_TEMP , offsetof(usercfg_variant_t,WDistCool),EMS_POINT_INT},
    {DEV_NO_EMS"."STOP_DIST_HOT_TEMP    , offsetof(usercfg_variant_t,SDistHot),EMS_POINT_INT},
    {DEV_NO_EMS"."STOP_DIST_COOL_TEMP   , offsetof(usercfg_variant_t,SDistCool),EMS_POINT_INT},
    // {DEV_NO_EMS"."PREPARE_DIST_HOT_TEMP , offsetof(usercfg_variant_t,PDistHot),EMS_POINT_INT},
    // {DEV_NO_EMS"."PREPARE_DIST_COOL_TEMP, offsetof(usercfg_variant_t,PDistCool),EMS_POINT_INT},

    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"1" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*0   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"2" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*1   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"3" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*2   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"4" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*3   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"5" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*4   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"6" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*5   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"7" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*6   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"8" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*7   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"9" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t,  demand_threshold)+sizeof(int)*8   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"10" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, demand_threshold)+sizeof(int)*9   ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"11" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, demand_threshold)+sizeof(int)*10  ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_THRESHOLD"12" ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, demand_threshold)+sizeof(int)*11  ,EMS_POINT_INT},

    {DEV_NO_EMS"."EMS_CHARGE_STARTPOWER,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, charge_startpower)                        ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DISCHARGE_THRESHOLD,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, discharge_threshold)                    ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_START_HOUR,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, tou_seg)+offsetof(demand_seg_t, StHour )  ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_START_MIN ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, tou_seg)+offsetof(demand_seg_t, StMin  )  ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_END_HOUT  ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, tou_seg)+offsetof(demand_seg_t, EnHour )  ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DEMAND_END_MIN   ,offsetof(usercfg_variant_t, demand_param)+offsetof(demand_param_t, tou_seg)+offsetof(demand_seg_t, EnMin  )  ,EMS_POINT_INT},

    {DEV_NO_EMS"."SINGLE_MAX_VOLTAGE              ,offsetof(usercfg_variant_t, SingleMaxVoltage)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."SINGLE_MIN_VOLTAGE              ,offsetof(usercfg_variant_t, SingleMinVoltage)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."EN_CELL_VOLT_PROTECT            ,offsetof(usercfg_variant_t, EnCellVoltProtect)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."EN_DATA_COLLECT            ,offsetof(usercfg_variant_t, EnDataCollect)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."SINGLE_MAX_VOLTAGE_ERR          ,offsetof(usercfg_variant_t, SingleMaxVoltageErr)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."SINGLE_MIN_VOLTAGE_ERR          ,offsetof(usercfg_variant_t, SingleMinVoltageErr)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."EMS_SOCMINERR                   ,offsetof(usercfg_variant_t, SOCmaxErr)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."EMS_SOCMAXERR                   ,offsetof(usercfg_variant_t, SOCminErr)               ,EMS_POINT_FLOAT},

    {DEV_NO_EMS"."CHARGE_MAX_POWER              ,offsetof(usercfg_variant_t, chargeMaxPower)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."DISCHARGE_THRES_HOLD              ,offsetof(usercfg_variant_t, dischargeThreshold)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."ACCIDENT_TGI              ,offsetof(usercfg_variant_t, Accident_tgi)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."ACCIDENT_EN              ,offsetof(usercfg_variant_t, Accident_en)               ,EMS_POINT_INT},

    // 微网
    {DEV_NO_EMS"."SOC_NET_DEAD_MAX              ,offsetof(usercfg_variant_t, SOCmaxNetDead)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."SOC_NET_DEAD_MIN              ,offsetof(usercfg_variant_t, SOCminNetDead)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."SOC_NET_MAX                   ,offsetof(usercfg_variant_t, SOCmaxNet)                   ,EMS_POINT_INT},
    {DEV_NO_EMS"."SOC_NET_MIN                   ,offsetof(usercfg_variant_t, SOCminNet)                   ,EMS_POINT_INT},
    {DEV_NO_EMS"."DG_RATED_POWER              ,offsetof(usercfg_variant_t, DGRatedPower)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."DG_BOOT_SOC              ,offsetof(usercfg_variant_t, DGBootSoc)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."SOC_ALARM              ,offsetof(usercfg_variant_t, SocAlarmThreshold)               ,EMS_POINT_FLOAT},
    //{DEV_NO_EMS"."EN_AC_D2C              ,offsetof(usercfg_variant_t, en_ac_d2c)               ,EMS_POINT_INT},
    //{DEV_NO_EMS"."EN_AC_C2D              ,offsetof(usercfg_variant_t, en_ac_c2d)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."EMS_DG_DIFF              ,offsetof(usercfg_variant_t, DgDiff)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."ACTION_TIMEOUT              ,offsetof(usercfg_variant_t, action_timeout)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."DG_CAP_PRO              ,offsetof(usercfg_variant_t, DG_Capacity_protection)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."PV_KM              ,offsetof(usercfg_variant_t, pv_km)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."PV_MODE              ,offsetof(usercfg_variant_t, pv_mode)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."DEAD_NIGHT              ,offsetof(usercfg_variant_t, dead_night)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."PV_ISCTRL              ,offsetof(usercfg_variant_t, pv_isctrl)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."EN_PV_PRECTRL              ,offsetof(usercfg_variant_t, EnPvPrectrl)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."MICRO_CHECK              ,offsetof(usercfg_variant_t, micro_check)               ,EMS_POINT_INT},
    

    // G100
    {DEV_NO_EMS"."G100_ENABLE              ,offsetof(usercfg_variant_t, g100Enable)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_UNLOCK_TIME              ,offsetof(usercfg_variant_t, g100UnlockTime)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_MAXCOUNT_MON              ,offsetof(usercfg_variant_t, g100LockMaxCount)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_MAXCOUNT_10MIN              ,offsetof(usercfg_variant_t, g100BackflowCount10Min)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_MAXCOUNT_DAY              ,offsetof(usercfg_variant_t, g100BackflowCountDay)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_BACKFLOW_LIMIT              ,offsetof(usercfg_variant_t, g100BackflowLimit)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_BACKFLOW_SEC              ,offsetof(usercfg_variant_t, g100BackflowSec)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_BACKFLOW_LOCK_TIME              ,offsetof(usercfg_variant_t, g100BackflowLockTime)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_OVERLOAD_LIMIT              ,offsetof(usercfg_variant_t, g100OverloadLimit)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_OVERLOAD_SEC              ,offsetof(usercfg_variant_t, g100OverloadSec)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."G100_OVERLOAD_LOCK_TIME              ,offsetof(usercfg_variant_t, g100OverloadLockTime)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."MPPT_EQ              ,offsetof(usercfg_variant_t, Mppt_eq)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."MPPT_EQ_TL              ,offsetof(usercfg_variant_t, Mppt_eq_tl)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."MPPT_EQ_RT              ,offsetof(usercfg_variant_t, Mppt_eq_rt)               ,EMS_POINT_FLOAT},
    {DEV_NO_EMS"."EN_SW_D2C              ,offsetof(usercfg_variant_t, EnSwD2C)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."EN_SW_C2D              ,offsetof(usercfg_variant_t, EnSwC2D)               ,EMS_POINT_INT},
    {DEV_NO_EMS"."UD_LOG              ,offsetof(usercfg_variant_t, udlog)               ,EMS_POINT_INT},
};
int ems_config_tab_count_g = sizeof(ems_config_tab) / sizeof(ems_config_tab[0]);

const char * ud_log_ctrl[] = 
{
    DEV_NO_EMS"."UD_LOG
};

//处理快速响应配置
const char * ems_config_fast_tab[] = 
{

};

//处理控制命令
const char * ems_contrl_tab[] = 
{
    DEV_NO_EMS"."ON_OFF_STATE,     
    DEV_NO_EMS"."SET_ACT_POWER, 
    DEV_NO_EMS"."SET_REACTPOWER,
    DEV_NO_EMS"."SET_CONNECT,  
    DEV_NO_EMS"."CLEAR_ALARM,
    DEV_NO_EMS"."SET_PV_POWER,
    DEV_NO_EMS"."CONTROL_MODE,
    DEV_NO_EMS"."BMS_UPPER,
    DEV_NO_EMS"."EN_RP_COMP,
    DEV_NO_EMS"."SET_POWER_FACTOR,
    DEV_NO_EMS"."CELL_VOLT_PROTECT_TIME,
    DEV_NO_EMS"."PCS_AUTO_TURN,
    DEV_NO_EMS"."PCS_FAULT_RESET,
    DEV_NO_EMS"."ENABLE_SINGLE_PHASE_REVERSE,
};

//DOD保护
const char * fast_stop_dod_protect_tab[] = 
{
    DEV_NO_BMS"."CURRENT_SOC,
    DEV_NO_BMS"."CURRENT_SOH,
};
//处理欠压故障
const char * fast_stop_discharge_tab[] = 
{
    DEV_NO_BMS"."CELL_UNDER_VOL2,
    DEV_NO_BMS"."CELL_UNDER_VOL3,
    DEV_NO_BMS"."RACK_UNDER_VOL2,
    DEV_NO_BMS"."RACK_UNDER_VOL3,
    DEV_NO_BMS"."CURRENT_SOC,
    DEV_NO_BMS "." RACK_MIN_VOLT,
    DEV_NO_EMS "." USER_STOP_DISCHA1,
    DEV_NO_EMS "." USER_STOP_DISCHA2,
    DEV_NO_EMS "." USER_STOP_DISCHA3
};

//处理过压故障
const char * fast_stop_charge_tab[] = 
{
    DEV_NO_BMS"."CELL_OVER_VOL2,
    DEV_NO_BMS"."CELL_OVER_VOL3,
    DEV_NO_BMS"."RACK_OVER_VOL2,
    DEV_NO_BMS"."RACK_OVER_VOL3,
    DEV_NO_BMS"."CURRENT_SOC,
    DEV_NO_BMS "." RACK_MAX_VOLT,
    DEV_NO_EMS "." USER_STOP_CHA1,
    DEV_NO_EMS "." USER_STOP_CHA2,
    DEV_NO_EMS "." USER_STOP_CHA3
};


//系统状态
const char * fast_stop_system_state_tab[] = 
{
    DEV_NO_BMS"."CELL_OVER_VOL3,
    DEV_NO_BMS"."RACK_OVER_VOL3,
    DEV_NO_BMS"."CELL_UNDER_VOL3,
    DEV_NO_BMS"."RACK_UNDER_VOL3,
    DEV_NO_EMS"."IO_PROTECT,
    DEV_NO_EMS"."METER_ERROR,
    DEV_NO_PCS"."PCS_FAULT,
    DEV_NO_PCS"."PCS_TOTAL_FAULT,
    DEV_NO_EMS"."USER_STOP1,
    DEV_NO_EMS"."USER_STOP2,
    DEV_NO_EMS"."USER_STOP3,
    DEV_NO_EMS"."TEMP_CTRL_ERR,//温控系统异常
    DEV_NO_EMS"."ALL_FIRE,//消防系统触发
    DEV_NO_EMS"."EMS_CONNECT_STATE,
    DEV_NO_EMS"."G100_LOCK_STATE,
    DEV_NO_EMS"."LC_SYSTEM_STATUS,//从机系统状态（有一个正常则为正常）
};

const char * fast_stop_system_state_tab_not[] = 
{
    DEV_NO_PCS"."STATE_ONLINE,
    DEV_NO_BMS"."STATE_ONLINE,
};

//温控系统异常
const char * fast_stop_temp_ctrl_tab[] = 
{
    DEV_NO_AIRCOND"."STATE_ONLINE,
    DEV_NO_AIRCOND"."DEV_FAULT,
    DEV_NO_LIQUID"."STATE_ONLINE,
    DEV_NO_LIQUID"."DEV_FAULT,
};

//最大充电功率
static const char *fast_maximum_charg_power_tab[] = {
    DEV_NO_BMS"." RACK_VOLTAGE,
    DEV_NO_BMS"." RACK_MAX_CHARGE_CUR,
};
//最大放电功率
static const char *fast_maximum_discharg_power_tab[] = {
    DEV_NO_BMS"." RACK_VOLTAGE,
    DEV_NO_BMS"." RACK_MAX_DISCHA_CUR,
};

//电表故障  此处回调改为周期检查
// const char * fast_stop_meter_err_tab[] = 
// {
//     DEV_NO_GRID_MT"."STATE_ONLINE,
//     DEV_NO_PCS_MT"."STATE_ONLINE,
// };

//外部消防触发  //在广播处触发


//消防触发（FireTrigger）

const char * fast_stop_fire_tab[] = 
{
    DEV_NO_EMS"."EXTERN_FIRE,//外部消防的点位
    DEV_NO_EMS"."FIRE,
};


//直流总压异常异常
const char * fast_stop_dc_voltage_unusual_tab[] = 
{
    DEV_NO_BMS"."RACL_VOLTAGE,
};

const char* fast_stop_power_tab[] =
{
    DEV_NO_EMS "." EMS_POWER, //当前系统是否停电 0 正常
};

const char* ems_on_off_status_tab[] =
{
    DEV_NO_EMS"."ON_OFF_STATE,
};

static const char *node_sync_tab[] = {
    DEV_NO_BMS "." CURRENT_SOC,
    DEV_NO_PCS "." ACTIVE_POWER,
    DEV_NO_PCS "." REACTIVE_POWER,
    DEV_NO_PCS "." PHASE_A_POWER,
    DEV_NO_PCS "." PHASE_B_POWER,
    DEV_NO_PCS "." PHASE_C_POWER,
};

// 光伏控制-手动模式
const char * fast_ph_ctrl[] = 
{
    DEV_NO_EMS"." PH_P,
    DEV_NO_EMS"." PH_ON,
    DEV_NO_EMS"."PH_OFF
};


static void ud_log_ctrl_function(char *nod,tag_value *data_value)
{
    {
        ud_log_Level = data_value->value.to_int;
        UD_log_update_en();
    }
}

static void fast_ph_ctrl_function(char *nod,tag_value *data_value)
{
    if (strcmp(nod,DEV_NO_EMS"."PH_P)==0)
    {
        ph_set_power_callback(data_value->value.to_float);
    }
    if (strcmp(nod,DEV_NO_EMS"."PH_ON)==0 && data_value->value.to_int)
    {
        ph_set_onoff_callback(1);
        data_value->value.to_int = 0;
    }
    if (strcmp(nod,DEV_NO_EMS"."PH_OFF)==0 && data_value->value.to_int)
    {
        ph_set_onoff_callback(0);
        data_value->value.to_int = 0;
    }

}

//向数采系统注册点位
ems_base_variant_t ems_base_variant[] =
    {
        // 读写点位 (参数配置)
        //使能负荷跟踪
        {DEV_NO_EMS, EN_TRACELOAD,          "Enable load tracking",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;",         0x03, 0x00, TYPE_INT,   ORDER_AB,   1},
        //使能逆流防护
        {DEV_NO_EMS, EN_PROTECT_REVERSE,    "Enable anti-backflow protection",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;",         0x03, 0x01, TYPE_INT,   ORDER_AB,   1},
        //需量控制
        {DEV_NO_EMS, EN_PROTECT_TRANSF,     "Demand control",    O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Disabled;1:Transformer demand;2:Maximum demand;",         0x03, 0x02, TYPE_INT,   ORDER_AB,   1},
        //设置工作模式
        {DEV_NO_EMS, CONTROL_MODE,          "Set working mode", O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Manual;1:Strategy;",         0x03, 0x03, TYPE_INT,   ORDER_AB,   1},
        //变压器容量
        {DEV_NO_EMS, EMS_PMLMAX,            "Transformer capacity(kVA)",        O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x04, TYPE_INT,   ORDER_AB,   1, 0, 10000},
        //需量控制系数
        {DEV_NO_EMS, EMS_K1,                "Demand control factor(%)",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x05, TYPE_INT,   ORDER_AB,   1, 0, 100},
        //负载跟踪系数
        {DEV_NO_EMS, EMS_K2,                "Load tracking factor(%)",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x06, TYPE_INT,   ORDER_AB,   1, 0, 100},
        //多站点分配系数
        {DEV_NO_EMS, EMS_K3,                "Multi site allocation factor(%)",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x07, TYPE_INT,   ORDER_AB,   1},
        //最大充电SOC
        {DEV_NO_EMS, EMS_SOCMAX,            "Maximum charging SOC(%)",       O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "",                      0x03, 0x09, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
        //最小放电SOC
        {DEV_NO_EMS, EMS_SOCMIN,            "Minimum discharge SOC(%)",       O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "",                      0x03, 0x0b, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
        //防逆流余量
        {DEV_NO_EMS, EMS_PSET,              "Anti-backflow margin(kW)",        O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x0d, TYPE_INT,   ORDER_AB,   1, -1000, 1000},
        //调整间隔
        {DEV_NO_EMS, EMS_ADJPRERIOD,        "Adjustment interval(s)",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x11, TYPE_INT,   ORDER_AB,   1},
        //调整间隔
        {DEV_NO_EMS, EMS_TEMP_THRESHOLD,    "Temperature threshold(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x12, TYPE_INT,   ORDER_AB,   1},
        //使能负荷跟踪限制
        {DEV_NO_EMS, EMS_TRACKING_LIMIT,    "Enable load tracking limit",  O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;",          0x03, 0x13, TYPE_INT,   ORDER_AB,   1},
        //使能DOD防护
        {DEV_NO_EMS, EN_PROTECT_DOD,        "Enable DOD protection",       O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;",          0x03, 0x15, TYPE_INT,   ORDER_AB,   1},
        //1月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"1","January demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x16, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //2月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"2","February demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x17, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //3月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"3","March demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x18, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //4月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"4","April demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x19, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //5月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"5","May demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x1A, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //6月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"6","June demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x1B, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //7月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"7","July demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x1C, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //8月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"8","August demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x1D, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //9月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"9","September demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x1E, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //10月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"10","October demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x1F, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //11月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"11","November demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x20, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //12月需量控制门限
        {DEV_NO_EMS, EMS_DEMAND_THRESHOLD"12","December demand control threshold(kW)",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,                   0x03, 0x21, TYPE_INT,    ORDER_AB,    1, 0, 10000},
        //充电开始小时
        {DEV_NO_EMS, EMS_DEMAND_START_HOUR, "Charging starting in hour",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,              0x03, 0x22, TYPE_INT,    ORDER_AB,    1},
        //充电开始分钟
        {DEV_NO_EMS, EMS_DEMAND_START_MIN , "Charging starting in minute",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                 0x03, 0x23, TYPE_INT,   ORDER_AB,   1},
        //充电结束小时
        {DEV_NO_EMS, EMS_DEMAND_END_HOUT  , "Charging ending in hour",      O_WRONLY | O_RDONLY,EMS_POINT_INT,    PROPERTY_REALDATA , "off",   "" ,              0x03, 0x24, TYPE_INT,    ORDER_AB,    1},
        //充电结束分钟
        {DEV_NO_EMS, EMS_DEMAND_END_MIN   , "Charging ending in minute",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                 0x03, 0x25, TYPE_INT,   ORDER_AB,   1},
        //设置策略模式
        {DEV_NO_EMS, STRANTAGY_TYPE,        "Set strategy mode",          O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", NULL, 0x03, 0x26, TYPE_INT,   ORDER_AB,   1},
        //使能BMS告警
        {DEV_NO_EMS, EN_BMS_ALARM,          "Enable BMS alarms",           O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Disabled;1:Enabled;",        0x03, 0x27, TYPE_INT,   ORDER_AB,   1},
        //使能风机跟随功率
        {DEV_NO_EMS, EN_DRAUG_FLOW_POWER   , "Enable fan to follow power",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;",    0x03, 0x28, TYPE_INT,   ORDER_AB,   1},
        //风机跟随功率门限
        {DEV_NO_EMS, EN_DRAUG_FLOW_POWER_T , "Fan following power threshold(kW)",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,       "off", "",                0x03, 0x29, TYPE_INT,   ORDER_AB,   1},
        //使能风机跟随温度
        {DEV_NO_EMS, EN_DRAUG_FLOW_TEM     , "Enable fan to follow TEMP",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;",    0x03, 0x2a, TYPE_INT,   ORDER_AB,   1},
        //风机跟随温度门限
        {DEV_NO_EMS, EN_DRAUG_FLOW_TEM_T   , "Fan following TEMP threshold(℃)",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",                 0x03, 0x2b, TYPE_INT,   ORDER_AB,   1},
        //跟随时间死区
        {DEV_NO_EMS, DRAUG_DEAE_TIME       , "Follow time deadband(s)",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",                 0x03, 0x2c, TYPE_INT,   ORDER_AB,   1, 0, 600},
        //储能电表功率方向
        {DEV_NO_EMS, METER_INVERT,          "Power direction of PCS-meter",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Normal;1:Reversed;",   0x03, 0x2d, TYPE_INT,   ORDER_AB,   1},
        //自动PCS关机
        {DEV_NO_EMS, PCS_AUTO_TURN,         "PCS auto-shutdown",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;",   0x03, 0x2e, TYPE_INT,   ORDER_AB,   1},
        //自动PCS关机时间
        {DEV_NO_EMS, PCS_AUTO_TURN_OFF_TIME,"PCS auto-shutdown time(s)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x2f, TYPE_INT,   ORDER_AB,   1},
        //工作时电芯抽样间隔
        {DEV_NO_EMS, WORK_SAMPLE_PERIOD,    "Sampling interval of battery cells during work(s)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x31, TYPE_INT,   ORDER_AB,   1},
        //空闲时电芯抽样间隔
        {DEV_NO_EMS, IDLE_SAMPLE_PERIOD ,   "Sampling interval of battery cells in idle(s)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x32, TYPE_INT,   ORDER_AB,   1},

        //使能液冷机管理
        {DEV_NO_EMS, ENABLE_AUTO_COOL,          "Enable liquid cooling MGT",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;",              0x03, 0x33, TYPE_INT,   ORDER_AB,   1},
        //使能间隙自循环
        {DEV_NO_EMS, EN_SELF_LOOP_DIFF,         "Enable gap self circulation",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;",              0x03, 0x34, TYPE_INT,   ORDER_AB,   1},
        // {DEV_NO_EMS, BEFORE_WORK_TIME    ,   "工作之前时间液冷启动(min)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",       0x03, 0x35, TYPE_INT,   ORDER_AB,   1},
        //工作段制热启动温度
        {DEV_NO_EMS, WORK_START_HOT_TEMP ,      "Work Heating start-up temperature(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x35, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //工作段制热停止温度
        {DEV_NO_EMS, WORK_END_HOT_TEMP   ,      "Work Heating stop temperature(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x36, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //工作段制冷启动温度
        {DEV_NO_EMS, WORK_START_COOL_TEMP,      "Work Cooling start-up temperature(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x37, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //工作段制冷停止温度
        {DEV_NO_EMS, WORK_END_COOL_TEMP  ,      "Work Cooling stop temperature(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x38, TYPE_INT,   ORDER_AB,   1, -100, 100},
        // {DEV_NO_EMS, PREPARE_START_HOT_TEMP ,"预热段制热启动温度",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x3a, TYPE_INT,   ORDER_AB,   1},
        // {DEV_NO_EMS, PREPARE_END_HOT_TEMP   ,"预热段制热停止温度",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x39, TYPE_INT,   ORDER_AB,   1},
        // {DEV_NO_EMS, PREPARE_START_COOL_TEMP,"预热段制冷启动温度",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x3a, TYPE_INT,   ORDER_AB,   1},
        // {DEV_NO_EMS, PREPARE_END_COOL_TEMP  ,"预热段制冷停止温度",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x3b, TYPE_INT,   ORDER_AB,   1},
        //空闲段制热启动温度
        {DEV_NO_EMS, STOP_START_HOT_TEMP ,   "TEMP for heating start-up in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x700, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制热停止温度
        {DEV_NO_EMS, STOP_END_HOT_TEMP   ,   "TEMP for heating stop in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x701, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制冷启动温度
        {DEV_NO_EMS, STOP_START_COOL_TEMP,   "TEMP for cooling start-up in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x702, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制冷停止温度
        {DEV_NO_EMS, STOP_END_COOL_TEMP  ,   "TEMP for cooling stop in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x703, TYPE_INT,   ORDER_AB,   1, -100, 100},



        //工作段制热目标温度
        {DEV_NO_EMS, WORK_DIST_HOT_TEMP    ,    "Work Heating target temperature(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x39, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //工作段制冷目标温度
        {DEV_NO_EMS, WORK_DIST_COOL_TEMP   ,    "Work Cooling target temperature(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x3a, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制热目标温度
        {DEV_NO_EMS, STOP_DIST_HOT_TEMP    ,    "Heating target TEMP in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x704, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制冷目标温度
        {DEV_NO_EMS, STOP_DIST_COOL_TEMP   ,    "Cooling target TEMP in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x705, TYPE_INT,   ORDER_AB,   1, -100, 100},
        // {DEV_NO_EMS, PREPARE_DIST_HOT_TEMP ,"预热段制热目标温度",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x44, TYPE_INT,   ORDER_AB,   1},
        // {DEV_NO_EMS, PREPARE_DIST_COOL_TEMP,"预热段制冷目标温度",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x45, TYPE_INT,   ORDER_AB,   1},
        //使能空调控制
        {DEV_NO_EMS, ENABLE_AIR_COND,          "Enable AC control",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,        "off", "0:Disabled;1:Enabled;",              0x03, 0x3b, TYPE_INT,   ORDER_AB,   1},
        //空调提前启动时间
        {DEV_NO_EMS, AIR_COND_AHEAD_TIME,      "AC early start time(min)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,     "off", "",              0x03, 0x3c, TYPE_INT,   ORDER_ABCD,   1, 0, 600},
        //防逆流滑动窗口
        {DEV_NO_EMS, PROTECT_REVERSE_WIN,      "Anti-backflow sliding window(s)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,     "off", "",              0x03, 0x3e, TYPE_UINT,   ORDER_AB,   1},
        
        //最大需量
        {DEV_NO_EMS, MAX_DEMAND,               "Maximum demand(kW)",         O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,                  "off", "",                 0x03, 0x3f, TYPE_INT, ORDER_ABCD, 1},
        //光伏总最大功率
        {DEV_NO_EMS, PV_MAX_POWER,             "Rated power of PV(kW)",   O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,       "off", "",                 0x03, 0x41, TYPE_FLOAT, ORDER_ABCD, 1, 0, 10000},
        //需量滑动窗口
        {DEV_NO_EMS, DEMAND_WIN,               "Demand sliding window(s)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,        "off", "",              0x03, 0x43, TYPE_UINT,   ORDER_AB,   1},
        //使能BMS功率限制
        {DEV_NO_EMS, BMS_POWER_LIMIT,          "Enable BMS power limitation",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;",   0x03, 0x44, TYPE_INT,   ORDER_AB,   1},
        //使能低压需量控制
        {DEV_NO_EMS, ENPROTECTRASLV ,          "Enable low voltage demand control",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,   "off", "0:Disabled;1:Enabled;",0x03, 0x45, TYPE_INT,   ORDER_AB,   1},
        //低压变压器容量
        {DEV_NO_EMS, PLVMLMAX ,                "Low voltage transformer capacity(kVA)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,   "off", "",                  0x03, 0x46, TYPE_INT,   ORDER_AB,   1, 0, 10000},
        //低压需量控制系数
        {DEV_NO_EMS, EMS_K4 ,                  "Low voltage demand control factor(%)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,   "off", "",                0x03, 0x47, TYPE_INT,   ORDER_AB,   1, 0, 100},
        //空调延后关机时间
        {DEV_NO_EMS, AIR_COND_DELAY_TIME,      "Delayed shutdown time of AC(min)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,     "off", "",              0x03, 0x48, TYPE_INT,   ORDER_ABCD,   1, 0, 600},
        //自循环启动温差
        {DEV_NO_EMS, START_SELF_LOOP_DIFF,      "Start self circulating TEMP difference(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x4a, TYPE_FLOAT,  ORDER_ABCD,   1, -100, 100},
        //自循环停止温差
        {DEV_NO_EMS, END_SELF_LOOP_DIFF,        "End self circulating TEMP difference(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x707, TYPE_FLOAT,  ORDER_ABCD,   1, -100, 100},
        
        //单体过压保护阈值
        {DEV_NO_EMS, SINGLE_MAX_VOLTAGE,       "Single cell Over-V protect threshold(V)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x4c, TYPE_FLOAT,   ORDER_ABCD,   1, 0, 10},
        //单体欠压保护阈值
        {DEV_NO_EMS, SINGLE_MIN_VOLTAGE,       "Single cell Under-V protect threshold(V)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x4e, TYPE_FLOAT,   ORDER_ABCD,   1, 0, 10},
        //使能单体电压保护
        {DEV_NO_EMS, EN_CELL_VOLT_PROTECT,     "Enable single cell voltage protection",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;",                      0x03, 0x50, TYPE_INT,   ORDER_AB,   1},
        //单体过压保护偏差
        {DEV_NO_EMS, SINGLE_MAX_VOLTAGE_ERR,   "Single cell Over-V protect difference(V)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x51, TYPE_FLOAT,   ORDER_ABCD,   1, 0, 10},
        //单体欠压保护偏差
        {DEV_NO_EMS, SINGLE_MIN_VOLTAGE_ERR,   "Single cell Under-V protect difference(V)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x53, TYPE_FLOAT,   ORDER_ABCD,   1, 0, 10},
        //禁止放电SOC回差
        {DEV_NO_EMS, EMS_SOCMINERR,            "SOC Prohibited discharging difference(%)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "",                              0x03, 0x55, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
        //禁止充电SOC回差
        {DEV_NO_EMS, EMS_SOCMAXERR,            "SOC Prohibited charging difference(%)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "",                              0x03, 0x57, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
        // 系统最大放电功率
        {DEV_NO_EMS, DISCHARGE_THRES_HOLD,     "Maximum discharge power of the system(kW)",   O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x5b, TYPE_FLOAT, ORDER_ABCD, 1, 0, 10000},
        // 系统最大充电功率
        {DEV_NO_EMS, CHARGE_MAX_POWER,         "Maximum charging power of the system(kW)",   O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x5d, TYPE_FLOAT, ORDER_ABCD, 1, 0, 10000},
        // 需量门限所使用的缓冲值(类比防逆流余量)
        {DEV_NO_EMS, DEMAND_MARGIN,             "Demand Margin(kW)",                        O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x5f, TYPE_INT, ORDER_AB, 1, 0, 10000},
        // 动态增容余量
        {DEV_NO_EMS, DYNAMIC_AUGMENT,          "Dynamic increase allowance(kW)",        O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",                                   0x03, 0x60, TYPE_INT, ORDER_AB, 1},
        // 事故反演时间颗粒度
        {DEV_NO_EMS, ACCIDENT_TGI,          "Time granularity of accident inversion",        O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",                                   0x03, 0x61, TYPE_INT, ORDER_AB, 1},
        // 事故反演本地使能开关
        {DEV_NO_EMS, ACCIDENT_EN,          "Local enable switch for accident inversion",        O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",                                   0x03, 0x62, TYPE_INT, ORDER_AB, 1},
        // 装机功率比例
        {DEV_NO_EMS, INSPOW_COEF,            "Proportion of installed capacity",        O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x63, TYPE_INT,   ORDER_AB,   1},
        // 单体电压保护延时, 只有vlc才会生效
        {DEV_NO_EMS, CELL_VOLT_PROTECT_TIME,            "Single cell voltage protection  delay time(s)",        O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",        0x03, 0x64, TYPE_INT,   ORDER_AB,   1},
        //是否被主机禁用
        {DEV_NO_EMS, ISDISABLE_BY_MASTER,            "is disabled by the master",        O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:no;1:yes;",                      0x03, 0x65, TYPE_INT,   ORDER_AB,   1},
        //使能单相防逆流
        {DEV_NO_EMS, ENABLE_SINGLE_PHASE_REVERSE, "enable single phase reverse",    O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;",                      0x03, 0x66, TYPE_INT,   ORDER_AB,   1},
        //设置A相功率
        {DEV_NO_EMS, SET_PHASE_A_POWER,         "Set active power of phase A(kW)",  O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,    "off", "",                  0x03, 0x67, TYPE_FLOAT,   ORDER_ABCD,   1},
        //设置B相功率
        {DEV_NO_EMS, SET_PHASE_B_POWER,         "Set active power of phase B(kW)",  O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,    "off", "",                  0x03, 0x69, TYPE_FLOAT,   ORDER_ABCD,   1},
        //设置C相功率
        {DEV_NO_EMS, SET_PHASE_C_POWER,         "Set active power of phase C(kW)",  O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,    "off", "",                  0x03, 0x6b, TYPE_FLOAT,   ORDER_ABCD,   1},

         // (设置动作)
        //开关机
        {DEV_NO_EMS, ON_OFF_STATE,         "Power on/off",            O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,   "both", "0:Off;1:On;",         0x03, 0x100, TYPE_INT,   ORDER_AB,   1},
        //设置有功功率
        {DEV_NO_EMS, SET_ACT_POWER,        "Set active power(kW)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,  "off", "",                     0x03, 0x102, TYPE_FLOAT, ORDER_ABCD, 1},
        //设置无功功率
        {DEV_NO_EMS, SET_REACTPOWER,       "Set reactive power(kVar)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,  "off", "",                     0x03, 0x104, TYPE_FLOAT, ORDER_ABCD, 1},
        //设置并离网模式
        {DEV_NO_EMS, SET_CONNECT,          "Set on/off-grid mode",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "both", "0:Off-grid;1:On-grid;",        0x03, 0x106, TYPE_INT,   ORDER_AB,    1},
        //清除保护
        {DEV_NO_EMS, CLEAR_ALARM,          "Clear all protections",          O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                     0x03, 0x107, TYPE_INT,   ORDER_AB,   1},
        //使能动环保护
        {DEV_NO_EMS, EN_IO_PROTECT,        "Enable dynamic environment protection",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Disabled;1:Enabled;",         0x03, 0x108, TYPE_INT,   ORDER_AB,   1},     
        //液冷机控制
        {DEV_NO_EMS, TMS_CTRL_STATE,     "Liquid cooling control",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Standby;1:Cooling;2:Heating;3:Pump circulation;4:fully automatic;", 0x03, 0x10a, TYPE_INT,   ORDER_AB,   1},     
        //脱扣
        {DEV_NO_EMS, TRIP    ,             "Trip",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,        "off", "",              0x03, 0x10c, TYPE_INT,   ORDER_AB,   1},     
        //限制光伏功率百分比
        {DEV_NO_EMS, SET_PV_POWER,         "Restrict PV power percentage",O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,  "off", "",              0x03, 0x10f,TYPE_FLOAT, ORDER_AB, 1},
        //开始充电功率
        {DEV_NO_EMS, EMS_CHARGE_STARTPOWER, "Starting charging power(kW)",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",      0x03, 0x110, TYPE_INT,   ORDER_AB,   1},
        //开始放电功率
        {DEV_NO_EMS, EMS_DISCHARGE_THRESHOLD, "Starting discharge power(kW)",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",    0x03, 0x111, TYPE_INT,   ORDER_AB,   1},
        //风机
        {DEV_NO_EMS, FAN,                   "Fan",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",             0x03, 0x112, TYPE_INT,   ORDER_AB,   1},
        //输出制冷目标温度
        {DEV_NO_EMS, TMS_CTRL_DIST_TEMP_COLD ,  "Output cooling target temperature(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x113, TYPE_INT,   ORDER_AB,   1},
        //输出制热目标温度
        {DEV_NO_EMS, TMS_CTRL_DIST_TEMP_HOT ,  "Output heating target temperature(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x114, TYPE_INT,   ORDER_AB,   1},
        //BMS上下高压
        {DEV_NO_EMS, BMS_UPPER,          "Set BMS HV_Connect",            O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,   "both", "0:HV connect;1:HV disconnect;",         0x03, 0x115, TYPE_INT,   ORDER_AB,   1},
        //启用无功补偿
        {DEV_NO_EMS, EN_RP_COMP,       "enable repower compensate",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Disabled;1:Enabled;",         0x03, 0x116, TYPE_INT,   ORDER_AB,   1},     
        // 设置功率因数
        {DEV_NO_EMS, SET_POWER_FACTOR,        "Set power factor",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,  "off", "",                     0x03, 0x117, TYPE_FLOAT, ORDER_ABCD, 1},
        // 使能数据汇聚
        {DEV_NO_EMS, EN_DATA_COLLECT,        "Enable data collect",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "0:Disabled;1:Enabled;",                     0x03, 0x119, TYPE_INT, ORDER_AB, 1},
        // G100 使能
        {DEV_NO_EMS, G100_ENABLE,            "G100 Enable",                     O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Disabled;1:Enabled;",      0x03, 0x11b, TYPE_INT,   ORDER_AB,   1}, 
        // G100 锁定后允许解锁时间
        {DEV_NO_EMS, G100_UNLOCK_TIME,       "G100 Allow Unlock Time(min)",     O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x11c, TYPE_INT,   ORDER_AB,   1}, 
        // G100 30天内允许的复位次数
        {DEV_NO_EMS, G100_MAXCOUNT_MON,      "G100 Max Reset Count in 30 Days",       O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x11d, TYPE_INT,   ORDER_AB,   1}, 
        // G100 10分钟内允许的异常次数
        {DEV_NO_EMS, G100_MAXCOUNT_10MIN,    "G100 Max Abnormal Count in 10 Minutes",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x11e, TYPE_INT,   ORDER_AB,   1}, 
        // G100  1天内允许的异常次数
        {DEV_NO_EMS, G100_MAXCOUNT_DAY,      "G100 Max Abnormal Count in 1 Day",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x11f, TYPE_INT,   ORDER_AB,   1}, 
        // G100 逆流滤波值
        {DEV_NO_EMS, G100_BACKFLOW_LIMIT,    "G100 Backflow Limit(kW)",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x120, TYPE_INT,   ORDER_AB,   1, 0, 1000}, 
        // G100 逆流滤波时间
        {DEV_NO_EMS, G100_BACKFLOW_SEC,      "G100 Backflow Filter Time(s)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x121, TYPE_INT,   ORDER_AB,   1, 0, 1000}, 
        // G100 逆流锁定时间
        {DEV_NO_EMS, G100_BACKFLOW_LOCK_TIME,"G100 Backflow Lock Time(s)",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x122, TYPE_INT,   ORDER_AB,   1}, 
        // G100 过载滤波值
        {DEV_NO_EMS, G100_OVERLOAD_LIMIT,    "G100 Overload Limit(kVA)",       O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x123, TYPE_INT,   ORDER_AB,   1, 0, 1000}, 
        // G100 过载滤波时间
        {DEV_NO_EMS, G100_OVERLOAD_SEC,      "G100 Overload Filter Time(s)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x124, TYPE_INT,   ORDER_AB,   1, 0, 1000}, 
        // G100 过载锁定时间
        {DEV_NO_EMS, G100_OVERLOAD_LOCK_TIME,"G100 Overload Lock Time(s)",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x125, TYPE_INT,   ORDER_AB,   1}, 
        // 热管理控制周期
        {DEV_NO_EMS, HEAT_CTR_CYCLE,         "Heat Ctrol Cycle Time(s)",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                           0x03, 0x126, TYPE_INT,   ORDER_AB,   1, 0, 600}, 
        // IEC104 心跳
        {DEV_NO_EMS, IEC104_HEARTBEAT,       "Iec104 Heartbeat bit",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "Switch between 0 and 1 every 5 seconds.",                           0x03, 0x127, TYPE_INT,   ORDER_AB,   1}, 
        // ModbusTcp 心跳
        {DEV_NO_EMS, MODBUSTCP_HEARTBEAT,    "ModbusTcp Heartbeat bit",   O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "Switch between 0 and 1 every 5 seconds.",                           0x03, 0x128, TYPE_INT,   ORDER_AB,   1}, 
        
        // 使能逆流转充
        {DEV_NO_EMS, EN_SW_D2C,         "Enable Adverse current To Charge",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Disabled;1:Enabled;",                           0x03, 0x129, TYPE_INT,   ORDER_AB,   1}, 
        // 使能超容转放
        {DEV_NO_EMS, EN_SW_C2D,         "Enable Super capacity To Discharge",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Disabled;1:Enabled;",                           0x03, 0x12a, TYPE_INT,   ORDER_AB,   1}, 
        //限制功率
        {DEV_NO_EMS, POWER_LIMIT,         "Limited power",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,    "off", "",        0x03, 0x12b, TYPE_FLOAT,   ORDER_ABCD,   1},        
        //清除手动保护
        {DEV_NO_EMS, LC_CLR_MANUAL_PROTECT,          "Clear manual protection",          O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                     0x03, 0x12d, TYPE_INT,   ORDER_AB,   1},
        //PCS故障复位
        {DEV_NO_EMS, PCS_FAULT_RESET,          "PCS fault reset",          O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                     0x03, 0x140, TYPE_INT,   ORDER_AB,   1},
        //使能动态功率因数调节
        {DEV_NO_EMS, EN_DYNAMICPOWFA_COR,        "enable power factor correction",          O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Disabled;1:Enabled;",                  0x03, 0x12e, TYPE_INT,   ORDER_AB,   1},
        //功率因数目标值
        {DEV_NO_EMS, POWERTARGET_VALUE,          "power factor target value",          O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,    "off", "",                     0x03, 0x12f, TYPE_FLOAT,   ORDER_ABCD,   1},
        //功率因数回差
        {DEV_NO_EMS, POWERFACTOR_DEVIATION,      "power factor deviation",          O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,    "off", "",                        0x03, 0x131, TYPE_FLOAT,   ORDER_ABCD,   1},
        //功率因数调整周期
        {DEV_NO_EMS, POWERFACTOR_ADJ_PER,        "power factor adjustment period(s)",          O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                  0x03, 0x133, TYPE_INT,   ORDER_AB,   1},


        {DEV_NO_EMS, UD_LOG,                         "ud log",                           O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                     0x03, 0x141, TYPE_INT,   ORDER_AB,   1},

        {DEV_NO_EMS, SURPLUS_POWER,             "Power of surplus to Grid(kW)",                           O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "", "",                     0x03, 0x142, TYPE_INT,   ORDER_AB,   1},
        
        // 只读点位
        //系统运行状态
        {DEV_NO_EMS, SYSTEM_STATUS,        "System operating status",     O_RDONLY, EMS_POINT_INT,   PROPERTY_REALDATA, "off", "0:Normal;1:Abnormal;",                 0x04, 0x00, TYPE_INT,   ORDER_AB,    1},
        //逆流窗口功率
        {DEV_NO_EMS, GRID_ACT_POWER,       "Anti-backflow window power(kW)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",                             0x04, 0x01, TYPE_FLOAT, ORDER_ABCD, 1},
        //负载功率
        {DEV_NO_EMS, LOAD_ACT_POWER,       "Load power(kW)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",                             0x04, 0x03, TYPE_FLOAT, ORDER_ABCD, 1},
        //期望有功功率
        {DEV_NO_EMS, EXPECT_ACT_POWER,     "Expected active power(kW)",     O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",                             0x04, 0x05, TYPE_FLOAT, ORDER_ABCD,  1},
        //LC输入功率
        {DEV_NO_EMS, LOCAL_CTRL_POWER,     "LC input power(kW)",       O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,  "both", "",                            0x04, 0x07, TYPE_FLOAT,  ORDER_ABCD, 1},
        //额定功率
        {DEV_NO_EMS, CAB_POWER ,           "Rated power(kW)",         O_RDONLY,EMS_POINT_INT,     PROPERTY_REALDATA , "off",   "" ,                            0x04, 0x09, TYPE_INT,    ORDER_AB,    1},
        //额定容量
        {DEV_NO_EMS, CAB_CAPACITY  ,       "Rated capacity(kWh)",         O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                                0x04, 0x0a, TYPE_INT,   ORDER_AB,   1},
        //告警数量
        {DEV_NO_EMS, ALARMCNT,             "Number of alarms",         O_RDONLY, EMS_POINT_INT,   PROPERTY_REALDATA,    "off", "",                              0x04, 0x0e, TYPE_INT,   ORDER_AB,   1},
        //历史告警数量
        {DEV_NO_EMS, ALARMHISCNT,  "Number of historical alarms", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "",                                0x04, 0x0d, TYPE_INT, ORDER_AB, 1},
        //禁充保护
        {DEV_NO_EMS, PROHIBITE_CHARGE,     "Prohibited charging protection",          O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Unprotected;1:Protected;",                 0x04, 0x0f, TYPE_INT, ORDER_AB, 1},
        //禁放保护
        {DEV_NO_EMS, PROHIBITE_DISCHARGE,  "Prohibited discharging protection",          O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Unprotected;1:Protected;",                 0x04, 0x10, TYPE_INT, ORDER_AB, 1},
        //上次充放功率
        //{DEV_NO_EMS, LAST_CHADISCHA_STA,   "Last charge and discharge power(kW)",       O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "",                 0x04, 0x11, TYPE_INT, ORDER_AB, 1},
        //DOD保护
        {DEV_NO_EMS, DOD_LIMITED,          "DOD protection",          O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x04, 0x12, TYPE_UINT, ORDER_AB, 1},
        //直流总压异常
        {DEV_NO_EMS, DC_TOTAL_VOL_LOW,     "DC total voltage abnormal",     O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",     0x04, 0x14, TYPE_UINT, ORDER_AB, 1},
        //最大可充功率
        {DEV_NO_EMS, MAX_CHARGE_POWER  ,   "Maximum rechargeable power(kW)",     O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",               0x04, 0x15, TYPE_FLOAT, ORDER_ABCD, 1},
        //最大可放功率
        {DEV_NO_EMS, MAX_DISCHA_POWER  ,   "Maximum dischargable power(kW)",     O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",               0x04, 0x17, TYPE_FLOAT, ORDER_ABCD, 1},
        //光伏设置百分比
        {DEV_NO_EMS, PV_CUR_PERCENT,         "Set PV percentage(%)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,  "change", "",              0x04, 0x19, TYPE_INT, ORDER_ABCD, 1},
        //EMS周期心跳指示
        {DEV_NO_EMS, EMS_CIRCLE_BEAT,      "EMS cycle heartbeat indicator", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x4, 0x21, TYPE_INT, ORDER_ABCD, 1},
        //PCS总有功功率
        {DEV_NO_EMS, PCS_ACTIVEPOWER,      "PCS total active power(kW)",  O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "period", "",  0x4, 0x23, TYPE_FLOAT, ORDER_AB, 1},
        //PCS总无功功率
        {DEV_NO_EMS, PCS_REACTIVEPOWER,    "PCS total reactive power(kVar)",  O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "period", "",  0x4, 0x24, TYPE_FLOAT, ORDER_AB, 1},
        //系统运行状态字
        {DEV_NO_EMS, SYSTEM_STATUS_W,        "System operation status word",     O_RDONLY, EMS_POINT_INT,   PROPERTY_REALDATA, "off", "",         0x04, 0x25, TYPE_INT,   ORDER_ABCD,    1},
        //总有功功率
        {DEV_NO_EMS, TOTAL_ACTIVE_POWER,    "System total active power(kW)",  O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "period", "",  0x4, 0x27, TYPE_FLOAT, ORDER_ABCD, 1},
        //总无功功率
        {DEV_NO_EMS, TOTAL_REACTIVE_POWER,  "System total reactive power(kVar)",  O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "period", "",  0x4, 0x29, TYPE_FLOAT, ORDER_ABCD, 1},
        //总正向电能
        {DEV_NO_EMS, TOTAL_FORWARD_ENERGY,    "Total positive electrical energy(kWh)",  O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",  0x4, 0x3b, TYPE_FLOAT, ORDER_ABCD, 1},
        //总反向电能
        {DEV_NO_EMS, TOTAL_REVERSE_ENERGY,    "Total reverse electrical energy(kWh)",  O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",  0x4, 0x3d, TYPE_FLOAT, ORDER_ABCD, 1},
        // 当前SOC
        {DEV_NO_EMS, CURRENT_SOC, "SOC", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x55, TYPE_FLOAT, ORDER_ABCD, 1},
        // 开关机状态
        {DEV_NO_EMS, ON_OFF_STATUS, "On/Off Status", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Off;1:On;", 0x04, 0x57, TYPE_INT, ORDER_AB, 1},
        // 有功功率
        {DEV_NO_EMS, ACTIVE_POWER, "active power(kW)", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x58, TYPE_INT, ORDER_ABCD, 1},
        // 无功功率
        {DEV_NO_EMS, REACTIVE_POWER, "reactive power(kVar)", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x5a, TYPE_INT, ORDER_ABCD, 1},
        // DOD禁充保护
        {DEV_NO_EMS, DOD_LIMITED_CH, "DOD prohibited charging protection", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Unprotected;1:Protected;", 0x04, 0x5c, TYPE_INT, ORDER_AB, 1},
        // DOD禁放保护
        {DEV_NO_EMS, DOD_LIMITED_DC, "DOD prohibited discharging protection", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Unprotected;1:Protected;", 0x04, 0x5d, TYPE_INT, ORDER_AB, 1},
        // 手动保护
        {DEV_NO_EMS, LC_MANUAL_PROTECT, "Manual protection", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Unprotected;1:Protected;", 0x04, 0x5e, TYPE_INT, ORDER_AB, 1},

        // G100 状态
        {DEV_NO_EMS, G100_LOCK_STATE,        "G100 Lock State",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_REALDATA, "off",      "0:Normal;1:Locked;2:ADLock;", 0x04, 0x60, TYPE_INT, ORDER_AB, 1},
        // G100 异常状态
        {DEV_NO_EMS, G100_ABNORMAL_STATE,    "G100 Abnormal State",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_REALDATA, "off","0:Normal;1:Backflow;2:Overload;" , 0x04, 0x62, TYPE_INT, ORDER_AB, 1},
        // G100 30天内复位次数
        {DEV_NO_EMS, G100_RESET_COUNT, "G100 Reset count in 30 day",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_REALDATA, "off","" , 0x04, 0x63, TYPE_INT, ORDER_AB, 1},
        // G100 10分钟内异常次数
        {DEV_NO_EMS, G100_COUNT_10MIN, "G100 Abnormal count in 10 min",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_REALDATA, "off","" , 0x04, 0x64, TYPE_INT, ORDER_AB, 1},
        // G100 一天内异常次数
        {DEV_NO_EMS, G100_COUNT_DAY,   "G100 Abnormal count in day",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_REALDATA, "off","" , 0x04, 0x65, TYPE_INT, ORDER_AB, 1},
        // 并离网状态
        {DEV_NO_EMS, CONNECT_STATUS, "Connect Status", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Off-grid;1:On-grid;", 0x04, 0x66, TYPE_INT, ORDER_AB, 1},
         //A相功率
         {DEV_NO_EMS, PHASE_A_POWER, "phase a power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x67, TYPE_INT, ORDER_ABCD, 1},
         //B相功率
         {DEV_NO_EMS, PHASE_B_POWER, "phase b power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x69, TYPE_INT, ORDER_ABCD, 1},
         //C相功率
         {DEV_NO_EMS, PHASE_C_POWER, "phase c power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x6B, TYPE_INT, ORDER_ABCD, 1},


        //状态机当前状态
        // {DEV_NO_EMS, STATE_ MACHINE,     "State Machine",      O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "1:并网;2:纯离网;4:初始状态;0:待机;", 0x04, 0x53, TYPE_INT,   ORDER_AB,   1},
        //
        // 只读信号量
        //EMS限功率运行
        // {DEV_NO_EMS, POWER_LIMITED,      "EMS running in limited power",     O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Unrestricted;1:Restricted;", 0x02, 0x00, TYPE_BOOL, ORDER_A, 1},
        //EMS逆流运行
        // {DEV_NO_EMS, POWER_REFLUX,       "EMS running in backflow",       O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:No backflow;1:Backflow occurred;", 0x02, 0x01, TYPE_BOOL, ORDER_A, 1},
        //手动保护
        {DEV_NO_EMS, SYS_STOPED,         "EMS manual protection",     O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x02, 0x02, TYPE_BOOL, ORDER_A, 1},
        //电表故障
        {DEV_NO_EMS, METER_ERROR,        "PCS-meter malfunction",          O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",     0x02, 0x06, TYPE_BOOL,  ORDER_A, 1},
        //动环保护
        {DEV_NO_EMS, IO_PROTECT,         "Dynamic environment protection",          O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x02, 0x08, TYPE_BOOL, ORDER_A, 1},
        //自定义提示1
        {DEV_NO_EMS, USER_ALARM1,        "Custom Tip 1",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "",                    0x02, 0x09,  TYPE_BOOL, ORDER_A,   1},
        //自定义提示2
        {DEV_NO_EMS, USER_ALARM2,        "Custom Tip 2",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "",                    0x02, 0x0a,  TYPE_BOOL, ORDER_A,   1},
        //自定义提示3
        {DEV_NO_EMS, USER_ALARM3,        "Custom Tip 3",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "",                    0x02, 0x0b,  TYPE_BOOL, ORDER_A,   1},
        //自定义停机1
        {DEV_NO_EMS, USER_STOP1 ,        "Custom Shutdown 1",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x0c,  TYPE_BOOL, ORDER_A,   1},
        //自定义停机2
        {DEV_NO_EMS, USER_STOP2 ,        "Custom Shutdown 2",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x0d,  TYPE_BOOL, ORDER_A,   1},
        //自定义停机3
        {DEV_NO_EMS, USER_STOP3 ,        "Custom Shutdown 3",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x0e,  TYPE_BOOL, ORDER_A,   1},
        //自定义告警
        {DEV_NO_EMS, USER_ALARM ,        "Custom alarm",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x0f,  TYPE_BOOL, ORDER_A,   1},
        //自定义提示告警
        {DEV_NO_EMS, USER_NOTICE_ALARM , "Custom prompt alarm",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x50,  TYPE_BOOL, ORDER_A,   1},
        //自定义重要告警
        {DEV_NO_EMS, USER_VITAL_ALARM ,  "Custom important alarm",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x51,  TYPE_BOOL, ORDER_A,   1},
        //自定义严重告警
        {DEV_NO_EMS, USER_SERVER_ALARM , "Custom critical alarm",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x52,  TYPE_BOOL, ORDER_A,   1},
 
        // {DEV_NO_EMS, ,          "柜消防灭火告警", O_RDONLY, EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:正常;1:异常",   0x02, 0x0f,  TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS,  ,          "柜消防急停联动", O_RDONLY, EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:正常;1:异常",   0x02, 0x10,  TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, PCS_LINK_ERR,        "PCS通讯故障",    O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:正常;1:异常",     0x02, 0x11, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_LINK_ERR,        "BMS通讯故障",    O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:正常;1:异常", 0x02, 0x12, TYPE_BOOL, ORDER_A, 1},
        //总消防
        {DEV_NO_EMS, ALL_FIRE,            "Host fire system",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x14, TYPE_BOOL, ORDER_A, 1},
        //外部消防
        {DEV_NO_EMS, EXTERN_FIRE,         "External fire system",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x15, TYPE_BOOL, ORDER_A, 1},
        //本机消防
        {DEV_NO_EMS, FIRE,                "Local fire protection",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x16, TYPE_BOOL, ORDER_A, 1},
        //温控系统异常
        {DEV_NO_EMS, TEMP_CTRL_ERR,       "Temperature control system abnormal",O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x1d, TYPE_BOOL, ORDER_A, 1},
        //空调启停控制
        {DEV_NO_EMS, AIR_COND_STARTSTOP_CTRL, "AC control", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Off;1:On;", 0x02, 0x1e, TYPE_BOOL, ORDER_A, 1},
        // 系统电源
        {DEV_NO_EMS, EMS_POWER,           "System power",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x1f, TYPE_BOOL, ORDER_A, 1},
        {DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, "Single cell voltage threshold alarm", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x20, TYPE_BOOL, ORDER_A, 1},
        // CPU使用率过高
        {DEV_NO_EMS, EMS_CPU_HIGH,           "CPU usage rate high",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x27, TYPE_BOOL, ORDER_A, 1},
        // 内存使用率过高
        {DEV_NO_EMS, EMS_MEM_HIGH,           "Memory usage rate high",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x28, TYPE_BOOL, ORDER_A, 1},
        // 磁盘使用率过高
        {DEV_NO_EMS, EMMC_DISK_HIGH,           "EMMC usage rate high",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x29, TYPE_BOOL, ORDER_A, 1},
        {DEV_NO_EMS, SSD_DISK_HIGH,           "SSD usage rate high",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x2a, TYPE_BOOL, ORDER_A, 1},
        //硬盘不存在
        {DEV_NO_EMS, SSD_NOT_EXIST,           "SSD not exist",   O_RDONLY,       EMS_POINT_INT,  PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x02, 0x31, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_PACK_ALARM"1",  "Pack1消防告警",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "", 0x02, 0x13, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_PACK_ALARM"2",  "Pack2消防告警",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "", 0x02, 0x14, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_PACK_ALARM"3",  "Pack3消防告警",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "", 0x02, 0x15, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_PACK_ALARM"4",  "Pack4消防告警",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "", 0x02, 0x16, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_PACK_ALARM"5",  "Pack5消防告警",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "", 0x02, 0x17, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_PACK_ALARM"6",  "Pack6消防告警",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "", 0x02, 0x18, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_PACK_ALARM"7",  "Pack7消防告警",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "", 0x02, 0x19, TYPE_BOOL, ORDER_A, 1},
        // {DEV_NO_EMS, BMS_PACK_ALARM"8",  "Pack8消防告警",      O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "", 0x02, 0x1a, TYPE_BOOL, ORDER_A, 1},
        
        //自定义充电时停机1
        {DEV_NO_EMS, USER_STOP_CHA1 ,        "Custom Shutdown in Charge1",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x21,  TYPE_BOOL, ORDER_A,   1},
        //自定义放电时停机2
        {DEV_NO_EMS, USER_STOP_DISCHA1 ,        "Custom Shutdown in Discharge1",  O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x22,  TYPE_BOOL, ORDER_A,   1},
        //自定义充电时停机3
        {DEV_NO_EMS, USER_STOP_CHA2 ,        "Custom Shutdown in Charge2",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x23,  TYPE_BOOL, ORDER_A,   1},
        //自定义放电时停机1
        {DEV_NO_EMS, USER_STOP_DISCHA2 ,        "Custom Shutdown in Discharge2",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x24,  TYPE_BOOL, ORDER_A,   1},
        //自定义充电时停机2
        {DEV_NO_EMS, USER_STOP_CHA3 ,        "Custom Shutdown in Charge3",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x25,  TYPE_BOOL, ORDER_A,   1},
        //自定义放电时停机3
        {DEV_NO_EMS, USER_STOP_DISCHA3 ,        "Custom Shutdown in Discharge3",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x26,  TYPE_BOOL, ORDER_A,   1},
        //策略SOC限制超出保护范围
        {DEV_NO_EMS, SOC_LIMIT_ALARM ,        "Soc exceeds the protection parameter limit",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x2b,  TYPE_BOOL, ORDER_A,   1},
        //充放电状态
        {DEV_NO_EMS, CH_DISCH_STATUS ,        "Charge/Discharge status",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_REALDATA, "off", "0:Idle;1:Charge;2:Discharge;",  0x02, 0x2c,  TYPE_BOOL, ORDER_A,   1},
        //从机系统状态
        {DEV_NO_EMS, LC_SYSTEM_STATUS ,        "LC system status",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_REALDATA, "off", "0:Normal;1:Abnormal;",  0x02, 0x2d,  TYPE_BOOL, ORDER_A,   1},
        //北向连接告警
        {DEV_NO_EMS, WHITELIST_ALARM ,        "Northbound connection alarm",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x2e,  TYPE_BOOL, ORDER_A,   1},
        //北向iec104连接告警
        {DEV_NO_EMS, IEC104_CONN_ALARM ,        "North Iec104 connection alarm",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x2f,  TYPE_BOOL, ORDER_A,   1},
        //北向modbusTcp连接告警
        {DEV_NO_EMS, MODBUSTCP_CONN_ALARM ,     "North ModbusTcp connection alarm",   O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;",  0x02, 0x30,  TYPE_BOOL, ORDER_A,   1},
        // 当前SOH
        {DEV_NO_EMS, CURRENT_SOH, "SOH", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x02, 0x36, TYPE_INT, ORDER_AB, 1},
};
const int g_ems_base_variant_count = sizeof(ems_base_variant) / sizeof(ems_base_variant_t);

ems_base_variant_t ems_microgri_variant[] =
{
    //并离网识别反馈
    {DEV_NO_EMS, CONN_SIGN,    "conn sign",     O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:disconnect;1:connect;", 0x04, 0x300, TYPE_INT, ORDER_AB, 1},
    //ATS反馈
    {DEV_NO_EMS, ATS_SIGN,     "ats sign",      O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:second;1:primary;", 0x04, 0x301, TYPE_INT, ORDER_AB, 1},
    //负载断路器反馈
    {DEV_NO_EMS, LCB_SIGN,     "lcb sign",      O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:off;1:on;", 0x04, 0x302, TYPE_INT, ORDER_AB, 1},
    //并离网断路器反馈
    {DEV_NO_EMS, ICB_SIGN,     "icb sign",      O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:off;1:on;", 0x04, 0x303, TYPE_INT, ORDER_AB, 1},
    //柴发启停反馈
    {DEV_NO_EMS, DG_SIGN,      "DG sign",       O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:stop;1:start;", 0x04, 0x304, TYPE_INT, ORDER_AB, 1},
    //微网状态机状态
    {DEV_NO_EMS, STATE_MACHINE,    "StateMachine status",     O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:待机状态;1:市电并网状态;2:离网状态;3:柴发并网状态;4:初始状态;5:异常状态;6:默认;", 0x04, 0x305, TYPE_INT, ORDER_AB, 1},  

    //并离网断路器控制
    {DEV_NO_EMS, ICB_CTRL,      "icb ctrl",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,   "off", "",         0x03, 0x306, TYPE_INT, ORDER_AB, 1},
    //负载断路器控制
    {DEV_NO_EMS, LCB_CTRL,      "lcb ctrl",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "",          0x03, 0x307, TYPE_INT, ORDER_AB, 1},
    //柴发控制
    {DEV_NO_EMS, DG_CTRL,       "DG ctrl",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "",            0x03, 0x308, TYPE_INT, ORDER_AB, 1},
	
	//总光伏功率-- 功率汇总--便于多柜调试
    {DEV_NO_EMS, TOTAL_PV_POWER,    "Total Pv Power(kW)",  O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x309, TYPE_FLOAT, ORDER_ABCD, 1},
    //总储能功率
    {DEV_NO_EMS, TOTAL_PCS_POWER,   "Total Pcs Power(kW)", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x30b, TYPE_FLOAT, ORDER_ABCD, 1},
    //平均SOC
    {DEV_NO_EMS, AVER_SOC,    "Aver Soc",     O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x30d, TYPE_FLOAT, ORDER_ABCD, 1}, 

    //使能交流放转充
    //{DEV_NO_EMS, EN_AC_D2C,      "Enable discharge to charge",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "0:Disabled;1:Enabled;",          0x03, 0x30f, TYPE_INT, ORDER_AB, 1},
    //使能交流充转放
    //{DEV_NO_EMS, EN_AC_C2D,      "Enable charge to discharge",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "0:Disabled;1:Enabled;",            0x03, 0x310, TYPE_INT, ORDER_AB, 1},

    // 离网SOC上限
    {DEV_NO_EMS, SOC_NET_DEAD_MAX,         "Off-grid SOC Upper limit(%)",   O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x311, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
    // 离网SOC下限
    {DEV_NO_EMS, SOC_NET_DEAD_MIN,         "Off-grid SOC Lower limit (%)",   O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x313, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
    // 柴发额定功率
    {DEV_NO_EMS, DG_RATED_POWER,         "Rated power of DG(kW)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x315, TYPE_FLOAT, ORDER_ABCD, 1, 0, 1000},
    // 柴发启动的SOC阈值
    {DEV_NO_EMS, DG_BOOT_SOC,         "SOC threshold for DG startup(%)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x317, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
    // SOC告警阈值
    {DEV_NO_EMS, SOC_ALARM,         "SOC alarm threshold (%)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x319, TYPE_FLOAT, ORDER_ABCD, 1},
    // 柴发容量回差
    {DEV_NO_EMS, EMS_DG_DIFF,       "DG capacity diff (kW)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "",                                              0x03, 0x402, TYPE_FLOAT, ORDER_ABCD, 1, 0, 1000},

    // SOC告警控制
    {DEV_NO_EMS, SOC_ALARM_CTRL, "Soc Alarm Ctrl",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "",          0x03, 0x404, TYPE_INT, ORDER_AB, 1},
    // 负载断路器异常
    {DEV_NO_EMS, LCB_ABNORMAL, "Lcb startup abnormal",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "0:正常;1:合闸异常;2:分闸异常;",          0x03, 0x406, TYPE_INT, ORDER_A, 1},
    // 并离网断路器异常
    {DEV_NO_EMS, ICB_ABNORMAL, "Icb startup abnormal",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "0:正常;1:合闸异常;2:分闸异常;",          0x03, 0x407, TYPE_INT, ORDER_A, 1},
    // 柴发启动异常
    {DEV_NO_EMS, DG_ABNORMAL, "DG startup abnormal",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "0:正常;1:启动异常;2:停机异常;",          0x03, 0x408, TYPE_INT, ORDER_A, 1},
    // 动作超时时间
    {DEV_NO_EMS, ACTION_TIMEOUT, "Execute action timeout",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,  "off", "",          0x03, 0x40c, TYPE_INT, ORDER_AB, 1},
    // 柴发容量保护开关
    {DEV_NO_EMS, DG_CAP_PRO,       "diesel generator Capacity protection",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;",         0x03, 0x40d, TYPE_INT, ORDER_AB, 1},
    // 光伏增长斜率
    {DEV_NO_EMS, PV_KM,       "Growth slope of PV inverter(%)",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "",                             0x03, 0x40e, TYPE_INT, ORDER_ABCD, 1},
    // 光伏控制模式
    {DEV_NO_EMS, PV_MODE,       "Control mode of PV inverter",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:power;1:percent;",            0x03, 0x500, TYPE_INT, ORDER_AB, 1},
    // 黑夜死区
    {DEV_NO_EMS, DEAD_NIGHT,       "Dead Zone of Night",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "",            0x03, 0x501, TYPE_INT, ORDER_AB, 1},
    // 光伏是否可控
    {DEV_NO_EMS, PV_ISCTRL,       "Whether PV is control",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "",            0x03, 0x502, TYPE_INT, ORDER_AB, 1},
    // 使能光伏精细化控制
    {DEV_NO_EMS, EN_PV_PRECTRL,   "Enable PV precise control",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;",   0x03, 0x503, TYPE_INT, ORDER_AB, 1},
    // 并网SOC上限
    {DEV_NO_EMS, SOC_NET_MAX, "grid-connection SOC Upper limit(%)",   O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",      0x03, 0x504, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
    // 并网SOC下限
    {DEV_NO_EMS, SOC_NET_MIN, "grid-connection SOC Lower limit (%)",   O_WRONLY | O_RDONLY, EMS_POINT_INT,  PROPERTY_REALDATA, "off", "",     0x03, 0x506, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
    // 光伏均衡功率调节的步进值kw
    // {DEV_NO_EMS, MPPT_EQ,       "Photovoltaic balance step value(kW)",         O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",                             0x03, 0x508, TYPE_FLOAT, ORDER_ABCD, 1},
    // 光伏平衡阶跃值总限制
    {DEV_NO_EMS, MPPT_EQ_TL,       "Photovoltaic ascending step value",         O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",                             0x03, 0x50a, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
    // 单光伏配比均衡步进值
    {DEV_NO_EMS, MPPT_EQ_RT,       "Photovoltaic descent step value(kW)",         O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "",                             0x03, 0x50c, TYPE_FLOAT, ORDER_ABCD, 1, 0, 100},
    //光伏总功率 交流侧光伏设置有功功率 直流侧设置总功率
    {DEV_NO_EMS, PH_P,       "The total power of photovoltaic Settings(kW)",         O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",       0x04, 0x50e, TYPE_FLOAT, ORDER_ABCD, 1},
    //光伏开机
    {DEV_NO_EMS, PH_ON,       "Photovoltaic startup",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "",                             0x04, 0x510,  TYPE_INT, ORDER_AB, 1},
    //光伏关机
    {DEV_NO_EMS, PH_OFF,       "Photovoltaic power off",         O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "",                             0x04, 0x511,  TYPE_INT, ORDER_AB, 1},

    //市电有功功率
    {DEV_NO_EMS, GRID_P,       "Active power of grid(kW)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x53f, TYPE_FLOAT, ORDER_ABCD, 1},
    //市电无功功率
    {DEV_NO_EMS, GRID_Q,       "Reactive power of grid(kVar)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x541, TYPE_FLOAT, ORDER_ABCD, 1},
    //充电桩有功功率
    {DEV_NO_EMS, PCU_P,       "Active power of charging station(kW)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x543, TYPE_FLOAT, ORDER_ABCD, 1},
    //储能有功功率
    {DEV_NO_EMS, PCS_P,       "Energy storage active power(kW)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x545, TYPE_FLOAT, ORDER_ABCD, 1},
    //储能无功功率
    {DEV_NO_EMS, PCS_Q,       "Energy storage reactive power(kVar)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x547, TYPE_FLOAT, ORDER_ABCD, 1},
    //PV发电功功率
    {DEV_NO_EMS, MPPT_P,       "PV generation power(kW)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x549, TYPE_FLOAT, ORDER_ABCD, 1},
    //储能直流功率
    {DEV_NO_EMS, BMS_P,       "Energy storage DC power(kW)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x54b, TYPE_FLOAT, ORDER_ABCD, 1},
    //储能SOC
    {DEV_NO_EMS, BMS_SOC,       "Energy storage SOC(%)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x54d, TYPE_FLOAT, ORDER_ABCD, 1},
    //光伏逆变器有功功率
    {DEV_NO_EMS, PV_P,       "Active power of PV inverter(kW)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x54f, TYPE_FLOAT, ORDER_ABCD, 1},
    //光伏逆变器无功功率
    {DEV_NO_EMS, PV_Q,       "Reactive power of PV inverter(kVar)",         O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x551, TYPE_FLOAT, ORDER_ABCD, 1},

    //微网检测
    {DEV_NO_EMS, MICRO_CHECK, "micro check",                    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "1:检查",                             0x04, 0x553, TYPE_INT, ORDER_AB, 1},
    
    {DEV_NO_EMS, BUS_V_MPPT, "BusVol_MPPT",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x554,TYPE_FLOAT, ORDER_ABCD, 1},
    {DEV_NO_EMS, BUS_C_MPPT, "BusCur_MPPT",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x556,TYPE_FLOAT, ORDER_ABCD, 1},
    {DEV_NO_EMS, BUS_P_MPPT, "BusPow_MPPT",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x558,TYPE_FLOAT, ORDER_ABCD, 1},
    {DEV_NO_EMS, BUS_O_MPPT, "OnOff_MPPT",                    O_RDONLY, TYPE_INT, PROPERTY_REALDATA, "off", "",                             0x04, 0x55a, TYPE_INT, ORDER_AB, 1},

    {DEV_NO_EMS, A_V_PV, "Aphase_V_PV",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x55b, TYPE_FLOAT, ORDER_ABCD, 1},
    {DEV_NO_EMS, B_V_PV, "Bphase_V_PV",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x55d, TYPE_FLOAT, ORDER_ABCD, 1},
    {DEV_NO_EMS, C_V_PV, "Cphase_V_PV",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x55f, TYPE_FLOAT, ORDER_ABCD, 1},
    {DEV_NO_EMS, A_C_PV, "Aphase_C_PV",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x561, TYPE_FLOAT, ORDER_ABCD, 1},
    {DEV_NO_EMS, B_C_PV, "Bphase_C_PV",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x563, TYPE_FLOAT, ORDER_ABCD, 1},
    {DEV_NO_EMS, C_C_PV, "Cphase_C_PV",                    O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "",                             0x04, 0x565, TYPE_FLOAT, ORDER_ABCD, 1},

};
const int g_ems_microgri_count = sizeof(ems_microgri_variant) / sizeof(ems_base_variant_t);

ems_base_variant_t vlc_base_variant[] =
    {
        // (设置动作)
        // ----------------------------------------------------------------------------------------------------------------------------------
        //使能BMS告警
        {DEV_NO_LC, EN_BMS_ALARM, "Enable BMS alarms", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x00, TYPE_INT, ORDER_AB, 1},
        //使能DOD防护
        {DEV_NO_LC, EN_PROTECT_DOD, "Enable DOD protection", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x01, TYPE_INT, ORDER_AB, 1},
        //使能BMS功率限制
        {DEV_NO_LC, BMS_POWER_LIMIT, "Enable BMS power limitation", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x02, TYPE_INT, ORDER_AB, 1},
        //自动PCS关机
        {DEV_NO_LC, PCS_AUTO_TURN, "PCS auto-shutdown", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x03, TYPE_INT, ORDER_AB, 1},
        //自动PCS关机时间
        {DEV_NO_LC, PCS_AUTO_TURN_OFF_TIME, "PCS auto-shutdown time(s)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x04, TYPE_INT, ORDER_AB, 1},
        //开关机
        {DEV_NO_LC, ON_OFF_STATE, "Power on/off", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Off;1:On;", 0x03, 0x05, TYPE_INT, ORDER_AB, 1},
        //设置有功功率
        {DEV_NO_LC, SET_ACT_POWER, "Set active power(kW)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x06, TYPE_INT, ORDER_ABCD, 1},
        //设置无功功率
        {DEV_NO_LC, SET_REACTPOWER, "Set reactive power(kVar)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x08, TYPE_INT, ORDER_ABCD, 1},
        //设置并离网模式
        {DEV_NO_LC, SET_CONNECT, "Set on/off-grid mode", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Off-grid;1:On-grid;", 0x03, 0x0a, TYPE_INT, ORDER_AB, 1},
        //清除保护
        {DEV_NO_LC, CLEAR_ALARM, "Clear all protections", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x0b, TYPE_INT, ORDER_AB, 1},
        //使能动环保护
        {DEV_NO_LC, EN_IO_PROTECT, "Enable dynamic environment protection", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x0c, TYPE_INT, ORDER_AB, 1},
        //最大充电SOC
        {DEV_NO_LC, EMS_SOCMAX, "Maximum charging SOC(%)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x0d, TYPE_INT, ORDER_ABCD, 1, 0, 100},
        //最小放电SOC
        {DEV_NO_LC, EMS_SOCMIN, "Minimum discharge SOC(%)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x0f, TYPE_INT, ORDER_ABCD, 1, 0, 100},
        //限制功率
        {DEV_NO_LC, POWER_LIMIT, "Limited power", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x11, TYPE_INT, ORDER_ABCD, 1},
        //脱扣
        {DEV_NO_LC, TRIP, "Trip", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x13, TYPE_INT, ORDER_AB, 1},
        //清除手动保护
        {DEV_NO_LC, LC_CLR_MANUAL_PROTECT, "Clear manual protection", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x14, TYPE_INT, ORDER_AB, 1},
        //BMS上下高压
        {DEV_NO_LC, BMS_UPPER, "Set BMS HV_Connect", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "both", "0:HV connect;1:HV disconnect;", 0x03, 0x15, TYPE_INT, ORDER_AB, 1},
        //使能无功-功率因数补偿
        {DEV_NO_LC, EN_RP_COMP,       "enable repower compensate",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "0:Disabled;1:Enabled;", 0x03, 0x016, TYPE_INT, ORDER_AB, 1},     
        // 设置功率因数
        {DEV_NO_LC, SET_POWER_FACTOR,        "Set power factor",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,  "off", "", 0x03, 0x17, TYPE_INT, ORDER_AB, 1},

        //工作段制热启动温度
        {DEV_NO_LC, WORK_START_HOT_TEMP, "Work Heating start-up temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x19, TYPE_INT, ORDER_AB, 1, -100, 100},
        //工作段制热停止温度
        {DEV_NO_LC, WORK_END_HOT_TEMP, "Work Heating stop temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x1a, TYPE_INT, ORDER_AB, 1, -100, 100},
        //工作段制冷启动温度
        {DEV_NO_LC, WORK_START_COOL_TEMP, "Work Cooling start-up temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x1b, TYPE_INT, ORDER_AB, 1, -100, 100},
        //工作段制冷停止温度
        {DEV_NO_LC, WORK_END_COOL_TEMP, "Work Cooling stop temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x1c, TYPE_INT, ORDER_AB, 1, -100, 100},
        //工作段制热目标温度
        {DEV_NO_LC, WORK_DIST_HOT_TEMP, "Work Heating target temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x1d, TYPE_INT, ORDER_AB, 1, -100, 100},
        //工作段制冷目标温度
        {DEV_NO_LC, WORK_DIST_COOL_TEMP, "Work Cooling target temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x1e, TYPE_INT, ORDER_AB, 1, -100, 100},
        
        //空闲段制热启动温度
        {DEV_NO_EMS, STOP_START_HOT_TEMP ,   "TEMP for heating start-up in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x41, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制热停止温度
        {DEV_NO_EMS, STOP_END_HOT_TEMP   ,   "TEMP for heating stop in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x42, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制冷启动温度
        {DEV_NO_EMS, STOP_START_COOL_TEMP,   "TEMP for cooling start-up in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x43, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制冷停止温度
        {DEV_NO_EMS, STOP_END_COOL_TEMP  ,   "TEMP for cooling stop in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x44, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制热目标温度
        {DEV_NO_EMS, STOP_DIST_HOT_TEMP    ,    "Heating target TEMP in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x45, TYPE_INT,   ORDER_AB,   1, -100, 100},
        //空闲段制冷目标温度
        {DEV_NO_EMS, STOP_DIST_COOL_TEMP   ,    "Cooling target TEMP in idle(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "",              0x03, 0x46, TYPE_INT,   ORDER_AB,   1, -100, 100},
        

        //输出制冷目标温度
        {DEV_NO_LC, TMS_CTRL_DIST_TEMP_COLD, "Output cooling target temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x1f, TYPE_INT, ORDER_AB, 1},
        //输出制热目标温度
        {DEV_NO_LC, TMS_CTRL_DIST_TEMP_HOT, "Output heating target temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x03, 0x20, TYPE_INT, ORDER_AB, 1},
        //液冷机控制
        {DEV_NO_LC, TMS_CTRL_STATE, "Liquid cooling control", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Standby;1:Cooling;2:Heating;3:Pump circulation;4:fully automatic;", 0x03, 0x21, TYPE_INT, ORDER_AB, 1},
        //自循环启动温差
        {DEV_NO_EMS, START_SELF_LOOP_DIFF, "Start self circulating TEMP difference(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "", 0x03, 0x22, TYPE_INT, ORDER_AB, 1, -100, 100},
        //自循环停止温差
        {DEV_NO_EMS, END_SELF_LOOP_DIFF, "End self circulating TEMP difference(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "", 0x03, 0x3c, TYPE_INT, ORDER_AB, 1, -100, 100},
        
        //空调启停控制
        {DEV_NO_LC, AIR_COND_STARTSTOP_CTRL, "AC control",O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Off;1:On;", 0x03, 0x23, TYPE_INT, ORDER_AB, 1},
        //使能空调控制
        {DEV_NO_LC, ENABLE_AIR_COND, "Enable AC control", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x24, TYPE_INT, ORDER_AB, 1},
        //使能液冷机管理
        {DEV_NO_LC, ENABLE_AUTO_COOL, "Enable liquid cooling MGT", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x25, TYPE_INT, ORDER_AB, 1},
        //使能间隙自循环
        {DEV_NO_LC, EN_SELF_LOOP_DIFF,         "Enable gap self circulation",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;", 0x03, 0x26, TYPE_INT, ORDER_AB, 1},
        //单体过压保护阈值(V)
        {DEV_NO_LC, SINGLE_MAX_VOLTAGE, "Single cell Over-V protect threshold(V)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x27, TYPE_INT, ORDER_ABCD, 1, 0, 10},
        //单体欠压保护阈值(V)
        {DEV_NO_LC, SINGLE_MIN_VOLTAGE, "Single cell Under-V protect threshold(V)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x29, TYPE_INT, ORDER_ABCD, 1, 0, 10},
        //使能单体电压保护
        {DEV_NO_LC, EN_CELL_VOLT_PROTECT, "Enable single cell voltage protection", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x2b, TYPE_INT, ORDER_AB, 1},
        //单体过压保护偏差
        {DEV_NO_LC, SINGLE_MAX_VOLTAGE_ERR,   "Single cell Over-V protect difference(V)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,    PROPERTY_REALDATA, "off", "", 0x03, 0x2d, TYPE_INT, ORDER_ABCD, 1, 0, 10},
        //单体欠压保护偏差
        {DEV_NO_LC, SINGLE_MIN_VOLTAGE_ERR,   "Single cell Under-V protect difference(V)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,    PROPERTY_REALDATA, "off", "", 0x03, 0x2f, TYPE_INT, ORDER_ABCD, 1, 0, 10},
        //禁止放电SOC偏差
        {DEV_NO_LC, EMS_SOCMINERR,            "SOC Prohibited discharging difference(%)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "", 0x03, 0x31, TYPE_INT, ORDER_ABCD, 1, 0, 100},
        //禁止充电SOC偏差
        {DEV_NO_LC, EMS_SOCMAXERR,            "SOC Prohibited charging difference(%)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", "", 0x03, 0x33, TYPE_INT, ORDER_ABCD, 1, 0, 100},
        //使能风机跟随功率
        {DEV_NO_LC, EN_DRAUG_FLOW_POWER   , "Enable fan to follow power",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;", 0x03, 0x35, TYPE_INT, ORDER_AB, 1},
        //风机跟随功率门限
        {DEV_NO_LC, EN_DRAUG_FLOW_POWER_T , "Fan following power threshold(kW)",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,       "off", "", 0x03, 0x36, TYPE_INT, ORDER_AB, 1},
        //使能风机跟随温度
        {DEV_NO_LC, EN_DRAUG_FLOW_TEM     , "Enable fan to follow TEMP",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "0:Disabled;1:Enabled;", 0x03, 0x37, TYPE_INT, ORDER_AB, 1},
        //风机跟随温度门限
        {DEV_NO_LC, EN_DRAUG_FLOW_TEM_T   , "Fan following TEMP threshold(℃)",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "", 0x03, 0x38, TYPE_INT, ORDER_AB, 1, 0, 600},
        //跟随时间死区
        {DEV_NO_LC, DRAUG_DEAE_TIME       , "Follow time deadband(s)",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", "", 0x03, 0x39, TYPE_INT, ORDER_AB, 1},
         //风机
        {DEV_NO_LC, FAN,                   "Fan",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:Off;1:On;", 0x03, 0x3a, TYPE_INT, ORDER_AB, 1},
        //装机功率比例
        {DEV_NO_LC, INSPOW_COEF,            "Proportion of installed capacity",        O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",                      0x03, 0x3b, TYPE_INT,   ORDER_AB,   1},
        // 单体电压保护延时, 只有vlc才会生效
        {DEV_NO_LC, CELL_VOLT_PROTECT_TIME,            "Single cell voltage protection  delay time(s)",        O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "",      0x03, 0x3c, TYPE_INT,   ORDER_AB,   1},
        //PCS故障复位
        {DEV_NO_LC, PCS_FAULT_RESET,          "PCS fault reset",          O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off", "",                     0x03, 0x3d, TYPE_INT,   ORDER_AB,   1},
        //设置A相功率
        {DEV_NO_LC, SET_PHASE_A_POWER, "Set active power of phase A(kW)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x3f, TYPE_INT, ORDER_ABCD, 1},
        //设置B相功率
        {DEV_NO_LC, SET_PHASE_B_POWER, "Set active power of phase B(kW)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x41, TYPE_INT, ORDER_ABCD, 1},
        //设置C相功率
        {DEV_NO_LC, SET_PHASE_C_POWER, "Set active power of phase C(kW)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x03, 0x43, TYPE_INT, ORDER_ABCD,   1},
        //使能单相防逆流
        {DEV_NO_LC, ENABLE_SINGLE_PHASE_REVERSE, "enable single phase reverse", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Disabled;1:Enabled;", 0x03, 0x45, TYPE_INT, ORDER_AB, 1},
        // ----------------------------------------------------------------------------------------------------------------------------------
        // 只读点位
        // 系统运行状态
        {DEV_NO_LC, SYSTEM_STATUS, "System operating status", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Normal;1:Abnormal;", 0x04, 0x800, TYPE_INT, ORDER_AB, 1},
        // 系统运行状态字
        {DEV_NO_LC, SYSTEM_STATUS_W, "System operation status word", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x04, 0x801, TYPE_INT, ORDER_AB, 1},
        // 期望有功功率
        {DEV_NO_LC, EXPECT_ACT_POWER, "Expected active power(kW)", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", "", 0x04, 0x802, TYPE_INT, ORDER_ABCD, 1},
        // 预留期望无功功率
        // 禁充保护
        {DEV_NO_LC, PROHIBITE_CHARGE, "Prohibited charging protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x04, 0x806, TYPE_INT, ORDER_AB, 1},
        // 禁放保护
        {DEV_NO_LC, PROHIBITE_DISCHARGE, "Discharging prohibited protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x04, 0x807, TYPE_INT, ORDER_AB, 1},
        // DOD保护
        {DEV_NO_LC, DOD_LIMITED, "DOD protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x04, 0x808, TYPE_INT, ORDER_AB, 1},
        // DOD禁充保护
        {DEV_NO_LC, DOD_LIMITED_CH, "DOD prohibited charging protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x04, 0x809, TYPE_INT, ORDER_AB, 1},
        // DOD禁放保护
        {DEV_NO_LC, DOD_LIMITED_DC, "DOD prohibited discharging protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x04, 0x80a, TYPE_INT, ORDER_AB, 1},
        // 单体电压阈值告警
        {DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, "Single cell voltage threshold alarm", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x04, 0x80b, TYPE_INT, ORDER_AB, 1},
        // 动环保护
        {DEV_NO_LC, IO_PROTECT, "Dynamic environment protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Unprotected;1:Protected;", 0x04, 0x80c, TYPE_INT, ORDER_AB, 1},
        // BMS最大可充功率
        {DEV_NO_LC, MAX_CHARGE_POWER, "BMS Maximum Charging Power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "", 0x04, 0x80e, TYPE_INT, ORDER_AB, 1},
        // BMS最大可放功率
        {DEV_NO_LC, MAX_DISCHA_POWER, "BMS Maximum Discharging Power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "", 0x04, 0x80f, TYPE_INT, ORDER_AB, 1},
        // 开关机状态
        {DEV_NO_LC, ON_OFF_STATUS, "On/Off Status", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Off;1:On;", 0x04, 0x810, TYPE_INT, ORDER_AB, 1},
        // 并离网状态
        {DEV_NO_LC, CONNECT_STATUS, "Connect Status", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Off-grid;1:On-grid;", 0x04, 0x811, TYPE_INT, ORDER_AB, 1},
        // 总有功功率
        {DEV_NO_LC, ACTIVE_POWER, "active power(kW)", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "", 0x04, 0x812, TYPE_INT, ORDER_ABCD, 1},
        // 总无功功率
        {DEV_NO_LC, REACTIVE_POWER, "reactive power(kVar)", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "", 0x04, 0x814, TYPE_INT, ORDER_ABCD, 1},
        // 当前SOC
        {DEV_NO_LC, CURRENT_SOC, "SOC", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "", 0x04, 0x816, TYPE_FLOAT, ORDER_ABCD, 1},
        // 手动保护
        {DEV_NO_LC, LC_MANUAL_PROTECT, "Manual protection", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "", 0x04, 0x818, TYPE_INT, ORDER_AB, 1},
        // 本机消防
        {DEV_NO_LC, FIRE, "Local fire protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", "0:Normal;1:Abnormal;", 0x04, 0x819, TYPE_INT, ORDER_AB, 1},
        // 告警数量
        {DEV_NO_LC, ALARMCNT, "Number of alarms", O_RDONLY, EMS_POINT_INT,   PROPERTY_REALDATA,    "off", "",  0x04, 0x81a, TYPE_INT,   ORDER_AB,   1},
        //历史告警数量
        {DEV_NO_LC, ALARMHISCNT, "Number of historical alarms", O_RDONLY, EMS_POINT_INT,   PROPERTY_REALDATA,    "off", "",  0x04, 0x81c, TYPE_INT,   ORDER_AB,   1},
        //充放电状态
        {DEV_NO_LC, CH_DISCH_STATUS, "Charge/Discharge status", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", "0:Idle;1:Charge;2:Discharge;", 0x04, 0x81b, TYPE_INT, ORDER_AB, 1},
        //是否被主机禁用
        {DEV_NO_EMS, ISDISABLE_BY_MASTER, "is disabled by the master", O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", "0:no;1:yes;", 0x04, 0x81d, TYPE_INT,   ORDER_AB,   1},
        // 当前SOH
        {DEV_NO_LC, CURRENT_SOH, "SOH", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "both", "", 0x04, 0x81e, TYPE_INT, ORDER_AB, 1},
        //A相功率
        {DEV_NO_LC, PHASE_A_POWER, "phase a power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "", 0x04, 0x820, TYPE_INT, ORDER_ABCD, 1},
        //B相功率
        {DEV_NO_LC, PHASE_B_POWER, "phase b power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "", 0x04, 0x822, TYPE_INT, ORDER_ABCD, 1},
        //C相功率
        {DEV_NO_LC, PHASE_C_POWER, "phase c power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", "", 0x04, 0x824, TYPE_INT, ORDER_ABCD, 1},
};

const int g_vlc_variant_count = sizeof(vlc_base_variant) / sizeof(vlc_base_variant[0]);

// 映射
typedef struct
{
    const char *tag_name;
    char *desc;
} ems_tag_description;

typedef struct
{
    int (*required)(void *par); // 条件
    int true_desc_map_size;
    ems_tag_description *true_desc_map;
    int false_desc_map_size;
    ems_tag_description *false_desc_map;
} ems_board_desc_mapping;
//
int enable_microgrid(void *par)
{
    return (get_cabinet_info()->mode_microgrid != 0);
}

ems_tag_description enable_microgrid_true_map[] =
    {
        {.tag_name = STRANTAGY_TYPE, .desc = "0:Planning Mode;1:Dynamic Capacity Increase;2:Grid First;3:Self Consumption;4:Backup Power;5:TOU;"},
};

ems_tag_description enable_microgrid_false_map[] =
    {
        {.tag_name = STRANTAGY_TYPE, .desc = "0:Planning Mode;1:Dynamic Capacity Increase;"},
};

ems_board_desc_mapping ems_point_desc_map[] =
    {
        {.required = enable_microgrid,
         .true_desc_map_size = sizeof(enable_microgrid_true_map) / sizeof(enable_microgrid_true_map[0]),
         .true_desc_map = enable_microgrid_true_map,
         .false_desc_map_size = sizeof(enable_microgrid_false_map) / sizeof(enable_microgrid_false_map[0]),
         .false_desc_map = enable_microgrid_false_map},
};

const int desc_num = sizeof(ems_point_desc_map) / sizeof(ems_point_desc_map[0]);

void set_point_desc()
{
    for (int r = 0; r < desc_num; r++)
    {
        if (ems_point_desc_map[r].required(NULL) != 0)
        {
            for (int i = 0; i < g_ems_base_variant_count; i++)
            {
                if (ems_base_variant[i].desc == NULL)
                {
                    for (int k = 0; k < ems_point_desc_map[r].true_desc_map_size; k++)
                    {
                        if (strcmp(ems_base_variant[i].variant, ems_point_desc_map[r].true_desc_map->tag_name) == 0)
                        {
                            ems_base_variant[i].desc = ems_point_desc_map[r].true_desc_map->desc;
                        }
                    }
                }
            }
        }
        else
        {
            for (int i = 0; i < g_ems_base_variant_count; i++)
            {
                if (ems_base_variant[i].desc == NULL)
                {
                    for (int k = 0; k < ems_point_desc_map[r].false_desc_map_size; k++)
                    {
                        if (strcmp(ems_base_variant[i].variant, ems_point_desc_map[r].false_desc_map->tag_name) == 0)
                        {
                            ems_base_variant[i].desc = ems_point_desc_map[r].false_desc_map->desc;
                        }
                    }
                }
            }
        }
    }
}

char* alloc_node_tag(const char* device,const char* variant)
{
    if(!device || !variant)return NULL;
    size_t size = strlen(device) + strlen(variant) + 1;
    char * node = malloc(size);
    if(!node) return NULL;
    sprintf(node,"%s.%s",device,variant);
    return node;
}

#define NODE_SIZE DEV_NAME_LEN + TAG_NAME_LEN
#define DESC_SIZE 1024
double get_meter_active_power(const char *dev_no)
{
    double ret = dev_get_dev_tag_float(dev_no, METER_POWER);
    if (dev_get_dev_tag_int(DEV_NO_EMS, METER_INVERT) != 0)
    {
        return -ret;
    }
    else
    {
        return ret;
    }
}

#if 0 // 移动到cc_lc_com/collector_api.c
/*********************************PCS操作方法,不同PCS操作方法不一样********************************************/
void def_set_pcs_power(const char* dev_id, float val)
{
    pe_set_power(dev_id, val * EXPECT_POWER_FACTOR);
}
void def_set_pcs_repower(const char* dev_id, float val)
{
    pe_set_repower(dev_id, val * EXPECT_POWER_FACTOR);
}

void def_set_pcs_onoff(const char* dev_id, int val)
{
    if (val == 0)
    {
        pe_set_onoff(dev_id, PE_ADP_OFF);
    }
    else
    {
        pe_set_onoff(dev_id, PE_ADP_ON);
    }
    
}

void def_set_pcs_mode(const char* dev_id, int val)
{
    pe_set_mode(dev_id, val);
}

void dev_set_pcs_connect(const char* dev_id, PCS_CONNSTA_E val)
{
    pe_set_connect(dev_id, val);
}

double def_get_pcs_power(const char* dev_id)
{
    double value = 0;
    pe_get_power(dev_id, &value);
    return value;
}

double def_get_pcs_repower(const char* dev_id)
{
    double value = 0;
    pe_get_repower(dev_id, &value);
    return value;
}

float def_get_pcs_repower(const char* dev_id)
{
    return pe_get_repower(dev_id);
}

int def_get_pcs_onoff(const char* dev_id)
{
    return pe_get_onoff(dev_id);
}

int dev_get_pcs_connect(const char* dev_id)
{
    return pe_get_connect(dev_id);
}
#endif
void set_alarm_cnt(int alarmcnt)
{
    if(get_cabinet_info()->is_slave == 0)//主机需要统计所有从机的告警
    {
        int lc_list_len = get_pcs_ctrl_var()->lc_list_len;
        lc_it *it_arr = get_pcs_ctrl_var()->lc_list;
        for(int i = 0; i < lc_list_len; i++)
        {
            if(it_arr[i].type != eLC_TYPE_VLC)
            {
                alarmcnt += dev_get_dev_tag_int(it_arr[i].no, ALARMCNT);
            }
        }
    }
    dev_set_dev_tag_int(DEV_NO_EMS, ALARMCNT,alarmcnt);
}

void set_hisalarm_cnt(int hisalarmcnt)
{
    dev_set_dev_tag_int(DEV_NO_EMS, ALARMHISCNT,hisalarmcnt);
}

// void set_fault(int fault)
// {
//     if (fault>0)
//     {
//         if(dev_get_dev_tag_int(DEV_NO_EMS, DEVFAULT)!=1)
//             dev_set_dev_tag_int(DEV_NO_EMS, DEVFAULT,1); 
//     }
//     else
//     {
//         if(dev_get_dev_tag_int(DEV_NO_EMS, DEVFAULT)!=0)
//             dev_set_dev_tag_int(DEV_NO_EMS, DEVFAULT,0); 
//     }
    
// }

void set_sample_period_by_run_state()
{
    float bms_currue = dev_get_dev_tag_float(DEV_NO_BMS, RACK_CURRUE);
    if (CHECK_STOP(bms_currue))
    {
        set_sample_period("BMS_CELLS",dev_get_dev_tag_float(DEV_NO_EMS, IDLE_SAMPLE_PERIOD));
    }
    else
    {
        set_sample_period("BMS_CELLS",dev_get_dev_tag_float(DEV_NO_EMS, WORK_SAMPLE_PERIOD));
    }
}

extern int update_ems_user_cfg(usercfg_variant_t *pcfg, const char *node_id, tag_value *data_value);
extern char* create_ems_template(template_info_t *info_p,ems_base_variant_t **tags,int tags_size);
static void ems_config_data_change_cb(char *nod,tag_value *data_value)
{
    pcs_ctrl_var_t *var = get_pcs_ctrl_var();
    if(update_ems_user_cfg(&g_usercfg_variant,nod,data_value)<0)return;
    var->config_chaged = true;
    var->config_save = true;
}


void mul_ems_expect_power_set(lc_power_info_t power_info)
{
    // 只有自动模式不可以写
    if(g_usercfg_variant.ControlMode == EMS_AUTO_MODE)
        return;
    check_lc_and_set(power_info);
}

int get_mode()
{
    return g_usercfg_variant.ControlMode;
}

static time_t voltage_dc_time = 0; // 单体电压延时记录
static time_t voltage_ch_time = 0; // 单体电压延时记录

static void ems_contrl_data_change_cb(char *nod,tag_value *data_value)
{
    if(data_value->type == 0)
        ems_syslog(LOG_NOTICE, "%s  -> [%ld]",nod,data_value->value.to_int);
    else
        ems_syslog(LOG_NOTICE, "%s  -> [%f]",nod,data_value->value.to_float);
    
    if(strcmp(nod,DEV_NO_EMS"."ON_OFF_STATE) == 0) 
    {
        if (data_value->value.to_int == 0)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, SET_ACT_POWER,0);
            /* code */
        }
        if (get_cabinet_info()->en_pcs_bus == 0)
        {
            set_total_pcs_onoff_reflush_time(data_value->value.to_int);
        }
        else
        {
            pcs_business_initset_onoff(data_value->value.to_int);
        }
    }
    else if(strcmp(nod,DEV_NO_EMS"."SET_ACT_POWER) == 0) {
        double repower = dev_get_dev_tag_float(DEV_NO_EMS, SET_REACTPOWER);
        lc_power_info_t power_info = {0};
        power_info.active_power = data_value->value.to_float;
        power_info.reactive_power = repower;
        mul_ems_expect_power_set(power_info);
    }
    else if(strcmp(nod,DEV_NO_EMS"."SET_REACTPOWER) == 0) {
        double power = dev_get_dev_tag_float(DEV_NO_EMS, SET_ACT_POWER);
        lc_power_info_t power_info = {0};
        power_info.reactive_power = data_value->value.to_float;
        power_info.active_power = power;
        mul_ems_expect_power_set(power_info);
    }
    else if(strcmp(nod,DEV_NO_EMS"."SET_CONNECT) == 0)
    {
        if (get_cabinet_info()->en_pcs_bus == 0)
        {
            set_total_pcs_connect(data_value->value.to_int);
        }
        else
        {
            pcs_business_init_set_connect(data_value->value.to_int);
        }
    }
    else if(strcmp(nod,DEV_NO_EMS"."SET_PV_POWER) == 0) set_total_pv_power(data_value->value.to_float);
    else if(strcmp(nod,DEV_NO_EMS"."CLEAR_ALARM) == 0)
    {
        if ((data_value->type == 0) && (data_value->value.to_int != 0))
        {
            clean_stop_state();
            dev_set_dev_tag_int(DEV_NO_EMS, CLEAR_ALARM,0);
        }
    }
    else if(strcmp(nod,DEV_NO_EMS"."CONTROL_MODE) == 0)
    {
        //切换为非自动模式,且这次模式和上一次不同(虽然是变化回调，但是上电第一次所有回调都会被调用一次，所以多了一个判断)
        if ((data_value->value.to_int != EMS_AUTO_MODE) && (data_value->value.to_int != data_value->value_last.to_int))
        {
            // dev_set_dev_tag_int(DEV_NO_EMS, SET_ACT_POWER,0);
        }
    }
    else if (strcmp(nod, DEV_NO_EMS "." BMS_UPPER) == 0)
    {
        set_total_bms_connect(data_value->value.to_int);
    }
    else if (strcmp(nod, DEV_NO_EMS "." EN_RP_COMP ) == 0) // PCS 无功功率补偿,设置功率因数
    {
        set_total_pcs_repower_comp(data_value->value.to_int);
    }
    else if (strcmp(nod, DEV_NO_EMS "." SET_POWER_FACTOR ) == 0) // PCS 无功功率补偿,设置功率因数
    {
        set_total_pcs_power_factor(data_value->value.to_float);
    }
    else if (strcmp(nod, DEV_NO_EMS "." CELL_VOLT_PROTECT_TIME ) == 0)
    {
        g_usercfg_variant.SingleVoltageTime = data_value->value.to_int;
    }
    else if(strcmp(nod, DEV_NO_EMS "." PCS_AUTO_TURN ) == 0)//手动模式不会持续发功率，如果使能开关变化，下发一次0功率
    {
        if(g_usercfg_variant.ControlMode == EMS_MANUAL_MODE && data_value->value.to_int == 1 && dev_get_dev_tag_float(DEV_NO_EMS, ACTIVE_POWER) == 0)
        {
            lc_power_info_t power_info = {0};
            set_lc_power(power_info);
        }
    }
    else if (strcmp(nod, DEV_NO_EMS "." PCS_FAULT_RESET ) == 0) // PCS故障复位
    {
        set_total_pcs_fault_reset(data_value->value.to_int);
    }
}

/**
 * @brief 清零所有 PCS 的功率设置
 *        在 ZC 模式下遍历所有 LC 列表，根据 LC 类型分别清零；
 *        在非 ZC 模式下直接清零单台 PCS 的三相功率。
 */
 static void clear_all_pcs_power(void)
 {
     if (cabinet_info.ctrl_mode == EMS_MODE_ZC)
     {
         pcs_ctrl_var_t *var = get_pcs_ctrl_var();
         int cur_sum = var->lc_list_len;
         lc_it *lc_cfg = var->lc_list;
         ems_syslog(LOG_NOTICE, "clear_all_pcs_power: ZC mode, lc_count=%d", cur_sum);
         char pcs_no[TAG_NAME_LEN] = {0};
         for (int i = 0; i < cur_sum; i++)
         {
             if (lc_cfg[i].type == eLC_TYPE_VLC)
             {
                 snprintf(pcs_no, sizeof(pcs_no), "%s.%s", lc_cfg[i].no, DEV_NO_PCS);
                 pe_set_value(pcs_no, "set_power_A", 0);
                 pe_set_value(pcs_no, "set_power_B", 0);
                 pe_set_value(pcs_no, "set_power_C", 0);
             }
         }
     }
     else
     {
         ems_syslog(LOG_NOTICE, "clear_all_pcs_power: non-ZC mode");
         pe_set_value(DEV_NO_PCS, "set_power_A", 0);
         pe_set_value(DEV_NO_PCS, "set_power_B", 0);
         pe_set_value(DEV_NO_PCS, "set_power_C", 0);
     }
 }
 

static void ems_contrl_data_change_cb_lc_ctr_mode(char *nod,tag_value *data_value)
{
    if(data_value->type == 0)
        ems_syslog(LOG_NOTICE, "%s  -> [%ld]",nod,data_value->value.to_int);
    else
        ems_syslog(LOG_NOTICE, "%s  -> [%f]",nod,data_value->value.to_float);
    
    if(strcmp(nod,DEV_NO_EMS"."ON_OFF_STATE) == 0)
    {
        // 不处理，在lc_server_sync_tag中同步
    }
    else if(strcmp(nod,DEV_NO_EMS"."SET_ACT_POWER) == 0)
    {
        double repower = dev_get_dev_tag_float(DEV_NO_EMS, SET_REACTPOWER);
        lc_power_info_t power_info = {0};
        power_info.active_power = data_value->value.to_float;
        power_info.reactive_power = repower;
        mul_ems_expect_power_set(power_info);
    }
    else if(strcmp(nod,DEV_NO_EMS"."SET_REACTPOWER) == 0)
    {
        double power = dev_get_dev_tag_float(DEV_NO_EMS, SET_ACT_POWER);
        lc_power_info_t power_info = {0};
        power_info.reactive_power = data_value->value.to_float;
        power_info.active_power = power;
        mul_ems_expect_power_set(power_info);
    }
    else if(strcmp(nod,DEV_NO_EMS"."SET_CONNECT) == 0)
    {
        // 不处理，在lc_server_sync_tag中同步
    }
    else if(strcmp(nod,DEV_NO_EMS"."SET_PV_POWER) == 0) set_total_pv_power(data_value->value.to_float);
    else if(strcmp(nod,DEV_NO_EMS"."CLEAR_ALARM) == 0)
    {

        if(dev_get_dev_tag_int(DEV_NO_EMS, CLEAR_ALARM)==0)
            return;
        clean_prohibite_chag_and_dischag(get_pcs_ctrl_var()->cabinet_cnt);
        dev_set_dev_tag_int(DEV_NO_EMS, CLEAR_ALARM,0);
    }
    else if(strcmp(nod,DEV_NO_EMS"."CONTROL_MODE) == 0)
    {
        
        if (data_value->value.to_int != EMS_AUTO_MODE)
        {
            //切换为远程模式,且这次模式和上一次不同(虽然是变化回调，但是上电第一次所有回调都会被调用一次，所以多了一个判断)
            if (data_value->value.to_int != data_value->value_last.to_int)
            {
                dev_set_dev_tag_int(DEV_NO_EMS, SET_ACT_POWER, 0);
            }
        }
        else
        {
            dev_set_dev_tag_int(DEV_NO_EMS, ON_OFF_STATE, 1);
        }
    }
    else if (strcmp(nod, DEV_NO_EMS "." BMS_UPPER) == 0)
    {
        set_total_bms_connect(data_value->value.to_int);
    }
    else if (strcmp(nod, DEV_NO_EMS "." PCS_FAULT_RESET ) == 0) // PCS故障复位
    {
        set_total_pcs_fault_reset(data_value->value.to_int);
    }
    else if(strcmp(nod, DEV_NO_EMS"."ENABLE_SINGLE_PHASE_REVERSE) == 0)
    {
        if(data_value->value.to_int == 0)
        {
            clear_all_pcs_power();//单相控制切总功率控制，给PCS三相发零
        } 
    }
}




#define SET_AMASK_BIT(alarm_flag, bit)	(alarm_flag |= (1ULL << (bit)))
#define CLR_AMASK_BIT(alarm_flag, bit)	(alarm_flag &= ~(1ULL << (bit)))

static void fast_stop_temp_ctrl_cb(char *nod,tag_value *data_value)
{
   int val = ALARM_STATUS_NO;
    static int status = 0;

    if(data_value->type == TYPE_TAG_INT)
        val = data_value->value.to_int;
    else 
        val = data_value->value.to_float;
    if (strcmp(nod,DEV_NO_AIRCOND"."STATE_ONLINE)==0)
    {
        if(val == 0)
        {
            SET_AMASK_BIT(status,0);
        }
        else
        {
            CLR_AMASK_BIT(status,0);
        }
    }
    else if (strcmp(nod,DEV_NO_AIRCOND"."DEV_FAULT)==0)
    {
        if(val == ALARM_STATUS_TRIG)
        {
            SET_AMASK_BIT(status,1);
        }
        else
        {
            CLR_AMASK_BIT(status,1);
        }
    }
    else if (strcmp(nod,DEV_NO_LIQUID"."STATE_ONLINE)==0)
    {
        if(val == 0)
        {
            SET_AMASK_BIT(status,2);
        }
        else
        {
            CLR_AMASK_BIT(status,2);
        }
    }
    else if (strcmp(nod,DEV_NO_LIQUID"."DEV_FAULT)==0)
    {
        if(val == ALARM_STATUS_TRIG)
        {
            SET_AMASK_BIT(status,3);
        }
        else
        {
            CLR_AMASK_BIT(status,3);
        }
    }
    ems_syslog(LOG_NOTICE, "fast stop temp_ctrl [nod:%s] -> [%d]",nod,val);
    if(status > 0)
    {
        dev_set_dev_tag_int(DEV_NO_EMS, TEMP_CTRL_ERR,  1);
    }
    else
    {
        dev_set_dev_tag_int(DEV_NO_EMS, TEMP_CTRL_ERR,  0);
    }
}

static void ems_on_off_status_tab_cb(char *nod,tag_value *data_value)
{ 
    if(data_value->type == 0)
    {
        dev_set_dev_tag_int(DEV_NO_EMS, ON_OFF_STATUS, data_value->value.to_int);
    }
}
static void fast_stop_dod_protect_cb(char *nod,tag_value *data_value)
{
    if (strcmp(nod,DEV_NO_BMS"."CURRENT_SOH) == 0)
    {
        int value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
        if(data_value->type == 0)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, CURRENT_SOH, value);
        }
        else if(data_value->type == 1)
        {
            dev_set_dev_tag_float(DEV_NO_EMS, CURRENT_SOH, value);
        }

        return;
    }

    static int chadischapro = 0; //0正常1上限2下限
    int need_dod = 0;
    int en_dod = dev_get_dev_tag_int(DEV_NO_EMS, EN_PROTECT_DOD);
    double value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
    if(data_value->type == 0)
    {
        dev_set_dev_tag_int(DEV_NO_EMS, CURRENT_SOC, value);
    }
    else if(data_value->type == 1)
    {
        dev_set_dev_tag_float(DEV_NO_EMS, CURRENT_SOC, value);
    }
    if(en_dod)
    {
        double value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
        ems_syslog(LOG_NOTICE, "fast stop discharge [nod:%s] -> [%f]",nod,value);
        double socmax = dev_get_dev_tag_float(DEV_NO_EMS, EMS_SOCMAX);
        double socmin = dev_get_dev_tag_float(DEV_NO_EMS, EMS_SOCMIN);
        if(value >= socmax)
        {
            chadischapro = 1;   
        }
        else if (value <= socmin)
        {
            chadischapro = 2;
        }
        
        if (chadischapro > 0)
        {
            double socmaxerr = dev_get_dev_tag_float(DEV_NO_EMS, EMS_SOCMAXERR);
            double socminerr = dev_get_dev_tag_float(DEV_NO_EMS, EMS_SOCMINERR);
            if ((chadischapro == 1) && (value < (socmax - socmaxerr)))
            {
                chadischapro = 0;
            }
            else if ((chadischapro == 2) && (value > (socmin + socminerr)))
            {
                chadischapro = 0;
            }

            if (chadischapro>0)
            {
                need_dod = 1;
            }
            else
            {
                need_dod = 0;
                if (dev_get_dev_tag_int(DEV_NO_EMS, DOD_LIMITED)!=0)
                {
                    dev_set_dev_tag_int(DEV_NO_EMS, DOD_LIMITED,0);
                }
            }
        } 
        else
        {
            need_dod = 0;
        } 
    }
    if (need_dod != dev_get_dev_tag_int(DEV_NO_EMS, DOD_LIMITED))
    {
        dev_set_dev_tag_int(DEV_NO_EMS, DOD_LIMITED,need_dod);
        // if (need_dod == 1 && (get_cabinet_info()->mode_microgrid == MODE_MICROGRID_NONE))
        // {
        //     set_lc_power(0, 0);
        // }
    }
}


static void fast_stop_charge_tab_cb(char *nod,tag_value *data_value)
{
    static int pro_chg_flag = 0;
    if (strcmp(nod,DEV_NO_BMS"."CURRENT_SOC) == 0)
    {
        if(dev_get_dev_tag_int(DEV_NO_EMS, EN_PROTECT_DOD))
        {
            double value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
            double socmax = dev_get_dev_tag_float(DEV_NO_EMS, EMS_SOCMAX);
            double socmaxerr = dev_get_dev_tag_float(DEV_NO_EMS, EMS_SOCMAXERR);
            if (value >= socmax)
            {
                SET_AMASK_BIT(pro_chg_flag,0);
            }
            else if (value < (socmax - socmaxerr))
            {
                CLR_AMASK_BIT(pro_chg_flag,0);
            }
        }
        else
        {
            CLR_AMASK_BIT(pro_chg_flag,0);
        }
    } 
    else if (strcmp(nod,DEV_NO_BMS"."RACK_MAX_VOLT) == 0  && (0 == get_cabinet_info()->mode_microgrid))
    {
        if(g_usercfg_variant.EnCellVoltProtect)
        {
            if(g_usercfg_variant.SingleVoltageTime == 0)
            {
                int val = data_value->value.to_int;
                int cur_vol_min = dev_get_dev_tag_int(DEV_NO_BMS, RACK_MIN_VOLT);
                int volmax = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MAX_VOLTAGE)*1000;
                int volmaxerr = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MAX_VOLTAGE_ERR)*1000;
                int volmin = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MIN_VOLTAGE)*1000;
                int volminerr = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MIN_VOLTAGE_ERR)*1000;
                if (val >= volmax)
                {
                    SET_AMASK_BIT(pro_chg_flag,5);
                    dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 1);
                }
                else if (val < (volmax - volmaxerr))
                {
                    CLR_AMASK_BIT(pro_chg_flag, 5);
                    if ((cur_vol_min > (volmin + volminerr)))
                    {
                        dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 0);
                    }
                }
            }
            else 
            {
                if(data_value != NULL)
                {
                    int val = data_value->value.to_int;
                    int cur_vol_min = dev_get_dev_tag_int(DEV_NO_BMS, RACK_MIN_VOLT);
                    int volmax = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MAX_VOLTAGE)*1000;
                    int volmaxerr = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MAX_VOLTAGE_ERR)*1000;
                    int volmin = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MIN_VOLTAGE)*1000;
                    int volminerr = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MIN_VOLTAGE_ERR)*1000;
                    if (val >= volmax)
                    {
                        if(voltage_ch_time == 0)
                        {
                            voltage_ch_time = time(NULL);
                        }
                    }
                    else if (val < (volmax - volmaxerr))
                    {
                        voltage_ch_time = 0;
                        CLR_AMASK_BIT(pro_chg_flag, 5);
                        if ((cur_vol_min > (volmin + volminerr)))
                        {
                            dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 0);
                        }
                    }
                }
                else 
                {
                    SET_AMASK_BIT(pro_chg_flag,5);
                    dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 1);
                }
            }
        }
        else
        {
            dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 0);
            CLR_AMASK_BIT(pro_chg_flag,5);
        }
    }
    else if (strcmp(nod, DEV_NO_EMS "." USER_STOP_CHA1) == 0 || strcmp(nod, DEV_NO_EMS "." USER_STOP_CHA2) == 0 || strcmp(nod, DEV_NO_EMS "." USER_STOP_CHA3) == 0)
    {
        int val = (data_value->type == TYPE_TAG_INT) ? data_value->value.to_int : data_value->value.to_float;
        if (val == ALARM_STATUS_TRIG)
            SET_AMASK_BIT(pro_chg_flag, 6);
        else
            CLR_AMASK_BIT(pro_chg_flag, 6);
    }
    else if(dev_get_dev_tag_int(DEV_NO_EMS, EN_BMS_ALARM) && data_value != NULL)
    {
        int val = (data_value->type == TYPE_TAG_INT) ? data_value->value.to_int : data_value->value.to_float;
        if (strcmp(nod,DEV_NO_BMS"."CELL_OVER_VOL2) == 0)
        {
            if(val == ALARM_STATUS_TRIG )
            {
                SET_AMASK_BIT(pro_chg_flag,1);
            }
            else
            {
                CLR_AMASK_BIT(pro_chg_flag,1);
            }
        }
        if (strcmp(nod,DEV_NO_BMS"."CELL_OVER_VOL3) == 0)
        {
            if(val == ALARM_STATUS_TRIG )
            {
                SET_AMASK_BIT(pro_chg_flag,2);
            }
            else
            {
                CLR_AMASK_BIT(pro_chg_flag,2);
            }
        }
        if (strcmp(nod,DEV_NO_BMS"."RACK_OVER_VOL2) == 0)
        {
            if(val == ALARM_STATUS_TRIG )
            {
                SET_AMASK_BIT(pro_chg_flag,3);
            }
            else
            {
                CLR_AMASK_BIT(pro_chg_flag,3);
            }
        }
        if (strcmp(nod,DEV_NO_BMS"."RACK_OVER_VOL3) == 0)
        {
            if(val == ALARM_STATUS_TRIG )
            {
                SET_AMASK_BIT(pro_chg_flag,4);
            }
            else
            {
                CLR_AMASK_BIT(pro_chg_flag,4);
            }
        }
    }
    else //不使能清空
    {
        CLR_AMASK_BIT(pro_chg_flag,1);
        CLR_AMASK_BIT(pro_chg_flag,2);
        CLR_AMASK_BIT(pro_chg_flag,3);
        CLR_AMASK_BIT(pro_chg_flag,4);
    }

    if (pro_chg_flag>0)
    {
        if (dev_get_dev_tag_int(DEV_NO_EMS, PROHIBITE_CHARGE)!=1)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, PROHIBITE_CHARGE,  1);
            lc_power_info_t power_info = {0};
            set_lc_power(power_info); 
        }
    }
    else
    {
        if (dev_get_dev_tag_int(DEV_NO_EMS, PROHIBITE_CHARGE)!=0)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, PROHIBITE_CHARGE,0);
        }
    }
}

static void fast_stop_discharge_tab_cb(char *nod,tag_value *data_value)
{
    static int pro_dischg_flag = 0;
    if (strcmp(nod,DEV_NO_BMS"."CURRENT_SOC) == 0)
    {
        if(g_usercfg_variant.EnProtectDOD)
        {
            double value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
            double socmin = dev_get_dev_tag_float(DEV_NO_EMS, EMS_SOCMIN);
            double socminerr = dev_get_dev_tag_float(DEV_NO_EMS, EMS_SOCMINERR);
            if (value <= socmin)
            {
                SET_AMASK_BIT(pro_dischg_flag,0);
            }
            else if (value > (socmin + socminerr))
            {
                CLR_AMASK_BIT(pro_dischg_flag,0);
            }
        }
        else
        {
            CLR_AMASK_BIT(pro_dischg_flag,0);
        }
    } 
    else if (strcmp(nod,DEV_NO_BMS"."RACK_MIN_VOLT) == 0  && (0 == get_cabinet_info()->mode_microgrid))
    {
        if(g_usercfg_variant.EnCellVoltProtect)
        {
            if(g_usercfg_variant.SingleVoltageTime == 0)
            {
                int val = data_value->value.to_int;
                int cur_vol_max = dev_get_dev_tag_int(DEV_NO_BMS, RACK_MAX_VOLT);
                int volmin = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MIN_VOLTAGE)*1000;
                int volminerr = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MIN_VOLTAGE_ERR)*1000;
                int volmax = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MAX_VOLTAGE)*1000;
                int volmaxerr = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MAX_VOLTAGE_ERR)*1000;
                if (val <= volmin)
                {
                    SET_AMASK_BIT(pro_dischg_flag,5);
                    dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 1);
                }
                else if (val > (volmin + volminerr))
                {
                    CLR_AMASK_BIT(pro_dischg_flag, 5);
                    if ((cur_vol_max < (volmax - volmaxerr)))
                    {
                        dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 0);
                    }
                }
            }
            else 
            {
                if(data_value != NULL)
                {
                    int val = data_value->value.to_int;
                    int cur_vol_max = dev_get_dev_tag_int(DEV_NO_BMS, RACK_MAX_VOLT);
                    int volmin = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MIN_VOLTAGE)*1000;
                    int volminerr = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MIN_VOLTAGE_ERR)*1000;
                    int volmax = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MAX_VOLTAGE)*1000;
                    int volmaxerr = dev_get_dev_tag_float(DEV_NO_EMS, SINGLE_MAX_VOLTAGE_ERR)*1000;
                    if (val <= volmin)
                    {
                        if(voltage_dc_time == 0)
                        {
                            voltage_dc_time = time(NULL);
                        }
                    }
                    else if(val > (volmin + volminerr))
                    {
                        voltage_dc_time = 0;
                        CLR_AMASK_BIT(pro_dischg_flag, 5);
                        if ((cur_vol_max < (volmax - volmaxerr)))
                        {
                            dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 0);
                        }
                    }
                }
                else 
                {
                    SET_AMASK_BIT(pro_dischg_flag,5);
                    dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 1);
                }
            }
        }
        else
        {
            dev_set_dev_tag_int(DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, 0);
            CLR_AMASK_BIT(pro_dischg_flag,5);
        }
    }

    else if (strcmp(nod, DEV_NO_EMS "." USER_STOP_DISCHA1) == 0 || strcmp(nod, DEV_NO_EMS "." USER_STOP_DISCHA2) == 0 || strcmp(nod, DEV_NO_EMS "." USER_STOP_DISCHA3) == 0)
    {
        int val = (data_value->type == TYPE_TAG_INT) ? data_value->value.to_int : data_value->value.to_float;
        if (val == ALARM_STATUS_TRIG)
            SET_AMASK_BIT(pro_dischg_flag, 7);
        else
            CLR_AMASK_BIT(pro_dischg_flag, 7);
    }
    else if(dev_get_dev_tag_int(DEV_NO_EMS, EN_BMS_ALARM) && data_value != NULL)
    {
        int val = (data_value->type == TYPE_TAG_INT) ? data_value->value.to_int : data_value->value.to_float;
        if (strcmp(nod,DEV_NO_BMS"."CELL_UNDER_VOL2) == 0)
        {
            if(val == ALARM_STATUS_TRIG )
            {
                SET_AMASK_BIT(pro_dischg_flag,1);
            }
            else
            {
                CLR_AMASK_BIT(pro_dischg_flag,1);
            }
        }
        if (strcmp(nod,DEV_NO_BMS"."CELL_UNDER_VOL3) == 0)
        {
            if(val == ALARM_STATUS_TRIG )
            {
                SET_AMASK_BIT(pro_dischg_flag,2);
            }
            else
            {
                CLR_AMASK_BIT(pro_dischg_flag,2);
            }
        }
        if (strcmp(nod,DEV_NO_BMS"."RACK_UNDER_VOL2) == 0)
        {
            if(val == ALARM_STATUS_TRIG )
            {
                SET_AMASK_BIT(pro_dischg_flag,3);
            }
            else
            {
                CLR_AMASK_BIT(pro_dischg_flag,3);
            }
        }
        if (strcmp(nod,DEV_NO_BMS"."RACK_UNDER_VOL3) == 0)
        {
            if(val == ALARM_STATUS_TRIG )
            {
                SET_AMASK_BIT(pro_dischg_flag,4);
            }
            else
            {
                CLR_AMASK_BIT(pro_dischg_flag,4);
            }
        }
    }
    else //不使能得清空
    {
        CLR_AMASK_BIT(pro_dischg_flag,1);
        CLR_AMASK_BIT(pro_dischg_flag,2);
        CLR_AMASK_BIT(pro_dischg_flag,3);
        CLR_AMASK_BIT(pro_dischg_flag,4);
    }

    if (pro_dischg_flag>0)
    {
        if (dev_get_dev_tag_int(DEV_NO_EMS, PROHIBITE_DISCHARGE)!=1)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, PROHIBITE_DISCHARGE,  1);
            lc_power_info_t power_info = {0};
            set_lc_power(power_info); 
        }
    }
    else
    {
        if (dev_get_dev_tag_int(DEV_NO_EMS, PROHIBITE_DISCHARGE)!=0)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, PROHIBITE_DISCHARGE,0);
        }
    }
}

static void fast_charge_max_power_cb(char *nod, tag_value *data_value)
{
    float value = (data_value->type == TYPE_TAG_INT) ? data_value->value.to_int : data_value->value.to_float;
    double RackVoltage = 0.0, RackMaxChargeCur = 0.0, ChargePower = 0.0;
    if(strstr(nod, RACK_VOLTAGE))
    {
        RackVoltage = value;
        RackMaxChargeCur = dev_get_dev_tag_float(DEV_NO_BMS, RACK_MAX_CHARGE_CUR);
    }
    else if(strstr(nod, RACK_MAX_CHARGE_CUR))
    {
        RackMaxChargeCur = value;
        RackVoltage = dev_get_dev_tag_float(DEV_NO_BMS, RACK_VOLTAGE);
    }
    ChargePower = RackVoltage * RackMaxChargeCur / 1000.0;
    dev_set_dev_tag_float(DEV_NO_EMS, MAX_CHARGE_POWER, ChargePower);
}


static void fast_discha_max_power_cb(char *nod, tag_value *data_value)
{
    float value = (data_value->type == TYPE_TAG_INT) ? data_value->value.to_int : data_value->value.to_float;
    double RackVoltage = 0.0, RackMaxDischargeCur = 0.0, DisChargePower = 0.0;
    if(strstr(nod, RACK_VOLTAGE))
    {
        RackVoltage = value;
        RackMaxDischargeCur = dev_get_dev_tag_float(DEV_NO_BMS, RACK_MAX_DISCHA_CUR);
    }
    else if(strstr(nod, RACK_MAX_DISCHA_CUR))
    {
        RackMaxDischargeCur = value;
        RackVoltage = dev_get_dev_tag_float(DEV_NO_BMS, RACK_VOLTAGE);
    }
    DisChargePower = RackVoltage * RackMaxDischargeCur / 1000.0;
    dev_set_dev_tag_float(DEV_NO_EMS, MAX_DISCHA_POWER, DisChargePower);
}



static void fast_stop_system_state_cb(char *nod, tag_value *data_value)
{
    int val = ALARM_STATUS_NO;
    static int status = 0;

    if (data_value->type == TYPE_TAG_INT)
        val = data_value->value.to_int;
    else
        val = data_value->value.to_float;

    // 检查是否是DEV_NO_PCS.STATE_ONLINE点位
    char online_tag[TAG_NAME_LEN] = {0};
    snprintf(online_tag, sizeof(online_tag), "%s.%s", DEV_NO_PCS, STATE_ONLINE);
    if (strstr(nod, online_tag) != NULL && val == 0)
    {
        // PCS离线，设置EMS的有功功率和无功功率为0
        dev_set_dev_tag_float(DEV_NO_EMS, ACTIVE_POWER, 0.0f);
        dev_set_dev_tag_float(DEV_NO_EMS, REACTIVE_POWER, 0.0f);
        dev_set_dev_tag_float(DEV_NO_EMS, PHASE_A_POWER, 0.0f);
        dev_set_dev_tag_float(DEV_NO_EMS, PHASE_B_POWER, 0.0f);
        dev_set_dev_tag_float(DEV_NO_EMS, PHASE_C_POWER, 0.0f);
    }

    int enableBmsAlarm = dev_get_dev_tag_int(DEV_NO_EMS, EN_BMS_ALARM);
    int fast_stop_system_state_tab_size = sizeof(fast_stop_system_state_tab) / sizeof(fast_stop_system_state_tab[0]);
    if (enableBmsAlarm == 0 && (strstr(nod, DEV_NO_BMS ".") == nod))
    {
        ems_syslog(LOG_NOTICE, "enableBmsAlarm is not true, nod:%s, val:%d", nod, val);
        return;
    }

    for (size_t i = 0; i < fast_stop_system_state_tab_size; i++)
    {
        if (strcmp(nod, fast_stop_system_state_tab[i]) == 0)
        {
            if (val != 0)
            {
                SET_AMASK_BIT(status, i);
            }
            else
            {
                CLR_AMASK_BIT(status, i);
            }
        }
    }

    for (size_t i = 0; i < sizeof(fast_stop_system_state_tab_not) / sizeof(fast_stop_system_state_tab_not[0]); i++)
    {
        if (strcmp(nod, fast_stop_system_state_tab_not[i]) == 0)
        {
            if (val == 0)
            {
                SET_AMASK_BIT(status, (i + fast_stop_system_state_tab_size));
            }
            else
            {
                CLR_AMASK_BIT(status, (i + fast_stop_system_state_tab_size));
            }
        }
    }

    dev_set_dev_tag_int(DEV_NO_EMS, SYSTEM_STATUS_W, status);
    if(status > 0 )
    {
        int sys_flag = dev_get_dev_tag_int(DEV_NO_EMS, SYSTEM_STATUS);
        dev_set_dev_tag_int(DEV_NO_EMS, SYSTEM_STATUS,  1);
        if (0 == sys_flag)
        {
            lc_power_info_t power_info = {0};
            set_lc_power(power_info);
        }
            
    }
    else
    {
        dev_set_dev_tag_int(DEV_NO_EMS, SYSTEM_STATUS, 0);
    }
}

static void fast_stop_dc_voltage_unusual_cb(char *nod,tag_value *data_value)
{

    float val = data_value->value.to_float;
    if (val<DC_TOTAL_VOL_LIMIT)
    {
        dev_set_dev_tag_int(DEV_NO_EMS, DC_TOTAL_VOL_LOW,  1);
    }
    else
    {
        dev_set_dev_tag_int(DEV_NO_EMS, DC_TOTAL_VOL_LOW,  0);
    }
    
}

void *context = NULL;
int add_ems_variant()
{
    ems_base_variant_multi_add(ems_base_variant,ARRAY_SIZE(ems_base_variant));
    ems_base_variant_t ems_var = {.dev = NULL, .flag = O_WRONLY | O_RDONLY, .data_type = TYPE_TAG_INT, .point_type = PROPERTY_REALDATA, .history_type = "off", .fun_code = 0x03, .addr = 0x1000,  .type = TYPE_INT, .order = ORDER_AB, .coefficient = 1};
    for(int i = 0;i< get_tou_max_num();i++)//最大96段
    {
        ems_var.dev = strdup(DEV_NO_EMS);
        
        ems_syslog(LOG_NOTICE, "ems_var.dev:%s",ems_var.dev);

        char *variant = NULL;
        char *name = NULL;
        char *desc=NULL;
        char variant_a[NODE_SIZE]={0};
        char name_a[NODE_SIZE]={0};
        char desc_a[DESC_SIZE]={0};
        {
        //TODO 数据类型
        snprintf(variant_a,sizeof(variant_a),"S%dStHour",i+1);
        ems_syslog(LOG_NOTICE, "variant_a:%s len:%lu",variant_a,(long unsigned int)strlen(variant_a));
        snprintf(name_a, sizeof(name_a), _("Starting hour of the %d strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"S%dStMin",i+1);
        snprintf(name_a, sizeof(name_a), _("Starting minute of the %d strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"S%dEnHour",i+1);
        snprintf(name_a, sizeof(name_a), _("Ending hour of the %d strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;
        
        snprintf(variant_a,sizeof(variant_a),"S%dEnMin",i+1);
        snprintf(name_a, sizeof(name_a), _("Ending minute of the %d strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);


        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"S%dPower",i+1);
        snprintf(name_a, sizeof(name_a), _("Executed power of the %d strategy(-charging +discharging)"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"S%dRePower",i+1);
        snprintf(name_a, sizeof(name_a), _("Executed repower of the %d strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"S%dSOCUpperLimit",i+1);
        snprintf(name_a, sizeof(name_a), _("Soc Limit upper of the %d strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"S%dSOCLowerLimit",i+1);
        snprintf(name_a, sizeof(name_a), _("Soc Limit lower of the %d strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        // snprintf(variant_a,sizeof(variant_a),"S%dMode",i+1);
        // snprintf(name_a,sizeof(name_a),"第%d段策略模式",i+1);

        // variant = strdup(variant_a);
        // name = strdup(name_a);
        
        // ems_var.name = name;
        // ems_var.variant = variant;
        // ems_base_variant_sing_add(&ems_var);   
    }      
        //TOU
        snprintf(variant_a,sizeof(variant_a),"TOUS%dStHour",i+1);
        snprintf(name_a, sizeof(name_a), _("Starting hour of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;


        snprintf(variant_a,sizeof(variant_a),"TOUS%dStMin",i+1);
        snprintf(name_a, sizeof(name_a), _("Starting minute of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dEnHour",i+1);
        snprintf(name_a, sizeof(name_a), _("Ending hour of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dEnMin",i+1);
        snprintf(name_a, sizeof(name_a), _("Ending minute of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dPower",i+1);
        snprintf(name_a, sizeof(name_a), _("Max power of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dStratagyType",i+1);
        snprintf(name_a, sizeof(name_a), _("Strategy of the %d TOU strategy"), i + 1);
        snprintf(desc_a, sizeof(desc_a), _("0:Self use absorption;1:To grid first;2:Emergency backup power;3:Dynamic augmentation;4:User defined"));

        variant = strdup(variant_a);
        name = strdup(name_a);
        desc = strdup(desc_a);
        ems_var.name = name;
        ems_var.variant = variant;
        ems_var.desc = desc;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;
        ems_var.desc = NULL;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dSOCUpperLimit",i+1);
        snprintf(name_a, sizeof(name_a), _("Soc Limit upper of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dSOCLowerLimit",i+1);
        snprintf(name_a, sizeof(name_a), _("Soc Limit lower of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dSurplusToGrid",i+1);
        snprintf(name_a, sizeof(name_a), _("Surplus to the grid of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dChargePower",i+1);
        snprintf(name_a, sizeof(name_a), _("Start charge power of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dDischargePower",i+1);
        snprintf(name_a, sizeof(name_a), _("Start discharge power of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;
        
        snprintf(variant_a,sizeof(variant_a),"TOUS%dChargeGrid",i+1);
        snprintf(name_a, sizeof(name_a), _("Allow charge from grid of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;

        snprintf(variant_a,sizeof(variant_a),"TOUS%dChargeDG",i+1);
        snprintf(name_a, sizeof(name_a), _("Allow charge from DG of the %d TOU strategy"), i + 1);

        variant = strdup(variant_a);
        name = strdup(name_a);

        ems_var.name = name;
        ems_var.variant = variant;
        ems_base_variant_sing_add(&ems_var);
        ems_var.addr++;
        

        for (size_t j = 0; j < g_usercfg_variant.TOU_info[i].userdefNum; j++)
        {
            snprintf(variant_a,sizeof(variant_a),"TOUS%d%s",i+1,g_usercfg_variant.TOU_info[i].userdef[j].id);
            tag_t *tag_tmp = find_tag_by_name(get_proto_forward_var(),g_usercfg_variant.TOU_info[i].userdef[j].tag);
            if (g_usercfg_variant.TOU_info[i].userdef[j].name)
            {
                char name_tmp[TAG_NAME_LEN] = {0};
                snprintf(name_tmp, sizeof(name_tmp), _("of the %d TOU strategy"), i + 1);
                snprintf(name_a, sizeof(name_a), "%s %s",g_usercfg_variant.TOU_info[i].userdef[j].name, name_tmp);
            }
            else if (tag_tmp)
            {
                char name_tmp[TAG_NAME_LEN] = {0};
                snprintf(name_tmp, sizeof(name_tmp), _("of the %d TOU strategy"), i + 1);
                snprintf(name_a, sizeof(name_a), "%s %s",tag_tmp->dev_tag_name, name_tmp);
            }
            else
            {
                proto_syslog(LOG_ERR, "TOU ERR time %d info %d not find!",i,j);
            }
            if (tag_tmp)
            {
                variant = strdup(variant_a);
                name = strdup(name_a);
                ems_var.name = name;
                ems_var.variant = variant;
                ems_var.desc = tag_tmp->desc;
                ems_base_variant_sing_add(&ems_var);
                ems_var.addr++;
                ems_var.desc = NULL;
            }
        }
        
    }

    if (get_cabinet_info()->mode_microgrid != 0){
        ems_base_variant_multi_add(ems_microgri_variant, ARRAY_SIZE(ems_microgri_variant));
    }
    return 0;
}


int device_variant_mirrors(void)
{

    // write_file_data(VAR_MIRROR_FILE, string, strlen(string));   
    return 0;
}
int device_layer_selftest(void *p)
{
    //TODO检查相关点位是否存在
    return 0;
}


static char *creat_vlc_template(void)
{
    int size = 1024;
    char *ret = NULL;
    char *proto_arr[] = {"opcua", "lc", NULL};
    template_info_t info = {.protocol = proto_arr, .vendor="Lnxall", .model = "LC", .version = "", .type = "EMS"};
    ems_base_variant_t **p = calloc(size, sizeof(ems_base_variant_t *));
    int cur = 0;
    for (int i = 0; i < sizeof(vlc_base_variant) / sizeof(vlc_base_variant[0]); i++)
    {
        if (cur < size)
        {
            p[cur] = calloc(1, sizeof(ems_base_variant_t));
            *p[cur] = vlc_base_variant[i];
            p[cur]->variant = strdup(vlc_base_variant[i].variant); // 为了后面统一释放
            p[cur]->name = strdup(vlc_base_variant[i].name);
            cur++;
        }
    }

    ret = create_ems_template(&info, p, cur);
    //
    for (int i = 0; i < cur; i++)
    {
        free(p[i]->variant);
        free(p[i]->name);
        free(p[i]);
    }
    free(p);

    return ret;
}


int check_and_creat_vlc_template(void)
{
    int ret = 0;
    char *vlc_template = creat_vlc_template();
    if (vlc_template == NULL)
    {
        proto_syslog(LOG_ERR, "vlc_template is NULL");
    }
    else
    {
        char *old_vlc_template = read_file_data(TEMPLATE_DIR"/"EMS_VLC_TEMPLATE);
        if (old_vlc_template == NULL)
        {
            write_file_data(TEMPLATE_DIR"/"EMS_VLC_TEMPLATE, vlc_template, strlen(vlc_template));
        }
        else
        {
            if (strcmp(old_vlc_template, vlc_template) != 0)
            {
                write_file_data(TEMPLATE_DIR"/"EMS_VLC_TEMPLATE, vlc_template, strlen(vlc_template));
            }
            free(old_vlc_template);
        }
        free(vlc_template);
    }

    return ret;
}

int device_layer_init(void *parm)
{
    int ret = 0;
    if (parm == NULL)
    {
        return -1;
    }
    MODBUS_SERVER_PARAM *var = ((proto_forward_t *)parm)->modbus_server_param;
    ret = add_ems_variant();
    char *proto_arr[] = {"ems", NULL};
    template_info_t info = {.protocol = proto_arr, .vendor ="Lnxall", .model = DEV_NO_EMS, .version = "", .type = "EMS"};
    ems_base_variant_t **base_var_p =NULL;
    int size = 0;
    ret = ems_base_variant_get(&base_var_p,&size); 
    if(ret == 0)
    {
        if(size == 0)
        {
            return -1;
        }
        bool  created = false;
        char *ems_dev_json = NULL;
        char *temp_json = NULL;
        char *ems_temp_json_save= NULL;
        char *ems_dev_json_save =NULL;

        var->modbus_ser_base_data->config_str_to_ems = create_md_server_tag_addr(base_var_p, size);
        if (var->modbus_ser_base_data->config_str_to_ems != NULL)
        {
            write_file_data(MODBUS_SERVER_TAG_ADDR_MAP_FILE, var->modbus_ser_base_data->config_str_to_ems, strlen(var->modbus_ser_base_data->config_str_to_ems));
        }
        else
        {
            ems_syslog(LOG_ERR, "create modbus server tag addr failed");
        }
        char *p_tmp = create_modbus_server_template(base_var_p, size);
        if (p_tmp != NULL)
        {
            write_file_data(MODBUS_SERVER_TAG_TEMPLATE_FILE, p_tmp, strlen(p_tmp));
            free(p_tmp);
        }
        else
        {
            ems_syslog(LOG_ERR, "create modbus server tag template failed");
        }
        
        ems_dev_json_save = read_file_data(CONFIG_PATH"/"EMS_DEVICE_MASTER_FILE);
        if(!ems_dev_json_save)
        {
            ems_dev_json = create_ems_device(EMS_TEMP_MASTER_FILE);
            if (ems_dev_json)
            {
                created = true;
                write_file_data(CONFIG_PATH"/"EMS_DEVICE_MASTER_FILE, ems_dev_json, strlen(ems_dev_json));
            }
            else
            {
                ems_syslog(LOG_ERR, "create ems device error!!!!");
            }
        }
        if(!created)
        {
            
            if(!ems_dev_json)
            {
                ems_dev_json = create_ems_device(EMS_TEMP_MASTER_FILE);
            }
            if(strcmp(ems_dev_json,ems_dev_json_save) != 0)
            {
                write_file_data(CONFIG_PATH"/"EMS_DEVICE_MASTER_FILE, ems_dev_json, strlen(ems_dev_json));
            } 

        }

        created = false;
        ems_temp_json_save = read_file_data(TEMPLATE_DIR"/"EMS_TEMP_MASTER_FILE);
        if(!ems_temp_json_save)
        {
            temp_json = create_ems_template(&info,base_var_p,size);
            if (temp_json)
            {
                created = true;
                write_file_data(TEMPLATE_DIR"/"EMS_TEMP_MASTER_FILE, temp_json, strlen(temp_json));
                free(temp_json);
                temp_json = NULL;
            }
        }
        if(!created)
        {   
            if(!temp_json)temp_json = create_ems_template(&info,base_var_p,size);
            if(strcmp(temp_json,ems_temp_json_save) != 0)
            {
                write_file_data(TEMPLATE_DIR"/"EMS_TEMP_MASTER_FILE, temp_json, strlen(temp_json));
            }        
        }

        if(temp_json!=NULL)
        {
            free(temp_json);
            temp_json = NULL;
        }
        if(ems_temp_json_save!=NULL)
        {
            free(ems_temp_json_save);
            ems_temp_json_save = NULL;
        }

        if(ems_dev_json!=NULL)
        {
            free(ems_dev_json);
            ems_dev_json = NULL;
        }
        if(ems_dev_json_save!=NULL)
        {
            free(ems_dev_json_save);
            ems_dev_json_save = NULL;
        }
        //ems_base_variant_free();内部释放不完全，加上只会调用一次所以直接不释放
    }
    return ret;
}

#define POWER_OFF_LOCK_TIME 5
static void fast_stop_fire_cb(char *nod,tag_value *data_value)
{
    if (dev_get_dev_tag_int(DEV_NO_EMS, EMS_POWER) == 1 && time(NULL) - get_pcs_ctrl_var()->power_down_time < POWER_OFF_LOCK_TIME)
        return;
    
    int val = ALARM_STATUS_NO;
    static int hold_status = 0;
    static int status = 0;

    if(data_value->type == TYPE_TAG_INT)
        val = data_value->value.to_int;
    else 
        val = data_value->value.to_float;
    


    if (strcmp(nod,DEV_NO_EMS"."EXTERN_FIRE)==0)
    {
        if(val == ALARM_STATUS_TRIG)
        {
            SET_AMASK_BIT(status,0);
        }
        else
        {
            CLR_AMASK_BIT(status,0);
        }
    }
    else if (strcmp(nod,DEV_NO_EMS"."FIRE)==0)
    {
        if (dev_get_dev_tag_int(DEV_NO_EMS, EN_IO_PROTECT) == 0)
        {
            return;
        }
        if(val == ALARM_STATUS_TRIG)
        {
            SET_AMASK_BIT(status,1);
        }
        else
        {
            CLR_AMASK_BIT(status,1);
        }
    }
    ems_syslog(LOG_NOTICE, "fast stop fast_stop_fire [nod:%s] -> [%d]",nod,val);
    if(status != hold_status)
    {
        hold_status = status;
        if (hold_status > 0)
        {
            dev_set_dev_tag_int(DEV_NO_EMS, ALL_FIRE, 1);
            do_trip(); //触发脱扣
                    // 是否切换为手动模式
            dev_set_dev_tag_int(DEV_NO_EMS, CONTROL_MODE, 0);
            dev_set_dev_tag_float(DEV_NO_EMS, SET_ACT_POWER, 0);
        }
        else
        {
            dev_set_dev_tag_int(DEV_NO_EMS, ALL_FIRE,  0);
        }
    }
}

static void fast_stop_power_cb(char* nod, tag_value* data_value)
{
    int val = 0;

    if (data_value->type == TYPE_TAG_INT)
        val = data_value->value.to_int;
    else
        val = data_value->value.to_float;


    if (val == 0)
    {
        ems_syslog(LOG_DEBUG, "ems power change : %d", val);
        get_pcs_ctrl_var()->power_down_time = 0;
    }
    else
    {
        ems_syslog(LOG_ERR, "ems power change : %d", val);
        get_pcs_ctrl_var()->power_down_time = time(NULL);
    }

}

void lc_fire_cb(int fireNum) //局域网内触发消防的数量不包含自己
{
    if (fireNum>0)
    {
        dev_set_dev_tag_int(DEV_NO_EMS, EXTERN_FIRE,1);
    }
    else
    {
        dev_set_dev_tag_int(DEV_NO_EMS, EXTERN_FIRE,0);
    }
}

static void node_sync_tab_cb(char *nod, tag_value *data_value)
{
    //
    const char *first_dot = strchr(nod, '.');
    if (first_dot == NULL)
    {
        ems_syslog(LOG_ERR, "No '.' found in the string:%s", nod);
        return;
    }
    if (data_value->type == 0)
    {
        dev_set_dev_tag_int(DEV_NO_EMS, first_dot + 1, data_value->value.to_int);
    }
    else
    {
        dev_set_dev_tag_float(DEV_NO_EMS, first_dot + 1, data_value->value.to_float);
    }
}

/*需要管理同步参数仅需在此处增减tag*/
const char* lc_server_sync_tag[] = {
    DEV_NO_EMS "." ON_OFF_STATE,
    DEV_NO_EMS "." SET_CONNECT,
    DEV_NO_EMS "." BMS_UPPER,
    DEV_NO_EMS "." EN_PROTECT_DOD,
    DEV_NO_EMS "." EN_BMS_ALARM,
    DEV_NO_EMS "." BMS_POWER_LIMIT,
    DEV_NO_EMS "." EMS_SOCMAX,
    DEV_NO_EMS "." EMS_SOCMIN,
    DEV_NO_EMS "." PCS_AUTO_TURN,
    DEV_NO_EMS "." PCS_AUTO_TURN_OFF_TIME,
    DEV_NO_EMS "." WORK_START_HOT_TEMP,
    DEV_NO_EMS "." WORK_END_HOT_TEMP,
    DEV_NO_EMS "." WORK_START_COOL_TEMP,
    DEV_NO_EMS "." WORK_END_COOL_TEMP,
    DEV_NO_EMS "." WORK_DIST_HOT_TEMP,
    DEV_NO_EMS "." WORK_DIST_COOL_TEMP,
    DEV_NO_EMS "." STOP_START_HOT_TEMP,
    DEV_NO_EMS "." STOP_END_HOT_TEMP,
    DEV_NO_EMS "." STOP_START_COOL_TEMP,
    DEV_NO_EMS "." STOP_END_COOL_TEMP,
    DEV_NO_EMS "." STOP_DIST_HOT_TEMP,
    DEV_NO_EMS "." STOP_DIST_COOL_TEMP,
    DEV_NO_EMS "." TMS_CTRL_DIST_TEMP_COLD,
    DEV_NO_EMS "." TMS_CTRL_DIST_TEMP_HOT,
    DEV_NO_EMS "." AIR_COND_STARTSTOP_CTRL,
    DEV_NO_EMS "." EN_SELF_LOOP_DIFF,
    DEV_NO_EMS "." START_SELF_LOOP_DIFF,
    DEV_NO_EMS "." END_SELF_LOOP_DIFF,
    DEV_NO_EMS "." ENABLE_AIR_COND,
    DEV_NO_EMS "." ENABLE_AUTO_COOL,
    DEV_NO_EMS "." EN_CELL_VOLT_PROTECT,
    DEV_NO_EMS "." EN_DRAUG_FLOW_POWER,
    DEV_NO_EMS "." EN_DRAUG_FLOW_POWER_T,
    DEV_NO_EMS "." EN_DRAUG_FLOW_TEM,
    DEV_NO_EMS "." EN_DRAUG_FLOW_TEM_T,
    DEV_NO_EMS "." DRAUG_DEAE_TIME,
    DEV_NO_EMS "." SINGLE_MIN_VOLTAGE,
    DEV_NO_EMS "." SINGLE_MAX_VOLTAGE,
    DEV_NO_EMS "." SINGLE_MIN_VOLTAGE_ERR,
    DEV_NO_EMS "." SINGLE_MAX_VOLTAGE_ERR,
    DEV_NO_EMS "." EMS_SOCMAXERR,
    DEV_NO_EMS "." EMS_SOCMINERR,
    DEV_NO_EMS "." EN_RP_COMP,
    DEV_NO_EMS "." SET_POWER_FACTOR,
    DEV_NO_EMS "." EN_IO_PROTECT,
    DEV_NO_EMS "." CELL_VOLT_PROTECT_TIME,
    DEV_NO_EMS "." PCS_FAULT_RESET,
    DEV_NO_EMS "." ENABLE_SINGLE_PHASE_REVERSE,
};

struct lc_server_sync_info{
    const char *tag;        // tag 来自于 lc_server_sync_tag
    int type;               // 类型: int:0 float:1 没找到该节点:-1
    union  {
        int to_int;
        double to_float;
    } data;                 // 存储数据
};

struct lc_server_sync_info *lc_server_sync_data_buf = NULL;      // 非外部初始化且规避内存泄漏

void lc_server_sync_data_init()
{

    int size = sizeof(lc_server_sync_tag) / sizeof(lc_server_sync_tag[0]);
    static struct lc_server_sync_info LC_data[sizeof(lc_server_sync_tag) / sizeof(lc_server_sync_tag[0])];
    for (size_t i = 0; i < size; i++)
    {
	const char *nod = NULL;
       	char *dot = NULL;

        double tmp_float = 0;
        int tmp_int = 0;
        nod = lc_server_sync_tag[i];
        dot = strchr(nod, '.');
        if (NULL == dot)
            continue;
        dot++;
        LC_data[i].tag = (const char *)dot;

        if (0 == collector_read_one_int_data(nod, &tmp_int)) // int查找，失败了转float 再失败则判定无此值
        {
            LC_data[i].type = 0;
            LC_data[i].data.to_int = tmp_int;
        }
        else if (0 == collector_read_one_float_data(nod, &tmp_float))
        {
            LC_data[i].type = 1;
            LC_data[i].data.to_float = tmp_float;
        }
        else
        {
            LC_data[i].type = -1;
            ems_syslog(LOG_ERR, "Error in writing data, tag = %s:failed to register", nod); // 没找到
        }
    }
    lc_server_sync_data_buf = LC_data;
}
void parameterSyncFlush()
{
    pcs_ctrl_var_t *var = get_pcs_ctrl_var();
    int lc_cnt = var->lc_list_len;
    int lc_sync_cnt = sizeof(lc_server_sync_tag) / sizeof(lc_server_sync_tag[0]);
    lc_it *lc_list_tmp = var->lc_list;

    char string_no[NODE_SIZE] = "";
    microgrid_cfg_t *microgrid_cfg = get_microgrid_cfg_var();
    for (int i = 0; i < lc_cnt; i++)
    {
        if (lc_list_tmp[i].disabled != 0)
        {
            continue;
        }
        for(int j = 0; j < lc_sync_cnt; j++)
        {
            snprintf(string_no, NODE_SIZE, "%s.%s", lc_list_tmp[i].no, lc_server_sync_data_buf[j].tag);

            if (microgrid_cfg->mode_microgrid != 0 && microgrid_cfg->en_sts == 1){  // 若微网模式+使能STS-->不发并离网操作
                if (strstr(string_no, "SetConnect")){
                    continue;
                }
            } 
            if(strstr(string_no, "PcsFaultReset") && lc_server_sync_data_buf[j].data.to_int == 1)
            {
                continue;
            }
            if (0 == lc_server_sync_data_buf[j].type)
            {
                collector_write_one_int_data(string_no, lc_server_sync_data_buf[j].data.to_int);
            }
            else if (1 == lc_server_sync_data_buf[j].type)
            {
                collector_write_one_float_data(string_no, lc_server_sync_data_buf[j].data.to_float);
            }
            else 
            {
                ems_syslog(LOG_ERR, "Error in writing data, tag = %s:failed to register", lc_server_sync_data_buf[j].tag);
            }
        }
    }
}
void *parameterSynchronizationThread(void *arg)
{

    while(1)
    {
        parameterSyncFlush();
        sleep(60);
    }
}
void parameterSynchronizationIni()
{

    if (NULL == lc_server_sync_data_buf)
    {
        lc_server_sync_data_init();
    }
    pthread_t threads;
    pthread_create(&threads, NULL, parameterSynchronizationThread, NULL);
    // XCl TODO

    // pthread_join(threads, NULL);
}

// 数据刷新缓冲区
void clServiceDataChange(char *nod, tag_value *data_value)
{
    int lc_sync_cnt = sizeof(lc_server_sync_tag) / sizeof(lc_server_sync_tag[0]);
    char *dot;

    // 遍历字符串数组
    for(int i = 0; i < lc_sync_cnt; i++)
    {
        dot = strchr(nod, '.');
        if (dot != NULL)
        {
            dot++;
            if (strcmp(dot, lc_server_sync_data_buf[i].tag) == 0)
            {
                if (data_value->type == 0)
                {
                    lc_server_sync_data_buf[i].type = 0;
                    lc_server_sync_data_buf[i].data.to_int = data_value->value.to_int;
                }
                else if (data_value->type == 1)
                {
                    lc_server_sync_data_buf[i].type = 1;
                    lc_server_sync_data_buf[i].data.to_float = data_value->value.to_float;
                }
                else
                {
                    ems_syslog(LOG_ERR, "Error in writing data, tag = %s:failed to register", lc_server_sync_data_buf[i].tag);
                }

                break;
            }
        }
    }
}

static void lcServiceDataSync(char *nod, tag_value *data_value)
{
    if (get_cabinet_info()->en_pcs_bus != 0)
     {

        struct ext_opt
        {
            char *tag;
            int (*opt)(int par);
        } ext_opt[2] = {{.tag = DEV_NO_EMS "." ON_OFF_STATE, .opt = pcs_business_initset_onoff}, {.tag = DEV_NO_EMS "." SET_CONNECT, .opt = pcs_business_init_set_connect}};
        for (int i = 0; i < sizeof(ext_opt) / sizeof(ext_opt[0]); i++)
        {
            if (strcmp(nod, ext_opt[i].tag) == 0)
            {
                ext_opt[i].opt(data_value->value.to_int);
                return;
            }
        }
     }

    if (NULL == lc_server_sync_data_buf)
    {
        lc_server_sync_data_init();
    }
    clServiceDataChange(nod, data_value);
    // 缓冲区刷新LC数据
    pcs_ctrl_var_t *var = get_pcs_ctrl_var();
    int lc_cnt = var->lc_list_len;
    lc_it *lc_list_tmp = var->lc_list;
    char *tag_start = strchr(nod, '.');
    if (tag_start == NULL)
    {
        ems_syslog(LOG_ERR, "tag[%s] find char '.' is NULL", nod);
    }
    else
    {
        tag_start++;
        if (0 == data_value->type)
        {
            for (int i = 0; i < lc_cnt; i++)
            {
                if (lc_list_tmp[i].disabled == 0)
                {
                    dev_set_dev_tag_int(lc_list_tmp[i].no, tag_start, data_value->value.to_int);
                }
            }
        }
        else if (1 == data_value->type)
        {
            for (int i = 0; i < lc_cnt; i++)
            {
                if (lc_list_tmp[i].disabled == 0)
                {
                    dev_set_dev_tag_float(lc_list_tmp[i].no, tag_start, data_value->value.to_float);
                }
            }
        }
        else
        {
            ems_syslog(LOG_ERR, "tag[%s] type is error", nod);
        }
    }
    }

int ems_config_point_register(pcs_ctrl_var_t *var,const ems_cfg_info_t *node, size_t size,
                                  void* tag_get_data_cb_t)
{
    int ret = -1;
    for (size_t i = 0; i < size; i++)
    {
        ret = collector_variant_monitor_add_one(var,node[i].nod,tag_get_data_cb_t);
        if(ret == -1) break;
    }

    for(int i = 0;i<get_tou_max_num();i++)//计划参数的回调默认注册  最大96段
    {       
        char name[64];

        snprintf(name,sizeof(name),"%s.S%dStHour",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret == -1) break;
        snprintf(name,sizeof(name),"%s.S%dStMin",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret == -1) break;
        snprintf(name,sizeof(name),"%s.S%dEnHour",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret == -1) break;
        snprintf(name,sizeof(name),"%s.S%dEnMin",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret == -1) break;
        snprintf(name,sizeof(name),"%s.S%dPower",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret == -1) break;
        snprintf(name,sizeof(name),"%s.S%dRePower",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret == -1) break; 
        snprintf(name,sizeof(name),"%s.S%dSOCUpperLimit",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret == -1) break; 
        snprintf(name,sizeof(name),"%s.S%dSOCLowerLimit",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret == -1) break; 
    }
    ems_syslog(LOG_ERR, "TOU regist start!!");
    for(int i = 0;i<get_tou_max_num();i++)//计划参数的回调默认注册  最大96段
    {       
        char name[64];

        snprintf(name,sizeof(name),"%s.TOUS%dStHour",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err%d",name,ret);
                break; 
            }
        snprintf(name,sizeof(name),"%s.TOUS%dStMin",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            }
        snprintf(name,sizeof(name),"%s.TOUS%dEnHour",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            }
        snprintf(name,sizeof(name),"%s.TOUS%dEnMin",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            }
        snprintf(name,sizeof(name),"%s.TOUS%dPower",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            }
        snprintf(name,sizeof(name),"%s.TOUS%dStratagyType",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            } 
        snprintf(name,sizeof(name),"%s.TOUS%dSOCUpperLimit",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            } 
        snprintf(name,sizeof(name),"%s.TOUS%dSOCLowerLimit",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            } 
        snprintf(name,sizeof(name),"%s.TOUS%dSurplusToGrid",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            } 
        snprintf(name,sizeof(name),"%s.TOUS%dChargePower",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            } 
        snprintf(name,sizeof(name),"%s.TOUS%dDischargePower",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            } 
        snprintf(name,sizeof(name),"%s.TOUS%dChargeGrid",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            } 
        snprintf(name,sizeof(name),"%s.TOUS%dChargeDG",DEV_NO_EMS,i+1);
        ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
        if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            } 
        for (size_t j = 0; j < g_usercfg_variant.TOU_info[j].userdefNum; j++)
        {
            snprintf(name,sizeof(name),"%s.TOUS%d%s",DEV_NO_EMS,i+1, g_usercfg_variant.TOU_info[i].userdef[j].id);
            ret = collector_variant_monitor_add_one(var,name,tag_get_data_cb_t);
            if(ret < 0) {
                ems_syslog(LOG_ERR, "TOU regist %s err,err:%d",name,ret);
                break; 
            }
        }
    }
    return  ret;
}

void check_voltage_time_std(void)
{
    time_t cur_time = time(NULL);
    
    if((voltage_dc_time != 0) && (cur_time - voltage_dc_time >= g_usercfg_variant.SingleVoltageTime) && g_usercfg_variant.SingleVoltageTime != 0)
    {
        fast_stop_discharge_tab_cb(DEV_NO_BMS"."RACK_MIN_VOLT, NULL);
    }
    //
    if((voltage_ch_time != 0) && (cur_time - voltage_ch_time >= g_usercfg_variant.SingleVoltageTime) && g_usercfg_variant.SingleVoltageTime != 0)
    {
        fast_stop_charge_tab_cb(DEV_NO_BMS"."RACK_MAX_VOLT, NULL);
    }

    return;
}



void *pcs_syncthread(void *par)
{
    while (1)
    {
        int onoff = def_get_pcs_onoff(DEV_NO_PCS);
        if (onoff < 0)
        {
            ems_syslog(LOG_ERR, "sync pcs: %s, get onoff failed", DEV_NO_PCS);
            sleep(1);
        }
        else
        {
            if (onoff != dev_get_dev_tag_int(DEV_NO_EMS, ON_OFF_STATUS))
            {
                dev_set_dev_tag_int(DEV_NO_EMS, ON_OFF_STATUS, onoff);
            }
        }
        //
        int connect = dev_get_pcs_connect(DEV_NO_PCS);
        if (connect < 0)
        {
            ems_syslog(LOG_ERR, "sync pcs: %s, get connect failed", DEV_NO_PCS);
            sleep(1);
        }
        else
        {
            if (connect != dev_get_dev_tag_int(DEV_NO_EMS, CONNECT_STATUS))
            {
                dev_set_dev_tag_int(DEV_NO_EMS, CONNECT_STATUS, connect);
            }
        }
        //
        usleep(200 * 1000); // xx ms
    }
}

int variant_cb_register(pcs_ctrl_var_t *var)
{
//********************回调函数不要做耗时操作(一定不要做不确定的阻塞操作)
//到内部点位中注册点位
    int ret = 0;
    ret = ems_config_point_register(var,ems_config_tab,ems_config_tab_count_g,ems_config_data_change_cb);
    if(ret != 0)
    ems_syslog(LOG_ERR, "load ems_config_tab table error");
    if (cabinet_info.ctrl_mode == EMS_MODE_ZC)
    {
        ret = collector_flush_variant_monitor_add(var,ems_contrl_tab, ARRAY_SIZE(ems_contrl_tab),ems_contrl_data_change_cb_lc_ctr_mode);
        if(ret != 0)
            ems_syslog(LOG_ERR, "load ems_contrl_tab table error");

        vlc_variant_cb_register(var);
        lc_variant_cb_register(var);
    }
    else
    {
        ret = collector_flush_variant_monitor_add(var, ems_contrl_tab, ARRAY_SIZE(ems_contrl_tab), ems_contrl_data_change_cb);
        if (ret != 0)
            ems_syslog(LOG_ERR, "load ems_contrl_tab table error");
        ret = collector_variant_monitor_add(var, fast_maximum_charg_power_tab, ARRAY_SIZE(fast_maximum_charg_power_tab), fast_charge_max_power_cb);
        if (ret != 0)
            ems_syslog(LOG_ERR, "load vlc_maximum_charg_power_tab table error");
        ret = collector_variant_monitor_add(var, fast_maximum_discharg_power_tab, ARRAY_SIZE(fast_maximum_discharg_power_tab), fast_discha_max_power_cb);
        if (ret != 0)
            ems_syslog(LOG_ERR, "load vlc_maximum_discharg_power_tab table error");
        if(get_cabinet_info()->ms_mode == MS_MODE_DC)
        {
            bau_variant_cb_register(var);
        }

        pthread_t thread = PTHREAD_NULL;
        if (0 == get_cabinet_info()->mode_microgrid && 0 == pthread_create(&thread, NULL, pcs_syncthread, NULL))
        {
            pthread_setname_np(thread, "pcs_sync");
        }
    }

//TODO 不用到UA注册的
    // ret = collector_variant_monitor_add(var,check_rack_max_temp_tab, ARRAY_SIZE(check_rack_max_temp_tab),check_rack_max_temp_cb);
    // if(ret != 0)
    //     ems_syslog(LOG_ERR, "load check_rack_max_temp_tan table error");
    ret = collector_flush_variant_monitor_add(var,fast_stop_dod_protect_tab, ARRAY_SIZE(fast_stop_dod_protect_tab),fast_stop_dod_protect_cb);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load collector_flush_variant_monitor_add table error");
    ret = collector_flush_variant_monitor_add(var,fast_stop_charge_tab, ARRAY_SIZE(fast_stop_charge_tab),fast_stop_charge_tab_cb);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load fast_stop_charge_tab table error");
    ret = collector_flush_variant_monitor_add(var,fast_stop_discharge_tab, ARRAY_SIZE(fast_stop_discharge_tab),fast_stop_discharge_tab_cb);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load fast_stop_discharge_tab table error"); 

    ret = collector_flush_variant_monitor_add(var,fast_stop_system_state_tab, ARRAY_SIZE(fast_stop_system_state_tab),fast_stop_system_state_cb);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load ffast_stop_system_state_tab error");

    ret = collector_flush_variant_monitor_add(var,fast_stop_system_state_tab_not, ARRAY_SIZE(fast_stop_system_state_tab_not),fast_stop_system_state_cb);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load fast_stop_system_state_tab_not error");


    ret = collector_variant_monitor_add(var,fast_stop_temp_ctrl_tab, ARRAY_SIZE(fast_stop_temp_ctrl_tab),fast_stop_temp_ctrl_cb);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load fast_stop_temp_ctrl_tab table error");
    ret = collector_variant_monitor_add(var,fast_stop_dc_voltage_unusual_tab, ARRAY_SIZE(fast_stop_dc_voltage_unusual_tab),fast_stop_dc_voltage_unusual_cb);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load fast_stop_dc_voltage_unusual_tab table error");
    
    ret = collector_flush_variant_monitor_add(var, lc_server_sync_tag, ARRAY_SIZE(lc_server_sync_tag), lcServiceDataSync);
    if (ret != 0)
        ems_syslog(LOG_ERR, "load lc_server_sync_tag table error");
    ret = collector_variant_monitor_add(var, ems_on_off_status_tab, ARRAY_SIZE(ems_on_off_status_tab), ems_on_off_status_tab_cb);
    if (ret != 0)
        ems_syslog(LOG_ERR, "load ems_on_off_status_tab table error");

    //消防回调
#if 1 /* removed for CC/LC */
    register_fire_cb(lc_fire_cb);  //通过广播获取消防其他设备消防信息
#endif
    ret = collector_flush_variant_monitor_add(var,fast_ph_ctrl, ARRAY_SIZE(fast_ph_ctrl), fast_ph_ctrl_function);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load fast_fire_tab table error");

    ret = collector_variant_monitor_add(var,fast_stop_fire_tab, ARRAY_SIZE(fast_stop_fire_tab),fast_stop_fire_cb);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load fast_fire_tab table error");

    ret = collector_variant_monitor_add(var, node_sync_tab, ARRAY_SIZE(node_sync_tab), node_sync_tab_cb);
    if (ret != 0)
        ems_syslog(LOG_ERR, "load fast_power_tab table error");

    ret = collector_variant_monitor_add(var, fast_stop_power_tab, ARRAY_SIZE(fast_stop_power_tab), fast_stop_power_cb);
    if (ret != 0)
        ems_syslog(LOG_ERR, "load fast_power_tab table error");

    ret = collector_flush_variant_monitor_add(var,ud_log_ctrl, ARRAY_SIZE(ud_log_ctrl), ud_log_ctrl_function);
    if(ret != 0)
        ems_syslog(LOG_ERR, "load ud_log_ctrl table error");

    if (cabinet_info.ctrl_mode == EMS_MODE_ZC)
    {
        automatic_cfg_merged(GLOBAL_AUTOMATIC_JSON_PATH);
        automatic_init(GLOBAL_AUTOMATIC_JSON_PATH);
    }
    else
    {
        automatic_init(CONFIG_PATH"/"AUTOMATIC_CONFIG);
    }
    return ret;
}

void require_cabinet_count(pcs_ctrl_var_t *var)
{
    if (var->enable_group_ctrl)
    {
        int cnt = get_same_type_devs_cnt(DEV_NO_PCS);
        if(cnt <=0 )
        {
            var->cabinet_cnt = 1; //缺省1组
            ems_syslog(LOG_ERR, "System must be included PCS device");
        }
        else {
            var->cabinet_cnt = cnt; 
            ems_syslog(LOG_NOTICE, "Find %d PCS in device list",var->cabinet_cnt);
        }
        cnt = get_same_type_devs_cnt(DEV_NO_PV);
        if(cnt <=0 )
        {
            var->pv_pcs_num = 1; //缺省1组
            ems_syslog(LOG_ERR, "System must be included PV device");
        }
        else {
            var->pv_pcs_num = cnt; 
            ems_syslog(LOG_NOTICE, "Find %d PV in device list",var->pv_pcs_num);
        }
    }
    else
    {
        var->cabinet_cnt = 1;//不是分组控制的时候使用1
    }
}
int clean_prohibite_chag_and_dischag(int cur_rack_sum)
{
    //
    ems_syslog(LOG_NOTICE, "CLEAR CHARGE PROTO!!");
    dev_set_dev_tag_int(DEV_NO_EMS, PROHIBITE_CHARGE, 0);
    dev_set_dev_tag_int(DEV_NO_EMS, PROHIBITE_DISCHARGE, 0);

    return 0;
}

int check_master_ems_offline(void)
{
    static tag_value tag = {.type = 0};
    static int old_disable = 0;
    int cur = get_ems_online();
    if (cur < 0)
    {
        //
    }
    else
    {

        //
        if (cur != 0)
        {
            if (old_disable != get_ems_disable())//1：被主机禁用 0：未被禁用
            {
                old_disable = get_ems_disable();
                dev_set_dev_tag_int(DEV_NO_EMS, ISDISABLE_BY_MASTER, old_disable);
                if (old_disable != 0)
                {
                    dev_set_dev_tag_int(DEV_NO_EMS, SET_ACT_POWER, 0);
                    dev_set_dev_tag_int(DEV_NO_EMS, SET_REACTPOWER, 0);
                }
            }
            if(old_disable == 0)
            {
                if (EMS_MANUAL_MODE != dev_get_dev_tag_int(DEV_NO_EMS, CONTROL_MODE))
                {
                    dev_set_dev_tag_int(DEV_NO_EMS, CONTROL_MODE, EMS_MANUAL_MODE);
                }
                int is_slave = 0;
                read_cabinet_info_by_name("is_slave", &is_slave);
                if (0 == is_slave)
                {
                    is_slave = 1;
                    write_cabinet_info_by_name("is_slave", &is_slave);
                }
            }
            cur = 0;
        }
        else
        {
            dev_set_dev_tag_int(DEV_NO_EMS, SET_ACT_POWER, 0);
            dev_set_dev_tag_int(DEV_NO_EMS, SET_REACTPOWER, 0);
            cur = 1;
        }

        // if (tag.value.to_int != cur)
        {
            tag.value.to_int = cur;
            fast_stop_system_state_cb(DEV_NO_EMS"."EMS_CONNECT_STATE, &tag);
        }
    }

    return 0;
}
