Merge pull request #499 from bwssytems/NewConnectors1

New connectors and fixes

Fixes #124 
Fixes #396 
Fixes #466 
Fixes #483 
Fixes #488
This commit is contained in:
BWS Systems
2017-02-25 10:31:58 -06:00
committed by GitHub
34 changed files with 1063 additions and 319 deletions

View File

@@ -33,23 +33,23 @@ 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-4.1.4.jar
java -jar ha-bridge-4.2.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-4.1.4.jar is in your /home/pi/habridge directory.
Create the directory and make sure that ha-bridge-4.2.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/v4.1.4/ha-bridge-4.1.4.jar
pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v4.2.0/ha-bridge-4.2.0.jar
```
Create the directory and make sure that ha-bridge-4.1.4.jar is in your /home/pi/habridge directory.
Create the directory and make sure that ha-bridge-4.2.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/v4.1.4/ha-bridge-4.1.4.jar
pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v4.2.0/ha-bridge-4.2.0.jar
```
#### System Control Setup on a pi (preferred)
For next gen Linux systems (this includes the Raspberry Pi), here is a systemctl unit file that you can install. Here is a link on how to do this: https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units
@@ -69,7 +69,7 @@ After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-4.1.4.jar
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-4.2.0.jar
[Install]
WantedBy=multi-user.target
@@ -104,7 +104,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-4.1.4.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-4.2.0.jar > /home/pi/habridge/habridge-log.txt 2>&1 &
chmod 777 /home/pi/habridge/habridge-log.txt
```

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId>
<version>4.1.4</version>
<version>4.2.0</version>
<packaging>jar</packaging>
<name>HA Bridge</name>
@@ -121,6 +121,11 @@
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>com.github.bwssytems</groupId>
<artifactId>lifx-sdk-java</artifactId>
<version>2.1.6</version>
</dependency>
</dependencies>
<build>

View File

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

View File

@@ -40,6 +40,7 @@ public class BridgeSettingsDescriptor {
private String hubversion;
private IpList domoticzaddress;
private boolean domoticzconfigured;
private boolean lifxconfigured;
public BridgeSettingsDescriptor() {
super();
@@ -263,6 +264,12 @@ public class BridgeSettingsDescriptor {
public void setDomoticzconfigured(boolean domoticzconfigured) {
this.domoticzconfigured = domoticzconfigured;
}
public boolean isLifxconfigured() {
return lifxconfigured;
}
public void setLifxconfigured(boolean lifxconfigured) {
this.lifxconfigured = lifxconfigured;
}
public Boolean isValidVera() {
if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0)
return false;
@@ -328,4 +335,7 @@ public class BridgeSettingsDescriptor {
return false;
return true;
}
public Boolean isValidLifx() {
return this.isLifxconfigured();
}
}

View File

@@ -26,6 +26,7 @@ public class DeviceMapTypes {
public final static String[] UDP_DEVICE_COMPAT = { "UDP", "UDP Device"};
public final static String[] HTTP_DEVICE = { "httpDevice", "HTTP Device"};
public final static String[] DOMOTICZ_DEVICE = { "domoticzDevice", "Domoticz Device"};
public final static String[] LIFX_DEVICE = { "lifxDevice", "LIFX Device"};
public final static int typeIndex = 0;
public final static int displayIndex = 1;
@@ -46,6 +47,7 @@ public class DeviceMapTypes {
deviceMapTypes.add(HASS_DEVICE);
deviceMapTypes.add(HTTP_DEVICE);
deviceMapTypes.add(HUE_DEVICE);
deviceMapTypes.add(LIFX_DEVICE);
deviceMapTypes.add(MQTT_MESSAGE);
deviceMapTypes.add(NEST_HOMEAWAY);
deviceMapTypes.add(NEST_THERMO_SET);

View File

@@ -13,6 +13,7 @@ import com.bwssystems.HABridge.plugins.harmony.HarmonyHome;
import com.bwssystems.HABridge.plugins.hass.HassHome;
import com.bwssystems.HABridge.plugins.http.HTTPHome;
import com.bwssystems.HABridge.plugins.hue.HueHome;
import com.bwssystems.HABridge.plugins.lifx.LifxHome;
import com.bwssystems.HABridge.plugins.mqtt.MQTTHome;
import com.bwssystems.HABridge.plugins.tcp.TCPHome;
import com.bwssystems.HABridge.plugins.udp.UDPHome;
@@ -71,7 +72,6 @@ public class HomeManager {
homeList.put(DeviceMapTypes.CUSTOM_DEVICE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
//setup the tcp handler Home
aHome = new TCPHome(bridgeSettings);
homeList.put(DeviceMapTypes.TCP_DEVICE[DeviceMapTypes.typeIndex], aHome);
@@ -80,13 +80,18 @@ public class HomeManager {
aHome = new UDPHome(bridgeSettings, aUdpDatagramSender);
homeList.put(DeviceMapTypes.UDP_DEVICE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.UDP_DEVICE_COMPAT[DeviceMapTypes.typeIndex], aHome);
// Setup Vera Home if available
aHome = new VeraHome(bridgeSettings);
resourceList.put(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex], aHome);
resourceList.put(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex], aHome);
//setup the HomeAssistant 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);
//setup the Lifx configuration if available
aHome = new LifxHome(bridgeSettings);
resourceList.put(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex], aHome);
}
public Home findHome(String type) {

View File

@@ -219,6 +219,12 @@ public class DeviceResource {
return homeManager.findResource(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex]);
}, new JsonTransformer());
get (API_CONTEXT + "/lifx/devices", "application/json", (request, response) -> {
log.debug("Get LIFX devices");
response.status(HttpStatus.SC_OK);
return homeManager.findResource(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex]);
}, new JsonTransformer());
get (API_CONTEXT + "/map/types", "application/json", (request, response) -> {
log.debug("Get map types");
return new DeviceMapTypes().getDeviceMapTypes();

View File

@@ -1,15 +1,10 @@
package com.bwssystems.HABridge.hue;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.DatatypeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.java.dev.eval.Expression;
public class BrightnessDecode {
@@ -49,9 +44,7 @@ public class BrightnessDecode {
}
if (request.contains(INTENSITY_BYTE)) {
if (isHex) {
BigInteger bigInt = BigInteger.valueOf(intensity);
byte[] theBytes = bigInt.toByteArray();
String hexValue = DatatypeConverter.printHexBinary(theBytes);
String hexValue = Integer.toHexString(intensity);
request = request.replace(INTENSITY_BYTE, hexValue);
} else {
String intensityByte = String.valueOf(intensity);
@@ -60,9 +53,7 @@ public class BrightnessDecode {
} else if (request.contains(INTENSITY_PERCENT)) {
int percentBrightness = (int) Math.round(intensity / 255.0 * 100);
if (isHex) {
BigInteger bigInt = BigInteger.valueOf(percentBrightness);
byte[] theBytes = bigInt.toByteArray();
String hexValue = DatatypeConverter.printHexBinary(theBytes);
String hexValue = Integer.toHexString(percentBrightness);
request = request.replace(INTENSITY_PERCENT, hexValue);
} else {
String intensityPercent = String.valueOf(percentBrightness);
@@ -81,9 +72,7 @@ public class BrightnessDecode {
BigDecimal result = exp.eval(variables);
Integer endResult = Math.round(result.floatValue());
if (isHex) {
BigInteger bigInt = BigInteger.valueOf(endResult);
byte[] theBytes = bigInt.toByteArray();
String hexValue = DatatypeConverter.printHexBinary(theBytes);
String hexValue = Integer.toHexString(endResult);
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE, hexValue);
} else {
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE,

View File

@@ -16,7 +16,6 @@ import com.bwssystems.HABridge.api.hue.HuePublicConfig;
import com.bwssystems.HABridge.api.hue.StateChangeBody;
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
import com.bwssystems.HABridge.dao.*;
import com.bwssystems.HABridge.plugins.hue.HueDeviceIdentifier;
import com.bwssystems.HABridge.plugins.hue.HueHome;
import com.bwssystems.HABridge.util.JsonTransformer;
import com.google.gson.Gson;

View File

@@ -3,11 +3,12 @@ package com.bwssystems.HABridge.plugins.domoticz;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.HABridge.api.NameValue;
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
import com.google.gson.Gson;
@@ -16,32 +17,33 @@ public class DomoticzHandler {
private static final String GET_REQUEST = "/json.htm?type=";
private static final String DEVICES_TYPE = "devices";
private static final String SCENES_TYPE = "scenes";
private static final String FILTER_USED = "&used=";
private HTTPHandler httpClient;
private static final String FILTER_USED = "&used=true";
private NamedIP domoticzAddress;
public DomoticzHandler(NamedIP addressName) {
super();
httpClient = new HTTPHandler();
domoticzAddress = addressName;
}
public List<DomoticzDevice> getDevices() {
return getDomoticzDevices(GET_REQUEST, DEVICES_TYPE, FILTER_USED);
public List<DomoticzDevice> getDevices(HTTPHandler httpClient) {
return getDomoticzDevices(GET_REQUEST, DEVICES_TYPE, FILTER_USED, httpClient);
}
public List<DomoticzDevice> getScenes() {
return getDomoticzDevices(GET_REQUEST, SCENES_TYPE, null);
public List<DomoticzDevice> getScenes(HTTPHandler httpClient) {
return getDomoticzDevices(GET_REQUEST, SCENES_TYPE, null, httpClient);
}
private List<DomoticzDevice> getDomoticzDevices(String rootRequest, String type, String postpend) {
private List<DomoticzDevice> getDomoticzDevices(String rootRequest, String type, String postpend, HTTPHandler httpClient) {
Devices theDomoticzApiResponse = null;
List<DomoticzDevice> deviceList = null;
String theUrl = null;
String theData;
theUrl = "http://" + domoticzAddress.getIp() + ":" + domoticzAddress.getPort() + rootRequest + type;
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
if(postpend != null && !postpend.isEmpty())
theUrl = buildUrl(rootRequest + type + postpend);
else
theUrl = buildUrl(rootRequest + type);
theData = httpClient.doHttpRequest(theUrl, null, null, null, buildHeaders());
if(theData != null) {
log.debug("GET " + type + " DomoticzApiResponse - data: " + theData);
theDomoticzApiResponse = new Gson().fromJson(theData, Devices.class);
@@ -70,6 +72,44 @@ public class DomoticzHandler {
return deviceList;
}
public String buildUrl(String thePayload) {
String newUrl = null;
if(thePayload != null && !thePayload.isEmpty()) {
if(domoticzAddress.getSecure() != null && domoticzAddress.getSecure())
newUrl = "https://";
else
newUrl = "http://";
newUrl = newUrl + domoticzAddress.getIp();
if(domoticzAddress.getPort() != null && !domoticzAddress.getPort().isEmpty())
newUrl = newUrl + ":" + domoticzAddress.getPort();
if(thePayload.startsWith("/"))
newUrl = newUrl + thePayload;
else
newUrl = newUrl + "/" + thePayload;
}
return newUrl;
}
public NameValue[] buildHeaders() {
NameValue[] headers = null;
if(domoticzAddress.getUsername() != null && !domoticzAddress.getUsername().isEmpty()
&& domoticzAddress.getPassword() != null && !domoticzAddress.getPassword().isEmpty()) {
NameValue theAuth = new NameValue();
theAuth.setName("Authorization");
String encoding = Base64.getEncoder().encodeToString((domoticzAddress.getUsername() + ":" + domoticzAddress.getPassword()).getBytes());
theAuth.setValue("Basic " + encoding);
headers = new NameValue[1];
headers[0] = theAuth;
}
return headers;
}
public NamedIP getDomoticzAddress() {
return domoticzAddress;
}

View File

@@ -13,13 +13,19 @@ import com.bwssystems.HABridge.BridgeSettingsDescriptor;
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.MultiCommandUtil;
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
import com.google.gson.Gson;
public class DomoticzHome implements Home {
private static final Logger log = LoggerFactory.getLogger(DomoticzHome.class);
private Map<String, DomoticzHandler> domoticzs;
private Boolean validDomoticz;
private HTTPHandler httpClient;
public DomoticzHome(BridgeSettingsDescriptor bridgeSettings) {
super();
@@ -36,14 +42,14 @@ public class DomoticzHome implements Home {
List<DomoticzDevice> deviceList = new ArrayList<DomoticzDevice>();
while(keys.hasNext()) {
String key = keys.next();
theResponse = domoticzs.get(key).getDevices();
theResponse = domoticzs.get(key).getDevices(httpClient);
if(theResponse != null)
addDomoticzDevices(deviceList, theResponse, key);
else {
log.warn("Cannot get lights for Domoticz with name: " + key + ", skipping this Domoticz.");
continue;
}
theResponse = domoticzs.get(key).getScenes();
theResponse = domoticzs.get(key).getScenes(httpClient);
if(theResponse != null)
addDomoticzDevices(deviceList, theResponse, key);
else
@@ -66,8 +72,54 @@ public class DomoticzHome implements Home {
@Override
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
// Not a device handler
return null;
Devices theDomoticzApiResponse = null;
String responseString = null;
String theUrl = anItem.getItem().getAsString();
if(theUrl != null && !theUrl.isEmpty () && (theUrl.startsWith("http://") || theUrl.startsWith("https://"))) {
String intermediate = theUrl.substring(theUrl.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;
DomoticzHandler theHandler = findHandlerByAddress(hostAddr);
if(theHandler != null){
String theData;
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody,
intensity, targetBri, targetBriInc, false);
theData = httpClient.doHttpRequest(theHandler.buildUrl(anUrl), null, null, null, theHandler.buildHeaders());
try {
theDomoticzApiResponse = new Gson().fromJson(theData, Devices.class);
if(theDomoticzApiResponse.getStatus().equals("OK"))
responseString = null;
else {
log.warn("Call failed for Domoticz " + theHandler.getDomoticzAddress().getName() + " with status " + theDomoticzApiResponse.getStatus() + " for item " + theDomoticzApiResponse.getTitle());
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 interrpret result from call for Domoticz " + theHandler.getDomoticzAddress().getName() + " as response is not parsable.");
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("Domoticz 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("Domoticz Call to be presented as http(s)://<ip_address>(:<port>)/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
@@ -76,6 +128,7 @@ public class DomoticzHome implements Home {
log.info("Domoticz Home created." + (validDomoticz ? "" : " No Domoticz devices configured."));
if(!validDomoticz)
return null;
httpClient = new HTTPHandler();
domoticzs = new HashMap<String, DomoticzHandler>();
Iterator<NamedIP> theList = bridgeSettings.getDomoticzaddress().getDevices().iterator();
while(theList.hasNext()) {
@@ -90,9 +143,25 @@ public class DomoticzHome implements Home {
return this;
}
private DomoticzHandler findHandlerByAddress(String hostAddress) {
DomoticzHandler aHandler = null;
boolean found = false;
Iterator<String> keys = domoticzs.keySet().iterator();
while(keys.hasNext()) {
String key = keys.next();
aHandler = domoticzs.get(key);
if(aHandler != null && aHandler.getDomoticzAddress().getIp().equals(hostAddress)) {
found = true;
break;
}
}
if(!found)
aHandler = null;
return aHandler;
}
@Override
public void closeHome() {
// noop
httpClient.closeHandler();
}
}

View File

@@ -4,6 +4,7 @@ import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
@@ -11,20 +12,20 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,23 +34,23 @@ import com.bwssystems.HABridge.api.NameValue;
public class HTTPHandler {
private static final Logger log = LoggerFactory.getLogger(HTTPHandler.class);
private HttpClient httpClient;
// private CloseableHttpClient httpclientSSL;
// private HttpClient httpClient;
private CloseableHttpClient httpClient;
// private SSLContext sslcontext;
// private SSLConnectionSocketFactory sslsf;
// private RequestConfig globalConfig;
private RequestConfig globalConfig;
public HTTPHandler() {
httpClient = HttpClients.createDefault();
// httpClient = HttpClients.createDefault();
// Removed Specific SSL as Apache HttpClient automatically uses SSL if the URI starts with https://
// Trust own CA and all self-signed certs
// sslcontext = SSLContexts.createDefault();
// Allow TLSv1 protocol only
// sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLS" }, null,
// SSLConnectionSocketFactory.getDefaultHostnameVerifier());
// globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
// httpclientSSL = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(globalConfig).build();
globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
httpClient = HttpClients.custom().setDefaultRequestConfig(globalConfig).build();
}
@@ -125,8 +126,16 @@ public class HTTPHandler {
+ e.getMessage(), e);
}
}
if (theContent == null)
theContent = "";
} else {
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: " + response.getStatusLine());
try {
EntityUtils.consume(response.getEntity()); // close out
// inputstream
// ignore
// content
} catch (Exception e) {
//noop
}
}
} catch (IOException e) {
log.warn("Error calling out to HA gateway: IOException in log", e);
@@ -134,23 +143,22 @@ public class HTTPHandler {
return theContent;
}
public HttpClient getHttpClient() {
// public HttpClient getHttpClient() {
// return httpClient;
// }
public CloseableHttpClient getHttpClient() {
return httpClient;
}
// public CloseableHttpClient getHttpclientSSL() {
// return httpclientSSL;
// }
public void closeHandler() {
try {
httpClient.close();
} catch (IOException e) {
// noop
}
httpClient = null;
// try {
// httpclientSSL.close();
// } catch (IOException e) {
// // noop
// }
// httpclientSSL = null;
}
}

View File

@@ -29,23 +29,25 @@ public class HTTPHome implements Home {
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
String responseString = null;
//Backwards Compatibility Items
if(anItem.getHttpVerb() == null || anItem.getHttpVerb().isEmpty())
{
if(device.getHttpVerb() != null && !device.getHttpVerb().isEmpty())
anItem.setHttpVerb(device.getHttpVerb());
}
String theUrl = anItem.getItem().getAsString();
if(theUrl != null && !theUrl.isEmpty () && (theUrl.startsWith("http://") || theUrl.startsWith("https://"))) {
//Backwards Compatibility Items
if(anItem.getHttpVerb() == null || anItem.getHttpVerb().isEmpty())
{
if(device.getHttpVerb() != null && !device.getHttpVerb().isEmpty())
anItem.setHttpVerb(device.getHttpVerb());
}
if(anItem.getHttpHeaders() == null || anItem.getHttpHeaders().isEmpty()) {
if(device.getHeaders() != null && !device.getHeaders().isEmpty() )
anItem.setHttpHeaders(device.getHeaders());
}
log.debug("executing HUE api request to Http "
+ (anItem.getHttpVerb() == null ? "GET" : anItem.getHttpVerb()) + ": "
+ anItem.getItem().getAsString());
if(anItem.getHttpHeaders() == null || anItem.getHttpHeaders().isEmpty()) {
if(device.getHeaders() != null && !device.getHeaders().isEmpty() )
anItem.setHttpHeaders(device.getHeaders());
}
log.debug("executing HUE api request to Http "
+ (anItem.getHttpVerb() == null ? "GET" : anItem.getHttpVerb()) + ": "
+ anItem.getItem().getAsString());
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(anItem.getItem().getAsString(),
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrl,
intensity, targetBri, targetBriInc, false);
anUrl = TimeDecode.replaceTimeValue(anUrl);
@@ -63,6 +65,13 @@ public class HTTPHome implements Home {
"Error on calling url to change device state", "/lights/"
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
}
} else {
log.warn("HTTP Call to be presented as http(s)://<ip_address>(:<port>)/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;
}

View File

@@ -0,0 +1,49 @@
package com.bwssystems.HABridge.plugins.lifx;
import com.github.besherman.lifx.LFXGroup;
import com.github.besherman.lifx.LFXLight;
public class LifxDevice {
private Object lifxObject;
private String type;
public final static String LIGHT_TYPE = "Light";
public final static String GROUP_TYPE = "Group";
public LifxDevice(Object lifxObject, String type) {
super();
this.lifxObject = lifxObject;
this.type = type;
}
public LifxEntry toEntry() {
LifxEntry anEntry = null;
if(type.equals(LIGHT_TYPE)) {
anEntry = new LifxEntry();
anEntry.setId(((LFXLight)lifxObject).getID());
anEntry.setName(((LFXLight)lifxObject).getLabel());
anEntry.setType(LIGHT_TYPE);
}
if(type.equals(GROUP_TYPE)) {
anEntry = new LifxEntry();
anEntry.setId("na");
anEntry.setName(((LFXGroup)lifxObject).getLabel());
anEntry.setType(GROUP_TYPE);
}
return anEntry;
}
public Object getLifxObject() {
return lifxObject;
}
public void setLifxObject(Object lifxObject) {
this.lifxObject = lifxObject;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

View File

@@ -0,0 +1,25 @@
package com.bwssystems.HABridge.plugins.lifx;
public class LifxEntry {
private String name;
private String id;
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

View File

@@ -0,0 +1,257 @@
package com.bwssystems.HABridge.plugins.lifx;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
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.BridgeSettingsDescriptor;
import com.bwssystems.HABridge.Home;
import com.bwssystems.HABridge.api.CallItem;
import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.bwssystems.HABridge.hue.BrightnessDecode;
import com.bwssystems.HABridge.hue.MultiCommandUtil;
import com.github.besherman.lifx.LFXClient;
import com.github.besherman.lifx.LFXGroup;
import com.github.besherman.lifx.LFXGroupCollection;
import com.github.besherman.lifx.LFXGroupCollectionListener;
import com.github.besherman.lifx.LFXLight;
import com.github.besherman.lifx.LFXLightCollection;
import com.github.besherman.lifx.LFXLightCollectionListener;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class LifxHome implements Home {
private static final Logger log = LoggerFactory.getLogger(LifxHome.class);
private static final float DIM_DIVISOR = (float)254.00;
private Map<String, LifxDevice> lifxMap;
private LFXClient client;
private Boolean validLifx;
private Gson aGsonHandler;
public LifxHome(BridgeSettingsDescriptor bridgeSettings) {
super();
createHome(bridgeSettings);
}
@Override
public Home createHome(BridgeSettingsDescriptor bridgeSettings) {
lifxMap = null;
aGsonHandler = null;
validLifx = bridgeSettings.isValidLifx();
log.info("LifxDevice Home created." + (validLifx ? "" : " No LifxDevices configured."));
if(validLifx) {
try {
log.info("Open Lifx client....");
InetAddress configuredAddress = InetAddress.getByName(bridgeSettings.getUpnpConfigAddress());
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(configuredAddress);
InetAddress bcastInetAddr = null;
if (networkInterface != null) {
for (InterfaceAddress ifaceAddr : networkInterface.getInterfaceAddresses()) {
InetAddress addr = ifaceAddr.getAddress();
if (addr instanceof Inet4Address) {
bcastInetAddr = ifaceAddr.getBroadcast();
break;
}
}
}
if(bcastInetAddr != null) {
lifxMap = new HashMap<String, LifxDevice>();
log.info("Opening LFX Client with broadcast address: " + bcastInetAddr.getHostAddress());
client = new LFXClient(bcastInetAddr.getHostAddress());
client.getLights().addLightCollectionListener(new MyLightListener(lifxMap));
client.getGroups().addGroupCollectionListener(new MyGroupListener(lifxMap));
client.open(false);
aGsonHandler =
new GsonBuilder()
.create();
} else {
log.warn("Could not open LIFX, no bcast addr available, check your upnp config address.");
client = null;
validLifx = false;
return this;
}
} catch (IOException e) {
log.warn("Could not open LIFX, with IO Exception", e);
client = null;
validLifx = false;
return this;
} catch (InterruptedException e) {
log.warn("Could not open LIFX, with Interruprted Exception", e);
client = null;
validLifx = false;
return this;
}
}
return this;
}
public LifxDevice getLifxDevice(String aName) {
if(!validLifx)
return null;
LifxDevice aLifxDevice = null;
if(aName == null || aName.equals("")) {
log.debug("Cannot get LifxDevice for name as it is empty.");
}
else {
aLifxDevice = lifxMap.get(aName);
log.debug("Retrieved a LifxDevice for name: " + aName);
}
return aLifxDevice;
}
@Override
public Object getItems(String type) {
log.debug("consolidating devices for lifx");
if(!validLifx)
return null;
LifxEntry theResponse = null;
Iterator<String> keys = lifxMap.keySet().iterator();
List<LifxEntry> deviceList = new ArrayList<LifxEntry>();
while(keys.hasNext()) {
String key = keys.next();
theResponse = lifxMap.get(key).toEntry();
if(theResponse != null)
deviceList.add(theResponse);
else {
log.warn("Cannot get LifxDevice with name: " + key + ", skipping this Lifx.");
continue;
}
}
return deviceList;
}
private Boolean addLifxLights(LFXLightCollection theDeviceList) {
if(!validLifx)
return false;
Iterator<LFXLight> devices = theDeviceList.iterator();;
while(devices.hasNext()) {
LFXLight theDevice = devices.next();
LifxDevice aNewLifxDevice = new LifxDevice(theDevice, LifxDevice.LIGHT_TYPE);
lifxMap.put(aNewLifxDevice.toEntry().getName(), aNewLifxDevice);
}
return true;
}
private Boolean addLifxGroups(LFXGroupCollection theDeviceList) {
if(!validLifx)
return false;
Iterator<LFXGroup> devices = theDeviceList.iterator();;
while(devices.hasNext()) {
LFXGroup theDevice = devices.next();
LifxDevice aNewLifxDevice = new LifxDevice(theDevice, LifxDevice.GROUP_TYPE);
lifxMap.put(aNewLifxDevice.toEntry().getName(), aNewLifxDevice);
}
return true;
}
@Override
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
String theReturn = null;
float aBriValue;
float theValue;
log.debug("executing HUE api request to send message to LifxDevice: " + anItem.getItem().toString());
if(!validLifx) {
log.warn("Should not get here, no LifxDevice clients configured");
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
+ "\",\"description\": \"Should not get here, no LifxDevices configured\", \"parameter\": \"/lights/"
+ lightId + "state\"}}]";
} else {
LifxEntry lifxCommand = null;
if(anItem.getItem().isJsonObject())
lifxCommand = aGsonHandler.fromJson(anItem.getItem(), LifxEntry.class);
else
lifxCommand = aGsonHandler.fromJson(anItem.getItem().getAsString(), LifxEntry.class);
LifxDevice theDevice = getLifxDevice(lifxCommand.getName());
if (theDevice == null) {
log.warn("Should not get here, no LifxDevices available");
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
+ "\",\"description\": \"Should not get here, no Lifx clients available\", \"parameter\": \"/lights/"
+ lightId + "state\"}}]";
} else {
log.debug("calling LifxDevice: " + lifxCommand.getName());
if(theDevice.getType().equals(LifxDevice.LIGHT_TYPE)) {
LFXLight theLight = (LFXLight)theDevice.getLifxObject();
if(body.contains("true"))
theLight.setPower(true);
if(body.contains("false"))
theLight.setPower(false);
if(targetBri != null || targetBriInc != null) {
aBriValue = (float)BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc);
theValue = aBriValue/DIM_DIVISOR;
if(theValue > (float)1.0)
theValue = (float)0.99;
theLight.setBrightness(theValue);
}
} else if (theDevice.getType().equals(LifxDevice.GROUP_TYPE)) {
LFXGroup theGroup = (LFXGroup)theDevice.getLifxObject();
if(body.contains("true"))
theGroup.setPower(true);
if(body.contains("false"))
theGroup.setPower(false);
}
}
}
return theReturn;
}
@Override
public void closeHome() {
if(!validLifx)
return;
client.close();
}
private static class MyLightListener implements LFXLightCollectionListener {
private static final Logger log = LoggerFactory.getLogger(MyLightListener.class);
private Map<String, LifxDevice> aLifxMap;
public MyLightListener(Map<String, LifxDevice> theMap) {
aLifxMap = theMap;
}
@Override
public void lightAdded(LFXLight light) {
log.debug("Light added, label: " + light.getLabel() + " and id: " + light.getID());
LifxDevice aNewLifxDevice = new LifxDevice(light, LifxDevice.LIGHT_TYPE);
aLifxMap.put(aNewLifxDevice.toEntry().getName(), aNewLifxDevice);
}
@Override
public void lightRemoved(LFXLight light) {
log.debug("Light removed, label: " + light.getLabel() + " and id: " + light.getID());
aLifxMap.remove(light.getLabel());
}
}
private static class MyGroupListener implements LFXGroupCollectionListener {
private static final Logger log = LoggerFactory.getLogger(MyLightListener.class);
private Map<String, LifxDevice> aLifxMap;
public MyGroupListener(Map<String, LifxDevice> theMap) {
aLifxMap = theMap;
}
@Override
public void groupAdded(LFXGroup group) {
log.debug("Group: " + group.getLabel() + " added: " + group.size());
LifxDevice aNewLifxDevice = new LifxDevice(group, LifxDevice.GROUP_TYPE);
aLifxMap.put(aNewLifxDevice.toEntry().getName(), aNewLifxDevice);
}
@Override
public void groupRemoved(LFXGroup group) {
log.debug("Group: " + group.getLabel() + " removed");
aLifxMap.remove(group.getLabel());
}
}
}

View File

@@ -32,41 +32,45 @@ public class TCPHome implements Home {
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
log.debug("executing HUE api request to TCP: " + anItem.getItem().getAsString());
String intermediate = anItem.getItem().getAsString().substring(anItem.getItem().getAsString().indexOf("://") + 3);
String hostPortion = intermediate.substring(0, intermediate.indexOf('/'));
String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1);
String hostAddr = null;
String port = null;
InetAddress IPAddress = null;
if (hostPortion.contains(":")) {
hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
port = hostPortion.substring(intermediate.indexOf(':') + 1);
String theUrl = anItem.getItem().getAsString();
if(theUrl != null && !theUrl.isEmpty () && theUrl.startsWith("tcp://")) {
String intermediate = theUrl.substring(theUrl.indexOf("://") + 3);
String hostPortion = intermediate.substring(0, intermediate.indexOf('/'));
String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1);
String hostAddr = null;
String port = null;
InetAddress IPAddress = null;
if (hostPortion.contains(":")) {
hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
port = hostPortion.substring(intermediate.indexOf(':') + 1);
} else
hostAddr = hostPortion;
try {
IPAddress = InetAddress.getByName(hostAddr);
} catch (UnknownHostException e) {
// noop
}
theUrlBody = TimeDecode.replaceTimeValue(theUrlBody);
if (theUrlBody.startsWith("0x")) {
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, true);
sendData = DatatypeConverter.parseHexBinary(theUrlBody.substring(2));
} else {
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false);
sendData = theUrlBody.getBytes();
}
try {
Socket dataSendSocket = new Socket(IPAddress, Integer.parseInt(port));
DataOutputStream outToClient = new DataOutputStream(dataSendSocket.getOutputStream());
outToClient.write(sendData);
outToClient.flush();
dataSendSocket.close();
} catch (Exception e) {
// noop
}
} else
hostAddr = hostPortion;
try {
IPAddress = InetAddress.getByName(hostAddr);
} catch (UnknownHostException e) {
// noop
}
theUrlBody = TimeDecode.replaceTimeValue(theUrlBody);
if (theUrlBody.startsWith("0x")) {
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, true);
sendData = DatatypeConverter.parseHexBinary(theUrlBody.substring(2));
} else {
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false);
sendData = theUrlBody.getBytes();
}
try {
Socket dataSendSocket = new Socket(IPAddress, Integer.parseInt(port));
DataOutputStream outToClient = new DataOutputStream(dataSendSocket.getOutputStream());
outToClient.write(sendData);
outToClient.flush();
dataSendSocket.close();
} catch (Exception e) {
// noop
}
log.warn("Tcp Call to be presented as tcp://<ip_address>:<port>/payload, format of request unknown: " + theUrl);
return null;
}

View File

@@ -33,39 +33,44 @@ public class UDPHome implements Home {
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
log.debug("executing HUE api request to UDP: " + anItem.getItem().getAsString());
String intermediate = anItem.getItem().getAsString().substring(anItem.getItem().getAsString().indexOf("://") + 3);
String hostPortion = intermediate.substring(0, intermediate.indexOf('/'));
String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1);
String hostAddr = null;
String port = null;
InetAddress IPAddress = null;
if (hostPortion.contains(":")) {
hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
port = hostPortion.substring(intermediate.indexOf(':') + 1);
String theUrl = anItem.getItem().getAsString();
if(theUrl != null && !theUrl.isEmpty () && theUrl.startsWith("udp://")) {
String intermediate = theUrl.substring(theUrl.indexOf("://") + 3);
String hostPortion = intermediate.substring(0, intermediate.indexOf('/'));
String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1);
String hostAddr = null;
String port = null;
InetAddress IPAddress = null;
if (hostPortion.contains(":")) {
hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
port = hostPortion.substring(intermediate.indexOf(':') + 1);
} else
hostAddr = hostPortion;
try {
IPAddress = InetAddress.getByName(hostAddr);
} catch (UnknownHostException e) {
log.warn("Udp Call, unknown host, continuing...");
return null;
}
theUrlBody = TimeDecode.replaceTimeValue(theUrlBody);
if (theUrlBody.startsWith("0x")) {
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, true);
sendData = DatatypeConverter.parseHexBinary(theUrlBody.substring(2));
} else {
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false);
sendData = theUrlBody.getBytes();
}
try {
theUDPDatagramSender.sendUDPResponse(sendData, IPAddress, Integer.parseInt(port));
} catch (NumberFormatException e) {
log.warn("Udp Call, Number format exception on port, continuing...");
} catch (IOException e) {
log.warn("IO exception on udp call, continuing...");
}
} else
hostAddr = hostPortion;
try {
IPAddress = InetAddress.getByName(hostAddr);
} catch (UnknownHostException e) {
log.warn("Udp Call, unknown host, continuing...");
return null;
}
log.warn("Udp Call to be presented as udp://<ip_address>:<port>/payload, format of request unknown: " + theUrl);
theUrlBody = TimeDecode.replaceTimeValue(theUrlBody);
if (theUrlBody.startsWith("0x")) {
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, true);
sendData = DatatypeConverter.parseHexBinary(theUrlBody.substring(2));
} else {
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false);
sendData = theUrlBody.getBytes();
}
try {
theUDPDatagramSender.sendUDPResponse(sendData, IPAddress, Integer.parseInt(port));
} catch (NumberFormatException e) {
log.warn("Udp Call, Number format exception on port, continuing...");
} catch (IOException e) {
log.warn("IO exception on udp call, continuing...");
}
return null;
}

View File

@@ -45,6 +45,9 @@ app.config (function ($locationProvider, $routeProvider) {
}).when ('/domoticzdevices', {
templateUrl: 'views/domoticzdevice.html',
controller: 'DomoticzController'
}).when ('/lifxdevices', {
templateUrl: 'views/lifxdevice.html',
controller: 'LifxController'
}).otherwise ({
templateUrl: 'views/configuration.html',
controller: 'ViewingController'
@@ -71,7 +74,7 @@ String.prototype.replaceAll = function (search, replace)
app.service ('bridgeService', function ($http, $window, ngToast) {
var self = this;
this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: {}, mapandid: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], mapTypes: [], olddevicename: "", logShowAll: false, isInControl: false, showVera: false, showHarmony: false, showNest: false, showHue: false, showHal: false, showMqtt: false, showHass: false, showDomoticz: false, habridgeversion: ""};
this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: {}, mapandid: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], mapTypes: [], olddevicename: "", logShowAll: false, isInControl: false, showVera: false, showHarmony: false, showNest: false, showHue: false, showHal: false, showMqtt: false, showHass: false, showDomoticz: false, showLifx: false, habridgeversion: ""};
this.displayWarn = function(errorTitle, error) {
var toastContent = errorTitle;
@@ -257,6 +260,11 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
return;
}
this.updateShowLifx = function () {
this.state.showLifx = self.state.settings.lifxconfigured;
return;
}
this.loadBridgeSettings = function () {
return $http.get(this.state.systemsbase + "/settings").then(
function (response) {
@@ -269,6 +277,7 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
self.updateShowMqtt();
self.updateShowHass();
self.updateShowDomoticz();
self.updateShowLifx();
},
function (error) {
self.displayWarn("Load Bridge Settings Error: ", error);
@@ -450,6 +459,19 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
);
};
this.viewLifxDevices = function () {
if (!this.state.showLifx)
return;
return $http.get(this.state.base + "/lifx/devices").then(
function (response) {
self.state.lifxdevices = response.data;
},
function (error) {
self.displayWarn("Get Lifx Devices Error: ", error);
}
);
};
this.formatCallItem = function (currentItem) {
if(!currentItem.startsWith("{\"item") && !currentItem.startsWith("[{\"item")) {
if (currentItem.startsWith("[") || currentItem.startsWith("{"))
@@ -1205,7 +1227,7 @@ app.controller('VeraController', function ($scope, $location, $http, bridgeServi
$scope.device = bridgeService.state.device;
};
$scope.buildDeviceUrls = function (veradevice, dim_control) {
$scope.buildDeviceUrls = function (veradevice, dim_control, buildonly) {
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0) {
dimpayload = "http://" + veradevice.veraaddress + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&DeviceNum="
@@ -1226,8 +1248,10 @@ app.controller('VeraController', function ($scope, $location, $http, bridgeServi
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, veradevice.id, veradevice.name, veradevice.veraname, "switch", "veraDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.buildSceneUrls = function (verascene) {
@@ -1246,10 +1270,11 @@ app.controller('VeraController', function ($scope, $location, $http, bridgeServi
$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.veradevices.length; x++) {
if(bridgeService.state.veradevices[x].id === $scope.bulk.devices[i]) {
$scope.buildDeviceUrls(bridgeService.state.veradevices[x],dim_control);
$scope.buildDeviceUrls(bridgeService.state.veradevices[x],dim_control,true);
devicesList[i] = {
name: $scope.device.name,
mapId: $scope.device.mapId,
@@ -1266,6 +1291,7 @@ app.controller('VeraController', function ($scope, $location, $http, bridgeServi
contentBodyDim: $scope.device.contentBodyDim,
contentBodyOff: $scope.device.contentBodyOff
};
$scope.clearDevice();
}
}
}
@@ -1309,7 +1335,7 @@ app.controller('VeraController', function ($scope, $location, $http, bridgeServi
else {
$scope.selectAll = true;
for(var x = 0; x < bridgeService.state.veradevices.length; x++) {
if($scope.bulk.devices.indexOf(bridgeService.state.veradevices[x]) < 0 && !bridgeService.findDeviceByMapId(bridgeService.state.veradevices[x].id, bridgeService.state.veradevices[x].veraname, "veraDevice"))
if($scope.bulk.devices.indexOf(bridgeService.state.veradevices[x]) < 0)
$scope.bulk.devices.push(bridgeService.state.veradevices[x].id);
}
}
@@ -1519,16 +1545,19 @@ app.controller('HueController', function ($scope, $location, $http, bridgeServic
offpayload = "{\"ipAddress\":\"" + huedevice.hueaddress + "\",\"deviceId\":\"" + huedevice.huedeviceid +"\",\"hueName\":\"" + huedevice.huename + "\"}";
bridgeService.buildUrls(onpayload, null, offpayload, true, huedevice.device.uniqueid, huedevice.device.name, huedevice.huename, "passthru", "hueDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
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.huedevices.length; x++) {
if(bridgeService.state.huedevices[x].device.uniqueid === $scope.bulk.devices[i]) {
$scope.buildDeviceUrls(bridgeService.state.huedevices[x]);
$scope.buildDeviceUrls(bridgeService.state.huedevices[x],true);
devicesList[i] = {
name: $scope.device.name,
mapId: $scope.device.mapId,
@@ -1545,6 +1574,7 @@ app.controller('HueController', function ($scope, $location, $http, bridgeServic
contentBodyDim: $scope.device.contentBodyDim,
contentBodyOff: $scope.device.contentBodyOff
};
$scope.clearDevice();
}
}
}
@@ -1632,7 +1662,7 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
$scope.device = bridgeService.state.device;
};
$scope.buildDeviceUrls = function (haldevice, dim_control) {
$scope.buildDeviceUrls = function (haldevice, dim_control, buildonly) {
var preOnCmd = "";
var preDimCmd = "";
var preOffCmd = "";
@@ -1687,11 +1717,13 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
+ postCmd;
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, haldevice.haldevicename + "-" + haldevice.halname, haldevice.haldevicename, haldevice.halname, aDeviceType, "halDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.buildButtonUrls = function (haldevice, onbutton, offbutton) {
$scope.buildButtonUrls = function (haldevice, onbutton, offbutton, buildonly) {
var actionOn = angular.fromJson(onbutton);
var actionOff = angular.fromJson(offbutton);
onpayload = "http://" + haldevice.haladdress + "/IrService!IrCmd=Set!IrDevice=" + haldevice.haldevicename.replaceAll(" ", "%20") + "!IrButton=" + actionOn.DeviceName.replaceAll(" ", "%20") + "?Token=" + $scope.bridge.settings.haltoken;
@@ -1699,20 +1731,24 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.halname + "-" + actionOn.DeviceName, haldevice.haldevicename, haldevice.halname, "button", "halButton", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.buildHALHomeUrls = function (haldevice) {
$scope.buildHALHomeUrls = function (haldevice, buildonly) {
onpayload = "http://" + haldevice.haladdress + "/ModeService!ModeCmd=Set!ModeName=Home?Token=" + $scope.bridge.settings.haltoken;
offpayload = "http://" + haldevice.haladdress + "/ModeService!ModeCmd=Set!ModeName=Away?Token=" + $scope.bridge.settings.haltoken;
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.halname + "-HomeAway", haldevice.haldevicename, haldevice.halname, "home", "halHome", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.buildHALHeatUrls = function (haldevice) {
$scope.buildHALHeatUrls = function (haldevice, buildonly) {
onpayload = "http://" + haldevice.haladdress
+ "/HVACService!HVACCmd=Set!HVACName="
+ haldevice.haldevicename.replaceAll(" ", "%20")
@@ -1730,11 +1766,13 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
+ $scope.bridge.settings.haltoken;
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, haldevice.haldevicename + "-" + haldevice.halname + "-SetHeat", haldevice.haldevicename + " Heat", haldevice.halname, "thermo", "halThermoSet", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.buildHALCoolUrls = function (haldevice) {
$scope.buildHALCoolUrls = function (haldevice, buildonly) {
onpayload = "http://" + haldevice.haladdress
+ "/HVACService!HVACCmd=Set!HVACName="
+ haldevice.haldevicename.replaceAll(" ", "%20")
@@ -1752,11 +1790,13 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
+ $scope.bridge.settings.haltoken;
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, haldevice.haldevicename + "-" + haldevice.halname + "-SetCool", haldevice.haldevicename + " Cool", haldevice.halname, "thermo", "halThermoSet", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.buildHALAutoUrls = function (haldevice) {
$scope.buildHALAutoUrls = function (haldevice, buildonly) {
onpayload = "http://" + haldevice.haladdress
+ "/HVACService!HVACCmd=Set!HVACName="
+ haldevice.haldevicename.replaceAll(" ", "%20")
@@ -1768,11 +1808,13 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
+ "!HVACMode=Off?Token="
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.halname + "-SetAuto", haldevice.haldevicename + " Auto", haldevice.halname, "thermo", "halThermoSet", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.buildHALOffUrls = function (haldevice) {
$scope.buildHALOffUrls = function (haldevice, buildonly) {
onpayload = "http://" + haldevice.haladdress
+ "/HVACService!HVACCmd=Set!HVACName="
+ haldevice.haldevicename.replaceAll(" ", "%20")
@@ -1785,11 +1827,13 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
$scope.device.offUrl = "http://" + haldevice.haladdress
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.halname + "-TurnOff", haldevice.haldevicename + " Thermostat", haldevice.halname, "thermo", "halThermoSet", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.buildHALFanUrls = function (haldevice) {
$scope.buildHALFanUrls = function (haldevice, buildonly) {
onpayload = "http://" + haldevice.haladdress
+ "/HVACService!HVACCmd=Set!HVACName="
+ haldevice.haldevicename.replaceAll(" ", "%20")
@@ -1802,21 +1846,24 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
+ $scope.bridge.settings.haltoken;
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.halname + "-SetFan", haldevice.haldevicename + " Fan", haldevice.halname, "thermo", "halThermoSet", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
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.haldevices.length; x++) {
if(bridgeService.state.haldevices[x].haldevicename === $scope.bulk.devices[i]) {
if(bridgeService.state.haldevices[x].haldevicetype === "HVAC")
$scope.buildHALAutoUrls(bridgeService.state.haldevices[x]);
$scope.buildHALAutoUrls(bridgeService.state.haldevices[x], true);
else if(bridgeService.state.haldevices[x].haldevicetype === "HOME")
$scope.buildHALHomeUrls(bridgeService.state.haldevices[x]);
$scope.buildHALHomeUrls(bridgeService.state.haldevices[x], true);
else
$scope.buildDeviceUrls(bridgeService.state.haldevices[x],dim_control);
$scope.buildDeviceUrls(bridgeService.state.haldevices[x],dim_control, true);
devicesList[i] = {
name: $scope.device.name,
mapId: $scope.device.mapId,
@@ -1833,6 +1880,7 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
contentBodyDim: $scope.device.contentBodyDim,
contentBodyOff: $scope.device.contentBodyOff
};
$scope.clearDevice();
}
}
}
@@ -1875,7 +1923,7 @@ app.controller('HalController', function ($scope, $location, $http, bridgeServic
else {
$scope.selectAll = true;
for(var x = 0; x < bridgeService.state.haldevices.length; x++) {
if($scope.bulk.devices.indexOf(bridgeService.state.haldevices[x]) < 0 && !bridgeService.findDeviceByMapId(bridgeService.state.haldevices[x].haldevicename + "-" + bridgeService.state.haldevices[x].halname, bridgeService.state.haldevices[x].halname, "halDevice"))
if($scope.bulk.devices.indexOf(bridgeService.state.haldevices[x]) < 0)
$scope.bulk.devices.push(bridgeService.state.haldevices[x].haldevicename);
}
}
@@ -1964,7 +2012,7 @@ app.controller('HassController', function ($scope, $location, $http, bridgeServi
$scope.device = bridgeService.state.device;
};
$scope.buildDeviceUrls = function (hassdevice, dim_control) {
$scope.buildDeviceUrls = function (hassdevice, dim_control, buildonly) {
onpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0))
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\",\"bri\":\"" + dim_control + "\"}";
@@ -1974,89 +2022,19 @@ app.controller('HassController', function ($scope, $location, $http, bridgeServi
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, hassdevice.hassname + "-" + hassdevice.deviceState.entity_id, hassdevice.deviceState.entity_id, hassdevice.hassname, hassdevice.domain, "hassDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
};
$scope.buildHassHeatUrls = function (hassdevice) {
onpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0))
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\",\"bri\":\"" + dim_control + "\"}";
else
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
offpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"off\"}";
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, hassdevice.hassname + "-" + hassdevice.deviceState.entity_id, hassdevice.deviceState.entity_id, hassdevice.hassname, hassdevice.domain, "hassDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
};
$scope.buildHassCoolUrls = function (hassdevice) {
onpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0))
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\",\"bri\":\"" + dim_control + "\"}";
else
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
offpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"off\"}";
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, hassdevice.hassname + "-" + hassdevice.deviceState.entity_id, hassdevice.deviceState.entity_id, hassdevice.hassname, hassdevice.domain, "hassDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
};
$scope.buildHassAutoUrls = function (hassdevice) {
onpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0))
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\",\"bri\":\"" + dim_control + "\"}";
else
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
offpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"off\"}";
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, hassdevice.hassname + "-" + hassdevice.deviceState.entity_id, hassdevice.deviceState.entity_id, hassdevice.hassname, hassdevice.domain, "hassDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
};
$scope.buildHassOffUrls = function (hassdevice) {
onpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0))
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\",\"bri\":\"" + dim_control + "\"}";
else
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
offpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"off\"}";
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, hassdevice.hassname + "-" + hassdevice.deviceState.entity_id, hassdevice.deviceState.entity_id, hassdevice.hassname, hassdevice.domain, "hassDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
};
$scope.buildHassFanUrls = function (hassdevice) {
onpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0))
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\",\"bri\":\"" + dim_control + "\"}";
else
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
offpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"off\"}";
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, hassdevice.hassname + "-" + hassdevice.deviceState.entity_id, hassdevice.deviceState.entity_id, hassdevice.hassname, hassdevice.domain, "hassDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
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.hassdevices.length; x++) {
if(bridgeService.state.hassdevices[x].deviceName === $scope.bulk.devices[i]) {
if(bridgeService.state.hassdevices[x].domain === "climate")
$scope.buildHassAutoUrls(bridgeService.state.hassdevices[x]);
else
$scope.buildDeviceUrls(bridgeService.state.hassdevices[x],dim_control);
if(bridgeService.state.hassdevices[x].deviceState.entity_id === $scope.bulk.devices[i] && bridgeService.state.hassdevices[x].domain !== "sensor" && bridgeService.state.hassdevices[x].domain !== "sun") {
$scope.buildDeviceUrls(bridgeService.state.hassdevices[x],dim_control,true);
devicesList[i] = {
name: $scope.device.name,
mapId: $scope.device.mapId,
@@ -2073,6 +2051,7 @@ app.controller('HassController', function ($scope, $location, $http, bridgeServi
contentBodyDim: $scope.device.contentBodyDim,
contentBodyOff: $scope.device.contentBodyOff
};
$scope.clearDevice();
}
}
}
@@ -2080,7 +2059,7 @@ app.controller('HassController', function ($scope, $location, $http, bridgeServi
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewhassdevices();
bridgeService.viewHassDevices();
},
function (error) {
bridgeService.displayWarn("Error adding Hass devices in bulk.", error)
@@ -2115,8 +2094,8 @@ app.controller('HassController', function ($scope, $location, $http, bridgeServi
else {
$scope.selectAll = true;
for(var x = 0; x < bridgeService.state.hassdevices.length; x++) {
if($scope.bulk.devices.indexOf(bridgeService.state.hassdevices[x]) < 0 && !bridgeService.findDeviceByMapId(bridgeService.state.hassdevices[x].hassdevicename + "-" + bridgeService.state.hassdevices[x].halname, bridgeService.state.hassdevices[x].halname, "hassdevice"))
$scope.bulk.devices.push(bridgeService.state.hassdevices[x].hassdevicename);
if($scope.bulk.devices.indexOf(bridgeService.state.hassdevices[x].deviceState.entity_id) < 0 && bridgeService.state.hassdevices[x].domain !== "sensor" && bridgeService.state.hassdevices[x].domain !== "sun")
$scope.bulk.devices.push(bridgeService.state.hassdevices[x].deviceState.entity_id);
}
}
};
@@ -2159,7 +2138,7 @@ app.controller('DomoticzController', function ($scope, $location, $http, bridgeS
$scope.device = bridgeService.state.device;
};
$scope.buildDeviceUrls = function (domoticzdevice, dim_control) {
$scope.buildDeviceUrls = function (domoticzdevice, dim_control, buildonly) {
var preCmd = "";
var postOnCmd = "";
var postDimCmd = "";
@@ -2198,16 +2177,19 @@ app.controller('DomoticzController', function ($scope, $location, $http, bridgeS
+ postOffCmd;
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, domoticzdevice.devicename + "-" + domoticzdevice.domoticzname, domoticzdevice.devicename, domoticzdevice.domoticzname, aDeviceType, "domoticzDevice", null, null);
$scope.device = bridgeService.state.device;
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
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.domoticzdevices.length; x++) {
if(bridgeService.state.domoticzdevices[x].devicename === $scope.bulk.devices[i]) {
$scope.buildDeviceUrls(bridgeService.state.domoticzdevices[x],dim_control);
$scope.buildDeviceUrls(bridgeService.state.domoticzdevices[x],dim_control,true);
devicesList[i] = {
name: $scope.device.name,
mapId: $scope.device.mapId,
@@ -2224,6 +2206,7 @@ app.controller('DomoticzController', function ($scope, $location, $http, bridgeS
contentBodyDim: $scope.device.contentBodyDim,
contentBodyOff: $scope.device.contentBodyOff
};
$scope.clearDevice();
}
}
}
@@ -2234,7 +2217,7 @@ app.controller('DomoticzController', function ($scope, $location, $http, bridgeS
bridgeService.viewHalDevices();
},
function (error) {
bridgeService.displayWarn("Error adding HAL devices in bulk.", error)
bridgeService.displayWarn("Error adding Domoticz devices in bulk.", error)
}
);
$scope.bulk = { devices: [] };
@@ -2266,8 +2249,130 @@ app.controller('DomoticzController', function ($scope, $location, $http, bridgeS
else {
$scope.selectAll = true;
for(var x = 0; x < bridgeService.state.haldevices.length; x++) {
if($scope.bulk.devices.indexOf(bridgeService.state.haldevices[x]) < 0 && !bridgeService.findDeviceByMapId(bridgeService.state.haldevices[x].haldevicename + "-" + bridgeService.state.haldevices[x].halname, bridgeService.state.haldevices[x].halname, "halDevice"))
$scope.bulk.devices.push(bridgeService.state.haldevices[x].haldevicename);
if($scope.bulk.devices.indexOf(bridgeService.state.domoticzdevices[x]) < 0)
$scope.bulk.devices.push(bridgeService.state.domoticzdevices[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('LifxController', function ($scope, $location, $http, bridgeService, ngDialog) {
$scope.bridge = bridgeService.state;
$scope.device = bridgeService.state.device;
$scope.device_dim_control = "";
$scope.bulk = { devices: [] };
$scope.selectAll = false;
bridgeService.viewLifxDevices();
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
$scope.buttonsVisible = false;
$scope.clearDevice = function () {
bridgeService.clearDevice();
$scope.device = bridgeService.state.device;
};
$scope.buildDeviceUrls = function (lifxdevice, dim_control, buildonly) {
dimpayload = angular.toJson(lifxdevice);
onpayload = angular.toJson(lifxdevice);
offpayload = angular.toJson(lifxdevice);
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, lifxdevice.name, lifxdevice.name, lifxdevice.name, null, "lifxDevice", 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.lifxdevices.length; x++) {
if(bridgeService.state.lifxdevices[x].devicename === $scope.bulk.devices[i]) {
$scope.buildDeviceUrls(bridgeService.state.lifxdevices[x],dim_control,true);
devicesList[i] = {
name: $scope.device.name,
mapId: $scope.device.mapId,
mapType: $scope.device.mapType,
deviceType: $scope.device.deviceType,
targetDevice: $scope.device.targetDevice,
onUrl: $scope.device.onUrl,
dimUrl: $scope.device.dimUrl,
offUrl: $scope.device.offUrl,
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 LIFX 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.haldevices.length; x++) {
if($scope.bulk.devices.indexOf(bridgeService.state.lifxdevices[x]) < 0)
$scope.bulk.devices.push(bridgeService.state.lifxdevices[x].devicename);
}
}
};
@@ -2566,6 +2671,20 @@ app.filter('configuredDomoticzItems', function (bridgeService) {
}
});
app.filter('configuredLifxItems', 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], "lifx")) {
out.push(input[i]);
}
}
return out;
}
});
app.controller('VersionController', function ($scope, bridgeService) {
$scope.bridge = bridgeService.state;
});

View File

@@ -20,6 +20,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -18,6 +18,7 @@
<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 role="presentation" class="active"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
@@ -35,7 +36,7 @@
done in the edit tab, click the 'Add Bridge Device' to finish that selection
setup. The 'Already Configured Domoticz Devices' list below will show what
is already setup for your Domoticz.</p>
<p>
<p class="text-muted">
Also, use this select menu for which type of dim control you would
like to be generated: <select name="device-dim-control"
id="device-dim-control" ng-model="device_dim_control">
@@ -45,7 +46,7 @@
<option value="${intensity.math(X*1)}">Custom Math</option>
</select>
</p>
<p>Use the check boxes by the names to use the bulk addition
<p class="text-muted">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 Domoticz.</p>
@@ -75,7 +76,7 @@
<td>{{domoticzdevice.domoticzname}}</td>
<td>
<button class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(domoticzdevice, device_dim_control)">Build Item</button>
ng-click="buildDeviceUrls(domoticzdevice, device_dim_control,false)">Build Item</button>
</td>
</tr>
</table>

View File

@@ -20,6 +20,7 @@
<li ng-if="bridge.showHass" role="presentation"><a
href="#!/hassdevices">HomeAssistant Devices</a></li>
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation" class="active"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
@@ -43,7 +44,7 @@
(${intensity..byte},${intensity.percent},${intensity.math(X*1)}) will
also work. Also, you can go back to any helper tab and click a build
action button to add another item for a multi-command.</p>
<p>When copying, update the name and select the "Add Bridge
<p class="text-muted">When copying, update the name and select the "Add Bridge
Device" Button.</p>
<form name="form">
@@ -129,6 +130,7 @@
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<div class="col-xs-12 col-md-4">
<th>Type</th>
<th>Target Item</th>
<th>Delay</th>
@@ -139,19 +141,21 @@
<th>Http Headers</th>
<th>Content Type</th>
<th>Manage</th>
</div>
</tr>
</thead>
<tr ng-repeat="onItem in onDevices">
<div class="col-xs-12 col-md-4">
<td><select
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
ng-model="onItem.type"></select></td>
<td><textarea rows="1" cols="20" class="form-control"
<td><textarea rows="1" class="form-control"
id="item-target" ng-model="onItem.item" placeholder="The Call"></textarea></td>
<td><textarea rows="1" cols="4" class="form-control"
<td><textarea rows="1" class="form-control"
id="item-delay" ng-model="onItem.delay" placeholder="millis"></textarea></td>
<td><textarea rows="1" cols="2" class="form-control"
<td><textarea rows="1" class="form-control"
id="item-count" ng-model="onItem.count" placeholder="number"></textarea></td>
<td><textarea rows="1" cols="16" class="form-control"
<td><textarea rows="1" class="form-control"
id="item-filterIPs" ng-model="onItem.filterIPs"
placeholder="restrict IPs"></textarea></td>
<td><select name="item-http-verb" id="item-http-verb"
@@ -162,7 +166,7 @@
<option value="PUT">PUT</option>
<option value="POST">POST</option>
</select></td>
<td><textarea rows="1" cols="16" class="form-control"
<td><textarea rows="1" class="form-control"
id="item-httpBody" ng-model="onItem.httpBody"
placeholder="body args"></textarea></td>
<td><textarea rows="1" cols="16" class="form-control"
@@ -188,8 +192,10 @@
</select></td>
<td><button class="btn btn-danger" type="submit"
ng-click="removeItemOn(onItem)">Del</button></td>
</div>
</tr>
<tr>
<div class="col-xs-12 col-md-4">
<td><select
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
ng-model="newOnItem.type"></select></td>
@@ -239,6 +245,7 @@
</select></td>
<td><button class="btn btn-success" type="submit"
ng-click="addItemOn(newOnItem)">Add</button></td>
</div>
</tr>
</table>
</scrollable-table></td>
@@ -250,6 +257,7 @@
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<div class="col-xs-12 col-md-4">
<th>Type</th>
<th>Target Item</th>
<th>Delay</th>
@@ -260,9 +268,11 @@
<th>Http Headers</th>
<th>Content Type</th>
<th>Manage</th>
</div>
</tr>
</thead>
<tr ng-repeat="dimItem in dimDevices">
<div class="col-xs-12 col-md-4">
<td><select
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
ng-model="dimItem.type"></select></td>
@@ -310,8 +320,10 @@
</select></td>
<td><button class="btn btn-danger" type="submit"
ng-click="removeItemDim(dimItem)">Del</button></td>
</div>
</tr>
<tr>
<div class="col-xs-12 col-md-4">
<td><select
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
ng-model="newDimItem.type"></select></td>
@@ -361,6 +373,7 @@
</select></td>
<td><button class="btn btn-success" type="submit"
ng-click="addItemDim(newDimItem)">Add</button></td>
</div>
</tr>
</table>
</scrollable-table></td>
@@ -372,6 +385,7 @@
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<div class="col-xs-12 col-md-4">
<th>Type</th>
<th>Target Item</th>
<th>Delay</th>
@@ -382,9 +396,11 @@
<th>Http Headers</th>
<th>Content Type</th>
<th>Manage</th>
</div>
</tr>
</thead>
<tr ng-repeat="offItem in offDevices">
<div class="col-xs-12 col-md-4">
<td><select
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
ng-model="offItem.type"></select></td>
@@ -432,8 +448,10 @@
</select></td>
<td><button class="btn btn-danger" type="submit"
ng-click="removeItemOff(offItem)">Del</button></td>
</div>
</tr>
<tr>
<div class="col-xs-12 col-md-4">
<td><select
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
ng-model="newOffItem.type"></select></td>
@@ -483,6 +501,7 @@
</select></td>
<td><button class="btn btn-success" type="submit"
ng-click="addItemOff(newOffItem)">Add</button></td>
</div>
</tr>
</table>
</scrollable-table></td>

View File

@@ -17,6 +17,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
@@ -34,7 +35,7 @@
done in the edit tab, click the 'Add Bridge Device' to finish that selection
setup. The 'Already Configured HAL Devices' list below will show what
is already setup for your HAL.</p>
<p>
<p class="text-muted">
Also, use this select menu for which type of dim control you would
like to be generated: <select name="device-dim-control"
id="device-dim-control" ng-model="device_dim_control">
@@ -44,7 +45,7 @@
<option value="${intensity.math(X*1)}">Custom Math</option>
</select>
</p>
<p>Use the check boxes by the names to use the bulk addition
<p class="text-muted">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 HAL.</p>
@@ -88,27 +89,27 @@
</td>
<td>
<button ng-if="haldevice.haldevicetype != 'Home' && haldevice.haldevicetype != 'HVAC' && haldevice.haldevicetype != 'IrData'" class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(haldevice, device_dim_control)">Build Item</button>
ng-click="buildDeviceUrls(haldevice, device_dim_control, false)">Build Item</button>
<button ng-if="haldevice.haldevicetype == 'Home'" class="btn btn-success" type="submit"
ng-click="buildHALHomeUrls(haldevice)">Build Home/Away</button>
ng-click="buildHALHomeUrls(haldevice, false)">Build Home/Away</button>
<button ng-if="haldevice.haldevicetype == 'IrData'" class="btn btn-success" type="submit"
ng-click="buildButtonUrls(haldevice, button_on, button_off)">Build
ng-click="buildButtonUrls(haldevice, button_on, button_off, false)">Build
A Button</button>
<ul ng-if="haldevice.haldevicetype == 'HVAC'" class="list-group">
<li class="list-group-item">
<p>
<button class="btn btn-success" type="submit"
ng-click="buildHALHeatUrls(haldevice)">Heat</button>
ng-click="buildHALHeatUrls(haldevice, false)">Heat</button>
<button class="btn btn-success" type="submit"
ng-click="buildHALCoolUrls(haldevice)">Cool</button>
ng-click="buildHALCoolUrls(haldevice, false)">Cool</button>
<button class="btn btn-success" type="submit"
ng-click="buildHALAutoUrls(haldevice)">Auto</button>
ng-click="buildHALAutoUrls(haldevice, false)">Auto</button>
</p>
<p>
<button class="btn btn-success" type="submit"
ng-click="buildHALOffUrls(haldevice)">Off</button>
ng-click="buildHALOffUrls(haldevice, false)">Off</button>
<button class="btn btn-success" type="submit"
ng-click="buildHALFanUrls(haldevice)">Fan</button>
ng-click="buildHALFanUrls(haldevice, false)">Fan</button>
</p>
</li>
</ul>

View File

@@ -18,6 +18,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -18,6 +18,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -13,11 +13,12 @@
<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" class="active"><a href="#!/haldevices">HAL
<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 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>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
@@ -35,7 +36,7 @@
done in the edit tab, click the 'Add Bridge Device' to finish that selection
setup. The 'Already Configured HomeAssistant Devices' list below will show what
is already setup for your HomeAssitant.</p>
<p>
<p class="text-muted">
Also, use this select menu for which type of dim control you would
like to be generated, BUT for Home Assistant, the selection should be Pass-thru: <select name="device-dim-control"
id="device-dim-control" ng-model="device_dim_control">
@@ -45,7 +46,7 @@
<option value="${intensity.math(X*1)}">Custom Math</option>
</select>
</p>
<p>Use the check boxes by the names to use the bulk addition
<p class="text-muted">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 HomeAssitant.</p>
@@ -72,26 +73,8 @@
{{hassdevice.deviceState.entity_id}}</td>
<td>{{hassdevice.hassname}}</td>
<td>
<button ng-if="hassdevice.domain != 'climate' && hassdevice.domain != 'sensor' && hassdevice.domain != 'sun'" class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(hassdevice, device_dim_control)">Build Item</button>
<ul ng-if="hassdevice.domain == 'climate'" class="list-group">
<li class="list-group-item">
<p>
<button class="btn btn-success" type="submit"
ng-click="buildhassHeatUrls(hassdevice)">Heat</button>
<button class="btn btn-success" type="submit"
ng-click="buildhassCoolUrls(hassdevice)">Cool</button>
<button class="btn btn-success" type="submit"
ng-click="buildhassAutoUrls(hassdevice)">Auto</button>
</p>
<p>
<button class="btn btn-success" type="submit"
ng-click="buildhassOffUrls(hassdevice)">Off</button>
<button class="btn btn-success" type="submit"
ng-click="buildhassFanUrls(hassdevice)">Fan</button>
</p>
</li>
</ul>
<button ng-if="hassdevice.domain != 'sensor' && hassdevice.domain != 'sun'" class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(hassdevice, device_dim_control, false)">Build Item</button>
</td>
</tr>
</table>

View File

@@ -18,6 +18,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
@@ -35,9 +36,9 @@
done in the edit tab, click the 'Add Bridge Device' to finish that selection
setup. The 'Already Configured Hue Devices' list below will show what
is already setup for your Hue.</p>
<p>Use the check boxes by the names to use the bulk addition
<p class="text-muted">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 on and off or dim and off if selected with the
will be added with on, off and dim with the
name of the device from the Hue.</p>
<scrollable-table watch="bridge.huedevices">
<table class="table table-bordered table-striped table-hover">
@@ -64,7 +65,7 @@
<td>{{huedevice.huename}}</td>
<td>
<button class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(huedevice)">Build Item</button>
ng-click="buildDeviceUrls(huedevice, false)">Build Item</button>
</td>
</tr>
</table>

View File

@@ -0,0 +1,122 @@
<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.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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li role="presentation" class="active"><a href="#!/lifxdevices">LIFX 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">LIFX Devices</h2>
</div>
<div class="panel-body">
<p class="text-muted">For any LIFX 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 LIFX Devices' list below will show what
is already setup for your LIFX.</p>
<p class="text-muted">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, off and dim
with the name of the device from the LIFX device.</p>
<scrollable-table watch="bridge.lifxdevices">
<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">ID</th>
<th sortable-header col="type">Type</th>
<th>Build Actions</th>
</tr>
</thead>
<tr ng-repeat="lifxdev in bridge.lifxdevices">
<td>{{$index+1}}</td>
<td><input type="checkbox" name="bulk.devices[]"
value="{{lifxdev.name}}"
ng-checked="bulk.devices.indexOf(lifxdev.name) > -1"
ng-click="toggleSelection(lifxdev.name)">{{lifxdev.name}}</td>
<td>{{lifxdev.id}}</td>
<td>{{lifxdev.type}}</td>
<td>
<button class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(lifxdev, false)">Build
Item</button>
</td>
</tr>
</table>
</scrollable-table>
<div class="panel-footer">
<button class="btn btn-success" type="submit"
ng-click="bulkAddDevices(device_dim_control)">Bulk Add
({{bulk.devices.length}})</button>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
Already Configured LIFX 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.lifxdevices">
<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">Light Name</th>
<th>Map Id</th>
<th>Actions</th>
</tr>
</thead>
<tr
ng-repeat="device in bridge.devices | configuredLifxItems | orderBy:predicate:reverse">
<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

@@ -18,6 +18,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -12,6 +12,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -18,6 +18,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -19,6 +19,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
@@ -375,6 +376,12 @@
ng-model="bridge.settings.farenheit" ng-true-value=true
ng-false-value=false> {{bridge.settings.farenheit}}</td>
</tr>
<tr>
<td>LIFX Support</td>
<td><input type="checkbox"
ng-model="bridge.settings.lifxconfigured" ng-true-value=true
ng-false-value=false> {{bridge.settings.lifxconfigured}}</td>
</tr>
<tr>
<td>Emulate Hue Hub Version</td>
<td><input id="bridge-settings-hubversion" class="form-control"

View File

@@ -17,6 +17,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
@@ -35,7 +36,7 @@
done in the edit tab, click the 'Add Bridge Device' to finish that selection
setup. The 'Already Configured Vera Devices' list below will show
what is already setup for your Vera.</p>
<p>
<p class="text-muted">
Also, use this select menu for which type of dim control you would
like to be generated: <select name="device-dim-control"
id="device-dim-control" ng-model="device_dim_control">
@@ -45,7 +46,7 @@
<option value="${intensity.math(X*1)}">Custom Math</option>
</select>
</p>
<p>Use the check boxes by the names to use the bulk addition
<p class="text-muted">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 Vera.</p>
@@ -79,7 +80,7 @@
<td>{{veradevice.veraname}}</td>
<td>
<button class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(veradevice, device_dim_control)">Build Item</button>
ng-click="buildDeviceUrls(veradevice, device_dim_control, false)">Build Item</button>
</td>
</tr>
</table>

View File

@@ -17,6 +17,7 @@
<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.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>