- IEC 61850 server: extended control service tracking

- IEC 61850 server: partially implemented setting group service tracking
- IEC 61850 server: partially implemented GoCB service tracking
pull/259/head
Michael Zillgith 5 years ago
parent b857e4c4ec
commit 649db2b3d6

@ -35,6 +35,22 @@
#include "libiec61850_platform_includes.h"
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
typedef enum
{
CST_NONE,
CST_SPCTRK,
CST_DPCTRK,
CST_INCTRK,
CST_ENCTRK1,
CST_APCFTRK,
CST_APCINTTRK,
CST_BSCTRK,
CST_ISCTRK,
CST_BACTRK
} ControlServiceCDC;
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
typedef struct sControlObject ControlObject;
struct sControlObject
@ -113,6 +129,11 @@ struct sControlObject
ControlWaitForExecutionHandler waitForExecutionHandler;
void* waitForExecutionHandlerParameter;
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
/* Common data class (CDC) of control object */
ControlServiceCDC cdc;
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
DataObject* dataObject;
};

@ -172,6 +172,27 @@ struct sUrcbTrkInstance
DataAttribute* gi;
};
typedef struct sGocbTrkInstance* GocbTrkInstance;
struct sGocbTrkInstance
{
/* inherited from ServiceTrkInstance */
DataObject* dobj;
DataAttribute* objRef;
DataAttribute* serviceType;
DataAttribute* errorCode;
DataAttribute* originatorID; /* optional */
DataAttribute* t;
/* GocbTrk specific attributes */
DataAttribute* goEna;
DataAttribute* goID;
DataAttribute* datSet;
DataAttribute* confRev;
DataAttribute* ndsCom;
DataAttribute* dstAddress;
};
typedef struct sControlTrkInstance* ControlTrkInstance;
struct sControlTrkInstance
@ -195,6 +216,26 @@ struct sControlTrkInstance
DataAttribute* respAddCause;
};
typedef struct sSgcbTrkInstance* SgcbTrkInstance;
struct sSgcbTrkInstance
{
/* inherited from ServiceTrkInstance */
DataObject* dobj;
DataAttribute* objRef;
DataAttribute* serviceType;
DataAttribute* errorCode;
DataAttribute* originatorID; /* optional */
DataAttribute* t;
/* SgcbTrk specific attributes */
DataAttribute* numOfSG;
DataAttribute* actSG;
DataAttribute* editSG;
DataAttribute* cnfEdit;
DataAttribute* lActTm;
};
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
struct sMmsMapping {
@ -237,11 +278,19 @@ struct sMmsMapping {
#endif
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
BrcbTrkInstance brcbTrk;
UrcbTrkInstance urcbTrk;
GocbTrkInstance gocbTrk;
ControlTrkInstance spcTrk;
ControlTrkInstance dpcTrk;
ControlTrkInstance incTrk;
ControlTrkInstance encTrk1;
ControlTrkInstance apcFTrk;
ControlTrkInstance apcIntTrk;
ControlTrkInstance bscTrk;
ControlTrkInstance iscTrk;
ControlTrkInstance bacTrk;
SgcbTrkInstance sgcbTrk;
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
/* flag indicates if data model is locked --> prevents reports to be sent */

@ -203,28 +203,43 @@ getCancelParameterTime(MmsValue* operParameters)
static void
copyControlValuesToTrackingObject(MmsMapping* self, ControlObject* controlObject, IEC61850_ServiceType serviceType)
{
//TODO determine type!
if (controlObject->ctlVal) {
ControlTrkInstance trkInst = NULL;
if (MmsValue_getType(controlObject->ctlVal) == MMS_BOOLEAN) {
//TODO handle binary controlled step position
//TODO handle binary controlled integer/analog
if (self->spcTrk) {
switch (controlObject->cdc) {
case CST_SPCTRK:
trkInst = self->spcTrk;
break;
case CST_DPCTRK:
trkInst = self->dpcTrk;
break;
case CST_INCTRK:
trkInst = self->incTrk;
break;
case CST_APCFTRK:
trkInst = self->apcFTrk;
break;
case CST_APCINTTRK:
trkInst = self->apcIntTrk;
break;
case CST_BSCTRK:
trkInst = self->bscTrk;
break;
case CST_ISCTRK:
trkInst = self->iscTrk;
break;
case CST_BACTRK:
trkInst = self->bacTrk;
break;
default:
break;
}
if (trkInst) {
if (trkInst->ctlVal)
MmsValue_update(trkInst->ctlVal->mmsValue, controlObject->ctlVal);
}
}
if (trkInst) {
if (trkInst->origin)
MmsValue_update(trkInst->origin->mmsValue, controlObject->origin);
@ -957,6 +972,97 @@ ControlObject_initialize(ControlObject* self)
MmsValue_setVisibleString(self->sbo, controlObjectReference);
}
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
/* determine CDC of control object for service tracking */
char* daName = NULL;
DataAttribute* da = NULL;
DataAttributeType ctlValType = -1;
DataAttributeType stValType = -1;
DataAttributeType mxValType = -1;
daName = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName, "/", self->lnName, ".", self->name, ".Oper.ctlVal");
da = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, daName);
if (da) {
ctlValType = da->type;
}
daName = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName, "/", self->lnName, ".", self->name, ".stVal");
da = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, daName);
if (da) {
stValType = da->type;
}
daName = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName, "/", self->lnName, ".", self->name, ".mxVal.f");
da = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, daName);
if (da) {
mxValType = da->type;
}
daName = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName, "/", self->lnName, ".", self->name, ".mxVal.i");
da = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, daName);
if (da) {
mxValType = da->type;
}
daName = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName, "/", self->lnName, ".", self->name, ".valWTr");
da = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, daName);
if (da) {
mxValType = da->type;
}
if (stValType == IEC61850_BOOLEAN && ctlValType == IEC61850_BOOLEAN)
{
self->cdc = CST_SPCTRK; /* SPC */
}
else if (stValType == IEC61850_CODEDENUM && ctlValType == IEC61850_BOOLEAN)
{
self->cdc = CST_DPCTRK; /* DPC */
}
else if (stValType == IEC61850_INT32 && ctlValType == IEC61850_INT32)
{
self->cdc = CST_INCTRK; /* INC */
}
else if (stValType == IEC61850_ENUMERATED && ctlValType == IEC61850_ENUMERATED)
{
self->cdc = CST_ENCTRK1; /* ENC */
}
else if (stValType == IEC61850_CONSTRUCTED && ctlValType == IEC61850_CODEDENUM)
{
self->cdc = CST_BSCTRK; /* BSC */
}
else if (stValType == IEC61850_CONSTRUCTED && ctlValType == IEC61850_INT8)
{
self->cdc = CST_ISCTRK; /* ISC */
}
else if ((mxValType == IEC61850_FLOAT32 || mxValType == IEC61850_FLOAT64) && (ctlValType == IEC61850_CONSTRUCTED))
{
self->cdc = CST_APCFTRK; /* APC (float) */
}
else if ((mxValType == IEC61850_INT32) && (ctlValType == IEC61850_CONSTRUCTED))
{
self->cdc = CST_APCINTTRK; /* APC (int) */
}
else if ((stValType == IEC61850_FLOAT32 || stValType == IEC61850_FLOAT64) && ctlValType == IEC61850_CODEDENUM)
{
self->cdc = CST_BACTRK; /* BAC */
}
else
{
if (DEBUG_IED_SERVER)
printf("IED_SERVER: ERROR - stValType or ctlValType could not be determined!\n");
self->cdc = CST_NONE;
}
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
char* stSeldName = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName, "/", self->lnName, ".", self->name, ".stSeld");
self->stSeld = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, stSeldName);

