mirror of
https://github.com/zyphlar/LanternPowerMonitor.git
synced 2024-03-08 14:07:47 +00:00
Add a rules engine so I can be notified when I forget to close my garage door.
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.services</groupId>
|
||||
<groupId>com.lanternsoftware.zwave</groupId>
|
||||
<artifactId>lantern-datamodel-zwave</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
@@ -33,6 +33,11 @@
|
||||
<artifactId>lantern-zwave</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.rules</groupId>
|
||||
<artifactId>lantern-datamodel-rules</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.util</groupId>
|
||||
<artifactId>lantern-util-dao-mongo</artifactId>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.lanternsoftware.zwave.context;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||
import com.lanternsoftware.datamodel.rules.Event;
|
||||
import com.lanternsoftware.datamodel.rules.EventType;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.datamodel.zwave.Switch;
|
||||
import com.lanternsoftware.datamodel.zwave.SwitchSchedule;
|
||||
import com.lanternsoftware.datamodel.zwave.SwitchTransition;
|
||||
@@ -32,6 +34,7 @@ import com.lanternsoftware.zwave.message.impl.ThermostatSetPointReportRequest;
|
||||
import com.lanternsoftware.zwave.message.impl.ThermostatSetPointSetRequest;
|
||||
import com.lanternsoftware.zwave.message.thermostat.ThermostatSetPointIndex;
|
||||
import com.lanternsoftware.zwave.relay.RelayController;
|
||||
import com.lanternsoftware.zwave.security.SecurityController;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
@@ -39,6 +42,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -48,8 +52,8 @@ import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class ZWaveApp {
|
||||
public static final AESTool aes = new AESTool(ResourceLoader.loadFile(LanternFiles.OPS_PATH + "authKey.dat"));
|
||||
public static String authCode = aes.encryptToBase64(DaoSerializer.toZipBson(new AuthCode(100, null)));
|
||||
public static final AESTool aes = AESTool.authTool();
|
||||
public static String authCode;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ZWaveApp.class);
|
||||
|
||||
@@ -57,6 +61,7 @@ public class ZWaveApp {
|
||||
private ZWaveConfig config;
|
||||
private Controller controller;
|
||||
private RelayController relayController;
|
||||
private SecurityController securityController;
|
||||
private final Map<Integer, Switch> originalSwitches = new HashMap<>();
|
||||
private final Map<Integer, Switch> switches = new HashMap<>();
|
||||
private final Map<Integer, Switch> mySwitches = new HashMap<>();
|
||||
@@ -79,12 +84,14 @@ public class ZWaveApp {
|
||||
controller = new Controller();
|
||||
controller.start(config.getCommPort());
|
||||
}
|
||||
authCode = aes.encryptToBase64(DaoSerializer.toZipBson(new AuthCode(config.getAccountId(), null)));
|
||||
if (!config.isMaster()) {
|
||||
HttpGet get = new HttpGet(config.getMasterUrl() + "/config");
|
||||
get.setHeader("auth_code", authCode);
|
||||
ZWaveConfig switchConfig = DaoSerializer.parse(pool.executeToString(get), ZWaveConfig.class);
|
||||
if (switchConfig != null) {
|
||||
config.setSwitches(switchConfig.getSwitches());
|
||||
config.setRulesUrl(switchConfig.getRulesUrl());
|
||||
}
|
||||
else {
|
||||
logger.error("Failed to retrieve switch config from master controller");
|
||||
@@ -125,6 +132,20 @@ public class ZWaveApp {
|
||||
if (CollectionUtils.anyQualify(mySwitches.values(), Switch::isRelay)) {
|
||||
relayController = new RelayController();
|
||||
}
|
||||
List<Switch> securitySwitches = CollectionUtils.filter(mySwitches.values(), Switch::isSecurity);
|
||||
if (!securitySwitches.isEmpty()) {
|
||||
securityController = new SecurityController();
|
||||
for (Switch s : securitySwitches) {
|
||||
s.setLevel(securityController.isOpen(s.getGpioPin())?1:0);
|
||||
logger.info("Monitoring security sensor " + s.getFullDisplay() + " on gpio pin " + s.getGpioPin());
|
||||
securityController.listen(s, (_nodeId, _open) -> {
|
||||
s.setLevel(_open?1:0);
|
||||
logger.info(s.getFullDisplay() + " is " + ((s.getLevel() == 0)?"closed":"open"));
|
||||
fireSwitchLevelEvent(s);
|
||||
persistConfig();
|
||||
});
|
||||
}
|
||||
}
|
||||
for (List<Switch> group : groups.values()) {
|
||||
for (Switch sw : group) {
|
||||
peers.put(sw.getNodeId(), CollectionUtils.filter(group, _sw -> _sw.getNodeId() != sw.getNodeId()));
|
||||
@@ -161,6 +182,7 @@ public class ZWaveApp {
|
||||
if (sw != null) {
|
||||
if (NullUtils.isOneOf(_message.getIndex(), ThermostatSetPointIndex.HEATING, ThermostatSetPointIndex.COOLING)) {
|
||||
sw.setLevel((int) Math.round(_message.getTemperatureCelsius() * 1.8) + 32);
|
||||
fireSwitchLevelEvent(sw);
|
||||
persistConfig();
|
||||
}
|
||||
}
|
||||
@@ -222,6 +244,7 @@ public class ZWaveApp {
|
||||
if ((sw != null) && !sw.isPrimary()) {
|
||||
int newLevel = sw.isMultilevel()?_primaryLevel:((_primaryLevel == 0)?0:99);
|
||||
sw.setLevel(newLevel);
|
||||
fireSwitchLevelEvent(sw);
|
||||
for (Switch peer : CollectionUtils.makeNotNull(peers.get(_secondaryNodeId))) {
|
||||
if (peer.isPrimary()) {
|
||||
logger.info("Mirror Event from node {} to node {}", _secondaryNodeId, peer.getNodeId());
|
||||
@@ -254,22 +277,52 @@ public class ZWaveApp {
|
||||
nextScheduleTask = null;
|
||||
}
|
||||
|
||||
public int getAccountId() {
|
||||
return config == null ? 0 : config.getAccountId();
|
||||
}
|
||||
|
||||
public void setSwitchLevel(int _nodeId, int _level) {
|
||||
setSwitchLevel(_nodeId, _level, true);
|
||||
}
|
||||
|
||||
public void fireSwitchLevelEvent(Switch _sw) {
|
||||
if (NullUtils.isEmpty(config.getRulesUrl()))
|
||||
return;
|
||||
Event event = new Event();
|
||||
event.setEventDescription(_sw.getFullDisplay() + " set to " + _sw.getLevel());
|
||||
event.setType(EventType.SWITCH_LEVEL);
|
||||
event.setTime(new Date());
|
||||
event.setValue(_sw.getLevel());
|
||||
event.setSourceId(String.valueOf(_sw.getNodeId()));
|
||||
event.setAccountId(config.getAccountId());
|
||||
logger.info("Sending event to rules server - " + event.getEventDescription());
|
||||
HttpPost post = new HttpPost(NullUtils.terminateWith(config.getRulesUrl(), "/") + "event");
|
||||
post.setHeader("auth_code", authCode);
|
||||
post.setEntity(new ByteArrayEntity(DaoSerializer.toZipBson(event)));
|
||||
pool.execute(post);
|
||||
}
|
||||
|
||||
public void setSwitchLevel(int _nodeId, int _level, boolean _updatePeers) {
|
||||
Switch sw = switches.get(_nodeId);
|
||||
if ((sw == null) || !sw.isPrimary())
|
||||
return;
|
||||
sw.setLevel(_level);
|
||||
if (config.isMySwitch(sw)) {
|
||||
fireSwitchLevelEvent(sw);
|
||||
if (sw.isSpaceHeaterThermostat()) {
|
||||
checkThermostat(sw);
|
||||
} else if (sw.isZWaveThermostat()) {
|
||||
controller.send(new ThermostatSetPointSetRequest((byte) sw.getNodeId(), sw.getThermostatMode() == ThermostatMode.COOL ? ThermostatSetPointIndex.COOLING : ThermostatSetPointIndex.HEATING, _level));
|
||||
} else if (sw.isRelay()) {
|
||||
relayController.setRelay(sw.getGpioPin(), sw.getLevel() > 0);
|
||||
} else if (sw.isRelayButton()) {
|
||||
relayController.setRelay(sw.getGpioPin(), true);
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
relayController.setRelay(sw.getGpioPin(), false);
|
||||
}
|
||||
}, 250);
|
||||
} else {
|
||||
setGroupSwitchLevel(sw, _level);
|
||||
}
|
||||
@@ -331,7 +384,8 @@ public class ZWaveApp {
|
||||
}
|
||||
}
|
||||
if (_updatePeers) {
|
||||
Set<String> peers = CollectionUtils.transformToSet(modified, Switch::getControllerUrl);
|
||||
Set<String> peers = CollectionUtils.transformToSet(switches.values(), Switch::getControllerUrl);
|
||||
peers.add(config.getMasterUrl());
|
||||
peers.remove(config.getUrl());
|
||||
for (String peer : peers) {
|
||||
for (Switch sw : modified) {
|
||||
@@ -354,11 +408,18 @@ public class ZWaveApp {
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
controller.stop();
|
||||
if (controller != null) {
|
||||
controller.stop();
|
||||
controller = null;
|
||||
}
|
||||
if (relayController != null) {
|
||||
relayController.shutdown();
|
||||
relayController = null;
|
||||
}
|
||||
if (securityController != null) {
|
||||
securityController.shutdown();
|
||||
securityController = null;
|
||||
}
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
package com.lanternsoftware.zwave.servlet;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.zwave.context.Globals;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@WebServlet("/config")
|
||||
public class ConfigServlet extends SecureServlet {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package com.lanternsoftware.zwave.servlet;
|
||||
|
||||
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.auth.AuthCode;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import com.lanternsoftware.zwave.context.Globals;
|
||||
import com.lanternsoftware.zwave.context.ZWaveApp;
|
||||
@@ -16,7 +13,7 @@ public abstract class SecureServlet extends ZWaveServlet {
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
AuthCode authCode = DaoSerializer.fromZipBson(ZWaveApp.aes.decryptFromBase64(_req.getHeader("auth_code")), AuthCode.class);
|
||||
if ((authCode == null) || (authCode.getAccountId() != 100)) {
|
||||
if ((authCode == null) || (authCode.getAccountId() != Globals.app.getAccountId())) {
|
||||
_rep.setStatus(401);
|
||||
return;
|
||||
}
|
||||
@@ -29,7 +26,7 @@ public abstract class SecureServlet extends ZWaveServlet {
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
AuthCode authCode = DaoSerializer.fromZipBson(ZWaveApp.aes.decryptFromBase64(_req.getHeader("auth_code")), AuthCode.class);
|
||||
if ((authCode == null) || (authCode.getAccountId() != 100)) {
|
||||
if ((authCode == null) || (authCode.getAccountId() != Globals.app.getAccountId())) {
|
||||
_rep.setStatus(401);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.lanternsoftware.zwave.servlet;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.datamodel.zwave.Switch;
|
||||
import com.lanternsoftware.datamodel.zwave.SwitchSchedule;
|
||||
import com.lanternsoftware.datamodel.zwave.ThermostatMode;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.lanternsoftware.zwave.servlet;
|
||||
|
||||
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||
import com.lanternsoftware.util.dao.auth.AuthCode;
|
||||
import com.lanternsoftware.util.CollectionUtils;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
|
||||
@@ -6,6 +6,6 @@ import com.lanternsoftware.util.dao.generator.DaoSerializerGenerator;
|
||||
|
||||
public class GenerateSerializers {
|
||||
public static void main(String[] args) {
|
||||
DaoSerializerGenerator.generateSerializers(LanternFiles.SOURCE_PATH + "zwave", true, null);
|
||||
DaoSerializerGenerator.generateSerializers(LanternFiles.SOURCE_PATH, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user