#ifndef __EMS_CTRL__
#define __EMS__CTRL__
#include <syslog.h>
#include <time.h>
#include "ipc_session.h"
#include "mqtt_session.h"
#include "lnxall_list.h"
#include "dy_utils/dy_ds.h"
#include "dy_utils/dy_common.h"
#include "dy_utils/kv_array.h"
#include "dy_utils/dy_ipc.h"
#include "dy_utils/dy_can.h"
#include "dy_utils/modbus_utils.h"
#include "dy_utils/period_service.h"
#include "modbus/modbus.h"
#include "dy_utils/bitmap.h"

#include "my_public.h"
#include "lnxall_ubuslog.h"
// #define EMS_FILE_PATH "/app/config/ems/"

#define EMS_CFG_FILE "/app/config/ems/ems_cfg.json"
#define EMS_SOME_STATE_CFG_FILE "/app/config/ems/ems_some_state_cfg.json"
#define EMS_DEV_NODE_FILE "/app/config/ems/ems_node.json"
#define EMS_CFG_SAVE_FILE "/app/config/ems/ems_cfg_save.json" //// 保存 g_pcs_cfg_info 结构体的值
#define EMS_CFG_PLAN_FILE "/app/config/ems/ems_cfg_plan.json" //// 保存   g_strategr_mng_info 结构体的值

// #define EMS_CFG_FILE "ems_cfg.json"
// #define EMS_DEV_NODE_FILE "ems_node.json"
// #define EMS_CFG_SAVE_FILE "ems_cfg_save.json"
// #define EMS_CFG_PLAN_FILE "ems_cfg_plan.json"

typedef unsigned char BYTE;
typedef char CHAR;
typedef unsigned short USHORT;
typedef short SHORT;
typedef unsigned int UWORD;
typedef int WORD;
typedef long long DWORD;
typedef unsigned long long UDWORD;

#define POWER_MAX_VAL UINT16_MAX
#define AGAINST_POWER_MAX 60
#define SOC_MAX_VAL 100
#define SECOND_TIME 1000
#define THREE_HUNDRED_MS 300
#define PV_FLAG 0

// #define TEST
#ifdef TEST
#define MINUTE_VAL 5
#else
#define MINUTE_VAL 60 * 3
#endif
#define TIME_VAL_LEN 8
#define MQTT_QOS_LEVLE0 0

#define DIVIDE_OF_HOUR 4

#define GRP_NUM_MAX 10

#define TIME_NUM_MAX 60
#define POWER_NUM_MAX 128
#define PING_PANG 2
#define DCI_NUM_MAX 30

typedef enum strategy_type_s
{
    STRATEGY_TYPE_PEEK = 1,   //计划模式 削峰填谷
    STRATEGY_TYPE_DLKJ,       
    STRATEGY_TYPE_BN_TRACK,
    STRATEGY_TYPE_PV_TRACK,    //光伏和无光伏的最大需量（快卜）
    STRATEGY_TYPE_MAX          //最大值限定边界用
} STRATEGY_TYPE_E;
// typedef enum bool_s
// {
//     E_TRUE,
//     E_FALSE,
//     E_PLANINFO_ERR,
//     E_PCSYGGLERR,
//     E_PCSWGGLERR,
//     E_NOT_IDEL,
//     E_IDEENTIFIER_ERR,
//     E_RUNSTATE_ERR,
//     E_MALLOC_ERR
// } BOOL_E;

typedef enum charge_mode_s
{
    E_CHARGE_FIXED, //// 固定充电模式
    E_CHARGE_PLAN,  //// 计划充电模式
    E_CHARGE_TRACK, //// 负荷跟踪
    E_PV_TRACK
} CHARGE_MODE_E;

typedef enum fault_state_s
{
    E_PCS_BMS_FAULT_STATE = 4,
    E_TEMP_FAULT_STATE,
    E_FIRE_W_G_FAULT_STATE,
    E_STATE_MAX
} E_FAULT_STATE;

typedef enum pcs_conn_state_s
{
    E_PCS_DISCONNECT,
    E_PCS_CONNECT,
} PCS_CONN_STATE_E;

typedef struct demand_charge_info_s
{
    CHAR time[TIME_VAL_LEN];
    SHORT price;           //// 价格
    SHORT power;           //// 电量
    CHARGE_STATE_E option; //// 充电/放电/空闲指示
    BYTE flag;
} DEMAND_CHARGE_INFO_T;

typedef enum proxy_action_s
{
    E_MODE_TYPE_SET,
    E_POWER_SET,
    E_POWER_PLAN_SET,
    E_PV_POWER_SET
} PROXY_ACTION_E;

typedef enum mode_type_s
{
    E_POWER_SET_MODE = 1,
    E_POWER_PLAN_SET_MODE,
    E_PV_POWER_SET_MODE
} MODE_TYPE_E;

typedef struct mode2_power_plan_s
{
    int start_time;
    int end_time;
    int power;
} mode2_power_plan_t;

#define MAX_DEMAND_NUMBER 96

// typedef struct json_info_name{
//     char * name;

