24
24
25
25
import java .math .BigInteger ;
26
26
import java .util .*;
27
+ import java .util .concurrent .atomic .AtomicInteger ;
27
28
import java .util .stream .Collectors ;
28
29
import java .util .stream .LongStream ;
29
30
import java .util .stream .Stream ;
@@ -48,6 +49,8 @@ public class ControlBlockEditorService implements ControlBlockEditor {
48
49
private static final int HEXADECIMAL_BASE = 16 ;
49
50
private final ControlService controlService ;
50
51
private final LdeviceService ldeviceService ;
52
+ private final ConnectedAPService connectedAPService ;
53
+ private final SubNetworkService subNetworkService ;
51
54
52
55
@ Override
53
56
public List <SclReportItem > analyzeDataGroups (SCL scd ) {
@@ -114,8 +117,9 @@ private Stream<SclReportItem> configureNetworkForControlBlocks(SCL scl, Map<CbKe
114
117
}
115
118
List <Long > appIdToReuse = appIdsAndMacsToReuse .values ().stream ().map (AppIdAndMac ::appId ).toList ();
116
119
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 );
119
123
return scl .getIED ().stream ()
120
124
.flatMap (tied ->
121
125
tied .getAccessPoint ()
@@ -137,7 +141,7 @@ private Stream<SclReportItem> configureNetworkForControlBlocks(SCL scl, Map<CbKe
137
141
return newError (iedApLd , tControl , "Cannot configure communication for this ControlBlock because: No controlBlock communication settings found with these " + criteriaOrError .criteria );
138
142
}
139
143
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 );
141
145
})
142
146
.flatMap (Optional ::stream )
143
147
);
@@ -166,12 +170,13 @@ private CbComSettings parseCbCom(CBCom cbCom, TCBType tcbType) {
166
170
return new CbComSettings (appIds , macAddresses , settingsByCriteria );
167
171
}
168
172
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 ()) {
172
178
return newError (iedApLd , tControl , "Cannot configure communication for ControlBlock because no ConnectedAP found for AccessPoint" );
173
179
}
174
- TConnectedAP tConnectedAP = optConApAdapter .get ();
175
180
if (settings .vlanId () == null ) {
176
181
return newError (iedApLd , tControl , "Cannot configure communication for this ControlBlock because no Vlan Id was provided in the settings" );
177
182
}
@@ -182,10 +187,8 @@ private Optional<SclReportItem> configureControlBlockNetwork(TCommunication tCom
182
187
if (!appIdIterator .hasNext ()) {
183
188
return newError (iedApLd , tControl , "Cannot configure communication for this ControlBlock because range of appId is exhausted" );
184
189
}
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 ()));
189
192
}
190
193
191
194
List <TP > listOfPs = new ArrayList <>();
@@ -196,6 +199,7 @@ private Optional<SclReportItem> configureControlBlockNetwork(TCommunication tCom
196
199
listOfPs .add (newP (VLAN_PRIORITY_P_TYPE , String .valueOf (settings .vlanPriority ())));
197
200
}
198
201
202
+ TConnectedAP tConnectedAP = optionalTConnectedAP .orElseThrow ();
199
203
switch (tControl ) {
200
204
case TGSEControl ignored -> updateGseOrCreateIfNotExists (tConnectedAP , iedApLd .lDevice ().getInst (), tControl .getName (), listOfPs , SclConstructorHelper .newDurationInMilliSec (settings .minTime ), SclConstructorHelper .newDurationInMilliSec (settings .maxTime ));
201
205
case TSampledValueControl ignored -> updateSmvOrCreateIfNotExists (tConnectedAP , iedApLd .lDevice ().getInst (), tControl .getName (), listOfPs );
@@ -224,17 +228,6 @@ private Map<CbKey, AppIdAndMac> computeAppIdsAndMacToReuse(SCL scd, List<TSubNet
224
228
.collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
225
229
}
226
230
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
-
238
231
private void updateGseOrCreateIfNotExists (TConnectedAP tConnectedAP , String ldInst , String cbName , List <TP > listOfP , TDurationInMilliSec minTime , TDurationInMilliSec maxTime ) {
239
232
Optional <TGSE > optGse = tConnectedAP .isSetGSE () ?
240
233
tConnectedAP .getGSE ().stream ().filter (gse1 -> Objects .equals (ldInst , gse1 .getLdInst ()) && Objects .equals (cbName , gse1 .getCbName ())).findFirst ()
0 commit comments