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

pull/254/head
Michael Zillgith 5 years ago
parent 033ab5b648
commit 44872d3a3e

@ -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;

@ -69,6 +69,17 @@
<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" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn2" />
@ -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
@ -717,6 +718,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);

@ -71,6 +71,8 @@ struct sMmsGooseControlBlock {
char* dataSetRef;
char* gooseInterfaceId;
bool stateChangePending;
};
MmsGooseControlBlock
@ -257,6 +259,7 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self)
else
self->publisher = GoosePublisher_createEx(&commParameters, self->mmsMapping->gooseInterfaceId, self->useVlanTag);
if (self->publisher) {
self->minTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 6));
self->maxTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 7));
@ -289,6 +292,12 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self)
self->goEna = true;
}
else {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: Failed to create GOOSE publisher!\n");
}
}
}
@ -363,8 +372,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
@ -386,10 +402,13 @@ 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*
createMmsGooseControlBlock(char* gcbName)
@ -496,6 +515,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)
@ -606,6 +639,8 @@ GOOSE_createGOOSEControlBlocks(MmsMapping* self, MmsDomain* domain,
mmsGCB->mmsMapping = self;
mmsGCB->stateChangePending = false;
LinkedList_add(self->gseControls, mmsGCB);
currentGCB++;

@ -2921,6 +2921,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;
@ -2928,7 +2930,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);
}
}
}
}

@ -1029,6 +1029,7 @@ public class StaticModelGenerator {
GSE gse = connectedAP.lookupGSE(logicalDeviceName, gseControlBlock.getName());
if (gse != null) {
PhyComAddress gseAddress = gse.getAddress();
String gseString = "";
@ -1100,6 +1101,11 @@ public class StaticModelGenerator {
gseControlNumber++;
}
else {
System.out.println("GSE not found for GoCB " + gseControlBlock.getName());
}
}
}
private String getIpAddressByIedName(SclParser sclParser, String iedName, String apRef)

Loading…
Cancel
Save