// }JSON_INFO_NAME_T;

// #define _TO_STRING(a) #a
// #define TO_STRING(a) _TO_STRING(a)

// #define JSON_NAME_CLHA    CLCha
// #define JSON_NAME_CLDISCHA    CLDischa
// #define JSON_NAME_PMLMAX    Pmlmax
// #define JSON_NAME_K1    K1
// #define JSON_NAME_K2    K2
// #define JSON_NAME_SOCMAX SOCmax
// #define JSON_NAME_SOCMIN SOCmin
// #define JSON_NAME_PSET Pset
// #define JSON_NAME_PERR Perr
// #define JSON_NAME_PVMAX PVmax
// #define JSON_NAME_PCSMAX PCSmax
// #define JSON_NAME_PCHA  Pcha
// #define JSON_NAME_PCHAMAX  PchaMax
// #define JSON_NAME_PCHAMIN  PchaMin
// #define JSON_NAME_PDISC  PDisc
// #define JSON_NAME_PDISCMAX  PDiscMax
// #define JSON_NAME_PDISCMIN  PDiscMin
// #define JSON_NAME_ADJSTEP  Adjstep
// #define JSON_NAME_ADJPRERIOD Adjpreriod
// #define JSON_NAME_SLIPTIME  Sliptime

#define STRUCTURE_SET "structure_set"
#define PROXY_SET "proxy_set"
#define PCS_OPEN_CMD_SET "openpcs_set"   // 开启
#define PCS_OPEN_CMD_GET "openpcs_get"
#define PCS_CONNECT_CMD_SET "pcsconnect_set"
#define PCS_CONNECT_CMD_GET "pcsconnect_get"
#define PCS_GL_CMD_SET "pcsgl_set"
#define PCS_GL_CMD_GET "pcsgl_get"
#define PCS_SYS_CONFIG_CMD_SET "pcssysconfig_set"
#define PCS_SYS_CONFIG_CMD_GET "pcssysconfig_get"
#define PCS_CHARGE_MODE_CMD_SET "chargemode_set"
#define PCS_CHARGE_MODE_CMD_GET "chargemode_get"
#define PCS_CHARGE_CTRL_CMD_SET "chargectrl_set"
#define PCS_CHARGE_CTRL_CMD_GET "chargectrl_get"
#define PCS_MODE_SEL_SET "modesel_set"
#define PCS_MODE_SEL_GET "modesel_get"
#define PCS_CONFIG_SAVE "pcs_config_save"
#define PCS_POWER_TEST_SET "power_test_set"
#define PCS_STRATEGY_TEMPLATE "strategyTemplate"
#define PCS_RESET "pcs_reset"
#define LINKAGE_SET "linkage_set"
#define TOPIC_PCS_CTRL_SET "set"
#define TOPIC_PCS_CTRL_SET_REPLY "set_reply"
#define TOPIC_PCS_CTRL_GET "get"
#define TOPIC_PCS_CTRL_GET_REPLY "get_reply"
#define ENGERGY_ASSIGN_SERVICE_SET "on_service_set"

#define TOPIC_PCS_RUN_MODE_SET "pcs_run_mode_set"
#define TOPIC_PCS_RUN_MODE_GET "pcs_run_mode_get"

#define PV_PCS_OPEN_CMD_SET "pv_openpcs_set"
#define PV_PCS_GL_CMD_SET "pv_pcsgl_set"
#define PV_PCS_PENABLE_CMS_SET "pv_pcs_penable_set"

#define PV_PCS_OPEN_CMD_GET "pv_openpcs_get"
#define PV_PCS_GL_CMD_GET "pv_pcsgl_get"
#define PV_PCS_PENABLE_CMS_GET "pv_pcs_penable_get"

#define KB_EMS_CTRL
#ifdef KB_EMS_CTRL
#define BMS_RELAY_ONOFF "bms_relay_onoff"
#endif

#define _TO_STRING(a) #a
#define TO_STRING(a) _TO_STRING(a)

#define JSON_NAME_RUNSTATE    runState
#define JSON_NAME_CONNSTATE   connState
#define JSON_NAME_YGGL        pcs_yggl
#define JSON_NAME_WGGL        pcs_wggl


