Migrating from from wiringpi to pigpio. This increases the sample rate by a factor of 3 and will allow creation of a board that can monitor over 30 breakers with a single raspberry pi.

This is based on pi4j 2.0 which is in a beta status.  I have fixed a few bugs in a local version of pi4j 2.0 to get it to work but I haven't submitted those changes to pi4j yet.

This change requires a migration to Java 11 and will *NOT* be backwards compatible.  Upgrading to this hub software will require that java 11 and pigpio be installed on the hub.  This can be done from an ssh session with the following commands:

apt-get update
apt-get install openjdk-11-jre-headless
apt-get install pigpio

Alternatively, you can download a new sd image, reflash your sd card, and re-adopt your hub.
This commit is contained in:
Mark Milligan 2022-04-29 14:59:56 -05:00
parent 079206fcd7
commit c8319d6369
50 changed files with 637 additions and 412 deletions

View File

@ -1,15 +1,15 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-config-currentmonitor</artifactId> <artifactId>lantern-config-currentmonitor</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.1.0</version>
<name>lantern-config-currentmonitor</name> <name>lantern-config-currentmonitor</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.currentmonitor</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>currentmonitor</artifactId>
</properties> <version>1.1.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
@ -25,12 +25,12 @@
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao-mongo</artifactId> <artifactId>lantern-util-dao-mongo</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-common</artifactId> <artifactId>lantern-util-common</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
@ -56,8 +56,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,15 +1,15 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-currentmonitor</artifactId> <artifactId>lantern-currentmonitor</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.7</version> <version>1.1.0</version>
<name>lantern-currentmonitor</name> <name>lantern-currentmonitor</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.currentmonitor</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>currentmonitor</artifactId>
</properties> <version>1.1.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
@ -24,8 +24,13 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.pi4j</groupId> <groupId>com.pi4j</groupId>
<artifactId>pi4j-gpio-extension</artifactId> <artifactId>pi4j-core</artifactId>
<version>1.3</version> <version>2.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.pi4j</groupId>
<artifactId>pi4j-plugin-pigpio</artifactId>
<version>2.2.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.hypfvieh</groupId> <groupId>com.github.hypfvieh</groupId>
@ -35,12 +40,12 @@
<dependency> <dependency>
<groupId>com.lanternsoftware.currentmonitor</groupId> <groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-datamodel-currentmonitor</artifactId> <artifactId>lantern-datamodel-currentmonitor</artifactId>
<version>1.0.0</version> <version>${cm.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-http</artifactId> <artifactId>lantern-util-http</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.paho</groupId> <groupId>org.eclipse.paho</groupId>
@ -71,8 +76,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,18 +1,19 @@
package com.lanternsoftware.currentmonitor; package com.lanternsoftware.currentmonitor;
import com.lanternsoftware.currentmonitor.adc.MCP3008Pin;
import com.lanternsoftware.datamodel.currentmonitor.Breaker; import com.lanternsoftware.datamodel.currentmonitor.Breaker;
import com.pi4j.io.gpio.GpioPinAnalogInput;
import java.util.List; import java.util.List;
public class BreakerSamples { public class BreakerSamples {
private final Breaker breaker; private final Breaker breaker;
private final GpioPinAnalogInput voltagePin; private final MCP3008Pin voltagePin;
private final GpioPinAnalogInput currentPin; private final MCP3008Pin currentPin;
private final List<PowerSample> samples; private final List<PowerSample> samples;
private int cycleCnt;
private int sampleCnt; private int sampleCnt;
public BreakerSamples(Breaker _breaker, GpioPinAnalogInput _voltagePin, GpioPinAnalogInput _currentPin, List<PowerSample> _samples) { public BreakerSamples(Breaker _breaker, MCP3008Pin _voltagePin, MCP3008Pin _currentPin, List<PowerSample> _samples) {
breaker = _breaker; breaker = _breaker;
voltagePin = _voltagePin; voltagePin = _voltagePin;
currentPin = _currentPin; currentPin = _currentPin;
@ -23,11 +24,11 @@ public class BreakerSamples {
return breaker; return breaker;
} }
public GpioPinAnalogInput getVoltagePin() { public MCP3008Pin getVoltagePin() {
return voltagePin; return voltagePin;
} }
public GpioPinAnalogInput getCurrentPin() { public MCP3008Pin getCurrentPin() {
return currentPin; return currentPin;
} }
@ -35,8 +36,20 @@ public class BreakerSamples {
return samples; return samples;
} }
public PowerSample getSample(int _sample) { public void incrementCycleCnt() {
return samples.get(_sample); cycleCnt++;
}
public PowerSample incrementSample() {
return samples.get(sampleCnt++);
}
public int getCycleCnt() {
return cycleCnt;
}
public void setCycleCnt(int _cycleCnt) {
cycleCnt = _cycleCnt;
} }
public int getSampleCnt() { public int getSampleCnt() {

View File

@ -1,23 +1,20 @@
package com.lanternsoftware.currentmonitor; package com.lanternsoftware.currentmonitor;
import com.lanternsoftware.currentmonitor.adc.MCP3008;
import com.lanternsoftware.currentmonitor.adc.MCP3008Pin;
import com.lanternsoftware.datamodel.currentmonitor.Breaker; import com.lanternsoftware.datamodel.currentmonitor.Breaker;
import com.lanternsoftware.datamodel.currentmonitor.BreakerHub; import com.lanternsoftware.datamodel.currentmonitor.BreakerHub;
import com.lanternsoftware.datamodel.currentmonitor.BreakerPolarity; import com.lanternsoftware.datamodel.currentmonitor.BreakerPolarity;
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower; import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
import com.lanternsoftware.util.CollectionUtils; import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.concurrency.ConcurrencyUtils; import com.lanternsoftware.util.concurrency.ConcurrencyUtils;
import com.pi4j.gpio.extension.base.AdcGpioProvider; import com.pi4j.Pi4J;
import com.pi4j.gpio.extension.mcp.MCP3008GpioProvider; import com.pi4j.context.Context;
import com.pi4j.gpio.extension.mcp.MCP3008Pin; import com.pi4j.io.spi.Spi;
import com.pi4j.io.gpio.GpioController; import com.pi4j.io.spi.SpiMode;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinAnalogInput;
import com.pi4j.io.spi.SpiChannel;
import com.pi4j.io.spi.SpiDevice;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
@ -30,22 +27,15 @@ import java.util.concurrent.Executors;
public class CurrentMonitor { public class CurrentMonitor {
private static final Logger LOG = LoggerFactory.getLogger(CurrentMonitor.class); private static final Logger LOG = LoggerFactory.getLogger(CurrentMonitor.class);
private static final int BATCH_CNT = 4; private static final int BATCH_CNT = 4;
private GpioController gpio;
private final ExecutorService executor = Executors.newCachedThreadPool(); private final ExecutorService executor = Executors.newCachedThreadPool();
private final Map<Integer, AdcGpioProvider> chips = new HashMap<>(); private Context pi4j;
private final Map<Integer, GpioPinAnalogInput> pins = new HashMap<>(); private final Map<Integer, MCP3008> chips = new HashMap<>();
private Sampler sampler; private Sampler sampler;
private PowerListener listener; private PowerListener listener;
private boolean debug = false; private boolean debug = false;
public void start() { public void start() {
try { pi4j = Pi4J.newAutoContext();
gpio = GpioFactory.getInstance();
LOG.info("Current Monitor Started");
}
catch (Throwable t) {
LOG.info("Failed to get gpio factory", t);
}
} }
public void stop() { public void stop() {
@ -53,9 +43,12 @@ public class CurrentMonitor {
ConcurrencyUtils.sleep(1000); ConcurrencyUtils.sleep(1000);
executor.shutdown(); executor.shutdown();
ConcurrencyUtils.sleep(1000); ConcurrencyUtils.sleep(1000);
for (MCP3008 mcp : chips.values()) {
mcp.shutdown(pi4j);
}
ConcurrencyUtils.sleep(1000);
pi4j.shutdown();
chips.clear(); chips.clear();
pins.clear();
gpio.shutdown();
LOG.info("Power Monitor Service Stopped"); LOG.info("Power Monitor Service Stopped");
} }
@ -64,10 +57,9 @@ public class CurrentMonitor {
} }
public CalibrationResult calibrateVoltage(double _curCalibration) { public CalibrationResult calibrateVoltage(double _curCalibration) {
GpioPinAnalogInput voltagePin = getPin(0, 0); LOG.info("Calibrating Voltage");
if (voltagePin == null) MCP3008Pin voltagePin = new MCP3008Pin(getChip(0), 0);
return null; int maxSamples = 240000;
int maxSamples = 120000;
CalibrationSample[] samples = new CalibrationSample[maxSamples]; CalibrationSample[] samples = new CalibrationSample[maxSamples];
int offset = 0; int offset = 0;
for (;offset < maxSamples; offset++) { for (;offset < maxSamples; offset++) {
@ -77,7 +69,7 @@ public class CurrentMonitor {
long intervalEnd = System.nanoTime() + 2000000000L; //Scan voltage for 2 seconds long intervalEnd = System.nanoTime() + 2000000000L; //Scan voltage for 2 seconds
while (offset < maxSamples) { while (offset < maxSamples) {
samples[offset].time = System.nanoTime(); samples[offset].time = System.nanoTime();
samples[offset].voltage = voltagePin.getValue(); samples[offset].voltage = voltagePin.read();
offset++; offset++;
if (samples[offset-1].time > intervalEnd) if (samples[offset-1].time > intervalEnd)
break; break;
@ -128,10 +120,12 @@ public class CurrentMonitor {
stopMonitoring(); stopMonitoring();
listener = _listener; 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);
if (CollectionUtils.isEmpty(validBreakers)) if (CollectionUtils.isEmpty(validBreakers)) {
LOG.error("No breakers found for hub number {}", _hub.getHub());
return; return;
}
LOG.info("Monitoring {} breakers for hub {}", CollectionUtils.size(validBreakers), _hub.getHub()); LOG.info("Monitoring {} breakers for hub {}", CollectionUtils.size(validBreakers), _hub.getHub());
sampler = new Sampler(_hub, validBreakers, _intervalMs, 2); sampler = new Sampler(_hub, validBreakers, _intervalMs, 5);
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); executor.submit(sampler);
} }
@ -140,34 +134,17 @@ public class CurrentMonitor {
} }
} }
private GpioPinAnalogInput getPin(int _chip, int _pin) { private synchronized MCP3008 getChip(int _chip) {
GpioPinAnalogInput pin; MCP3008 chip = chips.get(_chip);
synchronized (pins) {
AdcGpioProvider chip = chips.get(_chip);
if (chip == null) { if (chip == null) {
SpiChannel channel = SpiChannel.getByNumber(_chip); String id = "SPI" + _chip;
if (channel == null) LOG.info("Creating chip {}", id);
return null; Spi spi = pi4j.create(Spi.newConfigBuilder(pi4j).mode(SpiMode.MODE_0).id(id).name("MCP3008_" + _chip).address(_chip).baud(810000).build());
try { LOG.info("is open {}", spi.isOpen());
chip = new MCP3008GpioProvider(channel, 1250000, SpiDevice.DEFAULT_SPI_MODE, false); chip = new MCP3008(spi);
chips.put(_chip, chip); chips.put(_chip, chip);
} catch (IOException _e) {
LOG.error("Failed to connect to chip {}", _chip, _e);
return null;
} }
} return chip;
int pinKey = pinKey(_chip, _pin);
pin = pins.get(pinKey);
if (pin == null) {
pin = gpio.provisionAnalogInputPin(chip, MCP3008Pin.ALL[_pin], String.valueOf(pinKey));
pins.put(pinKey, pin);
}
}
return pin;
}
private Integer pinKey(int _chip, int _pin) {
return (_chip*8)+_pin;
} }
public void submit(Runnable _runnable) { public void submit(Runnable _runnable) {
@ -190,14 +167,14 @@ public class CurrentMonitor {
public Sampler(BreakerHub _hub, List<Breaker> _breakers, int _intervalMs, int _concurrentBreakerCnt) { public Sampler(BreakerHub _hub, List<Breaker> _breakers, int _intervalMs, int _concurrentBreakerCnt) {
hub = _hub; hub = _hub;
GpioPinAnalogInput voltagePin = getPin(0, 0); MCP3008Pin voltagePin = new MCP3008Pin(getChip(0), 0);
breakers = CollectionUtils.transform(_breakers, _b->{ breakers = CollectionUtils.transform(_breakers, _b->{
LOG.info("Getting Chip {}, Pin {} for port {}", _b.getChip(), _b.getPin(), _b.getPort()); LOG.info("Getting Chip {}, Pin {} for port {}", _b.getChip(), _b.getPin(), _b.getPort());
GpioPinAnalogInput currentPin = getPin(_b.getChip(), _b.getPin()); MCP3008Pin currentPin = new MCP3008Pin(getChip(_b.getChip()), _b.getPin());
List<BreakerSamples> batches = new ArrayList<>(BATCH_CNT); List<BreakerSamples> batches = new ArrayList<>(BATCH_CNT);
for (int i=0; i<BATCH_CNT; i++) { for (int i=0; i<BATCH_CNT; i++) {
List<PowerSample> samples = new ArrayList<>(30000/_breakers.size()); List<PowerSample> samples = new ArrayList<>(30000/_breakers.size());
for (int j=0; j<30000/_breakers.size(); j++) { for (int j=0; j<60000/_breakers.size(); j++) {
samples.add(new PowerSample()); samples.add(new PowerSample());
} }
batches.add(new BreakerSamples(_b, voltagePin, currentPin, samples)); batches.add(new BreakerSamples(_b, voltagePin, currentPin, samples));
@ -213,6 +190,7 @@ public class CurrentMonitor {
long start = System.nanoTime(); long start = System.nanoTime();
long interval = 0; long interval = 0;
int cycle; int cycle;
int curBreaker;
BreakerSamples[] cycleBreakers = new BreakerSamples[concurrentBreakerCnt]; BreakerSamples[] cycleBreakers = new BreakerSamples[concurrentBreakerCnt];
try { try {
while (true) { while (true) {
@ -227,22 +205,18 @@ public class CurrentMonitor {
long intervalEnd = intervalStart + intervalNs; long intervalEnd = intervalStart + intervalNs;
cycle = 0; cycle = 0;
final int batch = (int) (interval % BATCH_CNT); final int batch = (int) (interval % BATCH_CNT);
int curBreaker;
for (curBreaker = 0; curBreaker < breakers.size(); curBreaker++) {
breakers.get(curBreaker).get(batch).setSampleCnt(0);
}
while (System.nanoTime() < intervalEnd) { while (System.nanoTime() < intervalEnd) {
for (curBreaker = 0; curBreaker < concurrentBreakerCnt; curBreaker++) { for (curBreaker = 0; curBreaker < concurrentBreakerCnt; curBreaker++) {
cycleBreakers[curBreaker] = breakers.get(((cycle * concurrentBreakerCnt) + curBreaker) % breakers.size()).get(batch); cycleBreakers[curBreaker] = breakers.get(((cycle * concurrentBreakerCnt) + curBreaker) % breakers.size()).get(batch);
cycleBreakers[curBreaker].incrementCycleCnt();
} }
cycle++; cycle++;
long cycleEnd = intervalStart + (cycle * (intervalNs / hub.getFrequency())); long cycleEnd = intervalStart + (cycle * (intervalNs / hub.getFrequency()));
while (System.nanoTime() < cycleEnd) { while (System.nanoTime() < cycleEnd) {
for (curBreaker = 0; curBreaker < concurrentBreakerCnt; curBreaker++) { for (curBreaker = 0; curBreaker < concurrentBreakerCnt; curBreaker++) {
PowerSample sample = cycleBreakers[curBreaker].getSample(cycleBreakers[curBreaker].getSampleCnt()); PowerSample sample = cycleBreakers[curBreaker].incrementSample();
sample.voltage = cycleBreakers[curBreaker].getVoltagePin().getValue(); sample.voltage = cycleBreakers[curBreaker].getVoltagePin().read();
sample.current = cycleBreakers[curBreaker].getCurrentPin().getValue(); sample.current = cycleBreakers[curBreaker].getCurrentPin().read();
cycleBreakers[curBreaker].setSampleCnt(cycleBreakers[curBreaker].getSampleCnt()+1);
} }
} }
} }
@ -284,10 +258,11 @@ public class CurrentMonitor {
if (debug) { if (debug) {
synchronized (CurrentMonitor.this) { synchronized (CurrentMonitor.this) {
LOG.info("===========================Start Port {}", samples.getBreaker().getPort()); LOG.info("===========================Start Port {}", samples.getBreaker().getPort());
LOG.info("Cycles: {}", samples.getCycleCnt());
LOG.info("Samples: {}", samples.getSampleCnt()); LOG.info("Samples: {}", samples.getSampleCnt());
LOG.info("vMin: {}, vMax: {}, vOffset: {}", String.format("%.3f", CollectionUtils.getSmallest(validSamples, Comparator.comparing(_v -> _v.voltage)).voltage), String.format("%.3f", CollectionUtils.getLargest(validSamples, Comparator.comparing(_v -> _v.voltage)).voltage), String.format("%.3f", vOffset)); LOG.info("vMin: {}, vMax: {}, vOffset: {}", String.format("%.3f", CollectionUtils.getSmallest(validSamples, Comparator.comparing(_v -> _v.voltage)).voltage), String.format("%.3f", CollectionUtils.getLargest(validSamples, Comparator.comparing(_v -> _v.voltage)).voltage), String.format("%.3f", vOffset));
LOG.info("iMin: {}, iMax: {}, iOffset: {}", String.format("%.3f", CollectionUtils.getSmallest(validSamples, Comparator.comparing(_v -> _v.current)).current), String.format("%.3f", CollectionUtils.getLargest(validSamples, Comparator.comparing(_v -> _v.current)).current), String.format("%.3f", iOffset)); LOG.info("iMin: {}, iMax: {}, iOffset: {}", String.format("%.3f", CollectionUtils.getSmallest(validSamples, Comparator.comparing(_v -> _v.current)).current), String.format("%.3f", CollectionUtils.getLargest(validSamples, Comparator.comparing(_v -> _v.current)).current), String.format("%.3f", iOffset));
double iRms = samples.getBreaker().getFinalCalibrationFactor() * Math.sqrt(CollectionUtils.mean(CollectionUtils.transform(validSamples, _p -> _p.current * _p.current))); double iRms = hub.getPortCalibrationFactor() * samples.getBreaker().getFinalCalibrationFactor() * Math.sqrt(CollectionUtils.mean(CollectionUtils.transform(validSamples, _p -> _p.current * _p.current)));
LOG.info("vRms: {}", String.format("%.3f", vRms)); LOG.info("vRms: {}", String.format("%.3f", vRms));
LOG.info("iRms: {}", String.format("%.3f", iRms)); LOG.info("iRms: {}", String.format("%.3f", iRms));
double apparentPower = vRms * iRms; double apparentPower = vRms * iRms;
@ -298,6 +273,8 @@ public class CurrentMonitor {
LOG.info("===========================End Port {}", samples.getBreaker().getPort()); LOG.info("===========================End Port {}", samples.getBreaker().getPort());
} }
} }
samples.setSampleCnt(0);
samples.setCycleCnt(0);
listener.onPowerEvent(new BreakerPower(samples.getBreaker().getPanel(), samples.getBreaker().getSpace(), readTime, realPower, vRms)); listener.onPowerEvent(new BreakerPower(samples.getBreaker().getPanel(), samples.getBreaker().getSpace(), readTime, realPower, vRms));
} }
}); });

View File

@ -35,12 +35,9 @@ import org.apache.http.entity.ContentType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.Console;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL; import java.net.URL;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
@ -210,8 +207,8 @@ public class MonitorApp {
version = getVersionNumber(); version = getVersionNumber();
config = DaoSerializer.parse(ResourceLoader.loadFileAsString(WORKING_DIR + "config.json"), MonitorConfig.class); config = DaoSerializer.parse(ResourceLoader.loadFileAsString(WORKING_DIR + "config.json"), MonitorConfig.class);
if (config == null) { if (config == null) {
LOG.error("Failed to load config file from {}", WORKING_DIR + "config.json"); config = new MonitorConfig();
return; ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config));
} }
pool = new HttpPool(10, 10, config.getSocketTimeout(), config.getConnectTimeout(), config.getSocketTimeout()); pool = new HttpPool(10, 10, config.getSocketTimeout(), config.getConnectTimeout(), config.getSocketTimeout());
if (NullUtils.isNotEmpty(config.getHost())) if (NullUtils.isNotEmpty(config.getHost()))
@ -219,8 +216,6 @@ public class MonitorApp {
monitor.setDebug(config.isDebug()); monitor.setDebug(config.isDebug());
monitor.start(); monitor.start();
LEDFlasher.setLEDOn(false); LEDFlasher.setLEDOn(false);
bluetoothConfig = new BluetoothConfig("Lantern Hub", bluetoothListener);
bluetoothConfig.start();
if (NullUtils.isNotEmpty(config.getAuthCode())) if (NullUtils.isNotEmpty(config.getAuthCode()))
authCode = config.getAuthCode(); authCode = config.getAuthCode();
else if (NullUtils.isNotEmpty(host) && NullUtils.isNotEmpty(config.getUsername()) && NullUtils.isNotEmpty(config.getPassword())) { else if (NullUtils.isNotEmpty(host) && NullUtils.isNotEmpty(config.getUsername()) && NullUtils.isNotEmpty(config.getPassword())) {
@ -231,7 +226,8 @@ public class MonitorApp {
if (NullUtils.isNotEmpty(config.getMqttBrokerUrl())) if (NullUtils.isNotEmpty(config.getMqttBrokerUrl()))
mqttPoster = new MqttPoster(config); mqttPoster = new MqttPoster(config);
if (NullUtils.isNotEmpty(host) && NullUtils.isNotEmpty(authCode)) { if (NullUtils.isNotEmpty(host) && NullUtils.isNotEmpty(authCode)) {
while (true) { int configAttempts = 0;
while (configAttempts < 5) {
HttpGet get = new HttpGet(host + "config"); HttpGet get = new HttpGet(host + "config");
get.addHeader("auth_code", authCode); get.addHeader("auth_code", authCode);
breakerConfig = DaoSerializer.parse(pool.executeToString(get), BreakerConfig.class); breakerConfig = DaoSerializer.parse(pool.executeToString(get), BreakerConfig.class);
@ -239,8 +235,11 @@ public class MonitorApp {
break; break;
LOG.error("Failed to load breaker config. Retrying in 5 seconds..."); LOG.error("Failed to load breaker config. Retrying in 5 seconds...");
ConcurrencyUtils.sleep(5000); ConcurrencyUtils.sleep(5000);
configAttempts++;
} }
} }
bluetoothConfig = new BluetoothConfig("Lantern Hub", bluetoothListener);
bluetoothConfig.start();
if ((mqttPoster != null) && (breakerConfig == null)) { if ((mqttPoster != null) && (breakerConfig == null)) {
LOG.info("Hub not configured by a Lantern Power Monitor server, defaulting to MQTT mode only"); LOG.info("Hub not configured by a Lantern Power Monitor server, defaulting to MQTT mode only");
BreakerHub hub = new BreakerHub(); BreakerHub hub = new BreakerHub();
@ -266,6 +265,7 @@ public class MonitorApp {
BreakerHub hub = breakerConfig.getHub(config.getHub()); BreakerHub hub = breakerConfig.getHub(config.getHub());
if (hub != null) { if (hub != null) {
if (config.isNeedsCalibration()) { if (config.isNeedsCalibration()) {
try {
CalibrationResult cal = monitor.calibrateVoltage(hub.getVoltageCalibrationFactor()); CalibrationResult cal = monitor.calibrateVoltage(hub.getVoltageCalibrationFactor());
if (cal != null) { if (cal != null) {
hub.setVoltageCalibrationFactor(cal.getVoltageCalibrationFactor()); hub.setVoltageCalibrationFactor(cal.getVoltageCalibrationFactor());
@ -275,6 +275,10 @@ public class MonitorApp {
post(DaoSerializer.toZipBson(breakerConfig), "config"); post(DaoSerializer.toZipBson(breakerConfig), "config");
} }
} }
catch (Throwable t) {
LOG.error("Exception trying to read from voltage pin", t);
}
}
List<Breaker> breakers = breakerConfig.getBreakersForHub(config.getHub()); List<Breaker> breakers = breakerConfig.getBreakersForHub(config.getHub());
monitor.monitorPower(hub, breakers, 1000, logger); monitor.monitorPower(hub, breakers, 1000, logger);
} }
@ -288,18 +292,10 @@ public class MonitorApp {
monitor.stop(); monitor.stop();
pool.shutdown(); pool.shutdown();
}, "Monitor Shutdown")); }, "Monitor Shutdown"));
Console c = System.console();
BufferedReader reader = (c == null)?new BufferedReader(new InputStreamReader(System.in)):null;
while (running.get()) {
try { try {
String command = c != null ? c.readLine() : reader.readLine(); monitor.wait();
if (NullUtils.isEqual("exit", command)) } catch (InterruptedException _e) {
break; LOG.error("Interrupted, shutting down", _e);
}
catch (Exception _e) {
LOG.error("Exception while reading from console input", _e);
break;
}
} }
} }
@ -360,7 +356,7 @@ public class MonitorApp {
byte[] payload = DaoSerializer.toZipBson(minutePost); byte[] payload = DaoSerializer.toZipBson(minutePost);
if (!post(payload, "power/hub")) { if (!post(payload, "power/hub")) {
LOG.info("Failed Posting HubPowerMinute, writing cache"); LOG.info("Failed Posting HubPowerMinute, writing cache");
ResourceLoader.writeFile(WORKING_DIR + "cache/" + UUID.randomUUID().toString() + ".min", payload); ResourceLoader.writeFile(WORKING_DIR + "cache/" + UUID.randomUUID() + ".min", payload);
} }
} }
if (post != null) { if (post != null) {

View File

@ -2,6 +2,7 @@ package com.lanternsoftware.currentmonitor;
import com.lanternsoftware.datamodel.currentmonitor.Breaker; import com.lanternsoftware.datamodel.currentmonitor.Breaker;
import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.dao.annotations.DBSerializable; import com.lanternsoftware.util.dao.annotations.DBSerializable;
import java.util.List; import java.util.List;
@ -12,11 +13,11 @@ public class MonitorConfig {
private String authCode; private String authCode;
private String username; private String username;
private String password; private String password;
private int hub; private int hub = -1;
private boolean debug; private boolean debug;
private int connectTimeout; private int connectTimeout;
private int socketTimeout; private int socketTimeout;
private boolean needsCalibration; private boolean needsCalibration = true;
private String mqttBrokerUrl; private String mqttBrokerUrl;
private String mqttUserName; private String mqttUserName;
private String mqttPassword; private String mqttPassword;
@ -34,7 +35,7 @@ public class MonitorConfig {
} }
public String getHost() { public String getHost() {
return host; return NullUtils.isEmpty(host) ? "https://lanternpowermonitor.com/" : host;
} }
public void setHost(String _host) { public void setHost(String _host) {

View File

@ -0,0 +1,36 @@
package com.lanternsoftware.currentmonitor.adc;
import com.pi4j.context.Context;
import com.pi4j.io.spi.Spi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MCP3008 {
private static final Logger LOG = LoggerFactory.getLogger(MCP3008.class);
private static final byte[][] pins = new byte[8][];
private final Spi spi;
private final byte[] resp = new byte[3];
static {
for (int p = 0; p < 8; p++) {
pins[p] = new byte[]{1,(byte)(p + 8 << 4),0};
}
}
public MCP3008(Spi _spi) {
spi = _spi;
}
public void shutdown(Context _pi4j) {
spi.close();
spi.shutdown(_pi4j);
}
public int readPin(int _pin) {
if (spi.transfer(pins[_pin], resp) > 2) {
return ((resp[1] & 0x03) << 8) + (resp[2] & 0xFF);
}
return 0;
}
}

View File

@ -0,0 +1,15 @@
package com.lanternsoftware.currentmonitor.adc;
public class MCP3008Pin {
private final MCP3008 chip;
private final int pin;
public MCP3008Pin(MCP3008 _chip, int _pin) {
chip = _chip;
pin = _pin;
}
public int read() {
return chip.readPin(pin);
}
}

View File

@ -21,6 +21,7 @@
</appender> </appender>
<logger name="com.lanternsoftware" level="INFO"/> <logger name="com.lanternsoftware" level="INFO"/>
<logger name="com.pi4j" level="INFO"/>
<root level="OFF"> <root level="OFF">
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>

View File

@ -1,31 +1,31 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-dataaccess-currentmonitor</artifactId> <artifactId>lantern-dataaccess-currentmonitor</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.1.0</version>
<name>lantern-dataaccess-currentmonitor</name> <name>lantern-dataaccess-currentmonitor</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.currentmonitor</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>currentmonitor</artifactId>
</properties> <version>1.1.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.currentmonitor</groupId> <groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-datamodel-currentmonitor</artifactId> <artifactId>lantern-datamodel-currentmonitor</artifactId>
<version>1.0.0</version> <version>${cm.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.rules</groupId> <groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-datamodel-rules</artifactId> <artifactId>lantern-datamodel-rules</artifactId>
<version>1.0.0</version> <version>${rules.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao-mongo</artifactId> <artifactId>lantern-util-dao-mongo</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mindrot</groupId> <groupId>org.mindrot</groupId>
@ -56,8 +56,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -54,6 +54,7 @@ public interface CurrentMonitorDao {
String getAuthCodeForEmail(String _email, TimeZone _tz); String getAuthCodeForEmail(String _email, TimeZone _tz);
Account authCodeToAccount(String _authCode); Account authCodeToAccount(String _authCode);
AuthCode decryptAuthCode(String _authCode); AuthCode decryptAuthCode(String _authCode);
String exchangeAuthCode(String _authCode, int _acctId);
Account putAccount(Account _account); Account putAccount(Account _account);
Account getAccount(int _accountId); Account getAccount(int _accountId);

View File

@ -90,6 +90,9 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
updateEnergySummaries(minute); updateEnergySummaries(minute);
} }
proxy.delete(DirtyMinute.class, new DaoQuery()); proxy.delete(DirtyMinute.class, new DaoQuery());
if (!proxy.exists(Sequence.class, null)) {
proxy.save(new Sequence());
}
} }
public void shutdown() { public void shutdown() {
@ -303,7 +306,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
TimeZone tz = getTimeZoneForAccount(_accountId); TimeZone tz = getTimeZoneForAccount(_accountId);
Date month = DateUtils.getStartOfMonth(range.getStart(), tz); Date month = DateUtils.getStartOfMonth(range.getStart(), tz);
Date end = DateUtils.getEndOfMonth(range.getEnd(), tz); Date end = DateUtils.getEndOfMonth(range.getEnd(), tz);
while (month.before(end)) { while ((month != null) && month.before(end)) {
statuses.computeIfAbsent(month, _m->new ArchiveStatus(_accountId, _m, 0)); statuses.computeIfAbsent(month, _m->new ArchiveStatus(_accountId, _m, 0));
month = DateUtils.addMonths(month, 1, tz); month = DateUtils.addMonths(month, 1, tz);
} }
@ -326,6 +329,8 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
TimeZone tz = getTimeZoneForAccount(_minute.getAccountId()); TimeZone tz = getTimeZoneForAccount(_minute.getAccountId());
BreakerConfig config = getConfig(_minute.getAccountId()); BreakerConfig config = getConfig(_minute.getAccountId());
BreakerGroup group = CollectionUtils.getFirst(config.getBreakerGroups()); BreakerGroup group = CollectionUtils.getFirst(config.getBreakerGroups());
if (group == null)
return;
Date day = DateUtils.getMidnightBefore(_minute.getMinuteAsDate(), tz); Date day = DateUtils.getMidnightBefore(_minute.getMinuteAsDate(), tz);
DebugTimer t2 = new DebugTimer("Updating energy", logger); DebugTimer t2 = new DebugTimer("Updating energy", logger);
EnergySummary energy = getEnergySummary(_minute.getAccountId(), group.getId(), EnergyViewMode.DAY, day); EnergySummary energy = getEnergySummary(_minute.getAccountId(), group.getId(), EnergyViewMode.DAY, day);
@ -412,13 +417,13 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
putEnergySummary(summary); putEnergySummary(summary);
} }
private void updateChargeSummary(BreakerConfig _config, EnergySummary _energySummary, TimeZone _tz) { public void updateChargeSummary(BreakerConfig _config, EnergySummary _energySummary, TimeZone _tz) {
Date lookback = null; Date lookback = null;
for (BillingPlan p : CollectionUtils.makeNotNull(_config.getBillingPlans())) { for (BillingPlan p : CollectionUtils.makeNotNull(_config.getBillingPlans())) {
Date cycleStart = p.getBillingCycleStart(_energySummary.getStart(), _tz); Date cycleStart = p.getBillingCycleStart(_energySummary.getStart(), _tz);
if (cycleStart.after(_energySummary.getStart())) if (cycleStart.after(_energySummary.getStart()))
cycleStart = DateUtils.addMonths(cycleStart, -1, _tz); cycleStart = DateUtils.addMonths(cycleStart, -1, _tz);
if ((lookback == null) || cycleStart.before(lookback)) if ((lookback == null) || ((cycleStart != null) && cycleStart.before(lookback)))
lookback = cycleStart; lookback = cycleStart;
} }
if (lookback != null) { if (lookback != null) {
@ -462,7 +467,7 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
Date yearMonthStart = yearStart; Date yearMonthStart = yearStart;
Set<String> monthSummaryIds = new HashSet<>(); Set<String> monthSummaryIds = new HashSet<>();
Date loopEnd = DateUtils.addDays(yearEnd, 1, _tz); Date loopEnd = DateUtils.addDays(yearEnd, 1, _tz);
while (yearMonthStart.before(loopEnd)) { while ((yearMonthStart != null) && yearMonthStart.before(loopEnd)) {
Date billingStart = plan.getBillingCycleStart(yearMonthStart, _tz); Date billingStart = plan.getBillingCycleStart(yearMonthStart, _tz);
if (DateUtils.isBetween(billingStart, yearStart, yearEnd)) if (DateUtils.isBetween(billingStart, yearStart, yearEnd))
monthSummaryIds.add(ChargeSummary.toId(rootGroup.getAccountId(), plan.getPlanId(), rootGroup.getId(), EnergyViewMode.MONTH, billingStart)); monthSummaryIds.add(ChargeSummary.toId(rootGroup.getAccountId(), plan.getPlanId(), rootGroup.getId(), EnergyViewMode.MONTH, billingStart));
@ -691,6 +696,11 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
return (account == null)?null:toAuthCode(account.getId(), account.getAuxiliaryAccountIds()); return (account == null)?null:toAuthCode(account.getId(), account.getAuxiliaryAccountIds());
} }
@Override
public String exchangeAuthCode(String _authCode, int _acctId) {
return null;
}
public String toAuthCode(int _acctId, List<Integer> _auxAcctIds) { public String toAuthCode(int _acctId, List<Integer> _auxAcctIds) {
if (_acctId < 1) if (_acctId < 1)
return null; return null;
@ -777,6 +787,8 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
if (entity == null) if (entity == null)
return false; return false;
Account acct = getAccountByUsername(aes.decryptFromBase64ToString(_key)); Account acct = getAccountByUsername(aes.decryptFromBase64ToString(_key));
if (acct == null)
return false;
acct.setPassword(_password); acct.setPassword(_password);
putAccount(acct); putAccount(acct);
proxy.delete("password_reset", new DaoQuery("_id", _key)); proxy.delete("password_reset", new DaoQuery("_id", _key));

View File

@ -1,21 +1,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-datamodel-currentmonitor</artifactId> <artifactId>lantern-datamodel-currentmonitor</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.1.0</version>
<name>lantern-datamodel-currentmonitor</name> <name>lantern-datamodel-currentmonitor</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.currentmonitor</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>currentmonitor</artifactId>
</properties> <version>1.1.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao</artifactId> <artifactId>lantern-util-dao</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
@ -41,8 +41,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -39,7 +39,7 @@ public class BreakerHub implements IIdentical<BreakerHub> {
} }
public double getPortCalibrationFactor() { public double getPortCalibrationFactor() {
return portCalibrationFactor == 0.0?1.25:portCalibrationFactor; return portCalibrationFactor == 0.0?1.20:portCalibrationFactor;
} }
public void setPortCalibrationFactor(double _portCalibrationFactor) { public void setPortCalibrationFactor(double _portCalibrationFactor) {

View File

@ -0,0 +1,52 @@
package com.lanternsoftware.datamodel.currentmonitor;
import com.lanternsoftware.util.dao.annotations.DBSerializable;
@DBSerializable
public class EmailCredentials {
private EmailProvider provider;
private String apiKey;
private String apiSecret;
private String emailFrom;
private String serverUrlBase;
public EmailProvider getProvider() {
return provider;
}
public void setProvider(EmailProvider _provider) {
provider = _provider;
}
public String getApiKey() {
return apiKey;
}
public void setApiKey(String _apiKey) {
apiKey = _apiKey;
}
public String getApiSecret() {
return apiSecret;
}
public void setApiSecret(String _apiSecret) {
apiSecret = _apiSecret;
}
public String getEmailFrom() {
return emailFrom;
}
public void setEmailFrom(String _emailFrom) {
emailFrom = _emailFrom;
}
public String getServerUrlBase() {
return serverUrlBase;
}
public void setServerUrlBase(String _serverUrlBase) {
serverUrlBase = _serverUrlBase;
}
}

View File

@ -0,0 +1,6 @@
package com.lanternsoftware.datamodel.currentmonitor;
public enum EmailProvider {
SENDGRID,
MAILJET
}

View File

@ -21,7 +21,7 @@ public enum HubConfigCharacteristic {
Shutdown(13, CharacteristicFlag.WRITE), Shutdown(13, CharacteristicFlag.WRITE),
Version(14, CharacteristicFlag.READ), Version(14, CharacteristicFlag.READ),
Update(15, CharacteristicFlag.WRITE), Update(15, CharacteristicFlag.WRITE),
ReloadConfig(15, CharacteristicFlag.WRITE); ReloadConfig(16, CharacteristicFlag.WRITE);
public final int idx; public final int idx;
public final UUID uuid; public final UUID uuid;

View File

@ -36,6 +36,10 @@ public class NetworkStatus {
pingSuccessful = _pingSuccessful; pingSuccessful = _pingSuccessful;
} }
public boolean isNetworkConnected() {
return isWifiConnected() || isEthernetConnected();
}
public boolean isWifiConnected() { public boolean isWifiConnected() {
return CollectionUtils.isNotEmpty(wifiIPs); return CollectionUtils.isNotEmpty(wifiIPs);
} }

View File

@ -0,0 +1,48 @@
package com.lanternsoftware.datamodel.currentmonitor.dao;
import com.lanternsoftware.datamodel.currentmonitor.EmailCredentials;
import com.lanternsoftware.datamodel.currentmonitor.EmailProvider;
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 EmailCredentialsSerializer extends AbstractDaoSerializer<EmailCredentials>
{
@Override
public Class<EmailCredentials> getSupportedClass()
{
return EmailCredentials.class;
}
@Override
public List<DaoProxyType> getSupportedProxies() {
return Collections.singletonList(DaoProxyType.MONGO);
}
@Override
public DaoEntity toDaoEntity(EmailCredentials _o)
{
DaoEntity d = new DaoEntity();
d.put("provider", DaoSerializer.toEnumName(_o.getProvider()));
d.put("api_key", _o.getApiKey());
d.put("api_secret", _o.getApiSecret());
d.put("email_from", _o.getEmailFrom());
d.put("server_url_base", _o.getServerUrlBase());
return d;
}
@Override
public EmailCredentials fromDaoEntity(DaoEntity _d)
{
EmailCredentials o = new EmailCredentials();
o.setProvider(DaoSerializer.getEnum(_d, "provider", EmailProvider.class));
o.setApiKey(DaoSerializer.getString(_d, "api_key"));
o.setApiSecret(DaoSerializer.getString(_d, "api_secret"));
o.setEmailFrom(DaoSerializer.getString(_d, "email_from"));
o.setServerUrlBase(DaoSerializer.getString(_d, "server_url_base"));
return o;
}
}

View File

@ -15,6 +15,7 @@ com.lanternsoftware.datamodel.currentmonitor.dao.BreakerPowerSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerSerializer com.lanternsoftware.datamodel.currentmonitor.dao.BreakerSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.ChargeSummarySerializer com.lanternsoftware.datamodel.currentmonitor.dao.ChargeSummarySerializer
com.lanternsoftware.datamodel.currentmonitor.dao.ChargeTotalSerializer com.lanternsoftware.datamodel.currentmonitor.dao.ChargeTotalSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.EmailCredentialsSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.EnergyBlockSerializer com.lanternsoftware.datamodel.currentmonitor.dao.EnergyBlockSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.EnergySummarySerializer com.lanternsoftware.datamodel.currentmonitor.dao.EnergySummarySerializer
com.lanternsoftware.datamodel.currentmonitor.dao.EnergyTotalSerializer com.lanternsoftware.datamodel.currentmonitor.dao.EnergyTotalSerializer

View File

@ -1,16 +1,15 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-service-currentmonitor</artifactId> <artifactId>lantern-service-currentmonitor</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
<version>1.0.0</version> <version>1.1.0</version>
<name>lantern-service-currentmonitor</name> <name>lantern-service-currentmonitor</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.currentmonitor</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>currentmonitor</artifactId>
</properties> <version>1.1.0</version>
</parent>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
@ -33,18 +32,18 @@
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-servlet</artifactId> <artifactId>lantern-util-servlet</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-http</artifactId> <artifactId>lantern-util-http</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.rules</groupId> <groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-service-rules</artifactId> <artifactId>lantern-service-rules</artifactId>
<version>1.0.0</version> <version>${rules.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.api-client</groupId> <groupId>com.google.api-client</groupId>
@ -67,9 +66,9 @@
<version>1.2.3</version> <version>1.2.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sendgrid</groupId> <groupId>com.mailjet</groupId>
<artifactId>sendgrid-java</artifactId> <artifactId>mailjet-client</artifactId>
<version>4.7.2</version> <version>4.2.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
@ -95,8 +94,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -0,0 +1,7 @@
package com.lanternsoftware.currentmonitor.email;
import com.lanternsoftware.datamodel.currentmonitor.EmailCredentials;
public interface IEmailProvider {
int sendTextEmail(EmailCredentials _credentials, String _to, String _subject, String _message);
}

View File

@ -0,0 +1,36 @@
package com.lanternsoftware.currentmonitor.email;
import com.lanternsoftware.datamodel.currentmonitor.EmailCredentials;
import com.mailjet.client.ClientOptions;
import com.mailjet.client.MailjetClient;
import com.mailjet.client.MailjetRequest;
import com.mailjet.client.MailjetResponse;
import com.mailjet.client.resource.Emailv31;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MailJetProvider implements IEmailProvider {
protected static final Logger LOG = LoggerFactory.getLogger(MailJetProvider.class);
@Override
public int sendTextEmail(EmailCredentials _credentials, String _to, String _subject, String _message) {
MailjetClient client;
MailjetRequest request;
MailjetResponse response;
client = new MailjetClient(_credentials.getApiKey(), _credentials.getApiSecret(), new ClientOptions("v3.1"));
request = new MailjetRequest(Emailv31.resource).property(Emailv31.MESSAGES, new JSONArray().put(new JSONObject()
.put(Emailv31.Message.FROM, new JSONObject().put("Email", _credentials.getEmailFrom()).put("Name", "Lantern Power Monitor"))
.put(Emailv31.Message.TO, new JSONArray().put(new JSONObject().put("Email", _to)))
.put(Emailv31.Message.SUBJECT, _subject)
.put(Emailv31.Message.TEXTPART, _message)));
try {
response = client.post(request);
return response.getStatus();
} catch (Exception _e) {
LOG.error("Failed to send email", _e);
return 500;
}
}
}

View File

@ -0,0 +1,26 @@
package com.lanternsoftware.currentmonitor.email;
import com.lanternsoftware.datamodel.currentmonitor.EmailCredentials;
public class SendGridProvider implements IEmailProvider {
@Override
public int sendTextEmail(EmailCredentials _credentials, String _to, String _subject, String _message) {
/* Email to = new Email(email);
Content content = new Content("text/plain", "Reset your password using this link:\nhttps://lanternpowermonitor.com/currentmonitor/resetPassword/" + key);
Mail mail = new Mail(from, subject, to, content);
SendGrid sg = new SendGrid(api_key);
Request request = new Request();
try {
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
Response response = sg.api(request);
LOG.info("Password reset email status: {}\nfrom: {}\nto: {}\nkey: {}\nhost: {}", response.getStatusCode(), from.getEmail(), to.getEmail(), api_key, sg.getHost());
zipBsonResponse(_resp, new DaoEntity("success", response.getStatusCode() == 200));
} catch (IOException ex) {
LOG.error("Failed to send password reset email", ex);
_resp.setStatus(500);
}*/
return 500;
}
}

View File

@ -1,22 +1,19 @@
package com.lanternsoftware.currentmonitor.servlet; package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals; import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.currentmonitor.email.IEmailProvider;
import com.lanternsoftware.currentmonitor.email.MailJetProvider;
import com.lanternsoftware.datamodel.currentmonitor.Account;
import com.lanternsoftware.datamodel.currentmonitor.EmailCredentials;
import com.lanternsoftware.util.CollectionUtils; import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.external.LanternFiles;
import com.lanternsoftware.util.NullUtils; import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.ResourceLoader; import com.lanternsoftware.util.ResourceLoader;
import com.lanternsoftware.util.dao.DaoEntity; import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoSerializer; import com.lanternsoftware.util.dao.DaoSerializer;
import com.lanternsoftware.util.email.EmailValidator; import com.lanternsoftware.util.email.EmailValidator;
import com.lanternsoftware.util.external.LanternFiles;
import com.lanternsoftware.util.servlet.FreemarkerConfigUtil; import com.lanternsoftware.util.servlet.FreemarkerConfigUtil;
import com.lanternsoftware.util.servlet.FreemarkerServlet; import com.lanternsoftware.util.servlet.FreemarkerServlet;
import com.sendgrid.Method;
import com.sendgrid.Request;
import com.sendgrid.Response;
import com.sendgrid.SendGrid;
import com.sendgrid.helpers.mail.Mail;
import com.sendgrid.helpers.mail.objects.Content;
import com.sendgrid.helpers.mail.objects.Email;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -25,13 +22,13 @@ import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.io.IOException;
@WebServlet("/resetPassword/*") @WebServlet("/resetPassword/*")
public class ResetPasswordServlet extends FreemarkerServlet { public class ResetPasswordServlet extends FreemarkerServlet {
protected static final Logger LOG = LoggerFactory.getLogger(ResetPasswordServlet.class); protected static final Logger LOG = LoggerFactory.getLogger(ResetPasswordServlet.class);
protected static final Configuration CONFIG = FreemarkerConfigUtil.createConfig(ResetPasswordServlet.class, "/templates", 100); protected static final Configuration CONFIG = FreemarkerConfigUtil.createConfig(ResetPasswordServlet.class, "/templates", 100);
protected static final String api_key = ResourceLoader.loadFileAsString(LanternFiles.CONFIG_PATH + "sendgrid.txt"); protected static final EmailCredentials credentials = DaoSerializer.parse(ResourceLoader.loadFileAsString(LanternFiles.CONFIG_PATH + "email.json"), EmailCredentials.class);
protected static final IEmailProvider provider = new MailJetProvider();
@Override @Override
protected Configuration getFreemarkerConfig() { protected Configuration getFreemarkerConfig() {
@ -63,25 +60,11 @@ public class ResetPasswordServlet extends FreemarkerServlet {
} else { } else {
DaoEntity payload = getRequestZipBson(_req); DaoEntity payload = getRequestZipBson(_req);
String email = DaoSerializer.getString(payload, "email"); String email = DaoSerializer.getString(payload, "email");
if (EmailValidator.getInstance().isValid(email)) { Account account = Globals.dao.getAccountByUsername(email);
if ((account != null) && EmailValidator.getInstance().isValid(email)) {
String key = Globals.dao.addPasswordResetKey(email); String key = Globals.dao.addPasswordResetKey(email);
Email from = new Email("mark.milligan@lanternsoftware.com"); int status = provider.sendTextEmail(credentials, email, "Password Reset - Lantern Power Monitor", "Reset your password using this link:\n" + credentials.getServerUrlBase() + "resetPassword/" + key);
String subject = "Password Reset - Lantern Power Monitor"; zipBsonResponse(_resp, new DaoEntity("success", status == 200));
Email to = new Email(email);
Content content = new Content("text/plain", "Reset your password using this link:\nhttps://lanternpowermonitor.com/currentmonitor/resetPassword/" + key);
Mail mail = new Mail(from, subject, to, content);
SendGrid sg = new SendGrid(api_key);
Request request = new Request();
try {
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
Response response = sg.api(request);
zipBsonResponse(_resp, new DaoEntity("success", response.getStatusCode() == 200));
} catch (IOException ex) {
LOG.error("Failed to send password reset email", ex);
_resp.setStatus(500);
}
} }
else else
_resp.setStatus(400); _resp.setStatus(400);

View File

@ -6,10 +6,10 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory; import com.google.api.client.json.gson.GsonFactory;
import com.lanternsoftware.currentmonitor.context.Globals; import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.util.external.LanternFiles;
import com.lanternsoftware.util.ResourceLoader; import com.lanternsoftware.util.ResourceLoader;
import com.lanternsoftware.util.dao.DaoEntity; import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoSerializer; import com.lanternsoftware.util.dao.DaoSerializer;
import com.lanternsoftware.util.external.LanternFiles;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -4,12 +4,13 @@
<groupId>com.lanternsoftware.currentmonitor</groupId> <groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>currentmonitor</artifactId> <artifactId>currentmonitor</artifactId>
<name>currentmonitor</name> <name>currentmonitor</name>
<version>1.0.0</version> <version>1.1.0</version>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>LanternPowerMonitor</artifactId>
</properties> <version>1.0.0</version>
</parent>
<modules> <modules>
<module>lantern-config-currentmonitor</module> <module>lantern-config-currentmonitor</module>

View File

@ -7,8 +7,13 @@
<version>1.0.0</version> <version>1.0.0</version>
<properties> <properties>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cm.version>1.1.0</cm.version>
<util.version>1.0.0</util.version>
<rules.version>1.0.0</rules.version>
<zw.version>1.0.0</zw.version>
</properties> </properties>
<modules> <modules>

View File

@ -1,26 +1,26 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-dataaccess-rules</artifactId> <artifactId>lantern-dataaccess-rules</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.0.0</version>
<name>lantern-dataaccess-rules</name> <name>lantern-dataaccess-rules</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.rules</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>rules</artifactId>
</properties> <version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.rules</groupId> <groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-datamodel-rules</artifactId> <artifactId>lantern-datamodel-rules</artifactId>
<version>1.0.0</version> <version>${rules.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao-mongo</artifactId> <artifactId>lantern-util-dao-mongo</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
@ -46,8 +46,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,21 +1,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-datamodel-rules</artifactId> <artifactId>lantern-datamodel-rules</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.0.0</version>
<name>lantern-datamodel-rules</name> <name>lantern-datamodel-rules</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.rules</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>rules</artifactId>
</properties> <version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao</artifactId> <artifactId>lantern-util-dao</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
@ -41,8 +41,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,16 +1,16 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-service-rules</artifactId> <artifactId>lantern-service-rules</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.0.0</version>
<name>lantern-service-rules</name> <name>lantern-service-rules</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.rules</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>rules</artifactId>
</properties> <version>1.0.0</version>
</parent>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
@ -37,17 +37,17 @@
<dependency> <dependency>
<groupId>com.lanternsoftware.rules</groupId> <groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-dataaccess-rules</artifactId> <artifactId>lantern-dataaccess-rules</artifactId>
<version>1.0.0</version> <version>${rules.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.currentmonitor</groupId> <groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-dataaccess-currentmonitor</artifactId> <artifactId>lantern-dataaccess-currentmonitor</artifactId>
<version>1.0.0</version> <version>${cm.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-servlet</artifactId> <artifactId>lantern-util-servlet</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax</groupId> <groupId>javax</groupId>
@ -84,8 +84,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -2,14 +2,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging> <packaging>pom</packaging>
<groupId>com.lanternsoftware.rules</groupId> <groupId>com.lanternsoftware.rules</groupId>
<artifactId>rules-reactor</artifactId> <artifactId>rules</artifactId>
<name>rules-reactor</name> <name>rules</name>
<version>1.0.0</version> <version>1.0.0</version>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>LanternPowerMonitor</artifactId>
</properties> <version>1.0.0</version>
</parent>
<modules> <modules>
<module>lantern-dataaccess-rules</module> <module>lantern-dataaccess-rules</module>

View File

@ -1,13 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-common</artifactId> <artifactId>lantern-util-common</artifactId>
<name>lantern-util-common</name> <name>lantern-util-common</name>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
@ -43,8 +47,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,13 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao-ephemeral</artifactId> <artifactId>lantern-util-dao-ephemeral</artifactId>
<name>lantern-util-dao-ephemeral</name> <name>lantern-util-dao-ephemeral</name>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
@ -38,8 +42,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,30 +1,27 @@
package com.lanternsoftware.util.dao.ephemeral; package com.lanternsoftware.util.dao.ephemeral;
import java.io.File; import com.lanternsoftware.util.CollectionUtils;
import java.util.ArrayList; import com.lanternsoftware.util.IFilter;
import java.util.Collection; import com.lanternsoftware.util.NullUtils;
import java.util.HashMap; import com.lanternsoftware.util.ResourceLoader;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import com.lanternsoftware.util.dao.AbstractDaoProxy; import com.lanternsoftware.util.dao.AbstractDaoProxy;
import com.lanternsoftware.util.dao.DaoEntity; import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoProxyType; import com.lanternsoftware.util.dao.DaoProxyType;
import com.lanternsoftware.util.dao.DaoQuery; import com.lanternsoftware.util.dao.DaoQuery;
import com.lanternsoftware.util.dao.DaoSerializer; import com.lanternsoftware.util.dao.DaoSerializer;
import com.lanternsoftware.util.dao.DaoSort; import com.lanternsoftware.util.dao.DaoSort;
import com.lanternsoftware.util.dao.annotations.PrimaryKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.lanternsoftware.util.CollectionUtils; import java.io.File;
import com.lanternsoftware.util.IFilter; import java.util.ArrayList;
import com.lanternsoftware.util.ITransformer; import java.util.Collection;
import com.lanternsoftware.util.NullUtils; import java.util.HashMap;
import com.lanternsoftware.util.ResourceLoader; import java.util.List;
import com.lanternsoftware.util.dao.annotations.PrimaryKey; import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
public class EphemeralProxy extends AbstractDaoProxy { public class EphemeralProxy extends AbstractDaoProxy {
private static final Logger LOG = LoggerFactory.getLogger(EphemeralProxy.class); private static final Logger LOG = LoggerFactory.getLogger(EphemeralProxy.class);
@ -42,9 +39,11 @@ public class EphemeralProxy extends AbstractDaoProxy {
try { try {
File file = new File(_path); File file = new File(_path);
if (file.isDirectory()) { if (file.isDirectory()) {
for (File child : file.listFiles()) { File[] files = file.listFiles();
if (files != null) {
for (File child : files) {
if (child.getName().endsWith(".json")) { if (child.getName().endsWith(".json")) {
Class<?> clazz = null; Class<?> clazz;
try { try {
clazz = Class.forName(child.getName().substring(0, child.getName().length() - 5)); clazz = Class.forName(child.getName().substring(0, child.getName().length() - 5));
} catch (ClassNotFoundException _e) { } catch (ClassNotFoundException _e) {
@ -55,6 +54,7 @@ public class EphemeralProxy extends AbstractDaoProxy {
} }
} }
} }
}
} catch (Exception _e) { } catch (Exception _e) {
LOG.error("Failed to load directory: " + _path); LOG.error("Failed to load directory: " + _path);
} }
@ -108,18 +108,14 @@ public class EphemeralProxy extends AbstractDaoProxy {
@Override @Override
public synchronized void update(Class<?> _class, DaoQuery _query, DaoEntity _changes) { public synchronized void update(Class<?> _class, DaoQuery _query, DaoEntity _changes) {
for (DaoEntity entity : queryForEntities(DaoSerializer.getTableName(_class, getType()), _query)) { for (DaoEntity entity : queryForEntities(DaoSerializer.getTableName(_class, getType()), _query)) {
for (Entry<String, Object> change : _changes.entrySet()) { entity.putAll(_changes);
entity.put(change.getKey(), change.getValue());
}
} }
} }
@Override @Override
public synchronized <T> T updateOne(Class<T> _class, DaoQuery _query, DaoEntity _changes) { public synchronized <T> T updateOne(Class<T> _class, DaoQuery _query, DaoEntity _changes) {
DaoEntity entity = CollectionUtils.getFirst(queryForEntities(DaoSerializer.getTableName(_class, getType()), _query)); DaoEntity entity = CollectionUtils.getFirst(queryForEntities(DaoSerializer.getTableName(_class, getType()), _query));
for (Entry<String, Object> change : _changes.entrySet()) { entity.putAll(_changes);
entity.put(change.getKey(), change.getValue());
}
return DaoSerializer.fromDaoEntity(entity, _class); return DaoSerializer.fromDaoEntity(entity, _class);
} }
@ -152,18 +148,12 @@ public class EphemeralProxy extends AbstractDaoProxy {
} }
} else if (value instanceof Integer) { } else if (value instanceof Integer) {
if (((Integer) value) == 0) { if (((Integer) value) == 0) {
value = new Long(getNextSequence()).intValue(); value = Long.valueOf(getNextSequence()).intValue();
} }
} }
_entity.put(key, value); _entity.put(key, value);
} }
pk = CollectionUtils.commaSeparated(CollectionUtils.transform(CollectionUtils.getAll(_entity, _primaryKeys), new ITransformer<Object, String>() { pk = CollectionUtils.commaSeparated(CollectionUtils.transform(CollectionUtils.getAll(_entity, _primaryKeys), DaoSerializer::toString));
@Override
public String transform(Object _o) {
return DaoSerializer.toString(_o);
}
}));
} }
else else
pk = DaoSerializer.getString(_entity, "_id"); pk = DaoSerializer.getString(_entity, "_id");
@ -187,12 +177,7 @@ public class EphemeralProxy extends AbstractDaoProxy {
IFilter<DaoEntity> filter = new QueryFilter(_query); IFilter<DaoEntity> filter = new QueryFilter(_query);
Map<String, DaoEntity> table = tables.get(_tableName); Map<String, DaoEntity> table = tables.get(_tableName);
if (table != null) { if (table != null) {
Iterator<DaoEntity> iter = table.values().iterator(); table.values().removeIf(filter::isFiltered);
while (iter.hasNext()) {
DaoEntity entity = iter.next();
if (filter.isFiltered(entity))
iter.remove();
}
} }
return true; return true;
} }
@ -241,16 +226,16 @@ public class EphemeralProxy extends AbstractDaoProxy {
if ((comp != null) && !DaoSerializer.getString(_daoEntity, qual.getKey()).toLowerCase().contains(((String) comp).toLowerCase())) if ((comp != null) && !DaoSerializer.getString(_daoEntity, qual.getKey()).toLowerCase().contains(((String) comp).toLowerCase()))
return false; return false;
comp = child.get("$equalssIgnoreCase"); comp = child.get("$equalssIgnoreCase");
if ((comp != null) && !DaoSerializer.getString(_daoEntity, qual.getKey()).toLowerCase().equals(((String) comp).toLowerCase())) if ((comp != null) && !DaoSerializer.getString(_daoEntity, qual.getKey()).equalsIgnoreCase(((String) comp)))
return false; return false;
comp = child.get("$startsWithIgnoreCase"); comp = child.get("$startsWithIgnoreCase");
if ((comp != null) && !DaoSerializer.getString(_daoEntity, qual.getKey()).toLowerCase().startsWith(((String) comp).toLowerCase())) if ((comp != null) && !DaoSerializer.getString(_daoEntity, qual.getKey()).toLowerCase().startsWith(((String) comp).toLowerCase()))
return false; return false;
comp = child.get("$in"); comp = child.get("$in");
if ((comp != null) && !in(_daoEntity.get(qual.getKey()), (Collection) comp)) if ((comp != null) && !in(_daoEntity.get(qual.getKey()), (Collection<?>) comp))
return false; return false;
comp = child.get("$nin"); comp = child.get("$nin");
if ((comp != null) && in(_daoEntity.get(qual.getKey()), (Collection) comp)) if ((comp != null) && in(_daoEntity.get(qual.getKey()), (Collection<?>) comp))
return false; return false;
} }
else if ((qual.getValue() instanceof String) && NullUtils.isEqual(qual.getValue(), "$null")) { else if ((qual.getValue() instanceof String) && NullUtils.isEqual(qual.getValue(), "$null")) {
@ -268,10 +253,10 @@ public class EphemeralProxy extends AbstractDaoProxy {
} }
} }
private boolean in(Object field, Collection qual) { private boolean in(Object field, Collection<?> qual) {
for (Object qualObject : qual) { for (Object qualObject : qual) {
if (field instanceof Collection) { if (field instanceof Collection) {
for (Object fieldObject : (Collection) field) { for (Object fieldObject : (Collection<?>) field) {
if (NullUtils.isEqual(fieldObject, qualObject)) if (NullUtils.isEqual(fieldObject, qualObject))
return true; return true;
} }

View File

@ -1,13 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao-mongo</artifactId> <artifactId>lantern-util-dao-mongo</artifactId>
<name>lantern-util-dao-mongo</name> <name>lantern-util-dao-mongo</name>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
@ -43,8 +47,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,13 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao</artifactId> <artifactId>lantern-util-dao</artifactId>
<name>lantern-util-dao</name> <name>lantern-util-dao</name>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
@ -38,8 +42,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,6 +1,8 @@
package com.lanternsoftware.util.dao; package com.lanternsoftware.util.dao;
import java.util.Arrays; import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.NullUtils;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -11,10 +13,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.ITransformer;
import com.lanternsoftware.util.NullUtils;
public abstract class AbstractDaoProxy implements IDaoProxy { public abstract class AbstractDaoProxy implements IDaoProxy {
private ExecutorService executor; private ExecutorService executor;
private int maxThreads = 50; private int maxThreads = 50;
@ -57,37 +55,37 @@ public abstract class AbstractDaoProxy implements IDaoProxy {
@Override @Override
public <T> Future<List<T>> queryAsync(Class<T> _class, DaoQuery _query) { public <T> Future<List<T>> queryAsync(Class<T> _class, DaoQuery _query) {
return submit(new QueryExecution<T>(this, _class, _query)); return submit(new QueryExecution<>(this, _class, _query));
} }
@Override @Override
public <T> Future<List<T>> queryAsync(Class<T> _class, DaoQuery _query, DaoSort _sort) { public <T> Future<List<T>> queryAsync(Class<T> _class, DaoQuery _query, DaoSort _sort) {
return submit(new QueryExecution<T>(this, _class, _query, _sort)); return submit(new QueryExecution<>(this, _class, _query, _sort));
} }
@Override @Override
public <T> Future<List<T>> queryAsync(Class<T> _class, DaoQuery _query, Collection<String> _fields) { public <T> Future<List<T>> queryAsync(Class<T> _class, DaoQuery _query, Collection<String> _fields) {
return submit(new QueryExecution<T>(this, _class, _query, _fields)); return submit(new QueryExecution<>(this, _class, _query, _fields));
} }
@Override @Override
public <T> Future<List<T>> queryAsync(Class<T> _class, DaoQuery _query, Collection<String> _fields, DaoSort _sort) { public <T> Future<List<T>> queryAsync(Class<T> _class, DaoQuery _query, Collection<String> _fields, DaoSort _sort) {
return submit(new QueryExecution<T>(this, _class, _query, _fields, _sort)); return submit(new QueryExecution<>(this, _class, _query, _fields, _sort));
} }
@Override @Override
public <T, V> Future<List<V>> queryWithFinalizer(Class<T> _class, DaoQuery _query, Collection<String> _fields, DaoSort _sort, QueryFinalizer<T, V> _finalizer) { public <T, V> Future<List<V>> queryWithFinalizer(Class<T> _class, DaoQuery _query, Collection<String> _fields, DaoSort _sort, QueryFinalizer<T, V> _finalizer) {
return submit(new QueryFinalizerExecution<T, V>(this, _class, _query, _fields, _sort, _finalizer)); return submit(new QueryFinalizerExecution<>(this, _class, _query, _fields, _sort, _finalizer));
} }
@Override @Override
public <T> DaoPage<T> queryPage(Class<T> _class, DaoQuery _query, Collection<String> _fields, DaoSort _sort, int _offset, int _count) { public <T> DaoPage<T> queryPage(Class<T> _class, DaoQuery _query, Collection<String> _fields, DaoSort _sort, int _offset, int _count) {
return new DaoPage<T>(query(_class, _query, _fields, _sort, _offset, _count), count(_class, _query)); return new DaoPage<>(query(_class, _query, _fields, _sort, _offset, _count), count(_class, _query));
} }
@Override @Override
public DaoPage<DaoEntity> queryForEntitiesPage(String _tableName, DaoQuery _query, Collection<String> _fields, DaoSort _sort, int _offset, int _count) { public DaoPage<DaoEntity> queryForEntitiesPage(String _tableName, DaoQuery _query, Collection<String> _fields, DaoSort _sort, int _offset, int _count) {
return new DaoPage<DaoEntity>(queryForEntities(_tableName, _query, _fields, _sort, _offset, _count), count(_tableName, _query)); return new DaoPage<>(queryForEntities(_tableName, _query, _fields, _sort, _offset, _count), count(_tableName, _query));
} }
@Override @Override
@ -112,22 +110,22 @@ public abstract class AbstractDaoProxy implements IDaoProxy {
@Override @Override
public <T> Future<T> queryOneAsync(Class<T> _class, DaoQuery _query) { public <T> Future<T> queryOneAsync(Class<T> _class, DaoQuery _query) {
return submit(new QueryOneExecution<T>(this, _class, _query)); return submit(new QueryOneExecution<>(this, _class, _query));
} }
@Override @Override
public <T> Future<T> queryOneAsync(Class<T> _class, DaoQuery _query, DaoSort _sort) { public <T> Future<T> queryOneAsync(Class<T> _class, DaoQuery _query, DaoSort _sort) {
return submit(new QueryOneExecution<T>(this, _class, _query, _sort)); return submit(new QueryOneExecution<>(this, _class, _query, _sort));
} }
@Override @Override
public <T> Future<T> queryOneAsync(Class<T> _class, DaoQuery _query, Collection<String> _fields) { public <T> Future<T> queryOneAsync(Class<T> _class, DaoQuery _query, Collection<String> _fields) {
return submit(new QueryOneExecution<T>(this, _class, _query, _fields)); return submit(new QueryOneExecution<>(this, _class, _query, _fields));
} }
@Override @Override
public <T> Future<T> queryOneAsync(Class<T> _class, DaoQuery _query, Collection<String> _fields, DaoSort _sort) { public <T> Future<T> queryOneAsync(Class<T> _class, DaoQuery _query, Collection<String> _fields, DaoSort _sort) {
return submit(new QueryOneExecution<T>(this, _class, _query, _fields, _sort)); return submit(new QueryOneExecution<>(this, _class, _query, _fields, _sort));
} }
@Override @Override
@ -157,7 +155,7 @@ public abstract class AbstractDaoProxy implements IDaoProxy {
@Override @Override
public <T> DaoPage<T> queryImportantPage(Class<T> _class, DaoQuery _query, DaoSort _sort, int _offset, int _count) { public <T> DaoPage<T> queryImportantPage(Class<T> _class, DaoQuery _query, DaoSort _sort, int _offset, int _count) {
return new DaoPage<T>(queryImportant(_class, _query, _sort, _offset, _count), count(_class, _query)); return new DaoPage<>(queryImportant(_class, _query, _sort, _offset, _count), count(_class, _query));
} }
@Override @Override
@ -247,22 +245,12 @@ public abstract class AbstractDaoProxy implements IDaoProxy {
@Override @Override
public List<String> queryForField(Class<?> _class, DaoQuery _query, final String _field, DaoSort _sort) { public List<String> queryForField(Class<?> _class, DaoQuery _query, final String _field, DaoSort _sort) {
return CollectionUtils.transform(queryForEntities(DaoSerializer.getTableName(_class, getType()), _query, Arrays.asList(_field), _sort), new ITransformer<DaoEntity, String>() { return CollectionUtils.transform(queryForEntities(DaoSerializer.getTableName(_class, getType()), _query, List.of(_field), _sort), _daoEntity -> DaoSerializer.getString(_daoEntity, _field));
@Override
public String transform(DaoEntity _daoEntity) {
return DaoSerializer.getString(_daoEntity, _field);
}
});
} }
@Override @Override
public List<String> queryForField(String _tableName, DaoQuery _query, final String _field) { public List<String> queryForField(String _tableName, DaoQuery _query, final String _field) {
return CollectionUtils.transform(queryForEntities(_tableName, _query, Arrays.asList(_field)), new ITransformer<DaoEntity, String>() { return CollectionUtils.transform(queryForEntities(_tableName, _query, List.of(_field)), _daoEntity -> DaoSerializer.getString(_daoEntity, _field));
@Override
public String transform(DaoEntity _daoEntity) {
return DaoSerializer.getString(_daoEntity, _field);
}
});
} }
@Override @Override
@ -272,7 +260,7 @@ public abstract class AbstractDaoProxy implements IDaoProxy {
@Override @Override
public <T> Map<String, T> save(Collection<T> _objects) { public <T> Map<String, T> save(Collection<T> _objects) {
Map<String, T> ids = new HashMap<String, T>(); Map<String, T> ids = new HashMap<>();
for (T o : _objects) { for (T o : _objects) {
String id = save(o); String id = save(o);
if (NullUtils.isNotEmpty(id)) if (NullUtils.isNotEmpty(id))
@ -284,6 +272,8 @@ public abstract class AbstractDaoProxy implements IDaoProxy {
@Override @Override
public Map<String, DaoEntity> save(Class<?> _class, Collection<DaoEntity> _entities) { public Map<String, DaoEntity> save(Class<?> _class, Collection<DaoEntity> _entities) {
Map<String, DaoEntity> ids = new HashMap<>(); Map<String, DaoEntity> ids = new HashMap<>();
if (_entities == null)
return ids;
for (DaoEntity e : _entities) { for (DaoEntity e : _entities) {
ids.put(saveEntity(_class, e), e); ids.put(saveEntity(_class, e), e);
} }
@ -328,12 +318,7 @@ public abstract class AbstractDaoProxy implements IDaoProxy {
} }
protected <T> List<T> toObjects(List<DaoEntity> _entities, final Class<T> _class) { protected <T> List<T> toObjects(List<DaoEntity> _entities, final Class<T> _class) {
return CollectionUtils.transform(_entities, new ITransformer<DaoEntity, T>() { return CollectionUtils.transform(_entities, _daoEntity -> DaoSerializer.fromDaoEntity(_daoEntity, _class, getType()));
@Override
public T transform(DaoEntity _daoEntity) {
return DaoSerializer.fromDaoEntity(_daoEntity, _class, getType());
}
});
} }
protected DaoQuery prepareQuery(DaoQuery _query) { protected DaoQuery prepareQuery(DaoQuery _query) {
if (queryPreparer == null) if (queryPreparer == null)

View File

@ -49,7 +49,7 @@ public class JdbcProxy extends AbstractJdbcProxy {
else else
driver = "oracle.jdbc.driver.OracleDriver"; driver = "oracle.jdbc.driver.OracleDriver";
try { try {
DriverManager.registerDriver(Class.forName(driver).asSubclass(Driver.class).newInstance()); DriverManager.registerDriver(Class.forName(driver).asSubclass(Driver.class).getDeclaredConstructor().newInstance());
JdbcProxy proxy = new JdbcProxy(DriverManager.getConnection(_connectionString, _username, _password)); JdbcProxy proxy = new JdbcProxy(DriverManager.getConnection(_connectionString, _username, _password));
proxy.databaseType = _type; proxy.databaseType = _type;
return proxy; return proxy;

View File

@ -2,12 +2,17 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-excel</artifactId> <artifactId>lantern-util-excel</artifactId>
<name>lantern-util-excel</name> <name>lantern-util-excel</name>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
@ -38,8 +43,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,13 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-http</artifactId> <artifactId>lantern-util-http</artifactId>
<name>lantern-util-http</name> <name>lantern-util-http</name>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
@ -48,8 +52,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,13 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-servlet</artifactId> <artifactId>lantern-util-servlet</artifactId>
<name>lantern-util-servlet</name> <name>lantern-util-servlet</name>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent>
<groupId>com.lanternsoftware.util</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
@ -44,8 +48,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,18 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>util</artifactId> <artifactId>util</artifactId>
<name>util</name> <name>util</name>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<properties> <parent>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <groupId>com.lanternsoftware</groupId>
<maven.compiler.source>1.8</maven.compiler.source> <artifactId>LanternPowerMonitor</artifactId>
<maven.compiler.target>1.8</maven.compiler.target> <version>1.0.0</version>
</properties> </parent>
<modules> <modules>
<module>lantern-util-common</module> <module>lantern-util-common</module>

View File

@ -1,21 +1,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.zwave</groupId>
<artifactId>lantern-datamodel-zwave</artifactId> <artifactId>lantern-datamodel-zwave</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.0.0</version>
<name>lantern-datamodel-zwave</name> <name>lantern-datamodel-zwave</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.zwave</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>zwave</artifactId>
</properties> <version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao</artifactId> <artifactId>lantern-util-dao</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
@ -41,8 +41,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,22 +1,22 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.thermometer</groupId>
<artifactId>lantern-service-thermometer</artifactId> <artifactId>lantern-service-thermometer</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
<version>1.0.0</version> <version>1.0.0</version>
<name>lantern-service-thermometer</name> <name>lantern-service-thermometer</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.zwave</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>zwave</artifactId>
</properties> <version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-servlet</artifactId> <artifactId>lantern-util-servlet</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax</groupId> <groupId>javax</groupId>
@ -69,8 +69,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,27 +1,27 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.zwave</groupId>
<artifactId>lantern-service-zwave</artifactId> <artifactId>lantern-service-zwave</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
<version>1.0.0</version> <version>1.0.0</version>
<name>lantern-service-zwave</name> <name>lantern-service-zwave</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.zwave</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>zwave</artifactId>
</properties> <version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.zwave</groupId> <groupId>com.lanternsoftware.zwave</groupId>
<artifactId>lantern-datamodel-zwave</artifactId> <artifactId>lantern-datamodel-zwave</artifactId>
<version>1.0.0</version> <version>${zw.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.currentmonitor</groupId> <groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-datamodel-currentmonitor</artifactId> <artifactId>lantern-datamodel-currentmonitor</artifactId>
<version>1.0.0</version> <version>${cm.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.pi4j</groupId> <groupId>com.pi4j</groupId>
@ -31,22 +31,22 @@
<dependency> <dependency>
<groupId>com.lanternsoftware.zwave</groupId> <groupId>com.lanternsoftware.zwave</groupId>
<artifactId>lantern-zwave</artifactId> <artifactId>lantern-zwave</artifactId>
<version>1.0.0</version> <version>${zw.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.rules</groupId> <groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-datamodel-rules</artifactId> <artifactId>lantern-datamodel-rules</artifactId>
<version>1.0.0</version> <version>${rules.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao-mongo</artifactId> <artifactId>lantern-util-dao-mongo</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-http</artifactId> <artifactId>lantern-util-http</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
@ -83,8 +83,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,21 +1,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.zwave</groupId>
<artifactId>lantern-uirt</artifactId> <artifactId>lantern-uirt</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.0.0</version>
<name>lantern-uirt</name> <name>lantern-uirt</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.zwave</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>zwave</artifactId>
</properties> <version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao</artifactId> <artifactId>lantern-util-dao</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.java.dev.jna</groupId> <groupId>net.java.dev.jna</groupId>
@ -46,8 +46,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -1,15 +1,15 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.lanternsoftware.zwave</groupId>
<artifactId>lantern-zwave</artifactId> <artifactId>lantern-zwave</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.0.0</version> <version>1.0.0</version>
<name>lantern-zwave</name> <name>lantern-zwave</name>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware.zwave</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>zwave</artifactId>
</properties> <version>1.0.0</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
@ -31,7 +31,7 @@
<dependency> <dependency>
<groupId>com.lanternsoftware.util</groupId> <groupId>com.lanternsoftware.util</groupId>
<artifactId>lantern-util-dao</artifactId> <artifactId>lantern-util-dao</artifactId>
<version>1.0.0</version> <version>${util.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
@ -57,8 +57,8 @@
<optimize>true</optimize> <optimize>true</optimize>
<showDeprecation>true</showDeprecation> <showDeprecation>true</showDeprecation>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<source>1.8</source> <source>${maven.compiler.source}</source>
<target>1.8</target> <target>${maven.compiler.target}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@ -19,7 +19,7 @@ public abstract class MessageEngine {
for (Message m : ServiceLoader.load(Message.class)) { for (Message m : ServiceLoader.load(Message.class)) {
messages.put(m.getKey(), m); messages.put(m.getKey(), m);
} }
for (IMessageSubscriber s : ServiceLoader.load(IMessageSubscriber.class)) { for (IMessageSubscriber<?> s : ServiceLoader.load(IMessageSubscriber.class)) {
subscribe(s); subscribe(s);
} }
} }
@ -50,7 +50,7 @@ public abstract class MessageEngine {
return null; return null;
} }
try { try {
Message ret = message.getClass().newInstance(); Message ret = message.getClass().getDeclaredConstructor().newInstance();
ret.fromPayload(_data); ret.fromPayload(_data);
return ret; return ret;
} catch (Exception _e) { } catch (Exception _e) {

View File

@ -2,14 +2,15 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging> <packaging>pom</packaging>
<groupId>com.lanternsoftware.zwave</groupId> <groupId>com.lanternsoftware.zwave</groupId>
<artifactId>zwave-reactor</artifactId> <artifactId>zwave</artifactId>
<name>zwave-reactor</name> <name>zwave</name>
<version>1.0.0</version> <version>1.0.0</version>
<properties> <parent>
<maven.compiler.source>1.8</maven.compiler.source> <groupId>com.lanternsoftware</groupId>
<maven.compiler.target>1.8</maven.compiler.target> <artifactId>LanternPowerMonitor</artifactId>
</properties> <version>1.0.0</version>
</parent>
<modules> <modules>
<module>lantern-datamodel-zwave</module> <module>lantern-datamodel-zwave</module>