Skip to content

Commit ed853ab

Browse files
authored
Merge pull request #480 from com-pas/develop
Release 0.2.38
2 parents 9f1b9ff + 0062f76 commit ed853ab

File tree

7 files changed

+195
-38
lines changed

7 files changed

+195
-38
lines changed

sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class SclAutomationServiceIntegrationTest {
3232
private SclAutomationService sclAutomationService ;
3333
private static final SclEditor sclEditor = new SclService() ;
3434
private static final SubstationEditor substationEditor = new SubstationService(new VoltageLevelService()) ;
35-
private static final ControlBlockEditor controlBlockEditor = new ControlBlockEditorService(new ControlService(), new LdeviceService(new LnService()));
35+
private static final ControlBlockEditor controlBlockEditor = new ControlBlockEditorService(new ControlService(), new LdeviceService(new LnService()), new ConnectedAPService(), new SubNetworkService());
3636

3737
private HeaderDTO headerDTO;
3838

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockEditorService.java

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import java.math.BigInteger;
2626
import java.util.*;
27+
import java.util.concurrent.atomic.AtomicInteger;
2728
import java.util.stream.Collectors;
2829
import java.util.stream.LongStream;
2930
import java.util.stream.Stream;
@@ -48,6 +49,8 @@ public class ControlBlockEditorService implements ControlBlockEditor {
4849
private static final int HEXADECIMAL_BASE = 16;
4950
private final ControlService controlService;
5051
private final LdeviceService ldeviceService;
52+
private final ConnectedAPService connectedAPService;
53+
private final SubNetworkService subNetworkService;
5154

5255
@Override
5356
public List<SclReportItem> analyzeDataGroups(SCL scd) {
@@ -114,8 +117,9 @@ private Stream<SclReportItem> configureNetworkForControlBlocks(SCL scl, Map<CbKe
114117
}
115118
List<Long> appIdToReuse = appIdsAndMacsToReuse.values().stream().map(AppIdAndMac::appId).toList();
116119
List<Long> macToReuse = appIdsAndMacsToReuse.values().stream().map(AppIdAndMac::mac).toList();
117-
PrimitiveIterator.OfLong appIdIterator = cbComSettings.appIds.filter(appId -> !appIdToReuse.contains(appId)).iterator();
118-
PrimitiveIterator.OfLong macIterator = cbComSettings.macAddresses.filter(mac -> !macToReuse.contains(mac)).iterator();
120+
PrimitiveIterator.OfLong appIdIterator = cbComSettings.appIds().filter(appId -> !appIdToReuse.contains(appId)).iterator();
121+
List<Long> macAddresseList = cbComSettings.macAddresses().filter(mac -> !macToReuse.contains(mac)).boxed().toList();
122+
AtomicInteger macAddresseIndex = new AtomicInteger(0);
119123
return scl.getIED().stream()
120124
.flatMap(tied ->
121125
tied.getAccessPoint()
@@ -137,7 +141,7 @@ private Stream<SclReportItem> configureNetworkForControlBlocks(SCL scl, Map<CbKe
137141
return newError(iedApLd, tControl, "Cannot configure communication for this ControlBlock because: No controlBlock communication settings found with these " + criteriaOrError.criteria);
138142
}
139143
AppIdAndMac reuseAppIdAndMac = appIdsAndMacsToReuse.get(new CbKey(iedApLd.ied.getName(), iedApLd.lDevice.getInst(), tControl.getName()));
140-
return configureControlBlockNetwork(scl.getCommunication(), settings, appIdIterator, macIterator, tControl, iedApLd, reuseAppIdAndMac);
144+
return configureControlBlockNetwork(scl.getCommunication(), settings, appIdIterator, macAddresseList, macAddresseIndex, tControl, iedApLd, reuseAppIdAndMac);
141145
})
142146
.flatMap(Optional::stream)
143147
);
@@ -166,12 +170,13 @@ private CbComSettings parseCbCom(CBCom cbCom, TCBType tcbType) {
166170
return new CbComSettings(appIds, macAddresses, settingsByCriteria);
167171
}
168172

169-
private Optional<SclReportItem> configureControlBlockNetwork(TCommunication tCommunication, Settings settings, PrimitiveIterator.OfLong appIdIterator, PrimitiveIterator.OfLong macAddressIterator, TControl tControl, IedApLd iedApLd, AppIdAndMac reuseAppIdAndMac) {
170-
Optional<TConnectedAP> optConApAdapter = findConnectedAp(tCommunication, iedApLd.ied.getName(), iedApLd.apName);
171-
if (optConApAdapter.isEmpty()) {
173+
private Optional<SclReportItem> configureControlBlockNetwork(TCommunication tCommunication, Settings settings, PrimitiveIterator.OfLong appIdIterator, List<Long> macAddressList, AtomicInteger macAddresseIndex, TControl tControl, IedApLd iedApLd, AppIdAndMac reuseAppIdAndMac) {
174+
Optional<TConnectedAP> optionalTConnectedAP = subNetworkService.getSubNetworks(tCommunication)
175+
.flatMap(tSubNetwork -> connectedAPService.getFilteredConnectedAP(tSubNetwork, connectedAP -> iedApLd.ied.getName().equals(connectedAP.getIedName()) && iedApLd.apName.equals(connectedAP.getApName())))
176+
.findFirst();
177+
if (optionalTConnectedAP.isEmpty()) {
172178
return newError(iedApLd, tControl, "Cannot configure communication for ControlBlock because no ConnectedAP found for AccessPoint");
173179
}
174-
TConnectedAP tConnectedAP = optConApAdapter.get();
175180
if (settings.vlanId() == null) {
176181
return newError(iedApLd, tControl, "Cannot configure communication for this ControlBlock because no Vlan Id was provided in the settings");
177182
}
@@ -182,10 +187,8 @@ private Optional<SclReportItem> configureControlBlockNetwork(TCommunication tCom
182187
if (!appIdIterator.hasNext()) {
183188
return newError(iedApLd, tControl, "Cannot configure communication for this ControlBlock because range of appId is exhausted");
184189
}
185-
if (!macAddressIterator.hasNext()) {
186-
return newError(iedApLd, tControl, "Cannot configure communication for this ControlBlock because range of MAC Address is exhausted");
187-
}
188-
appIdAndMac = new AppIdAndMac(appIdIterator.nextLong(), macAddressIterator.nextLong());
190+
// For the MAC adress assignation, we restart from the begining if we reach the end of the range
191+
appIdAndMac = new AppIdAndMac(appIdIterator.nextLong(), macAddressList.get(macAddresseIndex.getAndIncrement() % macAddressList.size()));
189192
}
190193

191194
List<TP> listOfPs = new ArrayList<>();
@@ -196,6 +199,7 @@ private Optional<SclReportItem> configureControlBlockNetwork(TCommunication tCom
196199
listOfPs.add(newP(VLAN_PRIORITY_P_TYPE, String.valueOf(settings.vlanPriority())));
197200
}
198201

202+
TConnectedAP tConnectedAP = optionalTConnectedAP.orElseThrow();
199203
switch (tControl) {
200204
case TGSEControl ignored -> updateGseOrCreateIfNotExists(tConnectedAP, iedApLd.lDevice().getInst(), tControl.getName(), listOfPs, SclConstructorHelper.newDurationInMilliSec(settings.minTime), SclConstructorHelper.newDurationInMilliSec(settings.maxTime));
201205
case TSampledValueControl ignored -> updateSmvOrCreateIfNotExists(tConnectedAP, iedApLd.lDevice().getInst(), tControl.getName(), listOfPs);
@@ -224,17 +228,6 @@ private Map<CbKey, AppIdAndMac> computeAppIdsAndMacToReuse(SCL scd, List<TSubNet
224228
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
225229
}
226230

227-
private Optional<TConnectedAP> findConnectedAp(TCommunication tCommunication, String iedName, String apName) {
228-
if (tCommunication == null || !tCommunication.isSetSubNetwork()) {
229-
return Optional.empty();
230-
}
231-
return tCommunication.getSubNetwork().stream()
232-
.filter(TSubNetwork::isSetConnectedAP)
233-
.flatMap(tSubNetwork -> tSubNetwork.getConnectedAP().stream())
234-
.filter(tConnectedAP -> iedName.equals(tConnectedAP.getIedName()) && apName.equals(tConnectedAP.getApName()))
235-
.findFirst();
236-
}
237-
238231
private void updateGseOrCreateIfNotExists(TConnectedAP tConnectedAP, String ldInst, String cbName, List<TP> listOfP, TDurationInMilliSec minTime, TDurationInMilliSec maxTime) {
239232
Optional<TGSE> optGse = tConnectedAP.isSetGSE() ?
240233
tConnectedAP.getGSE().stream().filter(gse1 -> Objects.equals(ldInst, gse1.getLdInst()) && Objects.equals(cbName, gse1.getCbName())).findFirst()

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/IedService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import org.lfenergy.compas.scl2007b4.model.SCL;
88
import org.lfenergy.compas.scl2007b4.model.TIED;
9+
import org.lfenergy.compas.sct.commons.exception.ScdException;
910

1011
import java.util.Optional;
1112
import java.util.function.Predicate;
@@ -20,4 +21,10 @@ public Stream<TIED> getFilteredIeds(SCL scd, Predicate<TIED> iedPredicate) {
2021
public Optional<TIED> findIed(SCL scd, Predicate<TIED> iedPredicate) {
2122
return getFilteredIeds(scd, iedPredicate).findFirst();
2223
}
24+
25+
public Optional<TIED> findByName(SCL scd, String iedName) {
26+
if (null == iedName)
27+
throw new ScdException("The given iedName is null");
28+
return findIed(scd, tied -> iedName.equals(tied.getName()));
29+
}
2330
}

sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SubNetworkService.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
package org.lfenergy.compas.sct.commons;
66

7-
import org.lfenergy.compas.scl2007b4.model.TSubNetwork;
87
import org.lfenergy.compas.scl2007b4.model.SCL;
8+
import org.lfenergy.compas.scl2007b4.model.TCommunication;
9+
import org.lfenergy.compas.scl2007b4.model.TSubNetwork;
910

1011
import java.util.Optional;
1112
import java.util.function.Predicate;
@@ -23,6 +24,13 @@ public Stream<TSubNetwork> getSubNetworks(SCL scl) {
2324
return scl.getCommunication().getSubNetwork().stream();
2425
}
2526

27+
public Stream<TSubNetwork> getSubNetworks(TCommunication tCommunication) {
28+
if (!tCommunication.isSetSubNetwork()) {
29+
return Stream.empty();
30+
}
31+
return tCommunication.getSubNetwork().stream();
32+
}
33+
2634
public Stream<TSubNetwork> getFilteredSubNetworks(SCL tlNodeType, Predicate<TSubNetwork> tdoPredicate) {
2735
return getSubNetworks(tlNodeType).filter(tdoPredicate);
2836
}

sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockEditorServiceTest.java

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class ControlBlockEditorServiceTest {
5050

5151
@BeforeEach
5252
void init() {
53-
controlBlockEditorService = new ControlBlockEditorService(new ControlService(), new LdeviceService(new LnService()));
53+
controlBlockEditorService = new ControlBlockEditorService(new ControlService(), new LdeviceService(new LnService()), new ConnectedAPService(), new SubNetworkService());
5454
}
5555

5656
@Test
@@ -347,14 +347,67 @@ void configureNetworkForAllControlBlocks_should_create_GSE_with_incremental_appi
347347
cbCom.getAppIdRanges().getAppIdRange().getFirst().setEnd("000B");
348348
cbCom.getMacRanges().getMacRange().getFirst().setStart("01-02-03-04-00-FF");
349349
cbCom.getMacRanges().getMacRange().getFirst().setEnd("01-02-03-04-01-01");
350+
351+
// When
352+
List<SclReportItem> sclReportItems = controlBlockEditorService.configureNetworkForAllControlBlocks(scd, cbCom);
353+
354+
// Then
355+
assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue();
356+
assertThat(scd.getCommunication().getSubNetwork())
357+
.flatExtracting(TSubNetwork::getConnectedAP)
358+
.flatExtracting(TConnectedAP::getGSE)
359+
.extracting(TControlBlock::getAddress)
360+
.flatExtracting(TAddress::getP)
361+
.extracting(TP::getType, TP::getValue)
362+
.containsExactly(
363+
Tuple.tuple("APPID", "0009"),
364+
Tuple.tuple("MAC-Address", "01-02-03-04-00-FF"),
365+
Tuple.tuple("VLAN-ID", "12D"),
366+
Tuple.tuple("VLAN-PRIORITY", "1"),
367+
Tuple.tuple("APPID", "000A"),
368+
Tuple.tuple("MAC-Address", "01-02-03-04-01-00"),
369+
Tuple.tuple("VLAN-ID", "12D"),
370+
Tuple.tuple("VLAN-PRIORITY", "1"),
371+
Tuple.tuple("APPID", "000B"),
372+
Tuple.tuple("MAC-Address", "01-02-03-04-01-01"),
373+
Tuple.tuple("VLAN-ID", "12E"),
374+
Tuple.tuple("VLAN-PRIORITY", "2")
375+
);
376+
}
377+
378+
@Test
379+
void configureNetworkForAllControlBlocks_should_restart_Mac_adress() {
380+
// Given
381+
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml");
382+
CBCom cbCom = createCbCom();
383+
cbCom.getMacRanges().getMacRange().getFirst().setStart("01-0C-CD-01-00-00");
384+
cbCom.getMacRanges().getMacRange().getFirst().setEnd("01-0C-CD-01-00-01");
385+
350386
// When
351387
List<SclReportItem> sclReportItems = controlBlockEditorService.configureNetworkForAllControlBlocks(scd, cbCom);
388+
352389
// Then
353390
assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue();
354-
assertThat(streamAllConnectedApGseP(scd, "APPID"))
355-
.containsExactlyInAnyOrder("0009", "000A", "000B");
356-
assertThat(streamAllConnectedApGseP(scd, "MAC-Address"))
357-
.containsExactlyInAnyOrder("01-02-03-04-00-FF", "01-02-03-04-01-00", "01-02-03-04-01-01");
391+
assertThat(scd.getCommunication().getSubNetwork())
392+
.flatExtracting(TSubNetwork::getConnectedAP)
393+
.flatExtracting(TConnectedAP::getGSE)
394+
.extracting(TControlBlock::getAddress)
395+
.flatExtracting(TAddress::getP)
396+
.extracting(TP::getType, TP::getValue)
397+
.containsExactly(
398+
Tuple.tuple("APPID", "0000"),
399+
Tuple.tuple("MAC-Address", "01-0C-CD-01-00-00"),
400+
Tuple.tuple("VLAN-ID", "12D"),
401+
Tuple.tuple("VLAN-PRIORITY", "1"),
402+
Tuple.tuple("APPID", "0001"),
403+
Tuple.tuple("MAC-Address", "01-0C-CD-01-00-01"),
404+
Tuple.tuple("VLAN-ID", "12D"),
405+
Tuple.tuple("VLAN-PRIORITY", "1"),
406+
Tuple.tuple("APPID", "0002"),
407+
Tuple.tuple("MAC-Address", "01-0C-CD-01-00-00"),
408+
Tuple.tuple("VLAN-ID", "12E"),
409+
Tuple.tuple("VLAN-PRIORITY", "2")
410+
);
358411
}
359412

360413
@ParameterizedTest
@@ -378,18 +431,13 @@ public static Stream<Arguments> provideConfigureNetworkForAllControlBlocksErrors
378431
CBCom cbComWithNotEnoughAppId = createCbCom();
379432
cbComWithNotEnoughAppId.getAppIdRanges().getAppIdRange().getFirst().setStart("0000");
380433
cbComWithNotEnoughAppId.getAppIdRanges().getAppIdRange().getFirst().setEnd("00001");
381-
CBCom cbComWithNotEnoughMacAddress = createCbCom();
382-
cbComWithNotEnoughMacAddress.getMacRanges().getMacRange().getFirst().setStart("01-0C-CD-01-00-00");
383-
cbComWithNotEnoughMacAddress.getMacRanges().getMacRange().getFirst().setEnd("01-0C-CD-01-00-01");
384434

385435
return Stream.of(
386436
Arguments.of(cbComWithNoVlan, "Cannot configure communication for this ControlBlock because: No controlBlock communication settings found with these Criteria[cbType=GOOSE, systemVersionWithoutV=01.00.009.001, iedType=BCU, iedRedundancy=A, iedSystemVersionInstance=1, bayIntOrExt=BAY_INTERNAL]",
387437
"/SCL/IED[@name=\"IED_NAME2\"]/AccessPoint[@name=\"AP_NAME\"]/Server/LDevice[@inst=\"LD_INST21\"]/LN0/GSEControl[@name=\"CB_LD_INST21_GMI\"]"),
388438
Arguments.of(cbComWithMissingVlanId, "Cannot configure communication for this ControlBlock because no Vlan Id was provided in the settings",
389439
"/SCL/IED[@name=\"IED_NAME2\"]/AccessPoint[@name=\"AP_NAME\"]/Server/LDevice[@inst=\"LD_INST21\"]/LN0/GSEControl[@name=\"CB_LD_INST21_GMI\"]"),
390440
Arguments.of(cbComWithNotEnoughAppId, "Cannot configure communication for this ControlBlock because range of appId is exhausted",
391-
"/SCL/IED[@name=\"IED_NAME3\"]/AccessPoint[@name=\"AP_NAME\"]/Server/LDevice[@inst=\"LD_INST31\"]/LN0/GSEControl[@name=\"CB_LD_INST31_GSE\"]"),
392-
Arguments.of(cbComWithNotEnoughMacAddress, "Cannot configure communication for this ControlBlock because range of MAC Address is exhausted",
393441
"/SCL/IED[@name=\"IED_NAME3\"]/AccessPoint[@name=\"AP_NAME\"]/Server/LDevice[@inst=\"LD_INST31\"]/LN0/GSEControl[@name=\"CB_LD_INST31_GSE\"]")
394442
);
395443
}

sct-commons/src/test/java/org/lfenergy/compas/sct/commons/IedServiceTest.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,24 @@
88
import org.junit.jupiter.api.Test;
99
import org.lfenergy.compas.scl2007b4.model.SCL;
1010
import org.lfenergy.compas.scl2007b4.model.TIED;
11+
import org.lfenergy.compas.sct.commons.exception.ScdException;
1112
import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller;
1213

1314
import java.util.List;
1415

1516
import static org.assertj.core.api.Assertions.assertThat;
17+
import static org.assertj.core.api.Assertions.assertThatCode;
1618

1719
class IedServiceTest {
1820

1921
@Test
2022
void getFilteredIeds_should_return_ldevices() {
2123
//Given
2224
SCL std = SclTestMarshaller.getSCLFromFile("/std/std_sample.std");
23-
IedService ldeviceService = new IedService();
25+
IedService iedService = new IedService();
2426

2527
//When
26-
List<TIED> tieds = ldeviceService.getFilteredIeds(std, tied -> "IED4d4fe1a8cda64cf88a5ee4176a1a0eef".equals(tied.getName())).toList();
28+
List<TIED> tieds = iedService.getFilteredIeds(std, tied -> "IED4d4fe1a8cda64cf88a5ee4176a1a0eef".equals(tied.getName())).toList();
2729

2830
//Then
2931
assertThat(tieds)
@@ -32,14 +34,42 @@ void getFilteredIeds_should_return_ldevices() {
3234
.containsExactly(Tuple.tuple("IED4d4fe1a8cda64cf88a5ee4176a1a0eef", "ADU"));
3335
}
3436

37+
@Test
38+
void findByName_should_return_ied_infos() {
39+
//Given
40+
SCL std = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_binders_test.xml");
41+
IedService iedService = new IedService();
42+
43+
//When
44+
TIED tied = iedService.findByName(std, "IED_NAME1").orElseThrow();
45+
46+
//Then
47+
assertThat(tied)
48+
.extracting(TIED::getName, TIED::getType)
49+
.containsExactly("IED_NAME1", null);
50+
}
51+
52+
@Test
53+
void findByName_should_fail() {
54+
//Given
55+
SCL std = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_binders_test.xml");
56+
IedService iedService = new IedService();
57+
58+
//When
59+
//Then
60+
assertThatCode(() -> iedService.findByName(std, null))
61+
.isInstanceOf(ScdException.class)
62+
.hasMessage("The given iedName is null");
63+
}
64+
3565
@Test
3666
void findIed_should_return_ldevice() {
3767
//Given
3868
SCL std = SclTestMarshaller.getSCLFromFile("/std/std_sample.std");
39-
IedService ldeviceService = new IedService();
69+
IedService iedService = new IedService();
4070

4171
//When
42-
TIED tied = ldeviceService.findIed(std, ied -> "IED4d4fe1a8cda64cf88a5ee4176a1a0eef".equals(ied.getName())).orElseThrow();
72+
TIED tied = iedService.findIed(std, ied -> "IED4d4fe1a8cda64cf88a5ee4176a1a0eef".equals(ied.getName())).orElseThrow();
4373

4474
//Then
4575
assertThat(tied)

0 commit comments

Comments
 (0)