#define JSON_NAME_CLHA CLCha
#define JSON_NAME_CLDISCHA CLDischa
#define JSON_NAME_PMLMAX Pmlmax
#define JSON_NAME_DYLMAX Dylmax
#define JSON_NAME_EDD EDD
#define JSON_NAME_MD MD
#define JSON_NAME_DCI DCI
#define JSON_NAME_K1 K1
#define JSON_NAME_K2 K2
#define JSON_NAME_SOCMAX SOCmax
#define JSON_NAME_SOCMIN SOCmin
#define JSON_NAME_PSET Pset
#define JSON_NAME_PERR Perr
#define JSON_NAME_PVMAX PVmax
#define JSON_NAME_PCSMAX PCSmax
#define JSON_NAME_PCHA Pcha
#define JSON_NAME_PCHAMAX PchaMax
#define JSON_NAME_PCHAMIN PchaMin
#define JSON_NAME_PDISC PDisc
#define JSON_NAME_PDISCMAX PDiscMax
#define JSON_NAME_PDISCMIN PDiscMin
#define JSON_NAME_ADJSTEP Adjstep
#define JSON_NAME_ADJPRERIOD Adjpreriod
#define JSON_NAME_SLIPTIME Sliptime
#define JSON_NAME_LOADGRIDMETERSHARE LoadGridMeterShare
#define JSON_NAME_UPGRADE_PLAN_ONEDAY DayUPtime
#define JSON_NAME_SOCDRT SOCdrt
#define JSON_NAME_PLANINFO PlanInfo
#define JSON_NAME_TIME time
#define JSON_NAME_POWER power
#define JSON_NAME_PRICE price
#define JSON_NAME_OPTION option
#define JSON_NAME_RUN_STATE runState
#define JSON_NAME_TRACK_DIFF trackDiff
#define JSON_NAME_TYPE type
#define JSON_NAME_DISCHARGE_THRESHOLD dischargeThreshold
#define JSON_NAME_CHARGE_START_POWER chargeStartPower
#define JSON_NAME_CHARGE_END_POWER chargeEndPower
#define JSON_NAME_DISCHARGE_END_THRESHOLD dischargeEndThreshold
#define JSON_NAME_DISCHARGE_THRESHOLD_OFFSET dischargeThresholdOffset

#define JSON_NAME_KM                KM
#define JSON_NAME_SAVESTATE        savestate
#define JSON_NAME_PVSWITCH          PvSwitch
#define JSON_NAME_SOCTHRESHOLD      socThreshold
#define JSON_NAME_FORBIDDEN         forbidden
#define JSON_NAME_MAXSUPPLEMENT_P   MAXSupplementP
#define JSON_NAME_P1_MARGIN         p1Margin
#define JSON_NAME_PV_MAX_POWER      pvMaxPower

#define JSON_NAME_ALARMCLOSE   alarmClose
#define JSON_NAME_SUPPORTSTANDY   supportStandy
#define JSON_NAME_SOCPV   SOCpv
#define JSON_NAME_AIRCOND_SET_TIMEOUT_BEFORE   aircond_set_timeout_before
#define JSON_NAME_AIRCOND_SET_TIMEOUT_AFTER   aircond_set_timeout_after
#define JSON_NAME_SINGLEMAX   singlemax
#define JSON_NAME_SINGLEMIN   singlemin
#define JSON_NAME_DEV_ONLINE_TIMEOUT   dev_online_timeout
#define JSON_NAME_DEV_METER_FLAG   meter_flag

#define JSON_NAME_TEMP_THRESHOLD tempThreshold
#define JSON_NAME_DOOR_FLAG doorflag

#define PROXY_MODE_CFG_FILE         "/app/config/ems/proxy_mode_set.json"
#define PROXY_POWER_SET_CFG_FILE    "/app/config/ems/proxy_power_set.json"
#define PROXY_PLAN_CFG_FILE         "/app/config/ems/proxy_power_plan_set.json"
#define PROXY_PV_CFG_FILE           "/app/config/ems/proxy_pv_power_set.json"
#define PROXY_SUMMARY_FILE          "/app/config/ems/proxy_summary.json"
#define PROXY_DEFAULT_MODE          0
#define PROXY_DEFAULT_POWER         0

// #define PCS_CFG_PROPERTY(a) g_pcs_cfg_info.a

// JSON_INFO_NAME_T json_info_table[] = {
//     {TO_STRING(JSON_NAME_CLHA      )},
//     {TO_STRING(JSON_NAME_CLDISCHA  )},
//     {TO_STRING(JSON_NAME_PMLMAX    )},
//     {TO_STRING(JSON_NAME_K1    	   )},
//     {TO_STRING(JSON_NAME_K2    	   )},
//     {TO_STRING(JSON_NAME_SOCMAX    )},
//     {TO_STRING(JSON_NAME_SOCMIN    )},
//     {TO_STRING(JSON_NAME_PSET 	   )},
//     {TO_STRING(JSON_NAME_PERR 	   )},
//     {TO_STRING(JSON_NAME_PVMAX 	   )},
//     {TO_STRING(JSON_NAME_PCSMAX    )},
//     {TO_STRING(JSON_NAME_PCHA  	   )},
//     {TO_STRING(JSON_NAME_PCHAMAX   )},
//     {TO_STRING(JSON_NAME_PCHAMIN   )},
//     {TO_STRING(JSON_NAME_PDISC     )},
//     {TO_STRING(JSON_NAME_PDISCMAX  )},
//     {TO_STRING(JSON_NAME_PDISCMIN  )},
//     {TO_STRING(JSON_NAME_ADJSTEP   )},
//     {TO_STRING(JSON_NAME_ADJPRERIOD)},
//     {TO_STRING(JSON_NAME_SLIPTIME  )}
// };

