Merge branch 'master' into master

This commit is contained in:
diamond5170
2017-09-24 21:45:56 +03:00
committed by GitHub
37 changed files with 601 additions and 423 deletions

View File

@@ -201,43 +201,44 @@ 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();
while (userIterator.hasNext()) {
validUser = userIterator.next();
if (validUser.equals(aUser))
if (validUser.equals(aUser)) {
found = true;
log.debug("validateWhitelistUser: found a user <" + aUser + ">");
}
}
}
}
if(!found && !strict) {
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) {
return HueErrorResponse.createResponse("1", "/api/" + aUser, "unauthorized user", null, null, null).getTheErrors();
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();
}
Object anUser = securityDescriptor.getWhitelist().remove(DEPRACATED_INTERNAL_USER);
if(anUser != null)
setSettingsChanged(true);
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);
}
}

View File

@@ -12,6 +12,9 @@ public class BridgeSettingsDescriptor {
@SerializedName("upnpconfigaddress")
@Expose
private String upnpconfigaddress;
@SerializedName("useupnpiface")
@Expose
private boolean useupnpiface;
@SerializedName("serverport")
@Expose
private Integer serverport;
@@ -108,6 +111,7 @@ public class BridgeSettingsDescriptor {
public BridgeSettingsDescriptor() {
super();
this.upnpstrict = true;
this.useupnpiface = false;
this.traceupnp = false;
this.nestconfigured = false;
this.veraconfigured = false;
@@ -118,8 +122,11 @@ public class BridgeSettingsDescriptor {
this.halconfigured = false;
this.mqttconfigured = false;
this.hassconfigured = false;
this.domoticzconfigured = false;
this.somfyconfigured = false;
this.lifxconfigured = false;
this.farenheit = true;
this.whitelist = null;
this.securityData = null;
this.settingsChanged = false;
this.myechourl = "echo.amazon.com/#cards";
this.webaddress = "0.0.0.0";
@@ -131,6 +138,12 @@ public class BridgeSettingsDescriptor {
public void setUpnpConfigAddress(String upnpConfigAddress) {
this.upnpconfigaddress = upnpConfigAddress;
}
public boolean isUseupnpiface() {
return useupnpiface;
}
public void setUseupnpiface(boolean useupnpiface) {
this.useupnpiface = useupnpiface;
}
public Integer getServerPort() {
return serverport;
}
@@ -410,8 +423,10 @@ public class BridgeSettingsDescriptor {
List<NamedIP> devicesList = this.getHaladdress().getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
return false;
if(this.getHaltoken() == null || this.getHaltoken().equals(""))
return false;
if(devicesList.get(0).getPassword() == null || devicesList.get(0).getPassword().trim().isEmpty()) {
if(this.getHaltoken() == null || this.getHaltoken().equals(""))
return false;
}
return true;
}
public Boolean isValidMQTT() {
@@ -449,4 +464,15 @@ public class BridgeSettingsDescriptor {
public Boolean isValidLifx() {
return this.isLifxconfigured();
}
public void updateHue(NamedIP aHue) {
int indexHue = -1;
for( int i = 0; i < hueaddress.getDevices().size(); i++) {
if(hueaddress.getDevices().get(i).getName().equals(aHue.getName()))
indexHue = i;
}
if(indexHue >= 0) {
hueaddress.getDevices().set(indexHue, aHue);
this.setSettingsChanged(true);
}
}
}

View File

@@ -49,6 +49,7 @@ public class HABridge {
staticFileLocation("/public");
while(!bridgeSettings.getBridgeControl().isStop()) {
bridgeSettings.buildSettings();
bridgeSettings.getBridgeSecurity().removeTestUsers();
log.info("HA Bridge initializing....");
// sparkjava config directive to set ip address for the web server to listen on
ipAddress(bridgeSettings.getBridgeSettingsDescriptor().getWebaddress());

View File

@@ -18,9 +18,9 @@ public class HueApiResponse {
private Map<String, JsonObject> rules;
private HueConfig config;
public HueApiResponse(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion) {
public HueApiResponse(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion, boolean isLinkButtonPressed) {
super();
this.setConfig(HueConfig.createConfig(name, ipaddress, awhitelist, emulateHubVersion));
this.setConfig(HueConfig.createConfig(name, ipaddress, awhitelist, emulateHubVersion, isLinkButtonPressed));
this.setRules(new HashMap<>());
this.setSensors(new HashMap<>());
this.setSchedules(new HashMap<>());

View File

@@ -34,7 +34,7 @@ public class HueConfig
private String replacesbridgeid;
private Map<String, WhitelistEntry> whitelist;
public static HueConfig createConfig(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion) {
public static HueConfig createConfig(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion, boolean isLinkButtonPressed) {
HueConfig aConfig = new HueConfig();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
@@ -44,7 +44,7 @@ public class HueConfig
aConfig.setPortalservices(false);
aConfig.setGateway(ipaddress);
aConfig.setSwversion(emulateHubVersion);
aConfig.setLinkbutton(true);
aConfig.setLinkbutton(isLinkButtonPressed);
aConfig.setIpaddress(ipaddress);
aConfig.setProxyport(0);
aConfig.setSwupdate(Swupdate.createSwupdate());

View File

@@ -1,8 +1,8 @@
package com.bwssystems.HABridge.api.hue;
public class HueConstants {
public final static String HUB_VERSION = "01036659";
public final static String API_VERSION = "1.15.0";
public final static String HUB_VERSION = "1705121051";
public final static String API_VERSION = "1.19.0";
public final static String MODEL_ID = "BSB002";
public final static String UUID_PREFIX = "2f402f80-da50-11e1-9b23-";
}

View File

@@ -74,7 +74,8 @@ public class DeviceDescriptor{
@SerializedName("comments")
@Expose
private String comments;
@SerializedName("deviceState")
@Expose
private DeviceState deviceState;
public String getName() {

View File

@@ -61,6 +61,7 @@ public class DeviceRepository extends BackupHandler {
{
DeviceDescriptor list[] = gson.fromJson(jsonContent, DeviceDescriptor[].class);
for(int i = 0; i < list.length; i++) {
list[i].setDeviceState(null);
put(list[i].getId(), list[i]);
if(Integer.decode(list[i].getId()) > nextId) {
nextId = Integer.decode(list[i].getId());

View File

@@ -2,6 +2,7 @@ package com.bwssystems.HABridge.hue;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang3.Conversion;
@@ -83,7 +84,7 @@ public class BrightnessDecode {
replaceTarget = INTENSITY_PERCENT_HEX;
notDone = true;
} else if (request.contains(INTENSITY_DECIMAL_PERCENT)) {
replaceValue = String.format("%1.2f", decimalBrightness);
replaceValue = String.format(Locale.ROOT, "%1.2f", decimalBrightness);
replaceTarget = INTENSITY_DECIMAL_PERCENT;
notDone = true;
} else if (request.contains(INTENSITY_MATH_CLOSE)) {

View File

@@ -14,6 +14,9 @@ public class DeviceDataDecode {
private static final String DEVICE_MAPTYPE = "${device.mapType}";
private static final String DEVICE_DEVICETYPE = "${device.deviceType}";
private static final String DEVICE_TARGETDEVICE = "${device.targetDevice}";
private static final String DEVICE_REQUESTERADDRESS = "${device.requesterAddress}";
private static final String DEVICE_DESCRIPTION = "${device.description}";
private static final String DEVICE_COMMENTS = "${device.comments}";
public static String replaceDeviceData(String request, DeviceDescriptor device) {
if (request == null) {
@@ -58,6 +61,21 @@ public class DeviceDataDecode {
notDone = true;
}
if (request.contains(DEVICE_REQUESTERADDRESS)) {
request = request.replace(DEVICE_REQUESTERADDRESS, device.getRequesterAddress());
notDone = true;
}
if (request.contains(DEVICE_DESCRIPTION)) {
request = request.replace(DEVICE_DESCRIPTION, device.getDescription());
notDone = true;
}
if (request.contains(DEVICE_COMMENTS)) {
request = request.replace(DEVICE_COMMENTS, device.getComments());
notDone = true;
}
log.debug("Request <<" + request + ">>, not done: " + notDone);
}
return request;

View File

@@ -60,6 +60,7 @@ public class HueMulator {
validMapTypes = new DeviceMapTypes();
bridgeSettingMaster = bridgeMaster;
bridgeSettings = bridgeSettingMaster.getBridgeSettingsDescriptor();
homeManager= aHomeManager;
myHueHome = (HueHome) homeManager.findHome(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex]);
aGsonHandler = new GsonBuilder().create();
@@ -69,6 +70,7 @@ public class HueMulator {
public void setupServer() {
log.info("Hue emulator service started....");
before(HUE_CONTEXT + "/*", (request, response) -> {
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")) {
@@ -118,6 +120,17 @@ public class HueMulator {
log.debug("group add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body());
return "[{\"success\":{\"id\":\"1\"}}]";
});
// http://ip_address:port/api/:userid/groups/<groupid>/action
// Dummy handler
// Error forces Logitech Pop to fall back to individual light control
// instead of scene-based control.
put(HUE_CONTEXT + "/:userid/groups/:groupid/action", "application/json", (request, response) -> {
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.type("application/json");
response.status(HttpStatus.SC_OK);
log.debug("put action to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body());
return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]";
});
// http://ip_address:port/api/{userId}/scenes returns json objects of
// all scenes configured
get(HUE_CONTEXT + "/:userid/scenes", "application/json", (request, response) -> {
@@ -742,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) {
@@ -750,15 +765,15 @@ 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.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton());
log.debug("api response config <<<" + aGsonHandler.toJson(apiResponse.getConfig()) + ">>>");
return apiResponse.getConfig();
}
@@ -766,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.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));

View File

@@ -1,10 +1,11 @@
package com.bwssystems.HABridge.plugins.hal;
import com.bwssystems.HABridge.NamedIP;
public class HalDevice {
private String haldevicetype;
private String haldevicename;
private String haladdress;
private String halname;
private NamedIP haladdress;
private DeviceElements buttons;
public String getHaldevicetype() {
return haldevicetype;
@@ -18,18 +19,12 @@ public class HalDevice {
public void setHaldevicename(String haldevicename) {
this.haldevicename = haldevicename;
}
public String getHaladdress() {
public NamedIP getHaladdress() {
return haladdress;
}
public void setHaladdress(String haladdress) {
public void setHaladdress(NamedIP haladdress) {
this.haladdress = haladdress;
}
public String getHalname() {
return halname;
}
public void setHalname(String halname) {
this.halname = halname;
}
public DeviceElements getButtons() {
return buttons;
}

View File

@@ -13,8 +13,14 @@ import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.Home;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.HABridge.api.CallItem;
import com.bwssystems.HABridge.api.hue.HueError;
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.bwssystems.HABridge.hue.BrightnessDecode;
import com.bwssystems.HABridge.hue.DeviceDataDecode;
import com.bwssystems.HABridge.hue.MultiCommandUtil;
import com.bwssystems.HABridge.hue.TimeDecode;
import com.google.gson.Gson;
public class HalHome implements Home {
private static final Logger log = LoggerFactory.getLogger(HalHome.class);
@@ -30,7 +36,7 @@ public class HalHome implements Home {
public Object getItems(String type) {
if(!validHal)
return null;
log.debug("consolidating devices for hues");
log.debug("consolidating devices for HALs");
List<HalDevice> theResponse = null;
Iterator<String> keys = hals.keySet().iterator();
List<HalDevice> deviceList = new ArrayList<HalDevice>();
@@ -106,8 +112,63 @@ public class HalHome implements Home {
@Override
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
// Not a device handler
return null;
boolean halFound = false;
String responseString = null;
String theUrl = anItem.getItem().getAsString();
if(theUrl != null && !theUrl.isEmpty () && theUrl.contains("http")) {
String intermediate = theUrl.substring(theUrl.indexOf("://") + 3);
String hostPortion = intermediate.substring(0, intermediate.indexOf('/'));
// String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1);
// String hostAddr = null;
// String port = null;
// if (hostPortion.contains(":")) {
// hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
// port = hostPortion.substring(intermediate.indexOf(':') + 1);
// } else
// hostAddr = hostPortion;
log.debug("executing HUE api request to Http "
+ (anItem.getHttpVerb() == null ? "GET" : anItem.getHttpVerb()) + ": "
+ anItem.getItem().getAsString());
String anUrl = null;
anUrl = BrightnessDecode.calculateReplaceIntensityValue(intermediate, intensity, targetBri, targetBriInc, false);
anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device);
anUrl = TimeDecode.replaceTimeValue(anUrl);
for (Map.Entry<String, HalInfo> entry : hals.entrySet())
{
if(entry.getValue().getHalAddress().getIp().equals(hostPortion)) {
halFound = true;
if(entry.getValue().getHalAddress().getSecure()!= null && entry.getValue().getHalAddress().getSecure())
anUrl = "https://" + anUrl;
else
anUrl = "http://" + anUrl;
if(!anUrl.contains("?Token="))
anUrl = anUrl + "?Token=" + entry.getValue().getHalAddress().getPassword();
log.debug("executing HUE api request to Http "
+ (anItem.getHttpVerb() == null ? "GET" : anItem.getHttpVerb()) + ": "
+ anUrl);
if (entry.getValue().deviceCommand(anUrl) == null) {
log.warn("Error on calling hal to change device state: " + anUrl);
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
"Error on calling url to change device state", "/lights/"
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
}
}
}
}
if(!halFound) {
log.warn("No HAL found to call: " + theUrl);
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
"No HAL found.", "/lights/"
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
}
return responseString;
}
@Override

View File

@@ -35,13 +35,13 @@ public class HalInfo {
private static final String IRDATA_TYPE = "IrData";
private HTTPHandler httpClient;
private NamedIP halAddress;
private String theToken;
public HalInfo(NamedIP addressName, String aGivenToken) {
super();
httpClient = new HTTPHandler();
halAddress = addressName;
theToken = aGivenToken;
if(halAddress.getPassword() == null || halAddress.getPassword().trim().isEmpty())
halAddress.setPassword(aGivenToken);
}
public List<HalDevice> getLights() {
@@ -98,12 +98,16 @@ public class HalInfo {
String theUrl = null;
String theData;
theUrl = "http://" + halAddress.getIp() + apiType + theToken;
if(halAddress.getSecure()!= null && halAddress.getSecure())
theUrl = "https://";
else
theUrl = "http://";
theUrl = theUrl + halAddress.getIp() + apiType + halAddress.getPassword();
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
if(theData != null) {
log.debug("GET " + deviceType + " HalApiResponse - data: " + theData);
theHalApiResponse = new Gson().fromJson(theData, DeviceElements.class);
if(theHalApiResponse.getDeviceElements() == null) {
if(theHalApiResponse == null || theHalApiResponse.getDeviceElements() == null) {
StatusDescription theStatus = new Gson().fromJson(theData, StatusDescription.class);
if(theStatus.getStatus() == null) {
log.warn("Cannot get an devices for type " + deviceType + " for hal " + halAddress.getName() + " as response is not parsable.");
@@ -121,8 +125,10 @@ public class HalInfo {
HalDevice aNewHalDevice = new HalDevice();
aNewHalDevice.setHaldevicetype(deviceType);
aNewHalDevice.setHaldevicename(theDevice.getDeviceName());
aNewHalDevice.setHaladdress(halAddress.getIp());
aNewHalDevice.setHalname(halAddress.getName());
NamedIP theaddress = new NamedIP();
theaddress.setIp(halAddress.getIp());
theaddress.setName(halAddress.getName());
aNewHalDevice.setHaladdress(theaddress);
deviceList.add(aNewHalDevice);
}
@@ -145,7 +151,11 @@ public class HalInfo {
deviceList = new ArrayList<HalDevice>();
while (theHalDevices.hasNext()) {
HalDevice theHalDevice = theHalDevices.next();
theUrl = "http://" + halAddress.getIp() + IRBUTTON_REQUEST + TextStringFormatter.forQuerySpaceUrl(theHalDevice.getHaldevicename()) + TOKEN_REQUEST + theToken;
if(halAddress.getSecure()!= null && halAddress.getSecure())
theUrl = "https://";
else
theUrl = "http://";
theUrl = theUrl + halAddress.getIp() + IRBUTTON_REQUEST + TextStringFormatter.forQuerySpaceUrl(theHalDevice.getHaldevicename()) + TOKEN_REQUEST + halAddress.getPassword();
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
if (theData != null) {
log.debug("GET IrData for IR Device " + theHalDevice.getHaldevicename() + " HalApiResponse - data: " + theData);
@@ -177,6 +187,12 @@ public class HalInfo {
return deviceList;
}
public String deviceCommand(String theUrl) {
String theData = null;
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
return theData;
}
public NamedIP getHalAddress() {
return halAddress;
}
@@ -190,6 +206,5 @@ public class HalInfo {
httpClient.closeHandler();
httpClient = null;
halAddress = null;
theToken = null;
}
}

View File

@@ -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;
}
}

View File

@@ -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() + " with pressTime of: " + aDeviceButton.getPressTime() + " 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;
}

View File

@@ -181,7 +181,7 @@ public class HarmonyHome implements Home {
aMultiUtil.setTheDelay(anItem.getDelay());
else
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
log.debug("pressing button: " + deviceButtons[z].getDevice() + " - " + deviceButtons[z].getButton() + " - iteration: " + String.valueOf(z) + " - count: " + String.valueOf(y));
log.debug("pressing button: " + deviceButtons[z].getDevice() + " - " + deviceButtons[z].getButton() + " with pressTime of: " + deviceButtons[z].getPressTime() + " - iteration: " + String.valueOf(z) + " - count: " + String.valueOf(y));
if(deviceButtons[z].getHub() == null || deviceButtons[z].getHub().isEmpty())
deviceButtons[z].setHub(device.getTargetDevice());
HarmonyHandler myHarmony = getHarmonyHandler(deviceButtons[z].getHub());

View File

@@ -6,6 +6,7 @@ import java.net.URISyntaxException;
import java.nio.charset.Charset;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
@@ -67,73 +68,67 @@ public class HTTPHandler {
if (requestBody != null)
putRequest.setEntity(requestBody);
request = putRequest;
}
else
} else
request = new HttpGet(theURI);
} catch (IllegalArgumentException e) {
log.warn("Error creating outbound http request: IllegalArgumentException in log", e);
return null;
}
log.debug("Making outbound call in doHttpRequest: " + request);
log.debug("Making outbound call in doHttpRequest: <<<" + request.toString() + ">>>");
if (headers != null && headers.length > 0) {
for (int i = 0; i < headers.length; i++) {
request.setHeader(headers[i].getName(), headers[i].getValue());
}
}
HttpResponse response;
try {
for(int retryCount = 0; retryCount < 2; retryCount++) {
HttpResponse response = null;
for (int retryCount = 0; retryCount < 2; retryCount++) {
try {
response = httpClient.execute(request);
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute (" + retryCount + ") on URL responded: "
+ response.getStatusLine().getStatusCode());
if (response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
if (response.getEntity() != null) {
try {
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
// content
// for
// data
EntityUtils.consume(response.getEntity()); // close out
// inputstream
// ignore
// content
} catch (Exception e) {
log.debug("Error ocurred in handling response entity after successful call, still responding success. "
+ e.getMessage(), e);
}
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
}
} catch (ClientProtocolException e) {
log.warn("Client Protocol Exception received, retyring....");
} catch (IOException e) {
log.warn("Error calling out to HA gateway: IOException in log", e);
retryCount = 2;
}
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute (" + retryCount + ") on URL responded: "
+ response.getStatusLine().getStatusCode());
if (response != null && response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
retryCount = 2;
} else if (response != null) {
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: "
+ response.getStatusLine());
if (response.getStatusLine().getStatusCode() == 504) {
log.warn("HTTP response code was 504, retrying...");
} else
retryCount = 2;
} else {
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: " + response.getStatusLine());
try {
String someContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
// content
// for
// data
EntityUtils.consume(response.getEntity()); // close out
// inputstream
// ignore
// content
log.debug("Unsuccessfull response - The http response is <<<" + someContent + ">>>");
} catch (Exception e) {
//noop
}
if (response.getStatusLine().getStatusCode() == 504) {
log.warn("HTTP response code was 504, retrying...");
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// noop
}
}
else
retryCount = 2;
}
if (response != null && response.getEntity() != null) {
try {
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
// content
// for
// data
EntityUtils.consume(response.getEntity()); // close out
// inputstream
// ignore
// content
} catch (Exception e) {
log.debug("Error ocurred in handling response entity after successful call, still responding success. "
+ e.getMessage(), e);
}
}
if(retryCount < 2) {
theContent = null;
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// noop
}
}
} catch (IOException e) {
log.warn("Error calling out to HA gateway: IOException in log", e);
}
return theContent;
}

View File

@@ -24,9 +24,11 @@ public class HueHome implements Home {
private Map<String, HueInfo> hues;
private Boolean validHue;
private Gson aGsonHandler;
private BridgeSettings theBridgeSettings;
public HueHome(BridgeSettings bridgeSettings) {
super();
theBridgeSettings = bridgeSettings;
createHome(bridgeSettings);
}
@@ -113,12 +115,19 @@ public class HueHome implements Home {
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getHueaddress().getDevices().iterator();
while(theList.hasNext()) {
NamedIP aHue = theList.next();
hues.put(aHue.getName(), new HueInfo(aHue));
hues.put(aHue.getName(), new HueInfo(aHue, this));
}
aGsonHandler = new GsonBuilder().create();
}
return this;
}
protected void updateHue(NamedIP aHue) {
theBridgeSettings.getBridgeSettingsDescriptor().updateHue(aHue);
if(theBridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged()) {
theBridgeSettings.updateConfigFile();
}
}
@Override
public void closeHome() {

View File

@@ -27,12 +27,14 @@ public class HueInfo {
private static final Logger log = LoggerFactory.getLogger(HueInfo.class);
private HTTPHandler httpClient;
private NamedIP hueAddress;
private HueHome myHome;
public static final String HUE_REQUEST = "/api";
public HueInfo(NamedIP addressName) {
public HueInfo(NamedIP addressName, HueHome theHome) {
super();
httpClient = new HTTPHandler();
hueAddress = addressName;
myHome = theHome;
}
public HueApiResponse getHueApiResponse() {
@@ -62,7 +64,7 @@ public class HueInfo {
// ignore
}
}
theUrl = "http://" + hueAddress.getIp() + HueUtil.HUE_REQUEST + "/" + hueAddress.getUsername();
theUrl = "http://" + hueAddress.getIp() + HUE_REQUEST + "/" + hueAddress.getUsername();
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
if(theData != null) {
log.debug("GET HueApiResponse - data: " + theData);
@@ -118,6 +120,7 @@ public class HueInfo {
else {
SuccessUserResponse[] theResponses = new Gson().fromJson(theBody, SuccessUserResponse[].class); //read content for data, SuccessUserResponse[].class);
hueAddress.setUsername(theResponses[0].getSuccess().getUsername());
myHome.updateHue(hueAddress);
}
}
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content

View File

@@ -1,56 +0,0 @@
package com.bwssystems.HABridge.plugins.hue;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.api.SuccessUserResponse;
import com.bwssystems.HABridge.api.UserCreateRequest;
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
import com.google.gson.Gson;
public class HueUtil {
private static final Logger log = LoggerFactory.getLogger(HueUtil.class);
public static final String HUE_REQUEST = "/api";
public static final String registerWithHue(HTTPHandler anHttpHandler, String ipAddress, String aName, String theUser) {
UserCreateRequest theLogin = new UserCreateRequest();
theLogin.setDevicetype("HABridge#MyMachine");
HttpPost postRequest = new HttpPost("http://" + ipAddress + HUE_REQUEST);
ContentType parsedContentType = ContentType.parse("application/json");
StringEntity requestBody = new StringEntity(new Gson().toJson(theLogin), parsedContentType);
HttpResponse response = null;
postRequest.setEntity(requestBody);
HttpClient anHttpClient = anHttpHandler.getHttpClient();
try {
response = anHttpClient.execute(postRequest);
log.debug("POST execute on URL responded: " + response.getStatusLine().getStatusCode());
if(response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300){
String theBody = EntityUtils.toString(response.getEntity());
log.debug("registerWithHue response data: " + theBody);
if(theBody.contains("[{\"error\":")) {
if(theBody.contains("link button not")) {
log.warn("registerWithHue needs link button pressed on HUE bridge: " + aName);
}
else
log.warn("registerWithHue returned an unexpected error: " + theBody);
}
else {
SuccessUserResponse[] theResponses = new Gson().fromJson(theBody, SuccessUserResponse[].class); //read content for data, SuccessUserResponse[].class);
theUser = theResponses[0].getSuccess().getUsername();
}
}
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
} catch (IOException e) {
log.warn("Error logging into HUE: IOException in log", e);
}
return theUser;
}
}

View File

@@ -13,11 +13,12 @@ import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.NamedIP;
import java.util.Optional;
public class MQTTHandler {
private static final Logger log = LoggerFactory.getLogger(MQTTHandler.class);
private NamedIP myConfig;
private MqttClient myClient;
private int qos = 1;
public MQTTHandler(NamedIP aConfig) {
super();
@@ -40,20 +41,19 @@ public class MQTTHandler {
}
try {
myClient.connect(connOpts);
} catch (MqttSecurityException e) {
log.error("Could not connect MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
} catch (MqttException e) {
log.error("Could not connect MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
}
}
public void publishMessage(String topic, String content) {
public void publishMessage(String topic, String content, Integer qos, Boolean retain) {
MqttMessage message = new MqttMessage(StringEscapeUtils.unescapeJava(content).getBytes());
message.setQos(qos);
message.setQos(Optional.ofNullable(qos).orElse(1));
message.setRetained(Optional.ofNullable(retain).orElse(false));
try {
myClient.publish(topic, message);
} catch (MqttPersistenceException e) {
log.error("Could not publish to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
} catch (MqttException e) {
log.error("Could not publish to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
}

View File

@@ -37,9 +37,7 @@ public class MQTTHome implements Home {
return;
log.debug("Shutting down MQTT handlers.");
if(handlers != null && !handlers.isEmpty()) {
Iterator<String> keys = handlers.keySet().iterator();
while(keys.hasNext()) {
String key = keys.next();
for (String key : handlers.keySet()) {
handlers.get(key).shutdown();
}
}
@@ -108,7 +106,7 @@ public class MQTTHome implements Home {
if (mqttHandler == null) {
log.warn("Should not get here, no mqtt hanlder available");
} else {
mqttHandler.publishMessage(mqttMessages[y].getTopic(), mqttMessages[y].getMessage());
mqttHandler.publishMessage(mqttMessages[y].getTopic(), mqttMessages[y].getMessage(), mqttMessages[y].getQos(), mqttMessages[y].getRetain());
}
}
}
@@ -130,13 +128,10 @@ public class MQTTHome implements Home {
aGsonHandler =
new GsonBuilder()
.create();
handlers = new HashMap<String, MQTTHandler>();
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getMqttaddress().getDevices().iterator();
while(theList.hasNext()) {
NamedIP aClientConfig = theList.next();
handlers = new HashMap<>();
for (NamedIP aClientConfig : bridgeSettings.getBridgeSettingsDescriptor().getMqttaddress().getDevices()) {
MQTTHandler aHandler = new MQTTHandler(aClientConfig);
if(aHandler != null)
handlers.put(aClientConfig.getName(), aHandler);
handlers.put(aClientConfig.getName(), aHandler);
}
}
return this;

View File

@@ -6,6 +6,8 @@ public class MQTTMessage {
private String message;
private Integer delay;
private Integer count;
private Integer qos;
private Boolean retain;
public String getClientId() {
return clientId;
}
@@ -36,4 +38,19 @@ public class MQTTMessage {
public void setCount(Integer count) {
this.count = count;
}
public Integer getQos() {
return qos;
}
public void setQos(Integer qos) {
this.qos = qos;
}
public Boolean getRetain() {
return retain;
}
public void setRetain(Boolean retain) {
this.retain = retain;
}
}

View File

@@ -25,6 +25,7 @@ public class UpnpListener {
private String responseAddress;
private boolean strict;
private boolean traceupnp;
private boolean useUpnpIface;
private BridgeControlDescriptor bridgeControl;
private String bridgeId;
private String bridgeSNUUID;
@@ -74,6 +75,7 @@ public class UpnpListener {
responseAddress = theSettings.getUpnpConfigAddress();
strict = theSettings.isUpnpStrict();
traceupnp = theSettings.isTraceupnp();
useUpnpIface = theSettings.isUseupnpiface();
bridgeControl = theControl;
aHueConfig = HuePublicConfig.createConfig("temp", responseAddress, HueConstants.HUB_VERSION);
bridgeId = aHueConfig.getBridgeid();
@@ -114,7 +116,10 @@ public class UpnpListener {
else
log.debug(name + " ... has addr " + addr);
if (InetAddressUtils.isIPv4Address(addr.getHostAddress())) {
IPsPerNic++;
if(!useUpnpIface)
IPsPerNic++;
else if(addr.getHostAddress().equals(responseAddress))
IPsPerNic++;
}
}
log.debug("Checking " + name + " to our interface set");