diff --git a/src/main/java/info/peper/vz/rest/FillAggregateTableMain3.java b/src/main/java/info/peper/vz/rest/FillAggregateTableMain3.java index f40fe6d..ba21ea4 100644 --- a/src/main/java/info/peper/vz/rest/FillAggregateTableMain3.java +++ b/src/main/java/info/peper/vz/rest/FillAggregateTableMain3.java @@ -29,15 +29,27 @@ public class FillAggregateTableMain3 { "jdbc:mariadb://mariadb.fritz.box/volkszaehler", "vz", getPassword())) { - 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"); - - final List aggregates = processHouse(1, startTimeStamp, finalEndTimeStamp, 60*1000, 4, 1, con); - saveValues(con, aggregates, 1); + processKerpen(con); + processRoki(con); } } + private static void processKerpen(final Connection con) throws SQLException { + final long startTimeStamp = getTimestamp("2022-05-20T09:00:00"); + final long finalEndTimeStamp = getTimestamp("2025-03-09T15:00:00"); + + final List aggregates = processHouse(1, startTimeStamp, finalEndTimeStamp, 60*1000, 4, 1, con); + saveValues(con, aggregates, 1); + } + + private static void processRoki(final Connection con) throws SQLException { + final long startTimeStamp = getTimestamp("2024-06-23T17:00:00"); + final long finalEndTimeStamp = getTimestamp("2025-03-09T15:00:00"); + + final List aggregates = processHouseMulti(2, startTimeStamp, finalEndTimeStamp, 60*1000, new int[] {24}, new int[] {18, 19, 20}, con); + saveValues(con, aggregates, 2); + } + private static List processHouse(final int houseId, final long startTimestamp, final long endTimestamp, @@ -72,6 +84,9 @@ public class FillAggregateTableMain3 { while (currentTsSolar <= endTimestamp || currentTsMeter <= endTimestamp) { + currentTsSolar = intervalStartTimestamp; + currentTsMeter = intervalStartTimestamp; + System.out.print(intervalStartTimestamp + ": "); while (currentTsSolar < intervalEndTimestamp && (noNextRecordSolar || rsSolar.next())) { @@ -131,6 +146,144 @@ public class FillAggregateTableMain3 { return result; } + private static List processHouseMulti(final int houseId, + final long startTimestamp, + final long endTimestamp, + final long interval, + final int[] channelIdsSolar, + final int[] channelIdsMeter, + final Connection con) throws SQLException { + final List result = new LinkedList(); + + final PreparedStatement[] stmtSolar = new PreparedStatement[channelIdsSolar.length]; + final PreparedStatement[] stmtMeter = new PreparedStatement[channelIdsMeter.length]; + final ResultSet[] rsSolar = new ResultSet[channelIdsSolar.length]; + final ResultSet[] rsMeter = new ResultSet[channelIdsMeter.length]; + long[] currentTsSolar = new long[channelIdsSolar.length]; + long[] currentTsMeter = new long[channelIdsMeter.length]; + boolean[] noNextRecordSolar = new boolean[channelIdsSolar.length]; + boolean[] noNextRecordMeter = new boolean[channelIdsMeter.length]; + + for (int i = 0; i < channelIdsSolar.length; i++) { + stmtSolar[i] = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;"); + stmtSolar[i].setInt(1, channelIdsSolar[i]); + stmtSolar[i].setLong(2, startTimestamp); + stmtSolar[i].setFetchSize(1000); + rsSolar[i] = stmtSolar[i].executeQuery(); + currentTsSolar[i] = startTimestamp; + noNextRecordSolar[i] = false; + } + + for (int i = 0; i < channelIdsMeter.length; i++) { + stmtMeter[i] = con.prepareStatement("SELECT * FROM volkszaehler.data WHERE channel_id=? AND timestamp>? ORDER BY timestamp;"); + stmtMeter[i].setInt(1, channelIdsMeter[i]); + stmtMeter[i].setLong(2, startTimestamp); + stmtMeter[i].setFetchSize(1000); + rsMeter[i] = stmtMeter[i].executeQuery(); + currentTsMeter[i] = startTimestamp; + noNextRecordMeter[i] = false; + } + + System.out.println("Starting..."); + long intervalProduced = 0; + long intervalObtained = 0; + long intervalInjected = 0; + + long intervalStartTimestamp = startTimestamp; + long intervalEndTimestamp = startTimestamp + interval; + + // Eigentliche Verarbeitung + + while (getMinOfArray(currentTsSolar) <= endTimestamp || getMinOfArray(currentTsMeter) <= endTimestamp) { + System.out.print(intervalStartTimestamp + ": "); + + for (int iSolar = 0; iSolar < channelIdsSolar.length; iSolar++) { + currentTsSolar[iSolar] = intervalStartTimestamp; + + while (currentTsSolar[iSolar] < intervalEndTimestamp && (noNextRecordSolar[iSolar] || rsSolar[iSolar].next())) { + if (noNextRecordSolar[iSolar]) { + noNextRecordSolar[iSolar] = false; + } + + final long tsSolar = rsSolar[iSolar].getLong("timestamp"); + final double value = rsSolar[iSolar].getDouble("value") > 1.0 ? rsSolar[iSolar].getDouble("value") : 0.0; + final long tsDiff = (tsSolar < intervalEndTimestamp) ? tsSolar - currentTsSolar[iSolar] : intervalEndTimestamp - currentTsSolar[iSolar]; + + currentTsSolar[iSolar] = tsSolar; + + intervalProduced += Math.round(value * tsDiff); + + if (currentTsSolar[iSolar] >= intervalEndTimestamp) { + noNextRecordSolar[iSolar] = true; + } + System.out.print("."); + } + } + + double meterValue = 0; + for (int iMeter = 0; iMeter < channelIdsMeter.length; iMeter++) { + currentTsMeter[iMeter] = intervalStartTimestamp; + + while (currentTsMeter[iMeter] < intervalEndTimestamp && (noNextRecordMeter[iMeter] || rsMeter[iMeter].next())) { + if (noNextRecordMeter[iMeter]) { + noNextRecordMeter[iMeter] = false; + } + final long tsMeter = rsMeter[iMeter].getLong("timestamp"); + final double value = rsMeter[iMeter].getDouble("value"); + final long tsDiff = (tsMeter < intervalEndTimestamp) ? tsMeter - currentTsMeter[iMeter] : intervalEndTimestamp - currentTsMeter[iMeter]; + + currentTsMeter[iMeter] = tsMeter; + + meterValue += Math.round(value * tsDiff); + + if (currentTsMeter[iMeter] >= intervalEndTimestamp) { + noNextRecordMeter[iMeter] = true; + } + System.out.print("#"); + } + } + if (meterValue > 0.0) { + intervalObtained += Math.round(meterValue); + } else { + intervalInjected += Math.abs(Math.round(meterValue)); + } + + System.out.println(" " + intervalProduced + " / " + intervalObtained + " / " + intervalInjected); + + result.add(new Aggregate2(houseId, intervalStartTimestamp, intervalEndTimestamp, intervalProduced, intervalObtained, intervalInjected)); + + intervalStartTimestamp += interval; + intervalEndTimestamp += interval; + + intervalInjected = 0; + intervalObtained = 0; + intervalProduced = 0; + } + + // Aufräumen + for (int i = 0; i < channelIdsSolar.length; i++) { + rsSolar[i].close(); + stmtSolar[i].close(); + } + + for (int i = 0; i < channelIdsMeter.length; i++) { + rsMeter[i].close(); + stmtMeter[i].close(); + } + + return result; + } + + private static long getMinOfArray(final long[] input) { + long result = Long.MAX_VALUE; + for (long i : input) { + if (i < result) { + result = i; + } + } + return result; + } + private static void saveValues(final Connection con, final List aggregates, final int houseId) throws SQLException { System.out.println("Saving entries... : " + aggregates.size()); try (final PreparedStatement stmt = con.prepareStatement("INSERT INTO tobias_aggregate2 (house_id, timestamp_start, timestamp_end, produced_energy, obtained_energy, injected_energy) VALUES (?, ?, ?, ?, ?, ?)")) {