From fe613f768888b8d6c18d2c039f130181413d4c71 Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 15 Dec 2017 16:34:58 -0600 Subject: [PATCH] Basic OpenHAB functionality added. Need to add String selection functionality. --- pom.xml | 2 +- .../bwssystems/HABridge/BridgeSettings.java | 1 + .../bwssystems/HABridge/DeviceMapTypes.java | 3 +- .../com/bwssystems/HABridge/HomeManager.java | 5 + .../devicemanagmeent/DeviceResource.java | 6 + .../plugins/domoticz/DomoticzHome.java | 26 ++- .../plugins/homewizard/HomeWizardHome.java | 2 +- .../plugins/openhab/OpenHABCommand.java | 19 ++ .../plugins/openhab/OpenHABDevice.java | 27 +++ .../HABridge/plugins/openhab/OpenHABHome.java | 147 ++++++++++++-- .../plugins/openhab/OpenHABInstance.java | 84 +++----- src/main/resources/public/scripts/app.js | 190 +++++++++++++++++- .../resources/public/views/configuration.html | 30 +-- .../resources/public/views/editdevice.html | 32 ++- .../resources/public/views/openhabdevice.html | 141 +++++++++++++ src/main/resources/public/views/system.html | 87 ++++++-- 16 files changed, 670 insertions(+), 132 deletions(-) create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABCommand.java create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABDevice.java create mode 100644 src/main/resources/public/views/openhabdevice.html diff --git a/pom.xml b/pom.xml index f9fa477..a0e0d8e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 5.1.0a + 5.1.0b jar HA Bridge diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java index b8eb403..9ae4d7f 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java @@ -210,6 +210,7 @@ public class BridgeSettings extends BackupHandler { theBridgeSettings.setDomoticzconfigured(theBridgeSettings.isValidDomoticz()); theBridgeSettings.setSomfyconfigured(theBridgeSettings.isValidSomfy()); theBridgeSettings.setHomeWizardConfigured(theBridgeSettings.isValidHomeWizard()); + theBridgeSettings.setOpenhabconfigured(theBridgeSettings.isValidOpenhab()); // Lifx is either configured or not, so it does not need an update. if(serverPortOverride != null) theBridgeSettings.setServerPort(serverPortOverride); diff --git a/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java b/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java index b32e9d9..9167437 100644 --- a/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java +++ b/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java @@ -31,6 +31,7 @@ public class DeviceMapTypes { public final static String[] DOMOTICZ_DEVICE = { "domoticzDevice", "Domoticz Device"}; public final static String[] SOMFY_DEVICE = { "somfyDevice", "Somfy Device"}; public final static String[] LIFX_DEVICE = { "lifxDevice", "LIFX Device"}; + public final static String[] OPENHAB_DEVICE = { "openhabDevice", "OpenHAB Device"}; public final static int typeIndex = 0; public final static int displayIndex = 1; @@ -56,7 +57,6 @@ public class DeviceMapTypes { deviceMapTypes.add(MQTT_MESSAGE); deviceMapTypes.add(NEST_HOMEAWAY); deviceMapTypes.add(NEST_THERMO_SET); - deviceMapTypes.add(SOMFY_DEVICE); deviceMapTypes.add(TCP_DEVICE); deviceMapTypes.add(UDP_DEVICE); deviceMapTypes.add(VERA_DEVICE); @@ -64,6 +64,7 @@ public class DeviceMapTypes { deviceMapTypes.add(FIBARO_DEVICE); deviceMapTypes.add(FIBARO_SCENE); deviceMapTypes.add(SOMFY_DEVICE); + deviceMapTypes.add(OPENHAB_DEVICE); } public static int getTypeIndex() { return typeIndex; diff --git a/src/main/java/com/bwssystems/HABridge/HomeManager.java b/src/main/java/com/bwssystems/HABridge/HomeManager.java index f488885..6dbd3dd 100644 --- a/src/main/java/com/bwssystems/HABridge/HomeManager.java +++ b/src/main/java/com/bwssystems/HABridge/HomeManager.java @@ -19,6 +19,7 @@ import com.bwssystems.HABridge.plugins.http.HTTPHome; import com.bwssystems.HABridge.plugins.hue.HueHome; import com.bwssystems.HABridge.plugins.lifx.LifxHome; import com.bwssystems.HABridge.plugins.mqtt.MQTTHome; +import com.bwssystems.HABridge.plugins.openhab.OpenHABHome; import com.bwssystems.HABridge.plugins.somfy.SomfyHome; import com.bwssystems.HABridge.plugins.tcp.TCPHome; import com.bwssystems.HABridge.plugins.udp.UDPHome; @@ -113,6 +114,10 @@ public class HomeManager { aHome = new LifxHome(bridgeSettings); resourceList.put(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex], aHome); homeList.put(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex], aHome); + //setup the OpenHAB configuration if available + aHome = new OpenHABHome(bridgeSettings); + resourceList.put(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex], aHome); + homeList.put(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex], aHome); } public Home findHome(String type) { diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java index 849ec21..cca67ad 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -315,6 +315,12 @@ public class DeviceResource { return homeManager.findResource(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex]); }, new JsonTransformer()); + get (API_CONTEXT + "/openhab/devices", "application/json", (request, response) -> { + log.debug("Get OpenHAB devices"); + response.status(HttpStatus.SC_OK); + return homeManager.findResource(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex]); + }, new JsonTransformer()); + get (API_CONTEXT + "/map/types", "application/json", (request, response) -> { log.debug("Get map types"); return new DeviceMapTypes().getDeviceMapTypes(); diff --git a/src/main/java/com/bwssystems/HABridge/plugins/domoticz/DomoticzHome.java b/src/main/java/com/bwssystems/HABridge/plugins/domoticz/DomoticzHome.java index 11af8ca..1fbcdfb 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/domoticz/DomoticzHome.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/domoticz/DomoticzHome.java @@ -18,7 +18,10 @@ import com.bwssystems.HABridge.api.hue.HueErrorResponse; import com.bwssystems.HABridge.dao.DeviceDescriptor; import com.bwssystems.HABridge.hue.BrightnessDecode; import com.bwssystems.HABridge.hue.ColorData; +import com.bwssystems.HABridge.hue.ColorDecode; +import com.bwssystems.HABridge.hue.DeviceDataDecode; import com.bwssystems.HABridge.hue.MultiCommandUtil; +import com.bwssystems.HABridge.hue.TimeDecode; import com.bwssystems.HABridge.plugins.http.HTTPHandler; import com.bwssystems.HABridge.plugins.http.HTTPHome; import com.google.gson.Gson; @@ -41,7 +44,7 @@ public class DomoticzHome implements Home { public Object getItems(String type) { if(!validDomoticz) return null; - log.debug("consolidating devices for hues"); + log.debug("consolidating devices for Domoticzs"); List theResponse = null; Iterator keys = domoticzs.keySet().iterator(); List deviceList = new ArrayList(); @@ -95,7 +98,23 @@ public class DomoticzHome implements Home { String theData; String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false); - theData = httpClient.doHttpRequest(theHandler.buildUrl(anUrl), null, null, null, theHandler.buildHeaders()); + if (colorData != null) { + anUrl = ColorDecode.replaceColorData(anUrl, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false); + } + anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device); + anUrl = TimeDecode.replaceTimeValue(anUrl); + + String aBody = null; + if(anItem.getHttpBody()!= null && !anItem.getHttpBody().isEmpty()) { + aBody = BrightnessDecode.calculateReplaceIntensityValue(anItem.getHttpBody(), + intensity, targetBri, targetBriInc, false); + if (colorData != null) { + aBody = ColorDecode.replaceColorData(aBody, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false); + } + aBody = DeviceDataDecode.replaceDeviceData(aBody, device); + aBody = TimeDecode.replaceTimeValue(aBody); + } + theData = httpClient.doHttpRequest(theHandler.buildUrl(anUrl), null, null, aBody, theHandler.buildHeaders()); try { theDomoticzApiResponse = new Gson().fromJson(theData, Devices.class); if(theDomoticzApiResponse.getStatus().equals("OK")) @@ -167,7 +186,7 @@ public class DomoticzHome implements Home { @Override public void closeHome() { log.debug("Closing Home."); - if(closed) { + if(closed || !validDomoticz) { log.debug("Home is already closed...."); return; } @@ -175,6 +194,7 @@ public class DomoticzHome implements Home { if(httpClient != null) httpClient.closeHandler(); + domoticzs = null; closed = true; } } diff --git a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java index b80fd1e..125a139 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java @@ -85,7 +85,7 @@ public class HomeWizardHome implements Home { public List getDevices() { - log.debug("consolidating devices for plug gateways"); + log.debug("consolidating devices for HomeWizard plug gateways"); Iterator keys = plugGateways.keySet().iterator(); ArrayList deviceList = new ArrayList<>(); diff --git a/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABCommand.java b/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABCommand.java new file mode 100644 index 0000000..ef10e5b --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABCommand.java @@ -0,0 +1,19 @@ +package com.bwssystems.HABridge.plugins.openhab; + +public class OpenHABCommand { + private String url; + private String command; + public String getUrl() { + return url; + } + public void setUrl(String url) { + this.url = url; + } + public String getCommand() { + return command; + } + public void setCommand(String command) { + this.command = command; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABDevice.java b/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABDevice.java new file mode 100644 index 0000000..24afef5 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABDevice.java @@ -0,0 +1,27 @@ +package com.bwssystems.HABridge.plugins.openhab; + +public class OpenHABDevice { + + private String address; + private String name; + private OpenHABItem item; + public String getAddress() { + return address; + } + public void setAddress(String address) { + this.address = address; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public OpenHABItem getItem() { + return item; + } + public void setItem(OpenHABItem item) { + this.item = item; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABHome.java b/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABHome.java index 3057fb8..fbafecb 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABHome.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABHome.java @@ -1,7 +1,9 @@ package com.bwssystems.HABridge.plugins.openhab; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.slf4j.Logger; @@ -11,17 +13,24 @@ import com.bwssystems.HABridge.BridgeSettings; import com.bwssystems.HABridge.Home; import com.bwssystems.HABridge.NamedIP; import com.bwssystems.HABridge.api.CallItem; +import com.bwssystems.HABridge.api.hue.HueError; +import com.bwssystems.HABridge.api.hue.HueErrorResponse; import com.bwssystems.HABridge.dao.DeviceDescriptor; +import com.bwssystems.HABridge.hue.BrightnessDecode; import com.bwssystems.HABridge.hue.ColorData; +import com.bwssystems.HABridge.hue.ColorDecode; +import com.bwssystems.HABridge.hue.DeviceDataDecode; import com.bwssystems.HABridge.hue.MultiCommandUtil; +import com.bwssystems.HABridge.hue.TimeDecode; +import com.bwssystems.HABridge.plugins.http.HTTPHandler; +import com.bwssystems.HABridge.plugins.http.HTTPHome; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; public class OpenHABHome implements Home { private static final Logger log = LoggerFactory.getLogger(OpenHABHome.class); private Map openhabMap; private Boolean validOpenhab; - private Gson aGsonHandler; + private HTTPHandler httpClient; private boolean closed; public OpenHABHome(BridgeSettings bridgeSettings) { @@ -35,34 +44,118 @@ public class OpenHABHome implements Home { @Override public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) { - // TODO Auto-generated method stub - return null; + + String theUrl = anItem.getItem().getAsString(); + String responseString = null; + + if(theUrl != null && !theUrl.isEmpty()) { + OpenHABCommand theCommand = null; + try { + theCommand = new Gson().fromJson(theUrl, OpenHABCommand.class); + } catch(Exception e) { + log.warn("Cannot parse command to OpenHAB <<<" + theUrl + ">>>", e); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + return responseString; + } + String intermediate = theCommand.getUrl().substring(theCommand.getUrl().indexOf("://") + 3); + String hostPortion = intermediate.substring(0, intermediate.indexOf('/')); + String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1); + String hostAddr = null; + if (hostPortion.contains(":")) { + hostAddr = hostPortion.substring(0, intermediate.indexOf(':')); + } else + hostAddr = hostPortion; + OpenHABInstance theHandler = findHandlerByAddress(hostAddr); + if(theHandler != null) { + String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, + intensity, targetBri, targetBriInc, false); + if (colorData != null) { + anUrl = ColorDecode.replaceColorData(anUrl, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false); + } + anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device); + anUrl = TimeDecode.replaceTimeValue(anUrl); + + String aCommand = null; + if(theCommand.getCommand() != null && !theCommand.getCommand().isEmpty()) { + aCommand = BrightnessDecode.calculateReplaceIntensityValue(theCommand.getCommand(), + intensity, targetBri, targetBriInc, false); + if (colorData != null) { + aCommand = ColorDecode.replaceColorData(aCommand, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false); + } + aCommand = DeviceDataDecode.replaceDeviceData(aCommand, device); + aCommand = TimeDecode.replaceTimeValue(aCommand); + } + try { + theHandler.callCommand(anUrl, aCommand, httpClient); + } catch (Exception e) { + log.warn("Cannot send comand to OpenHAB", e); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + } + } else { + log.warn("OpenHAB Call could not complete, no address found: " + theUrl); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + } + } else { + log.warn("OpenHAB Call to be presented as http(s)://(:)/payload, format of request unknown: " + theUrl); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + } + return responseString; } @Override public Object getItems(String type) { - // TODO Auto-generated method stub - return null; + + if(!validOpenhab) + return null; + log.debug("consolidating devices for OpenHAB"); + List theResponse = null; + Iterator keys = openhabMap.keySet().iterator(); + List deviceList = new ArrayList(); + while(keys.hasNext()) { + String key = keys.next(); + theResponse = openhabMap.get(key).getDevices(httpClient); + if(theResponse != null) + addOpenhabDevices(deviceList, theResponse, key); + else { + log.warn("Cannot get devices for OpenHAB with name: " + key + ", skipping this OpenHAB."); + continue; + } + } + return deviceList; + } + + private Boolean addOpenhabDevices(List theDeviceList, List theSourceList, String theKey) { + Iterator devices = theSourceList.iterator(); + while(devices.hasNext()) { + OpenHABDevice theDevice = devices.next(); + theDeviceList.add(theDevice); + } + return true; } @Override public Home createHome(BridgeSettings bridgeSettings) { openhabMap = null; - aGsonHandler = null; validOpenhab = bridgeSettings.getBridgeSettingsDescriptor().isValidOpenhab(); log.info("OpenHAB Home created." + (validOpenhab ? "" : " No OpenHABs configured.")); if(validOpenhab) { openhabMap = new HashMap(); - aGsonHandler = - new GsonBuilder() - .create(); - Iterator theList = bridgeSettings.getBridgeSettingsDescriptor().getHassaddress().getDevices().iterator(); + httpClient = HTTPHome.getHandler(); + Iterator theList = bridgeSettings.getBridgeSettingsDescriptor().getOpenhabaddress().getDevices().iterator(); while(theList.hasNext() && validOpenhab) { NamedIP anOpenhab = theList.next(); try { openhabMap.put(anOpenhab.getName(), new OpenHABInstance(anOpenhab)); } catch (Exception e) { - log.error("Cannot get hass (" + anOpenhab.getName() + ") setup, Exiting with message: " + e.getMessage(), e); + log.error("Cannot get OpenHAB (" + anOpenhab.getName() + ") setup, Exiting with message: " + e.getMessage(), e); validOpenhab = false; } } @@ -70,12 +163,36 @@ public class OpenHABHome implements Home { return this; } + private OpenHABInstance findHandlerByAddress(String hostAddress) { + OpenHABInstance aHandler = null; + boolean found = false; + Iterator keys = openhabMap.keySet().iterator(); + while(keys.hasNext()) { + String key = keys.next(); + aHandler = openhabMap.get(key); + if(aHandler != null && aHandler.getOpenHABAddress().getIp().equals(hostAddress)) { + found = true; + break; + } + } + if(!found) + aHandler = null; + return aHandler; + } + @Override public void closeHome() { - if(!closed) { - + log.debug("Closing Home."); + if(!closed && validOpenhab) { + log.debug("Home is already closed...."); + return; } - + + if(httpClient != null) + httpClient.closeHandler(); + + openhabMap = null; + closed = true; } diff --git a/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABInstance.java b/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABInstance.java index f81306d..8e5c295 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABInstance.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/openhab/OpenHABInstance.java @@ -1,7 +1,6 @@ package com.bwssystems.HABridge.plugins.openhab; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.apache.http.client.methods.HttpGet; @@ -12,17 +11,14 @@ import org.slf4j.LoggerFactory; import com.bwssystems.HABridge.NamedIP; import com.bwssystems.HABridge.api.NameValue; import com.bwssystems.HABridge.plugins.http.HTTPHandler; -import com.bwssystems.HABridge.plugins.http.HTTPHome; import com.google.gson.Gson; public class OpenHABInstance { private static final Logger log = LoggerFactory.getLogger(OpenHABInstance.class); private NamedIP theOpenHAB; - private HTTPHandler anHttpHandler; public OpenHABInstance(NamedIP openhabLocation) { super(); - anHttpHandler = HTTPHome.getHandler(); theOpenHAB = openhabLocation; } @@ -34,65 +30,38 @@ public class OpenHABInstance { this.theOpenHAB = openhabAddress; } - public Boolean callCommand(String aCommand) { - log.debug("calling HomeAssistant: " + aCommand); + public Boolean callCommand(String aCommand, String commandData, HTTPHandler httpClient) { + log.debug("calling OpenHAB: " + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + aCommand); String aUrl = null; - if(theOpenHAB.getSecure() != null && theOpenHAB.getSecure()) - aUrl = "https"; - else - aUrl = "http"; -/* String domain = aCommand.getEntityId().substring(0, aCommand.getEntityId().indexOf(".")); - aUrl = aUrl + "://" + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + "/api/services/"; - if(domain.equals("group")) - aUrl = aUrl + "homeassistant"; - else - aUrl = aUrl + domain; - String aBody = "{\"entity_id\":\"" + aCommand.getEntityId() + "\""; NameValue[] headers = null; - if(theOpenHAB.getPassword() != null && !theOpenHAB.getPassword().isEmpty()) { - NameValue password = new NameValue(); - password.setName("x-ha-access"); - password.setValue(theOpenHAB.getPassword()); - headers = new NameValue[1]; - headers[0] = password; + if(theOpenHAB.getSecure() != null && theOpenHAB.getSecure()) + aUrl = "https://"; + else + aUrl = "http://"; + if(theOpenHAB.getUsername() != null && !theOpenHAB.getUsername().isEmpty() && theOpenHAB.getPassword() != null && !theOpenHAB.getPassword().isEmpty()) { + aUrl = aUrl + theOpenHAB.getUsername() + ":" + theOpenHAB.getPassword() + "@"; } - if(aCommand.getState().equalsIgnoreCase("on")) { - aUrl = aUrl + "/turn_on"; - if(aCommand.getBri() != null) - aBody = aBody + ",\"brightness\":" + aCommand.getBri() + "}"; - else - aBody = aBody + "}"; - } - else { - aUrl = aUrl + "/turn_off"; - aBody = aBody + "}"; - } - log.debug("Calling HomeAssistant with url: " + aUrl); - String theData = anHttpHandler.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "application/json", aBody, headers); + aUrl = aUrl + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + "/" + aCommand; + String theData = httpClient.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "text/plain", commandData, headers); log.debug("call Command return is: <" + theData + ">"); - */ return true; } - public List getDevices() { - List theDeviceStates = null; + public List getDevices(HTTPHandler httpClient) { + List deviceList = null; OpenHABItem[] theOpenhabStates; String theUrl = null; String theData; NameValue[] headers = null; - if(theOpenHAB.getPassword() != null && !theOpenHAB.getPassword().isEmpty()) { - NameValue password = new NameValue(); - password.setName("x-ha-access"); - password.setValue(theOpenHAB.getPassword()); - headers = new NameValue[1]; - headers[0] = password; - } if(theOpenHAB.getSecure() != null && theOpenHAB.getSecure()) - theUrl = "https"; + theUrl = "https://"; else - theUrl = "http"; - theUrl = theUrl + "://" + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + "/rest/items?recursive=false"; - theData = anHttpHandler.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, headers); + theUrl = "http://"; + if(theOpenHAB.getUsername() != null && !theOpenHAB.getUsername().isEmpty() && theOpenHAB.getPassword() != null && !theOpenHAB.getPassword().isEmpty()) { + theUrl = theUrl + theOpenHAB.getUsername() + ":" + theOpenHAB.getPassword() + "@"; + } + theUrl = theUrl + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + "/rest/items?recursive=false"; + theData = httpClient.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, headers); if(theData != null) { log.debug("GET OpenHAB States - data: " + theData); theOpenhabStates = new Gson().fromJson(theData, OpenHABItem[].class); @@ -100,17 +69,24 @@ public class OpenHABInstance { log.warn("Cannot get an devices for OpenHAB " + theOpenHAB.getName() + " as response is not parsable."); } else { - theDeviceStates = new ArrayList(Arrays.asList(theOpenhabStates)); + deviceList = new ArrayList(); + + for (int i = 0; i < theOpenhabStates.length; i++) { + OpenHABDevice aNewOpenHABDeviceDevice = new OpenHABDevice(); + aNewOpenHABDeviceDevice.setItem(theOpenhabStates[i]); + aNewOpenHABDeviceDevice.setAddress(theOpenHAB.getIp() + ":" + theOpenHAB.getPort()); + aNewOpenHABDeviceDevice.setName(theOpenHAB.getName()); + deviceList.add(aNewOpenHABDeviceDevice); + + } } } else log.warn("Cannot get an devices for OpenHAB " + theOpenHAB.getName() + " http call failed."); - return theDeviceStates; + return deviceList; } protected void closeClient() { - anHttpHandler.closeHandler(); - anHttpHandler = null; } } diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 5c4bc52..9278166 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -79,6 +79,10 @@ app.config (function ($locationProvider, $routeProvider) { templateUrl: 'views/lifxdevice.html', controller: 'LifxController', requiresAuthentication: true + }).when ('/openhabdevices', { + templateUrl: 'views/openhabdevice.html', + controller: 'OpenHABController', + requiresAuthentication: true }).when ('/login', { templateUrl: 'views/login.html', controller: 'LoginController' @@ -147,7 +151,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n this.state = {base: "./api/devices", bridgelocation: ".", systemsbase: "./system", huebase: "./api", configs: [], backups: [], devices: [], device: {}, mapandid: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], mapTypes: [], olddevicename: "", logShowAll: false, isInControl: false, showVera: false, showFibaro: false, showHarmony: false, showNest: false, showHue: false, showHal: false, showMqtt: false, showHass: false, - showHomeWizard: false, showDomoticz: false, showSomfy: false, showLifx: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null, + showHomeWizard: false, showDomoticz: false, showSomfy: false, showLifx: false, showOpenHAB: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null, filterDevicesOnlyFiltered: false, filterDeviceType: null}; this.displayWarn = function(errorTitle, error) { @@ -460,6 +464,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n return false; } + this.compareHarmonyNumber = function(r1, r2) { if (r1.device !== undefined) { if (r1.device.id === r2.device.id) @@ -557,6 +562,11 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n return; } + this.updateShowOpenHAB = function () { + this.state.showOpenHAB = self.state.settings.openhabconfigured; + return; + } + this.loadBridgeSettings = function () { return $http.get(this.state.systemsbase + "/settings").then( function (response) { @@ -573,6 +583,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n self.updateShowDomoticz(); self.updateShowSomfy(); self.updateShowLifx(); + self.updateShowOpenHAB(); }, function (error) { if (error.status === 401) @@ -880,6 +891,22 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n ); }; + this.viewOpenHABDevices = function () { + if (!this.state.showOpenHAB) + return; + return $http.get(this.state.base + "/openhab/devices").then( + function (response) { + self.state.openhabdevices = response.data; + }, + function (error) { + if (error.status === 401) + $rootScope.$broadcast('securityReinit', 'done'); + else + self.displayWarn("Get OpenHAB Devices Error: ", error); + } + ); + }; + this.formatCallItem = function (currentItem) { if(!currentItem.startsWith("{\"item") && !currentItem.startsWith("[{\"item")) { if (currentItem.startsWith("[") || currentItem.startsWith("{")) @@ -1584,6 +1611,25 @@ app.controller ('SystemController', function ($scope, $location, bridgeService, } } }; + $scope.addOpenHABtoSettings = function (newopenhabname, newopenhabip, newopenhabport, newopenhabusername, newopenhabpassword, newopenhabsecure) { + if($scope.bridge.settings.openhabaddress === undefined || $scope.bridge.settings.openhabaddress === null) { + $scope.bridge.settings.openhabaddress = { devices: [] }; + } + var newopenhab = {name: newopenhabname, ip: newopenhabip, port: newopenhabport, username: newopenhabusername, password: newopenhabpassword, secure: newopenhabsecure } + $scope.bridge.settings.openhabaddress.devices.push(newopenhab); + $scope.newopenhabname = null; + $scope.newopenhabip = null; + $scope.newopenhabport = null; + $scope.newopenhabusername = null; + $scope.newopenhabpassword = null; + }; + $scope.removeOpenHABtoSettings = function (openhabname, openhabip) { + for(var i = $scope.bridge.settings.openhabaddress.devices.length - 1; i >= 0; i--) { + if($scope.bridge.settings.openhabaddress.devices[i].name === openhabname && $scope.bridge.settings.openhabaddress.devices[i].ip === openhabip) { + $scope.bridge.settings.openhabaddress.devices.splice(i, 1); + } + } + }; $scope.bridgeReinit = function () { bridgeService.reinit(); @@ -3549,6 +3595,134 @@ app.controller('SomfyController', function ($scope, $location, bridgeService, ng }; }); +app.controller('OpenHABController', function ($scope, $location, bridgeService, ngDialog) { + $scope.bridge = bridgeService.state; + $scope.device = bridgeService.state.device; + $scope.device_dim_control = ""; + $scope.bulk = { devices: [] }; + $scope.selectAll = false; + bridgeService.viewOpenHABDevices(); + $scope.imgButtonsUrl = "glyphicon glyphicon-plus"; + $scope.buttonsVisible = false; + + $scope.clearDevice = function () { + bridgeService.clearDevice(); + $scope.device = bridgeService.state.device; + }; + + $scope.buildDeviceUrls = function (openhabdevice, dim_control, buildonly) { + var preCmd = "/rest/items/" + openhabdevice.item.name; + if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)) { + dimpayload = "{\"url\":\"http://" + openhabdevice.address + preCmd + "\",\"command\":\"" + dim_control + "\"}"; + } + else + dimpayload = null; + onpayload = "{\"url\":\"http://" + openhabdevice.address + preCmd + "\",\"command\":\"ON\"}"; + offpayload = "{\"url\":\"http://" + openhabdevice.address + preCmd + "\",\"command\":\"OFF\"}"; + bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, true, openhabdevice.item.name + "-" + openhabdevice.name, openhabdevice.item.name, openhabdevice.name, openhabdevice.item.type, "openhabDevice", null, null); + $scope.device = bridgeService.state.device; + if (!buildonly) { + bridgeService.editNewDevice($scope.device); + $location.path('/editdevice'); + } + }; + + $scope.bulkAddDevices = function(dim_control) { + var devicesList = []; + $scope.clearDevice(); + for(var i = 0; i < $scope.bulk.devices.length; i++) { + for(var x = 0; x < bridgeService.state.openhabdevices.length; x++) { + if(bridgeService.state.openhabdevices[x].devicename === $scope.bulk.devices[i]) { + $scope.buildDeviceUrls(bridgeService.state.openhabdevices[x],dim_control,true); + devicesList[i] = { + name: $scope.device.name, + mapId: $scope.device.mapId, + mapType: $scope.device.mapType, + deviceType: $scope.device.deviceType, + targetDevice: $scope.device.targetDevice, + onUrl: $scope.device.onUrl, + dimUrl: $scope.device.dimUrl, + offUrl: $scope.device.offUrl, + colorUrl: $scope.device.colorUrl, + headers: $scope.device.headers, + httpVerb: $scope.device.httpVerb, + contentType: $scope.device.contentType, + contentBody: $scope.device.contentBody, + contentBodyDim: $scope.device.contentBodyDim, + contentBodyOff: $scope.device.contentBodyOff + }; + $scope.clearDevice(); + } + } + } + bridgeService.bulkAddDevice(devicesList).then( + function () { + $scope.clearDevice(); + bridgeService.viewDevices(); + bridgeService.viewHalDevices(); + }, + function (error) { + bridgeService.displayWarn("Error adding openhab devices in bulk.", error) + } + ); + $scope.bulk = { devices: [] }; + $scope.selectAll = false; + }; + + $scope.toggleSelection = function toggleSelection(deviceId) { + var idx = $scope.bulk.devices.indexOf(deviceId); + + // is currently selected + if (idx > -1) { + $scope.bulk.devices.splice(idx, 1); + if($scope.bulk.devices.length === 0 && $scope.selectAll) + $scope.selectAll = false; + } + + // is newly selected + else { + $scope.bulk.devices.push(deviceId); + $scope.selectAll = true; + } + }; + + $scope.toggleSelectAll = function toggleSelectAll() { + if($scope.selectAll) { + $scope.selectAll = false; + $scope.bulk = { devices: [] }; + } + else { + $scope.selectAll = true; + for(var x = 0; x < bridgeService.state.openhabdevices.length; x++) { + if($scope.bulk.devices.indexOf(bridgeService.state.openhabdevices[x]) < 0) + $scope.bulk.devices.push(bridgeService.state.openhabdevices[x].devicename); + } + } + }; + + $scope.toggleButtons = function () { + $scope.buttonsVisible = !$scope.buttonsVisible; + if($scope.buttonsVisible) + $scope.imgButtonsUrl = "glyphicon glyphicon-minus"; + else + $scope.imgButtonsUrl = "glyphicon glyphicon-plus"; + }; + + $scope.deleteDevice = function (device) { + $scope.bridge.device = device; + ngDialog.open({ + template: 'deleteDialog', + controller: 'DeleteDialogCtrl', + className: 'ngdialog-theme-default' + }); + }; + + $scope.editDevice = function (device) { + bridgeService.editDevice(device); + $location.path('/editdevice'); + }; +}); + app.controller('EditController', function ($scope, $location, bridgeService) { $scope.bridge = bridgeService.state; $scope.device = bridgeService.state.device; @@ -3966,6 +4140,20 @@ app.filter('configuredHomeWizardDevices', function (bridgeService) { } }); +app.filter('configuredOpenHABItems', function (bridgeService) { + return function(input) { + var out = []; + if(input === undefined || input === null || input.length === undefined) + return out; + for (var i = 0; i < input.length; i++) { + if (bridgeService.deviceContainsType(input[i], "openhab")) { + out.push(input[i]); + } + } + return out; + } +}); + app.filter('filterDevicesByRequester', function () { return function(input,search,mustContain,deviceType) { var out = []; diff --git a/src/main/resources/public/views/configuration.html b/src/main/resources/public/views/configuration.html index 030aeb9..5456ddd 100644 --- a/src/main/resources/public/views/configuration.html +++ b/src/main/resources/public/views/configuration.html @@ -1,32 +1,24 @@
diff --git a/src/main/resources/public/views/editdevice.html b/src/main/resources/public/views/editdevice.html index a28e5bc..8fe6139 100644 --- a/src/main/resources/public/views/editdevice.html +++ b/src/main/resources/public/views/editdevice.html @@ -2,31 +2,23 @@
  • Bridge Devices
  • Bridge Control
  • Logs
  • -
  • Vera Devices
  • -
  • Vera Scenes
  • -
  • Fibaro Devices
  • -
  • Fibaro Scenes
  • -
  • Harmony Activities
  • -
  • Harmony Devices
  • +
  • Vera Devices
  • +
  • Vera Scenes
  • +
  • Fibaro Devices
  • +
  • Fibaro Scenes
  • +
  • Harmony Activities
  • +
  • Harmony Devices
  • Nest
  • -
  • Hue Devices
  • -
  • HAL Devices
  • -
  • MQTT Messages
  • -
  • HomeAssistant Devices
  • +
  • Hue Devices
  • +
  • HAL Devices
  • +
  • MQTT Messages
  • +
  • HomeAssistant Devices
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • +
  • HomeWizard Devices
  • +
  • OpenHAB Devices
  • diff --git a/src/main/resources/public/views/openhabdevice.html b/src/main/resources/public/views/openhabdevice.html new file mode 100644 index 0000000..44a687d --- /dev/null +++ b/src/main/resources/public/views/openhabdevice.html @@ -0,0 +1,141 @@ + + +
    +
    +

    OpenHAB Device List + ({{bridge.openhabdevices.length}})

    +
    +
    +

    For any OpenHAB Device, use the build action buttons + to generate the item addition information into the ha-bridge device and this will put you into the edit screen. Then + you can modify the name to anything you want that will be the keyword + for the Echo or Google Home. Also, you can go back to any helper tab and click a build + action button to add another item for a multi-command. After you are + done in the edit tab, click the 'Add Bridge Device' to finish that selection + setup. The 'Already Configured OpenHAB Devices' list below will show what + is already setup for your OpenHAB.

    +

    + Also, use this select menu for which type of dim control you would + like to be generated: +

    +

    Use the check boxes by the names to use the bulk addition + feature. Select your items and dim control type if wanted, then click + bulk add below. Your items will be added with on and off or dim and + off if selected with the name of the device from the OpenHAB.

    + + + + + + + + + + + + + + + + + + +
    Row + NameTypeOpenHABBuild Actions
    {{$index+1}} + {{openhabdevice.item.name}}{{openhabdevice.item.type}}{{openhabdevice.name}} + +
    +
    + +
    +
    +
    +
    +

    + Already Configured OpenHAB Devices +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + +
    RowNameCategoryOpenHABMap IdActions
    {{$index+1}}{{device.name}}{{device.deviceType}}{{device.targetDevice}}{{device.mapId}} +

    + + +

    +
    +
    +
    +
    + diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index 095814f..b360be9 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -3,29 +3,22 @@
  • Logs
  • -
  • Vera Devices
  • -
  • Vera Scenes
  • -
  • Fibaro Devices
  • -
  • Fibaro Scenes
  • -
  • Harmony Activities
  • -
  • Harmony Devices
  • +
  • Vera Devices
  • +
  • Vera Scenes
  • +
  • Fibaro Devices
  • +
  • Fibaro Scenes
  • +
  • Harmony Activities
  • +
  • Harmony Devices
  • Nest
  • -
  • Hue Devices
  • -
  • HAL Devices
  • +
  • Hue Devices
  • +
  • HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • -
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • +
  • HomeWizard Devices
  • +
  • OpenHAB Devices
  • Add/Edit
  • @@ -572,6 +565,66 @@ + + OpenHAB Names and IP Addresses + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameIPPortPassword (opt)Use SSLManage
    + Nest Username