Adding long press

This commit is contained in:
Admin
2017-06-20 16:35:03 -05:00
parent 0900fec60f
commit 63ac729967
8 changed files with 73 additions and 40 deletions

View File

@@ -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. 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 ### 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 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:~ $ mkdir habridge
pi@raspberrypi:~ $ cd 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) #### System Control Setup on a pi (preferred)
@@ -92,7 +92,7 @@ After=network.target
[Service] [Service]
Type=simple Type=simple
WorkingDirectory=/home/pi/habridge 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] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
@@ -127,7 +127,7 @@ Then cut and past this, modify any locations that are not correct
``` ```
cd /home/pi/habridge cd /home/pi/habridge
rm /home/pi/habridge/habridge-log.txt 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 chmod 777 /home/pi/habridge/habridge-log.txt
``` ```

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId> <groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId> <artifactId>ha-bridge</artifactId>
<version>4.5.5a</version> <version>4.5.5b</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>HA Bridge</name> <name>HA Bridge</name>
@@ -33,7 +33,7 @@
<dependency> <dependency>
<groupId>com.github.bwssytems</groupId> <groupId>com.github.bwssytems</groupId>
<artifactId>harmony-java-client</artifactId> <artifactId>harmony-java-client</artifactId>
<version>1.1.1</version> <version>1.1.5</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>

View File

@@ -201,12 +201,15 @@ public class BridgeSecurity {
public void setSettingsChanged(boolean settingsChanged) { public void setSettingsChanged(boolean settingsChanged) {
this.settingsChanged = settingsChanged; this.settingsChanged = settingsChanged;
} }
public Map<String, WhitelistEntry> getWhitelist() {
return securityDescriptor.getWhitelist();
}
public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) { public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
String validUser = null; String validUser = null;
boolean found = false; boolean found = false;
if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null") if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null")
&& !aUser.equalsIgnoreCase("")) { && !aUser.equalsIgnoreCase("") && !aUser.equals(DEPRACATED_INTERNAL_USER)) {
if (securityDescriptor.getWhitelist() != null) { if (securityDescriptor.getWhitelist() != null) {
Set<String> theUserIds = securityDescriptor.getWhitelist().keySet(); Set<String> theUserIds = securityDescriptor.getWhitelist().keySet();
Iterator<String> userIterator = theUserIds.iterator(); Iterator<String> userIterator = theUserIds.iterator();
@@ -218,7 +221,6 @@ public class BridgeSecurity {
} }
} }
} }
}
if(!found && !strict) { if(!found && !strict) {
log.debug("validateWhitelistUser: a user was not found and it is not strict rules <" + aUser + "> being created"); log.debug("validateWhitelistUser: a user was not found and it is not strict rules <" + aUser + "> being created");
@@ -226,18 +228,17 @@ public class BridgeSecurity {
found = true; found = true;
} }
}
if (!found) { 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 HueErrorResponse.createResponse("1", "/api/" + aUser == null ? "" : aUser, "unauthorized user", null, null, null).getTheErrors();
} }
return null; return null;
} }
public void newWhitelistUser(String aUser, String userDescription) { private void newWhitelistUser(String aUser, String userDescription) {
if(aUser.equals(DEPRACATED_INTERNAL_USER))
return;
if (securityDescriptor.getWhitelist() == null) { if (securityDescriptor.getWhitelist() == null) {
securityDescriptor.setWhitelist(new HashMap<>()); securityDescriptor.setWhitelist(new HashMap<>());
} }
@@ -278,9 +279,8 @@ public class BridgeSecurity {
Iterator<Entry<String, WhitelistEntry>> it = securityDescriptor.getWhitelist().entrySet().iterator(); Iterator<Entry<String, WhitelistEntry>> it = securityDescriptor.getWhitelist().entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry<String, WhitelistEntry> pair = it.next(); Map.Entry<String, WhitelistEntry> pair = it.next();
it.remove(); // avoids a ConcurrentModificationException
if(pair.getValue().getName().equals(TEST_USER_TYPE)) { if(pair.getValue().getName().equals(TEST_USER_TYPE)) {
securityDescriptor.getWhitelist().remove(pair.getKey()); it.remove(); // avoids a ConcurrentModificationException
setSettingsChanged(true); setSettingsChanged(true);
} }
} }

View File

@@ -70,7 +70,7 @@ public class HueMulator {
public void setupServer() { public void setupServer() {
log.info("Hue emulator service started...."); log.info("Hue emulator service started....");
before(HUE_CONTEXT + "/*", (request, response) -> { 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()) { if(bridgeSettingMaster.getBridgeSecurity().isSecure()) {
String pathInfo = request.pathInfo(); String pathInfo = request.pathInfo();
if(pathInfo != null && pathInfo.contains(HUE_CONTEXT + "/devices")) { 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" : "")); log.debug("hue api user create requested for device type: " + aDeviceType + " and username: " + newUser + (followingSlash ? " /api/ called" : ""));
return "[{\"success\":{\"username\":\"" + newUser + "\"}}]"; 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) { 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.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + ipAddress);
log.debug("hue api config requested: " + userId + " from " + ipAddress); log.debug("hue api config requested: " + userId + " from " + ipAddress);
if (bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) != null) { 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", HuePublicConfig apiResponse = HuePublicConfig.createConfig("Philips hue",
bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion()); bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion());
return apiResponse; return apiResponse;
} }
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), 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()) + ">>>"); log.debug("api response config <<<" + aGsonHandler.toJson(apiResponse.getConfig()) + ">>>");
return apiResponse.getConfig(); return apiResponse.getConfig();
} }
@@ -779,11 +781,13 @@ public class HueMulator {
private Object getFullState(String userId, String ipAddress) { private Object getFullState(String userId, String ipAddress) {
log.debug("hue api full state requested: " + userId + " from " + ipAddress); log.debug("hue api full state requested: " + userId + " from " + ipAddress);
HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); 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; return theErrors;
}
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), 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.setLights((Map<String, DeviceResponse>) this.lightsListHandler(userId, ipAddress));
apiResponse.setGroups((Map<String, GroupResponse>) this.groupsListHandler(userId, ipAddress)); apiResponse.setGroups((Map<String, GroupResponse>) this.groupsListHandler(userId, ipAddress));

