diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java index 7c28678..3e8eec7 100644 --- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java +++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java @@ -33,6 +33,7 @@ public interface CurrentMonitorDao { void updateSummaries(BreakerGroup _rootGroup, Set _daysToSummarize, TimeZone _tz); void rebuildSummaries(int _accountId); + void rebuildSummariesAsync(int _accountId); void rebuildSummaries(int _accountId, Date _start, Date _end); String addPasswordResetKey(String _email); diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java index 3bacc51..6260a68 100644 --- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java +++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java @@ -192,6 +192,11 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao { } } + @Override + public void rebuildSummariesAsync(int _accountId) { + executor.submit(()->rebuildSummaries(_accountId)); + } + @Override public void rebuildSummaries(int _accountId) { HubPowerMinute firstMinute = proxy.queryOne(HubPowerMinute.class, new DaoQuery("account_id", _accountId), DaoSort.sort("minute")); diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupEnergy.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupEnergy.java index 8ae8613..4eec58c 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupEnergy.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupEnergy.java @@ -14,7 +14,6 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.TimeZone; import java.util.TreeMap; @@ -30,6 +29,10 @@ public class BreakerGroupEnergy { private List energyBlocks; private double toGrid; private double fromGrid; + private double peakToGrid; + private double peakFromGrid; + private double peakConsumption; + private double peakProduction; private TimeZone timezone; public BreakerGroupEnergy() { @@ -65,7 +68,7 @@ public class BreakerGroupEnergy { resetEnergy(minute); } int idx; - Map meters = new HashMap<>(); + Map> minutes = new TreeMap<>(); for (HubPowerMinute hubPower : _hubPower) { Date minute = hubPower.getMinuteAsDate(); for (BreakerPowerMinute breaker : CollectionUtils.makeNotNull(hubPower.getBreakers())) { @@ -75,7 +78,7 @@ public class BreakerGroupEnergy { BreakerGroup group = _breakerKeyToGroup.get(breaker.breakerKey()); if (group == null) continue; - MeterMinuteValues meter = meters.computeIfAbsent(new MeterMinute(b.getMeter(), minute), _p->new MeterMinuteValues()); + MeterMinute meter = minutes.computeIfAbsent(hubPower.getMinute(), _p->new TreeMap<>()).computeIfAbsent(b.getMeter(), _m->new MeterMinute(b.getMeter(), hubPower.getMinuteAsDate())); idx = 0; EnergyBlock block = getBlock(group.getId(), minute); if (block != null) { @@ -94,27 +97,64 @@ public class BreakerGroupEnergy { } double monthFromGrid = _month == null ? 0.0 : _month.getFromGrid(); double secondFromGrid; - for (Map.Entry meter : meters.entrySet()) { + for (MeterMinute minute : CollectionUtils.aggregate(minutes.values(), Map::values)) { double monthkWh = monthFromGrid/3600000; - List consumptionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.FROM, meter.getKey().meter, monthkWh, meter.getKey().minute, timezone)); - List productionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.TO, meter.getKey().meter, monthkWh, meter.getKey().minute, timezone)); + List consumptionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.FROM, minute.getMeter(), monthkWh, minute.getMinute(), timezone)); + List productionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.TO, minute.getMeter(), monthkWh, minute.getMinute(), timezone)); for (int i = 0; i < 60; i++) { - secondFromGrid = meter.getValue().usage[i] - meter.getValue().solar[i]; + if (minute.usage[i] > peakConsumption) + peakConsumption = minute.usage[i]; + if (minute.solar[i] > peakProduction) + peakProduction = minute.solar[i]; + secondFromGrid = minute.usage[i] - minute.solar[i]; monthFromGrid += secondFromGrid; if (secondFromGrid > 0) { fromGrid += secondFromGrid; + if (secondFromGrid > peakFromGrid) + peakFromGrid = secondFromGrid; for (BillingRate rate : consumptionRates) { - meter.getValue().charges[i] += rate.apply(secondFromGrid/3600000); + minute.charges[i] += rate.apply(secondFromGrid/3600000); } } else { - toGrid -= secondFromGrid; + secondFromGrid = -secondFromGrid; + toGrid += secondFromGrid; + if (secondFromGrid > peakToGrid) + peakToGrid = secondFromGrid; for (BillingRate rate : productionRates) { - meter.getValue().charges[i] += rate.apply(secondFromGrid/3600000); + minute.charges[i] -= rate.apply(secondFromGrid/3600000); } } } } + double curConsumption; + double curProduction; + double curToGrid; + double curFromGrid; + for (Map meters : minutes.values()) { + for (int i=0; i < 60; i++) { + curConsumption = 0; + curProduction = 0; + curToGrid = 0; + curFromGrid = 0; + for (MeterMinute meterValues : meters.values()) { + curConsumption += meterValues.usage[i]; + curProduction += meterValues.solar[i]; + if (meterValues.solar[i] > meterValues.usage[i]) + curToGrid += meterValues.solar[i] - meterValues.usage[i]; + else + curFromGrid += meterValues.usage[i] - meterValues.solar[i]; + } + if (curConsumption > peakConsumption) + peakConsumption = curConsumption; + if (curProduction > peakProduction) + peakProduction = curProduction; + if (curToGrid > peakToGrid) + peakToGrid = curToGrid; + if (curFromGrid > peakFromGrid) + peakFromGrid = curFromGrid; + } + } for (HubPowerMinute hubPower : _hubPower) { Date minute = hubPower.getMinuteAsDate(); for (BreakerPowerMinute breaker : CollectionUtils.makeNotNull(hubPower.getBreakers())) { @@ -124,7 +164,7 @@ public class BreakerGroupEnergy { BreakerGroup group = _breakerKeyToGroup.get(breaker.breakerKey()); if (group == null) continue; - MeterMinuteValues meter = meters.get(new MeterMinute(b.getMeter(), minute)); + MeterMinute meter = minutes.get(hubPower.getMinute()).get(b.getMeter()); idx = 0; double charge = 0.0; for (Float power : CollectionUtils.makeNotNull(breaker.getReadings())) { @@ -190,6 +230,14 @@ public class BreakerGroupEnergy { block.addCharge(curEnergy.getCharge()); energy.setToGrid(energy.getToGrid()+curEnergy.getToGrid()); energy.setFromGrid(energy.getFromGrid()+curEnergy.getFromGrid()); + if (curEnergy.getPeakFromGrid() > energy.getPeakFromGrid()) + energy.setPeakFromGrid(curEnergy.getPeakFromGrid()); + if (curEnergy.getPeakToGrid() > energy.getPeakToGrid()) + energy.setPeakToGrid(curEnergy.getPeakToGrid()); + if (curEnergy.getPeakConsumption() > energy.getPeakConsumption()) + energy.setPeakConsumption(curEnergy.getPeakConsumption()); + if (curEnergy.getPeakProduction() > energy.getPeakProduction()) + energy.setPeakProduction(curEnergy.getPeakProduction()); } return energy; } @@ -304,6 +352,38 @@ public class BreakerGroupEnergy { fromGrid = _fromGrid; } + public double getPeakToGrid() { + return peakToGrid; + } + + public void setPeakToGrid(double _peakToGrid) { + peakToGrid = _peakToGrid; + } + + public double getPeakFromGrid() { + return peakFromGrid; + } + + public void setPeakFromGrid(double _peakFromGrid) { + peakFromGrid = _peakFromGrid; + } + + public double getPeakConsumption() { + return peakConsumption; + } + + public void setPeakConsumption(double _peakConsumption) { + peakConsumption = _peakConsumption; + } + + public double getPeakProduction() { + return peakProduction; + } + + public void setPeakProduction(double _peakProduction) { + peakProduction = _peakProduction; + } + public TimeZone getTimeZone() { return timezone; } @@ -430,21 +510,14 @@ public class BreakerGroupEnergy { minute = _minute; } - @Override - public boolean equals(Object _o) { - if (this == _o) return true; - if (_o == null || getClass() != _o.getClass()) return false; - MeterMinute that = (MeterMinute) _o; - return meter == that.meter && minute.equals(that.minute); + public int getMeter() { + return meter; } - @Override - public int hashCode() { - return Objects.hash(meter, minute); + public Date getMinute() { + return minute; } - } - private static class MeterMinuteValues { public double[] usage = new double[60]; public double[] solar = new double[60]; public double[] charges = new double[60]; diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupSummary.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupSummary.java index e9882fd..9140444 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupSummary.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupSummary.java @@ -24,6 +24,10 @@ public class BreakerGroupSummary { private double charge; private double toGrid; private double fromGrid; + private double peakToGrid; + private double peakFromGrid; + private double peakConsumption; + private double peakProduction; public BreakerGroupSummary() { } @@ -39,6 +43,10 @@ public class BreakerGroupSummary { charge = _energy.charge(null, false); toGrid = _energy.getToGrid(); fromGrid = _energy.getFromGrid(); + peakToGrid = _energy.getPeakToGrid(); + peakFromGrid = _energy.getPeakFromGrid(); + peakConsumption = _energy.getPeakConsumption(); + peakProduction = _energy.getPeakProduction(); } public String getId() { @@ -133,6 +141,38 @@ public class BreakerGroupSummary { fromGrid = _fromGrid; } + public double getPeakConsumption() { + return peakConsumption; + } + + public void setPeakConsumption(double _peakConsumption) { + peakConsumption = _peakConsumption; + } + + public double getPeakProduction() { + return peakProduction; + } + + public void setPeakProduction(double _peakProduction) { + peakProduction = _peakProduction; + } + + public double getPeakToGrid() { + return peakToGrid; + } + + public void setPeakToGrid(double _peakToGrid) { + peakToGrid = _peakToGrid; + } + + public double getPeakFromGrid() { + return peakFromGrid; + } + + public void setPeakFromGrid(double _peakFromGrid) { + peakFromGrid = _peakFromGrid; + } + public List getAllGroups() { Map groups = new TreeMap<>(); getAllGroups(groups); diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BreakerGroupEnergySerializer.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BreakerGroupEnergySerializer.java index 774155d..0190d3d 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BreakerGroupEnergySerializer.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BreakerGroupEnergySerializer.java @@ -74,6 +74,10 @@ public class BreakerGroupEnergySerializer extends AbstractDaoSerializerlantern-util-servlet 1.0.0 + + com.lanternsoftware.util + lantern-util-http + 1.0.0 + test + com.lanternsoftware.rules lantern-service-rules diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/RebuildSummariesServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/RebuildSummariesServlet.java new file mode 100644 index 0000000..05cf8f2 --- /dev/null +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/RebuildSummariesServlet.java @@ -0,0 +1,26 @@ +package com.lanternsoftware.currentmonitor.servlet; + +import com.lanternsoftware.currentmonitor.context.Globals; +import com.lanternsoftware.datamodel.currentmonitor.Account; +import com.lanternsoftware.util.dao.DaoSerializer; +import com.lanternsoftware.util.dao.auth.AuthCode; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet("/rebuildSummaries") +public class RebuildSummariesServlet extends SecureServlet { + @Override + protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) { + if (_authCode.getAccountId() == 100) { + for (String sId : Globals.dao.getProxy().queryForField(Account.class, null, "_id")) { + int id = DaoSerializer.toInteger(sId); + if (id != 0) + Globals.dao.rebuildSummariesAsync(id); + } + } + else + _rep.setStatus(401); + } +} diff --git a/currentmonitor/lantern-service-currentmonitor/src/test/java/com/lanternsoftware/currentmonitor/CreateAuthCode.java b/currentmonitor/lantern-service-currentmonitor/src/test/java/com/lanternsoftware/currentmonitor/CreateAuthCode.java index 93ec941..b630950 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/test/java/com/lanternsoftware/currentmonitor/CreateAuthCode.java +++ b/currentmonitor/lantern-service-currentmonitor/src/test/java/com/lanternsoftware/currentmonitor/CreateAuthCode.java @@ -1,10 +1,10 @@ package com.lanternsoftware.currentmonitor; -import com.lanternsoftware.datamodel.currentmonitor.AuthCode; import com.lanternsoftware.util.LanternFiles; import com.lanternsoftware.util.ResourceLoader; import com.lanternsoftware.util.cryptography.AESTool; import com.lanternsoftware.util.dao.DaoSerializer; +import com.lanternsoftware.util.dao.auth.AuthCode; public class CreateAuthCode { private static final AESTool aes = new AESTool(ResourceLoader.loadFile(LanternFiles.OPS_PATH + "authKey.dat")); diff --git a/currentmonitor/lantern-service-currentmonitor/src/test/java/com/lanternsoftware/currentmonitor/RebuildSummariesRemote.java b/currentmonitor/lantern-service-currentmonitor/src/test/java/com/lanternsoftware/currentmonitor/RebuildSummariesRemote.java new file mode 100644 index 0000000..0051eb2 --- /dev/null +++ b/currentmonitor/lantern-service-currentmonitor/src/test/java/com/lanternsoftware/currentmonitor/RebuildSummariesRemote.java @@ -0,0 +1,16 @@ +package com.lanternsoftware.currentmonitor; + +import com.lanternsoftware.util.http.HttpPool; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; + +public class RebuildSummariesRemote { + public static void main(String[] args) { + HttpPool pool = new HttpPool(10, 10, 10000, 10000, 10000); + HttpGet r = new HttpGet("https://lanternpowermonitor.com/currentmonitor/rebuildSummaries"); + r.addHeader("auth_code", ""); + CloseableHttpResponse resp = pool.execute(r); + System.out.println(resp.getStatusLine().getStatusCode()); + pool.shutdown(); + } +} diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java index 99ca3f1..2890b30 100644 --- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java +++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java @@ -266,7 +266,7 @@ public class CollectionUtils { public static List aggregate(Collection _coll, IAggregator _aggregator) { List list = new ArrayList<>(); for (T t : makeNotNull(_coll)) { - List vs = _aggregator.aggregate(t); + Collection vs = _aggregator.aggregate(t); if (vs != null) list.addAll(vs); } diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/IAggregator.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/IAggregator.java index 0df527f..40c568b 100644 --- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/IAggregator.java +++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/IAggregator.java @@ -1,7 +1,7 @@ package com.lanternsoftware.util; -import java.util.List; +import java.util.Collection; public interface IAggregator { - List aggregate(T _t); + Collection aggregate(T _t); }