|
|
|
|
/****************************************************************************
|
|
|
|
|
** 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 *)¶meter;
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
}
|