typedef struct pcs_cfg_s
{
    CHARGE_MODE_E CLCha;    //// 充电模式 0 -固定模式，1-计划模式
    CHARGE_MODE_E CLDischa; //// 放电模式 0 -固定模式，1-计划模式，2-负载跟踪模式
    USHORT Pmlmax;          //// 变压器最大容量，用于需量跟踪    //防逆流   *13
    USHORT Dylmax;          //// 动态需量最大值
    BYTE EDD;               //// 是否启用动态需量
    USHORT MD;              //// 月初需量
    BYTE DCI;               //// 需量计算间隔
    USHORT Pdownlimit;      // 电网功率下限 < Pmlmax
    USHORT PdlimitOffset;   // 电网功率下限误差;
    USHORT PmlRecoverMax;   // 电网功率反向需量最大值。
    USHORT GridRateVol;     // 电网额定电压
    USHORT K1T;
    USHORT DK1T;
    USHORT G1T;
    USHORT RK1T;
    USHORT G2T;
    USHORT GST1;
    USHORT GST2;
    USHORT PFT1;
    double pf;
    BYTE RK1;
    BYTE G1; // 额定电压系数
    BYTE DK2;

    BYTE K1;                 // 需量控制系数
    BYTE K2;                 // 放电负载跟踪系数        *8
    double SOCmax;           //// soc最大充电阈值      *11
    double SOCmin;           //// soc放电最小阈值      *12
    double SOCpv;
    SHORT Pset;               //// 电网供电功率下限
    BYTE Perr;               //// 电网供电功率下限误差
    USHORT PVmax;            //// 光伏最大值  //光伏放电最大额定功率 削峰填谷用
    USHORT PCSmax;           //// PCS最大容量值
    WORD Pcha;               //// 固定充电值KW
    USHORT PchaMax;          //// 充电最大值，yut需量控制中pcs充电最大功率      *5
    USHORT PchaMin;          //// 充电最小值，yut需量控制中pcs充电最小功率
    USHORT PDisc;            //// 固定放电值
    USHORT PDiscMax;         //// 放电最大值, yut需量控制中pcs放电最大功率      *6
    USHORT PDiscMin;         //// 放电最小值，yut需量控制中pcs放电最小功率
    BYTE Adjstep;            //// 功率调整步进值KW
    BYTE Adjpreriod;         //// 调整监控周期分钟 （最大需量的调整周期 秒）
    BYTE Sliptime;           //// 调整频率分钟
    BYTE loadgridmetershare; //// 负载模式，负载与电网共享配置1-共享，0-独立
    CHAR DayUPgradeTime[TIME_VAL_LEN];
    BYTE SOCdrt;
    BYTE runState;   //配置文件内 保存的运行模式
    USHORT trackDiff;
    BYTE type; //// 1--计划模式 2--调峰模式  4--光伏最大需量
    BYTE door_io_flag;
    double tempThreshold;        //// 温度阈值,高于则温度告警
    UWORD dischargeThreshold;    //// 放电阈值，yut 在最大需量控制模式下为需要储能放电时的电网功率阈值  *2
    UWORD dischargeEndThreshold; // 放电结束阈值
    UWORD dischareeEndThresholdVal;
    UWORD chargeStartPower; // 充电阈值， yut 在最大需量控制模式下为需要储能充电时的电网功率阈值
    UWORD chargeEndPower;   // 充电结束阈值

    double  KM; //功率调整速率，在多套系统跟随P1的时候降低调整速度 默认建议和实际系统数量倒数一致 例如两台配置为0.5
    BYTE  savestate; //ems保存一些状态开关，0关闭， 1打开，非正常关机后是否保存状态
    BYTE  PvSwitch;         // 光伏开关 0关闭 1开启   *1
    UWORD socThreshold;     //允许储能放电soc阈值  *3
    UWORD forbidden;        //充放电转换的 死区  *4
    UWORD MAXSupplementP;          //储能电网最大补电功率 *7
    UWORD p1Margin;         //电网防逆流余量 *9
    UWORD pvMaxPower;       //光伏放电最大额定功率 *10
    UWORD alarmClose;  //告警是否关机标志 0不关机 1关机
    UWORD supportStandy; //是否支持待机  0待机写功率0 1待机发送待机 
    USHORT loadTrackingLimit;
    DEMAND_CHARGE_INFO_T demand_table[MAX_DEMAND_NUMBER];
    DEMAND_CHARGE_INFO_T remoterdemand_table[MAX_DEMAND_NUMBER];
    int aircond_set_timeout_before;
    int aircond_set_timeout_after;
	float singlemax;         //// 最高单体电压
	float singlemin;         //// 最低单体电压
	int dev_online_timeout;  //// 电网电表离线超时时间             默认 30
	int meter_flag;          //// 防逆流表和需量表是否共用FLAG
} PCS_CFG_T;

typedef enum onoff_e
{
    E_OFF,
    E_ON,
    E_IDLE
} ON_OFF_E;

typedef enum ctrl_mode_s
{
    E_CTRL_MANUAL,  //手动
    E_CTRL_AUTO,    //自动模式
    E_CTRL_REMOTER, 
    E_CTRL_AUTO_DLKJ,
    E_CTRL_MAX, 
} CTRL_MODE_E;

