mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-16 18:24:36 +00:00
Adding long press
This commit is contained in:
10
README.md
10
README.md
@@ -61,17 +61,17 @@ ATTENTION: This requires JDK 1.8 to run
|
||||
ATTENTION: Due to port 80 being the default, Linux restricts this to super user. Use the instructions below.
|
||||
|
||||
```
|
||||
java -jar ha-bridge-4.5.5.jar
|
||||
java -jar ha-bridge-4.5.6.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.5.5.jar is in your /home/pi/habridge directory.
|
||||
Create the directory and make sure that ha-bridge-4.5.6.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.5.5/ha-bridge-4.5.5.jar
|
||||
pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v4.5.6/ha-bridge-4.5.6.jar
|
||||
```
|
||||
|
||||
#### System Control Setup on a pi (preferred)
|
||||
@@ -92,7 +92,7 @@ After=network.target
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/home/pi/habridge
|
||||
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-4.5.5.jar
|
||||
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-4.5.6.jar
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -127,7 +127,7 @@ Then cut and past this, modify any locations that are not correct
|
||||
```
|
||||
cd /home/pi/habridge
|
||||
rm /home/pi/habridge/habridge-log.txt
|
||||
nohup java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-4.5.5.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.5.6.jar > /home/pi/habridge/habridge-log.txt 2>&1 &
|
||||
|
||||
chmod 777 /home/pi/habridge/habridge-log.txt
|
||||
```
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>4.5.5a</version>
|
||||
<version>4.5.5b</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
@@ -33,7 +33,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.bwssytems</groupId>
|
||||
<artifactId>harmony-java-client</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<version>1.1.5</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
||||
@@ -201,12 +201,15 @@ public class BridgeSecurity {
|
||||
public void setSettingsChanged(boolean settingsChanged) {
|
||||
this.settingsChanged = settingsChanged;
|
||||
}
|
||||
public Map<String, WhitelistEntry> getWhitelist() {
|
||||
return securityDescriptor.getWhitelist();
|
||||
}
|
||||
|
||||
public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
|
||||
String validUser = null;
|
||||
boolean found = false;
|
||||
if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null")
|
||||
&& !aUser.equalsIgnoreCase("")) {
|
||||
&& !aUser.equalsIgnoreCase("") && !aUser.equals(DEPRACATED_INTERNAL_USER)) {
|
||||
if (securityDescriptor.getWhitelist() != null) {
|
||||
Set<String> theUserIds = securityDescriptor.getWhitelist().keySet();
|
||||
Iterator<String> userIterator = theUserIds.iterator();
|
||||
@@ -218,26 +221,24 @@ public class BridgeSecurity {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!found && !strict) {
|
||||
log.debug("validateWhitelistUser: a user was not found and it is not strict rules <" + aUser + "> being created");
|
||||
newWhitelistUser(aUser, userDescription);
|
||||
|
||||
found = true;
|
||||
if(!found && !strict) {
|
||||
log.debug("validateWhitelistUser: a user was not found and it is not strict rules <" + aUser + "> being created");
|
||||
newWhitelistUser(aUser, userDescription);
|
||||
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
log.debug("validateWhitelistUser: a user was not found and it is strict rules <" + aUser + ">");
|
||||
log.debug("validateWhitelistUser: a user was not found and strict rules is set to: " + strict + "for user <" + aUser + ">");
|
||||
return HueErrorResponse.createResponse("1", "/api/" + aUser == null ? "" : aUser, "unauthorized user", null, null, null).getTheErrors();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void newWhitelistUser(String aUser, String userDescription) {
|
||||
if(aUser.equals(DEPRACATED_INTERNAL_USER))
|
||||
return;
|
||||
private void newWhitelistUser(String aUser, String userDescription) {
|
||||
if (securityDescriptor.getWhitelist() == null) {
|
||||
securityDescriptor.setWhitelist(new HashMap<>());
|
||||
}
|
||||
@@ -278,9 +279,8 @@ public class BridgeSecurity {
|
||||
Iterator<Entry<String, WhitelistEntry>> it = securityDescriptor.getWhitelist().entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, WhitelistEntry> pair = it.next();
|
||||
it.remove(); // avoids a ConcurrentModificationException
|
||||
if(pair.getValue().getName().equals(TEST_USER_TYPE)) {
|
||||
securityDescriptor.getWhitelist().remove(pair.getKey());
|
||||
it.remove(); // avoids a ConcurrentModificationException
|
||||
setSettingsChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class HueMulator {
|
||||
public void setupServer() {
|
||||
log.info("Hue emulator service started....");
|
||||
before(HUE_CONTEXT + "/*", (request, response) -> {
|
||||
log.debug("HueMulator GET called on api/* with request <" + request.pathInfo() + ">");
|
||||
log.debug("HueMulator " + request.requestMethod() + " called on api/* with request <<<" + request.pathInfo() + ">>>, and body <<<" + request.body() + ">>>");
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSecure()) {
|
||||
String pathInfo = request.pathInfo();
|
||||
if(pathInfo != null && pathInfo.contains(HUE_CONTEXT + "/devices")) {
|
||||
@@ -755,7 +755,9 @@ public class HueMulator {
|
||||
log.debug("hue api user create requested for device type: " + aDeviceType + " and username: " + newUser + (followingSlash ? " /api/ called" : ""));
|
||||
return "[{\"success\":{\"username\":\"" + newUser + "\"}}]";
|
||||
}
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("1", "/api/", "unauthorized user", null, null, null).getTheErrors());
|
||||
else
|
||||
log.debug("user add toContinue was false, returning not authorized");
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("101", "/api/", "link button not pressed", null, null, null).getTheErrors());
|
||||
}
|
||||
|
||||
private Object getConfig(String userId, String ipAddress) {
|
||||
@@ -763,14 +765,14 @@ public class HueMulator {
|
||||
log.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + ipAddress);
|
||||
log.debug("hue api config requested: " + userId + " from " + ipAddress);
|
||||
if (bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) != null) {
|
||||
log.debug("hue api config requested, No User supplied, returning public config");
|
||||
log.debug("hue api config requested, User invalid, returning public config");
|
||||
HuePublicConfig apiResponse = HuePublicConfig.createConfig("Philips hue",
|
||||
bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion());
|
||||
return apiResponse;
|
||||
}
|
||||
|
||||
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(),
|
||||
bridgeSettings.getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton());
|
||||
bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton());
|
||||
log.debug("api response config <<<" + aGsonHandler.toJson(apiResponse.getConfig()) + ">>>");
|
||||
return apiResponse.getConfig();
|
||||
}
|
||||
@@ -779,11 +781,13 @@ public class HueMulator {
|
||||
private Object getFullState(String userId, String ipAddress) {
|
||||
log.debug("hue api full state requested: " + userId + " from " + ipAddress);
|
||||
HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors != null)
|
||||
if (theErrors != null) {
|
||||
log.debug("full state error occurred <<<" + aGsonHandler.toJson(theErrors) + ">>>");
|
||||
return theErrors;
|
||||
}
|
||||
|
||||
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(),
|
||||
bridgeSettings.getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton());
|
||||
bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton());
|
||||
apiResponse.setLights((Map<String, DeviceResponse>) this.lightsListHandler(userId, ipAddress));
|
||||
apiResponse.setGroups((Map<String, GroupResponse>) this.groupsListHandler(userId, ipAddress));
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ public class ButtonPress {
|
||||
private Integer delay;
|
||||
private Integer count;
|
||||
private String hub;
|
||||
private Integer pressTime;
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
@@ -43,4 +44,10 @@ public class ButtonPress {
|
||||
public void setHub(String hub) {
|
||||
this.hub = hub;
|
||||
}
|
||||
public Integer getPressTime() {
|
||||
return pressTime;
|
||||
}
|
||||
public void setPressTime(Integer pressTime) {
|
||||
this.pressTime = pressTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class HarmonyHandler {
|
||||
}
|
||||
|
||||
public Boolean startActivity(RunActivity anActivity) {
|
||||
log.debug("Harmony api start activity requested for: " + anActivity.getName() + " noop mode: " + noopCalls);
|
||||
log.debug("Harmony api start activity requested for: " + anActivity.getName() + " for a hub: " + anActivity.getHub() + " noop mode: " + noopCalls);
|
||||
if (anActivity.isValid()) {
|
||||
try {
|
||||
if (noopCalls || devMode) {
|
||||
@@ -72,7 +72,7 @@ public class HarmonyHandler {
|
||||
devResponse.setCurrentActivity(devResponse.getConfig().getActivityByName(anActivity.getName()));
|
||||
}
|
||||
|
||||
log.info("noop mode: Harmony api start activity requested for: " + anActivity.getName());
|
||||
log.info("noop mode: Harmony api start activity requested for: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
||||
}
|
||||
else
|
||||
harmonyClient.startActivity(Integer.parseInt(anActivity.getName()));
|
||||
@@ -81,12 +81,12 @@ public class HarmonyHandler {
|
||||
if (!noopCalls)
|
||||
harmonyClient.startActivityByName(anActivity.getName());
|
||||
} catch (IllegalArgumentException ei) {
|
||||
log.error("Error in finding activity: " + anActivity.getName());
|
||||
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.error("Error in finding activity: " + anActivity.getName());
|
||||
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -94,26 +94,30 @@ public class HarmonyHandler {
|
||||
}
|
||||
|
||||
public Boolean pressButton(ButtonPress aDeviceButton) {
|
||||
log.debug("Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton() + " noop mode: " + noopCalls);
|
||||
log.debug("Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub() + " noop mode: " + noopCalls);
|
||||
if (aDeviceButton.isValid()) {
|
||||
try {
|
||||
if (noopCalls || devMode) {
|
||||
log.info("noop mode: Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton());
|
||||
log.info("noop mode: Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton() +
|
||||
" with a pressTime of: " + aDeviceButton.getPressTime() + " for a hub: " + aDeviceButton.getHub());
|
||||
}
|
||||
else
|
||||
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton());
|
||||
|
||||
else {
|
||||
if(aDeviceButton.getPressTime() != null && aDeviceButton.getPressTime() > 0)
|
||||
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton(), aDeviceButton.getPressTime());
|
||||
else
|
||||
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
try {
|
||||
if (!noopCalls)
|
||||
harmonyClient.pressButton(aDeviceButton.getDevice(), aDeviceButton.getButton());
|
||||
} catch (IllegalArgumentException ei) {
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton());
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton());
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1930,10 +1930,17 @@ app.controller('HarmonyController', function ($scope, $location, bridgeService,
|
||||
$location.path('/editdevice');
|
||||
};
|
||||
|
||||
$scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton) {
|
||||
$scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton, onpresstime, offpresstime) {
|
||||
var actionOn = angular.fromJson(onbutton);
|
||||
var actionOff = angular.fromJson(offbutton);
|
||||
var postCmd = "\"}";
|
||||
if(onpresstime !== undefined && onpresstime !== "0")
|
||||
postCmd = "\",\"pressTime\":" + onpresstime + "}";
|
||||
onpayload = "{\"device\":\"" + harmonydevice.device.id + "\",\"button\":\"" + actionOn.command + "\",\"hub\":\"" + harmonydevice.hub + "\"}";
|
||||
if(offpresstime !== undefined && offpresstime !== "0")
|
||||
postCmd = "\",\"pressTime\":" + offpresstime + "}";
|
||||
else
|
||||
postCmd = "\"}";
|
||||
offpayload = "{\"device\":\"" + harmonydevice.device.id + "\",\"button\":\"" + actionOff.command + "\",\"hub\":\"" + harmonydevice.hub + "\"}";
|
||||
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, actionOn.command, harmonydevice.device.label, harmonydevice.hub, "button", "harmonyButton", null, null);
|
||||
@@ -3058,7 +3065,7 @@ app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
$scope.onDevices = null;
|
||||
$scope.dimDevices = null;
|
||||
$scope.offDevices = null;
|
||||
if ($scope.device !== undefined && $scope.device.name !== undefined) {
|
||||
if ($scope.devicec && $scope.device.name !== undefined) {
|
||||
if($scope.bridge.device.onUrl !== undefined)
|
||||
$scope.onDevices = bridgeService.getCallObjects($scope.bridge.device.onUrl);
|
||||
if($scope.bridge.device.dimUrl !== undefined)
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
'Add Bridge Device' to finish that selection setup. The 'Already
|
||||
Configured Harmony Buttons' list below will show what is already
|
||||
setup for your Harmony Hubs.</p>
|
||||
<p>Note: The press time areas are for adding a press time in milliseconds to handle various long press scenarios. If left alone it will default to the original 200ms.</p>
|
||||
|
||||
<scrollable-table watch="bridge.harmonydevices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
@@ -47,7 +48,9 @@
|
||||
<th sortable-header col="id" comparator-fn="comparatorNumber">Id</th>
|
||||
<th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th>
|
||||
<th>On Button</th>
|
||||
<th>On Press Time</th>
|
||||
<th>Off Button</th>
|
||||
<th>Off Press Time</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -64,6 +67,10 @@
|
||||
value="{{funcon.action}}">{{funcon.label}}</option>
|
||||
</optgroup>
|
||||
</select></td>
|
||||
<td>
|
||||
<textarea class="form-control" id="onpresstime"
|
||||
ng-model="onpresstime" placeholder="On Press Time in ms"></textarea>
|
||||
</td>
|
||||
<td><select name="device-ctrloff" id="device-ctrloff"
|
||||
ng-model="devicectrloff">
|
||||
<optgroup ng-repeat="ctrloff in harmonydevice.device.controlGroup"
|
||||
@@ -72,9 +79,13 @@
|
||||
value="{{funcoff.action}}">{{funcoff.label}}</option>
|
||||
</optgroup>
|
||||
</select></td>
|
||||
<td>
|
||||
<textarea class="form-control" id="offpresstime"
|
||||
ng-model="offpresstime" placeholder="Off Press Time in ms"></textarea>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildButtonUrls(harmonydevice, devicectrlon, devicectrloff)">Build
|
||||
ng-click="buildButtonUrls(harmonydevice, devicectrlon, devicectrloff, onpresstime, offpresstime)">Build
|
||||
A Button</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user