diff --git a/pom.xml b/pom.xml index cf9bade..60e0910 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 2.0.7 + 2.0.7-hal jar HA Bridge diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java index 5482187..40245bd 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java @@ -155,6 +155,7 @@ public class BridgeSettings extends BackupHandler { theBridgeSettings.setHarmonyconfigured(theBridgeSettings.isValidHarmony()); theBridgeSettings.setNestConfigured(theBridgeSettings.isValidNest()); theBridgeSettings.setHueconfigured(theBridgeSettings.isValidHue()); + theBridgeSettings.setHalconfigured(theBridgeSettings.isValidHal()); if(serverPortOverride != null) theBridgeSettings.setServerPort(serverPortOverride); setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-"); @@ -171,27 +172,7 @@ public class BridgeSettings extends BackupHandler { private void _loadConfig(Path aPath) { String jsonContent = configReader(aPath); - BridgeSettingsDescriptor aBridgeSettings = new Gson().fromJson(jsonContent, BridgeSettingsDescriptor.class); - theBridgeSettings.setButtonsleep(aBridgeSettings.getButtonsleep()); - theBridgeSettings.setUpnpConfigAddress(aBridgeSettings.getUpnpConfigAddress()); - theBridgeSettings.setServerPort(aBridgeSettings.getServerPort()); - theBridgeSettings.setUpnpResponsePort(aBridgeSettings.getUpnpResponsePort()); - theBridgeSettings.setUpnpDeviceDb(aBridgeSettings.getUpnpDeviceDb()); - theBridgeSettings.setVeraAddress(aBridgeSettings.getVeraAddress()); - theBridgeSettings.setHarmonyAddress(aBridgeSettings.getHarmonyAddress()); - theBridgeSettings.setHarmonyUser(aBridgeSettings.getHarmonyUser()); - theBridgeSettings.setHarmonyPwd(aBridgeSettings.getHarmonyPwd()); - theBridgeSettings.setUpnpStrict(aBridgeSettings.isUpnpStrict()); - theBridgeSettings.setTraceupnp(aBridgeSettings.isTraceupnp()); - theBridgeSettings.setNestuser(aBridgeSettings.getNestuser()); - theBridgeSettings.setNestpwd(aBridgeSettings.getNestpwd()); - theBridgeSettings.setVeraconfigured(aBridgeSettings.isValidVera()); - theBridgeSettings.setHarmonyconfigured(aBridgeSettings.isValidHarmony()); - theBridgeSettings.setNestConfigured(aBridgeSettings.isValidNest()); - theBridgeSettings.setNumberoflogmessages(aBridgeSettings.getNumberoflogmessages()); - theBridgeSettings.setFarenheit(aBridgeSettings.isFarenheit()); - theBridgeSettings.setHueaddress(aBridgeSettings.getHueaddress()); - theBridgeSettings.setHueconfigured(aBridgeSettings.isValidHue()); + theBridgeSettings = new Gson().fromJson(jsonContent, BridgeSettingsDescriptor.class); } public void save(BridgeSettingsDescriptor newBridgeSettings) { diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java index b362e6c..284b46c 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java @@ -24,6 +24,9 @@ public class BridgeSettingsDescriptor { private Integer numberoflogmessages; private IpList hueaddress; private boolean hueconfigured; + private IpList haladdress; + private String haltoken; + private boolean halconfigured; public BridgeSettingsDescriptor() { super(); @@ -167,6 +170,24 @@ public class BridgeSettingsDescriptor { public void setHueconfigured(boolean hueconfigured) { this.hueconfigured = hueconfigured; } + public IpList getHaladdress() { + return haladdress; + } + public void setHaladdress(IpList haladdress) { + this.haladdress = haladdress; + } + public String getHaltoken() { + return haltoken; + } + public void setHaltoken(String haltoken) { + this.haltoken = haltoken; + } + public boolean isHalconfigured() { + return halconfigured; + } + public void setHalconfigured(boolean halconfigured) { + this.halconfigured = halconfigured; + } public Boolean isValidVera() { if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0) return false; @@ -202,4 +223,14 @@ public class BridgeSettingsDescriptor { return false; return true; } + public Boolean isValidHal() { + if(this.getHaladdress() == null || this.getHaladdress().getDevices().size() <= 0) + return false; + List devicesList = this.getHaladdress().getDevices(); + if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + return false; + if(this.getHaltoken() == null || this.getHaltoken().equals("")) + return false; + return true; + } } diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java index db8a981..d29681f 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -21,6 +21,7 @@ import com.bwssystems.HABridge.dao.DeviceDescriptor; import com.bwssystems.HABridge.dao.DeviceRepository; import com.bwssystems.HABridge.dao.ErrorMessage; import com.bwssystems.NestBridge.NestHome; +import com.bwssystems.hal.HalHome; import com.bwssystems.harmony.HarmonyHome; import com.bwssystems.hue.HueHome; import com.bwssystems.luupRequests.Device; @@ -40,6 +41,7 @@ public class DeviceResource { private HarmonyHome myHarmonyHome; private NestHome nestHome; private HueHome hueHome; + private HalHome halHome; private static final Set supportedVerbs = new HashSet<>(Arrays.asList("get", "put", "post")); public DeviceResource(BridgeSettingsDescriptor theSettings, HarmonyHome theHarmonyHome, NestHome aNestHome, HueHome aHueHome) { @@ -64,7 +66,13 @@ public class DeviceResource { this.hueHome = aHueHome; else this.hueHome = null; - setupEndpoints(); + + if(theSettings.isValidHal()) + this.hueHome = aHueHome; + else + this.halHome = null; + + setupEndpoints(); } public DeviceRepository getDeviceRepository() { @@ -262,6 +270,16 @@ public class DeviceResource { return hueHome.getDevices(); }, new JsonTransformer()); + get (API_CONTEXT + "/hal/devices", "application/json", (request, response) -> { + log.debug("Get hal items"); + if(halHome == null) { + response.status(HttpStatus.SC_NOT_FOUND); + return new ErrorMessage("A Hal is not available."); + } + response.status(HttpStatus.SC_OK); + return halHome.getDevices(); + }, new JsonTransformer()); + get (API_CONTEXT + "/backup/available", "application/json", (request, response) -> { log.debug("Get backup filenames"); response.status(HttpStatus.SC_OK); diff --git a/src/main/java/com/bwssystems/hal/DeviceElements.java b/src/main/java/com/bwssystems/hal/DeviceElements.java new file mode 100644 index 0000000..3f6e1e2 --- /dev/null +++ b/src/main/java/com/bwssystems/hal/DeviceElements.java @@ -0,0 +1,15 @@ +package com.bwssystems.hal; + +import java.util.List; + +public class DeviceElements { + private List DeviceElements; + + public List getDeviceElements() { + return DeviceElements; + } + + public void setDeviceElements(List deviceElements) { + DeviceElements = deviceElements; + } +} diff --git a/src/main/java/com/bwssystems/hal/DeviceName.java b/src/main/java/com/bwssystems/hal/DeviceName.java new file mode 100644 index 0000000..948a95a --- /dev/null +++ b/src/main/java/com/bwssystems/hal/DeviceName.java @@ -0,0 +1,14 @@ +package com.bwssystems.hal; + +public class DeviceName { + private String DeviceName; + + public String getDeviceName() { + return DeviceName; + } + + public void setDeviceName(String deviceName) { + DeviceName = deviceName; + } + +} diff --git a/src/main/java/com/bwssystems/hal/HalDevice.java b/src/main/java/com/bwssystems/hal/HalDevice.java new file mode 100644 index 0000000..62dd241 --- /dev/null +++ b/src/main/java/com/bwssystems/hal/HalDevice.java @@ -0,0 +1,32 @@ +package com.bwssystems.hal; + +public class HalDevice { + private String haldevicetype; + private String haldevicename; + private String haladdress; + private String halname; + public String getHaldevicetype() { + return haldevicetype; + } + public void setHaldevicetype(String haldevicetype) { + this.haldevicetype = haldevicetype; + } + public String getHaldevicename() { + return haldevicename; + } + public void setHaldevicename(String haldevicename) { + this.haldevicename = haldevicename; + } + public String getHaladdress() { + return haladdress; + } + public void setHaladdress(String haladdress) { + this.haladdress = haladdress; + } + public String getHalname() { + return halname; + } + public void setHalname(String halname) { + this.halname = halname; + } +} diff --git a/src/main/java/com/bwssystems/hal/HalHome.java b/src/main/java/com/bwssystems/hal/HalHome.java new file mode 100644 index 0000000..0c50d5f --- /dev/null +++ b/src/main/java/com/bwssystems/hal/HalHome.java @@ -0,0 +1,60 @@ +package com.bwssystems.hal; + +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.NamedIP; + +public class HalHome { + private static final Logger log = LoggerFactory.getLogger(HalHome.class); + private Map hals; + + public HalHome(BridgeSettingsDescriptor bridgeSettings) { + super(); + hals = new HashMap(); + if(!bridgeSettings.isValidHal()) + return; + Iterator theList = bridgeSettings.getHarmonyAddress().getDevices().iterator(); + while(theList.hasNext()) { + NamedIP aHal = theList.next(); + try { + hals.put(aHal.getName(), new HalInfo(aHal, bridgeSettings.getHaltoken())); + } catch (Exception e) { + log.error("Cannot get harmony client (" + aHal.getName() + ") setup, Exiting with message: " + e.getMessage(), e); + return; + } + } + } + + public List getDevices() { + log.debug("consolidating devices for hues"); + Iterator keys = hals.keySet().iterator(); + List deviceList = new ArrayList(); + while(keys.hasNext()) { + String key = keys.next(); + List theResponse = hals.get(key).getLights(); + if(theResponse != null) { + Iterator devices = theResponse.iterator(); + while(devices.hasNext()) { + HalDevice theDevice = devices.next(); + HalDevice aNewHalDevice = new HalDevice(); + aNewHalDevice.setHaldevicetype(theDevice.getHaldevicetype()); + aNewHalDevice.setHaldevicename(theDevice.getHaldevicename()); + aNewHalDevice.setHaladdress(hals.get(key).getHalAddress().getIp()); + aNewHalDevice.setHalname(key); + deviceList.add(aNewHalDevice); + } + } + else + log.warn("Cannot get lights for Hal with name: " + key); + } + return deviceList; + } +} diff --git a/src/main/java/com/bwssystems/hal/HalInfo.java b/src/main/java/com/bwssystems/hal/HalInfo.java new file mode 100644 index 0000000..1461595 --- /dev/null +++ b/src/main/java/com/bwssystems/hal/HalInfo.java @@ -0,0 +1,89 @@ +package com.bwssystems.hal; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.bwssystems.HABridge.NamedIP; +import com.google.gson.Gson; + +public class HalInfo { + private static final Logger log = LoggerFactory.getLogger(HalInfo.class); + private static final String LIGHTS_REQUEST = "/DeviceData!DeviceCmd=GetNames!DeviceType=Light?Token="; + private HttpClient httpClient; + private NamedIP halAddress; + private String theToken; + + public HalInfo(NamedIP addressName, String aGivenToken) { + super(); + httpClient = HttpClients.createDefault(); + halAddress = addressName; + theToken = aGivenToken; + } + + public List getLights() { + DeviceElements theHalApiResponse = null; + List deviceList = null; + + String theUrl = null; + String theData; + theUrl = "http://" + halAddress.getIp() + LIGHTS_REQUEST + theToken; + theData = doHttpGETRequest(theUrl); + if(theData != null) { + log.debug("GET HalApiResponse - data: " + theData); + theHalApiResponse = new Gson().fromJson(theData, DeviceElements.class); + deviceList = new ArrayList(); + + Iterator theDeviceNames = theHalApiResponse.getDeviceElements().iterator(); + while(theDeviceNames.hasNext()) { + DeviceName theDevice = theDeviceNames.next(); + HalDevice aNewHalDevice = new HalDevice(); + aNewHalDevice.setHaldevicetype("lights"); + aNewHalDevice.setHaldevicename(theDevice.getDeviceName()); + deviceList.add(aNewHalDevice); + + } + } + else { + log.warn("GET HalApiResponse for " + halAddress.getName() + " - returned null, no data."); + } + return deviceList; + } + + // This function executes the url against the hal + protected String doHttpGETRequest(String url) { + String theContent = null; + log.debug("calling GET on URL: " + url); + HttpGet httpGet = new HttpGet(url); + try { + HttpResponse response = httpClient.execute(httpGet); + log.debug("GET on URL responded: " + response.getStatusLine().getStatusCode()); + if(response.getStatusLine().getStatusCode() == 200){ + theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); //read content for data + EntityUtils.consume(response.getEntity()); //close out inputstream ignore content + } + } catch (IOException e) { + log.error("doHttpGETRequest: Error calling out to HA gateway: " + e.getMessage()); + } + return theContent; + } + + public NamedIP getHalAddress() { + return halAddress; + } + + public void setHalAddress(NamedIP halAddress) { + this.halAddress = halAddress; + } + +} diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 9eae577..be266f5 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -34,6 +34,9 @@ app.config(function ($routeProvider) { }).when('/huedevices', { templateUrl: 'views/huedevice.html', controller: 'HueController' + }).when('/haldevices', { + templateUrl: 'views/haldevice.html', + controller: 'HalController' }).otherwise({ templateUrl: 'views/configuration.html', controller: 'ViewingController' @@ -47,7 +50,7 @@ app.run( function (bridgeService) { 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: [], olddevicename: "", logShowAll: false, isInControl: false, showVera: false, showHarmony: false, showNest: false, showHue: 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: [], olddevicename: "", logShowAll: false, isInControl: false, showVera: false, showHarmony: false, showNest: false, showHue: false, showHal: false, habridgeversion: ""}; this.displayWarn = function(errorTitle, error) { var toastContent = errorTitle; @@ -155,6 +158,11 @@ app.service('bridgeService', function ($http, $window, ngToast) { return; } + this.updateShowHal = function () { + this.state.showHal = self.state.settings.halconfigured; + return; + } + this.loadBridgeSettings = function () { return $http.get(this.state.systemsbase + "/settings").then( function (response) { @@ -163,6 +171,7 @@ app.service('bridgeService', function ($http, $window, ngToast) { self.updateShowHarmony(); self.updateShowNest(); self.updateShowHue(); + self.updateShowHal(); }, function (error) { self.displayWarn("Load Bridge Settings Error: ", error); @@ -292,6 +301,19 @@ app.service('bridgeService', function ($http, $window, ngToast) { ); }; + this.viewHalDevices = function () { + if(!this.state.showHal) + return; + return $http.get(this.state.base + "/hal/devices").then( + function (response) { + self.state.haldevices = response.data; + }, + function (error) { + self.displayWarn("Get Hal Devices Error: ", error); + } + ); + }; + this.updateLogLevels = function(logComponents) { return $http.put(this.state.systemsbase + "/logmgmt/update", logComponents ).then( function (response) { @@ -616,6 +638,22 @@ app.controller('SystemController', function ($scope, $location, $http, $window, } } }; + $scope.addHaltoSettings = function (newhalname, newhalip) { + if($scope.bridge.settings.haladdress == null) { + $scope.bridge.settings.haladdress = { devices: [] }; + } + var newhal = {name: newhalname, ip: newhalip } + $scope.bridge.settings.haladdress.devices.push(newhal); + $scope.newhalname = null; + $scope.newhalip = null; + }; + $scope.removeHaltoSettings = function (halname, halip) { + for(var i = $scope.bridge.settings.haladdress.devices.length - 1; i >= 0; i--) { + if($scope.bridge.settings.haladdress.devices[i].name === halname && $scope.bridge.settings.haladdress.devices[i].ip === halip) { + $scope.bridge.settings.haladdress.devices.splice(i, 1); + } + } + }; $scope.bridgeReinit = function () { $scope.isInControl = false; bridgeService.reinit(); @@ -1270,6 +1308,131 @@ app.controller('HueController', function ($scope, $location, $http, bridgeServic }); +app.controller('HalController', function ($scope, $location, $http, bridgeService, ngDialog) { + $scope.bridge = bridgeService.state; + $scope.device = $scope.bridge.device; + $scope.device_dim_control = ""; + $scope.bulk = { devices: [] }; + bridgeService.viewHalDevices(); + $scope.imgButtonsUrl = "glyphicon glyphicon-plus"; + $scope.buttonsVisible = false; + + $scope.clearDevice = function () { + bridgeService.clearDevice(); + }; + + $scope.buildDeviceUrls = function (haldevice, dim_control) { + bridgeService.clearDevice(); + $scope.device.deviceType = "switch"; + $scope.device.name = haldevice.haldevicename; + $scope.device.targetDevice = haldevice.halname; + $scope.device.mapType = "halDevice"; + $scope.device.mapId = haldevice.haldevicename + "-" + haldevice.halname; + if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0) + $scope.device.dimUrl = "http://" + haldevice.veraaddress + + "/DeviceService!DeviceName=" + + haldevice.haldevicename + + "!DeviceCmd=SetDevice!DeviceValue=Dim!DevicePercent=" + + dim_control + + "?Token=" + + $scope.bridge.settings.haltoken; + else + $scope.device.dimUrl = "http://" + veradevice.veraaddress + + "/DeviceService!DeviceName=" + + haldevice.haldevicename + + "!DeviceCmd=SetDevice!DeviceValue=On?Token=" + + $scope.bridge.settings.haltoken; + $scope.device.onUrl = "http://" + veradevice.veraaddress + + "/DeviceService!DeviceName=" + + haldevice.haldevicename + + "!DeviceCmd=SetDevice!DeviceValue=On?Token=" + + $scope.bridge.settings.haltoken;; + $scope.device.offUrl = "http://" + veradevice.veraaddress + + "/DeviceService!DeviceName=" + + haldevice.haldevicename + + "!DeviceCmd=SetDevice!DeviceValue=Off?Token=" + + $scope.bridge.settings.haltoken;; + }; + + $scope.addDevice = function () { + if($scope.device.name == "" && $scope.device.onUrl == "") + return; + bridgeService.addDevice($scope.device).then( + function () { + $scope.clearDevice(); + bridgeService.viewDevices(); + bridgeService.viewHalDevices(); + }, + function (error) { + bridgeService.displayWarn("Error adding device: " + $scope.device.name, error) + } + ); + + }; + + $scope.bulkAddDevices = function(dim_control) { + var devicesList = []; + 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); + 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, + offUrl: $scope.device.offUrl, + headers: $scope.device.headers, + httpVerb: $scope.device.httpVerb, + contentType: $scope.device.contentType, + contentBody: $scope.device.contentBody, + contentBodyOff: $scope.device.contentBodyOff + }; + } + } + } + bridgeService.bulkAddDevice(devicesList); + $scope.clearDevice(); + bridgeService.viewDevices(); + bridgeService.HalVeraDevices(); + $scope.bulk = { devices: [] }; + }; + + $scope.toggleSelection = function toggleSelection(deviceId) { + var idx = $scope.bulk.devices.indexOf(deviceId); + + // is currently selected + if (idx > -1) { + $scope.bulk.devices.splice(idx, 1); + } + + // is newly selected + else { + $scope.bulk.devices.push(deviceId); + } + }; + + $scope.toggleButtons = function () { + $scope.buttonsVisible = !$scope.buttonsVisible; + if($scope.buttonsVisible) + $scope.imgButtonsUrl = "glyphicon glyphicon-minus"; + else + $scope.imgButtonsUrl = "glyphicon glyphicon-plus"; + }; + + $scope.deleteDeviceByMapId = function (id, mapType) { + $scope.bridge.mapandid = { id, mapType }; + ngDialog.open({ + template: 'deleteMapandIdDialog', + controller: 'DeleteMapandIdDialogCtrl', + className: 'ngdialog-theme-default' + }); + }; + +}); + app.controller('EditController', function ($scope, $location, $http, bridgeService) { $scope.bridge = bridgeService.state; $scope.device = $scope.bridge.device; diff --git a/src/main/resources/public/views/configuration.html b/src/main/resources/public/views/configuration.html index 5e224e3..c1b36eb 100644 --- a/src/main/resources/public/views/configuration.html +++ b/src/main/resources/public/views/configuration.html @@ -8,6 +8,7 @@
  • Harmony Devices
  • Nest
  • Hue Devices
  • +
  • HAL Devices
  • Manual Add
  • diff --git a/src/main/resources/public/views/haldevice.html b/src/main/resources/public/views/haldevice.html new file mode 100644 index 0000000..1056fce --- /dev/null +++ b/src/main/resources/public/views/haldevice.html @@ -0,0 +1,160 @@ + + +
    +
    +

    HAL Device List ({{bridge.haldevices.length}})

    +
    +
      +
    • +

      For any HAL Device, use the action buttons to generate the device addition information below automatically. + Then you can modify the name to anything you want that will be the keyword for Alexa. 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.

      +

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

      +

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

      + + + + + + + + + + + + + + + + + + +
      RowNameCategoryHALActions
      {{$index+1}} {{haldevice.haldevicename}}{{haldevice.haldevicetype}}{{haldevice.halname}} + +
      +
      +

      + +

      +
    • +
    +
    +

    Already Configured HAL Devices

    +
    +
      +
    • + + + + + + + + + + + + + + + + + + +
      RowNameCategoryHALActions
      {{$index+1}}{{haldevice.haldevicename}}{{haldevice.haldevicetype}}{{haldevice.halname}} + +
      +
      +
    • +
    +
    +
    +
    +

    Add Bridge Device for a HAL Device

    +
    +
      +
    • +
      +
      + + +
      + +
      + +
      +
      +
      + + +
      + +
      + +
      +
      +
      + + +
      + +
      +
      +
      +
      +
      + + +
      + +
      +
      + +
    • +
    +
    + diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index bea828d..6a090f6 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -169,6 +169,38 @@ + + HAL Names and IP Addresses + + + + + + + + + + + + + + + + + + +
    NameIPManage
    {{hal.name}}{{hal.ip}}
    + + + + HAL Token + + Nest Username