- IED Server/GOOSE: Don't send GOOSE message with new event while data model is locked

pull/265/head
Michael Zillgith 5 years ago
parent 805d73b86f
commit 9ab37e9836

@ -104,6 +104,8 @@ int main(int argc, char** argv) {
float anIn1 = 0.f;
int eventCount = 10;
while (running) {
IedServer_lockDataModel(iedServer);
@ -111,6 +113,21 @@ int main(int argc, char** argv) {
IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_t, Hal_getTimeInMs());
IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_mag_f, anIn1);
if (eventCount) {
IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4_t, Hal_getTimeInMs());
if (eventCount % 2) {
IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4_q, QUALITY_VALIDITY_GOOD);
IedServer_updateBooleanAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4_stVal, true);
}
else {
IedServer_updateQuality(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4_q, QUALITY_VALIDITY_INVALID);
IedServer_updateBooleanAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4_stVal, false);
}
eventCount--;
}
IedServer_unlockDataModel(iedServer);
anIn1 += 0.1;

@ -68,6 +68,17 @@
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" />
</DataSet>
<DataSet name="Events3" desc="Events3">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" daName="q" />
</DataSet>
<DataSet name="AnalogValues" desc="analog values">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn1" />
@ -88,7 +99,7 @@
<RptEnabled max="1" />
</ReportControl>
<GSEControl appID="events" name="gcbEvents" type="GOOSE" datSet="Events" confRev="2" />
<GSEControl appID="events" name="gcbEvents" type="GOOSE" datSet="Events3" confRev="2" />
<GSEControl appID="analog" name="gcbAnalogValues" type="GOOSE" datSet="AnalogValues" confRev="2"/>
<DOI name="Mod">

@ -9,6 +9,7 @@ static void initializeValues();
extern DataSet iedModelds_GenericIO_LLN0_Events;
extern DataSet iedModelds_GenericIO_LLN0_Events2;
extern DataSet iedModelds_GenericIO_LLN0_Events3;
extern DataSet iedModelds_GenericIO_LLN0_AnalogValues;
@ -115,6 +116,103 @@ DataSet iedModelds_GenericIO_LLN0_Events2 = {
"LLN0$Events2",
4,
&iedModelds_GenericIO_LLN0_Events2_fcda0,
&iedModelds_GenericIO_LLN0_Events3
};
extern DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda0;
extern DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda1;
extern DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda2;
extern DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda3;
extern DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda4;
extern DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda5;
extern DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda6;
extern DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda7;
DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda0 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO1$stVal",
-1,
NULL,
NULL,
&iedModelds_GenericIO_LLN0_Events3_fcda1
};
DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda1 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO1$q",
-1,
NULL,
NULL,
&iedModelds_GenericIO_LLN0_Events3_fcda2
};
DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda2 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO2$stVal",
-1,
NULL,
NULL,
&iedModelds_GenericIO_LLN0_Events3_fcda3
};
DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda3 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO2$q",
-1,
NULL,
NULL,
&iedModelds_GenericIO_LLN0_Events3_fcda4
};
DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda4 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO3$stVal",
-1,
NULL,
NULL,
&iedModelds_GenericIO_LLN0_Events3_fcda5
};
DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda5 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO3$q",
-1,
NULL,
NULL,
&iedModelds_GenericIO_LLN0_Events3_fcda6
};
DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda6 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO4$stVal",
-1,
NULL,
NULL,
&iedModelds_GenericIO_LLN0_Events3_fcda7
};
DataSetEntry iedModelds_GenericIO_LLN0_Events3_fcda7 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO4$q",
-1,
NULL,
NULL,
NULL
};
DataSet iedModelds_GenericIO_LLN0_Events3 = {
"GenericIO",
"LLN0$Events3",
8,
&iedModelds_GenericIO_LLN0_Events3_fcda0,
&iedModelds_GenericIO_LLN0_AnalogValues
};
@ -1896,7 +1994,7 @@ static PhyComAddress iedModel_GenericIO_LLN0_gse0_address = {
{0x1, 0xc, 0xcd, 0x1, 0x0, 0x1}
};
GSEControlBlock iedModel_GenericIO_LLN0_gse0 = {&iedModel_GenericIO_LLN0, "gcbEvents", "events", "Events", 2, false, &iedModel_GenericIO_LLN0_gse0_address, 1000, 3000, &iedModel_GenericIO_LLN0_gse1};
GSEControlBlock iedModel_GenericIO_LLN0_gse0 = {&iedModel_GenericIO_LLN0, "gcbEvents", "events", "Events3", 2, false, &iedModel_GenericIO_LLN0_gse0_address, 1000, 3000, &iedModel_GenericIO_LLN0_gse1};
static PhyComAddress iedModel_GenericIO_LLN0_gse1_address = {
4,

@ -69,7 +69,10 @@ LIB61850_INTERNAL void
MmsGooseControlBlock_checkAndPublish(MmsGooseControlBlock self, uint64_t currentTime);
LIB61850_INTERNAL void
MmsGooseControlBlock_observedObjectChanged(MmsGooseControlBlock self);
MmsGooseControlBlock_setStateChangePending(MmsGooseControlBlock self);
LIB61850_INTERNAL void
MmsGooseControlBlock_publishNewState(MmsGooseControlBlock self);
LIB61850_INTERNAL void
MmsGooseControlBlock_enable(MmsGooseControlBlock self);
@ -77,6 +80,9 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self);
LIB61850_INTERNAL void
MmsGooseControlBlock_disable(MmsGooseControlBlock self);
LIB61850_INTERNAL void
GOOSE_sendPendingEvents(MmsMapping* self);
LIB61850_INTERNAL MmsVariableSpecification*
GOOSE_createGOOSEControlBlocks(MmsMapping* self, MmsDomain* domain,
LogicalNode* logicalNode, int gseCount);

