Merge pull request #843 from bwssytems/FixesForV5

Fixes for v5

Fixes #842 Show and manage linked devices to the ha-bridge enhancement
Fixes #797 harmony hub not pairing bug question
Fixes #817 Log full of error: The requested route [/(null)] has not been mapped in Spark bug question
Fixes #821 Support HEX-Formatted RGB Values for color enhancement question
Fixes #837 -Dexec.garden breaks script execution with trailing slash enhancement question
Fixes #800 5.0.0 no longer connects to the vera enhancement question
Fixes #801 Fibaro scenes are not created bug question
Fixes #805 Fibaro HomeCenter2: Devices "Build Item" broken bug question
Fixes #841 add support for timestamp http URL variable
Fixes #836 Add support for cheap HomeWizard SmartPlugs (Smartwares Smarthome Controller)
This commit is contained in:
BWS Systems
2017-12-12 15:53:08 -06:00
committed by GitHub
38 changed files with 1171 additions and 34 deletions

View File

@@ -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
@@ -358,7 +360,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://<your stuff here>` 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://<your secure call here>`. 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:
```
@@ -378,7 +380,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://<ip_address>:<port>/<your stuff here>` to send a UDP request. TCP calls are handled the same way as `tcp://<ip_address>:<port>/<your stuff here>`. 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, "${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:
```
@@ -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(<your expression using "X" as the value to operate on>)} 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.

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId>
<version>5.0.0</version>
<version>5.1.0</version>
<packaging>jar</packaging>
<name>HA Bridge</name>

View File

@@ -205,6 +205,12 @@ public class BridgeSecurity {
return securityDescriptor.getWhitelist();
}
public void setWhitelist(Map<String, WhitelistEntry> aWhitelist) {
securityDescriptor.setWhitelist(aWhitelist);
settingsChanged = true;
return;
}
public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
String validUser = null;
boolean found = false;
@@ -238,6 +244,31 @@ public class BridgeSecurity {
return null;
}
public String findWhitelistUserByDeviceType(String aDeviceType) {
String validUser = null;
boolean found = false;
WhitelistEntry anEntry = null;
if (aDeviceType != null) {
if (securityDescriptor.getWhitelist() != null) {
Set<String> theUserIds = securityDescriptor.getWhitelist().keySet();
Iterator<String> 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 +281,14 @@ public class BridgeSecurity {
}
public String createWhitelistUser(String userDescription) {
String aUser = getNewUserID();
newWhitelistUser(aUser, userDescription);
String aUser = null;
String theEntry = findWhitelistUserByDeviceType(userDescription);
if(theEntry == null) {
aUser = getNewUserID();
newWhitelistUser(aUser, userDescription);
} else {
aUser = theEntry;
}
return aUser;
}

View File

@@ -209,6 +209,7 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setHassconfigured(theBridgeSettings.isValidHass());
theBridgeSettings.setDomoticzconfigured(theBridgeSettings.isValidDomoticz());
theBridgeSettings.setSomfyconfigured(theBridgeSettings.isValidSomfy());
theBridgeSettings.setHomeWizardConfigured(theBridgeSettings.isValidHomeWizard());
// Lifx is either configured or not, so it does not need an update.
if(serverPortOverride != null)
theBridgeSettings.setServerPort(serverPortOverride);

View File

@@ -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;
@@ -93,7 +96,9 @@ public class BridgeSettingsDescriptor {
@SerializedName("securityData")
@Expose
private String securityData;
@SerializedName("homewizardaddress")
@Expose
private IpList homewizardaddress;
private boolean settingsChanged;
private boolean veraconfigured;
@@ -107,7 +112,8 @@ public class BridgeSettingsDescriptor {
private boolean domoticzconfigured;
private boolean somfyconfigured;
private boolean lifxconfigured;
private boolean homewizardconfigured;
// Deprecated settings
private String haltoken;
private boolean upnpstrict;
@@ -116,6 +122,7 @@ public class BridgeSettingsDescriptor {
super();
this.upnpstrict = true;
this.useupnpiface = false;
this.userooms = false;
this.traceupnp = false;
this.nestconfigured = false;
this.veraconfigured = false;
@@ -127,7 +134,7 @@ public class BridgeSettingsDescriptor {
this.mqttconfigured = false;
this.hassconfigured = false;
this.domoticzconfigured = false;
this.somfyconfigured = false;
this.homewizardconfigured = false;
this.lifxconfigured = false;
this.farenheit = true;
this.securityData = null;
@@ -149,6 +156,12 @@ public class BridgeSettingsDescriptor {
public void setUseupnpiface(boolean useupnpiface) {
this.useupnpiface = useupnpiface;
}
public boolean isUserooms() {
return userooms;
}
public void setUserooms(boolean userooms) {
this.userooms = userooms;
}
public Integer getServerPort() {
return serverport;
}
@@ -188,6 +201,9 @@ public class BridgeSettingsDescriptor {
public IpList getSomfyAddress() {
return somfyaddress;
}
public IpList getHomeWizardAddress() {
return homewizardaddress;
}
public void setVeraAddress(IpList veraAddress) {
this.veraaddress = veraAddress;
}
@@ -197,6 +213,9 @@ public class BridgeSettingsDescriptor {
public void setSomfyAddress(IpList somfyAddress) {
this.somfyaddress = somfyAddress;
}
public void setHomeWizardAddress(IpList homewizardaddress) {
this.homewizardaddress = homewizardaddress;
}
public IpList getHarmonyAddress() {
return harmonyaddress;
}
@@ -236,6 +255,9 @@ public class BridgeSettingsDescriptor {
public boolean isSomfyconfigured() {
return somfyconfigured;
}
public boolean isHomeWizardConfigured() {
return homewizardconfigured;
}
public void setVeraconfigured(boolean veraconfigured) {
this.veraconfigured = veraconfigured;
}
@@ -245,6 +267,9 @@ public class BridgeSettingsDescriptor {
public void setSomfyconfigured(boolean somfyconfigured) {
this.somfyconfigured = somfyconfigured;
}
public void setHomeWizardConfigured(boolean homewizardconfigured) {
this.homewizardconfigured = homewizardconfigured;
}
public boolean isHarmonyconfigured() {
return harmonyconfigured;
}
@@ -492,4 +517,14 @@ public class BridgeSettingsDescriptor {
this.setSettingsChanged(true);
}
}
public Boolean isValidHomeWizard() {
if(this.getHomeWizardAddress() == null || this.getHomeWizardAddress().getDevices().size() <= 0)
return false;
List<NamedIP> devicesList = this.getHomeWizardAddress().getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
return false;
return true;
}
}

View File

@@ -22,6 +22,7 @@ public class DeviceMapTypes {
public final static String[] EXEC_DEVICE_COMPAT = { "exec", "Execute Script/Program"};
public final static String[] CMD_DEVICE = { "cmdDevice", "Execute Command/Script/Program"};
public final static String[] HASS_DEVICE = { "hassDevice", "HomeAssistant Device"};
public final static String[] HOMEWIZARD_DEVICE = { "homewizardDevice", "HomeWizard Device"};
public final static String[] TCP_DEVICE = { "tcpDevice", "TCP Device"};
public final static String[] TCP_DEVICE_COMPAT = { "TCP", "TCP Device"};
public final static String[] UDP_DEVICE = { "udpDevice", "UDP Device"};
@@ -48,6 +49,7 @@ public class DeviceMapTypes {
deviceMapTypes.add(HARMONY_ACTIVITY);
deviceMapTypes.add(HARMONY_BUTTON);
deviceMapTypes.add(HASS_DEVICE);
deviceMapTypes.add(HOMEWIZARD_DEVICE);
deviceMapTypes.add(HTTP_DEVICE);
deviceMapTypes.add(HUE_DEVICE);
deviceMapTypes.add(LIFX_DEVICE);

View File

@@ -14,6 +14,7 @@ import com.bwssystems.HABridge.plugins.exec.CommandHome;
import com.bwssystems.HABridge.plugins.hal.HalHome;
import com.bwssystems.HABridge.plugins.harmony.HarmonyHome;
import com.bwssystems.HABridge.plugins.hass.HassHome;
import com.bwssystems.HABridge.plugins.homewizard.HomeWizardHome;
import com.bwssystems.HABridge.plugins.http.HTTPHome;
import com.bwssystems.HABridge.plugins.hue.HueHome;
import com.bwssystems.HABridge.plugins.lifx.LifxHome;
@@ -68,6 +69,10 @@ public class HomeManager {
aHome = new HassHome(bridgeSettings);
resourceList.put(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex], aHome);
// Setup the HomeWizard configuration if available
aHome = new HomeWizardHome(bridgeSettings);
resourceList.put(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex], aHome);
//setup the command execution Home
aHome = new CommandHome(bridgeSettings);
homeList.put(DeviceMapTypes.EXEC_DEVICE_COMPAT[DeviceMapTypes.typeIndex], aHome);
@@ -96,7 +101,7 @@ public class HomeManager {
aHome = new FibaroHome(bridgeSettings);
resourceList.put(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex], aHome);
resourceList.put(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex], aHome);
//setup the Domoticz configuration if available
//setup the Domoticz configuration if available
aHome = new DomoticzHome(bridgeSettings);
homeList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
resourceList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);

View File

@@ -8,6 +8,7 @@ import static spark.Spark.before;
import static spark.Spark.halt;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
@@ -16,11 +17,13 @@ import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Timer;
import java.util.Base64;
import java.util.Map;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
import com.bwssystems.HABridge.dao.BackupFilename;
import com.bwssystems.HABridge.util.JsonTransformer;
import com.bwssystems.HABridge.util.TextStringFormatter;
@@ -28,6 +31,7 @@ import com.bwssystems.logservices.LoggerInfo;
import com.bwssystems.logservices.LoggingForm;
import com.bwssystems.logservices.LoggingManager;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
@@ -295,6 +299,36 @@ public class SystemControl {
return bridgeSettings.getBridgeSecurity().getSecurityInfo();
}, new JsonTransformer());
// http://ip_address:port/system/whitelist gets the whitelist for the bridge
get (SYSTEM_CONTEXT + "/whitelist", (request, response) -> {
log.debug("Get whitelist");
response.status(HttpStatus.SC_OK);
response.type("application/json");
return bridgeSettings.getBridgeSecurity().getWhitelist();
}, new JsonTransformer());
// http://ip_address:port/system/setwhitelist CORS request
options(SYSTEM_CONTEXT + "/setwhitelist", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
// http://ip_address:port/system/setwhitelist which sets the whitelist after being managed
post(SYSTEM_CONTEXT + "/setwhitelist", (request, response) -> {
log.debug("setwhitelist....");
Type listType = new TypeToken<Map<String, WhitelistEntry>>() {
}.getType();
Map<String, WhitelistEntry> 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);

View File

@@ -291,6 +291,12 @@ public class DeviceResource {
return homeManager.findResource(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex]);
}, new JsonTransformer());
get (API_CONTEXT + "/homewizard/devices", "application/json", (request, response) -> {
log.debug("Get HomeWizard Clients");
response.status(HttpStatus.SC_OK);
return homeManager.findResource(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]);
}, new JsonTransformer());
get (API_CONTEXT + "/domoticz/devices", "application/json", (request, response) -> {
log.debug("Get Domoticz Clients");
response.status(HttpStatus.SC_OK);

View File

@@ -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<Integer> convertCIEtoRGB(List<Double> xy, int brightness) {
@@ -175,6 +179,26 @@ public class ColorDecode {
notDone = true;
}
if (request.contains(COLOR_RX)) {
request = request.replace(COLOR_RX, String.format("%02X", rgb.get(0)));
notDone = true;
}
if (request.contains(COLOR_GX)) {
request = request.replace(COLOR_GX, String.format("%02X", rgb.get(1)));
notDone = true;
}
if (request.contains(COLOR_BX)) {
request = request.replace(COLOR_BX, String.format("%02X", rgb.get(2)));
notDone = true;
}
if (request.contains(COLOR_RGBX)) {
request = request.replace(COLOR_RGBX, String.format("%02X%02X%02X", rgb.get(0), rgb.get(1), rgb.get(2)));
notDone = true;
}
Matcher m = COLOR_MILIGHT.matcher(request);
while (m.find()) {
int group = Integer.parseInt(m.group(1));

View File

@@ -76,10 +76,11 @@ public class HueMulator {
public void setupServer() {
log.info("Hue emulator service started....");
before(HUE_CONTEXT + "/*", (request, response) -> {
String path = request.pathInfo();
if (path.endsWith("/")) { // it should work with or without a trailing slash
response.redirect(path.substring(0, path.length() - 1));
}
// This currently causes an error with Spark replies
// String path = request.pathInfo();
// if (path.endsWith("/")) { // it should work with or without a trailing slash
// response.redirect(path.substring(0, path.length() - 1));
// }
log.debug("HueMulator " + request.requestMethod() + " called on api/* with request <<<" + request.pathInfo() + ">>>, and body <<<" + request.body() + ">>>");
if(bridgeSettingMaster.getBridgeSecurity().isSecure()) {
String pathInfo = request.pathInfo();
@@ -922,7 +923,7 @@ public class HueMulator {
toContinue = true;
if(toContinue) {
log.debug("hue api user create requested: " + body + " from " + ipAddress);
log.debug("user add toContinue was true, creating user.");
if (body != null && !body.isEmpty()) {
try {
@@ -938,6 +939,8 @@ public class HueMulator {
if (aDeviceType == null)
aDeviceType = "<not given>";
else
aDeviceType = aDeviceType + "#" + ipAddress;
if (newUser == null) {
newUser = bridgeSettingMaster.getBridgeSecurity().createWhitelistUser(aDeviceType);
@@ -1000,7 +1003,7 @@ public class HueMulator {
if (theErrors != null)
return theErrors;
if (Integer.parseInt(lightId) >= 10000) {
if (bridgeSettings.isUserooms() && Integer.parseInt(lightId) >= 10000) {
GroupDescriptor group = groupRepository.findOne(String.valueOf(Integer.parseInt(lightId) - 10000));
return DeviceResponse.createResponseForVirtualLight(group);
}
@@ -1084,7 +1087,7 @@ public class HueMulator {
}
private String changeState(String userId, String lightId, String body, String ipAddress, boolean ignoreRequester) {
if (Integer.parseInt(lightId) >= 10000) {
if (bridgeSettings.isUserooms() && Integer.parseInt(lightId) >= 10000) {
return changeGroupState(userId, String.valueOf(Integer.parseInt(lightId) - 10000), body, ipAddress, true);
}
String responseString = null;

View File

@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
public class TimeDecode {
private static final Logger log = LoggerFactory.getLogger(TimeDecode.class);
private static final String TIME_FORMAT = "${time.format(";
private static final String TIMESTAMP = "${time.millis}";
private static final String TIME_FORMAT_CLOSE = ")}";
/*
@@ -38,6 +39,10 @@ public class TimeDecode {
log.warn("Could not format current time: " + timeFormatDescriptor, e);
}
}
if (request.contains(TIMESTAMP)) {
request = request.replace(TIMESTAMP, String.valueOf(System.currentTimeMillis()));
notDone = true;
}
}
return request;
}

View File

@@ -1,5 +1,6 @@
package com.bwssystems.HABridge.plugins.exec;
import java.io.File;
import java.io.IOException;
import org.slf4j.Logger;
@@ -45,10 +46,7 @@ public class CommandHome implements Home {
intermediate = TimeDecode.replaceTimeValue(intermediate);
String execGarden = theSettings.getBridgeSecurity().getExecGarden();
if(execGarden != null && !execGarden.trim().isEmpty()) {
if(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)
intermediate = execGarden + "\\" + intermediate;
else
intermediate = execGarden + "/" + intermediate;
intermediate = new File(execGarden.trim(), intermediate).getAbsolutePath();
}
String anError = doExecRequest(intermediate, lightId);

View File

@@ -0,0 +1,150 @@
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<String, HomeWizzardSmartPlugInfo> 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<HomeWizardSmartPlugDevice> getDevices() {
log.debug("consolidating devices for plug gateways");
Iterator<String> keys = plugGateways.keySet().iterator();
ArrayList<HomeWizardSmartPlugDevice> 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<NamedIP> 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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,242 @@
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)
{
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");
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);
result = false;
}
}
else
{
result = false;
}
return result;
}
public List<HomeWizardSmartPlugDevice> getDevices()
{
List<HomeWizardSmartPlugDevice> 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) throws JSONException, IOException {
// 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();
}
// Send request to HomeWizard cloud
if (!sendAction("/" + cloudPlugId + "/devices/" + deviceId + "/action", action))
{
throw new IOException("Send action to HomeWizard Cloud failed.");
}
}
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;
}
}

View File

@@ -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;
}
}

View File

@@ -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) {
@@ -273,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)
@@ -314,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);
}
);
};
@@ -406,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;
}
@@ -504,11 +532,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 +569,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 +815,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;
@@ -1115,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
@@ -1468,6 +1530,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: [] };
@@ -1655,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;
@@ -1763,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);
};
@@ -2024,7 +2145,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) {
@@ -2037,7 +2158,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);
@@ -2894,6 +3015,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 +3952,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 = [];

View File

@@ -23,6 +23,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
@@ -38,6 +39,7 @@
<div class="form-group">
<button class="btn btn-primary" type="submit" ng-click="renumberDevices()">Renumber Devices</button>
<button ng-if="bridge.securityInfo.useLinkButton" class="btn btn-primary" type="submit" ng-click="pushLinkButton()">Link</button>
<button class="btn btn-primary" type="submit" ng-click="manageLinksButton()">Manage Links</button>
<label for="device-ip-filter">Show devices visible to: </label>
<input type="text" id="device-ip-filter" style="width:150px"
ng-model="bridge.state.filterDevicesByIpAddress" placeholder="">

View File

@@ -21,6 +21,7 @@
Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li role="presentation" class="active"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -23,6 +23,7 @@
href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a
href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -17,6 +17,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -17,6 +17,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -20,6 +20,7 @@
Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -21,6 +21,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -21,6 +21,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -19,6 +19,7 @@
href="#!/huedevices">Hue Devices</a></li>
<li ng-if="bridge.showHal" role="presentation"><a href="#!/haldevices">HAL
Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li role="presentation" class="active"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>

View File

@@ -0,0 +1,127 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#!/">Bridge Devices</a></li>
<li role="presentation"><a href="#!/system">Bridge Control</a></li>
<li role="presentation"><a href="#!/logs">Logs</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#!/harmonyactivities">Harmony Activities</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#!/harmonydevices">Harmony Devices</a></li>
<li ng-if="bridge.showNest" role="presentation"><a href="#!/nest">Nest</a></li>
<li ng-if="bridge.showHue" role="presentation"><a href="#!/huedevices">Hue Devices</a></li>
<li ng-if="bridge.showHal" role="presentation"><a href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation" class="active"><a href="#!/homewizarddevices">Somfy Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">HomeWizard Device List
({{bridge.homewizarddevices.length}})</h2>
</div>
<div class="panel-body">
<p class="text-muted">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.</p>
<p>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.</p>
</div>
<scrollable-table watch="bridge.homewizarddevices">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Row</th>
<th sortable-header col="name"><span><input type="checkbox" name="selectAll"
value="{{selectAll}}"
ng-checked="selectAll"
ng-click="toggleSelectAll()"> Name</span></th>
<th sortable-header col="id" comparator-fn="comparatorUniqueId">Id</th>
<th sortable-header col="type">Type</th>
<th>Build Actions</th>
</tr>
</thead>
<tr
ng-repeat="homewizarddevice in bridge.homewizarddevices">
<td>{{$index+1}}</td>
<td><input type="checkbox" name="bulk.devices[]"
value="{{homewizarddevice.id}}"
ng-checked="bulk.devices.indexOf(homewizarddevice.id) > -1"
ng-click="toggleSelection(homewizarddevice.id)">
{{homewizarddevice.name}}</td>
<td>{{homewizarddevice.id}}</td>
<td>{{homewizarddevice.typeName}}</td>
<td>
<!--TODO - taken device_dim_control out of here since not yet used-->
<button class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(homewizarddevice, false)">Build Item</button>
</td>
</tr>
</table>
</scrollable-table>
<div class="panel-footer">
<button class="btn btn-success" type="submit"
ng-click="bulkAddDevices()">Bulk Add
({{bulk.devices.length}})</button>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
Already Configured HomeWizard Devices <a ng-click="toggleButtons()"><span
class={{imgButtonsUrl}} aria-hidden="true"></span></a>
</h2>
</div>
<div ng-if="buttonsVisible" class="panel-body">
<scrollable-table watch="bridge.devices">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Row</th>
<th sortable-header col="name">Name</th>
<th sortable-header col="targetDevice">HomeWizard Gateway</th>
<th>Map Id</th>
<th>Actions</th>
</tr>
</thead>
<tr
ng-repeat="device in bridge.devices |configuredHomeWizardDevices">
<td>{{$index+1}}</td>
<td>{{device.name}}</td>
<td>{{device.targetDevice}}</td>
<td>{{device.mapId}}</td>
<td>
<p>
<button class="btn btn-warning" type="submit"
ng-click="editDevice(device)">Edit</button>
<button class="btn btn-danger" type="submit"
ng-click="deleteDevice(device)">Delete</button>
</p>
</td>
</tr>
</table>
</scrollable-table>
</div>
</div>
<script type="text/ng-template" id="deleteMapandIdDialog">
<div class="ngdialog-message">
<h2>Device Map and Id?</h2>
<p>{{mapandid.mapType}} with {{mapandid.id}}</p>
<p>Are you Sure?</p>
</div>
<div class="ngdialog-buttons mt">
<button type="button" class="ngdialog-button ngdialog-button-error" ng-click="deleteMapandId(mapandid)">Delete</button>
</div>
</script>

View File

@@ -21,6 +21,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -13,6 +13,7 @@
<li ng-if="bridge.showHal" role="presentation"><a href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li role="presentation" class="active"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -21,6 +21,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -0,0 +1,32 @@
<div class="form-container ngdialog-message" ng-controller="ManageLinksDialogCtrl">
<form name="manageLinksForm" role="form">
<legend class="form-label">Manage Links</legend>
<div>
<scrollable-table watch="whitelist">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Create Date</th>
<th>Manage</th>
</tr>
</thead>
<tr ng-repeat="linkItem in whitelist">
<td>{{linkItem.name}}</td>
<td>{{linkItem.createDate}}</td>
<td><button class="btn btn-danger" type="submit"
ng-click="delEntry(linkItem.name)">Del</button></td>
</tr>
</table>
</scrollable-table></td>
</div>
<div class="form-group">
<button type="button" class="btn btn-success" ng-click="dismissDialog()" autofocus>Dismiss</button>
<button type="button" class="btn btn-info" ng-click="refresh()" autofocus>Refresh</button>
<button type="button" class="btn btn-warning" ng-click="setWhitelist()" autofocus>Save</button>
<button type="button" class="btn btn-danger" ng-click="delAll()" autofocus>Clear All</button>
</div>
</form>
</div>

View File

@@ -13,6 +13,7 @@
<li ng-if="bridge.showHal" role="presentation"><a href="#!/haldevices">HAL Devices</a></li>
<li role="presentation" class="active"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -21,6 +21,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -17,6 +17,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation" class="active"><a href="#!/somfydevices">Somfy Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>

View File

@@ -22,6 +22,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
@@ -99,6 +100,12 @@
ng-model="bridge.settings.useupnpiface" ng-true-value=true
ng-false-value=false> {{bridge.settings.useupnpiface}}</td>
</tr>
<tr>
<td>Use Rooms for Alexa</td>
<td><input type="checkbox"
ng-model="bridge.settings.userooms" ng-true-value=true
ng-false-value=false> {{bridge.settings.userooms}}</td>
</tr>
<tr>
<td>Web Server IP Address</td>
<td><input id="bridge-settings-webaddress"
@@ -417,6 +424,53 @@
</tr>
</table></td>
</tr>
<tr>
<td>HomeWizard Gateways</td>
<td><table
class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>IP</th>
<th>Username</th>
<th>Password</th>
<th>Manage</th>
</tr>
</thead>
<tr ng-repeat="homewizard in bridge.settings.homewizardaddress.devices">
<td><input id="bridge-settings-next-homewizard-name"
class="form-control" type="text" ng-model="homewizard.name"
placeholder="A HomeWizard Gateway"></td>
<td><input id="bridge-settings-next-homewizard-ip"
class="form-control" type="text" ng-model="homewizard.ip"
placeholder="http://www.homewizard.nl"></td>
<td><input id="bridge-settings-next-homewizard-username"
class="form-control" type="text" ng-model="homewizard.username"
placeholder="HomeWizard username"></td>
<td><input id="bridge-settings-next-homewizard-password"
class="form-control" type="password" ng-model="homewizard.password"
placeholder="HomeWizard password"></td>
<td><button class="btn btn-danger" type="submit"
ng-click="removeHomeWizardtoSettings(homewizard.name, homewizard.ip)">Del</button></td>
</tr>
<tr>
<td><input id="bridge-settings-new-homewizard-name"
class="form-control" type="text" ng-model="newhomewizardname"
placeholder="A HomeWizard Gateway"></td>
<td><input id="bridge-settings-new-homewizard-ip"
class="form-control" type="text" ng-model="newhomewizardip"
placeholder="http://www.homewizard.nl"></td>
<td><input id="bridge-settings-new-homewizard-username"
class="form-control" type="text" ng-model="newhomewizardusername"
placeholder="HomeWizard username"></td>
<td><input id="bridge-settings-new-homewizard-password"
class="form-control" type="password" ng-model="newhomewizardpassword"
placeholder="HomeWizard password"></td>
<td><button class="btn btn-success" type="submit"
ng-click="addHomeWizardtoSettings(newhomewizardname, newhomewizardip, newhomewizardusername, newhomewizardpassword)">Add</button></td>
</tr>
</table></td>
</tr>
<tr>
<td>Domoticz Names and IP Addresses</td>
<td><table

View File

@@ -17,6 +17,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>

View File

@@ -17,6 +17,7 @@
href="#!/haldevices">HAL Devices</a></li>
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>