diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java index 40396c5..2fe3326 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java @@ -160,7 +160,7 @@ public class BridgeSettings extends BackupHandler { } theBridgeSettings.setSomfyAddress(theSomfyList); - theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true"))); + // theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true"))); theBridgeSettings.setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false"))); theBridgeSettings.setButtonsleep(Integer.parseInt(System.getProperty("button.sleep", Configuration.DEFAULT_BUTTON_SLEEP))); theBridgeSettings.setNestuser(System.getProperty("nest.user")); @@ -223,9 +223,13 @@ public class BridgeSettings extends BackupHandler { if(serverIpOverride != null) { theBridgeSettings.setWebaddress(serverIpOverride); theBridgeSettings.setUpnpConfigAddress(serverIpOverride); - } + } + + /* if(upnpStrictOverride != null) - theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(upnpStrictOverride)); + theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(upnpStrictOverride)); + */ + setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-"); bridgeSecurity.setSecurityData(theBridgeSettings.getSecurityData()); diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java index a72edb7..41b608e 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java @@ -90,9 +90,9 @@ public class BridgeSettingsDescriptor { @SerializedName("openhabaddress") @Expose private IpList openhabaddress; - @SerializedName("moziotgateway") + @SerializedName("moziotaddress") @Expose - private IpList moziotgateway; + private IpList moziotaddress; @SerializedName("hubversion") @Expose private String hubversion; @@ -120,6 +120,9 @@ public class BridgeSettingsDescriptor { @SerializedName("tracestate") @Expose private boolean tracestate; + @SerializedName("upnporiginal") + @Expose + private boolean upnporiginal; // @SerializedName("activeloggers") // @Expose // private List activeloggers; @@ -142,11 +145,11 @@ public class BridgeSettingsDescriptor { // Deprecated settings private String haltoken; - private boolean upnpstrict; + // private boolean upnpstrict; public BridgeSettingsDescriptor() { super(); - this.upnpstrict = true; + // this.upnpstrict = true; this.useupnpiface = false; this.userooms = false; this.traceupnp = false; @@ -175,6 +178,7 @@ public class BridgeSettingsDescriptor { this.upnpsenddelay = Configuration.UPNP_SEND_DELAY; this.broadlinkconfigured = false; this.tracestate = false; + this.upnporiginal = false; } public String getUpnpConfigAddress() { @@ -280,7 +284,7 @@ public class BridgeSettingsDescriptor { public void setHarmonyAddress(IpList harmonyaddress) { this.harmonyaddress = harmonyaddress; } - +/* public boolean isUpnpStrict() { return upnpstrict; } @@ -288,7 +292,7 @@ public class BridgeSettingsDescriptor { public void setUpnpStrict(boolean upnpStrict) { this.upnpstrict = upnpStrict; } - +*/ public boolean isTraceupnp() { return traceupnp; } @@ -753,19 +757,19 @@ public class BridgeSettingsDescriptor { this.tracestate = tracestate; } - public IpList getMoziotgateway() { - return moziotgateway; + public IpList getMoziotaddress() { + return moziotaddress; } - public void setMoziotgateway(IpList moziotgateway) { - this.moziotgateway = moziotgateway; + public void setMoziotgaddress(IpList moziotgateway) { + this.moziotaddress = moziotgateway; } public Boolean isValidMozIot() { - if (this.getMoziotgateway() == null || this.getMoziotgateway().getDevices().size() <= 0) + if (this.getMoziotaddress() == null || this.getMoziotaddress().getDevices().size() <= 0) return false; - List devicesList = this.getMoziotgateway().getDevices(); + List devicesList = this.getMoziotaddress().getDevices(); if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; @@ -779,4 +783,12 @@ public class BridgeSettingsDescriptor { public void setMoziotconfigured(boolean moziotconfigured) { this.moziotconfigured = moziotconfigured; } + + public boolean isUpnporiginal() { + return upnporiginal; + } + + public void setUpnporiginal(boolean upnporiginal) { + this.upnporiginal = upnporiginal; + } } diff --git a/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java b/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java index 24f8f5f..9fc09ad 100644 --- a/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java +++ b/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java @@ -32,6 +32,7 @@ public class DeviceMapTypes { public final static String[] SOMFY_DEVICE = { "somfyDevice", "Somfy Device"}; public final static String[] LIFX_DEVICE = { "lifxDevice", "LIFX Device"}; public final static String[] OPENHAB_DEVICE = { "openhabDevice", "OpenHAB Device"}; + public final static String[] MOZIOT_DEVICE = { "moziotDevice", "Mozilla IOT Device"}; public final static String[] FHEM_DEVICE = { "fhemDevice", "FHEM Device"}; public final static String[] BROADLINK_DEVICE = { "broadlinkDevice", "Broadlink Device"}; @@ -67,6 +68,7 @@ public class DeviceMapTypes { deviceMapTypes.add(FIBARO_SCENE); deviceMapTypes.add(SOMFY_DEVICE); deviceMapTypes.add(OPENHAB_DEVICE); + deviceMapTypes.add(MOZIOT_DEVICE); deviceMapTypes.add(FHEM_DEVICE); deviceMapTypes.add(BROADLINK_DEVICE); } diff --git a/src/main/java/com/bwssystems/HABridge/HomeManager.java b/src/main/java/com/bwssystems/HABridge/HomeManager.java index 30d7b17..a9e56fa 100644 --- a/src/main/java/com/bwssystems/HABridge/HomeManager.java +++ b/src/main/java/com/bwssystems/HABridge/HomeManager.java @@ -20,6 +20,7 @@ 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; +import com.bwssystems.HABridge.plugins.moziot.MozIotHome; import com.bwssystems.HABridge.plugins.mqtt.MQTTHome; import com.bwssystems.HABridge.plugins.openhab.OpenHABHome; import com.bwssystems.HABridge.plugins.somfy.SomfyHome; @@ -120,7 +121,11 @@ public class HomeManager { aHome = new OpenHABHome(bridgeSettings); resourceList.put(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex], aHome); homeList.put(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex], aHome); - //setup the OpenHAB configuration if available + //setup the Mozilla IOT configuration if available + aHome = new MozIotHome(bridgeSettings); + resourceList.put(DeviceMapTypes.MOZIOT_DEVICE[DeviceMapTypes.typeIndex], aHome); + homeList.put(DeviceMapTypes.MOZIOT_DEVICE[DeviceMapTypes.typeIndex], aHome); + //setup the FHEM configuration if available aHome = new FHEMHome(bridgeSettings); resourceList.put(DeviceMapTypes.FHEM_DEVICE[DeviceMapTypes.typeIndex], aHome); homeList.put(DeviceMapTypes.FHEM_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 6b2e14f..bad312f 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -321,6 +321,12 @@ public class DeviceResource { return homeManager.findResource(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex]); }, new JsonTransformer()); + get (API_CONTEXT + "/moziot/devices", "application/json", (request, response) -> { + log.debug("Get MOzilla IOT devices"); + response.status(HttpStatus.SC_OK); + return homeManager.findResource(DeviceMapTypes.MOZIOT_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.MOZIOT_DEVICE[DeviceMapTypes.typeIndex]); + }, new JsonTransformer()); + get (API_CONTEXT + "/fhem/devices", "application/json", (request, response) -> { log.debug("Get FHEM devices"); response.status(HttpStatus.SC_OK); diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/Actions.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Actions.java new file mode 100644 index 0000000..6c0b84b --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Actions.java @@ -0,0 +1,8 @@ + +package com.bwssystems.HABridge.plugins.moziot; + + +public class Actions { + + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/Events.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Events.java new file mode 100644 index 0000000..4a4a5df --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Events.java @@ -0,0 +1,8 @@ + +package com.bwssystems.HABridge.plugins.moziot; + + +public class Events { + + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/JWT.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/JWT.java new file mode 100644 index 0000000..e399897 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/JWT.java @@ -0,0 +1,21 @@ + +package com.bwssystems.HABridge.plugins.moziot; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class JWT { + + @SerializedName("jwt") + @Expose + private String jwt; + + public String getJwt() { + return jwt; + } + + public void setJwt(String jwt) { + this.jwt = jwt; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/Level.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Level.java new file mode 100644 index 0000000..9357051 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Level.java @@ -0,0 +1,88 @@ + +package com.bwssystems.HABridge.plugins.moziot; + +import java.util.List; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Level { + + @SerializedName("title") + @Expose + private String title; + @SerializedName("type") + @Expose + private String type; + @SerializedName("@type") + @Expose + private String attype; + @SerializedName("unit") + @Expose + private String unit; + @SerializedName("minimum") + @Expose + private Integer minimum; + @SerializedName("maximum") + @Expose + private Integer maximum; + @SerializedName("links") + @Expose + private List links = null; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getAttype() { + return attype; + } + + public void setAttype(String attype) { + this.attype = attype; + } + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + public Integer getMinimum() { + return minimum; + } + + public void setMinimum(Integer minimum) { + this.minimum = minimum; + } + + public Integer getMaximum() { + return maximum; + } + + public void setMaximum(Integer maximum) { + this.maximum = maximum; + } + + public List getLinks() { + return links; + } + + public void setLinks(List links) { + this.links = links; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/Link.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Link.java new file mode 100644 index 0000000..ed9ae99 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Link.java @@ -0,0 +1,43 @@ + +package com.bwssystems.HABridge.plugins.moziot; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Link { + + @SerializedName("rel") + @Expose + private String rel; + @SerializedName("href") + @Expose + private String href; + @SerializedName("mediaType") + @Expose + private String mediaType; + + public String getRel() { + return rel; + } + + public void setRel(String rel) { + this.rel = rel; + } + + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href; + } + + public String getMediaType() { + return mediaType; + } + + public void setMediaType(String mediaType) { + this.mediaType = mediaType; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotCommand.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotCommand.java new file mode 100644 index 0000000..acb78fe --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotCommand.java @@ -0,0 +1,19 @@ +package com.bwssystems.HABridge.plugins.moziot; + +public class MozIotCommand { + private String url; + private String command; + public String getUrl() { + return url; + } + public void setUrl(String url) { + this.url = url; + } + public String getCommand() { + return command; + } + public void setCommand(String command) { + this.command = command; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotHome.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotHome.java new file mode 100644 index 0000000..a351be6 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotHome.java @@ -0,0 +1,207 @@ +package com.bwssystems.HABridge.plugins.moziot; + +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.Home; +import com.bwssystems.HABridge.NamedIP; +import com.bwssystems.HABridge.api.CallItem; +import com.bwssystems.HABridge.api.hue.HueError; +import com.bwssystems.HABridge.api.hue.HueErrorResponse; +import com.bwssystems.HABridge.dao.DeviceDescriptor; +import com.bwssystems.HABridge.hue.BrightnessDecode; +import com.bwssystems.HABridge.hue.ColorData; +import com.bwssystems.HABridge.hue.ColorDecode; +import com.bwssystems.HABridge.hue.DeviceDataDecode; +import com.bwssystems.HABridge.hue.MultiCommandUtil; +import com.bwssystems.HABridge.hue.TimeDecode; +import com.bwssystems.HABridge.plugins.http.HTTPHandler; +import com.bwssystems.HABridge.plugins.http.HTTPHome; +import com.google.gson.Gson; + +public class MozIotHome implements Home { + private static final Logger log = LoggerFactory.getLogger(MozIotHome.class); + private Map moziotMap; + private Boolean validMoziot; + private HTTPHandler httpClient; + private boolean closed; + + public MozIotHome(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 theUrl = anItem.getItem().getAsString(); + String responseString = null; + + if(theUrl != null && !theUrl.isEmpty()) { + MozIotCommand theCommand = null; + try { + theCommand = new Gson().fromJson(theUrl, MozIotCommand.class); + } catch(Exception e) { + log.warn("Cannot parse command to Mozilla IOT <<<" + theUrl + ">>>", e); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + return responseString; + } + String intermediate = theCommand.getUrl().substring(theCommand.getUrl().indexOf("://") + 3); + String hostPortion = intermediate.substring(0, intermediate.indexOf('/')); + String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1); + String hostAddr = null; + if (hostPortion.contains(":")) { + hostAddr = hostPortion.substring(0, intermediate.indexOf(':')); + } else + hostAddr = hostPortion; + MozIotInstance theHandler = findHandlerByAddress(hostAddr); + if(theHandler != null) { + String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, + intensity, targetBri, targetBriInc, false); + if (colorData != null) { + anUrl = ColorDecode.replaceColorData(anUrl, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false); + } + anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device); + anUrl = TimeDecode.replaceTimeValue(anUrl); + + String aCommand = null; + if(theCommand.getCommand() != null && !theCommand.getCommand().isEmpty()) { + aCommand = BrightnessDecode.calculateReplaceIntensityValue(theCommand.getCommand(), + intensity, targetBri, targetBriInc, false); + if (colorData != null) { + aCommand = ColorDecode.replaceColorData(aCommand, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false); + } + aCommand = DeviceDataDecode.replaceDeviceData(aCommand, device); + aCommand = TimeDecode.replaceTimeValue(aCommand); + } + try { + boolean success = theHandler.callCommand(anUrl, aCommand, httpClient); + if(!success) { + log.warn("Comand had error to Mozilla IOT"); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + } + } catch (Exception e) { + log.warn("Cannot send comand to Mozilla IOT", e); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + } + } else { + log.warn("Mozilla IOT Call could not complete, no address found: " + theUrl); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + } + } else { + log.warn("Mozilla IOT Call to be presented as http(s)://(:)/payload, format of request unknown: " + theUrl); + responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId, + "Error on calling url to change device state", "/lights/" + + lightId + "state", null, null).getTheErrors(), HueError[].class); + } + return responseString; + } + + @Override + public Object getItems(String type) { + + if(!validMoziot) + return null; + log.debug("consolidating devices for Mozilla IOT"); + List theResponse = null; + Iterator keys = moziotMap.keySet().iterator(); + List deviceList = new ArrayList(); + while(keys.hasNext()) { + String key = keys.next(); + theResponse = moziotMap.get(key).getDevices(httpClient); + if(theResponse != null) + addMozIotDevices(deviceList, theResponse, key); + else { + log.warn("Cannot get devices for Mozilla IOT with name: " + key + ", skipping this Mozilla IOT."); + continue; + } + } + return deviceList; + } + + private Boolean addMozIotDevices(List theDeviceList, List theSourceList, String theKey) { + Iterator devices = theSourceList.iterator(); + while(devices.hasNext()) { + MozillaThing theDevice = devices.next(); + theDeviceList.add(theDevice); + } + return true; + } + + @Override + public Home createHome(BridgeSettings bridgeSettings) { + moziotMap = null; + validMoziot = bridgeSettings.getBridgeSettingsDescriptor().isValidMozIot(); + log.info("Mozilla IOT Home created." + (validMoziot ? "" : " No Mozilla IOTs configured.")); + if(validMoziot) { + moziotMap = new HashMap(); + httpClient = HTTPHome.getHandler(); + Iterator theList = bridgeSettings.getBridgeSettingsDescriptor().getMoziotaddress().getDevices().iterator(); + while(theList.hasNext() && validMoziot) { + NamedIP aMoziot = theList.next(); + try { + moziotMap.put(aMoziot.getName(), new MozIotInstance(aMoziot, httpClient)); + } catch (Exception e) { + log.error("Cannot get Mozilla IOT (" + aMoziot.getName() + ") setup, Exiting with message: " + e.getMessage(), e); + validMoziot = false; + } + } + } + return this; + } + + private MozIotInstance findHandlerByAddress(String hostAddress) { + MozIotInstance aHandler = null; + boolean found = false; + Iterator keys = moziotMap.keySet().iterator(); + while(keys.hasNext()) { + String key = keys.next(); + aHandler = moziotMap.get(key); + if(aHandler != null && aHandler.getMozIotIP().getIp().equals(hostAddress)) { + found = true; + break; + } + } + if(!found) + aHandler = null; + return aHandler; + } + + @Override + public void closeHome() { + log.debug("Closing Home."); + if(!closed && validMoziot) { + log.debug("Home is already closed...."); + return; + } + + if(httpClient != null) + httpClient.closeHandler(); + + moziotMap = null; + closed = true; + } + + @Override + public void refresh() { + // noop + } +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotInstance.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotInstance.java new file mode 100644 index 0000000..b6de7b5 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozIotInstance.java @@ -0,0 +1,131 @@ +package com.bwssystems.HABridge.plugins.moziot; + +import java.util.ArrayList; +import java.util.List; + +import com.bwssystems.HABridge.NamedIP; +import com.bwssystems.HABridge.api.NameValue; +import com.bwssystems.HABridge.plugins.http.HTTPHandler; +import com.google.gson.Gson; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpPost; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MozIotInstance { + private static final Logger log = LoggerFactory.getLogger(MozIotInstance.class); + private JWT moziotToken; + private NamedIP mozIotIP; + private NameValue[] headers; + + public MozIotInstance(NamedIP theNamedIp, HTTPHandler httpClient) { + mozIotIP = theNamedIp; + headers = null; + gatewayLogin(httpClient); + } + + public Boolean callCommand(String aCommand, String commandData, HTTPHandler httpClient) { + log.debug("calling Mozilla IOT: " + mozIotIP.getIp() + ":" + mozIotIP.getPort() + aCommand); + String aUrl = null; + + if (mozIotIP.getSecure() != null && mozIotIP.getSecure()) + aUrl = "https://"; + else + aUrl = "http://"; + headers = getAuthHeader(); + + aUrl = aUrl + mozIotIP.getIp() + ":" + mozIotIP.getPort() + "/" + aCommand; + String theData = httpClient.doHttpRequest(aUrl, HttpPut.METHOD_NAME, "application/json", commandData, headers); + log.debug("call Command return is: <" + theData + ">"); + if (theData.contains("error") || theData.contains("ERROR") || theData.contains("Error")) + return false; + return true; + } + + public List getDevices(HTTPHandler httpClient) { + log.debug("calling Mozilla IOT: " + mozIotIP.getIp() + ":" + mozIotIP.getPort()); + List deviceList = null; + MozillaThing[] theThings; + String theUrl = null; + String theData; + + if (mozIotIP.getSecure() != null && mozIotIP.getSecure()) + theUrl = "https://"; + else + theUrl = "http://"; + headers = getAuthHeader(); + + theUrl = theUrl + mozIotIP.getIp() + ":" + mozIotIP.getPort() + "/things"; + theData = httpClient.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, headers); + if (theData != null) { + log.debug("GET Mozilla IOT Devices - data: " + theData); + try { + theThings = new Gson().fromJson(theData, MozillaThing[].class); + if (theThings != null && theThings.length > 0) { + deviceList = new ArrayList(); + for (int i = 0; i < theThings.length; i++) { + deviceList.add(theThings[i]); + } + } + } catch (Exception e) { + log.warn("Cannot get an devices for Mozilla IOT " + mozIotIP.getName() + " Gson Parse Error."); + } + } + return deviceList; + } + + private NameValue[] getAuthHeader() { + if (headers == null) { + headers = new NameValue[1]; + headers[0] = new NameValue(); + headers[0].setName("Authorization"); + headers[0].setValue("Bearer " + moziotToken.getJwt()); + } + return headers; + } + + private void gatewayLogin(HTTPHandler httpClient) { + String aUrl = null; + + if (mozIotIP.getSecure() != null && mozIotIP.getSecure()) + aUrl = "https://"; + else + aUrl = "http://"; + + aUrl = aUrl + mozIotIP.getIp() + ":" + mozIotIP.getPort() + "/login"; + String commandData = "{\"email\": \"" + mozIotIP.getUsername() + "\", \"password\":\"" + mozIotIP.getPassword() + + "\"}"; + String theData = httpClient.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "application/json", commandData, null); + if (theData != null) { + log.info("GET Mozilla login - data: " + theData); + try { + moziotToken = new Gson().fromJson(theData, JWT.class); + } catch (Exception e) { + log.warn("Cannot get login for Mozilla IOT " + mozIotIP.getName() + " Gson Parse Error."); + } + } else { + log.warn("Could not login " + mozIotIP.getName() + " error: <<<" + theData + ">>>"); + } + } + + public NamedIP getMozIotIP() { + return mozIotIP; + } + + public void setMozIotIP(NamedIP mozIotIP) { + this.mozIotIP = mozIotIP; + } + + protected void closeClient() { + } + + public JWT getMoziotToken() { + return moziotToken; + } + + public void setMoziotToken(JWT moziotToken) { + this.moziotToken = moziotToken; + } +} \ No newline at end of file diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozillaThing.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozillaThing.java new file mode 100644 index 0000000..cc54c62 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/MozillaThing.java @@ -0,0 +1,154 @@ + +package com.bwssystems.HABridge.plugins.moziot; + +import java.util.List; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class MozillaThing { + + @SerializedName("name") + @Expose + private String name; + @SerializedName("type") + @Expose + private String type; + @SerializedName("@context") + @Expose + private String atcontext; + @SerializedName("@type") + @Expose + private List attype = null; + @SerializedName("description") + @Expose + private String description; + @SerializedName("href") + @Expose + private String href; + @SerializedName("properties") + @Expose + private Properties properties; + @SerializedName("actions") + @Expose + private Actions actions; + @SerializedName("events") + @Expose + private Events events; + @SerializedName("links") + @Expose + private List links = null; + @SerializedName("layoutIndex") + @Expose + private Integer layoutIndex; + @SerializedName("selectedCapability") + @Expose + private String selectedCapability; + @SerializedName("iconHref") + @Expose + private Object iconHref; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getAtcontext() { + return atcontext; + } + + public void setAtcontext(String atcontext) { + this.atcontext = atcontext; + } + + public List getAttype() { + return attype; + } + + public void setAttype(List attype) { + this.attype = attype; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href; + } + + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } + + public Actions getActions() { + return actions; + } + + public void setActions(Actions actions) { + this.actions = actions; + } + + public Events getEvents() { + return events; + } + + public void setEvents(Events events) { + this.events = events; + } + + public List getLinks() { + return links; + } + + public void setLinks(List links) { + this.links = links; + } + + public Integer getLayoutIndex() { + return layoutIndex; + } + + public void setLayoutIndex(Integer layoutIndex) { + this.layoutIndex = layoutIndex; + } + + public String getSelectedCapability() { + return selectedCapability; + } + + public void setSelectedCapability(String selectedCapability) { + this.selectedCapability = selectedCapability; + } + + public Object getIconHref() { + return iconHref; + } + + public void setIconHref(Object iconHref) { + this.iconHref = iconHref; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/On.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/On.java new file mode 100644 index 0000000..ad0588b --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/On.java @@ -0,0 +1,55 @@ + +package com.bwssystems.HABridge.plugins.moziot; + +import java.util.List; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class On { + + @SerializedName("title") + @Expose + private String title; + @SerializedName("type") + @Expose + private String type; + @SerializedName("attype") + @Expose + private String attype; + @SerializedName("links") + @Expose + private List links = null; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getAttype() { + return attype; + } + + public void setAttype(String attype) { + this.attype = attype; + } + + public List getLinks() { + return links; + } + + public void setLinks(List links) { + this.links = links; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/moziot/Properties.java b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Properties.java new file mode 100644 index 0000000..4a9c21b --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/moziot/Properties.java @@ -0,0 +1,32 @@ + +package com.bwssystems.HABridge.plugins.moziot; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Properties { + + @SerializedName("on") + @Expose + private On on; + @SerializedName("level") + @Expose + private Level level; + + public On getOn() { + return on; + } + + public void setOn(On on) { + this.on = on; + } + + public Level getLevel() { + return level; + } + + public void setLevel(Level level) { + this.level = level; + } + +} diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java index 26e4925..c2039b9 100644 --- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java +++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java @@ -17,13 +17,13 @@ import java.time.temporal.ChronoUnit; import java.util.Enumeration; import org.apache.http.conn.util.*; - public class UpnpListener { private Logger log = LoggerFactory.getLogger(UpnpListener.class); private MulticastSocket upnpMulticastSocket; private int httpServerPort; private String upnpConfigIP; - private boolean strict; + // private boolean strict; + private boolean upnpOriginal; private boolean traceupnp; private boolean useUpnpIface; private BridgeControlDescriptor bridgeControl; @@ -31,77 +31,67 @@ public class UpnpListener { private String bridgeSNUUID; private HuePublicConfig aHueConfig; private Integer theUpnpSendDelay; - private String responseTemplate1 = "HTTP/1.1 200 OK\r\n" + - "HOST: %s:%s\r\n" + - "CACHE-CONTROL: max-age=100\r\n" + - "EXT:\r\n" + - "LOCATION: http://%s:%s/description.xml\r\n" + - "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + HueConstants.API_VERSION + "\r\n" + - "hue-bridgeid: %s\r\n" + - "ST: upnp:rootdevice\r\n" + - "USN: uuid:" + HueConstants.UUID_PREFIX + "%s::upnp:rootdevice\r\n\r\n"; - private String responseTemplate2 = "HTTP/1.1 200 OK\r\n" + - "HOST: %s:%s\r\n" + - "CACHE-CONTROL: max-age=100\r\n" + - "EXT:\r\n" + - "LOCATION: http://%s:%s/description.xml\r\n" + - "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + HueConstants.API_VERSION + "\r\n" + - "hue-bridgeid: %s\r\n" + - "ST: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n" + - "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n"; - private String responseTemplate3 = "HTTP/1.1 200 OK\r\n" + - "HOST: %s:%s\r\n" + - "CACHE-CONTROL: max-age=100\r\n" + - "EXT:\r\n" + - "LOCATION: http://%s:%s/description.xml\r\n" + - "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + HueConstants.API_VERSION + "\r\n" + - "hue-bridgeid: %s\r\n" + - "ST: urn:schemas-upnp-org:device:basic:1\r\n" + - "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n"; + private String responseTemplateOriginal = "HTTP/1.1 200 OK\r\n" + "CACHE-CONTROL: max-age=86400\r\n" + "EXT:\r\n" + + "LOCATION: http://%s:%s/description.xml\r\n" + "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/" + + HueConstants.API_VERSION + "\r\n" + "ST: urn:schemas-upnp-org:device:basic:1\r\n" + "USN: uuid:" + + HueConstants.UUID_PREFIX + "%s::urn:schemas-upnp-org:device:basic:1\r\n\r\n"; + private String responseTemplate1 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n" + + "EXT:\r\n" + "LOCATION: http://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + + HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: upnp:rootdevice\r\n" + "USN: uuid:" + + HueConstants.UUID_PREFIX + "%s::upnp:rootdevice\r\n\r\n"; + private String responseTemplate2 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n" + + "EXT:\r\n" + "LOCATION: http://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + + HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: uuid:" + HueConstants.UUID_PREFIX + + "%s\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n"; + private String responseTemplate3 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n" + + "EXT:\r\n" + "LOCATION: http://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + + HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: urn:schemas-upnp-org:device:basic:1\r\n" + + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n"; - private String notifyTemplate = "NOTIFY * HTTP/1.1\r\n" + - "HOST: %s:%s\r\n" + - "CACHE-CONTROL: max-age=100\r\n" + - "LOCATION: http://%s:%s/description.xml\r\n" + - "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + HueConstants.API_VERSION + "\r\n" + - "NTS: ssdp:alive\r\n" + - "hue-bridgeid: %s\r\n" + - "NT: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n" + - "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n"; + private String notifyTemplate = "NOTIFY * HTTP/1.1\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n" + + "LOCATION: http://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + + HueConstants.API_VERSION + "\r\n" + "NTS: ssdp:alive\r\n" + "hue-bridgeid: %s\r\n" + "NT: uuid:" + + HueConstants.UUID_PREFIX + "%s\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n"; - public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl, UDPDatagramSender aUdpDatagramSender) throws IOException { + public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl, + UDPDatagramSender aUdpDatagramSender) throws IOException { super(); upnpMulticastSocket = null; httpServerPort = Integer.valueOf(theSettings.getServerPort()); upnpConfigIP = theSettings.getUpnpConfigAddress(); - strict = theSettings.isUpnpStrict(); + // strict = theSettings.isUpnpStrict(); + upnpOriginal = theSettings.isUpnporiginal(); traceupnp = theSettings.isTraceupnp(); useUpnpIface = theSettings.isUseupnpiface(); theUpnpSendDelay = theSettings.getUpnpsenddelay(); bridgeControl = theControl; - aHueConfig = HuePublicConfig.createConfig("temp", upnpConfigIP, HueConstants.HUB_VERSION, theSettings.getHubmac()); + aHueConfig = HuePublicConfig.createConfig("temp", upnpConfigIP, HueConstants.HUB_VERSION, + theSettings.getHubmac()); bridgeId = aHueConfig.getBridgeid(); bridgeSNUUID = aHueConfig.getSNUUIDFromMac(); try { - if(useUpnpIface) - upnpMulticastSocket = new MulticastSocket(new InetSocketAddress(upnpConfigIP, Configuration.UPNP_DISCOVERY_PORT)); + if (useUpnpIface) + upnpMulticastSocket = new MulticastSocket( + new InetSocketAddress(upnpConfigIP, Configuration.UPNP_DISCOVERY_PORT)); else - upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT); - } catch(IOException e){ - log.error("Upnp Discovery Port is in use, or restricted by admin (try running with sudo or admin privs): " + Configuration.UPNP_DISCOVERY_PORT + " with message: " + e.getMessage()); - throw(e); + upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT); + } catch (IOException e) { + log.error("Upnp Discovery Port is in use, or restricted by admin (try running with sudo or admin privs): " + + Configuration.UPNP_DISCOVERY_PORT + " with message: " + e.getMessage()); + throw (e); } - + } - public boolean startListening(){ + public boolean startListening() { log.info("UPNP Discovery Listener starting...."); Enumeration ifs = null; - InetSocketAddress socketAddress = new InetSocketAddress(Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT); + InetSocketAddress socketAddress = new InetSocketAddress(Configuration.UPNP_MULTICAST_ADDRESS, + Configuration.UPNP_DISCOVERY_PORT); try { - ifs = NetworkInterface.getNetworkInterfaces(); - } catch (SocketException e) { + ifs = NetworkInterface.getNetworkInterfaces(); + } catch (SocketException e) { log.error("Could not get network interfaces for this machine: " + e.getMessage()); return false; } @@ -116,14 +106,14 @@ public class UpnpListener { InetAddress addr = addrs.nextElement(); log.debug(name + " ... has addr " + addr); if (InetAddressUtils.isIPv4Address(addr.getHostAddress())) { - if(!useUpnpIface) { - if(traceupnp) + if (!useUpnpIface) { + if (traceupnp) log.info("Traceupnp: Interface: " + name + " valid usable IP address: " + addr); IPsPerNic++; - } - else if(addr.getHostAddress().equals(upnpConfigIP)) { - if(traceupnp) - log.info("Traceupnp: Interface: " + name + " matches upnp config address of IP address: " + addr); + } else if (addr.getHostAddress().equals(upnpConfigIP)) { + if (traceupnp) + log.info("Traceupnp: Interface: " + name + " matches upnp config address of IP address: " + + addr); IPsPerNic++; } } @@ -162,13 +152,14 @@ public class UpnpListener { try { sendUpnpResponse(packet); } catch (IOException e) { - log.warn("UpnpListener encountered an error sending upnp response packet. IP: " + packet.getAddress().getHostAddress() + " with message: " + e.getMessage()); + log.warn("UpnpListener encountered an error sending upnp response packet. IP: " + + packet.getAddress().getHostAddress() + " with message: " + e.getMessage()); log.debug("UpnpListener send upnp exception: ", e); } } current = Instant.now(); - if(ChronoUnit.MILLIS.between(previous, current) > Configuration.UPNP_NOTIFY_TIMEOUT) { + if (ChronoUnit.MILLIS.between(previous, current) > Configuration.UPNP_NOTIFY_TIMEOUT) { sendUpnpNotify(socketAddress.getAddress()); previous = Instant.now(); } @@ -203,32 +194,33 @@ public class UpnpListener { /** * ssdp discovery packet detection */ - protected boolean isSSDPDiscovery(DatagramPacket packet){ - //Only respond to discover request for strict upnp form + protected boolean isSSDPDiscovery(DatagramPacket packet) { + // Only respond to discover request for strict upnp form String packetString = new String(packet.getData(), 0, packet.getLength()); - if(packetString != null && packetString.startsWith("M-SEARCH * HTTP/1.1") && packetString.contains("\"ssdp:discover\"")){ - if(strict && (packetString.contains("ST: urn:schemas-upnp-org:device:basic:1") || packetString.contains("ST: upnp:rootdevice") || packetString.contains("ST: ssdp:all"))) - { - if(traceupnp) { - log.info("Traceupnp: SSDP M-SEARCH packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort()); - } - else - log.debug("SSDP M-SEARCH packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: <<<" + packetString + ">>>"); + if (packetString != null && packetString.startsWith("M-SEARCH * HTTP/1.1") + && packetString.contains("\"ssdp:discover\"")) { + if ((packetString.contains("ST: urn:schemas-upnp-org:device:basic:1") + || packetString.contains("ST: upnp:rootdevice") || packetString.contains("ST: ssdp:all"))) { + if (traceupnp) { + log.info("Traceupnp: SSDP M-SEARCH packet from " + packet.getAddress().getHostAddress() + ":" + + packet.getPort()); + } else + log.debug("SSDP M-SEARCH packet from " + packet.getAddress().getHostAddress() + ":" + + packet.getPort() + ", body: <<<" + packetString + ">>>"); return true; - } - else if (!strict) - { - if(traceupnp) { - log.info("Traceupnp: SSDP M-SEARCH packet (!strict) from " + packet.getAddress().getHostAddress() + ":" + packet.getPort()); - } - else - log.debug("SSDP M-SEARCH packet (!strict) from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: <<<" + packetString + ">>>"); - return true; - } - } - else { -// log.debug("isSSDPDiscovery found message to not be valid - strict: " + strict); -// log.debug("SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString); + } /* + * else if (!strict) { if(traceupnp) { + * log.info("Traceupnp: SSDP M-SEARCH packet (!strict) from " + + * packet.getAddress().getHostAddress() + ":" + packet.getPort()); } else + * log.debug("SSDP M-SEARCH packet (!strict) from " + + * packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: <<<" + * + packetString + ">>>"); return true; } + */ + } else { + // log.debug("isSSDPDiscovery found message to not be valid - strict: " + + // strict); + log.debug("SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + + packetString); } return false; } @@ -245,65 +237,90 @@ public class UpnpListener { } catch (InterruptedException e) { // noop } - discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID); - if(traceupnp) { - log.info("Traceupnp: send upnp discovery template 1 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort); - } - else - log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " with discovery responseTemplate1 is <<<" + discoveryResponse + ">>>"); - sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort); - try { - Thread.sleep(theUpnpSendDelay); - } catch (InterruptedException e) { - // noop - } - discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID); - if(traceupnp) { - log.info("Traceupnp: send upnp discovery template 2 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort); - } - else - log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate2 is <<<" + discoveryResponse + ">>>"); - sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort); + if (upnpOriginal) { + discoveryResponse = String.format(responseTemplateOriginal, Configuration.UPNP_MULTICAST_ADDRESS, + Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID); + if (traceupnp) { + log.info("Traceupnp: send upnp discovery template Original with response address: " + httpLocationAddress + ":" + + httpServerPort + " to address: " + requester + ":" + sourcePort); + } else + log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + + " with discovery responseTemplateOriginal is <<<" + discoveryResponse + ">>>"); + sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort); + } else { + discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, + Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID); + if (traceupnp) { + log.info("Traceupnp: send upnp discovery template 1 with response address: " + httpLocationAddress + ":" + + httpServerPort + " to address: " + requester + ":" + sourcePort); + } else + log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + + " with discovery responseTemplate1 is <<<" + discoveryResponse + ">>>"); + sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort); - try { - Thread.sleep(theUpnpSendDelay); - } catch (InterruptedException e) { - // noop + try { + Thread.sleep(theUpnpSendDelay); + } catch (InterruptedException e) { + // noop + } + discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS, + Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID, + bridgeSNUUID); + if (traceupnp) { + log.info("Traceupnp: send upnp discovery template 2 with response address: " + httpLocationAddress + ":" + + httpServerPort + " to address: " + requester + ":" + sourcePort); + } else + log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + + " discovery responseTemplate2 is <<<" + discoveryResponse + ">>>"); + sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort); + + try { + Thread.sleep(theUpnpSendDelay); + } catch (InterruptedException e) { + // noop + } + discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS, + Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID); + if (traceupnp) { + log.info("Traceupnp: send upnp discovery template 3 with response address: " + httpLocationAddress + ":" + + httpServerPort + " to address: " + requester + ":" + sourcePort); + } else + log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + + " discovery responseTemplate3 is <<<" + discoveryResponse + ">>>"); + sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort); } - discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID); - if(traceupnp) { - log.info("Traceupnp: send upnp discovery template 3 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort); - } - else - log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate3 is <<<" + discoveryResponse + ">>>"); - sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort); } private void sendUDPResponse(byte[] udpMessage, InetAddress requester, int sourcePort) throws IOException { log.debug("Sending response string: <<<" + new String(udpMessage) + ">>>"); - if(upnpMulticastSocket == null) + if (upnpMulticastSocket == null) throw new IOException("Socket not initialized"); DatagramPacket response = new DatagramPacket(udpMessage, udpMessage.length, requester, sourcePort); upnpMulticastSocket.send(response); } - + protected void sendUpnpNotify(InetAddress aSocketAddress) { String notifyData = null; - notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, upnpConfigIP, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID); + notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, + Configuration.UPNP_DISCOVERY_PORT, upnpConfigIP, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID); log.debug("sendUpnpNotify notifyTemplate is <<<" + notifyData + ">>>"); - DatagramPacket notifyPacket = new DatagramPacket(notifyData.getBytes(), notifyData.length(), aSocketAddress, Configuration.UPNP_DISCOVERY_PORT); + DatagramPacket notifyPacket = new DatagramPacket(notifyData.getBytes(), notifyData.length(), aSocketAddress, + Configuration.UPNP_DISCOVERY_PORT); try { upnpMulticastSocket.send(notifyPacket); } catch (IOException e1) { - log.warn("UpnpListener encountered an error sending upnp notify packet. IP: " + notifyPacket.getAddress().getHostAddress() + " with message: " + e1.getMessage()); + log.warn("UpnpListener encountered an error sending upnp notify packet. IP: " + + notifyPacket.getAddress().getHostAddress() + " with message: " + e1.getMessage()); log.debug("UpnpListener send upnp notify exception: ", e1); } } // added by https://github.com/pvint - // Ruthlessly stolen from https://stackoverflow.com/questions/22045165/java-datagrampacket-receive-how-to-determine-local-ip-interface - // Try to get a source IP that makes sense for the requestor to contact for use in the LOCATION header in replies + // Ruthlessly stolen from + // https://stackoverflow.com/questions/22045165/java-datagrampacket-receive-how-to-determine-local-ip-interface + // Try to get a source IP that makes sense for the requestor to contact for use + // in the LOCATION header in replies private InetAddress getOutboundAddress(SocketAddress remoteAddress) throws SocketException { DatagramSocket sock = new DatagramSocket(); // connect is needed to bind the socket and retrieve the local address diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 2e5c28b..b9823f0 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -83,6 +83,10 @@ app.config (function ($locationProvider, $routeProvider) { templateUrl: 'views/openhabdevice.html', controller: 'OpenHABController', requiresAuthentication: true + }).when ('/moziotdevices', { + templateUrl: 'views/moziotdevice.html', + controller: 'MozIotController', + requiresAuthentication: true }).when ('/fhemdevices', { templateUrl: 'views/fhemdevice.html', controller: 'FhemController', @@ -159,7 +163,8 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n this.state = {base: "./api/devices", bridgelocation: ".", systemsbase: "./system", huebase: "./api", configs: [], backups: [], devices: [], device: {}, mapandid: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], mapTypes: [], olddevicename: "", logShowAll: false, isInControl: false, showVera: false, showFibaro: false, showHarmony: false, showNest: false, showHue: false, showHal: false, showMqtt: false, showHass: false, - showHomeWizard: false, showDomoticz: false, showSomfy: false, showLifx: false, showOpenHAB: false, showFHEM: false, showBroadlink: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null, + showHomeWizard: false, showDomoticz: false, showSomfy: false, showLifx: false, showOpenHAB: false, showMozIot: false, showFHEM: false, showBroadlink: false, habridgeversion: {}, + viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null, filterDevicesOnlyFiltered: false, filterDeviceType: null}; this.displayWarn = function(errorTitle, error) { @@ -575,6 +580,11 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n return; }; + this.updateShowMozIot = function () { + this.state.showMozIot = self.state.settings.moziotconfigured; + return; + }; + this.updateShowFhem = function () { this.state.showFHEM = self.state.settings.fhemconfigured; return; @@ -602,6 +612,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n self.updateShowSomfy(); self.updateShowLifx(); self.updateShowOpenHAB(); + self.updateShowMozIot(); self.updateShowFhem(); self.updateShowBroadlink(); }, @@ -927,6 +938,22 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n ); }; + this.viewMozIotDevices = function () { + if (!this.state.showMozIot) + return; + return $http.get(this.state.base + "/moziot/devices").then( + function (response) { + self.state.moziotdevices = response.data; + }, + function (error) { + if (error.status === 401) + $rootScope.$broadcast('securityReinit', 'done'); + else + self.displayWarn("Get Mozilla IOT Devices Error: ", error); + } + ); + }; + this.viewFhemDevices = function () { if (!this.state.showFHEM) return; @@ -1740,6 +1767,26 @@ app.controller ('SystemController', function ($scope, $location, bridgeService, } }; + $scope.addMozIottoSettings = function (newmoziotname, newmoziotip, newmoziotport, newmoziotusername, newmoziotpassword, newmoziotsecure) { + if($scope.bridge.settings.moziotaddress === undefined || $scope.bridge.settings.moziotaddress === null) { + $scope.bridge.settings.moziotaddress = { devices: [] }; + } + var newmoziot = {name: newmoziotname, ip: newmoziotip, port: newmoziotport, username: newmoziotusername, password: newmoziotpassword, secure: newmoziotsecure }; + $scope.bridge.settings.moziotaddress.devices.push(newmoziot); + $scope.newmoziotname = null; + $scope.newmoziotip = null; + $scope.newmoziotport = "4443"; + $scope.newmoziotusername = null; + $scope.newmoziotpassword = null; + }; + $scope.removeMozIottoSettings = function (moziotname, moziotip) { + for(var i = $scope.bridge.settings.moziotaddress.devices.length - 1; i >= 0; i--) { + if($scope.bridge.settings.moziotaddress.devices[i].name === moziotname && $scope.bridge.settings.moziotaddress.devices[i].ip === moziotip) { + $scope.bridge.settings.moziotaddress.devices.splice(i, 1); + } + } + }; + $scope.addFhemtoSettings = function (newfhemname, newfhemip, newfhemport, newfhemusername, newfhempassword, newfhemwebhook, newfhemsecure) { if($scope.bridge.settings.fhemaddress === undefined || $scope.bridge.settings.fhemaddress === null) { $scope.bridge.settings.fhemaddress = { devices: [] }; @@ -3931,6 +3978,142 @@ app.controller('OpenHABController', function ($scope, $location, bridgeService, }; }); +app.controller('MozIotController', 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.viewMozIotDevices(); + $scope.imgButtonsUrl = "glyphicon glyphicon-plus"; + $scope.buttonsVisible = false; + + $scope.clearDevice = function () { + bridgeService.clearDevice(); + $scope.device = bridgeService.state.device; + }; + + $scope.buildDeviceUrls = function (moziotdevice, dim_control, colordata, buildonly) { + var preCmd = moziotdevice.href + "/"; + onpayload = null; + offpayload = null; + dimpayload = null; + colorpayload = null; + if(moziotdevice.properties.on !== undefined) { + onpayload = "{\"url\":\"" + preCmd + "on\",\"command\":{\"on\":true}}"; + offpayload = "{\"url\":\"" + preCmd + "on\",\"command\":{\"on\":false}}"; + } + if(moziotdevice.properties.level !== undefined) { + dimpayload = "{\"url\":\"" + preCmd + "level\",\"command\":{\"level\":" + dim_control + "}}"; + } + if(moziotdevice.properties.color !== undefined) { + colorpayload = "{\"url\":\"" + preCmd + "color\",\"command\":\"{\"color\":" + colordata + "}}"; + } + + bridgeService.buildUrls(onpayload, dimpayload, offpayload, colorpayload, true, moziotdevice.name + "-" + moziotdevice.type, moziotdevice.name, moziotdevice.name, moziotdevice.type, "moziotDevice", null, null); + $scope.device = bridgeService.state.device; + if (!buildonly) { + bridgeService.editNewDevice($scope.device); + $location.path('/editdevice'); + } + }; + + $scope.bulkAddDevices = function(dim_control) { + var devicesList = []; + $scope.clearDevice(); + for(var i = 0; i < $scope.bulk.devices.length; i++) { + for(var x = 0; x < bridgeService.state.moziotdevices.length; x++) { + if(bridgeService.state.moziotdevices[x].devicename === $scope.bulk.devices[i]) { + $scope.buildDeviceUrls(bridgeService.state.moziotdevices[x],dim_control, null, 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 Mozilla IOT 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.moziotdevices.length; x++) { + if($scope.bulk.devices.indexOf(bridgeService.state.moziotdevices[x]) < 0) + $scope.bulk.devices.push(bridgeService.state.moziotdevices[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('FhemController', function ($scope, $location, bridgeService, ngDialog) { $scope.bridge = bridgeService.state; $scope.device = bridgeService.state.device; diff --git a/src/main/resources/public/views/broadlinkdevice.html b/src/main/resources/public/views/broadlinkdevice.html index 2ae1206..f4ee90f 100644 --- a/src/main/resources/public/views/broadlinkdevice.html +++ b/src/main/resources/public/views/broadlinkdevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/configuration.html b/src/main/resources/public/views/configuration.html index 4e19e96..d351cac 100644 --- a/src/main/resources/public/views/configuration.html +++ b/src/main/resources/public/views/configuration.html @@ -20,6 +20,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/domoticzdevice.html b/src/main/resources/public/views/domoticzdevice.html index c68282e..c2d365f 100644 --- a/src/main/resources/public/views/domoticzdevice.html +++ b/src/main/resources/public/views/domoticzdevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/editdevice.html b/src/main/resources/public/views/editdevice.html index 37c715c..09a41cf 100644 --- a/src/main/resources/public/views/editdevice.html +++ b/src/main/resources/public/views/editdevice.html @@ -20,6 +20,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • diff --git a/src/main/resources/public/views/fhemdevice.html b/src/main/resources/public/views/fhemdevice.html index 9e7d8f0..61ac469 100644 --- a/src/main/resources/public/views/fhemdevice.html +++ b/src/main/resources/public/views/fhemdevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/fibarodevice.html b/src/main/resources/public/views/fibarodevice.html index cbe8cd7..da4d4ba 100644 --- a/src/main/resources/public/views/fibarodevice.html +++ b/src/main/resources/public/views/fibarodevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/fibaroscene.html b/src/main/resources/public/views/fibaroscene.html index cc41ce7..9913c3e 100644 --- a/src/main/resources/public/views/fibaroscene.html +++ b/src/main/resources/public/views/fibaroscene.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/haldevice.html b/src/main/resources/public/views/haldevice.html index 11a0a0d..d269a90 100644 --- a/src/main/resources/public/views/haldevice.html +++ b/src/main/resources/public/views/haldevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/harmonyactivity.html b/src/main/resources/public/views/harmonyactivity.html index eff91fc..bfd79c3 100644 --- a/src/main/resources/public/views/harmonyactivity.html +++ b/src/main/resources/public/views/harmonyactivity.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/harmonydevice.html b/src/main/resources/public/views/harmonydevice.html index 475477d..bef18ca 100644 --- a/src/main/resources/public/views/harmonydevice.html +++ b/src/main/resources/public/views/harmonydevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/hassdevice.html b/src/main/resources/public/views/hassdevice.html index 574609b..4144fbb 100644 --- a/src/main/resources/public/views/hassdevice.html +++ b/src/main/resources/public/views/hassdevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/homewizarddevice.html b/src/main/resources/public/views/homewizarddevice.html index 0096871..45df646 100644 --- a/src/main/resources/public/views/homewizarddevice.html +++ b/src/main/resources/public/views/homewizarddevice.html @@ -19,6 +19,7 @@
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/huedevice.html b/src/main/resources/public/views/huedevice.html index 7a992ae..f1fadd3 100644 --- a/src/main/resources/public/views/huedevice.html +++ b/src/main/resources/public/views/huedevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/lifxdevice.html b/src/main/resources/public/views/lifxdevice.html index 2230dd1..c3462cf 100644 --- a/src/main/resources/public/views/lifxdevice.html +++ b/src/main/resources/public/views/lifxdevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/logs.html b/src/main/resources/public/views/logs.html index fd051d4..8d043ba 100644 --- a/src/main/resources/public/views/logs.html +++ b/src/main/resources/public/views/logs.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/moziotdevice.html b/src/main/resources/public/views/moziotdevice.html new file mode 100644 index 0000000..7d35cf4 --- /dev/null +++ b/src/main/resources/public/views/moziotdevice.html @@ -0,0 +1,151 @@ + + +
    +
    +

    Mozilla show Device List + ({{bridge.moziotdevices.length}})

    +
    +
    +

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

    +

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

    +

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

    + + + + + + + + + + + + + + + + + + + + +
    Row + NameTypeMozilla IOTColor ActionsBuild Actions
    {{$index+1}} + {{moziotdevice.name}}{{moziotdevice.type}}{{moziotdevice.name}} + + + +
    +
    + +
    +
    +
    +
    +

    + Already Configured OpenHAB Devices +

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

    + + +

    +
    +
    +
    +
    + diff --git a/src/main/resources/public/views/mqttpublish.html b/src/main/resources/public/views/mqttpublish.html index 5ee77ad..4bcdac8 100644 --- a/src/main/resources/public/views/mqttpublish.html +++ b/src/main/resources/public/views/mqttpublish.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/nestactions.html b/src/main/resources/public/views/nestactions.html index 92355da..7ce237b 100644 --- a/src/main/resources/public/views/nestactions.html +++ b/src/main/resources/public/views/nestactions.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/openhabdevice.html b/src/main/resources/public/views/openhabdevice.html index 3b658b4..d7660d2 100644 --- a/src/main/resources/public/views/openhabdevice.html +++ b/src/main/resources/public/views/openhabdevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/somfydevice.html b/src/main/resources/public/views/somfydevice.html index 208555f..a0d99a9 100644 --- a/src/main/resources/public/views/somfydevice.html +++ b/src/main/resources/public/views/somfydevice.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index eb4c8d6..fd4d5f7 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -757,7 +757,7 @@ + placeholder="An Mozilla IOT "> @@ -766,23 +766,20 @@ placeholder="8080"> + placeholder="Mozilla IOT username"> - + placeholder="Mozilla IOT password"> + ng-click="removeMozIottoSettings(moziot.name, moziot.ip)">Del + placeholder="A Mozilla IOT "> @@ -791,18 +788,15 @@ placeholder="8080"> + placeholder="Mozilla IOT username"> - + placeholder="Mozilla IOT password "> + ng-click="addMozIottoSettings(newmoziotname, newmoziotip, newmoziotport, newsmoziotusername, newmoziotpassword, newmoziotwebhook, newmoziotsecure)">Add @@ -865,6 +859,12 @@ ng-model="bridge.settings.numberoflogmessages" min="100" max="65535"> + + UPNP Original (simple version) + {{bridge.settings.upnporiginal}} + Trace UPNP Calls HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • diff --git a/src/main/resources/public/views/verascene.html b/src/main/resources/public/views/verascene.html index 35644dc..37695ae 100644 --- a/src/main/resources/public/views/verascene.html +++ b/src/main/resources/public/views/verascene.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit