From 9c52ebbcd18ca62c17883b0ea1415b976fe77842 Mon Sep 17 00:00:00 2001 From: cagrabowski Date: Thu, 31 Oct 2019 11:14:46 -0400 Subject: [PATCH 01/27] Fixed behavior when udoo neo does not respond --- .../java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java index 8108f8c..66a07e3 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java @@ -128,6 +128,7 @@ public void setSensors(){ public void pollDevice() { try { + attributes = new HashMap(); String command = ""; for(NeoSensor sensor: sensors){ command += sensor.getCommand(); @@ -167,20 +168,19 @@ public void pollDevice() { channel.disconnect(); session.disconnect(); - Map results = new HashMap(); for(NeoSensor sensor: sensors){ - results.putAll(sensor.parseResponse(lines)); + attributes.putAll(sensor.parseResponse(lines)); } - - attributes = results; convertRawReadings(); } catch (JSchException e1){ logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); logger.severe(e1.getMessage()); + attributes = new HashMap(); } catch (IOException e) { logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); logger.severe(e.getMessage()); + attributes = new HashMap(); } return; } From 719313e48d4a2d5a4d981746a3af66ad8a4b5135 Mon Sep 17 00:00:00 2001 From: cagrabowski Date: Tue, 19 Nov 2019 11:17:58 -0500 Subject: [PATCH 02/27] Reimplemented PHLE monitor with simple http requests --- build.gradle | 1 + .../java/edu/cmu/sei/kalki/IotInterface.java | 7 +- .../PhilipsHueLightEmulatorMonitor.java | 285 ++++++------------ 3 files changed, 100 insertions(+), 193 deletions(-) diff --git a/build.gradle b/build.gradle index 5835a51..9bde64c 100644 --- a/build.gradle +++ b/build.gradle @@ -32,5 +32,6 @@ dependencies { compile name: 'huelocalsdk' compile name: 'huesdkresources' compile 'com.jcraft:jsch:0.1.55' + compile 'org.apache.httpcomponents:httpclient:4.5.10' // compile name: 'tablelayout' } diff --git a/src/main/java/edu/cmu/sei/kalki/IotInterface.java b/src/main/java/edu/cmu/sei/kalki/IotInterface.java index f2d4697..c27c304 100644 --- a/src/main/java/edu/cmu/sei/kalki/IotInterface.java +++ b/src/main/java/edu/cmu/sei/kalki/IotInterface.java @@ -1,4 +1,5 @@ package edu.cmu.sei.kalki; +import edu.cmu.sei.kalki.Monitors.PhilipsHueLightEmulatorMonitor; import edu.cmu.sei.kalki.api.*; import edu.cmu.sei.ttg.kalki.models.Device; @@ -13,10 +14,12 @@ public static void main(String[] args) { try { apiUrl = args[0]; } catch (ArrayIndexOutOfBoundsException e) { } + PhilipsHueLightEmulatorMonitor monitor = new PhilipsHueLightEmulatorMonitor(1, "localhost", 8000, 3000); +// monitor.start(); - DeviceMonitor monitor = new DeviceMonitor("http://"+apiUrl+"/device-controller-api/"); +// DeviceMonitor monitor = new DeviceMonitor("http://"+apiUrl+"/device-controller-api/"); logger.info("[IotInterface] DeviceMonitor initialized."); - ApiServerStartup.start(monitor); +// ApiServerStartup.start(monitor); logger.info("[IotInterface] APIServerStartup started."); } } diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java index 75f6abe..b6d1b5d 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java @@ -1,228 +1,131 @@ package edu.cmu.sei.kalki.Monitors; -import edu.cmu.sei.ttg.kalki.models.*; +import edu.cmu.sei.ttg.kalki.models.DeviceStatus; + +import java.io.*; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.*; + +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.HttpClientBuilder; +import org.json.JSONException; +import org.json.JSONObject; + +import javax.net.ssl.*; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpHeaders; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; -import com.philips.lighting.hue.sdk.*; -import com.philips.lighting.model.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.UUID; - -//Adapted from https://github.com/PhilipsHue/PhilipsHueSDK-Java-MultiPlatform-Android/tree/master/JavaDesktopApp public class PhilipsHueLightEmulatorMonitor extends PollingMonitor { - private PHHueSDK phHueSDK; - private String username; + + private int deviceId; + private String authCode = "927bfc7c145594fc0b7b8b689ba37e9"; private String ip; - private static final int MAX_HUE=65535; + private int port = 8000; private List lights = new ArrayList(); - private DeviceStatus status; + Set lightKeys = new HashSet(); - public PhilipsHueLightEmulatorMonitor( int deviceId, String ip, int samplingRate, String url) { - super(); + public PhilipsHueLightEmulatorMonitor(int deviceId, String ip, int port, int samplingRate){ + this.deviceId = deviceId; + this.pollInterval = samplingRate; this.isPollable = true; - logger.info("[PhilipsHueLightEmulatorMonitor] Starting monitor for device: "+deviceId); - this.apiUrl = url; this.ip = ip; - - PHHueSDK phHueSDK = PHHueSDK.create(); - phHueSDK.getNotificationManager().registerSDKListener(listener); - this.pollInterval = samplingRate; - this.phHueSDK = PHHueSDK.getInstance(); - this.deviceId = deviceId; - this.username = "f450ab20effc384c3298bbcf745272a"; + this.port = port; + logger.info("[PhilipsHueLightEmulatorMonitor] Starting monitor."); start(); } - @Override - public void start(){ - connectToDevice(); - super.start(); - } - - public void findBridges() { - phHueSDK = PHHueSDK.getInstance(); - PHBridgeSearchManager sm = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE); - sm.search(true, true); - } - - private PHSDKListener listener = new PHSDKListener() { - - @Override - public void onAccessPointsFound(List accessPointsList) { - logger.info("Found AccessPoints!"); - } - - @Override - public void onAuthenticationRequired(PHAccessPoint accessPoint) { - // Start the Pushlink Authentication. - logger.info("AuthenticationRequired"); - phHueSDK.startPushlinkAuthentication(accessPoint); - } - - @Override - public void onBridgeConnected(PHBridge bridge, String username) { - phHueSDK.setSelectedBridge(bridge); - logger.info("Connected to bridge"); - String lastIpAddress = bridge.getResourceCache().getBridgeConfiguration().getIpAddress(); - logger.info("IP is : " + lastIpAddress); - logger.info("device ip is: "+ip); - if(!comparePorts(ip, lastIpAddress)) - return; - logger.info("Username is: " + username); - if(pollingEnabled){ - phHueSDK.disableAllHeartbeat(); - phHueSDK.enableHeartbeat(bridge, getHeartbeatInterval()); - } - setStatuses(bridge); - } - - @Override - public void onCacheUpdated(List arg0, PHBridge arg1) { - } - @Override - public void onConnectionLost(PHAccessPoint arg0) { - } + public String issueCommand(String path){ + String targetURL = "http://" + ip + ":" + Integer.toString(port) + "/api/" + authCode + "/" + path; + logger.info(targetURL); + try{ - @Override - public void onConnectionResumed(PHBridge arg0) { - } + int timeout = 5; + RequestConfig config = RequestConfig.custom() + .setConnectTimeout(timeout * 1000) + .setConnectionRequestTimeout(timeout * 1000) + .setSocketTimeout(timeout * 1000).build(); + CloseableHttpClient httpClient = + HttpClientBuilder.create().setDefaultRequestConfig(config).build(); + HttpGet request = new HttpGet(targetURL); - @Override - public void onError(int code, final String message) { - if (code == PHHueError.BRIDGE_NOT_RESPONDING) { - logger.info("Bridge not responding: " + message); - } - else if (code == PHMessageType.PUSHLINK_BUTTON_NOT_PRESSED) { - logger.info("Button not pressed: " + message); - } - else if (code == PHMessageType.PUSHLINK_AUTHENTICATION_FAILED) { - logger.info("Authentication failed: " + message); - } - else if (code == PHMessageType.BRIDGE_NOT_FOUND) { - logger.info("Bridge not found: " + message); - } - } + CloseableHttpResponse response = httpClient.execute(request); - @Override - public void onParsingErrors(List parsingErrorsList) { - for (PHHueParsingError parsingError: parsingErrorsList) { - logger.info("ParsingError : " + parsingError.getMessage()); + HttpEntity entity = response.getEntity(); + logger.info(entity.toString()); + if (entity != null) { + logger.info("converting to string"); + String result = EntityUtils.toString(entity); + logger.info("closing up"); + response.close(); + httpClient.close(); + return result; } - } - }; - - public void randomLights() { - PHBridge bridge = phHueSDK.getSelectedBridge(); - PHBridgeResourcesCache cache = bridge.getResourceCache(); - - List allLights = cache.getAllLights(); - Random rand = new Random(); - - for (PHLight light : allLights) { - PHLightState lightState = new PHLightState(); - lightState.setHue(rand.nextInt(MAX_HUE)); - bridge.updateLightState(light, lightState); // If no bridge response is required then use this simpler form. + return "Error"; + } catch (IOException e) { + logger.severe("[PhilipsHueLightEmulatorMonitor] Error: "+ e); + return "Error"; } } - private boolean comparePorts(String deviceUrl, String bridgeUrl){ - String[] dev = deviceUrl.split(":"); - String[] bridge = bridgeUrl.split(":"); - - if(dev[1].equals(bridge[1])) - return true; - - return false; - } - - public void setStatuses(PHBridge bridge) { - PHBridgeResourcesCache cache = bridge.getResourceCache(); - // And now you can get any resource you want, for example: - List myLights = cache.getAllLights(); + @Override + public void pollDevice() { lights = new ArrayList(); - for(PHLight light : myLights){ - PHLightState state = light.getLastKnownLightState(); - String id = light.getUniqueId(); - if (id == null){ - id = UUID.randomUUID().toString(); - light.setUniqueId(id); + String response = issueCommand("lights"); + logger.info("[PhilipsHueLightEmulatorMonitor] Getting current status from response " + response); + try { + JSONObject json = new JSONObject(response); + Iterator keys = json.keys(); + while(keys.hasNext()) { // Each key is a different light, build set of keys to report empty statuses when device can't be reached + String key = keys.next(); + if (!lightKeys.contains(key)) { + lightKeys.add(key); + } + } + for (String key : lightKeys){ + DeviceStatus light = new DeviceStatus(deviceId); + light.addAttribute("lightId", key); + JSONObject lightJson = json.getJSONObject(key); + String name = lightJson.getString("name"); + JSONObject state = lightJson.getJSONObject("state"); + String brightness = Integer.toString(state.getInt("bri")); + String hue = Integer.toString(state.getInt("hue")); + String isOn = Boolean.toString(state.getBoolean("on")); + light.addAttribute("hue", hue); + light.addAttribute("isOn", isOn); + light.addAttribute("brightness", brightness); + light.addAttribute("name", name); + lights.add(light); } - DeviceStatus newLight = new DeviceStatus(deviceId); - newLight.addAttribute("brightness", state.getBrightness().toString()); - newLight.addAttribute("hue", state.getHue().toString()); - newLight.addAttribute("isOn", state.isOn().toString()); - newLight.addAttribute("lightId", id); - lights.add(newLight); - } - } - - /** - * Connects to bridge using the given ip. - * @param ip address of the bridge. - * @return true if there was sufficient information to attempt a connection. - */ - public boolean connectToAccessPoint(String ip) { - if (username==null || ip == null) { - logger.info("Missing Last Username or Last IP. Last known connection not found."); - return false; - } - PHAccessPoint accessPoint = new PHAccessPoint(); - accessPoint.setIpAddress(ip); - accessPoint.setUsername(username); - phHueSDK.connect(accessPoint); - return true; - } - @Override - public void startPolling(){ - super.startPolling(); - PHBridge bridge = phHueSDK.getSelectedBridge(); - if (bridge != null){ - phHueSDK.enableHeartbeat(bridge, getHeartbeatInterval()); + } catch (JSONException err){ + logger.severe("[PhilipsHueLightEmulatorMonitor] Error: " + err.toString()); } } - /** - * Heartbeat interval needs to be slightly less than the pollInterval to guarantee correctness. - * @return - */ - private int getHeartbeatInterval(){ - return Math.max(pollInterval/3, pollInterval-300); - } - - @Override - public void stopPolling() { - super.stopPolling(); - PHBridge bridge = phHueSDK.getSelectedBridge(); - phHueSDK.disableHeartbeat(bridge); - } - - @Override - public void pollDevice() { - PHHueSDK phHueSDK = PHHueSDK.getInstance(); - PHBridge bridge = phHueSDK.getSelectedBridge(); - if (bridge == null){ - logger.severe("Null Bridge"); - return; - } - } @Override public void saveCurrentState() { - for(DeviceStatus light : lights){ + for (DeviceStatus light : lights) { sendToDeviceController(light); + logger.info("[PhilipsHueLightEmulatorMonitor] State saved: "+ light.toString()); } } - - public void connectToDevice() { - connectToAccessPoint(ip); - } -} +} \ No newline at end of file From 3589f82b71590c479c82d080cfd333ba8f47c3fb Mon Sep 17 00:00:00 2001 From: cagrabowski Date: Tue, 19 Nov 2019 11:35:53 -0500 Subject: [PATCH 03/27] small changes to PHLE auth --- .../cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java index b6d1b5d..44ee49b 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java @@ -32,7 +32,7 @@ public class PhilipsHueLightEmulatorMonitor extends PollingMonitor { private int deviceId; - private String authCode = "927bfc7c145594fc0b7b8b689ba37e9"; + private String authCode = "newdeveloper"; //Default username works for most GET operations private String ip; private int port = 8000; From 7e2f267fecaaa71fa7509ee39d84770d51e74ae1 Mon Sep 17 00:00:00 2001 From: cagrabowski Date: Wed, 20 Nov 2019 09:58:55 -0500 Subject: [PATCH 04/27] Changed behavior when emulator can't be reached --- .../sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java index 44ee49b..b3c88e8 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java @@ -99,7 +99,7 @@ public void pollDevice() { lightKeys.add(key); } } - for (String key : lightKeys){ + for (String key : lightKeys) { DeviceStatus light = new DeviceStatus(deviceId); light.addAttribute("lightId", key); JSONObject lightJson = json.getJSONObject(key); @@ -114,9 +114,12 @@ public void pollDevice() { light.addAttribute("name", name); lights.add(light); } - } catch (JSONException err){ logger.severe("[PhilipsHueLightEmulatorMonitor] Error: " + err.toString()); + for (String key : lightKeys){ + DeviceStatus light = new DeviceStatus(deviceId); + lights.add(light); + } } } From 8c07acb7c46251832a72db2d638e9edd1140f7e4 Mon Sep 17 00:00:00 2001 From: cam292 Date: Wed, 20 Nov 2019 13:47:20 -0500 Subject: [PATCH 05/27] Improved error handling in wemo script --- wemo.py | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/wemo.py b/wemo.py index e3e1995..205dba1 100644 --- a/wemo.py +++ b/wemo.py @@ -7,23 +7,25 @@ insight_ip = sys.argv[1] command = sys.argv[2] -#try: -device = Insight("http://"+insight_ip+":49153/setup.xml") -if command == "turn-off": - device.off() - print "Insight turned off:", device.name -if command == "turn-on": - device.on() - print "Insight turned on:", device.name -if command == "status": - result = device.insight_params - result['today_kwh'] = device.today_kwh - result['today_standby_time'] = device.today_standby_time - result['lastchange'] = result['lastchange'].strftime("%Y-%m-%d %H:%M:%S") - if(result['state'] == '1'): - result['isOn'] = True +try: + device = Insight("http://"+insight_ip+":49153/setup.xml") + if command == "turn-off": + device.off() + print "Insight turned off:", device.name + elif command == "turn-on": + device.on() + print "Insight turned on:", device.name + elif command == "status": + result = device.insight_params + result['today_kwh'] = device.today_kwh + result['today_standby_time'] = device.today_standby_time + result['lastchange'] = result['lastchange'].strftime("%Y-%m-%d %H:%M:%S") + if(result['state'] == '1'): + result['isOn'] = True + else: + result['isOn'] = False + print(result) else: - result['isOn'] = False - print(result) -#except: -# print("Unknown Device") + print "" +except: + print "" From 0582d7e7b1c5696353cc89c4be4b85054691dd97 Mon Sep 17 00:00:00 2001 From: cam292 Date: Wed, 20 Nov 2019 14:14:52 -0500 Subject: [PATCH 06/27] Updated Alert constructor in apiservlet for new model --- src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java b/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java index 6478104..31314b0 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java @@ -82,6 +82,7 @@ protected Alert parseAlert(JSONObject alert) { int deviceId = alert.getInt("deviceId"); Integer deviceStatusId = alert.getInt("deviceStatusId"); int alertTypeId = alert.getInt("alertTypeId"); - return new Alert(id, name, timestamp, alerterId, deviceId, deviceStatusId, alertTypeId); + String info = alert.getString("info"); + return new Alert(id, name, timestamp, alerterId, deviceId, deviceStatusId, alertTypeId, info); } } From 3f68153e652aa5f696ddfce610f0d3e620de78ba Mon Sep 17 00:00:00 2001 From: cam292 Date: Wed, 20 Nov 2019 14:30:27 -0500 Subject: [PATCH 07/27] Refactored constructor to match PollingMonitor --- .../kalki/Monitors/PhilipsHueLightEmulatorMonitor.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java index 44ee49b..8c37cde 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java @@ -34,17 +34,15 @@ public class PhilipsHueLightEmulatorMonitor extends PollingMonitor { private int deviceId; private String authCode = "newdeveloper"; //Default username works for most GET operations private String ip; - private int port = 8000; private List lights = new ArrayList(); Set lightKeys = new HashSet(); - public PhilipsHueLightEmulatorMonitor(int deviceId, String ip, int port, int samplingRate){ + public PhilipsHueLightEmulatorMonitor(int deviceId, String ip, int samplingRate, String url){ this.deviceId = deviceId; this.pollInterval = samplingRate; this.isPollable = true; this.ip = ip; - this.port = port; logger.info("[PhilipsHueLightEmulatorMonitor] Starting monitor."); start(); } @@ -52,7 +50,7 @@ public PhilipsHueLightEmulatorMonitor(int deviceId, String ip, int port, int sam public String issueCommand(String path){ - String targetURL = "http://" + ip + ":" + Integer.toString(port) + "/api/" + authCode + "/" + path; + String targetURL = "http://" + ip + "/api/" + authCode + "/" + path; logger.info(targetURL); try{ @@ -128,4 +126,4 @@ public void saveCurrentState() { logger.info("[PhilipsHueLightEmulatorMonitor] State saved: "+ light.toString()); } } -} \ No newline at end of file +} From 39f91b1fa7b191feaabb3424c967c5017c2c6bc9 Mon Sep 17 00:00:00 2001 From: cam292 Date: Wed, 20 Nov 2019 14:46:24 -0500 Subject: [PATCH 08/27] Fixed null pointer of apiUrl --- .../cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java index 8c37cde..0b35e40 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java @@ -43,6 +43,7 @@ public PhilipsHueLightEmulatorMonitor(int deviceId, String ip, int samplingRate, this.pollInterval = samplingRate; this.isPollable = true; this.ip = ip; + this.apiUrl = url; logger.info("[PhilipsHueLightEmulatorMonitor] Starting monitor."); start(); } From 11fa4044ab33e31177f63ff0acafb95f911db257 Mon Sep 17 00:00:00 2001 From: cagrabowski Date: Wed, 20 Nov 2019 15:53:33 -0500 Subject: [PATCH 09/27] Moved saving device status and non-responsive device handling to PollingMonitor --- .../PhilipsHueLightEmulatorMonitor.java | 54 ++++++------------- .../sei/kalki/Monitors/PollingMonitor.java | 17 ++++-- .../sei/kalki/Monitors/UdooNeoMonitor.java | 39 ++++++-------- .../kalki/Monitors/WeMoInsightMonitor.java | 13 ++--- 4 files changed, 47 insertions(+), 76 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java index 7818285..ce3de74 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java @@ -35,9 +35,6 @@ public class PhilipsHueLightEmulatorMonitor extends PollingMonitor { private String authCode = "newdeveloper"; //Default username works for most GET operations private String ip; - private List lights = new ArrayList(); - Set lightKeys = new HashSet(); - public PhilipsHueLightEmulatorMonitor(int deviceId, String ip, int samplingRate, String url){ this.deviceId = deviceId; this.pollInterval = samplingRate; @@ -85,49 +82,28 @@ public String issueCommand(String path){ } @Override - public void pollDevice() { - lights = new ArrayList(); + public void pollDevice(DeviceStatus status) { String response = issueCommand("lights"); logger.info("[PhilipsHueLightEmulatorMonitor] Getting current status from response " + response); try { JSONObject json = new JSONObject(response); - Iterator keys = json.keys(); - while(keys.hasNext()) { // Each key is a different light, build set of keys to report empty statuses when device can't be reached - String key = keys.next(); - if (!lightKeys.contains(key)) { - lightKeys.add(key); - } - } - for (String key : lightKeys) { - DeviceStatus light = new DeviceStatus(deviceId); - light.addAttribute("lightId", key); - JSONObject lightJson = json.getJSONObject(key); - String name = lightJson.getString("name"); - JSONObject state = lightJson.getJSONObject("state"); - String brightness = Integer.toString(state.getInt("bri")); - String hue = Integer.toString(state.getInt("hue")); - String isOn = Boolean.toString(state.getBoolean("on")); - light.addAttribute("hue", hue); - light.addAttribute("isOn", isOn); - light.addAttribute("brightness", brightness); - light.addAttribute("name", name); - lights.add(light); - } + Set keys = json.keySet(); + + String key = keys.iterator().next(); //Assumes only one light is connected, does not verify + status.addAttribute("lightId", key); + JSONObject lightJson = json.getJSONObject(key); + String name = lightJson.getString("name"); + JSONObject state = lightJson.getJSONObject("state"); + String brightness = Integer.toString(state.getInt("bri")); + String hue = Integer.toString(state.getInt("hue")); + String isOn = Boolean.toString(state.getBoolean("on")); + status.addAttribute("hue", hue); + status.addAttribute("isOn", isOn); + status.addAttribute("brightness", brightness); + status.addAttribute("name", name); } catch (JSONException err){ logger.severe("[PhilipsHueLightEmulatorMonitor] Error: " + err.toString()); - for (String key : lightKeys){ - DeviceStatus light = new DeviceStatus(deviceId); - lights.add(light); - } } } - - @Override - public void saveCurrentState() { - for (DeviceStatus light : lights) { - sendToDeviceController(light); - logger.info("[PhilipsHueLightEmulatorMonitor] State saved: "+ light.toString()); - } - } } diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java index 0b9bd6b..b549d13 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java @@ -1,19 +1,25 @@ package edu.cmu.sei.kalki.Monitors; +import edu.cmu.sei.ttg.kalki.models.DeviceSecurityState; +import edu.cmu.sei.ttg.kalki.models.DeviceStatus; + import java.util.Timer; import java.util.TimerTask; public abstract class PollingMonitor extends IotMonitor { /** - * Polls the device for updates. + * Polls the device for updates. Adds all device attributes to status. */ - public abstract void pollDevice(); + public abstract void pollDevice(DeviceStatus Status); /** * Saves the current state of the iot device to the database */ - public abstract void saveCurrentState(); + public void saveCurrentState(DeviceStatus status){ + sendToDeviceController(status); + logger.info("Sent status to device controller:" + status.toString()); + } /** * Connect to the device and begin monitoring. @@ -50,8 +56,9 @@ protected void stopPolling() { */ class PollTask extends TimerTask { public void run() { - pollDevice(); - saveCurrentState(); + DeviceStatus status = new DeviceStatus(deviceId); + pollDevice(status); // pollDevice adds attributes to currentStatus + saveCurrentState(status); } } diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java index 66a07e3..aab876b 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java @@ -24,9 +24,6 @@ public class UdooNeoMonitor extends PollingMonitor { private String password; private String ip; private int deviceId; - private DeviceStatus status; - - private Map attributes = new HashMap(); public UdooNeoMonitor(int deviceId, String ip, String username, String password, int samplingRate, String url){ this(deviceId, ip, samplingRate, url); @@ -125,10 +122,11 @@ public void setSensors(){ } @Override - public void pollDevice() { + public void pollDevice(DeviceStatus status) { try { - attributes = new HashMap(); + Map attributes = new HashMap(); + String command = ""; for(NeoSensor sensor: sensors){ command += sensor.getCommand(); @@ -171,39 +169,40 @@ public void pollDevice() { for(NeoSensor sensor: sensors){ attributes.putAll(sensor.parseResponse(lines)); } - convertRawReadings(); + convertRawReadings(attributes); + for (String key : attributes.keySet()){ + status.addAttribute(key, attributes.get(key)); + } } catch (JSchException e1){ logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); logger.severe(e1.getMessage()); - attributes = new HashMap(); } catch (IOException e) { logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); logger.severe(e.getMessage()); - attributes = new HashMap(); } return; } - public void convertRawReadings(){ + public void convertRawReadings(Map attributes){ //convert accelerometer readings to g's double accelCoefficient = 0.000244 / 4; - convertThreeAxisReading("accelerometer", accelCoefficient); + convertThreeAxisReading("accelerometer", accelCoefficient, attributes); //convert gyroscope readings to degrees/second double gyroCoefficient = 0.0625; - convertThreeAxisReading("gyroscope", gyroCoefficient); + convertThreeAxisReading("gyroscope", gyroCoefficient, attributes); //convert magnetometer readings to micro Teslas double magCoefficient = 0.1; - convertThreeAxisReading("magnetometer", magCoefficient); + convertThreeAxisReading("magnetometer", magCoefficient, attributes); //convert temperature readings to celsius double tempCoefficient = 1/1000; - convertTempReading("input", tempCoefficient); - convertTempReading("max", tempCoefficient); - convertTempReading("max_hyst", tempCoefficient); + convertTempReading("input", tempCoefficient, attributes); + convertTempReading("max", tempCoefficient, attributes); + convertTempReading("max_hyst", tempCoefficient, attributes); } - private void convertThreeAxisReading(String sensor, double coefficient){ + private void convertThreeAxisReading(String sensor, double coefficient, Map attributes){ double xReading = Double.valueOf(attributes.get(sensor+"X")) * coefficient; double yReading = Double.valueOf(attributes.get(sensor+"Y")) * coefficient; double zReading = Double.valueOf(attributes.get(sensor+"Z")) * coefficient; @@ -212,15 +211,9 @@ private void convertThreeAxisReading(String sensor, double coefficient){ attributes.replace(sensor+"Z", String.valueOf(zReading)); } - private void convertTempReading(String suffix, double coefficient) { + private void convertTempReading(String suffix, double coefficient, Map attributes) { double reading = Double.valueOf(attributes.get("temp"+suffix)) * coefficient; attributes.replace("temp"+suffix, String.valueOf(reading)); } - @Override - public void saveCurrentState() { - logger.info("[UdooNeoMonitor] Saving current state"); - status = new DeviceStatus(deviceId, attributes); - sendToDeviceController(status); - } } diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java index 0cc1ff7..ee282b5 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java @@ -31,7 +31,7 @@ public WeMoInsightMonitor(int deviceId, String ip, int samplingRate, String url) } @Override - public void pollDevice() { + public void pollDevice(DeviceStatus status) { attributes = new HashMap(); try { @@ -70,6 +70,9 @@ public void pollDevice() { while ((s = stdError.readLine()) != null) { logger.severe(s); } + for (String key : attributes.keySet()){ + status.addAttribute(key, attributes.get(key)); + } } catch (IOException e) { logger.severe("Error polling Wemo Insight: " + e.toString()); } catch (JSONException e) { @@ -78,12 +81,4 @@ public void pollDevice() { } } - - @Override - public void saveCurrentState() { - logger.info("[WeMoInsightMonitor] Saving current state"); - DeviceStatus wemo = new DeviceStatus(deviceId, attributes); - sendToDeviceController(wemo); - logger.info("[WeMoInsightMonitor] State saved: "+wemo.toString()); - } } From 707904c5dfc4a440fc11cd8568907351d6b0bc72 Mon Sep 17 00:00:00 2001 From: cagrabowski Date: Wed, 20 Nov 2019 16:16:10 -0500 Subject: [PATCH 10/27] Remvoed deviceId field from PHLE --- .../cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java index ce3de74..6b272c1 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java @@ -30,8 +30,6 @@ public class PhilipsHueLightEmulatorMonitor extends PollingMonitor { - - private int deviceId; private String authCode = "newdeveloper"; //Default username works for most GET operations private String ip; From 9c0ede753f037e55fbae7dbb467f62c6bcecb698 Mon Sep 17 00:00:00 2001 From: cam292 Date: Fri, 20 Dec 2019 11:00:21 -0500 Subject: [PATCH 11/27] Added constructor to PollTask to pass the deviceId --- .../edu/cmu/sei/kalki/Monitors/PollingMonitor.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java index b549d13..9925f0e 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java @@ -36,7 +36,7 @@ public void start(){ */ protected void startPolling() { pollTimer = new Timer(); - pollTimer.schedule(new PollTask(), pollInterval, pollInterval); + pollTimer.schedule(new PollTask(deviceId), pollInterval, pollInterval); timerGoing = true; } @@ -55,8 +55,14 @@ protected void stopPolling() { * Started from startPolling */ class PollTask extends TimerTask { + private int deviceId; + + public PollTask(int deviceId){ + this.deviceId = deviceId; + } + public void run() { - DeviceStatus status = new DeviceStatus(deviceId); + DeviceStatus status = new DeviceStatus(this.deviceId); pollDevice(status); // pollDevice adds attributes to currentStatus saveCurrentState(status); } From d48a637ae39c4b1912dbafb8136ffad4d0cfd2f1 Mon Sep 17 00:00:00 2001 From: cam292 Date: Fri, 20 Dec 2019 11:04:51 -0500 Subject: [PATCH 12/27] Removed duplicate class property --- src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java | 2 +- .../java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java index 49a840e..875874f 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java @@ -14,7 +14,7 @@ public abstract class IotMonitor { protected boolean isPollable; protected boolean pollingEnabled = true; protected boolean timerGoing = false; - public int deviceId; + protected int deviceId; protected final Logger logger = Logger.getLogger("iot-interface"); diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java index ee282b5..a2fcfc0 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java @@ -15,7 +15,6 @@ public class WeMoInsightMonitor extends PollingMonitor { private String deviceIp; private Boolean isOn; - private int deviceId; private Map attributes; private DeviceStatus status; From 1794726a45371a57d4f5af3def7c01b66f289c05 Mon Sep 17 00:00:00 2001 From: cam292 Date: Fri, 20 Dec 2019 11:19:51 -0500 Subject: [PATCH 13/27] Added printing of exception --- wemo.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wemo.py b/wemo.py index 205dba1..6655a18 100644 --- a/wemo.py +++ b/wemo.py @@ -11,10 +11,10 @@ device = Insight("http://"+insight_ip+":49153/setup.xml") if command == "turn-off": device.off() - print "Insight turned off:", device.name + print("Insight turned off: " + device.name) elif command == "turn-on": device.on() - print "Insight turned on:", device.name + print("Insight turned on: " + device.name) elif command == "status": result = device.insight_params result['today_kwh'] = device.today_kwh @@ -26,6 +26,6 @@ result['isOn'] = False print(result) else: - print "" -except: - print "" + print("Unknown command") +except Exception as e: + print("Exception happened " + str(e)) From cbabda197d9e571b8b3a3edd50b141cf88c73903 Mon Sep 17 00:00:00 2001 From: cam292 Date: Fri, 20 Dec 2019 11:23:59 -0500 Subject: [PATCH 14/27] Added run script to set proxy env variables properly --- run.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 run.sh diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..1ce5653 --- /dev/null +++ b/run.sh @@ -0,0 +1,5 @@ +export http_proxy="" +export https_proxy="" +export HTTP_PROXY="" +export HTTPS_PROXY="" +./gradlew run From 6bf58d2ad1f589eb4335262f5c7d126d8d08786c Mon Sep 17 00:00:00 2001 From: cam292 Date: Fri, 20 Dec 2019 11:38:43 -0500 Subject: [PATCH 15/27] Added debugging log statements to wemo command sender --- .../edu/cmu/sei/kalki/commanders/WemoCommandSender.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java b/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java index 777d3e5..41958ec 100644 --- a/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java @@ -44,17 +44,25 @@ private static void sendCommand(Device device, DeviceCommand command) { try { Process p = Runtime.getRuntime().exec(args); + logger.info("[WemoCommandSender] Python script executed"); + BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); + logger.info("[WemoCommandSender] Input stream captured"); + BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); + logger.info("[WemoCommandSender] Error stream captured"); + + logger.info("[WemoCommandSender] Processing input stream"); // read the output from the command while ((s = stdInput.readLine()) != null) { logger.info("[WemoCommandSender] " + s); } + logger.info("[WemoCommandSender] Processing error stream"); // read any errors from the attempted command while ((s = stdError.readLine()) != null) { logger.severe("[WemoCommandSender] Error with wemo.py: "+s); From b49cef33ab0e06e27fe39e4b0e463ea21599113f Mon Sep 17 00:00:00 2001 From: cam292 Date: Thu, 16 Jan 2020 13:09:32 -0500 Subject: [PATCH 16/27] Removed usage of philips hue sdk from phlecommandsender --- .../kalki/commanders/PhleCommandSender.java | 116 +++++------------- 1 file changed, 34 insertions(+), 82 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/commanders/PhleCommandSender.java b/src/main/java/edu/cmu/sei/kalki/commanders/PhleCommandSender.java index bc83d80..6459034 100644 --- a/src/main/java/edu/cmu/sei/kalki/commanders/PhleCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/commanders/PhleCommandSender.java @@ -10,44 +10,41 @@ import edu.cmu.sei.ttg.kalki.models.StageLog; import org.json.JSONObject; +import java.io.BufferedReader; +import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.net.HttpURLConnection; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Logger; public class PhleCommandSender { - private static PHHueSDK phHueSDK; private static Logger logger = Logger.getLogger("iot-interface"); public static void sendCommands(Device device, List commands, String apiUrl){ logger.info("[PhleCommandSender] Sending commands to PHLE: "+device.getId()); - connectToHue(device); - PHBridge bridge = null; - for (int i=0; i < 10 && bridge == null; i++){ - logger.info("Waiting to discover PHLE bridge..."); - try {Thread.sleep(100);}catch (Exception e) { } - bridge = phHueSDK.getSelectedBridge(); - } - if(bridge == null){ - logger.severe("Unable to connect to PHLE bridge & send commands to device: "+device.getId()); + + JSONObject lights = getAllLights(device.getIp()); + if(lights == null){ + logger.severe("[PhleCommandSender] Unable to get lights from bridge"); return; } - PHBridgeResourcesCache cache = bridge.getResourceCache(); - List lights = cache.getAllLights(); - for(int i=0;i< lights.size();i++){ + Iterator lightIds = lights.keys(); + while(lightIds.hasNext()){ + int id = Integer.parseInt(lightIds.next()); for(DeviceCommand command: commands){ switch (command.getName()){ case "turn-on": logger.info("[PhleCommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); - sendIsOn(device.getIp(), i+1,"true"); + sendIsOn(device.getIp(), id,"true"); logSendCommand(device, command.getName(), apiUrl); break; case "turn-off": logger.info("[PhleCommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); - sendIsOn(device.getIp(), i+1,"false"); + sendIsOn(device.getIp(), id,"false"); logSendCommand(device, command.getName(), apiUrl); break; case "set-name": @@ -72,7 +69,8 @@ private static void logSendCommand(Device device, String command, String apiUrl) private static void sendIsOn(String ip, int lightId, String isOn) { try { - URL url = new URL("http://"+ip+"/api/newdeveloper/lights/"+lightId+"/state/"); + + URL url = new URL("http://"+ip+"/api/newdeveloper/lights/"+lightId+"/state"); HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); httpCon.setDoOutput(true); httpCon.setRequestMethod("PUT"); @@ -81,78 +79,32 @@ private static void sendIsOn(String ip, int lightId, String isOn) { out.write(json.toString()); out.close(); httpCon.getInputStream(); + httpCon.disconnect(); } catch (Exception e) { logger.severe("[PhleCommandSender] Error sending command to device!"); logger.severe(e.getMessage()); } } - private static void connectToHue(Device device) { - phHueSDK = PHHueSDK.getInstance(); - phHueSDK.getNotificationManager().registerSDKListener(listener); - - PHAccessPoint accessPoint = new PHAccessPoint(); - accessPoint.setIpAddress(device.getIp()); - accessPoint.setUsername("newdeveloper"); - phHueSDK.connect(accessPoint); - } - - private static PHSDKListener listener = new PHSDKListener() { - - @Override - public void onAccessPointsFound(List accessPointsList) { - logger.info("Found AccessPoints!"); - } - - @Override - public void onAuthenticationRequired(PHAccessPoint accessPoint) { - // Start the Pushlink Authentication. - logger.info("AuthenticationRequired"); - phHueSDK.startPushlinkAuthentication(accessPoint); - } - - @Override - public void onBridgeConnected(PHBridge bridge, String username) { - phHueSDK.setSelectedBridge(bridge); - logger.info("Connected to bridge"); -/* String lastIpAddress = bridge.getResourceCache().getBridgeConfiguration().getIpAddress(); - logger.info("IP is : " + lastIpAddress); - logger.info("Username is: " + username);*/ - } - - @Override - public void onCacheUpdated(List arg0, PHBridge arg1) { - } - - @Override - public void onConnectionLost(PHAccessPoint arg0) { - } - - @Override - public void onConnectionResumed(PHBridge arg0) { - } - - @Override - public void onError(int code, final String message) { - if (code == PHHueError.BRIDGE_NOT_RESPONDING) { - logger.severe("Bridge not responding: " + message); - } - else if (code == PHMessageType.PUSHLINK_BUTTON_NOT_PRESSED) { - logger.severe("Button not pressed: " + message); - } - else if (code == PHMessageType.PUSHLINK_AUTHENTICATION_FAILED) { - logger.severe("Authentication failed: " + message); - } - else if (code == PHMessageType.BRIDGE_NOT_FOUND) { - logger.severe("Bridge not found: " + message); - } - } - - @Override - public void onParsingErrors(List parsingErrorsList) { - for (PHHueParsingError parsingError: parsingErrorsList) { - logger.severe("ParsingError : " + parsingError.getMessage()); + private static JSONObject getAllLights(String apiUrl) { + JSONObject json = null; + try { + URL url = new URL("http://"+apiUrl+"/api/newdeveloper/lights"); + HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); + httpCon.setRequestMethod("GET"); + BufferedReader in = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); + StringBuilder response = new StringBuilder(); + String line = ""; + while((line = in.readLine()) != null) { + response.append(line); } + logger.info(response.toString()); + json = new JSONObject(response.toString()); + httpCon.disconnect(); + } catch (Exception e) { + logger.severe("[PhleCommandSender] Error getting all lights."); + logger.severe(e.getMessage()); } - }; + return json; + } } From 90bf01033bfdbba70be4ff8b47ea3c68baf98ea0 Mon Sep 17 00:00:00 2001 From: cam292 Date: Fri, 17 Jan 2020 14:30:15 -0500 Subject: [PATCH 17/27] Refactored commmand senders heirarchy to function like the IoTMonitors --- .../cmu/sei/kalki/api/SendCommandServlet.java | 2 +- .../kalki/commanders/DeviceCommandSender.java | 68 ++++++++++++++----- .../kalki/commanders/PhleCommandSender.java | 26 ++----- .../kalki/commanders/WemoCommandSender.java | 16 ++--- 4 files changed, 62 insertions(+), 50 deletions(-) diff --git a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java b/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java index 94e84d5..10c9e74 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java @@ -50,7 +50,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) logger.info("[SendCommandServlet] Sending commands to device: "+device.toString()); DeviceMonitor monitor = (DeviceMonitor) getServletContext().getAttribute("monitor"); - DeviceCommandSender.sendCommands(device, commandList, monitor.getApiUrl()); + DeviceCommandSender.processCommands(device, commandList, monitor.getApiUrl()); } private List parseCommandList(JSONArray commandList) { diff --git a/src/main/java/edu/cmu/sei/kalki/commanders/DeviceCommandSender.java b/src/main/java/edu/cmu/sei/kalki/commanders/DeviceCommandSender.java index 1239a1e..d09b6fb 100644 --- a/src/main/java/edu/cmu/sei/kalki/commanders/DeviceCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/commanders/DeviceCommandSender.java @@ -1,33 +1,67 @@ package edu.cmu.sei.kalki.commanders; +import edu.cmu.sei.kalki.utils.DeviceControllerApi; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; import edu.cmu.sei.ttg.kalki.models.DeviceType; +import edu.cmu.sei.ttg.kalki.models.StageLog; +import java.lang.reflect.Constructor; import java.util.List; import java.util.logging.Logger; public abstract class DeviceCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); - public static void sendCommands(Device device, List commands, String apiUrl){ - DeviceType deviceType = device.getType(); - switch (deviceType.getId()){ - case 1: // DLC - logger.severe("[DeviceCommandSender] Error: there are no commands for a DLink Camera"); - break; - case 2: // UNTS - logger.severe("[DeviceCommandSender] Error: there are no commands for a Udoo Neo with Temperature Sensor"); - break; - case 3: //WeMo - WemoCommandSender.sendCommands(device, commands, apiUrl); - break; - case 4: // PHLE - PhleCommandSender.sendCommands(device, commands, apiUrl); - break; - default: - logger.severe("[DeviceCommandSender] System not configured to send commands to type: " + deviceType.getName()); + protected Device device; + protected List commands; + protected String apiUrl; + + + public DeviceCommandSender(){} + + public DeviceCommandSender(Device device, List commands, String apiUrl){ + this.device = device; + this.commands = commands; + this.apiUrl = apiUrl; + } + + public static void processCommands(Device device, List commands, String apiUrl){ + try { + String classPath = "edu.cmu.kalki.commanders."+getDeviceTypeCommandSenderClassName(device.getType().getName()); + Constructor con = Class.forName(classPath).getConstructor(Device.class, List.class, String.class); + DeviceCommandSender commandSender = (DeviceCommandSender) con.newInstance(device, commands, apiUrl); + commandSender.sendCommands(); + } catch (Exception e) { + logger.severe("[DeviceCommandSender] Error: there are no commands for a "+device.getType().getName()); } } + /** + * Removes spaces from device type's name and append 'Monitor' + * @param devTypeName + * @return device type's monitor class name + */ + private static String getDeviceTypeCommandSenderClassName(String devTypeName) { + String[] temp = devTypeName.split(" "); + String name = ""; + for(int i=0;i commands, String apiUrl){ + @Override + public void sendCommands() { logger.info("[PhleCommandSender] Sending commands to PHLE: "+device.getId()); @@ -35,17 +27,17 @@ public static void sendCommands(Device device, List commands, Str Iterator lightIds = lights.keys(); while(lightIds.hasNext()){ int id = Integer.parseInt(lightIds.next()); - for(DeviceCommand command: commands){ + for(DeviceCommand command: this.commands){ switch (command.getName()){ case "turn-on": logger.info("[PhleCommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"true"); - logSendCommand(device, command.getName(), apiUrl); + logSendCommand(command.getName()); break; case "turn-off": logger.info("[PhleCommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"false"); - logSendCommand(device, command.getName(), apiUrl); + logSendCommand(command.getName()); break; case "set-name": case "set-brightness": @@ -61,12 +53,6 @@ public static void sendCommands(Device device, List commands, Str } - private static void logSendCommand(Device device, String command, String apiUrl) { - logger.info("[PhleCommandSender] Logging that a command was sent to the device."); - StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.SEND_COMMAND, StageLog.Stage.FINISH, "Sent command to device: "+command); - DeviceControllerApi.sendLog(log, apiUrl); - } - private static void sendIsOn(String ip, int lightId, String isOn) { try { diff --git a/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java b/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java index 41958ec..71db0b6 100644 --- a/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java @@ -1,17 +1,14 @@ package edu.cmu.sei.kalki.commanders; -import edu.cmu.sei.kalki.utils.DeviceControllerApi; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; -import edu.cmu.sei.ttg.kalki.models.StageLog; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.List; import java.util.logging.Logger; -public class WemoCommandSender { +public class WemoCommandSender extends DeviceCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); private static String[] args = new String[]{ "python", @@ -20,7 +17,8 @@ public class WemoCommandSender { "command" }; - public static void sendCommands(Device device, List commands, String apiUrl) { + @Override + public void sendCommands() { logger.info("[WemoCommandSender] Sending commands to device: "+device.getId()); for(DeviceCommand command: commands) { @@ -28,7 +26,7 @@ public static void sendCommands(Device device, List commands, Str case "turn-on": case "turn-off": sendCommand(device, command); - logSendCommand(device, command.getName(), apiUrl); + logSendCommand(command.getName()); break; default: logger.severe("[WemoCommandSender] Command: " + command.getName() + " is not a valid command for a Wemo Insight"); @@ -73,10 +71,4 @@ private static void sendCommand(Device device, DeviceCommand command) { } } - private static void logSendCommand(Device device, String command, String apiUrl) { - logger.info("[WemoCommandSender] Logging that a command was sent to the device."); - StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.SEND_COMMAND, StageLog.Stage.FINISH, "Sent command to device: "+command); - DeviceControllerApi.sendLog(log, apiUrl); - } - } From 3652d05d6fe445d33f6d4e981c4afab810fb3613 Mon Sep 17 00:00:00 2001 From: cam292 Date: Fri, 17 Jan 2020 15:12:21 -0500 Subject: [PATCH 18/27] Renamed command senders to be CommandSender --- .../kalki/commanders/DeviceCommandSender.java | 2 +- ...PhilipsHueLightEmulatorCommandSender.java} | 16 +++++++------- ...der.java => WeMoInsightCommandSender.java} | 22 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) rename src/main/java/edu/cmu/sei/kalki/commanders/{PhleCommandSender.java => PhilipsHueLightEmulatorCommandSender.java} (77%) rename src/main/java/edu/cmu/sei/kalki/commanders/{WemoCommandSender.java => WeMoInsightCommandSender.java} (63%) diff --git a/src/main/java/edu/cmu/sei/kalki/commanders/DeviceCommandSender.java b/src/main/java/edu/cmu/sei/kalki/commanders/DeviceCommandSender.java index d09b6fb..741929f 100644 --- a/src/main/java/edu/cmu/sei/kalki/commanders/DeviceCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/commanders/DeviceCommandSender.java @@ -57,7 +57,7 @@ private static String getDeviceTypeCommandSenderClassName(String devTypeName) { * @param command The name of the command */ protected void logSendCommand(String command) { - logger.info("[PhleCommandSender] Logging that a command was sent to the device."); + logger.info("[DeviceCommandSender] Logging that a command was sent to the device."); StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.SEND_COMMAND, StageLog.Stage.FINISH, "Sent command to device: "+command); DeviceControllerApi.sendLog(log, apiUrl); } diff --git a/src/main/java/edu/cmu/sei/kalki/commanders/PhleCommandSender.java b/src/main/java/edu/cmu/sei/kalki/commanders/PhilipsHueLightEmulatorCommandSender.java similarity index 77% rename from src/main/java/edu/cmu/sei/kalki/commanders/PhleCommandSender.java rename to src/main/java/edu/cmu/sei/kalki/commanders/PhilipsHueLightEmulatorCommandSender.java index 9d6b62d..e28cbc9 100644 --- a/src/main/java/edu/cmu/sei/kalki/commanders/PhleCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/commanders/PhilipsHueLightEmulatorCommandSender.java @@ -11,17 +11,17 @@ import java.util.Iterator; import java.util.logging.Logger; -public class PhleCommandSender extends DeviceCommandSender { +public class PhilipsHueLightEmulatorCommandSender extends DeviceCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); @Override public void sendCommands() { - logger.info("[PhleCommandSender] Sending commands to PHLE: "+device.getId()); + logger.info("[PhilipsHueLightEmulatorCommandSender] Sending commands to PHLE: "+device.getId()); JSONObject lights = getAllLights(device.getIp()); if(lights == null){ - logger.severe("[PhleCommandSender] Unable to get lights from bridge"); + logger.severe("[PhilipsHueLightEmulatorCommandSender] Unable to get lights from bridge"); return; } Iterator lightIds = lights.keys(); @@ -30,12 +30,12 @@ public void sendCommands() { for(DeviceCommand command: this.commands){ switch (command.getName()){ case "turn-on": - logger.info("[PhleCommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); + logger.info("[PhilipsHueLightEmulatorCommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"true"); logSendCommand(command.getName()); break; case "turn-off": - logger.info("[PhleCommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); + logger.info("[PhilipsHueLightEmulatorCommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"false"); logSendCommand(command.getName()); break; @@ -46,7 +46,7 @@ public void sendCommands() { case "set-group": case "set-scene": default: - logger.severe("[PhleCommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); + logger.severe("[PhilipsHueLightEmulatorCommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); } } } @@ -67,7 +67,7 @@ private static void sendIsOn(String ip, int lightId, String isOn) { httpCon.getInputStream(); httpCon.disconnect(); } catch (Exception e) { - logger.severe("[PhleCommandSender] Error sending command to device!"); + logger.severe("[PhilipsHueLightEmulatorCommandSender] Error sending command to device!"); logger.severe(e.getMessage()); } } @@ -88,7 +88,7 @@ private static JSONObject getAllLights(String apiUrl) { json = new JSONObject(response.toString()); httpCon.disconnect(); } catch (Exception e) { - logger.severe("[PhleCommandSender] Error getting all lights."); + logger.severe("[PhilipsHueLightEmulatorCommandSender] Error getting all lights."); logger.severe(e.getMessage()); } return json; diff --git a/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java b/src/main/java/edu/cmu/sei/kalki/commanders/WeMoInsightCommandSender.java similarity index 63% rename from src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java rename to src/main/java/edu/cmu/sei/kalki/commanders/WeMoInsightCommandSender.java index 71db0b6..44aa21b 100644 --- a/src/main/java/edu/cmu/sei/kalki/commanders/WemoCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/commanders/WeMoInsightCommandSender.java @@ -8,7 +8,7 @@ import java.io.InputStreamReader; import java.util.logging.Logger; -public class WemoCommandSender extends DeviceCommandSender { +public class WeMoInsightCommandSender extends DeviceCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); private static String[] args = new String[]{ "python", @@ -19,7 +19,7 @@ public class WemoCommandSender extends DeviceCommandSender { @Override public void sendCommands() { - logger.info("[WemoCommandSender] Sending commands to device: "+device.getId()); + logger.info("[WeMoInsightCommandSender] Sending commands to device: "+device.getId()); for(DeviceCommand command: commands) { switch (command.getName()){ @@ -29,7 +29,7 @@ public void sendCommands() { logSendCommand(command.getName()); break; default: - logger.severe("[WemoCommandSender] Command: " + command.getName() + " is not a valid command for a Wemo Insight"); + logger.severe("[WeMoInsightCommandSender] Command: " + command.getName() + " is not a valid command for a Wemo Insight"); } } } @@ -42,31 +42,31 @@ private static void sendCommand(Device device, DeviceCommand command) { try { Process p = Runtime.getRuntime().exec(args); - logger.info("[WemoCommandSender] Python script executed"); + logger.info("[WeMoInsightCommandSender] Python script executed"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); - logger.info("[WemoCommandSender] Input stream captured"); + logger.info("[WeMoInsightCommandSender] Input stream captured"); BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); - logger.info("[WemoCommandSender] Error stream captured"); + logger.info("[WeMoInsightCommandSender] Error stream captured"); - logger.info("[WemoCommandSender] Processing input stream"); + logger.info("[WeMoInsightCommandSender] Processing input stream"); // read the output from the command while ((s = stdInput.readLine()) != null) { - logger.info("[WemoCommandSender] " + s); + logger.info("[WeMoInsightCommandSender] " + s); } - logger.info("[WemoCommandSender] Processing error stream"); + logger.info("[WeMoInsightCommandSender] Processing error stream"); // read any errors from the attempted command while ((s = stdError.readLine()) != null) { - logger.severe("[WemoCommandSender] Error with wemo.py: "+s); + logger.severe("[WeMoInsightCommandSender] Error with wemo.py: "+s); } } catch (IOException e) { - logger.severe("[WemoCommandSender] Error reading response from " + device.getId() + ") " + device.getName()); + logger.severe("[WeMoInsightCommandSender] Error reading response from " + device.getId() + ") " + device.getName()); logger.severe(e.getMessage()); } } From 63c4a5043bb0e86e8e579f9162a9514ebbe1085f Mon Sep 17 00:00:00 2001 From: cam292 Date: Fri, 17 Jan 2020 15:58:09 -0500 Subject: [PATCH 19/27] Created new package devicetypes with a package for each devicetype containing monitor and commandsender classes --- .../java/edu/cmu/sei/kalki/IotInterface.java | 1 - .../cmu/sei/kalki/Monitors/IotMonitor.java | 18 ++----------- .../cmu/sei/kalki/api/SendCommandServlet.java | 2 +- .../DeviceCommandSender.java | 21 +++------------- .../DLinkCamera/Monitor.java} | 9 ++++--- .../CommandSender.java} | 19 +++++++------- .../PhilipsHueLightEmulator/Monitor.java} | 15 +++++------ .../UdooNeo/Monitor.java} | 19 +++++++------- .../WeMoInsight/CommandSender.java} | 25 ++++++++++--------- .../WeMoInsight/Monitor.java} | 9 ++++--- 10 files changed, 57 insertions(+), 81 deletions(-) rename src/main/java/edu/cmu/sei/kalki/{commanders => commandsender}/DeviceCommandSender.java (73%) rename src/main/java/edu/cmu/sei/kalki/{Monitors/DLinkCameraMonitor.java => devicetypes/DLinkCamera/Monitor.java} (68%) rename src/main/java/edu/cmu/sei/kalki/{commanders/PhilipsHueLightEmulatorCommandSender.java => devicetypes/PhilipsHueLightEmulator/CommandSender.java} (76%) rename src/main/java/edu/cmu/sei/kalki/{Monitors/PhilipsHueLightEmulatorMonitor.java => devicetypes/PhilipsHueLightEmulator/Monitor.java} (86%) rename src/main/java/edu/cmu/sei/kalki/{Monitors/UdooNeoMonitor.java => devicetypes/UdooNeo/Monitor.java} (90%) rename src/main/java/edu/cmu/sei/kalki/{commanders/WeMoInsightCommandSender.java => devicetypes/WeMoInsight/CommandSender.java} (62%) rename src/main/java/edu/cmu/sei/kalki/{Monitors/WeMoInsightMonitor.java => devicetypes/WeMoInsight/Monitor.java} (90%) diff --git a/src/main/java/edu/cmu/sei/kalki/IotInterface.java b/src/main/java/edu/cmu/sei/kalki/IotInterface.java index c4c81cf..f612e5f 100644 --- a/src/main/java/edu/cmu/sei/kalki/IotInterface.java +++ b/src/main/java/edu/cmu/sei/kalki/IotInterface.java @@ -1,5 +1,4 @@ package edu.cmu.sei.kalki; -import edu.cmu.sei.kalki.Monitors.PhilipsHueLightEmulatorMonitor; import edu.cmu.sei.kalki.api.*; import java.util.logging.Logger; diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java index 875874f..0239e54 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java @@ -23,7 +23,8 @@ public IotMonitor(){ } public static IotMonitor fromDevice(Device device, String apiUrl){ Logger logger = Logger.getLogger("iot-interface"); try { - String classPath = "edu.cmu.sei.kalki.Monitors."+getDeviceTypeMonitorClassName(device.getType().getName()); + String deviceTypeName = device.getType().getName(); + String classPath = "edu.cmu.sei.kalki.devicetypes."+deviceTypeName.replace("\\s+", "")+".Monitor"; Constructor con = Class.forName(classPath).getConstructor(Integer.TYPE, String.class, Integer.TYPE, String.class); IotMonitor mon = (IotMonitor) con.newInstance(device.getId(), device.getIp(), device.getSamplingRate(), apiUrl); return mon; @@ -35,21 +36,6 @@ public static IotMonitor fromDevice(Device device, String apiUrl){ } } - /** - * Removes spaces from device type's name and append 'Monitor' - * @param devTypeName - * @return device type's monitor class name - */ - private static String getDeviceTypeMonitorClassName(String devTypeName) { - String[] temp = devTypeName.split(" "); - String name = ""; - for(int i=0;i commands, String a public static void processCommands(Device device, List commands, String apiUrl){ try { - String classPath = "edu.cmu.kalki.commanders."+getDeviceTypeCommandSenderClassName(device.getType().getName()); + String deviceTypeName = device.getType().getName(); + String classPath = "edu.cmu.kalki.devicetypes."+deviceTypeName.replace("\\s+","")+".CommandSender"; Constructor con = Class.forName(classPath).getConstructor(Device.class, List.class, String.class); DeviceCommandSender commandSender = (DeviceCommandSender) con.newInstance(device, commands, apiUrl); commandSender.sendCommands(); @@ -37,21 +37,6 @@ public static void processCommands(Device device, List commands, } } - /** - * Removes spaces from device type's name and append 'Monitor' - * @param devTypeName - * @return device type's monitor class name - */ - private static String getDeviceTypeCommandSenderClassName(String devTypeName) { - String[] temp = devTypeName.split(" "); - String name = ""; - for(int i=0;i lightIds = lights.keys(); @@ -30,12 +31,12 @@ public void sendCommands() { for(DeviceCommand command: this.commands){ switch (command.getName()){ case "turn-on": - logger.info("[PhilipsHueLightEmulatorCommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); + logger.info("[CommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"true"); logSendCommand(command.getName()); break; case "turn-off": - logger.info("[PhilipsHueLightEmulatorCommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); + logger.info("[CommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"false"); logSendCommand(command.getName()); break; @@ -46,7 +47,7 @@ public void sendCommands() { case "set-group": case "set-scene": default: - logger.severe("[PhilipsHueLightEmulatorCommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); + logger.severe("[CommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); } } } @@ -67,7 +68,7 @@ private static void sendIsOn(String ip, int lightId, String isOn) { httpCon.getInputStream(); httpCon.disconnect(); } catch (Exception e) { - logger.severe("[PhilipsHueLightEmulatorCommandSender] Error sending command to device!"); + logger.severe("[CommandSender] Error sending command to device!"); logger.severe(e.getMessage()); } } @@ -88,7 +89,7 @@ private static JSONObject getAllLights(String apiUrl) { json = new JSONObject(response.toString()); httpCon.disconnect(); } catch (Exception e) { - logger.severe("[PhilipsHueLightEmulatorCommandSender] Error getting all lights."); + logger.severe("[CommandSender] Error getting all lights."); logger.severe(e.getMessage()); } return json; diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java similarity index 86% rename from src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java rename to src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java index 6b272c1..b71415d 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PhilipsHueLightEmulatorMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java @@ -1,5 +1,6 @@ -package edu.cmu.sei.kalki.Monitors; +package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; +import edu.cmu.sei.kalki.Monitors.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.io.*; @@ -28,18 +29,18 @@ import org.apache.http.util.EntityUtils; -public class PhilipsHueLightEmulatorMonitor extends PollingMonitor { +public class Monitor extends PollingMonitor { private String authCode = "newdeveloper"; //Default username works for most GET operations private String ip; - public PhilipsHueLightEmulatorMonitor(int deviceId, String ip, int samplingRate, String url){ + public Monitor(int deviceId, String ip, int samplingRate, String url){ this.deviceId = deviceId; this.pollInterval = samplingRate; this.isPollable = true; this.ip = ip; this.apiUrl = url; - logger.info("[PhilipsHueLightEmulatorMonitor] Starting monitor."); + logger.info("[Monitor] Starting monitor."); start(); } @@ -74,7 +75,7 @@ public String issueCommand(String path){ } return "Error"; } catch (IOException e) { - logger.severe("[PhilipsHueLightEmulatorMonitor] Error: "+ e); + logger.severe("[Monitor] Error: "+ e); return "Error"; } } @@ -82,7 +83,7 @@ public String issueCommand(String path){ @Override public void pollDevice(DeviceStatus status) { String response = issueCommand("lights"); - logger.info("[PhilipsHueLightEmulatorMonitor] Getting current status from response " + response); + logger.info("[Monitor] Getting current status from response " + response); try { JSONObject json = new JSONObject(response); Set keys = json.keySet(); @@ -100,7 +101,7 @@ public void pollDevice(DeviceStatus status) { status.addAttribute("brightness", brightness); status.addAttribute("name", name); } catch (JSONException err){ - logger.severe("[PhilipsHueLightEmulatorMonitor] Error: " + err.toString()); + logger.severe("[Monitor] Error: " + err.toString()); } } diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java similarity index 90% rename from src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java rename to src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java index aab876b..2656c0e 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/UdooNeoMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java @@ -1,5 +1,6 @@ -package edu.cmu.sei.kalki.Monitors; +package edu.cmu.sei.kalki.devicetypes.UdooNeo; +import edu.cmu.sei.kalki.Monitors.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.io.IOException; @@ -17,7 +18,7 @@ import com.jcraft.jsch.Session; import com.jcraft.jsch.JSchException; -public class UdooNeoMonitor extends PollingMonitor { +public class Monitor extends PollingMonitor { private List sensors = new ArrayList(); private String username; @@ -25,16 +26,16 @@ public class UdooNeoMonitor extends PollingMonitor { private String ip; private int deviceId; - public UdooNeoMonitor(int deviceId, String ip, String username, String password, int samplingRate, String url){ + public Monitor(int deviceId, String ip, String username, String password, int samplingRate, String url){ this(deviceId, ip, samplingRate, url); this.username = username; this.password = password; this.isPollable = true; } - public UdooNeoMonitor(int deviceId, String ip, int samplingRate, String url){ + public Monitor(int deviceId, String ip, int samplingRate, String url){ super(); - logger.info("[UdooNeoMonitor] Starting Neo Monitor for device: " + deviceId); + logger.info("[Monitor] Starting Neo Monitor for device: " + deviceId); this.ip = ip; this.deviceId = deviceId; this.username = "udooer"; @@ -68,7 +69,7 @@ public String getCommand(){ public Map parseResponse(List responses) { Map result = new HashMap(); if (responses.size() < 1){ - logger.severe("[UdooNeoMonitor] Missing response from Udoo Neo."); + logger.severe("[Monitor] Missing response from Udoo Neo."); } else { String response = responses.get(0); @@ -148,7 +149,7 @@ public void pollDevice(DeviceStatus status) { channel.connect(); InputStream inStream = channel.getInputStream(); - logger.info("[UdooNeoMonitor] Sent commands to device"); + logger.info("[Monitor] Sent commands to device"); List lines = new ArrayList(); int c = inStream.read(); @@ -174,11 +175,11 @@ public void pollDevice(DeviceStatus status) { status.addAttribute(key, attributes.get(key)); } } catch (JSchException e1){ - logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); + logger.severe("[Monitor] Exception happened - here's what I know: "); logger.severe(e1.getMessage()); } catch (IOException e) { - logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); + logger.severe("[Monitor] Exception happened - here's what I know: "); logger.severe(e.getMessage()); } return; diff --git a/src/main/java/edu/cmu/sei/kalki/commanders/WeMoInsightCommandSender.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java similarity index 62% rename from src/main/java/edu/cmu/sei/kalki/commanders/WeMoInsightCommandSender.java rename to src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java index 44aa21b..4302bf1 100644 --- a/src/main/java/edu/cmu/sei/kalki/commanders/WeMoInsightCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java @@ -1,5 +1,6 @@ -package edu.cmu.sei.kalki.commanders; +package edu.cmu.sei.kalki.devicetypes.WeMoInsight; +import edu.cmu.sei.kalki.commandsender.DeviceCommandSender; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; @@ -8,7 +9,7 @@ import java.io.InputStreamReader; import java.util.logging.Logger; -public class WeMoInsightCommandSender extends DeviceCommandSender { +public class CommandSender extends DeviceCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); private static String[] args = new String[]{ "python", @@ -19,7 +20,7 @@ public class WeMoInsightCommandSender extends DeviceCommandSender { @Override public void sendCommands() { - logger.info("[WeMoInsightCommandSender] Sending commands to device: "+device.getId()); + logger.info("[CommandSender] Sending commands to device: "+device.getId()); for(DeviceCommand command: commands) { switch (command.getName()){ @@ -29,7 +30,7 @@ public void sendCommands() { logSendCommand(command.getName()); break; default: - logger.severe("[WeMoInsightCommandSender] Command: " + command.getName() + " is not a valid command for a Wemo Insight"); + logger.severe("[CommandSender] Command: " + command.getName() + " is not a valid command for a Wemo Insight"); } } } @@ -42,31 +43,31 @@ private static void sendCommand(Device device, DeviceCommand command) { try { Process p = Runtime.getRuntime().exec(args); - logger.info("[WeMoInsightCommandSender] Python script executed"); + logger.info("[CommandSender] Python script executed"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); - logger.info("[WeMoInsightCommandSender] Input stream captured"); + logger.info("[CommandSender] Input stream captured"); BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); - logger.info("[WeMoInsightCommandSender] Error stream captured"); + logger.info("[CommandSender] Error stream captured"); - logger.info("[WeMoInsightCommandSender] Processing input stream"); + logger.info("[CommandSender] Processing input stream"); // read the output from the command while ((s = stdInput.readLine()) != null) { - logger.info("[WeMoInsightCommandSender] " + s); + logger.info("[CommandSender] " + s); } - logger.info("[WeMoInsightCommandSender] Processing error stream"); + logger.info("[CommandSender] Processing error stream"); // read any errors from the attempted command while ((s = stdError.readLine()) != null) { - logger.severe("[WeMoInsightCommandSender] Error with wemo.py: "+s); + logger.severe("[CommandSender] Error with wemo.py: "+s); } } catch (IOException e) { - logger.severe("[WeMoInsightCommandSender] Error reading response from " + device.getId() + ") " + device.getName()); + logger.severe("[CommandSender] Error reading response from " + device.getId() + ") " + device.getName()); logger.severe(e.getMessage()); } } diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java similarity index 90% rename from src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java rename to src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java index a2fcfc0..a25e408 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/WeMoInsightMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java @@ -1,5 +1,6 @@ -package edu.cmu.sei.kalki.Monitors; +package edu.cmu.sei.kalki.devicetypes.WeMoInsight; +import edu.cmu.sei.kalki.Monitors.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.io.BufferedReader; @@ -11,7 +12,7 @@ import org.json.JSONException; import org.json.JSONObject; -public class WeMoInsightMonitor extends PollingMonitor { +public class Monitor extends PollingMonitor { private String deviceIp; private Boolean isOn; @@ -19,13 +20,13 @@ public class WeMoInsightMonitor extends PollingMonitor { private Map attributes; private DeviceStatus status; - public WeMoInsightMonitor(int deviceId, String ip, int samplingRate, String url){ + public Monitor(int deviceId, String ip, int samplingRate, String url){ this.deviceIp = ip; this.deviceId = deviceId; this.pollInterval = samplingRate; this.isPollable = true; this.apiUrl = url; - logger.info("[WeMoInsightMonitor] Starting monitor."); + logger.info("[Monitor] Starting monitor."); start(); } From daf20b7bdc124ba7095a068af55d4e796ca9c775 Mon Sep 17 00:00:00 2001 From: cam292 Date: Wed, 22 Jan 2020 14:24:04 -0500 Subject: [PATCH 20/27] Major refactor. Moving of parent and helper classes to utils. Renaming of monitor/command managers --- .gitignore | 1 + config.json | 3 +- .../edu/cmu/sei/kalki/CommandManager.java | 39 +++++++ .../java/edu/cmu/sei/kalki/DeviceMonitor.java | 78 ------------- .../java/edu/cmu/sei/kalki/IotInterface.java | 6 +- .../edu/cmu/sei/kalki/MonitorManager.java | 106 ++++++++++++++++++ .../cmu/sei/kalki/Monitors/IotMonitor.java | 56 --------- .../cmu/sei/kalki/api/ApiServerStartup.java | 4 +- .../cmu/sei/kalki/api/NewDeviceServlet.java | 4 +- .../cmu/sei/kalki/api/SendCommandServlet.java | 8 +- .../sei/kalki/api/UpdateDeviceServlet.java | 4 +- .../commandsender/DeviceCommandSender.java | 52 --------- .../devicetypes/DLinkCamera/Monitor.java | 6 +- .../CommandSender.java | 83 ++++++++------ .../PhilipsHueLightEmulator/Monitor.java | 10 +- .../kalki/devicetypes/UdooNeo/Monitor.java | 2 +- .../WeMoInsight/CommandSender.java | 65 ++++++----- .../devicetypes/WeMoInsight/Monitor.java | 2 +- .../sei/kalki/utils/DeviceControllerApi.java | 15 +++ .../cmu/sei/kalki/utils/IotCommandSender.java | 46 ++++++++ .../edu/cmu/sei/kalki/utils/IotMonitor.java | 35 ++++++ .../{Monitors => utils}/PollingMonitor.java | 3 +- .../{Mail => utils/mail}/EventObserver.java | 2 +- .../{Mail => utils/mail}/MailServer.java | 5 +- .../mail}/MyMessageHandlerFactory.java | 2 +- .../kalki/{Mail => utils/mail}/SendMail.java | 2 +- 26 files changed, 359 insertions(+), 280 deletions(-) create mode 100644 src/main/java/edu/cmu/sei/kalki/CommandManager.java delete mode 100644 src/main/java/edu/cmu/sei/kalki/DeviceMonitor.java create mode 100644 src/main/java/edu/cmu/sei/kalki/MonitorManager.java delete mode 100644 src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java delete mode 100644 src/main/java/edu/cmu/sei/kalki/commandsender/DeviceCommandSender.java create mode 100644 src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java create mode 100644 src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java rename src/main/java/edu/cmu/sei/kalki/{Monitors => utils}/PollingMonitor.java (95%) rename src/main/java/edu/cmu/sei/kalki/{Mail => utils/mail}/EventObserver.java (66%) rename src/main/java/edu/cmu/sei/kalki/{Mail => utils/mail}/MailServer.java (93%) rename src/main/java/edu/cmu/sei/kalki/{Mail => utils/mail}/MyMessageHandlerFactory.java (98%) rename src/main/java/edu/cmu/sei/kalki/{Mail => utils/mail}/SendMail.java (97%) diff --git a/.gitignore b/.gitignore index aa2d4c2..6f38751 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ build/* .DS_Store # BlueJ files *.ctxt +ouimeaux-env/ !gradle-wrapper.jar diff --git a/config.json b/config.json index f4fe9c6..b57c059 100644 --- a/config.json +++ b/config.json @@ -1,3 +1,4 @@ { - "MAIL_PORT":25000 + "MAIL_PORT":25000, + "device_controller_api": "10.27.153.3:9090" } diff --git a/src/main/java/edu/cmu/sei/kalki/CommandManager.java b/src/main/java/edu/cmu/sei/kalki/CommandManager.java new file mode 100644 index 0000000..ab5819b --- /dev/null +++ b/src/main/java/edu/cmu/sei/kalki/CommandManager.java @@ -0,0 +1,39 @@ +package edu.cmu.sei.kalki; + +import edu.cmu.sei.kalki.utils.IotCommandSender; +import edu.cmu.sei.ttg.kalki.models.Device; +import edu.cmu.sei.ttg.kalki.models.DeviceCommand; + +import java.lang.reflect.Constructor; +import java.util.List; +import java.util.logging.Logger; + +public class CommandManager { + private static Logger logger = Logger.getLogger("iot-interface"); + + public CommandManager(){} + + /** + * Creates command sender from device's type and sends the list of commands + * @param device The device receiving commands + * @param commands The list of commands to send + * @param apiUrl The url of the DeviceControllerApi + */ + public static void processCommands(Device device, List commands, String apiUrl){ + try { + // Remove white spaces from device type name + String deviceTypeName = device.getType().getName(); + deviceTypeName.replace("\\s+",""); + + // Get command sender constructor via reflection + String classPath = "edu.cmu.kalki.devicetypes."+deviceTypeName+".CommandSender"; + Constructor con = Class.forName(classPath).getConstructor(Device.class, List.class, String.class); + + // Create instance and send sommands + IotCommandSender commandSender = (IotCommandSender) con.newInstance(device, commands, apiUrl); + commandSender.sendCommands(); + } catch (Exception e) { // No command sender found for the given device type + logger.severe("[CommandManager] Error: there are no commands for a "+device.getType().getName()); + } + } +} diff --git a/src/main/java/edu/cmu/sei/kalki/DeviceMonitor.java b/src/main/java/edu/cmu/sei/kalki/DeviceMonitor.java deleted file mode 100644 index 60eb0fb..0000000 --- a/src/main/java/edu/cmu/sei/kalki/DeviceMonitor.java +++ /dev/null @@ -1,78 +0,0 @@ -package edu.cmu.sei.kalki; - -import edu.cmu.sei.kalki.utils.DeviceControllerApi; -import edu.cmu.sei.ttg.kalki.models.Device; -import edu.cmu.sei.kalki.Monitors.IotMonitor; -import edu.cmu.sei.kalki.Monitors.PollingMonitor; -import edu.cmu.sei.ttg.kalki.models.StageLog; - -import java.util.HashMap; -import java.util.logging.Logger; - -public class DeviceMonitor { - private Logger logger = Logger.getLogger("iot-interface"); - private HashMap monitors; - private String apiUrl; - - public DeviceMonitor(String url) { - apiUrl = url; - monitors = new HashMap(); - } - - public String getApiUrl(){ - return apiUrl; - } - - /** - * Starts a new monitor for the given device - * @param device - */ - public void startMonitor(Device device) { - if(device.getSamplingRate() == 0){ - logger.info("[DeviceMonitor] Sampling rate of 0. Not starting monitor."); - logUpdateMonitor(device, "0 sampling rate"); - } - else { - logger.info("[DeviceMonitor] Starting monitor for device: "+device.getId()); - IotMonitor mon = IotMonitor.fromDevice(device, apiUrl); - monitors.put(device.getId(), mon); - logUpdateMonitor(device, "Monitor started"); - - } - } - - /** - * Updates the sampling rate for the given device - * @param device - */ - public void updateMonitor(Device device) { - IotMonitor mon = monitors.get(device.getId()); - if(mon != null && mon.getPollInterval() != device.getSamplingRate()){ - logger.info("[DeviceMonitor] Updating monitor for device: "+device.getId()); - if(mon.isPollable() && device.getSamplingRate() > 0){ - logger.info("[DeviceMonitor] Found monitor, updating sampling rate"); - mon.setPollInterval(device.getSamplingRate()); - monitors.replace(device.getId(), mon); - logUpdateMonitor(device, "Updated monitor"); - } else { - logUpdateMonitor(device, "Monitor not updated"); - } - - } else { - logger.severe("[DeviceMonitor] No monitor found for given device "+device.getId()+". Starting one..."); - startMonitor(device); - } - } - - /** - * Sends a StageLog to the DeviceControllerApi to record updating a sampling rate - * @param device Device the monitor was updated for - */ - private void logUpdateMonitor(Device device, String info) { - logger.info("[DeviceMonitor] Logging monitor update for device: "+device.getId()); - StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.INCREASE_SAMPLE_RATE, StageLog.Stage.FINISH, info); - DeviceControllerApi.sendLog(log, apiUrl); - } - - -} diff --git a/src/main/java/edu/cmu/sei/kalki/IotInterface.java b/src/main/java/edu/cmu/sei/kalki/IotInterface.java index f612e5f..a915d43 100644 --- a/src/main/java/edu/cmu/sei/kalki/IotInterface.java +++ b/src/main/java/edu/cmu/sei/kalki/IotInterface.java @@ -15,15 +15,15 @@ public static void main(String[] args) { logger.info("[IotInterface] No alternative API IP+port specified. Defaulting to: "+apiUrl); } - DeviceMonitor monitor = new DeviceMonitor("http://"+apiUrl+"/device-controller-api/"); - logger.info("[IotInterface] DeviceMonitor initialized."); + MonitorManager monitor = new MonitorManager("http://"+apiUrl+"/device-controller-api/"); + logger.info("[IotInterface] MonitorManager initialized."); boolean success = startApiServer(monitor); if(!success) return; } - private static boolean startApiServer(DeviceMonitor monitor) { + private static boolean startApiServer(MonitorManager monitor) { boolean success = false; int attempts = 0; diff --git a/src/main/java/edu/cmu/sei/kalki/MonitorManager.java b/src/main/java/edu/cmu/sei/kalki/MonitorManager.java new file mode 100644 index 0000000..971638c --- /dev/null +++ b/src/main/java/edu/cmu/sei/kalki/MonitorManager.java @@ -0,0 +1,106 @@ +package edu.cmu.sei.kalki; + +import edu.cmu.sei.kalki.utils.DeviceControllerApi; +import edu.cmu.sei.ttg.kalki.models.Device; +import edu.cmu.sei.kalki.utils.IotMonitor; +import edu.cmu.sei.ttg.kalki.models.StageLog; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.logging.Logger; + +public class MonitorManager { + private Logger logger = Logger.getLogger("iot-interface"); + private HashMap monitors; + private String apiUrl; + + public MonitorManager(String url) { + apiUrl = url; + monitors = new HashMap<>(); + } + + public String getApiUrl(){ + return apiUrl; + } + + /** + * Starts a new monitor for the given device + * @param device + */ + public void startMonitor(Device device) { + if(device.getSamplingRate() == 0){ + logger.info("[MonitorManager] Sampling rate of 0. Not starting monitor."); + logUpdateMonitor(device, "0 sampling rate"); + } + else { + logger.info("[MonitorManager] Starting monitor for device: "+device.getId()); + IotMonitor mon = fromDevice(device, apiUrl); + monitors.put(device.getId(), mon); + logUpdateMonitor(device, "Monitor started"); + + } + } + + /** + * Updates the sampling rate for the given device + * @param device + */ + public void updateMonitor(Device device) { + IotMonitor mon = monitors.get(device.getId()); + if(mon != null && mon.getPollInterval() != device.getSamplingRate()){ + logger.info("[MonitorManager] Updating monitor for device: "+device.getId()); + if(mon.isPollable() && device.getSamplingRate() > 0){ + logger.info("[MonitorManager] Found monitor, updating sampling rate"); + mon.setPollInterval(device.getSamplingRate()); + monitors.replace(device.getId(), mon); + logUpdateMonitor(device, "Updated monitor"); + } else { + logUpdateMonitor(device, "Monitor not updated"); + } + + } else { + logger.severe("[MonitorManager] No monitor found for given device "+device.getId()+". Starting one..."); + startMonitor(device); + } + } + + /** + * Creates an instance of an IotMonitor for the given device's type + * @param device The device to be monitored + * @param apiUrl The DeviceControllerApi url + * @return The instance of the device's monitor + */ + public static IotMonitor fromDevice(Device device, String apiUrl){ + Logger logger = Logger.getLogger("iot-interface"); + try { + // Remove white spaces from device type name + String deviceTypeName = device.getType().getName(); + deviceTypeName.replace("\\s+",""); + + // Get IotMonitor constructor via reflection + String classPath = "edu.cmu.sei.kalki.devicetypes."+deviceTypeName+".Monitor"; + Constructor con = Class.forName(classPath).getConstructor(Integer.TYPE, String.class, Integer.TYPE, String.class); + + // Create and return instance of specific IotMonitor + IotMonitor mon = (IotMonitor) con.newInstance(device.getId(), device.getIp(), device.getSamplingRate(), apiUrl); + return mon; + } catch (Exception e2){ + e2.printStackTrace(); + logger.info(e2.getMessage()); + + return null; + } + } + + /** + * Sends a StageLog to the DeviceControllerApi to record updating a sampling rate + * @param device Device the monitor was updated for + */ + private void logUpdateMonitor(Device device, String info) { + logger.info("[MonitorManager] Logging monitor update for device: "+device.getId()); + StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.INCREASE_SAMPLE_RATE, StageLog.Stage.FINISH, info); + DeviceControllerApi.sendLog(log, apiUrl); + } + + +} diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java b/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java deleted file mode 100644 index 0239e54..0000000 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/IotMonitor.java +++ /dev/null @@ -1,56 +0,0 @@ -package edu.cmu.sei.kalki.Monitors; - -import java.lang.reflect.Constructor; -import java.util.Timer; -import java.util.logging.Logger; - -import edu.cmu.sei.kalki.utils.DeviceControllerApi; -import edu.cmu.sei.ttg.kalki.models.*; - -public abstract class IotMonitor { - protected String apiUrl; - protected Timer pollTimer = new Timer(); - protected int pollInterval; - protected boolean isPollable; - protected boolean pollingEnabled = true; - protected boolean timerGoing = false; - protected int deviceId; - - protected final Logger logger = Logger.getLogger("iot-interface"); - - public IotMonitor(){ } - - public static IotMonitor fromDevice(Device device, String apiUrl){ - Logger logger = Logger.getLogger("iot-interface"); - try { - String deviceTypeName = device.getType().getName(); - String classPath = "edu.cmu.sei.kalki.devicetypes."+deviceTypeName.replace("\\s+", "")+".Monitor"; - Constructor con = Class.forName(classPath).getConstructor(Integer.TYPE, String.class, Integer.TYPE, String.class); - IotMonitor mon = (IotMonitor) con.newInstance(device.getId(), device.getIp(), device.getSamplingRate(), apiUrl); - return mon; - } catch (Exception e2){ - e2.printStackTrace(); - logger.info(e2.getMessage()); - - return null; - } - } - - public boolean isPollable() { - return isPollable; - } - - public void setPollInterval(int pollInterval) { - this.pollInterval = pollInterval; - } - - public int getPollInterval() { - return pollInterval; - } - - - protected void sendToDeviceController(DeviceStatus status) { - DeviceControllerApi.sendStatus(status, apiUrl); - } - -} diff --git a/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java b/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java index 703f70c..19ec888 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java +++ b/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java @@ -1,6 +1,6 @@ package edu.cmu.sei.kalki.api; -import edu.cmu.sei.kalki.DeviceMonitor; +import edu.cmu.sei.kalki.MonitorManager; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import java.util.logging.Logger; @@ -13,7 +13,7 @@ public class ApiServerStartup { /** * Starts a Jetty server, with handler for notifications */ - public static void start(DeviceMonitor monitor) throws Exception { + public static void start(MonitorManager monitor) throws Exception { try { Server httpServer = new Server(SERVER_PORT); ServletContextHandler handler = new ServletContextHandler(httpServer, API_URL); diff --git a/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java b/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java index 0af0a86..e1f5df6 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java @@ -4,7 +4,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import edu.cmu.sei.kalki.DeviceMonitor; +import edu.cmu.sei.kalki.MonitorManager; import edu.cmu.sei.ttg.kalki.models.*; import org.eclipse.jetty.http.HttpStatus; @@ -35,7 +35,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) logger.info("[NewDeviceServlet] Calling startMonitor for device: "+device.toString()); response.setStatus(HttpStatus.OK_200); - DeviceMonitor monitor = (DeviceMonitor) getServletContext().getAttribute("monitor"); + MonitorManager monitor = (MonitorManager) getServletContext().getAttribute("monitor"); monitor.startMonitor(device); } diff --git a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java b/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java index afbe3e2..f425e73 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java @@ -4,8 +4,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import edu.cmu.sei.kalki.DeviceMonitor; -import edu.cmu.sei.kalki.commandsender.DeviceCommandSender; +import edu.cmu.sei.kalki.CommandManager; +import edu.cmu.sei.kalki.MonitorManager; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; import org.eclipse.jetty.http.HttpStatus; @@ -49,8 +49,8 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) response.setStatus(HttpStatus.OK_200); logger.info("[SendCommandServlet] Sending commands to device: "+device.toString()); - DeviceMonitor monitor = (DeviceMonitor) getServletContext().getAttribute("monitor"); - DeviceCommandSender.processCommands(device, commandList, monitor.getApiUrl()); + MonitorManager monitor = (MonitorManager) getServletContext().getAttribute("monitor"); + CommandManager.processCommands(device, commandList, monitor.getApiUrl()); } private List parseCommandList(JSONArray commandList) { diff --git a/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java b/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java index deab652..f3dd78b 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java @@ -4,7 +4,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import edu.cmu.sei.kalki.DeviceMonitor; +import edu.cmu.sei.kalki.MonitorManager; import edu.cmu.sei.ttg.kalki.models.Device; import org.eclipse.jetty.http.HttpStatus; @@ -34,7 +34,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) logger.info("[UpdateDeviceServlet] Updating monitor for device: "+device.getId()); response.setStatus(HttpStatus.OK_200); - DeviceMonitor monitor = (DeviceMonitor) getServletContext().getAttribute("monitor"); + MonitorManager monitor = (MonitorManager) getServletContext().getAttribute("monitor"); monitor.updateMonitor(device); } } diff --git a/src/main/java/edu/cmu/sei/kalki/commandsender/DeviceCommandSender.java b/src/main/java/edu/cmu/sei/kalki/commandsender/DeviceCommandSender.java deleted file mode 100644 index 4ac0042..0000000 --- a/src/main/java/edu/cmu/sei/kalki/commandsender/DeviceCommandSender.java +++ /dev/null @@ -1,52 +0,0 @@ -package edu.cmu.sei.kalki.commandsender; - -import edu.cmu.sei.kalki.utils.DeviceControllerApi; -import edu.cmu.sei.ttg.kalki.models.Device; -import edu.cmu.sei.ttg.kalki.models.DeviceCommand; -import edu.cmu.sei.ttg.kalki.models.StageLog; - -import java.lang.reflect.Constructor; -import java.util.List; -import java.util.logging.Logger; - -public abstract class DeviceCommandSender { - private static Logger logger = Logger.getLogger("iot-interface"); - - protected Device device; - protected List commands; - protected String apiUrl; - - - public DeviceCommandSender(){} - - public DeviceCommandSender(Device device, List commands, String apiUrl){ - this.device = device; - this.commands = commands; - this.apiUrl = apiUrl; - } - - public static void processCommands(Device device, List commands, String apiUrl){ - try { - String deviceTypeName = device.getType().getName(); - String classPath = "edu.cmu.kalki.devicetypes."+deviceTypeName.replace("\\s+","")+".CommandSender"; - Constructor con = Class.forName(classPath).getConstructor(Device.class, List.class, String.class); - DeviceCommandSender commandSender = (DeviceCommandSender) con.newInstance(device, commands, apiUrl); - commandSender.sendCommands(); - } catch (Exception e) { - logger.severe("[DeviceCommandSender] Error: there are no commands for a "+device.getType().getName()); - } - } - - /** - * Sends StageLog to Device Controller indicating a command was sent to the device - * @param command The name of the command - */ - protected void logSendCommand(String command) { - logger.info("[DeviceCommandSender] Logging that a command was sent to the device."); - StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.SEND_COMMAND, StageLog.Stage.FINISH, "Sent command to device: "+command); - DeviceControllerApi.sendLog(log, apiUrl); - } - - public abstract void sendCommands(); - -} diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java index 81158c7..7318b11 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java @@ -1,8 +1,8 @@ package edu.cmu.sei.kalki.devicetypes.DLinkCamera; -import edu.cmu.sei.kalki.Mail.EventObserver; -import edu.cmu.sei.kalki.Mail.MailServer; -import edu.cmu.sei.kalki.Monitors.IotMonitor; +import edu.cmu.sei.kalki.utils.mail.EventObserver; +import edu.cmu.sei.kalki.utils.mail.MailServer; +import edu.cmu.sei.kalki.utils.IotMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; public class Monitor extends IotMonitor implements EventObserver { diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java index e05c026..eb55177 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java @@ -1,6 +1,7 @@ package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; -import edu.cmu.sei.kalki.commandsender.DeviceCommandSender; +import edu.cmu.sei.kalki.utils.IotCommandSender; +import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; import org.json.JSONObject; @@ -10,53 +11,64 @@ import java.net.URL; import java.net.HttpURLConnection; import java.util.Iterator; +import java.util.List; import java.util.logging.Logger; -public class CommandSender extends DeviceCommandSender { +public class CommandSender extends IotCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); + private JSONObject lights; - @Override - public void sendCommands() { - logger.info("[CommandSender] Sending commands to PHLE: "+device.getId()); + public CommandSender(Device device, List commands, String apiUrl) { + super(device, commands, apiUrl); + lights = getAllLights(device.getIp()); + } + /** + * Sends commands to each light associated with the given PHLE bridge + * @param command Currently supports turn-on & turn-off + */ + @Override + protected void sendCommand(DeviceCommand command) { + logger.info("[PhleCommandSender] Sending commands to PHLE: "+device.getId()); - JSONObject lights = getAllLights(device.getIp()); - if(lights == null){ - logger.severe("[CommandSender] Unable to get lights from bridge"); + if(lights== null){ + logger.severe("[PhleCommandSender] Unable to get lights from bridge"); return; } Iterator lightIds = lights.keys(); while(lightIds.hasNext()){ int id = Integer.parseInt(lightIds.next()); - for(DeviceCommand command: this.commands){ - switch (command.getName()){ - case "turn-on": - logger.info("[CommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); - sendIsOn(device.getIp(), id,"true"); - logSendCommand(command.getName()); - break; - case "turn-off": - logger.info("[CommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); - sendIsOn(device.getIp(), id,"false"); - logSendCommand(command.getName()); - break; - case "set-name": - case "set-brightness": - case "set-color": - case "set-schedule": - case "set-group": - case "set-scene": - default: - logger.severe("[CommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); - } + switch (command.getName()){ + case "turn-on": + logger.info("[CommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); + sendIsOn(device.getIp(), id,"true"); + logSendCommand(command.getName()); + break; + case "turn-off": + logger.info("[CommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); + sendIsOn(device.getIp(), id,"false"); + logSendCommand(command.getName()); + break; + case "set-name": + case "set-brightness": + case "set-color": + case "set-schedule": + case "set-group": + case "set-scene": + default: + logger.severe("[CommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); } } - } + /** + * Sets the light's state 'isOn' property + * @param ip The ip of the bridge + * @param lightId The id of the light on the bridge + * @param isOn String value of a boolean determining 'isOn' + */ private static void sendIsOn(String ip, int lightId, String isOn) { try { - URL url = new URL("http://"+ip+"/api/newdeveloper/lights/"+lightId+"/state"); HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); httpCon.setDoOutput(true); @@ -73,10 +85,15 @@ private static void sendIsOn(String ip, int lightId, String isOn) { } } - private static JSONObject getAllLights(String apiUrl) { + /** + * Get all the lights associated with the PHLE bridge + * @param ip The ip of the PHLE bridge + * @return JSON object representing all lights connected to the bridge + */ + private static JSONObject getAllLights(String ip) { JSONObject json = null; try { - URL url = new URL("http://"+apiUrl+"/api/newdeveloper/lights"); + URL url = new URL("http://"+ip+"/api/newdeveloper/lights"); HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); httpCon.setRequestMethod("GET"); BufferedReader in = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java index b71415d..c32b064 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java @@ -1,15 +1,9 @@ package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; -import edu.cmu.sei.kalki.Monitors.PollingMonitor; +import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.io.*; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; import java.util.*; import org.apache.http.client.ClientProtocolException; @@ -18,8 +12,6 @@ import org.json.JSONException; import org.json.JSONObject; -import javax.net.ssl.*; - import org.apache.http.HttpEntity; import org.apache.http.HttpHeaders; import org.apache.http.client.methods.CloseableHttpResponse; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java index 2656c0e..ff71798 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java @@ -1,6 +1,6 @@ package edu.cmu.sei.kalki.devicetypes.UdooNeo; -import edu.cmu.sei.kalki.Monitors.PollingMonitor; +import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.io.IOException; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java index 4302bf1..d275638 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java @@ -1,6 +1,6 @@ package edu.cmu.sei.kalki.devicetypes.WeMoInsight; -import edu.cmu.sei.kalki.commandsender.DeviceCommandSender; +import edu.cmu.sei.kalki.utils.IotCommandSender; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; @@ -8,39 +8,52 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.logging.Logger; +import java.util.List; -public class CommandSender extends DeviceCommandSender { +public class CommandSender extends IotCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); - private static String[] args = new String[]{ - "python", - "wemo.py", - "device", - "command" - }; + + public CommandSender(Device device, List commands, String apiUrl) { + super(device, commands, apiUrl); + } + @Override - public void sendCommands() { - logger.info("[CommandSender] Sending commands to device: "+device.getId()); - - for(DeviceCommand command: commands) { - switch (command.getName()){ - case "turn-on": - case "turn-off": - sendCommand(device, command); - logSendCommand(command.getName()); - break; - default: - logger.severe("[CommandSender] Command: " + command.getName() + " is not a valid command for a Wemo Insight"); - } + protected void sendCommand(DeviceCommand command) { + switch (command.getName()){ + case "turn-on": + case "turn-off": + executeScript(command.getName()); + break; + default: + logger.severe("[WemoCommandSender] Command: " + command.getName() + " is not a valid command for a Wemo Insight"); + return; } } - private static void sendCommand(Device device, DeviceCommand command) { - args[2] = device.getIp(); - args[3] = command.getName(); - String s = null; + /** + * Configures command line arguments to execute the wemo python script + * @param deviceIp The ip of the WemoInsight device + * @param command The command to be sent. Options: turn-off, turn-on, status (not applicable here) + * @return Array of command line args to execute the script + */ + private String[] setArgs(String deviceIp, String command){ + return new String[]{ + "python", + "wemo.py", + deviceIp, + command + }; + } + /** + * Executes the wemo python script and process output + * @param command The string that is the command's name + */ + private void executeScript(String command){ try { + String s = ""; + String[] args = setArgs(device.getIp(), command); Process p = Runtime.getRuntime().exec(args); logger.info("[CommandSender] Python script executed"); @@ -66,6 +79,8 @@ private static void sendCommand(Device device, DeviceCommand command) { while ((s = stdError.readLine()) != null) { logger.severe("[CommandSender] Error with wemo.py: "+s); } + + logSendCommand(command); } catch (IOException e) { logger.severe("[CommandSender] Error reading response from " + device.getId() + ") " + device.getName()); logger.severe(e.getMessage()); diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java index a25e408..1c0e4d7 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java @@ -1,6 +1,6 @@ package edu.cmu.sei.kalki.devicetypes.WeMoInsight; -import edu.cmu.sei.kalki.Monitors.PollingMonitor; +import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.io.BufferedReader; diff --git a/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java b/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java index 1622e31..2838e97 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java @@ -15,16 +15,31 @@ public class DeviceControllerApi { private static final String statusEndpoint = "new-status"; private static final String logEndpoint = "new-stage-log"; + /** + * Method to send a device status to the DeviceControllerApi + * @param status + * @param apiUrl + */ public static void sendStatus(DeviceStatus status, String apiUrl) { JSONObject json = new JSONObject(status.toString()); sendToApi(json, apiUrl+statusEndpoint); } + /** + * Method to send a Stage Log to the DeviceControllerApi + * @param log + * @param apiUrl + */ public static void sendLog(StageLog log, String apiUrl) { JSONObject json = new JSONObject(log.toString()); sendToApi(json, apiUrl+logEndpoint); } + /** + * Helper method to send a json object to the DeviceControllerApi + * @param object + * @param apiUrl + */ private static void sendToApi(JSONObject object, String apiUrl){ try { URL url = new URL(apiUrl); diff --git a/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java b/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java new file mode 100644 index 0000000..f95af11 --- /dev/null +++ b/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java @@ -0,0 +1,46 @@ +package edu.cmu.sei.kalki.utils; + +import edu.cmu.sei.ttg.kalki.models.Device; +import edu.cmu.sei.ttg.kalki.models.DeviceCommand; +import edu.cmu.sei.ttg.kalki.models.StageLog; + +import java.util.List; +import java.util.logging.Logger; + +public class IotCommandSender { + private static Logger logger = Logger.getLogger("iot-interface"); + + protected Device device; + protected List commands; + protected String apiUrl; + + + public IotCommandSender(){} + + public IotCommandSender(Device device, List commands, String apiUrl){ + this.device = device; + this.commands = commands; + this.apiUrl = apiUrl; + } + + public void sendCommands() { + for(DeviceCommand command: commands) { + sendCommand(command); + } + } + + /** + * Method to be overwritten by child class. Check if it's a valid command, then send accordingly + */ + protected void sendCommand(DeviceCommand command){ return;} + + /** + * Sends StageLog to Device Controller indicating a command was sent to the device + * @param command The name of the command + */ + protected void logSendCommand(String command) { + logger.info("[IotCommandSender] Logging that a command was sent to the device."); + StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.SEND_COMMAND, StageLog.Stage.FINISH, "Sent command to device: "+command); + DeviceControllerApi.sendLog(log, apiUrl); + } +} diff --git a/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java b/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java new file mode 100644 index 0000000..a3b948e --- /dev/null +++ b/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java @@ -0,0 +1,35 @@ +package edu.cmu.sei.kalki.utils; + +import edu.cmu.sei.ttg.kalki.models.*; + +import java.util.Timer; +import java.util.logging.Logger; + +public abstract class IotMonitor { + protected String apiUrl; + protected Timer pollTimer = new Timer(); + protected int pollInterval; + protected boolean isPollable; + protected boolean timerGoing = false; + protected int deviceId; + + protected final Logger logger = Logger.getLogger("iot-interface"); + + public IotMonitor(){ } + + public boolean isPollable() { + return isPollable; + } + + public void setPollInterval(int pollInterval) { + this.pollInterval = pollInterval; + } + + public int getPollInterval() { + return pollInterval; + } + + protected void sendToDeviceController(DeviceStatus status) { + DeviceControllerApi.sendStatus(status, apiUrl); + } +} diff --git a/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java b/src/main/java/edu/cmu/sei/kalki/utils/PollingMonitor.java similarity index 95% rename from src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java rename to src/main/java/edu/cmu/sei/kalki/utils/PollingMonitor.java index 9925f0e..1879035 100644 --- a/src/main/java/edu/cmu/sei/kalki/Monitors/PollingMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/PollingMonitor.java @@ -1,6 +1,5 @@ -package edu.cmu.sei.kalki.Monitors; +package edu.cmu.sei.kalki.utils; -import edu.cmu.sei.ttg.kalki.models.DeviceSecurityState; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.util.Timer; diff --git a/src/main/java/edu/cmu/sei/kalki/Mail/EventObserver.java b/src/main/java/edu/cmu/sei/kalki/utils/mail/EventObserver.java similarity index 66% rename from src/main/java/edu/cmu/sei/kalki/Mail/EventObserver.java rename to src/main/java/edu/cmu/sei/kalki/utils/mail/EventObserver.java index 7eaf469..b7af7d4 100644 --- a/src/main/java/edu/cmu/sei/kalki/Mail/EventObserver.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/mail/EventObserver.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.Mail; +package edu.cmu.sei.kalki.utils.mail; public interface EventObserver { public void notify(String message); diff --git a/src/main/java/edu/cmu/sei/kalki/Mail/MailServer.java b/src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java similarity index 93% rename from src/main/java/edu/cmu/sei/kalki/Mail/MailServer.java rename to src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java index ec03a85..3bcf838 100644 --- a/src/main/java/edu/cmu/sei/kalki/Mail/MailServer.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.Mail; +package edu.cmu.sei.kalki.utils.mail; import org.subethamail.smtp.server.SMTPServer; @@ -7,7 +7,6 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import java.util.logging.Logger; import org.json.JSONObject; @@ -61,7 +60,7 @@ public static void initialize() { } } else { - logger.info("[MailServer] Mail Server already initialized"); + logger.info("[MailServer] mail Server already initialized"); } } } diff --git a/src/main/java/edu/cmu/sei/kalki/Mail/MyMessageHandlerFactory.java b/src/main/java/edu/cmu/sei/kalki/utils/mail/MyMessageHandlerFactory.java similarity index 98% rename from src/main/java/edu/cmu/sei/kalki/Mail/MyMessageHandlerFactory.java rename to src/main/java/edu/cmu/sei/kalki/utils/mail/MyMessageHandlerFactory.java index 8de83a1..60133ca 100644 --- a/src/main/java/edu/cmu/sei/kalki/Mail/MyMessageHandlerFactory.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/mail/MyMessageHandlerFactory.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.Mail; +package edu.cmu.sei.kalki.utils.mail; import org.subethamail.smtp.*; diff --git a/src/main/java/edu/cmu/sei/kalki/Mail/SendMail.java b/src/main/java/edu/cmu/sei/kalki/utils/mail/SendMail.java similarity index 97% rename from src/main/java/edu/cmu/sei/kalki/Mail/SendMail.java rename to src/main/java/edu/cmu/sei/kalki/utils/mail/SendMail.java index cd87afe..3f84af9 100644 --- a/src/main/java/edu/cmu/sei/kalki/Mail/SendMail.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/mail/SendMail.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.Mail; +package edu.cmu.sei.kalki.utils.mail; import java.util.*; import javax.mail.*; From 9384f72b7d7ffe18f685b6c6e10bd66731ed2274 Mon Sep 17 00:00:00 2001 From: cam292 Date: Wed, 22 Jan 2020 14:59:50 -0500 Subject: [PATCH 21/27] Commenting code with documentation --- .../edu/cmu/sei/kalki/api/ApiServlet.java | 36 +++++++++++++++++++ .../cmu/sei/kalki/api/NewDeviceServlet.java | 6 ++++ .../cmu/sei/kalki/api/SendCommandServlet.java | 6 ++++ .../sei/kalki/api/UpdateDeviceServlet.java | 6 ++++ .../devicetypes/DLinkCamera/Monitor.java | 6 ++++ .../PhilipsHueLightEmulator/Monitor.java | 10 +++++- .../kalki/devicetypes/UdooNeo/Monitor.java | 32 +++++++++++++++++ .../devicetypes/WeMoInsight/Monitor.java | 4 +++ 8 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java b/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java index 31314b0..4a841c9 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java @@ -13,8 +13,18 @@ import java.io.IOException; import java.sql.Timestamp; +/** + * Base class for ApiServlets to handle requests from the DeviceController + */ public class ApiServlet extends HttpServlet { + /** + * Method to extract body of an HTTP request and convert it to a JSON object + * @param request + * @param response + * @return + * @throws ServletException + */ protected JSONObject parseRequestBody(HttpServletRequest request, HttpServletResponse response) throws ServletException { JSONObject requestBody; try { @@ -36,6 +46,12 @@ protected JSONObject parseRequestBody(HttpServletRequest request, HttpServletRes return requestBody; } + /** + * Method to convert a JSONObject to a Device + * @param deviceData + * @return + * @throws JSONException + */ protected Device parseDevice(JSONObject deviceData) throws JSONException { int id = deviceData.getInt("id"); String name = deviceData.getString("name"); @@ -53,18 +69,33 @@ protected Device parseDevice(JSONObject deviceData) throws JSONException { return device; } + /** + * Method to convert a JSONObject to a DeviceType + * @param type + * @return + */ protected DeviceType parseDeviceType(JSONObject type) { int id = type.getInt("id"); String name = type.getString("name"); return new DeviceType(id, name); } + /** + * Method to convert a JSONObject to a Group + * @param group + * @return + */ protected Group parseGroup(JSONObject group) { int id = group.getInt("id"); String name = group.getString("name"); return new Group(id, name); } + /** + * Method to convert a JSONObject to a DeviceSecurityState + * @param state + * @return + */ protected DeviceSecurityState parseSecurityState(JSONObject state) { int id = state.getInt("id"); int deviceId = state.getInt("deviceId"); @@ -74,6 +105,11 @@ protected DeviceSecurityState parseSecurityState(JSONObject state) { return new DeviceSecurityState(id, deviceId, stateId, timestamp, name); } + /** + * Method to convert a JSONObject to an Alert + * @param alert + * @return + */ protected Alert parseAlert(JSONObject alert) { int id = alert.getInt("id"); String name = alert.getString("name"); diff --git a/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java b/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java index e1f5df6..bc6842a 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java @@ -16,6 +16,12 @@ public class NewDeviceServlet extends ApiServlet { private Logger logger = Logger.getLogger("iot-interface"); + /** + * Extracts the Device from the request body and starts a monitor for it + * @param request + * @param response + * @throws ServletException + */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { logger.info("[NewDeviceServlet] Handling request."); diff --git a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java b/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java index f425e73..2e34446 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java @@ -21,6 +21,12 @@ public class SendCommandServlet extends ApiServlet { private Logger logger = Logger.getLogger("iot-interface"); + /** + * Extracts the device and commands from the request and initiates command sending + * @param request + * @param response + * @throws ServletException + */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { logger.info("[SendCommandServlet] Handling request"); diff --git a/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java b/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java index f3dd78b..ba882a2 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java @@ -16,6 +16,12 @@ public class UpdateDeviceServlet extends ApiServlet { private Logger logger = Logger.getLogger("iot-interface"); + /** + * Extracts the device from the request and updates its monitor + * @param request + * @param response + * @throws ServletException + */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { logger.info("[UpdateDeviceServlet] Handling request."); diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java index 7318b11..ac9acb7 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java @@ -18,6 +18,12 @@ public Monitor(int deviceId, String ip, int samplingRate, String url){ logger.info("[Monitor] Monitor started for device: "+deviceId); this.deviceId = deviceId; } + + /** + * The camera is configured to send a notification to listenEmail on motion detected. + * This method sends a status to the DeviceController on an appropriate message + * @param message The notification from the camera + */ public void notify(String message){ if (message.equals(listenEmail)){ DeviceStatus status = new DeviceStatus(deviceId); diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java index c32b064..8a6b2a7 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java @@ -37,7 +37,11 @@ public Monitor(int deviceId, String ip, int samplingRate, String url){ } - + /** + * Makes a get request to the PHLE REST API at the given path + * @param path The endpoint of the api + * @return String representation of the response from the API + */ public String issueCommand(String path){ String targetURL = "http://" + ip + "/api/" + authCode + "/" + path; logger.info(targetURL); @@ -72,6 +76,10 @@ public String issueCommand(String path){ } } + /** + * Gets the state of the lights from the PHLE bridge + * @param status The DeviceStatus to be inserted + */ @Override public void pollDevice(DeviceStatus status) { String response = issueCommand("lights"); diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java index ff71798..2c6fe17 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java @@ -47,11 +47,17 @@ public Monitor(int deviceId, String ip, int samplingRate, String url){ start(); } + /** + * Abstract class for the sensors on an Udoo Neo + */ public abstract class NeoSensor{ public abstract String getCommand(); public abstract Map parseResponse(List response); } + /** + * Class to interface with an Udoo Sensor with X,Y,Z values + */ public class NeoXYZSensor extends NeoSensor { private String name; @@ -83,6 +89,9 @@ public Map parseResponse(List responses) { } } + /** + * Class to interface with an Udoo Temperature Sensor + */ public class TemperatureSensor extends NeoSensor { List fields = new ArrayList(); @@ -115,6 +124,9 @@ public Map parseResponse(List responses) { } } + /** + * Sets the sensors that are available on the Udoo Neo + */ public void setSensors(){ sensors.add(new NeoXYZSensor("accelerometer")); sensors.add(new NeoXYZSensor("gyroscope")); @@ -122,6 +134,10 @@ public void setSensors(){ sensors.add(new TemperatureSensor()); } + /** + * Connects to device, gets raw sensor readings, and converts to human-readable values + * @param status The DeviceStatus to be sent to the DeviceControllerApi + */ @Override public void pollDevice(DeviceStatus status) { try { @@ -185,6 +201,10 @@ public void pollDevice(DeviceStatus status) { return; } + /** + * Helper method to convert the raw readings of sensors to human-readable values + * @param attributes + */ public void convertRawReadings(Map attributes){ //convert accelerometer readings to g's double accelCoefficient = 0.000244 / 4; @@ -203,6 +223,12 @@ public void convertRawReadings(Map attributes){ convertTempReading("max_hyst", tempCoefficient, attributes); } + /** + * Helper method to replace X,Y,Z values with converted value + * @param sensor The sensor with X,Y,Z values + * @param coefficient The conversion rate + * @param attributes The device status attributes(sensor + X,Y, or Z) + */ private void convertThreeAxisReading(String sensor, double coefficient, Map attributes){ double xReading = Double.valueOf(attributes.get(sensor+"X")) * coefficient; double yReading = Double.valueOf(attributes.get(sensor+"Y")) * coefficient; @@ -212,6 +238,12 @@ private void convertThreeAxisReading(String sensor, double coefficient, Map attributes) { double reading = Double.valueOf(attributes.get("temp"+suffix)) * coefficient; attributes.replace("temp"+suffix, String.valueOf(reading)); diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java index 1c0e4d7..80d8a26 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java @@ -30,6 +30,10 @@ public Monitor(int deviceId, String ip, int samplingRate, String url){ start(); } + /** + * Executes the wemo python script to get a WemoInsight's status + * @param status The DeviceStatus to be sent to the DeviceControllerApi + */ @Override public void pollDevice(DeviceStatus status) { attributes = new HashMap(); From b00cf8ab6b85c367005943a628a880e3b131c322 Mon Sep 17 00:00:00 2001 From: cam292 Date: Wed, 22 Jan 2020 16:19:15 -0500 Subject: [PATCH 22/27] Added new HttpRequest util class to reduce duplicate code. Fixed some logging identifiers --- .../CommandSender.java | 42 +++------ .../PhilipsHueLightEmulator/Monitor.java | 88 +++++++++---------- .../kalki/devicetypes/UdooNeo/Monitor.java | 10 +-- .../WeMoInsight/CommandSender.java | 14 +-- .../devicetypes/WeMoInsight/Monitor.java | 30 +++---- .../sei/kalki/utils/DeviceControllerApi.java | 12 +-- .../edu/cmu/sei/kalki/utils/HttpRequest.java | 57 ++++++++++++ 7 files changed, 138 insertions(+), 115 deletions(-) create mode 100644 src/main/java/edu/cmu/sei/kalki/utils/HttpRequest.java diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java index eb55177..707cd4a 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java @@ -1,15 +1,11 @@ package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; +import edu.cmu.sei.kalki.utils.HttpRequest; import edu.cmu.sei.kalki.utils.IotCommandSender; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; import org.json.JSONObject; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.URL; -import java.net.HttpURLConnection; import java.util.Iterator; import java.util.List; import java.util.logging.Logger; @@ -40,12 +36,12 @@ protected void sendCommand(DeviceCommand command) { int id = Integer.parseInt(lightIds.next()); switch (command.getName()){ case "turn-on": - logger.info("[CommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); + logger.info("[PhleCommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"true"); logSendCommand(command.getName()); break; case "turn-off": - logger.info("[CommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); + logger.info("[PhleCommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"false"); logSendCommand(command.getName()); break; @@ -56,7 +52,7 @@ protected void sendCommand(DeviceCommand command) { case "set-group": case "set-scene": default: - logger.severe("[CommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); + logger.severe("[PhleCommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); } } } @@ -69,18 +65,11 @@ protected void sendCommand(DeviceCommand command) { */ private static void sendIsOn(String ip, int lightId, String isOn) { try { - URL url = new URL("http://"+ip+"/api/newdeveloper/lights/"+lightId+"/state"); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setDoOutput(true); - httpCon.setRequestMethod("PUT"); - OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream()); - JSONObject json = new JSONObject("{\"on\":"+isOn+"}"); - out.write(json.toString()); - out.close(); - httpCon.getInputStream(); - httpCon.disconnect(); + JSONObject body = new JSONObject("{\"on\":"+isOn+"}"); + String apiUrl = "http://"+ip+"/api/newdeveloper/lights/"+lightId+"/state"; + HttpRequest.putRequest(body, apiUrl); } catch (Exception e) { - logger.severe("[CommandSender] Error sending command to device!"); + logger.severe("[PhleCommandSender] Error sending command to device!"); logger.severe(e.getMessage()); } } @@ -93,20 +82,9 @@ private static void sendIsOn(String ip, int lightId, String isOn) { private static JSONObject getAllLights(String ip) { JSONObject json = null; try { - URL url = new URL("http://"+ip+"/api/newdeveloper/lights"); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setRequestMethod("GET"); - BufferedReader in = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); - StringBuilder response = new StringBuilder(); - String line = ""; - while((line = in.readLine()) != null) { - response.append(line); - } - logger.info(response.toString()); - json = new JSONObject(response.toString()); - httpCon.disconnect(); + json = HttpRequest.getRequest("http://"+ip+"/api/newdeveloper/lights"); } catch (Exception e) { - logger.severe("[CommandSender] Error getting all lights."); + logger.severe("[PhleCommandSender] Error getting all lights."); logger.severe(e.getMessage()); } return json; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java index 8a6b2a7..160b139 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java @@ -1,24 +1,24 @@ package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; +import edu.cmu.sei.kalki.utils.HttpRequest; import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; -import java.io.*; -import java.util.*; +import java.util.Set; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.HttpClientBuilder; +//import org.apache.http.client.ClientProtocolException; +//import org.apache.http.client.config.RequestConfig; +//import org.apache.http.impl.client.HttpClientBuilder; import org.json.JSONException; import org.json.JSONObject; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; +//import org.apache.http.HttpEntity; +//import org.apache.http.HttpHeaders; +//import org.apache.http.client.methods.CloseableHttpResponse; +//import org.apache.http.client.methods.HttpGet; +//import org.apache.http.impl.client.CloseableHttpClient; +//import org.apache.http.impl.client.HttpClients; +//import org.apache.http.util.EntityUtils; public class Monitor extends PollingMonitor { @@ -32,7 +32,7 @@ public Monitor(int deviceId, String ip, int samplingRate, String url){ this.isPollable = true; this.ip = ip; this.apiUrl = url; - logger.info("[Monitor] Starting monitor."); + logger.info("[PhleMonitor] Starting monitor."); start(); } @@ -42,37 +42,38 @@ public Monitor(int deviceId, String ip, int samplingRate, String url){ * @param path The endpoint of the api * @return String representation of the response from the API */ - public String issueCommand(String path){ + public JSONObject issueCommand(String path){ String targetURL = "http://" + ip + "/api/" + authCode + "/" + path; logger.info(targetURL); try{ - int timeout = 5; - RequestConfig config = RequestConfig.custom() - .setConnectTimeout(timeout * 1000) - .setConnectionRequestTimeout(timeout * 1000) - .setSocketTimeout(timeout * 1000).build(); - CloseableHttpClient httpClient = - HttpClientBuilder.create().setDefaultRequestConfig(config).build(); - HttpGet request = new HttpGet(targetURL); - - - CloseableHttpResponse response = httpClient.execute(request); - - HttpEntity entity = response.getEntity(); - logger.info(entity.toString()); - if (entity != null) { - logger.info("converting to string"); - String result = EntityUtils.toString(entity); - logger.info("closing up"); - response.close(); - httpClient.close(); - return result; - } - return "Error"; - } catch (IOException e) { - logger.severe("[Monitor] Error: "+ e); - return "Error"; +// int timeout = 5; +// RequestConfig config = RequestConfig.custom() +// .setConnectTimeout(timeout * 1000) +// .setConnectionRequestTimeout(timeout * 1000) +// .setSocketTimeout(timeout * 1000).build(); +// CloseableHttpClient httpClient = +// HttpClientBuilder.create().setDefaultRequestConfig(config).build(); +// HttpGet request = new HttpGet(targetURL); +// +// +// CloseableHttpResponse response = httpClient.execute(request); +// +// HttpEntity entity = response.getEntity(); +// logger.info(entity.toString()); +// if (entity != null) { +// logger.info("converting to string"); +// String result = EntityUtils.toString(entity); +// logger.info("closing up"); +// response.close(); +// httpClient.close(); +// return result; +// } + + return HttpRequest.getRequest(targetURL); + } catch (Exception e) { + logger.severe("[PhleMonitor] Error getting a response from the bridge: "+ e); + return new JSONObject("{\"error\": \"Error\"}"); } } @@ -82,10 +83,9 @@ public String issueCommand(String path){ */ @Override public void pollDevice(DeviceStatus status) { - String response = issueCommand("lights"); - logger.info("[Monitor] Getting current status from response " + response); + JSONObject json = issueCommand("lights"); + logger.info("[PhleMonitor] Getting current status from response " + json.toString()); try { - JSONObject json = new JSONObject(response); Set keys = json.keySet(); String key = keys.iterator().next(); //Assumes only one light is connected, does not verify @@ -101,7 +101,7 @@ public void pollDevice(DeviceStatus status) { status.addAttribute("brightness", brightness); status.addAttribute("name", name); } catch (JSONException err){ - logger.severe("[Monitor] Error: " + err.toString()); + logger.severe("[PhleMonitor] Error: " + err.toString()); } } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java index 2c6fe17..af05296 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java @@ -35,7 +35,7 @@ public Monitor(int deviceId, String ip, String username, String password, int sa public Monitor(int deviceId, String ip, int samplingRate, String url){ super(); - logger.info("[Monitor] Starting Neo Monitor for device: " + deviceId); + logger.info("[UdooNeoMonitor] Starting Neo Monitor for device: " + deviceId); this.ip = ip; this.deviceId = deviceId; this.username = "udooer"; @@ -75,7 +75,7 @@ public String getCommand(){ public Map parseResponse(List responses) { Map result = new HashMap(); if (responses.size() < 1){ - logger.severe("[Monitor] Missing response from Udoo Neo."); + logger.severe("[UdooNeoMonitor] Missing response from Udoo Neo."); } else { String response = responses.get(0); @@ -165,7 +165,7 @@ public void pollDevice(DeviceStatus status) { channel.connect(); InputStream inStream = channel.getInputStream(); - logger.info("[Monitor] Sent commands to device"); + logger.info("[UdooNeoMonitor] Sent commands to device"); List lines = new ArrayList(); int c = inStream.read(); @@ -191,11 +191,11 @@ public void pollDevice(DeviceStatus status) { status.addAttribute(key, attributes.get(key)); } } catch (JSchException e1){ - logger.severe("[Monitor] Exception happened - here's what I know: "); + logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); logger.severe(e1.getMessage()); } catch (IOException e) { - logger.severe("[Monitor] Exception happened - here's what I know: "); + logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); logger.severe(e.getMessage()); } return; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java index d275638..d60900a 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java @@ -56,33 +56,33 @@ private void executeScript(String command){ String[] args = setArgs(device.getIp(), command); Process p = Runtime.getRuntime().exec(args); - logger.info("[CommandSender] Python script executed"); + logger.info("[WemoCommandSender] Python script executed"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); - logger.info("[CommandSender] Input stream captured"); + logger.info("[WemoCommandSender] Input stream captured"); BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); - logger.info("[CommandSender] Error stream captured"); + logger.info("[WemoCommandSender] Error stream captured"); - logger.info("[CommandSender] Processing input stream"); + logger.info("[WemoCommandSender] Processing input stream"); // read the output from the command while ((s = stdInput.readLine()) != null) { logger.info("[CommandSender] " + s); } - logger.info("[CommandSender] Processing error stream"); + logger.info("[WemoCommandSender] Processing error stream"); // read any errors from the attempted command while ((s = stdError.readLine()) != null) { - logger.severe("[CommandSender] Error with wemo.py: "+s); + logger.severe("[WemoCommandSender] Error with wemo.py: "+s); } logSendCommand(command); } catch (IOException e) { - logger.severe("[CommandSender] Error reading response from " + device.getId() + ") " + device.getName()); + logger.severe("[WemoCommandSender] Error reading response from " + device.getId() + ") " + device.getName()); logger.severe(e.getMessage()); } } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java index 80d8a26..8054df6 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java @@ -26,7 +26,7 @@ public Monitor(int deviceId, String ip, int samplingRate, String url){ this.pollInterval = samplingRate; this.isPollable = true; this.apiUrl = url; - logger.info("[Monitor] Starting monitor."); + logger.info("[WemoMonitor] Starting monitor."); start(); } @@ -57,19 +57,17 @@ public void pollDevice(DeviceStatus status) { // read the output from the command StringBuilder st = new StringBuilder(); - String s = null; - while ((s = stdInput.readLine()) != null) { - st.append(s); - //s = s.replace("Switch: " + deviceIp, ""); - //isOn = s.contains("on"); + String s = null; + while ((s = stdInput.readLine()) != null) { + st.append(s); + } + logger.info("Output from device: "+st.toString()); + JSONObject json = new JSONObject(st.toString()); + for(Object keyObj : json.keySet()){ + String key = (String) keyObj; + String value = (String) json.get(key).toString(); + attributes.put(key, value); } - logger.info("Output from device: "+st.toString()); - JSONObject json = new JSONObject(st.toString()); - for(Object keyObj : json.keySet()){ - String key = (String) keyObj; - String value = (String) json.get(key).toString(); - attributes.put(key, value); - } // read any errors from the attempted command while ((s = stdError.readLine()) != null) { logger.severe(s); @@ -78,10 +76,10 @@ public void pollDevice(DeviceStatus status) { status.addAttribute(key, attributes.get(key)); } } catch (IOException e) { - logger.severe("Error polling Wemo Insight: " + e.toString()); + logger.severe("[WemoMonitor] Error polling Wemo Insight: " + e.toString()); } catch (JSONException e) { - logger.severe("Error parsing JSON respons from Wemo Insight: " + deviceId + ". " + e.getMessage()); - e.printStackTrace(); + logger.severe("[WemoMonitor] Error parsing JSON response from Wemo Insight: " + deviceId + ". " + e.getMessage()); + e.printStackTrace(); } } diff --git a/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java b/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java index 2838e97..7d99510 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java @@ -4,9 +4,6 @@ import edu.cmu.sei.ttg.kalki.models.StageLog; import org.json.JSONObject; -import java.io.OutputStreamWriter; -import java.net.HttpURLConnection; -import java.net.URL; import java.util.logging.Logger; public class DeviceControllerApi { @@ -42,14 +39,7 @@ public static void sendLog(StageLog log, String apiUrl) { */ private static void sendToApi(JSONObject object, String apiUrl){ try { - URL url = new URL(apiUrl); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setDoOutput(true); - httpCon.setRequestMethod("POST"); - OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream()); - out.write(object.toString()); - out.close(); - httpCon.getInputStream(); + HttpRequest.postRequest(object, apiUrl); } catch (Exception e) { logger.severe("[DeviceControllerApi] Error sending object to DeviceController: "+object.toString()); logger.severe(e.getMessage()); diff --git a/src/main/java/edu/cmu/sei/kalki/utils/HttpRequest.java b/src/main/java/edu/cmu/sei/kalki/utils/HttpRequest.java new file mode 100644 index 0000000..21c0bde --- /dev/null +++ b/src/main/java/edu/cmu/sei/kalki/utils/HttpRequest.java @@ -0,0 +1,57 @@ +package edu.cmu.sei.kalki.utils; + +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; + +public class HttpRequest { + + public static void putRequest(JSONObject body, String apiUrl) throws Exception { + sendData(body, apiUrl, "PUT"); + } + + public static void postRequest(JSONObject body, String apiUrl) throws Exception { + sendData(body, apiUrl, "POST"); + } + + private static void sendData(JSONObject body, String apiUrl, String method) throws IOException { + HttpURLConnection con = makeConnection(apiUrl, true, method); + appendBodyToRequest(con, body); + con.getInputStream(); + con.disconnect(); + } + + public static JSONObject getRequest(String apiUrl) throws IOException { + HttpURLConnection con = makeConnection(apiUrl, false, "GET"); + BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); + + StringBuilder response = new StringBuilder(); + String line = ""; + while((line = in.readLine()) != null) { + response.append(line); + } + + con.disconnect(); + + return new JSONObject(response.toString()); + } + + private static void appendBodyToRequest(HttpURLConnection con, JSONObject body) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream()); + out.write(body.toString()); + out.close(); + } + + private static HttpURLConnection makeConnection(String endpoint, boolean output, String method) throws IOException { + URL url = new URL(endpoint); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setDoOutput(output); + con.setRequestMethod(method); + return con; + } +} From 0a1facbceff71f5939e941cb014c59db88db9c68 Mon Sep 17 00:00:00 2001 From: cam292 Date: Wed, 22 Jan 2020 16:35:05 -0500 Subject: [PATCH 23/27] Added Config util to parse config.json --- config.json | 2 +- .../java/edu/cmu/sei/kalki/IotInterface.java | 20 ++++++----- .../java/edu/cmu/sei/kalki/utils/Config.java | 34 +++++++++++++++++++ .../cmu/sei/kalki/utils/mail/MailServer.java | 25 ++------------ 4 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 src/main/java/edu/cmu/sei/kalki/utils/Config.java diff --git a/config.json b/config.json index b57c059..eeb0b0b 100644 --- a/config.json +++ b/config.json @@ -1,4 +1,4 @@ { - "MAIL_PORT":25000, + "MAIL_PORT": "25000", "device_controller_api": "10.27.153.3:9090" } diff --git a/src/main/java/edu/cmu/sei/kalki/IotInterface.java b/src/main/java/edu/cmu/sei/kalki/IotInterface.java index a915d43..ea16f76 100644 --- a/src/main/java/edu/cmu/sei/kalki/IotInterface.java +++ b/src/main/java/edu/cmu/sei/kalki/IotInterface.java @@ -1,26 +1,30 @@ package edu.cmu.sei.kalki; import edu.cmu.sei.kalki.api.*; +import edu.cmu.sei.kalki.utils.Config; + +import java.io.IOException; import java.util.logging.Logger; public class IotInterface { private static Logger logger = Logger.getLogger("iot-interface"); public static void main(String[] args) { - String apiUrl = "10.27.153.3:9090"; try { - apiUrl = args[0]; - - } catch (ArrayIndexOutOfBoundsException e) { - logger.info("[IotInterface] No alternative API IP+port specified. Defaulting to: "+apiUrl); + Config.load("config.json"); + } catch (IOException e) { + logger.severe("[IotInterface] Error parsing the config.json. Exiting."); + e.printStackTrace(); + System.exit(-1); } + String apiUrl = Config.data.get("device_controller_api"); + MonitorManager monitor = new MonitorManager("http://"+apiUrl+"/device-controller-api/"); logger.info("[IotInterface] MonitorManager initialized."); - boolean success = startApiServer(monitor); - if(!success) - return; + if(!startApiServer(monitor)) + System.exit(-1); } private static boolean startApiServer(MonitorManager monitor) { diff --git a/src/main/java/edu/cmu/sei/kalki/utils/Config.java b/src/main/java/edu/cmu/sei/kalki/utils/Config.java new file mode 100644 index 0000000..eca1164 --- /dev/null +++ b/src/main/java/edu/cmu/sei/kalki/utils/Config.java @@ -0,0 +1,34 @@ +package edu.cmu.sei.kalki.utils; + +import org.json.JSONObject; +import org.json.JSONTokener; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by sebastianecheverria on 8/2/17. + */ +public class Config { + public static Map data = new HashMap<>(); + + public static void load(String configFilePath) throws IOException { + System.out.println(System.getProperty("user.dir")); + InputStream fs = new FileInputStream(configFilePath); + JSONTokener parser = new JSONTokener(fs); + JSONObject config = new JSONObject(parser); + + Iterator configData = config.keys(); + while(configData.hasNext()) { + String paramName = configData.next(); + String paramValue = config.getString(paramName); + data.put(paramName, paramValue); + } + + fs.close(); + } +} diff --git a/src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java b/src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java index 3bcf838..a06e618 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java @@ -1,16 +1,12 @@ package edu.cmu.sei.kalki.utils.mail; +import edu.cmu.sei.kalki.utils.Config; import org.subethamail.smtp.server.SMTPServer; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; -import org.json.JSONObject; -import org.json.JSONTokener; public class MailServer { @@ -42,23 +38,8 @@ public static void notify(String fromEmail){ public static void initialize() { if (mailServer == null){ logger.info("Initializing mail server"); - - try{ - - InputStream fs = new FileInputStream("config.json"); - JSONTokener parser = new JSONTokener(fs); - JSONObject config = new JSONObject(parser); - int port = config.getInt("MAIL_PORT"); - fs.close(); - - mailServer = new MailServer(port); - logger.info("[MailServer] Succesfully initialized mail Server."); - } - catch(IOException e){ - logger.severe("[MailServer] Error intializing mail server."); - System.exit(-1); - } - + mailServer = new MailServer(Integer.valueOf(Config.data.get("MAIL_PORT"))); + logger.info("[MailServer] Successfully initialized mail Server."); } else { logger.info("[MailServer] mail Server already initialized"); } From 46f372cc52758b703253ff53074c9b50a42c8d8f Mon Sep 17 00:00:00 2001 From: cam292 Date: Thu, 23 Jan 2020 10:33:33 -0500 Subject: [PATCH 24/27] Removed dependency on device controller api url from monitors/command senders, moved to the util. Added endpoints to config file --- config.json | 9 +++++++- .../edu/cmu/sei/kalki/CommandManager.java | 7 +++---- .../java/edu/cmu/sei/kalki/IotInterface.java | 9 ++++---- .../edu/cmu/sei/kalki/MonitorManager.java | 19 +++++++---------- .../cmu/sei/kalki/api/ApiServerStartup.java | 9 ++++---- .../cmu/sei/kalki/api/SendCommandServlet.java | 3 +-- .../devicetypes/DLinkCamera/Monitor.java | 12 +++++------ .../CommandSender.java | 4 ++-- .../PhilipsHueLightEmulator/Monitor.java | 4 ++-- .../kalki/devicetypes/UdooNeo/Monitor.java | 8 +++---- .../WeMoInsight/CommandSender.java | 4 ++-- .../devicetypes/WeMoInsight/Monitor.java | 8 ++----- .../sei/kalki/utils/DeviceControllerApi.java | 21 +++++++++---------- .../cmu/sei/kalki/utils/IotCommandSender.java | 6 ++---- .../edu/cmu/sei/kalki/utils/IotMonitor.java | 3 +-- 15 files changed, 60 insertions(+), 66 deletions(-) diff --git a/config.json b/config.json index eeb0b0b..7076aa7 100644 --- a/config.json +++ b/config.json @@ -1,4 +1,11 @@ { "MAIL_PORT": "25000", - "device_controller_api": "10.27.153.3:9090" + "dlink_notification_email": "camera1@dlink.com", + "iot_int_api_path": "/iot-interface-api", + "new_device_path": "/new-device", + "update_device_path": "update-device", + "send_command_path": "/send-command", + "device_controller_api": "10.27.153.3:9090", + "new_status_path": "/new-status", + "new_stage_log_path": "/new-stage-log" } diff --git a/src/main/java/edu/cmu/sei/kalki/CommandManager.java b/src/main/java/edu/cmu/sei/kalki/CommandManager.java index ab5819b..467f0c3 100644 --- a/src/main/java/edu/cmu/sei/kalki/CommandManager.java +++ b/src/main/java/edu/cmu/sei/kalki/CommandManager.java @@ -17,9 +17,8 @@ public CommandManager(){} * Creates command sender from device's type and sends the list of commands * @param device The device receiving commands * @param commands The list of commands to send - * @param apiUrl The url of the DeviceControllerApi */ - public static void processCommands(Device device, List commands, String apiUrl){ + public static void processCommands(Device device, List commands){ try { // Remove white spaces from device type name String deviceTypeName = device.getType().getName(); @@ -27,10 +26,10 @@ public static void processCommands(Device device, List commands, // Get command sender constructor via reflection String classPath = "edu.cmu.kalki.devicetypes."+deviceTypeName+".CommandSender"; - Constructor con = Class.forName(classPath).getConstructor(Device.class, List.class, String.class); + Constructor con = Class.forName(classPath).getConstructor(Device.class, List.class); // Create instance and send sommands - IotCommandSender commandSender = (IotCommandSender) con.newInstance(device, commands, apiUrl); + IotCommandSender commandSender = (IotCommandSender) con.newInstance(device, commands); commandSender.sendCommands(); } catch (Exception e) { // No command sender found for the given device type logger.severe("[CommandManager] Error: there are no commands for a "+device.getType().getName()); diff --git a/src/main/java/edu/cmu/sei/kalki/IotInterface.java b/src/main/java/edu/cmu/sei/kalki/IotInterface.java index ea16f76..b0d7058 100644 --- a/src/main/java/edu/cmu/sei/kalki/IotInterface.java +++ b/src/main/java/edu/cmu/sei/kalki/IotInterface.java @@ -18,13 +18,14 @@ public static void main(String[] args) { System.exit(-1); } - String apiUrl = Config.data.get("device_controller_api"); - - MonitorManager monitor = new MonitorManager("http://"+apiUrl+"/device-controller-api/"); + MonitorManager monitor = new MonitorManager(); logger.info("[IotInterface] MonitorManager initialized."); - if(!startApiServer(monitor)) + if(!startApiServer(monitor)){ + logger.info("[IotInterface] APIServerStartup failed. Exiting."); System.exit(-1); + } + } private static boolean startApiServer(MonitorManager monitor) { diff --git a/src/main/java/edu/cmu/sei/kalki/MonitorManager.java b/src/main/java/edu/cmu/sei/kalki/MonitorManager.java index 971638c..b39581c 100644 --- a/src/main/java/edu/cmu/sei/kalki/MonitorManager.java +++ b/src/main/java/edu/cmu/sei/kalki/MonitorManager.java @@ -1,5 +1,6 @@ package edu.cmu.sei.kalki; +import edu.cmu.sei.kalki.utils.Config; import edu.cmu.sei.kalki.utils.DeviceControllerApi; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.kalki.utils.IotMonitor; @@ -12,17 +13,11 @@ public class MonitorManager { private Logger logger = Logger.getLogger("iot-interface"); private HashMap monitors; - private String apiUrl; - public MonitorManager(String url) { - apiUrl = url; + public MonitorManager() { monitors = new HashMap<>(); } - public String getApiUrl(){ - return apiUrl; - } - /** * Starts a new monitor for the given device * @param device @@ -34,7 +29,7 @@ public void startMonitor(Device device) { } else { logger.info("[MonitorManager] Starting monitor for device: "+device.getId()); - IotMonitor mon = fromDevice(device, apiUrl); + IotMonitor mon = fromDevice(device); monitors.put(device.getId(), mon); logUpdateMonitor(device, "Monitor started"); @@ -70,7 +65,7 @@ public void updateMonitor(Device device) { * @param apiUrl The DeviceControllerApi url * @return The instance of the device's monitor */ - public static IotMonitor fromDevice(Device device, String apiUrl){ + public static IotMonitor fromDevice(Device device){ Logger logger = Logger.getLogger("iot-interface"); try { // Remove white spaces from device type name @@ -79,10 +74,10 @@ public static IotMonitor fromDevice(Device device, String apiUrl){ // Get IotMonitor constructor via reflection String classPath = "edu.cmu.sei.kalki.devicetypes."+deviceTypeName+".Monitor"; - Constructor con = Class.forName(classPath).getConstructor(Integer.TYPE, String.class, Integer.TYPE, String.class); + Constructor con = Class.forName(classPath).getConstructor(Integer.TYPE, String.class, Integer.TYPE); // Create and return instance of specific IotMonitor - IotMonitor mon = (IotMonitor) con.newInstance(device.getId(), device.getIp(), device.getSamplingRate(), apiUrl); + IotMonitor mon = (IotMonitor) con.newInstance(device.getId(), device.getIp(), device.getSamplingRate()); return mon; } catch (Exception e2){ e2.printStackTrace(); @@ -99,7 +94,7 @@ public static IotMonitor fromDevice(Device device, String apiUrl){ private void logUpdateMonitor(Device device, String info) { logger.info("[MonitorManager] Logging monitor update for device: "+device.getId()); StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.INCREASE_SAMPLE_RATE, StageLog.Stage.FINISH, info); - DeviceControllerApi.sendLog(log, apiUrl); + DeviceControllerApi.sendLog(log); } diff --git a/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java b/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java index 19ec888..578f360 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java +++ b/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java @@ -1,13 +1,14 @@ package edu.cmu.sei.kalki.api; import edu.cmu.sei.kalki.MonitorManager; +import edu.cmu.sei.kalki.utils.Config; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import java.util.logging.Logger; public class ApiServerStartup { private static Logger logger = Logger.getLogger("iot-interface"); - private static final String API_URL = "/iot-interface-api"; + private static final String API_URL = Config.data.get("iot_int_api_path"); private static final int SERVER_PORT = 5050; /** @@ -17,9 +18,9 @@ public static void start(MonitorManager monitor) throws Exception { try { Server httpServer = new Server(SERVER_PORT); ServletContextHandler handler = new ServletContextHandler(httpServer, API_URL); - handler.addServlet(NewDeviceServlet.class, "/new-device"); - handler.addServlet(UpdateDeviceServlet.class, "/update-device"); - handler.addServlet(SendCommandServlet.class, "/send-command"); + handler.addServlet(NewDeviceServlet.class, Config.data.get("new_device_path")); + handler.addServlet(UpdateDeviceServlet.class, Config.data.get("update_device_path")); + handler.addServlet(SendCommandServlet.class, Config.data.get("send_command_path")); handler.setAttribute("monitor", monitor); httpServer.start(); diff --git a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java b/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java index 2e34446..cd42478 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java @@ -55,8 +55,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) response.setStatus(HttpStatus.OK_200); logger.info("[SendCommandServlet] Sending commands to device: "+device.toString()); - MonitorManager monitor = (MonitorManager) getServletContext().getAttribute("monitor"); - CommandManager.processCommands(device, commandList, monitor.getApiUrl()); + CommandManager.processCommands(device, commandList); } private List parseCommandList(JSONArray commandList) { diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java index ac9acb7..55407a1 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java @@ -1,5 +1,6 @@ package edu.cmu.sei.kalki.devicetypes.DLinkCamera; +import edu.cmu.sei.kalki.utils.Config; import edu.cmu.sei.kalki.utils.mail.EventObserver; import edu.cmu.sei.kalki.utils.mail.MailServer; import edu.cmu.sei.kalki.utils.IotMonitor; @@ -7,16 +8,15 @@ public class Monitor extends IotMonitor implements EventObserver { - private String listenEmail = "camera1@dlink.com"; + private final String listenEmail = Config.data.get("dlink_notification_email"); - public Monitor(int deviceId, String ip, int samplingRate, String url){ - this.apiUrl = url; + public Monitor(int deviceId, String ip, int samplingRate){ + this.isPollable = false; + this.pollInterval = samplingRate; + this.deviceId = deviceId; MailServer.initialize(); MailServer.registerObserver(this); - isPollable = false; - this.pollInterval = samplingRate; logger.info("[Monitor] Monitor started for device: "+deviceId); - this.deviceId = deviceId; } /** diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java index 707cd4a..38dde3a 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java @@ -14,8 +14,8 @@ public class CommandSender extends IotCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); private JSONObject lights; - public CommandSender(Device device, List commands, String apiUrl) { - super(device, commands, apiUrl); + public CommandSender(Device device, List commands) { + super(device, commands); lights = getAllLights(device.getIp()); } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java index 160b139..4750bfa 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java @@ -1,5 +1,6 @@ package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; +import edu.cmu.sei.kalki.utils.Config; import edu.cmu.sei.kalki.utils.HttpRequest; import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; @@ -26,12 +27,11 @@ public class Monitor extends PollingMonitor { private String authCode = "newdeveloper"; //Default username works for most GET operations private String ip; - public Monitor(int deviceId, String ip, int samplingRate, String url){ + public Monitor(int deviceId, String ip, int samplingRate){ this.deviceId = deviceId; this.pollInterval = samplingRate; this.isPollable = true; this.ip = ip; - this.apiUrl = url; logger.info("[PhleMonitor] Starting monitor."); start(); } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java index af05296..505238b 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java @@ -1,5 +1,6 @@ package edu.cmu.sei.kalki.devicetypes.UdooNeo; +import edu.cmu.sei.kalki.utils.Config; import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; @@ -26,14 +27,14 @@ public class Monitor extends PollingMonitor { private String ip; private int deviceId; - public Monitor(int deviceId, String ip, String username, String password, int samplingRate, String url){ - this(deviceId, ip, samplingRate, url); + public Monitor(int deviceId, String ip, String username, String password, int samplingRate){ + this(deviceId, ip, samplingRate); this.username = username; this.password = password; this.isPollable = true; } - public Monitor(int deviceId, String ip, int samplingRate, String url){ + public Monitor(int deviceId, String ip, int samplingRate){ super(); logger.info("[UdooNeoMonitor] Starting Neo Monitor for device: " + deviceId); this.ip = ip; @@ -42,7 +43,6 @@ public Monitor(int deviceId, String ip, int samplingRate, String url){ this.password = "udooer"; this.pollInterval = samplingRate; this.isPollable = true; - this.apiUrl = url; setSensors(); start(); } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java index d60900a..e81dea9 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java @@ -13,8 +13,8 @@ public class CommandSender extends IotCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); - public CommandSender(Device device, List commands, String apiUrl) { - super(device, commands, apiUrl); + public CommandSender(Device device, List commands) { + super(device, commands); } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java index 8054df6..d2c6159 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java @@ -1,5 +1,6 @@ package edu.cmu.sei.kalki.devicetypes.WeMoInsight; +import edu.cmu.sei.kalki.utils.Config; import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; @@ -13,19 +14,14 @@ import org.json.JSONObject; public class Monitor extends PollingMonitor { - private String deviceIp; - private Boolean isOn; - private Map attributes; - private DeviceStatus status; - public Monitor(int deviceId, String ip, int samplingRate, String url){ + public Monitor(int deviceId, String ip, int samplingRate) { this.deviceIp = ip; this.deviceId = deviceId; this.pollInterval = samplingRate; this.isPollable = true; - this.apiUrl = url; logger.info("[WemoMonitor] Starting monitor."); start(); } diff --git a/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java b/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java index 7d99510..63daa2a 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java @@ -9,37 +9,36 @@ public class DeviceControllerApi { private static final Logger logger = Logger.getLogger("iot-interface"); - private static final String statusEndpoint = "new-status"; - private static final String logEndpoint = "new-stage-log"; + private static final String apiUrl = Config.data.get("device_controller_api"); + private static final String statusPath = Config.data.get("new_status_path"); + private static final String logPath = Config.data.get("new_stage_log_path"); /** * Method to send a device status to the DeviceControllerApi * @param status - * @param apiUrl */ - public static void sendStatus(DeviceStatus status, String apiUrl) { + public static void sendStatus(DeviceStatus status) { JSONObject json = new JSONObject(status.toString()); - sendToApi(json, apiUrl+statusEndpoint); + sendToApi(json, apiUrl+statusPath); } /** * Method to send a Stage Log to the DeviceControllerApi * @param log - * @param apiUrl */ - public static void sendLog(StageLog log, String apiUrl) { + public static void sendLog(StageLog log) { JSONObject json = new JSONObject(log.toString()); - sendToApi(json, apiUrl+logEndpoint); + sendToApi(json, apiUrl+logPath); } /** * Helper method to send a json object to the DeviceControllerApi * @param object - * @param apiUrl + * @param endpoint */ - private static void sendToApi(JSONObject object, String apiUrl){ + private static void sendToApi(JSONObject object, String endpoint){ try { - HttpRequest.postRequest(object, apiUrl); + HttpRequest.postRequest(object, endpoint); } catch (Exception e) { logger.severe("[DeviceControllerApi] Error sending object to DeviceController: "+object.toString()); logger.severe(e.getMessage()); diff --git a/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java b/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java index f95af11..d138d7b 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java @@ -12,15 +12,13 @@ public class IotCommandSender { protected Device device; protected List commands; - protected String apiUrl; public IotCommandSender(){} - public IotCommandSender(Device device, List commands, String apiUrl){ + public IotCommandSender(Device device, List commands){ this.device = device; this.commands = commands; - this.apiUrl = apiUrl; } public void sendCommands() { @@ -41,6 +39,6 @@ public void sendCommands() { protected void logSendCommand(String command) { logger.info("[IotCommandSender] Logging that a command was sent to the device."); StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.SEND_COMMAND, StageLog.Stage.FINISH, "Sent command to device: "+command); - DeviceControllerApi.sendLog(log, apiUrl); + DeviceControllerApi.sendLog(log); } } diff --git a/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java b/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java index a3b948e..c23aa0b 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java @@ -6,7 +6,6 @@ import java.util.logging.Logger; public abstract class IotMonitor { - protected String apiUrl; protected Timer pollTimer = new Timer(); protected int pollInterval; protected boolean isPollable; @@ -30,6 +29,6 @@ public int getPollInterval() { } protected void sendToDeviceController(DeviceStatus status) { - DeviceControllerApi.sendStatus(status, apiUrl); + DeviceControllerApi.sendStatus(status); } } From dba5f37a18c5ea9a7bb8402cef6ed1c84c217e50 Mon Sep 17 00:00:00 2001 From: cam292 Date: Thu, 23 Jan 2020 11:04:28 -0500 Subject: [PATCH 25/27] Bug fixes --- config.json | 2 +- src/main/java/edu/cmu/sei/kalki/CommandManager.java | 6 +++--- src/main/java/edu/cmu/sei/kalki/MonitorManager.java | 3 +-- .../sei/kalki/devicetypes/WeMoInsight/CommandSender.java | 5 ++++- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/config.json b/config.json index 7076aa7..806a192 100644 --- a/config.json +++ b/config.json @@ -3,7 +3,7 @@ "dlink_notification_email": "camera1@dlink.com", "iot_int_api_path": "/iot-interface-api", "new_device_path": "/new-device", - "update_device_path": "update-device", + "update_device_path": "/update-device", "send_command_path": "/send-command", "device_controller_api": "10.27.153.3:9090", "new_status_path": "/new-status", diff --git a/src/main/java/edu/cmu/sei/kalki/CommandManager.java b/src/main/java/edu/cmu/sei/kalki/CommandManager.java index 467f0c3..616efdd 100644 --- a/src/main/java/edu/cmu/sei/kalki/CommandManager.java +++ b/src/main/java/edu/cmu/sei/kalki/CommandManager.java @@ -21,11 +21,10 @@ public CommandManager(){} public static void processCommands(Device device, List commands){ try { // Remove white spaces from device type name - String deviceTypeName = device.getType().getName(); - deviceTypeName.replace("\\s+",""); + String deviceTypeName = device.getType().getName().replaceAll("\\s+",""); // Get command sender constructor via reflection - String classPath = "edu.cmu.kalki.devicetypes."+deviceTypeName+".CommandSender"; + String classPath = "edu.cmu.sei.kalki.devicetypes."+deviceTypeName+".CommandSender"; Constructor con = Class.forName(classPath).getConstructor(Device.class, List.class); // Create instance and send sommands @@ -33,6 +32,7 @@ public static void processCommands(Device device, List commands){ commandSender.sendCommands(); } catch (Exception e) { // No command sender found for the given device type logger.severe("[CommandManager] Error: there are no commands for a "+device.getType().getName()); + logger.severe("[CommandManager] Error: "+e); } } } diff --git a/src/main/java/edu/cmu/sei/kalki/MonitorManager.java b/src/main/java/edu/cmu/sei/kalki/MonitorManager.java index b39581c..c5859db 100644 --- a/src/main/java/edu/cmu/sei/kalki/MonitorManager.java +++ b/src/main/java/edu/cmu/sei/kalki/MonitorManager.java @@ -69,8 +69,7 @@ public static IotMonitor fromDevice(Device device){ Logger logger = Logger.getLogger("iot-interface"); try { // Remove white spaces from device type name - String deviceTypeName = device.getType().getName(); - deviceTypeName.replace("\\s+",""); + String deviceTypeName = device.getType().getName().replaceAll("\\s+",""); // Get IotMonitor constructor via reflection String classPath = "edu.cmu.sei.kalki.devicetypes."+deviceTypeName+".Monitor"; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java index e81dea9..7407223 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java @@ -75,10 +75,13 @@ private void executeScript(String command){ } logger.info("[WemoCommandSender] Processing error stream"); + StringBuilder error = new StringBuilder(); // read any errors from the attempted command while ((s = stdError.readLine()) != null) { - logger.severe("[WemoCommandSender] Error with wemo.py: "+s); + error.append(s+"\n"); } + if(error.toString().length()>0) + logger.severe("[WemoCommandSender] Error with wemo.py: "+error.toString()); logSendCommand(command); } catch (IOException e) { From 9549a062ad10e857410c45bf2730d99f47679bd8 Mon Sep 17 00:00:00 2001 From: cam292 Date: Thu, 23 Jan 2020 11:29:43 -0500 Subject: [PATCH 26/27] Final bug fixes --- config.json | 2 +- .../PhilipsHueLightEmulator/Monitor.java | 40 +------------------ .../kalki/devicetypes/UdooNeo/Monitor.java | 1 - .../devicetypes/WeMoInsight/Monitor.java | 1 - 4 files changed, 2 insertions(+), 42 deletions(-) diff --git a/config.json b/config.json index 806a192..1a8567f 100644 --- a/config.json +++ b/config.json @@ -5,7 +5,7 @@ "new_device_path": "/new-device", "update_device_path": "/update-device", "send_command_path": "/send-command", - "device_controller_api": "10.27.153.3:9090", + "device_controller_api": "http://10.27.153.3:9090/device-controller-api", "new_status_path": "/new-status", "new_stage_log_path": "/new-stage-log" } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java index 4750bfa..690e0fe 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java @@ -1,27 +1,14 @@ package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; -import edu.cmu.sei.kalki.utils.Config; import edu.cmu.sei.kalki.utils.HttpRequest; import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.util.Set; -//import org.apache.http.client.ClientProtocolException; -//import org.apache.http.client.config.RequestConfig; -//import org.apache.http.impl.client.HttpClientBuilder; import org.json.JSONException; import org.json.JSONObject; -//import org.apache.http.HttpEntity; -//import org.apache.http.HttpHeaders; -//import org.apache.http.client.methods.CloseableHttpResponse; -//import org.apache.http.client.methods.HttpGet; -//import org.apache.http.impl.client.CloseableHttpClient; -//import org.apache.http.impl.client.HttpClients; -//import org.apache.http.util.EntityUtils; - - public class Monitor extends PollingMonitor { private String authCode = "newdeveloper"; //Default username works for most GET operations @@ -44,32 +31,7 @@ public Monitor(int deviceId, String ip, int samplingRate){ */ public JSONObject issueCommand(String path){ String targetURL = "http://" + ip + "/api/" + authCode + "/" + path; - logger.info(targetURL); try{ - -// int timeout = 5; -// RequestConfig config = RequestConfig.custom() -// .setConnectTimeout(timeout * 1000) -// .setConnectionRequestTimeout(timeout * 1000) -// .setSocketTimeout(timeout * 1000).build(); -// CloseableHttpClient httpClient = -// HttpClientBuilder.create().setDefaultRequestConfig(config).build(); -// HttpGet request = new HttpGet(targetURL); -// -// -// CloseableHttpResponse response = httpClient.execute(request); -// -// HttpEntity entity = response.getEntity(); -// logger.info(entity.toString()); -// if (entity != null) { -// logger.info("converting to string"); -// String result = EntityUtils.toString(entity); -// logger.info("closing up"); -// response.close(); -// httpClient.close(); -// return result; -// } - return HttpRequest.getRequest(targetURL); } catch (Exception e) { logger.severe("[PhleMonitor] Error getting a response from the bridge: "+ e); @@ -84,7 +46,6 @@ public JSONObject issueCommand(String path){ @Override public void pollDevice(DeviceStatus status) { JSONObject json = issueCommand("lights"); - logger.info("[PhleMonitor] Getting current status from response " + json.toString()); try { Set keys = json.keySet(); @@ -100,6 +61,7 @@ public void pollDevice(DeviceStatus status) { status.addAttribute("isOn", isOn); status.addAttribute("brightness", brightness); status.addAttribute("name", name); + logger.info("[PhleMonitor] Successfully polled device."); } catch (JSONException err){ logger.severe("[PhleMonitor] Error: " + err.toString()); } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java index 505238b..d5034ae 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java @@ -1,6 +1,5 @@ package edu.cmu.sei.kalki.devicetypes.UdooNeo; -import edu.cmu.sei.kalki.utils.Config; import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java index d2c6159..e5bbbcd 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java @@ -1,6 +1,5 @@ package edu.cmu.sei.kalki.devicetypes.WeMoInsight; -import edu.cmu.sei.kalki.utils.Config; import edu.cmu.sei.kalki.utils.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; From e970ea86b1d9759b4c698483b02b39e7b5a3ae99 Mon Sep 17 00:00:00 2001 From: cam292 Date: Thu, 23 Jan 2020 14:46:31 -0500 Subject: [PATCH 27/27] Changes proposed in pull request comments --- build.gradle | 8 +--- config.json | 10 ++--- .../{ => iotinterface}/CommandManager.java | 4 +- .../{ => iotinterface}/IotInterface.java | 6 +-- .../{ => iotinterface}/MonitorManager.java | 39 +++++++++++-------- .../api/ApiServerStartup.java | 16 ++++---- .../{ => iotinterface}/api/ApiServlet.java | 3 +- .../api/NewDeviceServlet.java | 4 +- .../api/SendCommandServlet.java | 5 +-- .../api/UpdateDeviceServlet.java | 4 +- .../devicetypes/DLinkCamera/Monitor.java | 17 ++++---- .../devicetypes}/IotCommandSender.java | 9 ++--- .../devicetypes}/IotMonitor.java | 24 +++++------- .../CommandSender.java | 26 +++++++------ .../PhilipsHueLightEmulator/Monitor.java | 24 +++++------- .../devicetypes}/PollingMonitor.java | 18 ++++++++- .../devicetypes/UdooNeo/Monitor.java | 37 +++++++----------- .../WeMoInsight/CommandSender.java | 22 +++++------ .../devicetypes/WeMoInsight/Monitor.java | 27 +++++-------- .../{ => iotinterface}/utils/Config.java | 2 +- .../utils/DeviceControllerApi.java | 12 ++++-- .../{ => iotinterface}/utils/HttpRequest.java | 2 +- .../utils/mail/EventObserver.java | 2 +- .../utils/mail/MailServer.java | 4 +- .../utils/mail/MyMessageHandlerFactory.java | 2 +- .../utils/mail/SendMail.java | 2 +- 26 files changed, 156 insertions(+), 173 deletions(-) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/CommandManager.java (93%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/IotInterface.java (91%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/MonitorManager.java (65%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/api/ApiServerStartup.java (62%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/api/ApiServlet.java (98%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/api/NewDeviceServlet.java (93%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/api/SendCommandServlet.java (95%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/api/UpdateDeviceServlet.java (93%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/devicetypes/DLinkCamera/Monitor.java (64%) rename src/main/java/edu/cmu/sei/kalki/{utils => iotinterface/devicetypes}/IotCommandSender.java (84%) rename src/main/java/edu/cmu/sei/kalki/{utils => iotinterface/devicetypes}/IotMonitor.java (54%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/devicetypes/PhilipsHueLightEmulator/CommandSender.java (69%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/devicetypes/PhilipsHueLightEmulator/Monitor.java (73%) rename src/main/java/edu/cmu/sei/kalki/{utils => iotinterface/devicetypes}/PollingMonitor.java (81%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/devicetypes/UdooNeo/Monitor.java (88%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/devicetypes/WeMoInsight/CommandSender.java (75%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/devicetypes/WeMoInsight/Monitor.java (69%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/utils/Config.java (95%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/utils/DeviceControllerApi.java (72%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/utils/HttpRequest.java (97%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/utils/mail/EventObserver.java (59%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/utils/mail/MailServer.java (92%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/utils/mail/MyMessageHandlerFactory.java (97%) rename src/main/java/edu/cmu/sei/kalki/{ => iotinterface}/utils/mail/SendMail.java (96%) diff --git a/build.gradle b/build.gradle index 9bde64c..6539fbe 100644 --- a/build.gradle +++ b/build.gradle @@ -7,9 +7,7 @@ apply plugin: 'java' apply plugin: 'application' -//mainClassName = 'MonitorLauncher' -mainClassName = 'edu.cmu.sei.kalki.IotInterface' -//mainClassName = 'edu.cmu.sei.kalki.Mail.SendMail' +mainClassName = 'edu.cmu.sei.kalki.iotinterface.IotInterface' sourceCompatibility = 1.8 @@ -22,9 +20,6 @@ repositories { } dependencies { -// compile name: 'slf4j-api-1.6.1' -// compile name: 'mail' -// compile name: 'activation' compile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.4.19.v20190610' compile group: 'org.subethamail', name: 'subethasmtp', version: '3.1.3' compile 'org.json:json:20171018' @@ -33,5 +28,4 @@ dependencies { compile name: 'huesdkresources' compile 'com.jcraft:jsch:0.1.55' compile 'org.apache.httpcomponents:httpclient:4.5.10' -// compile name: 'tablelayout' } diff --git a/config.json b/config.json index 1a8567f..9686508 100644 --- a/config.json +++ b/config.json @@ -1,11 +1,7 @@ { "MAIL_PORT": "25000", "dlink_notification_email": "camera1@dlink.com", - "iot_int_api_path": "/iot-interface-api", - "new_device_path": "/new-device", - "update_device_path": "/update-device", - "send_command_path": "/send-command", - "device_controller_api": "http://10.27.153.3:9090/device-controller-api", - "new_status_path": "/new-status", - "new_stage_log_path": "/new-stage-log" + "iot_interface_api_port": "5050", + "device_controller_api_ip": "10.27.153.3", + "device_controller_api_port": "9090" } diff --git a/src/main/java/edu/cmu/sei/kalki/CommandManager.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/CommandManager.java similarity index 93% rename from src/main/java/edu/cmu/sei/kalki/CommandManager.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/CommandManager.java index 616efdd..c9da281 100644 --- a/src/main/java/edu/cmu/sei/kalki/CommandManager.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/CommandManager.java @@ -1,6 +1,6 @@ -package edu.cmu.sei.kalki; +package edu.cmu.sei.kalki.iotinterface; -import edu.cmu.sei.kalki.utils.IotCommandSender; +import edu.cmu.sei.kalki.iotinterface.devicetypes.IotCommandSender; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; diff --git a/src/main/java/edu/cmu/sei/kalki/IotInterface.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/IotInterface.java similarity index 91% rename from src/main/java/edu/cmu/sei/kalki/IotInterface.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/IotInterface.java index b0d7058..011fa01 100644 --- a/src/main/java/edu/cmu/sei/kalki/IotInterface.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/IotInterface.java @@ -1,6 +1,6 @@ -package edu.cmu.sei.kalki; -import edu.cmu.sei.kalki.api.*; -import edu.cmu.sei.kalki.utils.Config; +package edu.cmu.sei.kalki.iotinterface; +import edu.cmu.sei.kalki.iotinterface.api.*; +import edu.cmu.sei.kalki.iotinterface.utils.Config; import java.io.IOException; import java.util.logging.Logger; diff --git a/src/main/java/edu/cmu/sei/kalki/MonitorManager.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/MonitorManager.java similarity index 65% rename from src/main/java/edu/cmu/sei/kalki/MonitorManager.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/MonitorManager.java index c5859db..b9298de 100644 --- a/src/main/java/edu/cmu/sei/kalki/MonitorManager.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/MonitorManager.java @@ -1,9 +1,9 @@ -package edu.cmu.sei.kalki; +package edu.cmu.sei.kalki.iotinterface; -import edu.cmu.sei.kalki.utils.Config; -import edu.cmu.sei.kalki.utils.DeviceControllerApi; +import edu.cmu.sei.kalki.iotinterface.devicetypes.PollingMonitor; +import edu.cmu.sei.kalki.iotinterface.utils.DeviceControllerApi; import edu.cmu.sei.ttg.kalki.models.Device; -import edu.cmu.sei.kalki.utils.IotMonitor; +import edu.cmu.sei.kalki.iotinterface.devicetypes.IotMonitor; import edu.cmu.sei.ttg.kalki.models.StageLog; import java.lang.reflect.Constructor; @@ -13,6 +13,7 @@ public class MonitorManager { private Logger logger = Logger.getLogger("iot-interface"); private HashMap monitors; + private static final String className = "[MonitorManager]"; public MonitorManager() { monitors = new HashMap<>(); @@ -24,11 +25,11 @@ public MonitorManager() { */ public void startMonitor(Device device) { if(device.getSamplingRate() == 0){ - logger.info("[MonitorManager] Sampling rate of 0. Not starting monitor."); + logger.info(className + " Sampling rate of 0. Not starting monitor."); logUpdateMonitor(device, "0 sampling rate"); } else { - logger.info("[MonitorManager] Starting monitor for device: "+device.getId()); + logger.info(className + " Starting monitor for device: "+device.getId()); IotMonitor mon = fromDevice(device); monitors.put(device.getId(), mon); logUpdateMonitor(device, "Monitor started"); @@ -42,19 +43,24 @@ public void startMonitor(Device device) { */ public void updateMonitor(Device device) { IotMonitor mon = monitors.get(device.getId()); - if(mon != null && mon.getPollInterval() != device.getSamplingRate()){ - logger.info("[MonitorManager] Updating monitor for device: "+device.getId()); - if(mon.isPollable() && device.getSamplingRate() > 0){ - logger.info("[MonitorManager] Found monitor, updating sampling rate"); - mon.setPollInterval(device.getSamplingRate()); - monitors.replace(device.getId(), mon); - logUpdateMonitor(device, "Updated monitor"); + if(mon != null){ // monitor exists + + if(!mon.isPollable()){ // monitor doesn't have a sampling rate + logger.info((className + "Monitor is not pollable, no sampling rate to update")); + return; + } + + PollingMonitor pollMon = (PollingMonitor) mon; + if(pollMon.getPollInterval() != device.getSamplingRate()) { // the sampling rate has been updated + logger.info(className + " Updating monitor for device: "+device.getId()); + pollMon.setPollInterval(device.getSamplingRate()); + monitors.replace(device.getId(), pollMon); } else { - logUpdateMonitor(device, "Monitor not updated"); + logger.info(className + " Not updating monitor for device: "+device.getId()+". Sampling rate hasn't changed."); } } else { - logger.severe("[MonitorManager] No monitor found for given device "+device.getId()+". Starting one..."); + logger.info(className + " No monitor found for given device "+device.getId()+". Starting one..."); startMonitor(device); } } @@ -62,7 +68,6 @@ public void updateMonitor(Device device) { /** * Creates an instance of an IotMonitor for the given device's type * @param device The device to be monitored - * @param apiUrl The DeviceControllerApi url * @return The instance of the device's monitor */ public static IotMonitor fromDevice(Device device){ @@ -91,7 +96,7 @@ public static IotMonitor fromDevice(Device device){ * @param device Device the monitor was updated for */ private void logUpdateMonitor(Device device, String info) { - logger.info("[MonitorManager] Logging monitor update for device: "+device.getId()); + logger.info( className + " Logging monitor update for device: "+device.getId()); StageLog log = new StageLog(device.getCurrentState().getId(), StageLog.Action.INCREASE_SAMPLE_RATE, StageLog.Stage.FINISH, info); DeviceControllerApi.sendLog(log); } diff --git a/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/ApiServerStartup.java similarity index 62% rename from src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/api/ApiServerStartup.java index 578f360..d459c92 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/ApiServerStartup.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/ApiServerStartup.java @@ -1,15 +1,15 @@ -package edu.cmu.sei.kalki.api; +package edu.cmu.sei.kalki.iotinterface.api; -import edu.cmu.sei.kalki.MonitorManager; -import edu.cmu.sei.kalki.utils.Config; +import edu.cmu.sei.kalki.iotinterface.MonitorManager; +import edu.cmu.sei.kalki.iotinterface.utils.Config; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import java.util.logging.Logger; public class ApiServerStartup { private static Logger logger = Logger.getLogger("iot-interface"); - private static final String API_URL = Config.data.get("iot_int_api_path"); - private static final int SERVER_PORT = 5050; + private static final String API_URL = "/iot-interface-api"; + private static final int SERVER_PORT = Integer.parseInt(Config.data.get("iot_interface_api_port")); /** * Starts a Jetty server, with handler for notifications @@ -18,9 +18,9 @@ public static void start(MonitorManager monitor) throws Exception { try { Server httpServer = new Server(SERVER_PORT); ServletContextHandler handler = new ServletContextHandler(httpServer, API_URL); - handler.addServlet(NewDeviceServlet.class, Config.data.get("new_device_path")); - handler.addServlet(UpdateDeviceServlet.class, Config.data.get("update_device_path")); - handler.addServlet(SendCommandServlet.class, Config.data.get("send_command_path")); + handler.addServlet(NewDeviceServlet.class, "/new-device"); + handler.addServlet(UpdateDeviceServlet.class, "/update-device"); + handler.addServlet(SendCommandServlet.class, "/send-command"); handler.setAttribute("monitor", monitor); httpServer.start(); diff --git a/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/ApiServlet.java similarity index 98% rename from src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/api/ApiServlet.java index 4a841c9..87fca5b 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/ApiServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/ApiServlet.java @@ -1,7 +1,6 @@ -package edu.cmu.sei.kalki.api; +package edu.cmu.sei.kalki.iotinterface.api; import edu.cmu.sei.ttg.kalki.models.*; -import org.eclipse.jetty.http.HttpStatus; import org.json.JSONException; import org.json.JSONObject; diff --git a/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/NewDeviceServlet.java similarity index 93% rename from src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/api/NewDeviceServlet.java index bc6842a..01a2bc2 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/NewDeviceServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/NewDeviceServlet.java @@ -1,10 +1,10 @@ -package edu.cmu.sei.kalki.api; +package edu.cmu.sei.kalki.iotinterface.api; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import edu.cmu.sei.kalki.MonitorManager; +import edu.cmu.sei.kalki.iotinterface.MonitorManager; import edu.cmu.sei.ttg.kalki.models.*; import org.eclipse.jetty.http.HttpStatus; diff --git a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/SendCommandServlet.java similarity index 95% rename from src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/api/SendCommandServlet.java index cd42478..fdfb655 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/SendCommandServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/SendCommandServlet.java @@ -1,11 +1,10 @@ -package edu.cmu.sei.kalki.api; +package edu.cmu.sei.kalki.iotinterface.api; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import edu.cmu.sei.kalki.CommandManager; -import edu.cmu.sei.kalki.MonitorManager; +import edu.cmu.sei.kalki.iotinterface.CommandManager; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; import org.eclipse.jetty.http.HttpStatus; diff --git a/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/UpdateDeviceServlet.java similarity index 93% rename from src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/api/UpdateDeviceServlet.java index ba882a2..36c7d65 100644 --- a/src/main/java/edu/cmu/sei/kalki/api/UpdateDeviceServlet.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/api/UpdateDeviceServlet.java @@ -1,10 +1,10 @@ -package edu.cmu.sei.kalki.api; +package edu.cmu.sei.kalki.iotinterface.api; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import edu.cmu.sei.kalki.MonitorManager; +import edu.cmu.sei.kalki.iotinterface.MonitorManager; import edu.cmu.sei.ttg.kalki.models.Device; import org.eclipse.jetty.http.HttpStatus; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/DLinkCamera/Monitor.java similarity index 64% rename from src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/DLinkCamera/Monitor.java index 55407a1..2ec1935 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/DLinkCamera/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/DLinkCamera/Monitor.java @@ -1,22 +1,21 @@ -package edu.cmu.sei.kalki.devicetypes.DLinkCamera; +package edu.cmu.sei.kalki.iotinterface.devicetypes.DLinkCamera; -import edu.cmu.sei.kalki.utils.Config; -import edu.cmu.sei.kalki.utils.mail.EventObserver; -import edu.cmu.sei.kalki.utils.mail.MailServer; -import edu.cmu.sei.kalki.utils.IotMonitor; +import edu.cmu.sei.kalki.iotinterface.utils.Config; +import edu.cmu.sei.kalki.iotinterface.utils.mail.EventObserver; +import edu.cmu.sei.kalki.iotinterface.utils.mail.MailServer; +import edu.cmu.sei.kalki.iotinterface.devicetypes.IotMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; public class Monitor extends IotMonitor implements EventObserver { private final String listenEmail = Config.data.get("dlink_notification_email"); + private static final String logId = "[DLinkCameraMonitor]"; public Monitor(int deviceId, String ip, int samplingRate){ - this.isPollable = false; - this.pollInterval = samplingRate; - this.deviceId = deviceId; + super(deviceId, ip, false); MailServer.initialize(); MailServer.registerObserver(this); - logger.info("[Monitor] Monitor started for device: "+deviceId); + logger.info(logId + " Monitor started for device: "+deviceId); } /** diff --git a/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/IotCommandSender.java similarity index 84% rename from src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/IotCommandSender.java index d138d7b..f7c4915 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/IotCommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/IotCommandSender.java @@ -1,5 +1,6 @@ -package edu.cmu.sei.kalki.utils; +package edu.cmu.sei.kalki.iotinterface.devicetypes; +import edu.cmu.sei.kalki.iotinterface.utils.DeviceControllerApi; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; import edu.cmu.sei.ttg.kalki.models.StageLog; @@ -7,15 +8,13 @@ import java.util.List; import java.util.logging.Logger; -public class IotCommandSender { +public abstract class IotCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); protected Device device; protected List commands; - public IotCommandSender(){} - public IotCommandSender(Device device, List commands){ this.device = device; this.commands = commands; @@ -30,7 +29,7 @@ public void sendCommands() { /** * Method to be overwritten by child class. Check if it's a valid command, then send accordingly */ - protected void sendCommand(DeviceCommand command){ return;} + protected abstract void sendCommand(DeviceCommand command); /** * Sends StageLog to Device Controller indicating a command was sent to the device diff --git a/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/IotMonitor.java similarity index 54% rename from src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/IotMonitor.java index c23aa0b..c5b59c1 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/IotMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/IotMonitor.java @@ -1,33 +1,27 @@ -package edu.cmu.sei.kalki.utils; +package edu.cmu.sei.kalki.iotinterface.devicetypes; +import edu.cmu.sei.kalki.iotinterface.utils.DeviceControllerApi; import edu.cmu.sei.ttg.kalki.models.*; -import java.util.Timer; import java.util.logging.Logger; public abstract class IotMonitor { - protected Timer pollTimer = new Timer(); - protected int pollInterval; - protected boolean isPollable; - protected boolean timerGoing = false; protected int deviceId; + protected String deviceIp; + protected boolean isPollable; protected final Logger logger = Logger.getLogger("iot-interface"); - public IotMonitor(){ } + public IotMonitor(int deviceId, String deviceIp, boolean isPollable){ + this.deviceId = deviceId; + this.deviceIp = deviceIp; + this.isPollable = isPollable; + } public boolean isPollable() { return isPollable; } - public void setPollInterval(int pollInterval) { - this.pollInterval = pollInterval; - } - - public int getPollInterval() { - return pollInterval; - } - protected void sendToDeviceController(DeviceStatus status) { DeviceControllerApi.sendStatus(status); } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PhilipsHueLightEmulator/CommandSender.java similarity index 69% rename from src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PhilipsHueLightEmulator/CommandSender.java index 38dde3a..25abea5 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PhilipsHueLightEmulator/CommandSender.java @@ -1,7 +1,7 @@ -package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; +package edu.cmu.sei.kalki.iotinterface.devicetypes.PhilipsHueLightEmulator; -import edu.cmu.sei.kalki.utils.HttpRequest; -import edu.cmu.sei.kalki.utils.IotCommandSender; +import edu.cmu.sei.kalki.iotinterface.utils.HttpRequest; +import edu.cmu.sei.kalki.iotinterface.devicetypes.IotCommandSender; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; import org.json.JSONObject; @@ -12,6 +12,8 @@ public class CommandSender extends IotCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); + private static final String logId = "[PhleCommandSender]"; + private static final String phleBasePath = "/api/newdeveloper/lights/"; private JSONObject lights; public CommandSender(Device device, List commands) { @@ -25,10 +27,10 @@ public CommandSender(Device device, List commands) { */ @Override protected void sendCommand(DeviceCommand command) { - logger.info("[PhleCommandSender] Sending commands to PHLE: "+device.getId()); + logger.info(logId + " Sending commands to PHLE: "+device.getId()); if(lights== null){ - logger.severe("[PhleCommandSender] Unable to get lights from bridge"); + logger.severe(logId + " Unable to get lights from bridge"); return; } Iterator lightIds = lights.keys(); @@ -36,12 +38,12 @@ protected void sendCommand(DeviceCommand command) { int id = Integer.parseInt(lightIds.next()); switch (command.getName()){ case "turn-on": - logger.info("[PhleCommandSender] Sending 'turn-on' command to PHLE: " + device.getId()); + logger.info(logId + " Sending 'turn-on' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"true"); logSendCommand(command.getName()); break; case "turn-off": - logger.info("[PhleCommandSender] Sending 'turn-off' command to PHLE: " + device.getId()); + logger.info(logId + " Sending 'turn-off' command to PHLE: " + device.getId()); sendIsOn(device.getIp(), id,"false"); logSendCommand(command.getName()); break; @@ -52,7 +54,7 @@ protected void sendCommand(DeviceCommand command) { case "set-group": case "set-scene": default: - logger.severe("[PhleCommandSender] Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); + logger.severe(logId + " Command: " + command.getName() + " not supported for Phillips Hue Light Emulator."); } } } @@ -66,10 +68,10 @@ protected void sendCommand(DeviceCommand command) { private static void sendIsOn(String ip, int lightId, String isOn) { try { JSONObject body = new JSONObject("{\"on\":"+isOn+"}"); - String apiUrl = "http://"+ip+"/api/newdeveloper/lights/"+lightId+"/state"; + String apiUrl = "http://"+ip+ phleBasePath +lightId+"/state"; HttpRequest.putRequest(body, apiUrl); } catch (Exception e) { - logger.severe("[PhleCommandSender] Error sending command to device!"); + logger.severe(logId + " Error sending command to device!"); logger.severe(e.getMessage()); } } @@ -82,9 +84,9 @@ private static void sendIsOn(String ip, int lightId, String isOn) { private static JSONObject getAllLights(String ip) { JSONObject json = null; try { - json = HttpRequest.getRequest("http://"+ip+"/api/newdeveloper/lights"); + json = HttpRequest.getRequest("http://"+ip+phleBasePath); } catch (Exception e) { - logger.severe("[PhleCommandSender] Error getting all lights."); + logger.severe(logId + " Error getting all lights."); logger.severe(e.getMessage()); } return json; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PhilipsHueLightEmulator/Monitor.java similarity index 73% rename from src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PhilipsHueLightEmulator/Monitor.java index 690e0fe..8ddabe2 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/PhilipsHueLightEmulator/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PhilipsHueLightEmulator/Monitor.java @@ -1,7 +1,7 @@ -package edu.cmu.sei.kalki.devicetypes.PhilipsHueLightEmulator; +package edu.cmu.sei.kalki.iotinterface.devicetypes.PhilipsHueLightEmulator; -import edu.cmu.sei.kalki.utils.HttpRequest; -import edu.cmu.sei.kalki.utils.PollingMonitor; +import edu.cmu.sei.kalki.iotinterface.utils.HttpRequest; +import edu.cmu.sei.kalki.iotinterface.devicetypes.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.util.Set; @@ -10,16 +10,12 @@ import org.json.JSONObject; public class Monitor extends PollingMonitor { - + private static final String logId = "[PhleMonitor]"; private String authCode = "newdeveloper"; //Default username works for most GET operations - private String ip; public Monitor(int deviceId, String ip, int samplingRate){ - this.deviceId = deviceId; - this.pollInterval = samplingRate; - this.isPollable = true; - this.ip = ip; - logger.info("[PhleMonitor] Starting monitor."); + super(deviceId, ip, true, samplingRate); + logger.info(logId + " Starting monitor."); start(); } @@ -30,11 +26,11 @@ public Monitor(int deviceId, String ip, int samplingRate){ * @return String representation of the response from the API */ public JSONObject issueCommand(String path){ - String targetURL = "http://" + ip + "/api/" + authCode + "/" + path; + String targetURL = "http://" + deviceIp + "/api/" + authCode + "/" + path; try{ return HttpRequest.getRequest(targetURL); } catch (Exception e) { - logger.severe("[PhleMonitor] Error getting a response from the bridge: "+ e); + logger.severe(logId + " Error getting a response from the bridge: "+ e); return new JSONObject("{\"error\": \"Error\"}"); } } @@ -61,9 +57,9 @@ public void pollDevice(DeviceStatus status) { status.addAttribute("isOn", isOn); status.addAttribute("brightness", brightness); status.addAttribute("name", name); - logger.info("[PhleMonitor] Successfully polled device."); + logger.info(logId + " Successfully polled device."); } catch (JSONException err){ - logger.severe("[PhleMonitor] Error: " + err.toString()); + logger.severe(logId + " Error: " + err.toString()); } } diff --git a/src/main/java/edu/cmu/sei/kalki/utils/PollingMonitor.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PollingMonitor.java similarity index 81% rename from src/main/java/edu/cmu/sei/kalki/utils/PollingMonitor.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PollingMonitor.java index 1879035..7bb2793 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/PollingMonitor.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/PollingMonitor.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.utils; +package edu.cmu.sei.kalki.iotinterface.devicetypes; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; @@ -6,6 +6,16 @@ import java.util.TimerTask; public abstract class PollingMonitor extends IotMonitor { + protected int pollInterval; + protected Timer pollTimer; + private boolean timerGoing; + + public PollingMonitor(int deviceId, String deviceIp, boolean isPollable, int pollInterval) { + super(deviceId, deviceIp, isPollable); + this.pollInterval = pollInterval; + this.pollTimer = new Timer(); + this.timerGoing = false; + } /** * Polls the device for updates. Adds all device attributes to status. @@ -71,10 +81,14 @@ public void run() { * Sets the interval for polling the device for updates. * @param newInterval new interval, in milliseconds. */ - @Override public void setPollInterval(int newInterval) { pollInterval = newInterval; stopPolling(); startPolling(); } + + public int getPollInterval() { + return pollInterval; + } + } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/UdooNeo/Monitor.java similarity index 88% rename from src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/UdooNeo/Monitor.java index d5034ae..9ed159b 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/UdooNeo/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/UdooNeo/Monitor.java @@ -1,6 +1,6 @@ -package edu.cmu.sei.kalki.devicetypes.UdooNeo; +package edu.cmu.sei.kalki.iotinterface.devicetypes.UdooNeo; -import edu.cmu.sei.kalki.utils.PollingMonitor; +import edu.cmu.sei.kalki.iotinterface.devicetypes.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.io.IOException; @@ -19,31 +19,22 @@ import com.jcraft.jsch.JSchException; public class Monitor extends PollingMonitor { - + private static final String logId = "[UdooNeoMonitor]"; private List sensors = new ArrayList(); private String username; private String password; - private String ip; - private int deviceId; - public Monitor(int deviceId, String ip, String username, String password, int samplingRate){ - this(deviceId, ip, samplingRate); + public Monitor(int deviceId, String ip, int samplingRate, String username, String password){ + super(deviceId, ip, true, samplingRate); this.username = username; this.password = password; - this.isPollable = true; + logger.info(logId + " Starting Neo Monitor for device: " + deviceId); + setSensors(); + start(); } public Monitor(int deviceId, String ip, int samplingRate){ - super(); - logger.info("[UdooNeoMonitor] Starting Neo Monitor for device: " + deviceId); - this.ip = ip; - this.deviceId = deviceId; - this.username = "udooer"; - this.password = "udooer"; - this.pollInterval = samplingRate; - this.isPollable = true; - setSensors(); - start(); + this(deviceId, ip, samplingRate, "udooer", "udooer"); } /** @@ -74,7 +65,7 @@ public String getCommand(){ public Map parseResponse(List responses) { Map result = new HashMap(); if (responses.size() < 1){ - logger.severe("[UdooNeoMonitor] Missing response from Udoo Neo."); + logger.severe(logId + " Missing response from Udoo Neo."); } else { String response = responses.get(0); @@ -151,7 +142,7 @@ public void pollDevice(DeviceStatus status) { Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); JSch jsch = new JSch(); - Session session = jsch.getSession(username, ip, 22); + Session session = jsch.getSession(username, deviceIp, 22); session.setPassword(password); session.setConfig(config); session.connect(); @@ -164,7 +155,7 @@ public void pollDevice(DeviceStatus status) { channel.connect(); InputStream inStream = channel.getInputStream(); - logger.info("[UdooNeoMonitor] Sent commands to device"); + logger.info(logId + " Sent commands to poll device"); List lines = new ArrayList(); int c = inStream.read(); @@ -190,11 +181,11 @@ public void pollDevice(DeviceStatus status) { status.addAttribute(key, attributes.get(key)); } } catch (JSchException e1){ - logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); + logger.severe(logId + " Exception happened - here's what I know: "); logger.severe(e1.getMessage()); } catch (IOException e) { - logger.severe("[UdooNeoMonitor] Exception happened - here's what I know: "); + logger.severe(logId + " Exception happened - here's what I know: "); logger.severe(e.getMessage()); } return; diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/WeMoInsight/CommandSender.java similarity index 75% rename from src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/WeMoInsight/CommandSender.java index 7407223..c674345 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/CommandSender.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/WeMoInsight/CommandSender.java @@ -1,6 +1,6 @@ -package edu.cmu.sei.kalki.devicetypes.WeMoInsight; +package edu.cmu.sei.kalki.iotinterface.devicetypes.WeMoInsight; -import edu.cmu.sei.kalki.utils.IotCommandSender; +import edu.cmu.sei.kalki.iotinterface.devicetypes.IotCommandSender; import edu.cmu.sei.ttg.kalki.models.Device; import edu.cmu.sei.ttg.kalki.models.DeviceCommand; @@ -12,7 +12,7 @@ public class CommandSender extends IotCommandSender { private static Logger logger = Logger.getLogger("iot-interface"); - + private static final String logId = "[WemoCommandSender]"; public CommandSender(Device device, List commands) { super(device, commands); } @@ -26,7 +26,7 @@ protected void sendCommand(DeviceCommand command) { executeScript(command.getName()); break; default: - logger.severe("[WemoCommandSender] Command: " + command.getName() + " is not a valid command for a Wemo Insight"); + logger.severe(logId + " Command: " + command.getName() + " is not a valid command for a Wemo Insight"); return; } } @@ -56,36 +56,36 @@ private void executeScript(String command){ String[] args = setArgs(device.getIp(), command); Process p = Runtime.getRuntime().exec(args); - logger.info("[WemoCommandSender] Python script executed"); + logger.info(logId + " Python script executed"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); - logger.info("[WemoCommandSender] Input stream captured"); + logger.info(logId + " Input stream captured"); BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); - logger.info("[WemoCommandSender] Error stream captured"); + logger.info(logId + " Error stream captured"); - logger.info("[WemoCommandSender] Processing input stream"); + logger.info(logId + " Processing input stream"); // read the output from the command while ((s = stdInput.readLine()) != null) { logger.info("[CommandSender] " + s); } - logger.info("[WemoCommandSender] Processing error stream"); + logger.info(logId + " Processing error stream"); StringBuilder error = new StringBuilder(); // read any errors from the attempted command while ((s = stdError.readLine()) != null) { error.append(s+"\n"); } if(error.toString().length()>0) - logger.severe("[WemoCommandSender] Error with wemo.py: "+error.toString()); + logger.severe(logId + " Error with wemo.py: "+error.toString()); logSendCommand(command); } catch (IOException e) { - logger.severe("[WemoCommandSender] Error reading response from " + device.getId() + ") " + device.getName()); + logger.severe(logId + " Error reading response from " + device.getId() + ") " + device.getName()); logger.severe(e.getMessage()); } } diff --git a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/WeMoInsight/Monitor.java similarity index 69% rename from src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/WeMoInsight/Monitor.java index e5bbbcd..b523ca2 100644 --- a/src/main/java/edu/cmu/sei/kalki/devicetypes/WeMoInsight/Monitor.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/devicetypes/WeMoInsight/Monitor.java @@ -1,27 +1,21 @@ -package edu.cmu.sei.kalki.devicetypes.WeMoInsight; +package edu.cmu.sei.kalki.iotinterface.devicetypes.WeMoInsight; -import edu.cmu.sei.kalki.utils.PollingMonitor; +import edu.cmu.sei.kalki.iotinterface.devicetypes.PollingMonitor; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; import java.lang.StringBuilder; import org.json.JSONException; import org.json.JSONObject; public class Monitor extends PollingMonitor { - private String deviceIp; - private Map attributes; + private static final String logId = "[WemoMonitor]"; public Monitor(int deviceId, String ip, int samplingRate) { - this.deviceIp = ip; - this.deviceId = deviceId; - this.pollInterval = samplingRate; - this.isPollable = true; - logger.info("[WemoMonitor] Starting monitor."); + super(deviceId, ip, true, samplingRate); + logger.info(logId + " Starting monitor."); start(); } @@ -31,7 +25,6 @@ public Monitor(int deviceId, String ip, int samplingRate) { */ @Override public void pollDevice(DeviceStatus status) { - attributes = new HashMap(); try { // run the command @@ -61,19 +54,17 @@ public void pollDevice(DeviceStatus status) { for(Object keyObj : json.keySet()){ String key = (String) keyObj; String value = (String) json.get(key).toString(); - attributes.put(key, value); + status.addAttribute(key, value); } // read any errors from the attempted command while ((s = stdError.readLine()) != null) { logger.severe(s); } - for (String key : attributes.keySet()){ - status.addAttribute(key, attributes.get(key)); - } + } catch (IOException e) { - logger.severe("[WemoMonitor] Error polling Wemo Insight: " + e.toString()); + logger.severe(logId + " Error polling Wemo Insight: " + e.toString()); } catch (JSONException e) { - logger.severe("[WemoMonitor] Error parsing JSON response from Wemo Insight: " + deviceId + ". " + e.getMessage()); + logger.severe(logId + " Error parsing JSON response from Wemo Insight: " + deviceId + ". " + e.getMessage()); e.printStackTrace(); } diff --git a/src/main/java/edu/cmu/sei/kalki/utils/Config.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/Config.java similarity index 95% rename from src/main/java/edu/cmu/sei/kalki/utils/Config.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/utils/Config.java index eca1164..af160e9 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/Config.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/Config.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.utils; +package edu.cmu.sei.kalki.iotinterface.utils; import org.json.JSONObject; import org.json.JSONTokener; diff --git a/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/DeviceControllerApi.java similarity index 72% rename from src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/utils/DeviceControllerApi.java index 63daa2a..87cbfec 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/DeviceControllerApi.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/DeviceControllerApi.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.utils; +package edu.cmu.sei.kalki.iotinterface.utils; import edu.cmu.sei.ttg.kalki.models.DeviceStatus; import edu.cmu.sei.ttg.kalki.models.StageLog; @@ -9,9 +9,13 @@ public class DeviceControllerApi { private static final Logger logger = Logger.getLogger("iot-interface"); - private static final String apiUrl = Config.data.get("device_controller_api"); - private static final String statusPath = Config.data.get("new_status_path"); - private static final String logPath = Config.data.get("new_stage_log_path"); + private static final String apiIp = Config.data.get("device_controller_api_ip"); + private static final String apiPort = Config.data.get("device_controller_api_port"); + private static final String basePath = "/device-controller-api"; + + private static final String apiUrl = "http://"+apiIp+":"+apiPort+basePath; + private static final String statusPath = "/new-status"; + private static final String logPath = "/new-stage-log"; /** * Method to send a device status to the DeviceControllerApi diff --git a/src/main/java/edu/cmu/sei/kalki/utils/HttpRequest.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/HttpRequest.java similarity index 97% rename from src/main/java/edu/cmu/sei/kalki/utils/HttpRequest.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/utils/HttpRequest.java index 21c0bde..a9c4018 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/HttpRequest.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/HttpRequest.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.utils; +package edu.cmu.sei.kalki.iotinterface.utils; import org.json.JSONObject; diff --git a/src/main/java/edu/cmu/sei/kalki/utils/mail/EventObserver.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/EventObserver.java similarity index 59% rename from src/main/java/edu/cmu/sei/kalki/utils/mail/EventObserver.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/EventObserver.java index b7af7d4..b0ebed1 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/mail/EventObserver.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/EventObserver.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.utils.mail; +package edu.cmu.sei.kalki.iotinterface.utils.mail; public interface EventObserver { public void notify(String message); diff --git a/src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/MailServer.java similarity index 92% rename from src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/MailServer.java index a06e618..8dc840f 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/mail/MailServer.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/MailServer.java @@ -1,6 +1,6 @@ -package edu.cmu.sei.kalki.utils.mail; +package edu.cmu.sei.kalki.iotinterface.utils.mail; -import edu.cmu.sei.kalki.utils.Config; +import edu.cmu.sei.kalki.iotinterface.utils.Config; import org.subethamail.smtp.server.SMTPServer; import java.util.ArrayList; diff --git a/src/main/java/edu/cmu/sei/kalki/utils/mail/MyMessageHandlerFactory.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/MyMessageHandlerFactory.java similarity index 97% rename from src/main/java/edu/cmu/sei/kalki/utils/mail/MyMessageHandlerFactory.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/MyMessageHandlerFactory.java index 60133ca..bd28f4d 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/mail/MyMessageHandlerFactory.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/MyMessageHandlerFactory.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.utils.mail; +package edu.cmu.sei.kalki.iotinterface.utils.mail; import org.subethamail.smtp.*; diff --git a/src/main/java/edu/cmu/sei/kalki/utils/mail/SendMail.java b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/SendMail.java similarity index 96% rename from src/main/java/edu/cmu/sei/kalki/utils/mail/SendMail.java rename to src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/SendMail.java index 3f84af9..0459224 100644 --- a/src/main/java/edu/cmu/sei/kalki/utils/mail/SendMail.java +++ b/src/main/java/edu/cmu/sei/kalki/iotinterface/utils/mail/SendMail.java @@ -1,4 +1,4 @@ -package edu.cmu.sei.kalki.utils.mail; +package edu.cmu.sei.kalki.iotinterface.utils.mail; import java.util.*; import javax.mail.*;