Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ public ReportNode updateMeasurements(Branch<?> branch, BranchModificationInfos b
return estimSubReportNode;
}

private void upsertMeasurement(Measurements<?> measurements, Measurement.Type type, ThreeSides side, Double value, Boolean validity, List<ReportNode> reports) {
if (value == null && validity == null) {
private void upsertMeasurement(Measurements<?> measurements, Measurement.Type type, ThreeSides side, Double value, Boolean requestedValidity, List<ReportNode> reports) {
if (value == null && requestedValidity == null) {
return;
}
String measurementType = (type == Measurement.Type.ACTIVE_POWER ? "Active power" : "Reactive power") + " measurement ";
Expand All @@ -223,20 +223,21 @@ private void upsertMeasurement(Measurements<?> measurements, Measurement.Type ty
m.setValue(value);
reports.add(ModificationUtils.buildModificationReport(oldValue, value, measurementType + VALUE, TypedValue.INFO_SEVERITY));
}
if (validity != null) {
if (requestedValidity != null) {
boolean oldValidity = m.isValid();
m.setValid(validity);
reports.add(ModificationUtils.buildModificationReport(oldValidity, validity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));

ModificationUtils.updateMeasurementValidity(m, requestedValidity);
reports.add(ModificationUtils.buildModificationReport(oldValidity, requestedValidity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
}
} else { // add new measurement
var mAdder = measurements.newMeasurement().setId(UUID.randomUUID().toString()).setType(type).setSide(side);
if (value != null) {
mAdder.setValue(value);
reports.add(ModificationUtils.buildModificationReport(null, value, measurementType + VALUE, TypedValue.INFO_SEVERITY));
}
if (validity != null) {
mAdder.setValid(validity);
reports.add(ModificationUtils.buildModificationReport(null, validity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
if (requestedValidity != null) {
mAdder.setValid(requestedValidity);
reports.add(ModificationUtils.buildModificationReport(null, requestedValidity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
}
mAdder.add();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ protected ReportNode updateMeasurements(Injection<?> injection, InjectionModific
return estimSubReportNode;
}

private void upsertMeasurement(Measurements<?> measurements, Measurement.Type type, Double value, Boolean validity, List<ReportNode> reports) {
if (value == null && validity == null) {
private void upsertMeasurement(Measurements<?> measurements, Measurement.Type type, Double value, Boolean requestedValidity, List<ReportNode> reports) {
if (value == null && requestedValidity == null) {
return;
}
String measurementType = (type == Measurement.Type.ACTIVE_POWER ? "Active power" : "Reactive power") + " measurement ";
Expand All @@ -72,20 +72,21 @@ private void upsertMeasurement(Measurements<?> measurements, Measurement.Type ty
measurement.setValue(value);
reports.add(ModificationUtils.buildModificationReport(oldValue, value, measurementType + VALUE, TypedValue.INFO_SEVERITY));
}
if (validity != null) {
if (requestedValidity != null) {
boolean oldValidity = measurement.isValid();
measurement.setValid(validity);
reports.add(ModificationUtils.buildModificationReport(oldValidity, validity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));

ModificationUtils.updateMeasurementValidity(measurement, requestedValidity);
reports.add(ModificationUtils.buildModificationReport(oldValidity, requestedValidity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
}
} else {
var measurementAdder = measurements.newMeasurement().setId(UUID.randomUUID().toString()).setType(type);
if (value != null) {
measurementAdder.setValue(value);
reports.add(ModificationUtils.buildModificationReport(null, value, measurementType + VALUE, TypedValue.INFO_SEVERITY));
}
if (validity != null) {
measurementAdder.setValid(validity);
reports.add(ModificationUtils.buildModificationReport(null, validity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
if (requestedValidity != null) {
measurementAdder.setValid(requestedValidity);
reports.add(ModificationUtils.buildModificationReport(null, requestedValidity, measurementType + VALIDITY, TypedValue.INFO_SEVERITY));
}
measurementAdder.add();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public final class ModificationUtils {
private static final String COULD_NOT_ACTION_EQUIPMENT_ON_SIDE = COULD_NOT_ACTION_EQUIPMENT + " on side %s";
public static final String CONNECT = "connect";
public static final String DISCONNECT = "disconnect";
private static final String MEASUREMENT_VALIDITY_PROPERTY = "validity";
public static final String FIELD_MAX_ACTIVE_POWER = "Maximum active power";
public static final String FIELD_MIN_ACTIVE_POWER = "Minimum active power";
public static final String FIELD_PLANNED_ACTIVE_POWER_SET_POINT = "Planned active power set point";
Expand Down Expand Up @@ -2193,5 +2194,27 @@ public void createNewActivePowerControlForInjectionCreation(ActivePowerControlAd
}

}
}

public static void updateMeasurementValidity(Measurement measurement, boolean requestedValidity) {
measurement.setValid(requestedValidity);
if (measurement.getProperty(MEASUREMENT_VALIDITY_PROPERTY) != null) {
if (requestedValidity) {
switch (measurement.getProperty(MEASUREMENT_VALIDITY_PROPERTY)) {
//validity = 1 → TM non valid & not masked
//validity = 3 → TM non valid & masked
case "1": measurement.putProperty(MEASUREMENT_VALIDITY_PROPERTY, "0"); break;
case "3": measurement.putProperty(MEASUREMENT_VALIDITY_PROPERTY, "2"); break;
default: break;
}
} else {
switch (measurement.getProperty(MEASUREMENT_VALIDITY_PROPERTY)) {
//validity = 0 → TM valid & not masked
//validity = 2 → TM valid & masked
case "0": measurement.putProperty(MEASUREMENT_VALIDITY_PROPERTY, "1"); break;
case "2": measurement.putProperty(MEASUREMENT_VALIDITY_PROPERTY, "3"); break;
default: break;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -591,4 +591,208 @@ void testLimitsPropertiesModificationSameOperationalLimitsReplace() {
assertEquals(OLG_PROP3_VALUE, repLimitsGroup2.getProperty(OLG_PROP3_NAME));
}

@Test
void testMeasurementValidityPropertyForLine() {
Line line = getNetwork().getLine("line1");
Measurements<?> measurements = (Measurements<?>) line.getExtension(Measurements.class);
assertNotNull(measurements);
Measurement activePowerMeasurement = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.ONE)
.findFirst()
.orElseThrow();

LineModificationInfos addSide1ActiveByValue = LineModificationInfos.builder()
.equipmentId("line1")
.p1MeasurementValue(new AttributeModification<>(79.0, OperationType.SET))
.build();
addSide1ActiveByValue.toModification().apply(getNetwork());
assertEquals(79.0, activePowerMeasurement.getValue());

activePowerMeasurement.putProperty("validity", "1");
LineModificationInfos modificationInfosTrueFromOne = LineModificationInfos.builder()
.equipmentId("line1")
.p1MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
.build();
modificationInfosTrueFromOne.toModification().apply(getNetwork());
assertEquals("0", activePowerMeasurement.getProperty("validity"));

activePowerMeasurement.putProperty("validity", "3");
LineModificationInfos modificationInfosTrueFromThree = LineModificationInfos.builder()
.equipmentId("line1")
.p1MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
.build();
modificationInfosTrueFromThree.toModification().apply(getNetwork());
assertEquals("2", activePowerMeasurement.getProperty("validity"));

Measurement reactivePowerMeasurement = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.ONE)
.findFirst()
.orElseThrow();
reactivePowerMeasurement.putProperty("validity", "2");
LineModificationInfos modificationInfosFalseFromTwo = LineModificationInfos.builder()
.equipmentId("line1")
.q1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
.build();
modificationInfosFalseFromTwo.toModification().apply(getNetwork());
assertEquals("3", reactivePowerMeasurement.getProperty("validity"));

reactivePowerMeasurement.putProperty("validity", "0");
LineModificationInfos modificationInfosFalseFromZero = LineModificationInfos.builder()
.equipmentId("line1")
.q1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
.build();
modificationInfosFalseFromZero.toModification().apply(getNetwork());
assertEquals("1", reactivePowerMeasurement.getProperty("validity"));

// update validity on existing measurement without legacy property
reactivePowerMeasurement.removeProperty("validity");
LineModificationInfos modificationInfosTrueWithoutProperty = LineModificationInfos.builder()
.equipmentId("line1")
.q1MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
.build();
modificationInfosTrueWithoutProperty.toModification().apply(getNetwork());
assertTrue(reactivePowerMeasurement.isValid());
assertNull(reactivePowerMeasurement.getProperty("validity"));

// add side 2 (new) measurement by value only
assertTrue(measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream().noneMatch(m -> m.getSide() == ThreeSides.TWO));
LineModificationInfos addSide2ActiveByValue = LineModificationInfos.builder()
.equipmentId("line1")
.p2MeasurementValue(new AttributeModification<>(42.0, OperationType.SET))
.build();
addSide2ActiveByValue.toModification().apply(getNetwork());
Measurement addedActiveSide2 = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.TWO)
.findFirst()
.orElseThrow();
assertEquals(42.0, addedActiveSide2.getValue());

// add side 2 reactive measurement by validity only then update it
assertTrue(measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream().noneMatch(m -> m.getSide() == ThreeSides.TWO));
LineModificationInfos addSide2ReactiveByValidity = LineModificationInfos.builder()
.equipmentId("line1")
.q2MeasurementValue(new AttributeModification<>(MEASUREMENT_Q_VALUE, OperationType.SET))
.q2MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
.build();
addSide2ReactiveByValidity.toModification().apply(getNetwork());

Measurement addedReactiveSide2 = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.TWO)
.findFirst()
.orElseThrow();
assertFalse(addedReactiveSide2.isValid());

LineModificationInfos updateSide2ReactiveValidity = LineModificationInfos.builder()
.equipmentId("line1")
.q2MeasurementValue(new AttributeModification<>(MEASUREMENT_Q_VALUE, OperationType.SET))
.q2MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
.build();
updateSide2ReactiveValidity.toModification().apply(getNetwork());
assertTrue(addedReactiveSide2.isValid());
}

@Test
void testCreateMeasurementsExtensionWhenMissing() {
Line line = getNetwork().getLine("line2");
assertNull(line.getExtension(Measurements.class));

LineModificationInfos lineModificationInfos = LineModificationInfos.builder()
.equipmentId("line2")
.p1MeasurementValidity(new AttributeModification<>(true, OperationType.SET))
.p1MeasurementValue(new AttributeModification<>(MEASUREMENT_P_VALUE, OperationType.SET))
.q1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
.q1MeasurementValue(new AttributeModification<>(MEASUREMENT_Q_VALUE, OperationType.SET))
.build();
lineModificationInfos.toModification().apply(getNetwork());

Measurements<?> measurements = (Measurements<?>) line.getExtension(Measurements.class);
assertNotNull(measurements);

Measurement p1Measurement = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.ONE)
.findFirst()
.orElseThrow();
assertEquals(10.0, p1Measurement.getValue());
assertTrue(p1Measurement.isValid());

Measurement q1Measurement = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.ONE)
.findFirst()
.orElseThrow();
assertEquals(-10.0, q1Measurement.getValue());
assertFalse(q1Measurement.isValid());
}

@Test
void testCreateMeasurementsExtensionWhenMissingOnlyWithValue() {
Line line = getNetwork().getLine("line2");
assertNull(line.getExtension(Measurements.class));

LineModificationInfos lineModificationInfos = LineModificationInfos.builder()
.equipmentId("line2")
.p1MeasurementValue(new AttributeModification<>(MEASUREMENT_P_VALUE, OperationType.SET))
.q1MeasurementValue(new AttributeModification<>(MEASUREMENT_Q_VALUE, OperationType.SET))
.build();
lineModificationInfos.toModification().apply(getNetwork());

Measurements<?> measurements = (Measurements<?>) line.getExtension(Measurements.class);
assertNotNull(measurements);

Measurement p1Measurement = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.ONE)
.findFirst()
.orElseThrow();
assertEquals(10.0, p1Measurement.getValue());
assertTrue(p1Measurement.isValid()); // a Measurement is valid by default

Measurement q1Measurement = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.ONE)
.findFirst()
.orElseThrow();
assertEquals(-10.0, q1Measurement.getValue());
assertTrue(q1Measurement.isValid());
}

@Test
void testCreateMeasurementsExtensionWhenMissingOnlyWithFalseValidity() {
Line line = getNetwork().getLine("line2");
assertNull(line.getExtension(Measurements.class));

LineModificationInfos lineModificationInfos = LineModificationInfos.builder()
.equipmentId("line2")
.p1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
.q1MeasurementValidity(new AttributeModification<>(false, OperationType.SET))
.build();
lineModificationInfos.toModification().apply(getNetwork());

Measurements<?> measurements = (Measurements<?>) line.getExtension(Measurements.class);
assertNotNull(measurements);

Measurement p1Measurement = measurements.getMeasurements(Measurement.Type.ACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.ONE)
.findFirst()
.orElseThrow();
assertTrue(Double.isNaN(p1Measurement.getValue()));
assertFalse(p1Measurement.isValid());

Measurement q1Measurement = measurements.getMeasurements(Measurement.Type.REACTIVE_POWER).stream()
.filter(m -> m.getSide() == ThreeSides.ONE)
.findFirst()
.orElseThrow();
assertTrue(Double.isNaN(q1Measurement.getValue()));
assertFalse(q1Measurement.isValid());
}

@Test
void testCannotCreateMeasurementsExtensionWhenMissingWithOnlyTrueValidity() {
Line line = getNetwork().getLine("line2");
assertNull(line.getExtension(Measurements.class));

LineModificationInfos lineModificationInfos = LineModificationInfos.builder()
.equipmentId("line2")
.p1MeasurementValidity(new AttributeModification<>(true, OperationType.SET)) // not allowed by powsybl on extension creation
.build();
PowsyblException e = assertThrows(PowsyblException.class, () -> lineModificationInfos.toModification().apply(getNetwork()));
assertEquals("Valid measurement cannot have an undefined value", e.getMessage());
}
}
Loading