From 43d99ad43841e3aba02c031016082cda2c539fd1 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Thu, 28 Jan 2016 15:57:01 +0100 Subject: [PATCH] - extended 9-2LE example --- .../iec61850_9_2_LE_example/CMakeLists.txt | 10 +- examples/iec61850_9_2_LE_example/Makefile | 4 +- .../iec61850_9_2_LE_example.c | 152 ++++++++++++++++++ .../iec61850_9_2_LE_example/server_example2.c | 86 ---------- .../iec61850_9_2_LE_example/static_model.c | 16 +- examples/iec61850_9_2_LE_example/sv.icd | 16 +- src/sampled_values/sv_publisher.c | 92 +++++------ 7 files changed, 214 insertions(+), 162 deletions(-) create mode 100644 examples/iec61850_9_2_LE_example/iec61850_9_2_LE_example.c delete mode 100644 examples/iec61850_9_2_LE_example/server_example2.c diff --git a/examples/iec61850_9_2_LE_example/CMakeLists.txt b/examples/iec61850_9_2_LE_example/CMakeLists.txt index 994caae3..fdaa929f 100644 --- a/examples/iec61850_9_2_LE_example/CMakeLists.txt +++ b/examples/iec61850_9_2_LE_example/CMakeLists.txt @@ -2,20 +2,20 @@ include_directories( . ) -set(server_example2_SRCS +set(sv_9_2_LE_example_SRCS server_example2.c static_model.c ) IF(WIN32) -set_source_files_properties(${server_example2_SRCS} +set_source_files_properties(${sv_9_2_LE_example_SRCS} PROPERTIES LANGUAGE CXX) ENDIF(WIN32) -add_executable(server_example2 - ${server_example2_SRCS} +add_executable(sv_9_2_LE_example + ${sv_9_2_LE_example_SRCS} ) -target_link_libraries(server_example2 +target_link_libraries(sv_9_2_LE_example iec61850 ) diff --git a/examples/iec61850_9_2_LE_example/Makefile b/examples/iec61850_9_2_LE_example/Makefile index 3781758b..8437cf31 100644 --- a/examples/iec61850_9_2_LE_example/Makefile +++ b/examples/iec61850_9_2_LE_example/Makefile @@ -1,7 +1,7 @@ LIBIEC_HOME=../.. -PROJECT_BINARY_NAME = server_example2 -PROJECT_SOURCES = server_example2.c +PROJECT_BINARY_NAME = sv_9_2LE_example +PROJECT_SOURCES = iec61850_9_2_LE_example.c PROJECT_SOURCES += static_model.c PROJECT_ICD_FILE = complexModel.icd diff --git a/examples/iec61850_9_2_LE_example/iec61850_9_2_LE_example.c b/examples/iec61850_9_2_LE_example/iec61850_9_2_LE_example.c new file mode 100644 index 00000000..86c1cdbc --- /dev/null +++ b/examples/iec61850_9_2_LE_example/iec61850_9_2_LE_example.c @@ -0,0 +1,152 @@ +/* + * iec61850_9_2_LE_example.c + * + * Copyright 2016 Michael Zillgith + * + * This file is part of libIEC61850. + * + * libIEC61850 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libIEC61850 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libIEC61850. If not, see . + * + * See COPYING file for the complete license text. + */ + +#include "iec61850_server.h" +#include "sv_publisher.h" +#include "hal_thread.h" +#include +#include +#include + + +/* Include the generated header with the model access handles */ +#include "static_model.h" + +/* import IEC 61850 device model created from SCL-File */ +extern IedModel iedModel; + +static int running = 0; + +void sigint_handler(int signalId) +{ + running = 0; +} + +static int amp1; +static int amp2; +static int amp3; +static int amp4; + +static int vol1; +static int vol2; +static int vol3; +static int vol4; + +static SampledValuesPublisher svPublisher; +static SV_ASDU asdu; + +static void +setupSVPublisher() +{ + svPublisher = SampledValuesPublisher_create("eth1"); + + asdu = SampledValuesPublisher_addASDU(svPublisher, "xxxxMUnn01", NULL, 1); + + amp1 = SV_ASDU_addINT32(asdu); + amp2 = SV_ASDU_addINT32(asdu); + amp3 = SV_ASDU_addINT32(asdu); + amp4 = SV_ASDU_addINT32(asdu); + + vol1 = SV_ASDU_addINT32(asdu); + vol2 = SV_ASDU_addINT32(asdu); + vol3 = SV_ASDU_addINT32(asdu); + vol4 = SV_ASDU_addINT32(asdu); + + SampledValuesPublisher_setupComplete(svPublisher); +} + +int +main(int argc, char** argv) +{ + IedServer iedServer = IedServer_create(&iedModel); + + // TODO set initial measurement and status values from process + + /* MMS server will be instructed to start listening to client connections. */ + IedServer_start(iedServer, 102); + + if (!IedServer_isRunning(iedServer)) { + printf("Starting server failed! Exit.\n"); + IedServer_destroy(iedServer); + exit(-1); + } + + running = 1; + + signal(SIGINT, sigint_handler); + + setupSVPublisher(); + + int voltage = 1; + int current = 1; + + while (running) { + + uint64_t timeval = Hal_getTimeInMs(); + + IedServer_lockDataModel(iedServer); + + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR1_Amp_instMag_i, current); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR2_Amp_instMag_i, current); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR3_Amp_instMag_i, current); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR3_Amp_instMag_i, current); + + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR1_Vol_instMag_i, voltage); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR2_Vol_instMag_i, voltage); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR3_Vol_instMag_i, voltage); + IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR4_Vol_instMag_i, voltage); + + IedServer_unlockDataModel(iedServer); + + if (1) { + + SV_ASDU_setINT32(asdu, amp1, current); + SV_ASDU_setINT32(asdu, amp2, current); + SV_ASDU_setINT32(asdu, amp3, current); + SV_ASDU_setINT32(asdu, amp4, current); + + SV_ASDU_setINT32(asdu, vol1, voltage); + SV_ASDU_setINT32(asdu, vol2, voltage); + SV_ASDU_setINT32(asdu, vol3, voltage); + SV_ASDU_setINT32(asdu, vol4, voltage); + + SV_ASDU_increaseSmpCnt(asdu); + + SampledValuesPublisher_publish(svPublisher); + } + + voltage++; + current++; + + Thread_sleep(500); + } + + /* stop MMS server - close TCP server socket and all client sockets */ + IedServer_stop(iedServer); + + /* Cleanup - free all resources */ + SampledValuesPublisher_destroy(svPublisher); + IedServer_destroy(iedServer); + + return 0; +} /* main() */ diff --git a/examples/iec61850_9_2_LE_example/server_example2.c b/examples/iec61850_9_2_LE_example/server_example2.c deleted file mode 100644 index 662cf501..00000000 --- a/examples/iec61850_9_2_LE_example/server_example2.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * server_example2.c - * - * Copyright 2013 Michael Zillgith - * - * This file is part of libIEC61850. - * - * libIEC61850 is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libIEC61850 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with libIEC61850. If not, see . - * - * See COPYING file for the complete license text. - */ - -#include "iec61850_server.h" -#include "hal_thread.h" -#include -#include -#include - - -/* Include the generated header with the model access handles */ -#include "static_model.h" - -/* import IEC 61850 device model created from SCL-File */ -extern IedModel iedModel; - -static int running = 0; - -void sigint_handler(int signalId) -{ - running = 0; -} - -int -main(int argc, char** argv) -{ - IedServer iedServer = IedServer_create(&iedModel); - - // TODO get stored values from persistent storage - - // TODO set initial measurement and status values from process - - /* MMS server will be instructed to start listening to client connections. */ - IedServer_start(iedServer, 102); - - if (!IedServer_isRunning(iedServer)) { - printf("Starting server failed! Exit.\n"); - IedServer_destroy(iedServer); - exit(-1); - } - - running = 1; - - signal(SIGINT, sigint_handler); - - float power = 500.f; - - while (running) { - - uint64_t timeval = Hal_getTimeInMs(); - - IedServer_unlockDataModel(iedServer); - - power += 0.1f; - - Thread_sleep(500); - } - - /* stop MMS server - close TCP server socket and all client sockets */ - IedServer_stop(iedServer); - - /* Cleanup - free all resources */ - IedServer_destroy(iedServer); - - return 0; -} /* main() */ diff --git a/examples/iec61850_9_2_LE_example/static_model.c b/examples/iec61850_9_2_LE_example/static_model.c index 06c58685..5962f83d 100644 --- a/examples/iec61850_9_2_LE_example/static_model.c +++ b/examples/iec61850_9_2_LE_example/static_model.c @@ -22,7 +22,7 @@ extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda7; DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda0 = { "MUnn", false, - "TCTR1$MX$Amp", + "TCTR1$MX$Amp$instMag$i", -1, NULL, NULL, @@ -32,7 +32,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda0 = { DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda1 = { "MUnn", false, - "TCTR2$MX$Amp", + "TCTR2$MX$Amp$instMag$i", -1, NULL, NULL, @@ -42,7 +42,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda1 = { DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda2 = { "MUnn", false, - "TCTR3$MX$Amp", + "TCTR3$MX$Amp$instMag$i", -1, NULL, NULL, @@ -52,7 +52,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda2 = { DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda3 = { "MUnn", false, - "TCTR4$MX$Amp", + "TCTR4$MX$Amp$instMag$i", -1, NULL, NULL, @@ -62,7 +62,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda3 = { DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda4 = { "MUnn", false, - "TVTR1$MX$Vol", + "TVTR1$MX$Vol$instMag$i", -1, NULL, NULL, @@ -72,7 +72,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda4 = { DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda5 = { "MUnn", false, - "TVTR2$MX$Vol", + "TVTR2$MX$Vol$instMag$i", -1, NULL, NULL, @@ -82,7 +82,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda5 = { DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda6 = { "MUnn", false, - "TVTR3$MX$Vol", + "TVTR3$MX$Vol$instMag$i", -1, NULL, NULL, @@ -92,7 +92,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda6 = { DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda7 = { "MUnn", false, - "TVTR4$MX$Vol", + "TVTR4$MX$Vol$instMag$i", -1, NULL, NULL, diff --git a/examples/iec61850_9_2_LE_example/sv.icd b/examples/iec61850_9_2_LE_example/sv.icd index b52f8d92..9ef2d1a1 100644 --- a/examples/iec61850_9_2_LE_example/sv.icd +++ b/examples/iec61850_9_2_LE_example/sv.icd @@ -74,21 +74,21 @@ SCL.xsd"> + doName="Amp" daName="instMag.i"/> + doName="Amp" daName="instMag.i"/> + doName="Amp" daName="instMag.i"/> + doName="Amp" daName="instMag.i"/> + doName="Vol" daName="instMag.i"/> + doName="Vol" daName="instMag.i"/> + doName="Vol" daName="instMag.i"/> + doName="Vol" daName="instMag.i"/> diff --git a/src/sampled_values/sv_publisher.c b/src/sampled_values/sv_publisher.c index ccf1bc8d..67e65f88 100644 --- a/src/sampled_values/sv_publisher.c +++ b/src/sampled_values/sv_publisher.c @@ -24,7 +24,11 @@ #include "stack_config.h" #include "libiec61850_platform_includes.h" + +#include "sv_publisher.h" + #include "hal_ethernet.h" +#include "ber_encoder.h" #define DEBUG_SV_PUBLISHER 1 @@ -36,14 +40,6 @@ #define SV_MAX_MESSAGE_SIZE 1518 -#define IEC61850_SV_SMPSYNC_NOT_SYNCHRONIZED 0 -#define IEC61850_SV_SMPSYNC_SYNCED_UNSPEC_LOCAL_CLOCK 1 -#define IEC61850_SV_SMPSYNC_SYNCED_GLOBAL_CLOCK 2 - -#define IEC61850_SV_SMPMOD_PER_NOMINAL_PERIOD 0 -#define IEC61850_SV_SMPMOD_SAMPLES_PER_SECOND 1 -#define IEC61850_SV_SMPMOD_SECONDS_PER_SAMPLE 2 - typedef struct sCommParameters { uint8_t vlanPriority; uint16_t vlanId; @@ -51,7 +47,7 @@ typedef struct sCommParameters { uint8_t dstAddress[6]; } CommParameters; -typedef struct sSV_ASDU* SV_ASDU; + struct sSV_ASDU { char* svID; @@ -73,7 +69,7 @@ struct sSV_ASDU { SV_ASDU _next; }; -typedef struct sSampledValuesPublisher* SampledValuesPublisher; + struct sSampledValuesPublisher { uint8_t* buffer; @@ -93,7 +89,7 @@ struct sSampledValuesPublisher { static void -preparePacketBuffer(SampledValuesPublisher self, CommParameters* parameters, char* interfaceID) +preparePacketBuffer(SampledValuesPublisher self, CommParameters* parameters, const char* interfaceID) { uint8_t srcAddr[6]; @@ -208,6 +204,26 @@ encodeUInt32FixedSize(uint32_t value, uint8_t* buffer, int bufPos) return bufPos; } +static int +encodeInt32FixedSize(int32_t value, uint8_t* buffer, int bufPos) +{ + uint8_t* valueArray = (uint8_t*) &value; + +#if (ORDER_LITTLE_ENDIAN == 1) + buffer[bufPos++] = valueArray[3]; + buffer[bufPos++] = valueArray[2]; + buffer[bufPos++] = valueArray[1]; + buffer[bufPos++] = valueArray[0]; +#else + buffer[bufPos++] = valueArray[0]; + buffer[bufPos++] = valueArray[1]; + buffer[bufPos++] = valueArray[2]; + buffer[bufPos++] = valueArray[3]; +#endif + + return bufPos; +} + SampledValuesPublisher SampledValuesPublisher_create(const char* interfaceId) @@ -302,7 +318,7 @@ SV_ASDU_encodeToBuffer(SV_ASDU self, uint8_t* buffer, int bufPos) if (self->datset != NULL) bufPos = BerEncoder_encodeStringWithTag(0x81, self->datset, buffer, bufPos); - uint8_t octetString[4]; + //uint8_t octetString[4]; /* SmpCnt */ bufPos = BerEncoder_encodeTL(0x82, 2, buffer, bufPos); @@ -447,6 +463,12 @@ SV_ASDU_addINT32(SV_ASDU self) return index; } +void +SV_ASDU_setINT32(SV_ASDU self, int index, int32_t value) +{ + encodeInt32FixedSize(value, self->_dataBuffer, index); +} + int SV_ASDU_addFLOAT(SV_ASDU self) { @@ -480,7 +502,9 @@ SV_ASDU_setFLOAT(SV_ASDU self, int index, float value) void SV_ASDU_setSmpCnt(SV_ASDU self, uint16_t value) { - //TODO write value to correct field in buffer + self->smpCnt = value; + + encodeUInt16FixedSize(self->smpCnt, self->smpCntBuf, 0); } void @@ -498,45 +522,7 @@ SV_ASDU_setRefrTm(SV_ASDU self, Timestamp refrTm) } #endif - -int -main(int argc, char** argv) -{ - SampledValuesPublisher svPublisher = SampledValuesPublisher_create("eth1"); - - SV_ASDU asdu1 = SampledValuesPublisher_addASDU(svPublisher, "svpub1", NULL, 1); - - int float1 = SV_ASDU_addFLOAT(asdu1); - int float2 = SV_ASDU_addFLOAT(asdu1); - - SV_ASDU asdu2 = SampledValuesPublisher_addASDU(svPublisher, "svpub2", NULL, 1); - - int float3 = SV_ASDU_addFLOAT(asdu2); - int float4 = SV_ASDU_addFLOAT(asdu2); - - SampledValuesPublisher_setupComplete(svPublisher); - - float fVal1 = 1234.5678f; - float fVal2 = 0.12345f; - - int i; - - for (i = 0; i < 10; i++) { - SV_ASDU_setFLOAT(asdu1, float1, fVal1); - SV_ASDU_setFLOAT(asdu1, float2, fVal2); - - SV_ASDU_increaseSmpCnt(asdu1); - SV_ASDU_increaseSmpCnt(asdu2); - - fVal1 += 1.1f; - fVal2 += 0.1f; - - SampledValuesPublisher_publish(svPublisher); - } - - SampledValuesPublisher_destroy(svPublisher); -} - +#if 0 int main1(int argc, char** argv) { @@ -568,4 +554,4 @@ main1(int argc, char** argv) SampledValuesPublisher_destroy(svPublisher); } - +#endif