@ -36,6 +36,7 @@
#include "mms_goose.h"
#include "goose_publisher.h"
#include "ied_server_private.h"
struct sMmsGooseControlBlock {
char* name;
@ -73,6 +74,104 @@ struct sMmsGooseControlBlock {
char* gooseInterfaceId;
};
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
static void
copyGCBValuesToTrackingObject(MmsGooseControlBlock gc)
{
if (gc->mmsMapping->gocbTrk) {
GocbTrkInstance trkInst = gc->mmsMapping->gocbTrk;
if (trkInst->goEna)
MmsValue_setBoolean(trkInst->goEna->mmsValue, MmsGooseControlBlock_isEnabled(gc));
if (trkInst->goID)
MmsValue_setMmsString(trkInst->goID->mmsValue, gc->goId);
if (trkInst->datSet)
MmsValue_setMmsString(trkInst->datSet->mmsValue, gc->dataSet->name);
if (trkInst->confRev) {
uint32_t confRev = MmsValue_toUint32(MmsValue_getElement(gc->mmsValue, 3));
MmsValue_setUint32(trkInst->confRev->mmsValue, confRev);
}
if (trkInst->ndsCom) {
bool ndsCom = MmsValue_getBoolean(MmsValue_getElement(gc->mmsValue, 4));
MmsValue_setBoolean(trkInst->ndsCom->mmsValue, ndsCom);
}
if (trkInst->dstAddress) {
MmsValue_update(trkInst->dstAddress->mmsValue, MmsValue_getElement(gc->mmsValue, 5));
}
}
}
static IEC61850_ServiceError
convertMmsDataAccessErrorToServiceError(MmsDataAccessError mmsError)
{
IEC61850_ServiceError errVal = IEC61850_SERVICE_ERROR_NO_ERROR;
switch (mmsError) {
case DATA_ACCESS_ERROR_SUCCESS:
break;
case DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE:
errVal = IEC61850_SERVICE_ERROR_INSTANCE_LOCKED_BY_OTHER_CLIENT;
break;
case DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED:
errVal = IEC61850_SERVICE_ERROR_ACCESS_VIOLATION;
break;
case DATA_ACCESS_ERROR_TYPE_INCONSISTENT:
errVal = IEC61850_SERVICE_ERROR_PARAMETER_VALUE_INCONSISTENT;
break;
case DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT:
errVal = IEC61850_SERVICE_ERROR_INSTANCE_NOT_AVAILABLE;
break;
default:
printf("Data access error %i not mapped!\n", mmsError);
errVal = IEC61850_SERVICE_ERROR_FAILED_DUE_TO_SERVER_CONSTRAINT;
break;
}
return errVal;
}
static void
updateGenericTrackingObjectValues(MmsGooseControlBlock gc, IEC61850_ServiceType serviceType, MmsDataAccessError errVal)
{
ServiceTrkInstance trkInst = NULL;
if (gc->mmsMapping->gocbTrk) {
trkInst = (ServiceTrkInstance) gc->mmsMapping->gocbTrk;
}
if (trkInst) {
if (trkInst->serviceType)
MmsValue_setInt32(trkInst->serviceType->mmsValue, (int) serviceType);
if (trkInst->t)
MmsValue_setUtcTimeMs(trkInst->t->mmsValue, Hal_getTimeInMs());
if (trkInst->errorCode)
MmsValue_setInt32(trkInst->errorCode->mmsValue, convertMmsDataAccessErrorToServiceError(errVal));
char objRef[129];
/* create object reference */
LogicalNode* ln = (LogicalNode*) gc->logicalNode;
LogicalDevice* ld = (LogicalDevice*) ln->parent;
char* iedName = gc->mmsMapping->iedServer->mmsDevice->deviceName;
snprintf(objRef, 129, "%s%s/%s", iedName, ld->name, gc->name);
if (trkInst->objRef) {
IedServer_updateVisibleStringAttributeValue(gc->mmsMapping->iedServer, trkInst->objRef, objRef);
}
}
}
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
MmsGooseControlBlock
MmsGooseControlBlock_create()
{
@ -288,6 +387,12 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self)
}
self->goEna = true;
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS;
copyGCBValuesToTrackingObject(self);
updateGenericTrackingObjectValues(self, IEC61850_SERVICE_TYPE_SET_GOCB_VALUES, retVal);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
}
}
@ -318,6 +423,12 @@ MmsGooseControlBlock_disable(MmsGooseControlBlock self)
self->dataSetValues = NULL;
}
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS;
copyGCBValuesToTrackingObject(self);
updateGenericTrackingObjectValues(self, IEC61850_SERVICE_TYPE_SET_GOCB_VALUES, retVal);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->publisherMutex);
#endif