// 高悦io定义
typedef struct io_state_info_s
{
    BYTE connectok;
    BYTE iostate;
    BYTE iostatenew;
    BYTE surge_io_in_line;    //// SPD1
    BYTE surge_io_in_station; //// SPD2
    BYTE door_io_state;       //// 门禁
    BYTE load_io_state;       //// 负载断路器
    BYTE grid_io_state;       //// 并网断路器
    BYTE trans_io_state;      //// 变压器进线柜断路器
    BYTE tiaoji_io_state;     // 常闭   -1   //// 跳机反馈
    BYTE smog_io_state;       //// 烟感
    BYTE temp_io_state;       //// 温感
    BYTE gas_io_state;        //// 可燃气体
    BYTE fire_io_state;       //// 消防故障
    BYTE emer_stop_io_state;  // 常闭  -1  //// 急停
} IO_STATE_INFO_T;

typedef struct do_state_info_s
{
    BYTE load_do_state;
    BYTE grid_do_state;
    BYTE station_do_state;
    BYTE fire_do_state;
    BYTE epo_do_state;
    BYTE tiaoji_do_state;
    BYTE fan_do_state;
    BYTE warning_do_state;
} DO_STATE_INFO_T;

typedef struct _data_update_time_t
{
    time_t P1; //// 防逆流电表功率
    time_t P3; //// 放电设置功率(储能电表读出的数值除以簇数)
    time_t Pv; // 光伏功率。
    time_t Pf; // 柴发功率。
    time_t P2; // 储能功率。
    time_t P1_1;
	time_t P1_2;
} data_update_time_t;

typedef struct
{
    int system; // 总保护等级，子系统保护等级或以后的结果 下面的两个仅仅临时使用
    int eng_ass;
    int guard;
} protect_level_t;

typedef struct
{
    time_t MIN_L;                     
    time_t MIN_H;
} time_item_t;

typedef struct
{
    BYTE num;                     
    time_item_t time_map[TIME_NUM_MAX];
} critical_map_t;

typedef struct
{
    int num;                     
    float p[POWER_NUM_MAX];
} power_t;

typedef struct
{
    int num;                     
    float data[DCI_NUM_MAX];
} power_data_t;


typedef struct
{
    BYTE ping_pong;
	time_t action_tim;
	time_t step_tim;
	time_t dci_tim;
	BYTE triger;
	struct tm back_tim;
	critical_map_t critical_map;
	pthread_mutex_t demand_lock;
    pthread_cond_t demand_cond;
    power_t pingpangbuff[PING_PANG];
	power_data_t power_data;
} dynamic_demand_t;

typedef struct charge_mng_info_s
{
    CTRL_MODE_E ctrlMode; //// 调节模式       手动还是自动
    CTRL_MODE_E lastCtrlMode;//记录上一次运行状态 用以在自动模式切换的时候 重置状态机
    BYTE devState;
    BYTE runState;//开关机上报状态
    BYTE pcserr;
    BYTE pcserrflag;
    BYTE bmserr;
    BYTE bmserrflag;
    BYTE pcsbmserrflag;
    BYTE bmsfire;
    BYTE socmaxreport;
    BYTE socminreport;
    double soc;                 //// 当前的soc
    BYTE chFull;   //上次充满过标志 0未充满过 1充满过
    BYTE dischNull; //上次放空过标志 0未放空过 1放空过
    BYTE last_discharge_null; //记录上次放空的状态的标志
    BYTE can_discharge;//记录是否可以放电
    PCS_CONN_STATE_E connState; //// pcs 并网离网操作
    BYTE bmsState;
    WORD currentDischaPower;  //// pcs 当前放电功率   
    WORD currentCharPower;    //// pcs 当前充电功率()
    WORD P2ToWrite;           //要设置的储能功率  负冲正放
    WORD PvCurrent;           //要设置的光伏放电功率
    double pcs_yggl;          //// pcs 有功功率
    double pcs_wggl;          //// pcs 无功功率
    double P1;                //// 防逆流电表功率 (防逆流和需量公用一个表)
    double P1_1;              // 防逆流电表
	double P1_2;              // 需量电表
    double P3;                //// 放电设置功率(储能电表读出的数值除以簇数)
    double Pv;                // 光伏功率。
    double P2;                // 储能功率。
    double Pf;                // 柴发功率。
    BYTE   last_charge_stat;   //记录上次充放电状态 0放电 1充电
    double CharStaP;          // 充电桩功率。
    double CharStaExpP;       // 充电桩希望功率。
    double VG1;               // 电网电压。
    CHARGE_MODE_E chargeMode; //// pcs 充电模式(固定功率/计划模式)
    CHARGE_MODE_E DischaMode; //// pcs 放电模式(固定功率/计划模式/负荷跟踪)
    CHARGE_STATE_E action;    //// pcs 状态 (==0空闲/==1充电/==2放电/==3bms故障==4温度故障)
    CHARGE_STATE_E actionnew;
    BYTE pcs_openState;      //// pcs是否开启 (==1 开启 ==0 关闭)
    BYTE pv_pcs_openState;   //// 光伏pcs是否开启 (==1 开启 ==0 关闭)
    BYTE pf_pcs_openState;   // 柴发pcs是否开启 (==1 开启 ==0 关闭)
    BYTE pv_penable;         // 光伏控制使能（0--不是能 1--使能）
    USHORT battleVol;        // 电池电压
    BYTE PVrunState;         // 光伏运行状态
    BYTE BMSFull;            // bms充满
    BYTE PvPEnable;          // 光伏功率限制使能
    double pv_pcs_yggl;      //// pcs 有功功率
    double pv_pcs_wggl;      //// pcs 无功功率
    USHORT Adjpreriodcouter; //// 负荷跟踪调整时间计数
    BYTE AdjpreriodFlag;     //// 负荷跟踪调整时间标志位
    DWORD switchCounter;   //定期执行开关的计数
    BYTE SlipFlag;
    BYTE demandState;  //// 需量控制
    BYTE AgainstState; //// ==1防逆流开启
    BYTE lgState;
    USHORT Againstcouter;
    BYTE AgainstErr;
    BYTE fireAlarm;
    BYTE fireAlarmState;
    BYTE smogAlarm;
    BYTE smogAlarmState;
    BYTE waterImAlarm;
    BYTE waterImAlarmState;
    double tempVal;
    BYTE gridOffFlag;
    BYTE mastSwitch;
    BYTE K1Fault;
    BYTE K3Fault;
    IO_STATE_INFO_T ioinfo;
    DO_STATE_INFO_T doinfo;
    DEMAND_CHARGE_INFO_T planInfo; //// 存放要执行的计划
    data_update_time_t update_time;
    protect_level_t total_lev; //这个故障可以看作 协调控制本身和guard模块本身的故障
    protect_level_t grps_lev[GRP_NUM_MAX];
    bool lev_changed;
    int grps_num;
	dynamic_demand_t dynamic_demand;
	int multi_meter_flag;
} CHARGE_MNG_INFO_T;

