From b9437d42e85a371c19b1306f60cf16d3c9400398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Rennfanz?= Date: Sat, 9 Dec 2017 21:15:02 +0100 Subject: [PATCH 1/9] Update README.md file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56d5179..23b69ca 100644 --- a/README.md +++ b/README.md @@ -358,7 +358,7 @@ The Add/Edit tab will show you the fields to fill in for the above in a form, wh The format of the item can be the default HTTP request which executes the URLs formatted as `http://` as a GET. Other options to this are to select the HTTP Verb and add the data type and add a body that is passed with the request. Secure https is supported as well, just use `https://`. When using POST and PUT, you have the ability to specify the body that will be sent with the request as well as the application type for the http call. The valid device types are: "custom", "veraDevice", "veraScene", "harmonyActivity", "harmonyButton", "nestHomeAway", "nestThermoSet", "hueDevice", "halDevice", - "halButton", "halHome", "halThermoSet", "mqttMessage", "cmdDevice", "hassDevice", "tcpDevice", "udpDevice", "httpDevice", "domoticzDevice", "somfyDevice" + "halButton", "halHome", "halThermoSet", "mqttMessage", "cmdDevice", "hassDevice", "homewizardDevice", "tcpDevice", "udpDevice", "httpDevice", "domoticzDevice", "somfyDevice" Filter Ip example: ``` From d337546da70ab27e5acc92d08f4d03acbedf0fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Rennfanz?= Date: Sat, 9 Dec 2017 21:15:18 +0100 Subject: [PATCH 2/9] Add java part of plug-in for HomeWizard SmartPlug support --- .../bwssystems/HABridge/BridgeSettings.java | 1 + .../HABridge/BridgeSettingsDescriptor.java | 31 ++- .../bwssystems/HABridge/DeviceMapTypes.java | 2 + .../com/bwssystems/HABridge/HomeManager.java | 7 +- .../devicemanagmeent/DeviceResource.java | 6 + .../plugins/homewizard/HomeWizardHome.java | 151 ++++++++++++ .../homewizard/HomeWizardSmartPlugDevice.java | 47 ++++ .../homewizard/HomeWizzardSmartPlugInfo.java | 215 ++++++++++++++++++ .../plugins/homewizard/json/Device.java | 49 ++++ 9 files changed, 505 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardSmartPlugDevice.java create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizzardSmartPlugInfo.java create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/homewizard/json/Device.java diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java index 611ec04..b8eb403 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java @@ -209,6 +209,7 @@ public class BridgeSettings extends BackupHandler { theBridgeSettings.setHassconfigured(theBridgeSettings.isValidHass()); theBridgeSettings.setDomoticzconfigured(theBridgeSettings.isValidDomoticz()); theBridgeSettings.setSomfyconfigured(theBridgeSettings.isValidSomfy()); + theBridgeSettings.setHomeWizardConfigured(theBridgeSettings.isValidHomeWizard()); // 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/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java index 4160d2f..6bb1108 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java @@ -93,7 +93,9 @@ public class BridgeSettingsDescriptor { @SerializedName("securityData") @Expose private String securityData; - + @SerializedName("homewizardaddress") + @Expose + private IpList homewizardaddress; private boolean settingsChanged; private boolean veraconfigured; @@ -107,7 +109,8 @@ public class BridgeSettingsDescriptor { private boolean domoticzconfigured; private boolean somfyconfigured; private boolean lifxconfigured; - + private boolean homewizardconfigured; + // Deprecated settings private String haltoken; private boolean upnpstrict; @@ -127,7 +130,7 @@ public class BridgeSettingsDescriptor { this.mqttconfigured = false; this.hassconfigured = false; this.domoticzconfigured = false; - this.somfyconfigured = false; + this.homewizardconfigured = false; this.lifxconfigured = false; this.farenheit = true; this.securityData = null; @@ -188,6 +191,9 @@ public class BridgeSettingsDescriptor { public IpList getSomfyAddress() { return somfyaddress; } + public IpList getHomeWizardAddress() { + return homewizardaddress; + } public void setVeraAddress(IpList veraAddress) { this.veraaddress = veraAddress; } @@ -197,6 +203,9 @@ public class BridgeSettingsDescriptor { public void setSomfyAddress(IpList somfyAddress) { this.somfyaddress = somfyAddress; } + public void setHomeWizardAddress(IpList homewizardaddress) { + this.homewizardaddress = homewizardaddress; + } public IpList getHarmonyAddress() { return harmonyaddress; } @@ -236,6 +245,9 @@ public class BridgeSettingsDescriptor { public boolean isSomfyconfigured() { return somfyconfigured; } + public boolean isHomeWizardConfigured() { + return homewizardconfigured; + } public void setVeraconfigured(boolean veraconfigured) { this.veraconfigured = veraconfigured; } @@ -245,6 +257,9 @@ public class BridgeSettingsDescriptor { public void setSomfyconfigured(boolean somfyconfigured) { this.somfyconfigured = somfyconfigured; } + public void setHomeWizardConfigured(boolean homewizardconfigured) { + this.homewizardconfigured = homewizardconfigured; + } public boolean isHarmonyconfigured() { return harmonyconfigured; } @@ -492,4 +507,14 @@ public class BridgeSettingsDescriptor { this.setSettingsChanged(true); } } + public Boolean isValidHomeWizard() { + if(this.getHomeWizardAddress() == null || this.getHomeWizardAddress().getDevices().size() <= 0) + return false; + + List devicesList = this.getHomeWizardAddress().getDevices(); + if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + return false; + + return true; + } } diff --git a/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java b/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java index 9c13d71..b32e9d9 100644 --- a/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java +++ b/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java @@ -22,6 +22,7 @@ public class DeviceMapTypes { public final static String[] EXEC_DEVICE_COMPAT = { "exec", "Execute Script/Program"}; public final static String[] CMD_DEVICE = { "cmdDevice", "Execute Command/Script/Program"}; public final static String[] HASS_DEVICE = { "hassDevice", "HomeAssistant Device"}; + public final static String[] HOMEWIZARD_DEVICE = { "homewizardDevice", "HomeWizard Device"}; public final static String[] TCP_DEVICE = { "tcpDevice", "TCP Device"}; public final static String[] TCP_DEVICE_COMPAT = { "TCP", "TCP Device"}; public final static String[] UDP_DEVICE = { "udpDevice", "UDP Device"}; @@ -48,6 +49,7 @@ public class DeviceMapTypes { deviceMapTypes.add(HARMONY_ACTIVITY); deviceMapTypes.add(HARMONY_BUTTON); deviceMapTypes.add(HASS_DEVICE); + deviceMapTypes.add(HOMEWIZARD_DEVICE); deviceMapTypes.add(HTTP_DEVICE); deviceMapTypes.add(HUE_DEVICE); deviceMapTypes.add(LIFX_DEVICE); diff --git a/src/main/java/com/bwssystems/HABridge/HomeManager.java b/src/main/java/com/bwssystems/HABridge/HomeManager.java index 0d6824c..f488885 100644 --- a/src/main/java/com/bwssystems/HABridge/HomeManager.java +++ b/src/main/java/com/bwssystems/HABridge/HomeManager.java @@ -14,6 +14,7 @@ import com.bwssystems.HABridge.plugins.exec.CommandHome; import com.bwssystems.HABridge.plugins.hal.HalHome; import com.bwssystems.HABridge.plugins.harmony.HarmonyHome; import com.bwssystems.HABridge.plugins.hass.HassHome; +import com.bwssystems.HABridge.plugins.homewizard.HomeWizardHome; import com.bwssystems.HABridge.plugins.http.HTTPHome; import com.bwssystems.HABridge.plugins.hue.HueHome; import com.bwssystems.HABridge.plugins.lifx.LifxHome; @@ -68,6 +69,10 @@ public class HomeManager { aHome = new HassHome(bridgeSettings); resourceList.put(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex], aHome); homeList.put(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex], aHome); + // Setup the HomeWizard configuration if available + aHome = new HomeWizardHome(bridgeSettings); + resourceList.put(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex], aHome); + homeList.put(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex], aHome); //setup the command execution Home aHome = new CommandHome(bridgeSettings); homeList.put(DeviceMapTypes.EXEC_DEVICE_COMPAT[DeviceMapTypes.typeIndex], aHome); @@ -96,7 +101,7 @@ public class HomeManager { aHome = new FibaroHome(bridgeSettings); resourceList.put(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex], aHome); resourceList.put(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex], aHome); - //setup the Domoticz configuration if available + //setup the Domoticz configuration if available aHome = new DomoticzHome(bridgeSettings); homeList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome); resourceList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome); diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java index c3067b1..849ec21 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -291,6 +291,12 @@ public class DeviceResource { return homeManager.findResource(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex]); }, new JsonTransformer()); + get (API_CONTEXT + "/homewizard/devices", "application/json", (request, response) -> { + log.debug("Get HomeWizard Clients"); + response.status(HttpStatus.SC_OK); + return homeManager.findResource(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]); + }, new JsonTransformer()); + get (API_CONTEXT + "/domoticz/devices", "application/json", (request, response) -> { log.debug("Get Domoticz Clients"); response.status(HttpStatus.SC_OK); diff --git a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java new file mode 100644 index 0000000..02d7278 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java @@ -0,0 +1,151 @@ +package com.bwssystems.HABridge.plugins.homewizard; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.bwssystems.HABridge.BridgeSettings; +import com.bwssystems.HABridge.DeviceMapTypes; +import com.bwssystems.HABridge.Home; +import com.bwssystems.HABridge.NamedIP; +import com.bwssystems.HABridge.api.CallItem; +import com.bwssystems.HABridge.dao.DeviceDescriptor; +import com.bwssystems.HABridge.hue.ColorData; +import com.bwssystems.HABridge.hue.MultiCommandUtil; + +/** + * Control HomeWizard devices over HomeWizard Cloud + * + * @author Björn Rennfanz (bjoern@fam-rennfanz.de) + * + */ +public class HomeWizardHome implements Home { + + private static final Logger log = LoggerFactory.getLogger(HomeWizardHome.class); + + private Map plugGateways; + private Boolean validHomeWizard; + private boolean closed; + + public HomeWizardHome(BridgeSettings bridgeSettings) { + super(); + closed = true; + createHome(bridgeSettings); + closed = false; + } + + @Override + public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, + Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) { + + String responseString = null; + if (!validHomeWizard) { + + log.warn("Should not get here, no HomeWizard smart plug available"); + responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + + "\",\"description\": \"Should not get here, no HomeWizard smart plug available\", \"parameter\": \"/lights/" + + lightId + "state\"}}]"; + } else { + + if (anItem.getType() != null && anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex])) { + + log.debug("Executing HUE api request to change activity to HomeWizard smart plug: " + anItem.getItem().toString()); + String jsonToPost = anItem.getItem().toString(); + + HomeWizzardSmartPlugInfo homeWizzardHandler = getHomeWizzardHandler(device.getTargetDevice()); + if(homeWizzardHandler == null) { + log.warn("Should not get here, no HomeWizard smart plug configured"); + responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + + "\",\"description\": \"Should not get here, no HomeWizard smart plug configured\", \"parameter\": \"/lights/" + + lightId + "state\"}}]"; + } else { + try { + + homeWizzardHandler.execApply(jsonToPost); + } catch (Exception e) { + + log.warn("Error posting request to HomeWizard smart plug"); + responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + + "\",\"description\": \"Error posting request to HomeWizard smart plug\", \"parameter\": \"/lights/" + lightId + "state\"}}]"; + } + } + } + } + + return responseString; + } + + public HomeWizzardSmartPlugInfo getHomeWizzardHandler(String plugName) { + return plugGateways.get(plugName); + } + + public List getDevices() { + + log.debug("consolidating devices for plug gateways"); + Iterator keys = plugGateways.keySet().iterator(); + ArrayList deviceList = new ArrayList<>(); + + while(keys.hasNext()) + { + String key = keys.next(); + for(HomeWizardSmartPlugDevice device : plugGateways.get(key).getDevices()) + deviceList.add(device); + } + + return deviceList; + } + + @Override + public Object getItems(String type) { + + if (validHomeWizard) + { + if (type.equalsIgnoreCase(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex])) + { + return getDevices(); + } + } + + return null; + } + + @Override + public Home createHome(BridgeSettings bridgeSettings) { + + validHomeWizard = bridgeSettings.getBridgeSettingsDescriptor().isValidHomeWizard(); + log.info("HomeWizard Home created. " + (validHomeWizard ? "" : "No HomeWizard gateways configured.")); + + if (validHomeWizard) + { + plugGateways = new HashMap<>(); + Iterator gatewaysList = bridgeSettings.getBridgeSettingsDescriptor().getHomeWizardAddress().getDevices().iterator(); + + while(gatewaysList.hasNext()) { + + NamedIP gateway = gatewaysList.next(); + plugGateways.put(gateway.getName(), new HomeWizzardSmartPlugInfo(gateway, gateway.getName())); + } + } + + return this; + } + + @Override + public void closeHome() { + + log.debug("Closing Home."); + if(closed) { + + log.debug("Home is already closed...."); + return; + } + + plugGateways = null; + closed = true; + } +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardSmartPlugDevice.java b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardSmartPlugDevice.java new file mode 100644 index 0000000..83b4b0a --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardSmartPlugDevice.java @@ -0,0 +1,47 @@ +package com.bwssystems.HABridge.plugins.homewizard; + +/** + * Control HomeWizard devices over HomeWizard Cloud + * + * @author Björn Rennfanz (bjoern@fam-rennfanz.de) + * + */ +public class HomeWizardSmartPlugDevice { + + private String name; + private String gateway; + private String id; + private String typeName; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGateway() { + return gateway; + } + + public void setGateway(String gateway) { + this.gateway = gateway; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTypeName() { + return this.typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizzardSmartPlugInfo.java b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizzardSmartPlugInfo.java new file mode 100644 index 0000000..e27b2a2 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizzardSmartPlugInfo.java @@ -0,0 +1,215 @@ +package com.bwssystems.HABridge.plugins.homewizard; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.bwssystems.HABridge.NamedIP; +import com.bwssystems.HABridge.plugins.homewizard.json.Device; +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import us.monoid.json.JSONException; +import us.monoid.json.JSONObject; + +/** + * Control HomeWizard devices over HomeWizard Cloud + * + * @author Björn Rennfanz (bjoern@fam-rennfanz.de) + * + */ +public class HomeWizzardSmartPlugInfo { + + private static final Logger log = LoggerFactory.getLogger(HomeWizardHome.class); + + private static final String HOMEWIZARD_LOGIN_URL = "https://cloud.homewizard.com/account/login"; + private static final String HOMEWIZARD_API_URL = "https://plug.homewizard.com/plugs"; + private static final String EMPTY_STRING = ""; + + private final String cloudAuth; + private final Gson gson; + + private String cloudSessionId; + private String cloudPlugName; + private String cloudPlugId; + + public HomeWizzardSmartPlugInfo(NamedIP gateway, String name) { + + super(); + + cloudAuth = "Basic " + new String(Base64.encodeBase64((gateway.getUsername() + ":" + DigestUtils.sha1Hex(gateway.getPassword())).getBytes())); + cloudPlugName = name; + gson = new Gson(); + } + + public boolean login() + { + try + { + URL url = new URL(HOMEWIZARD_LOGIN_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("Authorization", cloudAuth); + connection.setRequestProperty("Content-Type", "application/json;charset=utf-8"); + connection.connect(); + + BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); + StringBuilder buffer = new StringBuilder(); + String line; + + while((line = br.readLine()) != null) + { + buffer.append(line).append("\n"); + } + br.close(); + + // Get session id from result JSON + JSONObject json = new JSONObject(buffer.toString()); + cloudSessionId = json.get("session").toString(); + } + catch(IOException | JSONException e) + { + log.warn("Error while login to cloud service ", e); + return false; + } + + return true; + } + + private String requestJson(String request) + { + String result = null; + + // Check login was successful + if (login()) { + + // Request JSON from Cloud service + try + { + URL url = new URL(HOMEWIZARD_API_URL + request); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + connection.setRequestMethod("GET"); + connection.setRequestProperty("X-Session-Token", cloudSessionId); + connection.setRequestProperty("Content-Type", "application/json;charset=utf-8"); + connection.connect(); + + BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); + StringBuilder buffer = new StringBuilder(); + String line; + + while((line = br.readLine()) != null) + { + buffer.append(line).append("\n"); + } + + br.close(); + + result = buffer.toString(); + result = StringUtils.strip(result, "[]"); + } + catch(IOException e) + { + log.warn("Error while get json request: {} ", request, e); + } + } + + return result; + } + + private boolean sendAction(String request, String action) + { + // Check login was successful + if (login()) { + + // Post action into Cloud service + try + { + URL url = new URL(HOMEWIZARD_API_URL + request); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("X-Session-Token", cloudSessionId); + connection.setRequestProperty("Content-Type", "application/json;charset=utf-8"); + + JsonObject actionJson = new JsonObject(); + actionJson.addProperty("action", action); + + OutputStream os = connection.getOutputStream(); + os.write(actionJson.toString().getBytes("UTF-8")); + os.close(); + } + catch(IOException e) + { + log.warn("Error while post json action: {} ", request, e); + return false; + } + } + else + { + return false; + } + + return true; + } + + public List getDevices() + { + List homewizardDevices = new ArrayList<>(); + try { + + String result = requestJson(EMPTY_STRING); + JSONObject resultJson = new JSONObject(result); + cloudPlugId = resultJson.getString("id"); + + String all_devices_json = resultJson.get("devices").toString(); + Device[] devices = gson.fromJson(all_devices_json, Device[].class); + + // Fix names from JSON + for (Device device : devices) { + device.setTypeName(StringUtils.capitalize(device.getTypeName().replace("_", " "))); + homewizardDevices.add(mapDeviceToHomeWizardSmartPlugDevice(device)); + } + } + catch(JSONException e) { + log.warn("Error while get devices from cloud service ", e); + } + + log.info("Found: " + homewizardDevices.size() + " devices"); + return homewizardDevices; + } + + public void execApply(String jsonToPost) { + try + { + JSONObject resultJson = new JSONObject(jsonToPost); + String deviceId = resultJson.getString("deviceid"); + String action = resultJson.getString("action"); + + sendAction("/" + cloudPlugId + "/devices/" + deviceId + "/action", action); + } + catch(JSONException e) { + log.warn("Error while get devices from cloud service ", e); + } + } + + protected HomeWizardSmartPlugDevice mapDeviceToHomeWizardSmartPlugDevice(Device device) { + HomeWizardSmartPlugDevice homewizardDevice = new HomeWizardSmartPlugDevice(); + homewizardDevice.setId(device.getId()); + homewizardDevice.setGateway(cloudPlugName); + homewizardDevice.setName(device.getName()); + homewizardDevice.setTypeName(device.getTypeName()); + + return homewizardDevice; + } +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/json/Device.java b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/json/Device.java new file mode 100644 index 0000000..01052e7 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/json/Device.java @@ -0,0 +1,49 @@ +package com.bwssystems.HABridge.plugins.homewizard.json; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/** + * Control HomeWizard devices over HomeWizard Cloud + * + * @author Björn Rennfanz (bjoern@fam-rennfanz.de) + * + */ +public class Device { + + @SerializedName("id") + @Expose + private String id; + + @SerializedName("name") + @Expose + private String name; + + @SerializedName("typeName") + @Expose + private String typeName; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTypeName() { + return this.typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } +} From a2136723415d9d9da6c8e33161fb8ce904c269cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Rennfanz?= Date: Sat, 9 Dec 2017 21:17:05 +0100 Subject: [PATCH 3/9] Add web part of plug-in for HomeWizard SmartPlug support --- src/main/resources/public/scripts/app.js | 196 +++++++++++++++++- .../resources/public/views/configuration.html | 1 + .../public/views/domoticzdevice.html | 1 + .../resources/public/views/editdevice.html | 1 + .../resources/public/views/fibarodevice.html | 1 + .../resources/public/views/fibaroscene.html | 1 + .../resources/public/views/haldevice.html | 1 + .../public/views/harmonyactivity.html | 1 + .../resources/public/views/harmonydevice.html | 1 + .../resources/public/views/hassdevice.html | 1 + .../public/views/homewizarddevice.html | 127 ++++++++++++ .../resources/public/views/huedevice.html | 1 + .../resources/public/views/lifxdevice.html | 1 + src/main/resources/public/views/logs.html | 1 + .../resources/public/views/mqttpublish.html | 1 + .../resources/public/views/nestactions.html | 1 + .../resources/public/views/somfydevice.html | 1 + src/main/resources/public/views/system.html | 48 +++++ .../resources/public/views/veradevice.html | 1 + .../resources/public/views/verascene.html | 1 + 20 files changed, 382 insertions(+), 6 deletions(-) create mode 100644 src/main/resources/public/views/homewizarddevice.html diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 0b8ae5d..f29c6d1 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -62,7 +62,11 @@ app.config (function ($locationProvider, $routeProvider) { }).when ('/hassdevices', { templateUrl: 'views/hassdevice.html', controller: 'HassController', - requiresAuthentication: true + requiresAuthentication: true + }).when ('/homewizarddevices', { + templateUrl: 'views/homewizarddevice.html', + controller: 'HomeWizardController', + requiresAuthentication: true }).when ('/domoticzdevices', { templateUrl: 'views/domoticzdevice.html', controller: 'DomoticzController', @@ -143,7 +147,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, - showDomoticz: false, showSomfy: false, showLifx: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null, + showHomeWizard: false, showDomoticz: false, showSomfy: false, showLifx: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null, filterDevicesOnlyFiltered: false, filterDeviceType: null}; this.displayWarn = function(errorTitle, error) { @@ -504,11 +508,16 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n return; } - this.updateShowHass = function () { - this.state.showHass = self.state.settings.hassconfigured; + this.updateShowHomeWizard = function () { + this.state.showHomeWizard = self.state.settings.homewizardconfigured; return; } + this.updateShowHass = function () { + this.state.showHass = self.state.settings.hassconfigured; + return; + } + this.updateShowDomoticz = function () { this.state.showDomoticz = self.state.settings.domoticzconfigured; return; @@ -536,6 +545,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n self.updateShowHal(); self.updateShowMqtt(); self.updateShowHass(); + self.updateShowHomeWizard(); self.updateShowDomoticz(); self.updateShowSomfy(); self.updateShowLifx(); @@ -781,6 +791,22 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n ); }; + this.viewHomeWizardDevices = function () { + if (!this.state.showHomeWizard) + return; + return $http.get(this.state.base + "/homewizard/devices").then( + function (response) { + self.state.homewizarddevices = response.data; + }, + function (error) { + if (error.status === 401) + $rootScope.$broadcast('securityReinit', 'done'); + else + self.displayWarn("Get HomeWizard Devices Error: ", error); + } + ); + }; + this.viewDomoticzDevices = function () { if (!this.state.showDomoticz) return; @@ -1468,6 +1494,24 @@ app.controller ('SystemController', function ($scope, $location, bridgeService, } } }; + $scope.addHomeWizardtoSettings = function (newhomewizardname, newhomewizardip, newhomewizardusername, newhomewizardpassword) { + if($scope.bridge.settings.homewizardaddress === undefined || $scope.bridge.settings.homewizardaddress === null) { + $scope.bridge.settings.homewizardaddress = { devices: [] }; + } + var newhomewizard = { name: newhomewizardname, ip: newhomewizardip, username: newhomewizardusername, password: newhomewizardpassword } + $scope.bridge.settings.homewizardaddress.devices.push(newhomewizard); + $scope.newhomewizardname = null; + $scope.newhomewizardip = null; + $scope.newhomewizardusername = null; + $scope.newhomewizardpassword = null; + }; + $scope.removeHomeWizardtoSettings = function (homewizardname, homewizardip) { + for(var i = $scope.bridge.settings.homewizardaddress.devices.length - 1; i >= 0; i--) { + if($scope.bridge.settings.homewizardaddress.devices[i].name === homewizardname && $scope.bridge.settings.homewizardaddress.devices[i].ip === homewizardip) { + $scope.bridge.settings.homewizardaddress.devices.splice(i, 1); + } + } + }; $scope.addDomoticztoSettings = function (newdomoticzname, newdomoticzip, newdomoticzport, newdomoticzusername, newdomoticzpassword) { if($scope.bridge.settings.domoticzaddress === undefined || $scope.bridge.settings.domoticzaddress === null) { $scope.bridge.settings.domoticzaddress = { devices: [] }; @@ -2782,7 +2826,7 @@ app.controller('HassController', function ($scope, $location, bridgeService, ngD $scope.device = bridgeService.state.device; }; - $scope.buildDeviceUrls = function (hassdevice, dim_control, buildonly) { + $scope.buildDeviceUrls = function (hassdevice, buildonly) { onpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}"; if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)) dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\",\"bri\":\"" + dim_control + "\"}"; @@ -2798,7 +2842,7 @@ app.controller('HassController', function ($scope, $location, bridgeService, ngD } }; - $scope.bulkAddDevices = function(dim_control) { + $scope.bulkAddDevices = function() { var devicesList = []; $scope.clearDevice(); for(var i = 0; i < $scope.bulk.devices.length; i++) { @@ -2894,6 +2938,132 @@ app.controller('HassController', function ($scope, $location, bridgeService, ngD }; }); +app.controller('HomeWizardController', 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.viewHomeWizardDevices(); + $scope.imgButtonsUrl = "glyphicon glyphicon-plus"; + $scope.buttonsVisible = false; + + $scope.clearDevice = function () { + bridgeService.clearDevice(); + $scope.device = bridgeService.state.device; + }; + + $scope.buildDeviceUrls = function (homewizarddevice, buildonly) { + + dimpayload = "{\"deviceid\":\"" + homewizarddevice.id + "\",\"action\":\"on\"}"; + onpayload = "{\"deviceid\":\"" + homewizarddevice.id + "\",\"action\":\"on\"}"; + offpayload = "{\"deviceid\":\"" + homewizarddevice.id + "\",\"action\":\"off\"}"; + + bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, true, homewizarddevice.id ,homewizarddevice.name, homewizarddevice.gateway, null, "homewizardDevice", null, null); + $scope.device = bridgeService.state.device; + + if (!buildonly) { + bridgeService.editNewDevice($scope.device); + $location.path('/editdevice'); + } + }; + + $scope.bulkAddDevices = function() { + var devicesList = []; + $scope.clearDevice(); + for(var i = 0; i < $scope.bulk.devices.length; i++) { + for(var x = 0; x < bridgeService.state.homewizarddevices.length; x++) { + if(bridgeService.state.homewizarddevices[x].id === $scope.bulk.devices[i]) { + $scope.buildDeviceUrls(bridgeService.state.homewizarddevices[x],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 HomeWizard 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.homewizarddevices.length; x++) { + if($scope.bulk.devices.indexOf(bridgeService.state.homewizarddevices[x]) < 0) + $scope.bulk.devices.push(bridgeService.state.homewizarddevices[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('DomoticzController', function ($scope, $location, bridgeService, ngDialog) { $scope.bridge = bridgeService.state; $scope.device = bridgeService.state.device; @@ -3705,6 +3875,20 @@ app.filter('configuredSomfyDevices', function (bridgeService) { } }); +app.filter('configuredHomeWizardDevices', 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], "homewizardDevice")){ + 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 eebbbdd..96b73a6 100644 --- a/src/main/resources/public/views/configuration.html +++ b/src/main/resources/public/views/configuration.html @@ -23,6 +23,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/domoticzdevice.html b/src/main/resources/public/views/domoticzdevice.html index 0d32594..4dfb914 100644 --- a/src/main/resources/public/views/domoticzdevice.html +++ b/src/main/resources/public/views/domoticzdevice.html @@ -21,6 +21,7 @@ Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/editdevice.html b/src/main/resources/public/views/editdevice.html index 457806c..a28e5bc 100644 --- a/src/main/resources/public/views/editdevice.html +++ b/src/main/resources/public/views/editdevice.html @@ -23,6 +23,7 @@ href="#!/mqttmessages">MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/fibarodevice.html b/src/main/resources/public/views/fibarodevice.html index 95e428c..eefe91d 100644 --- a/src/main/resources/public/views/fibarodevice.html +++ b/src/main/resources/public/views/fibarodevice.html @@ -17,6 +17,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/fibaroscene.html b/src/main/resources/public/views/fibaroscene.html index c5c35fa..f23e9f5 100644 --- a/src/main/resources/public/views/fibaroscene.html +++ b/src/main/resources/public/views/fibaroscene.html @@ -17,6 +17,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/haldevice.html b/src/main/resources/public/views/haldevice.html index 37f6bc7..88baa9f 100644 --- a/src/main/resources/public/views/haldevice.html +++ b/src/main/resources/public/views/haldevice.html @@ -20,6 +20,7 @@ Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/harmonyactivity.html b/src/main/resources/public/views/harmonyactivity.html index 3b63c91..093b4db 100644 --- a/src/main/resources/public/views/harmonyactivity.html +++ b/src/main/resources/public/views/harmonyactivity.html @@ -21,6 +21,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/harmonydevice.html b/src/main/resources/public/views/harmonydevice.html index a62adf0..9cd2f5b 100644 --- a/src/main/resources/public/views/harmonydevice.html +++ b/src/main/resources/public/views/harmonydevice.html @@ -21,6 +21,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/hassdevice.html b/src/main/resources/public/views/hassdevice.html index 71d7525..66e81ec 100644 --- a/src/main/resources/public/views/hassdevice.html +++ b/src/main/resources/public/views/hassdevice.html @@ -19,6 +19,7 @@ href="#!/huedevices">Hue Devices
  • HAL Devices
  • +
  • HomeWizard Devices
  • MQTT Messages
  • Domoticz Devices
  • diff --git a/src/main/resources/public/views/homewizarddevice.html b/src/main/resources/public/views/homewizarddevice.html new file mode 100644 index 0000000..40c8727 --- /dev/null +++ b/src/main/resources/public/views/homewizarddevice.html @@ -0,0 +1,127 @@ + + +
    +
    +

    HomeWizard Device List + ({{bridge.homewizarddevices.length}})

    +
    +
    +

    For any HomeWizard 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 HomeWizard Devices' list below will show + what is already setup for your HomeWizard Gateway.

    +

    Use the check boxes by the names to use the bulk addition + feature. Select your items, then click + bulk add below. Your items will be added with the name of the device from the HomeWizard Cloud.

    +
    + + + + + + + + + + + + + + + + + + +
    Row NameIdTypeBuild Actions
    {{$index+1}} + {{homewizarddevice.name}}{{homewizarddevice.id}}{{homewizarddevice.typeName}} + + +
    +
    + +
    + +
    +
    +

    + Already Configured HomeWizard Devices +

    +
    +
    + + + + + + + + + + + + + + + + + + +
    RowNameHomeWizard GatewayMap IdActions
    {{$index+1}}{{device.name}}{{device.targetDevice}}{{device.mapId}} +

    + + +

    +
    +
    +
    +
    + diff --git a/src/main/resources/public/views/huedevice.html b/src/main/resources/public/views/huedevice.html index 6855894..b02f0e0 100644 --- a/src/main/resources/public/views/huedevice.html +++ b/src/main/resources/public/views/huedevice.html @@ -21,6 +21,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/lifxdevice.html b/src/main/resources/public/views/lifxdevice.html index c220e3b..4f8bdf6 100644 --- a/src/main/resources/public/views/lifxdevice.html +++ b/src/main/resources/public/views/lifxdevice.html @@ -13,6 +13,7 @@
  • HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • diff --git a/src/main/resources/public/views/logs.html b/src/main/resources/public/views/logs.html index fca1aee..f31d666 100644 --- a/src/main/resources/public/views/logs.html +++ b/src/main/resources/public/views/logs.html @@ -21,6 +21,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/mqttpublish.html b/src/main/resources/public/views/mqttpublish.html index 940b211..593a4af 100644 --- a/src/main/resources/public/views/mqttpublish.html +++ b/src/main/resources/public/views/mqttpublish.html @@ -13,6 +13,7 @@
  • HAL Devices
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/nestactions.html b/src/main/resources/public/views/nestactions.html index 34875b9..1563e47 100644 --- a/src/main/resources/public/views/nestactions.html +++ b/src/main/resources/public/views/nestactions.html @@ -21,6 +21,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/somfydevice.html b/src/main/resources/public/views/somfydevice.html index 8bd5000..5f5dd19 100644 --- a/src/main/resources/public/views/somfydevice.html +++ b/src/main/resources/public/views/somfydevice.html @@ -17,6 +17,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index 603c4c7..8e08304 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -22,6 +22,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • @@ -417,6 +418,53 @@ + + HomeWizard Gateways + + + + + + + + + + + + + + + + + + + + + + + + +
    NameIPUsernamePasswordManage
    + Domoticz Names and IP Addresses HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • diff --git a/src/main/resources/public/views/verascene.html b/src/main/resources/public/views/verascene.html index 0357754..c793a89 100644 --- a/src/main/resources/public/views/verascene.html +++ b/src/main/resources/public/views/verascene.html @@ -17,6 +17,7 @@ href="#!/haldevices">HAL Devices
  • MQTT Messages
  • HomeAssistant Devices
  • +
  • HomeWizard Devices
  • Domoticz Devices
  • Somfy Devices
  • LIFX Devices
  • From bdf5770ba00ba4d8e515903a491433ccec9bf330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Rennfanz?= Date: Sat, 9 Dec 2017 14:27:27 +0100 Subject: [PATCH 4/9] Some corrections after rebasing code of HomeWizard SmartPlug plug-in --- .../plugins/homewizard/HomeWizardHome.java | 1 - .../homewizard/HomeWizzardSmartPlugInfo.java | 63 +++++++++++++------ src/main/resources/public/scripts/app.js | 4 +- 3 files changed, 47 insertions(+), 21 deletions(-) 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 02d7278..b80fd1e 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizardHome.java @@ -65,7 +65,6 @@ public class HomeWizardHome implements Home { + lightId + "state\"}}]"; } else { try { - homeWizzardHandler.execApply(jsonToPost); } catch (Exception e) { diff --git a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizzardSmartPlugInfo.java b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizzardSmartPlugInfo.java index e27b2a2..4620d64 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizzardSmartPlugInfo.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/homewizard/HomeWizzardSmartPlugInfo.java @@ -130,37 +130,59 @@ public class HomeWizzardSmartPlugInfo { private boolean sendAction(String request, String action) { + boolean result = true; + // Check login was successful if (login()) { - + // Post action into Cloud service try { URL url = new URL(HOMEWIZARD_API_URL + request); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("X-Session-Token", cloudSessionId); - connection.setRequestProperty("Content-Type", "application/json;charset=utf-8"); - + JsonObject actionJson = new JsonObject(); - actionJson.addProperty("action", action); + actionJson.addProperty("action", StringUtils.capitalize(action)); + + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setRequestProperty("X-Session-Token", cloudSessionId); + connection.setRequestProperty("Content-Type", "application/json; charset=utf-8"); OutputStream os = connection.getOutputStream(); os.write(actionJson.toString().getBytes("UTF-8")); os.close(); + + BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); + StringBuilder buffer = new StringBuilder(); + String line; + + while((line = br.readLine()) != null) + { + buffer.append(line).append("\n"); + } + + br.close(); + connection.disconnect(); + + // Check if request was Ok + if (!buffer.toString().contains("Success")) + { + result = false; + } } catch(IOException e) { log.warn("Error while post json action: {} ", request, e); - return false; + result = false; } } else { - return false; + result = false; } - return true; + return result; } public List getDevices() @@ -189,17 +211,22 @@ public class HomeWizzardSmartPlugInfo { return homewizardDevices; } - public void execApply(String jsonToPost) { - try - { - JSONObject resultJson = new JSONObject(jsonToPost); - String deviceId = resultJson.getString("deviceid"); - String action = resultJson.getString("action"); + public void execApply(String jsonToPost) throws JSONException, IOException { - sendAction("/" + cloudPlugId + "/devices/" + deviceId + "/action", action); + // Extract + JSONObject resultJson = new JSONObject(jsonToPost); + String deviceId = resultJson.getString("deviceid"); + String action = resultJson.getString("action"); + + // Check if we have an plug id stored + if (StringUtils.isBlank(cloudPlugId)) { + getDevices(); } - catch(JSONException e) { - log.warn("Error while get devices from cloud service ", e); + + // Send request to HomeWizard cloud + if (!sendAction("/" + cloudPlugId + "/devices/" + deviceId + "/action", action)) + { + throw new IOException("Send action to HomeWizard Cloud failed."); } } diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index f29c6d1..9ec0790 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -2826,7 +2826,7 @@ app.controller('HassController', function ($scope, $location, bridgeService, ngD $scope.device = bridgeService.state.device; }; - $scope.buildDeviceUrls = function (hassdevice, buildonly) { + $scope.buildDeviceUrls = function (hassdevice, dim_control, buildonly) { onpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}"; if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)) dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\",\"bri\":\"" + dim_control + "\"}"; @@ -2842,7 +2842,7 @@ app.controller('HassController', function ($scope, $location, bridgeService, ngD } }; - $scope.bulkAddDevices = function() { + $scope.bulkAddDevices = function(dim_control) { var devicesList = []; $scope.clearDevice(); for(var i = 0; i < $scope.bulk.devices.length; i++) { From 800f5ec2aa2588f250fc511d41808f0b2ccf28dc Mon Sep 17 00:00:00 2001 From: Rainer Burgstaller Date: Mon, 11 Dec 2017 08:30:33 +0100 Subject: [PATCH 5/9] add support for timestamp http URL variable - certain devices require a current date/time in their HTTP request (Warema shades) --- README.md | 2 +- src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 56d5179..05013d2 100644 --- a/README.md +++ b/README.md @@ -378,7 +378,7 @@ Headers can be added as well using a Json construct [{"name":"header type name", Another option that is detected by the bridge is to use UDP or TCP direct calls such as `udp://:/` to send a UDP request. TCP calls are handled the same way as `tcp://:/`. If your data for the UDP or TCP request is formatted as "0x00F009B9" lexical hex format, the bridge will convert the data into a binary stream to send. -You can also use the value replacement constructs within these statements. Such as using the expressions "${time.format(Java time format string)}" for inserting a date/time stamp, ${intensity.percent} or ${intensity.percent.hex} for 0-100 or ${intensity.decimal_percent} for 0.00-1.00 or ${intensity.byte} or ${intensity.byte.hex} for 0-255 for straight pass through of the value or items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}" or "${intensity.math(X/4).hex}". See Value Passing Controls Below. +You can also use the value replacement constructs within these statements. Such as using the expressions "${time.format(Java time format string)}" for inserting a date/time stamp, "${timestamp}" for inserting a pure timestamp (milliseconds from 1.1.1970), ${intensity.percent} or ${intensity.percent.hex} for 0-100 or ${intensity.decimal_percent} for 0.00-1.00 or ${intensity.byte} or ${intensity.byte.hex} for 0-255 for straight pass through of the value or items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}" or "${intensity.math(X/4).hex}". See Value Passing Controls Below. Examples: ``` diff --git a/src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java b/src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java index 62343f7..2c1a329 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java +++ b/src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java @@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory; public class TimeDecode { private static final Logger log = LoggerFactory.getLogger(TimeDecode.class); private static final String TIME_FORMAT = "${time.format("; + private static final String TIMESTAMP = "${timestamp}"; private static final String TIME_FORMAT_CLOSE = ")}"; /* @@ -38,6 +39,10 @@ public class TimeDecode { log.warn("Could not format current time: " + timeFormatDescriptor, e); } } + if (request.contains(TIMESTAMP)) { + request = request.replace(TIMESTAMP, String.valueOf(System.currentTimeMillis())); + notDone = true; + } } return request; } From 58fb0851807d3fb36cf8b7314c3422bc570ace82 Mon Sep 17 00:00:00 2001 From: Rainer Burgstaller Date: Mon, 11 Dec 2017 18:26:26 +0100 Subject: [PATCH 6/9] renamed variable `timestamp` to `time.millis` --- README.md | 2 +- src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 05013d2..70b8252 100644 --- a/README.md +++ b/README.md @@ -378,7 +378,7 @@ Headers can be added as well using a Json construct [{"name":"header type name", Another option that is detected by the bridge is to use UDP or TCP direct calls such as `udp://:/` to send a UDP request. TCP calls are handled the same way as `tcp://:/`. If your data for the UDP or TCP request is formatted as "0x00F009B9" lexical hex format, the bridge will convert the data into a binary stream to send. -You can also use the value replacement constructs within these statements. Such as using the expressions "${time.format(Java time format string)}" for inserting a date/time stamp, "${timestamp}" for inserting a pure timestamp (milliseconds from 1.1.1970), ${intensity.percent} or ${intensity.percent.hex} for 0-100 or ${intensity.decimal_percent} for 0.00-1.00 or ${intensity.byte} or ${intensity.byte.hex} for 0-255 for straight pass through of the value or items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}" or "${intensity.math(X/4).hex}". See Value Passing Controls Below. +You can also use the value replacement constructs within these statements. Such as using the expressions "${time.format(Java time format string)}" for inserting a date/time stamp, "${time.millis}" for inserting a pure timestamp (milliseconds from 1.1.1970), ${intensity.percent} or ${intensity.percent.hex} for 0-100 or ${intensity.decimal_percent} for 0.00-1.00 or ${intensity.byte} or ${intensity.byte.hex} for 0-255 for straight pass through of the value or items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}" or "${intensity.math(X/4).hex}". See Value Passing Controls Below. Examples: ``` diff --git a/src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java b/src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java index 2c1a329..0c3140c 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java +++ b/src/main/java/com/bwssystems/HABridge/hue/TimeDecode.java @@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory; public class TimeDecode { private static final Logger log = LoggerFactory.getLogger(TimeDecode.class); private static final String TIME_FORMAT = "${time.format("; - private static final String TIMESTAMP = "${timestamp}"; + private static final String TIMESTAMP = "${time.millis}"; private static final String TIME_FORMAT_CLOSE = ")}"; /* From 4c86e42776fabdbcdd96d2191ec13cf7f0a054be Mon Sep 17 00:00:00 2001 From: Admin Date: Mon, 11 Dec 2017 16:40:59 -0600 Subject: [PATCH 7/9] Added hex color codes, added swith to utilize groups/rooms. updated exec to use new path parsing. Revert back to Spark 2.3 due to issues. --- pom.xml | 4 +-- .../bwssystems/HABridge/BridgeSecurity.java | 35 +++++++++++++++++-- .../HABridge/BridgeSettingsDescriptor.java | 10 ++++++ .../com/bwssystems/HABridge/HABridge.java | 2 +- .../devicemanagmeent/DeviceResource.java | 5 ++- .../bwssystems/HABridge/hue/ColorDecode.java | 24 +++++++++++++ .../bwssystems/HABridge/hue/HueMulator.java | 34 ++++++++++++++---- .../HABridge/plugins/exec/CommandHome.java | 6 ++-- src/main/resources/public/scripts/app.js | 4 +-- src/main/resources/public/views/system.html | 6 ++++ 10 files changed, 112 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index cf0a3da..1b22967 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 5.0.0 + 5.0.0a jar HA Bridge @@ -63,7 +63,7 @@ com.sparkjava spark-core - 2.7.1 + 2.3 slf4j-simple diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java b/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java index 0c6fb70..a91db6b 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java @@ -238,6 +238,31 @@ public class BridgeSecurity { return null; } + public String findWhitelistUserByDeviceType(String aDeviceType) { + String validUser = null; + boolean found = false; + WhitelistEntry anEntry = null; + if (aDeviceType != null) { + if (securityDescriptor.getWhitelist() != null) { + Set theUserIds = securityDescriptor.getWhitelist().keySet(); + Iterator userIterator = theUserIds.iterator(); + while (!found && userIterator.hasNext()) { + validUser = userIterator.next(); + anEntry = securityDescriptor.getWhitelist().get(validUser); + if (anEntry.getName().equals(aDeviceType)) { + found = true; + log.debug("findWhitelistUserByDeviceType: found a user <" + validUser + "> for device type <" + aDeviceType + ">"); + } + } + } + } + + if(!found) + validUser = null; + + return validUser; + } + private void newWhitelistUser(String aUser, String userDescription) { if (securityDescriptor.getWhitelist() == null) { securityDescriptor.setWhitelist(new HashMap<>()); @@ -250,8 +275,14 @@ public class BridgeSecurity { } public String createWhitelistUser(String userDescription) { - String aUser = getNewUserID(); - newWhitelistUser(aUser, userDescription); + String aUser = null; + String theEntry = findWhitelistUserByDeviceType(userDescription); + if(theEntry == null) { + aUser = getNewUserID(); + newWhitelistUser(aUser, userDescription); + } else { + aUser = theEntry; + } return aUser; } diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java index 6bb1108..7da1551 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java @@ -15,6 +15,9 @@ public class BridgeSettingsDescriptor { @SerializedName("useupnpiface") @Expose private boolean useupnpiface; + @SerializedName("userooms") + @Expose + private boolean userooms; @SerializedName("serverport") @Expose private Integer serverport; @@ -119,6 +122,7 @@ public class BridgeSettingsDescriptor { super(); this.upnpstrict = true; this.useupnpiface = false; + this.userooms = false; this.traceupnp = false; this.nestconfigured = false; this.veraconfigured = false; @@ -152,6 +156,12 @@ public class BridgeSettingsDescriptor { public void setUseupnpiface(boolean useupnpiface) { this.useupnpiface = useupnpiface; } + public boolean isUserooms() { + return userooms; + } + public void setUserooms(boolean userooms) { + this.userooms = userooms; + } public Integer getServerPort() { return serverport; } diff --git a/src/main/java/com/bwssystems/HABridge/HABridge.java b/src/main/java/com/bwssystems/HABridge/HABridge.java index 55b48cf..72cd939 100644 --- a/src/main/java/com/bwssystems/HABridge/HABridge.java +++ b/src/main/java/com/bwssystems/HABridge/HABridge.java @@ -62,7 +62,7 @@ public class HABridge { // sparkjava config directive to set port for the web server to listen on port(bridgeSettings.getBridgeSettingsDescriptor().getServerPort()); staticFileLocation("/public"); - initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort())); +// initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort())); if(!bridgeSettings.getBridgeControl().isReinit()) init(); bridgeSettings.getBridgeControl().setReinit(false); diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java index 849ec21..99a3743 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -48,7 +48,10 @@ public class DeviceResource { public DeviceResource(BridgeSettings theSettings, HomeManager aHomeManager) { bridgeSettings = theSettings; this.deviceRepository = new DeviceRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpDeviceDb()); - this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb()); + if(bridgeSettings.getBridgeSettingsDescriptor().isUserooms()) + this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb()); + else + this.groupRepository = null; homeManager = aHomeManager; aGsonHandler = new GsonBuilder().create(); setupEndpoints(); diff --git a/src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java b/src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java index 34506f4..b9f26a2 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java +++ b/src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java @@ -16,6 +16,10 @@ public class ColorDecode { private static final String COLOR_R = "${color.r}"; private static final String COLOR_G = "${color.g}"; private static final String COLOR_B = "${color.b}"; + private static final String COLOR_RX = "${color.rx}"; + private static final String COLOR_GX = "${color.gx}"; + private static final String COLOR_BX = "${color.bx}"; + private static final String COLOR_RGBX = "${color.rgbx}"; private static final Pattern COLOR_MILIGHT = Pattern.compile("\\$\\{color.milight\\:([01234])\\}"); public static List convertCIEtoRGB(List xy, int brightness) { @@ -175,6 +179,26 @@ public class ColorDecode { notDone = true; } + if (request.contains(COLOR_RX)) { + request = request.replace(COLOR_RX, String.format("%02X", rgb.get(0))); + notDone = true; + } + + if (request.contains(COLOR_GX)) { + request = request.replace(COLOR_GX, String.format("%02X", rgb.get(1))); + notDone = true; + } + + if (request.contains(COLOR_BX)) { + request = request.replace(COLOR_BX, String.format("%02X", rgb.get(2))); + notDone = true; + } + + if (request.contains(COLOR_RGBX)) { + request = request.replace(COLOR_RGBX, String.format("%02X%02X%02X", rgb.get(0), rgb.get(1), rgb.get(2))); + notDone = true; + } + Matcher m = COLOR_MILIGHT.matcher(request); while (m.find()) { int group = Integer.parseInt(m.group(1)); diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index 23cc4fa..c0e07a0 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -127,7 +127,12 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return addGroup(request.params(":userid"), request.ip(), request.body()); + if(bridgeSettings.isUserooms()) { + return addGroup(request.params(":userid"), request.ip(), request.body()); + } else { + log.debug("group add requested from (No Use Rooms) " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + return "[{\"success\":{\"id\":\"1\"}}]"; + } }); // http://ip_address:port/api/:userid/groups/ // delete a group @@ -135,7 +140,12 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return deleteGroup(request.params(":userid"), request.params(":groupid"), request.ip()); + if(bridgeSettings.isUserooms()) { + return deleteGroup(request.params(":userid"), request.params(":groupid"), request.ip()); + } else { + log.debug("delete to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; + } }); // http://ip_address:port/api/:userid/groups/ // modify a single group @@ -143,7 +153,12 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return modifyGroup(request.params(":userid"), request.params(":groupid"), request.ip(), request.body()); + if(bridgeSettings.isUserooms()) { + return modifyGroup(request.params(":userid"), request.params(":groupid"), request.ip(), request.body()); + } else { + log.debug("put to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; + } }); // http://ip_address:port/api/:userid/groups//action // group acions @@ -151,7 +166,12 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false); + if(bridgeSettings.isUserooms()) { + return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false); + } else { + log.debug("put action to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; + } }); // http://ip_address:port/api/{userId}/scenes returns json objects of // all scenes configured @@ -922,7 +942,7 @@ public class HueMulator { toContinue = true; if(toContinue) { - log.debug("hue api user create requested: " + body + " from " + ipAddress); + log.debug("user add toContinue was true, creating user."); if (body != null && !body.isEmpty()) { try { @@ -938,6 +958,8 @@ public class HueMulator { if (aDeviceType == null) aDeviceType = ""; + else + aDeviceType = aDeviceType + "#" + ipAddress; if (newUser == null) { newUser = bridgeSettingMaster.getBridgeSecurity().createWhitelistUser(aDeviceType); @@ -1084,7 +1106,7 @@ public class HueMulator { } private String changeState(String userId, String lightId, String body, String ipAddress, boolean ignoreRequester) { - if (Integer.parseInt(lightId) >= 10000) { + if (bridgeSettings.isUserooms() && Integer.parseInt(lightId) >= 10000) { return changeGroupState(userId, String.valueOf(Integer.parseInt(lightId) - 10000), body, ipAddress, true); } String responseString = null; diff --git a/src/main/java/com/bwssystems/HABridge/plugins/exec/CommandHome.java b/src/main/java/com/bwssystems/HABridge/plugins/exec/CommandHome.java index a501c7b..fcb4708 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/exec/CommandHome.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/exec/CommandHome.java @@ -1,5 +1,6 @@ package com.bwssystems.HABridge.plugins.exec; +import java.io.File; import java.io.IOException; import org.slf4j.Logger; @@ -45,10 +46,7 @@ public class CommandHome implements Home { intermediate = TimeDecode.replaceTimeValue(intermediate); String execGarden = theSettings.getBridgeSecurity().getExecGarden(); if(execGarden != null && !execGarden.trim().isEmpty()) { - if(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) - intermediate = execGarden + "\\" + intermediate; - else - intermediate = execGarden + "/" + intermediate; + intermediate = new File(execGarden.trim(), intermediate).getAbsolutePath(); } String anError = doExecRequest(intermediate, lightId); diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 9ec0790..1a539ee 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -2068,7 +2068,7 @@ app.controller('FibaroController', function ($scope, $location, bridgeService, n onpayload = "http://" + fibarodevice.fibaroaddress + ":" + fibarodevice.fibaroport + "/api/callAction?deviceID=" + fibarodevice.id + "&name=turnOn"; offpayload = "http://" + fibarodevice.fibaroaddress + ":" + fibarodevice.fibaroport + "/api/callAction?deviceID=" + fibarodevice.id + "&name=turnOff"; - bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, fibarodevice.id, fibarodevice.name, fibarodevice.fibaroname, "switch", "fibaroDevice", null, null); + bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, false, fibarodevice.id, fibarodevice.name, fibarodevice.fibaroname, "switch", "fibaroDevice", null, null); bridgeService.state.device.headers = "[{\"name\":\"Authorization\",\"value\":\"" + fibarodevice.fibaroAuth + "\"}]"; $scope.device = bridgeService.state.device; if (!buildonly) { @@ -2081,7 +2081,7 @@ app.controller('FibaroController', function ($scope, $location, bridgeService, n onpayload = "http://" + fibaroscene.fibaroaddress + ":" + fibaroscene.fibaroport + "/api/sceneControl?id=" + fibaroscene.id + "&action=start"; offpayload = "http://" + fibaroscene.fibaroaddress + ":" + fibaroscene.fibaroport + "/api/sceneControl?id=" + fibaroscene.id + "&action=stop"; - bridgeService.buildUrls(onpayload, null, offpayload, false, fibaroscene.id, fibaroscene.name, fibaroscene.fibaroname, "scene", "fibaroScene", null, null); + bridgeService.buildUrls(onpayload, null, offpayload, null, false, fibaroscene.id, fibaroscene.name, fibaroscene.fibaroname, "scene", "fibaroScene", null, null); bridgeService.state.device.headers = "[{\"name\":\"Authorization\",\"value\":\"" + fibaroscene.fibaroAuth + "\"}]"; $scope.device = bridgeService.state.device; bridgeService.editNewDevice($scope.device); diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index 8e08304..095814f 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -100,6 +100,12 @@ ng-model="bridge.settings.useupnpiface" ng-true-value=true ng-false-value=false> {{bridge.settings.useupnpiface}} + + + + + +
    + + + + +
    + + + \ No newline at end of file From 9d07fac9292a210c990ef463bcd4dab5ec1fa420 Mon Sep 17 00:00:00 2001 From: Admin Date: Tue, 12 Dec 2017 15:48:03 -0600 Subject: [PATCH 9/9] updated readme --- README.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 035d046..e59b573 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ THe Harmony Hub Path looks like this: **FAQ: Please look here for the current FAQs! https://github.com/bwssytems/ha-bridge/wiki/HA-Bridge-FAQs** -In the cases of systems that require authorization and/or have APIs that cannot be handled in the current method, a module may need to be built. The Harmony Hub is such a module and so is the Nest module. The Bridge has helpers to build devices for the gateway for the Logitech Harmony Hub, Vera, Vera Lite or Vera Edge, Nest, Somfy Tahoma and the ability to proxy all of your real Hue bridges behind this bridge. +In the cases of systems that require authorization and/or have APIs that cannot be handled in the current method, a module may need to be built. The Harmony Hub is such a module and so is the Nest module. The Bridge has helpers to build devices for the gateway for the Logitech Harmony Hub, Vera, Vera Lite or Vera Edge, Nest, Somfy Tahoma, Home Assistant, Domoticz, HAL, Fibaro, HomeWizard and the ability to proxy all of your real Hue bridges behind this bridge. Alternatively the Bridge supports custom calls as well using http/https/udp and tcp such as the LimitlessLED/MiLight bulbs using the UDP protocol. Binary data is supported with UDP/TCP. @@ -61,17 +61,17 @@ ATTENTION: This requires JDK 1.8 to run ATTENTION: Due to port 80 being the default, Linux restricts this to super user. Use the instructions below. ``` -java -jar ha-bridge-5.0.0.jar +java -jar ha-bridge-5.1.0.jar ``` ### Automation on Linux systems To have this configured and running automatically there are a few resources to use. One is using Docker and a docker container has been built for this and can be gotten here: https://github.com/aptalca/docker-ha-bridge -Create the directory and make sure that ha-bridge-5.0.0.jar is in your /home/pi/habridge directory. +Create the directory and make sure that ha-bridge-5.1.0.jar is in your /home/pi/habridge directory. ``` pi@raspberrypi:~ $ mkdir habridge pi@raspberrypi:~ $ cd habridge -pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.0.0/ha-bridge-5.0.0.jar +pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.1.0/ha-bridge-5.1.0.jar ``` #### System Control Setup on a pi (preferred) @@ -92,7 +92,7 @@ After=network.target [Service] Type=simple WorkingDirectory=/home/pi/habridge -ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.0.0.jar +ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.1.0.jar [Install] WantedBy=multi-user.target @@ -127,7 +127,7 @@ Then cut and past this, modify any locations that are not correct ``` cd /home/pi/habridge rm /home/pi/habridge/habridge-log.txt -nohup java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.0.0.jar > /home/pi/habridge/habridge-log.txt 2>&1 & +nohup java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.1.0.jar > /home/pi/habridge/habridge-log.txt 2>&1 & chmod 777 /home/pi/habridge/habridge-log.txt ``` @@ -257,6 +257,8 @@ The default location for the db to contain the devices as they are added is "dat The server defaults to the first available address on the host if this is not given. This default may NOT be the correct IP that is your public IP for your host on the network. It is best to set this parameter to not have discovery issues. Replace this value with the server ipv4 address you would like to use as the address that any upnp device will call after discovery. #### Use UPNP Address Interface The server tries to bind to all interfaces to respond to UPNP request. Setting this to `true` will make the binding to the interface that has the `UPNP IP Address`. The default is to be all interfaces which is set as false. +#### Use Rooms for Alexa +This setting controls rooms for Alexa. If it is set to true, any device ID abaove 10000 is treated as a special group. The default is set as false. #### Web Server IP Address The server defaults to all interfaces on the machine (0.0.0.0). Replace this value with the server ipv4 address you would like to use as the address that will bind to a specific ip address on an interface if you would like. This is only necessary if you want to isolate how access is handled to the web UI. #### Web Server Port @@ -432,7 +434,12 @@ There are multiple replacement constructs available to be put into any of the ca You can control items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}". -For the items that want to have a date time put into the message, utilize ${time.format(yyyy-MM-ddTHH:mm:ssXXX)} where "yyyy-MM-ddTHH:mm:ssXXX" can be any format from the Java SimpleDateFormat documented here: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html +For the items that want to have a date time put into the message, utilize ${time.format(yyyy-MM-ddTHH:mm:ssXXX)} where "yyyy-MM-ddTHH:mm:ssXXX" can be any format from the Java SimpleDateFormat documented here: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html. Also, there is a $(time.millis) which will put the millis timestamp where this replacement control is located. + +Color has been added as a replacement control and the available values are $(color.r), $(color.g), $(color.b) which are representations of each color as 0 - 255. There are hex equivalents as well as $(color.rx), $(color.gx), $(color.bx) and $(color.rgbx) as 2 place hex representations except for rgbx which is a six place hex representation. + +Special handling for milights is included and is handled by $(color.milight:x). The usage for that is as follows: udp://ip:port/0x${color.milight:x} where x is a number between 0 and 4 (0 all groups, 1-4 specific group). The group is necessary in case the color turns out to be white. The correct group on must of course be sent before that udp packet. +Note that milight can only use 255 colors and white is handled completely separate for the rgbw strips, so setting temperature via ct with milight does something but not really the desired result Also, device data can be inserted into your payloads by the use of "${device.name}", "${device.id}", "${device.uniqueid}", "${device.targetDevice}", "${device.mapId}", "${device.mapType}", "${device.deviceType}", "${device.requesterAddress}", "${device.description}" and "${device.comments}". These work just like the dimming value replacements. e.g.
    Use Rooms for Alexa {{bridge.settings.userooms}}
    Web Server IP Address Date: Tue, 12 Dec 2017 15:21:45 -0600 Subject: [PATCH 8/9] Fixed enable rooms for Alexa. Removed huemulator redirect for Spark. Added Link management as links are now stored with IP. --- pom.xml | 4 +- .../bwssystems/HABridge/BridgeSecurity.java | 6 ++ .../com/bwssystems/HABridge/HABridge.java | 2 +- .../bwssystems/HABridge/SystemControl.java | 34 ++++++++ .../devicemanagmeent/DeviceResource.java | 5 +- .../bwssystems/HABridge/hue/HueMulator.java | 39 +++------ src/main/resources/public/scripts/app.js | 79 ++++++++++++++++++- .../resources/public/views/configuration.html | 1 + .../public/views/managelinksdialog.html | 32 ++++++++ 9 files changed, 165 insertions(+), 37 deletions(-) create mode 100644 src/main/resources/public/views/managelinksdialog.html diff --git a/pom.xml b/pom.xml index 1b22967..a55b325 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 5.0.0a + 5.1.0 jar HA Bridge @@ -63,7 +63,7 @@ com.sparkjava spark-core - 2.3 + 2.7.1 slf4j-simple diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java b/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java index a91db6b..6e883e5 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java @@ -205,6 +205,12 @@ public class BridgeSecurity { return securityDescriptor.getWhitelist(); } + public void setWhitelist(Map aWhitelist) { + securityDescriptor.setWhitelist(aWhitelist); + settingsChanged = true; + return; + } + public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) { String validUser = null; boolean found = false; diff --git a/src/main/java/com/bwssystems/HABridge/HABridge.java b/src/main/java/com/bwssystems/HABridge/HABridge.java index 72cd939..55b48cf 100644 --- a/src/main/java/com/bwssystems/HABridge/HABridge.java +++ b/src/main/java/com/bwssystems/HABridge/HABridge.java @@ -62,7 +62,7 @@ public class HABridge { // sparkjava config directive to set port for the web server to listen on port(bridgeSettings.getBridgeSettingsDescriptor().getServerPort()); staticFileLocation("/public"); -// initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort())); + initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort())); if(!bridgeSettings.getBridgeControl().isReinit()) init(); bridgeSettings.getBridgeControl().setReinit(false); diff --git a/src/main/java/com/bwssystems/HABridge/SystemControl.java b/src/main/java/com/bwssystems/HABridge/SystemControl.java index c7210fb..e66e898 100644 --- a/src/main/java/com/bwssystems/HABridge/SystemControl.java +++ b/src/main/java/com/bwssystems/HABridge/SystemControl.java @@ -8,6 +8,7 @@ import static spark.Spark.before; import static spark.Spark.halt; import java.io.IOException; +import java.lang.reflect.Type; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; @@ -16,11 +17,13 @@ import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Timer; import java.util.Base64; +import java.util.Map; import org.apache.http.HttpStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.bwssystems.HABridge.api.hue.WhitelistEntry; import com.bwssystems.HABridge.dao.BackupFilename; import com.bwssystems.HABridge.util.JsonTransformer; import com.bwssystems.HABridge.util.TextStringFormatter; @@ -28,6 +31,7 @@ import com.bwssystems.logservices.LoggerInfo; import com.bwssystems.logservices.LoggingForm; import com.bwssystems.logservices.LoggingManager; import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.spi.ILoggingEvent; @@ -295,6 +299,36 @@ public class SystemControl { return bridgeSettings.getBridgeSecurity().getSecurityInfo(); }, new JsonTransformer()); + // http://ip_address:port/system/whitelist gets the whitelist for the bridge + get (SYSTEM_CONTEXT + "/whitelist", (request, response) -> { + log.debug("Get whitelist"); + response.status(HttpStatus.SC_OK); + response.type("application/json"); + return bridgeSettings.getBridgeSecurity().getWhitelist(); + }, new JsonTransformer()); + +// http://ip_address:port/system/setwhitelist CORS request + options(SYSTEM_CONTEXT + "/setwhitelist", (request, response) -> { + response.status(HttpStatus.SC_OK); + response.header("Access-Control-Allow-Origin", request.headers("Origin")); + response.header("Access-Control-Allow-Methods", "GET, POST, PUT"); + response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers")); + response.header("Content-Type", "text/html; charset=utf-8"); + return ""; + }); +// http://ip_address:port/system/setwhitelist which sets the whitelist after being managed + post(SYSTEM_CONTEXT + "/setwhitelist", (request, response) -> { + log.debug("setwhitelist...."); + Type listType = new TypeToken>() { + }.getType(); + Map aWhitelist = new Gson().fromJson(request.body(), listType); + bridgeSettings.getBridgeSecurity().setWhitelist(aWhitelist); + bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor()); + response.status(HttpStatus.SC_OK); + response.type("application/json"); + return bridgeSettings.getBridgeSecurity().getWhitelist(); + }, new JsonTransformer()); + // http://ip_address:port/system/logmgmt/update CORS request options(SYSTEM_CONTEXT + "/logmgmt/update", (request, response) -> { response.status(HttpStatus.SC_OK); diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java index 99a3743..849ec21 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -48,10 +48,7 @@ public class DeviceResource { public DeviceResource(BridgeSettings theSettings, HomeManager aHomeManager) { bridgeSettings = theSettings; this.deviceRepository = new DeviceRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpDeviceDb()); - if(bridgeSettings.getBridgeSettingsDescriptor().isUserooms()) - this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb()); - else - this.groupRepository = null; + this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb()); homeManager = aHomeManager; aGsonHandler = new GsonBuilder().create(); setupEndpoints(); diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index c0e07a0..8c59d40 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -76,10 +76,11 @@ public class HueMulator { public void setupServer() { log.info("Hue emulator service started...."); before(HUE_CONTEXT + "/*", (request, response) -> { - String path = request.pathInfo(); - if (path.endsWith("/")) { // it should work with or without a trailing slash - response.redirect(path.substring(0, path.length() - 1)); - } + // This currently causes an error with Spark replies +// String path = request.pathInfo(); +// if (path.endsWith("/")) { // it should work with or without a trailing slash +// response.redirect(path.substring(0, path.length() - 1)); +// } log.debug("HueMulator " + request.requestMethod() + " called on api/* with request <<<" + request.pathInfo() + ">>>, and body <<<" + request.body() + ">>>"); if(bridgeSettingMaster.getBridgeSecurity().isSecure()) { String pathInfo = request.pathInfo(); @@ -127,12 +128,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - if(bridgeSettings.isUserooms()) { - return addGroup(request.params(":userid"), request.ip(), request.body()); - } else { - log.debug("group add requested from (No Use Rooms) " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); - return "[{\"success\":{\"id\":\"1\"}}]"; - } + return addGroup(request.params(":userid"), request.ip(), request.body()); }); // http://ip_address:port/api/:userid/groups/ // delete a group @@ -140,12 +136,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - if(bridgeSettings.isUserooms()) { - return deleteGroup(request.params(":userid"), request.params(":groupid"), request.ip()); - } else { - log.debug("delete to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); - return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; - } + return deleteGroup(request.params(":userid"), request.params(":groupid"), request.ip()); }); // http://ip_address:port/api/:userid/groups/ // modify a single group @@ -153,12 +144,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - if(bridgeSettings.isUserooms()) { - return modifyGroup(request.params(":userid"), request.params(":groupid"), request.ip(), request.body()); - } else { - log.debug("put to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); - return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; - } + return modifyGroup(request.params(":userid"), request.params(":groupid"), request.ip(), request.body()); }); // http://ip_address:port/api/:userid/groups//action // group acions @@ -166,12 +152,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - if(bridgeSettings.isUserooms()) { - return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false); - } else { - log.debug("put action to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); - return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; - } + return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false); }); // http://ip_address:port/api/{userId}/scenes returns json objects of // all scenes configured @@ -1022,7 +1003,7 @@ public class HueMulator { if (theErrors != null) return theErrors; - if (Integer.parseInt(lightId) >= 10000) { + if (bridgeSettings.isUserooms() && Integer.parseInt(lightId) >= 10000) { GroupDescriptor group = groupRepository.findOne(String.valueOf(Integer.parseInt(lightId) - 10000)); return DeviceResponse.createResponseForVirtualLight(group); } diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 1a539ee..5c4bc52 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -277,6 +277,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n return $http.post(this.state.huebase, "{\"devicetype\":\"test_ha_bridge\"}").then( function (response) { self.state.testuser = response.data[0].success.username; + self.getWhitelist(); }, function (error) { if (error.status === 401) @@ -318,7 +319,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n if (error.status === 401) $rootScope.$broadcast('securityReinit', 'done'); else - self.displayWarn("Update ecurity settings Error: ", error); + self.displayWarn("Update security settings Error: ", error); } ); }; @@ -410,6 +411,29 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n ); }; + this.getWhitelist = function () { + return $http.get(this.state.systemsbase + "/whitelist").then( + function (response) { + self.state.whitelist = response.data; + }, + function (error) { + self.displayWarn("Cannot get swhitelist: ", error); + } + ); + }; + + this.setWhitelist = function (whitelist) { + return $http.post(this.state.systemsbase + "/setwhitelist", whitelist ).then( + function (response) { + self.state.whitelist = response.data; + self.displaySuccess("Updated whitelist.") + }, + function (error) { + self.displayWarn("Update whitelist Error: ", error); + } + ); + }; + this.aContainsB = function (a, b) { return a.indexOf(b) >= 0; } @@ -1141,6 +1165,18 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n }; + this.saveSettingsNoReinit = function () { + return $http.put(this.state.systemsbase + "/settings", this.state.settings).then( + function (response) { + self.displaySuccess("Save Settings completed."); + }, + function (error) { + self.displayWarn("Save Settings Error: ", error); + } + ); + + }; + this.backupSettings = function (afilename) { return $http.put(this.state.systemsbase + "/backup/create", { filename: afilename @@ -1699,6 +1735,40 @@ app.controller('SecurityDialogCtrl', function ($scope, bridgeService, ngDialog) }; }); +app.controller('ManageLinksDialogCtrl', function ($scope, bridgeService, ngDialog) { + bridgeService.getWhitelist(); + $scope.whitelist = bridgeService.state.whitelist; + + $scope.setWhitelist = function () { + bridgeService.setWhitelist($scope.whitelist); + ngDialog.close('ngdialog1'); + }; + + $scope.delEntry = function (anEntry) { + for(var key in $scope.whitelist) { + if ($scope.whitelist.hasOwnProperty(key)) { + var theEntry = $scope.whitelist[key]; + if(theEntry.name === anEntry) { + delete $scope.whitelist[key]; + } + } + } + }; + + $scope.refresh = function () { + bridgeService.getWhitelist(); + $scope.whitelist = bridgeService.state.whitelist; + } + + $scope.delAll = function () { + $scope.whitelist = null; + }; + + $scope.dismissDialog = function () { + ngDialog.close('ngdialog1'); + }; +}); + app.controller('LogsController', function ($scope, $location, bridgeService) { bridgeService.viewLogs(); $scope.bridge = bridgeService.state; @@ -1807,6 +1877,13 @@ app.controller('ViewingController', function ($scope, $location, bridgeService, $scope.pushLinkButton = function() { bridgeService.pushLinkButton(); }; + $scope.manageLinksButton = function() { + ngDialog.open({ + template: 'views/managelinksdialog.html', + controller: 'ManageLinksDialogCtrl', + className: 'ngdialog-theme-default' + }); + }; $scope.backupDeviceDb = function (optionalbackupname) { bridgeService.backupDeviceDb(optionalbackupname); }; diff --git a/src/main/resources/public/views/configuration.html b/src/main/resources/public/views/configuration.html index 96b73a6..030aeb9 100644 --- a/src/main/resources/public/views/configuration.html +++ b/src/main/resources/public/views/configuration.html @@ -39,6 +39,7 @@
    + diff --git a/src/main/resources/public/views/managelinksdialog.html b/src/main/resources/public/views/managelinksdialog.html new file mode 100644 index 0000000..a928d03 --- /dev/null +++ b/src/main/resources/public/views/managelinksdialog.html @@ -0,0 +1,32 @@ +
    + +
    + Manage Links +
    + + + + + + + + + + + + + + +
    NameCreate DateManage
    {{linkItem.name}}{{linkItem.createDate}}
    +