From 16a248ba8e9c7753cd1e612fb347655617c3da10 Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 1 Feb 2017 16:53:08 -0600 Subject: [PATCH] Starting impl of LIFX devices --- pom.xml | 7 +- .../bwssystems/HABridge/BridgeSettings.java | 1 + .../HABridge/BridgeSettingsDescriptor.java | 10 + .../bwssystems/HABridge/DeviceMapTypes.java | 2 + .../com/bwssystems/HABridge/HomeManager.java | 9 +- .../bwssystems/HABridge/hue/HueMulator.java | 1 - .../HABridge/plugins/lifx/LifxDevice.java | 47 +++++ .../HABridge/plugins/lifx/LifxEntry.java | 18 ++ .../HABridge/plugins/lifx/LifxHome.java | 177 ++++++++++++++++++ src/main/resources/public/scripts/app.js | 155 ++++++++++++++- src/main/resources/public/views/system.html | 6 + 11 files changed, 428 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxDevice.java create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxEntry.java create mode 100644 src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxHome.java diff --git a/pom.xml b/pom.xml index 72d092f..077a0c8 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 4.1.2 + 4.1.2a jar HA Bridge @@ -121,6 +121,11 @@ junit 4.11 + + com.github.bwssytems + lifx-sdk-java + 2.1.1 + diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java index 1d67a37..13d84d4 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java @@ -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) diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java index 442513b..556d85f 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java @@ -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(); + } } diff --git a/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java b/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java index 870fa2c..1ee8125 100644 --- a/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java +++ b/src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java @@ -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); diff --git a/src/main/java/com/bwssystems/HABridge/HomeManager.java b/src/main/java/com/bwssystems/HABridge/HomeManager.java index 83b1118..ed51668 100644 --- a/src/main/java/com/bwssystems/HABridge/HomeManager.java +++ b/src/main/java/com/bwssystems/HABridge/HomeManager.java @@ -12,6 +12,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; @@ -79,13 +80,17 @@ 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); 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) { diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index 67b3db5..017d8e2 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -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; diff --git a/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxDevice.java b/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxDevice.java new file mode 100644 index 0000000..8ca81f9 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxDevice.java @@ -0,0 +1,47 @@ +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()); + } + if(type.equals(GROUP_TYPE)) { + anEntry = new LifxEntry(); + anEntry.setId("na"); + anEntry.setName(((LFXGroup)lifxObject).getLabel()); + } + 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; + } +} \ No newline at end of file diff --git a/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxEntry.java b/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxEntry.java new file mode 100644 index 0000000..44574d5 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxEntry.java @@ -0,0 +1,18 @@ +package com.bwssystems.HABridge.plugins.lifx; + +public class LifxEntry { + private String name; + private String id; + 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; + } +} diff --git a/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxHome.java b/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxHome.java new file mode 100644 index 0000000..1a03b88 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/plugins/lifx/LifxHome.java @@ -0,0 +1,177 @@ +package com.bwssystems.HABridge.plugins.lifx; + +import java.io.IOException; +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.LFXLight; +import com.github.besherman.lifx.LFXLightCollection; +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 Map lifxMap; + private LFXClient client = new LFXClient(); + 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...."); + client.open(true); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + aGsonHandler = + new GsonBuilder() + .create(); + lifxMap = new HashMap(); + this.addLifxLights(client.getLights()); + this.addLifxGroups(client.getGroups()); + } + 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 keys = lifxMap.keySet().iterator(); + List deviceList = new ArrayList(); + 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 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 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; + 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); + int aBriValue = BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc); + 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) + theLight.setBrightness((float)(aBriValue/254)); + } 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(); + } +} diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index e22505a..e6ae6d4 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -45,6 +45,9 @@ app.config (function ($locationProvider, $routeProvider) { }).when ('/domoticzdevices', { templateUrl: 'views/domoticzdevice.html', controller: 'DomoticzController' + }).when ('/lifxdevices', { + templateUrl: 'views/lifxdevice.html', + controller: 'DomoticzController' }).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.showDomoticz = self.state.settings.lifxconfigured; + return; + } + this.loadBridgeSettings = function () { return $http.get(this.state.systemsbase + "/settings").then( function (response) { @@ -450,6 +458,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("{")) @@ -2295,6 +2316,124 @@ app.controller('DomoticzController', function ($scope, $location, $http, bridgeS }; }); +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) { + dimpayload = "{\"name\":\"" + lifxdevice.name + "\"}"; + onpayload = "{\"name\":\"" + lifxdevice.name + "\"}"; + offpayload = "{\"name\":\"" + lifxdevice.name + "\"}"; + bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, lifxdevice.name, lifxdevice.name, lifxdevice.name, aDeviceType, "lifxDevice", null, null); + $scope.device = bridgeService.state.device; + bridgeService.editNewDevice($scope.device); + $location.path('/editdevice'); + }; + + $scope.bulkAddDevices = function(dim_control) { + var devicesList = []; + 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); + 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 + }; + } + } + } + bridgeService.bulkAddDevice(devicesList).then( + function () { + $scope.clearDevice(); + bridgeService.viewDevices(); + bridgeService.viewHalDevices(); + }, + function (error) { + bridgeService.displayWarn("Error adding HAL 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.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); + } + } + }; + + $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('EditController', function ($scope, $location, $http, bridgeService) { bridgeService.viewMapTypes(); $scope.bridge = bridgeService.state; @@ -2566,6 +2705,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; }); \ No newline at end of file diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index 6451311..19564fb 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -375,6 +375,12 @@ ng-model="bridge.settings.farenheit" ng-true-value=true ng-false-value=false> {{bridge.settings.farenheit}} + + LIFX Support + {{bridge.settings.lifxconfigured}} + Emulate Hue Hub Version