From 6b4693eaafbeb292ced2e230bde3886790d76751 Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 25 May 2016 16:09:29 -0500 Subject: [PATCH] Added Home control, Thermostat and other enhancements. --- pom.xml | 2 +- .../bwssystems/HABridge/hue/HueMulator.java | 10 +- .../java/com/bwssystems/hal/HVACElements.java | 15 ++ .../java/com/bwssystems/hal/HVACName.java | 13 ++ src/main/java/com/bwssystems/hal/HalHome.java | 10 ++ src/main/java/com/bwssystems/hal/HalInfo.java | 58 +++++++- src/main/resources/public/scripts/app.js | 136 +++++++++++++++++- .../resources/public/views/haldevice.html | 26 +++- 8 files changed, 258 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/bwssystems/hal/HVACElements.java create mode 100644 src/main/java/com/bwssystems/hal/HVACName.java diff --git a/pom.xml b/pom.xml index 710f8a6..cec7347 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 2.0.7-hal-b + 2.0.7-hal-c jar HA Bridge diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index 759546e..b4c7755 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -395,7 +395,7 @@ public class HueMulator implements HueErrorStringSet { theHeaders = new Gson().fromJson(device.getHeaders(), NameValue[].class); responseString = this.formatSuccessHueResponse(state, request.body(), stateHasOn, lightId); - if(device.getDeviceType().toLowerCase().contains("hue") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("hueDevice"))) + if((device.getMapType() != null && device.getMapType().equalsIgnoreCase("hueDevice"))) { if(myHueHome != null) { url = device.getOnUrl(); @@ -460,7 +460,7 @@ public class HueMulator implements HueErrorStringSet { } - if(device.getDeviceType().toLowerCase().contains("activity") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyActivity"))) + if((device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyActivity"))) { log.debug("executing HUE api request to change activity to Harmony: " + url); if(myHarmonyHome != null) @@ -480,7 +480,7 @@ public class HueMulator implements HueErrorStringSet { responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/" + lightId + "state\"}}]"; } } - else if(device.getDeviceType().toLowerCase().contains("button") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyButton"))) + else if((device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyButton"))) { log.debug("executing HUE api request to button press(es) to Harmony: " + url); if(myHarmonyHome != null) @@ -510,7 +510,7 @@ public class HueMulator implements HueErrorStringSet { } } - else if(device.getDeviceType().toLowerCase().contains("home") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("nestHomeAway"))) + else if((device.getMapType() != null && device.getMapType().equalsIgnoreCase("nestHomeAway"))) { log.debug("executing HUE api request to set away for nest home: " + url); if(theNest == null) @@ -523,7 +523,7 @@ public class HueMulator implements HueErrorStringSet { theNest.getHome(homeAway.getName()).setAway(homeAway.getAway()); } } - else if(device.getDeviceType().toLowerCase().contains("thermo") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("nestThermoSet"))) + else if((device.getMapType() != null && device.getMapType().equalsIgnoreCase("nestThermoSet"))) { log.debug("executing HUE api request to set thermostat for nest: " + url); if(theNest == null) diff --git a/src/main/java/com/bwssystems/hal/HVACElements.java b/src/main/java/com/bwssystems/hal/HVACElements.java new file mode 100644 index 0000000..446ef42 --- /dev/null +++ b/src/main/java/com/bwssystems/hal/HVACElements.java @@ -0,0 +1,15 @@ +package com.bwssystems.hal; + +import java.util.List; + +public class HVACElements { + private List HVACElements; + + public List getHVACElements() { + return HVACElements; + } + + public void setHVACElements(List hVACElements) { + HVACElements = hVACElements; + } +} diff --git a/src/main/java/com/bwssystems/hal/HVACName.java b/src/main/java/com/bwssystems/hal/HVACName.java new file mode 100644 index 0000000..b4fcd6d --- /dev/null +++ b/src/main/java/com/bwssystems/hal/HVACName.java @@ -0,0 +1,13 @@ +package com.bwssystems.hal; + +public class HVACName { + private String HVACName; + + public String getHVACName() { + return HVACName; + } + + public void setHVACName(String hVACName) { + HVACName = hVACName; + } +} diff --git a/src/main/java/com/bwssystems/hal/HalHome.java b/src/main/java/com/bwssystems/hal/HalHome.java index 6988fbb..5a35893 100644 --- a/src/main/java/com/bwssystems/hal/HalHome.java +++ b/src/main/java/com/bwssystems/hal/HalHome.java @@ -60,6 +60,16 @@ public class HalHome { addHalDevices(deviceList, theResponse, key); else log.warn("Cannot get custom for Hal with name: " + key); + theResponse = hals.get(key).getHVAC(); + if(theResponse != null) + addHalDevices(deviceList, theResponse, key); + else + log.warn("Cannot get HVAC for Hal with name: " + key); + theResponse = hals.get(key).getHome(key); + if(theResponse != null) + addHalDevices(deviceList, theResponse, key); + else + log.warn("Cannot get HVAC for Hal with name: " + key); } return deviceList; } diff --git a/src/main/java/com/bwssystems/hal/HalInfo.java b/src/main/java/com/bwssystems/hal/HalInfo.java index d9016d5..ebaa23e 100644 --- a/src/main/java/com/bwssystems/hal/HalInfo.java +++ b/src/main/java/com/bwssystems/hal/HalInfo.java @@ -20,12 +20,15 @@ import com.google.gson.Gson; public class HalInfo { private static final Logger log = LoggerFactory.getLogger(HalInfo.class); private static final String DEVICE_REQUEST = "/DeviceData!DeviceCmd=GetNames!DeviceType="; + private static final String HVAC_REQUEST = "/HVACData!HVACCmd=GetNames"; private static final String TOKEN_REQUEST = "?Token="; private static final String LIGHT_REQUEST = "Light"; private static final String APPL_REQUEST = "Appl"; - private static final String VIDEO_REQUEST = "Video"; + // private static final String VIDEO_REQUEST = "Video"; private static final String THEATRE_REQUEST = "Theatre"; private static final String CUSTOM_REQUEST = "Custom"; + private static final String HVAC_TYPE = "HVAC"; + private static final String HOME_TYPE = "HOME"; private HttpClient httpClient; private NamedIP halAddress; private String theToken; @@ -53,6 +56,20 @@ public class HalInfo { return getHalDevices(DEVICE_REQUEST + CUSTOM_REQUEST + TOKEN_REQUEST, CUSTOM_REQUEST); } + public List getHVAC() { + return getHalHVAC(HVAC_REQUEST + TOKEN_REQUEST, HVAC_TYPE); + } + + public List getHome(String theDeviceName) { + List deviceList = null; + deviceList = new ArrayList(); + HalDevice aNewHalDevice = new HalDevice(); + aNewHalDevice.setHaldevicetype(HOME_TYPE); + aNewHalDevice.setHaldevicename(theDeviceName); + deviceList.add(aNewHalDevice); + return deviceList; + } + private List getHalDevices(String apiType, String deviceType) { DeviceElements theHalApiResponse = null; List deviceList = null; @@ -92,6 +109,45 @@ public class HalInfo { return deviceList; } + private List getHalHVAC(String apiType, String deviceType) { + HVACElements theHalApiResponse = null; + List deviceList = null; + + String theUrl = null; + String theData; + theUrl = "http://" + halAddress.getIp() + apiType + theToken; + theData = doHttpGETRequest(theUrl); + if(theData != null) { + log.debug("GET HalApiResponse - data: " + theData); + theHalApiResponse = new Gson().fromJson(theData, HVACElements.class); + if(theHalApiResponse.getHVACElements() == null) { + StatusDescription theStatus = new Gson().fromJson(theData, StatusDescription.class); + if(theStatus.getStatus() == null) { + log.warn("Cannot get an devices for type " + deviceType + " for hal " + halAddress.getName() + " as response is not parsable."); + } + else { + log.warn("Cannot get an devices for type " + deviceType + " for hal " + halAddress.getName() + ". Status: " + theStatus.getStatus() + ", with description: " + theStatus.getDescription()); + } + return deviceList; + } + deviceList = new ArrayList(); + + Iterator theDeviceNames = theHalApiResponse.getHVACElements().iterator(); + while(theDeviceNames.hasNext()) { + HVACName theDevice = theDeviceNames.next(); + HalDevice aNewHalDevice = new HalDevice(); + aNewHalDevice.setHaldevicetype(deviceType); + aNewHalDevice.setHaldevicename(theDevice.getHVACName()); + deviceList.add(aNewHalDevice); + + } + } + else { + log.warn("Get Hal device types " + deviceType + " for " + halAddress.getName() + " - returned null, no data."); + } + return deviceList; + } + // This function executes the url against the hal protected String doHttpGETRequest(String url) { String theContent = null; diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 2dcc002..72f833e 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -1429,6 +1429,118 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic }; + $scope.buildHALHomeUrls = function (haldevice) { + bridgeService.clearDevice(); + $scope.device.deviceType = "home"; + $scope.device.name = haldevice.haldevicename; + $scope.device.targetDevice = haldevice.halname; + $scope.device.mapType = "halHome"; + $scope.device.mapId = haldevice.haldevicename + "-" + haldevice.halname + "-HomeAway"; + $scope.device.onUrl = "http://" + haldevice.haladdress + "/ModeService!ModeCmd=Set!ModeName=Home?Token=" + $scope.bridge.settings.haltoken; + $scope.device.offUrl = "http://" + haldevice.haladdress + "/ModeService!ModeCmd=Set!ModeName=Away?Token=" + $scope.bridge.settings.haltoken; + }; + + $scope.buildHALHeatUrls = function (haldevice) { + bridgeService.clearDevice(); + $scope.device.deviceType = "thermo"; + $scope.device.name = haldevice.haldevicename + " Heat"; + $scope.device.targetDevice = haldevice.halname; + $scope.device.mapType = "HALThermoSet"; + $scope.device.mapId = haldevice.haldevicename + "-" + haldevice.halname + "-SetHeat"; + $scope.device.onUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Heat?Token=" + + $scope.bridge.settings.haltoken; + $scope.device.dimUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Heat!HeatSpValue=${intensity.percent}?Token=" + + $scope.bridge.settings.haltoken; + $scope.device.offUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Off?Token=" + }; + + $scope.buildHALCoolUrls = function (haldevice) { + bridgeService.clearDevice(); + $scope.device.deviceType = "thermo"; + $scope.device.name = haldevice.haldevicename + " Cool"; + $scope.device.targetDevice = haldevice.halname; + $scope.device.mapType = "HALThermoSet"; + $scope.device.mapId = haldevice.haldevicename + "-" + haldevice.halname + "-SetCool"; + $scope.device.onUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Cool?Token=" + + $scope.bridge.settings.haltoken; + $scope.device.dimUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Cool!CoolSpValue=${intensity.percent}?Token=" + + $scope.bridge.settings.haltoken; + $scope.device.offUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Off?Token=" + }; + + $scope.buildHALAutoUrls = function (haldevice) { + bridgeService.clearDevice(); + $scope.device.deviceType = "thermo"; + $scope.device.name = haldevice.haldevicename + " Auto"; + $scope.device.targetDevice = haldevice.halname; + $scope.device.mapType = "HALThermoSet"; + $scope.device.mapId = haldevice.haldevicename + "-" + haldevice.halname + "-SetAuto"; + $scope.device.onUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Auto?Token=" + + $scope.bridge.settings.haltoken; + $scope.device.offUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Off?Token=" + }; + + $scope.buildHALOffUrls = function (haldevice) { + bridgeService.clearDevice(); + $scope.device.deviceType = "thermo"; + $scope.device.name = haldevice.haldevicename + " Thermostat"; + $scope.device.targetDevice = haldevice.halname; + $scope.device.mapType = "HALThermoSet"; + $scope.device.mapId = haldevice.haldevicename + "-" + haldevice.halname + "-TurnOff"; + $scope.device.onUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Auto?Token=" + + $scope.bridge.settings.haltoken; + $scope.device.offUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!HVACMode=Off?Token=" + }; + + $scope.buildHALFanUrls = function (haldevice) { + bridgeService.clearDevice(); + $scope.device.deviceType = "thermo"; + $scope.device.name = haldevice.haldevicename + " Fan"; + $scope.device.targetDevice = haldevice.halname; + $scope.device.mapType = "HALThermoSet"; + $scope.device.mapId = haldevice.haldevicename + "-" + haldevice.halname + "-SetFan"; + $scope.device.onUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!FanMode=On?Token=" + + $scope.bridge.settings.haltoken; + $scope.device.offUrl = "http://" + haldevice.haladdress + + "/HVACService!HVACCmd=Set!HVACName=" + + haldevice.haldevicename.replaceAll(" ", "%20") + + "!FanMode=Auto?Token=" + + $scope.bridge.settings.haltoken; + }; + $scope.addDevice = function () { if($scope.device.name == "" && $scope.device.onUrl == "") return; @@ -1450,7 +1562,12 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic for(var i = 0; i < $scope.bulk.devices.length; i++) { for(var x = 0; x < bridgeService.state.haldevices.length; x++) { if(bridgeService.state.haldevices[x].haldevicename == $scope.bulk.devices[i]) { - $scope.buildDeviceUrls(bridgeService.state.haldevices[x],dim_control); + if(bridgeService.state.haldevices[x].haldevicetype == "HVAC") + $scope.buildHALAutoUrls(bridgeService.state.haldevices[x]); + else if(bridgeService.state.haldevices[x].haldevicetype == "HOME") + $scope.buildHALHomeUrls(bridgeService.state.haldevices[x]); + else + $scope.buildDeviceUrls(bridgeService.state.haldevices[x],dim_control); devicesList[i] = { name: $scope.device.name, mapId: $scope.device.mapId, @@ -1523,6 +1640,10 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic $scope.deleteDeviceByMapId = function (haldevicename, halname, mapType) { var id = haldevicename + "-" + halname; + if(mapType == "HOME") + id = id + "-HomeAway"; + if(mapType == "HALThermoSet") + id = id + "-SetAuto"; $scope.bridge.mapandid = { id, mapType }; ngDialog.open({ template: 'deleteMapandIdDialog', @@ -1770,7 +1891,8 @@ app.filter('availableHalDeviceId', function(bridgeService) { if(input == null) return out; for (var i = 0; i < input.length; i++) { - if(!bridgeService.findDeviceByMapId(input[i].haldevicename + "-" + input[i].halname, input[i].halname, "halDevice")){ + if(!bridgeService.findDeviceByMapId(input[i].haldevicename + "-" + input[i].halname, input[i].halname, "halDevice") && + !bridgeService.findDeviceByMapId(input[i].haldevicename + "-" + input[i].halname + "-HomeAway", input[i].halname, "halHome") ){ out.push(input[i]); } } @@ -1788,6 +1910,16 @@ app.filter('unavailableHalDeviceId', function(bridgeService) { out.push(input[i]); } } + for (var i = 0; i < input.length; i++) { + if(bridgeService.findDeviceByMapId(input[i].haldevicename + "-" + input[i].halname + "-HomeAway", input[i].halname, "halHome")){ + out.push(input[i]); + } + } + for (var i = 0; i < input.length; i++) { + if(input[i].mapType == "HALThermoSet"){ + out.push(input[i]); + } + } return out; } }); diff --git a/src/main/resources/public/views/haldevice.html b/src/main/resources/public/views/haldevice.html index eba0de7..93b0487 100644 --- a/src/main/resources/public/views/haldevice.html +++ b/src/main/resources/public/views/haldevice.html @@ -10,7 +10,7 @@ href="#/harmonyactivities">Harmony Activities
  • Harmony Devices
  • -
  • Nest
  • +
  • HAL
  • Hue Devices