Skip to content

Commit

Permalink
NET-422: continue work on AlsoEnergy cloud integration.
Browse files Browse the repository at this point in the history
  • Loading branch information
msqr committed Nov 22, 2024
1 parent ac3c7fb commit 69898fa
Show file tree
Hide file tree
Showing 8 changed files with 896 additions and 27 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* ==================================================================
* AlsoEnergyFieldFunction.java - 22/11/2024 5:33:25 pm
*
* Copyright 2024 SolarNetwork.net Dev Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ==================================================================
*/

package net.solarnetwork.central.c2c.biz.impl;

/**
* Enumeration of AlsoEnergy field functions.
*
* @author matt
* @version 1.0
*/
public enum AlsoEnergyFieldFunction {
/** Average. */
Avg,

/** Last posted. */
Last,

/** Minimum. */
Min,

/** Maximum. */
Max,

/** Difference. */
Diff,

/** Sum. */
Sum,

/** Integral. */
Integral,

/** Difference, non zero. */
DiffNonZero,

/** Previous. */
Previous,

;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/* ==================================================================
* AlsoEnergyGranularity.java - 22/11/2024 2:19:11 pm
*
* Copyright 2024 SolarNetwork.net Dev Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ==================================================================
*/

package net.solarnetwork.central.c2c.biz.impl;

import java.time.Duration;
import java.time.Instant;
import java.time.Period;
import java.time.ZoneId;
import java.time.temporal.TemporalAmount;
import com.fasterxml.jackson.annotation.JsonCreator;

/**
* Enumeration of AlsoEnergy data granularity ("BinSize") values.
*
* @author matt
* @version 1.0
*/
public enum AlsoEnergyGranularity {

/** Raw data. */
Raw("Raw", null),

/** Five minutes. */
FiveMinute("5Min", Duration.ofMinutes(5)),

/** Fifteen minutes. */
FifteenMinute("15Min", Duration.ofMinutes(15)),

/** One hour. */
Hour("1Hour", Duration.ofHours(1)),

/** One day. */
Day("Day", Duration.ofDays(1)),

/** One month. */
Month("Month", Period.ofMonths(1)),

/** One year. */
Year("Year", Period.ofYears(1)),

;

private final String key;
private final String queryKey;
private final TemporalAmount tickAmount;

private AlsoEnergyGranularity(String key, TemporalAmount tickAmount) {
this.key = key;
this.queryKey = "Bin" + key;
this.tickAmount = tickAmount;
}

/**
* Get the key.
*
* @return the key, never {@code null}
*/
public String getKey() {
return key;
}

/**
* Get the query key.
*
* @return the query key, never {@code null}
*/
public String getQueryKey() {
return queryKey;
}

/**
* Get a clock tick duration appropriate for this granularity.
*
* @return the duration, or {@code null}
*/
public TemporalAmount getTickAmount() {
return tickAmount;
}

/**
* Get the start of a tick boundary that includes a given instant.
*
* @param ts
* the instant to get the tick boundary start for
* @param zone
* the time zone, for tick amounts greater than a day
* @return the start instant
*/
public Instant tickStart(Instant ts, ZoneId zone) {
if ( tickAmount == null ) {
return ts;
}
if ( tickAmount instanceof Duration d ) {
return CloudIntegrationsUtils.truncateDate(ts, d);
} else if ( tickAmount instanceof Period p ) {
return CloudIntegrationsUtils.truncateDate(ts, p, zone);
}
return ts;
}

/**
* Get the previous starting tick boundary.
*
* @param tickStart
* the starting tick boundary
* @param zone
* the time zone, for tick amounts greater than a day
* @return the starting tick boundary immediately before {@code tickStart}
*/
public Instant prevTickStart(Instant tickStart, ZoneId zone) {
return CloudIntegrationsUtils.prevTickStart(tickAmount, tickStart, zone);
}

/**
* Get the next starting tick boundary.
*
* @param tickStart
* the starting tick boundary
* @param zone
* the time zone, for tick amounts greater than a day
* @return the starting tick boundary immediately after {@code tickStart}
*/
public Instant nextTickStart(Instant tickStart, ZoneId zone) {
return CloudIntegrationsUtils.nextTickStart(tickAmount, tickStart, zone);
}

/**
* Get an enum instance for a name or key value.
*
* @param value
* the enumeration name or key value, case-insensitve
* @return the enum; if {@code value} is {@literal null} or empty then
* {@link #Latest} is returned
* @throws IllegalArgumentException
* if {@code value} is not a valid value
*/
@JsonCreator
public static AlsoEnergyGranularity fromValue(String value) {
if ( value == null || value.isEmpty() ) {
return Raw;
}
for ( AlsoEnergyGranularity e : AlsoEnergyGranularity.values() ) {
if ( value.equalsIgnoreCase(e.key) || value.equalsIgnoreCase(e.name()) ) {
return e;
}
}
throw new IllegalArgumentException("Unknown AlsoEnergyGranularity value [" + value + "]");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Clock;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalAmount;

/**
* Helper methods for cloud integrations.
Expand Down Expand Up @@ -60,4 +68,71 @@ public static Instant truncateDate(Instant date, Duration period) {
return Clock.tick(Clock.fixed(date, UTC), period).instant();
}

/**
* Truncate a date based on a period.
*
* @param date
* the date to truncate
* @param period
* the period to truncate to; only week, month, and year are
* supported
* @param zone
* the zone
* @return the truncated date
*/
public static Instant truncateDate(Instant date, Period period, ZoneId zone) {
TemporalAdjuster adj = period.getYears() > 0 ? TemporalAdjusters.firstDayOfYear()
: period.getMonths() > 0 ? TemporalAdjusters.firstDayOfMonth()
: TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY);
return date.atZone(zone).with(adj).toInstant().truncatedTo(ChronoUnit.DAYS);
}

/**
* Get the previous starting tick boundary.
*
* @param tick
* the tick amount; a valid time- or date-based unit is assumed; see
* {@link java.time.temporal.TemporalUnit#isTimeBased()} and
* {@link java.time.temporal.TemporalUnit#isDateBased()}
* @param tickStart
* a starting tick boundary instant
* @param zone
* the time zone, for ticks larger than 1 day
* @return the previous boundary start
*/
public static Instant prevTickStart(TemporalAmount tick, Instant tickStart, ZoneId zone) {
if ( tick == null ) {
return tickStart;
}
if ( tick.getUnits().get(0).isTimeBased() ) {
return tickStart.minus(tick);
}
ZonedDateTime zdt = tickStart.atZone(zone);
return zdt.minus(tick).toInstant();
}

/**
* Get the next starting tick boundary.
*
* @param tick
* the tick amount; a valid time- or date-based unit is assumed; see
* {@link java.time.temporal.TemporalUnit#isTimeBased()} and
* {@link java.time.temporal.TemporalUnit#isDateBased()}
* @param tickStart
* a starting tick boundary instant
* @param zone
* the time zone, for ticks larger than 1 day
* @return the next boundary start
*/
public static Instant nextTickStart(TemporalAmount tick, Instant tickStart, ZoneId zone) {
if ( tick == null ) {
return tickStart;
}
if ( tick.getUnits().get(0).isTimeBased() ) {
return tickStart.plus(tick);
}
ZonedDateTime zdt = tickStart.atZone(zone);
return zdt.plus(tick).toInstant();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.jdbc.core.JdbcOperations;
Expand Down Expand Up @@ -120,9 +119,6 @@ public class AlsoEnergyConfig {
@Autowired
private CloudIntegrationsExpressionService expressionService;

@Autowired
private AsyncTaskExecutor taskExecutor;

@Autowired(required = false)
private UserServiceAuditor userServiceAuditor;

Expand Down Expand Up @@ -176,7 +172,7 @@ public OAuth2AuthorizedClientManager alsoEnergyOauthAuthorizedClientManager(
@Qualifier(ALSO_ENERGY)
public CloudDatumStreamService alsoEnergyCloudDatumStreamService(
@Qualifier(ALSO_ENERGY) OAuth2AuthorizedClientManager oauthClientManager) {
var service = new AlsoEnergyCloudDatumStreamService(taskExecutor, userEventAppender, encryptor,
var service = new AlsoEnergyCloudDatumStreamService(userEventAppender, encryptor,
expressionService, integrationConfigurationDao, datumStreamConfigurationDao,
datumStreamMappingConfigurationDao, datumStreamPropertyConfigurationDao, restOps,
oauthClientManager);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.function.Function;
import org.slf4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
Expand Down Expand Up @@ -79,10 +80,10 @@ public OAuth2RestOperationsHelper(Logger log, UserEventAppenderBiz userEventAppe
}

@Override
public <R, C extends CloudIntegrationsConfigurationEntity<C, K>, K extends UserRelatedCompositeKey<K>, T> T httpGet(
String description, C configuration, Class<R> responseType, Function<HttpHeaders, URI> setup,
Function<ResponseEntity<R>, T> handler) {
return super.httpGet(description, configuration, responseType, (headers) -> {
public <B, R, C extends CloudIntegrationsConfigurationEntity<C, K>, K extends UserRelatedCompositeKey<K>, T> T http(
String description, HttpMethod method, B body, C configuration, Class<R> responseType,
Function<HttpHeaders, URI> setup, Function<ResponseEntity<R>, T> handler) {
return super.http(description, method, body, configuration, responseType, (headers) -> {
if ( configuration instanceof CloudIntegrationConfiguration integration ) {
final var decrypted = integration.copyWithId(integration.getId());
decrypted.unmaskSensitiveInformation(sensitiveKeyProvider, encryptor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,18 @@ title = AlsoEnergy Datum Stream

dataValueFilter.siteId.key = Site ID
dataValueFilter.siteId.desc = The site identifier to restrict the results to.

granularity.key = Granularity
granularity.desc = The resolution of the data to request.

granularity.raw.key = Raw
granularity.5min.key = 5 minute
granularity.15min.key = 15 minute
granularity.hourly.key = Hourly
granularity.daily.key = Daily
granularity.monthly.key = Monthly
granularity.yearly.key = Yearly

tz.key = Time Zone
tz.desc = The time zone of the source data, for example <code>Pacific/Auckland</code>. Only \
required if <b>Granularity</b> is <b>Monthly</b> or higher.
Loading

0 comments on commit 69898fa

Please sign in to comment.