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 56d51796..23b69ca0 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 611ec04d..b8eb4036 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java @@ -209,6 +209,7 @@ public void buildSettings() { 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 4160d2f5..6bb1108a 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 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 IpList getFibaroAddress() { public IpList getSomfyAddress() { return somfyaddress; } + public IpList getHomeWizardAddress() { + return homewizardaddress; + } public void setVeraAddress(IpList veraAddress) { this.veraaddress = veraAddress; } @@ -197,6 +203,9 @@ public void setFibaroAddress(IpList fibaroAddress) { 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 boolean isFibaroconfigured() { public boolean isSomfyconfigured() { return somfyconfigured; } + public boolean isHomeWizardConfigured() { + return homewizardconfigured; + } public void setVeraconfigured(boolean veraconfigured) { this.veraconfigured = veraconfigured; } @@ -245,6 +257,9 @@ public void setFibaroconfigured(boolean fibaroconfigured) { 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 void updateHue(NamedIP aHue) { 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 9c13d711..b32e9d99 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 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 0d6824ca..f488885b 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.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 void buildHomes(BridgeSettings bridgeSettings, UDPDatagramSender aUdpData 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 void buildHomes(BridgeSettings bridgeSettings, UDPDatagramSender aUdpData 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 c3067b15..849ec216 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 @@ private void setupEndpoints() { 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 00000000..02d72783 --- /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 00000000..83b4b0a9 --- /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 00000000..e27b2a2b --- /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 00000000..01052e72 --- /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 0b8ae5d8..f29c6d1b 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 eebbbddc..96b73a64 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 0d325941..4dfb9145 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 457806cd..a28e5bc3 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 95e428c9..eefe91d5 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 c5c35fac..f23e9f5a 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 37f6bc75..88baa9fb 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 3b63c919..093b4db9 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 a62adf07..9cd2f5b2 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 71d75253..66e81ec8 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 00000000..40c87273 --- /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 6855894f..b02f0e0c 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 c220e3b7..4f8bdf65 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 fca1aee4..f31d6663 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 940b2117..593a4afb 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 34875b97..1563e47b 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 8bd50003..5f5dd197 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 603c4c7c..8e083043 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 @@

    Bridge Settings

    + + 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 0357754b..c793a892 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 | 61 +++++++++++++------ src/main/resources/public/scripts/app.js | 4 +- 3 files changed, 46 insertions(+), 20 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 02d72783..b80fd1e9 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 String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String + 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 e27b2a2b..4620d649 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 @@ private String requestJson(String request) 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(); + + JsonObject actionJson = new JsonObject(); + 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"); - - JsonObject actionJson = new JsonObject(); - actionJson.addProperty("action", action); + 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 List getDevices() 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 f29c6d1b..9ec07901 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 56d51796..05013d20 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 62343f7b..2c1a329c 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 @@ 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 static String replaceTimeValue(String request) { 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 05013d20..70b8252e 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 2c1a329c..0c3140ca 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 @@ 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 cf0a3daf..1b22967b 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 0c6fb701..a91db6bd 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java @@ -238,6 +238,31 @@ public HueError[] validateWhitelistUser(String aUser, String userDescription, bo 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 @@ private void newWhitelistUser(String aUser, String userDescription) { } 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 6bb1108a..7da15511 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 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 boolean isUseupnpiface() { 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 55b48cf7..72cd9390 100644 --- a/src/main/java/com/bwssystems/HABridge/HABridge.java +++ b/src/main/java/com/bwssystems/HABridge/HABridge.java @@ -62,7 +62,7 @@ public static void main(String[] args) { // 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 849ec216..99a3743c 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 34506f40..b9f26a2e 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 static String replaceColorData(String request, ColorData colorData, int s 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 23cc4fa3..c0e07a0e 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 void setupServer() { 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 void setupServer() { 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 void setupServer() { 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 void setupServer() { 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 @@ else if(!bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) 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 @@ else if(!bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) if (aDeviceType == null) aDeviceType = ""; + else + aDeviceType = aDeviceType + "#" + ipAddress; if (newUser == null) { newUser = bridgeSettingMaster.getBridgeSecurity().createWhitelistUser(aDeviceType); @@ -1084,7 +1106,7 @@ else if (body.contains("\"bri\"")) { } 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 a501c7bb..fcb47087 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 String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String 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 9ec07901..1a539ee7 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 8e083043..095814fb 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -100,6 +100,12 @@

    Bridge Settings

    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 035d0468..e59b5739 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 1b22967b..a55b3255 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 a91db6bd..6e883e57 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java @@ -205,6 +205,12 @@ public Map getWhitelist() { 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 72cd9390..55b48cf7 100644 --- a/src/main/java/com/bwssystems/HABridge/HABridge.java +++ b/src/main/java/com/bwssystems/HABridge/HABridge.java @@ -62,7 +62,7 @@ public static void main(String[] args) { // 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 c7210fbe..e66e8988 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.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.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.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 void setupServer() { 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 99a3743c..849ec216 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 c0e07a0e..8c59d401 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 HueMulator(BridgeSettings bridgeMaster, DeviceRepository aDeviceRepositor 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 void setupServer() { 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 void setupServer() { 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 void setupServer() { 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 void setupServer() { 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 @@ private Object getLight(String userId, String lightId, String ipAddress) { 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 1a539ee7..5c4bc525 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 96b73a64..030aeb92 100644 --- a/src/main/resources/public/views/configuration.html +++ b/src/main/resources/public/views/configuration.html @@ -39,6 +39,7 @@

    Current devices ({{bridge.devices.length}})

    + diff --git a/src/main/resources/public/views/managelinksdialog.html b/src/main/resources/public/views/managelinksdialog.html new file mode 100644 index 00000000..a928d038 --- /dev/null +++ b/src/main/resources/public/views/managelinksdialog.html @@ -0,0 +1,32 @@ +
    + +
    + Manage Links +
    + + + + + + + + + + + + + + +
    NameCreate DateManage
    {{linkItem.name}}{{linkItem.createDate}}
    +