2424
2525import java .math .BigInteger ;
2626import java .util .*;
27+ import java .util .concurrent .atomic .AtomicInteger ;
2728import java .util .stream .Collectors ;
2829import java .util .stream .LongStream ;
2930import 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 ()
0 commit comments