diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java
index 30ec3c0..7a51e5b 100644
--- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java
+++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/CurrentMonitorDao.java
@@ -1,7 +1,7 @@
package com.lanternsoftware.dataaccess.currentmonitor;
import com.lanternsoftware.datamodel.currentmonitor.Account;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java
index 3ca5724..7a70a38 100644
--- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java
+++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java
@@ -1,7 +1,7 @@
package com.lanternsoftware.dataaccess.currentmonitor;
import com.lanternsoftware.datamodel.currentmonitor.Account;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
@@ -14,9 +14,7 @@ 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;
@@ -42,7 +40,7 @@ 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 AESTool aes = AESTool.authTool();
private static final int BCRYPT_ROUNDS = 11;
private final Timer delayTimer = new Timer();
private final ExecutorService executor = Executors.newCachedThreadPool();
diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer b/currentmonitor/lantern-datamodel-currentmonitor/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
index 55475d5..4bfec17 100644
--- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
+++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
@@ -1,5 +1,4 @@
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
diff --git a/currentmonitor/lantern-service-currentmonitor/pom.xml b/currentmonitor/lantern-service-currentmonitor/pom.xml
index adec441..0d36b0b 100644
--- a/currentmonitor/lantern-service-currentmonitor/pom.xml
+++ b/currentmonitor/lantern-service-currentmonitor/pom.xml
@@ -12,6 +12,18 @@
1.8
+
+
+
+ com.google.api-client
+ google-api-client-bom
+ 1.32.1
+ pom
+ import
+
+
+
+
com.lanternsoftware.currentmonitor
@@ -23,10 +35,14 @@
lantern-util-servlet
1.0.0
+
+ com.lanternsoftware.rules
+ lantern-service-rules
+ 1.0.0
+
com.google.api-client
google-api-client
- 1.30.4
javax
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java
index 3ee445c..890724d 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java
@@ -2,6 +2,7 @@ package com.lanternsoftware.currentmonitor.context;
import com.lanternsoftware.dataaccess.currentmonitor.CurrentMonitorDao;
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
+import com.lanternsoftware.rules.RulesEngine;
import com.lanternsoftware.util.LanternFiles;
import com.lanternsoftware.util.dao.mongo.MongoConfig;
@@ -14,10 +15,12 @@ public class Globals implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
+ RulesEngine.instance().start();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
dao.shutdown();
+ RulesEngine.shutdown();
}
}
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java
index 192127b..d770bbc 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java
@@ -4,7 +4,7 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeToken
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
-import com.google.api.client.json.jackson2.JacksonFactory;
+import com.google.api.client.json.gson.GsonFactory;
import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.util.DateUtils;
import com.lanternsoftware.util.LanternFiles;
@@ -13,6 +13,7 @@ import com.lanternsoftware.util.ResourceLoader;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoSerializer;
import com.lanternsoftware.util.servlet.BasicAuth;
+import com.lanternsoftware.util.servlet.LanternServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,9 +22,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/auth/*")
-public class AuthServlet extends CMServlet {
+public class AuthServlet extends LanternServlet {
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 googleClientId;
private static final String googleClientSecret;
@@ -41,7 +41,7 @@ public class AuthServlet extends CMServlet {
if (NullUtils.isEqual(auth.getUsername(), "googlesso")) {
logger.info("Attempting google SSO");
try {
- GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(transport, jsonFactory, "https://oauth2.googleapis.com/token", googleClientId, googleClientSecret, auth.getPassword(), "").execute();
+ GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(transport, new GsonFactory(), "https://oauth2.googleapis.com/token", googleClientId, googleClientSecret, auth.getPassword(), "").execute();
if (tokenResponse != null) {
GoogleIdToken idToken = tokenResponse.parseIdToken();
if (idToken != null) {
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/BomServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/BomServlet.java
index e2d76f0..756136a 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/BomServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/BomServlet.java
@@ -8,13 +8,14 @@ import com.lanternsoftware.util.csv.CSVWriter;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoQuery;
import com.lanternsoftware.util.dao.DaoSerializer;
+import com.lanternsoftware.util.servlet.LanternServlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/bom/*")
-public class BomServlet extends CMServlet {
+public class BomServlet extends LanternServlet {
@Override
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
String[] path = path(_req);
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CommandServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CommandServlet.java
index 8003152..0672fc8 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CommandServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CommandServlet.java
@@ -1,6 +1,6 @@
package com.lanternsoftware.currentmonitor.servlet;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.LanternFiles;
import com.lanternsoftware.util.NullUtils;
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java
index 86980a7..e48dd6f 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java
@@ -1,11 +1,8 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
-import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
@@ -13,13 +10,8 @@ import javax.servlet.http.HttpServletResponse;
@WebServlet("/config/*")
public class ConfigServlet extends SecureServlet {
- private static final Logger logger = LoggerFactory.getLogger(ConfigServlet.class);
-
@Override
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
- if (_authCode.getAccountId() == 100) {
- logger.error("my ip: " + _req.getRemoteAddr());
- }
if (isPath(_req, 0, "bin"))
zipBsonResponse(_rep, Globals.dao.getMergedConfig(_authCode));
else
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GenerateBomServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GenerateBomServlet.java
index 596949e..52c0893 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GenerateBomServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GenerateBomServlet.java
@@ -1,7 +1,7 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.util.dao.DaoEntity;
import javax.servlet.annotation.WebServlet;
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GroupEnergyServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GroupEnergyServlet.java
index 449729c..f42eafe 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GroupEnergyServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GroupEnergyServlet.java
@@ -1,7 +1,7 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
import com.lanternsoftware.util.CollectionUtils;
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GroupPowerServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GroupPowerServlet.java
index 5af0898..29b4ed8 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GroupPowerServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/GroupPowerServlet.java
@@ -1,15 +1,9 @@
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.auth.AuthCode;
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;
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/PowerServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/PowerServlet.java
index a0bd27c..3abca86 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/PowerServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/PowerServlet.java
@@ -1,7 +1,7 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
import com.lanternsoftware.util.CollectionUtils;
@@ -31,7 +31,9 @@ public class PowerServlet extends SecureServlet {
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));
+ HubPowerMinute m = getRequestPayload(_req, HubPowerMinute.class);
+ m.setAccountId(_authCode.getAccountId());
+ Globals.dao.putHubPowerMinute(m);
return;
}
if ((path.length > 0) && NullUtils.isEqual(CollectionUtils.get(path, 0), "batch")) {
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/SecureServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/SecureServlet.java
index bf89561..8dec803 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/SecureServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/SecureServlet.java
@@ -1,12 +1,13 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.AuthCode;
+import com.lanternsoftware.util.servlet.LanternServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-public abstract class SecureServlet extends CMServlet {
+public abstract class SecureServlet extends LanternServlet {
@Override
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
AuthCode authCode = Globals.dao.decryptAuthCode(_req.getHeader("auth_code"));
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/SignupServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/SignupServlet.java
index d6c956b..3a8a6a3 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/SignupServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/SignupServlet.java
@@ -7,13 +7,14 @@ import com.lanternsoftware.util.DateUtils;
import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.email.EmailValidator;
import com.lanternsoftware.util.servlet.BasicAuth;
+import com.lanternsoftware.util.servlet.LanternServlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/signup")
-public class SignupServlet extends CMServlet {
+public class SignupServlet extends LanternServlet {
@Override
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
BasicAuth auth = new BasicAuth(_req);
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/UpdateServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/UpdateServlet.java
index b5ab090..6383c7b 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/UpdateServlet.java
+++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/UpdateServlet.java
@@ -3,6 +3,7 @@ package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.util.LanternFiles;
import com.lanternsoftware.util.ResourceLoader;
import com.lanternsoftware.util.dao.DaoSerializer;
+import com.lanternsoftware.util.servlet.LanternServlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
@@ -11,7 +12,7 @@ import javax.ws.rs.core.MediaType;
import java.io.File;
@WebServlet("/update/*")
-public class UpdateServlet extends CMServlet {
+public class UpdateServlet extends LanternServlet {
@Override
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
if (isPath(_req, 0, "version"))
diff --git a/pom.xml b/pom.xml
index faaced3..93b94d2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,7 @@
currentmonitor
util
+ rules
zwave
\ No newline at end of file
diff --git a/rules/lantern-dataaccess-rules/pom.xml b/rules/lantern-dataaccess-rules/pom.xml
new file mode 100644
index 0000000..725a824
--- /dev/null
+++ b/rules/lantern-dataaccess-rules/pom.xml
@@ -0,0 +1,78 @@
+
+ 4.0.0
+ com.lanternsoftware.rules
+ lantern-dataaccess-rules
+ jar
+ 1.0.0
+ lantern-dataaccess-rules
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.lanternsoftware.rules
+ lantern-datamodel-rules
+ 1.0.0
+
+
+ com.lanternsoftware.util
+ lantern-util-dao-mongo
+ 1.0.0
+
+
+
+
+
+ src/main/resources
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.2
+
+
+
+ testCompile
+
+ compile
+
+
+
+ true
+ true
+ UTF-8
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.4
+
+
+ package
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.5
+
+
+ true
+
+
+
+
+
+
diff --git a/rules/lantern-dataaccess-rules/src/main/java/com/lanternsoftware/dataaccess/rules/MongoRulesDataAccess.java b/rules/lantern-dataaccess-rules/src/main/java/com/lanternsoftware/dataaccess/rules/MongoRulesDataAccess.java
new file mode 100644
index 0000000..f4a46cd
--- /dev/null
+++ b/rules/lantern-dataaccess-rules/src/main/java/com/lanternsoftware/dataaccess/rules/MongoRulesDataAccess.java
@@ -0,0 +1,70 @@
+package com.lanternsoftware.dataaccess.rules;
+
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.datamodel.rules.EventType;
+import com.lanternsoftware.datamodel.rules.FcmDevice;
+import com.lanternsoftware.datamodel.rules.Rule;
+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 java.util.Date;
+import java.util.List;
+
+public class MongoRulesDataAccess implements RulesDataAccess {
+ private final MongoProxy proxy;
+
+ public MongoRulesDataAccess(MongoConfig _config) {
+ proxy = new MongoProxy(_config);
+ proxy.ensureIndex(Rule.class, DaoSort.sort("account_id"));
+ proxy.ensureIndex(Event.class, DaoSort.sort("account_id").then("type").then("source_id").then("time"));
+ proxy.ensureIndex(FcmDevice.class, DaoSort.sort("account_id"));
+ }
+
+ @Override
+ public void shutdown() {
+ proxy.shutdown();
+ }
+
+ @Override
+ public void putRule(Rule _rule) {
+ proxy.save(_rule);
+ }
+
+ @Override
+ public List getRulesForAccount(int _accountId) {
+ return proxy.query(Rule.class, new DaoQuery("account_id", _accountId));
+ }
+
+ @Override
+ public void deleteRule(String _ruleId) {
+ proxy.delete(Rule.class, new DaoQuery("_id", _ruleId));
+ }
+
+ @Override
+ public void putEvent(Event _event) {
+ proxy.save(_event);
+ }
+
+ @Override
+ public Event getMostRecentEvent(int _accountId, EventType _type, String _sourceId) {
+ return proxy.queryOne(Event.class, new DaoQuery("account_id", _accountId).and("type", DaoSerializer.toEnumName(_type)).and("source_id", _sourceId), DaoSort.sortDesc("time"));
+ }
+
+ @Override
+ public List getEvents(int _accountId, EventType _type, String _sourceId, Date _from, Date _to) {
+ return proxy.query(Event.class, new DaoQuery("account_id", _accountId).and("type", DaoSerializer.toEnumName(_type)).and("source_id", _sourceId).andBetweenInclusiveExclusive("time", DaoSerializer.toLong(_from), DaoSerializer.toLong(_to)));
+ }
+
+ @Override
+ public void putFcmDevice(FcmDevice _device) {
+ proxy.save(_device);
+ }
+
+ @Override
+ public List getFcmDevicesForAccount(int _accountId) {
+ return proxy.query(FcmDevice.class, new DaoQuery("account_id", _accountId));
+ }
+}
diff --git a/rules/lantern-dataaccess-rules/src/main/java/com/lanternsoftware/dataaccess/rules/RulesDataAccess.java b/rules/lantern-dataaccess-rules/src/main/java/com/lanternsoftware/dataaccess/rules/RulesDataAccess.java
new file mode 100644
index 0000000..08535d4
--- /dev/null
+++ b/rules/lantern-dataaccess-rules/src/main/java/com/lanternsoftware/dataaccess/rules/RulesDataAccess.java
@@ -0,0 +1,21 @@
+package com.lanternsoftware.dataaccess.rules;
+
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.datamodel.rules.EventType;
+import com.lanternsoftware.datamodel.rules.FcmDevice;
+import com.lanternsoftware.datamodel.rules.Rule;
+
+import java.util.Date;
+import java.util.List;
+
+public interface RulesDataAccess {
+ void shutdown();
+ void putRule(Rule _rule);
+ List getRulesForAccount(int _accountId);
+ void deleteRule(String _ruleId);
+ void putEvent(Event _event);
+ Event getMostRecentEvent(int _accountId, EventType _type, String _sourceId);
+ List getEvents(int _accountId, EventType _type, String _sourceId, Date _from, Date _to);
+ void putFcmDevice(FcmDevice _device);
+ List getFcmDevicesForAccount(int _accountId);
+}
diff --git a/rules/lantern-dataaccess-rules/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer b/rules/lantern-dataaccess-rules/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
new file mode 100644
index 0000000..e69de29
diff --git a/rules/lantern-datamodel-rules/pom.xml b/rules/lantern-datamodel-rules/pom.xml
new file mode 100644
index 0000000..5c84ae6
--- /dev/null
+++ b/rules/lantern-datamodel-rules/pom.xml
@@ -0,0 +1,73 @@
+
+ 4.0.0
+ com.lanternsoftware.rules
+ lantern-datamodel-rules
+ jar
+ 1.0.0
+ lantern-datamodel-rules
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.lanternsoftware.util
+ lantern-util-dao
+ 1.0.0
+
+
+
+
+
+ src/main/resources
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.2
+
+
+
+ testCompile
+
+ compile
+
+
+
+ true
+ true
+ UTF-8
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.4
+
+
+ package
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.5
+
+
+ true
+
+
+
+
+
+
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Action.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Action.java
new file mode 100644
index 0000000..176a245
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Action.java
@@ -0,0 +1,43 @@
+package com.lanternsoftware.datamodel.rules;
+
+import com.lanternsoftware.util.dao.annotations.DBSerializable;
+
+@DBSerializable
+public class Action {
+ private ActionType type;
+ private String description;
+ private String destinationId;
+ private double value;
+
+ public ActionType getType() {
+ return type;
+ }
+
+ public void setType(ActionType _type) {
+ type = _type;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String _description) {
+ description = _description;
+ }
+
+ public String getDestinationId() {
+ return destinationId;
+ }
+
+ public void setDestinationId(String _destinationId) {
+ destinationId = _destinationId;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public void setValue(double _value) {
+ value = _value;
+ }
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/ActionType.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/ActionType.java
new file mode 100644
index 0000000..188a9a6
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/ActionType.java
@@ -0,0 +1,7 @@
+package com.lanternsoftware.datamodel.rules;
+
+public enum ActionType {
+ SET_SWITCH,
+ MOBILE_ALERT_STATIC,
+ MOBILE_ALERT_EVENT_DESCRIPTION
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Alert.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Alert.java
new file mode 100644
index 0000000..676910e
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Alert.java
@@ -0,0 +1,23 @@
+package com.lanternsoftware.datamodel.rules;
+
+import com.lanternsoftware.util.dao.annotations.DBSerializable;
+
+@DBSerializable
+public class Alert {
+ private String message;
+
+ public Alert() {
+ }
+
+ public Alert(String _message) {
+ message = _message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String _message) {
+ message = _message;
+ }
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Criteria.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Criteria.java
new file mode 100644
index 0000000..b660d20
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Criteria.java
@@ -0,0 +1,172 @@
+package com.lanternsoftware.datamodel.rules;
+
+import com.lanternsoftware.util.CollectionUtils;
+import com.lanternsoftware.util.DateUtils;
+import com.lanternsoftware.util.NullUtils;
+import com.lanternsoftware.util.dao.DaoSerializer;
+import com.lanternsoftware.util.dao.annotations.DBSerializable;
+
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TimeZone;
+
+@DBSerializable
+public class Criteria {
+ private EventType type;
+ private String sourceId;
+ private Operator operator;
+ private double value;
+ private boolean or;
+ private List criteria;
+
+ public EventType getType() {
+ return type;
+ }
+
+ public void setType(EventType _type) {
+ type = _type;
+ }
+
+ public String getSourceId() {
+ return sourceId;
+ }
+
+ public void setSourceId(String _sourceId) {
+ sourceId = _sourceId;
+ }
+
+ public Operator getOperator() {
+ return operator;
+ }
+
+ public void setOperator(Operator _operator) {
+ operator = _operator;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public void setValue(double _value) {
+ value = _value;
+ }
+
+ public boolean isOr() {
+ return or;
+ }
+
+ public void setOr(boolean _or) {
+ or = _or;
+ }
+
+ public List getCriteria() {
+ return criteria;
+ }
+
+ public void setCriteria(List _criteria) {
+ criteria = _criteria;
+ }
+
+ public EventId toEventId() {
+ return new EventId(type, sourceId);
+ }
+
+ public Set toJavaDays() {
+ if (type != EventType.TIME)
+ return Collections.emptySet();
+ return CollectionUtils.transformToSet(CriteriaDay.toEnumSet(sourceId), _d->_d.javaDay);
+ }
+
+ public boolean isMet(List _events, TimeZone _tz) {
+ Event e = CollectionUtils.filterOne(_events, this::triggers);
+ if (type == EventType.TIME) {
+ int day = DateUtils.toCalendar(new Date(), _tz).get(Calendar.DAY_OF_WEEK);
+ if (!toJavaDays().contains(day))
+ return false;
+ Date timeToday = timeOfDay(new Date(), DaoSerializer.toInteger(getValue()), day, _tz);
+ if (!e.getTime().equals(timeToday))
+ return false;
+ }
+ else if (operator != null) {
+ if (operator == Operator.GREATER) {
+ if (e.getValue() <= value)
+ return false;
+ }
+ else if (operator == Operator.GREATER_EQUAL) {
+ if (e.getValue() < value)
+ return false;
+ }
+ else if (operator == Operator.EQUAL) {
+ if (e.getValue() != value)
+ return false;
+ }
+ else if (operator == Operator.LESS_EQUAL) {
+ if (e.getValue() > value)
+ return false;
+ }
+ else if (operator == Operator.LESS) {
+ if (e.getValue() >= value)
+ return false;
+ }
+ }
+ if (CollectionUtils.isNotEmpty(criteria)) {
+ if (or)
+ return CollectionUtils.anyQualify(criteria, _c->_c.isMet(_events, _tz));
+ return CollectionUtils.allQualify(criteria, _c->_c.isMet(_events, _tz));
+ }
+ return true;
+ }
+
+ public boolean triggers(Event _event) {
+ if (_event.getType() != type)
+ return false;
+ if (NullUtils.isEmpty(_event.getSourceId()) || NullUtils.isEqual(_event.getSourceId(), "*") || NullUtils.isEqual(_event.getSourceId(), sourceId))
+ return true;
+ return CollectionUtils.anyQualify(criteria, _c->_c.triggers(_event));
+ }
+
+ public void addAllCriteria(List _criteria) {
+ _criteria.add(this);
+ CollectionUtils.edit(criteria, _c->_c.addAllCriteria(_criteria));
+ }
+
+ public Date getNextTriggerDate(TimeZone _tz) {
+ if (type != EventType.TIME)
+ return null;
+ Collection dates = CollectionUtils.transform(CriteriaDay.toEnumSet(getSourceId()), _s->nextTimeOfDay(new Date(), DaoSerializer.toInteger(getValue()), _s.javaDay, _tz));
+ return CollectionUtils.getSmallest(dates);
+ }
+
+ public Date timeOfDay(Date _now, int _time, int _day, TimeZone _tz) {
+ Calendar cal = DateUtils.toCalendar(_now, _tz);
+ cal.set(Calendar.DAY_OF_WEEK, _day);
+ cal.set(Calendar.HOUR_OF_DAY, hour(_time));
+ cal.set(Calendar.MINUTE, minute(_time));
+ cal.set(Calendar.SECOND, second(_time));
+ cal.set(Calendar.MILLISECOND, 0);
+ return cal.getTime();
+ }
+
+ public Date nextTimeOfDay(Date _now, int _time, int _day, TimeZone _tz) {
+ Date time = timeOfDay(_now, _time, _day, _tz);
+ return time.before(_now)?DateUtils.addDays(time,7, _tz):time;
+ }
+
+ public int hour(int _timeOfDay) {
+ return _timeOfDay/3600;
+ }
+
+ public int minute(int _timeOfDay) {
+ return (_timeOfDay/60)%60;
+ }
+
+ public int second(int _timeOfDay) {
+ return _timeOfDay%60;
+ }
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/CriteriaDay.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/CriteriaDay.java
new file mode 100644
index 0000000..f171717
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/CriteriaDay.java
@@ -0,0 +1,35 @@
+package com.lanternsoftware.datamodel.rules;
+
+import com.lanternsoftware.util.CollectionUtils;
+import com.lanternsoftware.util.NullUtils;
+
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Set;
+
+public enum CriteriaDay {
+ SUN(Calendar.SUNDAY),
+ MON(Calendar.MONDAY),
+ TUE(Calendar.TUESDAY),
+ WED(Calendar.WEDNESDAY),
+ THU(Calendar.THURSDAY),
+ FRI(Calendar.FRIDAY),
+ SAT(Calendar.SATURDAY);
+
+ public final int javaDay;
+
+ CriteriaDay(int _javaDay) {
+ javaDay = _javaDay;
+ }
+
+ public static String toString(Collection _coll) {
+ return CollectionUtils.transformToCommaSeparated(_coll, Enum::name, false);
+ }
+
+ public static EnumSet toEnumSet(String _days) {
+ String[] days = NullUtils.cleanSplit(_days, ",");
+ Set setDays = CollectionUtils.transformToSet(CollectionUtils.asArrayList(days), _s->NullUtils.toEnum(CriteriaDay.class, _s));
+ return setDays.isEmpty()?EnumSet.allOf(CriteriaDay.class):EnumSet.copyOf(setDays);
+ }
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Event.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Event.java
new file mode 100644
index 0000000..7ae3aa6
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Event.java
@@ -0,0 +1,73 @@
+package com.lanternsoftware.datamodel.rules;
+
+import com.lanternsoftware.util.dao.annotations.DBSerializable;
+import com.lanternsoftware.util.dao.annotations.PrimaryKey;
+
+import java.util.Date;
+
+@DBSerializable
+public class Event {
+ @PrimaryKey private String id;
+ private int accountId;
+ private EventType type;
+ private Date time;
+ private String eventDescription;
+ private String sourceId;
+ private double value;
+
+ 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 EventType getType() {
+ return type;
+ }
+
+ public void setType(EventType _type) {
+ type = _type;
+ }
+
+ public Date getTime() {
+ return time;
+ }
+
+ public void setTime(Date _time) {
+ time = _time;
+ }
+
+ public String getEventDescription() {
+ return eventDescription;
+ }
+
+ public void setEventDescription(String _eventDescription) {
+ eventDescription = _eventDescription;
+ }
+
+ public String getSourceId() {
+ return sourceId;
+ }
+
+ public void setSourceId(String _sourceId) {
+ sourceId = _sourceId;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public void setValue(double _value) {
+ value = _value;
+ }
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/EventId.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/EventId.java
new file mode 100644
index 0000000..e906d67
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/EventId.java
@@ -0,0 +1,34 @@
+package com.lanternsoftware.datamodel.rules;
+
+import java.util.Objects;
+
+public class EventId {
+ private final EventType type;
+ private final String sourceId;
+
+ public EventId(EventType _type, String _sourceId) {
+ type = _type;
+ sourceId = _sourceId;
+ }
+
+ public EventType getType() {
+ return type;
+ }
+
+ public String getSourceId() {
+ return sourceId;
+ }
+
+ @Override
+ public boolean equals(Object _o) {
+ if (this == _o) return true;
+ if (_o == null || getClass() != _o.getClass()) return false;
+ EventId eventId = (EventId) _o;
+ return type == eventId.type && Objects.equals(sourceId, eventId.sourceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, sourceId);
+ }
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/EventType.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/EventType.java
new file mode 100644
index 0000000..cedf880
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/EventType.java
@@ -0,0 +1,8 @@
+package com.lanternsoftware.datamodel.rules;
+
+public enum EventType {
+ SWITCH_LEVEL,
+ TEMPERATURE,
+ TIME,
+ POWER
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/FcmDevice.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/FcmDevice.java
new file mode 100644
index 0000000..34f654e
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/FcmDevice.java
@@ -0,0 +1,65 @@
+package com.lanternsoftware.datamodel.rules;
+
+import com.lanternsoftware.util.dao.annotations.DBSerializable;
+import com.lanternsoftware.util.dao.annotations.PrimaryKey;
+
+import java.util.Date;
+
+@DBSerializable
+public class FcmDevice {
+ @PrimaryKey private String id;
+ private int accountId;
+ private String token;
+ private String name;
+ private Date posted;
+
+ public FcmDevice() {
+ }
+
+ public FcmDevice(int _accountId, String _token, String _name, Date _posted) {
+ accountId = _accountId;
+ token = _token;
+ name = _name;
+ posted = _posted;
+ }
+
+ 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 getToken() {
+ return token;
+ }
+
+ public void setToken(String _token) {
+ token = _token;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String _name) {
+ name = _name;
+ }
+
+ public Date getPosted() {
+ return posted;
+ }
+
+ public void setPosted(Date _posted) {
+ posted = _posted;
+ }
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Operator.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Operator.java
new file mode 100644
index 0000000..1291c9f
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Operator.java
@@ -0,0 +1,9 @@
+package com.lanternsoftware.datamodel.rules;
+
+public enum Operator {
+ GREATER,
+ GREATER_EQUAL,
+ EQUAL,
+ LESS_EQUAL,
+ LESS
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Rule.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Rule.java
new file mode 100644
index 0000000..386e035
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/Rule.java
@@ -0,0 +1,80 @@
+package com.lanternsoftware.datamodel.rules;
+
+import com.lanternsoftware.util.CollectionUtils;
+import com.lanternsoftware.util.dao.annotations.DBSerializable;
+import com.lanternsoftware.util.dao.annotations.PrimaryKey;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimeZone;
+
+@DBSerializable
+public class Rule {
+ @PrimaryKey private String id;
+ private int accountId;
+ private boolean or;
+ private List criteria;
+ private List actions;
+
+ 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 boolean isOr() {
+ return or;
+ }
+
+ public void setOr(boolean _or) {
+ or = _or;
+ }
+
+ public List getCriteria() {
+ return criteria;
+ }
+
+ public List getAllCriteria() {
+ List allCriteria = new ArrayList<>();
+ CollectionUtils.edit(criteria, _c->_c.addAllCriteria(allCriteria));
+ return allCriteria;
+ }
+
+ public void setCriteria(List _criteria) {
+ criteria = _criteria;
+ }
+
+ public List getActions() {
+ return actions;
+ }
+
+ public void setActions(List _actions) {
+ actions = _actions;
+ }
+
+ public boolean isMet(List _events, TimeZone _tz) {
+ if (or)
+ return CollectionUtils.anyQualify(criteria, _c->_c.isMet(_events, _tz));
+ return CollectionUtils.allQualify(criteria, _c->_c.isMet(_events, _tz));
+ }
+
+ public List getCriteriaNeedingData(Event _event) {
+ List allCriteria = getAllCriteria();
+ allCriteria.removeIf(_c->_c.triggers(_event));
+ return allCriteria;
+ }
+
+ public boolean triggers(Event _event) {
+ return CollectionUtils.anyQualify(criteria, _c-> _c.triggers(_event));
+ }
+}
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/ActionSerializer.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/ActionSerializer.java
new file mode 100644
index 0000000..e3af7ed
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/ActionSerializer.java
@@ -0,0 +1,46 @@
+package com.lanternsoftware.datamodel.rules.dao;
+
+import com.lanternsoftware.datamodel.rules.Action;
+import com.lanternsoftware.datamodel.rules.ActionType;
+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 ActionSerializer extends AbstractDaoSerializer
+{
+ @Override
+ public Class getSupportedClass()
+ {
+ return Action.class;
+ }
+
+ @Override
+ public List getSupportedProxies() {
+ return Collections.singletonList(DaoProxyType.MONGO);
+ }
+
+ @Override
+ public DaoEntity toDaoEntity(Action _o)
+ {
+ DaoEntity d = new DaoEntity();
+ d.put("type", DaoSerializer.toEnumName(_o.getType()));
+ d.put("description", _o.getDescription());
+ d.put("destination_id", _o.getDestinationId());
+ d.put("value", _o.getValue());
+ return d;
+ }
+
+ @Override
+ public Action fromDaoEntity(DaoEntity _d)
+ {
+ Action o = new Action();
+ o.setType(DaoSerializer.getEnum(_d, "type", ActionType.class));
+ o.setDescription(DaoSerializer.getString(_d, "description"));
+ o.setDestinationId(DaoSerializer.getString(_d, "destination_id"));
+ o.setValue(DaoSerializer.getDouble(_d, "value"));
+ return o;
+ }
+}
\ No newline at end of file
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/AlertSerializer.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/AlertSerializer.java
new file mode 100644
index 0000000..bc4fe64
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/AlertSerializer.java
@@ -0,0 +1,39 @@
+package com.lanternsoftware.datamodel.rules.dao;
+
+import com.lanternsoftware.datamodel.rules.Alert;
+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 AlertSerializer extends AbstractDaoSerializer
+{
+ @Override
+ public Class getSupportedClass()
+ {
+ return Alert.class;
+ }
+
+ @Override
+ public List getSupportedProxies() {
+ return Collections.singletonList(DaoProxyType.MONGO);
+ }
+
+ @Override
+ public DaoEntity toDaoEntity(Alert _o)
+ {
+ DaoEntity d = new DaoEntity();
+ d.put("message", _o.getMessage());
+ return d;
+ }
+
+ @Override
+ public Alert fromDaoEntity(DaoEntity _d)
+ {
+ Alert o = new Alert();
+ o.setMessage(DaoSerializer.getString(_d, "message"));
+ return o;
+ }
+}
\ No newline at end of file
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/CriteriaSerializer.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/CriteriaSerializer.java
new file mode 100644
index 0000000..2cd2068
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/CriteriaSerializer.java
@@ -0,0 +1,51 @@
+package com.lanternsoftware.datamodel.rules.dao;
+
+import com.lanternsoftware.datamodel.rules.Criteria;
+import com.lanternsoftware.datamodel.rules.EventType;
+import com.lanternsoftware.datamodel.rules.Operator;
+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 CriteriaSerializer extends AbstractDaoSerializer
+{
+ @Override
+ public Class getSupportedClass()
+ {
+ return Criteria.class;
+ }
+
+ @Override
+ public List getSupportedProxies() {
+ return Collections.singletonList(DaoProxyType.MONGO);
+ }
+
+ @Override
+ public DaoEntity toDaoEntity(Criteria _o)
+ {
+ DaoEntity d = new DaoEntity();
+ d.put("type", DaoSerializer.toEnumName(_o.getType()));
+ d.put("source_id", _o.getSourceId());
+ d.put("operator", DaoSerializer.toEnumName(_o.getOperator()));
+ d.put("value", _o.getValue());
+ d.put("or", _o.isOr());
+ d.put("criteria", DaoSerializer.toDaoEntities(_o.getCriteria(), DaoProxyType.MONGO));
+ return d;
+ }
+
+ @Override
+ public Criteria fromDaoEntity(DaoEntity _d)
+ {
+ Criteria o = new Criteria();
+ o.setType(DaoSerializer.getEnum(_d, "type", EventType.class));
+ o.setSourceId(DaoSerializer.getString(_d, "source_id"));
+ o.setOperator(DaoSerializer.getEnum(_d, "operator", Operator.class));
+ o.setValue(DaoSerializer.getDouble(_d, "value"));
+ o.setOr(DaoSerializer.getBoolean(_d, "or"));
+ o.setCriteria(DaoSerializer.getList(_d, "criteria", Criteria.class));
+ return o;
+ }
+}
\ No newline at end of file
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/EventSerializer.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/EventSerializer.java
new file mode 100644
index 0000000..a45b893
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/EventSerializer.java
@@ -0,0 +1,53 @@
+package com.lanternsoftware.datamodel.rules.dao;
+
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.datamodel.rules.EventType;
+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 EventSerializer extends AbstractDaoSerializer
+{
+ @Override
+ public Class getSupportedClass()
+ {
+ return Event.class;
+ }
+
+ @Override
+ public List getSupportedProxies() {
+ return Collections.singletonList(DaoProxyType.MONGO);
+ }
+
+ @Override
+ public DaoEntity toDaoEntity(Event _o)
+ {
+ DaoEntity d = new DaoEntity();
+ if (_o.getId() != null)
+ d.put("_id", _o.getId());
+ d.put("account_id", _o.getAccountId());
+ d.put("type", DaoSerializer.toEnumName(_o.getType()));
+ d.put("time", DaoSerializer.toLong(_o.getTime()));
+ d.put("event_description", _o.getEventDescription());
+ d.put("source_id", _o.getSourceId());
+ d.put("value", _o.getValue());
+ return d;
+ }
+
+ @Override
+ public Event fromDaoEntity(DaoEntity _d)
+ {
+ Event o = new Event();
+ o.setId(DaoSerializer.getString(_d, "_id"));
+ o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
+ o.setType(DaoSerializer.getEnum(_d, "type", EventType.class));
+ o.setTime(DaoSerializer.getDate(_d, "time"));
+ o.setEventDescription(DaoSerializer.getString(_d, "event_description"));
+ o.setSourceId(DaoSerializer.getString(_d, "source_id"));
+ o.setValue(DaoSerializer.getDouble(_d, "value"));
+ return o;
+ }
+}
\ No newline at end of file
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/FcmDeviceSerializer.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/FcmDeviceSerializer.java
new file mode 100644
index 0000000..8d23c44
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/FcmDeviceSerializer.java
@@ -0,0 +1,48 @@
+package com.lanternsoftware.datamodel.rules.dao;
+
+import com.lanternsoftware.datamodel.rules.FcmDevice;
+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 FcmDeviceSerializer extends AbstractDaoSerializer
+{
+ @Override
+ public Class getSupportedClass()
+ {
+ return FcmDevice.class;
+ }
+
+ @Override
+ public List getSupportedProxies() {
+ return Collections.singletonList(DaoProxyType.MONGO);
+ }
+
+ @Override
+ public DaoEntity toDaoEntity(FcmDevice _o)
+ {
+ DaoEntity d = new DaoEntity();
+ if (_o.getId() != null)
+ d.put("_id", _o.getId());
+ d.put("account_id", _o.getAccountId());
+ d.put("token", _o.getToken());
+ d.put("name", _o.getName());
+ d.put("posted", DaoSerializer.toLong(_o.getPosted()));
+ return d;
+ }
+
+ @Override
+ public FcmDevice fromDaoEntity(DaoEntity _d)
+ {
+ FcmDevice o = new FcmDevice();
+ o.setId(DaoSerializer.getString(_d, "_id"));
+ o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
+ o.setToken(DaoSerializer.getString(_d, "token"));
+ o.setName(DaoSerializer.getString(_d, "name"));
+ o.setPosted(DaoSerializer.getDate(_d, "posted"));
+ return o;
+ }
+}
\ No newline at end of file
diff --git a/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/RuleSerializer.java b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/RuleSerializer.java
new file mode 100644
index 0000000..2095ab2
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/java/com/lanternsoftware/datamodel/rules/dao/RuleSerializer.java
@@ -0,0 +1,50 @@
+package com.lanternsoftware.datamodel.rules.dao;
+
+import com.lanternsoftware.datamodel.rules.Action;
+import com.lanternsoftware.datamodel.rules.Criteria;
+import com.lanternsoftware.datamodel.rules.Rule;
+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 RuleSerializer extends AbstractDaoSerializer
+{
+ @Override
+ public Class getSupportedClass()
+ {
+ return Rule.class;
+ }
+
+ @Override
+ public List getSupportedProxies() {
+ return Collections.singletonList(DaoProxyType.MONGO);
+ }
+
+ @Override
+ public DaoEntity toDaoEntity(Rule _o)
+ {
+ DaoEntity d = new DaoEntity();
+ if (_o.getId() != null)
+ d.put("_id", _o.getId());
+ d.put("account_id", _o.getAccountId());
+ d.put("or", _o.isOr());
+ d.put("criteria", DaoSerializer.toDaoEntities(_o.getCriteria(), DaoProxyType.MONGO));
+ d.put("actions", DaoSerializer.toDaoEntities(_o.getActions(), DaoProxyType.MONGO));
+ return d;
+ }
+
+ @Override
+ public Rule fromDaoEntity(DaoEntity _d)
+ {
+ Rule o = new Rule();
+ o.setId(DaoSerializer.getString(_d, "_id"));
+ o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
+ o.setOr(DaoSerializer.getBoolean(_d, "or"));
+ o.setCriteria(DaoSerializer.getList(_d, "criteria", Criteria.class));
+ o.setActions(DaoSerializer.getList(_d, "actions", Action.class));
+ return o;
+ }
+}
\ No newline at end of file
diff --git a/rules/lantern-datamodel-rules/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer b/rules/lantern-datamodel-rules/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
new file mode 100644
index 0000000..96f0cdc
--- /dev/null
+++ b/rules/lantern-datamodel-rules/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
@@ -0,0 +1,6 @@
+com.lanternsoftware.datamodel.rules.dao.ActionSerializer
+com.lanternsoftware.datamodel.rules.dao.AlertSerializer
+com.lanternsoftware.datamodel.rules.dao.CriteriaSerializer
+com.lanternsoftware.datamodel.rules.dao.EventSerializer
+com.lanternsoftware.datamodel.rules.dao.FcmDeviceSerializer
+com.lanternsoftware.datamodel.rules.dao.RuleSerializer
diff --git a/rules/lantern-service-rules/pom.xml b/rules/lantern-service-rules/pom.xml
new file mode 100644
index 0000000..1196897
--- /dev/null
+++ b/rules/lantern-service-rules/pom.xml
@@ -0,0 +1,93 @@
+
+ 4.0.0
+ com.lanternsoftware.rules
+ lantern-service-rules
+ jar
+ 1.0.0
+ lantern-service-rules
+
+
+ 1.8
+ 1.8
+
+
+
+
+
+ com.google.api-client
+ google-api-client-bom
+ 1.32.1
+ pom
+ import
+
+
+
+
+
+
+ com.google.api-client
+ google-api-client
+
+
+ com.google.firebase
+ firebase-admin
+ 8.0.0
+
+
+ com.lanternsoftware.rules
+ lantern-dataaccess-rules
+ 1.0.0
+
+
+ com.lanternsoftware.currentmonitor
+ lantern-dataaccess-currentmonitor
+ 1.0.0
+
+
+ com.lanternsoftware.util
+ lantern-util-servlet
+ 1.0.0
+
+
+ javax
+ javaee-api
+ 8.0
+ provided
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.29
+
+
+
+
+
+ src/main/resources
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.2
+
+
+
+ testCompile
+
+ compile
+
+
+
+ true
+ true
+ UTF-8
+
+ 1.8
+
+
+
+
+
diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/RulesEngine.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/RulesEngine.java
new file mode 100644
index 0000000..b06a2b8
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/RulesEngine.java
@@ -0,0 +1,147 @@
+package com.lanternsoftware.rules;
+
+import com.lanternsoftware.dataaccess.currentmonitor.CurrentMonitorDao;
+import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
+import com.lanternsoftware.dataaccess.rules.MongoRulesDataAccess;
+import com.lanternsoftware.dataaccess.rules.RulesDataAccess;
+import com.lanternsoftware.datamodel.currentmonitor.Account;
+import com.lanternsoftware.datamodel.rules.Action;
+import com.lanternsoftware.datamodel.rules.ActionType;
+import com.lanternsoftware.datamodel.rules.Criteria;
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.datamodel.rules.EventId;
+import com.lanternsoftware.datamodel.rules.EventType;
+import com.lanternsoftware.datamodel.rules.Rule;
+import com.lanternsoftware.rules.actions.ActionImpl;
+import com.lanternsoftware.util.CollectionUtils;
+import com.lanternsoftware.util.DateUtils;
+import com.lanternsoftware.util.LanternFiles;
+import com.lanternsoftware.util.dao.DaoSerializer;
+import com.lanternsoftware.util.dao.mongo.MongoConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+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 RulesEngine {
+ protected static final Logger LOG = LoggerFactory.getLogger(RulesEngine.class);
+
+ private static RulesEngine INSTANCE;
+ private final ExecutorService executor = Executors.newCachedThreadPool();
+ private final RulesDataAccess dao;
+ private final CurrentMonitorDao cmDao;
+ private final Map actions = new HashMap<>();
+ private final Map timeTasks = new HashMap<>();
+ private Timer timer;
+
+
+ public static RulesEngine instance() {
+ if (INSTANCE == null)
+ INSTANCE = new RulesEngine();
+ return INSTANCE;
+ }
+
+ public RulesEngine() {
+ ServiceLoader.load(ActionImpl.class).forEach(_action->actions.put(_action.getType(), _action));
+ dao = new MongoRulesDataAccess(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
+ cmDao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
+ timer = new Timer("RulesEngine Timer");
+ }
+
+ public void start() {
+ for (String id : cmDao.getProxy().queryForField(Account.class, null, "_id")) {
+ scheduleNextTimeEventForAccount(DaoSerializer.toInteger(id));
+ }
+ }
+
+ public RulesDataAccess dao() {
+ return dao;
+ }
+
+ public void fireEvent(Event _event) {
+ if (_event.getType() != EventType.TIME)
+ dao.putEvent(_event);
+ executor.submit(()->{
+ TimeZone tz = TimeZone.getTimeZone("America/Chicago"); //TODO: Get from the current monitor account
+ List rules = CollectionUtils.filter(dao.getRulesForAccount(_event.getAccountId()), _r->_r.triggers(_event));
+ if (!rules.isEmpty()) {
+ for (Rule rule : rules) {
+ List events = CollectionUtils.asArrayList(_event);
+ List critNeedingData = rule.getCriteriaNeedingData(_event);
+ if (!critNeedingData.isEmpty()) {
+ Set eventsToGet = CollectionUtils.transformToSet(critNeedingData, Criteria::toEventId);
+ for (EventId id : eventsToGet) {
+ Event event = dao.getMostRecentEvent(_event.getAccountId(), id.getType(), id.getSourceId());
+ if (event != null)
+ events.add(event);
+ }
+ }
+ if (rule.isMet(events, tz)) {
+ for (Action action : CollectionUtils.makeNotNull(rule.getActions())) {
+ ActionImpl impl = actions.get(action.getType());
+ impl.invoke(rule, events, action);
+ }
+ }
+ }
+ }
+ });
+ }
+
+ private void scheduleNextTimeEventForAccount(int _accountId) {
+ TimeZone tz = TimeZone.getTimeZone("America/Chicago"); //TODO: Get from the current monitor account
+ EventTimeTask nextTask = timeTasks.remove(_accountId);
+ if (nextTask != null)
+ nextTask.cancel();
+ List rules = CollectionUtils.filter(dao.getRulesForAccount(_accountId), _r->CollectionUtils.anyQualify(_r.getAllCriteria(), _c->_c.getType() == EventType.TIME));
+ if (rules.isEmpty())
+ return;
+ Collection dates = CollectionUtils.aggregate(rules, _r->CollectionUtils.transform(_r.getAllCriteria(), _c->_c.getNextTriggerDate(tz)));
+ Date nextDate = CollectionUtils.getSmallest(dates);
+ LOG.info("Scheduling next time event for account {} at {}", _accountId, DateUtils.format("MM/dd/yyyy HH:mm:ss", nextDate));
+ nextTask = new EventTimeTask(_accountId, nextDate);
+ timer.schedule(nextTask, nextDate);
+ }
+
+ public static void shutdown() {
+ if (INSTANCE == null)
+ return;
+ INSTANCE.executor.shutdown();
+ INSTANCE.dao.shutdown();
+ INSTANCE.cmDao.shutdown();
+ INSTANCE.timer.cancel();
+ INSTANCE.timer = null;
+ INSTANCE = null;
+ }
+
+ private class EventTimeTask extends TimerTask {
+ private final int accountId;
+ private final Date eventTime;
+
+ EventTimeTask(int _accountId, Date _eventTime) {
+ accountId = _accountId;
+ eventTime = _eventTime;
+ }
+
+ @Override
+ public void run() {
+ LOG.info("Firing time event for account {}", accountId);
+ Event event = new Event();
+ event.setAccountId(accountId);
+ event.setTime(eventTime);
+ event.setType(EventType.TIME);
+ fireEvent(event);
+ scheduleNextTimeEventForAccount(accountId);
+ }
+ }
+}
diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/AbstractAlertAction.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/AbstractAlertAction.java
new file mode 100644
index 0000000..ab531b5
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/AbstractAlertAction.java
@@ -0,0 +1,52 @@
+package com.lanternsoftware.rules.actions;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.FirebaseOptions;
+import com.google.firebase.messaging.AndroidConfig;
+import com.google.firebase.messaging.FirebaseMessaging;
+import com.google.firebase.messaging.Message;
+import com.lanternsoftware.datamodel.rules.Alert;
+import com.lanternsoftware.datamodel.rules.FcmDevice;
+import com.lanternsoftware.datamodel.rules.Rule;
+import com.lanternsoftware.rules.RulesEngine;
+import com.lanternsoftware.util.LanternFiles;
+import com.lanternsoftware.util.dao.DaoSerializer;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileInputStream;
+import java.util.List;
+
+public abstract class AbstractAlertAction implements ActionImpl {
+ protected static final Logger logger = LoggerFactory.getLogger(AbstractAlertAction.class);
+ protected static final FirebaseMessaging messaging;
+ static {
+ FirebaseMessaging m = null;
+ try {
+ FileInputStream is = new FileInputStream(LanternFiles.OPS_PATH + "google_account_key.json");
+ FirebaseOptions options = FirebaseOptions.builder().setCredentials(GoogleCredentials.fromStream(is)).build();
+ m = FirebaseMessaging.getInstance(FirebaseApp.initializeApp(options));
+ IOUtils.closeQuietly(is);
+ }
+ catch (Exception _e) {
+ logger.error("Failed to load google credentials", _e);
+ }
+ messaging = m;
+ }
+
+ protected void sendAlert(Rule _rule, Alert _alert) {
+ List devices = RulesEngine.instance().dao().getFcmDevicesForAccount(_rule.getAccountId());
+ if (devices.isEmpty())
+ return;
+ for (FcmDevice device : devices) {
+ Message msg = Message.builder().setToken(device.getToken()).putData("payload", DaoSerializer.toBase64ZipBson(_alert)).putData("payloadClass", Alert.class.getCanonicalName()).setAndroidConfig(AndroidConfig.builder().setPriority(AndroidConfig.Priority.HIGH).setDirectBootOk(true).build()).build();
+ try {
+ messaging.send(msg);
+ } catch (Exception _e) {
+ logger.error("Failed to send message to account {}, device {}", _rule.getAccountId(), device.getName(), _e);
+ }
+ }
+ }
+}
diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/ActionImpl.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/ActionImpl.java
new file mode 100644
index 0000000..bf9ca70
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/ActionImpl.java
@@ -0,0 +1,13 @@
+package com.lanternsoftware.rules.actions;
+
+import com.lanternsoftware.datamodel.rules.Action;
+import com.lanternsoftware.datamodel.rules.ActionType;
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.datamodel.rules.Rule;
+
+import java.util.List;
+
+public interface ActionImpl {
+ ActionType getType();
+ void invoke(Rule _rule, List _event, Action _action);
+}
diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/MobileAlertAction.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/MobileAlertAction.java
new file mode 100644
index 0000000..f73bfb4
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/MobileAlertAction.java
@@ -0,0 +1,22 @@
+package com.lanternsoftware.rules.actions;
+
+import com.lanternsoftware.datamodel.rules.Action;
+import com.lanternsoftware.datamodel.rules.ActionType;
+import com.lanternsoftware.datamodel.rules.Alert;
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.datamodel.rules.Rule;
+import com.lanternsoftware.util.CollectionUtils;
+
+import java.util.List;
+
+public class MobileAlertAction extends AbstractAlertAction {
+ @Override
+ public ActionType getType() {
+ return ActionType.MOBILE_ALERT_EVENT_DESCRIPTION;
+ }
+
+ @Override
+ public void invoke(Rule _rule, List _event, Action _action) {
+ sendAlert(_rule, new Alert(CollectionUtils.transformToCommaSeparated(_event, Event::getEventDescription)));
+ }
+}
diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/MobileAlertStatic.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/MobileAlertStatic.java
new file mode 100644
index 0000000..a301ae7
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/MobileAlertStatic.java
@@ -0,0 +1,22 @@
+package com.lanternsoftware.rules.actions;
+
+import com.lanternsoftware.datamodel.rules.Action;
+import com.lanternsoftware.datamodel.rules.ActionType;
+import com.lanternsoftware.datamodel.rules.Alert;
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.datamodel.rules.Rule;
+import com.lanternsoftware.util.CollectionUtils;
+
+import java.util.List;
+
+public class MobileAlertStatic extends AbstractAlertAction {
+ @Override
+ public ActionType getType() {
+ return ActionType.MOBILE_ALERT_STATIC;
+ }
+
+ @Override
+ public void invoke(Rule _rule, List _event, Action _action) {
+ sendAlert(_rule, new Alert(_action.getDescription()));
+ }
+}
diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/EventServlet.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/EventServlet.java
new file mode 100644
index 0000000..235c43f
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/EventServlet.java
@@ -0,0 +1,24 @@
+package com.lanternsoftware.rules.servlet;
+
+
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.rules.RulesEngine;
+import com.lanternsoftware.util.dao.auth.AuthCode;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet("/event")
+public class EventServlet extends SecureServlet {
+ @Override
+ protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
+ Event event = getRequestPayload(_req, Event.class);
+ if (event == null) {
+ _rep.setStatus(400);
+ return;
+ }
+ event.setAccountId(_authCode.getAccountId());
+ RulesEngine.instance().fireEvent(event);
+ }
+}
diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/FcmServlet.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/FcmServlet.java
new file mode 100644
index 0000000..1e03a5a
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/FcmServlet.java
@@ -0,0 +1,24 @@
+package com.lanternsoftware.rules.servlet;
+
+
+import com.lanternsoftware.datamodel.rules.FcmDevice;
+import com.lanternsoftware.rules.RulesEngine;
+import com.lanternsoftware.util.dao.auth.AuthCode;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet("/fcm")
+public class FcmServlet extends SecureServlet {
+ @Override
+ protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
+ FcmDevice device = getRequestPayload(_req, FcmDevice.class);
+ if (device == null) {
+ _rep.setStatus(400);
+ return;
+ }
+ device.setAccountId(_authCode.getAccountId());
+ RulesEngine.instance().dao().putFcmDevice(device);
+ }
+}
diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/SecureServlet.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/SecureServlet.java
new file mode 100644
index 0000000..cadc3dc
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/servlet/SecureServlet.java
@@ -0,0 +1,39 @@
+package com.lanternsoftware.rules.servlet;
+
+import com.lanternsoftware.util.cryptography.AESTool;
+import com.lanternsoftware.util.dao.DaoSerializer;
+import com.lanternsoftware.util.dao.auth.AuthCode;
+import com.lanternsoftware.util.servlet.LanternServlet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public abstract class SecureServlet extends LanternServlet {
+ private static final AESTool aes = AESTool.authTool();
+
+ @Override
+ protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
+ AuthCode authCode = DaoSerializer.fromZipBson(aes.decryptFromBase64(_req.getHeader("auth_code")), AuthCode.class);
+ 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 = DaoSerializer.fromZipBson(aes.decryptFromBase64(_req.getHeader("auth_code")), AuthCode.class);
+ if (authCode == null) {
+ _rep.setStatus(401);
+ return;
+ }
+ post(authCode, _req, _rep);
+ }
+
+ protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
+ }
+}
diff --git a/rules/lantern-service-rules/src/main/resources/META-INF/services/com.lanternsoftware.rules.actions.ActionImpl b/rules/lantern-service-rules/src/main/resources/META-INF/services/com.lanternsoftware.rules.actions.ActionImpl
new file mode 100644
index 0000000..3cc4cd4
--- /dev/null
+++ b/rules/lantern-service-rules/src/main/resources/META-INF/services/com.lanternsoftware.rules.actions.ActionImpl
@@ -0,0 +1,2 @@
+com.lanternsoftware.rules.actions.MobileAlertAction
+com.lanternsoftware.rules.actions.MobileAlertStatic
diff --git a/rules/lantern-service-rules/src/test/java/com/lanternsoftware/CreateRules.java b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/CreateRules.java
new file mode 100644
index 0000000..5cfbf25
--- /dev/null
+++ b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/CreateRules.java
@@ -0,0 +1,165 @@
+package com.lanternsoftware;
+
+import com.lanternsoftware.datamodel.rules.Action;
+import com.lanternsoftware.datamodel.rules.ActionType;
+import com.lanternsoftware.datamodel.rules.Criteria;
+import com.lanternsoftware.datamodel.rules.EventType;
+import com.lanternsoftware.datamodel.rules.Operator;
+import com.lanternsoftware.datamodel.rules.Rule;
+import com.lanternsoftware.rules.RulesEngine;
+import com.lanternsoftware.util.CollectionUtils;
+
+public class CreateRules {
+ public static void main(String[] args) {
+ for (Rule r : RulesEngine.instance().dao().getRulesForAccount(100)) {
+ RulesEngine.instance().dao().deleteRule(r.getId());
+ }
+ Rule r1 = new Rule();
+ r1.setAccountId(100);
+ Criteria c1 = new Criteria();
+ c1.setType(EventType.SWITCH_LEVEL);
+ c1.setSourceId("203");
+ c1.setOperator(Operator.EQUAL);
+ c1.setValue(1);
+ r1.setCriteria(CollectionUtils.asArrayList(c1));
+ Action a1 = new Action();
+ a1.setType(ActionType.MOBILE_ALERT_STATIC);
+ a1.setDescription("Garage Door 1 opened");
+ a1.setDestinationId("*");
+ r1.setActions(CollectionUtils.asArrayList(a1));
+ RulesEngine.instance().dao().putRule(r1);
+
+ Rule r2 = new Rule();
+ r2.setAccountId(100);
+ Criteria c2 = new Criteria();
+ c2.setType(EventType.SWITCH_LEVEL);
+ c2.setSourceId("203");
+ c2.setOperator(Operator.EQUAL);
+ c2.setValue(0);
+ r2.setCriteria(CollectionUtils.asArrayList(c2));
+ Action a2 = new Action();
+ a2.setType(ActionType.MOBILE_ALERT_STATIC);
+ a2.setDescription("Garage Door 1 closed");
+ a2.setDestinationId("*");
+ r2.setActions(CollectionUtils.asArrayList(a2));
+ RulesEngine.instance().dao().putRule(r2);
+
+ Rule r3 = new Rule();
+ r3.setAccountId(100);
+ Criteria c3 = new Criteria();
+ c3.setType(EventType.SWITCH_LEVEL);
+ c3.setSourceId("204");
+ c3.setOperator(Operator.EQUAL);
+ c3.setValue(1);
+ r3.setCriteria(CollectionUtils.asArrayList(c3));
+ Action a3 = new Action();
+ a3.setType(ActionType.MOBILE_ALERT_STATIC);
+ a3.setDescription("Garage Door 2 opened");
+ a3.setDestinationId("*");
+ r3.setActions(CollectionUtils.asArrayList(a3));
+ RulesEngine.instance().dao().putRule(r3);
+
+ Rule r4 = new Rule();
+ r4.setAccountId(100);
+ Criteria c4 = new Criteria();
+ c4.setType(EventType.SWITCH_LEVEL);
+ c4.setSourceId("204");
+ c4.setOperator(Operator.EQUAL);
+ c4.setValue(0);
+ r4.setCriteria(CollectionUtils.asArrayList(c4));
+ Action a4 = new Action();
+ a4.setType(ActionType.MOBILE_ALERT_STATIC);
+ a4.setDescription("Garage Door 2 closed");
+ a4.setDestinationId("*");
+ r4.setActions(CollectionUtils.asArrayList(a4));
+ RulesEngine.instance().dao().putRule(r4);
+
+ Rule r5 = new Rule();
+ r5.setAccountId(100);
+ Criteria c5 = new Criteria();
+ c5.setType(EventType.SWITCH_LEVEL);
+ c5.setSourceId("205");
+ c5.setOperator(Operator.EQUAL);
+ c5.setValue(1);
+ r5.setCriteria(CollectionUtils.asArrayList(c5));
+ Action a5 = new Action();
+ a5.setType(ActionType.MOBILE_ALERT_STATIC);
+ a5.setDescription("Garage Door 3 opened");
+ a5.setDestinationId("*");
+ r5.setActions(CollectionUtils.asArrayList(a5));
+ RulesEngine.instance().dao().putRule(r5);
+
+ Rule r6 = new Rule();
+ r6.setAccountId(100);
+ Criteria c6 = new Criteria();
+ c6.setType(EventType.SWITCH_LEVEL);
+ c6.setSourceId("205");
+ c6.setOperator(Operator.EQUAL);
+ c6.setValue(0);
+ r6.setCriteria(CollectionUtils.asArrayList(c6));
+ Action a6 = new Action();
+ a6.setType(ActionType.MOBILE_ALERT_STATIC);
+ a6.setDescription("Garage Door 3 closed");
+ a6.setDestinationId("*");
+ r6.setActions(CollectionUtils.asArrayList(a6));
+ RulesEngine.instance().dao().putRule(r6);
+
+ Rule r7 = new Rule();
+ r7.setAccountId(100);
+ Criteria c7 = new Criteria();
+ c7.setType(EventType.SWITCH_LEVEL);
+ c7.setSourceId("203");
+ c7.setOperator(Operator.EQUAL);
+ c7.setValue(1);
+ Criteria c7_2 = new Criteria();
+ c7_2.setType(EventType.TIME);
+ c7_2.setValue(79200);
+// c7_2.setValue(74400);
+ r7.setCriteria(CollectionUtils.asArrayList(c7, c7_2));
+ Action a7 = new Action();
+ a7.setType(ActionType.MOBILE_ALERT_STATIC);
+ a7.setDescription("Garage Door 1 is still open");
+ a7.setDestinationId("*");
+ r7.setActions(CollectionUtils.asArrayList(a7));
+ RulesEngine.instance().dao().putRule(r7);
+
+ Rule r8 = new Rule();
+ r8.setAccountId(100);
+ Criteria c8 = new Criteria();
+ c8.setType(EventType.SWITCH_LEVEL);
+ c8.setSourceId("204");
+ c8.setOperator(Operator.EQUAL);
+ c8.setValue(1);
+ Criteria c8_2 = new Criteria();
+ c8_2.setType(EventType.TIME);
+ c8_2.setValue(79200);
+// c8_2.setValue(74400);
+ r8.setCriteria(CollectionUtils.asArrayList(c8, c8_2));
+ Action a8 = new Action();
+ a8.setType(ActionType.MOBILE_ALERT_STATIC);
+ a8.setDescription("Garage Door 2 is still open");
+ a8.setDestinationId("*");
+ r8.setActions(CollectionUtils.asArrayList(a8));
+ RulesEngine.instance().dao().putRule(r8);
+
+ Rule r9 = new Rule();
+ r9.setAccountId(100);
+ Criteria c9 = new Criteria();
+ c9.setType(EventType.SWITCH_LEVEL);
+ c9.setSourceId("205");
+ c9.setOperator(Operator.EQUAL);
+ c9.setValue(1);
+ Criteria c9_2 = new Criteria();
+ c9_2.setType(EventType.TIME);
+ c9_2.setValue(79200);
+// c9_2.setValue(74400);
+ r9.setCriteria(CollectionUtils.asArrayList(c9, c9_2));
+ Action a9 = new Action();
+ a9.setType(ActionType.MOBILE_ALERT_STATIC);
+ a9.setDescription("Garage Door 3 is still open");
+ a9.setDestinationId("*");
+ r9.setActions(CollectionUtils.asArrayList(a9));
+ RulesEngine.instance().dao().putRule(r9);
+ RulesEngine.shutdown();
+ }
+}
diff --git a/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestRuleSchedule.java b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestRuleSchedule.java
new file mode 100644
index 0000000..df3c739
--- /dev/null
+++ b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestRuleSchedule.java
@@ -0,0 +1,23 @@
+package com.lanternsoftware;
+
+import com.lanternsoftware.datamodel.rules.EventType;
+import com.lanternsoftware.datamodel.rules.Rule;
+import com.lanternsoftware.rules.RulesEngine;
+import com.lanternsoftware.util.CollectionUtils;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+public class TestRuleSchedule {
+ public static void main(String[] args) {
+ TimeZone tz = TimeZone.getTimeZone("America/Chicago"); //TODO: Get from the current monitor account
+ List rules = CollectionUtils.filter(RulesEngine.instance().dao().getRulesForAccount(100), _r->CollectionUtils.anyQualify(_r.getAllCriteria(), _c->_c.getType() == EventType.TIME));
+ if (rules.isEmpty())
+ return;
+ Collection dates = CollectionUtils.aggregate(rules, _r->CollectionUtils.transform(_r.getAllCriteria(), _c->_c.getNextTriggerDate(tz), true));
+ Date nextDate = CollectionUtils.getSmallest(dates);
+
+ }
+}
diff --git a/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestSendAlert.java b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestSendAlert.java
new file mode 100644
index 0000000..7082f64
--- /dev/null
+++ b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestSendAlert.java
@@ -0,0 +1,36 @@
+package com.lanternsoftware;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.FirebaseOptions;
+import com.google.firebase.messaging.FirebaseMessaging;
+import com.google.firebase.messaging.Message;
+import com.lanternsoftware.dataaccess.rules.MongoRulesDataAccess;
+import com.lanternsoftware.dataaccess.rules.RulesDataAccess;
+import com.lanternsoftware.datamodel.rules.Alert;
+import com.lanternsoftware.datamodel.rules.FcmDevice;
+import com.lanternsoftware.util.LanternFiles;
+import com.lanternsoftware.util.dao.DaoSerializer;
+import com.lanternsoftware.util.dao.mongo.MongoConfig;
+import org.apache.commons.io.IOUtils;
+
+import java.io.FileInputStream;
+
+public class TestSendAlert {
+ public static void main(String[] args) {
+ RulesDataAccess dao = new MongoRulesDataAccess(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
+ for (FcmDevice d : dao.getFcmDevicesForAccount(100)) {
+ Alert alert = new Alert();
+ alert.setMessage("Test Alert");
+ Message msg = Message.builder().setToken(d.getToken()).putData("payload", DaoSerializer.toBase64ZipBson(alert)).putData("payloadClass", Alert.class.getCanonicalName()).build();
+ try {
+ FileInputStream is = new FileInputStream("d:\\zwave\\firebase\\account_key.json");
+ FirebaseOptions options = FirebaseOptions.builder().setCredentials(GoogleCredentials.fromStream(is)).build();
+ FirebaseMessaging.getInstance(FirebaseApp.initializeApp(options)).send(msg);
+ IOUtils.closeQuietly(is);
+ } catch (Exception _e) {
+ _e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestTimeRule.java b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestTimeRule.java
new file mode 100644
index 0000000..ace8c26
--- /dev/null
+++ b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestTimeRule.java
@@ -0,0 +1,21 @@
+package com.lanternsoftware;
+
+import com.lanternsoftware.datamodel.rules.Event;
+import com.lanternsoftware.datamodel.rules.EventType;
+import com.lanternsoftware.rules.RulesEngine;
+import com.lanternsoftware.util.DateUtils;
+import com.lanternsoftware.util.concurrency.ConcurrencyUtils;
+
+import java.util.TimeZone;
+
+public class TestTimeRule {
+ public static void main(String[] args) {
+ Event event = new Event();
+ event.setAccountId(100);
+ event.setTime(DateUtils.date(7, 15, 2021, 18, 30, 0, 0, TimeZone.getTimeZone("America/Chicago")));
+ event.setType(EventType.TIME);
+ RulesEngine.instance().fireEvent(event);
+ ConcurrencyUtils.sleep(200000);
+ RulesEngine.shutdown();
+ }
+}
diff --git a/rules/pom.xml b/rules/pom.xml
new file mode 100644
index 0000000..47c9545
--- /dev/null
+++ b/rules/pom.xml
@@ -0,0 +1,19 @@
+
+ 4.0.0
+ pom
+ com.lanternsoftware.rules
+ rules-reactor
+ rules-reactor
+ 1.0.0
+
+
+ 1.8
+ 1.8
+
+
+
+ lantern-dataaccess-rules
+ lantern-datamodel-rules
+ lantern-service-rules
+
+
\ No newline at end of file
diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java
index 5333a12..0bc70f1 100644
--- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java
+++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java
@@ -532,7 +532,6 @@ public class CollectionUtils {
return list;
}
-
public static void edit(Iterable _coll, IEditor _editor) {
if ((_coll == null) || (_editor == null))
return;
diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/LanternFiles.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/LanternFiles.java
index 340ca77..c4d5f47 100644
--- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/LanternFiles.java
+++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/LanternFiles.java
@@ -1,8 +1,11 @@
package com.lanternsoftware.util;
public abstract class LanternFiles {
- public static final String SOURCE_PATH = "C:\\lantern\\wc\\opensource\\LanternPowerMonitor\\";
- public static final String OPS_PATH = "D:\\zwave\\";
-// public static final String OPS_PATH = "D:\\zwave\\linux\\";
-// public static final String OPS_PATH = "/opt/tomcat/";
+ public static final String SOURCE_PATH = "C:\\lantern\\LanternPowerMonitor\\";
+// public static final String OPS_PATH = "D:\\zwave\\";
+// public static final String OPS_PATH = "D:\\zwave\\localhost\\";
+// public static final String OPS_PATH = "D:\\zwave\\mark4770\\";
+// public static final String OPS_PATH = "D:\\zwave\\prod\\";
+// public static final String OPS_PATH = "D:\\zwave\\prodremote\\";
+ public static final String OPS_PATH = "/opt/tomcat/";
}
diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/cryptography/AESTool.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/cryptography/AESTool.java
index b1c8b83..c4e9a18 100644
--- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/cryptography/AESTool.java
+++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/cryptography/AESTool.java
@@ -17,6 +17,8 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
+import com.lanternsoftware.util.LanternFiles;
+import com.lanternsoftware.util.ResourceLoader;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -76,6 +78,10 @@ public class AESTool {
System.out.println(builder.toString());
}
+ public static AESTool authTool() {
+ return new AESTool(ResourceLoader.loadFile(LanternFiles.OPS_PATH + "authKey.dat"));
+ }
+
/**
* @param _btKey the encoded form of a {@link SecretKey} object. See the {@link SecretKey#getEncoded()} method.
*/
diff --git a/util/lantern-util-dao-mongo/src/main/java/com/lanternsoftware/util/dao/mongo/MongoProxy.java b/util/lantern-util-dao-mongo/src/main/java/com/lanternsoftware/util/dao/mongo/MongoProxy.java
index 7b736e3..f46dc40 100644
--- a/util/lantern-util-dao-mongo/src/main/java/com/lanternsoftware/util/dao/mongo/MongoProxy.java
+++ b/util/lantern-util-dao-mongo/src/main/java/com/lanternsoftware/util/dao/mongo/MongoProxy.java
@@ -71,6 +71,8 @@ public class MongoProxy extends AbstractDaoProxy {
public MongoProxy(List _hosts, String _userName, String _password, String _clientKeystorePath, String _clientKeystorePassword, String _caKeystorePath, String _caKeystorePassword, String _dbName, String _authDbName) {
List listAddresses = new LinkedList<>();
+ if (CollectionUtils.isEmpty(_hosts))
+ _hosts = CollectionUtils.asArrayList("localhost");
for (String addr : _hosts) {
int portIdx = addr.indexOf(":");
if (portIdx > 0)
@@ -108,7 +110,7 @@ public class MongoProxy extends AbstractDaoProxy {
options = MongoClientOptions.builder().sslEnabled(false).build();
}
}
- client = new MongoClient(listAddresses, MongoCredential.createCredential(_userName, NullUtils.isNotEmpty(_authDbName) ? _authDbName : "admin", _password.toCharArray()), options);
+ client = NullUtils.isEmpty(_userName) ? new MongoClient(listAddresses, options) : new MongoClient(listAddresses, MongoCredential.createCredential(_userName, NullUtils.isNotEmpty(_authDbName) ? _authDbName : "admin", _password.toCharArray()), options);
dbName = _dbName;
}
diff --git a/util/lantern-util-dao-mongo/src/main/java/com/lanternsoftware/util/dao/mongo/dao/MongoConfigSerializer.java b/util/lantern-util-dao-mongo/src/main/java/com/lanternsoftware/util/dao/mongo/dao/MongoConfigSerializer.java
index b615123..746c513 100644
--- a/util/lantern-util-dao-mongo/src/main/java/com/lanternsoftware/util/dao/mongo/dao/MongoConfigSerializer.java
+++ b/util/lantern-util-dao-mongo/src/main/java/com/lanternsoftware/util/dao/mongo/dao/MongoConfigSerializer.java
@@ -1,13 +1,13 @@
package com.lanternsoftware.util.dao.mongo.dao;
-import com.lanternsoftware.util.CollectionUtils;
-import com.lanternsoftware.util.NullUtils;
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 com.lanternsoftware.util.dao.mongo.MongoConfig;
-
+import java.lang.String;
+import java.util.Collections;
+import java.util.List;
public class MongoConfigSerializer extends AbstractDaoSerializer
{
@@ -17,11 +17,16 @@ public class MongoConfigSerializer extends AbstractDaoSerializer
return MongoConfig.class;
}
+ @Override
+ public List getSupportedProxies() {
+ return Collections.singletonList(DaoProxyType.MONGO);
+ }
+
@Override
public DaoEntity toDaoEntity(MongoConfig _o)
{
DaoEntity d = new DaoEntity();
- d.put("hosts", CollectionUtils.commaSeparated(_o.getHosts()));
+ d.put("hosts", _o.getHosts());
d.put("username", _o.getUsername());
d.put("password", _o.getPassword());
d.put("client_keystore_path", _o.getClientKeystorePath());
@@ -37,7 +42,7 @@ public class MongoConfigSerializer extends AbstractDaoSerializer
public MongoConfig fromDaoEntity(DaoEntity _d)
{
MongoConfig o = new MongoConfig();
- o.setHosts(CollectionUtils.asArrayList(NullUtils.cleanSplit(DaoSerializer.getString(_d, "hosts"), ",")));
+ o.setHosts(DaoSerializer.getList(_d, "hosts", String.class));
o.setUsername(DaoSerializer.getString(_d, "username"));
o.setPassword(DaoSerializer.getString(_d, "password"));
o.setClientKeystorePath(DaoSerializer.getString(_d, "client_keystore_path"));
diff --git a/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/DaoSerializer.java b/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/DaoSerializer.java
index 3ed9a3b..e060935 100644
--- a/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/DaoSerializer.java
+++ b/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/DaoSerializer.java
@@ -20,6 +20,7 @@ import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
+import org.apache.commons.codec.binary.Base64;
import org.bson.BsonBinaryReader;
import org.bson.BsonBinaryWriter;
import org.bson.Document;
@@ -725,6 +726,14 @@ public class DaoSerializer {
return ZipUtils.zip(toBson(_entity, true));
}
+ public static String toBase64ZipBson(Object _o) {
+ return toBase64ZipBson(toDaoEntity(_o));
+ }
+
+ public static String toBase64ZipBson(DaoEntity _entity) {
+ return Base64.encodeBase64String(toZipBson(_entity));
+ }
+
public static T fromZipBson(byte[] _btZipBson, Class _class) {
return DaoSerializer.fromDaoEntity(fromZipBson(_btZipBson), _class);
}
@@ -733,6 +742,14 @@ public class DaoSerializer {
return fromBson(ZipUtils.unzip(_btZipBson));
}
+ public static T fromBase64ZipBson(String _zipBson, Class _class) {
+ return DaoSerializer.fromDaoEntity(fromBase64ZipBson(_zipBson), _class);
+ }
+
+ public static DaoEntity fromBase64ZipBson(String _zipBson) {
+ return fromBson(ZipUtils.unzip(Base64.decodeBase64(_zipBson)));
+ }
+
public static T fromBson(byte[] _btBson, Class _class) {
return fromDaoEntity(fromBson(_btBson), _class);
}
diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/AuthCode.java b/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/auth/AuthCode.java
similarity index 95%
rename from currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/AuthCode.java
rename to util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/auth/AuthCode.java
index fd5bf04..6f76879 100644
--- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/AuthCode.java
+++ b/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/auth/AuthCode.java
@@ -1,4 +1,4 @@
-package com.lanternsoftware.datamodel.currentmonitor;
+package com.lanternsoftware.util.dao.auth;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.dao.annotations.DBSerializable;
diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/AuthCodeSerializer.java b/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/auth/dao/AuthCodeSerializer.java
similarity index 86%
rename from currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/AuthCodeSerializer.java
rename to util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/auth/dao/AuthCodeSerializer.java
index f0afb65..bbbe20f 100644
--- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/AuthCodeSerializer.java
+++ b/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/auth/dao/AuthCodeSerializer.java
@@ -1,14 +1,12 @@
-package com.lanternsoftware.datamodel.currentmonitor.dao;
+package com.lanternsoftware.util.dao.auth.dao;
-import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
+import com.lanternsoftware.util.dao.auth.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;
diff --git a/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/jdbc/dao/JdbcConfigSerializer.java b/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/jdbc/dao/JdbcConfigSerializer.java
index 9df69ad..ecb3645 100644
--- a/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/jdbc/dao/JdbcConfigSerializer.java
+++ b/util/lantern-util-dao/src/main/java/com/lanternsoftware/util/dao/jdbc/dao/JdbcConfigSerializer.java
@@ -6,7 +6,6 @@ import com.lanternsoftware.util.dao.DaoProxyType;
import com.lanternsoftware.util.dao.DaoSerializer;
import com.lanternsoftware.util.dao.jdbc.DatabaseType;
import com.lanternsoftware.util.dao.jdbc.JdbcConfig;
-
import java.util.Collections;
import java.util.List;
diff --git a/util/lantern-util-dao/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer b/util/lantern-util-dao/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
index 6043f50..7b0b660 100644
--- a/util/lantern-util-dao/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
+++ b/util/lantern-util-dao/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer
@@ -1 +1,2 @@
+com.lanternsoftware.util.dao.auth.dao.AuthCodeSerializer
com.lanternsoftware.util.dao.jdbc.dao.JdbcConfigSerializer
diff --git a/util/lantern-util-servlet/src/main/java/com/lanternsoftware/util/servlet/FreemarkerServlet.java b/util/lantern-util-servlet/src/main/java/com/lanternsoftware/util/servlet/FreemarkerServlet.java
index d3e072c..24fa490 100644
--- a/util/lantern-util-servlet/src/main/java/com/lanternsoftware/util/servlet/FreemarkerServlet.java
+++ b/util/lantern-util-servlet/src/main/java/com/lanternsoftware/util/servlet/FreemarkerServlet.java
@@ -3,172 +3,79 @@ package com.lanternsoftware.util.servlet;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.dao.DaoEntity;
-import com.lanternsoftware.util.dao.DaoSerializer;
import freemarker.template.Configuration;
-import org.apache.commons.io.IOUtils;
import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.MediaType;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.HashMap;
import java.util.Map;
-public abstract class FreemarkerServlet extends HttpServlet {
- protected abstract Configuration getFreemarkerConfig();
-
- public static String[] getPath(HttpServletRequest _request) {
- String sPath = _request.getRequestURI().substring(_request.getContextPath().length());
- if (sPath.startsWith("/"))
- sPath = sPath.substring(1);
- String[] path = sPath.split("/");
- if ((path.length == 0) || (path[0].length() == 0))
- return new String[] { "index" };
- int iExtPos = CollectionUtils.last(path).lastIndexOf(".");
- if (iExtPos > -1) {
- path[path.length - 1] = CollectionUtils.last(path).substring(0, iExtPos);
- }
- return path;
- }
-
- public static void redirect(HttpServletResponse _response, String _sURL) throws IOException {
- _response.sendRedirect(_response.encodeRedirectURL(_sURL));
- }
-
- public void render(HttpServletResponse _rep, String _sHtmlResourceKey, Map _mapModel) {
- String html = FreemarkerUtil.render(getFreemarkerConfig(), _sHtmlResourceKey, _mapModel);
- if (html == null)
- _rep.setStatus(500);
- else
- setResponseHtml(_rep, html);
- }
+public abstract class FreemarkerServlet extends LanternServlet {
+ protected abstract Configuration getFreemarkerConfig();
- public static DaoEntity model(HttpServletRequest _req, String _name, Object _value) {
- DaoEntity model = model(_req);
- model.put(_name, _value);
- return model;
- }
+ public static String[] getPath(HttpServletRequest _request) {
+ String sPath = _request.getRequestURI().substring(_request.getContextPath().length());
+ if (sPath.startsWith("/"))
+ sPath = sPath.substring(1);
+ String[] path = sPath.split("/");
+ if ((path.length == 0) || (path[0].length() == 0))
+ return new String[]{"index"};
+ int iExtPos = CollectionUtils.last(path).lastIndexOf(".");
+ if (iExtPos > -1) {
+ path[path.length - 1] = CollectionUtils.last(path).substring(0, iExtPos);
+ }
+ return path;
+ }
- protected static DaoEntity model(HttpServletRequest _req) {
- DaoEntity model = new DaoEntity("context", _req.getContextPath());
- model.put("css_version", "1.0.0");
- return model;
- }
+ public static void redirect(HttpServletResponse _response, String _sURL) throws IOException {
+ _response.sendRedirect(_response.encodeRedirectURL(_sURL));
+ }
- public static T getSessionVar(HttpServletRequest _req, String _name) {
- return (T) _req.getSession().getAttribute(_name);
- }
+ public void render(HttpServletResponse _rep, String _sHtmlResourceKey, Map _mapModel) {
+ String html = FreemarkerUtil.render(getFreemarkerConfig(), _sHtmlResourceKey, _mapModel);
+ if (html == null)
+ _rep.setStatus(500);
+ else
+ setResponseHtml(_rep, html);
+ }
- public static void putSessionVar(HttpServletRequest _req, String _name, Object _var) {
- _req.getSession().setAttribute(_name, _var);
- }
+ public static DaoEntity model(HttpServletRequest _req, String _name, Object _value) {
+ DaoEntity model = model(_req);
+ model.put(_name, _value);
+ return model;
+ }
- protected String relativeOffset(HttpServletRequest _req) {
- String[] path = getPath(_req);
- StringBuilder offset = new StringBuilder();
- for (int i = 1; i < CollectionUtils.size(path); i++) {
- offset.append("../");
- }
- return offset.toString();
- }
-
- protected Cookie getCookie(HttpServletRequest _req, String _name) {
- if (_req.getCookies() != null) {
- for (Cookie c : _req.getCookies()) {
- if (NullUtils.isEqual(c.getName(), _name))
- return c;
- }
- }
- return null;
- }
+ protected static DaoEntity model(HttpServletRequest _req) {
+ DaoEntity model = new DaoEntity("context", _req.getContextPath());
+ model.put("css_version", "1.0.0");
+ return model;
+ }
- public static void setResponseHtml(HttpServletResponse _response, String _sHtml) {
- setResponseEntity(_response, MediaType.TEXT_HTML, _sHtml);
- }
+ public static T getSessionVar(HttpServletRequest _req, String _name) {
+ return (T) _req.getSession().getAttribute(_name);
+ }
- public static void setResponseEntity(HttpServletResponse _response, String _sContentType, String _sEntity) {
- setResponseEntity(_response, 200, _sContentType, _sEntity);
- }
+ public static void putSessionVar(HttpServletRequest _req, String _name, Object _var) {
+ _req.getSession().setAttribute(_name, _var);
+ }
- 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 getRequestPayload(HttpServletRequest _req, Class _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));
- }
+ protected String relativeOffset(HttpServletRequest _req) {
+ String[] path = getPath(_req);
+ StringBuilder offset = new StringBuilder();
+ for (int i = 1; i < CollectionUtils.size(path); i++) {
+ offset.append("../");
+ }
+ return offset.toString();
+ }
+ protected Cookie getCookie(HttpServletRequest _req, String _name) {
+ if (_req.getCookies() != null) {
+ for (Cookie c : _req.getCookies()) {
+ if (NullUtils.isEqual(c.getName(), _name))
+ return c;
+ }
+ }
+ return null;
+ }
}
diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CMServlet.java b/util/lantern-util-servlet/src/main/java/com/lanternsoftware/util/servlet/LanternServlet.java
similarity index 96%
rename from currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CMServlet.java
rename to util/lantern-util-servlet/src/main/java/com/lanternsoftware/util/servlet/LanternServlet.java
index ccc1bfd..348a4bf 100644
--- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/CMServlet.java
+++ b/util/lantern-util-servlet/src/main/java/com/lanternsoftware/util/servlet/LanternServlet.java
@@ -1,4 +1,4 @@
-package com.lanternsoftware.currentmonitor.servlet;
+package com.lanternsoftware.util.servlet;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.NullUtils;
@@ -13,7 +13,7 @@ import javax.ws.rs.core.MediaType;
import java.io.InputStream;
import java.io.OutputStream;
-public abstract class CMServlet extends HttpServlet {
+public abstract class LanternServlet extends HttpServlet {
public static void setResponseHtml(HttpServletResponse _response, String _sHtml) {
setResponseEntity(_response, MediaType.TEXT_HTML, _sHtml);
}
diff --git a/zwave/lantern-datamodel-zwave/pom.xml b/zwave/lantern-datamodel-zwave/pom.xml
index ca1fe14..a7e0089 100644
--- a/zwave/lantern-datamodel-zwave/pom.xml
+++ b/zwave/lantern-datamodel-zwave/pom.xml
@@ -1,6 +1,6 @@
4.0.0
- com.lanternsoftware.services
+ com.lanternsoftware.zwave
lantern-datamodel-zwave
jar
1.0.0
diff --git a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/Switch.java b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/Switch.java
index 5aca90e..426911e 100644
--- a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/Switch.java
+++ b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/Switch.java
@@ -154,6 +154,14 @@ public class Switch {
return type == SwitchType.RELAY;
}
+ public boolean isRelayButton() {
+ return type == SwitchType.RELAY_BUTTON;
+ }
+
+ public boolean isSecurity() {
+ return type == SwitchType.SECURITY;
+ }
+
public boolean isControlledBy(String _controllerUrl) {
return NullUtils.isEqual(_controllerUrl, controllerUrl);
}
diff --git a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/SwitchType.java b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/SwitchType.java
index e06e0b5..c1f1a60 100644
--- a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/SwitchType.java
+++ b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/SwitchType.java
@@ -7,5 +7,6 @@ public enum SwitchType {
SPACE_HEATER_THERMOSTAT,
THERMOMETER,
RELAY,
- SECURITY
+ SECURITY,
+ RELAY_BUTTON
}
diff --git a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/ZWaveConfig.java b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/ZWaveConfig.java
index 86a4af2..b79b769 100644
--- a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/ZWaveConfig.java
+++ b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/ZWaveConfig.java
@@ -13,6 +13,7 @@ public class ZWaveConfig {
private String commPort;
private String url;
private String masterUrl;
+ private String rulesUrl;
private List switches;
public int getAccountId() {
@@ -47,6 +48,14 @@ public class ZWaveConfig {
masterUrl = _masterUrl;
}
+ public String getRulesUrl() {
+ return rulesUrl;
+ }
+
+ public void setRulesUrl(String _rulesUrl) {
+ rulesUrl = _rulesUrl;
+ }
+
public List getSwitches() {
return switches;
}
diff --git a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/dao/SwitchSerializer.java b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/dao/SwitchSerializer.java
index 783d533..e7075ab 100644
--- a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/dao/SwitchSerializer.java
+++ b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/dao/SwitchSerializer.java
@@ -36,11 +36,11 @@ public class SwitchSerializer extends AbstractDaoSerializer
d.put("gpio_pin", _o.getGpioPin());
d.put("primary", _o.isPrimary());
d.put("hold", _o.isHold());
+ d.put("hidden", _o.isHidden());
d.put("thermometer_url", _o.getThermometerUrl());
d.put("controller_url", _o.getControllerUrl());
d.put("thermostat_mode", DaoSerializer.toEnumName(_o.getThermostatMode()));
d.put("low_level", _o.getLowLevel());
- d.put("hidden", _o.isHidden());
d.put("schedule", DaoSerializer.toDaoEntities(_o.getSchedule(), DaoProxyType.MONGO));
return d;
}
@@ -57,11 +57,11 @@ public class SwitchSerializer extends AbstractDaoSerializer
o.setGpioPin(DaoSerializer.getInteger(_d, "gpio_pin"));
o.setPrimary(DaoSerializer.getBoolean(_d, "primary"));
o.setHold(DaoSerializer.getBoolean(_d, "hold"));
+ o.setHidden(DaoSerializer.getBoolean(_d, "hidden"));
o.setThermometerUrl(DaoSerializer.getString(_d, "thermometer_url"));
o.setControllerUrl(DaoSerializer.getString(_d, "controller_url"));
o.setThermostatMode(DaoSerializer.getEnum(_d, "thermostat_mode", ThermostatMode.class));
o.setLowLevel(DaoSerializer.getInteger(_d, "low_level"));
- o.setHidden(DaoSerializer.getBoolean(_d, "hidden"));
o.setSchedule(DaoSerializer.getList(_d, "schedule", SwitchSchedule.class));
return o;
}
diff --git a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/dao/ZWaveConfigSerializer.java b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/dao/ZWaveConfigSerializer.java
index 9fb7bad..93e1614 100644
--- a/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/dao/ZWaveConfigSerializer.java
+++ b/zwave/lantern-datamodel-zwave/src/main/java/com/lanternsoftware/datamodel/zwave/dao/ZWaveConfigSerializer.java
@@ -31,6 +31,7 @@ public class ZWaveConfigSerializer extends AbstractDaoSerializer
d.put("comm_port", _o.getCommPort());
d.put("url", _o.getUrl());
d.put("master_url", _o.getMasterUrl());
+ d.put("rules_url", _o.getRulesUrl());
d.put("switches", DaoSerializer.toDaoEntities(_o.getSwitches(), DaoProxyType.MONGO));
return d;
}
@@ -43,6 +44,7 @@ public class ZWaveConfigSerializer extends AbstractDaoSerializer
o.setCommPort(DaoSerializer.getString(_d, "comm_port"));
o.setUrl(DaoSerializer.getString(_d, "url"));
o.setMasterUrl(DaoSerializer.getString(_d, "master_url"));
+ o.setRulesUrl(DaoSerializer.getString(_d, "rules_url"));
o.setSwitches(DaoSerializer.getList(_d, "switches", Switch.class));
return o;
}
diff --git a/zwave/lantern-service-zwave/pom.xml b/zwave/lantern-service-zwave/pom.xml
index fa4bdfb..06e808a 100644
--- a/zwave/lantern-service-zwave/pom.xml
+++ b/zwave/lantern-service-zwave/pom.xml
@@ -14,7 +14,7 @@
- com.lanternsoftware.services
+ com.lanternsoftware.zwave
lantern-datamodel-zwave
1.0.0
@@ -33,6 +33,11 @@
lantern-zwave
1.0.0
+
+ com.lanternsoftware.rules
+ lantern-datamodel-rules
+ 1.0.0
+
com.lanternsoftware.util
lantern-util-dao-mongo
diff --git a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/context/ZWaveApp.java b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/context/ZWaveApp.java
index 4957883..bd76c8f 100644
--- a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/context/ZWaveApp.java
+++ b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/context/ZWaveApp.java
@@ -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 originalSwitches = new HashMap<>();
private final Map switches = new HashMap<>();
private final Map 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 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 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 peers = CollectionUtils.transformToSet(modified, Switch::getControllerUrl);
+ Set 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;
diff --git a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/ConfigServlet.java b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/ConfigServlet.java
index af9995b..f8ddc78 100644
--- a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/ConfigServlet.java
+++ b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/ConfigServlet.java
@@ -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 {
diff --git a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/SecureServlet.java b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/SecureServlet.java
index e8442cc..6e2074c 100644
--- a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/SecureServlet.java
+++ b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/SecureServlet.java
@@ -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;
}
diff --git a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/SwitchServlet.java b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/SwitchServlet.java
index f427def..8593cbf 100644
--- a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/SwitchServlet.java
+++ b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/SwitchServlet.java
@@ -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;
diff --git a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/TemperatureServlet.java b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/TemperatureServlet.java
index e81a563..d0118d6 100644
--- a/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/TemperatureServlet.java
+++ b/zwave/lantern-service-zwave/src/main/java/com/lanternsoftware/zwave/servlet/TemperatureServlet.java
@@ -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;
diff --git a/zwave/lantern-service-zwave/src/test/java/com/lanternsoftware/zwave/GenerateSerializers.java b/zwave/lantern-service-zwave/src/test/java/com/lanternsoftware/zwave/GenerateSerializers.java
index 4f2efee..9955450 100644
--- a/zwave/lantern-service-zwave/src/test/java/com/lanternsoftware/zwave/GenerateSerializers.java
+++ b/zwave/lantern-service-zwave/src/test/java/com/lanternsoftware/zwave/GenerateSerializers.java
@@ -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);
}
}
diff --git a/zwave/lantern-uirt/pom.xml b/zwave/lantern-uirt/pom.xml
index 2aa546a..afee37e 100644
--- a/zwave/lantern-uirt/pom.xml
+++ b/zwave/lantern-uirt/pom.xml
@@ -1,6 +1,6 @@
4.0.0
- com.lanternsoftware.services
+ com.lanternsoftware.zwave
lantern-uirt
jar
1.0.0