From a6630febb2efe01dcd72e46dc671667494b21fb5 Mon Sep 17 00:00:00 2001 From: Nikunj Patel Date: Mon, 20 Feb 2023 13:05:42 +0100 Subject: [PATCH 1/4] Update iec61850.i --- pyiec61850/iec61850.i | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pyiec61850/iec61850.i b/pyiec61850/iec61850.i index 254fec64d..917c15d4c 100644 --- a/pyiec61850/iec61850.i +++ b/pyiec61850/iec61850.i @@ -160,3 +160,45 @@ void CommParameters_setDstAddress(CommParameters *gooseCommParameters, #include "servicePythonWrapper.hpp" %} %include "servicePythonWrapper.hpp" + + /* SV Subscriber section */ +%{ +struct sSVSubscriber; +typedef struct sSVSubscriber* SVSubscriber; +struct sSVSubscriber_ASDU { + + char* svId; + char* datSet; + + uint8_t* smpCnt; + uint8_t* confRev; + uint8_t* refrTm; + uint8_t* smpSynch; + uint8_t* smpMod; + uint8_t* smpRate; + + int dataBufferLength; + uint8_t* dataBuffer; +}; +typedef struct sSVSubscriber_ASDU* SVSubscriber_ASDU; +#include "sv_subscriber.h" +#include "sv_publisher.h" +%} +%include "sv_publisher.h" +%include "sv_subscriber.h" +struct sSVSubscriber_ASDU { + + char* svId; + char* datSet; + + uint8_t* smpCnt; + uint8_t* confRev; + uint8_t* refrTm; + uint8_t* smpSynch; + uint8_t* smpMod; + uint8_t* smpRate; + + int dataBufferLength; + uint8_t* dataBuffer; +}; +typedef struct sSVSubscriber_ASDU* SVSubscriber_ASDU; From a9b97418c2b5d34abd9548b6c7d452527fdba8bf Mon Sep 17 00:00:00 2001 From: Nikunj Patel Date: Mon, 20 Feb 2023 13:06:14 +0100 Subject: [PATCH 2/4] Update iec61850.i --- pyiec61850/iec61850.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyiec61850/iec61850.i b/pyiec61850/iec61850.i index 917c15d4c..3de0380ed 100644 --- a/pyiec61850/iec61850.i +++ b/pyiec61850/iec61850.i @@ -161,7 +161,7 @@ void CommParameters_setDstAddress(CommParameters *gooseCommParameters, %} %include "servicePythonWrapper.hpp" - /* SV Subscriber section */ +/* SV Subscriber section */ %{ struct sSVSubscriber; typedef struct sSVSubscriber* SVSubscriber; From f89bca0fb903a9fe6829c41fda105c5ffae8e800 Mon Sep 17 00:00:00 2001 From: Nikunj Patel Date: Tue, 7 Mar 2023 09:36:26 +0100 Subject: [PATCH 3/4] Adding ControlObjectClient_cancelWithValue --- src/iec61850/inc/iec61850_client.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/iec61850/inc/iec61850_client.h b/src/iec61850/inc/iec61850_client.h index 852f21920..190c6bce0 100644 --- a/src/iec61850/inc/iec61850_client.h +++ b/src/iec61850/inc/iec61850_client.h @@ -2190,6 +2190,19 @@ ControlObjectClient_selectWithValue(ControlObjectClient self, MmsValue* ctlVal); LIB61850_API bool ControlObjectClient_cancel(ControlObjectClient self); +/** + * \brief Send a cancel command to the server + * + * The cancel command can be used to stop an ongoing operation (when the server and application + * support this) and to cancel a former select command. + * + * \param self the control object instance to use + * \param ctlVal the control value (for APC the value may be either AnalogueValue (MMS_STRUCT) or MMS_FLOAT/MMS_INTEGER + * + * \return true if operation has been successful, false otherwise. + */ +LIB61850_API bool +ControlObjectClient_cancelWithValue(ControlObjectClient self, MmsValue* ctlVal); /** * \brief Send an operate command to the server - async version From 5f776d17ccfa2b9ce11708a4dcbab2fda1dfe712 Mon Sep 17 00:00:00 2001 From: Nikunj Patel Date: Tue, 7 Mar 2023 09:41:14 +0100 Subject: [PATCH 4/4] Adding ControlObjectClient_cancelWithValue Adding ControlObjectClient_cancelWithValue createCancelwParameters --- src/iec61850/client/client_control.c | 99 ++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/iec61850/client/client_control.c b/src/iec61850/client/client_control.c index caa071487..2cf45231d 100644 --- a/src/iec61850/client/client_control.c +++ b/src/iec61850/client/client_control.c @@ -1108,6 +1108,59 @@ createCancelParameters(ControlObjectClient self) return cancelParameters; } +static MmsValue* +createCancelwParameters(ControlObjectClient self, MmsValue* ctlVal) +{ + MmsValue* cancelParameters; + + if (self->hasTimeActivatedMode) + cancelParameters = MmsValue_createEmptyStructure(6); + else + cancelParameters = MmsValue_createEmptyStructure(5); + + MmsValue_setElement(cancelParameters, 0, ctlVal); + + int index = 1; + + if (self->hasTimeActivatedMode) { + MmsValue* operTm = MmsValue_newUtcTimeByMsTime(self->opertime); + MmsValue_setElement(cancelParameters, index++, operTm); + } + + MmsValue* origin = createOriginValue(self); + + MmsValue_setElement(cancelParameters, index++, origin); + + MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum); + MmsValue_setElement(cancelParameters, index++, ctlNum); + + uint64_t timestamp; + + if (self->useConstantT) + timestamp = self->constantT; + else + timestamp = Hal_getTimeInMs(); + + MmsValue* ctlTime; + + if (self->edition == 2) { + ctlTime = MmsValue_newUtcTimeByMsTime(timestamp); + + if (self->connection) + MmsValue_setUtcTimeQuality(ctlTime, self->connection->timeQuality); + } + else { + ctlTime = MmsValue_newBinaryTime(false); + MmsValue_setBinaryTime(ctlTime, timestamp); + } + MmsValue_setElement(cancelParameters, index++, ctlTime); + + MmsValue* ctlTest = MmsValue_newBoolean(self->test); + MmsValue_setElement(cancelParameters, index++, ctlTest); + + return cancelParameters; +} + bool ControlObjectClient_cancel(ControlObjectClient self) { @@ -1154,6 +1207,52 @@ ControlObjectClient_cancel(ControlObjectClient self) return true; } +bool +ControlObjectClient_cancelWithValue(ControlObjectClient self, MmsValue* ctlVal) +{ + resetLastApplError(self); + + MmsValue* cancelParameters = createCancelwParameters(self, ctlVal); + + char domainId[65]; + char itemId[65]; + + MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId); + + convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO"); + + strncat(itemId, "$Cancel", 64); + + if (DEBUG_IED_CLIENT) + printf("IED_CLIENT: cancel: %s/%s\n", domainId, itemId); + + MmsError mmsError; + + MmsDataAccessError writeResult = MmsConnection_writeVariable(IedConnection_getMmsConnection(self->connection), + &mmsError, domainId, itemId, cancelParameters); + + self->lastMmsError = mmsError; + self->lastAccessError = writeResult; + + MmsValue_setElement(cancelParameters, 0, NULL); + MmsValue_delete(cancelParameters); + + if (mmsError != MMS_ERROR_NONE) { + if (DEBUG_IED_CLIENT) + printf("IED_CLIENT: cancel failed!\n"); + return false; + } + else { + if (writeResult != DATA_ACCESS_ERROR_SUCCESS) { + if (DEBUG_IED_CLIENT) + printf("IED_CLIENT: cancel failed!\n"); + return false; + } + } + + return true; +} + static void internalCancelHandler(uint32_t invokeId, void* parameter, MmsError err, MmsDataAccessError accessError) {