Zwischenstand
This commit is contained in:
parent
b80eff98ad
commit
c4b8ea7106
@ -2,6 +2,8 @@ package info.peper.vz.rest;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import info.peper.vz.rest.bo.db.Aggregate;
|
||||
|
||||
interface AggregateRepository extends JpaRepository<Aggregate, Aggregate.CompositeKey> {
|
||||
|
||||
}
|
||||
|
||||
9
src/main/java/info/peper/vz/rest/DataRepository.java
Normal file
9
src/main/java/info/peper/vz/rest/DataRepository.java
Normal file
@ -0,0 +1,9 @@
|
||||
package info.peper.vz.rest;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import info.peper.vz.rest.bo.db.Data;
|
||||
|
||||
interface DataRepository extends JpaRepository<Data, Data.CompositeKey> {
|
||||
|
||||
}
|
||||
104
src/main/java/info/peper/vz/rest/FillAggregateTableMain.java
Normal file
104
src/main/java/info/peper/vz/rest/FillAggregateTableMain.java
Normal file
@ -0,0 +1,104 @@
|
||||
package info.peper.vz.rest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
public class FillAggregateTableMain {
|
||||
|
||||
private static final DateTimeFormatter DTF = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault());
|
||||
private static final int[] CHANNELS_TO_USE = new int[] {1, 4, };
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (final Connection con = DriverManager.getConnection(
|
||||
"jdbc:mariadb://mariadb.fritz.box/volkszaehler",
|
||||
"vz",
|
||||
getPassword())) {
|
||||
long startTimeStamp = getTimestamp("2022-06-01T00:00:00");
|
||||
long endTimeStamp = startTimeStamp + (24*60*60*1000);
|
||||
final long finalEndTimeStamp = getTimestamp("2025-02-24T00:00:00");
|
||||
while (endTimeStamp < finalEndTimeStamp) {
|
||||
for (int channelId : CHANNELS_TO_USE) {
|
||||
final long[] values = getValues(con, startTimeStamp, endTimeStamp, channelId);
|
||||
saveValues(con, startTimeStamp, endTimeStamp, channelId, values);
|
||||
System.out.println(DTF.format(Instant.ofEpochMilli(startTimeStamp)) + ": " + channelId);
|
||||
}
|
||||
startTimeStamp += 24*60*60*1000;
|
||||
endTimeStamp += 24*60*60*1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPassword() throws IOException {
|
||||
try (final InputStream is = new FileInputStream("db-password.txt")) {
|
||||
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
|
||||
return bufferedReader.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
private static long getTimestamp(final String dateTime) {
|
||||
final TemporalAccessor tempAccessor = DTF.parse(dateTime);
|
||||
final Instant instant = Instant.from(tempAccessor);
|
||||
return Instant.EPOCH.until(instant, ChronoUnit.MILLIS);
|
||||
}
|
||||
|
||||
private static void saveValues(final Connection con,
|
||||
final long startTimestamp,
|
||||
final long endTimestamp,
|
||||
final int channelId,
|
||||
final long[] values) throws SQLException {
|
||||
try (final PreparedStatement stmt = con.prepareStatement("INSERT INTO tobias_aggregate (channel_id, timestamp_start, timestamp_end, sum_positive, sum_negative) VALUES (?, ?, ?, ?, ?)")) {
|
||||
stmt.setInt(1, channelId);
|
||||
stmt.setLong(2, startTimestamp);
|
||||
stmt.setLong(3, endTimestamp);
|
||||
stmt.setLong(4, values[0]);
|
||||
stmt.setLong(5, values[1]);
|
||||
stmt.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private static long[] getValues(final Connection con,
|
||||
final long startTimestamp,
|
||||
final long endTimestamp,
|
||||
final int channelId) throws SQLException {
|
||||
long currentTimestamp = startTimestamp;
|
||||
long wattMillisecondsPos = 0;
|
||||
long wattMillisecondsNeg = 0;
|
||||
|
||||
while (currentTimestamp < endTimestamp) {
|
||||
try (final PreparedStatement stmt = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;")) {
|
||||
stmt.setMaxRows(10000);
|
||||
stmt.setInt(1, channelId);
|
||||
stmt.setLong(2, currentTimestamp);
|
||||
try (final ResultSet rs = stmt.executeQuery()) {
|
||||
while (rs.next() && currentTimestamp <= endTimestamp) {
|
||||
final long rsTimestamp = rs.getLong("timestamp");
|
||||
final long rsValue = rs.getLong("value");
|
||||
final long tsDiff = rsTimestamp - Math.min(endTimestamp, currentTimestamp);
|
||||
currentTimestamp = rsTimestamp;
|
||||
if (rsValue > 0) {
|
||||
wattMillisecondsPos += (rsValue * tsDiff);
|
||||
} else if (rsValue < 0) {
|
||||
wattMillisecondsNeg += (-rsValue * tsDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new long[] {wattMillisecondsPos/3600, wattMillisecondsNeg/3600};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -44,29 +44,29 @@ class LoadDatabase {
|
||||
|
||||
return args -> {
|
||||
LOG.info("################ jdbcTemplate: " + jdbcTemplate.getClass().getName());
|
||||
final long startTimestamp = getTimestamp("2022-06-01T00:00:00");
|
||||
final long endTimestamp = getTimestamp("2022-06-02T00:00:00");
|
||||
final List<Data> data = jdbcTemplate.query(
|
||||
"SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? AND timestamp<=? ORDER BY timestamp;",
|
||||
(rs, rowNum) -> new Data(rs.getInt("channel_id"), rs.getLong("timestamp"), rs.getInt("value")),
|
||||
1 ,startTimestamp, endTimestamp);
|
||||
|
||||
LOG.info("########## Count: " + data.size());
|
||||
long currentTimestamp = startTimestamp;
|
||||
long wattMillisecondsPos = 0;
|
||||
long wattMillisecondsNeg = 0;
|
||||
for (Data d : data) {
|
||||
final long rsTimestamp = d.timestamp;
|
||||
final long rsValue = d.value;
|
||||
final long tsDiff = rsTimestamp - Math.min(endTimestamp, currentTimestamp);
|
||||
currentTimestamp = rsTimestamp;
|
||||
if (rsValue > 0) {
|
||||
wattMillisecondsPos += (rsValue * tsDiff);
|
||||
} else if (rsValue < 0) {
|
||||
wattMillisecondsNeg += (-rsValue * tsDiff);
|
||||
}
|
||||
}
|
||||
repository.save(new Aggregate(1, startTimestamp, endTimestamp, wattMillisecondsPos, wattMillisecondsNeg));
|
||||
// final long startTimestamp = getTimestamp("2022-06-01T00:00:00");
|
||||
// final long endTimestamp = getTimestamp("2022-06-02T00:00:00");
|
||||
// final List<Data> data = jdbcTemplate.query(
|
||||
// "SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? AND timestamp<=? ORDER BY timestamp;",
|
||||
// (rs, rowNum) -> new Data(rs.getInt("channel_id"), rs.getLong("timestamp"), rs.getInt("value")),
|
||||
// 1 ,startTimestamp, endTimestamp);
|
||||
//
|
||||
// LOG.info("########## Count: " + data.size());
|
||||
// long currentTimestamp = startTimestamp;
|
||||
// long wattMillisecondsPos = 0;
|
||||
// long wattMillisecondsNeg = 0;
|
||||
// for (Data d : data) {
|
||||
// final long rsTimestamp = d.timestamp;
|
||||
// final long rsValue = d.value;
|
||||
// final long tsDiff = rsTimestamp - Math.min(endTimestamp, currentTimestamp);
|
||||
// currentTimestamp = rsTimestamp;
|
||||
// if (rsValue > 0) {
|
||||
// wattMillisecondsPos += (rsValue * tsDiff);
|
||||
// } else if (rsValue < 0) {
|
||||
// wattMillisecondsNeg += (-rsValue * tsDiff);
|
||||
// }
|
||||
// }
|
||||
// repository.save(new Aggregate(1, startTimestamp, endTimestamp, wattMillisecondsPos, wattMillisecondsNeg));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@ -22,6 +23,24 @@ public class ReadDbMain {
|
||||
private static final int[] CHANNELS_TO_USE = new int[] {1, 4, };
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (final Connection con = DriverManager.getConnection(
|
||||
"jdbc:mariadb://mariadb.fritz.box/volkszaehler",
|
||||
"vz",
|
||||
getPassword());
|
||||
final Statement stmt = con.createStatement();) {
|
||||
stmt.setFetchSize(10);
|
||||
stmt.setMaxRows(24*60*60);
|
||||
try (final ResultSet rs = stmt.executeQuery("SELECT * FROM data WHERE channel_id=1 AND timestamp>1656021600000");) {
|
||||
for (int i = 0; i < 50000; i++) {
|
||||
if (rs.next()) {
|
||||
rs.getDouble("value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void oldMain(String[] args) throws Exception {
|
||||
try (final Connection con = DriverManager.getConnection(
|
||||
"jdbc:mariadb://mariadb.fritz.box/volkszaehler",
|
||||
"vz",
|
||||
@ -35,18 +54,6 @@ public class ReadDbMain {
|
||||
saveValues(con, startTimeStamp, endTimeStamp, channelId, values);
|
||||
System.out.println(DTF.format(Instant.ofEpochMilli(startTimeStamp)) + ": " + channelId);
|
||||
}
|
||||
// final long[] zaehler = getValues(con, startTimeStamp, endTimeStamp, 1);
|
||||
// final long[] solar = getValues(con, startTimeStamp, endTimeStamp, 4);
|
||||
// System.out.println(DTF.format(Instant.ofEpochMilli(startTimeStamp)) +
|
||||
// "\t" +
|
||||
// DTF.format(Instant.ofEpochMilli(endTimeStamp)) +
|
||||
// "\t" +
|
||||
// zaehler[0] +
|
||||
// "\t" +
|
||||
// zaehler[1] +
|
||||
// "\t" +
|
||||
// solar[0]
|
||||
// );
|
||||
startTimeStamp += 24*60*60*1000;
|
||||
endTimeStamp += 24*60*60*1000;
|
||||
}
|
||||
@ -81,18 +88,19 @@ public class ReadDbMain {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static long[] getValues(final Connection con,
|
||||
final long startTimestamp,
|
||||
final long endTimestamp,
|
||||
final int channelId) throws SQLException {
|
||||
try (final PreparedStatement stmt = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? AND timestamp<=? ORDER BY timestamp;")) {
|
||||
long currentTimestamp = startTimestamp;
|
||||
long wattMillisecondsPos = 0;
|
||||
long wattMillisecondsNeg = 0;
|
||||
|
||||
while (currentTimestamp < endTimestamp) {
|
||||
try (final PreparedStatement stmt = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>?ORDER BY timestamp;")) {
|
||||
stmt.setMaxRows(10000);
|
||||
stmt.setInt(1, channelId);
|
||||
stmt.setLong(2, startTimestamp);
|
||||
stmt.setLong(3, endTimestamp + 24*60*60*1000);
|
||||
stmt.setLong(2, currentTimestamp);
|
||||
try (final ResultSet rs = stmt.executeQuery()) {
|
||||
while (rs.next() && currentTimestamp <= endTimestamp) {
|
||||
final long rsTimestamp = rs.getLong("timestamp");
|
||||
@ -106,8 +114,9 @@ public class ReadDbMain {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new long[] {wattMillisecondsPos/3600, wattMillisecondsNeg/3600};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,49 @@
|
||||
package info.peper.vz.rest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import info.peper.vz.rest.bo.Sums;
|
||||
import info.peper.vz.rest.bo.db.Aggregate;
|
||||
|
||||
@RestController
|
||||
class VzRestController {
|
||||
|
||||
private final AggregateRepository repository;
|
||||
private final AggregateRepository aggregateRep;
|
||||
private final DataRepository dataRep;
|
||||
|
||||
public VzRestController(final AggregateRepository repository) {
|
||||
this.repository = repository;
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
public VzRestController(final AggregateRepository aggregateRep, final DataRepository dataRep) {
|
||||
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 * FROM volkszaehler.tobias_aggregate WHERE channel_id=? AND timestamp_start>=? AND timestamp_end<=? ORDER BY timestamp_start;",
|
||||
(rs, rowNum) -> new Aggregate(rs.getInt("channel_id"), rs.getLong("timestamp_start"), rs.getLong("timestamp_end"),
|
||||
rs.getLong("sum_positive"), rs.getLong("sum_negative")),
|
||||
channelId ,timestampStart, timestampEnd);
|
||||
long sumPos = 0;
|
||||
long sumNeg = 0;
|
||||
for (Aggregate ag : aggregates) {
|
||||
sumPos += ag.getSumPositive();
|
||||
sumNeg += ag.getSumNegative();
|
||||
}
|
||||
return new Sums(sumPos, sumNeg);
|
||||
}
|
||||
|
||||
@GetMapping("/test/{name}")
|
||||
@ -22,7 +53,7 @@ class VzRestController {
|
||||
|
||||
@PostMapping("/test")
|
||||
Aggregate newAggregate(@RequestBody final Aggregate aggregate) {
|
||||
return repository.save(aggregate);
|
||||
return aggregateRep.save(aggregate);
|
||||
}
|
||||
|
||||
|
||||
|
||||
45
src/main/java/info/peper/vz/rest/bo/Sums.java
Normal file
45
src/main/java/info/peper/vz/rest/bo/Sums.java
Normal file
@ -0,0 +1,45 @@
|
||||
package info.peper.vz.rest.bo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Sums implements Serializable {
|
||||
private static final long serialVersionUID = -1816023197422851264L;
|
||||
private final long sumPositive;
|
||||
private final long sumNegative;
|
||||
public Sums(long sumPositive, long sumNegative) {
|
||||
super();
|
||||
this.sumPositive = sumPositive;
|
||||
this.sumNegative = sumNegative;
|
||||
}
|
||||
public long getSumPositive() {
|
||||
return sumPositive;
|
||||
}
|
||||
public long getSumNegative() {
|
||||
return sumNegative;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
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) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Sums other = (Sums) obj;
|
||||
if (sumNegative != other.sumNegative)
|
||||
return false;
|
||||
if (sumPositive != other.sumPositive)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package info.peper.vz.rest;
|
||||
package info.peper.vz.rest.bo.db;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -7,10 +7,10 @@ import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
|
||||
@Entity(name = "tobias_aggregate_spring")
|
||||
@Entity(name = "tobias_aggregate")
|
||||
@IdClass(Aggregate.CompositeKey.class)
|
||||
class Aggregate {
|
||||
static class CompositeKey implements Serializable {
|
||||
public class Aggregate {
|
||||
public static class CompositeKey implements Serializable {
|
||||
private static final long serialVersionUID = 3097284483123288289L;
|
||||
private int channelId;
|
||||
private long timestampStart;
|
||||
@ -48,7 +48,7 @@ class Aggregate {
|
||||
super();
|
||||
}
|
||||
|
||||
Aggregate(int channelId, long timestampStart, long timestampEnd, long sumPositive, long sumNegative) {
|
||||
public Aggregate(int channelId, long timestampStart, long timestampEnd, long sumPositive, long sumNegative) {
|
||||
super();
|
||||
this.channelId = channelId;
|
||||
this.timestampStart = timestampStart;
|
||||
@ -69,4 +69,43 @@ class Aggregate {
|
||||
private long sumPositive;
|
||||
@Column(name="sum_negative")
|
||||
private long sumNegative;
|
||||
public int getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(int channelId) {
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
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 long getSumPositive() {
|
||||
return sumPositive;
|
||||
}
|
||||
|
||||
public void setSumPositive(long sumPositive) {
|
||||
this.sumPositive = sumPositive;
|
||||
}
|
||||
|
||||
public long getSumNegative() {
|
||||
return sumNegative;
|
||||
}
|
||||
|
||||
public void setSumNegative(long sumNegative) {
|
||||
this.sumNegative = sumNegative;
|
||||
}
|
||||
}
|
||||
52
src/main/java/info/peper/vz/rest/bo/db/Data.java
Normal file
52
src/main/java/info/peper/vz/rest/bo/db/Data.java
Normal file
@ -0,0 +1,52 @@
|
||||
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 = "data")
|
||||
@IdClass(Data.CompositeKey.class)
|
||||
public class Data {
|
||||
public static class CompositeKey implements Serializable {
|
||||
private static final long serialVersionUID = -3486278368164696822L;
|
||||
private int channelId;
|
||||
private long timestamp;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + channelId;
|
||||
result = prime * result + (int) (timestamp ^ (timestamp >>> 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 (channelId != other.channelId)
|
||||
return false;
|
||||
if (timestamp != other.timestamp)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column(name="channel_id")
|
||||
private int channelId;
|
||||
@Id
|
||||
@Column(name="timestamp")
|
||||
private long timestamp;
|
||||
@Column(name="value")
|
||||
private double value;
|
||||
|
||||
}
|
||||
5
src/main/resources/application.properties
Normal file
5
src/main/resources/application.properties
Normal file
@ -0,0 +1,5 @@
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.datasource.url=jdbc:mariadb://mariadb.fritz.box:3306/volkszaehler
|
||||
spring.datasource.username=vz
|
||||
spring.datasource.password=2pG7GjQajemwY3f9
|
||||
spring.jpa.show-sql: true
|
||||
Loading…
Reference in New Issue
Block a user