Erster funktionierender Stand mit alter Aggregats-Tabelle

This commit is contained in:
tobias 2025-03-07 21:42:24 +01:00
parent 4787d0dd2d
commit 7381ddde07
5 changed files with 245 additions and 37 deletions

View File

@ -21,17 +21,17 @@ import java.util.List;
public class FillAggregateTableMain2 {
private static final DateTimeFormatter DTF = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault());
private static final int[] CHANNELS_TO_USE = new int[] {1, 4, };
private static final int[] CHANNELS_TO_USE = new int[] {1,/* 4,*/ };
private static final List<AggregateToSave> SAVELIST = new LinkedList<AggregateToSave>();
private static class AggregateToSave {
private final long startTs;
private final long endTs;
private final double valuePos;
private final double valueNeg;
private final long valuePos;
private final long valueNeg;
private final int channelId;
private AggregateToSave(long startTs, long endTs, double valuePos, double valueNeg, int channelId) {
private AggregateToSave(long startTs, long endTs, long valuePos, long valueNeg, int channelId) {
super();
this.startTs = startTs;
this.endTs = endTs;
@ -48,11 +48,11 @@ public class FillAggregateTableMain2 {
return endTs;
}
private double getValuePos() {
private long getValuePos() {
return valuePos;
}
private double getValueNeg() {
private long getValueNeg() {
return valueNeg;
}
@ -68,6 +68,7 @@ public class FillAggregateTableMain2 {
getPassword())) {
// long startTimeStamp = getTimestamp("2025-01-01T09:00:00");
final long startTimeStamp = getTimestamp("2022-05-20T09:00:00");
// final long finalEndTimeStamp = getTimestamp("2022-05-20T09:02:00");
final long finalEndTimeStamp = getTimestamp("2025-03-01T00:00:00");
for (int channelId : CHANNELS_TO_USE) {
processChannel(startTimeStamp, finalEndTimeStamp, 60*1000, channelId, con);
@ -117,10 +118,11 @@ public class FillAggregateTableMain2 {
sumDiff += tsDiff;
currentTimestamp = timestamp;
if (value > 0) {
intervalPos += (value * tsDiff);
intervalPos += Math.round(value * tsDiff);
} else if (value < 0) {
intervalNeg += (-value * tsDiff);
intervalNeg += Math.round(-value * tsDiff);
}
// System.out.println("ts: " + currentTimestamp + " / diff: " + tsDiff + " / value: " + value + " / intervalPos: " + intervalPos);
if (timestamp >= intervalEndTimestamp) {
if (sumDiff != interval) {
System.err.println("sumDiff: " + sumDiff + " / interval: " + interval);
@ -133,7 +135,7 @@ public class FillAggregateTableMain2 {
(intervalPos/3600) + " / " +
(intervalNeg/3600));
}
SAVELIST.add(new AggregateToSave(intervalStartTimestamp, intervalEndTimestamp, ((double)intervalPos)/3600, ((double)intervalNeg)/3600, channelId));
SAVELIST.add(new AggregateToSave(intervalStartTimestamp, intervalEndTimestamp, Math.round(intervalPos), Math.round(intervalNeg), channelId));
intervalStartTimestamp += interval;
intervalEndTimestamp += interval;
currentTimestamp = intervalStartTimestamp;

View File

@ -1,6 +1,11 @@
package info.peper.vz.rest;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -16,6 +21,7 @@ import org.springframework.web.bind.annotation.RestController;
import info.peper.vz.rest.bo.Sums;
import info.peper.vz.rest.bo.db.Aggregate;
import info.peper.vz.rest.bo.db.Data;
import info.peper.vz.rest.bo.db.EnergyPrice;
@RestController
class VzRestController {
@ -23,22 +29,60 @@ class VzRestController {
private static final Logger log = LoggerFactory.getLogger(VzRestController.class);
private final AggregateRepository aggregateRep;
private final DataRepository dataRep;
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private JdbcTemplate jdbcTemplateWithLimitedRows;
public VzRestController(final AggregateRepository aggregateRep, final DataRepository dataRep) {
public VzRestController(final AggregateRepository aggregateRep) {
this.aggregateRep = aggregateRep;
this.dataRep = dataRep;
}
@GetMapping("/data/sums")
Sums getData(@RequestParam("timestampStart")final long timestampStart,
@RequestParam("timestampEnd")final long timestampEnd,
@RequestParam("channelId")final int channelId) {
final List<Aggregate> aggregates = jdbcTemplate.query(
"SELECT MIN(timestamp_start) AS min_timestamp_start, MAX(timestamp_end) AS max_timestamp_end, SUM(sum_positive) AS sum_positive, SUM(sum_negative) AS sum_negative FROM volkszaehler.tobias_aggregate WHERE channel_id=? AND timestamp_start>=? AND timestamp_end<=?;",
(rs, rowNum) -> new Aggregate(channelId, rs.getLong("min_timestamp_start"), rs.getLong("max_timestamp_end"),
rs.getLong("sum_positive"), rs.getLong("sum_negative")),
channelId ,timestampStart, timestampEnd);
if (aggregates.size() != 1) {
throw new RuntimeException("Interal error in SQL query.");
}
final Aggregate aggregate = aggregates.iterator().next();
double sumPos = aggregate.getSumPositive();
double sumNeg = aggregate.getSumNegative();
log.debug("sumPos: " + sumPos + " / sumNeg: " + sumNeg);
log.debug("timestampStart: " + timestampStart);
log.debug("timestampEnd: " + timestampEnd);
log.debug("firstTimestamp: " + aggregate.getTimestampStart());
log.debug("lastTimestamp: " + aggregate.getTimestampEnd());
if (timestampStart < aggregate.getTimestampStart() ) {
final Sums startSums = getSums(timestampStart, aggregate.getTimestampStart(), channelId);
sumPos += startSums.getSumPositive();
sumNeg += startSums.getSumNegative();
log.debug("Start: " + startSums.toString());
}
if (timestampEnd > aggregate.getTimestampEnd()) {
final Sums endSums = getSums(aggregate.getTimestampEnd(), timestampEnd, channelId);
sumPos += endSums.getSumPositive();
sumNeg += endSums.getSumNegative();
log.debug("End: " + endSums.toString());
}
sumPos /= 3600;
sumNeg /= 3600;
return new Sums(Math.round(sumPos), Math.round(sumNeg));
}
@GetMapping("/data/sumsWithFactor")
Sums getDataWithFactor(@RequestParam("timestampStart")final long timestampStart,
@RequestParam("timestampEnd")final long timestampEnd,
@RequestParam("channelId")final int channelId) {
// this.jdbcTemplateWithLimitedRows.setMaxRows(1000);
final List<Aggregate> aggregates = jdbcTemplate.query(
"SELECT * FROM volkszaehler.tobias_aggregate WHERE channel_id=? AND timestamp_start>=? AND timestamp_end<=? ORDER BY timestamp_start;",
@ -49,7 +93,7 @@ class VzRestController {
long lastTimestamp = Long.MIN_VALUE;
double sumPos = 0;
double sumNeg = 0;
log.info("Number of aggregates: " + aggregates.size());
log.debug("Number of aggregates: " + aggregates.size());
for (Aggregate ag : aggregates) {
if (ag.getTimestampStart() < firstTimestamp) {
firstTimestamp = ag.getTimestampStart();
@ -60,38 +104,92 @@ class VzRestController {
sumPos += ag.getSumPositive();
sumNeg += ag.getSumNegative();
}
sumPos /= 3600;
sumNeg /= 3600;
log.info("sumPos: " + sumPos + " / sumNeg: " + sumNeg);
log.info("timestampStart: " + timestampStart);
log.info("timestampEnd: " + timestampEnd);
log.info("firstTimestamp: " + firstTimestamp);
log.info("lastTimestamp: " + lastTimestamp);
log.debug("sumPos: " + sumPos + " / sumNeg: " + sumNeg);
log.debug("timestampStart: " + timestampStart);
log.debug("timestampEnd: " + timestampEnd);
log.debug("firstTimestamp: " + firstTimestamp);
log.debug("lastTimestamp: " + lastTimestamp);
if (timestampStart < firstTimestamp ) {
final Sums startSums = getSums(timestampStart, firstTimestamp, channelId);
sumPos += startSums.getSumPositive();
sumNeg += startSums.getSumNegative();
log.info("Start: " + startSums.toString());
log.debug("Start: " + startSums.toString());
}
if (timestampEnd > lastTimestamp) {
final Sums endSums = getSums(lastTimestamp, timestampEnd, channelId);
sumPos += endSums.getSumPositive();
sumNeg += endSums.getSumNegative();
log.info("End: " + endSums.toString());
log.debug("End: " + endSums.toString());
}
return new Sums(sumPos, sumNeg);
sumPos /= 3600;
sumNeg /= 3600;
return new Sums(Math.round(sumPos), Math.round(sumNeg));
}
@GetMapping("/data/sums2")
Sums getData2(@RequestParam("timestampStart")final long timestampStart,
@RequestParam("timestampEnd")final long timestampEnd,
@RequestParam("channelId")final int channelId) {
final Sums startSums = getSums(timestampStart, timestampEnd, channelId);
return startSums;
final Sums returnSums = new Sums(Math.round((double)startSums.getSumPositive()/3600), Math.round((double)startSums.getSumNegative()/3600));
return returnSums;
}
@GetMapping("/data/prices")
List<EnergyPrice> getPrices(@RequestParam("timestampStart")final long timestampStart,
@RequestParam("timestampEnd")final long timestampEnd,
@RequestParam("contractId")final int contractId) {
final List<EnergyPrice> prices = jdbcTemplate.query(
"SELECT * FROM tobias_energy_price WHERE contract_id=? AND timestamp_start < ? AND timestamp_end >= ? ORDER BY timestamp_start;",
(rs, rowNum) -> new EnergyPrice(rs.getInt("contract_id"), rs.getLong("timestamp_start"), rs.getLong("timestamp_end"),
rs.getFloat("price")),
contractId ,timestampEnd, timestampStart);
return prices;
}
@GetMapping("/data/summary")
String getSummary(@RequestParam("timestampStart")final long timestampStart,
@RequestParam("timestampEnd")final long timestampEnd,
@RequestParam("contractId")final int contractId,
@RequestParam("channelIdMeter")final int channelIdMeter,
@RequestParam("channelIdSolar")final int channelIdSolar) {
final NumberFormat formatCurrency = new DecimalFormat("#,##0.00", new DecimalFormatSymbols(Locale.GERMAN));
final NumberFormat formatPercent = new DecimalFormat("#,##0.00", new DecimalFormatSymbols(Locale.GERMAN));
final NumberFormat formatEnergy = new DecimalFormat("#,##0", new DecimalFormatSymbols(Locale.GERMAN));
final List<EnergyPrice> prices = this.getPrices(timestampStart, timestampEnd, contractId);
final List<Sums> partsMeter = new LinkedList<Sums>();
final List<Sums> partsSolar = new LinkedList<Sums>();
float savedMoney = 0;
long totalSolar = 0;
long totalObtained = 0;
long totalInjected = 0;
for (EnergyPrice price : prices) {
final long tsStart = Math.max(price.getTimestampStart(), timestampStart);
final long tsEnd = Math.min(price.getTimestampEnd(), timestampEnd);
final Sums sumsMeter = getData(tsStart, tsEnd, channelIdMeter);
final Sums sumsSolar = getData(tsStart, tsEnd, channelIdSolar);
savedMoney += (float)(sumsSolar.getSumPositive() - sumsMeter.getSumNegative())/1000000 * price.getPrice();
totalSolar += sumsSolar.getSumPositive();
totalObtained += sumsMeter.getSumPositive();
totalInjected += sumsMeter.getSumNegative();
partsMeter.add(sumsMeter);
partsSolar.add(sumsSolar);
}
final StringBuilder sb = new StringBuilder();
sb.append("Erzeugter Strom von der Photovoltaik: " + formatEnergy.format(totalSolar/1000000) + " kWh\n");
sb.append("Eingespeister Strom von der Photovoltaik: " + formatEnergy.format(totalInjected/1000000) + " kWh\n");
sb.append("Genutzter Strom von der Photovoltaik: " + formatEnergy.format((totalSolar-totalInjected)/1000000) + " kWh (=");
sb.append(formatPercent.format((float)(totalSolar-totalInjected)/(float)totalSolar*100) + " %)\n");
sb.append("Bezogener Strom: " + formatEnergy.format(totalObtained/1000000) + " kWh\n");
sb.append("Autakie: " + formatPercent.format((float)(totalSolar-totalInjected)/(float)(totalObtained+totalSolar-totalInjected)*100) + " %\n");
sb.append("Eingespartes Geld: " + formatCurrency.format(savedMoney) + "\n");
return sb.toString();
}
@GetMapping("/test/{name}")
String hello(@PathVariable("name")final String name) {
return "Hello " + name + "!";
@ -127,7 +225,7 @@ class VzRestController {
}
}
}
return new Sums(wattMillisecondsPos/3600, wattMillisecondsNeg/3600);
return new Sums(Math.round(wattMillisecondsPos), Math.round(wattMillisecondsNeg));
}

View File

@ -5,22 +5,30 @@ import java.util.Objects;
public class Sums implements Serializable {
private static final long serialVersionUID = -1816023197422851264L;
private final double sumPositive;
private final double sumNegative;
public Sums(double sumPositive, double sumNegative) {
private final long sumPositive;
private final long sumNegative;
public Sums(long sumPositive, long sumNegative) {
super();
this.sumPositive = sumPositive;
this.sumNegative = sumNegative;
}
public double getSumPositive() {
public long getSumPositive() {
return sumPositive;
}
public double getSumNegative() {
public long getSumNegative() {
return sumNegative;
}
@Override
public String toString() {
return "Sums [sumPositive=" + sumPositive + ", sumNegative=" + sumNegative + "]";
}
@Override
public int hashCode() {
return Objects.hash(sumNegative, sumPositive);
final int prime = 31;
int result = 1;
result = prime * result + (int) (sumNegative ^ (sumNegative >>> 32));
result = prime * result + (int) (sumPositive ^ (sumPositive >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
@ -31,12 +39,11 @@ public class Sums implements Serializable {
if (getClass() != obj.getClass())
return false;
Sums other = (Sums) obj;
return Double.doubleToLongBits(sumNegative) == Double.doubleToLongBits(other.sumNegative)
&& Double.doubleToLongBits(sumPositive) == Double.doubleToLongBits(other.sumPositive);
}
@Override
public String toString() {
return "Sums [sumPositive=" + sumPositive + ", sumNegative=" + sumNegative + "]";
if (sumNegative != other.sumNegative)
return false;
if (sumPositive != other.sumPositive)
return false;
return true;
}

View File

@ -0,0 +1,101 @@
package info.peper.vz.rest.bo.db;
import java.io.Serializable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
@Entity(name = "tobias_energy_price")
@IdClass(EnergyPrice.CompositeKey.class)
public class EnergyPrice {
public static class CompositeKey implements Serializable {
private static final long serialVersionUID = 3097284483123288289L;
private int contractId;
private long timestampStart;
private long timestampEnd;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + contractId;
result = prime * result + (int) (timestampEnd ^ (timestampEnd >>> 32));
result = prime * result + (int) (timestampStart ^ (timestampStart >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CompositeKey other = (CompositeKey) obj;
if (contractId != other.contractId)
return false;
if (timestampEnd != other.timestampEnd)
return false;
if (timestampStart != other.timestampStart)
return false;
return true;
}
}
EnergyPrice() {
super();
}
public EnergyPrice(int contractId, long timestampStart, long timestampEnd, float price) {
super();
this.contractId = contractId;
this.timestampStart = timestampStart;
this.timestampEnd = timestampEnd;
this.price = price;
}
@Id
@Column(name="contract_id")
private int contractId;
@Id
@Column(name="timestamp_start")
private long timestampStart;
@Id
@Column(name="timestamp_end")
private long timestampEnd;
@Column(name="price")
private float price;
public int getContractId() {
return contractId;
}
public void setContractId(int contractId) {
this.contractId = contractId;
}
public long getTimestampStart() {
return timestampStart;
}
public void setTimestampStart(long timestampStart) {
this.timestampStart = timestampStart;
}
public long getTimestampEnd() {
return timestampEnd;
}
public void setTimestampEnd(long timestampEnd) {
this.timestampEnd = timestampEnd;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}

Binary file not shown.