- added IedServer_RCBEventHandler

pull/374/head
Michael Zillgith 4 years ago
parent d5ec52ef78
commit 88148f39ac

@ -3,7 +3,7 @@
*
* IEC 61850 server API for libiec61850.
*
* Copyright 2013-2020 Michael Zillgith
* Copyright 2013-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -1534,6 +1534,42 @@ IedServer_updateCtlModel(IedServer self, DataObject* ctlObject, ControlModel val
/**@}*/
/**
* @defgroup IEC61850_SERVER_RCB Server side report control block (RCB) handling
*
* @{
*/
typedef enum {
RCB_EVENT_GET_PARAMETER, /* << parameter read by client (not implemented) */
RCB_EVENT_SET_PARAMETER, /* << parameter set by client */
RCB_EVENT_UNRESERVED, /* << RCB reservation canceled */
RCB_EVENT_RESERVED, /* << RCB reserved */
RCB_EVENT_ENABLE, /* << RCB enabled */
RCB_EVENT_DISABLE, /* << RCB disabled */
RCB_EVENT_GI, /* << GI report triggered */
RCB_EVENT_PURGEBUF /* << Purge buffer procedure executed */
} IedServer_RCBEventType;
/**
* \brief Callback that is called in case of RCB event
*
* \param parameter user provided paramter
*/
typedef void (*IedServer_RCBEventHandler) (void* parameter, ReportControlBlock* rcb, ClientConnection connection, IedServer_RCBEventType event, const char* parameterName, MmsDataAccessError serviceError);
/**
* \brief Set a handler for report control block (RCB) events
*
* \param self the instance of IedServer to operate on.
* \param handler the event handler to be used
* \param parameter a user provided parameter that is passed to the handler.
*/
LIB61850_API void
IedServer_setRCBEventHandler(IedServer self, IedServer_RCBEventHandler handler, void* parameter);
/**@}*/
/**
* @defgroup IEC61850_SERVER_SVCB Server side sampled values control block (SVCB) handling
*

@ -1,7 +1,7 @@
/*
* mms_mapping_internal.h
*
* Copyright 2013-2020 Michael Zillgith
* Copyright 2013-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -328,6 +328,9 @@ struct sMmsMapping {
IedConnectionIndicationHandler connectionIndicationHandler;
void* connectionIndicationHandlerParameter;
IedServer_RCBEventHandler rcbEventHandler;
void* rcbEventHandlerParameter;
};
#endif /* MMS_MAPPING_INTERNAL_H_ */

@ -584,6 +584,13 @@ IedServer_createWithTlsSupport(IedModel* dataModel, TLSConfiguration tlsConfigur
return IedServer_createWithConfig(dataModel, tlsConfiguration, NULL);
}
void
IedServer_setRCBEventHandler(IedServer self, IedServer_RCBEventHandler handler, void* parameter)
{
self->mmsMapping->rcbEventHandler = handler;
self->mmsMapping->rcbEventHandlerParameter = parameter;
}
void
IedServer_destroy(IedServer self)
{

@ -1,7 +1,7 @@
/*
* reporting.c
*
* Copyright 2013-2020 Michael Zillgith
* Copyright 2013-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -1675,6 +1675,8 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
bool resvTmsAccess = false; /* access is to RecvTms or Resv */
bool dontUpdate = false;
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
/* check reservation timeout for buffered RCBs */
if (rc->buffered) {
@ -1713,6 +1715,10 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
rc->reserved = true;
rc->clientConnection = connection;
rc->reservationTimeout = Hal_getTimeInMs() + (rc->resvTms * 1000);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_RESERVED, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
else {
if (DEBUG_IED_SERVER)
@ -1735,6 +1741,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (rc->reserved == false) {
if ((strcmp(elementName, "Resv")) && (strcmp(elementName, "ResvTms"))) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
}
@ -1742,6 +1749,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if ((rc->reserved) && (rc->clientConnection != connection)) {
retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
goto exit_function;
}
@ -1764,6 +1772,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (rc->enabled == true) {
retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
goto exit_function;
}
@ -1803,6 +1812,11 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
MmsValue_setUint32(sqNum, 0U);
retVal = DATA_ACCESS_ERROR_SUCCESS;
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_ENABLE, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
goto exit_function;
}
else {
@ -1816,6 +1830,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (((rc->enabled) || (rc->reserved)) && (rc->clientConnection != connection)) {
retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
goto exit_function;
}
@ -1833,6 +1848,14 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
/* clear report buffer */
purgeBuf(rc);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_GI, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_DISABLE, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
rc->enabled = false;
@ -1849,10 +1872,16 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
}
retVal = DATA_ACCESS_ERROR_SUCCESS;
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_GI, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
goto exit_function;
}
else {
retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
goto exit_function;
}
}
@ -1861,6 +1890,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if ((rc->reserved) && (rc->clientConnection != connection)) {
retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
goto exit_function;
}
@ -1870,6 +1900,11 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
rc->reserved = value->value.boolean;
if (rc->reserved == true) {
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_RESERVED, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
updateOwner(rc, connection);
rc->clientConnection = connection;
}
@ -1888,6 +1923,11 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (MmsValue_getBoolean(value) == true) {
purgeBuf(rc);
retVal = DATA_ACCESS_ERROR_SUCCESS;
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_PURGEBUF, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
goto exit_function;
}
}
@ -1900,15 +1940,21 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (updateReportDataset(self, rc, value, connection)) {
if (rc->buffered)
if (rc->buffered) {
purgeBuf(rc);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_PURGEBUF, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
MmsValue_update(datSet, value);
increaseConfRev(rc);
}
else {
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
goto exit_function;
}
}
@ -1927,6 +1973,10 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (rc->buffered) {
rc->nextIntgReportTime = 0;
purgeBuf(rc);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_PURGEBUF, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
}
@ -1938,9 +1988,14 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (!MmsValue_equals(trgOps, value)) {
MmsValue_update(trgOps, value);
if (rc->buffered)
if (rc->buffered) {
purgeBuf(rc);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_PURGEBUF, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
refreshTriggerOptions(rc);
}
@ -1949,7 +2004,9 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
else if (strcmp(elementName, "EntryID") == 0) {
if (MmsValue_getOctetStringSize(value) != 8) {
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
goto exit_function;
}
@ -1957,7 +2014,9 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (!checkReportBufferForEntryID(rc, value)) {
rc->reportBuffer->isOverflow = true;
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
goto exit_function;
}
@ -1981,9 +2040,14 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (!MmsValue_equals(bufTm, value)) {
MmsValue_update(bufTm, value);
if (rc->buffered)
if (rc->buffered) {
purgeBuf(rc);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_PURGEBUF, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
refreshBufferTime(rc);
}
@ -1995,8 +2059,13 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (!MmsValue_equals(rptId, value)) {
MmsValue_update(rptId, value);
if (rc->buffered)
if (rc->buffered) {
purgeBuf(rc);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_PURGEBUF, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
}
goto exit_function;
@ -2017,11 +2086,19 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
rc->reservationTimeout = 0;
rc->reserved = false;
updateOwner(rc, NULL);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_UNRESERVED, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
else {
rc->reservationTimeout = Hal_getTimeInMs() + (rc->resvTms * 1000);
reserveRcb(rc, connection);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_RESERVED, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
MmsValue* resvTmsVal = ReportControl_getRCBValue(rc, "ResvTms");
@ -2029,18 +2106,22 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (resvTmsVal != NULL)
MmsValue_update(resvTmsVal, value);
}
else
else {
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
}
}
else {
if (self->iedServer->edition < IEC_61850_EDITION_2_1) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
else {
rc->reservationTimeout = Hal_getTimeInMs() + (RESV_TMS_IMPLICIT_VALUE * 1000);
reserveRcb(rc, connection);
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_RESERVED, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
}
}
@ -2049,18 +2130,22 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
}
else if (strcmp(elementName, "ConfRev") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
else if (strcmp(elementName, "SqNum") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
else if (strcmp(elementName, "Owner") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
else if (strcmp(elementName, "TimeofEntry") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
@ -2073,6 +2158,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
}
else {
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
goto exit_function;
}
@ -2118,6 +2204,10 @@ exit_function:
updateGenericTrackingObjectValues(self, rc, IEC61850_SERVICE_TYPE_SET_URCB_VALUES, retVal);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
if (self->rcbEventHandler) {
self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_SET_PARAMETER, elementName, retVal);
}
return retVal;
}

Loading…
Cancel
Save