typedef enum alarm_level
{
    E_ALARM_LEVEL0,
    E_ALARM_LEVEL1,
    E_ALARM_LEVEL2,
    E_ALARM_LEVEL3
} ALARM_LEVEL_E;

typedef struct service_info_s
{
    WORD mi;
    WORD timestamp;
    CHAR devSn[SN_MAX_LEN];
    CHAR identifier[IDENTIFIER_LEN];
} SERVICE_INFO_T;

#define DEV_NODE_NAME_LEN 16

typedef struct tag_node_s
{
    CHAR name[DEV_NODE_NAME_LEN];
    CHAR tag[DEV_NODE_NAME_LEN];
} TAG_NODE_T;

typedef struct tag_node_info_s
{
    BYTE nodecont;
    TAG_NODE_T *ptagNode;
} TAG_NODE_INFO;

typedef struct dev_node_cfg_s
{
    CHAR devSn[SN_MAX_LEN];
    CHAR name[DEV_NODE_NAME_LEN];
    CHAR identifier[IDENTIFIER_LEN];
    TAG_NODE_INFO tagNode;
} DEV_NODE_CFG_T;

typedef struct dev_node_info_s
{
    DEV_NODE_CFG_T *pdevnodecfg;
    BYTE cont;
} DEV_NODE_INFO_T;

typedef struct lingage_s
{
    CHAR identifier[IDENTIFIER_LEN];
    BYTE val;
} LINGAGE_T;

typedef struct lingage_info_s
{
    LINGAGE_T *plingage;
    BYTE cont;
} LINGAE_INFO_T;

#define STATE_STR_LEN 32

typedef struct switch_state_str_s
{
    char stateStr[STATE_STR_LEN];
} SWITCH_STATE_STR_T;

// typedef struct list_head LIST_STRUCT;
typedef enum
{
    POWERLIMITED, //EMS限功率运行
    POWERREFLUX, //EMS逆流运行
    SYSSTOPED,//EMS切手动保护
    GTIDMETEROFFLINE1,//电网电表离线
    //BMSMETERIFFLINE1,//储能电表离线
    ALARM_TYPE_MAX
}ALARM_TYPE;//弹窗告警类型

typedef enum
{
    INIT_STA = -1,//初始化状态
    NOALARM,//无告警 告警恢复
    ALARM,//告警
}ALARM_STATUS;//告警状态

typedef struct proxy_info_s
{
    MODE_TYPE_E cur_mode;
    int mode1_power_set;
    int mode2_power_plan_num;
    mode2_power_plan_t *mode2_power_plan;
    int mode3_pv_power_set;
} PROXY_INFO_T;

