Skip to content

Commit

Permalink
Release 3.5.2: Introduce DAO interfaces to clarify interface with dat…
Browse files Browse the repository at this point in the history
…a layer.
  • Loading branch information
dmkeen committed Nov 23, 2024
1 parent 464c004 commit 71dca07
Show file tree
Hide file tree
Showing 20 changed files with 262 additions and 52 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>org.keen</groupId>
<artifactId>solar</artifactId>
<version>3.5.1</version>
<version>3.5.2</version>

<name>solar</name>
<description>Retrieves solar data from a Fronius inverter and persists it to a data store.</description>
Expand Down Expand Up @@ -112,7 +112,7 @@
<!-- Excluding tests which call the Fronius API and hence will only run locally -->
<exclude>**/CurrentPowerRetrieverIT.java</exclude>
<exclude>**/StringPowerRetrieverIT.java</exclude>
<exclude>**/InverterInfoLoggerIT.java</exclude>
<exclude>**/SystemInfoLoggerIT.java</exclude>
</excludes>
</configuration>
<executions>
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/org/keen/solar/financial/PowerCostCalculator.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.keen.solar.financial;

import org.keen.solar.financial.dal.TariffRepository;
import org.keen.solar.financial.dal.PowerCostRepository;
import org.keen.solar.financial.dal.TariffDao;
import org.keen.solar.financial.dal.PowerCostDao;
import org.keen.solar.financial.domain.PowerCost;
import org.keen.solar.financial.domain.Tariff;
import org.keen.solar.system.domain.CurrentPower;
Expand Down Expand Up @@ -39,13 +39,13 @@ public class PowerCostCalculator {
* up to 3600 (the number of seconds in one hour).
*/
private final int collectionFrequencySeconds;
private final TariffRepository tariffRepository;
private final PowerCostRepository powerCostRepository;
private final TariffDao tariffRepository;
private final PowerCostDao powerCostRepository;
private final Deque<CurrentPower> uncostedPowers = new ConcurrentLinkedDeque<>();

public PowerCostCalculator(@Value("${app.power.collection-frequency-sec}") int collectionFrequencySeconds,
TariffRepository tariffRepository,
PowerCostRepository powerCostRepository) {
TariffDao tariffRepository,
PowerCostDao powerCostRepository) {
validateCollectionFrequency(collectionFrequencySeconds);

this.collectionFrequencySeconds = collectionFrequencySeconds;
Expand Down Expand Up @@ -89,15 +89,15 @@ private void calculateCostAndPersist(CurrentPower currentPower) {
LocalTime localTime = measurementZonedDateTime.toLocalTime();
// Get feed-in tariff
Tariff effectiveFeedInTariff = tariffRepository
.findEffectiveFeedInTariff(dayOfWeek, localTime, currentPower.getEpochTimestamp());
.getEffectiveFeedInTariff(dayOfWeek, localTime, currentPower.getEpochTimestamp());
if (effectiveFeedInTariff == null) {
logger.warn("No effective feed-in tariff found; unable to calculate power cost.");
return;
}
BigDecimal feedInTariffWattSecond = convertTariffToWattSeconds(effectiveFeedInTariff);
// Get usage tariff
Tariff effectiveUsageTariff = tariffRepository
.findEffectiveUsageTariff(dayOfWeek, localTime, currentPower.getEpochTimestamp());
.getEffectiveUsageTariff(dayOfWeek, localTime, currentPower.getEpochTimestamp());
if (effectiveUsageTariff == null) {
logger.warn("No effective usage tariff found; unable to calculate power cost.");
return;
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/keen/solar/financial/dal/PowerCostDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.keen.solar.financial.dal;

import org.keen.solar.financial.domain.PowerCost;

public interface PowerCostDao {

/**
* Persists the given PowerCost to the repository.
*/
void save(PowerCost powerCost);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.keen.solar.financial.dal;

import org.keen.solar.financial.domain.PowerCost;
import org.springframework.stereotype.Component;

@Component
public class PowerCostDaoSpringDataImpl implements PowerCostDao {

private final PowerCostRepository repository;

public PowerCostDaoSpringDataImpl(PowerCostRepository repository) {
this.repository = repository;
}


@Override
public void save(PowerCost powerCost) {
repository.save(powerCost);
}
}
31 changes: 31 additions & 0 deletions src/main/java/org/keen/solar/financial/dal/TariffDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.keen.solar.financial.dal;

import org.keen.solar.financial.domain.Tariff;

import java.time.DayOfWeek;
import java.time.LocalTime;

public interface TariffDao {

/**
* Retrieves the feed-in tariff for the given day and time, effective
* as at {@code epochTime}.
*
* @param dayOfWeek the day of the week to retrieve the tariff for
* @param localTime the time of day to retrieve the tariff for
* @param epochTime the epoch time that the tariff is effective for
* @return the feed-in tariff
*/
Tariff getEffectiveFeedInTariff(DayOfWeek dayOfWeek, LocalTime localTime, long epochTime);

/**
* Retrieves the usage tariff for the given day and time, effective
* as at {@code epochTime}.
*
* @param dayOfWeek the day of the week to retrieve the tariff for
* @param localTime the time of day to retrieve the tariff for
* @param epochTime the epoch time that the tariff is effective for
* @return the usage tariff
*/
Tariff getEffectiveUsageTariff(DayOfWeek dayOfWeek, LocalTime localTime, long epochTime);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.keen.solar.financial.dal;

import org.keen.solar.financial.domain.Tariff;
import org.springframework.stereotype.Component;

import java.time.DayOfWeek;
import java.time.LocalTime;

@Component
public class TariffDaoSpringDataImpl implements TariffDao {

private final TariffRepository repository;

public TariffDaoSpringDataImpl(TariffRepository repository) {
this.repository = repository;
}

@Override
public Tariff getEffectiveFeedInTariff(DayOfWeek dayOfWeek, LocalTime localTime, long epochTime) {
return repository.findEffectiveFeedInTariff(dayOfWeek, localTime, epochTime);
}

@Override
public Tariff getEffectiveUsageTariff(DayOfWeek dayOfWeek, LocalTime localTime, long epochTime) {
return repository.findEffectiveUsageTariff(dayOfWeek, localTime, epochTime);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.keen.solar.solcast.forecast;

import org.keen.solar.solcast.forecast.dal.ForecastRepository;
import org.keen.solar.solcast.forecast.dal.ForecastDao;
import org.keen.solar.solcast.forecast.domain.GenerationForecast;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
Expand All @@ -21,7 +21,7 @@ public class ForecastPersister {
private ForecastRetriever retriever;

@Autowired
private ForecastRepository repository;
private ForecastDao repository;

@Async
@Scheduled(cron = "${app.solcast.forecast-retrieval-cron}")
Expand All @@ -31,17 +31,7 @@ public void retrieveAndPersistAsync() {

public void retrieveAndPersist() {
List<GenerationForecast> forecasts = retriever.retrieve();
// Retrieve the id for any existing forecast for the same period so that it gets updated in the database,
// rather than inserted.
// Not particularly efficient, given that each forecast is retrieved individually from the database.
// Spring Data JDBC doesn't provide a mechanism to write queries that take collections as parameters.
forecasts.forEach(forecast -> {
GenerationForecast existingForecast = repository.findByPeriodEnd(forecast.getPeriod_end_epoch());
if (existingForecast != null) {
forecast.setId(existingForecast.getId());
}
});
repository.saveAll(forecasts);
repository.save(forecasts);
}

}
13 changes: 13 additions & 0 deletions src/main/java/org/keen/solar/solcast/forecast/dal/ForecastDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.keen.solar.solcast.forecast.dal;

import org.keen.solar.solcast.forecast.domain.GenerationForecast;

import java.util.Collection;

public interface ForecastDao {

/**
* Persists the given forecasts to the repository, updating them if they exist.
*/
void save(Collection<GenerationForecast> forecasts);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.keen.solar.solcast.forecast.dal;

import org.keen.solar.solcast.forecast.domain.GenerationForecast;
import org.springframework.stereotype.Component;

import java.util.Collection;

@Component
public class ForecastDaoSpringDataImpl implements ForecastDao {

private final ForecastRepository repository;

public ForecastDaoSpringDataImpl(ForecastRepository repository) {
this.repository = repository;
}

@Override
public void save(Collection<GenerationForecast> forecasts) {
// Retrieve the id for any existing forecast for the same period so that it gets updated in the database,
// rather than inserted.
// Not particularly efficient, given that each forecast is retrieved individually from the database.
// Spring Data JDBC doesn't provide a mechanism to write queries that take collections as parameters.
forecasts.forEach(forecast -> {
GenerationForecast existingForecast = repository.findByPeriodEnd(forecast.getPeriod_end_epoch());
if (existingForecast != null) {
forecast.setId(existingForecast.getId());
}
});
repository.saveAll(forecasts);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.keen.solar.solcast.measurement;

import org.keen.solar.system.dal.CurrentPowerRepository;
import org.keen.solar.system.dal.CurrentPowerDao;
import org.keen.solar.system.domain.CurrentPower;
import org.keen.solar.solcast.measurement.domain.Measurement;
import org.keen.solar.solcast.measurement.domain.MeasurementResponse;
Expand Down Expand Up @@ -28,7 +28,7 @@ public class MeasurementUploader {
private final Logger logger = LoggerFactory.getLogger(MeasurementUploader.class);

private final RestTemplate restTemplate;
private final CurrentPowerRepository repository;
private final CurrentPowerDao repository;

@Value("${app.solcast.base-url}")
private String solcastApiBaseUrl;
Expand All @@ -39,7 +39,7 @@ public class MeasurementUploader {
@Value("${app.solcast.api-key}")
private String solcastApiKey;

public MeasurementUploader(RestTemplateBuilder restTemplateBuilder, CurrentPowerRepository repository) {
public MeasurementUploader(RestTemplateBuilder restTemplateBuilder, CurrentPowerDao repository) {
this.restTemplate = restTemplateBuilder.build();
this.repository = repository;
}
Expand All @@ -48,7 +48,7 @@ public MeasurementUploader(RestTemplateBuilder restTemplateBuilder, CurrentPower
* Uploads all measurements not yet uploaded to Solcast
*/
public void uploadAll() {
List<CurrentPower> currentPowerNotUploaded = repository.findByUploaded(false);
List<CurrentPower> currentPowerNotUploaded = repository.getNotUploaded();
doUpload(currentPowerNotUploaded);
}

Expand Down Expand Up @@ -103,7 +103,7 @@ private void updateRepository(List<Measurement> measurementsToUpload, List<Measu
logger.debug("Updating repository");
measurementsUploaded.forEach(measurement -> {
measurement.getSource().parallelStream().forEach(currentPower -> currentPower.setUploaded(true));
repository.saveAll(measurement.getSource());
repository.save(measurement.getSource());
});
// Log which measurements were in error
measurementsToUpload.removeAll(returnedMeasurements);
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/keen/solar/string/dal/StringPowerDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.keen.solar.string.dal;

import org.keen.solar.string.domain.StringPower;

public interface StringPowerDao {

/**
* Persists the given StringPower to the repository.
*/
void save(StringPower stringPower);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.keen.solar.string.dal;

import org.keen.solar.string.domain.StringPower;
import org.springframework.stereotype.Component;

@Component
public class StringPowerDaoSpringDataImpl implements StringPowerDao {

private final StringPowerRepository repository;

public StringPowerDaoSpringDataImpl(StringPowerRepository repository) {
this.repository = repository;
}

@Override
public void save(StringPower stringPower) {
repository.save(stringPower);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.keen.solar.string.fronius;

import org.keen.solar.string.dal.StringPowerRepository;
import org.keen.solar.string.dal.StringPowerDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
Expand All @@ -11,7 +11,7 @@ public class StringPowerPersister {
private StringPowerRetriever retriever;

@Autowired
private StringPowerRepository repository;
private StringPowerDao repository;

@Async
@Scheduled(cron = "15 0/5 * * * *")
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/org/keen/solar/system/dal/CurrentPowerDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.keen.solar.system.dal;

import org.keen.solar.system.domain.CurrentPower;

import java.util.Collection;
import java.util.List;

public interface CurrentPowerDao {

/**
* Returns all CurrentPowers not yet uploaded to Solcast.
*/
List<CurrentPower> getNotUploaded();

/**
* Persists the given CurrentPower to the repository.
*/
void save(CurrentPower currentPower);

/**
* Persists the given CurrentPowers to the repository.
*/
void save(Collection<CurrentPower> currentPowers);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.keen.solar.system.dal;

import org.keen.solar.system.domain.CurrentPower;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;

@Component
public class CurrentPowerDaoSpringDataImpl implements CurrentPowerDao {

private final CurrentPowerRepository repository;

public CurrentPowerDaoSpringDataImpl(CurrentPowerRepository repository) {
this.repository = repository;
}

@Override
public List<CurrentPower> getNotUploaded() {
return repository.findByUploaded(false);
}

@Override
public void save(CurrentPower currentPower) {
repository.save(currentPower);
}

@Override
public void save(Collection<CurrentPower> currentPowers) {
repository.saveAll(currentPowers);
}
}
Loading

0 comments on commit 71dca07

Please sign in to comment.