- IEC 61850 server: made IEC 61850 edition configurable at runtime

pull/72/head
Michael Zillgith 7 years ago
parent 6199da1e55
commit 26af0d93c2

@ -29,6 +29,13 @@ namespace IEC61850
namespace Common namespace Common
{ {
public enum Iec61850Edition : byte
{
EDITION_1 = 0,
EDITION_2 = 1,
EDITION_2_1 = 2
}
public class LibIEC61850 public class LibIEC61850
{ {
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]

@ -23,6 +23,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850.Server namespace IEC61850.Server
{ {
@ -49,6 +50,12 @@ namespace IEC61850.Server
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedServerConfig_getFileServiceBasePath(IntPtr self); static extern IntPtr IedServerConfig_getFileServiceBasePath(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setEdition(IntPtr self, byte edition);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte IedServerConfig_getEdition(IntPtr self);
internal IntPtr self; internal IntPtr self;
public IedServerConfig () public IedServerConfig ()
@ -84,6 +91,16 @@ namespace IEC61850.Server
} }
} }
public Iec61850Edition Edition
{
get {
return (Iec61850Edition)IedServerConfig_getEdition (self);
}
set {
IedServerConfig_setEdition (self, (byte) value);
}
}
/// <summary> /// <summary>
/// Releases all resource used by the <see cref="IEC61850.Server.IedServerConfig"/> object. /// Releases all resource used by the <see cref="IEC61850.Server.IedServerConfig"/> object.
/// </summary> /// </summary>

@ -90,6 +90,8 @@ main(int argc, char** argv)
/* Set buffer size for buffered report control blocks to 200000 bytes */ /* Set buffer size for buffered report control blocks to 200000 bytes */
IedServerConfig_setReportBufferSize(config, 200000); IedServerConfig_setReportBufferSize(config, 200000);
IedServerConfig_setEdition(config, IEC_61850_EDITION_2);
/* Set the base path for the MMS file services */ /* Set the base path for the MMS file services */
IedServerConfig_setFileServiceBasePath(config, "./vmd-filestore/"); IedServerConfig_setFileServiceBasePath(config, "./vmd-filestore/");

@ -37,6 +37,15 @@ extern "C" {
*/ */
/**@{*/ /**@{*/
/** IEC 61850 edition 1 */
#define IEC_61850_EDITION_1 0
/** IEC 61850 edition 2 */
#define IEC_61850_EDITION_2 1
/** IEC 61850 edition 2.1 */
#define IEC_61850_EDITION_2_1 2
/** PhyComAddress type contains Ethernet address and VLAN attributes */ /** PhyComAddress type contains Ethernet address and VLAN attributes */
typedef struct { typedef struct {
uint8_t vlanPriority; uint8_t vlanPriority;

@ -62,6 +62,9 @@ struct sIedServerConfig
/** when true (default) enable log service */ /** when true (default) enable log service */
bool enableLogService; bool enableLogService;
/** IEC 61850 edition (0 = edition 1, 1 = edition 2, 2 = edition 2.1, ...) */
uint8_t edition;
}; };
/** /**
@ -78,6 +81,22 @@ IedServerConfig_create(void);
void void
IedServerConfig_destroy(IedServerConfig self); IedServerConfig_destroy(IedServerConfig self);
/**
* \brief Set the IEC 61850 standard edition to use (default is edition 2)
*
* \param edition IEC_61850_EDITION_1, IEC_61850_EDITION_2, or IEC_61850_EDITION_2_1
*/
void
IedServerConfig_setEdition(IedServerConfig self, uint8_t edition);
/**
* \brief Get the configued IEC 61850 standard edition
*
* \returns IEC_61850_EDITION_1, IEC_61850_EDITION_2, or IEC_61850_EDITION_2_1
*/
uint8_t
IedServerConfig_getEdition(IedServerConfig self);
/** /**
* \brief Set the report buffer size for buffered reporting * \brief Set the report buffer size for buffered reporting
* *

@ -55,6 +55,8 @@ struct sIedServer
bool logServiceEnabled; bool logServiceEnabled;
#endif #endif
uint8_t edition;
bool running; bool running;
}; };

@ -94,10 +94,12 @@ typedef struct {
ReportBuffer* reportBuffer; ReportBuffer* reportBuffer;
MmsValue* timeOfEntry; MmsValue* timeOfEntry;
IedServer server;
} ReportControl; } ReportControl;
ReportControl* ReportControl*
ReportControl_create(bool buffered, LogicalNode* parentLN, int reportBufferSize); ReportControl_create(bool buffered, LogicalNode* parentLN, int reportBufferSize, IedServer server);
void void
ReportControl_destroy(ReportControl* self); ReportControl_destroy(ReportControl* self);

@ -400,12 +400,20 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
self->running = false; self->running = false;
self->localIpAddress = NULL; self->localIpAddress = NULL;
#if (CONFIG_IEC61850_EDITION_1 == 1)
self->edition = IEC_61850_EDITION_1;
#else
self->edition = IEC_61850_EDITION_2;
#endif
#if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1)
self->logServiceEnabled = true; self->logServiceEnabled = true;
if (serverConfiguration) { if (serverConfiguration) {
self->logServiceEnabled = serverConfiguration->enableLogService; self->logServiceEnabled = serverConfiguration->enableLogService;
self->edition = serverConfiguration->edition;
} }
#endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */
#if (CONFIG_MMS_THREADLESS_STACK != 1) #if (CONFIG_MMS_THREADLESS_STACK != 1)
@ -430,12 +438,10 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
MmsServer_enableFileService(self->mmsServer, serverConfiguration->enableFileService); MmsServer_enableFileService(self->mmsServer, serverConfiguration->enableFileService);
MmsServer_enableDynamicNamedVariableListService(self->mmsServer, serverConfiguration->enableDynamicDataSetService); MmsServer_enableDynamicNamedVariableListService(self->mmsServer, serverConfiguration->enableDynamicDataSetService);
MmsServer_enableJournalService(self->mmsServer, serverConfiguration->enableLogService); MmsServer_enableJournalService(self->mmsServer, serverConfiguration->enableLogService);
MmsServer_setFilestoreBasepath(self->mmsServer, serverConfiguration->fileServiceBasepath);
} }
#endif #endif
if (serverConfiguration)
MmsServer_setFilestoreBasepath(self->mmsServer, serverConfiguration->fileServiceBasepath);
MmsMapping_setMmsServer(self->mmsMapping, self->mmsServer); MmsMapping_setMmsServer(self->mmsMapping, self->mmsServer);
MmsMapping_installHandlers(self->mmsMapping); MmsMapping_installHandlers(self->mmsMapping);

@ -35,6 +35,7 @@ IedServerConfig_create()
self->enableFileService = true; self->enableFileService = true;
self->enableDynamicDataSetService = true; self->enableDynamicDataSetService = true;
self->enableLogService = true; self->enableLogService = true;
self->edition = IEC_61850_EDITION_2;
} }
return self; return self;
@ -47,6 +48,18 @@ IedServerConfig_destroy(IedServerConfig self)
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
void
IedServerConfig_setEdition(IedServerConfig self, uint8_t edition)
{
self->edition = edition;
}
uint8_t
IedServerConfig_getEdition(IedServerConfig self)
{
return self->edition;
}
void void
IedServerConfig_setReportBufferSize(IedServerConfig self, int reportBufferSize) IedServerConfig_setReportBufferSize(IedServerConfig self, int reportBufferSize)
{ {

@ -47,11 +47,6 @@
#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 0 #define CONFIG_IEC61850_BRCB_WITH_RESVTMS 0
#endif #endif
#ifndef CONFIG_IEC61850_EDITION_1
#define CONFIG_IEC61850_EDITION_1 0
#endif
static ReportBuffer* static ReportBuffer*
ReportBuffer_create(int bufferSize) ReportBuffer_create(int bufferSize)
{ {
@ -84,7 +79,7 @@ ReportBuffer_destroy(ReportBuffer* self)
} }
ReportControl* ReportControl*
ReportControl_create(bool buffered, LogicalNode* parentLN, int reportBufferSize) ReportControl_create(bool buffered, LogicalNode* parentLN, int reportBufferSize, IedServer iedServer)
{ {
ReportControl* self = (ReportControl*) GLOBAL_MALLOC(sizeof(ReportControl)); ReportControl* self = (ReportControl*) GLOBAL_MALLOC(sizeof(ReportControl));
self->name = NULL; self->name = NULL;
@ -119,6 +114,8 @@ ReportControl_create(bool buffered, LogicalNode* parentLN, int reportBufferSize)
self->valueReferences = NULL; self->valueReferences = NULL;
self->lastEntryId = 0; self->lastEntryId = 0;
self->server = iedServer;
if (buffered) { if (buffered) {
self->reportBuffer = ReportBuffer_create(reportBufferSize); self->reportBuffer = ReportBuffer_create(reportBufferSize);
} }
@ -251,17 +248,21 @@ ReportControl_getRCBValue(ReportControl* rc, char* elementName)
return MmsValue_getElement(rc->rcbValues, 11); return MmsValue_getElement(rc->rcbValues, 11);
else if (strcmp(elementName, "TimeofEntry") == 0) else if (strcmp(elementName, "TimeofEntry") == 0)
return MmsValue_getElement(rc->rcbValues, 12); return MmsValue_getElement(rc->rcbValues, 12);
#if (CONFIG_IEC61850_EDITION_1 == 0)
if (rc->server->edition >= IEC_61850_EDITION_2) {
#if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) #if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1)
else if (strcmp(elementName, "ResvTms") == 0) if (strcmp(elementName, "ResvTms") == 0)
return MmsValue_getElement(rc->rcbValues, 13); return MmsValue_getElement(rc->rcbValues, 13);
else if (strcmp(elementName, "Owner") == 0) if (strcmp(elementName, "Owner") == 0)
return MmsValue_getElement(rc->rcbValues, 14); return MmsValue_getElement(rc->rcbValues, 14);
#else #else
else if (strcmp(elementName, "Owner") == 0) if (strcmp(elementName, "Owner") == 0)
return MmsValue_getElement(rc->rcbValues, 13); return MmsValue_getElement(rc->rcbValues, 13);
#endif #endif
#endif }
} else { } else {
if (strcmp(elementName, "RptID") == 0) if (strcmp(elementName, "RptID") == 0)
return MmsValue_getElement(rc->rcbValues, 0); return MmsValue_getElement(rc->rcbValues, 0);
@ -819,11 +820,12 @@ createUnbufferedReportControlBlock(ReportControlBlock* reportControlBlock,
mmsValue->deleteValue = false; mmsValue->deleteValue = false;
mmsValue->type = MMS_STRUCTURE; mmsValue->type = MMS_STRUCTURE;
#if ((CONFIG_IEC61850_EDITION_1 == 0)) int structSize;
int structSize = 12;
#else if (reportControl->server->edition >= IEC_61850_EDITION_2)
int structSize = 11; structSize = 12;
#endif else
structSize = 11;
mmsValue->value.structure.size = structSize; mmsValue->value.structure.size = structSize;
mmsValue->value.structure.components = (MmsValue**) GLOBAL_CALLOC(structSize, sizeof(MmsValue*)); mmsValue->value.structure.components = (MmsValue**) GLOBAL_CALLOC(structSize, sizeof(MmsValue*));
@ -925,14 +927,14 @@ createUnbufferedReportControlBlock(ReportControlBlock* reportControlBlock,
rcb->typeSpec.structure.elements[10] = namedVariable; rcb->typeSpec.structure.elements[10] = namedVariable;
mmsValue->value.structure.components[10] = MmsValue_newBoolean(false); mmsValue->value.structure.components[10] = MmsValue_newBoolean(false);
#if (CONFIG_IEC61850_EDITION_1 == 0) if (reportControl->server->edition >= IEC_61850_EDITION_2) {
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = StringUtils_copyString("Owner"); namedVariable->name = StringUtils_copyString("Owner");
namedVariable->type = MMS_OCTET_STRING; namedVariable->type = MMS_OCTET_STRING;
namedVariable->typeSpec.octetString = -64; namedVariable->typeSpec.octetString = -64;
rcb->typeSpec.structure.elements[11] = namedVariable; rcb->typeSpec.structure.elements[11] = namedVariable;
mmsValue->value.structure.components[11] = MmsValue_newOctetString(0, 128); mmsValue->value.structure.components[11] = MmsValue_newOctetString(0, 128);
#endif /* (CONFIG_IEC61850_EDITION_1 == 0) */ }
reportControl->rcbValues = mmsValue; reportControl->rcbValues = mmsValue;
@ -955,13 +957,14 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock,
int brcbElementCount = 13; int brcbElementCount = 13;
#if (CONFIG_IEC61850_EDITION_1 == 0) if (reportControl->server->edition >= IEC_61850_EDITION_2) {
#if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) #if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1)
brcbElementCount++; brcbElementCount++;
#endif #endif
brcbElementCount++; brcbElementCount++;
#endif /* (CONFIG_IEC61850_EDITION_1 == 0) */ }
MmsValue* mmsValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); MmsValue* mmsValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
mmsValue->deleteValue = false; mmsValue->deleteValue = false;
@ -1083,11 +1086,10 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock,
reportControl->timeOfEntry = mmsValue->value.structure.components[12]; reportControl->timeOfEntry = mmsValue->value.structure.components[12];
#if (CONFIG_IEC61850_EDITION_1 == 0) if (reportControl->server->edition >= IEC_61850_EDITION_2) {
int currentIndex = 13; int currentIndex = 13;
#endif
#if ((CONFIG_IEC61850_EDITION_1 == 0) && (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1)) #if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1)
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = StringUtils_copyString("ResvTms"); namedVariable->name = StringUtils_copyString("ResvTms");
namedVariable->type = MMS_INTEGER; namedVariable->type = MMS_INTEGER;
@ -1097,14 +1099,13 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock,
currentIndex++; currentIndex++;
#endif /* (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) */ #endif /* (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) */
#if (CONFIG_IEC61850_EDITION_1 == 0)
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = StringUtils_copyString("Owner"); namedVariable->name = StringUtils_copyString("Owner");
namedVariable->type = MMS_OCTET_STRING; namedVariable->type = MMS_OCTET_STRING;
namedVariable->typeSpec.octetString = -64; namedVariable->typeSpec.octetString = -64;
rcb->typeSpec.structure.elements[currentIndex] = namedVariable; rcb->typeSpec.structure.elements[currentIndex] = namedVariable;
mmsValue->value.structure.components[currentIndex] = MmsValue_newOctetString(0, 128); /* size 4 is enough to store client IPv4 address */ mmsValue->value.structure.components[currentIndex] = MmsValue_newOctetString(0, 128); /* size 4 is enough to store client IPv4 address */
#endif /* (CONFIG_IEC61850_EDITION_1 == 0) */ }
reportControl->rcbValues = mmsValue; reportControl->rcbValues = mmsValue;
@ -1158,7 +1159,7 @@ Reporting_createMmsBufferedRCBs(MmsMapping* self, MmsDomain* domain,
int currentReport = 0; int currentReport = 0;
while (currentReport < reportsCount) { while (currentReport < reportsCount) {
ReportControl* rc = ReportControl_create(true, logicalNode, self->iedServer->reportBufferSize); ReportControl* rc = ReportControl_create(true, logicalNode, self->iedServer->reportBufferSize, self->iedServer);
rc->domain = domain; rc->domain = domain;
@ -1195,7 +1196,7 @@ Reporting_createMmsUnbufferedRCBs(MmsMapping* self, MmsDomain* domain,
int currentReport = 0; int currentReport = 0;
while (currentReport < reportsCount) { while (currentReport < reportsCount) {
ReportControl* rc = ReportControl_create(false, logicalNode, self->iedServer->reportBufferSize); ReportControl* rc = ReportControl_create(false, logicalNode, self->iedServer->reportBufferSize, self->iedServer);
rc->domain = domain; rc->domain = domain;
@ -1221,7 +1222,8 @@ updateOwner(ReportControl* rc, MmsServerConnection connection)
{ {
rc->clientConnection = connection; rc->clientConnection = connection;
#if (CONFIG_IEC61850_EDITION_1 == 0) if (rc->server->edition >= IEC_61850_EDITION_2) {
MmsValue* owner = ReportControl_getRCBValue(rc, "Owner"); MmsValue* owner = ReportControl_getRCBValue(rc, "Owner");
if (owner != NULL) { if (owner != NULL) {
@ -1272,7 +1274,7 @@ updateOwner(ReportControl* rc, MmsServerConnection connection)
} }
} }
#endif /* (CONFIG_IEC61850_EDITION_1 == 0) */ }
} }

@ -610,3 +610,5 @@ EXPORTS
IedServerConfig_isDynamicDataSetServiceEnabled IedServerConfig_isDynamicDataSetServiceEnabled
IedServerConfig_enableLogService IedServerConfig_enableLogService
IedServerConfig_isLogServiceEnabled IedServerConfig_isLogServiceEnabled
IedServerConfig_setEdition
IedServerConfig_getEdition

@ -738,3 +738,5 @@ EXPORTS
IedServerConfig_isDynamicDataSetServiceEnabled IedServerConfig_isDynamicDataSetServiceEnabled
IedServerConfig_enableLogService IedServerConfig_enableLogService
IedServerConfig_isLogServiceEnabled IedServerConfig_isLogServiceEnabled
IedServerConfig_setEdition
IedServerConfig_getEdition

Loading…
Cancel
Save