typedef struct pcs_ctrl_var_s
{
    ipc_session_t *session;    // 内部broker的MQTT client，用于进程间通信。
    ipc_session_t *sessiondev; // 内部broker的MQTT client，获取虚拟设备信息。
    ipc_session_t *extsession; // 外部broker 的MQTT client。通过外部brocker 获取数据。
    WORD second_period_timer;
    CHAR port_type[SN_MAX_LEN];
    CHAR sn_str[SN_MAX_LEN];
    CHAR vir_sn_str[SN_MAX_LEN];
    CHAR loadmeterSn[SN_MAX_LEN];
    CHAR gridmeterSn[SN_MAX_LEN];
    CHAR pcsSn[SN_MAX_LEN];
    CHAR pvpcsSn[SN_MAX_LEN];
    CHAR bmsSn[SN_MAX_LEN];
    CHAR auxiSn[SN_MAX_LEN];          //// DIDO模块的 SN
    CHAR chargeStatinoSn[SN_MAX_LEN]; //// DIDO模块的 SN
    CHAR energyAssignSn[SN_MAX_LEN];  // 协调控制器
    CHAR guardSn[SN_MAX_LEN];         // 保护子系统
    CHAR deamndSn[SN_MAX_LEN];        // 需量子系统
    CHAR multiMeterSn[SN_MAX_LEN];        
    SERVICE_INFO_T servInfo;
    SERVICE_INFO_T devservInfo;
    SERVICE_INFO_T exdevservInfo;
    DEV_NODE_INFO_T devnodeinfo;
    DEV_NODE_INFO_T exdevnodeinfo;
    LINGAE_INFO_T fire_w_g_lingageInfo;
    LINGAE_INFO_T mastswitch_lingageInfo;
    CHAR cutimer[TIME_VAL_LEN];  //当前时间
    BYTE chargeType; // 0-负充电,1-正充电
    UWORD dischargeVal;
    UWORD startchargeVal;
    UWORD chargeVal;
    UWORD idleVal;
    BYTE aircond_set; // 1-设置启动,0-设置不启动 -1 初始值
    E_RUN_MODE runMode;
    MQTT_INFO_T mqttBroker;
    pthread_rwlock_t topic_lock;
    //   pthread_rwlock_init(&session->topic_lock, NULL); 锁添加
    int manu_state; // 手动模式下状态机
    int auto_state; // 自动模式下状态机
    SWITCH_STATE_STR_T switchStateStr[E_STATE_MAX];
    ALARM_STATUS alarm_status_list[ALARM_TYPE_MAX]; //有些无法周期判断是否告警 通过设置此标志位置 作为check_alarm_t判断方式
    PROXY_INFO_T proxy;
} pcs_ctrl_var_t;

typedef struct strategy_template_s
{
    double SOCmax; //// soc最大充电阈值  *11
    double SOCmin; //// soc最小充电阈值  *12
    USHORT PVmax;
    BYTE AgainstState;
    BYTE demandState;
	BYTE lgState;
    SHORT Pset;     //// 逆流调整最小值
    USHORT Pmlmax; // 最大容量，用于需量跟踪     *13 //电网供电功率上限
    BYTE EDD;               //// 是否启用动态需量
    USHORT MD;              //// 月初需量
    BYTE DCI;               //// 需量计算间隔
    USHORT PCSmax; //// PCS最大容量值
    BYTE Perr;     //// 逆流最小阈值值
    BYTE K1;       //// 需求跟踪系数
    BYTE K2;       // 放电负载跟踪系数
    BYTE CLCha;    // chargeMode;           //充电模式 0 -固定模式，1-计划模式
    WORD Pcha;     // 固定充电值KW
    BYTE CLDischa; // DischaMode;        //放电模式 0 -固定模式，1-计划模式，2-负载跟踪模式
    USHORT PDisc;  // 固定放电值
    BYTE type;     // 1--计划模式 2--调峰模式
    BYTE tempThreshold;
    UWORD dischargeThreshold;       // 放电阈值   *2
    UWORD chargeStartPower;         // 充电阈值
    UWORD chargeEndPower;           // 充电结束阈值
    UWORD dischargeEndThreshold;    // 放电结束阈值
    UWORD dischareeEndThresholdVal; // 放电阈值区间补充放电值
    USHORT PmlRecoverMax;           // 电网功率反向需量最大值。
    USHORT GridRateVol;             // 电网额定电压
    USHORT K1T;
    USHORT DK1T;
    USHORT G1T;
    USHORT G2T;
    USHORT RK1T;
    USHORT GST1;
    USHORT GST2;
    USHORT PFT1;
    double pf;
    BYTE RK1;
    BYTE G1; // 额定电压系数
    BYTE DK2;

    USHORT PchaMax; 
    USHORT PDiscMax; 
    BYTE  Adjpreriod;
    BYTE  PvSwitch;         // 光伏开关 0关闭 1开启   *1
    UWORD socThreshold;     //允许储能放电soc阈值  *3
    UWORD forbidden;        //充放电转换的 死区  *4
    UWORD MAXSupplementP;          //储能电网最大补电功率 *7
    UWORD p1Margin;         //电网防逆流余量 *9
    UWORD pvMaxPower;       //光伏放电最大额定功率 *10
    int aircond_set_timeout_before;
    int aircond_set_timeout_after;
    float singlemax;
	float singlemin;
    USHORT loadTrackingLimit;
    DEMAND_CHARGE_INFO_T PlanInfo[MAX_DEMAND_NUMBER];
} STRATEGY_TEMPLATE_T;

