- IedConnection: code format updates

v1.6
Michael Zillgith 4 weeks ago
parent 9b467fa60d
commit 8a4b7bb616

@ -1,7 +1,7 @@
/*
* client_control.c
*
* Copyright 2013-2021 Michael Zillgith
* Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -221,7 +221,8 @@ ControlObjectClient_create(const char* objectReference, IedConnection connection
/* request control model from server */
char reference[129];
if (strlen(objectReference) < 120) {
if (strlen(objectReference) < 120)
{
StringUtils_concatString(reference, 129, objectReference, ".ctlModel");
}
else
@ -261,19 +262,19 @@ exit_function:
void
ControlObjectClient_destroy(ControlObjectClient self)
{
if (self != NULL)
if (self)
{
GLOBAL_FREEMEM(self->objectReference);
iedConnection_removeControlClient(self->connection, self);
if (self->ctlVal != NULL)
if (self->ctlVal)
MmsValue_delete(self->ctlVal);
if (self->analogValue != NULL)
if (self->analogValue)
MmsValue_delete(self->analogValue);
if (self->orIdent != NULL)
if (self->orIdent)
GLOBAL_FREEMEM(self->orIdent);
GLOBAL_FREEMEM(self);
@ -316,7 +317,7 @@ ControlObjectClient_changeServerControlModel(ControlObjectClient self, ControlMo
MmsType
ControlObjectClient_getCtlValType(ControlObjectClient self)
{
if (self->analogValue != NULL)
if (self->analogValue)
return MmsValue_getType(self->analogValue);
else
return MmsValue_getType(self->ctlVal);
@ -334,10 +335,10 @@ ControlObjectClient_getLastError(ControlObjectClient self)
void
ControlObjectClient_setOrigin(ControlObjectClient self, const char* orIdent, int orCat)
{
if (self->orIdent != NULL)
if (self->orIdent)
GLOBAL_FREEMEM(self->orIdent);
if (orIdent != NULL)
if (orIdent)
self->orIdent = StringUtils_copyString(orIdent);
else
self->orIdent = NULL;
@ -596,14 +597,16 @@ ControlObjectClient_operateAsync(ControlObjectClient self, IedClientError* err,
*err = IED_ERROR_OK;
uint32_t invokeId = 0;
if (ctlVal == NULL) {
if (ctlVal == NULL)
{
*err = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT;
goto exit_function;
}
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self->connection);
if (call == NULL) {
if (call == NULL)
{
*err = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
goto exit_function;
}
@ -636,10 +639,12 @@ ControlObjectClient_operateAsync(ControlObjectClient self, IedClientError* err,
*err = iedConnection_mapMmsErrorToIedError(mmsError);
if (mmsError != MMS_ERROR_NONE) {
if (mmsError != MMS_ERROR_NONE)
{
iedConnection_releaseOutstandingCall(self->connection, call);
}
else {
else
{
MmsValue_update(self->ctlVal, ctlVal);
self->opertime = operTime;
@ -667,8 +672,10 @@ prepareSBOwParameters(ControlObjectClient self, MmsValue* ctlVal)
MmsValue* selValParameters = MmsValue_createEmptyStructure(selValElementCount);
/* support simplified usage of APC controls - user doesn't need to create the structure */
if (self->analogValue != NULL) {
if (MmsValue_getType(ctlVal) != MMS_STRUCTURE) {
if (self->analogValue)
{
if (MmsValue_getType(ctlVal) != MMS_STRUCTURE)
{
MmsValue_setElement(self->analogValue, 0, ctlVal);
ctlVal = self->analogValue;
}
@ -678,7 +685,8 @@ prepareSBOwParameters(ControlObjectClient self, MmsValue* ctlVal)
int index = 1;
if (self->hasTimeActivatedMode) {
if (self->hasTimeActivatedMode)
{
MmsValue* operTm = MmsValue_newUtcTimeByMsTime(0);
MmsValue_setElement(selValParameters, index++, operTm);
}
@ -688,7 +696,8 @@ prepareSBOwParameters(ControlObjectClient self, MmsValue* ctlVal)
self->ctlNum++;
if (self->hasCtlNum) {
if (self->hasCtlNum)
{
MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum);
MmsValue_setElement(selValParameters, index++, ctlNum);
}
@ -699,13 +708,15 @@ prepareSBOwParameters(ControlObjectClient self, MmsValue* ctlVal)
if (self->useConstantT)
self->constantT = timestamp;
if (self->edition == 2) {
if (self->edition == 2)
{
ctlTime = MmsValue_newUtcTimeByMsTime(timestamp);
if (self->connection)
MmsValue_setUtcTimeQuality(ctlTime, self->connection->timeQuality);
}
else {
else
{
ctlTime = MmsValue_newBinaryTime(false);
MmsValue_setBinaryTime(ctlTime, timestamp);
}
@ -763,7 +774,8 @@ ControlObjectClient_selectWithValue(ControlObjectClient self, MmsValue* ctlVal)
self->lastMmsError = mmsError;
self->lastAccessError = writeResult;
if (mmsError != MMS_ERROR_NONE) {
if (mmsError != MMS_ERROR_NONE)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select-with-value failed!\n");
@ -771,8 +783,10 @@ ControlObjectClient_selectWithValue(ControlObjectClient self, MmsValue* ctlVal)
goto exit_function;
}
else {
if (writeResult != DATA_ACCESS_ERROR_SUCCESS) {
else
{
if (writeResult != DATA_ACCESS_ERROR_SUCCESS)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select-with-value failed!\n");
@ -799,8 +813,8 @@ internalSelWithValHandler(uint32_t invokeId, void* parameter, MmsError err, MmsD
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self->connection, invokeId);
if (call) {
if (call)
{
ControlObjectClient_ControlActionHandler handler = (ControlObjectClient_ControlActionHandler)call->callback;
IedClientError iedError = iedConnection_mapMmsErrorToIedError(err);
@ -810,18 +824,21 @@ internalSelWithValHandler(uint32_t invokeId, void* parameter, MmsError err, MmsD
self->lastMmsError = err;
self->lastAccessError = accessError;
if (iedError == IED_ERROR_OK) {
if (iedError == IED_ERROR_OK)
{
iedError = iedConnection_mapDataAccessErrorToIedError(accessError);
if (iedError == IED_ERROR_OK)
success = true;
}
if (success) {
if (success)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select-with-value+\n");
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select-with-value failed!\n");
}
@ -830,7 +847,8 @@ internalSelWithValHandler(uint32_t invokeId, void* parameter, MmsError err, MmsD
iedConnection_releaseOutstandingCall(self->connection, call);
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@ -843,14 +861,16 @@ ControlObjectClient_selectWithValueAsync(ControlObjectClient self, IedClientErro
*err = IED_ERROR_OK;
uint32_t invokeId = 0;
if (ctlVal == NULL) {
if (ctlVal == NULL)
{
*err = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT;
goto exit_function;
}
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self->connection);
if (call == NULL) {
if (call == NULL)
{
*err = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
goto exit_function;
}
@ -876,7 +896,8 @@ ControlObjectClient_selectWithValueAsync(ControlObjectClient self, IedClientErro
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select with value: %s/%s\n", domainId, itemId);
MmsConnection_writeVariableAsync(self->connection->connection, &(call->invokeId), &mmsError, domainId, itemId, selValParameters, internalSelWithValHandler, self);
MmsConnection_writeVariableAsync(self->connection->connection, &(call->invokeId), &mmsError, domainId, itemId,
selValParameters, internalSelWithValHandler, self);
invokeId = call->invokeId;
@ -885,10 +906,12 @@ ControlObjectClient_selectWithValueAsync(ControlObjectClient self, IedClientErro
*err = iedConnection_mapMmsErrorToIedError(mmsError);
if (mmsError != MMS_ERROR_NONE) {
if (mmsError != MMS_ERROR_NONE)
{
iedConnection_releaseOutstandingCall(self->connection, call);
}
else {
else
{
MmsValue_update(self->ctlVal, ctlVal);
}
@ -919,8 +942,8 @@ ControlObjectClient_select(ControlObjectClient self)
MmsError mmsError;
MmsValue* value = MmsConnection_readVariable(IedConnection_getMmsConnection(self->connection),
&mmsError, domainId, itemId);
MmsValue* value =
MmsConnection_readVariable(IedConnection_getMmsConnection(self->connection), &mmsError, domainId, itemId);
bool selected = false;
@ -929,30 +952,36 @@ ControlObjectClient_select(ControlObjectClient self)
self->lastMmsError = mmsError;
self->lastAccessError = DATA_ACCESS_ERROR_SUCCESS;
if (value == NULL) {
if (value == NULL)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select: read SBO failed!\n");
goto exit_function;
}
if (MmsValue_getType(value) == MMS_VISIBLE_STRING) {
if (strcmp(MmsValue_toString(value), "") == 0) {
if (MmsValue_getType(value) == MMS_VISIBLE_STRING)
{
if (strcmp(MmsValue_toString(value), "") == 0)
{
if (DEBUG_IED_CLIENT)
printf("select-response-\n");
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("select-response+: (%s)\n", MmsValue_toString(value));
selected = true;
}
}
else if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) {
else if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
{
self->lastAccessError = MmsValue_getDataAccessError(value);
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select returned data-access-error: %i\n", self->lastAccessError);
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select: unexpected response from server!\n");
}
@ -970,8 +999,8 @@ internalSelectHandler(uint32_t invokeId, void* parameter, MmsError err, MmsValue
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self->connection, invokeId);
if (call) {
if (call)
{
ControlObjectClient_ControlActionHandler handler = (ControlObjectClient_ControlActionHandler) call->callback;
IedClientError iedError = iedConnection_mapMmsErrorToIedError(err);
@ -983,15 +1012,16 @@ internalSelectHandler(uint32_t invokeId, void* parameter, MmsError err, MmsValue
self->ctlNum++;
if (iedError == IED_ERROR_OK) {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) {
if (iedError == IED_ERROR_OK)
{
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
{
MmsDataAccessError dataAccessError = MmsValue_getDataAccessError(value);
self->lastAccessError = dataAccessError;
iedError = iedConnection_mapDataAccessErrorToIedError(dataAccessError);
}
else if (MmsValue_getType(value) == MMS_VISIBLE_STRING) {
else if (MmsValue_getType(value) == MMS_VISIBLE_STRING)
{
char domainId[65];
char itemId[65];
@ -1001,17 +1031,20 @@ internalSelectHandler(uint32_t invokeId, void* parameter, MmsError err, MmsValue
StringUtils_appendString(itemId, 65, "$SBO");
if (strcmp(MmsValue_toString(value), "") == 0) {
if (strcmp(MmsValue_toString(value), "") == 0)
{
if (DEBUG_IED_CLIENT)
printf("select-response-\n");
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("select-response+: (%s)\n", MmsValue_toString(value));
success = true;
}
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select: unexpected response from server!\n");
}
@ -1021,7 +1054,8 @@ internalSelectHandler(uint32_t invokeId, void* parameter, MmsError err, MmsValue
iedConnection_releaseOutstandingCall(self->connection, call);
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@ -1048,7 +1082,8 @@ ControlObjectClient_selectAsync(ControlObjectClient self, IedClientError* err, C
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self->connection);
if (call == NULL) {
if (call == NULL)
{
*err = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@ -1068,7 +1103,8 @@ ControlObjectClient_selectAsync(ControlObjectClient self, IedClientError* err, C
*err = iedConnection_mapMmsErrorToIedError(mmsError);
if (mmsError != MMS_ERROR_NONE) {
if (mmsError != MMS_ERROR_NONE)
{
iedConnection_releaseOutstandingCall(self->connection, call);
}
@ -1089,7 +1125,8 @@ createCancelParameters(ControlObjectClient self)
int index = 1;
if (self->hasTimeActivatedMode) {
if (self->hasTimeActivatedMode)
{
MmsValue* operTm = MmsValue_newUtcTimeByMsTime(self->opertime);
MmsValue_setElement(cancelParameters, index++, operTm);
}
@ -1110,13 +1147,15 @@ createCancelParameters(ControlObjectClient self)
MmsValue* ctlTime;
if (self->edition == 2) {
if (self->edition == 2)
{
ctlTime = MmsValue_newUtcTimeByMsTime(timestamp);
if (self->connection)
MmsValue_setUtcTimeQuality(ctlTime, self->connection->timeQuality);
}
else {
else
{
ctlTime = MmsValue_newBinaryTime(false);
MmsValue_setBinaryTime(ctlTime, timestamp);
}
@ -1158,13 +1197,16 @@ ControlObjectClient_cancel(ControlObjectClient self)
MmsValue_setElement(cancelParameters, 0, NULL);
MmsValue_delete(cancelParameters);
if (mmsError != MMS_ERROR_NONE) {
if (mmsError != MMS_ERROR_NONE)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: cancel failed!\n");
return false;
}
else {
if (writeResult != DATA_ACCESS_ERROR_SUCCESS) {
else
{
if (writeResult != DATA_ACCESS_ERROR_SUCCESS)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: cancel failed!\n");
return false;
@ -1181,8 +1223,8 @@ internalCancelHandler(uint32_t invokeId, void* parameter, MmsError err, MmsDataA
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self->connection, invokeId);
if (call) {
if (call)
{
ControlObjectClient_ControlActionHandler handler = (ControlObjectClient_ControlActionHandler)call->callback;
IedClientError iedError = iedConnection_mapMmsErrorToIedError(err);
@ -1192,18 +1234,21 @@ internalCancelHandler(uint32_t invokeId, void* parameter, MmsError err, MmsDataA
self->lastMmsError = err;
self->lastAccessError = accessError;
if (iedError == IED_ERROR_OK) {
if (iedError == IED_ERROR_OK)
{
iedError = iedConnection_mapDataAccessErrorToIedError(accessError);
if (iedError == IED_ERROR_OK)
success = true;
}
if (success) {
if (success)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: cancel+\n");
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: cancel failed!\n");
}
@ -1212,21 +1257,24 @@ internalCancelHandler(uint32_t invokeId, void* parameter, MmsError err, MmsDataA
iedConnection_releaseOutstandingCall(self->connection, call);
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
}
uint32_t
ControlObjectClient_cancelAsync(ControlObjectClient self, IedClientError* err, ControlObjectClient_ControlActionHandler handler, void* parameter)
ControlObjectClient_cancelAsync(ControlObjectClient self, IedClientError* err,
ControlObjectClient_ControlActionHandler handler, void* parameter)
{
*err = IED_ERROR_OK;
uint32_t invokeId = 0;
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self->connection);
if (call == NULL) {
if (call == NULL)
{
*err = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
goto exit_function;
}
@ -1252,7 +1300,8 @@ ControlObjectClient_cancelAsync(ControlObjectClient self, IedClientError* err, C
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select with value: %s/%s\n", domainId, itemId);
MmsConnection_writeVariableAsync(self->connection->connection, &(call->invokeId), &mmsError, domainId, itemId, cancelParameters, internalCancelHandler, self);
MmsConnection_writeVariableAsync(self->connection->connection, &(call->invokeId), &mmsError, domainId, itemId,
cancelParameters, internalCancelHandler, self);
invokeId = call->invokeId;
@ -1261,7 +1310,8 @@ ControlObjectClient_cancelAsync(ControlObjectClient self, IedClientError* err, C
*err = iedConnection_mapMmsErrorToIedError(mmsError);
if (mmsError != MMS_ERROR_NONE) {
if (mmsError != MMS_ERROR_NONE)
{
iedConnection_releaseOutstandingCall(self->connection, call);
}
@ -1326,6 +1376,6 @@ ControlObjectClient_setCtlNum(ControlObjectClient self, uint8_t ctlNum)
void
controlObjectClient_invokeCommandTerminationHandler(ControlObjectClient self)
{
if (self->commandTerminationHandler != NULL)
if (self->commandTerminationHandler)
self->commandTerminationHandler(self->commandTerminaionHandlerParameter, self);
}

@ -3,7 +3,7 @@
*
* Implementation of the ClientReportControlBlock class
*
* Copyright 2014-2024 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -1145,6 +1145,12 @@ IedConnection_setGoCBValuesAsync(IedConnection self, IedClientError* error, Clie
{
struct sWriteGoCBVariablesParameter* param = (struct sWriteGoCBVariablesParameter*) GLOBAL_MALLOC(sizeof(struct sWriteGoCBVariablesParameter));
if (param == NULL)
{
*error = IED_ERROR_UNKNOWN;
goto exit_function;
}
call->specificParameter2.pointer = param;
param->itemIds = itemIds;

@ -3,7 +3,7 @@
*
* Client implementation for IEC 61850 reporting.
*
* Copyright 2013-2024 Michael Zillgith
* Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -93,36 +93,42 @@ ClientReport_create()
{
ClientReport self = (ClientReport) GLOBAL_CALLOC(1, sizeof(struct sClientReport));
if (self)
{
self->dataSetSize = -1;
}
return self;
}
void
ClientReport_destroy(ClientReport self)
{
if (self)
{
if (self->entryId)
MmsValue_delete(self->entryId);
GLOBAL_FREEMEM(self->rcbReference);
if (self->rptId != NULL)
if (self->rptId)
GLOBAL_FREEMEM(self->rptId);
if (self->dataSetValues != NULL)
if (self->dataSetValues)
MmsValue_delete(self->dataSetValues);
if (self->dataReferences != NULL)
if (self->dataReferences)
MmsValue_delete(self->dataReferences);
if (self->reasonForInclusion != NULL)
if (self->reasonForInclusion)
GLOBAL_FREEMEM(self->reasonForInclusion);
if (self->dataSetName != NULL)
if (self->dataSetName)
GLOBAL_FREEMEM((void*) self->dataSetName);
GLOBAL_FREEMEM(self);
}
}
char*
ClientReport_getRcbReference(ClientReport self)
@ -163,7 +169,6 @@ ClientReport_getTimestamp(ClientReport self)
return self->timestamp;
}
bool
ClientReport_hasSeqNum(ClientReport self)
{
@ -223,11 +228,14 @@ ClientReport_getDataReference(ClientReport self, int elementIndex)
{
char* dataReference = NULL;
if (self->dataReferences != NULL) {
if (self->dataReferences)
{
MmsValue* dataRefValue = MmsValue_getElement(self->dataReferences, elementIndex);
if (dataRefValue != NULL) {
if (MmsValue_getType(dataRefValue) == MMS_VISIBLE_STRING) {
if (dataRefValue)
{
if (MmsValue_getType(dataRefValue) == MMS_VISIBLE_STRING)
{
return MmsValue_toString(dataRefValue);
}
}
@ -271,7 +279,8 @@ lookupReportHandler(IedConnection self, const char* rcbReference)
{
LinkedList element = LinkedList_getNext(self->enabledReports);
while (element != NULL) {
while (element)
{
ClientReport report = (ClientReport)element->data;
if (strcmp(report->rcbReference, rcbReference) == 0)
@ -288,21 +297,23 @@ uninstallReportHandler(IedConnection self, const char* rcbReference)
{
ClientReport report = lookupReportHandler(self, rcbReference);
if (report != NULL) {
if (report)
{
LinkedList_remove(self->enabledReports, report);
ClientReport_destroy(report);
}
}
void
IedConnection_installReportHandler(IedConnection self, const char* rcbReference, const char* rptId, ReportCallbackFunction handler,
void* handlerParameter)
IedConnection_installReportHandler(IedConnection self, const char* rcbReference, const char* rptId,
ReportCallbackFunction handler, void* handlerParameter)
{
Semaphore_wait(self->reportHandlerMutex);
ClientReport report = lookupReportHandler(self, rcbReference);
if (report != NULL) {
if (report)
{
uninstallReportHandler(self, rcbReference);
if (DEBUG_IED_CLIENT)
@ -310,11 +321,14 @@ IedConnection_installReportHandler(IedConnection self, const char* rcbReference,
}
report = ClientReport_create();
if (report)
{
report->callback = handler;
report->callbackParameter = handlerParameter;
report->rcbReference = StringUtils_copyString(rcbReference);
if (rptId != NULL)
if (rptId)
report->rptId = StringUtils_copyString(rptId);
else
report->rptId = NULL;
@ -326,6 +340,7 @@ IedConnection_installReportHandler(IedConnection self, const char* rcbReference,
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: Installed new report callback handler for %s\n", rcbReference);
}
}
void
IedConnection_uninstallReportHandler(IedConnection self, const char* rcbReference)
@ -361,13 +376,15 @@ IedConnection_triggerGIReport(IedConnection self, IedClientError* error, const c
MmsValue_delete(gi);
if (mmsError != MMS_ERROR_NONE) {
if (mmsError != MMS_ERROR_NONE)
{
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: failed to trigger GI for %s!\n", rcbReference);
*error = iedConnection_mapMmsErrorToIedError(mmsError);
}
else {
else
{
*error = IED_ERROR_OK;
}
}
@ -379,7 +396,8 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
MmsValue* rptIdValue = MmsValue_getElement(value, 0);
if ((rptIdValue == NULL) || (MmsValue_getType(rptIdValue) != MMS_VISIBLE_STRING)) {
if ((rptIdValue == NULL) || (MmsValue_getType(rptIdValue) != MMS_VISIBLE_STRING))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (RptId)\n");
@ -389,19 +407,22 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
LinkedList element = LinkedList_getNext(self->enabledReports);
ClientReport matchingReport = NULL;
while (element != NULL) {
while (element)
{
ClientReport report = (ClientReport)element->data;
char defaultRptId[130];
char* rptId = report->rptId;
if ((rptId == NULL) || (strlen(rptId) == 0)) {
if ((rptId == NULL) || (strlen(rptId) == 0))
{
StringUtils_concatString(defaultRptId, 130, report->rcbReference, "");
StringUtils_replace(defaultRptId, '.', '$');
rptId = defaultRptId;
}
if (strcmp(MmsValue_toString(rptIdValue), rptId) == 0) {
if (strcmp(MmsValue_toString(rptIdValue), rptId) == 0)
{
matchingReport = report;
break;
}
@ -426,7 +447,8 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
MmsValue* optFlds = MmsValue_getElement(value, 1);
if ((optFlds == NULL) || (MmsValue_getType(optFlds) != MMS_BIT_STRING)) {
if ((optFlds == NULL) || (MmsValue_getType(optFlds) != MMS_BIT_STRING))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (OptFlds)\n");
@ -436,11 +458,12 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
int inclusionIndex = 2;
/* has sequence-number */
if (MmsValue_getBitStringBit(optFlds, 1) == true) {
if (MmsValue_getBitStringBit(optFlds, 1) == true)
{
MmsValue* seqNum = MmsValue_getElement(value, inclusionIndex);
if ((seqNum == NULL) || (MmsValue_getType(seqNum) != MMS_UNSIGNED)) {
if ((seqNum == NULL) || (MmsValue_getType(seqNum) != MMS_UNSIGNED))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (seqNum)\n");
@ -454,11 +477,12 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
}
/* has report-timestamp */
if (MmsValue_getBitStringBit(optFlds, 2) == true) {
if (MmsValue_getBitStringBit(optFlds, 2) == true)
{
MmsValue* timeStampValue = MmsValue_getElement(value, inclusionIndex);
if ((timeStampValue == NULL) || (MmsValue_getType(timeStampValue) != MMS_BINARY_TIME)) {
if ((timeStampValue == NULL) || (MmsValue_getType(timeStampValue) != MMS_BINARY_TIME))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (timeStamp)\n");
@ -475,12 +499,14 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
}
/* check if data set name is present */
if (MmsValue_getBitStringBit(optFlds, 4) == true) {
if (MmsValue_getBitStringBit(optFlds, 4) == true)
{
matchingReport->hasDataSetName = true;
MmsValue* dataSetName = MmsValue_getElement(value, inclusionIndex);
if ((dataSetName == NULL) || (MmsValue_getType(dataSetName) != MMS_VISIBLE_STRING)) {
if ((dataSetName == NULL) || (MmsValue_getType(dataSetName) != MMS_VISIBLE_STRING))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (DatSet)\n");
@ -490,13 +516,16 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
int dataSetNameSize = MmsValue_getStringSize(dataSetName);
/* limit to prevent large memory allocation */
if (dataSetNameSize < 130) {
if (dataSetNameSize < 130)
{
const char* dataSetNameStr = MmsValue_toString(dataSetName);
if (matchingReport->dataSetName == NULL) {
if (matchingReport->dataSetName == NULL)
{
matchingReport->dataSetName = (char*)GLOBAL_MALLOC(dataSetNameSize + 1);
if (matchingReport->dataSetName == NULL) {
if (matchingReport->dataSetName == NULL)
{
matchingReport->dataSetNameSize = 0;
if (DEBUG_IED_CLIENT)
@ -507,13 +536,16 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
matchingReport->dataSetNameSize = dataSetNameSize + 1;
}
else {
if (matchingReport->dataSetNameSize < MmsValue_getStringSize(dataSetName) + 1) {
else
{
if (matchingReport->dataSetNameSize < MmsValue_getStringSize(dataSetName) + 1)
{
GLOBAL_FREEMEM((void*)matchingReport->dataSetName);
matchingReport->dataSetName = (char*)GLOBAL_MALLOC(dataSetNameSize + 1);
if (matchingReport->dataSetName == NULL) {
if (matchingReport->dataSetName == NULL)
{
matchingReport->dataSetNameSize = 0;
if (DEBUG_IED_CLIENT)
@ -528,7 +560,8 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
StringUtils_copyStringMax(matchingReport->dataSetName, dataSetNameSize + 1, dataSetNameStr);
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: report DatSet name too large (%i)\n", dataSetNameSize);
@ -542,10 +575,12 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
printf("IED_CLIENT: Found enabled report!\n");
/* check bufOvfl */
if (MmsValue_getBitStringBit(optFlds, 6) == true) {
if (MmsValue_getBitStringBit(optFlds, 6) == true)
{
MmsValue* bufOverflow = MmsValue_getElement(value, inclusionIndex);
if ((bufOverflow == NULL) || (MmsValue_getType(bufOverflow) != MMS_BOOLEAN)) {
if ((bufOverflow == NULL) || (MmsValue_getType(bufOverflow) != MMS_BOOLEAN))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (BufOvfl)\n");
@ -559,24 +594,28 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
}
/* check for entryId */
if (MmsValue_getBitStringBit(optFlds, 7) == true) {
if (MmsValue_getBitStringBit(optFlds, 7) == true)
{
MmsValue* entryId = MmsValue_getElement(value, inclusionIndex);
if ((entryId == NULL) || (MmsValue_getType(entryId) != MMS_OCTET_STRING)) {
if ((entryId == NULL) || (MmsValue_getType(entryId) != MMS_OCTET_STRING))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (entryID)\n");
goto exit_function;
}
if (matchingReport->entryId != NULL) {
if (!MmsValue_update(matchingReport->entryId, entryId)) {
if (matchingReport->entryId != NULL)
{
if (!MmsValue_update(matchingReport->entryId, entryId))
{
MmsValue_delete(matchingReport->entryId);
matchingReport->entryId = MmsValue_clone(entryId);
}
}
else {
else
{
matchingReport->entryId = MmsValue_clone(entryId);
}
@ -584,10 +623,12 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
}
/* check for confRev */
if (MmsValue_getBitStringBit(optFlds, 8) == true) {
if (MmsValue_getBitStringBit(optFlds, 8) == true)
{
MmsValue* confRev = MmsValue_getElement(value, inclusionIndex);
if ((confRev == NULL) || (MmsValue_getType(confRev) != MMS_UNSIGNED)) {
if ((confRev == NULL) || (MmsValue_getType(confRev) != MMS_UNSIGNED))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (confRev)\n");
@ -601,46 +642,53 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
}
/* handle segmentation fields (check ReportedOptFlds.segmentation) */
if (MmsValue_getBitStringBit(optFlds, 9) == true) {
if (MmsValue_getBitStringBit(optFlds, 9) == true)
{
MmsValue* subSeqNum = MmsValue_getElement(value, inclusionIndex);
inclusionIndex++;
if ((subSeqNum == NULL) || (MmsValue_getType(subSeqNum) != MMS_UNSIGNED)) {
if ((subSeqNum == NULL) || (MmsValue_getType(subSeqNum) != MMS_UNSIGNED))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (SubSeqNum)\n");
goto exit_function;
}
else {
else
{
matchingReport->subSeqNum = (uint16_t)MmsValue_toUint32(subSeqNum);
}
MmsValue* moreSegmentsFollow = MmsValue_getElement(value, inclusionIndex);
inclusionIndex++;
if ((moreSegmentsFollow == NULL) || (MmsValue_getType(moreSegmentsFollow) != MMS_BOOLEAN)) {
if ((subSeqNum == NULL) || (MmsValue_getType(subSeqNum) != MMS_UNSIGNED)) {
if ((moreSegmentsFollow == NULL) || (MmsValue_getType(moreSegmentsFollow) != MMS_BOOLEAN))
{
if ((subSeqNum == NULL) || (MmsValue_getType(subSeqNum) != MMS_UNSIGNED))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (MoreSegmentsFollow)\n");
goto exit_function;
}
}
else {
else
{
matchingReport->moreSegementsFollow = MmsValue_getBoolean(moreSegmentsFollow);
}
matchingReport->hasSequenceNumber = true;
}
else {
else
{
matchingReport->subSeqNum = 0;
matchingReport->moreSegementsFollow = false;
}
MmsValue* inclusion = MmsValue_getElement(value, inclusionIndex);
if ((inclusion == NULL) || (MmsValue_getType(inclusion) != MMS_BIT_STRING)) {
if ((inclusion == NULL) || (MmsValue_getType(inclusion) != MMS_BIT_STRING))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (inclusion)\n");
@ -649,11 +697,14 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
int dataSetSize = MmsValue_getBitStringSize(inclusion);
if (matchingReport->dataSetSize == -1) {
if (matchingReport->dataSetSize == -1)
{
matchingReport->dataSetSize = dataSetSize;
}
else {
if (dataSetSize != matchingReport->dataSetSize) {
else
{
if (dataSetSize != matchingReport->dataSetSize)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (inclusion has no plausible size)\n");
@ -664,14 +715,13 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
int includedElements = MmsValue_getNumberOfSetBits(inclusion);
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: Report includes %i data set elements of %i\n", includedElements,
dataSetSize);
printf("IED_CLIENT: Report includes %i data set elements of %i\n", includedElements, dataSetSize);
int valueIndex = inclusionIndex + 1;
/* parse data-references if required */
if (MmsValue_getBitStringBit(optFlds, 5) == true) {
if (MmsValue_getBitStringBit(optFlds, 5) == true)
{
if (matchingReport->dataReferences == NULL)
matchingReport->dataReferences = MmsValue_createEmptyArray(dataSetSize);
@ -679,19 +729,23 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
int elementIndex;
for (elementIndex = 0; elementIndex < dataSetSize; elementIndex++) {
if (MmsValue_getBitStringBit(inclusion, elementIndex) == true) {
for (elementIndex = 0; elementIndex < dataSetSize; elementIndex++)
{
if (MmsValue_getBitStringBit(inclusion, elementIndex) == true)
{
MmsValue* dataSetElement = MmsValue_getElement(matchingReport->dataReferences, elementIndex);
if (dataSetElement == NULL) {
if (dataSetElement == NULL)
{
MmsValue* dataRefValue = MmsValue_getElement(value, valueIndex);
if ((dataRefValue == NULL) || (MmsValue_getType(dataRefValue) != MMS_VISIBLE_STRING)) {
if ((dataRefValue == NULL) || (MmsValue_getType(dataRefValue) != MMS_VISIBLE_STRING))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: report contains invalid data reference\n");
}
else {
else
{
dataSetElement = MmsValue_clone(dataRefValue);
MmsValue_setElement(matchingReport->dataReferences, elementIndex, dataSetElement);
@ -705,16 +759,23 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
int i;
if (matchingReport->dataSetValues == NULL) {
if (matchingReport->dataSetValues == NULL)
{
matchingReport->dataSetValues = MmsValue_createEmptyArray(dataSetSize);
matchingReport->reasonForInclusion = (ReasonForInclusion*)
GLOBAL_MALLOC(sizeof(ReasonForInclusion) * dataSetSize);
matchingReport->reasonForInclusion =
(ReasonForInclusion*)GLOBAL_MALLOC(sizeof(ReasonForInclusion) * dataSetSize);
if (matchingReport->reasonForInclusion)
{
int elementIndex;
for (elementIndex = 0; elementIndex < dataSetSize; elementIndex++)
matchingReport->reasonForInclusion[elementIndex] = IEC61850_REASON_NOT_INCLUDED;
}
else
{
goto exit_function;
}
}
MmsValue* dataSetValues = matchingReport->dataSetValues;
@ -724,14 +785,16 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
if (hasReasonForInclusion)
matchingReport->hasReasonForInclusion = true;
for (i = 0; i < dataSetSize; i++) {
if (MmsValue_getBitStringBit(inclusion, i) == true) {
for (i = 0; i < dataSetSize; i++)
{
if (MmsValue_getBitStringBit(inclusion, i) == true)
{
MmsValue* dataSetElement = MmsValue_getElement(dataSetValues, i);
MmsValue* newElementValue = MmsValue_getElement(value, valueIndex);
if (newElementValue == NULL) {
if (newElementValue == NULL)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: report is missing expected element value\n");
@ -746,10 +809,12 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: update element value type: %i\n", MmsValue_getType(newElementValue));
if (hasReasonForInclusion) {
if (hasReasonForInclusion)
{
MmsValue* reasonForInclusion = MmsValue_getElement(value, includedElements + valueIndex);
if ((reasonForInclusion == NULL) || (MmsValue_getType(reasonForInclusion) != MMS_BIT_STRING)) {
if ((reasonForInclusion == NULL) || (MmsValue_getType(reasonForInclusion) != MMS_BIT_STRING))
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: report contains invalid reason-for-inclusion\n");
@ -769,18 +834,20 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
if (MmsValue_getBitStringBit(reasonForInclusion, 5) == true)
matchingReport->reasonForInclusion[i] |= IEC61850_REASON_GI;
}
else {
else
{
matchingReport->reasonForInclusion[i] = IEC61850_REASON_UNKNOWN;
}
valueIndex++;
}
else {
else
{
matchingReport->reasonForInclusion[i] = IEC61850_REASON_NOT_INCLUDED;
}
}
if (matchingReport->callback != NULL)
if (matchingReport->callback)
matchingReport->callback(matchingReport->callbackParameter, matchingReport);
exit_function:
@ -789,4 +856,3 @@ exit_function:
return;
}

@ -60,16 +60,19 @@ ClientReportControlBlock_create(const char* objectReference)
isBuffered = isBufferedRcb(objectReference, &isReferenceValid);
if (isReferenceValid == false) {
if (isReferenceValid == false)
{
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: RCB reference invalid\n");
return NULL;
}
ClientReportControlBlock self = (ClientReportControlBlock) GLOBAL_CALLOC(1, sizeof(struct sClientReportControlBlock));
ClientReportControlBlock self =
(ClientReportControlBlock)GLOBAL_CALLOC(1, sizeof(struct sClientReportControlBlock));
if (self) {
if (self)
{
self->objectReference = StringUtils_copyString(objectReference);
self->isBuffered = isBuffered;
}
@ -79,6 +82,8 @@ ClientReportControlBlock_create(const char* objectReference)
void
ClientReportControlBlock_destroy(ClientReportControlBlock self)
{
if (self)
{
GLOBAL_FREEMEM(self->objectReference);
@ -101,6 +106,7 @@ ClientReportControlBlock_destroy(ClientReportControlBlock self)
GLOBAL_FREEMEM(self);
}
}
char*
ClientReportControlBlock_getObjectReference(ClientReportControlBlock self)
@ -117,7 +123,7 @@ ClientReportControlBlock_isBuffered(ClientReportControlBlock self)
const char*
ClientReportControlBlock_getRptId(ClientReportControlBlock self)
{
if (self->rptId != NULL)
if (self->rptId)
return MmsValue_toString(self->rptId);
else
return NULL;
@ -132,11 +138,11 @@ ClientReportControlBlock_setRptId(ClientReportControlBlock self, const char* rpt
MmsValue_setVisibleString(self->rptId, rptId);
}
bool
ClientReportControlBlock_getRptEna(ClientReportControlBlock self)
{
if (self->rptEna != NULL) {
if (self->rptEna)
{
return MmsValue_getBoolean(self->rptEna);
}
else
@ -155,7 +161,8 @@ ClientReportControlBlock_setRptEna(ClientReportControlBlock self, bool rptEna)
bool
ClientReportControlBlock_getResv(ClientReportControlBlock self)
{
if (self->resv != NULL) {
if (self->resv)
{
return MmsValue_getBoolean(self->resv);
}
else
@ -174,7 +181,7 @@ ClientReportControlBlock_setResv(ClientReportControlBlock self, bool resv)
const char*
ClientReportControlBlock_getDataSetReference(ClientReportControlBlock self)
{
if (self->datSet != NULL)
if (self->datSet)
return MmsValue_toString(self->datSet);
else
return NULL;
@ -192,7 +199,7 @@ ClientReportControlBlock_setDataSetReference(ClientReportControlBlock self, cons
uint32_t
ClientReportControlBlock_getConfRev(ClientReportControlBlock self)
{
if (self->confRev != NULL)
if (self->confRev)
return MmsValue_toUint32(self->confRev);
else
return 0;
@ -219,7 +226,7 @@ ClientReportControlBlock_setOptFlds(ClientReportControlBlock self, int optFlds)
uint32_t
ClientReportControlBlock_getBufTm(ClientReportControlBlock self)
{
if (self->bufTm != NULL)
if (self->bufTm)
return MmsValue_toUint32(self->bufTm);
else
return 0;
@ -237,7 +244,7 @@ ClientReportControlBlock_setBufTm(ClientReportControlBlock self, uint32_t bufTm)
uint16_t
ClientReportControlBlock_getSqNum(ClientReportControlBlock self)
{
if (self->sqNum != NULL)
if (self->sqNum)
return (uint16_t) MmsValue_toUint32(self->sqNum);
else
return 0;
@ -248,7 +255,8 @@ ClientReportControlBlock_getTrgOps(ClientReportControlBlock self)
{
int triggerOps = 0;
if (self->trgOps != NULL) {
if (self->trgOps)
{
if (MmsValue_getBitStringBit(self->trgOps, 1))
triggerOps += TRG_OPT_DATA_CHANGED;
if (MmsValue_getBitStringBit(self->trgOps, 2))
@ -276,7 +284,7 @@ ClientReportControlBlock_setTrgOps(ClientReportControlBlock self, int trgOps)
uint32_t
ClientReportControlBlock_getIntgPd(ClientReportControlBlock self)
{
if (self->intgPd != NULL)
if (self->intgPd)
return MmsValue_toUint32(self->intgPd);
else
return 0;
@ -294,7 +302,7 @@ ClientReportControlBlock_setIntgPd(ClientReportControlBlock self, uint32_t intgP
bool
ClientReportControlBlock_getGI(ClientReportControlBlock self)
{
if (self->gi != NULL)
if (self->gi)
return MmsValue_getBoolean(self->gi);
else
return false;
@ -312,7 +320,7 @@ ClientReportControlBlock_setGI(ClientReportControlBlock self, bool gi)
bool
ClientReportControlBlock_getPurgeBuf(ClientReportControlBlock self)
{
if (self->purgeBuf != NULL)
if (self->purgeBuf)
return MmsValue_getBoolean(self->purgeBuf);
else
return false;
@ -336,7 +344,7 @@ ClientReportControlBlock_hasResvTms(ClientReportControlBlock self)
int16_t
ClientReportControlBlock_getResvTms(ClientReportControlBlock self)
{
if (self->resvTms != NULL)
if (self->resvTms)
return (int16_t) MmsValue_toInt32(self->resvTms);
else
return 0;
@ -360,11 +368,14 @@ ClientReportControlBlock_getEntryId(ClientReportControlBlock self)
void
ClientReportControlBlock_setEntryId(ClientReportControlBlock self, MmsValue* entryId)
{
if (self->entryId != NULL) {
if (self->entryId)
{
MmsValue_update(self->entryId, entryId);
}
else {
if (MmsValue_getType(entryId) != MMS_OCTET_STRING) {
else
{
if (MmsValue_getType(entryId) != MMS_OCTET_STRING)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: ClientReportControlBlock_setEntryId invalid argument type\n");
}
@ -376,7 +387,7 @@ ClientReportControlBlock_setEntryId(ClientReportControlBlock self, MmsValue* ent
uint64_t
ClientReportControlBlock_getEntryTime(ClientReportControlBlock self)
{
if (self->timeOfEntry != NULL)
if (self->timeOfEntry)
return MmsValue_getBinaryTimeAsUtcMs(self->timeOfEntry);
else
return 0;
@ -391,7 +402,7 @@ ClientReportControlBlock_getOwner(ClientReportControlBlock self)
static void
updateOrClone(MmsValue** valuePtr, MmsValue* values, int index)
{
if (*valuePtr != NULL)
if (*valuePtr)
MmsValue_update(*valuePtr, MmsValue_getElement(values, index));
else
*valuePtr = MmsValue_clone(MmsValue_getElement(values, index));
@ -421,53 +432,87 @@ clientReportControlBlock_updateValues(ClientReportControlBlock self, MmsValue* v
int rcbElementCount = MmsValue_getArraySize(values);
if (self->isBuffered) {
if ((rcbElementCount < 13) || (rcbElementCount > 15)) {
if (self->isBuffered)
{
if ((rcbElementCount < 13) || (rcbElementCount > 15))
{
return false;
}
if (!checkElementType(values, 0, MMS_VISIBLE_STRING)) return false;
if (!checkElementType(values, 1, MMS_BOOLEAN)) return false;
if (!checkElementType(values, 2, MMS_VISIBLE_STRING)) return false;
if (!checkElementType(values, 3, MMS_UNSIGNED)) return false;
if (!checkElementType(values, 4, MMS_BIT_STRING)) return false;
if (!checkElementType(values, 5, MMS_UNSIGNED)) return false;
if (!checkElementType(values, 6, MMS_UNSIGNED)) return false;
if (!checkElementType(values, 7, MMS_BIT_STRING)) return false;
if (!checkElementType(values, 8, MMS_UNSIGNED)) return false;
if (!checkElementType(values, 9, MMS_BOOLEAN)) return false;
if (!checkElementType(values, 10, MMS_BOOLEAN)) return false;
if (!checkElementType(values, 11, MMS_OCTET_STRING)) return false;
if (!checkElementType(values, 12, MMS_BINARY_TIME)) return false;
if (rcbElementCount == 14) {
if (!checkElementType(values, 0, MMS_VISIBLE_STRING))
return false;
if (!checkElementType(values, 1, MMS_BOOLEAN))
return false;
if (!checkElementType(values, 2, MMS_VISIBLE_STRING))
return false;
if (!checkElementType(values, 3, MMS_UNSIGNED))
return false;
if (!checkElementType(values, 4, MMS_BIT_STRING))
return false;
if (!checkElementType(values, 5, MMS_UNSIGNED))
return false;
if (!checkElementType(values, 6, MMS_UNSIGNED))
return false;
if (!checkElementType(values, 7, MMS_BIT_STRING))
return false;
if (!checkElementType(values, 8, MMS_UNSIGNED))
return false;
if (!checkElementType(values, 9, MMS_BOOLEAN))
return false;
if (!checkElementType(values, 10, MMS_BOOLEAN))
return false;
if (!checkElementType(values, 11, MMS_OCTET_STRING))
return false;
if (!checkElementType(values, 12, MMS_BINARY_TIME))
return false;
if (rcbElementCount == 14)
{
if (!checkElementType(values, 13, MMS_OCTET_STRING) && !checkElementType(values, 13, MMS_INTEGER))
return false;
}
else if (rcbElementCount == 15) {
if (!checkElementType(values, 13, MMS_INTEGER)) return false;
if (!checkElementType(values, 14, MMS_OCTET_STRING)) return false;
else if (rcbElementCount == 15)
{
if (!checkElementType(values, 13, MMS_INTEGER))
return false;
if (!checkElementType(values, 14, MMS_OCTET_STRING))
return false;
}
}
else {
if ((rcbElementCount < 11) || (rcbElementCount > 12)) {
else
{
if ((rcbElementCount < 11) || (rcbElementCount > 12))
{
return false;
}
if (!checkElementType(values, 0, MMS_VISIBLE_STRING)) return false;
if (!checkElementType(values, 1, MMS_BOOLEAN)) return false;
if (!checkElementType(values, 2, MMS_BOOLEAN)) return false;
if (!checkElementType(values, 3, MMS_VISIBLE_STRING)) return false;
if (!checkElementType(values, 4, MMS_UNSIGNED)) return false;
if (!checkElementType(values, 5, MMS_BIT_STRING)) return false;
if (!checkElementType(values, 6, MMS_UNSIGNED)) return false;
if (!checkElementType(values, 7, MMS_UNSIGNED)) return false;
if (!checkElementType(values, 8, MMS_BIT_STRING)) return false;
if (!checkElementType(values, 9, MMS_UNSIGNED)) return false;
if (!checkElementType(values, 10, MMS_BOOLEAN)) return false;
if (!checkElementType(values, 0, MMS_VISIBLE_STRING))
return false;
if (!checkElementType(values, 1, MMS_BOOLEAN))
return false;
if (!checkElementType(values, 2, MMS_BOOLEAN))
return false;
if (!checkElementType(values, 3, MMS_VISIBLE_STRING))
return false;
if (!checkElementType(values, 4, MMS_UNSIGNED))
return false;
if (!checkElementType(values, 5, MMS_BIT_STRING))
return false;
if (!checkElementType(values, 6, MMS_UNSIGNED))
return false;
if (!checkElementType(values, 7, MMS_UNSIGNED))
return false;
if (!checkElementType(values, 8, MMS_BIT_STRING))
return false;
if (!checkElementType(values, 9, MMS_UNSIGNED))
return false;
if (!checkElementType(values, 10, MMS_BOOLEAN))
return false;
if (rcbElementCount == 12) {
if (!checkElementType(values, 11, MMS_OCTET_STRING)) return false;
if (rcbElementCount == 12)
{
if (!checkElementType(values, 11, MMS_OCTET_STRING))
return false;
}
}
@ -476,7 +521,8 @@ clientReportControlBlock_updateValues(ClientReportControlBlock self, MmsValue* v
updateOrClone(&(self->rptId), values, 0);
updateOrClone(&(self->rptEna), values, 1);
if (self->isBuffered) {
if (self->isBuffered)
{
updateOrClone(&(self->datSet), values, 2);
updateOrClone(&(self->confRev), values, 3);
updateOrClone(&(self->optFlds), values, 4);
@ -489,21 +535,23 @@ clientReportControlBlock_updateValues(ClientReportControlBlock self, MmsValue* v
updateOrClone(&(self->entryId), values, 11);
updateOrClone(&(self->timeOfEntry), values, 12);
if (rcbElementCount > 13) {
if (rcbElementCount > 13)
{
MmsValue* element13 = MmsValue_getElement(values, 13);
if (MmsValue_getType(element13) == MMS_OCTET_STRING)
updateOrClone(&(self->owner), values, 13);
else {
else
{
updateOrClone(&(self->resvTms), values, 13);
if (rcbElementCount > 14)
updateOrClone(&(self->owner), values, 14);
}
}
}
else {
else
{
updateOrClone(&(self->resv), values, 2);
updateOrClone(&(self->datSet), values, 3);
updateOrClone(&(self->confRev), values, 4);
@ -667,30 +715,33 @@ IedConnection_getRCBValues(IedConnection self, IedClientError* error, const char
MmsValue* rcb = MmsConnection_readVariable(self->connection, &mmsError, domainId, itemId);
if (mmsError != MMS_ERROR_NONE) {
if (mmsError != MMS_ERROR_NONE)
{
*error = iedConnection_mapMmsErrorToIedError(mmsError);
return NULL;
}
if (rcb == NULL) {
if (rcb == NULL)
{
*error = IED_ERROR_OBJECT_DOES_NOT_EXIST;
return NULL;
}
if (MmsValue_getType(rcb) == MMS_DATA_ACCESS_ERROR) {
if (MmsValue_getType(rcb) == MMS_DATA_ACCESS_ERROR)
{
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: getRCBValues returned data-access-error!\n");
*error = iedConnection_mapDataAccessErrorToIedError(
MmsValue_getDataAccessError(rcb));
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(rcb));
MmsValue_delete(rcb);
return NULL;
}
if (MmsValue_getType(rcb) != MMS_STRUCTURE) {
if (MmsValue_getType(rcb) != MMS_STRUCTURE)
{
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: getRCBValues returned wrong type!\n");
@ -703,16 +754,19 @@ IedConnection_getRCBValues(IedConnection self, IedClientError* error, const char
if (returnRcb == NULL)
returnRcb = ClientReportControlBlock_create(rcbReference);
if (clientReportControlBlock_updateValues(returnRcb, rcb)) {
if (clientReportControlBlock_updateValues(returnRcb, rcb))
{
*error = IED_ERROR_OK;
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: getRCBValues returned wrong type!\n");
*error = IED_ERROR_TYPE_INCONSISTENT;
if (updateRcb == NULL) {
if (updateRcb == NULL)
{
ClientReportControlBlock_destroy(returnRcb);
returnRcb = NULL;
}
@ -724,26 +778,30 @@ IedConnection_getRCBValues(IedConnection self, IedClientError* error, const char
}
static void
writeMultipleVariablesHandler(uint32_t invokeId, void* parameter, MmsError mmsError, LinkedList /* <MmsValue*> */ accessResults)
writeMultipleVariablesHandler(uint32_t invokeId, void* parameter, MmsError mmsError,
LinkedList /* <MmsValue*> */ accessResults)
{
IedConnection self = (IedConnection)parameter;
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
if (call) {
if (call)
{
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler)call->callback;
if (accessResults != NULL) {
if (accessResults)
{
IedClientError error = IED_ERROR_OK;
LinkedList accessResult = LinkedList_getNext(accessResults);
while (accessResult != NULL) {
while (accessResult)
{
MmsValue* dataAccessError = (MmsValue*)accessResult->data;
if (MmsValue_getDataAccessError(dataAccessError) != DATA_ACCESS_ERROR_SUCCESS) {
if (MmsValue_getDataAccessError(dataAccessError) != DATA_ACCESS_ERROR_SUCCESS)
{
error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(dataAccessError));
break;
}
@ -755,13 +813,15 @@ writeMultipleVariablesHandler(uint32_t invokeId, void* parameter, MmsError mmsEr
handler(invokeId, call->callbackParameter, error);
}
else {
else
{
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(mmsError));
}
iedConnection_releaseOutstandingCall(self, call);
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call with invoke ID: %u!\n", invokeId);
}
@ -797,14 +857,15 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError mmsError, MmsD
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
if (call) {
if (call)
{
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler)call->callback;
struct sWriteRcbVariablesParameter* param = (struct sWriteRcbVariablesParameter*) call->specificParameter2.pointer;
if ((mmsError != MMS_ERROR_NONE) || (accessError != DATA_ACCESS_ERROR_SUCCESS)) {
struct sWriteRcbVariablesParameter* param =
(struct sWriteRcbVariablesParameter*)call->specificParameter2.pointer;
if ((mmsError != MMS_ERROR_NONE) || (accessError != DATA_ACCESS_ERROR_SUCCESS))
{
IedClientError err;
if (mmsError != MMS_ERROR_NONE)
@ -821,12 +882,14 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError mmsError, MmsD
param->currentItemId = LinkedList_getNext(param->currentItemId);
if (param->currentItemId == NULL) {
if (param->currentItemId == NULL)
{
handler(param->originalInvokeId, call->callbackParameter, IED_ERROR_OK);
releaseWriteCall(self, call, param);
}
else {
else
{
param->currentValue = LinkedList_getNext(param->currentValue);
char* itemId = (char*)LinkedList_getData(param->currentItemId);
@ -834,17 +897,21 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError mmsError, MmsD
MmsError writeError;
MmsConnection_writeVariableAsync(self->connection, &(call->invokeId), &writeError, param->domainId, itemId, value, writeVariableHandler, self);
MmsConnection_writeVariableAsync(self->connection, &(call->invokeId), &writeError, param->domainId, itemId,
value, writeVariableHandler, self);
if (writeError != MMS_ERROR_NONE) {
if (writeError != MMS_ERROR_NONE)
{
handler(param->originalInvokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(writeError));
handler(param->originalInvokeId, call->callbackParameter,
iedConnection_mapMmsErrorToIedError(writeError));
releaseWriteCall(self, call, param);
}
}
}
else {
else
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@ -856,7 +923,8 @@ exit_function:
uint32_t
IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, ClientReportControlBlock rcb,
uint32_t parametersMask, bool singleRequest, IedConnection_GenericServiceHandler handler, void* parameter)
uint32_t parametersMask, bool singleRequest,
IedConnection_GenericServiceHandler handler, void* parameter)
{
uint32_t invokeId = 0;
@ -883,7 +951,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
LinkedList values = LinkedList_create();
/* add resv/resvTms as first element and rptEna as last element */
if (parametersMask & RCB_ELEMENT_RESV) {
if (parametersMask & RCB_ELEMENT_RESV)
{
if (isBuffered)
goto error_invalid_parameter;
@ -895,7 +964,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_RESV_TMS) {
if (parametersMask & RCB_ELEMENT_RESV_TMS)
{
if (!isBuffered)
goto error_invalid_parameter;
@ -907,7 +977,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_RPT_ID) {
if (parametersMask & RCB_ELEMENT_RPT_ID)
{
StringUtils_appendString(itemId, 130, "$RptID");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -916,7 +987,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_DATSET) {
if (parametersMask & RCB_ELEMENT_DATSET)
{
StringUtils_appendString(itemId, 130, "$DatSet");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -925,7 +997,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_ENTRY_ID) {
if (parametersMask & RCB_ELEMENT_ENTRY_ID)
{
StringUtils_appendString(itemId, 130, "$EntryID");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -934,7 +1007,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_OPT_FLDS) {
if (parametersMask & RCB_ELEMENT_OPT_FLDS)
{
StringUtils_appendString(itemId, 130, "$OptFlds");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -943,7 +1017,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_BUF_TM) {
if (parametersMask & RCB_ELEMENT_BUF_TM)
{
StringUtils_appendString(itemId, 130, "$BufTm");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -952,7 +1027,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_TRG_OPS) {
if (parametersMask & RCB_ELEMENT_TRG_OPS)
{
StringUtils_appendString(itemId, 130, "$TrgOps");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -961,7 +1037,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_INTG_PD) {
if (parametersMask & RCB_ELEMENT_INTG_PD)
{
StringUtils_appendString(itemId, 130, "$IntgPd");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -970,14 +1047,16 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_GI) {
if (parametersMask & RCB_ELEMENT_RPT_ENA) {
if (parametersMask & RCB_ELEMENT_GI)
{
if (parametersMask & RCB_ELEMENT_RPT_ENA)
{
if (MmsValue_getBoolean(rcb->rptEna))
sendGILast = true;
}
if (sendGILast == false) {
if (sendGILast == false)
{
StringUtils_appendString(itemId, 130, "$GI");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -987,7 +1066,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
}
}
if (parametersMask & RCB_ELEMENT_PURGE_BUF) {
if (parametersMask & RCB_ELEMENT_PURGE_BUF)
{
if (!isBuffered)
goto error_invalid_parameter;
@ -999,7 +1079,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_TIME_OF_ENTRY) {
if (parametersMask & RCB_ELEMENT_TIME_OF_ENTRY)
{
if (!isBuffered)
goto error_invalid_parameter;
@ -1011,7 +1092,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_RPT_ENA) {
if (parametersMask & RCB_ELEMENT_RPT_ENA)
{
StringUtils_appendString(itemId, 130, "$RptEna");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1020,7 +1102,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
itemId[itemIdLen] = 0;
}
if (sendGILast) {
if (sendGILast)
{
StringUtils_appendString(itemId, 130, "$GI");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1031,7 +1114,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
if (call == NULL) {
if (call == NULL)
{
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
goto exit_function;
}
@ -1042,24 +1126,34 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
MmsError err;
if (singleRequest) {
MmsConnection_writeMultipleVariablesAsync(self->connection, &(call->invokeId), &err, domainId, itemIds, values, writeMultipleVariablesHandler, self);
if (singleRequest)
{
MmsConnection_writeMultipleVariablesAsync(self->connection, &(call->invokeId), &err, domainId, itemIds, values,
writeMultipleVariablesHandler, self);
*error = iedConnection_mapMmsErrorToIedError(err);
if (err != MMS_ERROR_NONE) {
if (err != MMS_ERROR_NONE)
{
iedConnection_releaseOutstandingCall(self, call);
}
else {
else
{
invokeId = call->invokeId;
}
goto exit_function;
}
else {
else
{
struct sWriteRcbVariablesParameter* param =
(struct sWriteRcbVariablesParameter*)GLOBAL_MALLOC(sizeof(struct sWriteRcbVariablesParameter));
struct sWriteRcbVariablesParameter* param = (struct sWriteRcbVariablesParameter*) GLOBAL_MALLOC(sizeof(struct sWriteRcbVariablesParameter));
if (param == NULL)
{
*error = IED_ERROR_UNKNOWN;
goto exit_function;
}
call->specificParameter2.pointer = param;
@ -1073,7 +1167,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
char* variableId = (char*)LinkedList_getData(param->currentItemId);
MmsValue* value = (MmsValue*)LinkedList_getData(param->currentValue);
MmsConnection_writeVariableAsync(self->connection, &(call->invokeId), &err, domainId, variableId, value, writeVariableHandler, self);
MmsConnection_writeVariableAsync(self->connection, &(call->invokeId), &err, domainId, variableId, value,
writeVariableHandler, self);
param->originalInvokeId = call->invokeId;
@ -1081,7 +1176,8 @@ IedConnection_setRCBValuesAsync(IedConnection self, IedClientError* error, Clien
*error = iedConnection_mapMmsErrorToIedError(err);
if (err != MMS_ERROR_NONE) {
if (err != MMS_ERROR_NONE)
{
iedConnection_releaseOutstandingCall(self, call);
GLOBAL_FREEMEM(param->domainId);
GLOBAL_FREEMEM(param);
@ -1132,8 +1228,10 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
LinkedList values = LinkedList_create();
/* add rptEna = false as first element */
if (ClientReportControlBlock_getRptEna(rcb) == false) {
if (parametersMask & RCB_ELEMENT_RPT_ENA) {
if (ClientReportControlBlock_getRptEna(rcb) == false)
{
if (parametersMask & RCB_ELEMENT_RPT_ENA)
{
StringUtils_appendString(itemId, 130, "$RptEna");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1144,7 +1242,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
}
/* add resv/resvTms as first element and rptEna as last element when enabling a report */
if (parametersMask & RCB_ELEMENT_RESV) {
if (parametersMask & RCB_ELEMENT_RESV)
{
if (isBuffered)
goto error_invalid_parameter;
@ -1156,7 +1255,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_RESV_TMS) {
if (parametersMask & RCB_ELEMENT_RESV_TMS)
{
if (!isBuffered)
goto error_invalid_parameter;
@ -1168,7 +1268,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_RPT_ID) {
if (parametersMask & RCB_ELEMENT_RPT_ID)
{
StringUtils_appendString(itemId, 130, "$RptID");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1177,7 +1278,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_DATSET) {
if (parametersMask & RCB_ELEMENT_DATSET)
{
StringUtils_appendString(itemId, 130, "$DatSet");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1186,7 +1288,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_ENTRY_ID) {
if (parametersMask & RCB_ELEMENT_ENTRY_ID)
{
StringUtils_appendString(itemId, 130, "$EntryID");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1195,7 +1298,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_OPT_FLDS) {
if (parametersMask & RCB_ELEMENT_OPT_FLDS)
{
StringUtils_appendString(itemId, 130, "$OptFlds");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1204,7 +1308,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_BUF_TM) {
if (parametersMask & RCB_ELEMENT_BUF_TM)
{
StringUtils_appendString(itemId, 130, "$BufTm");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1213,7 +1318,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_TRG_OPS) {
if (parametersMask & RCB_ELEMENT_TRG_OPS)
{
StringUtils_appendString(itemId, 130, "$TrgOps");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1222,7 +1328,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_INTG_PD) {
if (parametersMask & RCB_ELEMENT_INTG_PD)
{
StringUtils_appendString(itemId, 130, "$IntgPd");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1231,14 +1338,16 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_GI) {
if (parametersMask & RCB_ELEMENT_RPT_ENA) {
if (parametersMask & RCB_ELEMENT_GI)
{
if (parametersMask & RCB_ELEMENT_RPT_ENA)
{
if (MmsValue_getBoolean(rcb->rptEna))
sendGILast = true;
}
if (sendGILast == false) {
if (sendGILast == false)
{
StringUtils_appendString(itemId, 130, "$GI");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1248,7 +1357,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
}
}
if (parametersMask & RCB_ELEMENT_PURGE_BUF) {
if (parametersMask & RCB_ELEMENT_PURGE_BUF)
{
if (!isBuffered)
goto error_invalid_parameter;
@ -1260,7 +1370,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (parametersMask & RCB_ELEMENT_TIME_OF_ENTRY) {
if (parametersMask & RCB_ELEMENT_TIME_OF_ENTRY)
{
if (!isBuffered)
goto error_invalid_parameter;
@ -1272,8 +1383,10 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (ClientReportControlBlock_getRptEna(rcb) == true) {
if (parametersMask & RCB_ELEMENT_RPT_ENA) {
if (ClientReportControlBlock_getRptEna(rcb) == true)
{
if (parametersMask & RCB_ELEMENT_RPT_ENA)
{
StringUtils_appendString(itemId, 130, "$RptEna");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1283,7 +1396,8 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
}
}
if (sendGILast) {
if (sendGILast)
{
StringUtils_appendString(itemId, 130, "$GI");
LinkedList_add(itemIds, StringUtils_copyString(itemId));
@ -1292,19 +1406,23 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
itemId[itemIdLen] = 0;
}
if (singleRequest) {
if (singleRequest)
{
LinkedList accessResults = NULL;
MmsConnection_writeMultipleVariables(self->connection, &mmsError, domainId, itemIds, values, &accessResults);
if (accessResults != NULL) {
if (accessResults)
{
LinkedList accessResult = LinkedList_getNext(accessResults);
while (accessResult != NULL) {
while (accessResult)
{
MmsValue* dataAccessError = (MmsValue*)accessResult->data;
if (MmsValue_getDataAccessError(dataAccessError) != DATA_ACCESS_ERROR_SUCCESS) {
if (MmsValue_getDataAccessError(dataAccessError) != DATA_ACCESS_ERROR_SUCCESS)
{
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(dataAccessError));
break;
}
@ -1319,11 +1437,13 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
goto exit_function;
}
else {
else
{
LinkedList itemIdElement = LinkedList_getNext(itemIds);
LinkedList valueElement = LinkedList_getNext(values);
while (itemIdElement != NULL) {
while (itemIdElement)
{
char* rcbItemId = (char*)itemIdElement->data;
MmsValue* value = (MmsValue*)valueElement->data;

@ -1,7 +1,7 @@
/*
* client_sv_control.c
*
* Copyright 2015-2022 Michael Zillgith
* Copyright 2015-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -29,7 +29,8 @@
#include "libiec61850_platform_includes.h"
struct sClientSVControlBlock {
struct sClientSVControlBlock
{
IedConnection connection;
bool isMulticast;
char* reference;
@ -45,18 +46,21 @@ ClientSVControlBlock_create(IedConnection connection, const char* reference)
IedClientError error;
MmsValue* value = IedConnection_readObject(connection, &error, reference, IEC61850_FC_MS);
if ((error == IED_ERROR_OK) && (MmsValue_getType(value) != MMS_DATA_ACCESS_ERROR)) {
if ((error == IED_ERROR_OK) && (MmsValue_getType(value) != MMS_DATA_ACCESS_ERROR))
{
isMulticast = true;
MmsValue_delete(value);
}
else {
else
{
MmsValue_delete(value);
value = IedConnection_readObject(connection, &error, reference, IEC61850_FC_US);
if ((error == IED_ERROR_OK) && (MmsValue_getType(value) != MMS_DATA_ACCESS_ERROR))
MmsValue_delete(value);
else {
else
{
MmsValue_delete(value);
return NULL;
}
@ -64,7 +68,8 @@ ClientSVControlBlock_create(IedConnection connection, const char* reference)
ClientSVControlBlock self = (ClientSVControlBlock)GLOBAL_CALLOC(1, sizeof(struct sClientSVControlBlock));
if (self) {
if (self)
{
self->connection = connection;
self->reference = StringUtils_copyString(reference);
self->isMulticast = isMulticast;
@ -76,7 +81,8 @@ ClientSVControlBlock_create(IedConnection connection, const char* reference)
void
ClientSVControlBlock_destroy(ClientSVControlBlock self)
{
if (self) {
if (self)
{
GLOBAL_FREEMEM(self->reference);
GLOBAL_FREEMEM(self);
}
@ -110,7 +116,6 @@ setBooleanVariable(ClientSVControlBlock self, const char* varName, bool value)
else
IedConnection_writeBooleanValue(self->connection, &(self->lastError), refBuf, IEC61850_FC_US, value);
if (self->lastError == IED_ERROR_OK)
return true;
else
@ -288,27 +293,36 @@ ClientSVControlBlock_getDstAddress(ClientSVControlBlock self)
PhyComAddress retVal;
memset(&retVal, 0, sizeof(retVal));
if (dstAddrValue == NULL) goto exit_error;
if (dstAddrValue == NULL)
goto exit_error;
if (MmsValue_getType(dstAddrValue) != MMS_STRUCTURE) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - addr has wrong type\n");
if (MmsValue_getType(dstAddrValue) != MMS_STRUCTURE)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: SVCB - addr has wrong type\n");
goto exit_cleanup;
}
if (MmsValue_getArraySize(dstAddrValue) != 4) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - addr has wrong type\n");
if (MmsValue_getArraySize(dstAddrValue) != 4)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: SVCB - addr has wrong type\n");
goto exit_cleanup;
}
MmsValue* addr = MmsValue_getElement(dstAddrValue, 0);
if (MmsValue_getType(addr) != MMS_OCTET_STRING) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - addr has wrong type\n");
if (MmsValue_getType(addr) != MMS_OCTET_STRING)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: SVCB - addr has wrong type\n");
goto exit_cleanup;
}
if (MmsValue_getOctetStringSize(addr) != 6) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - addr has wrong size\n");
if (MmsValue_getOctetStringSize(addr) != 6)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: SVCB - addr has wrong size\n");
goto exit_cleanup;
}
@ -318,8 +332,10 @@ ClientSVControlBlock_getDstAddress(ClientSVControlBlock self)
MmsValue* prio = MmsValue_getElement(dstAddrValue, 1);
if (MmsValue_getType(prio) != MMS_UNSIGNED) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - prio has wrong type\n");
if (MmsValue_getType(prio) != MMS_UNSIGNED)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: SVCB - prio has wrong type\n");
goto exit_cleanup;
}
@ -327,8 +343,10 @@ ClientSVControlBlock_getDstAddress(ClientSVControlBlock self)
MmsValue* vid = MmsValue_getElement(dstAddrValue, 2);
if (MmsValue_getType(vid) != MMS_UNSIGNED) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - vid has wrong type\n");
if (MmsValue_getType(vid) != MMS_UNSIGNED)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: SVCB - vid has wrong type\n");
goto exit_cleanup;
}
@ -336,18 +354,18 @@ ClientSVControlBlock_getDstAddress(ClientSVControlBlock self)
MmsValue* appID = MmsValue_getElement(dstAddrValue, 3);
if (MmsValue_getType(appID) != MMS_UNSIGNED) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - appID has wrong type\n");
if (MmsValue_getType(appID) != MMS_UNSIGNED)
{
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: SVCB - appID has wrong type\n");
goto exit_cleanup;
}
retVal.appId = MmsValue_toUint32(appID);
exit_cleanup:
MmsValue_delete(dstAddrValue);
exit_error:
return retVal;
}

Loading…
Cancel
Save