View File

@@ -6,6 +6,7 @@ public class ButtonPress {
private Integer delay; private Integer delay;
private Integer count; private Integer count;
private String hub; private String hub;
private Integer pressTime;
public String getDevice() { public String getDevice() {
return device; return device;
} }
@@ -43,4 +44,10 @@ public class ButtonPress {
public void setHub(String hub) { public void setHub(String hub) {
this.hub = hub; this.hub = hub;
} }
public Integer getPressTime() {
return pressTime;
}
public void setPressTime(Integer pressTime) {
this.pressTime = pressTime;
}
} }

View File

@@ -62,7 +62,7 @@ public class HarmonyHandler {
} }
public Boolean startActivity(RunActivity anActivity) { 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()) { if (anActivity.isValid()) {
try { try {
if (noopCalls || devMode) { if (noopCalls || devMode) {
@@ -72,7 +72,7 @@ public class HarmonyHandler {
devResponse.setCurrentActivity(devResponse.getConfig().getActivityByName(anActivity.getName())); 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 else
harmonyClient.startActivity(Integer.parseInt(anActivity.getName())); harmonyClient.startActivity(Integer.parseInt(anActivity.getName()));
@@ -81,12 +81,12 @@ public class HarmonyHandler {
if (!noopCalls) if (!noopCalls)
harmonyClient.startActivityByName(anActivity.getName()); harmonyClient.startActivityByName(anActivity.getName());
} catch (IllegalArgumentException ei) { } 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; return false;
} }
} }
} else { } else {
log.error("Error in finding activity: " + anActivity.getName()); log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
return false; return false;
} }
@@ -94,26 +94,30 @@ public class HarmonyHandler {
} }
public Boolean pressButton(ButtonPress aDeviceButton) { 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()) { if (aDeviceButton.isValid()) {
try { try {
if (noopCalls || devMode) { 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 {
if(aDeviceButton.getPressTime() != null && aDeviceButton.getPressTime() > 0)
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton(), aDeviceButton.getPressTime());
else else
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton()); harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton());
}
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
try { try {
if (!noopCalls) if (!noopCalls)
harmonyClient.pressButton(aDeviceButton.getDevice(), aDeviceButton.getButton()); harmonyClient.pressButton(aDeviceButton.getDevice(), aDeviceButton.getButton());
} catch (IllegalArgumentException ei) { } 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; return false;
} }
} }
} else { } 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; return false;
} }

View File

@@ -1930,10 +1930,17 @@ app.controller('HarmonyController', function ($scope, $location, bridgeService,
$location.path('/editdevice'); $location.path('/editdevice');
}; };
$scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton) { $scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton, onpresstime, offpresstime) {
var actionOn = angular.fromJson(onbutton); var actionOn = angular.fromJson(onbutton);
var actionOff = angular.fromJson(offbutton); 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 + "\"}"; 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 + "\"}"; 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); 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.onDevices = null;
$scope.dimDevices = null; $scope.dimDevices = null;
$scope.offDevices = 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) if($scope.bridge.device.onUrl !== undefined)
$scope.onDevices = bridgeService.getCallObjects($scope.bridge.device.onUrl); $scope.onDevices = bridgeService.getCallObjects($scope.bridge.device.onUrl);
if($scope.bridge.device.dimUrl !== undefined) if($scope.bridge.device.dimUrl !== undefined)

View File

@@ -37,6 +37,7 @@
'Add Bridge Device' to finish that selection setup. The 'Already 'Add Bridge Device' to finish that selection setup. The 'Already
Configured Harmony Buttons' list below will show what is already Configured Harmony Buttons' list below will show what is already
setup for your Harmony Hubs.</p> 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"> <scrollable-table watch="bridge.harmonydevices">
<table class="table table-bordered table-striped table-hover"> <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="id" comparator-fn="comparatorNumber">Id</th>
<th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th> <th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th>
<th>On Button</th> <th>On Button</th>
<th>On Press Time</th>
<th>Off Button</th> <th>Off Button</th>
<th>Off Press Time</th>
<th>Build Actions</th> <th>Build Actions</th>
</tr> </tr>
</thead> </thead>
@@ -64,6 +67,10 @@
value="{{funcon.action}}">{{funcon.label}}</option> value="{{funcon.action}}">{{funcon.label}}</option>
</optgroup> </optgroup>
</select></td> </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" <td><select name="device-ctrloff" id="device-ctrloff"
ng-model="devicectrloff"> ng-model="devicectrloff">
<optgroup ng-repeat="ctrloff in harmonydevice.device.controlGroup" <optgroup ng-repeat="ctrloff in harmonydevice.device.controlGroup"
@@ -72,9 +79,13 @@
value="{{funcoff.action}}">{{funcoff.label}}</option> value="{{funcoff.action}}">{{funcoff.label}}</option>
</optgroup> </optgroup>
</select></td> </select></td>
<td>
<textarea class="form-control" id="offpresstime"
ng-model="offpresstime" placeholder="Off Press Time in ms"></textarea>
</td>
<td> <td>
<button class="btn btn-success" type="submit" <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> A Button</button>
</td> </td>
</tr> </tr>