mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-19 00:20:26 +00:00
Completed Hue passthru
This commit is contained in:
@@ -154,6 +154,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setVeraconfigured(theBridgeSettings.isValidVera());
|
||||
theBridgeSettings.setHarmonyconfigured(theBridgeSettings.isValidHarmony());
|
||||
theBridgeSettings.setNestConfigured(theBridgeSettings.isValidNest());
|
||||
theBridgeSettings.setHueconfigured(theBridgeSettings.isValidHue());
|
||||
if(serverPortOverride != null)
|
||||
theBridgeSettings.setServerPort(serverPortOverride);
|
||||
setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-");
|
||||
@@ -189,6 +190,8 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setNestConfigured(aBridgeSettings.isValidNest());
|
||||
theBridgeSettings.setNumberoflogmessages(aBridgeSettings.getNumberoflogmessages());
|
||||
theBridgeSettings.setFarenheit(aBridgeSettings.isFarenheit());
|
||||
theBridgeSettings.setHueaddress(aBridgeSettings.getHueaddress());
|
||||
theBridgeSettings.setHueconfigured(aBridgeSettings.isValidHue());
|
||||
}
|
||||
|
||||
public void save(BridgeSettingsDescriptor newBridgeSettings) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.bwssystems.HABridge.upnp.UpnpListener;
|
||||
import com.bwssystems.HABridge.upnp.UpnpSettingsResource;
|
||||
import com.bwssystems.NestBridge.NestHome;
|
||||
import com.bwssystems.harmony.HarmonyHome;
|
||||
import com.bwssystems.hue.HueHome;
|
||||
|
||||
public class HABridge {
|
||||
|
||||
@@ -34,6 +35,7 @@ public class HABridge {
|
||||
DeviceResource theResources;
|
||||
HarmonyHome harmonyHome;
|
||||
NestHome nestHome;
|
||||
HueHome hueHome;
|
||||
HueMulator theHueMulator;
|
||||
UpnpSettingsResource theSettingResponder;
|
||||
UpnpListener theUpnpListener;
|
||||
@@ -62,8 +64,10 @@ public class HABridge {
|
||||
harmonyHome = new HarmonyHome(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
//setup the nest connection if available
|
||||
nestHome = new NestHome(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
//setup the hue passtrhu configuration if available
|
||||
hueHome = new HueHome(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
// setup the class to handle the resource setup rest api
|
||||
theResources = new DeviceResource(bridgeSettings.getBridgeSettingsDescriptor(), harmonyHome, nestHome);
|
||||
theResources = new DeviceResource(bridgeSettings.getBridgeSettingsDescriptor(), harmonyHome, nestHome, hueHome);
|
||||
// setup the class to handle the hue emulator rest api
|
||||
theHueMulator = new HueMulator(bridgeSettings.getBridgeSettingsDescriptor(), theResources.getDeviceRepository(), harmonyHome, nestHome);
|
||||
theHueMulator.setupServer();
|
||||
@@ -77,6 +81,8 @@ public class HABridge {
|
||||
theUpnpListener = new UpnpListener(bridgeSettings.getBridgeSettingsDescriptor(), bridgeSettings.getBridgeControl());
|
||||
if(theUpnpListener.startListening())
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") reinitialization requessted....");
|
||||
else
|
||||
bridgeSettings.getBridgeControl().setStop(true);
|
||||
|
||||
bridgeSettings.getBridgeControl().setReinit(false);
|
||||
stop();
|
||||
|
||||
@@ -42,7 +42,7 @@ public class DeviceResource {
|
||||
private HueHome hueHome;
|
||||
private static final Set<String> supportedVerbs = new HashSet<>(Arrays.asList("get", "put", "post"));
|
||||
|
||||
public DeviceResource(BridgeSettingsDescriptor theSettings, HarmonyHome theHarmonyHome, NestHome aNestHome) {
|
||||
public DeviceResource(BridgeSettingsDescriptor theSettings, HarmonyHome theHarmonyHome, NestHome aNestHome, HueHome aHueHome) {
|
||||
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
||||
|
||||
if(theSettings.isValidVera())
|
||||
@@ -61,7 +61,7 @@ public class DeviceResource {
|
||||
this.nestHome = null;
|
||||
|
||||
if(theSettings.isValidHue())
|
||||
this.hueHome = new HueHome(theSettings);
|
||||
this.hueHome = aHueHome;
|
||||
else
|
||||
this.hueHome = null;
|
||||
setupEndpoints();
|
||||
|
||||
@@ -345,7 +345,7 @@ public class HueMulator {
|
||||
HueDeviceIdentifier deviceId = new Gson().fromJson(url, HueDeviceIdentifier.class);
|
||||
|
||||
// make call
|
||||
if (!doHttpRequest("http://"+deviceId.getIpAddress()+"/api/"+userId+"/lights/"+deviceId.getDeviceId(), HttpPut.METHOD_NAME, device.getContentType(), request.body())) {
|
||||
if (!doHttpRequest("http://"+deviceId.getIpAddress()+"/api/"+userId+"/lights/"+deviceId.getDeviceId()+"/state", HttpPut.METHOD_NAME, device.getContentType(), request.body())) {
|
||||
log.warn("Error on calling url to change device state: " + url);
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Error on calling url to change device state\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
|
||||
}
|
||||
@@ -605,63 +605,63 @@ public class HueMulator {
|
||||
if(body.contains("bri"))
|
||||
{
|
||||
if(justState)
|
||||
responseString = responseString + "true}}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/bri\":" + state.getBri() + "}}";
|
||||
responseString = responseString + "true}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/bri\":" + state.getBri() + "}";
|
||||
justState = false;
|
||||
}
|
||||
|
||||
if(body.contains("ct"))
|
||||
{
|
||||
if(justState)
|
||||
responseString = responseString + "true}}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/ct\":" + state.getCt() + "}}";
|
||||
responseString = responseString + "true}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/ct\":" + state.getCt() + "}";
|
||||
justState = false;
|
||||
}
|
||||
|
||||
if(body.contains("xy"))
|
||||
{
|
||||
if(justState)
|
||||
responseString = responseString + "true}}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/xy\":" + state.getXy() + "}}";
|
||||
responseString = responseString + "true}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/xy\":" + state.getXy() + "}";
|
||||
justState = false;
|
||||
}
|
||||
|
||||
if(body.contains("hue"))
|
||||
{
|
||||
if(justState)
|
||||
responseString = responseString + "true}}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/hue\":" + state.getHue() + "}}";
|
||||
responseString = responseString + "true}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/hue\":" + state.getHue() + "}";
|
||||
justState = false;
|
||||
}
|
||||
|
||||
if(body.contains("sat"))
|
||||
{
|
||||
if(justState)
|
||||
responseString = responseString + "true}}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/sat\":" + state.getSat() + "}}";
|
||||
responseString = responseString + "true}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/sat\":" + state.getSat() + "}";
|
||||
justState = false;
|
||||
}
|
||||
|
||||
if(body.contains("colormode"))
|
||||
{
|
||||
if(justState)
|
||||
responseString = responseString + "true}}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/colormode\":" + state.getColormode() + "}}";
|
||||
responseString = responseString + "true}";
|
||||
responseString = responseString + ",{\"success\":{\"/lights/" + lightId + "/state/colormode\":" + state.getColormode() + "}";
|
||||
justState = false;
|
||||
}
|
||||
|
||||
if(justState)
|
||||
{
|
||||
if (state.isOn()) {
|
||||
responseString = responseString + "true}}]";
|
||||
responseString = responseString + "true}";
|
||||
state.setBri(255);
|
||||
} else if (body.contains("false")) {
|
||||
responseString = responseString + "false}}";
|
||||
responseString = responseString + "false}";
|
||||
state.setBri(0);
|
||||
}
|
||||
}
|
||||
|
||||
responseString = responseString + "]";
|
||||
responseString = responseString + "}]";
|
||||
|
||||
return responseString;
|
||||
|
||||
|
||||
@@ -94,8 +94,10 @@ public class UpnpListener {
|
||||
log.info("UPNP Discovery Listener - ended, restart found");
|
||||
if(bridgeControl.isStop())
|
||||
log.info("UPNP Discovery Listener - ended, stop found");
|
||||
if(!bridgeControl.isStop()&& !bridgeControl.isReinit())
|
||||
if(!bridgeControl.isStop()&& !bridgeControl.isReinit()) {
|
||||
log.info("UPNP Discovery Listener - ended, error found");
|
||||
return false;
|
||||
}
|
||||
return bridgeControl.isReinit();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,24 +5,24 @@ import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
|
||||
public class HueDevice {
|
||||
private DeviceResponse device;
|
||||
private String hubaddress;
|
||||
private String hubname;
|
||||
private String hueaddress;
|
||||
private String huename;
|
||||
public DeviceResponse getDevice() {
|
||||
return device;
|
||||
}
|
||||
public void setDevice(DeviceResponse device) {
|
||||
this.device = device;
|
||||
public void setDevice(DeviceResponse adevice) {
|
||||
this.device = adevice;
|
||||
}
|
||||
public String getHubaddress() {
|
||||
return hubaddress;
|
||||
public String getHueaddress() {
|
||||
return hueaddress;
|
||||
}
|
||||
public void setHubaddress(String hubaddress) {
|
||||
this.hubaddress = hubaddress;
|
||||
public void setHueaddress(String ahueaddress) {
|
||||
this.hueaddress = ahueaddress;
|
||||
}
|
||||
public String getHubname() {
|
||||
return hubname;
|
||||
public String getHuename() {
|
||||
return huename;
|
||||
}
|
||||
public void setHubname(String hubname) {
|
||||
this.hubname = hubname;
|
||||
public void setHuename(String ahuename) {
|
||||
this.huename = ahuename;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||
|
||||
public class HueHome {
|
||||
private static final Logger log = LoggerFactory.getLogger(HueHome.class);
|
||||
@@ -21,7 +22,7 @@ public class HueHome {
|
||||
hues = new HashMap<String, HueInfo>();
|
||||
if(!bridgeSettings.isValidHue())
|
||||
return;
|
||||
Iterator<NamedIP> theList = bridgeSettings.getVeraAddress().getDevices().iterator();
|
||||
Iterator<NamedIP> theList = bridgeSettings.getHueaddress().getDevices().iterator();
|
||||
while(theList.hasNext()) {
|
||||
NamedIP aHue = theList.next();
|
||||
hues.put(aHue.getName(), new HueInfo(aHue));
|
||||
@@ -34,13 +35,16 @@ public class HueHome {
|
||||
ArrayList<HueDevice> deviceList = new ArrayList<HueDevice>();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
Map<String, DeviceResponse> theDevices = hues.get(key).getHueApiResponse().getLights();
|
||||
HueApiResponse theResponse = hues.get(key).getHueApiResponse();
|
||||
if(theResponse != null) {
|
||||
Map<String, DeviceResponse> theDevices = theResponse.getLights();
|
||||
if(theDevices != null) {
|
||||
Iterator<String> deviceKeys = theDevices.keySet().iterator();
|
||||
while(deviceKeys.hasNext()) {
|
||||
HueDevice aNewHueDevice = new HueDevice();
|
||||
aNewHueDevice.setDevice(theDevices.get(deviceKeys.next()));
|
||||
aNewHueDevice.setHubaddress("");
|
||||
aNewHueDevice.setHueaddress(hues.get(key).getHueAddress().getIp());
|
||||
aNewHueDevice.setHuename(key);
|
||||
deviceList.add(aNewHueDevice);
|
||||
}
|
||||
}
|
||||
@@ -49,6 +53,9 @@ public class HueHome {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
log.warn("Cannot get lights for Hue with name: " + key);
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.google.gson.Gson;
|
||||
public class HueInfo {
|
||||
private static final Logger log = LoggerFactory.getLogger(HueInfo.class);
|
||||
private HttpClient httpClient;
|
||||
private static final String HUE_REQUEST = "/api/habridge/config";
|
||||
private static final String HUE_REQUEST = "/api/habridge";
|
||||
private NamedIP hueAddress;
|
||||
|
||||
public HueInfo(NamedIP addressName) {
|
||||
@@ -58,4 +58,12 @@ public class HueInfo {
|
||||
}
|
||||
return theContent;
|
||||
}
|
||||
|
||||
public NamedIP getHueAddress() {
|
||||
return hueAddress;
|
||||
}
|
||||
|
||||
public void setHueAddress(NamedIP hueAddress) {
|
||||
this.hueAddress = hueAddress;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ app.config(function ($routeProvider) {
|
||||
}).when('/nest', {
|
||||
templateUrl: 'views/nestactions.html',
|
||||
controller: 'NestController'
|
||||
}).when('/huedevices', {
|
||||
templateUrl: 'views/huedevice.html',
|
||||
controller: 'HueController'
|
||||
}).otherwise({
|
||||
templateUrl: 'views/configuration.html',
|
||||
controller: 'ViewingController'
|
||||
@@ -48,8 +51,12 @@ app.service('bridgeService', function ($http, $window, ngToast) {
|
||||
|
||||
this.displayWarn = function(errorTitle, error) {
|
||||
var toastContent = errorTitle;
|
||||
if(error != null && typeof(error) != 'undefined')
|
||||
if(error != null && typeof(error) != 'undefined') {
|
||||
if(error.data != null)
|
||||
toastContent = toastContent + " " + error.data.message + " with status: " + error.statusText + " - " + error.status;
|
||||
else
|
||||
toastContent = error;
|
||||
}
|
||||
ngToast.create({
|
||||
className: "warning",
|
||||
dismissButton: true,
|
||||
@@ -589,6 +596,22 @@ app.controller('SystemController', function ($scope, $location, $http, $window,
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.addHuetoSettings = function (newhuename, newhueip) {
|
||||
if($scope.bridge.settings.hueaddress == null) {
|
||||
$scope.bridge.settings.hueaddress = { devices: [] };
|
||||
}
|
||||
var newhue = {name: newhuename, ip: newhueip }
|
||||
$scope.bridge.settings.hueaddress.devices.push(newhue);
|
||||
$scope.newhuename = null;
|
||||
$scope.newhueip = null;
|
||||
};
|
||||
$scope.removeHuetoSettings = function (huename, hueip) {
|
||||
for(var i = $scope.bridge.settings.hueaddress.devices.length - 1; i >= 0; i--) {
|
||||
if($scope.bridge.settings.hueaddress.devices[i].name === huename && $scope.bridge.settings.hueaddress.devices[i].ip === hueip) {
|
||||
$scope.bridge.settings.hueaddress.devices.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.bridgeReinit = function () {
|
||||
$scope.isInControl = false;
|
||||
bridgeService.reinit();
|
||||
@@ -1113,13 +1136,12 @@ app.controller('HueController', function ($scope, $location, $http, bridgeServic
|
||||
$scope.buildDeviceUrls = function (huedevice) {
|
||||
bridgeService.clearDevice();
|
||||
$scope.device.deviceType = "switch";
|
||||
$scope.device.name = huedevice.name;
|
||||
$scope.device.name = huedevice.device.name;
|
||||
$scope.device.targetDevice = huedevice.huename;
|
||||
$scope.device.contentType = "application/json";
|
||||
$scope.device.mapType = "hueDevice";
|
||||
$scope.device.mapId = huedevice.id;
|
||||
$scope.device.onUrl = "http://" + veradevice.veraaddress + ":" + $scope.vera.port
|
||||
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
|
||||
+ veradevice.id;
|
||||
$scope.device.mapId = huedevice.device.uniqueid;
|
||||
$scope.device.onUrl = "{\"ipAddress\":\"" + huedevice.hueaddress + "\",\"deviceId\":\"" + huedevice.device.uniqueid +"\"}";
|
||||
};
|
||||
|
||||
$scope.addDevice = function () {
|
||||
@@ -1400,6 +1422,34 @@ app.filter('unavailableNestItemId', function(bridgeService) {
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('availableHueDeviceId', function(bridgeService) {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
if(input == null)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(!bridgeService.findDeviceByMapId(input[i].device.uniqueid, input[i].huename, "hueDevice")){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('unavailableHueDeviceId', function(bridgeService) {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
if(input == null)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(bridgeService.findDeviceByMapId(input[i].device.uniqueid, input[i].huename, "hueDevice")){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('configuredButtons', function() {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
<option value="harmonyButton">Harmony Button</option>
|
||||
<option value="nestHomeAway">Nest Home Status</option>
|
||||
<option value="nestThermoSet">Nest Thermostat</option>
|
||||
<option value="hueDevice">Hue Device</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-danger" ng-click="clearDevice()">
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
</thead>
|
||||
<tr ng-repeat="huedevice in bridge.huedevices | availableHueDeviceId">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]" value="{{huedevice.id}}" ng-checked="bulk.devices.indexOf(huedevice.id) > -1" ng-click="toggleSelection(huedevice.id)"> {{huedevice.name}}</td>
|
||||
<td>{{huedevice.uniqueid}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]" value="{{huedevice.id}}" ng-checked="bulk.devices.indexOf(huedevice.id) > -1" ng-click="toggleSelection(huedevice.id)"> {{huedevice.device.name}}</td>
|
||||
<td>{{huedevice.device.uniqueid}}</td>
|
||||
<td>{{huedevice.huename}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
@@ -71,8 +71,8 @@
|
||||
</thead>
|
||||
<tr ng-repeat="huedevice in bridge.huedevices | unavailableHueDeviceId">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{huedevice.name}}</td>
|
||||
<td>{{huedevice.uniqueid}}</td>
|
||||
<td>{{huedevice.device.name}}</td>
|
||||
<td>{{huedevice.device.uniqueid}}</td>
|
||||
<td>{{huedevice.huename}}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
|
||||
@@ -143,6 +143,33 @@
|
||||
<td><input id="bridge-settings-harmonypwd" class="form-control" type="password"
|
||||
ng-model="bridge.settings.harmonypwd" placeholder="thepassword"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hue Names and IP Addresses</td>
|
||||
<td><table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>IP</th>
|
||||
<th>Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="hue in bridge.settings.hueaddress.devices">
|
||||
<td>{{hue.name}}</td>
|
||||
<td>{{hue.ip}}</td>
|
||||
<td><button class="btn btn-danger" type="submit"
|
||||
ng-click="removeHuetoSettings(hue.name, hue.ip)">Del</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input id="bridge-settings-next-hue-name" class="form-control" type="text"
|
||||
ng-model="newhuename" placeholder="A Hue"></td>
|
||||
<td><input id="bridge-settings-next-hue-ip" class="form-control" type="text"
|
||||
ng-model="newhueip" placeholder="192.168.1.3"></td>
|
||||
<td><button class="btn btn-success" type="submit"
|
||||
ng-click="addHuetoSettings(newhuename, newhueip)">Add</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Button Press Sleep Interval (ms)</td>
|
||||
<td><input id="bridge-settings-buttonsleep" class="form-control" type="number" name="input"
|
||||
|
||||
Reference in New Issue
Block a user