#define WEEK_DAY_NUM 7
typedef struct week_info_s
{
    BYTE weekNum[WEEK_DAY_NUM]; // 有效为1，无效为0
} WEEK_INFO_T;

typedef enum repeat_type_s
{
    E_REPEAT_KEEP = 1, // 无开始和结束
    E_REPEAT_DAY,      // 开始结束
    E_REPEAT_WEEK      // 周一二三等信息
} E_REPEAT_TYPE;

typedef struct strategy_repeat_s
{
    BYTE repeat;        //// 策略管理 执行周期(长期/每天重复/每周重复)
    BYTE priority;      //// 策略管理 优先级
    time_t startDate;   //// 策略管理 开始日期
    time_t endDate;     //// 策略管理 结束日期
    WEEK_INFO_T weekly; //// 每周7天 哪一天是否执行策略
    STRATEGY_TEMPLATE_T strategryTemplate;
} STRATEGY_REPEAT_T;

typedef struct strategy_mng_s
{
    USHORT cont;   // 规则数量
    BYTE update;   //// ==1 有新计划
    BYTE initflag; //// ==1 已经初始化
    BYTE dayflag;
    STRATEGY_REPEAT_T *pStrategyTable;
} STRATEGY_MNG_T;

typedef enum auxi_linkage_s
{
    E_LINGAGE_OFF,
    E_LINGAGE_ON
} E_AUXI_LINKAGE;


#define MAX_DO_NUM 8

#define EMS_TIMER_CONFIRM(timer)      \
    do                                \
    {                                 \
        if (my_timer_read(timer) < 0) \
            continue;                 \
    } while (0)
// static BYTE pcs_close_check(BYTE soc);
static BYTE pcs_demand_timer_close_check(BYTE index);
static BYTE pcs_sliptime_time_check();
static BYTE pcs_adjpreriod_timer_check();
// static void pcs_second_timer_loop();

static BYTE pcs_discharge_track(double p1, BYTE K2, USHORT p3, WORD *updown);
static BYTE pcs_charge_soc_check();
static BYTE pcs_discharge_soc_check();
static void update_plan_cfg();
// static void pcs_close();
static void pcs_state_process(pcs_ctrl_var_t *var);
static void pcs_charge_switch_process(pcs_ctrl_var_t *var, BYTE type, DEMAND_CHARGE_INFO_T char_info);
int report_option(pcs_ctrl_var_t *var, CHAR *pInfo, ...);
static int pcs_config_save();
void pcs_dev_open(pcs_ctrl_var_t *var);
void pcs_dev_close(pcs_ctrl_var_t *var);
void pf_pcs_dev_open(pcs_ctrl_var_t *var);
void pf_pcs_dev_close(pcs_ctrl_var_t *var);
void pcs_dev_connect_set(pcs_ctrl_var_t *var);
void pcs_dev_disconect_set(pcs_ctrl_var_t *var);
int ems_mode_set(int mode);
void pcs_dev_yggl_set(pcs_ctrl_var_t *var, WORD power);
int pcs_charge_plan_process(CHAR *ptimer, DEMAND_CHARGE_INFO_T *chInfo);
static void ems_dlkj_main(pcs_ctrl_var_t *var);
void ems_process_main(pcs_ctrl_var_t *var);
void ems_demand_ctrl_main(pcs_ctrl_var_t *var);
void ems_max_demand_ctrl_main(pcs_ctrl_var_t *var);
void ems_bn_process_main(pcs_ctrl_var_t *var);
void auxi_set(pcs_ctrl_var_t *var, CHAR *pidentifier, CHAR mode);
void fire_w_g_set_linkage(pcs_ctrl_var_t *var, int val);
void mastSwitch_set_linkage(pcs_ctrl_var_t *var, int val);
typedef int (*USER_DEFINE_PROCESS)(pcs_ctrl_var_t *var);

void pv_pcs_dev_open(pcs_ctrl_var_t *var);
void clear_pv(pcs_ctrl_var_t *var);
void pcs_dev_standby_set(pcs_ctrl_var_t *var);
void pcs_dev_standby_set_by_config(pcs_ctrl_var_t *var);
void pv_pcs_dev_close(pcs_ctrl_var_t *var);
void pv_pcs_dev_yggl_set(pcs_ctrl_var_t *var, WORD power, int pv_flag);
void pv_pcs_dev_powerenable_set(pcs_ctrl_var_t *var, WORD mode);
void run_mode_load();
void charge_station_power_set(pcs_ctrl_var_t *var, WORD power);
void publish_alarm_up(pcs_ctrl_var_t *var,char * dev_alarm_string, ALARM_TYPE type,ALARM_STATUS status);
void set_alarm_status(pcs_ctrl_var_t *var,ALARM_TYPE type,ALARM_STATUS status);
void pcs_dev_soc_max_min_set(pcs_ctrl_var_t *var, double soc_max, double soc_min);
void pcs_dev_modesel_set_ems(pcs_ctrl_var_t *var, int tmp);
#define msleep(n) usleep(n * 1000)

#undef NB_GY_EMS_CTRL

#endif
