- added functions SV_ASDU_addFLOAT64 and SV_ASDU_setFLOAT64 to SV publisher

This commit is contained in:
Michael Zillgith 2016-07-25 13:51:47 +02:00
parent c577bb3949
commit 7a5f4a25e2
12 changed files with 241 additions and 44 deletions

View file

@ -2,6 +2,7 @@ MODEL(simpleIO){
LD(GenericIO){
LN(LLN0){
DO(Mod 0){
DA(stVal 0 3 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=0;
@ -17,9 +18,9 @@ DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(NamPlt 0){
DA(vendor 0 20 5 0 0);
DA(swRev 0 20 5 0 0);
DA(d 0 20 5 0 0);
DA(vendor 0 20 5 0 0)="MZ Automation";
DA(swRev 0 20 5 0 0)="0.7.3";
DA(d 0 20 5 0 0)="libiec61850 server example";
DA(configRev 0 20 5 0 0);
DA(ldNs 0 20 11 0 0);
}
@ -29,24 +30,33 @@ DE(GGIO1$ST$SPCSO2$stVal);
DE(GGIO1$ST$SPCSO3$stVal);
DE(GGIO1$ST$SPCSO4$stVal);
}
DS(AnalogValues){
DE(GGIO1$MX$AnIn1);
DE(GGIO1$MX$AnIn2);
DE(GGIO1$MX$AnIn3);
DE(GGIO1$MX$AnIn4);
DS(Events2){
DE(GGIO1$ST$SPCSO1);
DE(GGIO1$ST$SPCSO2);
DE(GGIO1$ST$SPCSO3);
DE(GGIO1$ST$SPCSO4);
}
RC(EventsRCB01 Events 0 Events 1 24 111 50 1000);
RC(AnalogValuesRCB01 AnalogValues 0 AnalogValues 1 24 111 50 1000);
LC(EventLog Events GenericIO/LLN0$EventLog 19 0 0 1)
LC(GeneralLog - - 19 0 0 1)
LOG(GeneralLog)
LOG(EventLog)
GC(gcbEvents events Events 2 0 -1 -1 ){
PA(4 273 4096 010ccd010001);
}
GC(gcbAnalogValues analog AnalogValues 2 0 -1 -1 ){
PA(4 273 4096 010ccd010001);
DS(Measurements){
DE(GGIO1$MX$AnIn1$mag$f);
DE(GGIO1$MX$AnIn1$q);
DE(GGIO1$MX$AnIn2$mag$f);
DE(GGIO1$MX$AnIn2$q);
DE(GGIO1$MX$AnIn3$mag$f);
DE(GGIO1$MX$AnIn3$q);
DE(GGIO1$MX$AnIn4$mag$f);
DE(GGIO1$MX$AnIn4$q);
}
RC(EventsRCB01 Events1 0 Events 4294967295 24 111 50 1000);
RC(EventsIndexed01 Events2 0 Events 1 24 111 50 1000);
RC(EventsIndexed02 Events2 0 Events 1 24 111 50 1000);
RC(EventsIndexed03 Events2 0 Events 1 24 111 50 1000);
RC(Measurements01 Measurements 1 Measurements 1 16 111 50 1000);
RC(Measurements02 Measurements 1 Measurements 1 16 111 50 1000);
RC(Measurements03 Measurements 1 Measurements 1 16 111 50 1000);
LC(EventLog Events GenericIO/LLN0$EventLog 19 0 1 1);
LC(GeneralLog - - 19 0 1 1);
LOG(GeneralLog);
LOG(EventLog);
}
LN(LPHD1){
DO(PhyNam 0){
@ -92,11 +102,11 @@ DA(q 0 23 1 2 0);
DA(t 0 22 1 0 0);
}
DO(AnIn2 0){
DA(mag 0 27 1 1 101){
DA(mag 0 27 1 1 0){
DA(f 0 10 1 1 0);
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 102);
DA(t 0 22 1 0 0);
}
DO(AnIn3 0){
DA(mag 0 27 1 1 0){

View file

@ -20,7 +20,7 @@ void sigint_handler(int signalId)
int
main(int argc, char** argv)
{
SampledValuesPublisher svPublisher = SampledValuesPublisher_create("eth1");
SampledValuesPublisher svPublisher = SampledValuesPublisher_create("vboxnet0");
SV_ASDU asdu1 = SampledValuesPublisher_addASDU(svPublisher, "svpub1", NULL, 1);
@ -51,7 +51,7 @@ main(int argc, char** argv)
SampledValuesPublisher_publish(svPublisher);
Thread_sleep(50);
//Thread_sleep(50);
}
SampledValuesPublisher_destroy(svPublisher);

View file

@ -42,6 +42,11 @@ struct sIedServer
MmsMapping* mmsMapping;
LinkedList clientConnections;
uint8_t writeAccessPolicies;
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore dataModelLock;
#endif
bool running;
};

View file

@ -406,6 +406,10 @@ IedServer_create(IedModel* iedModel)
// self->running = false; /* not required due to CALLOC */
#if (CONFIG_MMS_THREADLESS_STACK != 1)
self->dataModelLock = Semaphore_create(1);
#endif
self->mmsMapping = MmsMapping_create(iedModel);
self->mmsDevice = MmsMapping_getMmsDeviceModel(self->mmsMapping);
@ -477,6 +481,11 @@ IedServer_destroy(IedServer self)
MmsMapping_destroy(self->mmsMapping);
LinkedList_destroyDeep(self->clientConnections, (LinkedListValueDeleteFunction) private_ClientConnection_destroy);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_destroy(self->dataModelLock);
#endif
GLOBAL_FREEMEM(self);
}
@ -891,8 +900,17 @@ IedServer_updateAttributeValue(IedServer self, DataAttribute* dataAttribute, Mms
if (MmsValue_equals(dataAttribute->mmsValue, value))
checkForUpdateTrigger(self, dataAttribute);
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_update(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
}
@ -910,7 +928,13 @@ IedServer_updateFloatAttributeValue(IedServer self, DataAttribute* dataAttribute
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setFloat(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
}
@ -928,7 +952,13 @@ IedServer_updateInt32AttributeValue(IedServer self, DataAttribute* dataAttribute
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setInt32(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
@ -947,7 +977,13 @@ IedServer_updateInt64AttributeValue(IedServer self, DataAttribute* dataAttribute
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setInt64(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
@ -966,7 +1002,13 @@ IedServer_updateUnsignedAttributeValue(IedServer self, DataAttribute* dataAttrib
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setUint32(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
@ -985,7 +1027,13 @@ IedServer_updateBitStringAttributeValue(IedServer self, DataAttribute* dataAttri
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setBitStringFromInteger(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
@ -1005,7 +1053,13 @@ IedServer_updateBooleanAttributeValue(IedServer self, DataAttribute* dataAttribu
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setBoolean(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
@ -1024,7 +1078,13 @@ IedServer_updateVisibleStringAttributeValue(IedServer self, DataAttribute* dataA
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setVisibleString(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
@ -1043,7 +1103,13 @@ IedServer_updateUTCTimeAttributeValue(IedServer self, DataAttribute* dataAttribu
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setUtcTimeMs(dataAttribute->mmsValue, value);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
@ -1060,7 +1126,13 @@ IedServer_updateTimestampAttributeValue(IedServer self, DataAttribute* dataAttri
checkForUpdateTrigger(self, dataAttribute);
}
else {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setUtcTimeByBuffer(dataAttribute->mmsValue, timestamp->val);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
checkForChangedTriggers(self, dataAttribute);
}
@ -1077,8 +1149,15 @@ IedServer_updateQuality(IedServer self, DataAttribute* dataAttribute, Quality qu
uint32_t oldQuality = MmsValue_getBitStringAsInteger(dataAttribute->mmsValue);
if (oldQuality != (uint32_t) quality) {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->dataModelLock);
#endif
MmsValue_setBitStringFromInteger(dataAttribute->mmsValue, (uint32_t) quality);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_post(self->dataModelLock);
#endif
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue);
#endif

View file

@ -542,10 +542,7 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
if (dataSet == NULL) {
/* check if association specific data set is requested */
if (dataSetName[0] == '@') {
if (rc->buffered == false) { /* for buffered report non-permanent datasets are not allowed */
@ -1643,8 +1640,6 @@ printReportId(ReportBufferEntry* report)
static void
removeAllGIReportsFromReportBuffer(ReportBuffer* reportBuffer)
{
printf("removeAllGIReportsFromReportBuffer\n");
ReportBufferEntry* currentReport = reportBuffer->oldestReport;
ReportBufferEntry* lastReport = NULL;
@ -2393,8 +2388,6 @@ Reporting_activateBufferedReports(MmsMapping* self)
static void
processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
{
if ((rc->enabled) || (rc->isBuffering)) {
if (rc->triggerOps & TRG_OPT_GI) {

View file

@ -545,6 +545,29 @@ SV_ASDU_setFLOAT(SV_ASDU self, int index, float value)
}
int
SV_ASDU_addFLOAT64(SV_ASDU self)
{
int index = self->dataSize;
self->dataSize += 8;
return index;
}
void
SV_ASDU_setFLOAT64(SV_ASDU self, int index, double value)
{
uint8_t* buf = (uint8_t*) &value;
#if (ORDER_LITTLE_ENDIAN == 1)
BerEncoder_revertByteOrder(buf, 8);
#endif
int i;
uint8_t* buffer = self->_dataBuffer + index;
for (i = 0; i < 8; i++) {
buffer[i] = buf[i];
}
}
void
SV_ASDU_setSmpCnt(SV_ASDU self, uint16_t value)
{

View file

@ -80,6 +80,12 @@ SV_ASDU_addFLOAT(SV_ASDU self);
void
SV_ASDU_setFLOAT(SV_ASDU self, int index, float value);
int
SV_ASDU_addFLOAT64(SV_ASDU self);
void
SV_ASDU_setFLOAT64(SV_ASDU self, int index, double value);
void
SV_ASDU_setSmpCnt(SV_ASDU self, uint16_t value);

View file

@ -547,3 +547,5 @@ EXPORTS
IedConnection_queryLogByTime
IedConnection_queryLogAfter
CDC_DPL_create
SV_ASDU_addFLOAT64
SV_ASDU_setFLOAT64

View file

@ -623,3 +623,5 @@ EXPORTS
IedConnection_queryLogByTime
IedConnection_queryLogAfter
CDC_DPL_create
SV_ASDU_addFLOAT64
SV_ASDU_setFLOAT64

Binary file not shown.

View file

@ -11,10 +11,13 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import com.libiec61850.scl.DataAttributeDefinition;
import com.libiec61850.scl.DataObjectDefinition;
import com.libiec61850.scl.SclParser;
import com.libiec61850.scl.SclParserException;
import com.libiec61850.scl.model.AttributeType;
import com.libiec61850.scl.model.LogicalNode;
import com.libiec61850.scl.types.DataAttributeType;
import com.libiec61850.scl.types.DataObjectType;
import com.libiec61850.scl.types.LogicalNodeType;
import com.libiec61850.scl.types.SclType;
@ -76,25 +79,48 @@ public class DynamicCodeGenerator {
Set<DataObjectType> doTypeDefs = new HashSet<DataObjectType>();
Set<LogicalNodeType> lnTypeDefs = new HashSet<LogicalNodeType>();
Set<DataAttributeType> daTypeDefs = new HashSet<DataAttributeType>();
List<String> functionPrototypes = new LinkedList<String>();
List<SclType> types = declarations.getTypeDeclarations();
/* Create type lists */
for (SclType type : types) {
for (SclType type : declarations.getTypeDeclarations()) {
if (type.getClass().equals(LogicalNodeType.class))
lnTypeDefs.add((LogicalNodeType) type);
else if (type.getClass().equals(DataObjectType.class))
doTypeDefs.add((DataObjectType) type);
else if (type.getClass().equals(DataAttributeType.class))
daTypeDefs.add((DataAttributeType) type);
}
/* Create function prototypes */
for (LogicalNodeType lnType : lnTypeDefs) {
String functionPrototype = "LogicalNode*\nLN_" + lnType.getId()
+ "_createInstance(char* lnName, LogicalDevice* parent);";
functionPrototypes.add(functionPrototype);
}
for (DataObjectType doType : doTypeDefs) {
String functionPrototype = "DataObject*\nDO_" + doType.getId()
+ "_createInstance(char* doName, ModelNode* parent);";
functionPrototypes.add(functionPrototype);
}
for (DataAttributeType daType : daTypeDefs) {
String functionPrototype = "DataAttribute*\nDA_" + daType.getId()
+ "_createInstance(char* daName, ModelNode* parent, FunctionalConstraint fc, uint8_t triggerOptions);";
functionPrototypes.add(functionPrototype);
}
for (LogicalNodeType lnType : lnTypeDefs) {
out.println("/**");
out.printf(" * LN: %s ", lnType.getId());
@ -109,7 +135,7 @@ public class DynamicCodeGenerator {
List<DataObjectDefinition> doDefs = lnType.getDataObjectDefinitions();
for (DataObjectDefinition objDef : doDefs) {
out.printf(" %s_createInstance(\"%s\", (ModelNode*) newLn);\n", objDef.getType(), objDef.getName());
out.printf(" DO_%s_createInstance(\"%s\", (ModelNode*) newLn);\n", objDef.getType(), objDef.getName());
}
out.println("\n return newLn;");
@ -117,11 +143,6 @@ public class DynamicCodeGenerator {
}
for (DataObjectType doType : doTypeDefs) {
String functionPrototype = "DataObject*\nDO_" + doType.getId()
+ "_createInstance(char* doName, ModelNode* parent);";
functionPrototypes.add(functionPrototype);
out.println("/**");
out.printf(" * DO: %s ", doType.getId());
if (doType.getDesc() != null)
@ -131,12 +152,70 @@ public class DynamicCodeGenerator {
out.println("DataObject*");
out.printf("DO_%s_createInstance(char* doName, ModelNode* parent)\n", doType.getId());
out.println("{");
out.println(" LogicalNode* newDo = DataObject_create(doName, parent);\n");
out.println(" DataObject* newDo = DataObject_create(doName, parent);\n");
for (DataAttributeDefinition dad : doType.getDataAttributes()) {
if (dad.getAttributeType() == AttributeType.CONSTRUCTED) {
out.print(" DA_" + dad.getType() + "_createInstance(\"" + dad.getName() + "\", ");
out.print("(ModelNode*) newDo, IEC61850_FC_" + dad.getFc().toString());
out.print(", " + dad.getTriggerOptions().getIntValue());
out.println(");");
}
else {
out.print(" DataAttribute_create(\"" + dad.getName() + "\", ");
out.print("(ModelNode*) newDo, IEC61850_" + dad.getAttributeType());
out.print(", IEC61850_FC_" + dad.getFc().toString());
out.print(", " + dad.getTriggerOptions().getIntValue());
out.print(", " + dad.getCount());
out.print(", 0");
out.println(");");
}
}
for (DataObjectDefinition dod : doType.getSubDataObjects()) {
out.print(" DO_" + dod.getType() + "_createInstance(\"" + dod.getName() + "\")");
out.println("(ModelNode*) newDo);");
}
out.println("\n return newDo;");
out.println("}\n\n");
}
for (DataAttributeType daType : daTypeDefs) {
out.println("/**");
out.printf(" * DA: %s ", daType.getId());
if (daType.getDesc() != null)
out.printf("(%s)", daType.getDesc());
out.println();
out.println(" */");
out.println("DataAttribute*");
out.printf("DA_%s_createInstance(char* daName, ModelNode* parent, FunctionalConstraint fc, uint8_t triggerOptions)\n", daType.getId());
out.println("{");
out.println(" DataAttribute* newDa = DataAttribute_create(daName, parent, IEC61850_CONSTRUCTED, fc, triggerOptions, 0, 0);\n");
for (DataAttributeDefinition dad : daType.getSubDataAttributes()) {
if (dad.getAttributeType() == AttributeType.CONSTRUCTED) {
out.print(" DA_" + dad.getType() + "_createInstance(\"" + dad.getName() + "\", ");
out.println("(ModelNode*) newDo, fc, triggerOptions);");
}
else {
out.print(" DataAttribute_create(\"" + dad.getName() + "\", ");
out.print("(ModelNode*) newDa, IEC61850_" + dad.getAttributeType());
out.print(", fc");
out.print(", triggerOptions");
out.print(", " + dad.getCount());
out.print(", 0");
out.println(");");
}
}
out.println("\n return newDo;");
out.println("}\n\n");
}
}

View file

@ -706,10 +706,8 @@ public class StaticModelGenerator {
cOut.println("};\n");
if (dataAttribute.getSubDataAttributes() != null)
printDataAttributeDefinitions(daName, dataAttribute.getSubDataAttributes());
if (dataAttribute.getSubDataAttributes() != null)
printDataAttributeDefinitions(daName, dataAttribute.getSubDataAttributes());
DataModelValue value = dataAttribute.getValue();