/****************************************************************************/
/* Copyright (c) 2007,许继集团有限公司                                      */
/* All rights reserved.                                                     */
/*                                                                          */
/* 模块描述：                                                              */
/**本地对象空间目录服务模块
 * 选择激活定值区 SelectActiveSG  
 * 选择编辑定值区 SelectEditSG 
 * 读定值 GetSGValues
 * 写定值 SetSGValues  
 * 确认编辑定值 ConfirmEditSGValues  
 * 读定值控制块 GetSGCBValues
 * @file  ac_sg.h				                                            */
/*                                                                          */
/* 日期         作者         注释                                           */
/* 2007/09/18   guoqiang     创建文件                                       */
/****************************************************************************/
#ifndef IEC61850_AC_SG_INCLUDED
#define IEC61850_AC_SG_INCLUDED

/**  
 * 
*/
#include "ai_obj.h"
#include "ac_reqm.h"

#ifdef __cplusplus
extern "C" {
#endif

/**  读定值服务请求所需信息结构定义*/
typedef struct 
{
	AI_OBJ_ID sgcb_id;			/**< 定值控制块ID*/
	ST_INT  group_num;			/**< 读定值组，如果传入-1，则认为是读当前激活区*/
	
	ST_INT  num_obj;
	AI_OBJ_ID *obj_ids;
	
	U_AC_REQ_DONE u_callback;	/**< 用户回调指针*/
	ST_INT  timeout;			/**< 超时时间*/
}AC_GETSGV_REQ_INFO;

/**  写定值服务请求所需信息结构定义*/
typedef struct 
{
	AI_OBJ_ID sgcb_id;			/**< 定值控制块ID*/
	ST_INT  group_num;			/**< 写定值组*/
	ST_INT sg_num;				/**< 写定值个数*/
	AI_OBJ_VAL *sg_vals;		/**< 写定值值数组*/
	U_AC_REQ_DONE u_callback;	/**< 用户回调指针*/
	ST_INT  timeout;			/**< 超时时间*/
}AC_SETSGV_REQ_INFO;

/**
 *  一个LD下所有定值的fcd集合   
 */
typedef struct 
{
	AI_OBJ_ID sgcb_id;	/**< 定值控制块ID*/
	ST_INT sg_num;		/**< 定值个数*/
	AI_OBJ_ID *sg_ids;	/**< 激活区定值ID*/
	AI_OBJ_ID *se_ids;	/**< 编辑区定值ID*/
}AC_LD_SG_CTRL;

/**
 *  一个IED下所有定值的fcd集合
 */
typedef struct
{
	ST_INT sgcb_num;	/**< 定值控制块个数*/
	AC_LD_SG_CTRL *ldsg_ctrl;/**< IED下的AC_LD_SG_CTRL结构数组*/
}AC_IED_SG_CTRL;

/**
 * 初始化客户端定值管理.
 * 先在ied内查找sgcb对象，然后查找fc为SG和SE的fcd，存到全局变量s_ied_sgs中。
 * 在每个ied对象空间创建完毕后，调用此接口。
 * @param	ied  ied对象
 * @param   ied_sg_ctrl  定值管理信息
 */
ST_VOID  ac_init_sg(AI_IED_CTRL *ied, AC_IED_SG_CTRL *ied_sg_ctrl);

/**
 * 反初始化定值管理
 * 释放初始化时分配的空间，在释放每个站点时调用
 * @return	ST_VOID
 */
ST_VOID ac_uninit_sg(AC_IED_SG_CTRL *ied_sg_ctrl);

/** 
 * 在s_ied_sgs里查找和传入的sgcb对应ld_sg_ctrl
 * @param	srv_id		服务器ID
 * @param	sgcb		定值控制块ID
 * @return	指向AC_LD_SG_CTRL结构的指针
 */
AC_LD_SG_CTRL *ac_find_ld_sg_ctrl(ST_INT srv_id, AI_OBJ_ID sgcb);

/**
 * 读定值，读取sgcb_id所属的ld下的所有定值。
 * 首先读sgcb的值，得到当前区号、编辑区号及定值区个数。
 * 如果要读的定值区号group_num==act_sg，则直接从激活区读取定值；
 * 如果要读的定值区号group_num==edit_sg，则直接从编辑区读取定值；
 * 如果要读的定值区号group_num!=act_sg && group_num!=edit_sg，
 * 则要先把编辑区号切换为group_num，然后从编辑区里读定值。
 * 支持两种模式，一次取完和分多次取。定值对应的fcd的id从全局变量g_ied_sgs中取。
 * @param srv_id		服务器ID
 * @param setSgv_info	读定值服务请求信息结构指针
 * @param req			请求结构(输出)
 */
ST_RET  ac_get_sg_values(ST_INT srv_id, AC_GETSGV_REQ_INFO *getSgv_info, AC_REQ_CTRL **req);

/**
 * 写定值。首先读sgcb的值，得到当前区号act_sg、编辑区号edit_sg及定值区个数num_of_sg。
 * 如果要写的定值区号group_num==edit_sg，则直接下发写服务；
 * 如果要写的定值区号group_num!=edit_sg，则切换编辑区为group_num， 然后再下发写服务；
 * 最后下发确认定值编辑服务，直到这步返回成功，才认为整个写定值成功。
 * 支持两种模式，一次写完和分多次写。
 * @param srv_id		服务器ID
 * @param setSgv_info	写定值服务请求信息结构指针
 * @param req			请求结构(输出)
 */
ST_RET  ac_set_sg_values(ST_INT srv_id, AC_SETSGV_REQ_INFO *setSgv_info, AC_REQ_CTRL **req);

/**
 *	不包括写定值确认步骤的写定值请求
 */
ST_RET  ac_set_sg_values_pre(ST_INT srv_id, AC_SETSGV_REQ_INFO *setSgv_info, AC_REQ_CTRL **req);

/**
 * 释放读定值控制块结构指针getSgv_ctrl指向的内存.
 * @param	getSgv_ctrl		读定值控制块结构指针
 * @return	ST_VOID
 */
ST_VOID ac_cleanup_getSgvCtrl(AC_GSGV_REQ_CTRL *getSgv_ctrl);

/**
 * 释放写定值控制块结构指针setSgv_ctrl指向的内存.
 * @param	setSgv_ctrl		读定值控制块结构指针
 * @return	ST_VOID
 */
ST_VOID ac_cleanup_setSgvCtrl(AC_SSGV_REQ_CTRL *setSgv_ctrl);
#ifdef __cplusplus
}
#endif

#endif /**<  IEC61850_AC_SG_INCLUDE */
