mirror of
https://github.com/zyphlar/LanternPowerMonitor.git
synced 2024-03-08 14:07:47 +00:00
Keep track of peak production, peak consumption, peak from grid, and peak to grid values to aid in solar panel and storage sizing.
This commit is contained in:
@@ -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<EnergyBlock> 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<MeterMinute, MeterMinuteValues> meters = new HashMap<>();
|
||||
Map<Integer, Map<Integer, MeterMinute>> 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<MeterMinute, MeterMinuteValues> meter : meters.entrySet()) {
|
||||
for (MeterMinute minute : CollectionUtils.aggregate(minutes.values(), Map::values)) {
|
||||
double monthkWh = monthFromGrid/3600000;
|
||||
List<BillingRate> consumptionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.FROM, meter.getKey().meter, monthkWh, meter.getKey().minute, timezone));
|
||||
List<BillingRate> productionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.TO, meter.getKey().meter, monthkWh, meter.getKey().minute, timezone));
|
||||
List<BillingRate> consumptionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.FROM, minute.getMeter(), monthkWh, minute.getMinute(), timezone));
|
||||
List<BillingRate> 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<Integer, MeterMinute> 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];
|
||||
|
||||
@@ -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<BreakerGroupSummary> getAllGroups() {
|
||||
Map<String, BreakerGroupSummary> groups = new TreeMap<>();
|
||||
getAllGroups(groups);
|
||||
|
||||
@@ -74,6 +74,10 @@ public class BreakerGroupEnergySerializer extends AbstractDaoSerializer<BreakerG
|
||||
}
|
||||
d.put("to_grid", _o.getToGrid());
|
||||
d.put("from_grid", _o.getFromGrid());
|
||||
d.put("peak_to_grid", _o.getPeakToGrid());
|
||||
d.put("peak_from_grid", _o.getPeakFromGrid());
|
||||
d.put("peak_production", _o.getPeakProduction());
|
||||
d.put("peak_consumption", _o.getPeakConsumption());
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -110,6 +114,10 @@ public class BreakerGroupEnergySerializer extends AbstractDaoSerializer<BreakerG
|
||||
}
|
||||
o.setToGrid(DaoSerializer.getDouble(_d, "to_grid"));
|
||||
o.setFromGrid(DaoSerializer.getDouble(_d, "from_grid"));
|
||||
o.setPeakToGrid(DaoSerializer.getDouble(_d, "peak_to_grid"));
|
||||
o.setPeakFromGrid(DaoSerializer.getDouble(_d, "peak_from_grid"));
|
||||
o.setPeakProduction(DaoSerializer.getDouble(_d, "peak_production"));
|
||||
o.setPeakConsumption(DaoSerializer.getDouble(_d, "peak_consumption"));
|
||||
return o;
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,10 @@ public class BreakerGroupSummarySerializer extends AbstractDaoSerializer<Breaker
|
||||
d.put("charge", _o.getCharge());
|
||||
d.put("to_grid", _o.getToGrid());
|
||||
d.put("from_grid", _o.getFromGrid());
|
||||
d.put("peak_to_grid", _o.getPeakToGrid());
|
||||
d.put("peak_from_grid", _o.getPeakFromGrid());
|
||||
d.put("peak_production", _o.getPeakProduction());
|
||||
d.put("peak_consumption", _o.getPeakConsumption());
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -52,6 +56,10 @@ public class BreakerGroupSummarySerializer extends AbstractDaoSerializer<Breaker
|
||||
o.setCharge(DaoSerializer.getDouble(_d, "charge"));
|
||||
o.setToGrid(DaoSerializer.getDouble(_d, "to_grid"));
|
||||
o.setFromGrid(DaoSerializer.getDouble(_d, "from_grid"));
|
||||
o.setPeakToGrid(DaoSerializer.getDouble(_d, "peak_to_grid"));
|
||||
o.setPeakFromGrid(DaoSerializer.getDouble(_d, "peak_from_grid"));
|
||||
o.setPeakProduction(DaoSerializer.getDouble(_d, "peak_production"));
|
||||
o.setPeakConsumption(DaoSerializer.getDouble(_d, "peak_consumption"));
|
||||
return o;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user