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++

1 year ago
/****************************************************************************
** 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());
1 year ago
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);
1 year ago
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);
1 year ago
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");
1 year ago
// 解析录播文件并入库
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);
1 year ago
}
stIedHandle.tIedModel = NULL;
1 year ago
}
// 根据icd节点名称获取传感器绑定关系
bool bGetDeviceBindRelationship(char *pNodeName, ST_DB_BODY &pDb, ST_DEVICE_INFO &stBaseInfo)
{
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 1.");
1 year ago
map<string, ST_PARAM_BIND>::iterator m_pIter;
//mutex_lock(g_map_parambind_mutex);
1 year ago
m_pIter = g_map_parambind.find((char*)pNodeName);
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 2.");
1 year ago
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);
1 year ago
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);
//}
1 year ago
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());
1 year ago
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.");
1 year ago
memcpy(&stBaseInfo, &(*m_pTIter).second, sizeof(ST_DEVICE_INFO));
//mutex_unlock(g_map_device_mutex);
vPrtLogMsg(LOG_WARNG, 0, "rensichao add list 6.");
1 year ago
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);
1 year ago
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))
1 year ago
fc = IEC61850_FC_ST;
else if(!stringncasecmp((const char*)stBind.nodetype, "SE", 2))
1 year ago
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);
1 year ago
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));
1 year ago
}
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");
1 year ago
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);
1 year ago
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));
1 year ago
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; // 取振幅值
}
1 year ago
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);
1 year ago
Add_SetList(&stBody,&stBase);
vPrtLogMsg(LOG_WARNG, 0, "rensichao read add list end[%s] \n", stBind.nodetype);
1 year ago
// 预警判断
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
}