- M/U SVCB implementation WIP

- added example project for IEC 61850-9-2 LE
pull/6/head
Michael Zillgith 10 years ago
parent 8482cfce9b
commit 0193902da1

@ -0,0 +1,21 @@
include_directories(
.
)
set(server_example2_SRCS
server_example2.c
static_model.c
)
IF(WIN32)
set_source_files_properties(${server_example2_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(WIN32)
add_executable(server_example2
${server_example2_SRCS}
)
target_link_libraries(server_example2
iec61850
)

@ -0,0 +1,24 @@
LIBIEC_HOME=../..
PROJECT_BINARY_NAME = server_example2
PROJECT_SOURCES = server_example2.c
PROJECT_SOURCES += static_model.c
PROJECT_ICD_FILE = complexModel.icd
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
all: $(PROJECT_BINARY_NAME)
include $(LIBIEC_HOME)/make/common_targets.mk
model: $(PROJECT_ICD_FILE)
java -jar $(LIBIEC_HOME)/tools/model_generator/genmodel.jar $(PROJECT_ICD_FILE)
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDFLAGS) $(LDLIBS)
clean:
rm -f $(PROJECT_BINARY_NAME)

@ -0,0 +1,86 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#include "iec61850_server.h"
#include "hal_thread.h"
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
/* 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() */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,161 @@
/*
* static_model.h
*
* automatically generated from sv.icd
*/
#ifndef STATIC_MODEL_H_
#define STATIC_MODEL_H_
#include <stdlib.h>
#include "iec61850_model.h"
extern IedModel iedModel;
extern LogicalDevice iedModel_MUnn;
extern LogicalNode iedModel_MUnn_LLN0;
extern DataObject iedModel_MUnn_LLN0_Mod;
extern DataAttribute iedModel_MUnn_LLN0_Mod_ctlVal;
extern DataAttribute iedModel_MUnn_LLN0_Mod_stVal;
extern DataAttribute iedModel_MUnn_LLN0_Mod_q;
extern DataAttribute iedModel_MUnn_LLN0_Mod_t;
extern LogicalNode iedModel_MUnn_TCTR1;
extern DataObject iedModel_MUnn_TCTR1_Amp;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_instMag;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_instMag_i;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_q;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC_offset;
extern LogicalNode iedModel_MUnn_TCTR2;
extern DataObject iedModel_MUnn_TCTR2_Amp;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_instMag;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_instMag_i;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_q;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC_offset;
extern LogicalNode iedModel_MUnn_TCTR3;
extern DataObject iedModel_MUnn_TCTR3_Amp;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_instMag;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_instMag_i;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_q;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC_offset;
extern LogicalNode iedModel_MUnn_TCTR4;
extern DataObject iedModel_MUnn_TCTR4_Amp;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_instMag;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_instMag_i;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_q;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC_offset;
extern LogicalNode iedModel_MUnn_TVTR1;
extern DataObject iedModel_MUnn_TVTR1_Vol;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_instMag;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_instMag_i;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_q;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC_offset;
extern LogicalNode iedModel_MUnn_TVTR2;
extern DataObject iedModel_MUnn_TVTR2_Vol;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_instMag;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_instMag_i;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_q;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC_offset;
extern LogicalNode iedModel_MUnn_TVTR3;
extern DataObject iedModel_MUnn_TVTR3_Vol;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_instMag;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_instMag_i;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_q;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC_offset;
extern LogicalNode iedModel_MUnn_TVTR4;
extern DataObject iedModel_MUnn_TVTR4_Vol;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_instMag;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_instMag_i;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_q;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC_offset;
#define IEDMODEL_MUnn (&iedModel_MUnn)
#define IEDMODEL_MUnn_LLN0 (&iedModel_MUnn_LLN0)
#define IEDMODEL_MUnn_LLN0_Mod (&iedModel_MUnn_LLN0_Mod)
#define IEDMODEL_MUnn_LLN0_Mod_ctlVal (&iedModel_MUnn_LLN0_Mod_ctlVal)
#define IEDMODEL_MUnn_LLN0_Mod_stVal (&iedModel_MUnn_LLN0_Mod_stVal)
#define IEDMODEL_MUnn_LLN0_Mod_q (&iedModel_MUnn_LLN0_Mod_q)
#define IEDMODEL_MUnn_LLN0_Mod_t (&iedModel_MUnn_LLN0_Mod_t)
#define IEDMODEL_MUnn_TCTR1 (&iedModel_MUnn_TCTR1)
#define IEDMODEL_MUnn_TCTR1_Amp (&iedModel_MUnn_TCTR1_Amp)
#define IEDMODEL_MUnn_TCTR1_Amp_instMag (&iedModel_MUnn_TCTR1_Amp_instMag)
#define IEDMODEL_MUnn_TCTR1_Amp_instMag_i (&iedModel_MUnn_TCTR1_Amp_instMag_i)
#define IEDMODEL_MUnn_TCTR1_Amp_q (&iedModel_MUnn_TCTR1_Amp_q)
#define IEDMODEL_MUnn_TCTR1_Amp_sVC (&iedModel_MUnn_TCTR1_Amp_sVC)
#define IEDMODEL_MUnn_TCTR1_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor)
#define IEDMODEL_MUnn_TCTR1_Amp_sVC_offset (&iedModel_MUnn_TCTR1_Amp_sVC_offset)
#define IEDMODEL_MUnn_TCTR2 (&iedModel_MUnn_TCTR2)
#define IEDMODEL_MUnn_TCTR2_Amp (&iedModel_MUnn_TCTR2_Amp)
#define IEDMODEL_MUnn_TCTR2_Amp_instMag (&iedModel_MUnn_TCTR2_Amp_instMag)
#define IEDMODEL_MUnn_TCTR2_Amp_instMag_i (&iedModel_MUnn_TCTR2_Amp_instMag_i)
#define IEDMODEL_MUnn_TCTR2_Amp_q (&iedModel_MUnn_TCTR2_Amp_q)
#define IEDMODEL_MUnn_TCTR2_Amp_sVC (&iedModel_MUnn_TCTR2_Amp_sVC)
#define IEDMODEL_MUnn_TCTR2_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor)
#define IEDMODEL_MUnn_TCTR2_Amp_sVC_offset (&iedModel_MUnn_TCTR2_Amp_sVC_offset)
#define IEDMODEL_MUnn_TCTR3 (&iedModel_MUnn_TCTR3)
#define IEDMODEL_MUnn_TCTR3_Amp (&iedModel_MUnn_TCTR3_Amp)
#define IEDMODEL_MUnn_TCTR3_Amp_instMag (&iedModel_MUnn_TCTR3_Amp_instMag)
#define IEDMODEL_MUnn_TCTR3_Amp_instMag_i (&iedModel_MUnn_TCTR3_Amp_instMag_i)
#define IEDMODEL_MUnn_TCTR3_Amp_q (&iedModel_MUnn_TCTR3_Amp_q)
#define IEDMODEL_MUnn_TCTR3_Amp_sVC (&iedModel_MUnn_TCTR3_Amp_sVC)
#define IEDMODEL_MUnn_TCTR3_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor)
#define IEDMODEL_MUnn_TCTR3_Amp_sVC_offset (&iedModel_MUnn_TCTR3_Amp_sVC_offset)
#define IEDMODEL_MUnn_TCTR4 (&iedModel_MUnn_TCTR4)
#define IEDMODEL_MUnn_TCTR4_Amp (&iedModel_MUnn_TCTR4_Amp)
#define IEDMODEL_MUnn_TCTR4_Amp_instMag (&iedModel_MUnn_TCTR4_Amp_instMag)
#define IEDMODEL_MUnn_TCTR4_Amp_instMag_i (&iedModel_MUnn_TCTR4_Amp_instMag_i)
#define IEDMODEL_MUnn_TCTR4_Amp_q (&iedModel_MUnn_TCTR4_Amp_q)
#define IEDMODEL_MUnn_TCTR4_Amp_sVC (&iedModel_MUnn_TCTR4_Amp_sVC)
#define IEDMODEL_MUnn_TCTR4_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor)
#define IEDMODEL_MUnn_TCTR4_Amp_sVC_offset (&iedModel_MUnn_TCTR4_Amp_sVC_offset)
#define IEDMODEL_MUnn_TVTR1 (&iedModel_MUnn_TVTR1)
#define IEDMODEL_MUnn_TVTR1_Vol (&iedModel_MUnn_TVTR1_Vol)
#define IEDMODEL_MUnn_TVTR1_Vol_instMag (&iedModel_MUnn_TVTR1_Vol_instMag)
#define IEDMODEL_MUnn_TVTR1_Vol_instMag_i (&iedModel_MUnn_TVTR1_Vol_instMag_i)
#define IEDMODEL_MUnn_TVTR1_Vol_q (&iedModel_MUnn_TVTR1_Vol_q)
#define IEDMODEL_MUnn_TVTR1_Vol_sVC (&iedModel_MUnn_TVTR1_Vol_sVC)
#define IEDMODEL_MUnn_TVTR1_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor)
#define IEDMODEL_MUnn_TVTR1_Vol_sVC_offset (&iedModel_MUnn_TVTR1_Vol_sVC_offset)
#define IEDMODEL_MUnn_TVTR2 (&iedModel_MUnn_TVTR2)
#define IEDMODEL_MUnn_TVTR2_Vol (&iedModel_MUnn_TVTR2_Vol)
#define IEDMODEL_MUnn_TVTR2_Vol_instMag (&iedModel_MUnn_TVTR2_Vol_instMag)
#define IEDMODEL_MUnn_TVTR2_Vol_instMag_i (&iedModel_MUnn_TVTR2_Vol_instMag_i)
#define IEDMODEL_MUnn_TVTR2_Vol_q (&iedModel_MUnn_TVTR2_Vol_q)
#define IEDMODEL_MUnn_TVTR2_Vol_sVC (&iedModel_MUnn_TVTR2_Vol_sVC)
#define IEDMODEL_MUnn_TVTR2_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor)
#define IEDMODEL_MUnn_TVTR2_Vol_sVC_offset (&iedModel_MUnn_TVTR2_Vol_sVC_offset)
#define IEDMODEL_MUnn_TVTR3 (&iedModel_MUnn_TVTR3)
#define IEDMODEL_MUnn_TVTR3_Vol (&iedModel_MUnn_TVTR3_Vol)
#define IEDMODEL_MUnn_TVTR3_Vol_instMag (&iedModel_MUnn_TVTR3_Vol_instMag)
#define IEDMODEL_MUnn_TVTR3_Vol_instMag_i (&iedModel_MUnn_TVTR3_Vol_instMag_i)
#define IEDMODEL_MUnn_TVTR3_Vol_q (&iedModel_MUnn_TVTR3_Vol_q)
#define IEDMODEL_MUnn_TVTR3_Vol_sVC (&iedModel_MUnn_TVTR3_Vol_sVC)
#define IEDMODEL_MUnn_TVTR3_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor)
#define IEDMODEL_MUnn_TVTR3_Vol_sVC_offset (&iedModel_MUnn_TVTR3_Vol_sVC_offset)
#define IEDMODEL_MUnn_TVTR4 (&iedModel_MUnn_TVTR4)
#define IEDMODEL_MUnn_TVTR4_Vol (&iedModel_MUnn_TVTR4_Vol)
#define IEDMODEL_MUnn_TVTR4_Vol_instMag (&iedModel_MUnn_TVTR4_Vol_instMag)
#define IEDMODEL_MUnn_TVTR4_Vol_instMag_i (&iedModel_MUnn_TVTR4_Vol_instMag_i)
#define IEDMODEL_MUnn_TVTR4_Vol_q (&iedModel_MUnn_TVTR4_Vol_q)
#define IEDMODEL_MUnn_TVTR4_Vol_sVC (&iedModel_MUnn_TVTR4_Vol_sVC)
#define IEDMODEL_MUnn_TVTR4_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor)
#define IEDMODEL_MUnn_TVTR4_Vol_sVC_offset (&iedModel_MUnn_TVTR4_Vol_sVC_offset)
#endif /* STATIC_MODEL_H_ */

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSPY v5 rel. 4 U (http://www.xmlspy.com) by Christoph Brunner (ABB Switzerland Ltd) -->
<SCL xmlns="http://www.iec.ch/61850/2003/SCL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.iec.ch/61850/2003/SCL
SCL.xsd">
<Header id="9-2LE-Spec" nameStructure="FuncName" version="0.7" revision="1"/>
<Communication>
<SubNetwork name="subnetwork1" type="8-MMS">
<Text>Station bus</Text>
<BitRate unit="b/s">10</BitRate>
<ConnectedAP iedName="TEMPLATE" apName="accessPoint1">
<Address>
<P type="IP">10.0.0.2</P>
<P type="IP-SUBNET">255.255.255.0</P>
<P type="IP-GATEWAY">10.0.0.1</P>
<P type="OSI-TSEL">0001</P>
<P type="OSI-PSEL">00000001</P>
<P type="OSI-SSEL">0001</P>
</Address>
<SMV ldInst="MUnn" cbName="MSVCB01">
<Address>
<P type="VLAN-ID">1</P>
<P type="VLAN-PRIORITY">4</P>
<P type="MAC-Address">01-0c-cd-04-00-01</P>
<P type="APPID">1001</P>
</Address>
</SMV>
</ConnectedAP>
</SubNetwork>
</Communication>
<Substation name="">
<VoltageLevel name="">
<Bay name="">
<ConductingEquipment name="Inn" type="CTR">
<SubEquipment name="A" phase="A">
<LNode lnClass="TCTR" lnInst="1"/>
</SubEquipment>
<SubEquipment name="B" phase="B">
<LNode lnClass="TCTR" lnInst="2"/>
</SubEquipment>
<SubEquipment name="C" phase="C">
<LNode lnClass="TCTR" lnInst="3"/>
</SubEquipment>
<SubEquipment name="N" phase="N">
<LNode lnClass="TCTR" lnInst="4"/>
</SubEquipment>
</ConductingEquipment>
<ConductingEquipment name="Unn" type="VTR">
<SubEquipment name="A" phase="A">
<LNode lnClass="TVTR" lnInst="1"/>
</SubEquipment>
<SubEquipment name="B" phase="B">
<LNode lnClass="TVTR" lnInst="2"/>
</SubEquipment>
<SubEquipment name="C" phase="C">
<LNode lnClass="TVTR" lnInst="3"/>
</SubEquipment>
<SubEquipment name="N" phase="N">
<LNode lnClass="TVTR" lnInst="4"/>
</SubEquipment>
</ConductingEquipment>
</Bay>
</VoltageLevel>
</Substation>
<IED name="TEMPLATE">
<AccessPoint name="accessPoint1">
<Server>
<Authentication/>
<LDevice inst="MUnn">
<LN0 lnType="9-2LELLN0" lnClass="LLN0" inst="">
<DataSet name="PhsMeas1">
<FCDA lnClass="TCTR" ldInst="1" fc="MX" doName="Amp"/>
<FCDA lnClass="TCTR" ldInst="2" fc="MX" doName="Amp"/>
<FCDA lnClass="TCTR" ldInst="3" fc="MX" doName="Amp"/>
<FCDA lnClass="TCTR" ldInst="4" fc="MX" doName="Amp"/>
<FCDA lnClass="TVTR" ldInst="1" fc="MX" doName="Vol"/>
<FCDA lnClass="TVTR" ldInst="2" fc="MX" doName="Vol"/>
<FCDA lnClass="TVTR" ldInst="3" fc="MX" doName="Vol"/>
<FCDA lnClass="TVTR" ldInst="4" fc="MX" doName="Vol"/>
</DataSet>
<SampledValueControl name="MSVCB01" datSet="PhsMeas1" smvID="xxxxMUnn01"
smpRate="80" nofASDU="1" confRev="1">
<SmvOpts refreshTime="false" sampleSynchronized="true"
security="false" dataRef="false"/>
</SampledValueControl>
</LN0>
<LN lnType="9-2LETCTR" lnClass="TCTR" inst="1"/>
<LN lnType="9-2LETCTR" lnClass="TCTR" inst="2"/>
<LN lnType="9-2LETCTR" lnClass="TCTR" inst="3"/>
<LN lnType="9-2LETCTR" lnClass="TCTR" inst="4"/>
<LN lnType="9-2LETVTR" lnClass="TVTR" inst="1"/>
<LN lnType="9-2LETVTR" lnClass="TVTR" inst="2"/>
<LN lnType="9-2LETVTR" lnClass="TVTR" inst="3"/>
<LN lnType="9-2LETVTR" lnClass="TVTR" inst="4"/>
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="9-2LELLN0" lnClass="LLN0">
<DO name="Mod" type="9-2LEINC"/>
</LNodeType>
<LNodeType id="9-2LETCTR" lnClass="TCTR">
<DO name="Amp" type="9-2LESAVAmp"/>
</LNodeType>
<LNodeType id="9-2LETVTR" lnClass="TVTR">
<DO name="Vol" type="9-2LESAVVol"/>
</LNodeType>
<DOType id="9-2LESAVAmp" cdc="SAV">
<DA name="instMag" bType="Struct" type="9-2LEAV" fc="MX"/>
<DA name="q" bType="Quality" fc="MX"/>
<DA name="sVC" bType="Struct" type="9-2LEsVCAmp" fc="CF"/>
</DOType>
<DOType id="9-2LESAVVol" cdc="SAV">
<DA name="instMag" bType="Struct" type="9-2LEAV" fc="MX"/>
<DA name="q" bType="Quality" fc="MX"/>
<DA name="sVC" bType="Struct" type="9-2LEsVCVol" fc="CF"/>
</DOType>
<DOType id="9-2LEINC" cdc="INC">
<DA name="ctlVal" fc="CO" bType="INT32"/>
<DA name="stVal" fc="ST" bType="INT32" dchg="true"/>
<DA name="q" fc="ST" bType="Quality" dchg="true"/>
<DA name="t" fc="ST" bType="Timestamp" dchg="true"/>
</DOType>
<DAType id="9-2LEAV">
<BDA name="i" bType="INT32"/>
</DAType>
<DAType id="9-2LEsVCAmp">
<BDA name="scaleFactor" bType="FLOAT32">
<Val>0.001</Val>
</BDA>
<BDA name="offset" bType="FLOAT32">
<Val>0</Val>
</BDA>
</DAType>
<DAType id="9-2LEsVCVol">
<BDA name="scaleFactor" bType="FLOAT32">
<Val>0.01</Val>
</BDA>
<BDA name="offset" bType="FLOAT32">
<Val>0</Val>
</BDA>
</DAType>
</DataTypeTemplates>
</SCL>

@ -15,6 +15,8 @@ print_help()
printf("-d show list of MMS domains\n"); printf("-d show list of MMS domains\n");
printf("-i show server identity\n"); printf("-i show server identity\n");
printf("-t <domain_name> show domain directory\n"); printf("-t <domain_name> show domain directory\n");
printf("-r <variable_name> read domain variable\n");
printf("-a <domain_name> specify domain for read or write command");
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
@ -24,14 +26,18 @@ int main(int argc, char** argv) {
int maxPduSize = 65000; int maxPduSize = 65000;
char* domainName = NULL; char* domainName = NULL;
char* variableName = NULL;
int readDeviceList = 0; int readDeviceList = 0;
int getDeviceDirectory = 0; int getDeviceDirectory = 0;
int identifyDevice = 0; int identifyDevice = 0;
int readWriteHasDomain = 0;
int readVariable = 0;
int c; int c;
while ((c = getopt(argc, argv, "idh:p:l:t:")) != -1) while ((c = getopt(argc, argv, "idh:p:l:t:a:r:")) != -1)
switch (c) { switch (c) {
case 'h': case 'h':
hostname = copyString(optarg); hostname = copyString(optarg);
@ -52,6 +58,15 @@ int main(int argc, char** argv) {
getDeviceDirectory = 1; getDeviceDirectory = 1;
domainName = copyString(optarg); domainName = copyString(optarg);
break; break;
case 'a':
readWriteHasDomain = 1;
domainName = copyString(optarg);
break;
case 'r':
readVariable = 1;
variableName = copyString(optarg);
break;
default: default:
print_help(); print_help();
return 0; return 0;
@ -103,12 +118,39 @@ int main(int argc, char** argv) {
while ((element = LinkedList_getNext(element)) != NULL) { while ((element = LinkedList_getNext(element)) != NULL) {
char* name = (char*) element->data; char* name = (char*) element->data;
if (strchr(name, '$') == NULL)
printf(" %s\n", name); printf(" %s\n", name);
} }
} }
if (readVariable) {
if (readWriteHasDomain) {
MmsValue* result = MmsConnection_readVariable(con, &error, domainName, variableName);
if (error != MMS_ERROR_NONE) {
printf("Reading variable failed: (ERROR %i)\n", error);
}
else {
printf("Read SUCCESS\n");
if (result != NULL) {
char outbuf[1024];
MmsValue_printToBuffer(result, outbuf, 1024);
printf("%s\n", outbuf);
}
else
printf("result: NULL\n");
}
}
else
printf("Reading VMD scope variable not yet supported!\n");
}
exit: exit:
MmsConnection_destroy(con); MmsConnection_destroy(con);
} }

@ -1,7 +1,7 @@
/* /*
* model.h * model.h
* *
* Copyright 2013, 2014 Michael Zillgith * Copyright 2013, 2014, 2015 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *

@ -24,8 +24,20 @@
#ifndef LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_ #ifndef LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_
#define LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_ #define LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_
typedef struct sMmsSampledValueControlBlock* MmsSampledValueControlBlock;
MmsSampledValueControlBlock
MmsSampledValueControlBlock_create(void);
void
MmsSampledValueControlBlock_destroy(MmsSampledValueControlBlock self);
MmsVariableSpecification* MmsVariableSpecification*
LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain, LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
LogicalNode* logicalNode, int svCount, bool unicast); LogicalNode* logicalNode, int svCount, bool unicast);
MmsValue*
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig);
#endif /* LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_ */ #endif /* LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_ */

@ -188,7 +188,16 @@ createMmsServerCache(IedServer self)
#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */ #endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
if ((strcmp(fcName, "BR") != 0) && (strcmp(fcName, "RP") != 0) if ((strcmp(fcName, "BR") != 0) && (strcmp(fcName, "RP") != 0)
&& (strcmp(fcName, "GO") != 0))
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
&& (strcmp(fcName, "GO") != 0)
#endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
&& (strcmp(fcName, "MS") != 0) && (strcmp(fcName, "US") != 0)
#endif
)
{ {
char* variableName = createString(3, lnName, "$", fcName); char* variableName = createString(3, lnName, "$", fcName);

@ -1,7 +1,7 @@
/* /*
* mms_mapping.c * mms_mapping.c
* *
* Copyright 2013, 2014 Michael Zillgith * Copyright 2013, 2014, 2015 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -28,6 +28,7 @@
#include "stack_config.h" #include "stack_config.h"
#include "mms_goose.h" #include "mms_goose.h"
#include "mms_sv.h"
#include "reporting.h" #include "reporting.h"
#include "control.h" #include "control.h"
#include "ied_server_private.h" #include "ied_server_private.h"
@ -1008,14 +1009,14 @@ createNamedVariableFromLogicalNode(MmsMapping* self, MmsDomain* domain,
/* Add MS and US named variables */ /* Add MS and US named variables */
if (msvcbCount > 0) { if (msvcbCount > 0) {
namedVariable->typeSpec.structure.elements[currentComponent] = namedVariable->typeSpec.structure.elements[currentComponent] =
LIBIEC61850_SV_creatSVControlBlocks(self, domain, logicalNode, msvcbCount, false); LIBIEC61850_SV_createSVControlBlocks(self, domain, logicalNode, msvcbCount, false);
currentComponent++; currentComponent++;
} }
if (usvcbCount > 0) { if (usvcbCount > 0) {
namedVariable->typeSpec.structure.elements[currentComponent] = namedVariable->typeSpec.structure.elements[currentComponent] =
LIBIEC61850_SV_creatSVControlBlocks(self, domain, logicalNode, msvcbCount, true); LIBIEC61850_SV_createSVControlBlocks(self, domain, logicalNode, msvcbCount, true);
currentComponent++; currentComponent++;
} }
@ -1243,7 +1244,7 @@ MmsMapping_destroy(MmsMapping* self)
#endif #endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) #if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
LinkedList_destroyDeep(self->svControls, (LinkedListValueDeleteFunction) MmsSvControlBlock_destroy); LinkedList_destroyDeep(self->svControls, (LinkedListValueDeleteFunction) MmsSampledValueControlBlock_destroy);
#endif #endif
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1) #if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
@ -1353,6 +1354,23 @@ isGooseControlBlock(char* separator)
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */ #endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
static bool
isSampledValueControlBlock(char* separator)
{
if (strncmp(separator + 1, "MS", 2) == 0)
return true;
if (strncmp(separator + 1, "US", 2) == 0)
return true;
return false;
}
#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */
char* char*
MmsMapping_getNextNameElement(char* name) MmsMapping_getNextNameElement(char* name)
{ {
@ -1679,6 +1697,14 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
} }
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */ #endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
/* Sampled Value control block - MS/US */
if (isSampledValueControlBlock(separator)) {
//TODO handle write access to SVCB
}
#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */
#if (CONFIG_IEC61850_REPORT_SERVICE == 1) #if (CONFIG_IEC61850_REPORT_SERVICE == 1)
/* Report control blocks - BR, RP */ /* Report control blocks - BR, RP */
if (isReportControlBlock(separator)) { if (isReportControlBlock(separator)) {
@ -2075,6 +2101,7 @@ readAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableI
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */ #endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
static MmsValue* static MmsValue*
mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection) mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection)
{ {
@ -2100,14 +2127,23 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
} }
#endif #endif
/* GOOSE control blocks - GO */
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) #if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
/* GOOSE control blocks - GO */
if (isGooseControlBlock(separator)) { if (isGooseControlBlock(separator)) {
retValue = readAccessGooseControlBlock(self, domain, variableId); retValue = readAccessGooseControlBlock(self, domain, variableId);
goto exit_function; goto exit_function;
} }
#endif #endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
/* Sampled Value control blocks - MS/US */
if (isSampledValueControlBlock(separator)) {
retValue = LIBIEC61850_SV_readAccessSampledValueControlBlock(self, domain, variableId);
goto exit_function;
}
#endif
#if (CONFIG_IEC61850_REPORT_SERVICE == 1) #if (CONFIG_IEC61850_REPORT_SERVICE == 1)
/* Report control blocks - BR, RP */ /* Report control blocks - BR, RP */
if (isReportControlBlock(separator)) { if (isReportControlBlock(separator)) {

@ -30,10 +30,109 @@
#include "linked_list.h" #include "linked_list.h"
#include "array_list.h" #include "array_list.h"
#include "mms_sv.h"
#include "mms_mapping_internal.h" #include "mms_mapping_internal.h"
struct sMmsSampledValueControlBlock {
char* name;
bool svEna;
char* dstAddress;
MmsDomain* domain;
LogicalNode* logicalNode;
MmsVariableSpecification* mmsType;
MmsValue* mmsValue;
//MmsMapping* mmsMapping;
};
MmsSampledValueControlBlock
MmsSampledValueControlBlock_create()
{
MmsSampledValueControlBlock self = (MmsSampledValueControlBlock) GLOBAL_CALLOC(1, sizeof(struct sMmsSampledValueControlBlock));
return self;
}
void
MmsSampledValueControlBlock_destroy(MmsSampledValueControlBlock self)
{
MmsValue_delete(self->mmsValue);
GLOBAL_FREEMEM(self);
}
static MmsSampledValueControlBlock
lookupSVCB(MmsMapping* self, MmsDomain* domain, char* lnName, char* objectName)
{
LinkedList element = LinkedList_getNext(self->svControls);
while (element != NULL) {
MmsSampledValueControlBlock mmsSVCB = (MmsSampledValueControlBlock) element->data;
if (mmsSVCB->domain == domain) {
if (strcmp(mmsSVCB->logicalNode->name, lnName) == 0) {
if (strcmp(mmsSVCB->name, objectName) == 0) {
return mmsSVCB;
}
}
}
element = LinkedList_getNext(element);
}
return NULL;
}
MmsValue*
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig)
{
MmsValue* value = NULL;
char variableId[130];
strncpy(variableId, variableIdOrig, 129);
char* separator = strchr(variableId, '$');
*separator = 0;
char* lnName = variableId;
if (lnName == NULL)
return NULL;
char* objectName = MmsMapping_getNextNameElement(separator + 1);
if (objectName == NULL)
return NULL;
char* varName = MmsMapping_getNextNameElement(objectName);
if (varName != NULL)
*(varName - 1) = 0;
MmsSampledValueControlBlock mmsSVCB = lookupSVCB(self, domain, lnName, objectName);
if (mmsSVCB != NULL) {
if (varName != NULL) {
value = MmsValue_getSubElement(mmsSVCB->mmsValue, mmsSVCB->mmsType, varName);
}
else {
value = mmsSVCB->mmsValue;
}
}
return value;
}
static GSEControlBlock* static SVControlBlock*
getSVCBForLogicalNodeWithIndex(MmsMapping* self, LogicalNode* logicalNode, int index, bool isUnicast) getSVCBForLogicalNodeWithIndex(MmsMapping* self, LogicalNode* logicalNode, int index, bool isUnicast)
{ {
int svCount = 0; int svCount = 0;
@ -88,6 +187,8 @@ createSVControlBlockMmsStructure(char* gcbName, bool isUnicast)
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("Resv"); namedVariable->name = copyString("Resv");
namedVariable->type = MMS_BOOLEAN; namedVariable->type = MMS_BOOLEAN;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
} }
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
@ -128,6 +229,13 @@ createSVControlBlockMmsStructure(char* gcbName, bool isUnicast)
gcb->typeSpec.structure.elements[currentElement++] = namedVariable; gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("SmpMod");
namedVariable->type = MMS_INTEGER;
namedVariable->typeSpec.integer = 8;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("DstAddress"); namedVariable->name = copyString("DstAddress");
MmsMapping_createPhyComAddrStructure(namedVariable); MmsMapping_createPhyComAddrStructure(namedVariable);
@ -205,7 +313,7 @@ LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
/* SmpMod */ /* SmpMod */
MmsValue* smpMod = MmsValue_getElement(svValues, currentIndex++); MmsValue* smpMod = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setInt32(smpRate, svControlBlock->smpMod); MmsValue_setInt32(smpMod, svControlBlock->smpMod);
/* Set communication parameters - DstAddress */ /* Set communication parameters - DstAddress */
uint8_t priority = CONFIG_GOOSE_DEFAULT_PRIORITY; uint8_t priority = CONFIG_GOOSE_DEFAULT_PRIORITY;
@ -242,6 +350,16 @@ LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
MmsValue* noASDU = MmsValue_getElement(svValues, currentIndex++); MmsValue* noASDU = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setInt32(noASDU, svControlBlock->noASDU); MmsValue_setInt32(noASDU, svControlBlock->noASDU);
MmsSampledValueControlBlock mmsSvCb = MmsSampledValueControlBlock_create();
mmsSvCb->mmsValue = svValues;
mmsSvCb->mmsType = svTypeSpec;
mmsSvCb->domain = domain;
mmsSvCb->logicalNode = logicalNode;
mmsSvCb->name = svControlBlock->name;
LinkedList_add(self->svControls, (void*) mmsSvCb);
currentSVCB++; currentSVCB++;
} }

@ -292,7 +292,8 @@ MmsConnection_getVariableListNamesAssociationSpecific(MmsConnection self, MmsErr
* \param itemId name of the variable to be read * \param itemId name of the variable to be read
* *
* \return Returns a MmsValue object or NULL if the request failed. The MmsValue object can * \return Returns a MmsValue object or NULL if the request failed. The MmsValue object can
* either be a simple value or a complex value or array. * either be a simple value or a complex value or array. It is also possible that the return value is NULL
* even if mmsError = MMS_ERROR_NON. This is the case when the servers returns an empty result list.
*/ */
MmsValue* MmsValue*
MmsConnection_readVariable(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId); MmsConnection_readVariable(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId);

@ -48,18 +48,16 @@ public class ConnectedAP {
List<Node> gseNodes = ParserUtils.getChildNodesWithTag(node, "GSE"); List<Node> gseNodes = ParserUtils.getChildNodesWithTag(node, "GSE");
for (Node gseNode : gseNodes) { for (Node gseNode : gseNodes)
gses.add(new GSE(gseNode)); gses.add(new GSE(gseNode));
}
smvs = new LinkedList<SMV>(); smvs = new LinkedList<SMV>();
List<Node> smvNodes = ParserUtils.getChildNodesWithTag(node, "SMV"); List<Node> smvNodes = ParserUtils.getChildNodesWithTag(node, "SMV");
for (Node smvNode : smvNodes) { for (Node smvNode : smvNodes)
smvs.add(new SMV(smvNode)); smvs.add(new SMV(smvNode));
} }
}
public String getIedName() { public String getIedName() {
return iedName; return iedName;

@ -117,6 +117,9 @@ public class LogicalNode implements DataModelNode {
/* Parse Sampled Values (SV) control block definitions */ /* Parse Sampled Values (SV) control block definitions */
smvControlBlocks = new LinkedList<SampledValueControl>(); smvControlBlocks = new LinkedList<SampledValueControl>();
List<Node> svControlNodes = ParserUtils.getChildNodesWithTag(lnNode, "SampledValueControl");
for (Node svControlNode : svControlNodes)
smvControlBlocks.add(new SampledValueControl(svControlNode));
/* Parse log control block definitions */ /* Parse log control block definitions */
logControlBlocks = new LinkedList<LogControl>(); logControlBlocks = new LinkedList<LogControl>();

@ -14,7 +14,7 @@ public class SampledValueControl {
private String smvID; private String smvID;
private int smpRate; private int smpRate;
private int nofASDU; private int nofASDU;
private boolean multicast; private boolean multicast = false;
private SmvOpts smvOpts; private SmvOpts smvOpts;
@ -31,7 +31,10 @@ public class SampledValueControl {
this.smvID = ParserUtils.parseAttribute(smvControlNode, "smvID"); this.smvID = ParserUtils.parseAttribute(smvControlNode, "smvID");
this.multicast = ParserUtils.parseBooleanAttribute(smvControlNode, "multicast"); Boolean multicast = ParserUtils.parseBooleanAttribute(smvControlNode, "multicast");
if (multicast != null)
this.multicast = multicast;
String smpRateString = ParserUtils.parseAttribute(smvControlNode, "smpRate"); String smpRateString = ParserUtils.parseAttribute(smvControlNode, "smpRate");

@ -8,11 +8,12 @@ import com.libiec61850.scl.SclParserException;
public class SmvOpts { public class SmvOpts {
private boolean refreshTime = false; private boolean refreshTime = false; /* 1 */
private boolean sampleRate = false; private boolean sampleSynchronized = false; /* 2 */
private boolean dataSet = false; private boolean sampleRate = false; /* 4 */
private boolean security = false; private boolean dataSet = false; /* 8 */
private boolean sampleSynchronized = false; private boolean security = false; /* 16 */
public SmvOpts(Node smvOptsNode) throws SclParserException { public SmvOpts(Node smvOptsNode) throws SclParserException {
@ -38,4 +39,16 @@ public class SmvOpts {
} }
public int getIntValue() {
int intValue = 0;
if (refreshTime) intValue += 1;
if (sampleSynchronized) intValue += 2;
if (sampleRate) intValue += 4;
if (dataSet) intValue += 8;
if (security) intValue += 16;
return intValue;
}
} }

@ -51,6 +51,7 @@ import com.libiec61850.scl.model.IED;
import com.libiec61850.scl.model.LogicalDevice; import com.libiec61850.scl.model.LogicalDevice;
import com.libiec61850.scl.model.LogicalNode; import com.libiec61850.scl.model.LogicalNode;
import com.libiec61850.scl.model.ReportControlBlock; import com.libiec61850.scl.model.ReportControlBlock;
import com.libiec61850.scl.model.SampledValueControl;
import com.libiec61850.scl.model.Server; import com.libiec61850.scl.model.Server;
import com.libiec61850.scl.model.SettingControl; import com.libiec61850.scl.model.SettingControl;
import com.libiec61850.scl.model.TriggerOptions; import com.libiec61850.scl.model.TriggerOptions;
@ -71,6 +72,10 @@ public class StaticModelGenerator {
private List<String> gseVariableNames; private List<String> gseVariableNames;
private int currentGseVariableNumber = 0; private int currentGseVariableNumber = 0;
private StringBuffer smvControlBlocks;
private List<String> smvVariableNames;
private int currentSvCBVariableNumber = 0;
private StringBuffer settingGroupControlBlocks; private StringBuffer settingGroupControlBlocks;
private List<String> sgcbVariableNames; private List<String> sgcbVariableNames;
private int currentSGCBVariableNumber = 0; private int currentSGCBVariableNumber = 0;
@ -101,6 +106,9 @@ public class StaticModelGenerator {
this.gseControlBlocks = new StringBuffer(); this.gseControlBlocks = new StringBuffer();
this.gseVariableNames = new LinkedList<String>(); this.gseVariableNames = new LinkedList<String>();
this.smvControlBlocks = new StringBuffer();
this.smvVariableNames = new LinkedList<String>();
this.settingGroupControlBlocks = new StringBuffer(); this.settingGroupControlBlocks = new StringBuffer();
this.sgcbVariableNames = new LinkedList<String>(); this.sgcbVariableNames = new LinkedList<String>();
@ -267,6 +275,8 @@ public class StaticModelGenerator {
createGooseVariableList(logicalDevices); createGooseVariableList(logicalDevices);
createSmvVariableList(logicalDevices);
createSettingControlsVariableList(logicalDevices); createSettingControlsVariableList(logicalDevices);
for (int i = 0; i < logicalDevices.size(); i++) { for (int i = 0; i < logicalDevices.size(); i++) {
@ -308,6 +318,11 @@ public class StaticModelGenerator {
cOut.println(reportControlBlocks); cOut.println(reportControlBlocks);
for (String smv : smvVariableNames)
cOut.println("extern SVControlBlock " + smv + ";");
cOut.println(smvControlBlocks);
for (String gcb : gseVariableNames) for (String gcb : gseVariableNames)
cOut.println("extern GSEControlBlock " + gcb + ";"); cOut.println("extern GSEControlBlock " + gcb + ";");
@ -338,6 +353,11 @@ public class StaticModelGenerator {
else else
cOut.println(" NULL,"); cOut.println(" NULL,");
if (smvVariableNames.size() > 0)
cOut.println(" &" + smvVariableNames.get(0) + ",");
else
cOut.println(" NULL,");
if (sgcbVariableNames.size() > 0) if (sgcbVariableNames.size() > 0)
cOut.println(" &" + sgcbVariableNames.get(0) + ","); cOut.println(" &" + sgcbVariableNames.get(0) + ",");
else else
@ -366,6 +386,28 @@ public class StaticModelGenerator {
} }
} }
private void createSmvVariableList(List<LogicalDevice> logicalDevices) {
for (LogicalDevice ld : logicalDevices) {
List<LogicalNode> lnodes = ld.getLogicalNodes();
String ldName = ld.getInst();
for (LogicalNode ln : lnodes) {
List<SampledValueControl> svCBs = ln.getSampledValueControlBlocks();
int smvCount = 0;
for (SampledValueControl smv : svCBs) {
String smvVariableName = modelPrefix + "_" + ldName + "_" + ln.getName() + "_smv" + smvCount;
smvVariableNames.add(smvVariableName);
smvCount++;
}
}
}
}
private void createReportVariableList(List<LogicalDevice> logicalDevices) { private void createReportVariableList(List<LogicalDevice> logicalDevices) {
for (LogicalDevice ld : logicalDevices) { for (LogicalDevice ld : logicalDevices) {
@ -445,6 +487,8 @@ public class StaticModelGenerator {
printGSEControlBlocks(ldName, lnName, logicalNode); printGSEControlBlocks(ldName, lnName, logicalNode);
printSVControlBlocks(ldName, lnName, logicalNode);
printSettingControlBlock(lnName, logicalNode); printSettingControlBlock(lnName, logicalNode);
} }
} }
@ -742,11 +786,100 @@ public class StaticModelGenerator {
hOut.println("#endif /* " + hDefineName + " */\n"); hOut.println("#endif /* " + hDefineName + " */\n");
} }
private void printSVControlBlocks(String ldName, String lnPrefix, LogicalNode logicalNode) {
List<SampledValueControl> svControlBlocks = logicalNode.getSampledValueControlBlocks();
/* strip "iedModel_" from ldName */
String[] ldNameComponents = ldName.split("_");
String logicalDeviceName = ldNameComponents[1];
int smvControlNumber = 0;
for (SampledValueControl svCB : svControlBlocks) {
System.out.println("SVCB: " + svCB.getName());
PhyComAddress svAddress = connectedAP.lookupSMVAddress(logicalDeviceName, svCB.getName());
String svString = "";
String phyComAddrName = "";
if (svAddress != null) {
phyComAddrName = lnPrefix + "_smv" + smvControlNumber + "_address";
svString += "\nstatic PhyComAddress " + phyComAddrName + " = {\n";
svString += " " + svAddress.getVlanPriority() + ",\n";
svString += " " + svAddress.getVlanId() + ",\n";
svString += " " + svAddress.getAppId() + ",\n";
svString += " {";
for (int i = 0; i < 6; i++) {
svString += "0x" + Integer.toHexString(svAddress.getMacAddress()[i]);
if (i == 5)
svString += "}\n";
else
svString += ", ";
}
svString += "};\n\n";
}
String smvVariableName = lnPrefix + "_smv" + smvControlNumber;
svString += "SVControlBlock " + smvVariableName + " = {";
svString += "&" + lnPrefix + ", ";
svString += "\"" + svCB.getName() + "\", ";
if (svCB.getSmvID() == null)
svString += "NULL, ";
else
svString += "\"" + svCB.getSmvID() + "\", ";
if (svCB.getDatSet() != null)
svString += "\"" + svCB.getDatSet() + "\", ";
else
svString += "NULL, ";
svString += svCB.getSmvOpts().getIntValue() + ", ";
svString += "0, " + svCB.getSmpRate() + ", ";
svString += svCB.getConfRev() + ", ";
if (svAddress != null)
svString += "&" + phyComAddrName + ", ";
else
svString += "NULL, ";
if (svCB.isMulticast())
svString += "false, ";
else
svString += "true, ";
svString += svCB.getNofASDI() + ", ";
currentSvCBVariableNumber++;
if (currentSvCBVariableNumber < smvVariableNames.size())
svString += "&" + smvVariableNames.get(currentSvCBVariableNumber);
else
svString += "NULL";
svString += "};\n";
this.smvControlBlocks.append(svString);
smvControlNumber++;
}
}
private void printGSEControlBlocks(String ldName, String lnPrefix, LogicalNode logicalNode) { private void printGSEControlBlocks(String ldName, String lnPrefix, LogicalNode logicalNode) {
List<GSEControl> gseControlBlocks = logicalNode.getGSEControlBlocks(); List<GSEControl> gseControlBlocks = logicalNode.getGSEControlBlocks();
/* strip "iedModel_" from ldName */
String[] ldNameComponents = ldName.split("_"); String[] ldNameComponents = ldName.split("_");
String logicalDeviceName = ldNameComponents[1]; String logicalDeviceName = ldNameComponents[1];
int gseControlNumber = 0; int gseControlNumber = 0;

Loading…
Cancel
Save