mirror of
https://github.com/zyphlar/LanternPowerMonitor.git
synced 2024-03-08 14:07:47 +00:00
Improve 3A+ case, making it easier to take the pi out. Improve the fit of the Z2 case.
Make it possible for a hub to reload a config automatically when it changes without being restarted. Prevent the auto-calibration on first install from being stomped by the app. Allow updating the hub software via the app.
This commit is contained in:
parent
88ed044ef7
commit
ed75ab1f05
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3,7 +3,7 @@
|
|||
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||
<artifactId>lantern-currentmonitor</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0.4</version>
|
||||
<version>1.0.6</version>
|
||||
<name>lantern-currentmonitor</name>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -97,13 +97,18 @@ public class CurrentMonitor {
|
|||
}
|
||||
|
||||
public void monitorPower(BreakerHub _hub, List<Breaker> _breakers, int _intervalMs, PowerListener _listener) {
|
||||
try {
|
||||
stopMonitoring();
|
||||
listener = _listener;
|
||||
List<Breaker> validBreakers = CollectionUtils.filter(_breakers, _b->_b.getPort() > 0 && _b.getPort() < 16);
|
||||
List<Breaker> validBreakers = CollectionUtils.filter(_breakers, _b -> _b.getPort() > 0 && _b.getPort() < 16);
|
||||
sampler = new Sampler(_hub, validBreakers, _intervalMs, 2);
|
||||
LOG.info("Starting to monitor ports {}", CollectionUtils.transformToCommaSeparated(validBreakers, _b->String.valueOf(_b.getPort())));
|
||||
LOG.info("Starting to monitor ports {}", CollectionUtils.transformToCommaSeparated(validBreakers, _b -> String.valueOf(_b.getPort())));
|
||||
executor.submit(sampler);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.error("throwable", t);
|
||||
}
|
||||
}
|
||||
|
||||
private GpioPinAnalogInput getPin(int _chip, int _pin) {
|
||||
GpioPinAnalogInput pin;
|
||||
|
@ -182,9 +187,11 @@ public class CurrentMonitor {
|
|||
try {
|
||||
while (true) {
|
||||
synchronized (this) {
|
||||
if (!running)
|
||||
if (!running) {
|
||||
LOG.error("Power Monitoring Stopped");
|
||||
break;
|
||||
}
|
||||
}
|
||||
final Date readTime = new Date();
|
||||
final long intervalStart = (interval * intervalNs) + start;
|
||||
long intervalEnd = intervalStart + intervalNs;
|
||||
|
|
|
@ -10,6 +10,8 @@ import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
|||
import com.lanternsoftware.datamodel.currentmonitor.BreakerHub;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerPowerMinute;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommand;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommands;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubConfigCharacteristic;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubConfigService;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||
|
@ -25,6 +27,7 @@ import com.lanternsoftware.util.dao.DaoSerializer;
|
|||
import com.lanternsoftware.util.http.HttpPool;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
|
@ -39,10 +42,12 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -64,7 +69,7 @@ public class MonitorApp {
|
|||
private static final AtomicBoolean running = new AtomicBoolean(true);
|
||||
private static final CurrentMonitor monitor = new CurrentMonitor();
|
||||
private static final List<BreakerPower> readings = new ArrayList<>();
|
||||
private static final String version = getVersionNumber();
|
||||
private static String version;
|
||||
private static final PowerListener logger = _p -> {
|
||||
if (!config.isDebug()) {
|
||||
_p.setHubVersion(version);
|
||||
|
@ -76,21 +81,7 @@ public class MonitorApp {
|
|||
} else
|
||||
LOG.info("Panel{} - Space{} Power: {}W", _p.getPanel(), Breaker.toSpaceDisplay(_p.getSpace()), String.format("%.3f", _p.getPower()));
|
||||
};
|
||||
private static MqttPoster mqttPoster;
|
||||
|
||||
public static void main(String[] args) {
|
||||
config = DaoSerializer.parse(ResourceLoader.loadFileAsString(WORKING_DIR + "config.json"), MonitorConfig.class);
|
||||
if (config == null) {
|
||||
LOG.error("Failed to load config file from {}", WORKING_DIR + "config.json");
|
||||
return;
|
||||
}
|
||||
pool = new HttpPool(10, 10, config.getSocketTimeout(), config.getConnectTimeout(), config.getSocketTimeout());
|
||||
if (NullUtils.isNotEmpty(config.getHost()))
|
||||
host = NullUtils.terminateWith(config.getHost(), "/");
|
||||
monitor.setDebug(config.isDebug());
|
||||
monitor.start();
|
||||
LEDFlasher.setLEDOn(false);
|
||||
final BluetoothConfig bluetoothConfig = new BluetoothConfig("Lantern Hub", new BleCharacteristicListener() {
|
||||
private static final BleCharacteristicListener bluetoothListener = new BleCharacteristicListener() {
|
||||
@Override
|
||||
public void write(String _name, byte[] _value) {
|
||||
HubConfigCharacteristic ch = NullUtils.toEnum(HubConfigCharacteristic.class, _name);
|
||||
|
@ -162,6 +153,24 @@ public class MonitorApp {
|
|||
LOG.error("Exception occurred while trying to shutdown", _e);
|
||||
}
|
||||
break;
|
||||
case Update:
|
||||
monitor.submit(new UpdateChecker(true));
|
||||
break;
|
||||
case ReloadConfig:
|
||||
HttpGet get = new HttpGet(host + "config");
|
||||
get.addHeader("auth_code", authCode);
|
||||
BreakerConfig newConfig = DaoSerializer.parse(pool.executeToString(get), BreakerConfig.class);
|
||||
if (newConfig != null) {
|
||||
breakerConfig = newConfig;
|
||||
List<Breaker> breakers = breakerConfig.getBreakersForHub(config.getHub());
|
||||
BreakerHub hub = breakerConfig.getHub(config.getHub());
|
||||
if (hub != null) {
|
||||
LOG.info("Monitoring {} breakers for hub {}", CollectionUtils.size(breakers), hub.getHub());
|
||||
if (CollectionUtils.size(breakers) > 0)
|
||||
monitor.monitorPower(hub, breakers, 1000, logger);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -188,9 +197,34 @@ public class MonitorApp {
|
|||
log = Arrays.copyOfRange(log, log.length-15, log.length);
|
||||
return ZipUtils.zip(NullUtils.toByteArray(CollectionUtils.delimit(Arrays.asList(log), "\n")));
|
||||
}
|
||||
if (HubConfigCharacteristic.Version == ch)
|
||||
return NullUtils.toByteArray(version);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
};
|
||||
private static BluetoothConfig bluetoothConfig;
|
||||
private static MqttPoster mqttPoster;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[]{"systemctl","restart","dbus"});
|
||||
ConcurrencyUtils.sleep(500);
|
||||
} catch (IOException _e) {
|
||||
LOG.error("Exception occurred while trying to restart", _e);
|
||||
}
|
||||
version = getVersionNumber();
|
||||
config = DaoSerializer.parse(ResourceLoader.loadFileAsString(WORKING_DIR + "config.json"), MonitorConfig.class);
|
||||
if (config == null) {
|
||||
LOG.error("Failed to load config file from {}", WORKING_DIR + "config.json");
|
||||
return;
|
||||
}
|
||||
pool = new HttpPool(10, 10, config.getSocketTimeout(), config.getConnectTimeout(), config.getSocketTimeout());
|
||||
if (NullUtils.isNotEmpty(config.getHost()))
|
||||
host = NullUtils.terminateWith(config.getHost(), "/");
|
||||
monitor.setDebug(config.isDebug());
|
||||
monitor.start();
|
||||
LEDFlasher.setLEDOn(false);
|
||||
bluetoothConfig = new BluetoothConfig("Lantern Hub", bluetoothListener);
|
||||
bluetoothConfig.start();
|
||||
if (NullUtils.isNotEmpty(config.getAuthCode()))
|
||||
authCode = config.getAuthCode();
|
||||
|
@ -303,6 +337,7 @@ public class MonitorApp {
|
|||
if (!readings.isEmpty()) {
|
||||
mqttReadings.addAll(readings);
|
||||
post = new DaoEntity("readings", DaoSerializer.toDaoEntities(readings));
|
||||
post.put("hub", config.getHub());
|
||||
if (curMinute != lastMinute) {
|
||||
HubPowerMinute minute = new HubPowerMinute();
|
||||
minute.setAccountId(breakerConfig.getAccountId());
|
||||
|
@ -336,7 +371,8 @@ public class MonitorApp {
|
|||
}
|
||||
if (post != null) {
|
||||
byte[] payload = DaoSerializer.toZipBson(post);
|
||||
if (post(payload, "power/batch")) {
|
||||
PostResponse<HubCommands> resp = post(payload, "power/batch", HubCommands.class);
|
||||
if (resp.success) {
|
||||
File[] files = new File(WORKING_DIR + "cache").listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
|
@ -347,6 +383,11 @@ public class MonitorApp {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (resp.t != null) {
|
||||
for (HubCommand command : resp.t.getCommands()) {
|
||||
bluetoothListener.write(command.getCharacteristic().name(), command.getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +396,6 @@ public class MonitorApp {
|
|||
if (DateUtils.diffInSeconds(new Date(), lastUpdateCheck) >= config.getUpdateInterval()) {
|
||||
lastUpdateCheck = new Date();
|
||||
monitor.submit(new UpdateChecker());
|
||||
monitor.submit(new CommandChecker());
|
||||
}
|
||||
long now = new Date().getTime();
|
||||
long duration = (now - firstPost)%1000;
|
||||
|
@ -371,34 +411,65 @@ public class MonitorApp {
|
|||
}
|
||||
}
|
||||
|
||||
private static void uploadLog() {
|
||||
LOG.info("Commanded to upload log file, preparing...");
|
||||
String log = ResourceLoader.loadFileAsString(WORKING_DIR + "log/log.txt");
|
||||
if (NullUtils.isNotEmpty(log)) {
|
||||
DaoEntity payload = new DaoEntity("command", "log").and("payload", log);
|
||||
post(DaoSerializer.toZipBson(payload), "command");
|
||||
}
|
||||
private static boolean post(byte[] _payload, String _path) {
|
||||
return post(_payload, _path, Boolean.class).success;
|
||||
}
|
||||
|
||||
private static boolean post(byte[] _payload, String _path) {
|
||||
private static <T> PostResponse<T> post(byte[] _payload, String _path, Class<T> _class) {
|
||||
if (NullUtils.isEmpty(host))
|
||||
return false;
|
||||
return new PostResponse<>(false, null);
|
||||
HttpPost post = new HttpPost(host + _path);
|
||||
post.addHeader("auth_code", authCode);
|
||||
post.setEntity(new ByteArrayEntity(_payload, ContentType.APPLICATION_OCTET_STREAM));
|
||||
InputStream is = null;
|
||||
CloseableHttpResponse resp = pool.execute(post);
|
||||
try {
|
||||
return ((resp != null) && (resp.getStatusLine() != null) && (resp.getStatusLine().getStatusCode() == 200));
|
||||
} finally {
|
||||
if ((resp != null) && (resp.getStatusLine() != null) && (resp.getStatusLine().getStatusCode() == 200)) {
|
||||
T t = null;
|
||||
HttpEntity entity = resp.getEntity();
|
||||
if (entity != null) {
|
||||
is = entity.getContent();
|
||||
byte[] payload = IOUtils.toByteArray(is);
|
||||
if (CollectionUtils.length(payload) > 0)
|
||||
t = DaoSerializer.fromZipBson(payload, _class);
|
||||
}
|
||||
return new PostResponse<>(true, t);
|
||||
}
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to make http request to " + post.getURI().toString(), _e);
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
IOUtils.closeQuietly(resp);
|
||||
}
|
||||
return new PostResponse<>(false, null);
|
||||
}
|
||||
|
||||
private static class PostResponse<T> {
|
||||
public final boolean success;
|
||||
public final T t;
|
||||
|
||||
public PostResponse(boolean _success, T _t) {
|
||||
success = _success;
|
||||
t = _t;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class UpdateChecker implements Runnable {
|
||||
private final boolean force;
|
||||
|
||||
public UpdateChecker() {
|
||||
force = false;
|
||||
}
|
||||
|
||||
public UpdateChecker(boolean _force) {
|
||||
force = _force;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (NullUtils.isNotEmpty(host) && config.isAutoUpdate()) {
|
||||
if (NullUtils.isNotEmpty(host) && (force || config.isAutoUpdate())) {
|
||||
DaoEntity meta = DaoSerializer.fromZipBson(pool.executeToByteArray(new HttpGet(host + "update/version")));
|
||||
String newVersion = DaoSerializer.getString(meta, "version");
|
||||
if (NullUtils.isNotEqual(newVersion, version)) {
|
||||
|
@ -407,9 +478,14 @@ public class MonitorApp {
|
|||
if (CollectionUtils.length(jar) == DaoSerializer.getInteger(meta, "size") && NullUtils.isEqual(DigestUtils.md5Hex(jar), DaoSerializer.getString(meta, "checksum"))) {
|
||||
LOG.info("Update downloaded, writing jar and restarting...");
|
||||
ResourceLoader.writeFile(WORKING_DIR + "lantern-currentmonitor.jar", jar);
|
||||
ConcurrencyUtils.sleep(10000);
|
||||
synchronized (running) {
|
||||
running.set(false);
|
||||
}
|
||||
monitor.stopMonitoring();
|
||||
bluetoothConfig.stop();
|
||||
pool.shutdown();
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[]{"systemctl", "restart", "currentmonitor"});
|
||||
Runtime.getRuntime().exec(new String[]{"systemctl","restart","currentmonitor"});
|
||||
} catch (IOException _e) {
|
||||
LOG.error("Exception occurred while trying to restart", _e);
|
||||
}
|
||||
|
@ -419,65 +495,29 @@ public class MonitorApp {
|
|||
}
|
||||
}
|
||||
|
||||
private static final class CommandChecker implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
if (NullUtils.isNotEmpty(host)) {
|
||||
HttpGet get = new HttpGet(host + "command");
|
||||
get.addHeader("auth_code", authCode);
|
||||
DaoEntity meta = DaoSerializer.fromZipBson(pool.executeToByteArray(get));
|
||||
for (String command : DaoSerializer.getList(meta, "commands", String.class)) {
|
||||
if (NullUtils.isEqual(command, "log")) {
|
||||
uploadLog();
|
||||
} else if (NullUtils.makeNotNull(command).startsWith("timeout")) {
|
||||
LOG.info("Updating timeouts...");
|
||||
String[] timeouts = NullUtils.cleanSplit(command, "-");
|
||||
if (CollectionUtils.size(timeouts) != 3)
|
||||
continue;
|
||||
config.setConnectTimeout(DaoSerializer.toInteger(timeouts[1]));
|
||||
config.setSocketTimeout(DaoSerializer.toInteger(timeouts[2]));
|
||||
HttpPool old = pool;
|
||||
pool = new HttpPool(10, 10, config.getSocketTimeout(), config.getConnectTimeout(), config.getSocketTimeout());
|
||||
old.shutdown();
|
||||
ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config));
|
||||
} else if (NullUtils.isEqual(command, "extend_filesystem")) {
|
||||
LOG.info("Extending filesystem and rebooting");
|
||||
public static String getVersionNumber() {
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[]{"sudo", "raspi-config", "--expand-rootfs"});
|
||||
ConcurrencyUtils.sleep(5000);
|
||||
Runtime.getRuntime().exec(new String[]{"reboot", "now"});
|
||||
} catch (IOException _e) {
|
||||
LOG.error("Exception occurred while trying to extend filesystem", _e);
|
||||
}
|
||||
} else if (NullUtils.isEqual(command, "restart")) {
|
||||
LOG.info("Restarting...");
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[]{"systemctl", "restart", "currentmonitor"});
|
||||
} catch (IOException _e) {
|
||||
LOG.error("Exception occurred while trying to restart", _e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getVersionNumber() {
|
||||
Enumeration<URL> resources = MonitorApp.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
|
||||
while (resources.hasMoreElements()) {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = MonitorApp.class.getResourceAsStream("/META-INF/MANIFEST.MF");
|
||||
is = resources.nextElement().openStream();
|
||||
Manifest manifest = new Manifest(is);
|
||||
Attributes attr = manifest.getMainAttributes();
|
||||
if (NullUtils.isEqual(attr.getValue("Specification-Title"), "Lantern Power Monitor")) {
|
||||
String version = attr.getValue("Specification-Version");
|
||||
LOG.info("Current Version: {}", version);
|
||||
return version;
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to get current version number", _e);
|
||||
return "";
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception _e) {
|
||||
LOG.error("Failed to get current version number", _e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.lanternsoftware.dataaccess.currentmonitor;
|
|||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||
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.Sequence;
|
||||
|
@ -10,14 +12,15 @@ import com.lanternsoftware.datamodel.rules.FcmDevice;
|
|||
import com.lanternsoftware.datamodel.rules.Rule;
|
||||
import com.lanternsoftware.util.DebugTimer;
|
||||
import com.lanternsoftware.util.LanternFiles;
|
||||
import com.lanternsoftware.util.dao.DaoQuery;
|
||||
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Backup {
|
||||
public static void main(String[] args) {
|
||||
CurrentMonitorDao dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
|
||||
CurrentMonitorDao backupDao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.BACKUP_PATH + "mongo.cfg"));
|
||||
CurrentMonitorDao dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.BACKUP_SOURCE + "mongo.cfg"));
|
||||
CurrentMonitorDao backupDao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.BACKUP_DEST + "mongo.cfg"));
|
||||
|
||||
DebugTimer t1 = new DebugTimer("Query Accounts");
|
||||
List<Account> accounts = dao.getProxy().queryAll(Account.class);
|
||||
|
@ -34,17 +37,39 @@ public class Backup {
|
|||
t4.stop();
|
||||
|
||||
DebugTimer t5 = new DebugTimer("Query Energy");
|
||||
List<EnergySummary> energy = dao.getProxy().queryAll(EnergySummary.class);
|
||||
t5.stop();
|
||||
DebugTimer t6 = new DebugTimer("Save Energy");
|
||||
for (Account a : accounts) {
|
||||
List<EnergySummary> energy = dao.getProxy().query(EnergySummary.class, new DaoQuery("account_id", a.getId()));
|
||||
DebugTimer t = new DebugTimer("Save Energy");
|
||||
backupDao.getProxy().save(energy);
|
||||
t.stop();
|
||||
}
|
||||
t5.stop();
|
||||
|
||||
DebugTimer t6 = new DebugTimer("Query Energy Totals");
|
||||
for (Account a : accounts) {
|
||||
List<EnergyTotal> total = dao.getProxy().query(EnergyTotal.class, new DaoQuery("account_id", a.getId()));
|
||||
DebugTimer t = new DebugTimer("Save Summary");
|
||||
backupDao.getProxy().save(total);
|
||||
t.stop();
|
||||
}
|
||||
t6.stop();
|
||||
|
||||
DebugTimer t7 = new DebugTimer("Query Summaries");
|
||||
List<EnergyTotal> summary = dao.getProxy().queryAll(EnergyTotal.class);
|
||||
DebugTimer t7 = new DebugTimer("Query Charges");
|
||||
for (Account a : accounts) {
|
||||
List<ChargeSummary> charges = dao.getProxy().query(ChargeSummary.class, new DaoQuery("account_id", a.getId()));
|
||||
DebugTimer t = new DebugTimer("Save Charges");
|
||||
backupDao.getProxy().save(charges);
|
||||
t.stop();
|
||||
}
|
||||
t7.stop();
|
||||
DebugTimer t8 = new DebugTimer("Save Summaries");
|
||||
backupDao.getProxy().save(summary);
|
||||
|
||||
DebugTimer t8 = new DebugTimer("Query Charge Totals");
|
||||
for (Account a : accounts) {
|
||||
List<ChargeTotal> charges = dao.getProxy().query(ChargeTotal.class, new DaoQuery("account_id", a.getId()));
|
||||
DebugTimer t = new DebugTimer("Save Charge Totals");
|
||||
backupDao.getProxy().save(charges);
|
||||
t.stop();
|
||||
}
|
||||
t8.stop();
|
||||
|
||||
DebugTimer t9 = new DebugTimer("Query Events");
|
||||
|
|
|
@ -16,8 +16,8 @@ import java.util.TimeZone;
|
|||
|
||||
public class BackupMinutes {
|
||||
public static void main(String[] args) {
|
||||
CurrentMonitorDao dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
|
||||
CurrentMonitorDao backupDao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.BACKUP_PATH + "mongo.cfg"));
|
||||
CurrentMonitorDao dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.BACKUP_SOURCE + "mongo.cfg"));
|
||||
CurrentMonitorDao backupDao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.BACKUP_DEST + "mongo.cfg"));
|
||||
Date now = new Date();
|
||||
for (Account a : dao.getProxy().queryAll(Account.class)) {
|
||||
if (a.getId() == 0)
|
||||
|
@ -30,12 +30,11 @@ public class BackupMinutes {
|
|||
HubPowerMinute minute = dao.getProxy().queryOne(HubPowerMinute.class, new DaoQuery("account_id", a.getId()), DaoSort.sort("minute"));
|
||||
if (minute == null)
|
||||
continue;
|
||||
Date minStart = DateUtils.addDays(DateUtils.getMidnightBeforeNow(tz), -60, tz);
|
||||
Date start = DateUtils.getMidnightBefore(minute.getMinuteAsDate(), tz);
|
||||
if (minStart.after(start))
|
||||
start = minStart;
|
||||
HubPowerMinute lastBackup = backupDao.getProxy().queryOne(HubPowerMinute.class, new DaoQuery("account_id", a.getId()), DaoSort.sortDesc("minute"));
|
||||
Date start = lastBackup == null ? DateUtils.getMidnightBefore(minute.getMinuteAsDate(), tz) : lastBackup.getMinuteAsDate();
|
||||
// Date start = DateUtils.date(10,16,2021,tz);
|
||||
Date end = DateUtils.addDays(start, 1, tz);
|
||||
while (end.before(now)) {
|
||||
while (start.before(now)) {
|
||||
DebugTimer t2 = new DebugTimer("Account Id: " + a.getId() + " Query Day " + DateUtils.format("MM/dd/yyyy", tz, start));
|
||||
List<HubPowerMinute> minutes = dao.getProxy().query(HubPowerMinute.class, new DaoQuery("account_id", a.getId()).andBetweenInclusiveExclusive("minute", (int) (start.getTime() / 60000), (int) (end.getTime() / 60000)));
|
||||
t2.stop();
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
|||
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergySummary;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.EnergyViewMode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommand;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.util.dao.mongo.MongoProxy;
|
||||
|
@ -48,5 +49,9 @@ public interface CurrentMonitorDao {
|
|||
TimeZone getTimeZoneForAccount(int _accountId);
|
||||
String getTimeZoneForAccount(String _authCode);
|
||||
|
||||
void putHubCommand(HubCommand _command);
|
||||
List<HubCommand> getAllHubCommands();
|
||||
void deleteHubCommand(String _id);
|
||||
|
||||
MongoProxy getProxy();
|
||||
}
|
||||
|
|
|
@ -6,12 +6,14 @@ 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.BreakerHub;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||
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.HubCommand;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Sequence;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
|
@ -404,6 +406,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
if (config == null) {
|
||||
config = new BreakerConfig();
|
||||
config.setAccountId(_authCode.getAccountId());
|
||||
config.setVersion(config.getVersion());
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
@ -416,6 +419,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
config.setMeters(CollectionUtils.aggregate(configs, BreakerConfig::getMeters));
|
||||
config.setBillingPlans(CollectionUtils.aggregate(configs, BreakerConfig::getBillingPlans));
|
||||
config.setBillingRates(CollectionUtils.aggregate(configs, BreakerConfig::getBillingRates));
|
||||
config.setVersion(CollectionUtils.getLargest(CollectionUtils.transform(configs, BreakerConfig::getVersion)));
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -424,6 +428,16 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
DaoQuery configQuery = new DaoQuery("_id", String.valueOf(_config.getAccountId()));
|
||||
BreakerConfig oldConfig = proxy.queryOne(BreakerConfig.class, configQuery);
|
||||
if (oldConfig != null) {
|
||||
logger.info("old version: {}, new version: {}", oldConfig.getVersion(), _config.getVersion());
|
||||
if (oldConfig.getVersion() > _config.getVersion()) {
|
||||
for (BreakerHub hub : CollectionUtils.makeNotNull(_config.getBreakerHubs())) {
|
||||
BreakerHub oldHub = oldConfig.getHub(hub.getHub());
|
||||
if (oldHub != null) {
|
||||
logger.info("Prevent overwrite of voltage calibration");
|
||||
hub.setVoltageCalibrationFactor(oldHub.getRawVoltageCalibrationFactor());
|
||||
}
|
||||
}
|
||||
}
|
||||
_config.setVersion(oldConfig.getVersion() + 1);
|
||||
if (NullUtils.isNotIdentical(_config, oldConfig)) {
|
||||
DaoEntity oldEntity = DaoSerializer.toDaoEntity(oldConfig);
|
||||
|
@ -441,6 +455,9 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
});
|
||||
}
|
||||
}
|
||||
for (BreakerHub hub : CollectionUtils.makeNotNull(_config.getBreakerHubs())) {
|
||||
logger.info("voltage calibration hub {}: {}", hub.getHub(), hub.getVoltageCalibrationFactor());
|
||||
}
|
||||
proxy.save(_config);
|
||||
}
|
||||
|
||||
|
@ -459,7 +476,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
AuthCode code = decryptAuthCode(_authCode);
|
||||
if (code == null)
|
||||
return null;
|
||||
return proxy.queryOne(Account.class, new DaoQuery("_id", code.getAccountId()));
|
||||
return proxy.queryOne(Account.class, new DaoQuery("_id", String.valueOf(code.getAccountId())));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -572,6 +589,23 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putHubCommand(HubCommand _command) {
|
||||
BreakerConfig config = getConfig(_command.getAccountId());
|
||||
if (config != null)
|
||||
proxy.save(_command.forAllHubs(config));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HubCommand> getAllHubCommands() {
|
||||
return proxy.queryAll(HubCommand.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteHubCommand(String _id) {
|
||||
proxy.delete(HubCommand.class, new DaoQuery("_id", _id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoProxy getProxy() {
|
||||
return proxy;
|
||||
|
|
|
@ -209,7 +209,7 @@ public class BreakerConfig implements IIdentical<BreakerConfig> {
|
|||
@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(billingPlans, _o.billingPlans);
|
||||
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.isIdentical(billingPlans, _o.billingPlans);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,7 +6,7 @@ import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
|||
|
||||
import java.util.Objects;
|
||||
|
||||
@DBSerializable
|
||||
@DBSerializable(autogen = false)
|
||||
public class BreakerHub implements IIdentical<BreakerHub> {
|
||||
private int hub;
|
||||
private double voltageCalibrationFactor;
|
||||
|
@ -22,16 +22,24 @@ public class BreakerHub implements IIdentical<BreakerHub> {
|
|||
hub = _hub;
|
||||
}
|
||||
|
||||
public double getRawVoltageCalibrationFactor() {
|
||||
return voltageCalibrationFactor;
|
||||
}
|
||||
|
||||
public double getVoltageCalibrationFactor() {
|
||||
return voltageCalibrationFactor == 0.0?1.0:voltageCalibrationFactor;
|
||||
return voltageCalibrationFactor == 0.0?0.3445:voltageCalibrationFactor;
|
||||
}
|
||||
|
||||
public void setVoltageCalibrationFactor(double _voltageCalibrationFactor) {
|
||||
voltageCalibrationFactor = _voltageCalibrationFactor;
|
||||
}
|
||||
|
||||
public double getRawPortCalibrationFactor() {
|
||||
return portCalibrationFactor;
|
||||
}
|
||||
|
||||
public double getPortCalibrationFactor() {
|
||||
return portCalibrationFactor == 0.0?1.0:portCalibrationFactor;
|
||||
return portCalibrationFactor == 0.0?1.25:portCalibrationFactor;
|
||||
}
|
||||
|
||||
public void setPortCalibrationFactor(double _portCalibrationFactor) {
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor;
|
||||
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
import com.lanternsoftware.util.dao.annotations.PrimaryKey;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@DBSerializable
|
||||
public class HubCommand {
|
||||
@PrimaryKey private String id;
|
||||
private int accountId;
|
||||
private int hub;
|
||||
private Date created;
|
||||
private HubConfigCharacteristic characteristic;
|
||||
private byte[] data;
|
||||
|
||||
public HubCommand() {
|
||||
}
|
||||
|
||||
public HubCommand(int _accountId, HubConfigCharacteristic _characteristic, byte[] _data) {
|
||||
accountId = _accountId;
|
||||
created = new Date();
|
||||
characteristic = _characteristic;
|
||||
data = _data;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String _id) {
|
||||
id = _id;
|
||||
}
|
||||
|
||||
public int getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(int _accountId) {
|
||||
accountId = _accountId;
|
||||
}
|
||||
|
||||
public int getHub() {
|
||||
return hub;
|
||||
}
|
||||
|
||||
public void setHub(int _hub) {
|
||||
hub = _hub;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Date _created) {
|
||||
created = _created;
|
||||
}
|
||||
|
||||
public HubConfigCharacteristic getCharacteristic() {
|
||||
return characteristic;
|
||||
}
|
||||
|
||||
public void setCharacteristic(HubConfigCharacteristic _characteristic) {
|
||||
characteristic = _characteristic;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] _data) {
|
||||
data = _data;
|
||||
}
|
||||
|
||||
public List<HubCommand> forAllHubs(BreakerConfig _config) {
|
||||
return CollectionUtils.transform(_config.getBreakerHubs(), _h->forHub(_h.getHub()));
|
||||
}
|
||||
|
||||
public HubCommand forHub(int _hub) {
|
||||
HubCommand c = new HubCommand();
|
||||
c.setAccountId(accountId);
|
||||
c.setHub(_hub);
|
||||
c.setCreated(created);
|
||||
c.setCharacteristic(characteristic);
|
||||
c.setData(data);
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object _o) {
|
||||
if (this == _o) return true;
|
||||
if (_o == null || getClass() != _o.getClass()) return false;
|
||||
HubCommand that = (HubCommand) _o;
|
||||
return Objects.equals(id, that.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor;
|
||||
|
||||
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@DBSerializable
|
||||
public class HubCommands {
|
||||
private List<HubCommand> commands;
|
||||
|
||||
public HubCommands() {
|
||||
}
|
||||
|
||||
public HubCommands(List<HubCommand> _commands) {
|
||||
commands = _commands;
|
||||
}
|
||||
|
||||
public List<HubCommand> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
public void setCommands(List<HubCommand> _commands) {
|
||||
commands = _commands;
|
||||
}
|
||||
}
|
|
@ -18,7 +18,10 @@ public enum HubConfigCharacteristic {
|
|||
Host(10, CharacteristicFlag.WRITE),
|
||||
Log(11, CharacteristicFlag.READ),
|
||||
NetworkDetails(12, CharacteristicFlag.READ),
|
||||
Shutdown(13, CharacteristicFlag.WRITE);
|
||||
Shutdown(13, CharacteristicFlag.WRITE),
|
||||
Version(14, CharacteristicFlag.READ),
|
||||
Update(15, CharacteristicFlag.WRITE),
|
||||
ReloadConfig(15, CharacteristicFlag.WRITE);
|
||||
|
||||
public final int idx;
|
||||
public final UUID uuid;
|
||||
|
|
|
@ -7,7 +7,6 @@ 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;
|
||||
|
||||
|
@ -31,7 +30,6 @@ public class BillingRateSerializer extends AbstractDaoSerializer<BillingRate>
|
|||
d.put("meter", _o.getMeter());
|
||||
d.put("flow", DaoSerializer.toEnumName(_o.getFlow()));
|
||||
d.put("rate", _o.getRate());
|
||||
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());
|
||||
|
@ -51,8 +49,6 @@ public class BillingRateSerializer extends AbstractDaoSerializer<BillingRate>
|
|||
o.setFlow(DaoSerializer.getEnum(_d, "flow", GridFlow.class));
|
||||
o.setRate(DaoSerializer.getDouble(_d, "rate"));
|
||||
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"));
|
||||
|
|
|
@ -26,8 +26,8 @@ public class BreakerHubSerializer extends AbstractDaoSerializer<BreakerHub>
|
|||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("hub", _o.getHub());
|
||||
d.put("voltage_calibration_factor", _o.getVoltageCalibrationFactor());
|
||||
d.put("port_calibration_factor", _o.getPortCalibrationFactor());
|
||||
d.put("voltage_calibration_factor", _o.getRawVoltageCalibrationFactor());
|
||||
d.put("port_calibration_factor", _o.getRawPortCalibrationFactor());
|
||||
d.put("frequency", _o.getFrequency());
|
||||
d.put("bluetooth_mac", _o.getBluetoothMac());
|
||||
return d;
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommand;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubConfigCharacteristic;
|
||||
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 HubCommandSerializer extends AbstractDaoSerializer<HubCommand>
|
||||
{
|
||||
@Override
|
||||
public Class<HubCommand> getSupportedClass()
|
||||
{
|
||||
return HubCommand.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DaoProxyType> getSupportedProxies() {
|
||||
return Collections.singletonList(DaoProxyType.MONGO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoEntity toDaoEntity(HubCommand _o)
|
||||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
if (_o.getId() != null)
|
||||
d.put("_id", _o.getId());
|
||||
d.put("account_id", _o.getAccountId());
|
||||
d.put("hub", _o.getHub());
|
||||
d.put("created", DaoSerializer.toLong(_o.getCreated()));
|
||||
d.put("characteristic", DaoSerializer.toEnumName(_o.getCharacteristic()));
|
||||
d.put("data", _o.getData());
|
||||
return d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HubCommand fromDaoEntity(DaoEntity _d)
|
||||
{
|
||||
HubCommand o = new HubCommand();
|
||||
o.setId(DaoSerializer.getString(_d, "_id"));
|
||||
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||
o.setHub(DaoSerializer.getInteger(_d, "hub"));
|
||||
o.setCreated(DaoSerializer.getDate(_d, "created"));
|
||||
o.setCharacteristic(DaoSerializer.getEnum(_d, "characteristic", HubConfigCharacteristic.class));
|
||||
o.setData(DaoSerializer.getByteArray(_d, "data"));
|
||||
return o;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommand;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommands;
|
||||
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 HubCommandsSerializer extends AbstractDaoSerializer<HubCommands>
|
||||
{
|
||||
@Override
|
||||
public Class<HubCommands> getSupportedClass()
|
||||
{
|
||||
return HubCommands.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DaoProxyType> getSupportedProxies() {
|
||||
return Collections.singletonList(DaoProxyType.MONGO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoEntity toDaoEntity(HubCommands _o)
|
||||
{
|
||||
DaoEntity d = new DaoEntity();
|
||||
d.put("commands", DaoSerializer.toDaoEntities(_o.getCommands(), DaoProxyType.MONGO));
|
||||
return d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HubCommands fromDaoEntity(DaoEntity _d)
|
||||
{
|
||||
HubCommands o = new HubCommands();
|
||||
o.setCommands(DaoSerializer.getList(_d, "commands", HubCommand.class));
|
||||
return o;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@ 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.HubCommandSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.HubCommandsSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.HubPowerMinuteSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.MeterSerializer
|
||||
com.lanternsoftware.datamodel.currentmonitor.dao.NetworkStatusSerializer
|
||||
|
|
|
@ -2,20 +2,31 @@ package com.lanternsoftware.currentmonitor.context;
|
|||
|
||||
import com.lanternsoftware.dataaccess.currentmonitor.CurrentMonitorDao;
|
||||
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommand;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommands;
|
||||
import com.lanternsoftware.rules.RulesEngine;
|
||||
import com.lanternsoftware.util.DateUtils;
|
||||
import com.lanternsoftware.util.LanternFiles;
|
||||
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class Globals implements ServletContextListener {
|
||||
public static CurrentMonitorDao dao;
|
||||
private static final Map<Integer, Map<Integer, List<HubCommand>>> commands = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
|
||||
RulesEngine.instance().start();
|
||||
RulesEngine.instance().schedule(new CommandTask(), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,4 +34,38 @@ public class Globals implements ServletContextListener {
|
|||
dao.shutdown();
|
||||
RulesEngine.shutdown();
|
||||
}
|
||||
|
||||
public static HubCommands getCommandsForHub(int _accountId, int _hub) {
|
||||
List<HubCommand> c = null;
|
||||
synchronized (commands) {
|
||||
Map<Integer, List<HubCommand>> hubCommands = commands.get(_accountId);
|
||||
if (hubCommands != null)
|
||||
c = hubCommands.remove(_hub);
|
||||
}
|
||||
if (c != null) {
|
||||
for (HubCommand command : c) {
|
||||
dao.deleteHubCommand(command.getId());
|
||||
}
|
||||
return new HubCommands(c);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class CommandTask extends TimerTask {
|
||||
@Override
|
||||
public void run() {
|
||||
List<HubCommand> c = Globals.dao.getAllHubCommands();
|
||||
Date stale = DateUtils.addMinutes(new Date(), -5);
|
||||
synchronized (commands) {
|
||||
commands.clear();
|
||||
for (HubCommand command : c) {
|
||||
if (DateUtils.isBefore(command.getCreated(), stale))
|
||||
dao.deleteHubCommand(command.getId());
|
||||
else
|
||||
commands.computeIfAbsent(command.getAccountId(), _t -> new HashMap<>()).computeIfAbsent(command.getHub(), _h->new ArrayList<>()).add(command);
|
||||
}
|
||||
}
|
||||
RulesEngine.instance().schedule(new CommandTask(), 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,11 +44,8 @@ public class AuthServlet extends LanternServlet {
|
|||
GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(transport, new GsonFactory(), "https://oauth2.googleapis.com/token", googleClientId, googleClientSecret, auth.getPassword(), "").execute();
|
||||
if (tokenResponse != null) {
|
||||
GoogleIdToken idToken = tokenResponse.parseIdToken();
|
||||
if (idToken != null) {
|
||||
logger.info("Successfully received google id token");
|
||||
if (idToken != null)
|
||||
authCode = Globals.dao.getAuthCodeForEmail(idToken.getPayload().getEmail(), DateUtils.fromTimeZoneId(_req.getHeader("timezone")));
|
||||
logger.info("Auth code for google user is valid: " + (authCode != null));
|
||||
}
|
||||
}
|
||||
} catch (Exception _e) {
|
||||
logger.error("Failed to validate google auth code", _e);
|
||||
|
|
|
@ -1,49 +1,19 @@
|
|||
package com.lanternsoftware.currentmonitor.servlet;
|
||||
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.LanternFiles;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.ResourceLoader;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@WebServlet("/command")
|
||||
public class CommandServlet extends SecureServlet {
|
||||
|
||||
@Override
|
||||
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
File folder = new File(LanternFiles.OPS_PATH + _authCode.getAccountId());
|
||||
List<String> commands = new ArrayList<>();
|
||||
if (folder.exists() && folder.isDirectory()) {
|
||||
for (File command : CollectionUtils.asArrayList(folder.listFiles())) {
|
||||
if (command.isDirectory())
|
||||
continue;
|
||||
String c = command.getName();
|
||||
String extension = NullUtils.after(c, ".");
|
||||
if (NullUtils.isNotEmpty(extension))
|
||||
c = c.replace("." + extension, "");
|
||||
commands.add(c);
|
||||
}
|
||||
}
|
||||
zipBsonResponse(_rep, new DaoEntity("commands", commands));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
DaoEntity payload = getRequestZipBson(_req);
|
||||
if (payload == null)
|
||||
return;
|
||||
String command = DaoSerializer.getString(payload, "command");
|
||||
String path = LanternFiles.OPS_PATH + _authCode.getAccountId() + File.separator + "payload" + File.separator;
|
||||
new File(path).mkdirs();
|
||||
ResourceLoader.writeFile(path+ command + ".txt", DaoSerializer.getString(payload, "payload"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.lanternsoftware.currentmonitor.servlet;
|
|||
|
||||
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommand;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubConfigCharacteristic;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -34,6 +36,10 @@ public class ConfigServlet extends SecureServlet {
|
|||
return;
|
||||
}
|
||||
logger.info("Received config for account {}", config.getAccountId());
|
||||
BreakerConfig oldConfig = Globals.dao.getConfig(config.getAccountId());
|
||||
if ((oldConfig == null) || !oldConfig.isIdentical(config))
|
||||
Globals.dao.putHubCommand(new HubCommand(config.getAccountId(), HubConfigCharacteristic.ReloadConfig, null));
|
||||
Globals.dao.putConfig(config);
|
||||
zipBsonResponse(_rep, Globals.dao.getMergedConfig(_authCode));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package com.lanternsoftware.currentmonitor.servlet;
|
||||
|
||||
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubCommands;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -15,6 +20,8 @@ import java.util.List;
|
|||
|
||||
@WebServlet("/power/*")
|
||||
public class PowerServlet extends SecureServlet {
|
||||
private static final Logger logger = LoggerFactory.getLogger(MongoCurrentMonitorDao.class);
|
||||
|
||||
@Override
|
||||
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
String[] path = path(_req);
|
||||
|
@ -32,19 +39,29 @@ public class PowerServlet extends SecureServlet {
|
|||
String[] path = path(_req);
|
||||
if ((path.length > 0) && NullUtils.isEqual(CollectionUtils.get(path, 0), "hub")) {
|
||||
HubPowerMinute m = getRequestPayload(_req, HubPowerMinute.class);
|
||||
if (m == null)
|
||||
return;
|
||||
logger.info("Hub Power from ip {}, account {}, hub {}", _req.getRemoteAddr(), m.getAccountId(), m.getHub());
|
||||
m.setAccountId(_authCode.getAccountId());
|
||||
Globals.dao.putHubPowerMinute(m);
|
||||
return;
|
||||
}
|
||||
if ((path.length > 0) && NullUtils.isEqual(CollectionUtils.get(path, 0), "batch")) {
|
||||
List<BreakerPower> powers = DaoSerializer.getList(getRequestZipBson(_req), "readings", BreakerPower.class);
|
||||
DaoEntity payload = getRequestZipBson(_req);
|
||||
List<BreakerPower> powers = DaoSerializer.getList(payload, "readings", BreakerPower.class);
|
||||
if (!powers.isEmpty()) {
|
||||
CollectionUtils.edit(powers, _p->_p.setAccountId(_authCode.getAccountId()));
|
||||
Globals.dao.getProxy().save(powers);
|
||||
int hub = DaoSerializer.getInteger(payload, "hub");
|
||||
HubCommands commands = Globals.getCommandsForHub(_authCode.getAccountId(), hub);
|
||||
if (commands != null)
|
||||
zipBsonResponse(_rep, commands);
|
||||
}
|
||||
return;
|
||||
}
|
||||
BreakerPower power = getRequestPayload(_req, BreakerPower.class);
|
||||
if (power == null)
|
||||
return;
|
||||
power.setAccountId(_authCode.getAccountId());
|
||||
Globals.dao.putBreakerPower(power);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.lanternsoftware.currentmonitor.servlet;
|
|||
|
||||
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
|
||||
|
@ -9,17 +11,23 @@ import javax.servlet.annotation.WebServlet;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/rebuildSummaries")
|
||||
@WebServlet("/rebuildSummaries/*")
|
||||
public class RebuildSummariesServlet extends SecureServlet {
|
||||
@Override
|
||||
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
if (_authCode.getAccountId() == 100) {
|
||||
String[] path = path(_req);
|
||||
if (path.length > 0) {
|
||||
Globals.dao.rebuildSummariesAsync(DaoSerializer.toInteger(CollectionUtils.get(path, 0)));
|
||||
}
|
||||
else {
|
||||
for (String sId : Globals.dao.getProxy().queryForField(Account.class, null, "_id")) {
|
||||
int id = DaoSerializer.toInteger(sId);
|
||||
if (id != 0)
|
||||
Globals.dao.rebuildSummariesAsync(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
_rep.setStatus(401);
|
||||
}
|
||||
|
|
|
@ -2,16 +2,21 @@
|
|||
<configuration>
|
||||
<property name="log.pattern" value="%date %-5level %logger{0} - %message%n"/>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>/opt/tomcat/logs/log.txt</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>/opt/tomcat/log/log.%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
|
||||
<maxFileSize>20MB</maxFileSize>
|
||||
<maxHistory>20</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
<logger name="com.lanternsoftware" level="DEBUG"/>
|
||||
|
||||
<root level="OFF">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -2,16 +2,21 @@
|
|||
<configuration>
|
||||
<property name="log.pattern" value="%date %-5level %logger{0} - %message%n"/>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>/opt/tomcat/logs/log.txt</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>/opt/tomcat/log/log.%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
|
||||
<maxFileSize>20MB</maxFileSize>
|
||||
<maxHistory>20</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
<logger name="com.lanternsoftware" level="DEBUG"/>
|
||||
|
||||
<root level="OFF">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -113,6 +113,12 @@ public class RulesEngine {
|
|||
timer.schedule(nextTask, nextDate);
|
||||
}
|
||||
|
||||
public void schedule(TimerTask _task, long _delay) {
|
||||
if (timer == null)
|
||||
return;
|
||||
timer.schedule(_task, _delay);
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
if (INSTANCE == null)
|
||||
return;
|
||||
|
|
|
@ -2,9 +2,9 @@ package com.lanternsoftware.util;
|
|||
|
||||
public abstract class LanternFiles {
|
||||
public static final String SOURCE_PATH = "C:\\lantern\\LanternPowerMonitor\\";
|
||||
// public static final String OPS_PATH = "D:\\zwave\\localhost\\";
|
||||
// public static final String OPS_PATH = "D:\\zwave\\mark4770\\";
|
||||
// public static final String OPS_PATH = "D:\\zwave\\prodremote\\";
|
||||
public static final String OPS_PATH = "/opt/tomcat/";
|
||||
public static final String BACKUP_PATH = "D:\\zwave\\localhost\\";
|
||||
// public static final String OPS_PATH = "D:\\zwave\\prodremote\\";
|
||||
// public static final String OPS_PATH = "D:\\zwave\\localhost\\";
|
||||
public static final String BACKUP_SOURCE = "D:\\zwave\\prodremote\\";
|
||||
public static final String BACKUP_DEST = "D:\\zwave\\localhost\\";
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class SecurityController {
|
|||
LOG.info("handling event {} pin {} most recent event is {}", eventIdx, _sw.getGpioPin(), high);
|
||||
if (high == null)
|
||||
return;
|
||||
_listener.onStateChanged(_sw.getNodeId(), high);
|
||||
_listener.onStateChanged(_sw.getNodeId(), pin.isHigh());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user