mirror of
https://github.com/zyphlar/LanternPowerMonitor.git
synced 2024-03-08 14:07:47 +00:00
Initial Commit
This commit is contained in:
parent
21c28201c5
commit
1334c110ff
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
*.iml
|
||||||
|
*.project
|
||||||
|
*.classpath
|
||||||
|
.idea/
|
||||||
|
.gradle/
|
||||||
|
*.settings/
|
||||||
|
*target/
|
||||||
|
build/
|
||||||
|
release/
|
105
currentmonitor/lantern-currentmonitor/pom.xml
Normal file
105
currentmonitor/lantern-currentmonitor/pom.xml
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
<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>
|
||||||
|
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||||
|
<artifactId>lantern-currentmonitor</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>lantern-currentmonitor</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.7.29</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.2.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.pi4j</groupId>
|
||||||
|
<artifactId>pi4j-gpio-extension</artifactId>
|
||||||
|
<version>1.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.hypfvieh</groupId>
|
||||||
|
<artifactId>bluez-dbus</artifactId>
|
||||||
|
<version>0.1.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||||
|
<artifactId>lantern-datamodel-currentmonitor</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lanternsoftware.util</groupId>
|
||||||
|
<artifactId>lantern-util-http</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>compile</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<optimize>true</optimize>
|
||||||
|
<showDeprecation>true</showDeprecation>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.1</version>
|
||||||
|
<configuration>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<finalName>lantern-currentmonitor</finalName>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<manifestEntries>
|
||||||
|
<Main-Class>com.lanternsoftware.currentmonitor.MonitorApp</Main-Class>
|
||||||
|
<Specification-Title>Lantern Power Monitor</Specification-Title>
|
||||||
|
<Specification-Version>${project.version}</Specification-Version>
|
||||||
|
<Specification-Vendor>Lantern Software, Inc.</Specification-Vendor>
|
||||||
|
</manifestEntries>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.bluetooth.BleApplication;
|
||||||
|
import com.lanternsoftware.currentmonitor.bluetooth.BleCharacteristic;
|
||||||
|
import com.lanternsoftware.currentmonitor.bluetooth.BleCharacteristicListener;
|
||||||
|
import com.lanternsoftware.currentmonitor.bluetooth.BleHelper;
|
||||||
|
import com.lanternsoftware.currentmonitor.bluetooth.BleService;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.HubConfigService;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class BluetoothConfig implements Runnable {
|
||||||
|
private final AtomicBoolean running = new AtomicBoolean(true);
|
||||||
|
private final BleApplication app;
|
||||||
|
|
||||||
|
public BluetoothConfig(String _hubName, BleCharacteristicListener _listener) {
|
||||||
|
BleHelper.getAdapter().setPowered(true);
|
||||||
|
BleHelper.requestBusName("com.lanternsoftware");
|
||||||
|
BleHelper.setBasePath("/com/lanternsoftware");
|
||||||
|
HubConfigService service = new HubConfigService();
|
||||||
|
List<BleCharacteristic> chars = CollectionUtils.transform(service.getCharacteristics(), _c->new BleCharacteristic("HubConfig", _c.getUUID(), _c.name(), _c.getFlags()));
|
||||||
|
chars.forEach(_c->_c.setListener(_listener));
|
||||||
|
app = new BleApplication("Lantern", _hubName, new BleService("HubConfig", service.getServiceUUID(), chars));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
app.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
synchronized (running) {
|
||||||
|
running.set(false);
|
||||||
|
}
|
||||||
|
app.stop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||||
|
import com.pi4j.io.gpio.GpioPinAnalogInput;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BreakerSamples {
|
||||||
|
private final Breaker breaker;
|
||||||
|
private final GpioPinAnalogInput voltagePin;
|
||||||
|
private final GpioPinAnalogInput currentPin;
|
||||||
|
private final List<PowerSample> samples;
|
||||||
|
private int sampleCnt;
|
||||||
|
|
||||||
|
public BreakerSamples(Breaker _breaker, GpioPinAnalogInput _voltagePin, GpioPinAnalogInput _currentPin, List<PowerSample> _samples) {
|
||||||
|
breaker = _breaker;
|
||||||
|
voltagePin = _voltagePin;
|
||||||
|
currentPin = _currentPin;
|
||||||
|
samples = _samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Breaker getBreaker() {
|
||||||
|
return breaker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GpioPinAnalogInput getVoltagePin() {
|
||||||
|
return voltagePin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GpioPinAnalogInput getCurrentPin() {
|
||||||
|
return currentPin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PowerSample> getSamples() {
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PowerSample getSample(int _sample) {
|
||||||
|
return samples.get(_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSampleCnt() {
|
||||||
|
return sampleCnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSampleCnt(int _sampleCnt) {
|
||||||
|
sampleCnt = _sampleCnt;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public interface CurrentListener {
|
||||||
|
void onCurrentEvent(int _chip, int _pin, double _currentAmps, Date _start);
|
||||||
|
}
|
|
@ -0,0 +1,241 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerHub;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPolarity;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.concurrency.ConcurrencyUtils;
|
||||||
|
import com.pi4j.gpio.extension.base.AdcGpioProvider;
|
||||||
|
import com.pi4j.gpio.extension.mcp.MCP3008GpioProvider;
|
||||||
|
import com.pi4j.gpio.extension.mcp.MCP3008Pin;
|
||||||
|
import com.pi4j.io.gpio.GpioController;
|
||||||
|
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.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class CurrentMonitor {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(CurrentMonitor.class);
|
||||||
|
private static final int BATCH_CNT = 4;
|
||||||
|
private GpioController gpio;
|
||||||
|
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||||
|
private final Map<Integer, AdcGpioProvider> chips = new HashMap<>();
|
||||||
|
private final Map<Integer, GpioPinAnalogInput> pins = new HashMap<>();
|
||||||
|
private Sampler sampler;
|
||||||
|
private PowerListener listener;
|
||||||
|
private boolean debug = false;
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
try {
|
||||||
|
gpio = GpioFactory.getInstance();
|
||||||
|
LOG.info("Current Monitor Started");
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
LOG.info("Failed to get gpio factory", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
stopMonitoring();
|
||||||
|
ConcurrencyUtils.sleep(1000);
|
||||||
|
executor.shutdownNow();
|
||||||
|
chips.clear();
|
||||||
|
pins.clear();
|
||||||
|
gpio.shutdown();
|
||||||
|
LOG.info("Current Monitor Stopped");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebug(boolean _debug) {
|
||||||
|
debug = _debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void monitorPower(BreakerHub _hub, List<Breaker> _breakers, int _intervalMs, PowerListener _listener) {
|
||||||
|
stopMonitoring();
|
||||||
|
listener = _listener;
|
||||||
|
sampler = new Sampler(_hub, _breakers, _intervalMs, 2);
|
||||||
|
LOG.info("Starting to monitor ports {}", CollectionUtils.transformToCommaSeparated(_breakers, _b->String.valueOf(_b.getPort())));
|
||||||
|
executor.submit(sampler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GpioPinAnalogInput getPin(int _chip, int _pin) {
|
||||||
|
GpioPinAnalogInput pin;
|
||||||
|
synchronized (pins) {
|
||||||
|
AdcGpioProvider chip = chips.get(_chip);
|
||||||
|
if (chip == null) {
|
||||||
|
SpiChannel channel = SpiChannel.getByNumber(_chip);
|
||||||
|
if (channel == null)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
chip = new MCP3008GpioProvider(channel, 1250000, SpiDevice.DEFAULT_SPI_MODE, false);
|
||||||
|
chips.put(_chip, chip);
|
||||||
|
} catch (IOException _e) {
|
||||||
|
LOG.error("Failed to connect to chip {}", _chip, _e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
executor.submit(_runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopMonitoring() {
|
||||||
|
if (sampler != null) {
|
||||||
|
sampler.stop();
|
||||||
|
sampler = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Sampler implements Runnable {
|
||||||
|
private boolean running = true;
|
||||||
|
private final BreakerHub hub;
|
||||||
|
private final List<List<BreakerSamples>> breakers;
|
||||||
|
private final int intervalNs;
|
||||||
|
private final int concurrentBreakerCnt;
|
||||||
|
|
||||||
|
public Sampler(BreakerHub _hub, List<Breaker> _breakers, int _intervalMs, int _concurrentBreakerCnt) {
|
||||||
|
hub = _hub;
|
||||||
|
GpioPinAnalogInput voltagePin = getPin(0, 0);
|
||||||
|
breakers = CollectionUtils.transform(_breakers, _b->{
|
||||||
|
LOG.info("Getting Chip {}, Pin {} for port {}", _b.getChip(), _b.getPin(), _b.getPort());
|
||||||
|
GpioPinAnalogInput currentPin = getPin(_b.getChip(), _b.getPin());
|
||||||
|
List<BreakerSamples> batches = new ArrayList<>(BATCH_CNT);
|
||||||
|
for (int i=0; i<BATCH_CNT; i++) {
|
||||||
|
List<PowerSample> samples = new ArrayList<>(30000/_breakers.size());
|
||||||
|
for (int j=0; j<30000/_breakers.size(); j++) {
|
||||||
|
samples.add(new PowerSample());
|
||||||
|
}
|
||||||
|
batches.add(new BreakerSamples(_b, voltagePin, currentPin, samples));
|
||||||
|
}
|
||||||
|
return batches;
|
||||||
|
});
|
||||||
|
intervalNs = _intervalMs*1000000;
|
||||||
|
concurrentBreakerCnt = Math.min(_breakers.size(), _concurrentBreakerCnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long start = System.nanoTime();
|
||||||
|
long interval = 0;
|
||||||
|
int cycle;
|
||||||
|
BreakerSamples[] cycleBreakers = new BreakerSamples[concurrentBreakerCnt];
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (!running)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
final Date readTime = new Date();
|
||||||
|
final long intervalStart = (interval * intervalNs) + start;
|
||||||
|
long intervalEnd = intervalStart + intervalNs;
|
||||||
|
cycle = 0;
|
||||||
|
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) {
|
||||||
|
for (curBreaker = 0; curBreaker < concurrentBreakerCnt; curBreaker++) {
|
||||||
|
cycleBreakers[curBreaker] = breakers.get(((cycle * concurrentBreakerCnt) + curBreaker) % breakers.size()).get(batch);
|
||||||
|
}
|
||||||
|
cycle++;
|
||||||
|
long cycleEnd = intervalStart + (cycle * (intervalNs / hub.getFrequency()));
|
||||||
|
while (System.nanoTime() < cycleEnd) {
|
||||||
|
for (curBreaker = 0; curBreaker < concurrentBreakerCnt; curBreaker++) {
|
||||||
|
PowerSample sample = cycleBreakers[curBreaker].getSample(cycleBreakers[curBreaker].getSampleCnt());
|
||||||
|
sample.voltage = cycleBreakers[curBreaker].getVoltagePin().getValue();
|
||||||
|
sample.current = cycleBreakers[curBreaker].getCurrentPin().getValue();
|
||||||
|
cycleBreakers[curBreaker].setSampleCnt(cycleBreakers[curBreaker].getSampleCnt()+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interval++;
|
||||||
|
executor.submit(() -> {
|
||||||
|
for (List<BreakerSamples> breaker : breakers) {
|
||||||
|
double vOffset = 0.0;
|
||||||
|
double iOffset = 0.0;
|
||||||
|
BreakerSamples samples = breaker.get(batch);
|
||||||
|
List<PowerSample> validSamples = samples.getSamples().subList(0, samples.getSampleCnt());
|
||||||
|
for (PowerSample sample : validSamples) {
|
||||||
|
vOffset += sample.voltage;
|
||||||
|
iOffset += sample.current;
|
||||||
|
}
|
||||||
|
vOffset /= samples.getSampleCnt();
|
||||||
|
iOffset /= samples.getSampleCnt();
|
||||||
|
int lowSamples = 0;
|
||||||
|
double pSum = 0.0;
|
||||||
|
double vRms = 0.0;
|
||||||
|
double lowPassFilter = samples.getBreaker().getLowPassFilter();
|
||||||
|
for (PowerSample sample : validSamples) {
|
||||||
|
sample.current -= iOffset;
|
||||||
|
if (Math.abs(sample.current) < lowPassFilter)
|
||||||
|
lowSamples++;
|
||||||
|
sample.voltage -= vOffset;
|
||||||
|
pSum += sample.current * sample.voltage;
|
||||||
|
vRms += sample.voltage * sample.voltage;
|
||||||
|
}
|
||||||
|
vRms /= validSamples.size();
|
||||||
|
vRms = hub.getVoltageCalibrationFactor() * Math.sqrt(vRms);
|
||||||
|
int lowSampleRatio = (lowSamples * 100) / samples.getSampleCnt();
|
||||||
|
double realPower = Math.abs((hub.getVoltageCalibrationFactor() * samples.getBreaker().getFinalCalibrationFactor() * pSum) / samples.getSampleCnt());
|
||||||
|
if ((lowSampleRatio > 75) && realPower < 13.0)
|
||||||
|
realPower = 0.0;
|
||||||
|
if (samples.getBreaker().getPolarity() == BreakerPolarity.SOLAR)
|
||||||
|
realPower = -realPower;
|
||||||
|
if (debug) {
|
||||||
|
synchronized (CurrentMonitor.this) {
|
||||||
|
LOG.info("===========================Start Port {}", samples.getBreaker().getPort());
|
||||||
|
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("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)));
|
||||||
|
LOG.info("vRms: {}", String.format("%.3f", vRms));
|
||||||
|
LOG.info("iRms: {}", String.format("%.3f", iRms));
|
||||||
|
double apparentPower = vRms * iRms;
|
||||||
|
LOG.info("Apparent Power: {} watts", String.format("%.3f", apparentPower));
|
||||||
|
LOG.info("Real Power: {} watts", String.format("%.3f", realPower));
|
||||||
|
double powerFactor = realPower / apparentPower;
|
||||||
|
LOG.info("Power Factor: {}", String.format("%.3f", powerFactor));
|
||||||
|
LOG.info("===========================End Port {}", samples.getBreaker().getPort());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listener.onPowerEvent(new BreakerPower(samples.getBreaker().getPanel(), samples.getBreaker().getSpace(), readTime, realPower, vRms));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
LOG.error("Exception while monitoring power", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void stop() {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,409 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.bluetooth.BleCharacteristicListener;
|
||||||
|
import com.lanternsoftware.currentmonitor.led.LEDFlasher;
|
||||||
|
import com.lanternsoftware.currentmonitor.util.NetworkMonitor;
|
||||||
|
import com.lanternsoftware.currentmonitor.wifi.WifiConfig;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerHub;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPowerMinute;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.HubConfigCharacteristic;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.HubConfigService;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.DateUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.concurrency.ConcurrencyUtils;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import com.lanternsoftware.util.http.HttpPool;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.ByteArrayEntity;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.Console;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.jar.Attributes;
|
||||||
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
|
public class MonitorApp {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(MonitorApp.class);
|
||||||
|
private static final String WORKING_DIR = "/opt/currentmonitor/";
|
||||||
|
private static String authCode;
|
||||||
|
private static MonitorConfig config;
|
||||||
|
private static BreakerConfig breakerConfig;
|
||||||
|
private static String host;
|
||||||
|
private static Date lastUpdateCheck = new Date();
|
||||||
|
private static HttpPool pool;
|
||||||
|
private static LEDFlasher flasher = null;
|
||||||
|
private static final AtomicBoolean running = new AtomicBoolean(true);
|
||||||
|
private static final CurrentMonitor monitor = new CurrentMonitor();
|
||||||
|
private static final List<BreakerPower> readings = new ArrayList<>();
|
||||||
|
private static final String version = getVersionNumber();
|
||||||
|
private static final PowerListener logger = _p -> {
|
||||||
|
if (!config.isDebug()) {
|
||||||
|
_p.setHubVersion(version);
|
||||||
|
if (breakerConfig != null)
|
||||||
|
_p.setAccountId(breakerConfig.getAccountId());
|
||||||
|
synchronized (readings) {
|
||||||
|
readings.add(_p);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
LOG.info("Panel{} - Space{} Power: {}W", _p.getPanel(), Breaker.toSpaceDisplay(_p.getSpace()), String.format("%.3f", _p.getPower()));
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
config = DaoSerializer.parse(ResourceLoader.loadFileAsString(WORKING_DIR + "config.json"), MonitorConfig.class);
|
||||||
|
if (config == null) {
|
||||||
|
LOG.error("Failed to load config file from {}", WORKING_DIR + "config.json");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pool = new HttpPool(10, 10, config.getSocketTimeout(), config.getConnectTimeout(), config.getSocketTimeout());
|
||||||
|
host = NullUtils.terminateWith(config.getHost(), "/");
|
||||||
|
monitor.setDebug(config.isDebug());
|
||||||
|
monitor.start();
|
||||||
|
LEDFlasher.setLEDOn(false);
|
||||||
|
final BluetoothConfig bluetoothConfig = new BluetoothConfig("Lantern Hub", new BleCharacteristicListener() {
|
||||||
|
@Override
|
||||||
|
public void write(String _name, byte[] _value) {
|
||||||
|
HubConfigCharacteristic ch = NullUtils.toEnum(HubConfigCharacteristic.class, _name);
|
||||||
|
LOG.info("Char Received, Name: {} Value: {}", _name, _value);
|
||||||
|
monitor.submit(()->{
|
||||||
|
switch (ch) {
|
||||||
|
case HubIndex:
|
||||||
|
if ((_value.length > 0)) {
|
||||||
|
config.setHub(_value[0]);
|
||||||
|
ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AuthCode:
|
||||||
|
String value = NullUtils.toString(_value);
|
||||||
|
if (NullUtils.isNotEmpty(value)) {
|
||||||
|
authCode = value;
|
||||||
|
config.setAuthCode(value);
|
||||||
|
ResourceLoader.writeFile(WORKING_DIR + "config.json", DaoSerializer.toJson(config));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WifiCredentials:
|
||||||
|
String ssid = HubConfigService.decryptWifiSSID(_value);
|
||||||
|
String pwd = HubConfigService.decryptWifiPassword(_value);
|
||||||
|
if (NullUtils.isNotEmpty(ssid) && NullUtils.isNotEmpty(pwd))
|
||||||
|
WifiConfig.setCredentials(ssid, pwd);
|
||||||
|
break;
|
||||||
|
case Flash:
|
||||||
|
if ((CollectionUtils.length(_value) == 0) || (_value[0] == 0)) {
|
||||||
|
if (flasher != null) {
|
||||||
|
flasher.stop();
|
||||||
|
flasher = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LEDFlasher.setLEDOn(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (flasher == null) {
|
||||||
|
flasher = new LEDFlasher();
|
||||||
|
monitor.submit(flasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Restart:
|
||||||
|
LOG.info("Restarting Current Monitor...");
|
||||||
|
try {
|
||||||
|
Runtime.getRuntime().exec("service currentmonitor restart");
|
||||||
|
} catch (IOException _e) {
|
||||||
|
LOG.error("Exception occurred while trying to restart", _e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Reboot:
|
||||||
|
LOG.info("Rebooting Pi...");
|
||||||
|
try {
|
||||||
|
Runtime.getRuntime().exec("reboot now");
|
||||||
|
} catch (IOException _e) {
|
||||||
|
LOG.error("Exception occurred while trying to reboot", _e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] read(String _name) {
|
||||||
|
HubConfigCharacteristic ch = NullUtils.toEnum(HubConfigCharacteristic.class, _name);
|
||||||
|
if (HubConfigCharacteristic.HubIndex == ch)
|
||||||
|
return new byte[]{(byte)(config == null?0:config.getHub())};
|
||||||
|
if (HubConfigCharacteristic.AccountId == ch)
|
||||||
|
return ByteBuffer.allocate(4).putInt(breakerConfig == null?0:breakerConfig.getAccountId()).array();
|
||||||
|
if (HubConfigCharacteristic.NetworkState == ch)
|
||||||
|
return new byte[]{NetworkMonitor.getNetworkStatus().toMask()};
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
monitor.submit(bluetoothConfig);
|
||||||
|
if (NullUtils.isNotEmpty(config.getAuthCode())) {
|
||||||
|
authCode = config.getAuthCode();
|
||||||
|
//TODO: check auth code validity
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
HttpGet auth = new HttpGet(host + "auth");
|
||||||
|
HttpPool.addBasicAuthHeader(auth, config.getUsername(), config.getPassword());
|
||||||
|
authCode = DaoSerializer.getString(DaoSerializer.parse(pool.executeToString(auth)), "auth_code");
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
HttpGet get = new HttpGet(host + "config");
|
||||||
|
get.addHeader("auth_code", authCode);
|
||||||
|
breakerConfig = DaoSerializer.parse(pool.executeToString(get), BreakerConfig.class);
|
||||||
|
if (breakerConfig != null)
|
||||||
|
break;
|
||||||
|
LOG.error("Failed to load breaker config. Retrying in 5 seconds...");
|
||||||
|
ConcurrencyUtils.sleep(5000);
|
||||||
|
}
|
||||||
|
LOG.info("Breaker Config loaded");
|
||||||
|
LOG.debug(DaoSerializer.toJson(breakerConfig));
|
||||||
|
BreakerHub hub = breakerConfig.getHub(config.getHub());
|
||||||
|
if (hub != null) {
|
||||||
|
List<Breaker> breakers = breakerConfig.getBreakersForHub(config.getHub());
|
||||||
|
LOG.info("Monitoring {} breakers for hub {}", CollectionUtils.size(breakers), hub.getHub());
|
||||||
|
monitor.monitorPower(hub, breakers, 1000, logger);
|
||||||
|
}
|
||||||
|
monitor.submit(new PowerPoster());
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
|
synchronized (running) {
|
||||||
|
running.set(false);
|
||||||
|
}
|
||||||
|
bluetoothConfig.stop();
|
||||||
|
monitor.stop();
|
||||||
|
pool.shutdown();
|
||||||
|
}, "Monitor Shutdown"));
|
||||||
|
Console c = System.console();
|
||||||
|
BufferedReader reader = (c == null)?new BufferedReader(new InputStreamReader(System.in)):null;
|
||||||
|
while (running.get()) {
|
||||||
|
try {
|
||||||
|
String command = c != null ? c.readLine() : reader.readLine();
|
||||||
|
if (NullUtils.isEqual("exit", command))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Exception while reading from console input", _e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PowerPoster implements Runnable {
|
||||||
|
private final long firstPost;
|
||||||
|
private long lastPost;
|
||||||
|
private int lastMinute;
|
||||||
|
private final Map<Integer, Float[]> breakers = new HashMap<>();
|
||||||
|
|
||||||
|
public PowerPoster() {
|
||||||
|
firstPost = (new Date().getTime()/1000)*1000;
|
||||||
|
lastPost = new Date().getTime();
|
||||||
|
lastMinute = (int)(new Date().getTime()/60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
synchronized (running) {
|
||||||
|
if (!running.get())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DaoEntity post = null;
|
||||||
|
DaoEntity minutePost = null;
|
||||||
|
int curMinute = (int) (new Date().getTime() / 60000);
|
||||||
|
synchronized (readings) {
|
||||||
|
if (!readings.isEmpty()) {
|
||||||
|
post = new DaoEntity("readings", DaoSerializer.toDaoEntities(readings));
|
||||||
|
if (curMinute != lastMinute) {
|
||||||
|
HubPowerMinute minute = new HubPowerMinute();
|
||||||
|
minute.setAccountId(breakerConfig.getAccountId());
|
||||||
|
minute.setHub(config.getHub());
|
||||||
|
minute.setMinute(lastMinute);
|
||||||
|
minute.setBreakers(CollectionUtils.transform(breakers.entrySet(), _e -> {
|
||||||
|
BreakerPowerMinute breaker = new BreakerPowerMinute();
|
||||||
|
breaker.setPanel(Breaker.toPanel(_e.getKey()));
|
||||||
|
breaker.setSpace(Breaker.toSpace(_e.getKey()));
|
||||||
|
breaker.setReadings(CollectionUtils.asArrayList(_e.getValue()));
|
||||||
|
return breaker;
|
||||||
|
}));
|
||||||
|
breakers.clear();
|
||||||
|
minutePost = DaoSerializer.toDaoEntity(minute);
|
||||||
|
lastMinute = curMinute;
|
||||||
|
}
|
||||||
|
for (BreakerPower power : readings) {
|
||||||
|
Float[] breakerReadings = breakers.computeIfAbsent(Breaker.toId(power.getPanel(), power.getSpace()), _i -> new Float[60]);
|
||||||
|
breakerReadings[(int) ((power.getReadTime().getTime() / 1000)%60)] = (float) power.getPower();
|
||||||
|
}
|
||||||
|
readings.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (minutePost != null) {
|
||||||
|
byte[] payload = DaoSerializer.toZipBson(minutePost);
|
||||||
|
if (!post(payload, "power/hub")) {
|
||||||
|
LOG.info("Failed Posting HubPowerMinute, writing cache");
|
||||||
|
ResourceLoader.writeFile(WORKING_DIR + "cache/" + UUID.randomUUID().toString() + ".min", payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (post != null) {
|
||||||
|
byte[] payload = DaoSerializer.toZipBson(post);
|
||||||
|
if (post(payload, "power/batch")) {
|
||||||
|
File[] files = new File(WORKING_DIR + "cache").listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
payload = ResourceLoader.loadFile(file.getAbsolutePath());
|
||||||
|
if (post(payload, file.getName().endsWith("dat") ? "power/batch" : "power/hub"))
|
||||||
|
file.delete();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DateUtils.diffInSeconds(new Date(), lastUpdateCheck) >= config.getUpdateInterval()) {
|
||||||
|
lastUpdateCheck = new Date();
|
||||||
|
monitor.submit(new UpdateChecker());
|
||||||
|
monitor.submit(new CommandChecker());
|
||||||
|
}
|
||||||
|
long now = new Date().getTime();
|
||||||
|
long duration = (now - firstPost)%1000;
|
||||||
|
if (now - lastPost < 1000) {
|
||||||
|
ConcurrencyUtils.sleep(1000 - duration);
|
||||||
|
}
|
||||||
|
lastPost = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
LOG.error("Exception in PowerPoster", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void uploadLog() {
|
||||||
|
LOG.info("Commanded to upload log file, preparing...");
|
||||||
|
String log = ResourceLoader.loadFileAsString(WORKING_DIR + "log/log.txt");
|
||||||
|
if (NullUtils.isNotEmpty(log)) {
|
||||||
|
DaoEntity payload = new DaoEntity("command", "log").and("payload", log);
|
||||||
|
post(DaoSerializer.toZipBson(payload), "command");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean post(byte[] _payload, String _path) {
|
||||||
|
HttpPost post = new HttpPost(host + _path);
|
||||||
|
post.addHeader("auth_code", authCode);
|
||||||
|
post.setEntity(new ByteArrayEntity(_payload, ContentType.APPLICATION_OCTET_STREAM));
|
||||||
|
CloseableHttpResponse resp = pool.execute(post);
|
||||||
|
try {
|
||||||
|
return ((resp != null) && (resp.getStatusLine() != null) && (resp.getStatusLine().getStatusCode() == 200));
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class UpdateChecker implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DaoEntity meta = DaoSerializer.fromZipBson(pool.executeToByteArray(new HttpGet(host + "update/version")));
|
||||||
|
String newVersion = DaoSerializer.getString(meta, "version");
|
||||||
|
if (NullUtils.isNotEqual(newVersion, version)) {
|
||||||
|
LOG.info("New version found, {}, downloading...", newVersion);
|
||||||
|
byte[] jar = pool.executeToByteArray(new HttpGet(host + "update"));
|
||||||
|
if (CollectionUtils.length(jar) == DaoSerializer.getInteger(meta, "size") && NullUtils.isEqual(DigestUtils.md5Hex(jar), DaoSerializer.getString(meta, "checksum"))) {
|
||||||
|
LOG.info("Update downloaded, writing jar and restarting...");
|
||||||
|
ResourceLoader.writeFile(WORKING_DIR + "lantern-currentmonitor.jar", jar);
|
||||||
|
try {
|
||||||
|
Runtime.getRuntime().exec("service currentmonitor restart");
|
||||||
|
} catch (IOException _e) {
|
||||||
|
LOG.error("Exception occurred while trying to restart", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class CommandChecker implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
HttpGet get = new HttpGet(host + "command");
|
||||||
|
get.addHeader("auth_code", authCode);
|
||||||
|
DaoEntity meta = DaoSerializer.fromZipBson(pool.executeToByteArray(get));
|
||||||
|
for (String command : DaoSerializer.getList(meta, "commands", String.class)) {
|
||||||
|
if (NullUtils.isEqual(command, "log")) {
|
||||||
|
uploadLog();
|
||||||
|
}
|
||||||
|
else if (NullUtils.makeNotNull(command).startsWith("timeout")) {
|
||||||
|
LOG.info("Updating timeouts...");
|
||||||
|
String[] timeouts = NullUtils.cleanSplit(command, "-");
|
||||||
|
if (CollectionUtils.size(timeouts) != 3)
|
||||||
|
continue;
|
||||||
|
config.setConnectTimeout(DaoSerializer.toInteger(timeouts[1]));
|
||||||
|
config.setSocketTimeout(DaoSerializer.toInteger(timeouts[2]));
|
||||||
|
HttpPool old = pool;
|
||||||
|
pool = new HttpPool(10, 10, config.getSocketTimeout(), config.getConnectTimeout(), config.getSocketTimeout());
|
||||||
|
old.shutdown();
|
||||||
|
ResourceLoader.writeFile(WORKING_DIR+"config.json", DaoSerializer.toJson(config));
|
||||||
|
}
|
||||||
|
else if (NullUtils.isEqual(command, "extend_filesystem")) {
|
||||||
|
LOG.info("Extending filesystem and rebooting");
|
||||||
|
try {
|
||||||
|
Runtime.getRuntime().exec("raspi-config --expand-rootfs");
|
||||||
|
ConcurrencyUtils.sleep(3000);
|
||||||
|
Runtime.getRuntime().exec("reboot");
|
||||||
|
} catch (IOException _e) {
|
||||||
|
LOG.error("Exception occurred while trying to extend filesystem", _e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (NullUtils.isEqual(command, "restart")) {
|
||||||
|
LOG.info("Restarting...");
|
||||||
|
try {
|
||||||
|
Runtime.getRuntime().exec("service currentmonitor restart");
|
||||||
|
} catch (IOException _e) {
|
||||||
|
LOG.error("Exception occurred while trying to restart", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getVersionNumber() {
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = MonitorApp.class.getResourceAsStream("/META-INF/MANIFEST.MF");
|
||||||
|
Manifest manifest = new Manifest(is);
|
||||||
|
Attributes attr = manifest.getMainAttributes();
|
||||||
|
String version = attr.getValue("Specification-Version");
|
||||||
|
LOG.info("Current Version: {}", version);
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to get current version number", _e);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
IOUtils.closeQuietly(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
@DBSerializable
|
||||||
|
public class MonitorConfig {
|
||||||
|
private String host;
|
||||||
|
private String authCode;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private int hub;
|
||||||
|
private boolean debug;
|
||||||
|
private int connectTimeout;
|
||||||
|
private int socketTimeout;
|
||||||
|
private int updateInterval;
|
||||||
|
|
||||||
|
public MonitorConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonitorConfig(int _hub, String _host) {
|
||||||
|
hub = _hub;
|
||||||
|
host = _host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHost(String _host) {
|
||||||
|
host = _host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthCode() {
|
||||||
|
return authCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthCode(String _authCode) {
|
||||||
|
authCode = _authCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String _username) {
|
||||||
|
username = _username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String _password) {
|
||||||
|
password = _password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHub() {
|
||||||
|
return hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHub(int _hub) {
|
||||||
|
hub = _hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDebug() {
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebug(boolean _debug) {
|
||||||
|
debug = _debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConnectTimeout() {
|
||||||
|
return connectTimeout == 0?3000:connectTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnectTimeout(int _connectTimeout) {
|
||||||
|
connectTimeout = _connectTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSocketTimeout() {
|
||||||
|
return socketTimeout == 0?5000:socketTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocketTimeout(int _socketTimeout) {
|
||||||
|
socketTimeout = _socketTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUpdateInterval() {
|
||||||
|
return updateInterval == 0?300:updateInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateInterval(int _updateInterval) {
|
||||||
|
updateInterval = _updateInterval;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||||
|
|
||||||
|
public interface PowerListener {
|
||||||
|
void onPowerEvent(BreakerPower _power);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
public class PowerSample {
|
||||||
|
public double voltage;
|
||||||
|
public double current;
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.bluetooth;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import org.freedesktop.dbus.DBusPath;
|
||||||
|
import org.freedesktop.dbus.interfaces.DBusInterface;
|
||||||
|
import org.freedesktop.dbus.interfaces.Properties;
|
||||||
|
import org.freedesktop.dbus.types.Variant;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class AbstractProperties implements Properties {
|
||||||
|
protected final String interfaceName;
|
||||||
|
protected final Map<String, Variant<?>> properties = new HashMap<>();
|
||||||
|
|
||||||
|
public AbstractProperties(Class<? extends DBusInterface> _bleClass) {
|
||||||
|
interfaceName = _bleClass.getCanonicalName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInterfaceName() {
|
||||||
|
return interfaceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract DBusPath getPath();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public <A> A Get(String _interface, String _propertyName) {
|
||||||
|
if (NullUtils.isNotEqual(_interface, interfaceName))
|
||||||
|
return null;
|
||||||
|
Variant<?> var = properties.get(_propertyName);
|
||||||
|
try {
|
||||||
|
return (A) var.getValue();
|
||||||
|
}
|
||||||
|
catch (ClassCastException _e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public <A> void Set(String _interface, String _propertyName, A _value) {
|
||||||
|
if ((_value == null) || NullUtils.isNotEqual(_interface, interfaceName))
|
||||||
|
return;
|
||||||
|
properties.put(_propertyName, new Variant(_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Variant<?>> GetAll(String _interfaceName) {
|
||||||
|
if (NullUtils.isNotEqual(_interfaceName, getInterfaceName()))
|
||||||
|
return new HashMap<>();
|
||||||
|
return getProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Variant<?>> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AbstractProperties> getAllObjects() {
|
||||||
|
List<AbstractProperties> objects = new ArrayList<>();
|
||||||
|
getAllObjects(objects);
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAllObjects(List<AbstractProperties> _objects) {
|
||||||
|
_objects.add(this);
|
||||||
|
for (AbstractProperties o : CollectionUtils.makeNotNull(getChildObjects())) {
|
||||||
|
o.getAllObjects(_objects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<? extends AbstractProperties> getChildObjects() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<DBusPath, Map<String, Map<String, Variant<?>>>> getAllManagedObjects() {
|
||||||
|
return getAllManagedObjects(getAllObjects());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<DBusPath, Map<String, Map<String, Variant<?>>>> getAllManagedObjects(List<AbstractProperties> _objects) {
|
||||||
|
Map<DBusPath, Map<String, Map<String, Variant<?>>>> objects = new HashMap<>();
|
||||||
|
for (AbstractProperties o : _objects) {
|
||||||
|
objects.put(o.getPath(), CollectionUtils.asHashMap(o.getInterfaceName(), o.getProperties()));
|
||||||
|
}
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.bluetooth;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import org.bluez.LEAdvertisement1;
|
||||||
|
import org.bluez.LEAdvertisingManager1;
|
||||||
|
import org.freedesktop.dbus.DBusPath;
|
||||||
|
import org.freedesktop.dbus.interfaces.Properties;
|
||||||
|
import org.freedesktop.dbus.types.Variant;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class BleAdvertisement extends AbstractProperties implements LEAdvertisement1, Properties {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(BleAdvertisement.class);
|
||||||
|
|
||||||
|
private final LEAdvertisingManager1 advertiser;
|
||||||
|
private final DBusPath advertisementPath;
|
||||||
|
|
||||||
|
public BleAdvertisement(String _name, BleApplication _app) {
|
||||||
|
super(LEAdvertisement1.class);
|
||||||
|
String[] serviceUUIDs = CollectionUtils.transform(_app.getServices(), _s->_s.getUuid().toString()).toArray(new String[0]);
|
||||||
|
advertisementPath = new DBusPath(BleHelper.advertismentPath(_app.getName()));
|
||||||
|
advertiser = BleHelper.getRemoteObject(BleHelper.getAdapter().getDbusPath(), LEAdvertisingManager1.class);
|
||||||
|
properties.put("Type", new Variant<>("peripheral"));
|
||||||
|
properties.put("ServiceUUIDs", new Variant<>(serviceUUIDs));
|
||||||
|
properties.put("LocalName", new Variant<>(_name));
|
||||||
|
properties.put("Includes", new Variant<>(new String[]{"tx-power"}));
|
||||||
|
BleHelper.unExportObject(this);
|
||||||
|
BleHelper.exportObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
try {
|
||||||
|
advertiser.RegisterAdvertisement(advertisementPath, new HashMap<>());
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to register advertisement", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
try {
|
||||||
|
advertiser.UnregisterAdvertisement(advertisementPath);
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to unregister advertisement", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRemote() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectPath() {
|
||||||
|
return advertisementPath.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DBusPath getPath() {
|
||||||
|
return advertisementPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void Release() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.bluetooth;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import org.bluez.GattApplication1;
|
||||||
|
import org.bluez.GattManager1;
|
||||||
|
import org.freedesktop.dbus.DBusPath;
|
||||||
|
import org.freedesktop.dbus.interfaces.ObjectManager;
|
||||||
|
import org.freedesktop.dbus.types.Variant;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BleApplication implements GattApplication1, ObjectManager {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(BleApplication.class);
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final DBusPath appPath;
|
||||||
|
private final GattManager1 appManager;
|
||||||
|
private final List<BleService> services;
|
||||||
|
private final BleAdvertisement advertisement;
|
||||||
|
|
||||||
|
public BleApplication(String _name, String _advertisedName, BleService... _services) {
|
||||||
|
this(_name, _advertisedName, CollectionUtils.asArrayList(_services));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BleApplication(String _name, String _advertisedName, List<BleService> _services) {
|
||||||
|
name = _name;
|
||||||
|
appPath = new DBusPath(BleHelper.applicationPath(_name));
|
||||||
|
appManager = BleHelper.getRemoteObject(BleHelper.getAdapter().getDbusPath(), GattManager1.class);
|
||||||
|
services = _services;
|
||||||
|
advertisement = new BleAdvertisement(_advertisedName, this);
|
||||||
|
List<AbstractProperties> objects = getManagedObjects();
|
||||||
|
BleHelper.unExportObject(this);
|
||||||
|
objects.forEach(BleHelper::unExportObject);
|
||||||
|
BleHelper.exportObject(this);
|
||||||
|
objects.forEach(BleHelper::exportObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AbstractProperties> getManagedObjects() {
|
||||||
|
return CollectionUtils.aggregate(services, AbstractProperties::getAllObjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BleService> getServices() {
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<DBusPath, Map<String, Map<String, Variant<?>>>> GetManagedObjects() {
|
||||||
|
return AbstractProperties.getAllManagedObjects(getManagedObjects());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
try {
|
||||||
|
appManager.RegisterApplication(appPath, new HashMap<>());
|
||||||
|
advertisement.start();
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to register application", _e);
|
||||||
|
_e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
try {
|
||||||
|
advertisement.stop();
|
||||||
|
appManager.UnregisterApplication(appPath);
|
||||||
|
BleHelper.connection.disconnect();
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to unregister application", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRemote() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectPath() {
|
||||||
|
return appPath.getPath();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.bluetooth;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.CharacteristicFlag;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import org.bluez.GattCharacteristic1;
|
||||||
|
import org.bluez.datatypes.TwoTuple;
|
||||||
|
import org.freedesktop.dbus.DBusPath;
|
||||||
|
import org.freedesktop.dbus.FileDescriptor;
|
||||||
|
import org.freedesktop.dbus.types.UInt16;
|
||||||
|
import org.freedesktop.dbus.types.Variant;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class BleCharacteristic extends AbstractProperties implements GattCharacteristic1 {
|
||||||
|
private final String charName;
|
||||||
|
private final DBusPath charPath;
|
||||||
|
private final UUID uuid;
|
||||||
|
private final List<BleDescriptor> descriptors;
|
||||||
|
private BleCharacteristicListener listener;
|
||||||
|
|
||||||
|
public BleCharacteristic(String _serviceName, UUID _uuid, String _characteristicName, Collection<CharacteristicFlag> _flags) {
|
||||||
|
this(_serviceName, _uuid, _characteristicName, _flags, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BleCharacteristic(String _serviceName, UUID _uuid, String _characteristicName, Collection<CharacteristicFlag> _flags, List<BleDescriptor> _descriptors) {
|
||||||
|
super(GattCharacteristic1.class);
|
||||||
|
charName = _characteristicName;
|
||||||
|
charPath = new DBusPath(BleHelper.characteristicPath(_serviceName, _characteristicName));
|
||||||
|
uuid = _uuid;
|
||||||
|
descriptors = _descriptors;
|
||||||
|
properties.put("Service", new Variant<>(new DBusPath(BleHelper.servicePath(_serviceName))));
|
||||||
|
if (uuid != null)
|
||||||
|
properties.put("UUID", new Variant<>(uuid.toString()));
|
||||||
|
if (CollectionUtils.isNotEmpty(_flags))
|
||||||
|
properties.put("Flags", new Variant<>(CharacteristicFlag.toArray(_flags)));
|
||||||
|
if (CollectionUtils.isNotEmpty(descriptors))
|
||||||
|
properties.put("Descriptors", new Variant<>(BleHelper.toPaths(descriptors)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListener(BleCharacteristicListener _listener) {
|
||||||
|
listener = _listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends AbstractProperties> getChildObjects() {
|
||||||
|
return descriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRemote() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBusPath getPath() {
|
||||||
|
return charPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectPath() {
|
||||||
|
return charPath.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] ReadValue(Map<String, Variant<?>> _options) {
|
||||||
|
if (listener == null)
|
||||||
|
return null;
|
||||||
|
int offset = 0;
|
||||||
|
Variant<?> voffset = _options.get("offset");
|
||||||
|
if (voffset != null) {
|
||||||
|
if (voffset.getValue() instanceof UInt16)
|
||||||
|
offset = ((UInt16)voffset.getValue()).intValue();
|
||||||
|
}
|
||||||
|
byte[] ret = listener.read(charName);
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
return offset > 0?Arrays.copyOfRange(ret, offset, ret.length):ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void WriteValue(byte[] _bytes, Map<String, Variant<?>> _map) {
|
||||||
|
if (listener != null)
|
||||||
|
listener.write(charName, _bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TwoTuple<FileDescriptor, UInt16> AcquireWrite(Map<String, Variant<?>> _map) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TwoTuple<FileDescriptor, UInt16> AcquireNotify(Map<String, Variant<?>> _map) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void StartNotify() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void StopNotify() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void Confirm() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BleDescriptor> getDescriptors() {
|
||||||
|
return descriptors;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.bluetooth;
|
||||||
|
|
||||||
|
public interface BleCharacteristicListener {
|
||||||
|
void write(String _name, byte[] _value);
|
||||||
|
byte[] read(String _name);
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.bluetooth;
|
||||||
|
|
||||||
|
import org.bluez.GattDescriptor1;
|
||||||
|
import org.freedesktop.dbus.DBusPath;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class BleDescriptor extends AbstractProperties {
|
||||||
|
private final DBusPath charPath;
|
||||||
|
private final UUID uuid;
|
||||||
|
|
||||||
|
public BleDescriptor(String _serviceName, String _characteristicName, String _descriptorName, UUID _uuid) {
|
||||||
|
super(GattDescriptor1.class);
|
||||||
|
charPath = new DBusPath(BleHelper.descriptorPath(_serviceName, _characteristicName, _descriptorName));
|
||||||
|
uuid = _uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DBusPath getPath() {
|
||||||
|
return charPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRemote() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectPath() {
|
||||||
|
return charPath.getPath();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.bluetooth;
|
||||||
|
|
||||||
|
import com.github.hypfvieh.bluetooth.DeviceManager;
|
||||||
|
import com.github.hypfvieh.bluetooth.wrapper.BluetoothAdapter;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
|
import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
|
import org.freedesktop.dbus.interfaces.DBusInterface;
|
||||||
|
import org.freedesktop.dbus.interfaces.Properties;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class BleHelper {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(BleHelper.class);
|
||||||
|
|
||||||
|
private static String basePath;
|
||||||
|
private static final DeviceManager deviceManager;
|
||||||
|
public static final DBusConnection connection;
|
||||||
|
static {
|
||||||
|
DeviceManager m = null;
|
||||||
|
DBusConnection c = null;
|
||||||
|
try {
|
||||||
|
DeviceManager.createInstance(false);
|
||||||
|
m = DeviceManager.getInstance();
|
||||||
|
c = m.getDbusConnection();
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to get dbus connection", _e);
|
||||||
|
}
|
||||||
|
deviceManager = m;
|
||||||
|
connection = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setBasePath(String _basePath) {
|
||||||
|
basePath = _basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBasePath() {
|
||||||
|
return basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String advertismentPath(String _advertisementName) {
|
||||||
|
return BleHelper.getBasePath() + "/advertisement/" + _advertisementName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String applicationPath(String _appPath) {
|
||||||
|
return BleHelper.getBasePath() + "/application/" + _appPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String servicePath(String _serviceName) {
|
||||||
|
return BleHelper.getBasePath() + "/service/" + _serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String characteristicPath(String _serviceName, String _characteristicName) {
|
||||||
|
return servicePath(_serviceName) + "/" + _characteristicName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String descriptorPath(String _serviceName, String _characteristicName, String _descriptorPath) {
|
||||||
|
return servicePath(_serviceName) + "/" + _characteristicName + "/" + _descriptorPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] toPaths(List<? extends AbstractProperties> _properties) {
|
||||||
|
return CollectionUtils.transform(_properties, Properties::getObjectPath).toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BluetoothAdapter getAdapter() {
|
||||||
|
return (deviceManager != null)?deviceManager.getAdapter():null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void requestBusName(String _name) {
|
||||||
|
try {
|
||||||
|
if (connection != null)
|
||||||
|
connection.requestBusName(_name);
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to request bus name", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends DBusInterface> T getRemoteObject(String _path, Class<T> _objClass) {
|
||||||
|
try {
|
||||||
|
return connection.getRemoteObject("org.bluez", _path, _objClass);
|
||||||
|
} catch (DBusException _e) {
|
||||||
|
LOG.error("Failed to get remote object", _e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void exportObject(DBusInterface _object) {
|
||||||
|
try {
|
||||||
|
if (connection != null)
|
||||||
|
connection.exportObject(_object.getObjectPath(), _object);
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to export object", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unExportObject(DBusInterface _object) {
|
||||||
|
if (_object != null)
|
||||||
|
unExportObject(_object.getObjectPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unExportObject(String _objectPath) {
|
||||||
|
try {
|
||||||
|
if (connection != null)
|
||||||
|
connection.unExportObject(_objectPath);
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to unexport object", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.bluetooth;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import org.bluez.GattService1;
|
||||||
|
import org.freedesktop.dbus.DBusPath;
|
||||||
|
import org.freedesktop.dbus.types.Variant;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
|
public class BleService extends AbstractProperties implements GattService1 {
|
||||||
|
private final DBusPath servicePath;
|
||||||
|
private final UUID uuid;
|
||||||
|
private final List<BleCharacteristic> characteristics;
|
||||||
|
|
||||||
|
public BleService(String _serviceName, UUID _uuid, List<BleCharacteristic> _characteristics) {
|
||||||
|
super(GattService1.class);
|
||||||
|
servicePath = new DBusPath(BleHelper.servicePath(_serviceName));
|
||||||
|
uuid = _uuid;
|
||||||
|
characteristics = _characteristics;
|
||||||
|
if (uuid != null)
|
||||||
|
properties.put("UUID", new Variant<>(uuid.toString()));
|
||||||
|
properties.put("Primary", new Variant<>(Boolean.TRUE));
|
||||||
|
if (CollectionUtils.isNotEmpty(characteristics))
|
||||||
|
properties.put("Characteristics", new Variant<>(BleHelper.toPaths(characteristics)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBusPath getPath() {
|
||||||
|
return servicePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRemote() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectPath() {
|
||||||
|
return getPath().getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends AbstractProperties> getChildObjects() {
|
||||||
|
return characteristics;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BleCharacteristic> getCharacteristics() {
|
||||||
|
return characteristics;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.MonitorConfig;
|
||||||
|
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 MonitorConfigSerializer extends AbstractDaoSerializer<MonitorConfig>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<MonitorConfig> getSupportedClass()
|
||||||
|
{
|
||||||
|
return MonitorConfig.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(MonitorConfig _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("host", _o.getHost());
|
||||||
|
d.put("auth_code", _o.getAuthCode());
|
||||||
|
d.put("username", _o.getUsername());
|
||||||
|
d.put("password", _o.getPassword());
|
||||||
|
d.put("hub", _o.getHub());
|
||||||
|
d.put("debug", _o.isDebug());
|
||||||
|
d.put("socket_timeout", _o.getSocketTimeout());
|
||||||
|
d.put("connect_timeout", _o.getConnectTimeout());
|
||||||
|
d.put("update_interval", _o.getUpdateInterval());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MonitorConfig fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
MonitorConfig o = new MonitorConfig();
|
||||||
|
o.setHost(DaoSerializer.getString(_d, "host"));
|
||||||
|
o.setAuthCode(DaoSerializer.getString(_d, "auth_code"));
|
||||||
|
o.setUsername(DaoSerializer.getString(_d, "username"));
|
||||||
|
o.setPassword(DaoSerializer.getString(_d, "password"));
|
||||||
|
o.setHub(DaoSerializer.getInteger(_d, "hub"));
|
||||||
|
o.setDebug(DaoSerializer.getBoolean(_d, "debug"));
|
||||||
|
o.setSocketTimeout(DaoSerializer.getInteger(_d, "socket_timeout"));
|
||||||
|
o.setConnectTimeout(DaoSerializer.getInteger(_d, "connect_timeout"));
|
||||||
|
o.setUpdateInterval(DaoSerializer.getInteger(_d, "update_interval"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.led;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.concurrency.ConcurrencyUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class LEDFlasher implements Runnable {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(LEDFlasher.class);
|
||||||
|
|
||||||
|
private final AtomicBoolean running = new AtomicBoolean(true);
|
||||||
|
private boolean on = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (running.get()) {
|
||||||
|
on = !on;
|
||||||
|
setLEDOn(on);
|
||||||
|
ConcurrencyUtils.sleep(250);
|
||||||
|
}
|
||||||
|
setLEDOn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
running.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setLEDOn(boolean _on) {
|
||||||
|
try {
|
||||||
|
if (_on)
|
||||||
|
Runtime.getRuntime().exec(new String[]{"sh", "-c", "echo default-on > /sys/class/leds/led1/trigger"});
|
||||||
|
else
|
||||||
|
Runtime.getRuntime().exec(new String[]{"sh", "-c", "echo none > /sys/class/leds/led1/trigger"});
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to change LED state", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.util;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.NetworkStatus;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public abstract class NetworkMonitor {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(NetworkMonitor.class);
|
||||||
|
|
||||||
|
private static final Pattern ethernetPattern = Pattern.compile(".*(eth[0-9]):(.*)");
|
||||||
|
private static final Pattern wifiPattern = Pattern.compile(".*(wlan[0-9]):(.*)");
|
||||||
|
|
||||||
|
public static NetworkStatus getNetworkStatus() {
|
||||||
|
NetworkStatus status = new NetworkStatus();
|
||||||
|
String[] commands = {"ifconfig", "-a"};
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = Runtime.getRuntime().exec(commands).getInputStream();
|
||||||
|
String ifconfig = IOUtils.toString(is);
|
||||||
|
status.setEthernetIPs(getIPs(ifconfig, ethernetPattern));
|
||||||
|
status.setWifiIPs(getIPs(ifconfig, wifiPattern));
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to check network state", _e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
IOUtils.closeQuietly(is);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> getIPs(String _ifConfig, Pattern _pattern) {
|
||||||
|
List<String> ips = new ArrayList<>();
|
||||||
|
Matcher m = _pattern.matcher(_ifConfig);
|
||||||
|
while (m.find()) {
|
||||||
|
int start = m.start(0);
|
||||||
|
int ipStart = _ifConfig.indexOf("inet ", start) + 5;
|
||||||
|
if (ipStart > 4) {
|
||||||
|
int ipEnd = _ifConfig.indexOf(" ", ipStart);
|
||||||
|
if (ipEnd > -1)
|
||||||
|
ips.add(_ifConfig.substring(ipStart, ipEnd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ips;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.wifi;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public abstract class WifiConfig {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(WifiConfig.class);
|
||||||
|
|
||||||
|
private static final String WIFI_CONFIG_PATH = "/etc/wpa_supplicant/wpa_supplicant.conf";
|
||||||
|
private static final String CONF_FORMAT = "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\nupdate_config=1\ncountry=US\nnetwork={\n\tssid=\"%s\"\n\t%s\n}\n";
|
||||||
|
|
||||||
|
public static void setCredentials(String _ssid, String _password) {
|
||||||
|
String[] commands = {"wpa_passphrase", _ssid, _password};
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = Runtime.getRuntime().exec(commands).getInputStream();
|
||||||
|
String newConf = IOUtils.toString(is);
|
||||||
|
if (newConf == null)
|
||||||
|
return;
|
||||||
|
int idx = newConf.indexOf("psk=");
|
||||||
|
if (idx > 0) {
|
||||||
|
if (newConf.charAt(idx-1) == '#')
|
||||||
|
idx = newConf.indexOf("psk=", idx+1);
|
||||||
|
if (idx > 0) {
|
||||||
|
int endIdx = newConf.indexOf("\n", idx);
|
||||||
|
if (endIdx > 0) {
|
||||||
|
String finalConf = String.format(CONF_FORMAT, _ssid, newConf.substring(idx, endIdx));
|
||||||
|
ResourceLoader.writeFile(WIFI_CONFIG_PATH, finalConf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
LOG.error("Failed to write wifi credentials", _e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
IOUtils.closeQuietly(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.bluez;
|
||||||
|
|
||||||
|
import org.freedesktop.dbus.interfaces.DBusInterface;
|
||||||
|
|
||||||
|
public interface GattApplication1 extends DBusInterface {
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
com.lanternsoftware.currentmonitor.dao.MonitorConfigSerializer
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<property name="log.pattern" value="%date %-5level %logger{0} - %message%n"/>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log.pattern}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>/opt/currentmonitor/log/log.txt</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>/opt/currentmonitor/log/log.%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
|
||||||
|
<maxFileSize>20MB</maxFileSize>
|
||||||
|
<maxHistory>20</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log.pattern}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<logger name="com.lanternsoftware" level="INFO"/>
|
||||||
|
|
||||||
|
<root level="OFF">
|
||||||
|
<appender-ref ref="FILE"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
public class CreateConfig {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// MonitorConfig c = new MonitorConfig(0, "https://mark.lanternsoftware.com/currentmonitor");
|
||||||
|
MonitorConfig c = new MonitorConfig(1, "https://mark.lanternsoftware.com/currentmonitor");
|
||||||
|
c.setDebug(true);
|
||||||
|
ResourceLoader.writeFile(LanternFiles.OPS_PATH + "hub1.json", DaoSerializer.toJson(c));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.cryptography.AESTool;
|
||||||
|
|
||||||
|
public class CreateSSIDKey {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
AESTool.printRandomSecretKey();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.dao.generator.DaoSerializerGenerator;
|
||||||
|
|
||||||
|
public class CurrentMonitorAppSerializers {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DaoSerializerGenerator.generateSerializers(LanternFiles.SOURCE_PATH + "currentmonitor", true, null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.util.NetworkMonitor;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.NetworkStatus;
|
||||||
|
|
||||||
|
public class NetworkTest {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
NetworkStatus status = NetworkMonitor.getNetworkStatus();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import com.lanternsoftware.util.xml.XmlNode;
|
||||||
|
import com.lanternsoftware.util.xml.XmlParser;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class ReleaseCurrentMonitor {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
XmlNode pom = XmlParser.loadXmlFile(LanternFiles.SOURCE_PATH + "currentmonitor" + File.separator + "lantern-currentmonitor" + File.separator + "pom.xml");
|
||||||
|
if (pom == null)
|
||||||
|
return;
|
||||||
|
XmlNode versionNode = pom.getChild(Collections.singletonList("version"));
|
||||||
|
String version = versionNode.getContent();
|
||||||
|
ProcessBuilder builder = new ProcessBuilder();
|
||||||
|
builder.directory(new File(LanternFiles.SOURCE_PATH));
|
||||||
|
builder.command("cmd.exe", "/c", "mvn clean install");
|
||||||
|
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
|
||||||
|
try {
|
||||||
|
Process process = builder.start();
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
assert exitCode == 0;
|
||||||
|
} catch (Exception _e) {
|
||||||
|
_e.printStackTrace();
|
||||||
|
}
|
||||||
|
byte[] jar = ResourceLoader.loadFile(LanternFiles.SOURCE_PATH + "currentmonitor" + File.separator + "lantern-currentmonitor" + File.separator + "target" + File.separator + "lantern-currentmonitor.jar");
|
||||||
|
DaoEntity meta = new DaoEntity("version", version).and("size", jar.length).and("checksum", DigestUtils.md5Hex(jar));
|
||||||
|
ResourceLoader.writeFile(LanternFiles.OPS_PATH + "release" + File.separator + "lantern-currentmonitor.jar", jar);
|
||||||
|
ResourceLoader.writeFile(LanternFiles.OPS_PATH + "release" + File.separator + "version.json", DaoSerializer.toJson(meta));
|
||||||
|
}
|
||||||
|
}
|
83
currentmonitor/lantern-dataaccess-currentmonitor/pom.xml
Normal file
83
currentmonitor/lantern-dataaccess-currentmonitor/pom.xml
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<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>
|
||||||
|
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||||
|
<artifactId>lantern-dataaccess-currentmonitor</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>lantern-dataaccess-currentmonitor</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||||
|
<artifactId>lantern-datamodel-currentmonitor</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lanternsoftware.util</groupId>
|
||||||
|
<artifactId>lantern-util-dao-mongo</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mindrot</groupId>
|
||||||
|
<artifactId>jbcrypt</artifactId>
|
||||||
|
<version>0.4</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>compile</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<optimize>true</optimize>
|
||||||
|
<showDeprecation>true</showDeprecation>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<index>true</index>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.lanternsoftware.dataaccess.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||||
|
import com.lanternsoftware.util.dao.mongo.MongoProxy;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
public interface CurrentMonitorDao {
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
void putBreakerPower(BreakerPower _current);
|
||||||
|
List<BreakerPower> getBreakerPowerForAccount(int _accountId);
|
||||||
|
BreakerPower getLatestBreakerPower(int _accountId, int _hub, int _port);
|
||||||
|
BreakerGroupEnergy getBreakerGroupEnergy(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start);
|
||||||
|
void putBreakerGroupEnergy(BreakerGroupEnergy _energy);
|
||||||
|
|
||||||
|
void putHubPowerMinute(HubPowerMinute _power);
|
||||||
|
|
||||||
|
BreakerConfig getConfig(int _accountId);
|
||||||
|
BreakerConfig getMergedConfig(AuthCode _authCode);
|
||||||
|
void putConfig(BreakerConfig _config);
|
||||||
|
|
||||||
|
void updateSummaries(BreakerGroup _rootGroup, Set<Date> _daysToSummarize, TimeZone _tz);
|
||||||
|
|
||||||
|
String authenticateAccount(String _username, String _password);
|
||||||
|
String getAuthCodeForEmail(String _email);
|
||||||
|
Account authCodeToAccount(String _authCode);
|
||||||
|
AuthCode decryptAuthCode(String _authCode);
|
||||||
|
|
||||||
|
Account putAccount(Account _account);
|
||||||
|
Account getAccount(int _accountId);
|
||||||
|
Account getAccountByUsername(String _username);
|
||||||
|
|
||||||
|
MongoProxy getProxy();
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.lanternsoftware.dataaccess.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@DBSerializable(autogen = false)
|
||||||
|
public class DirtyMinute {
|
||||||
|
private int accountId;
|
||||||
|
private int minute;
|
||||||
|
private Date posted;
|
||||||
|
|
||||||
|
public DirtyMinute() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public DirtyMinute(int _accountId, int _minute, Date _posted) {
|
||||||
|
accountId = _accountId;
|
||||||
|
minute = _minute;
|
||||||
|
posted = _posted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return accountId + "-" + minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getMinuteAsDate() {
|
||||||
|
return new Date(((long)minute)*60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinute() {
|
||||||
|
return minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinute(int _minute) {
|
||||||
|
minute = _minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinute(Date _minute) {
|
||||||
|
minute = (int)(_minute.getTime()/60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getPosted() {
|
||||||
|
return posted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosted(Date _posted) {
|
||||||
|
posted = _posted;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,273 @@
|
||||||
|
package com.lanternsoftware.dataaccess.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupSummary;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Sequence;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.DateUtils;
|
||||||
|
import com.lanternsoftware.util.DebugTimer;
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.cryptography.AESTool;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoQuery;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSort;
|
||||||
|
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||||
|
import com.lanternsoftware.util.dao.mongo.MongoProxy;
|
||||||
|
import org.mindrot.jbcrypt.BCrypt;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MongoCurrentMonitorDao.class);
|
||||||
|
private static final AESTool aes = new AESTool(ResourceLoader.loadFile(LanternFiles.OPS_PATH + "authKey.dat"));
|
||||||
|
private static final int BCRYPT_ROUNDS = 11;
|
||||||
|
private final Timer delayTimer = new Timer();
|
||||||
|
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
|
private final MongoProxy proxy;
|
||||||
|
|
||||||
|
public MongoCurrentMonitorDao(MongoConfig _config) {
|
||||||
|
proxy = new MongoProxy(_config);
|
||||||
|
proxy.ensureIndex(BreakerPower.class, DaoSort.sort("account_id").then("key"));
|
||||||
|
proxy.ensureIndex(HubPowerMinute.class, DaoSort.sort("account_id").then("minute"));
|
||||||
|
proxy.ensureIndex(BreakerGroupEnergy.class, DaoSort.sort("account_id").then("group_id").then("view_mode"));
|
||||||
|
proxy.ensureIndex(BreakerGroupSummary.class, DaoSort.sort("account_id").then("group_id").then("view_mode"));
|
||||||
|
proxy.ensureIndex(DirtyMinute.class, DaoSort.sort("posted"));
|
||||||
|
for (DirtyMinute minute : proxy.queryAll(DirtyMinute.class)) {
|
||||||
|
updateSummaries(minute);
|
||||||
|
}
|
||||||
|
proxy.delete(DirtyMinute.class, new DaoQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
delayTimer.cancel();
|
||||||
|
executor.shutdownNow();
|
||||||
|
proxy.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putBreakerPower(BreakerPower _power) {
|
||||||
|
proxy.save(_power);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putHubPowerMinute(HubPowerMinute _power) {
|
||||||
|
if (_power == null)
|
||||||
|
return;
|
||||||
|
proxy.save(_power);
|
||||||
|
DirtyMinute minute = new DirtyMinute(_power.getAccountId(), _power.getMinute(), new Date());
|
||||||
|
proxy.save(minute);
|
||||||
|
delayTimer.schedule(new TimerTask(){
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
executor.submit(()->{
|
||||||
|
if (proxy.queryOneAndDelete(DirtyMinute.class, new DaoQuery("_id", minute.getId())) != null)
|
||||||
|
updateSummaries(new DirtyMinute(_power.getAccountId(), _power.getMinute(), new Date()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSummaries(DirtyMinute _minute) {
|
||||||
|
DebugTimer timer = new DebugTimer("Updating summaries", logger);
|
||||||
|
List<HubPowerMinute> minutes = proxy.query(HubPowerMinute.class, new DaoQuery("account_id", _minute.getAccountId()).and("minute", _minute.getMinute()));
|
||||||
|
TimeZone tz = TimeZone.getTimeZone("America/Chicago");
|
||||||
|
BreakerConfig config = getConfig(_minute.getAccountId());
|
||||||
|
BreakerGroup group = CollectionUtils.getFirst(config.getBreakerGroups());
|
||||||
|
Date day = DateUtils.getMidnightBefore(_minute.getMinuteAsDate(), tz);
|
||||||
|
BreakerGroupEnergy summary = getBreakerGroupEnergy(_minute.getAccountId(), group.getId(), EnergyBlockViewMode.DAY, day);
|
||||||
|
if (summary == null)
|
||||||
|
summary = new BreakerGroupEnergy(group, minutes, EnergyBlockViewMode.DAY, day, tz);
|
||||||
|
else
|
||||||
|
summary.addEnergy(group, minutes, tz);
|
||||||
|
putBreakerGroupEnergy(summary);
|
||||||
|
updateSummaries(group, CollectionUtils.asHashSet(day), tz);
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BreakerPower> getBreakerPowerForAccount(int _accountId) {
|
||||||
|
return proxy.query(BreakerPower.class, new DaoQuery("account_id", _accountId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerPower getLatestBreakerPower(int _accountId, int _panel, int _space) {
|
||||||
|
return proxy.queryOne(BreakerPower.class, new DaoQuery("account_id", _accountId).and("key", Breaker.key(_panel, _space)), DaoSort.sortDesc("read_time"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerGroupEnergy getBreakerGroupEnergy(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start) {
|
||||||
|
return proxy.queryOne(BreakerGroupEnergy.class, new DaoQuery("_id", BreakerGroupEnergy.toId(_accountId, _groupId, _viewMode, _start)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSummaries(BreakerGroup _rootGroup, Set<Date> _daysToSummarize, TimeZone _tz) {
|
||||||
|
Set<Date> monthsToSummarize = CollectionUtils.transformToSet(_daysToSummarize, _c -> DateUtils.getStartOfMonth(_c, _tz));
|
||||||
|
Set<Date> yearsToSummarize = CollectionUtils.transformToSet(monthsToSummarize, _c -> DateUtils.getStartOfYear(_c, _tz));
|
||||||
|
for (Date month : monthsToSummarize) {
|
||||||
|
Calendar calDayStart = DateUtils.toCalendar(month, _tz);
|
||||||
|
Calendar end = DateUtils.getEndOfMonthCal(month, _tz);
|
||||||
|
List<String> groupEnergyIds = new ArrayList<>();
|
||||||
|
while (calDayStart.before(end)) {
|
||||||
|
groupEnergyIds.add(BreakerGroupEnergy.toId(_rootGroup.getAccountId(), _rootGroup.getId(), EnergyBlockViewMode.DAY, calDayStart.getTime()));
|
||||||
|
calDayStart.add(Calendar.DAY_OF_YEAR, 1);
|
||||||
|
}
|
||||||
|
List<BreakerGroupSummary> groupEnergies = CollectionUtils.aggregate(proxy.query(BreakerGroupSummary.class, DaoQuery.in("_id", groupEnergyIds)), BreakerGroupSummary::getAllGroups);
|
||||||
|
Map<String, List<BreakerGroupSummary>> energies = CollectionUtils.transformToMultiMap(groupEnergies, BreakerGroupSummary::getGroupId);
|
||||||
|
BreakerGroupEnergy summary = BreakerGroupEnergy.summary(_rootGroup, energies, EnergyBlockViewMode.MONTH, month, _tz);
|
||||||
|
putBreakerGroupEnergy(summary);
|
||||||
|
}
|
||||||
|
for (Date year : yearsToSummarize) {
|
||||||
|
Calendar calMonthStart = DateUtils.toCalendar(year, _tz);
|
||||||
|
Calendar end = DateUtils.getEndOfYearCal(year, _tz);
|
||||||
|
List<String> groupEnergyIds = new ArrayList<>();
|
||||||
|
while (calMonthStart.before(end)) {
|
||||||
|
groupEnergyIds.add(BreakerGroupEnergy.toId(_rootGroup.getAccountId(), _rootGroup.getId(), EnergyBlockViewMode.MONTH, calMonthStart.getTime()));
|
||||||
|
calMonthStart.add(Calendar.DAY_OF_YEAR, 1);
|
||||||
|
}
|
||||||
|
List<BreakerGroupSummary> groupEnergies = CollectionUtils.aggregate(proxy.query(BreakerGroupSummary.class, DaoQuery.in("_id", groupEnergyIds)), BreakerGroupSummary::getAllGroups);
|
||||||
|
Map<String, List<BreakerGroupSummary>> energies = CollectionUtils.transformToMultiMap(groupEnergies, BreakerGroupSummary::getGroupId);
|
||||||
|
BreakerGroupEnergy summary = BreakerGroupEnergy.summary(_rootGroup, energies, EnergyBlockViewMode.YEAR, year, _tz);
|
||||||
|
putBreakerGroupEnergy(summary);
|
||||||
|
}
|
||||||
|
List<BreakerGroupSummary> groupEnergies = CollectionUtils.aggregate(proxy.query(BreakerGroupSummary.class, new DaoQuery("group_id", _rootGroup.getId()).and("view_mode", EnergyBlockViewMode.YEAR.name())), BreakerGroupSummary::getAllGroups);
|
||||||
|
Map<String, List<BreakerGroupSummary>> energies = CollectionUtils.transformToMultiMap(groupEnergies, BreakerGroupSummary::getGroupId);
|
||||||
|
BreakerGroupEnergy summary = BreakerGroupEnergy.summary(_rootGroup, energies, EnergyBlockViewMode.ALL, new Date(0), _tz);
|
||||||
|
putBreakerGroupEnergy(summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putBreakerGroupEnergy(BreakerGroupEnergy _energy) {
|
||||||
|
proxy.save(_energy);
|
||||||
|
proxy.save(new BreakerGroupSummary(_energy));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerConfig getConfig(int _accountId) {
|
||||||
|
return proxy.queryOne(BreakerConfig.class, new DaoQuery("_id", String.valueOf(_accountId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerConfig getMergedConfig(AuthCode _authCode) {
|
||||||
|
if (_authCode == null)
|
||||||
|
return null;
|
||||||
|
List<BreakerConfig> configs = CollectionUtils.transform(_authCode.getAllAccountIds(), this::getConfig, true);
|
||||||
|
BreakerConfig config = new BreakerConfig();
|
||||||
|
config.setAccountId(_authCode.getAccountId());
|
||||||
|
config.setBreakerHubs(CollectionUtils.aggregate(configs, BreakerConfig::getBreakerHubs));
|
||||||
|
config.setBreakerGroups(CollectionUtils.aggregate(configs, BreakerConfig::getBreakerGroups));
|
||||||
|
config.setPanels(CollectionUtils.aggregate(configs, BreakerConfig::getPanels));
|
||||||
|
config.setMeters(CollectionUtils.aggregate(configs, BreakerConfig::getMeters));
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putConfig(BreakerConfig _config) {
|
||||||
|
DaoQuery configQuery = new DaoQuery("_id", String.valueOf(_config.getAccountId()));
|
||||||
|
BreakerConfig oldConfig = proxy.queryOne(BreakerConfig.class, configQuery);
|
||||||
|
if (oldConfig != null)
|
||||||
|
proxy.delete(BreakerGroup.class, DaoQuery.in("_id", oldConfig.getAllBreakerGroupIds()));
|
||||||
|
proxy.save(_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String authenticateAccount(String _username, String _password) {
|
||||||
|
Account acct = proxy.queryOne(Account.class, new DaoQuery("username", _username));
|
||||||
|
if ((acct == null) || !BCrypt.checkpw(_password, acct.getPassword()))
|
||||||
|
return null;
|
||||||
|
return aes.encryptToBase64(DaoSerializer.toZipBson(new AuthCode(acct.getId(), acct.getAuxiliaryAccountIds())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account authCodeToAccount(String _authCode) {
|
||||||
|
AuthCode code = decryptAuthCode(_authCode);
|
||||||
|
if (code == null)
|
||||||
|
return null;
|
||||||
|
return proxy.queryOne(Account.class, new DaoQuery("_id", code.getAccountId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthCode decryptAuthCode(String _authCode) {
|
||||||
|
return DaoSerializer.fromZipBson(aes.decryptFromBase64(_authCode), AuthCode.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthCodeForEmail(String _email) {
|
||||||
|
_email = _email.toLowerCase().trim();
|
||||||
|
Account account = getAccountByUsername(_email);
|
||||||
|
if (account == null) {
|
||||||
|
account = new Account();
|
||||||
|
account.setUsername(_email);
|
||||||
|
putAccount(account);
|
||||||
|
}
|
||||||
|
return aes.encryptToBase64(DaoSerializer.toZipBson(new AuthCode(account.getId(), account.getAuxiliaryAccountIds())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account putAccount(Account _account) {
|
||||||
|
if (_account == null)
|
||||||
|
return null;
|
||||||
|
_account.setUsername(NullUtils.makeNotNull(_account.getUsername()).toLowerCase().trim());
|
||||||
|
Account account = getAccountByUsername(_account.getUsername());
|
||||||
|
if (account != null) {
|
||||||
|
_account.setId(account.getId());
|
||||||
|
if (NullUtils.isEmpty(_account.getPassword()))
|
||||||
|
_account.setPassword(account.getPassword());
|
||||||
|
else
|
||||||
|
_account.setPassword(BCrypt.hashpw(_account.getPassword(), BCrypt.gensalt(BCRYPT_ROUNDS)));
|
||||||
|
}
|
||||||
|
else if (NullUtils.isNotEmpty(_account.getPassword())) {
|
||||||
|
_account.setPassword(BCrypt.hashpw(_account.getPassword(), BCrypt.gensalt(BCRYPT_ROUNDS)));
|
||||||
|
}
|
||||||
|
if (_account.getId() == 0)
|
||||||
|
_account.setId(proxy.updateOne(Sequence.class, null, new DaoEntity("$inc", new DaoEntity("sequence", 1))).getSequence());
|
||||||
|
proxy.save(_account);
|
||||||
|
return clearPassword(_account);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account getAccount(int _accountId) {
|
||||||
|
return clearPassword(proxy.queryOne(Account.class, new DaoQuery("_id", String.valueOf(_accountId))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account getAccountByUsername(String _username) {
|
||||||
|
return clearPassword(proxy.queryOne(Account.class, new DaoQuery("username", NullUtils.makeNotNull(_username).toLowerCase().trim())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Account clearPassword(Account _account) {
|
||||||
|
if (_account == null)
|
||||||
|
return null;
|
||||||
|
_account.setPassword(null);
|
||||||
|
return _account;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MongoProxy getProxy() {
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.lanternsoftware.dataaccess.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.dataaccess.currentmonitor.DirtyMinute;
|
||||||
|
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 DirtyMinuteSerializer extends AbstractDaoSerializer<DirtyMinute>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<DirtyMinute> getSupportedClass()
|
||||||
|
{
|
||||||
|
return DirtyMinute.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(DirtyMinute _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("_id", _o.getId());
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
d.put("minute", _o.getMinute());
|
||||||
|
d.put("posted", DaoSerializer.toLong(_o.getPosted()));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirtyMinute fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
DirtyMinute o = new DirtyMinute();
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setMinute(DaoSerializer.getInteger(_d, "minute"));
|
||||||
|
o.setPosted(DaoSerializer.getDate(_d, "posted"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
com.lanternsoftware.dataaccess.currentmonitor.dao.DirtyMinuteSerializer
|
73
currentmonitor/lantern-datamodel-currentmonitor/pom.xml
Normal file
73
currentmonitor/lantern-datamodel-currentmonitor/pom.xml
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
<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>
|
||||||
|
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||||
|
<artifactId>lantern-datamodel-currentmonitor</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>lantern-datamodel-currentmonitor</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lanternsoftware.util</groupId>
|
||||||
|
<artifactId>lantern-util-dao</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>compile</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<optimize>true</optimize>
|
||||||
|
<showDeprecation>true</showDeprecation>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<index>true</index>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.PrimaryKey;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@DBSerializable(autogen = false)
|
||||||
|
public class Account {
|
||||||
|
@PrimaryKey private int id;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private List<Integer> auxiliaryAccountIds;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int _id) {
|
||||||
|
id = _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String _username) {
|
||||||
|
username = _username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String _password) {
|
||||||
|
password = _password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getAuxiliaryAccountIds() {
|
||||||
|
return auxiliaryAccountIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuxiliaryAccountIds(List<Integer> _auxiliaryAccountIds) {
|
||||||
|
auxiliaryAccountIds = _auxiliaryAccountIds;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@DBSerializable(autogen = false)
|
||||||
|
public class AuthCode {
|
||||||
|
private int accountId;
|
||||||
|
private List<Integer> auxiliaryAccountIds;
|
||||||
|
|
||||||
|
public AuthCode() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthCode(int _accountId, List<Integer> _auxiliaryAccountIds) {
|
||||||
|
accountId = _accountId;
|
||||||
|
auxiliaryAccountIds = _auxiliaryAccountIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getAuxiliaryAccountIds() {
|
||||||
|
return auxiliaryAccountIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuxiliaryAccountIds(List<Integer> _auxiliaryAccountIds) {
|
||||||
|
auxiliaryAccountIds = _auxiliaryAccountIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getAllAccountIds() {
|
||||||
|
List<Integer> ids = new ArrayList<>();
|
||||||
|
ids.add(accountId);
|
||||||
|
if (auxiliaryAccountIds != null)
|
||||||
|
ids.addAll(auxiliaryAccountIds);
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAuthorized(int _accountId) {
|
||||||
|
return accountId == _accountId || CollectionUtils.contains(auxiliaryAccountIds, _accountId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
@DBSerializable()
|
||||||
|
public class Breaker {
|
||||||
|
private static final int TANDEM_BREAKER_MASK = 3072;
|
||||||
|
private static final int SPACE_MASK = 1023;
|
||||||
|
private static final int TANDEM_BREAKER_A_MASK = 1024;
|
||||||
|
private static final int TANDEM_BREAKER_B_MASK = 2048;
|
||||||
|
|
||||||
|
private int panel;
|
||||||
|
private int space;
|
||||||
|
private int meter;
|
||||||
|
private int hub;
|
||||||
|
private int port;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private int sizeAmps;
|
||||||
|
private double calibrationFactor;
|
||||||
|
private double lowPassFilter;
|
||||||
|
private BreakerPolarity polarity;
|
||||||
|
private BreakerType type;
|
||||||
|
private transient String key;
|
||||||
|
|
||||||
|
public Breaker() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Breaker(String _name, int _panel, int _space, int _hub, int _port, int _sizeAmps, double _lowPassFilter) {
|
||||||
|
name = _name;
|
||||||
|
panel = _panel;
|
||||||
|
space = _space;
|
||||||
|
hub = _hub;
|
||||||
|
port = _port;
|
||||||
|
sizeAmps = _sizeAmps;
|
||||||
|
lowPassFilter = _lowPassFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPanel() {
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPanel(int _panel) {
|
||||||
|
panel = _panel;
|
||||||
|
key = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSpace() {
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpace(int _space) {
|
||||||
|
space = _space;
|
||||||
|
key = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMeter() {
|
||||||
|
return meter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMeter(int _meter) {
|
||||||
|
meter = _meter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpaceDisplay() {
|
||||||
|
return toSpaceDisplay(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpaceTandemA(int _space) {
|
||||||
|
space = TANDEM_BREAKER_A_MASK | _space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpaceTandemB(int _space) {
|
||||||
|
space = TANDEM_BREAKER_B_MASK | _space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTandemBreaker() {
|
||||||
|
return (TANDEM_BREAKER_MASK & space) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTandemBreakerA() {
|
||||||
|
return isTandemBreakerA(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTandemBreakerB() {
|
||||||
|
return isTandemBreakerB(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String _name) {
|
||||||
|
name = _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String _description) {
|
||||||
|
description = _description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHub() {
|
||||||
|
return hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHub(int _hub) {
|
||||||
|
hub = _hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int _port) {
|
||||||
|
port = _port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChip() {
|
||||||
|
return portToChip(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPin() {
|
||||||
|
return portToPin(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSizeAmps() {
|
||||||
|
return sizeAmps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSizeAmps(int _sizeAmps) {
|
||||||
|
sizeAmps = _sizeAmps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLowPassFilter() {
|
||||||
|
return lowPassFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLowPassFilter(double _lowPassFilter) {
|
||||||
|
lowPassFilter = _lowPassFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerPolarity getPolarity() {
|
||||||
|
return polarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPolarity(BreakerPolarity _polarity) {
|
||||||
|
polarity = _polarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCalibrationFactor() {
|
||||||
|
return calibrationFactor == 0.0?1.0:calibrationFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCalibrationFactor(double _calibrationFactor) {
|
||||||
|
calibrationFactor = _calibrationFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerType getType() {
|
||||||
|
if (type == null) {
|
||||||
|
if (isTandemBreaker())
|
||||||
|
return BreakerType.SINGLE_POLE_TANDEM;
|
||||||
|
return BreakerType.SINGLE_POLE;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(BreakerType _type) {
|
||||||
|
type = _type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getFinalCalibrationFactor() {
|
||||||
|
return getCalibrationFactor() * getSizeAmps() / 380.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
if (key == null)
|
||||||
|
key = key(panel, space);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String key(int _panel, int _space) {
|
||||||
|
return String.format("%d-%d", _panel, _space);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int portToChip(int _port) {
|
||||||
|
return (_port < 9)?1:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int portToPin(int _port) {
|
||||||
|
return (_port < 9)?_port-1:_port-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toPort(int _chip, int _pin) {
|
||||||
|
return (_chip == 0)?_pin+8:_pin+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTandemBreakerA(int _space) {
|
||||||
|
return (TANDEM_BREAKER_A_MASK & _space) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTandemBreakerB(int _space) {
|
||||||
|
return (TANDEM_BREAKER_B_MASK & _space) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toId(int _panel, int _space) {
|
||||||
|
return (_panel << 12) | _space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toPanel(int _id) {
|
||||||
|
return _id >> 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toSpace(int _id) {
|
||||||
|
return _id & (TANDEM_BREAKER_MASK |SPACE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toSpaceDisplay(int _space) {
|
||||||
|
if (isTandemBreakerA(_space))
|
||||||
|
return String.format("%dA", _space & SPACE_MASK);
|
||||||
|
if (isTandemBreakerB(_space))
|
||||||
|
return String.format("%dB", _space & SPACE_MASK);
|
||||||
|
return String.valueOf(_space);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSpaceIndex() {
|
||||||
|
return space & SPACE_MASK;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.PrimaryKey;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@DBSerializable(autogen = false)
|
||||||
|
public class BreakerConfig {
|
||||||
|
@PrimaryKey
|
||||||
|
private int accountId;
|
||||||
|
private List<Meter> meters;
|
||||||
|
private List<BreakerPanel> panels;
|
||||||
|
private List<BreakerHub> breakerHubs;
|
||||||
|
private List<BreakerGroup> breakerGroups;
|
||||||
|
|
||||||
|
public BreakerConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerConfig(List<BreakerGroup> _breakerGroups) {
|
||||||
|
breakerGroups = _breakerGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Meter> getMeters() {
|
||||||
|
return meters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMeters(List<Meter> _meters) {
|
||||||
|
meters = _meters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerPanel> getPanels() {
|
||||||
|
return panels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPanels(List<BreakerPanel> _panels) {
|
||||||
|
panels = _panels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerHub> getBreakerHubs() {
|
||||||
|
return breakerHubs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBreakerHubs(List<BreakerHub> _breakerHubs) {
|
||||||
|
breakerHubs = _breakerHubs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerGroup> getBreakerGroups() {
|
||||||
|
return breakerGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBreakerGroups(List<BreakerGroup> _breakerGroups) {
|
||||||
|
breakerGroups = _breakerGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Breaker> getAllBreakers() {
|
||||||
|
List<Breaker> allBreakers = new ArrayList<>();
|
||||||
|
for (BreakerGroup g : CollectionUtils.makeNotNull(breakerGroups)) {
|
||||||
|
allBreakers.addAll(g.getAllBreakers());
|
||||||
|
}
|
||||||
|
return allBreakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerGroup> getAllBreakerGroups() {
|
||||||
|
List<BreakerGroup> groups = new ArrayList<>();
|
||||||
|
for (BreakerGroup g : CollectionUtils.makeNotNull(breakerGroups)) {
|
||||||
|
groups.addAll(g.getAllBreakerGroups());
|
||||||
|
}
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAllBreakerGroupIds() {
|
||||||
|
List<String> ids = new ArrayList<>();
|
||||||
|
for (BreakerGroup g : CollectionUtils.makeNotNull(breakerGroups)) {
|
||||||
|
ids.addAll(g.getAllBreakerGroupIds());
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Breaker> getBreakersForHub(int _hub) {
|
||||||
|
return CollectionUtils.filter(getAllBreakers(), _b -> _b.getHub() == _hub);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerHub getHub(int _hub) {
|
||||||
|
return CollectionUtils.filterOne(breakerHubs, _h->_h.getHub() == _hub);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSolarConfigured() {
|
||||||
|
return CollectionUtils.anyQualify(getAllBreakers(), _b->_b.getPolarity() == BreakerPolarity.SOLAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String nextGroupId() {
|
||||||
|
List<Integer> ids = CollectionUtils.transform(getAllBreakerGroupIds(), NullUtils::toInteger);
|
||||||
|
return String.valueOf(CollectionUtils.getLargest(ids) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addGroup(BreakerGroup _group) {
|
||||||
|
if (NullUtils.isEmpty(_group.getId())) {
|
||||||
|
_group.setId(nextGroupId());
|
||||||
|
}
|
||||||
|
if (breakerGroups == null)
|
||||||
|
breakerGroups = new ArrayList<>();
|
||||||
|
breakerGroups.add(_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeInvalidGroups() {
|
||||||
|
if (breakerGroups != null)
|
||||||
|
breakerGroups.removeIf(_g->!_g.removeInvalidGroups());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupIdForBreaker(Breaker _breaker) {
|
||||||
|
return getGroupIdForBreaker(_breaker.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupIdForBreaker(int _panel, int _space) {
|
||||||
|
return getGroupIdForBreaker(Breaker.key(_panel, _space));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupIdForBreaker(String _breakerKey) {
|
||||||
|
BreakerGroup group = getGroupForBreaker(_breakerKey);
|
||||||
|
return group != null ? group.getId() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup getGroupForBreaker(Breaker _breaker) {
|
||||||
|
return getGroupForBreaker(_breaker.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup getGroupForBreaker(int _panel, int _space) {
|
||||||
|
return getGroupForBreaker(Breaker.key(_panel, _space));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup getGroupForBreaker(String _breakerKey) {
|
||||||
|
if (_breakerKey == null)
|
||||||
|
return null;
|
||||||
|
for (BreakerGroup subGroup : CollectionUtils.makeNotNull(breakerGroups)) {
|
||||||
|
BreakerGroup group = subGroup.getGroupForBreaker(_breakerKey);
|
||||||
|
if (group != null)
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup findParentGroup(BreakerGroup _group) {
|
||||||
|
for (BreakerGroup group : CollectionUtils.makeNotNull(breakerGroups)) {
|
||||||
|
BreakerGroup parent = group.findParentGroup(_group);
|
||||||
|
if (parent != null)
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.PrimaryKey;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@DBSerializable()
|
||||||
|
public class BreakerGroup {
|
||||||
|
@PrimaryKey private String id;
|
||||||
|
private int accountId;
|
||||||
|
private String name;
|
||||||
|
private List<BreakerGroup> subGroups;
|
||||||
|
private List<Breaker> breakers;
|
||||||
|
|
||||||
|
public BreakerGroup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup(String _id, String _name, List<Breaker> _breakers) {
|
||||||
|
id = _id;
|
||||||
|
name = _name;
|
||||||
|
breakers = _breakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup(String _id, String _name, List<BreakerGroup> _subGroups, List<Breaker> _breakers) {
|
||||||
|
id = _id;
|
||||||
|
name = _name;
|
||||||
|
subGroups = _subGroups;
|
||||||
|
breakers = _breakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String _id) {
|
||||||
|
id = _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String _name) {
|
||||||
|
name = _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerGroup> getSubGroups() {
|
||||||
|
return subGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubGroups(List<BreakerGroup> _subGroups) {
|
||||||
|
subGroups = _subGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Breaker> getBreakers() {
|
||||||
|
return breakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBreakers(List<Breaker> _breakers) {
|
||||||
|
breakers = _breakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Breaker> getAllBreakers() {
|
||||||
|
List<Breaker> allBreakers = new ArrayList<>();
|
||||||
|
getAllBreakers(allBreakers);
|
||||||
|
return allBreakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAllBreakers(List<Breaker> _breakers) {
|
||||||
|
if (breakers != null)
|
||||||
|
_breakers.addAll(breakers);
|
||||||
|
for (BreakerGroup group : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
group.getAllBreakers(_breakers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAllBreakerKeys() {
|
||||||
|
return CollectionUtils.transform(getAllBreakers(), Breaker::getKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerGroup> getAllBreakerGroups() {
|
||||||
|
List<BreakerGroup> allGroups = new ArrayList<>();
|
||||||
|
getAllBreakerGroups(allGroups);
|
||||||
|
return allGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAllBreakerGroups(List<BreakerGroup> _groups) {
|
||||||
|
_groups.add(this);
|
||||||
|
for (BreakerGroup group : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
group.getAllBreakerGroups(_groups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAllBreakerGroupIds() {
|
||||||
|
return CollectionUtils.transform(getAllBreakerGroups(), BreakerGroup::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Breaker getBreaker(String _breakerKey) {
|
||||||
|
for (Breaker b : CollectionUtils.makeNotNull(breakers)) {
|
||||||
|
if (NullUtils.isEqual(b.getKey(), _breakerKey))
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
for (BreakerGroup group : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
Breaker b = group.getBreaker(_breakerKey);
|
||||||
|
if (b != null)
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupIdForBreaker(Breaker _breaker) {
|
||||||
|
return getGroupIdForBreaker(_breaker.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupIdForBreaker(int _panel, int _space) {
|
||||||
|
return getGroupIdForBreaker(Breaker.key(_panel, _space));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupIdForBreaker(String _breakerKey) {
|
||||||
|
BreakerGroup group = getGroupForBreaker(_breakerKey);
|
||||||
|
return group != null ? group.getId() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup getGroupForBreaker(Breaker _breaker) {
|
||||||
|
return getGroupForBreaker(_breaker.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup getGroupForBreaker(int _panel, int _space) {
|
||||||
|
return getGroupForBreaker(Breaker.key(_panel, _space));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup getGroupForBreaker(String _breakerKey) {
|
||||||
|
if (_breakerKey == null)
|
||||||
|
return null;
|
||||||
|
Breaker b = CollectionUtils.filterOne(breakers, _b->_breakerKey.equals(_b.getKey()));
|
||||||
|
if (b != null)
|
||||||
|
return this;
|
||||||
|
for (BreakerGroup subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
BreakerGroup group = subGroup.getGroupForBreaker(_breakerKey);
|
||||||
|
if (group != null)
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroup findParentGroup(BreakerGroup _group) {
|
||||||
|
if (CollectionUtils.contains(subGroups, _group))
|
||||||
|
return this;
|
||||||
|
for (BreakerGroup subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
BreakerGroup parent = subGroup.findParentGroup(_group);
|
||||||
|
if (parent != null)
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeInvalidGroups() {
|
||||||
|
if (subGroups != null)
|
||||||
|
subGroups.removeIf(_g->!_g.removeInvalidGroups());
|
||||||
|
if (breakers != null)
|
||||||
|
breakers.removeIf(_b->(_b.getType() == null) || (_b.getType() == BreakerType.EMPTY) || (_b.getPort() < 1));
|
||||||
|
return CollectionUtils.isNotEmpty(subGroups) || CollectionUtils.isNotEmpty(breakers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object _o) {
|
||||||
|
if (this == _o) return true;
|
||||||
|
if (_o == null || getClass() != _o.getClass()) return false;
|
||||||
|
BreakerGroup that = (BreakerGroup) _o;
|
||||||
|
return Objects.equals(id, that.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,337 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
@DBSerializable(autogen = false)
|
||||||
|
public class BreakerGroupEnergy {
|
||||||
|
private int accountId;
|
||||||
|
private String groupId;
|
||||||
|
private String groupName;
|
||||||
|
private EnergyBlockViewMode viewMode;
|
||||||
|
private Date start;
|
||||||
|
private List<BreakerGroupEnergy> subGroups;
|
||||||
|
private List<EnergyBlock> energyBlocks;
|
||||||
|
private double toGrid;
|
||||||
|
private double fromGrid;
|
||||||
|
|
||||||
|
public BreakerGroupEnergy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroupEnergy(BreakerGroup _group, Map<String, List<BreakerPower>> _powerReadings, EnergyBlockViewMode _viewMode, Date _start, TimeZone _tz) {
|
||||||
|
groupId = _group.getId();
|
||||||
|
groupName = _group.getName();
|
||||||
|
viewMode = _viewMode;
|
||||||
|
start = _start;
|
||||||
|
accountId = _group.getAccountId();
|
||||||
|
subGroups = CollectionUtils.transform(_group.getSubGroups(), _g -> new BreakerGroupEnergy(_g, _powerReadings, _viewMode, _start, _tz));
|
||||||
|
energyBlocks = new ArrayList<>();
|
||||||
|
List<String> breakerKeys = CollectionUtils.transform(_group.getBreakers(), Breaker::getKey);
|
||||||
|
if (!breakerKeys.isEmpty()) {
|
||||||
|
for (BreakerPower power : CollectionUtils.aggregate(breakerKeys, _powerReadings::get)) {
|
||||||
|
addEnergy(groupId, power.getReadTime(), power.getPower(), _tz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroupEnergy(BreakerGroup _group, List<HubPowerMinute> _power, EnergyBlockViewMode _viewMode, Date _start, TimeZone _tz) {
|
||||||
|
groupId = _group.getId();
|
||||||
|
groupName = _group.getName();
|
||||||
|
viewMode = _viewMode;
|
||||||
|
start = _start;
|
||||||
|
accountId = _group.getAccountId();
|
||||||
|
subGroups = CollectionUtils.transform(_group.getSubGroups(), _g -> new BreakerGroupEnergy(_g, (List<HubPowerMinute>)null, _viewMode, _start, _tz));
|
||||||
|
energyBlocks = new ArrayList<>();
|
||||||
|
addEnergy(_group, _power, _tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEnergy(BreakerGroup _group, List<HubPowerMinute> _hubPower, TimeZone _tz) {
|
||||||
|
Map<String, Breaker> breakers = CollectionUtils.transformToMap(_group.getAllBreakers(), Breaker::getKey);
|
||||||
|
Map<String, BreakerGroup> breakerKeyToGroup = new HashMap<>();
|
||||||
|
for (BreakerGroup group : _group.getAllBreakerGroups()) {
|
||||||
|
for (Breaker b : group.getAllBreakers()) {
|
||||||
|
breakerKeyToGroup.put(b.getKey(), group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEnergy(breakers, breakerKeyToGroup, _hubPower, _tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEnergy(Map<String, Breaker> _breakers, Map<String, BreakerGroup> _breakerKeyToGroup, List<HubPowerMinute> _hubPower, TimeZone _tz) {
|
||||||
|
if (CollectionUtils.isEmpty(_hubPower) || CollectionUtils.anyQualify(_hubPower, _p->_p.getAccountId() != accountId))
|
||||||
|
return;
|
||||||
|
Date minute = CollectionUtils.getFirst(_hubPower).getMinuteAsDate();
|
||||||
|
resetEnergy(minute, _tz);
|
||||||
|
Map<Integer, MeterMinute> meters = new HashMap<>();
|
||||||
|
for (HubPowerMinute hubPower : _hubPower) {
|
||||||
|
for (BreakerPowerMinute breaker : CollectionUtils.makeNotNull(hubPower.getBreakers())) {
|
||||||
|
Breaker b = _breakers.get(breaker.breakerKey());
|
||||||
|
if (b == null)
|
||||||
|
continue;
|
||||||
|
BreakerGroup group = _breakerKeyToGroup.get(breaker.breakerKey());
|
||||||
|
if (group == null)
|
||||||
|
continue;
|
||||||
|
MeterMinute meter = meters.computeIfAbsent(b.getMeter(), _p->new MeterMinute());
|
||||||
|
int idx = 0;
|
||||||
|
for (Float power : CollectionUtils.makeNotNull(breaker.getReadings())) {
|
||||||
|
if (power > 0)
|
||||||
|
meter.usage[idx] += power;
|
||||||
|
else
|
||||||
|
meter.solar[idx] += -power;
|
||||||
|
if (power != 0.0)
|
||||||
|
addEnergy(group.getId(), minute, power, _tz);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MeterMinute meter : meters.values()) {
|
||||||
|
for (int i = 0; i < 60; i++) {
|
||||||
|
if (meter.usage[i] > meter.solar[i])
|
||||||
|
fromGrid += meter.usage[i] - meter.solar[i];
|
||||||
|
else
|
||||||
|
toGrid += meter.solar[i] - meter.usage[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetEnergy(Date _readTime, TimeZone _tz) {
|
||||||
|
EnergyBlock block = getBlock(_readTime, _tz, false);
|
||||||
|
if (block != null)
|
||||||
|
block.setJoules(0);
|
||||||
|
for (BreakerGroupEnergy subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
subGroup.resetEnergy(_readTime, _tz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEnergy(String _groupId, Date _readTime, double _joules, TimeZone _tz) {
|
||||||
|
if (NullUtils.isEqual(groupId, _groupId))
|
||||||
|
getBlock(_readTime, _tz).addJoules(_joules);
|
||||||
|
else {
|
||||||
|
for (BreakerGroupEnergy subGroup : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
subGroup.addEnergy(_groupId, _readTime, _joules, _tz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BreakerGroupEnergy summary(BreakerGroup _group, Map<String, List<BreakerGroupSummary>> _energies, EnergyBlockViewMode _viewMode, Date _start, TimeZone _tz) {
|
||||||
|
BreakerGroupEnergy energy = new BreakerGroupEnergy();
|
||||||
|
energy.setGroupId(_group.getId());
|
||||||
|
energy.setGroupName(_group.getName());
|
||||||
|
energy.setAccountId(_group.getAccountId());
|
||||||
|
energy.setViewMode(_viewMode);
|
||||||
|
energy.setStart(_start);
|
||||||
|
energy.setSubGroups(CollectionUtils.transform(_group.getSubGroups(), _g -> BreakerGroupEnergy.summary(_g, _energies, _viewMode, _start, _tz)));
|
||||||
|
for (BreakerGroupSummary curEnergy : CollectionUtils.makeNotNull(_energies.get(_group.getId()))) {
|
||||||
|
EnergyBlock block = energy.getBlock(curEnergy.getStart(), _tz);
|
||||||
|
block.addJoules(curEnergy.getJoules());
|
||||||
|
energy.setToGrid(energy.getToGrid()+curEnergy.getToGrid());
|
||||||
|
energy.setFromGrid(energy.getFromGrid()+curEnergy.getFromGrid());
|
||||||
|
}
|
||||||
|
return energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EnergyBlock getBlock(Date _readTime, TimeZone _tz) {
|
||||||
|
return getBlock(_readTime, _tz, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private EnergyBlock getBlock(Date _readTime, TimeZone _tz, boolean _add) {
|
||||||
|
int size = CollectionUtils.size(energyBlocks);
|
||||||
|
int idx = viewMode.blockIndex(_readTime, _tz);
|
||||||
|
if (_add && (idx >= size)) {
|
||||||
|
if (energyBlocks == null)
|
||||||
|
energyBlocks = new ArrayList<>();
|
||||||
|
LinkedList<EnergyBlock> newBlocks = new LinkedList<>();
|
||||||
|
Date end = viewMode.toBlockEnd(_readTime, _tz);
|
||||||
|
while (idx >= size) {
|
||||||
|
Date start = viewMode.decrementBlock(end, _tz);
|
||||||
|
newBlocks.add(new EnergyBlock(start, end, 0));
|
||||||
|
end = start;
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
Iterator<EnergyBlock> iter = newBlocks.descendingIterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
energyBlocks.add(iter.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CollectionUtils.get(energyBlocks, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return toId(accountId, groupId, viewMode, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toId(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start) {
|
||||||
|
return _accountId + "-" + _groupId + "-" + DaoSerializer.toEnumName(_viewMode) + "-" + _start.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId(String _groupId) {
|
||||||
|
groupId = _groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupName() {
|
||||||
|
return groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupName(String _groupName) {
|
||||||
|
groupName = _groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroupEnergy getSubGroup(String _groupId) {
|
||||||
|
return CollectionUtils.filterOne(subGroups, _g->_groupId.equals(_g.getGroupId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerGroupEnergy> getSubGroups() {
|
||||||
|
return subGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnergyBlockViewMode getViewMode() {
|
||||||
|
return viewMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewMode(EnergyBlockViewMode _viewMode) {
|
||||||
|
viewMode = _viewMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStart(Date _start) {
|
||||||
|
start = _start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubGroups(List<BreakerGroupEnergy> _subGroups) {
|
||||||
|
subGroups = _subGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EnergyBlock> getEnergyBlocks() {
|
||||||
|
return energyBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnergyBlocks(List<EnergyBlock> _energyBlocks) {
|
||||||
|
energyBlocks = _energyBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getToGrid() {
|
||||||
|
return toGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToGrid(double _toGrid) {
|
||||||
|
toGrid = _toGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getFromGrid() {
|
||||||
|
return fromGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFromGrid(double _fromGrid) {
|
||||||
|
fromGrid = _fromGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double wattHours() {
|
||||||
|
return joules() / 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double wattHours(Set<String> _selectedBreakers) {
|
||||||
|
return joules(_selectedBreakers) / 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double joules() {
|
||||||
|
return joules(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double joules(Set<String> _selectedBreakers) {
|
||||||
|
return joules(_selectedBreakers, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double joules(Set<String> _selectedBreakers, boolean _includeSubgroups) {
|
||||||
|
double joules = 0.0;
|
||||||
|
if (_includeSubgroups) {
|
||||||
|
for (BreakerGroupEnergy group : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
joules += group.joules(_selectedBreakers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((energyBlocks != null) && ((_selectedBreakers == null) || _selectedBreakers.contains(getGroupId()))) {
|
||||||
|
for (EnergyBlock energy : energyBlocks) {
|
||||||
|
joules += energy.getJoules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return joules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerGroupEnergy> getAllGroups() {
|
||||||
|
Map<String, BreakerGroupEnergy> groups = new TreeMap<>();
|
||||||
|
getAllGroups(groups);
|
||||||
|
return new ArrayList<>(groups.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAllGroups(Map<String, BreakerGroupEnergy> _groups) {
|
||||||
|
_groups.put(getGroupId(), this);
|
||||||
|
for (BreakerGroupEnergy group : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
group.getAllGroups(_groups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EnergyBlock> getAllEnergyBlocks() {
|
||||||
|
return getAllEnergyBlocks(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EnergyBlock> getAllEnergyBlocks(Set<String> _selectedGroups) {
|
||||||
|
return getAllEnergyBlocks(_selectedGroups, EnergyBlockType.ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EnergyBlock> getAllEnergyBlocks(Set<String> _selectedGroups, EnergyBlockType _type) {
|
||||||
|
Map<Long, EnergyBlock> blocks = new TreeMap<>();
|
||||||
|
getAllEnergyBlocks(_selectedGroups, blocks, _type);
|
||||||
|
return new ArrayList<>(blocks.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAllEnergyBlocks(Set<String> _selectedGroups, Map<Long, EnergyBlock> _energyBlocks, EnergyBlockType _type) {
|
||||||
|
if ((energyBlocks != null) && ((_selectedGroups == null) || _selectedGroups.contains(getGroupId()))) {
|
||||||
|
for (EnergyBlock block : energyBlocks) {
|
||||||
|
if ((_type == EnergyBlockType.ANY) || ((_type == EnergyBlockType.POSITIVE) && block.getJoules() >= 0.0) || ((_type == EnergyBlockType.NEGATIVE) && block.getJoules() <= 0.0)) {
|
||||||
|
EnergyBlock b = _energyBlocks.get(block.getStart().getTime());
|
||||||
|
if (b == null) {
|
||||||
|
b = new EnergyBlock(block.getStart(), block.getEnd(), block.getJoules());
|
||||||
|
_energyBlocks.put(block.getStart().getTime(), b);
|
||||||
|
} else
|
||||||
|
b.addJoules(block.getJoules());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (BreakerGroupEnergy group : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
group.getAllEnergyBlocks(_selectedGroups, _energyBlocks, _type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MeterMinute {
|
||||||
|
public double[] usage = new double[60];
|
||||||
|
public double[] solar = new double[60];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
@DBSerializable(autogen = false)
|
||||||
|
public class BreakerGroupSummary {
|
||||||
|
private int accountId;
|
||||||
|
private String groupId;
|
||||||
|
private String groupName;
|
||||||
|
private EnergyBlockViewMode viewMode;
|
||||||
|
private Date start;
|
||||||
|
private List<BreakerGroupSummary> subGroups;
|
||||||
|
private double joules;
|
||||||
|
private double toGrid;
|
||||||
|
private double fromGrid;
|
||||||
|
|
||||||
|
public BreakerGroupSummary() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroupSummary(BreakerGroupEnergy _energy) {
|
||||||
|
accountId = _energy.getAccountId();
|
||||||
|
groupId = _energy.getGroupId();
|
||||||
|
groupName = _energy.getGroupName();
|
||||||
|
viewMode = _energy.getViewMode();
|
||||||
|
start = _energy.getStart();
|
||||||
|
subGroups = CollectionUtils.transform(_energy.getSubGroups(), BreakerGroupSummary::new);
|
||||||
|
joules = _energy.joules(null, false);
|
||||||
|
toGrid = _energy.getToGrid();
|
||||||
|
fromGrid = _energy.getFromGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return toId(accountId, groupId, viewMode, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toId(int _accountId, String _groupId, EnergyBlockViewMode _viewMode, Date _start) {
|
||||||
|
return _accountId + "-" + _groupId + "-" + DaoSerializer.toEnumName(_viewMode) + "-" + _start.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId(String _groupId) {
|
||||||
|
groupId = _groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupName() {
|
||||||
|
return groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupName(String _groupName) {
|
||||||
|
groupName = _groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerGroupSummary getSubGroup(String _groupId) {
|
||||||
|
return CollectionUtils.filterOne(subGroups, _g->_groupId.equals(_g.getGroupId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerGroupSummary> getSubGroups() {
|
||||||
|
return subGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnergyBlockViewMode getViewMode() {
|
||||||
|
return viewMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewMode(EnergyBlockViewMode _viewMode) {
|
||||||
|
viewMode = _viewMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStart(Date _start) {
|
||||||
|
start = _start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubGroups(List<BreakerGroupSummary> _subGroups) {
|
||||||
|
subGroups = _subGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getJoules() {
|
||||||
|
return joules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJoules(double _joules) {
|
||||||
|
joules = _joules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getToGrid() {
|
||||||
|
return toGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToGrid(double _toGrid) {
|
||||||
|
toGrid = _toGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getFromGrid() {
|
||||||
|
return fromGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFromGrid(double _fromGrid) {
|
||||||
|
fromGrid = _fromGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerGroupSummary> getAllGroups() {
|
||||||
|
Map<String, BreakerGroupSummary> groups = new TreeMap<>();
|
||||||
|
getAllGroups(groups);
|
||||||
|
return new ArrayList<>(groups.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAllGroups(Map<String, BreakerGroupSummary> _groups) {
|
||||||
|
if (NullUtils.isNotEmpty(getGroupId()))
|
||||||
|
_groups.put(getGroupId(), this);
|
||||||
|
for (BreakerGroupSummary group : CollectionUtils.makeNotNull(subGroups)) {
|
||||||
|
group.getAllGroups(_groups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
@DBSerializable
|
||||||
|
public class BreakerHub {
|
||||||
|
private int hub;
|
||||||
|
private double voltageCalibrationFactor;
|
||||||
|
private int frequency;
|
||||||
|
private String bluetoothMac;
|
||||||
|
|
||||||
|
public int getHub() {
|
||||||
|
return hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHub(int _hub) {
|
||||||
|
hub = _hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getVoltageCalibrationFactor() {
|
||||||
|
return voltageCalibrationFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVoltageCalibrationFactor(double _voltageCalibrationFactor) {
|
||||||
|
voltageCalibrationFactor = _voltageCalibrationFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFrequency() {
|
||||||
|
return frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrequency(int _frequency) {
|
||||||
|
frequency = _frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBluetoothMac() {
|
||||||
|
return bluetoothMac;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBluetoothMac(String _bluetoothMac) {
|
||||||
|
bluetoothMac = _bluetoothMac;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
@DBSerializable
|
||||||
|
public class BreakerPanel {
|
||||||
|
private int accountId;
|
||||||
|
private String name;
|
||||||
|
private int index;
|
||||||
|
private int spaces;
|
||||||
|
private int meter;
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String _name) {
|
||||||
|
name = _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(int _index) {
|
||||||
|
index = _index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSpaces() {
|
||||||
|
return spaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpaces(int _spaces) {
|
||||||
|
spaces = _spaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMeter() {
|
||||||
|
return meter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMeter(int _meter) {
|
||||||
|
meter = _meter;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
public enum BreakerPolarity {
|
||||||
|
NORMAL,
|
||||||
|
SOLAR;
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@DBSerializable(autogen = false)
|
||||||
|
public class BreakerPower {
|
||||||
|
private int accountId;
|
||||||
|
private int panel;
|
||||||
|
private int space;
|
||||||
|
private Date readTime;
|
||||||
|
private String hubVersion;
|
||||||
|
private double power;
|
||||||
|
private double voltage;
|
||||||
|
|
||||||
|
public BreakerPower() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreakerPower(int _panel, int _space, Date _readTime, double _power, double _voltage) {
|
||||||
|
panel = _panel;
|
||||||
|
space = _space;
|
||||||
|
readTime = _readTime;
|
||||||
|
power = _power;
|
||||||
|
voltage = _voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return String.format("%d-%d-%d", accountId, panel, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPanel() {
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPanel(int _panel) {
|
||||||
|
panel = _panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSpace() {
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpace(int _space) {
|
||||||
|
space = _space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getReadTime() {
|
||||||
|
return readTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadTime(Date _readTime) {
|
||||||
|
readTime = _readTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHubVersion() {
|
||||||
|
return hubVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHubVersion(String _hubVersion) {
|
||||||
|
hubVersion = _hubVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPower() {
|
||||||
|
return power;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPower(double _power) {
|
||||||
|
power = _power;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getVoltage() {
|
||||||
|
return voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVoltage(double _voltage) {
|
||||||
|
voltage = _voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return Breaker.key(panel, space);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@DBSerializable(autogen = false)
|
||||||
|
public class BreakerPowerMinute {
|
||||||
|
private int panel;
|
||||||
|
private int space;
|
||||||
|
private List<Float> readings;
|
||||||
|
|
||||||
|
public int getPanel() {
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPanel(int _panel) {
|
||||||
|
panel = _panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSpace() {
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpace(int _space) {
|
||||||
|
space = _space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String breakerKey() {
|
||||||
|
return Breaker.key(panel, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Float> getReadings() {
|
||||||
|
return readings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadings(List<Float> _readings) {
|
||||||
|
readings = _readings;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public enum BreakerType {
|
||||||
|
EMPTY("Empty"),
|
||||||
|
SINGLE_POLE("Single Pole"),
|
||||||
|
SINGLE_POLE_TANDEM("Single Pole Tandem (Two Breakers in One)"),
|
||||||
|
DOUBLE_POLE_TOP("Double Pole (240V)"),
|
||||||
|
DOUBLE_POLE_BOTTOM("Double Pole (240V)");
|
||||||
|
|
||||||
|
private final String display;
|
||||||
|
|
||||||
|
BreakerType(String _display) {
|
||||||
|
display = _display;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplay() {
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<BreakerType> selectable() {
|
||||||
|
return CollectionUtils.asArrayList(EMPTY, SINGLE_POLE, SINGLE_POLE_TANDEM, DOUBLE_POLE_TOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BreakerType fromDisplay(String _display) {
|
||||||
|
for (BreakerType type : values()) {
|
||||||
|
if (NullUtils.isEqual(_display, type.getDisplay()))
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public enum CharacteristicFlag {
|
||||||
|
BROADCAST("broadcast"),
|
||||||
|
READ("read"),
|
||||||
|
WRITE_WITHOUT_RESPONSE("write-without-response"),
|
||||||
|
WRITE("write"),
|
||||||
|
NOTIFY("notify"),
|
||||||
|
INDICATE("indicate"),
|
||||||
|
AUTHENTICATED_SIGNED_WRITES("authenticated-signed-writes"),
|
||||||
|
RELIABLE_WRITE("reliable-write"),
|
||||||
|
WRITABLE_AUXILIARIES("writable-auxiliaries"),
|
||||||
|
ENCRYPT_READ("encrypt-read"),
|
||||||
|
ENCRYPT_WRITE("encrypt-write"),
|
||||||
|
ENCRYPT_AUTHENTICATED_READ("encrypt-authenticated-read"),
|
||||||
|
ENCRYPT_AUTHENTICATED_WRITE("encrypt-authenticated-write");
|
||||||
|
|
||||||
|
CharacteristicFlag(String _value) {
|
||||||
|
value = _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String value;
|
||||||
|
|
||||||
|
public static String[] toArray(Collection<CharacteristicFlag> _flags) {
|
||||||
|
return CollectionUtils.transform(_flags, _c->_c.value).toArray(new String[0]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@DBSerializable
|
||||||
|
public class EnergyBlock {
|
||||||
|
private Date start;
|
||||||
|
private Date end;
|
||||||
|
private double joules;
|
||||||
|
|
||||||
|
public EnergyBlock() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnergyBlock(Date _start, Date _end, double _joules) {
|
||||||
|
start = _start;
|
||||||
|
end = _end;
|
||||||
|
joules = _joules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStart(Date _start) {
|
||||||
|
start = _start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getEnd() {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnd(Date _end) {
|
||||||
|
end = _end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getJoules() {
|
||||||
|
return joules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addJoules(double _joules) {
|
||||||
|
joules += _joules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJoules(double _joules) {
|
||||||
|
joules = _joules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double wattHours() {
|
||||||
|
return joules / 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAveragePower() {
|
||||||
|
if ((end == null) || (start == null))
|
||||||
|
return 0;
|
||||||
|
return 1000*joules/(end.getTime()-start.getTime());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
public enum EnergyBlockType {
|
||||||
|
ANY,
|
||||||
|
POSITIVE,
|
||||||
|
NEGATIVE
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.DateUtils;
|
||||||
|
|
||||||
|
import javax.management.remote.rmi._RMIConnection_Stub;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
public enum EnergyBlockViewMode {
|
||||||
|
DAY,
|
||||||
|
MONTH,
|
||||||
|
YEAR,
|
||||||
|
ALL;
|
||||||
|
|
||||||
|
public Date toStart(Date _dt, TimeZone _tz) {
|
||||||
|
if (this == DAY)
|
||||||
|
return DateUtils.getMidnightBefore(_dt, _tz);
|
||||||
|
if (this == MONTH)
|
||||||
|
return DateUtils.getStartOfMonth(_dt, _tz);
|
||||||
|
if (this == YEAR)
|
||||||
|
return DateUtils.getStartOfYear(_dt, _tz);
|
||||||
|
return new Date(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date toEnd(Date _dt, TimeZone _tz) {
|
||||||
|
if (this == DAY)
|
||||||
|
return DateUtils.getMidnightAfter(_dt, _tz);
|
||||||
|
if (this == MONTH)
|
||||||
|
return DateUtils.getEndOfMonth(_dt, _tz);
|
||||||
|
if (this == YEAR)
|
||||||
|
return DateUtils.getEndOfYear(_dt, _tz);
|
||||||
|
return new Date(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date toBlockStart(Date _dt, TimeZone _tz) {
|
||||||
|
if (this == DAY)
|
||||||
|
return DateUtils.getStartOfMinute(_dt, _tz);
|
||||||
|
if (this == MONTH)
|
||||||
|
return DateUtils.getMidnightBefore(_dt, _tz);
|
||||||
|
if (this == YEAR)
|
||||||
|
return DateUtils.getStartOfMonth(_dt, _tz);
|
||||||
|
return new Date(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date toBlockEnd(Date _dt, TimeZone _tz) {
|
||||||
|
if (this == DAY)
|
||||||
|
return DateUtils.getEndOfMinute(_dt, _tz);
|
||||||
|
if (this == MONTH)
|
||||||
|
return DateUtils.getMidnightAfter(_dt, _tz);
|
||||||
|
if (this == YEAR)
|
||||||
|
return DateUtils.getEndOfMonth(_dt, _tz);
|
||||||
|
return new Date(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date incrementBlock(Date _dt, TimeZone _tz) {
|
||||||
|
Calendar cal = DateUtils.toCalendar(_dt, _tz);
|
||||||
|
if (this == DAY)
|
||||||
|
cal.add(Calendar.MINUTE, 1);
|
||||||
|
else if (this == MONTH)
|
||||||
|
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||||
|
if (this == YEAR)
|
||||||
|
cal.add(Calendar.MONTH, 1);
|
||||||
|
return cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date decrementBlock(Date _dt, TimeZone _tz) {
|
||||||
|
Calendar cal = DateUtils.toCalendar(_dt, _tz);
|
||||||
|
if (this == DAY)
|
||||||
|
cal.add(Calendar.MINUTE, -1);
|
||||||
|
else if (this == MONTH)
|
||||||
|
cal.add(Calendar.DAY_OF_YEAR, -1);
|
||||||
|
if (this == YEAR)
|
||||||
|
cal.add(Calendar.MONTH, -1);
|
||||||
|
return cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date incrementView(Date _dt, TimeZone _tz) {
|
||||||
|
Calendar cal = DateUtils.toCalendar(_dt, _tz);
|
||||||
|
if (this == DAY)
|
||||||
|
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||||
|
else if (this == MONTH)
|
||||||
|
cal.add(Calendar.MONTH, 1);
|
||||||
|
if (this == YEAR)
|
||||||
|
cal.add(Calendar.YEAR, 1);
|
||||||
|
return cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date decrementView(Date _dt, TimeZone _tz) {
|
||||||
|
Calendar cal = DateUtils.toCalendar(_dt, _tz);
|
||||||
|
if (this == DAY)
|
||||||
|
cal.add(Calendar.DAY_OF_YEAR, -1);
|
||||||
|
else if (this == MONTH)
|
||||||
|
cal.add(Calendar.MONTH, -1);
|
||||||
|
if (this == YEAR)
|
||||||
|
cal.add(Calendar.YEAR, -1);
|
||||||
|
return cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int blockCount(Date _start, TimeZone _tz) {
|
||||||
|
if (this == ALL)
|
||||||
|
return 1;
|
||||||
|
Date end = toEnd(_start, _tz);
|
||||||
|
int blockCnt = 0;
|
||||||
|
while (_start.before(end)) {
|
||||||
|
blockCnt++;
|
||||||
|
_start = toBlockEnd(_start, _tz);
|
||||||
|
}
|
||||||
|
return blockCnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int blockIndex(Date _readTime, TimeZone _tz) {
|
||||||
|
if (this == DAY) {
|
||||||
|
Date start = DateUtils.getMidnightBefore(_readTime, _tz);
|
||||||
|
return (int)((_readTime.getTime() - start.getTime())/60000);
|
||||||
|
}
|
||||||
|
else if (this == MONTH) {
|
||||||
|
Calendar read = DateUtils.toCalendar(_readTime, _tz);
|
||||||
|
return read.get(Calendar.DAY_OF_MONTH) - 1;
|
||||||
|
}
|
||||||
|
if (this == YEAR) {
|
||||||
|
Calendar read = DateUtils.toCalendar(_readTime, _tz);
|
||||||
|
return read.get(Calendar.MONTH);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date toBlockStart(int _index, Date _start, TimeZone _tz) {
|
||||||
|
if (this == DAY)
|
||||||
|
return new Date(_start.getTime() + _index*60000);
|
||||||
|
else if (this == MONTH) {
|
||||||
|
Calendar read = DateUtils.toCalendar(_start, _tz);
|
||||||
|
read.add(Calendar.DAY_OF_MONTH, _index);
|
||||||
|
return read.getTime();
|
||||||
|
}
|
||||||
|
if (this == YEAR) {
|
||||||
|
Calendar read = DateUtils.toCalendar(_start, _tz);
|
||||||
|
read.add(Calendar.MONTH, _index);
|
||||||
|
return read.getTime();
|
||||||
|
}
|
||||||
|
return new Date(0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public enum HubConfigCharacteristic {
|
||||||
|
WifiCredentials(2, CharacteristicFlag.WRITE),
|
||||||
|
AuthCode(3, CharacteristicFlag.WRITE),
|
||||||
|
HubIndex(4, CharacteristicFlag.READ, CharacteristicFlag.WRITE),
|
||||||
|
Restart(5, CharacteristicFlag.WRITE),
|
||||||
|
Reboot(6, CharacteristicFlag.WRITE),
|
||||||
|
AccountId(7, CharacteristicFlag.READ),
|
||||||
|
NetworkState(8, CharacteristicFlag.READ),
|
||||||
|
Flash(9, CharacteristicFlag.WRITE);
|
||||||
|
|
||||||
|
public final int idx;
|
||||||
|
public final UUID uuid;
|
||||||
|
public final EnumSet<CharacteristicFlag> flags;
|
||||||
|
|
||||||
|
HubConfigCharacteristic(int _idx, CharacteristicFlag... _flags) {
|
||||||
|
idx = _idx;
|
||||||
|
uuid = HubConfigService.uuidFormat.format(_idx);
|
||||||
|
flags = EnumSet.copyOf(Arrays.asList(_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIdx() {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnumSet<CharacteristicFlag> getFlags() {
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChar(String _char) {
|
||||||
|
return NullUtils.isEqual(name(), _char);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.cryptography.AESTool;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class HubConfigService {
|
||||||
|
public static final UUIDFormatter uuidFormat = new UUIDFormatter("c5650001-d50f-49af-b906-cada0dc17937");
|
||||||
|
private static final AESTool aes = new AESTool(37320708309265127L,-8068168662055796771L,-4867793276337148572L,4425609941731230765L);
|
||||||
|
private static final UUID serviceUUID = uuidFormat.format(1);
|
||||||
|
|
||||||
|
public HubConfigService() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID getServiceUUID() {
|
||||||
|
return serviceUUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HubConfigCharacteristic> getCharacteristics() {
|
||||||
|
return Arrays.asList(HubConfigCharacteristic.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] encryptWifiCreds(String _ssid, String _password) {
|
||||||
|
DaoEntity creds = new DaoEntity("ssid", _ssid).and("pwd", _password);
|
||||||
|
return aes.encrypt(DaoSerializer.toZipBson(creds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decryptWifiSSID(byte[] _payload) {
|
||||||
|
return DaoSerializer.getString(DaoSerializer.fromZipBson(aes.decrypt(_payload)), "ssid");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decryptWifiPassword(byte[] _payload) {
|
||||||
|
return DaoSerializer.getString(DaoSerializer.fromZipBson(aes.decrypt(_payload)), "pwd");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@DBSerializable
|
||||||
|
public class HubPowerMinute {
|
||||||
|
private int accountId;
|
||||||
|
private int hub;
|
||||||
|
private int minute;
|
||||||
|
private List<BreakerPowerMinute> breakers;
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHub() {
|
||||||
|
return hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHub(int _hub) {
|
||||||
|
hub = _hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getMinuteAsDate() {
|
||||||
|
return new Date(((long)minute)*60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinute() {
|
||||||
|
return minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinute(int _minute) {
|
||||||
|
minute = _minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinute(Date _minute) {
|
||||||
|
minute = (int)(_minute.getTime()/60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BreakerPowerMinute> getBreakers() {
|
||||||
|
return breakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBreakers(List<BreakerPowerMinute> _breakers) {
|
||||||
|
breakers = _breakers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return String.format("%d-%d-%d", accountId, hub, minute);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
@DBSerializable
|
||||||
|
public class Meter {
|
||||||
|
private int accountId;
|
||||||
|
private int index;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public int getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(int _accountId) {
|
||||||
|
accountId = _accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(int _index) {
|
||||||
|
index = _index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String _name) {
|
||||||
|
name = _name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
public enum NetworkAdapter {
|
||||||
|
ETHERNET((byte)0x1),
|
||||||
|
WIFI((byte)0x2);
|
||||||
|
|
||||||
|
public final byte bt;
|
||||||
|
|
||||||
|
NetworkAdapter(byte _bt) {
|
||||||
|
bt = _bt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkAdapter fromByte(byte _bt) {
|
||||||
|
for (NetworkAdapter a : values()) {
|
||||||
|
if (a.bt == _bt)
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EnumSet<NetworkAdapter> fromMask(byte _bt) {
|
||||||
|
EnumSet<NetworkAdapter> values = EnumSet.noneOf(NetworkAdapter.class);
|
||||||
|
for (NetworkAdapter a : values()) {
|
||||||
|
if ((a.bt & _bt) == a.bt)
|
||||||
|
values.add(a);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte toMask(Collection<NetworkAdapter> _adapters) {
|
||||||
|
byte mask = 0;
|
||||||
|
for (NetworkAdapter a : CollectionUtils.makeNotNull(_adapters)) {
|
||||||
|
mask |= a.bt;
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NetworkStatus {
|
||||||
|
private List<String> wifiIPs;
|
||||||
|
private List<String> ethernetIPs;
|
||||||
|
|
||||||
|
public List<String> getWifiIPs() {
|
||||||
|
return wifiIPs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWifiIPs(List<String> _wifiIPs) {
|
||||||
|
wifiIPs = _wifiIPs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getEthernetIPs() {
|
||||||
|
return ethernetIPs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEthernetIPs(List<String> _ethernetIPs) {
|
||||||
|
ethernetIPs = _ethernetIPs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWifiConnected() {
|
||||||
|
return CollectionUtils.isNotEmpty(wifiIPs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEthernetConnected() {
|
||||||
|
return CollectionUtils.isNotEmpty(ethernetIPs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte toMask() {
|
||||||
|
EnumSet<NetworkAdapter> adapters = EnumSet.noneOf(NetworkAdapter.class);
|
||||||
|
if (isWifiConnected())
|
||||||
|
adapters.add(NetworkAdapter.WIFI);
|
||||||
|
if (isEthernetConnected())
|
||||||
|
adapters.add(NetworkAdapter.ETHERNET);
|
||||||
|
return NetworkAdapter.toMask(adapters);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.PrimaryKey;
|
||||||
|
|
||||||
|
@DBSerializable
|
||||||
|
public class Sequence {
|
||||||
|
@PrimaryKey
|
||||||
|
private String id;
|
||||||
|
private int sequence;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String _id) {
|
||||||
|
id = _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSequence() {
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSequence(int _sequence) {
|
||||||
|
sequence = _sequence;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.annotations.DBSerializable;
|
||||||
|
|
||||||
|
@DBSerializable
|
||||||
|
public class SignupResponse {
|
||||||
|
private String error;
|
||||||
|
private String authCode;
|
||||||
|
|
||||||
|
public SignupResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SignupResponse error(String _error) {
|
||||||
|
SignupResponse response = new SignupResponse();
|
||||||
|
response.setError(_error);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SignupResponse success(String _authCode) {
|
||||||
|
SignupResponse response = new SignupResponse();
|
||||||
|
response.setAuthCode(_authCode);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setError(String _error) {
|
||||||
|
error = _error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthCode() {
|
||||||
|
return authCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthCode(String _authCode) {
|
||||||
|
authCode = _authCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return NullUtils.isEmpty(error) && NullUtils.isNotEmpty(authCode);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UUIDFormatter {
|
||||||
|
private final String uuidPrefix;
|
||||||
|
private final String uuidSuffix;
|
||||||
|
|
||||||
|
public UUIDFormatter(String _uuid) {
|
||||||
|
uuidPrefix = _uuid.substring(0,4);
|
||||||
|
uuidSuffix = _uuid.substring(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID format(int _idx) {
|
||||||
|
return UUID.fromString(uuidPrefix + String.format("%04X", _idx) + uuidSuffix);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AccountSerializer extends AbstractDaoSerializer<Account>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<Account> getSupportedClass()
|
||||||
|
{
|
||||||
|
return Account.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(Account _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("_id", String.valueOf(_o.getId()));
|
||||||
|
d.put("username", _o.getUsername());
|
||||||
|
d.put("password", _o.getPassword());
|
||||||
|
if (CollectionUtils.isNotEmpty(_o.getAuxiliaryAccountIds()))
|
||||||
|
d.put("aux_account_ids", CollectionUtils.toByteArray(_o.getAuxiliaryAccountIds()));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
Account o = new Account();
|
||||||
|
o.setId(DaoSerializer.getInteger(_d, "_id"));
|
||||||
|
o.setUsername(DaoSerializer.getString(_d, "username"));
|
||||||
|
o.setPassword(DaoSerializer.getString(_d, "password"));
|
||||||
|
o.setAuxiliaryAccountIds(CollectionUtils.fromByteArrayOfIntegers(DaoSerializer.getByteArray(_d, "aux_account_ids")));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AuthCodeSerializer extends AbstractDaoSerializer<AuthCode>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<AuthCode> getSupportedClass()
|
||||||
|
{
|
||||||
|
return AuthCode.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(AuthCode _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
if (CollectionUtils.isNotEmpty(_o.getAuxiliaryAccountIds()))
|
||||||
|
d.put("aux_account_ids", CollectionUtils.toByteArray(_o.getAuxiliaryAccountIds()));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthCode fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
AuthCode o = new AuthCode();
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setAuxiliaryAccountIds(CollectionUtils.fromByteArrayOfIntegers(DaoSerializer.getByteArray(_d, "aux_account_ids")));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerHub;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPanel;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Meter;
|
||||||
|
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 BreakerConfigSerializer extends AbstractDaoSerializer<BreakerConfig>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<BreakerConfig> getSupportedClass()
|
||||||
|
{
|
||||||
|
return BreakerConfig.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(BreakerConfig _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("_id", String.valueOf(_o.getAccountId()));
|
||||||
|
d.put("meters", DaoSerializer.toDaoEntities(_o.getMeters(), DaoProxyType.MONGO));
|
||||||
|
d.put("panels", DaoSerializer.toDaoEntities(_o.getPanels(), DaoProxyType.MONGO));
|
||||||
|
d.put("breaker_hubs", DaoSerializer.toDaoEntities(_o.getBreakerHubs(), DaoProxyType.MONGO));
|
||||||
|
d.put("breaker_groups", DaoSerializer.toDaoEntities(_o.getBreakerGroups(), DaoProxyType.MONGO));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerConfig fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
BreakerConfig o = new BreakerConfig();
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "_id"));
|
||||||
|
o.setMeters(DaoSerializer.getList(_d, "meters", Meter.class));
|
||||||
|
o.setPanels(DaoSerializer.getList(_d, "panels", BreakerPanel.class));
|
||||||
|
o.setBreakerHubs(DaoSerializer.getList(_d, "breaker_hubs", BreakerHub.class));
|
||||||
|
o.setBreakerGroups(DaoSerializer.getList(_d, "breaker_groups", BreakerGroup.class));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlock;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
public class BreakerGroupEnergySerializer extends AbstractDaoSerializer<BreakerGroupEnergy>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<BreakerGroupEnergy> getSupportedClass()
|
||||||
|
{
|
||||||
|
return BreakerGroupEnergy.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(BreakerGroupEnergy _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("_id", _o.getId());
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
d.put("group_id", _o.getGroupId());
|
||||||
|
d.put("group_name", _o.getGroupName());
|
||||||
|
d.put("view_mode", DaoSerializer.toEnumName(_o.getViewMode()));
|
||||||
|
d.put("start", DaoSerializer.toLong(_o.getStart()));
|
||||||
|
d.put("sub_groups", DaoSerializer.toDaoEntities(_o.getSubGroups(), DaoProxyType.MONGO));
|
||||||
|
if (CollectionUtils.size(_o.getEnergyBlocks()) > 0) {
|
||||||
|
Date start = _o.getStart();
|
||||||
|
Date now = new Date();
|
||||||
|
TimeZone tz = TimeZone.getTimeZone("America/Chicago");
|
||||||
|
ByteBuffer bb = ByteBuffer.allocate(_o.getViewMode().blockCount(start, tz) * 4);
|
||||||
|
for (EnergyBlock b : _o.getEnergyBlocks()) {
|
||||||
|
if (b.getStart().before(start))
|
||||||
|
continue;
|
||||||
|
if (now.before(start))
|
||||||
|
break;
|
||||||
|
while (start.before(b.getStart())) {
|
||||||
|
bb.putFloat(0);
|
||||||
|
start = _o.getViewMode().toBlockEnd(start, tz);
|
||||||
|
}
|
||||||
|
bb.putFloat((float) b.getJoules());
|
||||||
|
start = _o.getViewMode().toBlockEnd(start, tz);
|
||||||
|
}
|
||||||
|
if (bb.position() < bb.limit())
|
||||||
|
d.put("blocks", Arrays.copyOfRange(bb.array(), 0, bb.position()));
|
||||||
|
else
|
||||||
|
d.put("blocks", bb.array());
|
||||||
|
}
|
||||||
|
d.put("to_grid", _o.getToGrid());
|
||||||
|
d.put("from_grid", _o.getFromGrid());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerGroupEnergy fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
TimeZone tz = TimeZone.getTimeZone("America/Chicago");
|
||||||
|
BreakerGroupEnergy o = new BreakerGroupEnergy();
|
||||||
|
o.setGroupId(DaoSerializer.getString(_d, "group_id"));
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setGroupName(DaoSerializer.getString(_d, "group_name"));
|
||||||
|
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyBlockViewMode.class));
|
||||||
|
o.setStart(DaoSerializer.getDate(_d, "start"));
|
||||||
|
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", BreakerGroupEnergy.class));
|
||||||
|
List<EnergyBlock> blocks = new ArrayList<>();
|
||||||
|
byte[] blockData = DaoSerializer.getByteArray(_d, "blocks");
|
||||||
|
if (CollectionUtils.length(blockData) > 0) {
|
||||||
|
ByteBuffer bb = ByteBuffer.wrap(blockData);
|
||||||
|
Date start = o.getStart();
|
||||||
|
while (bb.hasRemaining()) {
|
||||||
|
EnergyBlock block = new EnergyBlock(start, o.getViewMode().toBlockEnd(start, tz), bb.getFloat());
|
||||||
|
blocks.add(block);
|
||||||
|
start = block.getEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o.setEnergyBlocks(blocks);
|
||||||
|
o.setToGrid(DaoSerializer.getDouble(_d, "to_grid"));
|
||||||
|
o.setFromGrid(DaoSerializer.getDouble(_d, "from_grid"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||||
|
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 BreakerGroupSerializer extends AbstractDaoSerializer<BreakerGroup>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<BreakerGroup> getSupportedClass()
|
||||||
|
{
|
||||||
|
return BreakerGroup.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(BreakerGroup _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
if (_o.getId() != null)
|
||||||
|
d.put("_id", _o.getId());
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
d.put("name", _o.getName());
|
||||||
|
d.put("sub_groups", DaoSerializer.toDaoEntities(_o.getSubGroups(), DaoProxyType.MONGO));
|
||||||
|
d.put("breakers", DaoSerializer.toDaoEntities(_o.getBreakers(), DaoProxyType.MONGO));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerGroup fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
BreakerGroup o = new BreakerGroup();
|
||||||
|
o.setId(DaoSerializer.getString(_d, "_id"));
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setName(DaoSerializer.getString(_d, "name"));
|
||||||
|
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", BreakerGroup.class));
|
||||||
|
o.setBreakers(DaoSerializer.getList(_d, "breakers", Breaker.class));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupSummary;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||||
|
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoProxyType;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
public class BreakerGroupSummarySerializer extends AbstractDaoSerializer<BreakerGroupSummary> {
|
||||||
|
@Override
|
||||||
|
public Class<BreakerGroupSummary> getSupportedClass() {
|
||||||
|
return BreakerGroupSummary.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(BreakerGroupSummary _o) {
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("_id", _o.getId());
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
d.put("group_id", _o.getGroupId());
|
||||||
|
d.put("group_name", _o.getGroupName());
|
||||||
|
d.put("view_mode", DaoSerializer.toEnumName(_o.getViewMode()));
|
||||||
|
d.put("start", DaoSerializer.toLong(_o.getStart()));
|
||||||
|
d.put("sub_groups", DaoSerializer.toDaoEntities(_o.getSubGroups(), DaoProxyType.MONGO));
|
||||||
|
d.put("joules", _o.getJoules());
|
||||||
|
d.put("to_grid", _o.getToGrid());
|
||||||
|
d.put("from_grid", _o.getFromGrid());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerGroupSummary fromDaoEntity(DaoEntity _d) {
|
||||||
|
BreakerGroupSummary o = new BreakerGroupSummary();
|
||||||
|
o.setGroupId(DaoSerializer.getString(_d, "group_id"));
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setGroupName(DaoSerializer.getString(_d, "group_name"));
|
||||||
|
o.setViewMode(DaoSerializer.getEnum(_d, "view_mode", EnergyBlockViewMode.class));
|
||||||
|
o.setStart(DaoSerializer.getDate(_d, "start"));
|
||||||
|
o.setSubGroups(DaoSerializer.getList(_d, "sub_groups", BreakerGroupSummary.class));
|
||||||
|
o.setJoules(DaoSerializer.getDouble(_d, "joules"));
|
||||||
|
o.setToGrid(DaoSerializer.getDouble(_d, "to_grid"));
|
||||||
|
o.setFromGrid(DaoSerializer.getDouble(_d, "from_grid"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerHub;
|
||||||
|
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 BreakerHubSerializer extends AbstractDaoSerializer<BreakerHub>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<BreakerHub> getSupportedClass()
|
||||||
|
{
|
||||||
|
return BreakerHub.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(BreakerHub _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("hub", _o.getHub());
|
||||||
|
d.put("voltage_calibration_factor", _o.getVoltageCalibrationFactor());
|
||||||
|
d.put("frequency", _o.getFrequency());
|
||||||
|
d.put("bluetooth_mac", _o.getBluetoothMac());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerHub fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
BreakerHub o = new BreakerHub();
|
||||||
|
o.setHub(DaoSerializer.getInteger(_d, "hub"));
|
||||||
|
o.setVoltageCalibrationFactor(DaoSerializer.getDouble(_d, "voltage_calibration_factor"));
|
||||||
|
o.setFrequency(DaoSerializer.getInteger(_d, "frequency"));
|
||||||
|
o.setBluetoothMac(DaoSerializer.getString(_d, "bluetooth_mac"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPanel;
|
||||||
|
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 BreakerPanelSerializer extends AbstractDaoSerializer<BreakerPanel>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<BreakerPanel> getSupportedClass()
|
||||||
|
{
|
||||||
|
return BreakerPanel.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(BreakerPanel _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
d.put("name", _o.getName());
|
||||||
|
d.put("index", _o.getIndex());
|
||||||
|
d.put("spaces", _o.getSpaces());
|
||||||
|
d.put("meter", _o.getMeter());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerPanel fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
BreakerPanel o = new BreakerPanel();
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setName(DaoSerializer.getString(_d, "name"));
|
||||||
|
o.setIndex(DaoSerializer.getInteger(_d, "index"));
|
||||||
|
o.setSpaces(DaoSerializer.getInteger(_d, "spaces"));
|
||||||
|
o.setMeter(DaoSerializer.getInteger(_d, "meter"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPowerMinute;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BreakerPowerMinuteSerializer extends AbstractDaoSerializer<BreakerPowerMinute> {
|
||||||
|
@Override
|
||||||
|
public Class<BreakerPowerMinute> getSupportedClass() {
|
||||||
|
return BreakerPowerMinute.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(BreakerPowerMinute _o) {
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("panel", _o.getPanel());
|
||||||
|
d.put("space", _o.getSpace());
|
||||||
|
ByteBuffer bb = ByteBuffer.allocate(240);
|
||||||
|
for (Float reading : CollectionUtils.makeNotNull(_o.getReadings())) {
|
||||||
|
bb.putFloat(DaoSerializer.toFloat(reading));
|
||||||
|
}
|
||||||
|
d.put("readings", bb.array());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerPowerMinute fromDaoEntity(DaoEntity _d) {
|
||||||
|
BreakerPowerMinute o = new BreakerPowerMinute();
|
||||||
|
o.setPanel(DaoSerializer.getInteger(_d, "panel"));
|
||||||
|
o.setSpace(DaoSerializer.getInteger(_d, "space"));
|
||||||
|
byte[] data = DaoSerializer.getByteArray(_d, "readings");
|
||||||
|
List<Float> readings = new ArrayList<>();
|
||||||
|
o.setReadings(readings);
|
||||||
|
if (CollectionUtils.length(data) > 0) {
|
||||||
|
ByteBuffer bb = ByteBuffer.wrap(data);
|
||||||
|
while (bb.hasRemaining()) {
|
||||||
|
readings.add(bb.getFloat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||||
|
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 BreakerPowerSerializer extends AbstractDaoSerializer<BreakerPower>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<BreakerPower> getSupportedClass()
|
||||||
|
{
|
||||||
|
return BreakerPower.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(BreakerPower _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("_id", _o.getId());
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
d.put("panel", _o.getPanel());
|
||||||
|
d.put("space", _o.getSpace());
|
||||||
|
d.put("key", _o.getKey());
|
||||||
|
d.put("read_time", DaoSerializer.toLong(_o.getReadTime()));
|
||||||
|
d.put("hub_version", _o.getHubVersion());
|
||||||
|
d.put("power", _o.getPower());
|
||||||
|
d.put("voltage", _o.getVoltage());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BreakerPower fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
BreakerPower o = new BreakerPower();
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setPanel(DaoSerializer.getInteger(_d, "panel"));
|
||||||
|
o.setSpace(DaoSerializer.getInteger(_d, "space"));
|
||||||
|
o.setReadTime(DaoSerializer.getDate(_d, "read_time"));
|
||||||
|
o.setHubVersion(DaoSerializer.getString(_d, "hub_version"));
|
||||||
|
o.setPower(DaoSerializer.getDouble(_d, "power"));
|
||||||
|
o.setVoltage(DaoSerializer.getDouble(_d, "voltage"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPolarity;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerType;
|
||||||
|
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 BreakerSerializer extends AbstractDaoSerializer<Breaker>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<Breaker> getSupportedClass()
|
||||||
|
{
|
||||||
|
return Breaker.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(Breaker _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("panel", _o.getPanel());
|
||||||
|
d.put("space", _o.getSpace());
|
||||||
|
d.put("meter", _o.getMeter());
|
||||||
|
d.put("hub", _o.getHub());
|
||||||
|
d.put("port", _o.getPort());
|
||||||
|
d.put("name", _o.getName());
|
||||||
|
d.put("description", _o.getDescription());
|
||||||
|
d.put("size_amps", _o.getSizeAmps());
|
||||||
|
d.put("calibration_factor", _o.getCalibrationFactor());
|
||||||
|
d.put("low_pass_filter", _o.getLowPassFilter());
|
||||||
|
d.put("polarity", DaoSerializer.toEnumName(_o.getPolarity()));
|
||||||
|
d.put("type", DaoSerializer.toEnumName(_o.getType()));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Breaker fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
Breaker o = new Breaker();
|
||||||
|
o.setPanel(DaoSerializer.getInteger(_d, "panel"));
|
||||||
|
o.setSpace(DaoSerializer.getInteger(_d, "space"));
|
||||||
|
o.setMeter(DaoSerializer.getInteger(_d, "meter"));
|
||||||
|
o.setHub(DaoSerializer.getInteger(_d, "hub"));
|
||||||
|
o.setPort(DaoSerializer.getInteger(_d, "port"));
|
||||||
|
o.setName(DaoSerializer.getString(_d, "name"));
|
||||||
|
o.setDescription(DaoSerializer.getString(_d, "description"));
|
||||||
|
o.setSizeAmps(DaoSerializer.getInteger(_d, "size_amps"));
|
||||||
|
o.setCalibrationFactor(DaoSerializer.getDouble(_d, "calibration_factor"));
|
||||||
|
o.setLowPassFilter(DaoSerializer.getDouble(_d, "low_pass_filter"));
|
||||||
|
o.setPolarity(DaoSerializer.getEnum(_d, "polarity", BreakerPolarity.class));
|
||||||
|
o.setType(DaoSerializer.getEnum(_d, "type", BreakerType.class));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlock;
|
||||||
|
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 EnergyBlockSerializer extends AbstractDaoSerializer<EnergyBlock>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<EnergyBlock> getSupportedClass()
|
||||||
|
{
|
||||||
|
return EnergyBlock.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(EnergyBlock _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("start", DaoSerializer.toLong(_o.getStart()));
|
||||||
|
d.put("end", DaoSerializer.toLong(_o.getEnd()));
|
||||||
|
d.put("joules", _o.getJoules());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnergyBlock fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
EnergyBlock o = new EnergyBlock();
|
||||||
|
o.setStart(DaoSerializer.getDate(_d, "start"));
|
||||||
|
o.setEnd(DaoSerializer.getDate(_d, "end"));
|
||||||
|
o.setJoules(DaoSerializer.getDouble(_d, "joules"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPowerMinute;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||||
|
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 HubPowerMinuteSerializer extends AbstractDaoSerializer<HubPowerMinute>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<HubPowerMinute> getSupportedClass()
|
||||||
|
{
|
||||||
|
return HubPowerMinute.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(HubPowerMinute _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
d.put("hub", _o.getHub());
|
||||||
|
d.put("minute", _o.getMinute());
|
||||||
|
d.put("breakers", DaoSerializer.toDaoEntities(_o.getBreakers(), DaoProxyType.MONGO));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HubPowerMinute fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
HubPowerMinute o = new HubPowerMinute();
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setHub(DaoSerializer.getInteger(_d, "hub"));
|
||||||
|
o.setMinute(DaoSerializer.getInteger(_d, "minute"));
|
||||||
|
o.setBreakers(DaoSerializer.getList(_d, "breakers", BreakerPowerMinute.class));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Meter;
|
||||||
|
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 MeterSerializer extends AbstractDaoSerializer<Meter>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<Meter> getSupportedClass()
|
||||||
|
{
|
||||||
|
return Meter.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(Meter _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("account_id", _o.getAccountId());
|
||||||
|
d.put("index", _o.getIndex());
|
||||||
|
d.put("name", _o.getName());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Meter fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
Meter o = new Meter();
|
||||||
|
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
|
||||||
|
o.setIndex(DaoSerializer.getInteger(_d, "index"));
|
||||||
|
o.setName(DaoSerializer.getString(_d, "name"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Sequence;
|
||||||
|
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 SequenceSerializer extends AbstractDaoSerializer<Sequence>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<Sequence> getSupportedClass()
|
||||||
|
{
|
||||||
|
return Sequence.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(Sequence _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
if (_o.getId() != null)
|
||||||
|
d.put("_id", _o.getId());
|
||||||
|
d.put("sequence", _o.getSequence());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Sequence fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
Sequence o = new Sequence();
|
||||||
|
o.setId(DaoSerializer.getString(_d, "_id"));
|
||||||
|
o.setSequence(DaoSerializer.getInteger(_d, "sequence"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.lanternsoftware.datamodel.currentmonitor.dao;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.SignupResponse;
|
||||||
|
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 SignupResponseSerializer extends AbstractDaoSerializer<SignupResponse>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Class<SignupResponse> getSupportedClass()
|
||||||
|
{
|
||||||
|
return SignupResponse.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DaoProxyType> getSupportedProxies() {
|
||||||
|
return Collections.singletonList(DaoProxyType.MONGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DaoEntity toDaoEntity(SignupResponse _o)
|
||||||
|
{
|
||||||
|
DaoEntity d = new DaoEntity();
|
||||||
|
d.put("error", _o.getError());
|
||||||
|
d.put("auth_code", _o.getAuthCode());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignupResponse fromDaoEntity(DaoEntity _d)
|
||||||
|
{
|
||||||
|
SignupResponse o = new SignupResponse();
|
||||||
|
o.setError(DaoSerializer.getString(_d, "error"));
|
||||||
|
o.setAuthCode(DaoSerializer.getString(_d, "auth_code"));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.AccountSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.AuthCodeSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerConfigSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerGroupEnergySerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerGroupSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerGroupSummarySerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerHubSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerPanelSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerPowerMinuteSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerPowerSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.EnergyBlockSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.HubPowerMinuteSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.MeterSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.SequenceSerializer
|
||||||
|
com.lanternsoftware.datamodel.currentmonitor.dao.SignupResponseSerializer
|
89
currentmonitor/lantern-service-currentmonitor/pom.xml
Normal file
89
currentmonitor/lantern-service-currentmonitor/pom.xml
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
<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>
|
||||||
|
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||||
|
<artifactId>lantern-service-currentmonitor</artifactId>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>lantern-service-currentmonitor</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||||
|
<artifactId>lantern-dataaccess-currentmonitor</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lanternsoftware.util</groupId>
|
||||||
|
<artifactId>lantern-util-servlet</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.api-client</groupId>
|
||||||
|
<artifactId>google-api-client</artifactId>
|
||||||
|
<version>1.30.4</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax</groupId>
|
||||||
|
<artifactId>javaee-api</artifactId>
|
||||||
|
<version>8.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.7.29</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.2.3</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>compile</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<optimize>true</optimize>
|
||||||
|
<showDeprecation>true</showDeprecation>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addClasspath>true</addClasspath>
|
||||||
|
<classpathPrefix>lib/</classpathPrefix>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.context;
|
||||||
|
|
||||||
|
import com.lanternsoftware.dataaccess.currentmonitor.CurrentMonitorDao;
|
||||||
|
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
public class Globals implements ServletContextListener {
|
||||||
|
public static CurrentMonitorDao dao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent sce) {
|
||||||
|
dao.shutdown();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
|
||||||
|
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
|
||||||
|
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||||
|
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||||
|
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import com.lanternsoftware.util.servlet.BasicAuth;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@WebServlet("/auth/*")
|
||||||
|
public class AuthServlet extends CMServlet {
|
||||||
|
private static final NetHttpTransport transport = new NetHttpTransport();
|
||||||
|
private static final JacksonFactory jsonFactory = new JacksonFactory();
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AuthServlet.class);
|
||||||
|
private static final String googleSsoKey = ResourceLoader.loadFileAsString(LanternFiles.OPS_PATH + "google_sso_key.txt");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
String authCode = _req.getHeader("auth_code");
|
||||||
|
if (NullUtils.isEmpty(authCode)) {
|
||||||
|
BasicAuth auth = new BasicAuth(_req);
|
||||||
|
if (NullUtils.isEqual(auth.getUsername(), "googlesso")) {
|
||||||
|
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory).setAudience(Collections.singletonList(googleSsoKey)).build();
|
||||||
|
try {
|
||||||
|
GoogleIdToken idToken = verifier.verify(auth.getPassword());
|
||||||
|
if (idToken != null) {
|
||||||
|
GoogleIdToken.Payload payload = idToken.getPayload();
|
||||||
|
String email = payload.getEmail();
|
||||||
|
authCode = Globals.dao.getAuthCodeForEmail(email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception _e) {
|
||||||
|
logger.error("Failed to validate google auth token", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
authCode = Globals.dao.authenticateAccount(auth.getUsername(), auth.getPassword());
|
||||||
|
}
|
||||||
|
DaoEntity rep = new DaoEntity("auth_code", authCode);
|
||||||
|
if (isPath(_req, 0, "bin"))
|
||||||
|
zipBsonResponse(_rep, rep);
|
||||||
|
else
|
||||||
|
jsonResponse(_rep, rep);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public abstract class CMServlet extends HttpServlet {
|
||||||
|
public static void setResponseHtml(HttpServletResponse _response, String _sHtml) {
|
||||||
|
setResponseEntity(_response, MediaType.TEXT_HTML, _sHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setResponseEntity(HttpServletResponse _response, String _sContentType, String _sEntity) {
|
||||||
|
setResponseEntity(_response, 200, _sContentType, _sEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setResponseEntity(HttpServletResponse _response, String _sContentType, byte[] _btData) {
|
||||||
|
setResponseEntity(_response, 200, _sContentType, _btData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setResponseEntity(HttpServletResponse _response, int _iStatus, String _sContentType, String _sEntity) {
|
||||||
|
setResponseEntity(_response, _iStatus, _sContentType, NullUtils.toByteArray(_sEntity));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setResponseEntity(HttpServletResponse _response, int _iStatus, String _sContentType, byte[] _btData) {
|
||||||
|
OutputStream os = null;
|
||||||
|
try {
|
||||||
|
_response.setStatus(_iStatus);
|
||||||
|
_response.setCharacterEncoding("UTF-8");
|
||||||
|
_response.setContentType(_sContentType);
|
||||||
|
if ((_btData != null) && (_btData.length > 0)) {
|
||||||
|
_response.setContentLength(_btData.length);
|
||||||
|
os = _response.getOutputStream();
|
||||||
|
os.write(_btData);
|
||||||
|
} else
|
||||||
|
_response.setContentLength(0);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void zipBsonResponse(HttpServletResponse _response, Object _object)
|
||||||
|
{
|
||||||
|
setResponseEntity(_response, 200, MediaType.APPLICATION_OCTET_STREAM, DaoSerializer.toZipBson(_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void jsonResponse(HttpServletResponse _response, Object _object)
|
||||||
|
{
|
||||||
|
setResponseEntity(_response, 200, MediaType.APPLICATION_JSON, DaoSerializer.toJson(_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void jsonResponse(HttpServletResponse _response, String _json)
|
||||||
|
{
|
||||||
|
setResponseEntity(_response, 200, MediaType.APPLICATION_JSON, _json);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getRequestPayloadAsString(HttpServletRequest _req) {
|
||||||
|
return NullUtils.toString(getRequestPayload(_req));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] getRequestPayload(HttpServletRequest _req) {
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = _req.getInputStream();
|
||||||
|
return IOUtils.toByteArray(is);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
IOUtils.closeQuietly(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DaoEntity getRequestZipBson(HttpServletRequest _req) {
|
||||||
|
return DaoSerializer.fromZipBson(getRequestPayload(_req));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> T getRequestPayload(HttpServletRequest _req, Class<T> _retClass) {
|
||||||
|
return DaoSerializer.fromZipBson(getRequestPayload(_req), _retClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String[] path(HttpServletRequest _req) {
|
||||||
|
return NullUtils.cleanSplit(NullUtils.makeNotNull(_req.getPathInfo()), "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isPath(HttpServletRequest _req, int _index, String _path) {
|
||||||
|
return NullUtils.isEqual(_path, CollectionUtils.get(path(_req), _index));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@WebServlet("/command")
|
||||||
|
public class CommandServlet extends SecureServlet {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
File folder = new File(LanternFiles.OPS_PATH + _authCode.getAccountId());
|
||||||
|
List<String> commands = new ArrayList<>();
|
||||||
|
if (folder.exists() && folder.isDirectory()) {
|
||||||
|
for (File command : CollectionUtils.asArrayList(folder.listFiles())) {
|
||||||
|
if (command.isDirectory())
|
||||||
|
continue;
|
||||||
|
String c = command.getName();
|
||||||
|
String extension = NullUtils.after(c, ".");
|
||||||
|
if (NullUtils.isNotEmpty(extension))
|
||||||
|
c = c.replace("." + extension, "");
|
||||||
|
commands.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zipBsonResponse(_rep, new DaoEntity("commands", commands));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
DaoEntity payload = getRequestZipBson(_req);
|
||||||
|
if (payload == null)
|
||||||
|
return;
|
||||||
|
String command = DaoSerializer.getString(payload, "command");
|
||||||
|
String path = LanternFiles.OPS_PATH + _authCode.getAccountId() + File.separator + "payload" + File.separator;
|
||||||
|
new File(path).mkdirs();
|
||||||
|
ResourceLoader.writeFile(path+ command + ".txt", DaoSerializer.getString(payload, "payload"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@WebServlet("/config/*")
|
||||||
|
public class ConfigServlet extends SecureServlet {
|
||||||
|
@Override
|
||||||
|
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
if (isPath(_req, 0, "bin"))
|
||||||
|
zipBsonResponse(_rep, Globals.dao.getMergedConfig(_authCode));
|
||||||
|
else
|
||||||
|
jsonResponse(_rep, Globals.dao.getMergedConfig(_authCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
BreakerConfig config = getRequestPayload(_req, BreakerConfig.class);
|
||||||
|
if (config == null) {
|
||||||
|
_rep.setStatus(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (config.getAccountId() != _authCode.getAccountId()) {
|
||||||
|
_rep.setStatus(401);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Globals.dao.putConfig(config);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@WebServlet("/energy/group/*")
|
||||||
|
public class GroupEnergyServlet extends SecureServlet {
|
||||||
|
@Override
|
||||||
|
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
String[] path = path(_req);
|
||||||
|
if (path.length < 3) {
|
||||||
|
_rep.setStatus(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EnergyBlockViewMode viewMode = NullUtils.toEnum(EnergyBlockViewMode.class, path[1], EnergyBlockViewMode.DAY);
|
||||||
|
Date start = new Date(NullUtils.toLong(path[2]));
|
||||||
|
List<BreakerGroupEnergy> energies = CollectionUtils.transform(_authCode.getAllAccountIds(), _id->Globals.dao.getBreakerGroupEnergy(_id, path[0], viewMode, start), true);
|
||||||
|
if (CollectionUtils.isNotEmpty(energies)) {
|
||||||
|
BreakerGroupEnergy energy;
|
||||||
|
if (energies.size() > 1) {
|
||||||
|
energy = new BreakerGroupEnergy();
|
||||||
|
energy.setAccountId(_authCode.getAccountId());
|
||||||
|
energy.setGroupId("Sites");
|
||||||
|
energy.setGroupName("Sites");
|
||||||
|
energy.setStart(start);
|
||||||
|
energy.setViewMode(viewMode);
|
||||||
|
energy.setSubGroups(CollectionUtils.asArrayList(energies));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
energy = CollectionUtils.getFirst(energies);
|
||||||
|
if (NullUtils.isEqual(CollectionUtils.get(path, 3), "bin"))
|
||||||
|
zipBsonResponse(_rep, energy);
|
||||||
|
else
|
||||||
|
jsonResponse(_rep, energy);
|
||||||
|
} else
|
||||||
|
_rep.setStatus(404);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@WebServlet("/power/group/*")
|
||||||
|
public class GroupPowerServlet extends SecureServlet {
|
||||||
|
@Override
|
||||||
|
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
String[] path = path(_req);
|
||||||
|
if (path.length < 1)
|
||||||
|
zipBsonResponse(_rep, new DaoEntity("breakers", DaoSerializer.toDaoEntities(Globals.dao.getBreakerPowerForAccount(_authCode.getAccountId()))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@WebServlet("/power/*")
|
||||||
|
public class PowerServlet extends SecureServlet {
|
||||||
|
@Override
|
||||||
|
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
String[] path = path(_req);
|
||||||
|
if (path.length < 2) {
|
||||||
|
_rep.setStatus(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int hub = DaoSerializer.toInteger(CollectionUtils.get(path, 0));
|
||||||
|
int port = DaoSerializer.toInteger(CollectionUtils.get(path, 1));
|
||||||
|
jsonResponse(_rep, Globals.dao.getLatestBreakerPower(_authCode.getAccountId(), hub, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
String[] path = path(_req);
|
||||||
|
if ((path.length > 0) && NullUtils.isEqual(CollectionUtils.get(path, 0), "hub")) {
|
||||||
|
Globals.dao.putHubPowerMinute(getRequestPayload(_req, HubPowerMinute.class));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((path.length > 0) && NullUtils.isEqual(CollectionUtils.get(path, 0), "batch")) {
|
||||||
|
List<BreakerPower> powers = DaoSerializer.getList(getRequestZipBson(_req), "readings", BreakerPower.class);
|
||||||
|
if (!powers.isEmpty()) {
|
||||||
|
CollectionUtils.edit(powers, _p->_p.setAccountId(_authCode.getAccountId()));
|
||||||
|
Globals.dao.getProxy().save(powers);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BreakerPower power = getRequestPayload(_req, BreakerPower.class);
|
||||||
|
power.setAccountId(_authCode.getAccountId());
|
||||||
|
Globals.dao.putBreakerPower(power);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
public abstract class SecureServlet extends CMServlet {
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
AuthCode authCode = Globals.dao.decryptAuthCode(_req.getHeader("auth_code"));
|
||||||
|
if (authCode == null) {
|
||||||
|
_rep.setStatus(401);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
get(authCode, _req, _rep);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
AuthCode authCode = Globals.dao.decryptAuthCode(_req.getHeader("auth_code"));
|
||||||
|
if (authCode == null) {
|
||||||
|
_rep.setStatus(401);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
post(authCode, _req, _rep);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.SignupResponse;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.dao.DaoEntity;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import com.lanternsoftware.util.email.EmailValidator;
|
||||||
|
import com.lanternsoftware.util.servlet.BasicAuth;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@WebServlet("/signup")
|
||||||
|
public class SignupServlet extends CMServlet {
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
BasicAuth auth = new BasicAuth(_req);
|
||||||
|
Account acct = Globals.dao.getAccountByUsername(auth.getUsername());
|
||||||
|
if (acct != null) {
|
||||||
|
jsonResponse(_rep, SignupResponse.error("An account for " + auth.getUsername() + " already exists"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!EmailValidator.getInstance().isValid(auth.getUsername())) {
|
||||||
|
jsonResponse(_rep, SignupResponse.error(auth.getUsername() + " is not a valid email address"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (NullUtils.length(auth.getPassword()) < 8) {
|
||||||
|
jsonResponse(_rep, SignupResponse.error("Your password must be at least 8 characters long"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (NullUtils.isEqual("password", auth.getPassword())) {
|
||||||
|
jsonResponse(_rep, SignupResponse.error("Seriously? \"password\"? Come on."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
acct = new Account();
|
||||||
|
acct.setUsername(auth.getUsername());
|
||||||
|
acct.setPassword(auth.getPassword());
|
||||||
|
Globals.dao.putAccount(acct);
|
||||||
|
String authCode = Globals.dao.authenticateAccount(auth.getUsername(), auth.getPassword());
|
||||||
|
jsonResponse(_rep, SignupResponse.success(authCode));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.lanternsoftware.currentmonitor.servlet;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
@WebServlet("/update/*")
|
||||||
|
public class UpdateServlet extends CMServlet {
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
|
||||||
|
if (isPath(_req, 0, "version"))
|
||||||
|
setResponseEntity(_rep, MediaType.APPLICATION_OCTET_STREAM, DaoSerializer.toZipBson(DaoSerializer.parse(ResourceLoader.loadFileAsString(LanternFiles.OPS_PATH + "release" + File.separator + "version.json"))));
|
||||||
|
else
|
||||||
|
setResponseEntity(_rep, MediaType.APPLICATION_OCTET_STREAM, ResourceLoader.loadFile(LanternFiles.OPS_PATH + "release" + File.separator + "lantern-currentmonitor.jar"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<property name="log.pattern" value="%date %-5level %logger{0} - %message%n"/>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log.pattern}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
|
||||||
|
<logger name="com.lanternsoftware" level="DEBUG"/>
|
||||||
|
|
||||||
|
<root level="OFF">
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE web-app PUBLIC
|
||||||
|
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||||
|
"http://java.sun.com/dtd/web-app_2_3.dtd" >
|
||||||
|
|
||||||
|
<web-app>
|
||||||
|
<listener>
|
||||||
|
<listener-class>com.lanternsoftware.currentmonitor.context.Globals</listener-class>
|
||||||
|
</listener>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.dataaccess.currentmonitor.CurrentMonitorDao;
|
||||||
|
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Account;
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class CreateAccount {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CurrentMonitorDao dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
|
||||||
|
Account account = new Account();
|
||||||
|
account.setId(1);
|
||||||
|
account.setPassword("*redacted*");
|
||||||
|
|
||||||
|
account.setId(2);
|
||||||
|
account.setUsername("admin@lanternsoftware.com");
|
||||||
|
account.setPassword("*redacted*");
|
||||||
|
|
||||||
|
dao.putAccount(account);
|
||||||
|
dao.shutdown();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.cryptography.AESTool;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
|
||||||
|
public class CreateAuthCode {
|
||||||
|
private static final AESTool aes = new AESTool(ResourceLoader.loadFile(LanternFiles.OPS_PATH + "authKey.dat"));
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(aes.encryptToBase64(DaoSerializer.toZipBson(new AuthCode(100, null))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.cryptography.AESTool;
|
||||||
|
|
||||||
|
public class CreateAuthKey {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ResourceLoader.writeFile(LanternFiles.OPS_PATH + "authKey.dat", AESTool.generateRandomSecretKey().getEncoded());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,241 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.dataaccess.currentmonitor.CurrentMonitorDao;
|
||||||
|
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerHub;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPanel;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.BreakerPolarity;
|
||||||
|
import com.lanternsoftware.datamodel.currentmonitor.Meter;
|
||||||
|
import com.lanternsoftware.util.CollectionUtils;
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.NullUtils;
|
||||||
|
import com.lanternsoftware.util.ResourceLoader;
|
||||||
|
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||||
|
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CreateBreakers {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CurrentMonitorDao dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
|
||||||
|
|
||||||
|
/* Breaker bf1 = new Breaker("Solar A", 2, 20, 0, 1, 50, 1.6);
|
||||||
|
bf1.setPolarity(BreakerPolarity.SOLAR);
|
||||||
|
Breaker bf2 = new Breaker("Solar B", 2, 18, 0, 2, 50, 1.6);
|
||||||
|
bf2.setPolarity(BreakerPolarity.SOLAR);
|
||||||
|
Breaker bf3 = new Breaker("Septic Agitator", 2, 11, 0, 3, 20, 1.6);
|
||||||
|
Breaker bf4 = new Breaker("Garage/Guest Baths", 2, 5, 0, 4, 20, 1.6);
|
||||||
|
Breaker bf5 = new Breaker("Office", 2, 2, 0, 5, 20, 1.6);
|
||||||
|
Breaker bf6 = new Breaker("Upstairs Furnace R-A", 1, 2, 0, 6, 50, 1.6);
|
||||||
|
Breaker bf7 = new Breaker("Upstairs Furnace R-B", 1, 4, 0, 7, 50, 1.6);
|
||||||
|
Breaker bf8 = new Breaker("Upstairs Furnace R-C", 1, 6, 0, 8, 30, 1.6);
|
||||||
|
Breaker bf9 = new Breaker("Upstairs Furnace R-D", 1, 8, 0, 9, 30, 1.6);
|
||||||
|
Breaker bf10 = new Breaker("Upstairs Furnace HP-A", 1, 1, 0, 10, 30, 1.6);
|
||||||
|
Breaker bf11 = new Breaker("Upstairs Furnace HP-B", 1, 3, 0, 11, 30, 1.6);
|
||||||
|
Breaker bf12 = new Breaker("Dryer A", 2, 8, 0, 12, 30, 1.6);
|
||||||
|
Breaker bf13 = new Breaker("Dryer B", 2, 10, 0, 13, 30, 1.6);
|
||||||
|
Breaker bf2_1 = new Breaker("Main Furnace R-A", 0, 6, 1, 1, 50, 1.6);
|
||||||
|
Breaker bf2_2 = new Breaker("Main Furnace R-B", 0, 8, 1, 2, 50, 1.6);
|
||||||
|
Breaker bf2_3 = new Breaker("Main Furnace R-C", 0, 2, 1, 3, 50, 1.6);
|
||||||
|
Breaker bf2_4 = new Breaker("Main Furnace R-D", 0, 4, 1, 4, 50, 1.6);
|
||||||
|
Breaker bf2_5 = new Breaker("Main Furnace HP-A", 0, 1, 1, 5, 30, 1.6);
|
||||||
|
Breaker bf2_6 = new Breaker("Main Furnace HP-B", 0, 3, 1, 6, 30, 1.6);
|
||||||
|
Breaker bf2_7 = new Breaker("Hot Water Heater A", 0, 5, 1, 7, 30, 1.6);
|
||||||
|
Breaker bf2_8 = new Breaker("Hot Water Heater B", 0, 7, 1, 8, 30, 1.6);
|
||||||
|
Breaker bf2_9 = new Breaker("Basement HP-A", 1, 13, 1, 9, 30, 1.6);
|
||||||
|
Breaker bf2_10 = new Breaker("Basement HP-B", 1, 15, 1, 10, 30, 1.6);
|
||||||
|
Breaker bf2_11 = new Breaker("Oven A", 2, 12, 1, 11, 50, 1.6);
|
||||||
|
Breaker bf2_12 = new Breaker("Oven B", 2, 14, 1, 12, 50, 1.6);
|
||||||
|
Breaker bf2_13 = new Breaker("Master Bathroom", 3, 9, 2, 5, 20, 1.6);
|
||||||
|
Breaker bf2_14 = new Breaker("Refrigerator", 2, 6, 1, 14, 20, 1.6);
|
||||||
|
bf2_14.setSpaceTandemB(6);
|
||||||
|
Breaker bf2_15 = new Breaker("Master Bedroom", 2, 1, 1, 15, 20, 1.6);
|
||||||
|
BreakerGroup basementHP = new BreakerGroup("6", "Heat Pump", Arrays.asList(bf2_9, bf2_10));
|
||||||
|
BreakerGroup basementCC = new BreakerGroup("3", "Basement", Arrays.asList(basementHP), null);
|
||||||
|
BreakerGroup mainHP = new BreakerGroup("5", "Heat Pump", Arrays.asList(bf2_5, bf2_6));
|
||||||
|
BreakerGroup mainR = new BreakerGroup("4", "Air Handler/Resistive", Arrays.asList(bf2_1, bf2_2, bf2_3, bf2_4));
|
||||||
|
BreakerGroup mainCC = new BreakerGroup("2", "Main Floor", Arrays.asList(mainHP, mainR), null);
|
||||||
|
BreakerGroup upstairsHP = new BreakerGroup("34", "Heat Pump", Arrays.asList(bf10, bf11));
|
||||||
|
BreakerGroup upstairsR = new BreakerGroup("35", "Air Handler/Resistive", Arrays.asList(bf6, bf7, bf8, bf9));
|
||||||
|
BreakerGroup upstairsCC = new BreakerGroup("36", "Upstairs", Arrays.asList(upstairsHP, upstairsR), null);
|
||||||
|
BreakerGroup cc = new BreakerGroup("1", "Climate Control", Arrays.asList(mainCC, upstairsCC, basementCC), null);
|
||||||
|
BreakerGroup hotWater = new BreakerGroup("7", "Hot Water Heater", Arrays.asList(bf2_7, bf2_8));
|
||||||
|
BreakerGroup oven = new BreakerGroup("8", "Oven/Cooktop", Arrays.asList(bf2_11, bf2_12));
|
||||||
|
BreakerGroup masterBR = new BreakerGroup("9", "Master Bedroom", Arrays.asList(bf2_13, bf2_15));
|
||||||
|
BreakerGroup fridge = new BreakerGroup("10", "Refrigerator", Arrays.asList(bf2_14));
|
||||||
|
BreakerGroup solar = new BreakerGroup("11", "Solar", Arrays.asList(bf1, bf2));
|
||||||
|
BreakerGroup septic = new BreakerGroup("13", "Septic Aerator", Arrays.asList(bf3));
|
||||||
|
BreakerGroup garage = new BreakerGroup("14", "Garage/Guest Baths", Arrays.asList(bf4));
|
||||||
|
BreakerGroup office = new BreakerGroup("15", "Office", Arrays.asList(bf5));
|
||||||
|
BreakerGroup dryer = new BreakerGroup("37", "Dryer", Arrays.asList(bf12, bf13));
|
||||||
|
Breaker bf3_1 = new Breaker("Hub 2 Port 1", 3, 1, 2, 1, 20, 1.6);
|
||||||
|
Breaker bf3_2 = new Breaker("Hub 2 Port 2", 3, 3, 2, 2, 20, 1.6);
|
||||||
|
Breaker bf3_3 = new Breaker("Hub 2 Port 3", 3, 5, 2, 3, 20, 1.6);
|
||||||
|
Breaker bf3_4 = new Breaker("Hub 2 Port 4", 3, 7, 2, 4, 20, 1.6);
|
||||||
|
Breaker bf3_6 = new Breaker("Hub 2 Port 6", 3, 11, 2, 6, 20, 1.6);
|
||||||
|
Breaker bf3_7 = new Breaker("Hub 2 Port 7", 3, 13, 2, 7, 20, 1.6);
|
||||||
|
Breaker bf3_8 = new Breaker("Hub 2 Port 8", 3, 15, 2, 8, 20, 1.6);
|
||||||
|
Breaker bf3_9 = new Breaker("Hub 2 Port 9", 3, 2, 2, 9, 20, 1.6);
|
||||||
|
Breaker bf3_10 = new Breaker("Hub 2 Port 10", 3, 4, 2, 10, 20, 1.6);
|
||||||
|
Breaker bf3_12 = new Breaker("Hub 2 Port 12", 3, 6, 2, 12, 20, 1.6);
|
||||||
|
Breaker bf3_13 = new Breaker("Hub 2 Port 13", 3, 8, 2, 13, 20, 1.6);
|
||||||
|
Breaker bf3_14 = new Breaker("Hub 2 Port 14", 3, 10, 2, 14, 20, 1.6);
|
||||||
|
BreakerGroup g1 = new BreakerGroup("17", "Living Room/Printer/Outdoor Lights", Arrays.asList(bf3_1));
|
||||||
|
BreakerGroup g2 = new BreakerGroup("18", "Dishwasher/Disposal/Sink Lights", Arrays.asList(bf3_2));
|
||||||
|
BreakerGroup g3 = new BreakerGroup("19", "Microwave", Arrays.asList(bf3_3));
|
||||||
|
BreakerGroup g4 = new BreakerGroup("20", "Kitchen Outlets", Arrays.asList(bf3_4));
|
||||||
|
// BreakerGroup g5 = new BreakerGroup("21", "Hub 2 Port 5", Arrays.asList(bf3_5));
|
||||||
|
BreakerGroup g6 = new BreakerGroup("22", "Mini Fridge", Arrays.asList(bf3_6));
|
||||||
|
BreakerGroup g7 = new BreakerGroup("23", "Basement Lights/Outlets", Arrays.asList(bf3_7));
|
||||||
|
BreakerGroup g8 = new BreakerGroup("24", "Theatre", Arrays.asList(bf3_8));
|
||||||
|
BreakerGroup g9 = new BreakerGroup("25", "Sunroom Fan/Outside Floods", Arrays.asList(bf3_9));
|
||||||
|
BreakerGroup g10 = new BreakerGroup("26", "Radon/Deep Freezer", Arrays.asList(bf3_10));
|
||||||
|
// BreakerGroup g11 = new BreakerGroup("27", "Hub 2 Port 11", Arrays.asList(bf3_11));
|
||||||
|
BreakerGroup g12 = new BreakerGroup("28", "Kitchen Lights", Arrays.asList(bf3_12));
|
||||||
|
BreakerGroup g13 = new BreakerGroup("29", "Router/Networking", Arrays.asList(bf3_13));
|
||||||
|
BreakerGroup g14 = new BreakerGroup("30", "Half Bath/Utility/Garage Lights", Arrays.asList(bf3_14));
|
||||||
|
// BreakerGroup g15 = new BreakerGroup("31", "Bar Outlets", Arrays.asList(bf3_15));
|
||||||
|
BreakerGroup kitchen = new BreakerGroup("33", "Kitchen", Arrays.asList(oven, fridge, g2, g3, g4, g12), null);
|
||||||
|
|
||||||
|
Breaker b4_1 = new Breaker("Hub 3 Port 1", 4, 1, 3, 1, 20, 1.6);
|
||||||
|
Breaker b4_2 = new Breaker("Hub 3 Port 2", 4, 2, 3, 2, 30, 1.6);
|
||||||
|
Breaker b4_3 = new Breaker("Hub 3 Port 3", 4, 3, 3, 3, 50, 1.6);
|
||||||
|
Breaker b4_4 = new Breaker("Hub 3 Port 4", 4, 4, 3, 4, 20, 1.6);
|
||||||
|
Breaker b4_5 = new Breaker("Hub 3 Port 5", 4, 5, 3, 5, 20, 1.6);
|
||||||
|
Breaker b4_6 = new Breaker("Hub 3 Port 6", 4, 6, 3, 6, 20, 1.6);
|
||||||
|
Breaker b4_7 = new Breaker("Hub 3 Port 7", 4, 7, 3, 7, 20, 1.6);
|
||||||
|
Breaker b4_8 = new Breaker("Hub 3 Port 8", 4, 8, 3, 8, 20, 1.6);
|
||||||
|
Breaker b4_9 = new Breaker("Hub 3 Port 9", 4, 9, 3, 9, 20, 1.6);
|
||||||
|
Breaker b4_10 = new Breaker("Hub 3 Port 10", 4, 10, 3, 10, 20, 1.6);
|
||||||
|
Breaker b4_11 = new Breaker("Hub 3 Port 11", 4, 11, 3, 11, 20, 1.6);
|
||||||
|
Breaker b4_12 = new Breaker("Hub 3 Port 12", 4, 12, 3, 12, 20, 1.6);
|
||||||
|
Breaker b4_13 = new Breaker("Hub 3 Port 13", 4, 13, 3, 13, 20, 1.6);
|
||||||
|
Breaker b4_14 = new Breaker("Hub 3 Port 14", 4, 14, 3, 14, 20, 1.6);
|
||||||
|
Breaker b4_15 = new Breaker("Hub 3 Port 15", 4, 15, 3, 15, 20, 1.6);
|
||||||
|
BreakerGroup g4_1 = new BreakerGroup("41", "Hub 3 Port 1", Arrays.asList(b4_1));
|
||||||
|
BreakerGroup g4_2 = new BreakerGroup("42", "Hub 3 Port 2", Arrays.asList(b4_2));
|
||||||
|
BreakerGroup g4_3 = new BreakerGroup("43", "Hub 3 Port 3", Arrays.asList(b4_3));
|
||||||
|
BreakerGroup g4_4 = new BreakerGroup("44", "Hub 3 Port 4", Arrays.asList(b4_4));
|
||||||
|
BreakerGroup g4_5 = new BreakerGroup("45", "Hub 3 Port 5", Arrays.asList(b4_5));
|
||||||
|
BreakerGroup g4_6 = new BreakerGroup("46", "Hub 3 Port 6", Arrays.asList(b4_6));
|
||||||
|
BreakerGroup g4_7 = new BreakerGroup("47", "Hub 3 Port 7", Arrays.asList(b4_7));
|
||||||
|
BreakerGroup g4_8 = new BreakerGroup("48", "Hub 3 Port 8", Arrays.asList(b4_8));
|
||||||
|
BreakerGroup g4_9 = new BreakerGroup("49", "Hub 3 Port 9", Arrays.asList(b4_9));
|
||||||
|
BreakerGroup g4_10 = new BreakerGroup("50", "Hub 3 Port 10", Arrays.asList(b4_10));
|
||||||
|
BreakerGroup g4_11 = new BreakerGroup("51", "Hub 3 Port 11", Arrays.asList(b4_11));
|
||||||
|
BreakerGroup g4_12 = new BreakerGroup("52", "Hub 3 Port 12", Arrays.asList(b4_12));
|
||||||
|
BreakerGroup g4_13 = new BreakerGroup("53", "Hub 3 Port 13", Arrays.asList(b4_13));
|
||||||
|
BreakerGroup g4_14 = new BreakerGroup("54", "Hub 3 Port 14", Arrays.asList(b4_14));
|
||||||
|
BreakerGroup g4_15 = new BreakerGroup("55", "Hub 3 Port 15", Arrays.asList(b4_15));
|
||||||
|
BreakerGroup debug = new BreakerGroup("40", "Debug Hub 3", Arrays.asList(g4_1, g4_2, g4_3), null);
|
||||||
|
// BreakerGroup debug = new BreakerGroup("40", "Debug Hub 3", Arrays.asList(g4_1, g4_2, g4_3, g4_4, g4_5, g4_6, g4_7, g4_8, g4_9, g4_10, g4_11, g4_12, g4_13, g4_14, g4_15), null);
|
||||||
|
// BreakerGroup debug = new BreakerGroup("40", "Debug Hub 3", Arrays.asList(b4_1));
|
||||||
|
|
||||||
|
|
||||||
|
BreakerGroup house = new BreakerGroup("0", "*redacted*", Arrays.asList(solar, cc, hotWater, dryer, septic, masterBR, garage, office, kitchen, g1, g6, g7, g8, g9, g10, g13, g14, debug), null);
|
||||||
|
BreakerConfig config = new BreakerConfig(Collections.singletonList(house));
|
||||||
|
CollectionUtils.edit(config.getAllBreakerGroups(), _g->_g.setAccountId(1));
|
||||||
|
CollectionUtils.edit(config.getAllBreakers(), _b->{
|
||||||
|
_b.setAccountId(1);
|
||||||
|
_b.setCalibrationFactor(1.0);
|
||||||
|
});
|
||||||
|
b4_1.setCalibrationFactor(1.215);
|
||||||
|
b4_2.setCalibrationFactor(1.215);
|
||||||
|
b4_3.setCalibrationFactor(1.215);
|
||||||
|
config.setAccountId(1);
|
||||||
|
BreakerHub hub0 = new BreakerHub();
|
||||||
|
hub0.setHub(0);
|
||||||
|
hub0.setVoltageCalibrationFactor(0.4587);
|
||||||
|
hub0.setFrequency(60);
|
||||||
|
BreakerHub hub1 = new BreakerHub();
|
||||||
|
hub1.setHub(1);
|
||||||
|
hub1.setVoltageCalibrationFactor(0.439);
|
||||||
|
hub1.setFrequency(60);
|
||||||
|
BreakerHub hub2 = new BreakerHub();
|
||||||
|
hub2.setHub(2);
|
||||||
|
hub2.setVoltageCalibrationFactor(0.3535);
|
||||||
|
hub2.setFrequency(60);
|
||||||
|
BreakerHub hub3 = new BreakerHub();
|
||||||
|
hub3.setHub(3);
|
||||||
|
hub3.setVoltageCalibrationFactor(0.419);
|
||||||
|
hub3.setFrequency(60);
|
||||||
|
config.setBreakerHubs(Arrays.asList(hub0, hub1, hub2, hub3));
|
||||||
|
|
||||||
|
Meter heatMeter = new Meter();
|
||||||
|
heatMeter.setAccountId(1);
|
||||||
|
heatMeter.setIndex(0);
|
||||||
|
heatMeter.setName("Heat");
|
||||||
|
|
||||||
|
Meter mainMeter = new Meter();
|
||||||
|
mainMeter.setAccountId(1);
|
||||||
|
mainMeter.setIndex(1);
|
||||||
|
mainMeter.setName("Main/Solar");
|
||||||
|
|
||||||
|
config.setMeters(CollectionUtils.asArrayList(heatMeter, mainMeter));
|
||||||
|
|
||||||
|
BreakerPanel heat1 = new BreakerPanel();
|
||||||
|
heat1.setAccountId(1);
|
||||||
|
heat1.setIndex(0);
|
||||||
|
heat1.setMeter(heatMeter.getIndex());
|
||||||
|
heat1.setName("Heat 1");
|
||||||
|
heat1.setSpaces(20);
|
||||||
|
|
||||||
|
BreakerPanel heat2 = new BreakerPanel();
|
||||||
|
heat2.setAccountId(1);
|
||||||
|
heat2.setIndex(1);
|
||||||
|
heat2.setMeter(heatMeter.getIndex());
|
||||||
|
heat2.setName("Heat 2");
|
||||||
|
heat2.setSpaces(20);
|
||||||
|
|
||||||
|
BreakerPanel main = new BreakerPanel();
|
||||||
|
main.setAccountId(1);
|
||||||
|
main.setIndex(2);
|
||||||
|
main.setMeter(mainMeter.getIndex());
|
||||||
|
main.setName("Main");
|
||||||
|
main.setSpaces(20);
|
||||||
|
|
||||||
|
BreakerPanel sub = new BreakerPanel();
|
||||||
|
sub.setAccountId(1);
|
||||||
|
sub.setIndex(3);
|
||||||
|
sub.setMeter(mainMeter.getIndex());
|
||||||
|
sub.setName("Sub-Panel");
|
||||||
|
sub.setSpaces(20);
|
||||||
|
|
||||||
|
config.setPanels(CollectionUtils.asArrayList(heat1, heat2, main, sub));
|
||||||
|
|
||||||
|
Map<Integer, Integer> panelToMeter = CollectionUtils.transformToMap(config.getPanels(), BreakerPanel::getIndex, BreakerPanel::getMeter);
|
||||||
|
CollectionUtils.edit(config.getAllBreakers(), _b->_b.setMeter(DaoSerializer.toInteger(panelToMeter.get(_b.getPanel()))));*/
|
||||||
|
|
||||||
|
BreakerConfig config = dao.getConfig(1);
|
||||||
|
// BreakerConfig config = DaoSerializer.parse(ResourceLoader.loadFileAsString(LanternFiles.OPS_PATH + "breakerconfig_backup_210107.json"), BreakerConfig.class);
|
||||||
|
// ResourceLoader.writeFile(LanternFiles.OPS_PATH + "breakerconfig_backup_210107.json", DaoSerializer.toJson(config));
|
||||||
|
// CollectionUtils.edit(config.getAllBreakerGroups(), _g->{
|
||||||
|
// if (NullUtils.isEmpty(_g.getName())) {
|
||||||
|
// Breaker b = CollectionUtils.getFirst(_g.getBreakers());
|
||||||
|
// if (b != null)
|
||||||
|
// _g.setName(String.format("Panel %d, %s", b.getPanel(), b.getName()));
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// for (BreakerGroup group : CollectionUtils.filter(config.getAllBreakerGroups(), _g->NullUtils.isEmpty(_g.getId()))) {
|
||||||
|
// List<Integer> ids = CollectionUtils.transform(config.getAllBreakerGroupIds(), NullUtils::toInteger);
|
||||||
|
// group.setId(String.valueOf(CollectionUtils.getLargest(ids) + 1));
|
||||||
|
// }
|
||||||
|
// BreakerGroup root = CollectionUtils.getFirst(config.getBreakerGroups());
|
||||||
|
// root.getSubGroups().removeIf(_g->_g.getName().equals("Debug Hub 3"));
|
||||||
|
// config.removeInvalidGroups();
|
||||||
|
// for (BreakerGroup group : config.getAllBreakerGroups()) {
|
||||||
|
// if (NullUtils.isEmpty(group.getId())) {
|
||||||
|
// List<Integer> ids = CollectionUtils.transform(config.getAllBreakerGroupIds(), NullUtils::toInteger);
|
||||||
|
// group.setId(String.valueOf(CollectionUtils.getLargest(ids) + 1));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
dao.putConfig(config);
|
||||||
|
dao.shutdown();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.dao.mongo.MongoConfig;
|
||||||
|
|
||||||
|
public class CreateMongoConfig {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new MongoConfig("localhost", "*redacted*", "*redacted*", "CURRENT_MONITOR").saveToDisk(LanternFiles.OPS_PATH + "mongo.cfg");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.lanternsoftware.currentmonitor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lanternsoftware.util.LanternFiles;
|
||||||
|
import com.lanternsoftware.util.dao.generator.DaoSerializerGenerator;
|
||||||
|
import com.lanternsoftware.util.dao.generator.SwiftModelGenerator;
|
||||||
|
|
||||||
|
public class CurrentMonitorSerializers {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DaoSerializerGenerator.generateSerializers(LanternFiles.SOURCE_PATH + "currentmonitor", true, null);
|
||||||
|
SwiftModelGenerator.generateModel(LanternFiles.SOURCE_PATH + "currentmonitor", LanternFiles.SOURCE_PATH + "iOS");
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user