You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1238 lines
49 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/****************************************************************************
** File name : HTIEC61850.cpp
** Description : IEC 61850 库API
** 第三方库
** Create date : 2019.09.01
** Auther by : Liuyx
** Version info : V1.0.01
** Copyrigth By: xi'an huatek, Inc Co., Ltd
** Update record:
** DATE AUTHER DESC
** -------------------------------------------------------------------------
** 2019.09.01 Liuyx first build
****************************************************************************/
#include <stdio.h>
#include "HTGlobal.h"
#include "static_model.h"
static const char *_FILE_ = "HTIEC61850.cpp";
string vNextModelNode(ModelNode *pNode, string str)
{
if (!pNode) return str;
str.append(pNode->name).append("$");
vNextModelNode(pNode->firstChild, str);
return str;
}
/*
* ICD文件模型解析
*/
IedModel *LoadModelConfigFile(char *icd_file)
{
int cnt = 0, i = 0;
string szNodeStr = "", szSipl="";
LogicalDevice *pLD = NULL;
IedModel *model = ConfigFileParser_createModelFromConfigFileEx(icd_file);
cnt = IedModel_getLogicalDeviceCount(model);
int idx = 0;
szNodeStr.append(model->name);
szSipl.append(model->name);
for (int i = 0; i < cnt; i++)
{
pLD = IedModel_getDeviceByIndex(model, idx);
if (pLD) {
szNodeStr.append(pLD->name).append("/");
szSipl.append(pLD->name).append("/");
}
ModelNode *pNode = pLD->firstChild;
szNodeStr = vNextModelNode(pNode, szNodeStr);
szSipl = vNextModelNode(pNode->firstChild->sibling, szSipl);
//while (pNode) {
// szNodeStr.append(pNode->name);
// switch (pNode->modelType)
// {
// case LogicalDeviceModelType:
// break;
// case LogicalNodeModelType:
// szNodeStr.append("$");
// szSipl.append(pNode->sibling->name);
// break;
// case DataObjectModelType:
// szNodeStr.append("$");
// break;
// case DataAttributeModelType:
// break;
// }
// pNode = pNode->firstChild;
//}
//ModelNode *pNodeSpl = pLD->sibling;
//while (pNodeSpl) {
// szSipl.append(pNodeSpl->name); //.append("$")
// if (pNodeSpl->sibling) {
// szSipl.append("$");
// }
// pNodeSpl = pNodeSpl->sibling;
//}
printf("Node:%s\n", szNodeStr.c_str());
printf((const char*)"Node: %s\n", szNodeStr.c_str());
printf("Node: %s\n", szSipl.c_str());
}//IedModel_getModelNodeByObjectReference(model, iedModel_MONT);
//IedModel_getModelNodeByShortAddress
return model;
}
void reportCallbackFunction(void* parameter, ClientReport report)
{
char szTime[32] = { 0 };
MmsValue* dataSetValues = ClientReport_getDataSetValues(report);
printf("received report for: %s\n", ClientReport_getRcbReference(report));
int i;
for (i = 0; i < 4; i++) {
ReasonForInclusion reason = ClientReport_getReasonForInclusion(report, i);
vGetHostTimeFmt(szTime);
if (reason != IEC61850_REASON_NOT_INCLUDED) {
printf(" %s : GGIO1.SPCSO%d.stVal: %d (included for reason %d) rptid:%s\n", szTime, i,
MmsValue_getBoolean(MmsValue_getElement(dataSetValues, i)), reason, ClientReport_getRptId(report));
}
}
}
void reportCallbackFunctions(void* parameter, ClientReport report)
{
/*获取报告中的数据*/
MmsValue* dataSetValues = ClientReport_getDataSetValues(report);
/*获得数据集列表*/
LinkedList *m_list = (LinkedList *)&parameter;
int i = 0;
/*遍历数据集*/
while (LinkedList_getNext(*m_list) != NULL)
{
/*获取下一个节点可能是为了便于便利获取到的LinkedList的实际值时从第二个节点开始的*/
*m_list = LinkedList_getNext(*m_list);
/*获取上报原因*/
ReasonForInclusion reason = ClientReport_getReasonForInclusion(report, i);
/*这里如果reason是REASON_NOT_INCLUDED是不能获取数据值的*/
/*例如像数据变化时可能只上报了1个数据但是dataSetValues中会有所有数据的索引只不过其他数据的reason将会是REASON_NOT_INCLUDED*/
if (reason != REASON_NOT_INCLUDED) {
/*这里MmsValue_getBoolean只是假设返回的都是boolean类型实际应用中要根据实际数据类型调用不同的函数*/
printf(" %s: GGIO1.SPCSO%d.stVal: %d (included for reason %d) rptid:%s\n",
//printf(" %s : %i (included for reason %i)\n",
(char*)((*m_list)->data), i,
MmsValue_getBoolean(MmsValue_getElement(dataSetValues, i)), reason, ClientReport_getRptId(report));
}
i++;
}
}
// 获取错误消息
const char *getIedError(int error)
{
switch (error)
{
/* general errors */
case IED_ERROR_OK: //0,
return "No error occurred - service request has been successful";
case IED_ERROR_NOT_CONNECTED: // 1,
return "The service request can not be executed because the client is not yet connected";
case IED_ERROR_ALREADY_CONNECTED: // 2,
return "Connect service not execute because the client is already connected";
case IED_ERROR_CONNECTION_LOST: //3,
return "The service request can not be executed caused by a loss of connection";
case IED_ERROR_SERVICE_NOT_SUPPORTED: //4,
return " The service or some given parameters are not supported by the client stack or by the server";
case IED_ERROR_CONNECTION_REJECTED: //5,
return "Connection server failed";
case IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED: //6,
return "Cannot send request because outstanding call limit is reached";
/* client side errors */
case IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT: // 10,
return "API function has been called with an invalid argument";
case IED_ERROR_ENABLE_REPORT_FAILED_DATASET_MISMATCH: // 11,
return "The object report failed dataset mismatch";
case IED_ERROR_OBJECT_REFERENCE_INVALID: //12,
return "The object provided object reference is invalid (there is a syntactical error).";
case IED_ERROR_UNEXPECTED_VALUE_RECEIVED:// 13,
return "Received object is of unexpected type";
/* service error - error reported by server */
case IED_ERROR_TIMEOUT: //20,
return "The communication to the server failed with a timeout";
case IED_ERROR_ACCESS_DENIED:// 21,
return "The server rejected the access to the requested object/service due to access control";
case IED_ERROR_OBJECT_DOES_NOT_EXIST: //22,
return "The server reported that the requested object does not exist (returned by server)";
case IED_ERROR_OBJECT_EXISTS: // 23,
return "The server reported that the requested object already exists";
case IED_ERROR_OBJECT_ACCESS_UNSUPPORTED: // 24,
return "The server does not support the requested access method (returned by server)";
case IED_ERROR_TYPE_INCONSISTENT:// 25,
return "The server expected an object of another type (returned by server)";
case IED_ERROR_TEMPORARILY_UNAVAILABLE:// 26,
return "The object or service is temporarily unavailable (returned by server)";
case IED_ERROR_OBJECT_UNDEFINED:// 27,
return "The specified object is not defined in the server (returned by server)";
case IED_ERROR_INVALID_ADDRESS:// 28,
return "The specified address is invalid (returned by server)";
case IED_ERROR_HARDWARE_FAULT:// 29,
return "Service failed due to a hardware fault (returned by server)";
case IED_ERROR_TYPE_UNSUPPORTED: //30,
return "The requested data type is not supported by the server (returned by server)";
case IED_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT:// 31,
return "The provided attributes are inconsistent (returned by server)";
case IED_ERROR_OBJECT_VALUE_INVALID:// 32,
return "The provided object value is invalid (returned by server)";
case IED_ERROR_OBJECT_INVALIDATED:// 33,
return "The object is invalidated (returned by server)";
case IED_ERROR_MALFORMED_MESSAGE:// 34,
return "Received an invalid response message from the server";
case IED_ERROR_SERVICE_NOT_IMPLEMENTED:// 98,
return "Service not implemented";
case IED_ERROR_UNKNOWN:// 99
default:
//IedConnection_getLastApplError(g_IedConn.hConnHandle).error;
return "unknown error";
}
}
// 删除文件
void deleteComtradeFile(IedConnection con, const char *filename)
{
IedClientError error;
/* Delete file at server */
IedConnection_deleteFile(con, &error, filename);
if (error != IED_ERROR_OK)
vPrtLogMsg(LOG_DEBUG, error, "Failed to delete file! (code=%i)", error);
}
// 解析下载的录播文件并入库
int unPackComtradeFile(char *pfile)
{
CDBMySQL *pdbHandle = CDBMySQL::Instance();
if (!pdbHandle) return -1;
char *static_sql = NULL;
FILE *fd = NULL;
int n = 0;
ST_COMTRAD_DATA stAlmi;
static_sql = (char*)calloc((DEF_BUFFER_1K*DEF_BUFFER_1K), sizeof(char));
if (static_sql == NULL) {
vPrtLogMsg(LOG_ERROR, errno, "calloc buffer size=%d failed.", (DEF_BUFFER_1K*DEF_BUFFER_1K));
return -1;
}
fd = fopen(pfile, "r+b");
if (!fd) {
vPrtLogMsg(LOG_ERROR, errno, "Open csg pdfile %s failed! msg:%s", pfile, strerror(errno));
return errno;
}
int counter = 0;
sprintf(static_sql, "INSERT into busi_ampli_comtrad(id, comtrad_file, d_time,comtrad_data) "
"VALUES(guuid(),'%s',now(),'", pfile);
while (!feof(fd))
{
memset(&stAlmi, 0x00, sizeof(ST_COMTRAD_DATA));
n++;
counter = fread(&stAlmi, sizeof(char), sizeof(ST_COMTRAD_DATA), fd);
if (counter == sizeof(ST_COMTRAD_DATA))
{
sprintf(static_sql + strlen(static_sql),
"%d,%d,%d,%d,"
"%d,%d,%d,%d,"
"%d,%d,%d,%d,"
"%d,%d|",
//"%d, %d, %d, %d}",
(stAlmi.sno), (stAlmi.tme), (stAlmi.A1), (stAlmi.A2),
(stAlmi.B1), (stAlmi.B2), (stAlmi.C1), (stAlmi.C2),
(stAlmi.a1), (stAlmi.a2), (stAlmi.b1), (stAlmi.b2),
(stAlmi.c1), (stAlmi.c2)); // , (stAlmi.nsi), (stAlmi.crt));
}
}
fclose(fd);
static_sql[strlen(static_sql) - 1] = 0x00;
strcat(static_sql, "')");
pdbHandle->InsertRecord((const char*)static_sql);
vPrtLogMsg(LOG_DEBUG,0,"str_len = %d, SQL=%100s", strlen(static_sql), static_sql);
if (static_sql)
free(static_sql);
static_sql = NULL;
return n;
}
// IED录播文件浏览
void showComtradeFile(IedConnection con, const char *pszDirName )
{
IedClientError error;
bool moreFollows = false;
LinkedList rootDirectory; /* Get the root directory */
short no = 1;
// 设置下载文件跟路径
//IedConnection_setFilestoreBasepath(con, g_TConfig.getIEDComtradePath());
rootDirectory = IedConnection_getFileDirectoryEx(con, &error, pszDirName, NULL, &moreFollows);
if (error != IED_ERROR_OK) {
vPrtLogMsg(LOG_DEBUG, error, "Error retrieving file directory,MSG:%s", getIedError(error));
return;
}
LinkedList directoryEntry = LinkedList_getNext(rootDirectory);
while (directoryEntry != NULL)
{
FileDirectoryEntry entry = (FileDirectoryEntry)directoryEntry->data;
uint64_t last = FileDirectoryEntry_getLastModified(entry);
vPrtLogMsg(LOG_DEBUG, 0, "get comtrad No:%i,filesize:%i,filename:%s",no,
FileDirectoryEntry_getFileSize(entry), FileDirectoryEntry_getFileName(entry));
ST_FILES_ATTRIB stFiles;
stFiles.bstat = HT_COMTRADE_REDOWN; // 待下载
stFiles.sNo = no++;
//strcpy(stFiles.szFileName, FileDirectoryEntry_getFileName(entry));
sprintf(stFiles.szFileName, "%s%s", pszDirName, FileDirectoryEntry_getFileName(entry));
stFiles.iFileSize = FileDirectoryEntry_getFileSize(entry);
mutex_lock(g_list_comtrad_files_mutex);
g_list_comtrad_files.push_front(stFiles); // 录播文件如队列
mutex_unlock(g_list_comtrad_files_mutex);
directoryEntry = LinkedList_getNext(directoryEntry);
}
LinkedList_destroyDeep(rootDirectory, (LinkedListValueDeleteFunction)FileDirectoryEntry_destroy);
if (moreFollows)
vPrtLogMsg(LOG_DEBUG, 0, "--> more Comtrade files available...\n");
}
// 上传文件--目前IED不支持上传文件
void setComtradeFile(IedConnection con, const char *filename)
{
IedClientError error;
char szDirName[MAX_PATH] = { 0 };
char szFileName[MAX_PATH] = { 0 };
char szRemotePath[260];
char* dirc =strdup(filename);
char* basec = strdup(filename);
char* localDirName = getDirName(dirc, szDirName);
char* localFileName = getBaseName(basec, szFileName);
vPrtLogMsg(LOG_DEBUG, 0, "local dir: %s, local file: %s", localDirName, localFileName);
int size = get_file_size(filename);
/* IedConnection_setFilestoreBasepath requires the file separator at the end! */
strcpy(dirc, localDirName);
strcat(dirc, "/");
sprintf(szRemotePath, "%s%s", g_TConfig.getIEDComtradePath(), localFileName);
vPrtLogMsg(LOG_DEBUG, 0, "filestore basepath: %s", dirc);
IedConnection_setFilestoreBasepath(con, g_TConfig.getIEDComtradePath());
IedConnection_setFile(con, &error, filename, localFileName);
free(dirc);
free(basec);
if (error != IED_ERROR_OK)
vPrtLogMsg(LOG_ERROR, error, "Failed to upload file! (code=%i),MSG=%s", error, getIedError(error));
else vPrtLogMsg(LOG_ERROR, error, "Upload file:%s successed!", localFileName);
}
// 下载录播文件
static bool downloadFileHandler(void* parameter, uint8_t* buffer, uint32_t bytesRead)
{
FILE* fp = (FILE*)parameter;
vPrtLogMsg(LOG_DEBUG, 0, "received %i bytes", bytesRead);
if (fwrite(buffer, 1, bytesRead, fp) == bytesRead)
return true;
else {
vPrtLogMsg(LOG_ERROR, errno, "Failed to write local file!");
return false;
}
}
// 获取录播文件
void getComtradeFile(IedConnection con)
{
IedClientError error;
ST_FILES_ATTRIB stFiles;
char szLocalFile[MAX_PATH] = { 0 };
char szFilePath[MAX_PATH] = { 0 };
memset(&stFiles, 0x00, sizeof(ST_FILES_ATTRIB));
list<ST_FILES_ATTRIB>::iterator ptr = g_list_comtrad_files.begin();
while (ptr != g_list_comtrad_files.end())
{
mutex_lock(g_list_comtrad_files_mutex);
printf("%d-%d-%s\n", (*ptr).bstat, (*ptr).iFileSize, (*ptr).szFileName);
if (HT_COMTRADE_DOWNED == (*ptr).bstat) { // 已经下载完成
mutex_unlock(g_list_comtrad_files_mutex);
_SLEEP(100);
ptr++;
continue;
}
vPrtLogMsg(LOG_DEBUG, 0, "getComtradeFiles file_count= %d", g_list_comtrad_files.size());
memcpy(&stFiles, &(*ptr), sizeof(ST_FILES_ATTRIB));
char* bname = strdup((const char*)stFiles.szFileName);
char* localFilename = getBaseName(bname, szLocalFile);
strcpy(szFilePath, g_TConfig.getComtradePath());
strcat(szFilePath, "/");
strcat(szFilePath, szLocalFile);
FILE* fp = fopen(szFilePath, "wb");
if (fp != NULL)
{
/* Download a file from the server */
IedConnection_getFile(con, &error, stFiles.szFileName, downloadFileHandler, (void*)fp);
if (error == IED_ERROR_OK) {
if (g_TConfig.getIEDComtradeRemove()) // 下载完成后是否删除IED上的文件
deleteComtradeFile(con, stFiles.szFileName);
(*ptr).bstat = HT_COMTRADE_DOWNED;
strcpy((*ptr).szFileName, szFilePath); // 修改为本地路径+文件名
ptr++;
}
else vPrtLogMsg(LOG_ERROR, error, "Failed to get file:%s! MSG:%s", stFiles.szFileName,getIedError(error));
fclose(fp);
}
else vPrtLogMsg(LOG_ERROR, errno, "Failed to open file %s", szFilePath);
free(bname);
bname = NULL;
mutex_unlock(g_list_comtrad_files_mutex);
_SLEEP(50);
}
}
//
//// 录播文件下载,解析入库线程
//void vDownLoadComtradeFiles(/*void *arg*/ ST_IED_CONN_HANDLE &stIedCon)
//{
// IedClientError error;
// IedConnection con = IedConnection_create();
// ST_COMTRAD_FILES_ATTRIB stFiles;
// //vPrtLogMsg(LOG_DEBUG, 0, "thread_iec61850_getcomtrade_files = %d startup...", GETTID());
//
// IedConnection_connect(con, &error, g_TConfig.getModbusTcpAddr(), g_TConfig.getModbusTcpPort());
// //IedConnection_connect(con, &error, "192.168.1.1", 102);
// if (error != IED_ERROR_OK) {
// printf("Failed to connect to %s:%i\n", g_TConfig.getModbusTcpAddr(), g_TConfig.getModbusTcpPort());
// return ;
// }
// showComtradeFile(con, g_TConfig.getIEDComtradePath()); // 查看待下载的文件列表
// getComtradeFile(con); // 下载文件
// //setComtradeFile(con, "comtrad/sim_data1.dat");
// // 解析录播文件并入库
// memset(&stFiles, 0x00, sizeof(ST_COMTRAD_FILES_ATTRIB));
// while (!g_list_comtrad_files.empty() || g_list_comtrad_files.size() > 0)
// {
// vPrtLogMsg(LOG_DEBUG, 0, "getComtradeFiles count=%d, bstat=%d, file=%s,filesize=%d",
// g_list_comtrad_files.size(),
// g_list_comtrad_files.back().bstat,
// g_list_comtrad_files.back().szFileName, g_list_comtrad_files.back().iFileSize);
// if (HT_COMTRADE_REDOWN == g_list_comtrad_files.back().bstat) { // 未下载完成
// _SLEEP(100);
// continue;
// }
// mutex_lock(g_list_comtrad_files_mutex);
// memcpy(&stFiles, &(g_list_comtrad_files.back()), sizeof(ST_COMTRAD_FILES_ATTRIB)); // 由尾取出
// g_list_comtrad_files.pop_back(); // 由尾删除
// mutex_unlock(g_list_comtrad_files_mutex);
// //unPackComtradeFile(stFiles.szFileName); // 解析文件并入库
// }
//
// printf("file download and parser complate....\n");
// IedConnection_abort(con, &error);
// IedConnection_destroy(con);
// return ;
//}
// 录播文件下载,解析入库线程
void vDownLoadComtradeFiles(ST_IED_CONN_HANDLE &stIedCon)
{
ST_FILES_ATTRIB stFiles;
showComtradeFile(stIedCon.hConnHandle, g_TConfig.getIEDComtradePath()); // 查看待下载的文件列表
getComtradeFile(stIedCon.hConnHandle); // 下载文件
setComtradeFile(stIedCon.hConnHandle, "../etc/setting.ini");
// 解析录播文件并入库
memset(&stFiles, 0x00, sizeof(ST_FILES_ATTRIB));
while (!g_list_comtrad_files.empty() || g_list_comtrad_files.size() > 0)
{
vPrtLogMsg(LOG_DEBUG, 0, "getComtradeFiles count=%d, bstat=%d, file=%s,filesize=%d",
g_list_comtrad_files.size(),
g_list_comtrad_files.back().bstat,
g_list_comtrad_files.back().szFileName, g_list_comtrad_files.back().iFileSize);
if (HT_COMTRADE_REDOWN == g_list_comtrad_files.back().bstat) { // 未下载完成
_SLEEP(100);
continue;
}
mutex_lock(g_list_comtrad_files_mutex);
memcpy(&stFiles, &(g_list_comtrad_files.back()), sizeof(ST_FILES_ATTRIB)); // 由尾取出
g_list_comtrad_files.pop_back(); // 由尾删除
mutex_unlock(g_list_comtrad_files_mutex);
//unPackComtradeFile(stFiles.szFileName); // 解析文件并入库
}
printf("file download and parser complate....\n");
return;
}
/*****************************************************************************
* thread_iec61850_service_proc - iec61850 服务线程
******************************************************************************/
// 打印数据对象
void printDataDirectory(char* doRef, IedConnection con, int spaces)
{
IedClientError error;
LinkedList dataAttributes = IedConnection_getDataDirectory(con, &error, doRef);
if (dataAttributes != NULL)
{
LinkedList dataAttribute = LinkedList_getNext(dataAttributes);
while (dataAttribute != NULL)
{
char* daName = (char*)dataAttribute->data;
//printSpaces(spaces);
vPrtLogMsg(LOG_DEBUG, 0, " DA: %s", (char*)dataAttribute->data);
dataAttribute = LinkedList_getNext(dataAttribute);
char daRef[130];
sprintf(daRef, "%s.%s", doRef, daName);
printDataDirectory(daRef, con, spaces + 2);
}
}
LinkedList_destroy(dataAttributes);
}
// 获取IED的配置模型
int vGetRemoteIEDModelConfig(IedConnection con)
{
IedClientError error;
char lnRef[129] = { 0 }, doRef[129] = { 0 };
vPrtLogMsg(LOG_DEBUG,0,"Get logical device list...");
LinkedList deviceList = IedConnection_getLogicalDeviceList(con, &error);
if (error != IED_ERROR_OK) {
vPrtLogMsg(LOG_ERROR, error, "Failed to read device list (error code: %i)", error);
return error;
}
// 获取逻辑设备模型LD
LinkedList device = LinkedList_getNext(deviceList);
while (device != NULL)
{
vPrtLogMsg(LOG_DEBUG, error,"LD: %s", (char*)device->data);
LinkedList logicalNodes = IedConnection_getLogicalDeviceDirectory(con, &error,(char*)device->data);
LinkedList logicalNode = LinkedList_getNext(logicalNodes);
// 获取逻辑节点模型LN
while (logicalNode != NULL)
{
vPrtLogMsg(LOG_DEBUG, error, " LN: %s", (char*)logicalNode->data);
sprintf(lnRef, "%s/%s", (char*)device->data, (char*)logicalNode->data);
LinkedList dataObjects = IedConnection_getLogicalNodeDirectory(con, &error,lnRef, ACSI_CLASS_DATA_OBJECT);
LinkedList dataObject = LinkedList_getNext(dataObjects);
// 获取数据对象模型DO
while (dataObject != NULL)
{
char* dataObjectName = (char*)dataObject->data;
vPrtLogMsg(LOG_DEBUG, error, " DO: %s", dataObjectName);
dataObject = LinkedList_getNext(dataObject);
sprintf(doRef, "%s/%s.%s", (char*)device->data, (char*)logicalNode->data, dataObjectName);
printDataDirectory(doRef, con, 4);
}
LinkedList_destroy(dataObjects);
LinkedList dataSets = IedConnection_getLogicalNodeDirectory(con, &error, lnRef, ACSI_CLASS_DATA_SET);
LinkedList dataSet = LinkedList_getNext(dataSets);
// 获取数据类型定义DS
while (dataSet != NULL)
{
char* dataSetName = (char*)dataSet->data;
bool isDeletable;
char dataSetRef[130];
sprintf(dataSetRef, "%s.%s", lnRef, dataSetName);
LinkedList dataSetMembers = IedConnection_getDataSetDirectory(con, &error, dataSetRef, &isDeletable);
if (isDeletable)
vPrtLogMsg(LOG_DEBUG, error, " Data set: %s (deletable)", dataSetName);
else
vPrtLogMsg(LOG_DEBUG, error, " Data set: %s (not deletable)", dataSetName);
LinkedList dataSetMemberRef = LinkedList_getNext(dataSetMembers);
while (dataSetMemberRef != NULL)
{
char* memberRef = (char*)dataSetMemberRef->data;
vPrtLogMsg(LOG_DEBUG, error, " %s", memberRef);
dataSetMemberRef = LinkedList_getNext(dataSetMemberRef);
}
LinkedList_destroy(dataSetMembers);
dataSet = LinkedList_getNext(dataSet);
}
LinkedList_destroy(dataSets);
LinkedList reports = IedConnection_getLogicalNodeDirectory(con, &error, lnRef, ACSI_CLASS_URCB);
LinkedList report = LinkedList_getNext(reports);
while (report != NULL)
{
char* reportName = (char*)report->data;
vPrtLogMsg(LOG_DEBUG, error, " RP: %s", reportName);
report = LinkedList_getNext(report);
}
LinkedList_destroy(reports);
reports = IedConnection_getLogicalNodeDirectory(con, &error, lnRef, ACSI_CLASS_BRCB);
report = LinkedList_getNext(reports);
while (report != NULL)
{
char* reportName = (char*)report->data;
vPrtLogMsg(LOG_DEBUG, error, " BR: %s", reportName);
report = LinkedList_getNext(report);
}
LinkedList_destroy(reports);
logicalNode = LinkedList_getNext(logicalNode);
}
LinkedList_destroy(logicalNodes);
device = LinkedList_getNext(device);
}
LinkedList_destroy(deviceList);
return error;
}
// 初始化61850链接环境参数
void vIedInitIedEvent()
{
int ied_count = 0;
ST_IED_ADDR *pIed = NULL;
char szKey[64] = { 0 };
if (g_TConfig.getIEDCount() <= 0) {
vPrtLogMsg(LOG_ERROR, 0, "Can't found IED device configure,please check communication parame...");
return;
}
while (ied_count < g_TConfig.getIEDCount())
{
ST_IED_CONN_HANDLE stIedHandle;
string strKey = "";
pIed = g_TConfig.getIEDAddrsss(ied_count++);
if (pIed != NULL) {
memset(&stIedHandle, 0x00, sizeof(ST_IED_CONN_HANDLE));
strcpy(stIedHandle.ied_addr, pIed->IedAddr);
stIedHandle.ied_port = pIed->port;
sprintf(szKey, "%s:%d", stIedHandle.ied_addr, stIedHandle.ied_port);
strKey = szKey;
stIedHandle.hConnHandle = IedConnection_create();
IedConnection_setConnectTimeout(stIedHandle.hConnHandle, 6000); // connected timeout 6s
stIedHandle.bWarn = true;
mutex_lock(g_MapIedConn_mutex);
g_MapIedConn.insert(map<string, ST_IED_CONN_HANDLE>::value_type(strKey, stIedHandle));
mutex_unlock(g_MapIedConn_mutex);
}
}
}
// 释放链接及资源
void vIedFreeIedEvent(ST_IED_CONN_HANDLE &stIedHandle)
{
if (stIedHandle.hConnHandle) {
IedConnection_close(stIedHandle.hConnHandle);
IedConnection_destroy(stIedHandle.hConnHandle);
}
stIedHandle.hConnHandle = NULL;
if (stIedHandle.tIedModel) {
IedModel_destroy(stIedHandle.tIedModel);
}
stIedHandle.tIedModel = NULL;
}
// 根据icd节点名称获取传感器绑定关系
bool bGetDeviceBindRelationship(char *pNodeName, ST_DB_BODY &pDb, ST_DEVICE_INFO &stBaseInfo)
{
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 1.");
map<string, ST_PARAM_BIND>::iterator m_pIter;
//mutex_lock(g_map_parambind_mutex);
m_pIter = g_map_parambind.find((char*)pNodeName);
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 2.");
if (m_pIter == g_map_parambind.end()) {
vPrtLogMsg(LOG_WARNG, RET_FAIL, "can not found:[%s] bind device information.", pNodeName);
return false;
}
strcpy(pDb.szSensorID, m_pIter->second.sensorid);
strcpy(pDb.szFrequency , m_pIter->second.szFrequency);
//mutex_unlock(g_map_parambind_mutex);
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 3 [%s] [%s].",m_pIter->second.sensorid,m_pIter->second.szFrequency);
string strKey = pDb.szSensorID;
//vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 3 [%c][%c][%s][%s].",strKey[0],pDb.szSensorID[0],strKey,pDb.szSensorID);
//if (strlen(pDb.szFrequency) > 0) { // 无频率时为噪声和中心点传感器
// strKey.append("-").append(pDb.szFrequency);
//}
map<string, ST_DEVICE_INFO>::iterator m_pTIter;
//mutex_lock(g_map_device_mutex);
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 4 [%s].",(char*)strKey.c_str());
m_pTIter = g_map_device.find((char*)strKey.c_str());
if (m_pTIter == g_map_device.end()) {
vPrtLogMsg(LOG_WARNG, RET_FAIL, "can not found:[%s],objname:[%s] threshold setting.", pDb.szSensorID, pNodeName);
return false;
}
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 5.");
memcpy(&stBaseInfo, &(*m_pTIter).second, sizeof(ST_DEVICE_INFO));
//mutex_unlock(g_map_device_mutex);
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 6.");
return true ;
}
// 获取振动,噪声,中心点监测值
float getAccPriValue(IedConnection conn, char *pobjname, FunctionalConstraint fc)
{
IedClientError error;
float fval = 0.0f;
MmsValue* value = IedConnection_readObject(conn, &error, pobjname, fc);
if (value != NULL) {
fval = MmsValue_toFloat(value);
vPrtLogMsg(LOG_DEBUG, error, "read [%s] float value: %f", pobjname, fval);
MmsValue_delete(value);
}
return fval;
}
// 获取振动,噪声,中心点监测值
bool getIEDMoniValue(IedConnection conn, ST_PARAM_BIND &stBind, ST_IED_VALUES &stIedVal)
{
FunctionalConstraint fc;
IedClientError error;
char szTime[32] = { 0 };
bool ret = false;
vPrtLogMsg(LOG_WARNG, 0, "rensichao read [%s] \n", stBind.nodetype);
if (!stringncasecmp((const char*)stBind.nodetype, "MX", 2))
{fc = IEC61850_FC_MX;
vPrtLogMsg(LOG_WARNG, 0, "rensichao read fc [%d] \n", fc);}
else if(!stringncasecmp((const char*)stBind.nodetype, "ST", 2))
fc = IEC61850_FC_ST;
else if(!stringncasecmp((const char*)stBind.nodetype, "SE", 2))
fc = IEC61850_FC_SE;
else {
vPrtLogMsg(LOG_WARNG, 0, "read [%s],nodetype[MX|ST|SE] unkown!", stBind.nodename);
return false;
}
//vPrtLogMsg(LOG_WARNG, 0, "read [%s],[%d]\n", stBind.nodename,fc);
MmsValue* value = IedConnection_readObject(conn, &error, stBind.nodename, fc);
if (value != NULL && error == 0) {
int n = MmsValue_getArraySize(value);
MmsValue_getElement(value, 0);
switch (MmsValue_getType(value))
{
case MMS_ARRAY: // 0
break;
case MMS_STRUCTURE: //1
break;
case MMS_BOOLEAN:
stIedVal.ST_val = MmsValue_getBoolean(value);
vPrtLogMsg(LOG_DEBUG, error, "read [%s] state bool value: %f", stBind.nodename,
(stIedVal.ST_val == true ? "true" : "false"));
ret = true;
break;
case MMS_INTEGER:
break;
case MMS_UNSIGNED:
break;
case MMS_FLOAT:
stIedVal.MX_f = MmsValue_toFloat(value);
vPrtLogMsg(LOG_DEBUG, error, "read [%s] float value: %f", stBind.nodename, stIedVal.MX_f);
ret = true;
break;
case MMS_BINARY_TIME:
break;
case MMS_BIT_STRING:
break;
case MMS_STRING : //13,
break;
case MMS_UTC_TIME: // 14
stIedVal.t = MmsValue_toUnixTimestamp(value);
UTC2LocalTime(stIedVal.t, szTime);
vPrtLogMsg(LOG_DEBUG, error, "read [%s] time value: %s", stBind.nodename, szTime);
ret = true;
break;
default:
vPrtLogMsg(LOG_WARNG, error, "read [%s], value type unkown!", stBind.nodename);
vPrtLogMsg(LOG_WARNG, error, "rensichao read [%s], read [%d]", stBind.nodename, MmsValue_getType(value));
}
MmsValue_delete(value);
}
return ret;
}
// 获取振动,噪声,中心点监测时间值
time_t getTimeiValue(IedConnection conn, char *pobjname, FunctionalConstraint fc)
{
IedClientError error;
time_t fval ;
MmsValue* value = IedConnection_readObject(conn, &error, pobjname, fc);
if (value != NULL) {
fval = MmsValue_toUnixTimestamp(value);
vPrtLogMsg(LOG_DEBUG, error, "read [%s] time value: %i", pobjname, fval);
MmsValue_delete(value);
}
return fval;
}
// 获取告警监测值
bool getAlarmValue(IedConnection conn, char *pobjname,FunctionalConstraint fc)
{
IedClientError error;
bool bval = false;
MmsValue* value = IedConnection_readObject(conn, &error, pobjname, fc);
if (value != NULL) {
bval = MmsValue_getBoolean(value);
vPrtLogMsg(LOG_DEBUG, error, "read [%s] alarm bool value: %s", pobjname, (bval == true? "true":"false"));
MmsValue_delete(value);
}
return bval;
}
// 添加入库队列
void Add_SetList(ST_DB_BODY *pData, ST_DEVICE_INFO *pstBase)
{
ST_DB_BODY stSetData;
vPrtLogMsg(LOG_DEBUG, 0, "rensichao confirm add_setlist");
memset(&stSetData, 0x00, sizeof(ST_DB_BODY));
memcpy(&stSetData, pData, sizeof(ST_DB_BODY));
strcpy(stSetData.m_id, pstBase->szMID);
stSetData.in_out = pstBase->cInOut;
stSetData.phase = pstBase->cPhase;
stSetData.side = pstBase->cSide;
stSetData.szDevType = pstBase->cDevType;
vPrtLogMsg(LOG_DEBUG, 0, "rensichao confirm database %s,%c,%c,%c,%d",stSetData.m_id,stSetData.in_out,stSetData.phase,stSetData.side,stSetData.szDevType);
mutex_lock(g_list_db_body_mutex);
g_list_db_body.push_front(stSetData);
mutex_unlock(g_list_db_body_mutex);
}
// 添加阈值告警队列
void Add_SetWarning_List(ST_DB_WARN &stWarn)
{
mutex_lock(g_list_db_warn_mutex);
g_list_db_warn.push_front(stWarn);
mutex_unlock(g_list_db_warn_mutex);
}
// 检查预警告警
bool bWarningCheck(ST_DB_BODY stBody, ST_DB_WARN &stWarn)
{
string strKey = "";
map<string, ST_THRES_CONF>::iterator m_pIter;
strKey = stBody.szSensorID;
if (stBody.szDevType == '1') { //1:振动装置 2:噪声装置 3:中心点装置
strKey.append("-").append(stBody.szFrequency);
}
mutex_lock(g_thres_conf_mutex);
m_pIter = g_thres_conf.find((char*)strKey.c_str());
if (m_pIter == g_thres_conf.end())
{
mutex_unlock(g_thres_conf_mutex);
return false;
}
//找到阈值
if (stBody.value <= (*m_pIter).second.dThreshold) {
mutex_unlock(g_thres_conf_mutex);
return false;
}
stWarn.almtime = stBody.dtime;
stWarn.level = 1;
stWarn.state = 1;
strcpy(stWarn.szDesc, (*m_pIter).second.szSDevName);
strcpy(stWarn.s_id, (*m_pIter).second.szSubID);
stWarn.value = stBody.value;
if (stBody.szDevType == '1') { //1:振动装置 2:噪声装置 3:中心点装置
strcpy(stWarn.valunit, "mm/s²");
//1:通信异常告警 2 : 装置自检异常告警 3 : 信号异常告警 4 : 供电异常告警 5 : 振动阈值告警 6 : 噪声阈值告警 7 : 中心点阈值告警 8 : 日增长率告警 9 : 月增长率告警 10 : 月偏差率告警 11 : 服务器与IED通信异常 12 : 传感器振动告警 13 : 传感器噪声告警 14 : 传感器中心点告警
stWarn.warn_type = 5;
}
else if (stBody.szDevType == '2') {
strcpy(stWarn.valunit, "dB");
stWarn.warn_type = 6;
}
else if (stBody.szDevType == '3') {
strcpy(stWarn.valunit, "A");
stWarn.warn_type = 7;
}
mutex_unlock(g_thres_conf_mutex);
return true;
}
#if 1
// 获取实时监测数据-遥测
void vGetFCMXData_YC(IedConnection conn)
{
ST_PARAM_BIND stBind;
ST_IED_VALUES stIedVal;
ST_DEVICE_INFO stBase;
ST_DB_BODY stBody;
map<string, ST_PARAM_BIND>::iterator m_pIter;
mutex_lock(g_map_parambind_mutex);
for (m_pIter = g_map_parambind.begin(); m_pIter != g_map_parambind.end(); m_pIter++)
{
memset(&stBind, 0x00, sizeof(ST_PARAM_BIND));
memset(&stIedVal, 0x00, sizeof(ST_IED_VALUES));
memset(&stBody, 0x00, sizeof(ST_DB_BODY));
memset(&stBase, 0x00, sizeof(ST_DEVICE_INFO));
memcpy(&stBind, &m_pIter->second, sizeof(ST_PARAM_BIND));
vPrtLogMsg(LOG_WARNG, 0, "rensichao read pIter [%s] \n", stBind.nodetype);
if(false == getIEDMoniValue(conn, stBind, stIedVal))
{
continue; // 取振幅值
}
stBody.value = stIedVal.MX_f;
vPrtLogMsg(LOG_WARNG, 0, "rensichao read add list [%d] \n", stBody.value);
if(false==bGetDeviceBindRelationship(stBind.nodename, stBody, stBase)) continue;
vPrtLogMsg(LOG_WARNG, 0, "rensichao read add list midddle[%d] \n", stBody.value);
Add_SetList(&stBody,&stBase);
vPrtLogMsg(LOG_WARNG, 0, "rensichao read add list end[%s] \n", stBind.nodetype);
// 预警判断
ST_DB_WARN stWarn;
memset(&stWarn, 0x00, sizeof(ST_DB_WARN));
if (bWarningCheck(stBody,stWarn) == true) {
Add_SetWarning_List(stWarn);
}
}
mutex_unlock(g_map_parambind_mutex);
}
#else
// 获取实时监测数据-遥测
void vGetFCMXData_YC(IedConnection conn)
{
ST_MONI_DATA stFCMX;
memset(&stFCMX, 0x00, sizeof(ST_MONI_DATA));
char szMXNode[256] = { 0 };
string strKey;
for (int i = 1; i <= 12; i++) // SVBR01-SVBR16
{
// 振动分量监测值
for (int n = 1; n <= 19; n++)
{
ST_DB_BODY stBody;
ST_DEVICE_INFO stBase;
memset(&stBody, 0x00, sizeof(ST_DB_BODY));
memset(&stBase, 0x00, sizeof(ST_DEVICE_INFO));
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.AccPri%d.mag.f", i, n);
if (i == 1 && n == 1) strKey = szMXNode;
//sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d$AccPri%d$mag$f", i, n);
switch (n)
{
case 1:
stFCMX.AccPri1 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX); // 取振幅值
stBody.value = stFCMX.AccPri1;
bGetDeviceBindRelationship(szMXNode, stBody, stBase);
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.AccPri%d.mag.t", i, n);
stBody.dtime = getTimeiValue(conn, szMXNode, IEC61850_FC_MX);
Add_SetList(&stBody,&stBase);
break;
case 2:
stFCMX.AccPri2 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 3:
stFCMX.AccPri3 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 4:
stFCMX.AccPri4 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 5:
stFCMX.AccPri5 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 6:
stFCMX.AccPri6 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 7:
stFCMX.AccPri7 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 8:
stFCMX.AccPri8 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 9:
stFCMX.AccPri9 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 10:
stFCMX.AccPri10 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 11:
stFCMX.AccPri11 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 12:
stFCMX.AccPri12 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 13:
stFCMX.AccPri13 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 14:
stFCMX.AccPri14 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 15:
stFCMX.AccPri15 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 16:
stFCMX.AccPri16 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 17:
stFCMX.AccPri17 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 18:
stFCMX.AccPri18 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
case 19:
stFCMX.AccPri19 = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
break;
} // end switch
}// end for (n)
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.EnvNoiPri.mag.f", i); // 噪声值
//sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d$EnvNoiPri$mag$f", i); // 噪声值
stFCMX.EnvNoiPri = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.NeuCur.mag.f", i); // 中心点电流
//sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d$NeuCur$mag$f", i); // 中心点电流
stFCMX.NeuCur = getAccPriValue(conn, szMXNode, IEC61850_FC_MX);
}
}
#endif
// 获取实时监测数据-遥信
void vGetFCMXData_YX(IedConnection conn)
{
ST_WARN_ALARM stFCST;
memset(&stFCST, 0x00, sizeof(ST_WARN_ALARM));
char szMXNode[256] = { 0 };
for (int i = 1; i <= 12; i++) // SVBR01-SVBR16
{
// 振动分量监测值
for (int n = 1; n <= 19; n++)
{
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.AccPriAlm%d.stVal", i, n);
switch (n)
{
case 1:
stFCST.AccPriAlm1 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 2:
stFCST.AccPriAlm2 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 3:
stFCST.AccPriAlm3 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 4:
stFCST.AccPriAlm4 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 5:
stFCST.AccPriAlm5 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 6:
stFCST.AccPriAlm6 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 7:
stFCST.AccPriAlm7 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 8:
stFCST.AccPriAlm8 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 9:
stFCST.AccPriAlm9 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 10:
stFCST.AccPriAlm10 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 11:
stFCST.AccPriAlm11 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 12:
stFCST.AccPriAlm12 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 13:
stFCST.AccPriAlm13 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 14:
stFCST.AccPriAlm14 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 15:
stFCST.AccPriAlm15 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 16:
stFCST.AccPriAlm16 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 17:
stFCST.AccPriAlm17 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 18:
stFCST.AccPriAlm18 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
case 19:
stFCST.AccPriAlm19 = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
break;
} // end switch
}// end for (n)
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.MoDevConf.stVal", i); // 通信异常值
stFCST.MoDevConf = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.MoDevDetF.stVal", i); // 传感器自检异常
stFCST.MoDevDetF = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.MoDevSigF.stVal", i); // 传感器信号异常
stFCST.MoDevSigF = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.MoDevPowF.stVal", i); // 传感器供电异常
stFCST.MoDevPowF = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.EnvNoiPriAlm.stVal", i); // 传感器供电异常
stFCST.EnvNoiPriAlm = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
sprintf(szMXNode, "TEMPLATEMONT/SVBR%02d.NeuCurAlm.stVal", i); // 中性点电流告警
stFCST.NeuCurAlm = getAlarmValue(conn, szMXNode, IEC61850_FC_ST);
}
}
// 设置IED控制参数
int writeCtlValue(IedConnection conn, char *pObjname, FunctionalConstraint FC, int val)
{
/* write a variable to the server */
IedClientError error;
MmsValue* value = MmsValue_newIntegerFromInt32(val); // MmsValue_newVisibleString("libiec61850.com");
if (MmsValue_toInt32(value) != val) return -1;
IedConnection_writeObject(conn, &error, pObjname, FC, value);
if (error != IED_ERROR_OK)
vPrtLogMsg(LOG_DEBUG, error, "write [%s] alarm bool value: %i, MSG=%s", pObjname, val, getIedError(error));
MmsValue_delete(value);
return error;
}
// 设置控制参数
void vSetFCSEData_CTRL(IedConnection conn)
{
char szFCSECtrl[256] = { 0 };
for (int i = 1; i < 12; i++) {
// 缺失使能参数
sprintf(szFCSECtrl, "TEMPLATEMONT/SVBR%02d.SmpProd.setVal",i); // 采集频率
writeCtlValue(conn, szFCSECtrl, IEC61850_FC_SE, 5666);
sprintf(szFCSECtrl, "TEMPLATEMONT/SVBR%02d.SmpInt.setVal", i); // 采样间隔(H)
writeCtlValue(conn, szFCSECtrl, IEC61850_FC_SE, 5666);
sprintf(szFCSECtrl, "TEMPLATEMONT/SVBR%02d.StartTime.setVal", i);//起始时间
writeCtlValue(conn, szFCSECtrl, IEC61850_FC_SE, 5666);
}
}
void vGetDataSetList(IedConnection conn)
{
#if 0
/* read an analog measurement value from server */
MmsValue* value = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", IEC61850_FC_MX);
if (value != NULL) {
float fval = MmsValue_toFloat(value);
printf("read float value: %f\n", fval);
//MmsValue_delete(value);
}
/* read data set 获取服务端的实时数据集信息*/
ClientDataSet clientDataSet = IedConnection_readDataSetValues(con, &error, "simpleIOGenericIO/LLN0.Events", NULL);
if (clientDataSet == NULL)
printf("failed to read dataset\n");
else {
printf(" DataSet Ref: %s\n", (ClientDataSet_getReference(clientDataSet)));
printf(" DataSet Val: %f\n", MmsValue_toFloat(ClientDataSet_getValues(clientDataSet)));
}
bool deletable;
/*获取数据集列表这里要用LinkedList顺序不能错误不然在回调函数中匹配的数据信息就是错误的*/
LinkedList list = IedConnection_getDataSetDirectory(con, &error, "simpleIOGenericIO/LLN0$Events", &deletable);
/* Read RCB values 获取RCB的信息 */
ClientReportControlBlock rcb =
IedConnection_getRCBValues(con, &error, "simpleIOGenericIO/LLN0.RP.EventsRCB01", NULL);
printf(" RCBReference :%s\n", ClientReportControlBlock_getObjectReference(rcb));
printf(" RCBisBuffered :%i\n", ClientReportControlBlock_isBuffered(rcb));
printf(" RCBgetRptId :%s\n", ClientReportControlBlock_getRptId(rcb));
printf(" RCBgetResv :%i\n", ClientReportControlBlock_getResv(rcb));
printf(" RCBgetResv :%s\n", ClientReportControlBlock_getDataSetReference(rcb));
bool rptEna = ClientReportControlBlock_getRptEna(rcb);
printf("RptEna = %i\n", rptEna);
/* Install handler for reports 注册收到报告时的回调函数 */
IedConnection_installReportHandler(con, "simpleIOGenericIO/LLN0.RP.EventsRCB01",
ClientReportControlBlock_getRptId(rcb), reportCallbackFunctions, (void *)list);
/* Set trigger options and enable report */
//#define TRG_OPT_DATA_CHANGED 1 数据变换
//#define TRG_OPT_QUALITY_CHANGED 2 数据质量变换
//#define TRG_OPT_DATA_UPDATE 4 数据更新
//#define TRG_OPT_INTEGRITY 8 周期上送
//#define TRG_OPT_GI 16 一般请求(询问)
//#define TRG_OPT_TRANSIENT 128 仅在上升沿触发报告(瞬态变量)
//设置报告的触发参数,这里设置了周期性上报和数据改变时上报
ClientReportControlBlock_setTrgOps(rcb, TRG_OPT_DATA_UPDATE | TRG_OPT_INTEGRITY | TRG_OPT_GI);
//设置报告的触发参数,使能报告控制块
ClientReportControlBlock_setRptEna(rcb, true);
//设置报告的触发参数设置周期性报告周期这里设置为1000毫秒上报一次
ClientReportControlBlock_setIntgPd(rcb, 1000);
//设置报告控制块参数
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA | RCB_ELEMENT_TRG_OPS | RCB_ELEMENT_INTG_PD | RCB_ELEMENT_DATSET, true);
if (error != IED_ERROR_OK)
printf("report activation failed (code: %i)\n", error);
Sleep(1000);
/* trigger GI report 使能总召唤 */
ClientReportControlBlock_setGI(rcb, true);
///*使在报告控制块里添加总召唤的参数*/
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true);
if (error != IED_ERROR_OK)
printf("Error triggering a GI report (code: %i)\n", error);
Sleep(60000);
//IED_ERROR_TEMPORARILY_UNAVAILABLE
/* disable reporting 关闭报告控制块 */
ClientReportControlBlock_setRptEna(rcb, false);
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA, true);
if (error != IED_ERROR_OK)
printf("disable reporting failed (code: %i)\n", error);
ClientDataSet_destroy(clientDataSet);
ClientReportControlBlock_destroy(rcb);
#endif
}