mirror of
https://github.com/zyphlar/LanternPowerMonitor.git
synced 2024-03-08 14:07:47 +00:00
Add billing plans so different plans can be compared. Performance enhancements to charge calculations.
This commit is contained in:
parent
ecbf438082
commit
883cf7865d
|
@ -2,8 +2,8 @@ package com.lanternsoftware.dataaccess.currentmonitor;
|
|||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupSummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergySummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyTotal;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Sequence;
|
||||
import com.lanternsoftware.datamodel.rules.Event;
|
||||
import com.lanternsoftware.datamodel.rules.FcmDevice;
|
||||
|
@ -34,14 +34,14 @@ public class Backup {
|
|||
t4.stop();
|
||||
|
||||
DebugTimer t5 = new DebugTimer("Query Energy");
|
||||
List<BreakerGroupEnergy> energy = dao.getProxy().queryAll(BreakerGroupEnergy.class);
|
||||
List<EnergySummary> energy = dao.getProxy().queryAll(EnergySummary.class);
|
||||
t5.stop();
|
||||
DebugTimer t6 = new DebugTimer("Save Energy");
|
||||
backupDao.getProxy().save(energy);
|
||||
t6.stop();
|
||||
|
||||
DebugTimer t7 = new DebugTimer("Query Summaries");
|
||||
List<BreakerGroupSummary> summary = dao.getProxy().queryAll(BreakerGroupSummary.class);
|
||||
List<EnergyTotal> summary = dao.getProxy().queryAll(EnergyTotal.class);
|
||||
t7.stop();
|
||||
DebugTimer t8 = new DebugTimer("Save Summaries");
|
||||
backupDao.getProxy().save(summary);
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
package com.lanternsoftware.dataaccess.currentmonitor;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergySummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.util.dao.mongo.MongoProxy;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public interface CurrentMonitorDao {
|
||||
|
@ -21,9 +19,10 @@ public interface CurrentMonitorDao {
|
|||
void putBreakerPower(BreakerPower _current);
|
||||
List<BreakerPower> getBreakerPowerForAccount(int _accountId);
|
||||
BreakerPower getLatestBreakerPower(int _accountId, int _hub, int _port);
|
||||
BreakerGroupEnergy getBreakerGroupEnergy(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start);
|
||||
byte[] getBreakerGroupEnergyBinary(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start);
|
||||
void putBreakerGroupEnergy(BreakerGroupEnergy _energy);
|
||||
EnergySummary getEnergySummary(int _accountId, String _groupId, EnergyViewMode _viewMode, Date _start);
|
||||
byte[] getEnergySummaryBinary(int _accountId, String _groupId, EnergyViewMode _viewMode, Date _start);
|
||||
byte[] getChargeSummaryBinary(int _accountId, int _planId, String _groupId, EnergyViewMode _viewMode, Date _start);
|
||||
void putEnergySummary(EnergySummary _energy);
|
||||
|
||||
void putHubPowerMinute(HubPowerMinute _power);
|
||||
|
||||
|
@ -31,7 +30,6 @@ public interface CurrentMonitorDao {
|
|||
BreakerConfig getMergedConfig(AuthCode _authCode);
|
||||
void putConfig(BreakerConfig _config);
|
||||
|
||||
void updateSummaries(BreakerGroup _rootGroup, Set<Date> _daysToSummarize, TimeZone _tz);
|
||||
void rebuildSummaries(int _accountId);
|
||||
void rebuildSummariesAsync(int _accountId);
|
||||
void rebuildSummaries(int _accountId, Date _start, Date _end);
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package com.lanternsoftware.dataaccess.currentmonitor;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BillingPlan;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BillingRate;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupSummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.ChargeSummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.ChargeTotal;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergySummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyTotal;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Sequence;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
|
@ -23,6 +26,7 @@ import com.lanternsoftware.util.dao.DaoSort;
|
|||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||
import com.lanternsoftware.util.dao.mongo.MongoProxy;
|
||||
import com.lanternsoftware.util.mutable.MutableDouble;
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -31,6 +35,7 @@ import java.util.ArrayList;
|
|||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -53,11 +58,13 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
proxy = new MongoProxy(_config);
|
||||
proxy.ensureIndex(BreakerPower.class, DaoSort.sort("account_id").then("key"));
|
||||
proxy.ensureIndex(HubPowerMinute.class, DaoSort.sort("account_id").then("minute"));
|
||||
proxy.ensureIndex(BreakerGroupEnergy.class, DaoSort.sort("account_id").then("group_id").then("view_mode"));
|
||||
proxy.ensureIndex(BreakerGroupSummary.class, DaoSort.sort("account_id").then("group_id").then("view_mode").then("start"));
|
||||
proxy.ensureIndex(EnergySummary.class, DaoSort.sort("account_id").then("group_id").then("view_mode"));
|
||||
proxy.ensureIndex(EnergyTotal.class, DaoSort.sort("account_id").then("group_id").then("view_mode").then("start"));
|
||||
proxy.ensureIndex(ChargeSummary.class, DaoSort.sort("account_id").then("plan_id").then("group_id").then("view_mode"));
|
||||
proxy.ensureIndex(ChargeTotal.class, DaoSort.sort("account_id").then("plan_id").then("group_id").then("view_mode").then("start"));
|
||||
proxy.ensureIndex(DirtyMinute.class, DaoSort.sort("posted"));
|
||||
for (DirtyMinute minute : proxy.queryAll(DirtyMinute.class)) {
|
||||
updateSummaries(minute);
|
||||
updateEnergySummaries(minute);
|
||||
}
|
||||
proxy.delete(DirtyMinute.class, new DaoQuery());
|
||||
}
|
||||
|
@ -80,36 +87,49 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
proxy.save(_power);
|
||||
DirtyMinute minute = new DirtyMinute(_power.getAccountId(), _power.getMinute(), new Date());
|
||||
proxy.save(minute);
|
||||
delayTimer.schedule(new TimerTask(){
|
||||
delayTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
executor.submit(()->{
|
||||
executor.submit(() -> {
|
||||
if (proxy.queryOneAndDelete(DirtyMinute.class, new DaoQuery("_id", minute.getId())) != null)
|
||||
updateSummaries(new DirtyMinute(_power.getAccountId(), _power.getMinute(), new Date()));
|
||||
updateEnergySummaries(new DirtyMinute(_power.getAccountId(), _power.getMinute(), new Date()));
|
||||
});
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
private void updateSummaries(DirtyMinute _minute) {
|
||||
private void updateEnergySummaries(DirtyMinute _minute) {
|
||||
DebugTimer timer = new DebugTimer("Updating summaries", logger);
|
||||
List<HubPowerMinute> minutes = proxy.query(HubPowerMinute.class, new DaoQuery("account_id", _minute.getAccountId()).and("minute", _minute.getMinute()));
|
||||
TimeZone tz = getTimeZoneForAccount(_minute.getAccountId());
|
||||
BreakerConfig config = getConfig(_minute.getAccountId());
|
||||
BreakerGroup group = CollectionUtils.getFirst(config.getBreakerGroups());
|
||||
Date day = DateUtils.getMidnightBefore(_minute.getMinuteAsDate(), tz);
|
||||
BreakerGroupEnergy energy = getBreakerGroupEnergy(_minute.getAccountId(), group.getId(), EnergyBlockViewMode.DAY, day);
|
||||
Date monthStart = DateUtils.getStartOfMonth(day, tz);
|
||||
BreakerGroupSummary month = proxy.queryOne(BreakerGroupSummary.class, new DaoQuery("_id", BreakerGroupEnergy.toId(_minute.getAccountId(), group.getId(), EnergyBlockViewMode.MONTH, monthStart)));
|
||||
DebugTimer t2 = new DebugTimer("Updating energy", logger);
|
||||
EnergySummary energy = getEnergySummary(_minute.getAccountId(), group.getId(), EnergyViewMode.DAY, day);
|
||||
if (energy == null)
|
||||
energy = new BreakerGroupEnergy(group, minutes, EnergyBlockViewMode.DAY, day, month, config.getBillingRates(), tz);
|
||||
energy = new EnergySummary(group, minutes, EnergyViewMode.DAY, day, tz);
|
||||
else
|
||||
energy.addEnergy(group, minutes, month, config.getBillingRates());
|
||||
putBreakerGroupEnergy(energy);
|
||||
updateSummaries(group, CollectionUtils.asHashSet(day), tz);
|
||||
energy.addEnergy(group, minutes);
|
||||
putEnergySummary(energy);
|
||||
updateEnergySummaries(group, CollectionUtils.asHashSet(day), tz);
|
||||
t2.stop();
|
||||
DebugTimer t3 = new DebugTimer("Updating charges", logger);
|
||||
updateChargeSummary(config, energy, tz);
|
||||
updateChargeSummaries(config, CollectionUtils.asHashSet(energy.getStart()), tz);
|
||||
t3.stop();
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
private void putChargeSummary(ChargeSummary _summary) {
|
||||
putChargeSummaries(CollectionUtils.asArrayList(_summary));
|
||||
}
|
||||
|
||||
private void putChargeSummaries(Collection<ChargeSummary> _summaries) {
|
||||
proxy.save(_summaries);
|
||||
proxy.save(CollectionUtils.transform(_summaries, ChargeTotal::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BreakerPower> getBreakerPowerForAccount(int _accountId) {
|
||||
return proxy.query(BreakerPower.class, new DaoQuery("account_id", _accountId).andGt("read_time", DateUtils.minutesFromNow(-1).getTime()));
|
||||
|
@ -121,17 +141,21 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
}
|
||||
|
||||
@Override
|
||||
public BreakerGroupEnergy getBreakerGroupEnergy(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start) {
|
||||
return proxy.queryOne(BreakerGroupEnergy.class, new DaoQuery("_id", BreakerGroupEnergy.toId(_accountId, _groupId, _viewMode, _start)));
|
||||
public EnergySummary getEnergySummary(int _accountId, String _groupId, EnergyViewMode _viewMode, Date _start) {
|
||||
return proxy.queryOne(EnergySummary.class, new DaoQuery("_id", EnergySummary.toId(_accountId, _groupId, _viewMode, _start)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBreakerGroupEnergyBinary(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start) {
|
||||
return DaoSerializer.toZipBson(proxy.queryForEntity(BreakerGroupEnergy.class, new DaoQuery("_id", BreakerGroupEnergy.toId(_accountId, _groupId, _viewMode, _start))));
|
||||
public byte[] getEnergySummaryBinary(int _accountId, String _groupId, EnergyViewMode _viewMode, Date _start) {
|
||||
return DaoSerializer.toZipBson(proxy.queryForEntity(EnergySummary.class, new DaoQuery("_id", EnergySummary.toId(_accountId, _groupId, _viewMode, _start))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSummaries(BreakerGroup _rootGroup, Set<Date> _daysToSummarize, TimeZone _tz) {
|
||||
public byte[] getChargeSummaryBinary(int _accountId, int _planId, String _groupId, EnergyViewMode _viewMode, Date _start) {
|
||||
return DaoSerializer.toZipBson(proxy.queryForEntity(ChargeSummary.class, new DaoQuery("_id", ChargeSummary.toId(_accountId, _planId, _groupId, _viewMode, _start))));
|
||||
}
|
||||
|
||||
private void updateEnergySummaries(BreakerGroup _rootGroup, Set<Date> _daysToSummarize, TimeZone _tz) {
|
||||
Set<Date> monthsToSummarize = CollectionUtils.transformToSet(_daysToSummarize, _c -> DateUtils.getStartOfMonth(_c, _tz));
|
||||
Set<Date> yearsToSummarize = CollectionUtils.transformToSet(monthsToSummarize, _c -> DateUtils.getStartOfYear(_c, _tz));
|
||||
for (Date month : monthsToSummarize) {
|
||||
|
@ -139,31 +163,101 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
Calendar end = DateUtils.getEndOfMonthCal(month, _tz);
|
||||
List<String> groupEnergyIds = new ArrayList<>();
|
||||
while (calDayStart.before(end)) {
|
||||
groupEnergyIds.add(BreakerGroupEnergy.toId(_rootGroup.getAccountId(), _rootGroup.getId(), EnergyBlockViewMode.DAY, calDayStart.getTime()));
|
||||
groupEnergyIds.add(EnergySummary.toId(_rootGroup.getAccountId(), _rootGroup.getId(), EnergyViewMode.DAY, calDayStart.getTime()));
|
||||
calDayStart.add(Calendar.DAY_OF_YEAR, 1);
|
||||
}
|
||||
List<BreakerGroupSummary> groupEnergies = CollectionUtils.aggregate(proxy.query(BreakerGroupSummary.class, DaoQuery.in("_id", groupEnergyIds)), BreakerGroupSummary::getAllGroups);
|
||||
Map<String, List<BreakerGroupSummary>> energies = CollectionUtils.transformToMultiMap(groupEnergies, BreakerGroupSummary::getGroupId);
|
||||
BreakerGroupEnergy summary = BreakerGroupEnergy.summary(_rootGroup, energies, EnergyBlockViewMode.MONTH, month, _tz);
|
||||
putBreakerGroupEnergy(summary);
|
||||
List<EnergyTotal> groupEnergies = CollectionUtils.aggregate(proxy.query(EnergyTotal.class, DaoQuery.in("_id", groupEnergyIds)), EnergyTotal::flatten);
|
||||
Map<String, List<EnergyTotal>> energies = CollectionUtils.transformToMultiMap(groupEnergies, EnergyTotal::getGroupId);
|
||||
EnergySummary summary = EnergySummary.summary(_rootGroup, energies, EnergyViewMode.MONTH, month, _tz);
|
||||
putEnergySummary(summary);
|
||||
}
|
||||
for (Date year : yearsToSummarize) {
|
||||
Calendar calMonthStart = DateUtils.toCalendar(year, _tz);
|
||||
Calendar end = DateUtils.getEndOfYearCal(year, _tz);
|
||||
List<String> groupEnergyIds = new ArrayList<>();
|
||||
List<String> summaryIds = new ArrayList<>();
|
||||
while (calMonthStart.before(end)) {
|
||||
groupEnergyIds.add(BreakerGroupEnergy.toId(_rootGroup.getAccountId(), _rootGroup.getId(), EnergyBlockViewMode.MONTH, calMonthStart.getTime()));
|
||||
summaryIds.add(EnergySummary.toId(_rootGroup.getAccountId(), _rootGroup.getId(), EnergyViewMode.MONTH, calMonthStart.getTime()));
|
||||
calMonthStart.add(Calendar.MONTH, 1);
|
||||
}
|
||||
List<BreakerGroupSummary> groupEnergies = CollectionUtils.aggregate(proxy.query(BreakerGroupSummary.class, DaoQuery.in("_id", groupEnergyIds)), BreakerGroupSummary::getAllGroups);
|
||||
Map<String, List<BreakerGroupSummary>> energies = CollectionUtils.transformToMultiMap(groupEnergies, BreakerGroupSummary::getGroupId);
|
||||
BreakerGroupEnergy summary = BreakerGroupEnergy.summary(_rootGroup, energies, EnergyBlockViewMode.YEAR, year, _tz);
|
||||
putBreakerGroupEnergy(summary);
|
||||
List<EnergyTotal> groupEnergies = CollectionUtils.aggregate(proxy.query(EnergyTotal.class, DaoQuery.in("_id", summaryIds)), EnergyTotal::flatten);
|
||||
Map<String, List<EnergyTotal>> energies = CollectionUtils.transformToMultiMap(groupEnergies, EnergyTotal::getGroupId);
|
||||
EnergySummary summary = EnergySummary.summary(_rootGroup, energies, EnergyViewMode.YEAR, year, _tz);
|
||||
putEnergySummary(summary);
|
||||
}
|
||||
List<EnergyTotal> groupEnergies = CollectionUtils.aggregate(proxy.query(EnergyTotal.class, new DaoQuery("account_id", _rootGroup.getAccountId()).and("group_id", _rootGroup.getId()).and("view_mode", EnergyViewMode.YEAR.name())), EnergyTotal::flatten);
|
||||
Map<String, List<EnergyTotal>> energies = CollectionUtils.transformToMultiMap(groupEnergies, EnergyTotal::getGroupId);
|
||||
EnergySummary summary = EnergySummary.summary(_rootGroup, energies, EnergyViewMode.ALL, new Date(0), _tz);
|
||||
putEnergySummary(summary);
|
||||
}
|
||||
|
||||
private void updateChargeSummary(BreakerConfig _config, EnergySummary _energySummary, TimeZone _tz) {
|
||||
Date lookback = null;
|
||||
for (BillingPlan p : CollectionUtils.makeNotNull(_config.getBillingPlans())) {
|
||||
Date cycleStart = p.getBillingCycleStart(_energySummary.getStart(), _tz);
|
||||
if (cycleStart.after(_energySummary.getStart()))
|
||||
cycleStart = DateUtils.addMonths(cycleStart, -1, _tz);
|
||||
if ((lookback == null) || cycleStart.before(lookback))
|
||||
lookback = cycleStart;
|
||||
}
|
||||
if (lookback != null) {
|
||||
List<String> groupEnergyIds = new ArrayList<>();
|
||||
while (lookback.before(_energySummary.getStart())) {
|
||||
groupEnergyIds.add(EnergySummary.toId(_config.getAccountId(), _energySummary.getGroupId(), EnergyViewMode.DAY, lookback));
|
||||
lookback = DateUtils.addDays(lookback, 1, _tz);
|
||||
}
|
||||
List<EnergyTotal> totals = proxy.query(EnergyTotal.class, DaoQuery.in("_id", groupEnergyIds));
|
||||
putChargeSummaries(_energySummary.toChargeSummaries(_config, totals));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChargeSummaries(BreakerConfig _config, Set<Date> _daysToSummarize, TimeZone _tz) {
|
||||
if (CollectionUtils.isEmpty(_config.getBillingPlans()))
|
||||
return;
|
||||
Set<Date> yearsToSummarize = CollectionUtils.transformToSet(_daysToSummarize, _c -> DateUtils.getStartOfYear(_c, _tz));
|
||||
BreakerGroup rootGroup = _config.getRootGroup();
|
||||
for (BillingPlan plan : _config.getBillingPlans()) {
|
||||
List<ChargeSummary> summaries = new ArrayList<>();
|
||||
Set<Date> monthsToSummarize = CollectionUtils.transformToSet(_daysToSummarize, _c -> plan.getBillingCycleStart(_c, _tz));
|
||||
for (Date month : monthsToSummarize) {
|
||||
Calendar monthDayStart = DateUtils.toCalendar(month, _tz);
|
||||
Calendar monthEnd = DateUtils.toCalendar(plan.getBillingCycleEnd(month, _tz), _tz);
|
||||
Set<String> monthSummaryIds = new HashSet<>();
|
||||
while (monthDayStart.before(monthEnd)) {
|
||||
monthSummaryIds.add(ChargeSummary.toId(rootGroup.getAccountId(), plan.getPlanId(), rootGroup.getId(), EnergyViewMode.DAY, monthDayStart.getTime()));
|
||||
monthDayStart.add(Calendar.DAY_OF_YEAR, 1);
|
||||
}
|
||||
List<ChargeTotal> monthTotals = CollectionUtils.aggregate(proxy.query(ChargeTotal.class, DaoQuery.in("_id", monthSummaryIds)), ChargeTotal::flatten);
|
||||
Map<String, List<ChargeTotal>> monthCharges = CollectionUtils.transformToMultiMap(monthTotals, ChargeTotal::getGroupId);
|
||||
summaries.add(new ChargeSummary(rootGroup, plan, monthCharges, EnergyViewMode.MONTH, month, _tz));
|
||||
}
|
||||
putChargeSummaries(summaries);
|
||||
}
|
||||
for (BillingPlan plan : _config.getBillingPlans()) {
|
||||
List<ChargeSummary> summaries = new ArrayList<>();
|
||||
for (Date year : yearsToSummarize) {
|
||||
Date yearStart = DateUtils.getStartOfYear(year, _tz);
|
||||
Date yearEnd = DateUtils.addYears(yearStart, 1, _tz);
|
||||
Date yearMonthStart = yearStart;
|
||||
Set<String> monthSummaryIds = new HashSet<>();
|
||||
Date loopEnd = DateUtils.addDays(yearEnd, 1, _tz);
|
||||
while (yearMonthStart.before(loopEnd)) {
|
||||
Date billingStart = plan.getBillingCycleStart(yearMonthStart, _tz);
|
||||
if (DateUtils.isBetween(billingStart, yearStart, yearEnd))
|
||||
monthSummaryIds.add(ChargeSummary.toId(rootGroup.getAccountId(), plan.getPlanId(), rootGroup.getId(), EnergyViewMode.MONTH, billingStart));
|
||||
yearMonthStart = DateUtils.addMonths(yearMonthStart, 1, _tz);
|
||||
}
|
||||
List<ChargeTotal> flatTotals = CollectionUtils.aggregate(proxy.query(ChargeTotal.class, DaoQuery.in("_id", monthSummaryIds)), ChargeTotal::flatten);
|
||||
Map<String, List<ChargeTotal>> yearCharges = CollectionUtils.transformToMultiMap(flatTotals, ChargeTotal::getGroupId);
|
||||
summaries.add(new ChargeSummary(rootGroup, plan, yearCharges, EnergyViewMode.YEAR, yearStart, _tz));
|
||||
}
|
||||
putChargeSummaries(summaries);
|
||||
}
|
||||
for (BillingPlan plan : _config.getBillingPlans()) {
|
||||
List<ChargeTotal> yearTotals = CollectionUtils.aggregate(proxy.query(ChargeTotal.class, new DaoQuery("account_id", rootGroup.getAccountId()).and("plan_id", plan.getPlanId()).and("group_id", rootGroup.getId()).and("view_mode", EnergyViewMode.YEAR.name())), ChargeTotal::flatten);
|
||||
Map<String, List<ChargeTotal>> charges = CollectionUtils.transformToMultiMap(yearTotals, ChargeTotal::getGroupId);
|
||||
ChargeSummary summary = new ChargeSummary(rootGroup, plan, charges, EnergyViewMode.ALL, new Date(0), _tz);
|
||||
putChargeSummary(summary);
|
||||
}
|
||||
List<BreakerGroupSummary> groupEnergies = CollectionUtils.aggregate(proxy.query(BreakerGroupSummary.class, new DaoQuery("account_id", _rootGroup.getAccountId()).and("group_id", _rootGroup.getId()).and("view_mode", EnergyBlockViewMode.YEAR.name())), BreakerGroupSummary::getAllGroups);
|
||||
Map<String, List<BreakerGroupSummary>> energies = CollectionUtils.transformToMultiMap(groupEnergies, BreakerGroupSummary::getGroupId);
|
||||
BreakerGroupEnergy summary = BreakerGroupEnergy.summary(_rootGroup, energies, EnergyBlockViewMode.ALL, new Date(0), _tz);
|
||||
putBreakerGroupEnergy(summary);
|
||||
}
|
||||
|
||||
private void rebuildSummaries(int _accountId, Collection<BillingRate> _rates) {
|
||||
|
@ -172,7 +266,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
if (firstMinute == null)
|
||||
return;
|
||||
TimeZone tz = getTimeZoneForAccount(_accountId);
|
||||
Map<String, BillingRate> rates = CollectionUtils.transformToMap(_rates, _r->String.format("%d%d", DaoSerializer.toLong(_r.getBeginEffective()), DaoSerializer.toLong(_r.getEndEffective())));
|
||||
Map<String, BillingRate> rates = CollectionUtils.transformToMap(_rates, _r -> String.format("%d%d", DaoSerializer.toLong(_r.getBeginEffective()), DaoSerializer.toLong(_r.getEndEffective())));
|
||||
for (BillingRate rate : rates.values()) {
|
||||
Date start = rate.getBeginEffective();
|
||||
Date end = rate.getEndEffective();
|
||||
|
@ -194,7 +288,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
|
||||
@Override
|
||||
public void rebuildSummariesAsync(int _accountId) {
|
||||
executor.submit(()->rebuildSummaries(_accountId));
|
||||
executor.submit(() -> rebuildSummaries(_accountId));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -210,35 +304,88 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
BreakerConfig config = getConfig(_accountId);
|
||||
TimeZone tz = getTimeZoneForAccount(_accountId);
|
||||
Date start = DateUtils.getMidnightBefore(_start, tz);
|
||||
Date monthStart = DateUtils.getStartOfMonth(_start, tz);
|
||||
BreakerGroup root = CollectionUtils.getFirst(config.getBreakerGroups());
|
||||
if (root == null)
|
||||
return;
|
||||
proxy.delete(BreakerGroupSummary.class, new DaoQuery("_id", BreakerGroupEnergy.toId(_accountId, root.getId(), EnergyBlockViewMode.MONTH, monthStart)));
|
||||
Set<Date> dates = new HashSet<>();
|
||||
while (start.before(_end)) {
|
||||
Date dayEnd = DateUtils.getMidnightAfter(start, tz);
|
||||
DebugTimer timer = new DebugTimer("Time to rebuild one day");
|
||||
DebugTimer t1 = new DebugTimer("Loading hub power for day, account: " + _accountId + " day: " + DateUtils.format("MM/dd/yyyy", tz, start));
|
||||
List<HubPowerMinute> minutes = proxy.query(HubPowerMinute.class, new DaoQuery("account_id", _accountId).andBetweenInclusiveExclusive("minute", (int) (start.getTime() / 60000), (int) (dayEnd.getTime() / 60000)));
|
||||
t1.stop();
|
||||
monthStart = DateUtils.getStartOfMonth(start, tz);
|
||||
BreakerGroupSummary month = null;
|
||||
if (monthStart.equals(start))
|
||||
proxy.delete(BreakerGroupSummary.class, new DaoQuery("_id", BreakerGroupEnergy.toId(_accountId, root.getId(), EnergyBlockViewMode.MONTH, monthStart)));
|
||||
else
|
||||
month = proxy.queryOne(BreakerGroupSummary.class, new DaoQuery("_id", BreakerGroupEnergy.toId(_accountId, root.getId(), EnergyBlockViewMode.MONTH, monthStart)));
|
||||
BreakerGroupEnergy energy = new BreakerGroupEnergy(root, minutes, EnergyBlockViewMode.DAY, start, month, config.getBillingRates(), tz);
|
||||
timer.stop();
|
||||
putBreakerGroupEnergy(energy);
|
||||
updateSummaries(root, CollectionUtils.asHashSet(start), tz);
|
||||
DebugTimer timer = new DebugTimer("Time to rebuild one day", logger);
|
||||
DebugTimer t1 = new DebugTimer("Loading hub power for day, account: " + _accountId + " day: " + DateUtils.format("MM/dd/yyyy", tz, start), logger);
|
||||
List<HubPowerMinute> minutes = proxy.query(HubPowerMinute.class, new DaoQuery("account_id", _accountId).andBetweenInclusiveExclusive("minute", (int) (start.getTime() / 60000), (int) (dayEnd.getTime() / 60000)));
|
||||
t1.stop();
|
||||
if (!minutes.isEmpty()) {
|
||||
DebugTimer t2 = new DebugTimer("In memory rebuild", logger);
|
||||
EnergySummary energy = new EnergySummary(root, minutes, EnergyViewMode.DAY, start, tz);
|
||||
t2.stop();
|
||||
timer.stop();
|
||||
putEnergySummary(energy);
|
||||
DebugTimer t3 = new DebugTimer("Updating charges", logger);
|
||||
updateChargeSummary(config, energy, tz);
|
||||
t3.stop();
|
||||
}
|
||||
dates.add(start);
|
||||
start = DateUtils.addDays(start, 1, tz);
|
||||
}
|
||||
DebugTimer t4 = new DebugTimer("Updating month/year/lifetime energy summaries", logger);
|
||||
updateEnergySummaries(root, dates, tz);
|
||||
t4.stop();
|
||||
DebugTimer t5 = new DebugTimer("Updating month/year/lifetime charge summaries", logger);
|
||||
updateChargeSummaries(config, dates, tz);
|
||||
t5.stop();
|
||||
}
|
||||
|
||||
public void rebuildChargeSummaries(BreakerConfig _config, BillingPlan _plan) {
|
||||
TimeZone tz = getTimeZoneForAccount(_config.getAccountId());
|
||||
HubPowerMinute firstMinute = proxy.queryOne(HubPowerMinute.class, new DaoQuery("account_id", _config.getAccountId()), DaoSort.sort("minute"));
|
||||
if (firstMinute == null)
|
||||
return;
|
||||
Date start = DateUtils.getMidnightBefore(firstMinute.getMinuteAsDate(), tz);
|
||||
Date end = DateUtils.getMidnightAfter(new Date(), tz);
|
||||
BreakerGroup root = CollectionUtils.getFirst(_config.getBreakerGroups());
|
||||
if (root == null)
|
||||
return;
|
||||
Set<Date> dates = new HashSet<>();
|
||||
Date curDate = start;
|
||||
while (curDate.before(end)) {
|
||||
dates.add(curDate);
|
||||
curDate = DateUtils.addDays(curDate, 1, tz);
|
||||
}
|
||||
List<String> summaryIds = CollectionUtils.transform(dates, _dt->EnergySummary.toId(_config.getAccountId(), root.getId(), EnergyViewMode.DAY, _dt));
|
||||
DebugTimer t1 = new DebugTimer("Load Daily Energy Totals", logger);
|
||||
Map<Date, EnergyTotal> totals = CollectionUtils.transformToMap(proxy.query(EnergyTotal.class, DaoQuery.in("_id", summaryIds)), EnergyTotal::getStart);
|
||||
t1.stop();
|
||||
Map<String, Integer> breakerGroupMeters = _config.getRootGroup().mapToMeters();
|
||||
List<ChargeSummary> chargeSummaries = new ArrayList<>();
|
||||
DebugTimer t2 = new DebugTimer("Load Energy Summaries", logger);
|
||||
List<EnergySummary> energySummaries = proxy.query(EnergySummary.class, DaoQuery.in("_id", summaryIds));
|
||||
t2.stop();
|
||||
DebugTimer t3 = new DebugTimer("Rebuild Charges Summaries", logger);
|
||||
for (EnergySummary energy : energySummaries) {
|
||||
Date cycleStart = _plan.getBillingCycleStart(energy.getStart(), tz);
|
||||
double monthKwh = 0.0;
|
||||
while (cycleStart.before(energy.getStart())) {
|
||||
EnergyTotal total = totals.get(cycleStart);
|
||||
if (total != null)
|
||||
monthKwh += total.totalJoules();
|
||||
cycleStart = DateUtils.addDays(cycleStart, 1, tz);
|
||||
}
|
||||
monthKwh /= 3600000.0;
|
||||
chargeSummaries.add(energy.toChargeSummary(_plan.getPlanId(), _plan.getRates(), breakerGroupMeters, new MutableDouble(monthKwh)));
|
||||
}
|
||||
t3.stop();
|
||||
DebugTimer t4 = new DebugTimer("Persist Charge Summaries", logger);
|
||||
putChargeSummaries(chargeSummaries);
|
||||
t4.stop();
|
||||
DebugTimer t5 = new DebugTimer("Updating month/year/lifetime charge summaries", logger);
|
||||
updateChargeSummaries(_config, dates, tz);
|
||||
t5.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putBreakerGroupEnergy(BreakerGroupEnergy _energy) {
|
||||
public void putEnergySummary(EnergySummary _energy) {
|
||||
proxy.save(_energy);
|
||||
proxy.save(new BreakerGroupSummary(_energy));
|
||||
proxy.save(new EnergyTotal(_energy));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -250,6 +397,8 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
public BreakerConfig getMergedConfig(AuthCode _authCode) {
|
||||
if (_authCode == null)
|
||||
return null;
|
||||
if (CollectionUtils.size(_authCode.getAllAccountIds()) == 1)
|
||||
return getConfig(_authCode.getAccountId());
|
||||
List<BreakerConfig> configs = CollectionUtils.transform(_authCode.getAllAccountIds(), this::getConfig, true);
|
||||
BreakerConfig config = new BreakerConfig();
|
||||
config.setAccountId(_authCode.getAccountId());
|
||||
|
@ -257,6 +406,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
config.setBreakerGroups(CollectionUtils.aggregate(configs, BreakerConfig::getBreakerGroups));
|
||||
config.setPanels(CollectionUtils.aggregate(configs, BreakerConfig::getPanels));
|
||||
config.setMeters(CollectionUtils.aggregate(configs, BreakerConfig::getMeters));
|
||||
config.setBillingPlans(CollectionUtils.aggregate(configs, BreakerConfig::getBillingPlans));
|
||||
config.setBillingRates(CollectionUtils.aggregate(configs, BreakerConfig::getBillingRates));
|
||||
return config;
|
||||
}
|
||||
|
@ -274,10 +424,12 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
oldEntity.put("archive_date", DaoSerializer.toLong(new Date()));
|
||||
proxy.saveEntity("config_archive", oldEntity);
|
||||
executor.submit(() -> {
|
||||
List<BillingRate> changedRates = new ArrayList<>(_config.getBillingRates());
|
||||
changedRates.removeAll(CollectionUtils.makeNotNull(oldConfig.getBillingRates()));
|
||||
if (!changedRates.isEmpty())
|
||||
rebuildSummaries(_config.getAccountId(), changedRates);
|
||||
Map<Integer, BillingPlan> oldPlans = CollectionUtils.transformToMap(oldConfig.getBillingPlans(), BillingPlan::getPlanId);
|
||||
for (BillingPlan plan : CollectionUtils.makeNotNull(_config.getBillingPlans())) {
|
||||
BillingPlan oldPlan = oldPlans.get(plan.getPlanId());
|
||||
if ((oldPlan == null) || !oldPlan.isIdentical(plan))
|
||||
rebuildChargeSummaries(_config, plan);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -336,8 +488,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
_account.setPassword(account.getPassword());
|
||||
else
|
||||
_account.setPassword(BCrypt.hashpw(_account.getPassword(), BCrypt.gensalt(BCRYPT_ROUNDS)));
|
||||
}
|
||||
else if (NullUtils.isNotEmpty(_account.getPassword())) {
|
||||
} else if (NullUtils.isNotEmpty(_account.getPassword())) {
|
||||
_account.setPassword(BCrypt.hashpw(_account.getPassword(), BCrypt.gensalt(BCRYPT_ROUNDS)));
|
||||
}
|
||||
if (_account.getId() == 0)
|
||||
|
@ -363,8 +514,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
try {
|
||||
if (NullUtils.isNotEmpty(timezone))
|
||||
tz = TimeZone.getTimeZone(timezone);
|
||||
}
|
||||
catch (Exception _e) {
|
||||
} catch (Exception _e) {
|
||||
logger.error("TimeZone not configured correctly for account {}", _accountId);
|
||||
}
|
||||
return tz == null ? TimeZone.getTimeZone("America/Chicago") : tz;
|
||||
|
|
|
@ -23,4 +23,14 @@ public enum BillingCurrency {
|
|||
return "-" + symbol + _value.abs().setScale(2, RoundingMode.HALF_EVEN);
|
||||
return symbol + _value.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
public String formatValue(double _value) {
|
||||
return formatValue(BigDecimal.valueOf(_value));
|
||||
}
|
||||
|
||||
public String formatValue(BigDecimal _value) {
|
||||
if (_value.compareTo(BigDecimal.ZERO) < 0)
|
||||
return "-" + _value.abs().setScale(2, RoundingMode.HALF_EVEN);
|
||||
return _value.setScale(2, RoundingMode.HALF_EVEN).toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.DateUtils;
|
||||
import com.lanternsoftware.util.IIdentical;
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@DBSerializable
|
||||
public class BillingPlan implements IIdentical<BillingPlan> {
|
||||
private int accountId;
|
||||
private int planId;
|
||||
private int billingDay;
|
||||
private String name;
|
||||
private List<BillingRate> rates;
|
||||
|
||||
public int getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(int _accountId) {
|
||||
accountId = _accountId;
|
||||
}
|
||||
|
||||
public int getPlanId() {
|
||||
return planId;
|
||||
}
|
||||
|
||||
public void setPlanId(int _planId) {
|
||||
planId = _planId;
|
||||
}
|
||||
|
||||
public int getBillingDay() {
|
||||
return billingDay;
|
||||
}
|
||||
|
||||
public void setBillingDay(int _billingDay) {
|
||||
billingDay = _billingDay;
|
||||
}
|
||||
|
||||
public Date getBillingCycleStart(Date _for, TimeZone _tz) {
|
||||
Calendar cal = DateUtils.getStartOfMonthCal(_for, _tz);
|
||||
if (billingDay < 100) {
|
||||
cal.set(Calendar.DAY_OF_MONTH, (billingDay == 0) ? 1 : billingDay);
|
||||
if (cal.getTime().after(_for))
|
||||
cal.add(Calendar.MONTH, -1);
|
||||
return cal.getTime();
|
||||
}
|
||||
int dayOfWeek = (billingDay-101)%7 + 1;
|
||||
int weekOfMonth = (billingDay-101)/7;
|
||||
int dayOfMonthOffset = dayOfWeek-cal.get(Calendar.DAY_OF_WEEK);
|
||||
if (dayOfMonthOffset < 0)
|
||||
dayOfMonthOffset += 7;
|
||||
cal.set(Calendar.DAY_OF_MONTH, dayOfMonthOffset+(7*weekOfMonth)+1);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public Date getBillingCycleEnd(Date _for, TimeZone _tz) {
|
||||
return getBillingCycleStart(DateUtils.addMonths(_for, 1, _tz), _tz);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String _name) {
|
||||
name = _name;
|
||||
}
|
||||
|
||||
public List<BillingRate> getRates() {
|
||||
return rates;
|
||||
}
|
||||
|
||||
public void setRates(List<BillingRate> _rates) {
|
||||
rates = _rates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentical(BillingPlan _other) {
|
||||
return accountId == _other.accountId && planId == _other.planId && billingDay == _other.billingDay && CollectionUtils.isEqual(rates, _other.rates);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package com.lanternsoftware.datamodel.currentmonitor;
|
|||
import com.lanternsoftware.util.DateUtils;
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.TimeZone;
|
||||
|
@ -11,7 +10,6 @@ import java.util.TimeZone;
|
|||
@DBSerializable
|
||||
public class BillingRate {
|
||||
private int meter;
|
||||
private int dayBillingCycleStart;
|
||||
private GridFlow flow;
|
||||
private double rate;
|
||||
private BillingCurrency currency;
|
||||
|
@ -31,14 +29,6 @@ public class BillingRate {
|
|||
meter = _meter;
|
||||
}
|
||||
|
||||
public int getDayBillingCycleStart() {
|
||||
return dayBillingCycleStart;
|
||||
}
|
||||
|
||||
public void setDayBillingCycleStart(int _dayBillingCycleStart) {
|
||||
dayBillingCycleStart = _dayBillingCycleStart;
|
||||
}
|
||||
|
||||
public GridFlow getFlow() {
|
||||
return flow;
|
||||
}
|
||||
|
@ -119,7 +109,7 @@ public class BillingRate {
|
|||
recursAnnually = _recursAnnually;
|
||||
}
|
||||
|
||||
public boolean isApplicable(GridFlow _mode, int _meter, double _monthKWh, Date _time, TimeZone _tz) {
|
||||
public boolean isApplicable(GridFlow _mode, int _meter, double _monthKWh, int _secondsIntoDay) {
|
||||
if ((flow != GridFlow.BOTH) && (flow != _mode))
|
||||
return false;
|
||||
if ((meter != -1) && (_meter != meter))
|
||||
|
@ -128,6 +118,14 @@ public class BillingRate {
|
|||
return false;
|
||||
if ((monthKWhEnd > 0) && (_monthKWh >= monthKWhEnd))
|
||||
return false;
|
||||
if ((timeOfDayStart == 0) && (timeOfDayEnd == 0))
|
||||
return true;
|
||||
if ((timeOfDayStart > 0) && (_secondsIntoDay < timeOfDayStart))
|
||||
return false;
|
||||
return (timeOfDayEnd == 0) || (_secondsIntoDay < timeOfDayEnd);
|
||||
}
|
||||
|
||||
public boolean isApplicableForDay(Date _time, TimeZone _tz) {
|
||||
if ((beginEffective != null) && (endEffective != null) && recursAnnually) {
|
||||
Date begin = beginEffective;
|
||||
Date end = endEffective;
|
||||
|
@ -148,13 +146,7 @@ public class BillingRate {
|
|||
if ((endEffective != null) && endEffective.before(_time))
|
||||
return false;
|
||||
}
|
||||
if ((timeOfDayStart == 0) && (timeOfDayEnd == 0))
|
||||
return true;
|
||||
Calendar midnight = DateUtils.getMidnightBeforeCal(_time, _tz);
|
||||
int timeOfDay = (int)((_time.getTime() - midnight.getTimeInMillis()) / 1000);
|
||||
if ((timeOfDayStart > 0) && (timeOfDay < timeOfDayStart))
|
||||
return false;
|
||||
return (timeOfDayEnd == 0) || (timeOfDay < timeOfDayEnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
public double apply(double _kWh) {
|
||||
|
@ -166,18 +158,17 @@ public class BillingRate {
|
|||
if (this == _o) return true;
|
||||
if (_o == null || getClass() != _o.getClass()) return false;
|
||||
BillingRate that = (BillingRate) _o;
|
||||
return meter == that.meter && dayBillingCycleStart == that.dayBillingCycleStart && Double.compare(that.rate, rate) == 0 && timeOfDayStart == that.timeOfDayStart && timeOfDayEnd == that.timeOfDayEnd && Double.compare(that.monthKWhStart, monthKWhStart) == 0 && Double.compare(that.monthKWhEnd, monthKWhEnd) == 0 && recursAnnually == that.recursAnnually && flow == that.flow && currency == that.currency && Objects.equals(beginEffective, that.beginEffective) && Objects.equals(endEffective, that.endEffective);
|
||||
return meter == that.meter && Double.compare(that.rate, rate) == 0 && timeOfDayStart == that.timeOfDayStart && timeOfDayEnd == that.timeOfDayEnd && Double.compare(that.monthKWhStart, monthKWhStart) == 0 && Double.compare(that.monthKWhEnd, monthKWhEnd) == 0 && recursAnnually == that.recursAnnually && flow == that.flow && currency == that.currency && Objects.equals(beginEffective, that.beginEffective) && Objects.equals(endEffective, that.endEffective);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(meter, dayBillingCycleStart, flow, rate, currency, timeOfDayStart, timeOfDayEnd, monthKWhStart, monthKWhEnd, beginEffective, endEffective, recursAnnually);
|
||||
return Objects.hash(meter, flow, rate, currency, timeOfDayStart, timeOfDayEnd, monthKWhStart, monthKWhEnd, beginEffective, endEffective, recursAnnually);
|
||||
}
|
||||
|
||||
public BillingRate duplicate() {
|
||||
BillingRate r = new BillingRate();
|
||||
r.setMeter(meter);
|
||||
r.setDayBillingCycleStart(dayBillingCycleStart);
|
||||
r.setFlow(flow);
|
||||
r.setRate(rate);
|
||||
r.setCurrency(currency);
|
||||
|
|
|
@ -20,6 +20,7 @@ public class BreakerConfig implements IIdentical<BreakerConfig> {
|
|||
private List<BreakerHub> breakerHubs;
|
||||
private List<BreakerGroup> breakerGroups;
|
||||
private List<BillingRate> billingRates;
|
||||
private List<BillingPlan> billingPlans;
|
||||
private int version;
|
||||
|
||||
public BreakerConfig() {
|
||||
|
@ -69,6 +70,14 @@ public class BreakerConfig implements IIdentical<BreakerConfig> {
|
|||
breakerGroups = _breakerGroups;
|
||||
}
|
||||
|
||||
public List<BillingPlan> getBillingPlans() {
|
||||
return billingPlans;
|
||||
}
|
||||
|
||||
public void setBillingPlans(List<BillingPlan> _billingPlans) {
|
||||
billingPlans = _billingPlans;
|
||||
}
|
||||
|
||||
public List<BillingRate> getBillingRates() {
|
||||
return billingRates;
|
||||
}
|
||||
|
@ -85,6 +94,10 @@ public class BreakerConfig implements IIdentical<BreakerConfig> {
|
|||
version = _version;
|
||||
}
|
||||
|
||||
public BreakerGroup getRootGroup() {
|
||||
return CollectionUtils.getFirst(breakerGroups);
|
||||
}
|
||||
|
||||
public List<Breaker> getAllBreakers() {
|
||||
List<Breaker> allBreakers = new ArrayList<>();
|
||||
for (BreakerGroup g : CollectionUtils.makeNotNull(breakerGroups)) {
|
||||
|
@ -190,13 +203,13 @@ public class BreakerConfig implements IIdentical<BreakerConfig> {
|
|||
if (this == _o) return true;
|
||||
if (_o == null || getClass() != _o.getClass()) return false;
|
||||
BreakerConfig that = (BreakerConfig) _o;
|
||||
return accountId == that.accountId && CollectionUtils.isEqual(meters, that.meters) && CollectionUtils.isEqual(panels, that.panels) && CollectionUtils.isEqual(breakerHubs, that.breakerHubs) && CollectionUtils.isEqual(breakerGroups, that.breakerGroups) && CollectionUtils.isEqual(billingRates, that.billingRates);
|
||||
return accountId == that.accountId && CollectionUtils.isEqual(meters, that.meters) && CollectionUtils.isEqual(panels, that.panels) && CollectionUtils.isEqual(breakerHubs, that.breakerHubs) && CollectionUtils.isEqual(breakerGroups, that.breakerGroups) && CollectionUtils.isEqual(billingPlans, that.billingPlans);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentical(BreakerConfig _o) {
|
||||
if (this == _o) return true;
|
||||
return accountId == _o.accountId && CollectionUtils.isIdentical(meters, _o.meters) && CollectionUtils.isIdentical(panels, _o.panels) && CollectionUtils.isIdentical(breakerHubs, _o.breakerHubs) && CollectionUtils.isIdentical(breakerGroups, _o.breakerGroups) && CollectionUtils.isEqual(billingRates, _o.billingRates);
|
||||
return accountId == _o.accountId && CollectionUtils.isIdentical(meters, _o.meters) && CollectionUtils.isIdentical(panels, _o.panels) && CollectionUtils.isIdentical(breakerHubs, _o.breakerHubs) && CollectionUtils.isIdentical(breakerGroups, _o.breakerGroups) && CollectionUtils.isEqual(billingPlans, _o.billingPlans);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,7 +8,9 @@ import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
|||
import com.lanternsoftware.util.dao.annotations.PrimaryKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -170,6 +172,16 @@ public class BreakerGroup implements IIdentical<BreakerGroup> {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Map<String, Integer> mapToMeters() {
|
||||
Map<String, Integer> groups = new HashMap<>();
|
||||
for (BreakerGroup group : getAllBreakerGroups()) {
|
||||
Breaker b = CollectionUtils.getFirst(group.getBreakers());
|
||||
if (b != null)
|
||||
groups.put(group.getId(), b.getMeter());
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
public boolean removeInvalidGroups(Set<Integer> _validPanels) {
|
||||
if (subGroups != null)
|
||||
subGroups.removeIf(_g->!_g.removeInvalidGroups(_validPanels));
|
||||
|
|
|
@ -2,524 +2,220 @@ package com.lanternsoftware.datamodel.currentmonitor;
|
|||
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
import com.lanternsoftware.util.mutable.MutableDouble;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@DBSerializable(autogen = false)
|
||||
public class BreakerGroupEnergy {
|
||||
private int accountId;
|
||||
private String groupId;
|
||||
private String groupName;
|
||||
private EnergyBlockViewMode viewMode;
|
||||
private Date start;
|
||||
private List<BreakerGroupEnergy> subGroups;
|
||||
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;
|
||||
private int accountId;
|
||||
private String groupId;
|
||||
private String groupName;
|
||||
private EnergyViewMode viewMode;
|
||||
private Date start;
|
||||
private List<BreakerGroupEnergy> subGroups;
|
||||
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() {
|
||||
}
|
||||
public BreakerGroupEnergy() {
|
||||
}
|
||||
|
||||
public BreakerGroupEnergy(BreakerGroup _group, List<HubPowerMinute> _power, EnergyBlockViewMode _viewMode, Date _start, BreakerGroupSummary _month, List<BillingRate> _rates, TimeZone _timezone) {
|
||||
groupId = _group.getId();
|
||||
groupName = _group.getName();
|
||||
viewMode = _viewMode;
|
||||
start = _start;
|
||||
accountId = _group.getAccountId();
|
||||
timezone = _timezone;
|
||||
subGroups = CollectionUtils.transform(_group.getSubGroups(), _g -> new BreakerGroupEnergy(_g, null, _viewMode, _start, _month, _rates, timezone));
|
||||
addEnergy(_group, _power, _month, _rates);
|
||||
}
|
||||
public BreakerGroupEnergy(EnergySummary _summary, List<BillingRate> _rates, Map<String, Integer> _breakerGroupMeters) {
|
||||
groupId = _summary.getGroupId();
|
||||
groupName = _summary.getGroupName();
|
||||
viewMode = _summary.getViewMode();
|
||||
start = _summary.getStart();
|
||||
accountId = _summary.getAccountId();
|
||||
timezone = _summary.getTimeZone();
|
||||
peakToGrid = _summary.getPeakToGrid();
|
||||
peakFromGrid = _summary.getPeakFromGrid();
|
||||
peakConsumption = _summary.getPeakConsumption();
|
||||
peakProduction = _summary.getPeakProduction();
|
||||
Date readTime = start;
|
||||
if (_summary.getEnergy() != null) {
|
||||
for (float joules : _summary.getEnergy()) {
|
||||
addEnergy(readTime, joules);
|
||||
readTime = viewMode.incrementBlock(readTime, timezone);
|
||||
}
|
||||
}
|
||||
readTime = start;
|
||||
ChargeSummary charges = _summary.toChargeSummary(0, _rates, _breakerGroupMeters, new MutableDouble(0.0));
|
||||
for (double charge : charges.chargeBlocks(CollectionUtils.asHashSet(groupId), GridFlow.BOTH)) {
|
||||
addCharge(readTime, charge);
|
||||
readTime = viewMode.incrementBlock(readTime, timezone);
|
||||
}
|
||||
subGroups = CollectionUtils.transform(_summary.getSubGroups(), _e->new BreakerGroupEnergy(_e, _rates, _breakerGroupMeters));
|
||||
}
|
||||
|
||||
public void addEnergy(BreakerGroup _group, List<HubPowerMinute> _hubPower, BreakerGroupSummary _month, List<BillingRate> _rates) {
|
||||
Map<String, Breaker> breakers = CollectionUtils.transformToMap(_group.getAllBreakers(), Breaker::getKey);
|
||||
Map<String, BreakerGroup> breakerKeyToGroup = new HashMap<>();
|
||||
for (BreakerGroup group : _group.getAllBreakerGroups()) {
|
||||
for (Breaker b : group.getAllBreakers()) {
|
||||
breakerKeyToGroup.put(b.getKey(), group);
|
||||
}
|
||||
}
|
||||
addEnergy(breakers, breakerKeyToGroup, _hubPower, _month, _rates);
|
||||
}
|
||||
private void addEnergy(Date _readTime, double _joules) {
|
||||
EnergyBlock block = getBlock(_readTime);
|
||||
if (block != null)
|
||||
block.addJoules(_joules);
|
||||
}
|
||||
|
||||
public void addEnergy(Map<String, Breaker> _breakers, Map<String, BreakerGroup> _breakerKeyToGroup, List<HubPowerMinute> _hubPower, BreakerGroupSummary _month, List<BillingRate> _rates) {
|
||||
if (CollectionUtils.isEmpty(_hubPower) || CollectionUtils.anyQualify(_hubPower, _p->_p.getAccountId() != accountId))
|
||||
return;
|
||||
_hubPower.sort(Comparator.comparing(HubPowerMinute::getMinute));
|
||||
for (Date minute : CollectionUtils.transformToSet(_hubPower, HubPowerMinute::getMinuteAsDate)) {
|
||||
resetEnergy(minute);
|
||||
}
|
||||
int idx;
|
||||
Map<Integer, Map<Integer, MeterMinute>> minutes = new TreeMap<>();
|
||||
for (HubPowerMinute hubPower : _hubPower) {
|
||||
Date minute = hubPower.getMinuteAsDate();
|
||||
for (BreakerPowerMinute breaker : CollectionUtils.makeNotNull(hubPower.getBreakers())) {
|
||||
Breaker b = _breakers.get(breaker.breakerKey());
|
||||
if (b == null)
|
||||
continue;
|
||||
BreakerGroup group = _breakerKeyToGroup.get(breaker.breakerKey());
|
||||
if (group == null)
|
||||
continue;
|
||||
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) {
|
||||
for (Float power : CollectionUtils.makeNotNull(breaker.getReadings())) {
|
||||
if (idx >= 60)
|
||||
break;
|
||||
if (power > 0)
|
||||
meter.usage[idx] += power;
|
||||
else
|
||||
meter.solar[idx] -= power;
|
||||
block.addJoules(power);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
double monthFromGrid = _month == null ? 0.0 : _month.getFromGrid();
|
||||
double secondFromGrid;
|
||||
for (MeterMinute minute : CollectionUtils.aggregate(minutes.values(), Map::values)) {
|
||||
double monthkWh = monthFromGrid/3600000;
|
||||
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++) {
|
||||
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) {
|
||||
minute.charges[i] += rate.apply(secondFromGrid/3600000);
|
||||
}
|
||||
}
|
||||
else {
|
||||
secondFromGrid = -secondFromGrid;
|
||||
toGrid += secondFromGrid;
|
||||
if (secondFromGrid > peakToGrid)
|
||||
peakToGrid = secondFromGrid;
|
||||
for (BillingRate rate : productionRates) {
|
||||
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())) {
|
||||
Breaker b = _breakers.get(breaker.breakerKey());
|
||||
if (b == null)
|
||||
continue;
|
||||
BreakerGroup group = _breakerKeyToGroup.get(breaker.breakerKey());
|
||||
if (group == null)
|
||||
continue;
|
||||
MeterMinute meter = minutes.get(hubPower.getMinute()).get(b.getMeter());
|
||||
idx = 0;
|
||||
double charge = 0.0;
|
||||
for (Float power : CollectionUtils.makeNotNull(breaker.getReadings())) {
|
||||
if (b.getPolarity() == BreakerPolarity.SOLAR) {
|
||||
if (meter.charges[idx] < 0.0)
|
||||
charge -= meter.charges[idx] * (power/meter.solar[idx]);
|
||||
}
|
||||
else if (meter.charges[idx] > 0.0)
|
||||
charge += meter.charges[idx] * (power/meter.usage[idx]);
|
||||
idx++;
|
||||
}
|
||||
addCharge(group.getId(), minute, charge);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void addCharge(Date _readTime, double _charge) {
|
||||
EnergyBlock block = getBlock(_readTime);
|
||||
if (block != null)
|
||||
block.addCharge(_charge);
|
||||
}
|
||||
|
||||
public void resetEnergy(Date _readTime) {
|
||||
EnergyBlock block = getBlock(_readTime, false);
|
||||
if (block != null)
|
||||
block.setJoules(0);
|
||||
for (BreakerGroupEnergy subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||
subGroup.resetEnergy(_readTime);
|
||||
}
|
||||
}
|
||||
private EnergyBlock getBlock(Date _readTime) {
|
||||
int size = CollectionUtils.size(energyBlocks);
|
||||
int idx = viewMode.blockIndex(start, _readTime, timezone);
|
||||
if (idx >= size) {
|
||||
if (energyBlocks == null)
|
||||
energyBlocks = new ArrayList<>(viewMode.initBlockCount());
|
||||
LinkedList<EnergyBlock> newBlocks = new LinkedList<>();
|
||||
Date end = viewMode.toBlockEnd(_readTime, timezone);
|
||||
while (idx >= size) {
|
||||
Date start = viewMode.decrementBlock(end, timezone);
|
||||
newBlocks.add(new EnergyBlock(start, end, 0));
|
||||
end = start;
|
||||
size++;
|
||||
}
|
||||
Iterator<EnergyBlock> iter = newBlocks.descendingIterator();
|
||||
while (iter.hasNext()) {
|
||||
energyBlocks.add(iter.next());
|
||||
}
|
||||
}
|
||||
return CollectionUtils.get(energyBlocks, idx);
|
||||
}
|
||||
|
||||
private EnergyBlock getBlock(String _groupId, Date _readTime) {
|
||||
if (NullUtils.isEqual(groupId, _groupId))
|
||||
return getBlock(_readTime);
|
||||
else {
|
||||
for (BreakerGroupEnergy subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||
EnergyBlock block = subGroup.getBlock(_groupId, _readTime);
|
||||
if (block != null)
|
||||
return block;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public String getId() {
|
||||
return toId(accountId, groupId, viewMode, start);
|
||||
}
|
||||
|
||||
private void addEnergy(String _groupId, Date _readTime, double _joules) {
|
||||
EnergyBlock block = getBlock(_groupId, _readTime);
|
||||
if (block != null)
|
||||
block.addJoules(_joules);
|
||||
}
|
||||
public static String toId(int _accountId, String _groupId, EnergyViewMode _viewMode, Date _start) {
|
||||
return _accountId + "-" + _groupId + "-" + DaoSerializer.toEnumName(_viewMode) + "-" + _start.getTime();
|
||||
}
|
||||
|
||||
private void addCharge(String _groupId, Date _readTime, double _charge) {
|
||||
EnergyBlock block = getBlock(_groupId, _readTime);
|
||||
if (block != null)
|
||||
block.addCharge(_charge);
|
||||
}
|
||||
public int getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public static BreakerGroupEnergy summary(BreakerGroup _group, Map<String, List<BreakerGroupSummary>> _energies, EnergyBlockViewMode _viewMode, Date _start, TimeZone _tz) {
|
||||
BreakerGroupEnergy energy = new BreakerGroupEnergy();
|
||||
energy.setGroupId(_group.getId());
|
||||
energy.setGroupName(_group.getName());
|
||||
energy.setAccountId(_group.getAccountId());
|
||||
energy.setViewMode(_viewMode);
|
||||
energy.setStart(_start);
|
||||
energy.setTimeZone(_tz);
|
||||
energy.setSubGroups(CollectionUtils.transform(_group.getSubGroups(), _g -> BreakerGroupEnergy.summary(_g, _energies, _viewMode, _start, _tz)));
|
||||
for (BreakerGroupSummary curEnergy : CollectionUtils.makeNotNull(_energies.get(_group.getId()))) {
|
||||
EnergyBlock block = energy.getBlock(curEnergy.getStart());
|
||||
block.addJoules(curEnergy.getJoules());
|
||||
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;
|
||||
}
|
||||
public void setAccountId(int _accountId) {
|
||||
accountId = _accountId;
|
||||
}
|
||||
|
||||
private EnergyBlock getBlock(Date _readTime) {
|
||||
return getBlock(_readTime, true);
|
||||
}
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
private EnergyBlock getBlock(Date _readTime, boolean _add) {
|
||||
int size = CollectionUtils.size(energyBlocks);
|
||||
int idx = viewMode.blockIndex(start, _readTime, timezone);
|
||||
if (_add && (idx >= size)) {
|
||||
if (energyBlocks == null)
|
||||
energyBlocks = new ArrayList<>(viewMode.initBlockCount());
|
||||
LinkedList<EnergyBlock> newBlocks = new LinkedList<>();
|
||||
Date end = viewMode.toBlockEnd(_readTime, timezone);
|
||||
while (idx >= size) {
|
||||
Date start = viewMode.decrementBlock(end, timezone);
|
||||
newBlocks.add(new EnergyBlock(start, end, 0));
|
||||
end = start;
|
||||
size++;
|
||||
}
|
||||
Iterator<EnergyBlock> iter = newBlocks.descendingIterator();
|
||||
while (iter.hasNext()) {
|
||||
energyBlocks.add(iter.next());
|
||||
}
|
||||
}
|
||||
return CollectionUtils.get(energyBlocks, idx);
|
||||
}
|
||||
public void setGroupId(String _groupId) {
|
||||
groupId = _groupId;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return toId(accountId, groupId, viewMode, start);
|
||||
}
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public static String toId(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start) {
|
||||
return _accountId + "-" + _groupId + "-" + DaoSerializer.toEnumName(_viewMode) + "-" + _start.getTime();
|
||||
}
|
||||
public void setGroupName(String _groupName) {
|
||||
groupName = _groupName;
|
||||
}
|
||||
|
||||
public int getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
public BreakerGroupEnergy getSubGroup(String _groupId) {
|
||||
return CollectionUtils.filterOne(subGroups, _g -> _groupId.equals(_g.getGroupId()));
|
||||
}
|
||||
|
||||
public void setAccountId(int _accountId) {
|
||||
accountId = _accountId;
|
||||
}
|
||||
public List<BreakerGroupEnergy> getSubGroups() {
|
||||
return subGroups;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
public EnergyViewMode getViewMode() {
|
||||
return viewMode;
|
||||
}
|
||||
|
||||
public void setGroupId(String _groupId) {
|
||||
groupId = _groupId;
|
||||
}
|
||||
public void setViewMode(EnergyViewMode _viewMode) {
|
||||
viewMode = _viewMode;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
public Date getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setGroupName(String _groupName) {
|
||||
groupName = _groupName;
|
||||
}
|
||||
public void setStart(Date _start) {
|
||||
start = _start;
|
||||
}
|
||||
|
||||
public BreakerGroupEnergy getSubGroup(String _groupId) {
|
||||
return CollectionUtils.filterOne(subGroups, _g->_groupId.equals(_g.getGroupId()));
|
||||
}
|
||||
public void setSubGroups(List<BreakerGroupEnergy> _subGroups) {
|
||||
subGroups = _subGroups;
|
||||
}
|
||||
|
||||
public List<BreakerGroupEnergy> getSubGroups() {
|
||||
return subGroups;
|
||||
}
|
||||
public List<EnergyBlock> getEnergyBlocks() {
|
||||
return energyBlocks;
|
||||
}
|
||||
|
||||
public EnergyBlockViewMode getViewMode() {
|
||||
return viewMode;
|
||||
}
|
||||
public void setEnergyBlocks(List<EnergyBlock> _energyBlocks) {
|
||||
energyBlocks = _energyBlocks;
|
||||
}
|
||||
|
||||
public void setViewMode(EnergyBlockViewMode _viewMode) {
|
||||
viewMode = _viewMode;
|
||||
}
|
||||
public double getToGrid() {
|
||||
return toGrid;
|
||||
}
|
||||
|
||||
public Date getStart() {
|
||||
return start;
|
||||
}
|
||||
public void setToGrid(double _toGrid) {
|
||||
toGrid = _toGrid;
|
||||
}
|
||||
|
||||
public void setStart(Date _start) {
|
||||
start = _start;
|
||||
}
|
||||
public double getFromGrid() {
|
||||
return fromGrid;
|
||||
}
|
||||
|
||||
public void setSubGroups(List<BreakerGroupEnergy> _subGroups) {
|
||||
subGroups = _subGroups;
|
||||
}
|
||||
public void setFromGrid(double _fromGrid) {
|
||||
fromGrid = _fromGrid;
|
||||
}
|
||||
|
||||
public List<EnergyBlock> getEnergyBlocks() {
|
||||
return energyBlocks;
|
||||
}
|
||||
public double getPeakToGrid() {
|
||||
return peakToGrid;
|
||||
}
|
||||
|
||||
public void setEnergyBlocks(List<EnergyBlock> _energyBlocks) {
|
||||
energyBlocks = _energyBlocks;
|
||||
}
|
||||
public void setPeakToGrid(double _peakToGrid) {
|
||||
peakToGrid = _peakToGrid;
|
||||
}
|
||||
|
||||
public double getToGrid() {
|
||||
return toGrid;
|
||||
}
|
||||
public double getPeakFromGrid() {
|
||||
return peakFromGrid;
|
||||
}
|
||||
|
||||
public void setToGrid(double _toGrid) {
|
||||
toGrid = _toGrid;
|
||||
}
|
||||
public void setPeakFromGrid(double _peakFromGrid) {
|
||||
peakFromGrid = _peakFromGrid;
|
||||
}
|
||||
|
||||
public double getFromGrid() {
|
||||
return fromGrid;
|
||||
}
|
||||
public double getPeakConsumption() {
|
||||
return peakConsumption;
|
||||
}
|
||||
|
||||
public void setFromGrid(double _fromGrid) {
|
||||
fromGrid = _fromGrid;
|
||||
}
|
||||
public void setPeakConsumption(double _peakConsumption) {
|
||||
peakConsumption = _peakConsumption;
|
||||
}
|
||||
|
||||
public double getPeakToGrid() {
|
||||
return peakToGrid;
|
||||
}
|
||||
public double getPeakProduction() {
|
||||
return peakProduction;
|
||||
}
|
||||
|
||||
public void setPeakToGrid(double _peakToGrid) {
|
||||
peakToGrid = _peakToGrid;
|
||||
}
|
||||
public void setPeakProduction(double _peakProduction) {
|
||||
peakProduction = _peakProduction;
|
||||
}
|
||||
|
||||
public double getPeakFromGrid() {
|
||||
return peakFromGrid;
|
||||
}
|
||||
public TimeZone getTimeZone() {
|
||||
return timezone;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void setTimeZone(TimeZone _timezone) {
|
||||
timezone = _timezone;
|
||||
}
|
||||
|
||||
public double wattHours() {
|
||||
return joules() / 3600;
|
||||
}
|
||||
|
||||
public double wattHours(Set<String> _selectedBreakers) {
|
||||
return joules(_selectedBreakers) / 3600;
|
||||
}
|
||||
|
||||
public double joules() {
|
||||
return joules(null);
|
||||
}
|
||||
|
||||
public double joules(Set<String> _selectedBreakers) {
|
||||
return joules(_selectedBreakers, true);
|
||||
}
|
||||
|
||||
public double joules(Set<String> _selectedBreakers, boolean _includeSubgroups) {
|
||||
double joules = 0.0;
|
||||
if (_includeSubgroups) {
|
||||
for (BreakerGroupEnergy group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
joules += group.joules(_selectedBreakers);
|
||||
}
|
||||
}
|
||||
if ((energyBlocks != null) && ((_selectedBreakers == null) || _selectedBreakers.contains(getGroupId()))) {
|
||||
for (EnergyBlock energy : energyBlocks) {
|
||||
joules += energy.getJoules();
|
||||
}
|
||||
}
|
||||
return joules;
|
||||
}
|
||||
|
||||
public double charge() {
|
||||
return charge(null);
|
||||
}
|
||||
|
||||
public double charge(Set<String> _selectedBreakers) {
|
||||
return charge(_selectedBreakers, true);
|
||||
}
|
||||
|
||||
public double charge(Set<String> _selectedBreakers, GridFlow _mode) {
|
||||
return charge(_selectedBreakers, true, _mode);
|
||||
}
|
||||
|
||||
public double charge(Set<String> _selectedBreakers, boolean _includeSubgroups) {
|
||||
return charge(_selectedBreakers, _includeSubgroups, null);
|
||||
}
|
||||
|
||||
public double charge(Set<String> _selectedBreakers, boolean _includeSubgroups, GridFlow _mode) {
|
||||
double charge = 0.0;
|
||||
if (_includeSubgroups) {
|
||||
for (BreakerGroupEnergy group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
charge += group.charge(_selectedBreakers, true, _mode);
|
||||
}
|
||||
}
|
||||
if ((energyBlocks != null) && ((_selectedBreakers == null) || _selectedBreakers.contains(getGroupId()))) {
|
||||
for (EnergyBlock energy : energyBlocks) {
|
||||
if ((_mode == null) || ((_mode == GridFlow.TO) && energy.getCharge() < 0.0) || (_mode == GridFlow.FROM && energy.getCharge() > 0.0))
|
||||
charge += energy.getCharge();
|
||||
}
|
||||
}
|
||||
return charge;
|
||||
}
|
||||
|
||||
public List<BreakerGroupEnergy> getAllGroups() {
|
||||
Map<String, BreakerGroupEnergy> groups = new TreeMap<>();
|
||||
getAllGroups(groups);
|
||||
return new ArrayList<>(groups.values());
|
||||
}
|
||||
|
||||
public void getAllGroups(Map<String, BreakerGroupEnergy> _groups) {
|
||||
_groups.put(getGroupId(), this);
|
||||
for (BreakerGroupEnergy group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
group.getAllGroups(_groups);
|
||||
}
|
||||
}
|
||||
|
||||
public List<EnergyBlock> getAllEnergyBlocks() {
|
||||
return getAllEnergyBlocks(null);
|
||||
}
|
||||
|
||||
public List<EnergyBlock> getAllEnergyBlocks(Set<String> _selectedGroups) {
|
||||
return getAllEnergyBlocks(_selectedGroups, EnergyBlockType.ANY);
|
||||
}
|
||||
|
||||
public List<EnergyBlock> getAllEnergyBlocks(Set<String> _selectedGroups, EnergyBlockType _type) {
|
||||
Map<Long, EnergyBlock> blocks = new TreeMap<>();
|
||||
getAllEnergyBlocks(_selectedGroups, blocks, _type);
|
||||
return new ArrayList<>(blocks.values());
|
||||
}
|
||||
|
||||
private void getAllEnergyBlocks(Set<String> _selectedGroups, Map<Long, EnergyBlock> _energyBlocks, EnergyBlockType _type) {
|
||||
if ((energyBlocks != null) && ((_selectedGroups == null) || _selectedGroups.contains(getGroupId()))) {
|
||||
for (EnergyBlock block : energyBlocks) {
|
||||
if ((_type == EnergyBlockType.ANY) || ((_type == EnergyBlockType.POSITIVE) && block.getJoules() >= 0.0) || ((_type == EnergyBlockType.NEGATIVE) && block.getJoules() <= 0.0)) {
|
||||
EnergyBlock b = _energyBlocks.get(block.getStart().getTime());
|
||||
if (b == null) {
|
||||
b = new EnergyBlock(block.getStart(), block.getEnd(), block.getJoules());
|
||||
_energyBlocks.put(block.getStart().getTime(), b);
|
||||
} else
|
||||
b.addJoules(block.getJoules());
|
||||
b.addCharge(block.getCharge());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (BreakerGroupEnergy group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
group.getAllEnergyBlocks(_selectedGroups, _energyBlocks, _type);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MeterMinute {
|
||||
private final int meter;
|
||||
private final Date minute;
|
||||
|
||||
public MeterMinute(int _meter, Date _minute) {
|
||||
meter = _meter;
|
||||
minute = _minute;
|
||||
}
|
||||
|
||||
public int getMeter() {
|
||||
return meter;
|
||||
}
|
||||
|
||||
public Date getMinute() {
|
||||
return minute;
|
||||
}
|
||||
|
||||
public double[] usage = new double[60];
|
||||
public double[] solar = new double[60];
|
||||
public double[] charges = new double[60];
|
||||
}
|
||||
public void setTimeZone(TimeZone _timezone) {
|
||||
timezone = _timezone;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.DateUtils;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@DBSerializable(autogen = false)
|
||||
public class ChargeSummary {
|
||||
private int accountId;
|
||||
private int planId;
|
||||
private String groupId;
|
||||
private String groupName;
|
||||
private EnergyViewMode viewMode;
|
||||
private Date start;
|
||||
private List<ChargeSummary> subGroups;
|
||||
private TimeZone timezone;
|
||||
private double[] charges;
|
||||
private double totalUsageJoules;
|
||||
private double totalSolarJoules;
|
||||
private double fromGridJoules;
|
||||
private double toGridJoules;
|
||||
private double peakToGrid;
|
||||
private double peakFromGrid;
|
||||
private double peakConsumption;
|
||||
private double peakProduction;
|
||||
|
||||
public ChargeSummary() {
|
||||
}
|
||||
|
||||
public ChargeSummary(int _accountId, int _planId, String _groupId, String _groupName, EnergyViewMode _viewMode, Date _start, TimeZone _timezone) {
|
||||
accountId = _accountId;
|
||||
planId = _planId;
|
||||
groupId = _groupId;
|
||||
groupName = _groupName;
|
||||
viewMode = _viewMode;
|
||||
start = _start;
|
||||
timezone = _timezone;
|
||||
}
|
||||
|
||||
public ChargeSummary(BreakerGroup _group, BillingPlan _plan, Map<String, List<ChargeTotal>> _charges, EnergyViewMode _viewMode, Date _start, TimeZone _timezone) {
|
||||
this(_group.getAccountId(), _plan.getPlanId(), _group.getId(), _group.getName(), _viewMode, _start, _timezone);
|
||||
subGroups = CollectionUtils.transform(_group.getSubGroups(), _g -> new ChargeSummary(_g, _plan, _charges, _viewMode, _start, _timezone));
|
||||
if (_viewMode == EnergyViewMode.MONTH) {
|
||||
charges = new double[DateUtils.getDaysBetween(_start, _plan.getBillingCycleEnd(_start, _timezone), _timezone)];
|
||||
}
|
||||
else
|
||||
charges = new double[_viewMode.blockCount(_start, _timezone)];
|
||||
for (ChargeTotal charge : CollectionUtils.makeNotNull(_charges.get(_group.getId()))) {
|
||||
int idx;
|
||||
if (_viewMode == EnergyViewMode.MONTH)
|
||||
idx = DateUtils.getDaysBetween(_start, charge.getStart(), _timezone);
|
||||
else
|
||||
idx = viewMode.blockIndex(start, charge.getStart(), timezone);
|
||||
if (idx < charges.length)
|
||||
charges[idx] += charge.getCharge();
|
||||
}
|
||||
totalUsageJoules = CollectionUtils.sum(CollectionUtils.transform(_charges.get(_group.getId()), ChargeTotal::getTotalUsageJoules));
|
||||
totalSolarJoules = CollectionUtils.sum(CollectionUtils.transform(_charges.get(_group.getId()), ChargeTotal::getTotalSolarJoules));
|
||||
fromGridJoules = CollectionUtils.sum(CollectionUtils.transform(_charges.get(_group.getId()), ChargeTotal::getFromGridJoules));
|
||||
toGridJoules = CollectionUtils.sum(CollectionUtils.transform(_charges.get(_group.getId()), ChargeTotal::getToGridJoules));
|
||||
peakToGrid = DaoSerializer.toDouble(CollectionUtils.getLargest(CollectionUtils.transform(_charges.get(_group.getId()), ChargeTotal::getPeakToGrid)));
|
||||
peakFromGrid = DaoSerializer.toDouble(CollectionUtils.getLargest(CollectionUtils.transform(_charges.get(_group.getId()), ChargeTotal::getPeakFromGrid)));
|
||||
peakConsumption = DaoSerializer.toDouble(CollectionUtils.getLargest(CollectionUtils.transform(_charges.get(_group.getId()), ChargeTotal::getPeakConsumption)));
|
||||
peakProduction = DaoSerializer.toDouble(CollectionUtils.getLargest(CollectionUtils.transform(_charges.get(_group.getId()), ChargeTotal::getPeakProduction)));
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return toId(accountId, planId, groupId, viewMode, start);
|
||||
}
|
||||
|
||||
public int getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(int _accountId) {
|
||||
accountId = _accountId;
|
||||
}
|
||||
|
||||
public int getPlanId() {
|
||||
return planId;
|
||||
}
|
||||
|
||||
public void setPlanId(int _planId) {
|
||||
planId = _planId;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(String _groupId) {
|
||||
groupId = _groupId;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public void setGroupName(String _groupName) {
|
||||
groupName = _groupName;
|
||||
}
|
||||
|
||||
public EnergyViewMode getViewMode() {
|
||||
return viewMode;
|
||||
}
|
||||
|
||||
public void setViewMode(EnergyViewMode _viewMode) {
|
||||
viewMode = _viewMode;
|
||||
}
|
||||
|
||||
public Date getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(Date _start) {
|
||||
start = _start;
|
||||
}
|
||||
|
||||
public List<ChargeSummary> getSubGroups() {
|
||||
return subGroups;
|
||||
}
|
||||
|
||||
public void setSubGroups(List<ChargeSummary> _subGroups) {
|
||||
subGroups = _subGroups;
|
||||
}
|
||||
|
||||
public double[] getCharges() {
|
||||
return charges;
|
||||
}
|
||||
|
||||
public void setCharges(double[] _charges) {
|
||||
charges = _charges;
|
||||
}
|
||||
|
||||
public TimeZone getTimezone() {
|
||||
return timezone;
|
||||
}
|
||||
|
||||
public void setTimezone(TimeZone _timezone) {
|
||||
timezone = _timezone;
|
||||
}
|
||||
|
||||
public double getTotalUsageJoules() {
|
||||
return totalUsageJoules;
|
||||
}
|
||||
|
||||
public void setTotalUsageJoules(double _totalUsageJoules) {
|
||||
totalUsageJoules = _totalUsageJoules;
|
||||
}
|
||||
|
||||
public double getTotalSolarJoules() {
|
||||
return totalSolarJoules;
|
||||
}
|
||||
|
||||
public void setTotalSolarJoules(double _totalSolarJoules) {
|
||||
totalSolarJoules = _totalSolarJoules;
|
||||
}
|
||||
|
||||
public double getFromGridJoules() {
|
||||
return fromGridJoules;
|
||||
}
|
||||
|
||||
public void setFromGridJoules(double _fromGridJoules) {
|
||||
fromGridJoules = _fromGridJoules;
|
||||
}
|
||||
|
||||
public double getToGridJoules() {
|
||||
return toGridJoules;
|
||||
}
|
||||
|
||||
public void setToGridJoules(double _toGridJoules) {
|
||||
toGridJoules = _toGridJoules;
|
||||
}
|
||||
|
||||
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 double charge() {
|
||||
return charge(null);
|
||||
}
|
||||
|
||||
public double charge(Set<String> _selectedBreakers) {
|
||||
return charge(_selectedBreakers, true);
|
||||
}
|
||||
|
||||
public double charge(Set<String> _selectedBreakers, GridFlow _mode) {
|
||||
return charge(_selectedBreakers, true, _mode);
|
||||
}
|
||||
|
||||
public double charge(Set<String> _selectedBreakers, boolean _includeSubgroups) {
|
||||
return charge(_selectedBreakers, _includeSubgroups, null);
|
||||
}
|
||||
|
||||
public double charge(Set<String> _selectedBreakers, boolean _includeSubgroups, GridFlow _mode) {
|
||||
double charge = 0.0;
|
||||
if (_includeSubgroups) {
|
||||
for (ChargeSummary group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
charge += group.charge(_selectedBreakers, true, _mode);
|
||||
}
|
||||
}
|
||||
if ((charges != null) && ((_selectedBreakers == null) || _selectedBreakers.contains(getGroupId()))) {
|
||||
for (double c : charges) {
|
||||
if ((_mode == null) || ((_mode == GridFlow.TO) && c < 0.0) || (_mode == GridFlow.FROM && c > 0.0))
|
||||
charge += c;
|
||||
}
|
||||
}
|
||||
return charge;
|
||||
}
|
||||
|
||||
public float[] chargeBlocks() {
|
||||
return chargeBlocks(null);
|
||||
}
|
||||
|
||||
public float[] chargeBlocks(Set<String> _selectedGroups) {
|
||||
return chargeBlocks(_selectedGroups, GridFlow.BOTH);
|
||||
}
|
||||
|
||||
public float[] chargeBlocks(Set<String> _selectedGroups, GridFlow _flow) {
|
||||
float[] blocks = new float[blockCount()];
|
||||
chargeBlocks(_selectedGroups, blocks, _flow);
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private void chargeBlocks(Set<String> _selectedGroups, float[] _chargeBlocks, GridFlow _flow) {
|
||||
if ((charges != null) && ((_selectedGroups == null) || _selectedGroups.contains(getGroupId()))) {
|
||||
for (int i = 0; i < charges.length; i++) {
|
||||
if ((_flow == GridFlow.BOTH) || ((_flow == GridFlow.FROM) && charges[i] >= 0.0) || ((_flow == GridFlow.TO) && charges[i] <= 0.0))
|
||||
_chargeBlocks[i] += charges[i];
|
||||
}
|
||||
}
|
||||
for (ChargeSummary group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
group.chargeBlocks(_selectedGroups, _chargeBlocks, _flow);
|
||||
}
|
||||
}
|
||||
|
||||
private int blockCount() {
|
||||
int blocks = 0;
|
||||
for (ChargeSummary s : CollectionUtils.makeNotNull(subGroups)) {
|
||||
blocks = Math.max(blocks, s.blockCount());
|
||||
}
|
||||
if ((charges != null) && (charges.length > blocks))
|
||||
return charges.length;
|
||||
return blocks;
|
||||
}
|
||||
|
||||
public static String toId(int _accountId, int _planId, String _groupId, EnergyViewMode _viewMode, Date _start) {
|
||||
return _accountId + "-" + _planId + "-" + _groupId + "-" + DaoSerializer.toEnumName(_viewMode) + "-" + _start.getTime();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor;
|
||||
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@DBSerializable(autogen = false)
|
||||
public class ChargeTotal {
|
||||
private int accountId;
|
||||
private String groupId;
|
||||
private int planId;
|
||||
private EnergyViewMode viewMode;
|
||||
private Date start;
|
||||
private double charge;
|
||||
private List<ChargeTotal> subGroups;
|
||||
private double totalUsageJoules;
|
||||
private double totalSolarJoules;
|
||||
private double fromGridJoules;
|
||||
private double toGridJoules;
|
||||
private double peakToGrid;
|
||||
private double peakFromGrid;
|
||||
private double peakConsumption;
|
||||
private double peakProduction;
|
||||
|
||||
public ChargeTotal() {
|
||||
}
|
||||
|
||||
public ChargeTotal(ChargeSummary _summary) {
|
||||
accountId = _summary.getAccountId();
|
||||
groupId = _summary.getGroupId();
|
||||
planId = _summary.getPlanId();
|
||||
viewMode = _summary.getViewMode();
|
||||
start = _summary.getStart();
|
||||
if (_summary.getCharges() != null) {
|
||||
for (double c : _summary.getCharges()) {
|
||||
charge += c;
|
||||
}
|
||||
}
|
||||
subGroups = CollectionUtils.transform(_summary.getSubGroups(), ChargeTotal::new);
|
||||
totalUsageJoules = _summary.getTotalUsageJoules();
|
||||
totalSolarJoules = _summary.getTotalSolarJoules();
|
||||
fromGridJoules = _summary.getFromGridJoules();
|
||||
toGridJoules = _summary.getToGridJoules();
|
||||
peakToGrid = _summary.getPeakToGrid();
|
||||
peakFromGrid = _summary.getPeakFromGrid();
|
||||
peakConsumption = _summary.getPeakConsumption();
|
||||
peakProduction = _summary.getPeakProduction();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return ChargeSummary.toId(accountId, planId, groupId, viewMode, start);
|
||||
}
|
||||
|
||||
|
||||
public int getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(int _accountId) {
|
||||
accountId = _accountId;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(String _groupId) {
|
||||
groupId = _groupId;
|
||||
}
|
||||
|
||||
public int getPlanId() {
|
||||
return planId;
|
||||
}
|
||||
|
||||
public void setPlanId(int _planId) {
|
||||
planId = _planId;
|
||||
}
|
||||
|
||||
public EnergyViewMode getViewMode() {
|
||||
return viewMode;
|
||||
}
|
||||
|
||||
public void setViewMode(EnergyViewMode _viewMode) {
|
||||
viewMode = _viewMode;
|
||||
}
|
||||
|
||||
public Date getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(Date _start) {
|
||||
start = _start;
|
||||
}
|
||||
|
||||
public double getCharge() {
|
||||
return charge;
|
||||
}
|
||||
|
||||
public void setCharge(double _charge) {
|
||||
charge = _charge;
|
||||
}
|
||||
|
||||
public List<ChargeTotal> getSubGroups() {
|
||||
return subGroups;
|
||||
}
|
||||
|
||||
public void setSubGroups(List<ChargeTotal> _subGroups) {
|
||||
subGroups = _subGroups;
|
||||
}
|
||||
|
||||
public double getTotalUsageJoules() {
|
||||
return totalUsageJoules;
|
||||
}
|
||||
|
||||
public void setTotalUsageJoules(double _totalUsageJoules) {
|
||||
totalUsageJoules = _totalUsageJoules;
|
||||
}
|
||||
|
||||
public double getTotalSolarJoules() {
|
||||
return totalSolarJoules;
|
||||
}
|
||||
|
||||
public void setTotalSolarJoules(double _totalSolarJoules) {
|
||||
totalSolarJoules = _totalSolarJoules;
|
||||
}
|
||||
|
||||
public double getFromGridJoules() {
|
||||
return fromGridJoules;
|
||||
}
|
||||
|
||||
public void setFromGridJoules(double _fromGridJoules) {
|
||||
fromGridJoules = _fromGridJoules;
|
||||
}
|
||||
|
||||
public double getToGridJoules() {
|
||||
return toGridJoules;
|
||||
}
|
||||
|
||||
public void setToGridJoules(double _toGridJoules) {
|
||||
toGridJoules = _toGridJoules;
|
||||
}
|
||||
|
||||
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 double chargeTotal() {
|
||||
double retCharge = charge;
|
||||
for (ChargeTotal t : CollectionUtils.makeNotNull(subGroups)) {
|
||||
retCharge += t.chargeTotal();
|
||||
}
|
||||
return retCharge;
|
||||
}
|
||||
|
||||
public List<ChargeTotal> flatten() {
|
||||
List<ChargeTotal> totals = new ArrayList<>();
|
||||
flatten(totals);
|
||||
return totals;
|
||||
}
|
||||
|
||||
private void flatten(List<ChargeTotal> _totals) {
|
||||
_totals.add(this);
|
||||
for (ChargeTotal total : CollectionUtils.makeNotNull(subGroups)) {
|
||||
total.flatten(_totals);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ public class EnergyBlock {
|
|||
public void setCharge(double _charge) {
|
||||
charge = _charge;
|
||||
}
|
||||
|
||||
public void addCharge(double _charge) {
|
||||
charge += _charge;
|
||||
}
|
||||
|
@ -63,10 +64,4 @@ public class EnergyBlock {
|
|||
public double wattHours() {
|
||||
return joules / 3600;
|
||||
}
|
||||
|
||||
public double getAveragePower() {
|
||||
if ((end == null) || (start == null))
|
||||
return 0;
|
||||
return 1000*joules/(end.getTime()-start.getTime());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,503 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor;
|
||||
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
import com.lanternsoftware.util.mutable.MutableDouble;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@DBSerializable(autogen = false)
|
||||
public class EnergySummary {
|
||||
private int accountId;
|
||||
private String groupId;
|
||||
private String groupName;
|
||||
private EnergyViewMode viewMode;
|
||||
private Date start;
|
||||
private List<EnergySummary> subGroups;
|
||||
private float[] energy;
|
||||
private float[] gridEnergy;
|
||||
private double peakToGrid;
|
||||
private double peakFromGrid;
|
||||
private double peakConsumption;
|
||||
private double peakProduction;
|
||||
private TimeZone timezone;
|
||||
|
||||
public EnergySummary() {
|
||||
}
|
||||
|
||||
public EnergySummary(BreakerGroup _group, List<HubPowerMinute> _power, EnergyViewMode _viewMode, Date _start, TimeZone _timezone) {
|
||||
groupId = _group.getId();
|
||||
groupName = _group.getName();
|
||||
viewMode = _viewMode;
|
||||
start = _start;
|
||||
accountId = _group.getAccountId();
|
||||
timezone = _timezone;
|
||||
subGroups = CollectionUtils.transform(_group.getSubGroups(), _g -> new EnergySummary(_g, null, _viewMode, _start, timezone));
|
||||
if (_power != null)
|
||||
addEnergy(_group, _power);
|
||||
}
|
||||
|
||||
public void addEnergy(BreakerGroup _group, List<HubPowerMinute> _hubPower) {
|
||||
Map<String, Breaker> breakers = CollectionUtils.transformToMap(_group.getAllBreakers(), Breaker::getKey);
|
||||
Map<String, BreakerGroup> breakerKeyToGroup = new HashMap<>();
|
||||
for (BreakerGroup group : _group.getAllBreakerGroups()) {
|
||||
for (Breaker b : CollectionUtils.makeNotNull(group.getBreakers())) {
|
||||
breakerKeyToGroup.put(b.getKey(), group);
|
||||
}
|
||||
}
|
||||
addEnergy(breakers, breakerKeyToGroup, _hubPower);
|
||||
}
|
||||
|
||||
public void addEnergy(Map<String, Breaker> _breakers, Map<String, BreakerGroup> _breakerKeyToGroup, List<HubPowerMinute> _hubPower) {
|
||||
if (CollectionUtils.isEmpty(_hubPower) || CollectionUtils.anyQualify(_hubPower, _p -> _p.getAccountId() != accountId))
|
||||
return;
|
||||
_hubPower.sort(Comparator.comparing(HubPowerMinute::getMinute));
|
||||
for (Date minute : CollectionUtils.transformToSet(_hubPower, HubPowerMinute::getMinuteAsDate)) {
|
||||
resetEnergy(minute);
|
||||
}
|
||||
int idx;
|
||||
Map<Integer, Map<Integer, MeterMinute>> minutes = new HashMap<>();
|
||||
for (HubPowerMinute hubPower : _hubPower) {
|
||||
Date minute = hubPower.getMinuteAsDate();
|
||||
for (BreakerPowerMinute breaker : CollectionUtils.makeNotNull(hubPower.getBreakers())) {
|
||||
String key = breaker.breakerKey();
|
||||
Breaker b = _breakers.get(key);
|
||||
if (b == null)
|
||||
continue;
|
||||
BreakerGroup group = _breakerKeyToGroup.get(key);
|
||||
if (group == null)
|
||||
continue;
|
||||
MeterMinute meter = minutes.computeIfAbsent(hubPower.getMinute(), _p -> new HashMap<>()).computeIfAbsent(b.getMeter(), _m -> new MeterMinute(b.getMeter(), minute));
|
||||
idx = 0;
|
||||
for (Float power : CollectionUtils.makeNotNull(breaker.getReadings())) {
|
||||
if (idx >= 60)
|
||||
break;
|
||||
if (power > 0)
|
||||
meter.usage[idx] += power;
|
||||
else
|
||||
meter.solar[idx] -= power;
|
||||
addEnergy(group.getId(), minute, power);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 minute : meters.values()) {
|
||||
curConsumption += minute.usage[i];
|
||||
curProduction += minute.solar[i];
|
||||
minute.flow[i] = minute.usage[i] - minute.solar[i];
|
||||
if (minute.flow[i] > 0)
|
||||
curFromGrid += minute.flow[i];
|
||||
else
|
||||
curToGrid -= minute.flow[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())) {
|
||||
String key = breaker.breakerKey();
|
||||
Breaker b = _breakers.get(key);
|
||||
if (b == null)
|
||||
continue;
|
||||
BreakerGroup group = _breakerKeyToGroup.get(key);
|
||||
if (group == null)
|
||||
continue;
|
||||
MeterMinute meter = minutes.get(hubPower.getMinute()).get(b.getMeter());
|
||||
idx = 0;
|
||||
double flow = 0.0;
|
||||
for (Float power : CollectionUtils.makeNotNull(breaker.getReadings())) {
|
||||
if ((b.getPolarity() == BreakerPolarity.SOLAR) && (meter.flow[idx] < 0.0))
|
||||
flow -= meter.flow[idx] * (power / meter.solar[idx]);
|
||||
else if ((b.getPolarity() != BreakerPolarity.SOLAR) && (meter.flow[idx] > 0.0))
|
||||
flow += meter.flow[idx] * (power / meter.usage[idx]);
|
||||
idx++;
|
||||
}
|
||||
addFlow(group.getId(), minute, flow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void resetEnergy(Date _readTime) {
|
||||
if (energy == null)
|
||||
return;
|
||||
int idx = viewMode.blockIndex(start, _readTime, timezone);
|
||||
if (idx < energy.length)
|
||||
energy[idx] = 0f;
|
||||
for (EnergySummary subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||
subGroup.resetEnergy(_readTime);
|
||||
}
|
||||
}
|
||||
|
||||
public static EnergySummary summary(BreakerGroup _group, Map<String, List<EnergyTotal>> _energies, EnergyViewMode _viewMode, Date _start, TimeZone _tz) {
|
||||
EnergySummary energy = new EnergySummary();
|
||||
energy.setGroupId(_group.getId());
|
||||
energy.setGroupName(_group.getName());
|
||||
energy.setAccountId(_group.getAccountId());
|
||||
energy.setViewMode(_viewMode);
|
||||
energy.setStart(_start);
|
||||
energy.setTimeZone(_tz);
|
||||
energy.setSubGroups(CollectionUtils.transform(_group.getSubGroups(), _g -> EnergySummary.summary(_g, _energies, _viewMode, _start, _tz)));
|
||||
for (EnergyTotal curEnergy : CollectionUtils.makeNotNull(_energies.get(_group.getId()))) {
|
||||
energy.addEnergy(curEnergy.getStart(), curEnergy.getJoules());
|
||||
energy.addFlow(curEnergy.getStart(), curEnergy.getFlow());
|
||||
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;
|
||||
}
|
||||
|
||||
private boolean addEnergy(String _groupId, Date _readTime, double _joules) {
|
||||
if (NullUtils.isEqual(groupId, _groupId)) {
|
||||
addEnergy(_readTime, _joules);
|
||||
return true;
|
||||
} else {
|
||||
for (EnergySummary subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||
if (subGroup.addEnergy(_groupId, _readTime, _joules))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addEnergy(Date _readTime, double _joules) {
|
||||
if (energy == null)
|
||||
energy = new float[blockCount()];
|
||||
int idx = viewMode.blockIndex(start, _readTime, timezone);
|
||||
if (idx < energy.length)
|
||||
energy[idx] += _joules;
|
||||
}
|
||||
|
||||
private boolean addFlow(String _groupId, Date _readTime, double _joules) {
|
||||
if (NullUtils.isEqual(groupId, _groupId)) {
|
||||
addFlow(_readTime, _joules);
|
||||
return true;
|
||||
} else {
|
||||
for (EnergySummary subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||
if (subGroup.addFlow(_groupId, _readTime, _joules))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addFlow(Date _readTime, double _joules) {
|
||||
if (gridEnergy == null)
|
||||
gridEnergy = new float[blockCount()];
|
||||
int idx = viewMode.blockIndex(start, _readTime, timezone);
|
||||
if (idx < gridEnergy.length)
|
||||
gridEnergy[idx] += _joules;
|
||||
}
|
||||
|
||||
private int blockCount() {
|
||||
return viewMode.blockCount(start, timezone);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return toId(accountId, groupId, viewMode, start);
|
||||
}
|
||||
|
||||
public static String toId(int _accountId, String _groupId, EnergyViewMode _viewMode, Date _start) {
|
||||
return _accountId + "-" + _groupId + "-" + DaoSerializer.toEnumName(_viewMode) + "-" + _start.getTime();
|
||||
}
|
||||
|
||||
public int getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(int _accountId) {
|
||||
accountId = _accountId;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(String _groupId) {
|
||||
groupId = _groupId;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public void setGroupName(String _groupName) {
|
||||
groupName = _groupName;
|
||||
}
|
||||
|
||||
public EnergySummary getSubGroup(String _groupId) {
|
||||
return CollectionUtils.filterOne(subGroups, _g -> _groupId.equals(_g.getGroupId()));
|
||||
}
|
||||
|
||||
public List<EnergySummary> getSubGroups() {
|
||||
return subGroups;
|
||||
}
|
||||
|
||||
public EnergyViewMode getViewMode() {
|
||||
return viewMode;
|
||||
}
|
||||
|
||||
public void setViewMode(EnergyViewMode _viewMode) {
|
||||
viewMode = _viewMode;
|
||||
}
|
||||
|
||||
public Date getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(Date _start) {
|
||||
start = _start;
|
||||
}
|
||||
|
||||
public void setSubGroups(List<EnergySummary> _subGroups) {
|
||||
subGroups = _subGroups;
|
||||
}
|
||||
|
||||
public float[] getEnergy() {
|
||||
return energy;
|
||||
}
|
||||
|
||||
public void setEnergy(float[] _energy) {
|
||||
energy = _energy;
|
||||
}
|
||||
|
||||
public float[] getGridEnergy() {
|
||||
return gridEnergy;
|
||||
}
|
||||
|
||||
public void setGridEnergy(float[] _gridEnergy) {
|
||||
gridEnergy = _gridEnergy;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void setTimeZone(TimeZone _timezone) {
|
||||
timezone = _timezone;
|
||||
}
|
||||
|
||||
public double wattHours() {
|
||||
return joules() / 3600;
|
||||
}
|
||||
|
||||
public double wattHours(Set<String> _selectedBreakers) {
|
||||
return joules(_selectedBreakers) / 3600;
|
||||
}
|
||||
|
||||
public double joules() {
|
||||
return joules(null);
|
||||
}
|
||||
|
||||
public double joules(Set<String> _selectedBreakers) {
|
||||
return joules(_selectedBreakers, true, GridFlow.BOTH);
|
||||
}
|
||||
|
||||
public double joules(Set<String> _selectedBreakers, boolean _includeSubgroups, GridFlow _mode) {
|
||||
double joules = 0.0;
|
||||
if (_includeSubgroups) {
|
||||
for (EnergySummary group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
joules += group.joules(_selectedBreakers, true, _mode);
|
||||
}
|
||||
}
|
||||
if ((energy != null) && ((_selectedBreakers == null) || _selectedBreakers.contains(getGroupId()))) {
|
||||
for (float block : energy) {
|
||||
if ((_mode == GridFlow.BOTH) || ((_mode == GridFlow.FROM) && (block > 0f)) || ((_mode == GridFlow.TO) && (block < 0f)))
|
||||
joules += block;
|
||||
}
|
||||
}
|
||||
return joules;
|
||||
}
|
||||
|
||||
public double flow() {
|
||||
return flow(null);
|
||||
}
|
||||
|
||||
public double flow(Set<String> _selectedBreakers) {
|
||||
return flow(_selectedBreakers, true, GridFlow.BOTH);
|
||||
}
|
||||
|
||||
public double flow(Set<String> _selectedBreakers, boolean _includeSubgroups, GridFlow _mode) {
|
||||
double flow = 0.0;
|
||||
if (_includeSubgroups) {
|
||||
for (EnergySummary group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
flow += group.flow(_selectedBreakers, true, _mode);
|
||||
}
|
||||
}
|
||||
if ((gridEnergy != null) && ((_selectedBreakers == null) || _selectedBreakers.contains(getGroupId()))) {
|
||||
for (float block : gridEnergy) {
|
||||
if ((_mode == GridFlow.BOTH) || ((_mode == GridFlow.FROM) && (block > 0f)) || ((_mode == GridFlow.TO) && (block < 0f)))
|
||||
flow += block;
|
||||
}
|
||||
}
|
||||
return flow;
|
||||
}
|
||||
|
||||
public List<EnergySummary> getAllGroups() {
|
||||
Map<String, EnergySummary> groups = new TreeMap<>();
|
||||
getAllGroups(groups);
|
||||
return new ArrayList<>(groups.values());
|
||||
}
|
||||
|
||||
public void getAllGroups(Map<String, EnergySummary> _groups) {
|
||||
_groups.put(getGroupId(), this);
|
||||
for (EnergySummary group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
group.getAllGroups(_groups);
|
||||
}
|
||||
}
|
||||
|
||||
public float[] energyBlocks() {
|
||||
return energyBlocks(null);
|
||||
}
|
||||
|
||||
public float[] energyBlocks(Set<String> _selectedGroups) {
|
||||
return energyBlocks(_selectedGroups, GridFlow.BOTH);
|
||||
}
|
||||
|
||||
public float[] energyBlocks(Set<String> _selectedGroups, GridFlow _flow) {
|
||||
float[] blocks = new float[blockCount()];
|
||||
energyBlocks(_selectedGroups, blocks, _flow);
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private void energyBlocks(Set<String> _selectedGroups, float[] _energyBlocks, GridFlow _flow) {
|
||||
if ((energy != null) && ((_selectedGroups == null) || _selectedGroups.contains(getGroupId()))) {
|
||||
for (int i = 0; i < energy.length; i++) {
|
||||
if ((_flow == GridFlow.BOTH) || ((_flow == GridFlow.FROM) && energy[i] >= 0.0) || ((_flow == GridFlow.TO) && energy[i] <= 0.0))
|
||||
_energyBlocks[i] += energy[i];
|
||||
}
|
||||
}
|
||||
for (EnergySummary group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
group.energyBlocks(_selectedGroups, _energyBlocks, _flow);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ChargeSummary> toChargeSummaries(BreakerConfig _config, List<EnergyTotal> _totals) {
|
||||
Map<String, Integer> breakerGroupMeters = _config.getRootGroup().mapToMeters();
|
||||
return CollectionUtils.transform(_config.getBillingPlans(), _p->{
|
||||
double monthKwh = CollectionUtils.sum(CollectionUtils.transform(CollectionUtils.filter(_totals, _t->_t.getStart().getTime() >= _p.getBillingCycleStart(start, timezone).getTime()), EnergyTotal::totalJoules))/3600000.0;
|
||||
return toChargeSummary(_p.getPlanId(), _p.getRates(), breakerGroupMeters, new MutableDouble(monthKwh));
|
||||
});
|
||||
}
|
||||
|
||||
public ChargeSummary toChargeSummary(int _planId, List<BillingRate> _rates, Map<String, Integer> _breakerGroupMeters, MutableDouble _monthKwh) {
|
||||
return toChargeSummaryForRates(_planId, CollectionUtils.filter(_rates, _r->_r.isApplicableForDay(start, timezone)), _breakerGroupMeters, _monthKwh);
|
||||
}
|
||||
|
||||
private ChargeSummary toChargeSummaryForRates(int _planId, List<BillingRate> _rates, Map<String, Integer> _breakerGroupMeters, MutableDouble _monthKwh) {
|
||||
ChargeSummary summary = new ChargeSummary(accountId, _planId, groupId, groupName, viewMode, start, timezone);
|
||||
if (gridEnergy != null) {
|
||||
double[] charges = new double[gridEnergy.length];
|
||||
for (int i = 0; i < gridEnergy.length; i++) {
|
||||
_monthKwh.add(gridEnergy[i]/3600000.0);
|
||||
for (BillingRate rate : _rates) {
|
||||
if (gridEnergy[i] > 0f) {
|
||||
if (rate.isApplicable(GridFlow.FROM, DaoSerializer.toInteger(_breakerGroupMeters.get(groupId)), _monthKwh.getValue(), i*60))
|
||||
charges[i] += rate.apply(((double) gridEnergy[i]) / 3600000.0);
|
||||
} else if (rate.isApplicable(GridFlow.TO, DaoSerializer.toInteger(_breakerGroupMeters.get(groupId)), _monthKwh.getValue(), i*60))
|
||||
charges[i] += rate.apply(((double) gridEnergy[i]) / 3600000.0);
|
||||
}
|
||||
}
|
||||
summary.setCharges(charges);
|
||||
}
|
||||
summary.setSubGroups(CollectionUtils.transform(subGroups, _s->_s.toChargeSummary(_planId, _rates, _breakerGroupMeters, _monthKwh)));
|
||||
summary.setTotalUsageJoules(joules(null, true, GridFlow.FROM));
|
||||
summary.setTotalSolarJoules(Math.abs(joules(null, true, GridFlow.TO)));
|
||||
summary.setFromGridJoules(flow(null, true, GridFlow.FROM));
|
||||
summary.setToGridJoules(Math.abs(flow(null, true, GridFlow.TO)));
|
||||
summary.setPeakConsumption(peakConsumption);
|
||||
summary.setPeakProduction(peakProduction);
|
||||
summary.setPeakFromGrid(peakFromGrid);
|
||||
summary.setPeakToGrid(peakToGrid);
|
||||
return summary;
|
||||
}
|
||||
|
||||
private static class MeterMinute {
|
||||
private final int meter;
|
||||
private final Date minute;
|
||||
|
||||
public MeterMinute(int _meter, Date _minute) {
|
||||
meter = _meter;
|
||||
minute = _minute;
|
||||
}
|
||||
|
||||
public int getMeter() {
|
||||
return meter;
|
||||
}
|
||||
|
||||
public Date getMinute() {
|
||||
return minute;
|
||||
}
|
||||
|
||||
public double[] usage = new double[60];
|
||||
public double[] solar = new double[60];
|
||||
public double[] flow = new double[60];
|
||||
}
|
||||
}
|
|
@ -2,47 +2,38 @@ package com.lanternsoftware.datamodel.currentmonitor;
|
|||
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@DBSerializable(autogen = false)
|
||||
public class BreakerGroupSummary {
|
||||
public class EnergyTotal {
|
||||
private int accountId;
|
||||
private String groupId;
|
||||
private String groupName;
|
||||
private EnergyBlockViewMode viewMode;
|
||||
private EnergyViewMode viewMode;
|
||||
private Date start;
|
||||
private List<BreakerGroupSummary> subGroups;
|
||||
private List<EnergyTotal> subGroups;
|
||||
private double joules;
|
||||
private double charge;
|
||||
private double toGrid;
|
||||
private double fromGrid;
|
||||
private double flow;
|
||||
private double peakToGrid;
|
||||
private double peakFromGrid;
|
||||
private double peakConsumption;
|
||||
private double peakProduction;
|
||||
|
||||
public BreakerGroupSummary() {
|
||||
public EnergyTotal() {
|
||||
}
|
||||
|
||||
public BreakerGroupSummary(BreakerGroupEnergy _energy) {
|
||||
public EnergyTotal(EnergySummary _energy) {
|
||||
accountId = _energy.getAccountId();
|
||||
groupId = _energy.getGroupId();
|
||||
groupName = _energy.getGroupName();
|
||||
viewMode = _energy.getViewMode();
|
||||
start = _energy.getStart();
|
||||
subGroups = CollectionUtils.transform(_energy.getSubGroups(), BreakerGroupSummary::new);
|
||||
joules = _energy.joules(null, false);
|
||||
charge = _energy.charge(null, false);
|
||||
toGrid = _energy.getToGrid();
|
||||
fromGrid = _energy.getFromGrid();
|
||||
subGroups = CollectionUtils.transform(_energy.getSubGroups(), EnergyTotal::new);
|
||||
joules = _energy.joules(null, false, GridFlow.BOTH);
|
||||
flow = _energy.flow(null, false, GridFlow.BOTH);
|
||||
peakToGrid = _energy.getPeakToGrid();
|
||||
peakFromGrid = _energy.getPeakFromGrid();
|
||||
peakConsumption = _energy.getPeakConsumption();
|
||||
|
@ -53,7 +44,7 @@ public class BreakerGroupSummary {
|
|||
return toId(accountId, groupId, viewMode, start);
|
||||
}
|
||||
|
||||
public static String toId(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start) {
|
||||
public static String toId(int _accountId, String _groupId, EnergyViewMode _viewMode, Date _start) {
|
||||
return _accountId + "-" + _groupId + "-" + DaoSerializer.toEnumName(_viewMode) + "-" + _start.getTime();
|
||||
}
|
||||
|
||||
|
@ -73,27 +64,19 @@ public class BreakerGroupSummary {
|
|||
groupId = _groupId;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public void setGroupName(String _groupName) {
|
||||
groupName = _groupName;
|
||||
}
|
||||
|
||||
public BreakerGroupSummary getSubGroup(String _groupId) {
|
||||
public EnergyTotal getSubGroup(String _groupId) {
|
||||
return CollectionUtils.filterOne(subGroups, _g->_groupId.equals(_g.getGroupId()));
|
||||
}
|
||||
|
||||
public List<BreakerGroupSummary> getSubGroups() {
|
||||
public List<EnergyTotal> getSubGroups() {
|
||||
return subGroups;
|
||||
}
|
||||
|
||||
public EnergyBlockViewMode getViewMode() {
|
||||
public EnergyViewMode getViewMode() {
|
||||
return viewMode;
|
||||
}
|
||||
|
||||
public void setViewMode(EnergyBlockViewMode _viewMode) {
|
||||
public void setViewMode(EnergyViewMode _viewMode) {
|
||||
viewMode = _viewMode;
|
||||
}
|
||||
|
||||
|
@ -105,7 +88,7 @@ public class BreakerGroupSummary {
|
|||
start = _start;
|
||||
}
|
||||
|
||||
public void setSubGroups(List<BreakerGroupSummary> _subGroups) {
|
||||
public void setSubGroups(List<EnergyTotal> _subGroups) {
|
||||
subGroups = _subGroups;
|
||||
}
|
||||
|
||||
|
@ -117,28 +100,12 @@ public class BreakerGroupSummary {
|
|||
joules = _joules;
|
||||
}
|
||||
|
||||
public double getCharge() {
|
||||
return charge;
|
||||
public double getFlow() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
public void setCharge(double _charge) {
|
||||
charge = _charge;
|
||||
}
|
||||
|
||||
public double getToGrid() {
|
||||
return toGrid;
|
||||
}
|
||||
|
||||
public void setToGrid(double _toGrid) {
|
||||
toGrid = _toGrid;
|
||||
}
|
||||
|
||||
public double getFromGrid() {
|
||||
return fromGrid;
|
||||
}
|
||||
|
||||
public void setFromGrid(double _fromGrid) {
|
||||
fromGrid = _fromGrid;
|
||||
public void setFlow(double _flow) {
|
||||
flow = _flow;
|
||||
}
|
||||
|
||||
public double getPeakConsumption() {
|
||||
|
@ -173,17 +140,24 @@ public class BreakerGroupSummary {
|
|||
peakFromGrid = _peakFromGrid;
|
||||
}
|
||||
|
||||
public List<BreakerGroupSummary> getAllGroups() {
|
||||
Map<String, BreakerGroupSummary> groups = new TreeMap<>();
|
||||
getAllGroups(groups);
|
||||
return new ArrayList<>(groups.values());
|
||||
public double totalJoules() {
|
||||
double total = joules;
|
||||
for (EnergyTotal t : CollectionUtils.makeNotNull(subGroups)) {
|
||||
total += t.totalJoules();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public void getAllGroups(Map<String, BreakerGroupSummary> _groups) {
|
||||
if (NullUtils.isNotEmpty(getGroupId()))
|
||||
_groups.put(getGroupId(), this);
|
||||
for (BreakerGroupSummary group : CollectionUtils.makeNotNull(subGroups)) {
|
||||
group.getAllGroups(_groups);
|
||||
public List<EnergyTotal> flatten() {
|
||||
List<EnergyTotal> totals = new ArrayList<>();
|
||||
flatten(totals);
|
||||
return totals;
|
||||
}
|
||||
|
||||
private void flatten(List<EnergyTotal> _totals) {
|
||||
_totals.add(this);
|
||||
for (EnergyTotal total : CollectionUtils.makeNotNull(subGroups)) {
|
||||
total.flatten(_totals);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import java.util.Calendar;
|
|||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public enum EnergyBlockViewMode {
|
||||
public enum EnergyViewMode {
|
||||
DAY,
|
||||
MONTH,
|
||||
YEAR,
|
||||
|
@ -54,59 +54,58 @@ public enum EnergyBlockViewMode {
|
|||
}
|
||||
|
||||
public Date incrementBlock(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = DateUtils.toCalendar(_dt, _tz);
|
||||
if (this == DAY)
|
||||
cal.add(Calendar.MINUTE, 1);
|
||||
else if (this == MONTH)
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
return DateUtils.addMinutes(_dt, 1);
|
||||
if (this == MONTH)
|
||||
return DateUtils.addDays(_dt, 1, _tz);
|
||||
if (this == YEAR)
|
||||
cal.add(Calendar.MONTH, 1);
|
||||
return cal.getTime();
|
||||
return DateUtils.addMonths(_dt, 1, _tz);
|
||||
return _dt;
|
||||
}
|
||||
|
||||
public Date decrementBlock(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = DateUtils.toCalendar(_dt, _tz);
|
||||
if (this == DAY)
|
||||
cal.add(Calendar.MINUTE, -1);
|
||||
else if (this == MONTH)
|
||||
cal.add(Calendar.DAY_OF_YEAR, -1);
|
||||
return DateUtils.addMinutes(_dt, -1);
|
||||
if (this == MONTH)
|
||||
return DateUtils.addDays(_dt, -1, _tz);
|
||||
if (this == YEAR)
|
||||
cal.add(Calendar.MONTH, -1);
|
||||
return cal.getTime();
|
||||
return DateUtils.addMonths(_dt, -1, _tz);
|
||||
return _dt;
|
||||
}
|
||||
|
||||
public Date incrementView(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = DateUtils.toCalendar(_dt, _tz);
|
||||
if (this == DAY)
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
else if (this == MONTH)
|
||||
cal.add(Calendar.MONTH, 1);
|
||||
return DateUtils.addDays(_dt, 1, _tz);
|
||||
if (this == MONTH)
|
||||
return DateUtils.addMonths(_dt, 1, _tz);
|
||||
if (this == YEAR)
|
||||
cal.add(Calendar.YEAR, 1);
|
||||
return cal.getTime();
|
||||
return DateUtils.addYears(_dt, 1, _tz);
|
||||
return _dt;
|
||||
}
|
||||
|
||||
public Date decrementView(Date _dt, TimeZone _tz) {
|
||||
Calendar cal = DateUtils.toCalendar(_dt, _tz);
|
||||
if (this == DAY)
|
||||
cal.add(Calendar.DAY_OF_YEAR, -1);
|
||||
else if (this == MONTH)
|
||||
cal.add(Calendar.MONTH, -1);
|
||||
return DateUtils.addDays(_dt, -1, _tz);
|
||||
if (this == MONTH)
|
||||
return DateUtils.addMonths(_dt, -1, _tz);
|
||||
if (this == YEAR)
|
||||
cal.add(Calendar.YEAR, -1);
|
||||
return cal.getTime();
|
||||
return DateUtils.addYears(_dt, -1, _tz);
|
||||
return _dt;
|
||||
}
|
||||
|
||||
public int blockCount(Date _start, TimeZone _tz) {
|
||||
if (this == ALL)
|
||||
return 1;
|
||||
Date end = toEnd(_start, _tz);
|
||||
int blockCnt = 0;
|
||||
while (_start.before(end)) {
|
||||
blockCnt++;
|
||||
_start = toBlockEnd(_start, _tz);
|
||||
if (this == YEAR)
|
||||
return 12;
|
||||
if (this == MONTH) {
|
||||
Calendar end = DateUtils.getEndOfMonthCal(_start, _tz);
|
||||
end.add(Calendar.MINUTE, -2);
|
||||
return end.get(Calendar.DAY_OF_MONTH);
|
||||
}
|
||||
return blockCnt;
|
||||
if (this == DAY) {
|
||||
Date end = DateUtils.getMidnightAfter(_start, _tz);
|
||||
return (int)((end.getTime() - _start.getTime()) / 60000);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int initBlockCount() {
|
|
@ -5,7 +5,7 @@ import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@DBSerializable
|
||||
@DBSerializable(autogen = false)
|
||||
public class HubPowerMinute {
|
||||
private int accountId;
|
||||
private int hub;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BillingPlan;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BillingRate;
|
||||
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class BillingPlanSerializer extends AbstractDaoSerializer<BillingPlan>
|
||||
{
|
||||
@Override
|
||||
public Class<BillingPlan> getSupportedClass()
|
||||
{
|
||||
return BillingPlan.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DaoProxyType> getSupportedProxies() {
|
||||
return Collections.singletonList(DaoProxyType.MONGO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoEntity toDaoEntity(BillingPlan _o)
|
||||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("account_id", _o.getAccountId());
|
||||
d.put("plan_id", _o.getPlanId());
|
||||
d.put("billing_day", _o.getBillingDay());
|
||||
d.put("name", _o.getName());
|
||||
d.put("rates", DaoSerializer.toDaoEntities(_o.getRates(), DaoProxyType.MONGO));
|
||||
return d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BillingPlan fromDaoEntity(DaoEntity _d)
|
||||
{
|
||||
BillingPlan o = new BillingPlan();
|
||||
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||
o.setPlanId(DaoSerializer.getInteger(_d, "plan_id"));
|
||||
o.setBillingDay(DaoSerializer.getInteger(_d, "billing_day"));
|
||||
o.setName(DaoSerializer.getString(_d, "name"));
|
||||
o.setRates(DaoSerializer.getList(_d, "rates", BillingRate.class));
|
||||
return o;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,13 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BillingCurrency;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.GridFlow;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BillingRate;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.GridFlow;
|
||||
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -28,10 +29,10 @@ public class BillingRateSerializer extends AbstractDaoSerializer<BillingRate>
|
|||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("meter", _o.getMeter());
|
||||
d.put("day_billing_cycle_start", _o.getDayBillingCycleStart());
|
||||
d.put("flow", DaoSerializer.toEnumName(_o.getFlow()));
|
||||
d.put("rate", _o.getRate());
|
||||
d.put("unit", DaoSerializer.toEnumName(_o.getCurrency()));
|
||||
d.put("unit", DaoSerializer.toEnumName(_o.getCurrency())); //TODO: Remove post migration
|
||||
d.put("currency", DaoSerializer.toEnumName(_o.getCurrency()));
|
||||
d.put("time_of_day_start", _o.getTimeOfDayStart());
|
||||
d.put("time_of_day_end", _o.getTimeOfDayEnd());
|
||||
d.put("month_kwh_start", _o.getMonthKWhStart());
|
||||
|
@ -47,10 +48,11 @@ public class BillingRateSerializer extends AbstractDaoSerializer<BillingRate>
|
|||
{
|
||||
BillingRate o = new BillingRate();
|
||||
o.setMeter(DaoSerializer.getInteger(_d, "meter"));
|
||||
o.setDayBillingCycleStart(DaoSerializer.getInteger(_d, "day_billing_cycle_start"));
|
||||
o.setFlow(DaoSerializer.getEnum(_d, "flow", GridFlow.class, GridFlow.BOTH));
|
||||
o.setFlow(DaoSerializer.getEnum(_d, "flow", GridFlow.class));
|
||||
o.setRate(DaoSerializer.getDouble(_d, "rate"));
|
||||
o.setCurrency(DaoSerializer.getEnum(_d, "unit", BillingCurrency.class));
|
||||
o.setCurrency(DaoSerializer.getEnum(_d, "currency", BillingCurrency.class));
|
||||
if (o.getCurrency() == null)
|
||||
o.setCurrency(DaoSerializer.getEnum(_d, "unit", BillingCurrency.class));
|
||||
o.setTimeOfDayStart(DaoSerializer.getInteger(_d, "time_of_day_start"));
|
||||
o.setTimeOfDayEnd(DaoSerializer.getInteger(_d, "time_of_day_end"));
|
||||
o.setMonthKWhStart(DaoSerializer.getDouble(_d, "month_kwh_start"));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BillingPlan;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BillingRate;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||
|
@ -36,6 +37,7 @@ public class BreakerConfigSerializer extends AbstractDaoSerializer<BreakerConfig
|
|||
d.put("panels", DaoSerializer.toDaoEntities(_o.getPanels(), DaoProxyType.MONGO));
|
||||
d.put("breaker_hubs", DaoSerializer.toDaoEntities(_o.getBreakerHubs(), DaoProxyType.MONGO));
|
||||
d.put("breaker_groups", DaoSerializer.toDaoEntities(_o.getBreakerGroups(), DaoProxyType.MONGO));
|
||||
d.put("billing_plans", DaoSerializer.toDaoEntities(_o.getBillingPlans(), DaoProxyType.MONGO));
|
||||
d.put("billing_rates", DaoSerializer.toDaoEntities(_o.getBillingRates(), DaoProxyType.MONGO));
|
||||
d.put("version", _o.getVersion());
|
||||
return d;
|
||||
|
@ -50,6 +52,7 @@ public class BreakerConfigSerializer extends AbstractDaoSerializer<BreakerConfig
|
|||
o.setPanels(DaoSerializer.getList(_d, "panels", BreakerPanel.class));
|
||||
o.setBreakerHubs(DaoSerializer.getList(_d, "breaker_hubs", BreakerHub.class));
|
||||
o.setBreakerGroups(DaoSerializer.getList(_d, "breaker_groups", BreakerGroup.class));
|
||||
o.setBillingPlans(DaoSerializer.getList(_d, "billing_plans", BillingPlan.class));
|
||||
o.setBillingRates(DaoSerializer.getList(_d, "billing_rates", BillingRate.class));
|
||||
o.setVersion(DaoSerializer.getInteger(_d, "version"));
|
||||
return o;
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.lanternsoftware.datamodel.currentmonitor.dao;
|
|||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlock;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.DateUtils;
|
||||
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||
|
@ -11,12 +11,7 @@ import com.lanternsoftware.util.dao.DaoProxyType;
|
|||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.*;
|
||||
|
||||
public class BreakerGroupEnergySerializer extends AbstractDaoSerializer<BreakerGroupEnergy>
|
||||
{
|
||||
|
@ -88,7 +83,7 @@ public class BreakerGroupEnergySerializer extends AbstractDaoSerializer<BreakerG
|
|||
o.setGroupId(DaoSerializer.getString(_d, "group_id"));
|
||||
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||
o.setGroupName(DaoSerializer.getString(_d, "group_name"));
|
||||
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyBlockViewMode.class));
|
||||
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyViewMode.class));
|
||||
o.setStart(DaoSerializer.getDate(_d, "start"));
|
||||
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", BreakerGroupEnergy.class));
|
||||
o.setTimeZone(DateUtils.fromTimeZoneId(DaoSerializer.getString(_d, "timezone")));
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.ChargeSummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.DateUtils;
|
||||
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class ChargeSummarySerializer extends AbstractDaoSerializer<ChargeSummary>
|
||||
{
|
||||
@Override
|
||||
public Class<ChargeSummary> getSupportedClass()
|
||||
{
|
||||
return ChargeSummary.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DaoProxyType> getSupportedProxies() {
|
||||
return Collections.singletonList(DaoProxyType.MONGO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoEntity toDaoEntity(ChargeSummary _o)
|
||||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("_id", _o.getId());
|
||||
d.put("account_id", _o.getAccountId());
|
||||
d.put("plan_id", _o.getPlanId());
|
||||
d.put("group_id", _o.getGroupId());
|
||||
d.put("group_name", _o.getGroupName());
|
||||
d.put("view_mode", DaoSerializer.toEnumName(_o.getViewMode()));
|
||||
d.put("start", DaoSerializer.toLong(_o.getStart()));
|
||||
d.put("sub_groups", DaoSerializer.toDaoEntities(_o.getSubGroups(), DaoProxyType.MONGO));
|
||||
TimeZone tz = DateUtils.defaultTimeZone(_o.getTimezone());
|
||||
d.put("timezone", tz.getID());
|
||||
if (_o.getCharges() != null)
|
||||
d.put("charges", CollectionUtils.toByteArray(_o.getCharges()));
|
||||
d.put("total_usage_joules", _o.getTotalUsageJoules());
|
||||
d.put("total_solar_joules", _o.getTotalSolarJoules());
|
||||
d.put("from_grid_joules", _o.getFromGridJoules());
|
||||
d.put("to_grid_joules", _o.getToGridJoules());
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChargeSummary fromDaoEntity(DaoEntity _d)
|
||||
{
|
||||
ChargeSummary o = new ChargeSummary();
|
||||
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||
o.setPlanId(DaoSerializer.getInteger(_d, "plan_id"));
|
||||
o.setGroupId(DaoSerializer.getString(_d, "group_id"));
|
||||
o.setGroupName(DaoSerializer.getString(_d, "group_name"));
|
||||
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyViewMode.class));
|
||||
o.setStart(DaoSerializer.getDate(_d, "start"));
|
||||
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", ChargeSummary.class));
|
||||
o.setTimezone(DateUtils.fromTimeZoneId(DaoSerializer.getString(_d, "timezone")));
|
||||
o.setCharges(CollectionUtils.toDoubleArray(DaoSerializer.getByteArray(_d, "charges")));
|
||||
o.setTotalUsageJoules(DaoSerializer.getDouble(_d, "total_usage_joules"));
|
||||
o.setTotalSolarJoules(DaoSerializer.getDouble(_d, "total_solar_joules"));
|
||||
o.setFromGridJoules(DaoSerializer.getDouble(_d, "from_grid_joules"));
|
||||
o.setToGridJoules(DaoSerializer.getDouble(_d, "to_grid_joules"));
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.ChargeTotal;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ChargeTotalSerializer extends AbstractDaoSerializer<ChargeTotal>
|
||||
{
|
||||
@Override
|
||||
public Class<ChargeTotal> getSupportedClass()
|
||||
{
|
||||
return ChargeTotal.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DaoProxyType> getSupportedProxies() {
|
||||
return Collections.singletonList(DaoProxyType.MONGO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoEntity toDaoEntity(ChargeTotal _o)
|
||||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("_id", _o.getId());
|
||||
d.put("account_id", _o.getAccountId());
|
||||
d.put("group_id", _o.getGroupId());
|
||||
d.put("plan_id", _o.getPlanId());
|
||||
d.put("view_mode", DaoSerializer.toEnumName(_o.getViewMode()));
|
||||
d.put("start", DaoSerializer.toLong(_o.getStart()));
|
||||
d.put("charge", _o.getCharge());
|
||||
d.put("sub_groups", DaoSerializer.toDaoEntities(_o.getSubGroups(), DaoProxyType.MONGO));
|
||||
d.put("total_usage_joules", _o.getTotalUsageJoules());
|
||||
d.put("total_solar_joules", _o.getTotalSolarJoules());
|
||||
d.put("from_grid_joules", _o.getFromGridJoules());
|
||||
d.put("to_grid_joules", _o.getToGridJoules());
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChargeTotal fromDaoEntity(DaoEntity _d)
|
||||
{
|
||||
ChargeTotal o = new ChargeTotal();
|
||||
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||
o.setGroupId(DaoSerializer.getString(_d, "group_id"));
|
||||
o.setPlanId(DaoSerializer.getInteger(_d, "plan_id"));
|
||||
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyViewMode.class));
|
||||
o.setStart(DaoSerializer.getDate(_d, "start"));
|
||||
o.setCharge(DaoSerializer.getDouble(_d, "charge"));
|
||||
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", ChargeTotal.class));
|
||||
o.setTotalUsageJoules(DaoSerializer.getDouble(_d, "total_usage_joules"));
|
||||
o.setTotalSolarJoules(DaoSerializer.getDouble(_d, "total_solar_joules"));
|
||||
o.setFromGridJoules(DaoSerializer.getDouble(_d, "from_grid_joules"));
|
||||
o.setToGridJoules(DaoSerializer.getDouble(_d, "to_grid_joules"));
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergySummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.DateUtils;
|
||||
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class EnergySummarySerializer extends AbstractDaoSerializer<EnergySummary>
|
||||
{
|
||||
@Override
|
||||
public Class<EnergySummary> getSupportedClass()
|
||||
{
|
||||
return EnergySummary.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DaoProxyType> getSupportedProxies() {
|
||||
return Collections.singletonList(DaoProxyType.MONGO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoEntity toDaoEntity(EnergySummary _o)
|
||||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("_id", _o.getId());
|
||||
d.put("account_id", _o.getAccountId());
|
||||
d.put("group_id", _o.getGroupId());
|
||||
d.put("group_name", _o.getGroupName());
|
||||
d.put("view_mode", DaoSerializer.toEnumName(_o.getViewMode()));
|
||||
d.put("start", DaoSerializer.toLong(_o.getStart()));
|
||||
d.put("sub_groups", DaoSerializer.toDaoEntities(_o.getSubGroups(), DaoProxyType.MONGO));
|
||||
TimeZone tz = DateUtils.defaultTimeZone(_o.getTimeZone());
|
||||
d.put("timezone", tz.getID());
|
||||
if (_o.getEnergy() != null)
|
||||
d.put("energy", CollectionUtils.toByteArray(_o.getEnergy()));
|
||||
if (_o.getGridEnergy() != null)
|
||||
d.put("grid_energy", CollectionUtils.toByteArray(_o.getGridEnergy()));
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnergySummary fromDaoEntity(DaoEntity _d)
|
||||
{
|
||||
EnergySummary o = new EnergySummary();
|
||||
o.setGroupId(DaoSerializer.getString(_d, "group_id"));
|
||||
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||
o.setGroupName(DaoSerializer.getString(_d, "group_name"));
|
||||
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyViewMode.class));
|
||||
o.setStart(DaoSerializer.getDate(_d, "start"));
|
||||
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", EnergySummary.class));
|
||||
o.setTimeZone(DateUtils.fromTimeZoneId(DaoSerializer.getString(_d, "timezone")));
|
||||
o.setEnergy(CollectionUtils.toFloatArray(DaoSerializer.getByteArray(_d, "energy")));
|
||||
o.setGridEnergy(CollectionUtils.toFloatArray(DaoSerializer.getByteArray(_d, "grid_energy")));
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupSummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyTotal;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||
|
@ -9,12 +9,11 @@ import com.lanternsoftware.util.dao.DaoSerializer;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class BreakerGroupSummarySerializer extends AbstractDaoSerializer<BreakerGroupSummary> {
|
||||
public class EnergyTotalSerializer extends AbstractDaoSerializer<EnergyTotal> {
|
||||
@Override
|
||||
public Class<BreakerGroupSummary> getSupportedClass() {
|
||||
return BreakerGroupSummary.class;
|
||||
public Class<EnergyTotal> getSupportedClass() {
|
||||
return EnergyTotal.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,19 +22,16 @@ public class BreakerGroupSummarySerializer extends AbstractDaoSerializer<Breaker
|
|||
}
|
||||
|
||||
@Override
|
||||
public DaoEntity toDaoEntity(BreakerGroupSummary _o) {
|
||||
public DaoEntity toDaoEntity(EnergyTotal _o) {
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("_id", _o.getId());
|
||||
d.put("account_id", _o.getAccountId());
|
||||
d.put("group_id", _o.getGroupId());
|
||||
d.put("group_name", _o.getGroupName());
|
||||
d.put("view_mode", DaoSerializer.toEnumName(_o.getViewMode()));
|
||||
d.put("start", DaoSerializer.toLong(_o.getStart()));
|
||||
d.put("sub_groups", DaoSerializer.toDaoEntities(_o.getSubGroups(), DaoProxyType.MONGO));
|
||||
d.put("joules", _o.getJoules());
|
||||
d.put("charge", _o.getCharge());
|
||||
d.put("to_grid", _o.getToGrid());
|
||||
d.put("from_grid", _o.getFromGrid());
|
||||
d.put("flow", _o.getFlow());
|
||||
d.put("peak_to_grid", _o.getPeakToGrid());
|
||||
d.put("peak_from_grid", _o.getPeakFromGrid());
|
||||
d.put("peak_production", _o.getPeakProduction());
|
||||
|
@ -44,18 +40,15 @@ public class BreakerGroupSummarySerializer extends AbstractDaoSerializer<Breaker
|
|||
}
|
||||
|
||||
@Override
|
||||
public BreakerGroupSummary fromDaoEntity(DaoEntity _d) {
|
||||
BreakerGroupSummary o = new BreakerGroupSummary();
|
||||
public EnergyTotal fromDaoEntity(DaoEntity _d) {
|
||||
EnergyTotal o = new EnergyTotal();
|
||||
o.setGroupId(DaoSerializer.getString(_d, "group_id"));
|
||||
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||
o.setGroupName(DaoSerializer.getString(_d, "group_name"));
|
||||
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyBlockViewMode.class));
|
||||
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyViewMode.class));
|
||||
o.setStart(DaoSerializer.getDate(_d, "start"));
|
||||
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", BreakerGroupSummary.class));
|
||||
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", EnergyTotal.class));
|
||||
o.setJoules(DaoSerializer.getDouble(_d, "joules"));
|
||||
o.setCharge(DaoSerializer.getDouble(_d, "charge"));
|
||||
o.setToGrid(DaoSerializer.getDouble(_d, "to_grid"));
|
||||
o.setFromGrid(DaoSerializer.getDouble(_d, "from_grid"));
|
||||
o.setFlow(DaoSerializer.getDouble(_d, "flow"));
|
||||
o.setPeakToGrid(DaoSerializer.getDouble(_d, "peak_to_grid"));
|
||||
o.setPeakFromGrid(DaoSerializer.getDouble(_d, "peak_from_grid"));
|
||||
o.setPeakProduction(DaoSerializer.getDouble(_d, "peak_production"));
|
|
@ -26,6 +26,7 @@ public class HubPowerMinuteSerializer extends AbstractDaoSerializer<HubPowerMinu
|
|||
public DaoEntity toDaoEntity(HubPowerMinute _o)
|
||||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("_id", _o.getId());
|
||||
d.put("account_id", _o.getAccountId());
|
||||
d.put("hub", _o.getHub());
|
||||
d.put("minute", _o.getMinute());
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
com.lanternsoftware.datamodel.currentmonitor.dao.AccountSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BillingPlanSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BillingRateSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerConfigSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerGroupEnergySerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerGroupSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerGroupSummarySerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerHubSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerPanelSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerPowerMinuteSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerPowerSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.ChargeSummarySerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.ChargeTotalSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.EnergyBlockSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.EnergySummarySerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.EnergyTotalSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.HubPowerMinuteSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.MeterSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.NetworkStatusSerializer
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.lanternsoftware.currentmonitor.servlet;
|
||||
|
||||
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
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;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.util.Date;
|
||||
|
||||
@WebServlet("/charge/*")
|
||||
public class ChargeServlet extends SecureServlet {
|
||||
@Override
|
||||
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
String[] path = path(_req);
|
||||
if (path.length < 3) {
|
||||
_rep.setStatus(400);
|
||||
return;
|
||||
}
|
||||
int accountId = DaoSerializer.toInteger(CollectionUtils.getFirst(_authCode.getAllAccountIds()));
|
||||
if (accountId == 0) {
|
||||
_rep.setStatus(404);
|
||||
return;
|
||||
}
|
||||
EnergyViewMode viewMode = NullUtils.toEnum(EnergyViewMode.class, path[2], EnergyViewMode.DAY);
|
||||
Date start = new Date(NullUtils.toLong(path[3]));
|
||||
byte[] charges = Globals.dao.getChargeSummaryBinary(accountId, DaoSerializer.toInteger(path[0]), path[1], viewMode, start);
|
||||
if (charges == null)
|
||||
_rep.setStatus(404);
|
||||
else
|
||||
setResponseEntity(_rep, 200, MediaType.APPLICATION_OCTET_STREAM, charges);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.lanternsoftware.currentmonitor.servlet;
|
||||
|
||||
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
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;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.util.Date;
|
||||
|
||||
@WebServlet("/energy/*")
|
||||
public class EnergyServlet extends SecureServlet {
|
||||
@Override
|
||||
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
String[] path = path(_req);
|
||||
if (path.length < 3) {
|
||||
_rep.setStatus(400);
|
||||
return;
|
||||
}
|
||||
int accountId = DaoSerializer.toInteger(CollectionUtils.getFirst(_authCode.getAllAccountIds()));
|
||||
if (accountId == 0) {
|
||||
_rep.setStatus(404);
|
||||
return;
|
||||
}
|
||||
EnergyViewMode viewMode = NullUtils.toEnum(EnergyViewMode.class, path[1], EnergyViewMode.DAY);
|
||||
Date start = new Date(NullUtils.toLong(path[2]));
|
||||
byte[] energy = Globals.dao.getEnergySummaryBinary(accountId, path[0], viewMode, start);
|
||||
if (energy == null)
|
||||
_rep.setStatus(404);
|
||||
else
|
||||
setResponseEntity(_rep, 200, MediaType.APPLICATION_OCTET_STREAM, energy);
|
||||
}
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
package com.lanternsoftware.currentmonitor.servlet;
|
||||
|
||||
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.*;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.DateUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
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;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
@WebServlet("/energy/group/*")
|
||||
public class GroupEnergyServlet extends SecureServlet {
|
||||
|
@ -23,34 +23,31 @@ public class GroupEnergyServlet extends SecureServlet {
|
|||
_rep.setStatus(400);
|
||||
return;
|
||||
}
|
||||
EnergyBlockViewMode viewMode = NullUtils.toEnum(EnergyBlockViewMode.class, path[1], EnergyBlockViewMode.DAY);
|
||||
Date start = new Date(NullUtils.toLong(path[2]));
|
||||
if ((CollectionUtils.size(_authCode.getAllAccountIds()) == 1) && NullUtils.isEqual(CollectionUtils.get(path, 3), "bin")) {
|
||||
byte[] energy = Globals.dao.getBreakerGroupEnergyBinary(CollectionUtils.getFirst(_authCode.getAllAccountIds()), path[0], viewMode, start);
|
||||
if (energy == null)
|
||||
_rep.setStatus(404);
|
||||
else
|
||||
setResponseEntity(_rep, 200, MediaType.APPLICATION_OCTET_STREAM, energy);
|
||||
}
|
||||
List<BreakerGroupEnergy> energies = CollectionUtils.transform(_authCode.getAllAccountIds(), _id->Globals.dao.getBreakerGroupEnergy(_id, path[0], viewMode, start), true);
|
||||
if (CollectionUtils.isNotEmpty(energies)) {
|
||||
BreakerGroupEnergy energy;
|
||||
if (energies.size() > 1) {
|
||||
energy = new BreakerGroupEnergy();
|
||||
energy.setAccountId(_authCode.getAccountId());
|
||||
energy.setGroupId("Sites");
|
||||
energy.setGroupName("Sites");
|
||||
energy.setStart(start);
|
||||
energy.setViewMode(viewMode);
|
||||
energy.setSubGroups(CollectionUtils.asArrayList(energies));
|
||||
}
|
||||
else
|
||||
energy = CollectionUtils.getFirst(energies);
|
||||
if (NullUtils.isEqual(CollectionUtils.get(path, 3), "bin"))
|
||||
zipBsonResponse(_rep, energy);
|
||||
else
|
||||
jsonResponse(_rep, energy);
|
||||
} else
|
||||
int accountId = DaoSerializer.toInteger(CollectionUtils.getFirst(_authCode.getAllAccountIds()));
|
||||
if (accountId == 0) {
|
||||
_rep.setStatus(404);
|
||||
return;
|
||||
}
|
||||
EnergyViewMode viewMode = NullUtils.toEnum(EnergyViewMode.class, path[1], EnergyViewMode.DAY);
|
||||
Date start = new Date(NullUtils.toLong(path[2]));
|
||||
EnergySummary summary = Globals.dao.getEnergySummary(accountId, path[0], viewMode, start);
|
||||
if (summary == null)
|
||||
_rep.setStatus(404);
|
||||
else {
|
||||
BreakerConfig config = Globals.dao.getConfig(accountId);
|
||||
Account acct = Globals.dao.getAccount(accountId);
|
||||
TimeZone tz = DateUtils.fromTimeZoneId(acct.getTimezone(), "America/Chicago");
|
||||
List<BillingRate> rates = CollectionUtils.filter(config.getBillingRates(), _r->_r.isApplicableForDay(start, tz));
|
||||
Map<String, Integer> breakerGroupMeters = new HashMap<>();
|
||||
for (BreakerGroup group : config.getAllBreakerGroups()) {
|
||||
Breaker b = CollectionUtils.getFirst(group.getBreakers());
|
||||
if (b != null)
|
||||
breakerGroupMeters.put(group.getId(), b.getMeter());
|
||||
}
|
||||
BreakerGroupEnergy energy = new BreakerGroupEnergy(summary, rates, breakerGroupMeters);
|
||||
energy.setToGrid(-summary.flow(null, true, GridFlow.TO));
|
||||
energy.setFromGrid(summary.flow(null, true, GridFlow.FROM));
|
||||
setResponseEntity(_rep, 200, MediaType.APPLICATION_OCTET_STREAM, DaoSerializer.toZipBson(energy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ public class MongoRulesDataAccess implements RulesDataAccess {
|
|||
|
||||
@Override
|
||||
public void putFcmDevice(FcmDevice _device) {
|
||||
proxy.delete(FcmDevice.class, new DaoQuery("account_id", _device.getAccountId()).and("token", _device.getToken()));
|
||||
proxy.save(_device);
|
||||
}
|
||||
|
||||
|
|
|
@ -955,4 +955,48 @@ public class CollectionUtils {
|
|||
return 0;
|
||||
return _arr.length;
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(float[] _floats) {
|
||||
if ((_floats == null) || (_floats.length == 0))
|
||||
return null;
|
||||
ByteBuffer bb = ByteBuffer.allocate(_floats.length * 4);
|
||||
for (float f : _floats) {
|
||||
bb.putFloat(f);
|
||||
}
|
||||
return bb.array();
|
||||
}
|
||||
|
||||
public static float[] toFloatArray(byte[] _bytes) {
|
||||
if ((_bytes == null) || (_bytes.length == 0))
|
||||
return null;
|
||||
int offset = 0;
|
||||
float[] floats = new float[_bytes.length/4];
|
||||
ByteBuffer bb = ByteBuffer.wrap(_bytes);
|
||||
while (bb.hasRemaining()) {
|
||||
floats[offset++] = bb.getFloat();
|
||||
}
|
||||
return floats;
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(double[] _doubles) {
|
||||
if ((_doubles == null) || (_doubles.length == 0))
|
||||
return null;
|
||||
ByteBuffer bb = ByteBuffer.allocate(_doubles.length * 8);
|
||||
for (double d : _doubles) {
|
||||
bb.putDouble(d);
|
||||
}
|
||||
return bb.array();
|
||||
}
|
||||
|
||||
public static double[] toDoubleArray(byte[] _bytes) {
|
||||
if ((_bytes == null) || (_bytes.length == 0))
|
||||
return null;
|
||||
int offset = 0;
|
||||
double[] doubles = new double[_bytes.length/8];
|
||||
ByteBuffer bb = ByteBuffer.wrap(_bytes);
|
||||
while (bb.hasRemaining()) {
|
||||
doubles[offset++] = bb.getDouble();
|
||||
}
|
||||
return doubles;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.lanternsoftware.util;
|
|||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
@ -224,6 +226,11 @@ public abstract class DateUtils {
|
|||
return String.format("%d years", iYears);
|
||||
}
|
||||
|
||||
public static int getDaysBetween(Date _start, Date _end, TimeZone _tz) {
|
||||
ZoneId tz = _tz.toZoneId();
|
||||
return (int)ChronoUnit.DAYS.between(_start.toInstant().atZone(tz).toLocalDate(), _end.toInstant().atZone(tz).toLocalDate());
|
||||
}
|
||||
|
||||
public static int getMonthsBetween(Date _dtStart, Date _dtEnd) {
|
||||
Calendar calStart = getGMTCalendar(_dtStart.getTime());
|
||||
Calendar calEnd = getGMTCalendar(_dtEnd.getTime());
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package com.lanternsoftware.util.mutable;
|
||||
|
||||
public class MutableDouble {
|
||||
private double value;
|
||||
|
||||
public MutableDouble() {
|
||||
}
|
||||
|
||||
public MutableDouble(double _value) {
|
||||
value = _value;
|
||||
}
|
||||
|
||||
public double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(double _value) {
|
||||
value = _value;
|
||||
}
|
||||
|
||||
public void add(double _value) {
|
||||
value += _value;
|
||||
}
|
||||
|
||||
public void subtract(double _value) {
|
||||
value -= _value;
|
||||
}
|
||||
}
|
|
@ -3,12 +3,14 @@ package com.lanternsoftware.util.servlet;
|
|||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import freemarker.template.Configuration;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class FreemarkerServlet extends LanternServlet {
|
||||
|
@ -48,6 +50,16 @@ public abstract class FreemarkerServlet extends LanternServlet {
|
|||
|
||||
protected static DaoEntity model(HttpServletRequest _req) {
|
||||
DaoEntity model = new DaoEntity("context", _req.getContextPath());
|
||||
String linkPrefix = "";
|
||||
String[] path = getPath(_req);
|
||||
if (path.length > 1) {
|
||||
StringBuilder prefix = new StringBuilder();
|
||||
for(int i=0; i<path.length-1; i++) {
|
||||
prefix.append("../");
|
||||
}
|
||||
linkPrefix = prefix.toString();
|
||||
}
|
||||
model.put("link_prefix", linkPrefix);
|
||||
model.put("css_version", "1.0.0");
|
||||
return model;
|
||||
}
|
||||
|
@ -78,4 +90,46 @@ public abstract class FreemarkerServlet extends LanternServlet {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void ajaxRender(HttpServletResponse _rep, String _template, Map<String, Object> _templateModel) {
|
||||
ajaxRender(_rep, _template, _templateModel, null);
|
||||
}
|
||||
|
||||
protected void ajaxRender(HttpServletResponse _rep, String _templateName, Map<String, Object> _templateModel, Map<String, Object> _jsonRep) {
|
||||
ajaxHtml(_rep, FreemarkerUtil.render(getFreemarkerConfig(), _templateName, _templateModel), _jsonRep);
|
||||
|
||||
}
|
||||
|
||||
protected static void ajaxHtml(HttpServletResponse _rep, String _html) {
|
||||
ajaxHtml(_rep, _html, null);
|
||||
}
|
||||
|
||||
protected static void ajaxHtml(HttpServletResponse _rep, String _html, Map<String, Object> _model) {
|
||||
if (_model == null) {
|
||||
_model = new HashMap<>();
|
||||
}
|
||||
_model.put("html", _html);
|
||||
ajaxJson(_rep, _model);
|
||||
}
|
||||
|
||||
protected static void ajaxJson(HttpServletResponse _rep, Map<String, Object> _model) {
|
||||
DaoEntity json = new DaoEntity(_model);
|
||||
setResponseEntity(_rep, "application/json", DaoSerializer.toJson(json));
|
||||
}
|
||||
|
||||
protected void ajaxRedirect(HttpServletResponse _rep, String _url) {
|
||||
setResponseEntity(_rep, "application/json", DaoSerializer.toJson(new DaoEntity("redirect", _url)));
|
||||
}
|
||||
|
||||
protected void ajaxError(HttpServletResponse _rep, String _error) {
|
||||
ajaxError(_rep, _error, null);
|
||||
}
|
||||
|
||||
protected void ajaxError(HttpServletResponse _rep, String _error, DaoEntity _model) {
|
||||
if (_model == null) {
|
||||
_model = new DaoEntity();
|
||||
}
|
||||
_model.put("error", _error);
|
||||
setResponseEntity(_rep, "application/json", DaoSerializer.toJson(_model, false, false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
package com.lanternsoftware.zwave;
|
||||
|
||||
import com.lanternsoftware.dataaccess.currentmonitor.CurrentMonitorDao;
|
||||
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
|
||||
import com.lanternsoftware.datamodel.zwave.Switch;
|
||||
import com.lanternsoftware.datamodel.zwave.SwitchSchedule;
|
||||
import com.lanternsoftware.datamodel.zwave.ZWaveConfig;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.LanternFiles;
|
||||
import com.lanternsoftware.util.ResourceLoader;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||
import com.lanternsoftware.zwave.dao.MongoZWaveDao;
|
||||
|
||||
public class CreateConfig {
|
||||
public static void main(String[] args) {
|
||||
MongoZWaveDao dao = new MongoZWaveDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
|
||||
ZWaveConfig config = dao.getConfig(1);
|
||||
// ZWaveConfig cconfig = DaoSerializer.parse(ResourceLoader.loadFile(LanternFiles.OPS_PATH + "config - christmas lights.dat"), ZWaveConfig.class);
|
||||
// Switch c = CollectionUtils.filterOne(config.getSwitches(), _s->_s.getName().contains("hristm"));
|
||||
// CollectionUtils.filterMod(config.getSwitches(), _s->!_s.getRoom().equals("Treehouse"));
|
||||
// Switch treehouse = new Switch("Treehouse", "Interior", 14, true, true, null, 0);
|
||||
// Switch to = new Switch("Treehouse", "Floods", 15, true, true, null, 0);
|
||||
// Switch out = new Switch("Outside", "Repeater Outlet", 10, true, false, null, 0);
|
||||
// config.getSwitches().add(out);
|
||||
Switch c = CollectionUtils.filterOne(config.getSwitches(), _s->_s.getName().contains("Agitator"));
|
||||
c.setName("Septic Aerator");
|
||||
dao.putConfig(config);
|
||||
// if (c != null) {
|
||||
// c.setNodeId(8);
|
||||
// dao.putConfig(config);
|
||||
// }
|
||||
// ZWaveConfig config = DaoSerializer.parse(ResourceLoader.loadFile(LanternFiles.OPS_PATH + "config.dat"), ZWaveConfig.class);
|
||||
// config.setAccountId(1);
|
||||
// config.getSwitches().add(new Switch("Garage", "Septic Agitator", 12, 0, true, false, false, null, 0, Arrays.asList(new SwitchTransition(20))));
|
||||
// Switch thermo = CollectionUtils.filterOne(config.getSwitches(), _sw->_sw.getNodeId() == 0);
|
||||
// if (thermo != null)
|
||||
// thermo.setNodeId(100);
|
||||
// config.getSwitches().add(new Switch("Basement", "Temperature", 101, true, false, "https://basement.lanternsoftware.com/thermometer/temp", 0));
|
||||
|
||||
/* ZWaveConfig config = new ZWaveConfig();
|
||||
List<Switch> switches = new ArrayList<>();
|
||||
switches.add(new Switch("Basement", "Main", 3, true, true, null, 0));
|
||||
switches.add(new Switch("Basement", "Main", 5, false, true, null, 0));
|
||||
switches.add(new Switch("Basement", "Bar", 4, true, true, null, 0));
|
||||
switches.add(new Switch("Basement", "Bar", 6, false, true, null, 0));
|
||||
switches.add(new Switch("Master Bedroom", "Heater", 7, true, true, "https://thermometer.lanternsoftware.com/thermometer/temp", 0));
|
||||
switches.add(new Switch("Bruce's Room", "Heater", 8, true, true, "https://bruce.lanternsoftware.com/thermometer/temp", 0));
|
||||
switches.add(new Switch("Master Bedroom", "Heater", 9, false, true, "", 0));
|
||||
Switch out = new Switch("Outside", "Christmas Lights", 10, true, false, "", 0);
|
||||
out.setSchedule(CollectionUtils.asArrayList(
|
||||
new SwitchTransition(Calendar.FRIDAY, 12, 42, 0, 0),
|
||||
new SwitchTransition(Calendar.FRIDAY, 12, 42, 10, 0xFF),
|
||||
new SwitchTransition(Calendar.FRIDAY, 12, 42, 20, 0),
|
||||
new SwitchTransition(Calendar.FRIDAY, 12, 42, 30, 0xFF),
|
||||
new SwitchTransition(Calendar.FRIDAY, 12, 42, 40, 0),
|
||||
new SwitchTransition(Calendar.FRIDAY, 12, 42, 50, 0xFF)));
|
||||
switches.add(out);
|
||||
config.setSwitches(switches);
|
||||
*/
|
||||
// config.setSwitches(switches);
|
||||
// Switch sump = CollectionUtils.filterOne(config.getSwitches(), _c->_c.getNodeId() == 12);
|
||||
// SwitchSchedule transition = CollectionUtils.getFirst(sump.getSchedule());
|
||||
// transition.setLevel(0xFF);
|
||||
// transition.setMinutesPerHour(15);
|
||||
// dao.putConfig(config);
|
||||
dao.shutdown();
|
||||
// TimeZone tz = TimeZone.getTimeZone("America/Chicago");
|
||||
// Date next = transition.getNextTransition(tz);
|
||||
// System.out.println("Next Transition: " + DateUtils.format(tz, next, "hh:mm:ssa"));
|
||||
|
||||
// ResourceLoader.writeFile(LanternFiles.OPS_PATH + "config.dat", DaoSerializer.toJson(config));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user