@ -34,6 +34,7 @@
#include "libiec61850_platform_includes.h"
#include "mms_sv.h"
#include "mms_goose.h"
#ifndef DEBUG_IED_SERVER
#define DEBUG_IED_SERVER 0
@ -728,6 +729,11 @@ IedServer_lockDataModel(IedServer self)
void
IedServer_unlockDataModel(IedServer self)
{
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
/* check if GOOSE messages have to be sent */
GOOSE_sendPendingEvents(self->mmsMapping);
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
/* check if reports have to be sent! */
Reporting_processReportEventsAfterUnlock(self->mmsMapping);

@ -72,6 +72,8 @@ struct sMmsGooseControlBlock {
char* dataSetRef;
char* gooseInterfaceId;
bool stateChangePending;
};
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
@ -357,43 +359,50 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self)
else
self->publisher = GoosePublisher_createEx(&commParameters, self->mmsMapping->gooseInterfaceId, self->useVlanTag);
self->minTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 6));
self->maxTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 7));
if (self->publisher) {
self->minTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 6));
self->maxTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 7));
GoosePublisher_setTimeAllowedToLive(self->publisher, self->maxTime * 3);
GoosePublisher_setTimeAllowedToLive(self->publisher, self->maxTime * 3);
GoosePublisher_setDataSetRef(self->publisher, self->dataSetRef);
GoosePublisher_setDataSetRef(self->publisher, self->dataSetRef);
GoosePublisher_setGoCbRef(self->publisher, self->goCBRef);
GoosePublisher_setGoCbRef(self->publisher, self->goCBRef);
uint32_t confRev = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 3));
uint32_t confRev = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 3));
GoosePublisher_setConfRev(self->publisher, confRev);
GoosePublisher_setConfRev(self->publisher, confRev);
bool needsCom = MmsValue_getBoolean(MmsValue_getElement(self->mmsValue, 4));
bool needsCom = MmsValue_getBoolean(MmsValue_getElement(self->mmsValue, 4));
GoosePublisher_setNeedsCommission(self->publisher, needsCom);
GoosePublisher_setNeedsCommission(self->publisher, needsCom);
if (self->goId != NULL)
GoosePublisher_setGoID(self->publisher, self->goId);
if (self->goId != NULL)
GoosePublisher_setGoID(self->publisher, self->goId);
/* prepare data set values */
self->dataSetValues = LinkedList_create();
/* prepare data set values */
self->dataSetValues = LinkedList_create();
DataSetEntry* dataSetEntry = self->dataSet->fcdas;
DataSetEntry* dataSetEntry = self->dataSet->fcdas;
while (dataSetEntry != NULL) {
LinkedList_add(self->dataSetValues, dataSetEntry->value);
dataSetEntry = dataSetEntry->sibling;
}
while (dataSetEntry != NULL) {
LinkedList_add(self->dataSetValues, dataSetEntry->value);
dataSetEntry = dataSetEntry->sibling;
}
self->goEna = true;
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);
MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS;
copyGCBValuesToTrackingObject(self);
updateGenericTrackingObjectValues(self, IEC61850_SERVICE_TYPE_SET_GOCB_VALUES, retVal);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
}
else {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: Failed to create GOOSE publisher!\n");
}
}
}
@ -475,8 +484,15 @@ MmsGooseControlBlock_checkAndPublish(MmsGooseControlBlock self, uint64_t current
}
void
MmsGooseControlBlock_observedObjectChanged(MmsGooseControlBlock self)
MmsGooseControlBlock_setStateChangePending(MmsGooseControlBlock self)
{
self->stateChangePending = true;
}
void
MmsGooseControlBlock_publishNewState(MmsGooseControlBlock self)
{
if (self->stateChangePending) {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->publisherMutex);
#endif
@ -498,9 +514,12 @@ MmsGooseControlBlock_observedObjectChanged(MmsGooseControlBlock self)
GoosePublisher_publish(self->publisher, self->dataSetValues);
self->stateChangePending = false;
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->publisherMutex);
#endif
}
}
static MmsVariableSpecification*
@ -608,6 +627,20 @@ createDataSetReference(char* domainName, char* lnName, char* dataSetName)
return dataSetReference;
}
void
GOOSE_sendPendingEvents(MmsMapping* self)
{
LinkedList element = self->gseControls;
while ((element = LinkedList_getNext(element)) != NULL) {
MmsGooseControlBlock gcb = (MmsGooseControlBlock) element->data;
if (MmsGooseControlBlock_isEnabled(gcb)) {
MmsGooseControlBlock_publishNewState(gcb);
}
}
}
MmsVariableSpecification*
GOOSE_createGOOSEControlBlocks(MmsMapping* self, MmsDomain* domain,
LogicalNode* logicalNode, int gseCount)
@ -718,6 +751,8 @@ GOOSE_createGOOSEControlBlocks(MmsMapping* self, MmsDomain* domain,
mmsGCB->mmsMapping = self;
mmsGCB->stateChangePending = false;
LinkedList_add(self->gseControls, mmsGCB);
currentGCB++;

@ -3509,6 +3509,8 @@ MmsMapping_triggerGooseObservers(MmsMapping* self, MmsValue* value)
{
LinkedList element = self->gseControls;
bool modelLocked = self->isModelLocked;
while ((element = LinkedList_getNext(element)) != NULL) {
MmsGooseControlBlock gcb = (MmsGooseControlBlock) element->data;
@ -3516,7 +3518,11 @@ MmsMapping_triggerGooseObservers(MmsMapping* self, MmsValue* value)
DataSet* dataSet = MmsGooseControlBlock_getDataSet(gcb);
if (DataSet_isMemberValue(dataSet, value, NULL)) {
MmsGooseControlBlock_observedObjectChanged(gcb);
MmsGooseControlBlock_setStateChangePending(gcb);
if (modelLocked == false) {
MmsGooseControlBlock_publishNewState(gcb);
}
}
}
}

@ -1028,77 +1028,83 @@ public class StaticModelGenerator {
for (GSEControl gseControlBlock : gseControlBlocks) {
GSE gse = connectedAP.lookupGSE(logicalDeviceName, gseControlBlock.getName());
PhyComAddress gseAddress = gse.getAddress();
String gseString = "";
if (gse != null) {
PhyComAddress gseAddress = gse.getAddress();
String gseString = "";
String phyComAddrName = "";
String phyComAddrName = "";
if (gseAddress != null) {
phyComAddrName = lnPrefix + "_gse" + gseControlNumber + "_address";
if (gseAddress != null) {
phyComAddrName = lnPrefix + "_gse" + gseControlNumber + "_address";
gseString += "\nstatic PhyComAddress " + phyComAddrName + " = {\n";
gseString += " " + gseAddress.getVlanPriority() + ",\n";
gseString += " " + gseAddress.getVlanId() + ",\n";
gseString += " " + gseAddress.getAppId() + ",\n";
gseString += " {";
gseString += "\nstatic PhyComAddress " + phyComAddrName + " = {\n";
gseString += " " + gseAddress.getVlanPriority() + ",\n";
gseString += " " + gseAddress.getVlanId() + ",\n";
gseString += " " + gseAddress.getAppId() + ",\n";
gseString += " {";
for (int i = 0; i < 6; i++) {
gseString += "0x" + Integer.toHexString(gseAddress.getMacAddress()[i]);
if (i == 5)
gseString += "}\n";
else
gseString += ", ";
for (int i = 0; i < 6; i++) {
gseString += "0x" + Integer.toHexString(gseAddress.getMacAddress()[i]);
if (i == 5)
gseString += "}\n";
else
gseString += ", ";
}
gseString += "};\n\n";
}
gseString += "};\n\n";
}
String gseVariableName = lnPrefix + "_gse" + gseControlNumber;
String gseVariableName = lnPrefix + "_gse" + gseControlNumber;
gseString += "GSEControlBlock " + gseVariableName + " = {";
gseString += "&" + lnPrefix + ", ";
gseString += "GSEControlBlock " + gseVariableName + " = {";
gseString += "&" + lnPrefix + ", ";
gseString += "\"" + gseControlBlock.getName() + "\", ";
gseString += "\"" + gseControlBlock.getName() + "\", ";
if (gseControlBlock.getAppID() == null)
gseString += "NULL, ";
else
gseString += "\"" + gseControlBlock.getAppID() + "\", ";
if (gseControlBlock.getAppID() == null)
gseString += "NULL, ";
else
gseString += "\"" + gseControlBlock.getAppID() + "\", ";
if (gseControlBlock.getDataSet() != null)
gseString += "\"" + gseControlBlock.getDataSet() + "\", ";
else
gseString += "NULL, ";
if (gseControlBlock.getDataSet() != null)
gseString += "\"" + gseControlBlock.getDataSet() + "\", ";
else
gseString += "NULL, ";
gseString += gseControlBlock.getConfRev() + ", ";
gseString += gseControlBlock.getConfRev() + ", ";
if (gseControlBlock.isFixedOffs())
gseString += "true, ";
else
gseString += "false, ";
if (gseControlBlock.isFixedOffs())
gseString += "true, ";
else
gseString += "false, ";
if (gseAddress != null)
gseString += "&" + phyComAddrName + ", ";
else
gseString += "NULL, ";
gseString += gse.getMinTime() + ", ";
gseString += gse.getMaxTime() + ", ";
if (gseAddress != null)
gseString += "&" + phyComAddrName + ", ";
else
gseString += "NULL, ";
gseString += gse.getMinTime() + ", ";
gseString += gse.getMaxTime() + ", ";
currentGseVariableNumber++;
if (currentGseVariableNumber < gseVariableNames.size())
gseString += "&" + gseVariableNames.get(currentGseVariableNumber);
else
gseString += "NULL";
currentGseVariableNumber++;
if (currentGseVariableNumber < gseVariableNames.size())
gseString += "&" + gseVariableNames.get(currentGseVariableNumber);
else
gseString += "NULL";
gseString += "};\n";
gseString += "};\n";
this.gseControlBlocks.append(gseString);
this.gseControlBlocks.append(gseString);
gseControlNumber++;
}
else {
System.out.println("GSE not found for GoCB " + gseControlBlock.getName());
}
gseControlNumber++;
}
}

Loading…
Cancel
Save