@ -584,6 +584,103 @@ unselectAllSettingGroups(MmsMapping* self, MmsServerConnection serverCon)
}
}
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
static void
copySGCBValuesToTrackingObject(MmsMapping* self, SettingGroupControlBlock* sgcb)
{
if (self->sgcbTrk) {
SgcbTrkInstance trkInst = self->sgcbTrk;
if (trkInst->numOfSG)
MmsValue_setUint8(trkInst->numOfSG->mmsValue, sgcb->numOfSGs);
if (trkInst->actSG)
MmsValue_setUint8(trkInst->actSG->mmsValue, sgcb->actSG);
if (trkInst->editSG)
MmsValue_setUint8(trkInst->editSG->mmsValue, sgcb->editSG);
if (trkInst->cnfEdit)
MmsValue_setBoolean(trkInst->cnfEdit->mmsValue, sgcb->cnfEdit);
if (trkInst->lActTm) {
SettingGroup* sg = getSettingGroupBySGCB(self, sgcb);
MmsValue* lActTm = MmsValue_getElement(sg->sgcbMmsValues, 4);
MmsValue_update(trkInst->lActTm->mmsValue, lActTm);
}
}
}
static IEC61850_ServiceError
convertMmsDataAccessErrorToServiceError(MmsDataAccessError mmsError)
{
IEC61850_ServiceError errVal = IEC61850_SERVICE_ERROR_NO_ERROR;
switch (mmsError) {
case DATA_ACCESS_ERROR_SUCCESS:
break;
case DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE:
errVal = IEC61850_SERVICE_ERROR_INSTANCE_LOCKED_BY_OTHER_CLIENT;
break;
case DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED:
errVal = IEC61850_SERVICE_ERROR_ACCESS_VIOLATION;
break;
case DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID:
errVal = IEC61850_SERVICE_ERROR_PARAMETER_VALUE_INAPPROPRIATE;
break;
case DATA_ACCESS_ERROR_TYPE_INCONSISTENT:
errVal = IEC61850_SERVICE_ERROR_PARAMETER_VALUE_INCONSISTENT;
break;
case DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT:
errVal = IEC61850_SERVICE_ERROR_INSTANCE_NOT_AVAILABLE;
break;
default:
printf("Data access error %i not mapped!\n", mmsError);
errVal = IEC61850_SERVICE_ERROR_FAILED_DUE_TO_SERVER_CONSTRAINT;
break;
}
return errVal;
}
static void
updateGenericTrackingObjectValues(MmsMapping* self, SettingGroupControlBlock* sgcb, IEC61850_ServiceType serviceType, MmsDataAccessError errVal)
{
ServiceTrkInstance trkInst = NULL;
if (self->sgcbTrk) {
trkInst = (ServiceTrkInstance) self->sgcbTrk;
}
if (trkInst) {
if (trkInst->serviceType)
MmsValue_setInt32(trkInst->serviceType->mmsValue, (int) serviceType);
if (trkInst->t)
MmsValue_setUtcTimeMs(trkInst->t->mmsValue, Hal_getTimeInMs());
if (trkInst->errorCode)
MmsValue_setInt32(trkInst->errorCode->mmsValue, convertMmsDataAccessErrorToServiceError(errVal));
char objRef[129];
/* create object reference */
LogicalNode* ln = (LogicalNode*) sgcb->parent;
LogicalDevice* ld = (LogicalDevice*) ln->parent;
char* iedName = self->iedServer->mmsDevice->deviceName;
snprintf(objRef, 129, "%s%s/%s.SGCB", iedName, ld->name, sgcb->parent->name);
if (trkInst->objRef) {
IedServer_updateVisibleStringAttributeValue(self->iedServer, trkInst->objRef, objRef);
}
}
}
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
void
MmsMapping_checkForSettingGroupReservationTimeouts(MmsMapping* self, uint64_t currentTime)
{
@ -699,6 +796,12 @@ MmsMapping_changeActiveSettingGroup(MmsMapping* self, SettingGroupControlBlock*
MmsValue_setUint8(actSg, sgcb->actSG);
MmsValue_setUtcTimeMs(lActTm, Hal_getTimeInMs());
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
copySGCBValuesToTrackingObject(self, sgcb);
updateGenericTrackingObjectValues(self, sgcb, IEC61850_SERVICE_TYPE_SELECT_ACTIVE_SG, DATA_ACCESS_ERROR_SUCCESS);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
}
}
}
@ -1025,6 +1128,89 @@ getUrcbTrackingAttributes(UrcbTrkInstance svcTrkInst, DataObject* trkObj)
}
}
static void
getGocbTrackingAttributes(GocbTrkInstance svcTrkInst, DataObject* trkObj)
{
ModelNode* modelNode = trkObj->firstChild;
while (modelNode) {
if (modelNode->modelType == DataAttributeModelType) {
DataAttribute* da = (DataAttribute*) modelNode;
if (!strcmp(da->name, "goEna")) {
svcTrkInst->goEna = da;
}
if (!strcmp(da->name, "goID")) {
svcTrkInst->goID = da;
}
else if (!strcmp(da->name, "datSet")) {
svcTrkInst->datSet = da;
}
else if (!strcmp(da->name, "confRev")) {
svcTrkInst->confRev = da;
}
else if (!strcmp(da->name, "ndsCom")) {
svcTrkInst->ndsCom = da;
}
else if (!strcmp(da->name, "dstAddress")) {
svcTrkInst->dstAddress = da;
}
}
modelNode = modelNode->sibling;
}
/* check if all mandatory attributes are present */
if (svcTrkInst->goEna && svcTrkInst->goID && svcTrkInst->datSet && svcTrkInst->confRev &&
svcTrkInst->ndsCom && svcTrkInst->dstAddress) {
}
else {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: required attribute missing in gocbTrk service tracking object %s\n",trkObj->name);
}
}
static void
getSgcbTrackingAttributes(SgcbTrkInstance svcTrkInst, DataObject* trkObj)
{
ModelNode* modelNode = trkObj->firstChild;
while (modelNode) {
if (modelNode->modelType == DataAttributeModelType) {
DataAttribute* da = (DataAttribute*) modelNode;
if (!strcmp(da->name, "numOfSG")) {
svcTrkInst->numOfSG = da;
}
if (!strcmp(da->name, "actSG")) {
svcTrkInst->actSG = da;
}
else if (!strcmp(da->name, "editSG")) {
svcTrkInst->editSG = da;
}
else if (!strcmp(da->name, "cnfEdit")) {
svcTrkInst->cnfEdit = da;
}
else if (!strcmp(da->name, "lActTm")) {
svcTrkInst->lActTm = da;
}
}
modelNode = modelNode->sibling;
}
/* check if all mandatory attributes are present */
if (svcTrkInst->numOfSG && svcTrkInst->actSG && svcTrkInst->editSG && svcTrkInst->cnfEdit &&
svcTrkInst->lActTm) {
}
else {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: required attribute missing in sgcbTrk service tracking object %s\n",trkObj->name);
}
}
static void
getControlTrackingAttributes(ControlTrkInstance svcTrkInst, DataObject* trkObj)
{
@ -1071,24 +1257,49 @@ checkForServiceTrackingVariables(MmsMapping* self, LogicalNode* logicalNode)
while (modelNode) {
if (!strcmp(modelNode->name, "SpcTrk")) {
if (!strcmp(modelNode->name, "SpcTrk") || !strcmp(modelNode->name, "DpcTrk") ||
!strcmp(modelNode->name, "IncTrk") || !strcmp(modelNode->name, "EncTrk1") ||
!strcmp(modelNode->name, "ApcFTrk") || !strcmp(modelNode->name, "ApcIntTrk") ||
!strcmp(modelNode->name, "BscTrk") || !strcmp(modelNode->name, "IscTrk") ||
!strcmp(modelNode->name, "BacIntTrk"))
{
if (DEBUG_IED_SERVER)
printf("SpcTrk data object found!\n");
DataObject* spcTrk = (DataObject*) modelNode;
if (self->spcTrk) {
printf("%s data object found!\n", modelNode->name);
DataObject* actTrk = (DataObject*) modelNode;
ControlTrkInstance* actInstance = NULL;
if (!strcmp(modelNode->name, "SpcTrk"))
actInstance = &self->spcTrk;
else if (!strcmp(modelNode->name, "DpcTrk"))
actInstance = &self->spcTrk;
else if (!strcmp(modelNode->name, "IncTrk"))
actInstance = &self->incTrk;
else if (!strcmp(modelNode->name, "EncTrk1"))
actInstance = &self->encTrk1;
else if (!strcmp(modelNode->name, "ApcFTrk"))
actInstance = &self->apcFTrk;
else if (!strcmp(modelNode->name, "ApcIntTrk"))
actInstance = &self->apcIntTrk;
else if (!strcmp(modelNode->name, "BscTrk"))
actInstance = &self->bscTrk;
else if (!strcmp(modelNode->name, "IscTrk"))
actInstance = &self->iscTrk;
else if (!strcmp(modelNode->name, "BacTrk"))
actInstance = &self->bacTrk;
if (*actInstance != NULL) {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: ERROR: multiple SpcTrk instances found in server\n");
printf("IED_SERVER: ERROR: multiple %s instances found in server\n", modelNode->name);
}
else {
self->spcTrk = (ControlTrkInstance) GLOBAL_CALLOC(1, sizeof(struct sControlTrkInstance));
*actInstance = (ControlTrkInstance) GLOBAL_CALLOC(1, sizeof(struct sControlTrkInstance));
if (self->spcTrk) {
self->spcTrk->dobj = spcTrk;
if (*actInstance != NULL) {
(*actInstance)->dobj = actTrk;
getCommonTrackingAttributes((ServiceTrkInstance) self->spcTrk, spcTrk);
getControlTrackingAttributes(self->spcTrk, spcTrk);
getCommonTrackingAttributes((ServiceTrkInstance) *actInstance, actTrk);
getControlTrackingAttributes(*actInstance, actTrk);
}
}
@ -1128,7 +1339,7 @@ checkForServiceTrackingVariables(MmsMapping* self, LogicalNode* logicalNode)
printf("IED_SERVER: ERROR: multiple UrcbTrk instances found in server\n");
}
else {
/* Setup BrcbTrk references */
/* Setup UrcbTrk references */
self->urcbTrk = (UrcbTrkInstance) GLOBAL_CALLOC(1, sizeof(struct sUrcbTrkInstance));
if (self->urcbTrk) {
@ -1140,7 +1351,52 @@ checkForServiceTrackingVariables(MmsMapping* self, LogicalNode* logicalNode)
}
}
else if (!strcmp(modelNode->name, "GocbTrk")) {
if (DEBUG_IED_SERVER)
printf("GocbTrk data object found!\n");
DataObject* gocbTrk = (DataObject*) modelNode;
if (self->gocbTrk) {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: ERROR: multiple GocbTrk instances found in server\n");
}
else {
/* Setup GocbTrk references */
self->gocbTrk = (GocbTrkInstance) GLOBAL_CALLOC(1, sizeof(struct sGocbTrkInstance));
if (self->gocbTrk) {
self->gocbTrk->dobj = gocbTrk;
getCommonTrackingAttributes((ServiceTrkInstance) self->gocbTrk, gocbTrk);
getGocbTrackingAttributes(self->gocbTrk, gocbTrk);
}
}
}
else if (!strcmp(modelNode->name, "SgcbTrk")) {
if (DEBUG_IED_SERVER)
printf("SgcbTrk data object found!\n");
DataObject* sgcbTrk = (DataObject*) modelNode;
if (self->sgcbTrk) {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: ERROR: multiple SgcbTrk instances found in server\n");
}
else {
/* Setup SgcbTrk references */
self->sgcbTrk = (SgcbTrkInstance) GLOBAL_CALLOC(1, sizeof(struct sSgcbTrkInstance));
if (self->sgcbTrk) {
self->sgcbTrk->dobj = sgcbTrk;
getCommonTrackingAttributes((ServiceTrkInstance) self->sgcbTrk, sgcbTrk);
getSgcbTrackingAttributes(self->sgcbTrk, sgcbTrk);
}
}
}
modelNode = modelNode->sibling;
}
@ -2225,6 +2481,7 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
if (strcmp(nameId, "ActSG") == 0) {
SettingGroup* sg = getSettingGroupByMmsDomain(self, domain);
MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS;
if (sg != NULL) {
uint32_t val = MmsValue_toUint32(value);
@ -2246,33 +2503,38 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
}
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
return DATA_ACCESS_ERROR_SUCCESS;
}
else
return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
}
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
copySGCBValuesToTrackingObject(self, sg->sgcb);
updateGenericTrackingObjectValues(self, sg->sgcb, IEC61850_SERVICE_TYPE_SELECT_ACTIVE_SG, retVal);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
return retVal;
}
else if (strcmp(nameId, "EditSG") == 0) {
SettingGroup* sg = getSettingGroupByMmsDomain(self, domain);
MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS;
if (sg != NULL) {
uint32_t val = MmsValue_toUint32(value);
if ((sg->editingClient != NULL) && ( sg->editingClient != (ClientConnection) connection))
if ((sg->editingClient != NULL) && ( sg->editingClient != (ClientConnection) connection)) {
/* Edit SG was set by other client */
return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
}
else {
if (val == 0) {
unselectEditSettingGroup(sg);
return DATA_ACCESS_ERROR_SUCCESS;
retVal = DATA_ACCESS_ERROR_SUCCESS;
}
else {
if ((val > 0) && (val <= sg->sgcb->numOfSGs)) {
@ -2292,22 +2554,35 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
MmsValue_setUint16(resvTms, sg->sgcb->resvTms);
MmsValue_setUint8(editSg, sg->sgcb->editSG);
return DATA_ACCESS_ERROR_SUCCESS;
retVal = DATA_ACCESS_ERROR_SUCCESS;
}
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
else
return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
}
}
}
else {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
}
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
copySGCBValuesToTrackingObject(self, sg->sgcb);
updateGenericTrackingObjectValues(self, sg->sgcb, IEC61850_SERVICE_TYPE_SELECT_EDIT_SG, retVal);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
return retVal;
}
else if (strcmp(nameId, "CnfEdit") == 0) {
SettingGroup* sg = getSettingGroupByMmsDomain(self, domain);
MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS;
if (sg != NULL) {
bool val = MmsValue_getBoolean(value);
@ -2321,20 +2596,29 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
unselectEditSettingGroup(sg);
return DATA_ACCESS_ERROR_SUCCESS;
retVal = DATA_ACCESS_ERROR_SUCCESS;
}
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
else
return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
}
else {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
}
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
copySGCBValuesToTrackingObject(self, sg->sgcb);
updateGenericTrackingObjectValues(self, sg->sgcb, IEC61850_SERVICE_TYPE_CONFIRM_EDIT_SG_VALUES, retVal);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
return retVal;
}
}

Loading…
Cancel
Save