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
@@ -0,0 +1,53 @@
package energy.trolie.client.model.common;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* Enumeration of the possible origins of a rating value, as reported by a
* ratings provider on a rating proposal. Preserves the provenance or quality
* of a rating value at the point of submission, distinguishing ratings that
* arose from sensor/calculation failures from those derived normally.
*/
public enum CurrentSource {

/**
* The rating value was derived directly from telemetered sensor data.
*/
TELEMETERED,

/**
* The rating value was derived from a calculation, such as a weather-based
* or dynamic rating calculation.
*/
CALCULATED,

/**
* The rating value was estimated, typically as a fallback when telemetry
* or calculation inputs were unavailable or failed.
*/
ESTIMATED,

/**
* The rating value was manually entered or overridden by an operator.
*/
MANUAL;

/**
* @return the lower-case value used to represent this current-source in JSON.
*/
@JsonValue
public String toJson() {
return name().toLowerCase();
}

/**
* Resolves a {@link CurrentSource} from its JSON representation.
* @param value the JSON string value
* @return the matching {@link CurrentSource}
*/
@JsonCreator
public static CurrentSource fromJson(String value) {
return value == null ? null : CurrentSource.valueOf(value.toUpperCase());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import energy.trolie.client.model.common.CurrentSource;
import energy.trolie.client.model.common.EmergencyRatingValue;
import energy.trolie.client.model.common.RatingValue;

Expand Down Expand Up @@ -40,4 +41,11 @@ public class ForecastPeriodSnapshot {

@JsonProperty("emergency-operating-limits")
private List<EmergencyRatingValue> emergencyOperatingLimits;

/**
* Optional origin/quality of the rating value, e.g. telemetered, calculated,
* estimated, or manual.
*/
@JsonProperty("current-source")
private CurrentSource currentSource;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import energy.trolie.client.model.common.CurrentSource;
import energy.trolie.client.model.common.EmergencyRatingValue;
import energy.trolie.client.model.common.RatingValue;

Expand All @@ -32,4 +33,11 @@ public class RealTimeLimit {
@JsonProperty("emergency-operating-limits")
private List<EmergencyRatingValue> emergencyOperatingLimits;

/**
* Optional origin/quality of the rating value, e.g. telemetered, calculated,
* estimated, or manual.
*/
@JsonProperty("current-source")
private CurrentSource currentSource;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import energy.trolie.client.model.common.CurrentSource;
import energy.trolie.client.model.common.EmergencyRatingValue;
import energy.trolie.client.model.common.RatingValue;
import lombok.AllArgsConstructor;
Expand Down Expand Up @@ -41,4 +42,11 @@ public class SeasonalPeriodSnapshot {

@JsonProperty("emergency-operating-limits")
private List<EmergencyRatingValue> emergencyOperatingLimits;

/**
* Optional origin/quality of the rating value, e.g. telemetered, calculated,
* estimated, or manual.
*/
@JsonProperty("current-source")
private CurrentSource currentSource;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import energy.trolie.client.model.common.CurrentSource;
import energy.trolie.client.model.common.InputValue;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down Expand Up @@ -40,4 +41,11 @@ public class ForecastRatingPeriod {

@JsonProperty("inputs-used")
private List<InputValue> inputsUsed;

/**
* Optional origin/quality of the rating value, e.g. telemetered, calculated,
* estimated, or manual.
*/
@JsonProperty("current-source")
private CurrentSource currentSource;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import energy.trolie.client.model.common.CurrentSource;
import energy.trolie.client.model.common.EmergencyRatingValue;
import energy.trolie.client.model.common.InputValue;
import energy.trolie.client.model.common.RatingValue;
Expand Down Expand Up @@ -33,4 +34,11 @@ public class RealTimeRating {

@JsonProperty("inputs-used")
private List<InputValue> inputsUsed;

/**
* Optional origin/quality of the rating value, e.g. telemetered, calculated,
* estimated, or manual.
*/
@JsonProperty("current-source")
private CurrentSource currentSource;
}
26 changes: 13 additions & 13 deletions java-client/src/test/java/energy/trolie/client/TrolieClientIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -1938,12 +1938,12 @@ private void writeForecastSnapshot(JsonGenerator json, Instant startTime) throws
json.writeFieldName("periods");
json.writeStartArray();
for (int j=0;j<24;j++) {
ForecastPeriodSnapshot period = new ForecastPeriodSnapshot(
startTime,
startTime,
RatingValue.fromMva(100f),
Collections.emptyList()
);
ForecastPeriodSnapshot period = ForecastPeriodSnapshot.builder()
.periodStart(startTime)
.periodEnd(startTime)
.continuousOperatingLimit(RatingValue.fromMva(100f))
.emergencyOperatingLimits(Collections.emptyList())
.build();
json.writeObject(period);
}
json.writeEndArray();
Expand Down Expand Up @@ -1995,13 +1995,13 @@ private void writeSeasonalSnapshot(JsonGenerator json, Instant startTime, String
json.writeFieldName("periods");
json.writeStartArray();
for (int j=0;j<24;j++) {
SeasonalPeriodSnapshot period = new SeasonalPeriodSnapshot(
startTime,
startTime,
season,
RatingValue.fromMva(100f),
Collections.emptyList()
);
SeasonalPeriodSnapshot period = SeasonalPeriodSnapshot.builder()
.periodStart(startTime)
.periodEnd(startTime)
.seasonName(season)
.continuousOperatingLimit(RatingValue.fromMva(100f))
.emergencyOperatingLimits(Collections.emptyList())
.build();
json.writeObject(period);
}
json.writeEndArray();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package energy.trolie.client.model.common;

import com.fasterxml.jackson.databind.ObjectMapper;
import energy.trolie.client.model.operatingsnapshots.RealTimeLimit;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

class CurrentSourceTest {

private final ObjectMapper objectMapper = new ObjectMapper();

@Test
void serializes_to_lowercase_json_value() throws IOException {
assertEquals("\"telemetered\"", objectMapper.writeValueAsString(CurrentSource.TELEMETERED));
assertEquals("\"calculated\"", objectMapper.writeValueAsString(CurrentSource.CALCULATED));
assertEquals("\"estimated\"", objectMapper.writeValueAsString(CurrentSource.ESTIMATED));
assertEquals("\"manual\"", objectMapper.writeValueAsString(CurrentSource.MANUAL));
}

@Test
void deserializes_from_lowercase_json_value() throws IOException {
assertEquals(CurrentSource.TELEMETERED, objectMapper.readValue("\"telemetered\"", CurrentSource.class));
assertEquals(CurrentSource.CALCULATED, objectMapper.readValue("\"calculated\"", CurrentSource.class));
assertEquals(CurrentSource.ESTIMATED, objectMapper.readValue("\"estimated\"", CurrentSource.class));
assertEquals(CurrentSource.MANUAL, objectMapper.readValue("\"manual\"", CurrentSource.class));
}

@Test
void field_is_optional_on_real_time_limit() throws IOException {
RealTimeLimit withoutCurrentSource = RealTimeLimit.builder()
.resourceId("resource1")
.continuousOperatingLimit(RatingValue.fromMva(100f))
.build();

String json = objectMapper.writeValueAsString(withoutCurrentSource);
RealTimeLimit roundTripped = objectMapper.readValue(json, RealTimeLimit.class);

assertNull(roundTripped.getCurrentSource());
}

@Test
void field_round_trips_on_real_time_limit() throws IOException {
RealTimeLimit withCurrentSource = RealTimeLimit.builder()
.resourceId("resource1")
.continuousOperatingLimit(RatingValue.fromMva(100f))
.currentSource(CurrentSource.MANUAL)
.build();

String json = objectMapper.writeValueAsString(withCurrentSource);
RealTimeLimit roundTripped = objectMapper.readValue(json, RealTimeLimit.class);

assertEquals(CurrentSource.MANUAL, roundTripped.getCurrentSource());
}
}
Loading