diff --git a/case/3A+/LPM_Case_Flange_3A+.blend b/case/3A+/LPM_Case_Flange_3A+.blend index 87157c2..be65a05 100644 Binary files a/case/3A+/LPM_Case_Flange_3A+.blend and b/case/3A+/LPM_Case_Flange_3A+.blend differ diff --git a/case/3A+/LPM_Case_Flange_3A+.stl b/case/3A+/LPM_Case_Flange_3A+.stl index 389066b..c9d0ffc 100644 Binary files a/case/3A+/LPM_Case_Flange_3A+.stl and b/case/3A+/LPM_Case_Flange_3A+.stl differ diff --git a/case/3A+/LPM_Case_Lid_3A+.blend b/case/3A+/LPM_Case_Lid_3A+.blend index 5b0d876..9b09dd0 100644 Binary files a/case/3A+/LPM_Case_Lid_3A+.blend and b/case/3A+/LPM_Case_Lid_3A+.blend differ diff --git a/case/3A+/LPM_Case_Lid_3A+.stl b/case/3A+/LPM_Case_Lid_3A+.stl index ef94caa..bff7777 100644 Binary files a/case/3A+/LPM_Case_Lid_3A+.stl and b/case/3A+/LPM_Case_Lid_3A+.stl differ diff --git a/case/Z2/LPM_Case_Z2_Base_Flange.blend b/case/Z2/LPM_Case_Z2_Base_Flange.blend index fe5085f..f3e3f3a 100644 Binary files a/case/Z2/LPM_Case_Z2_Base_Flange.blend and b/case/Z2/LPM_Case_Z2_Base_Flange.blend differ diff --git a/case/Z2/LPM_Case_Z2_Base_Flange.stl b/case/Z2/LPM_Case_Z2_Base_Flange.stl index aec6d62..80263ba 100644 Binary files a/case/Z2/LPM_Case_Z2_Base_Flange.stl and b/case/Z2/LPM_Case_Z2_Base_Flange.stl differ diff --git a/case/Z2/LPM_Case_Z2_Lid.blend b/case/Z2/LPM_Case_Z2_Lid.blend index d50c95e..77281ee 100644 Binary files a/case/Z2/LPM_Case_Z2_Lid.blend and b/case/Z2/LPM_Case_Z2_Lid.blend differ diff --git a/case/Z2/LPM_Case_Z2_Lid.stl b/case/Z2/LPM_Case_Z2_Lid.stl index de5cf92..b80ffaf 100644 Binary files a/case/Z2/LPM_Case_Z2_Lid.stl and b/case/Z2/LPM_Case_Z2_Lid.stl differ diff --git a/case/Z2/LPM_Case_Z2_Middle.blend b/case/Z2/LPM_Case_Z2_Middle.blend index 36e3ed4..de18e2a 100644 Binary files a/case/Z2/LPM_Case_Z2_Middle.blend and b/case/Z2/LPM_Case_Z2_Middle.blend differ diff --git a/case/Z2/LPM_Case_Z2_Middle.stl b/case/Z2/LPM_Case_Z2_Middle.stl index 035f08d..40da7b1 100644 Binary files a/case/Z2/LPM_Case_Z2_Middle.stl and b/case/Z2/LPM_Case_Z2_Middle.stl differ diff --git a/currentmonitor/lantern-currentmonitor/pom.xml b/currentmonitor/lantern-currentmonitor/pom.xml index 0efbf53..c21dc13 100644 --- a/currentmonitor/lantern-currentmonitor/pom.xml +++ b/currentmonitor/lantern-currentmonitor/pom.xml @@ -3,7 +3,7 @@ com.lanternsoftware.currentmonitor lantern-currentmonitor jar - 1.0.4 + 1.0.6 lantern-currentmonitor diff --git a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/CurrentMonitor.java b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/CurrentMonitor.java index f11672a..4ea7013 100644 --- a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/CurrentMonitor.java +++ b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/CurrentMonitor.java @@ -97,12 +97,17 @@ public class CurrentMonitor { } public void monitorPower(BreakerHub _hub, List _breakers, int _intervalMs, PowerListener _listener) { - stopMonitoring(); - listener = _listener; - List 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()))); - executor.submit(sampler); + try { + stopMonitoring(); + listener = _listener; + List 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()))); + executor.submit(sampler); + } + catch (Throwable t) { + LOG.error("throwable", t); + } } private GpioPinAnalogInput getPin(int _chip, int _pin) { @@ -182,8 +187,10 @@ 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; diff --git a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/MonitorApp.java b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/MonitorApp.java index ca90a0e..ab70184 100644 --- a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/MonitorApp.java +++ b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/MonitorApp.java @@ -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 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,9 +81,138 @@ public class MonitorApp { } else LOG.info("Panel{} - Space{} Power: {}W", _p.getPanel(), Breaker.toSpaceDisplay(_p.getSpace()), String.format("%.3f", _p.getPower())); }; + private static final BleCharacteristicListener bluetoothListener = new BleCharacteristicListener() { + @Override + public void write(String _name, byte[] _value) { + HubConfigCharacteristic ch = NullUtils.toEnum(HubConfigCharacteristic.class, _name); + LOG.info("Char Received, Name: {} Value: {}", _name, _value); + monitor.submit(()->{ + synchronized (monitor) { + switch (ch) { + case Host: + if ((_value.length > 0)) { + config.setHost(NullUtils.terminateWith(NullUtils.toString(_value), "/") + "currentmonitor/"); + ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config)); + } + break; + case HubIndex: + if ((_value.length > 0)) { + config.setHub(_value[0]); + ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config)); + } + break; + case AuthCode: + String value = NullUtils.toString(_value); + if (NullUtils.isNotEmpty(value)) { + authCode = value; + config.setAuthCode(value); + ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config)); + } + break; + case WifiCredentials: + String ssid = HubConfigService.decryptWifiSSID(_value); + String pwd = HubConfigService.decryptWifiPassword(_value); + if (NullUtils.isNotEmpty(ssid) && NullUtils.isNotEmpty(pwd)) + WifiConfig.setCredentials(ssid, pwd); + break; + case Flash: + if ((CollectionUtils.length(_value) == 0) || (_value[0] == 0)) { + if (flasher != null) { + flasher.stop(); + flasher = null; + } else + LEDFlasher.setLEDOn(false); + } else { + if (flasher == null) { + flasher = new LEDFlasher(); + monitor.submit(flasher); + } + } + break; + case Restart: + LOG.info("Restarting Current Monitor..."); + try { + Runtime.getRuntime().exec(new String[]{"systemctl","restart","currentmonitor"}); + } catch (IOException _e) { + LOG.error("Exception occurred while trying to restart", _e); + } + break; + case Reboot: + LOG.info("Rebooting Pi..."); + try { + Runtime.getRuntime().exec(new String[]{"reboot","now"}); + } catch (IOException _e) { + LOG.error("Exception occurred while trying to reboot", _e); + } + break; + case Shutdown: + LOG.info("Shutting down Pi..."); + try { + Runtime.getRuntime().exec(new String[]{"shutdown","now"}); + } catch (IOException _e) { + 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 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; + } + } + }); + } + + @Override + public byte[] read(String _name) { + HubConfigCharacteristic ch = NullUtils.toEnum(HubConfigCharacteristic.class, _name); + if (HubConfigCharacteristic.HubIndex == ch) + return new byte[]{(byte)(config == null?0:config.getHub())}; + if (HubConfigCharacteristic.AccountId == ch) + return ByteBuffer.allocate(4).putInt(breakerConfig == null?0:breakerConfig.getAccountId()).array(); + if (HubConfigCharacteristic.NetworkState == ch) + return new byte[]{NetworkMonitor.getNetworkStatus().toMask()}; + if (HubConfigCharacteristic.NetworkDetails == ch) { + NetworkStatus status = NetworkMonitor.getNetworkStatus(); + DaoEntity meta = (host == null)?null:DaoSerializer.fromZipBson(pool.executeToByteArray(new HttpGet(host + "update/version"))); + status.setPingSuccessful(CollectionUtils.isNotEmpty(meta)); + return DaoSerializer.toZipBson(status); + } + if (HubConfigCharacteristic.Log == ch) { + String[] log = NullUtils.cleanSplit(ResourceLoader.loadFileAsString(WORKING_DIR + "log/log.txt"), "\n"); + if (log.length > 15) + 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"); @@ -90,107 +224,7 @@ public class MonitorApp { monitor.setDebug(config.isDebug()); monitor.start(); LEDFlasher.setLEDOn(false); - final BluetoothConfig bluetoothConfig = new BluetoothConfig("Lantern Hub", new BleCharacteristicListener() { - @Override - public void write(String _name, byte[] _value) { - HubConfigCharacteristic ch = NullUtils.toEnum(HubConfigCharacteristic.class, _name); - LOG.info("Char Received, Name: {} Value: {}", _name, _value); - monitor.submit(()->{ - synchronized (monitor) { - switch (ch) { - case Host: - if ((_value.length > 0)) { - config.setHost(NullUtils.terminateWith(NullUtils.toString(_value), "/") + "currentmonitor/"); - ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config)); - } - break; - case HubIndex: - if ((_value.length > 0)) { - config.setHub(_value[0]); - ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config)); - } - break; - case AuthCode: - String value = NullUtils.toString(_value); - if (NullUtils.isNotEmpty(value)) { - authCode = value; - config.setAuthCode(value); - ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config)); - } - break; - case WifiCredentials: - String ssid = HubConfigService.decryptWifiSSID(_value); - String pwd = HubConfigService.decryptWifiPassword(_value); - if (NullUtils.isNotEmpty(ssid) && NullUtils.isNotEmpty(pwd)) - WifiConfig.setCredentials(ssid, pwd); - break; - case Flash: - if ((CollectionUtils.length(_value) == 0) || (_value[0] == 0)) { - if (flasher != null) { - flasher.stop(); - flasher = null; - } else - LEDFlasher.setLEDOn(false); - } else { - if (flasher == null) { - flasher = new LEDFlasher(); - monitor.submit(flasher); - } - } - break; - case Restart: - LOG.info("Restarting Current Monitor..."); - try { - Runtime.getRuntime().exec(new String[]{"systemctl","restart","currentmonitor"}); - } catch (IOException _e) { - LOG.error("Exception occurred while trying to restart", _e); - } - break; - case Reboot: - LOG.info("Rebooting Pi..."); - try { - Runtime.getRuntime().exec(new String[]{"reboot","now"}); - } catch (IOException _e) { - LOG.error("Exception occurred while trying to reboot", _e); - } - break; - case Shutdown: - LOG.info("Shutting down Pi..."); - try { - Runtime.getRuntime().exec(new String[]{"shutdown","now"}); - } catch (IOException _e) { - LOG.error("Exception occurred while trying to shutdown", _e); - } - break; - } - } - }); - } - - @Override - public byte[] read(String _name) { - HubConfigCharacteristic ch = NullUtils.toEnum(HubConfigCharacteristic.class, _name); - if (HubConfigCharacteristic.HubIndex == ch) - return new byte[]{(byte)(config == null?0:config.getHub())}; - if (HubConfigCharacteristic.AccountId == ch) - return ByteBuffer.allocate(4).putInt(breakerConfig == null?0:breakerConfig.getAccountId()).array(); - if (HubConfigCharacteristic.NetworkState == ch) - return new byte[]{NetworkMonitor.getNetworkStatus().toMask()}; - if (HubConfigCharacteristic.NetworkDetails == ch) { - NetworkStatus status = NetworkMonitor.getNetworkStatus(); - DaoEntity meta = (host == null)?null:DaoSerializer.fromZipBson(pool.executeToByteArray(new HttpGet(host + "update/version"))); - status.setPingSuccessful(CollectionUtils.isNotEmpty(meta)); - return DaoSerializer.toZipBson(status); - } - if (HubConfigCharacteristic.Log == ch) { - String[] log = NullUtils.cleanSplit(ResourceLoader.loadFileAsString(WORKING_DIR + "log/log.txt"), "\n"); - if (log.length > 15) - log = Arrays.copyOfRange(log, log.length-15, log.length); - return ZipUtils.zip(NullUtils.toByteArray(CollectionUtils.delimit(Arrays.asList(log), "\n"))); - } - return null; - } - }); + 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 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 PostResponse post(byte[] _payload, String _path, Class _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 { + 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"); - 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() { - InputStream is = null; + public static String getVersionNumber() { try { - is = MonitorApp.class.getResourceAsStream("/META-INF/MANIFEST.MF"); - Manifest manifest = new Manifest(is); - Attributes attr = manifest.getMainAttributes(); - String version = attr.getValue("Specification-Version"); - LOG.info("Current Version: {}", version); - return version; + Enumeration resources = MonitorApp.class.getClassLoader().getResources("META-INF/MANIFEST.MF"); + while (resources.hasMoreElements()) { + InputStream is = null; + try { + 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; + } + } + finally { + IOUtils.closeQuietly(is); + } + } } catch (Exception _e) { LOG.error("Failed to get current version number", _e); - return ""; - } - finally { - IOUtils.closeQuietly(is); } + return ""; } } diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/Backup.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/Backup.java index 69bdb65..a382bdb 100644 --- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/Backup.java +++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/Backup.java @@ -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 accounts = dao.getProxy().queryAll(Account.class); @@ -34,17 +37,39 @@ public class Backup { t4.stop(); DebugTimer t5 = new DebugTimer("Query Energy"); - List energy = dao.getProxy().queryAll(EnergySummary.class); + for (Account a : accounts) { + List 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("Save Energy"); - backupDao.getProxy().save(energy); + + DebugTimer t6 = new DebugTimer("Query Energy Totals"); + for (Account a : accounts) { + List 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 summary = dao.getProxy().queryAll(EnergyTotal.class); + DebugTimer t7 = new DebugTimer("Query Charges"); + for (Account a : accounts) { + List 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 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"); diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/BackupMinutes.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/BackupMinutes.java index 0a3478a..2565504 100644 --- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/BackupMinutes.java +++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/BackupMinutes.java @@ -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 minutes = dao.getProxy().query(HubPowerMinute.class, new DaoQuery("account_id", a.getId()).andBetweenInclusiveExclusive("minute", (int) (start.getTime() / 60000), (int) (end.getTime() / 60000))); t2.stop(); diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java index 6b2203e..6c8171d 100644 --- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java +++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java @@ -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 getAllHubCommands(); + void deleteHubCommand(String _id); + MongoProxy getProxy(); } diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java index fe4637a..ad17f4f 100644 --- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java +++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java @@ -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 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; diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerConfig.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerConfig.java index b9f5826..9e97ec4 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerConfig.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerConfig.java @@ -209,7 +209,7 @@ public class BreakerConfig implements IIdentical { @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 diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerHub.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerHub.java index bb47fcd..d54251b 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerHub.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerHub.java @@ -6,7 +6,7 @@ import com.lanternsoftware.util.dao.annotations.DBSerializable; import java.util.Objects; -@DBSerializable +@DBSerializable(autogen = false) public class BreakerHub implements IIdentical { private int hub; private double voltageCalibrationFactor; @@ -22,16 +22,24 @@ public class BreakerHub implements IIdentical { 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) { diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubCommand.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubCommand.java new file mode 100644 index 0000000..05e4a23 --- /dev/null +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubCommand.java @@ -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 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); + } +} diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubCommands.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubCommands.java new file mode 100644 index 0000000..0c8fce8 --- /dev/null +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubCommands.java @@ -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 commands; + + public HubCommands() { + } + + public HubCommands(List _commands) { + commands = _commands; + } + + public List getCommands() { + return commands; + } + + public void setCommands(List _commands) { + commands = _commands; + } +} diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubConfigCharacteristic.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubConfigCharacteristic.java index f3e4c73..221b5c4 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubConfigCharacteristic.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/HubConfigCharacteristic.java @@ -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; diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BillingRateSerializer.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BillingRateSerializer.java index 66d98f8..9062774 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BillingRateSerializer.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BillingRateSerializer.java @@ -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 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 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")); diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BreakerHubSerializer.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BreakerHubSerializer.java index 180926d..776059b 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BreakerHubSerializer.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BreakerHubSerializer.java @@ -26,8 +26,8 @@ public class BreakerHubSerializer extends AbstractDaoSerializer { 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; diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/HubCommandSerializer.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/HubCommandSerializer.java new file mode 100644 index 0000000..a4c0b0b --- /dev/null +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/HubCommandSerializer.java @@ -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 +{ + @Override + public Class getSupportedClass() + { + return HubCommand.class; + } + + @Override + public List 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; + } +} \ No newline at end of file diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/HubCommandsSerializer.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/HubCommandsSerializer.java new file mode 100644 index 0000000..fac22df --- /dev/null +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/HubCommandsSerializer.java @@ -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 +{ + @Override + public Class getSupportedClass() + { + return HubCommands.class; + } + + @Override + public List 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; + } +} \ No newline at end of file diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer b/currentmonitor/lantern-datamodel-currentmonitor/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer index e2de4e0..3a3f460 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer @@ -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 diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java index 890724d..e4f387c 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java @@ -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>> 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 c = null; + synchronized (commands) { + Map> 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 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); + } + } } diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java index d770bbc..ccab743 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java @@ -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); diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CommandServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CommandServlet.java index 0672fc8..a58aad0 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CommandServlet.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CommandServlet.java @@ -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 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")); } } diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java index e22df18..d746628 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java @@ -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)); } } diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/PowerServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/PowerServlet.java index 3abca86..f159626 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/PowerServlet.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/PowerServlet.java @@ -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 powers = DaoSerializer.getList(getRequestZipBson(_req), "readings", BreakerPower.class); + DaoEntity payload = getRequestZipBson(_req); + List 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); } diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/RebuildSummariesServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/RebuildSummariesServlet.java index 05cf8f2..2719412 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/RebuildSummariesServlet.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/RebuildSummariesServlet.java @@ -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,15 +11,21 @@ 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) { - for (String sId : Globals.dao.getProxy().queryForField(Account.class, null, "_id")) { - int id = DaoSerializer.toInteger(sId); - if (id != 0) - Globals.dao.rebuildSummariesAsync(id); + 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 diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/resources/logback.xml b/currentmonitor/lantern-service-currentmonitor/src/main/resources/logback.xml index ece41c5..6f04b4c 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/resources/logback.xml +++ b/currentmonitor/lantern-service-currentmonitor/src/main/resources/logback.xml @@ -2,16 +2,21 @@ - + + /opt/tomcat/logs/log.txt + + /opt/tomcat/log/log.%d{yyyy-MM-dd}.%i.txt + 20MB + 20 + ${log.pattern} - - + \ No newline at end of file diff --git a/currentmonitor/lantern-service-currentmonitor/src/test/resources/logback.xml b/currentmonitor/lantern-service-currentmonitor/src/test/resources/logback.xml index ece41c5..6f04b4c 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/test/resources/logback.xml +++ b/currentmonitor/lantern-service-currentmonitor/src/test/resources/logback.xml @@ -2,16 +2,21 @@ - + + /opt/tomcat/logs/log.txt + + /opt/tomcat/log/log.%d{yyyy-MM-dd}.%i.txt + 20MB + 20 + ${log.pattern} - - + \ No newline at end of file diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/RulesEngine.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/RulesEngine.java index b06a2b8..2a94532 100644 --- a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/RulesEngine.java +++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/RulesEngine.java @@ -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; diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/LanternFiles.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/LanternFiles.java index cfb4294..b71952b 100644 --- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/LanternFiles.java +++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/LanternFiles.java @@ -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\\"; } diff --git a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/security/SecurityController.java b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/security/SecurityController.java index 449379f..07b13db 100644 --- a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/security/SecurityController.java +++ b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/security/SecurityController.java @@ -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()); }); }); }