mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-16 18:24:36 +00:00
Updates for RC2 fixing FHEM issues, Fiabaro Issues, adding functionality
for color tests, and sending multiple requests based on the Hue API body.
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>5.2.0RC1</version>
|
||||
<version>5.2.0RC2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
|
||||
@@ -80,7 +80,10 @@ public class DeviceDescriptor{
|
||||
@SerializedName("deviceState")
|
||||
@Expose
|
||||
private DeviceState deviceState;
|
||||
|
||||
@SerializedName("onFirstDim")
|
||||
@Expose
|
||||
private boolean onFirstDim;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -275,6 +278,14 @@ public class DeviceDescriptor{
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public boolean isOnFirstDim() {
|
||||
return onFirstDim;
|
||||
}
|
||||
|
||||
public void setOnFirstDim(boolean onFirstDim) {
|
||||
this.onFirstDim = onFirstDim;
|
||||
}
|
||||
|
||||
public boolean containsType(String aType) {
|
||||
if(aType == null)
|
||||
return false;
|
||||
|
||||
@@ -1096,10 +1096,11 @@ public class HueMulator {
|
||||
DeviceState state = null;
|
||||
Integer targetBri = null;
|
||||
Integer targetBriInc = null;
|
||||
MultiCommandUtil aMultiUtil = new MultiCommandUtil();
|
||||
aMultiUtil.setTheDelay(bridgeSettings.getButtonsleep());
|
||||
aMultiUtil.setDelayDefault(bridgeSettings.getButtonsleep());
|
||||
aMultiUtil.setSetCount(1);
|
||||
boolean isColorRequest = false;
|
||||
boolean isDimRequest = false;
|
||||
boolean isOnRequest = false;
|
||||
boolean previousError = false;
|
||||
ColorData colorData = null;
|
||||
log.debug("hue state change requested: " + userId + " from " + ipAddress + " body: " + body);
|
||||
HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors != null) {
|
||||
@@ -1125,136 +1126,127 @@ public class HueMulator {
|
||||
"Could not find device.", "/lights/" + lightId, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
|
||||
if (body.contains("\"bri_inc\"")) {
|
||||
targetBriInc = new Integer(theStateChanges.getBri_inc());
|
||||
}
|
||||
else if (body.contains("\"bri\"")) {
|
||||
targetBri = new Integer(theStateChanges.getBri());
|
||||
}
|
||||
|
||||
state = device.getDeviceState();
|
||||
if (state == null) {
|
||||
state = DeviceState.createDeviceState(device.isColorDevice());
|
||||
device.setDeviceState(state);
|
||||
}
|
||||
|
||||
if (targetBri != null || targetBriInc != null) {
|
||||
url = device.getDimUrl();
|
||||
if (body.contains("\"bri_inc\"")) {
|
||||
targetBriInc = new Integer(theStateChanges.getBri_inc());
|
||||
isDimRequest = true;
|
||||
}
|
||||
else if (body.contains("\"bri\"")) {
|
||||
targetBri = new Integer(theStateChanges.getBri());
|
||||
isDimRequest = true;
|
||||
}
|
||||
|
||||
if (url == null || url.length() == 0)
|
||||
url = device.getOnUrl();
|
||||
} else {
|
||||
if (body.contains("\"xy\"") || body.contains("\"ct\"") || body.contains("\"hue\"")) {
|
||||
url = device.getColorUrl();
|
||||
} else if (theStateChanges.isOn()) {
|
||||
if (body.contains("\"xy\"") || body.contains("\"ct\"") || body.contains("\"hue\"") || body.contains("\"xy_inc\"") || body.contains("\"ct_inc\"") || body.contains("\"hue_inc\"")) {
|
||||
List<Double> xy = theStateChanges.getXy();
|
||||
List<Double> xyInc = theStateChanges.getXy_inc();
|
||||
Integer ct = theStateChanges.getCt();
|
||||
Integer ctInc = theStateChanges.getCt_inc();
|
||||
if (xy != null && xy.size() == 2) {
|
||||
colorData = new ColorData(ColorData.ColorMode.XY, xy);
|
||||
} else if (xyInc != null && xyInc.size() == 2) {
|
||||
List<Double> current = state.getXy();
|
||||
current.set(0, current.get(0) + xyInc.get(0));
|
||||
current.set(1, current.get(1) + xyInc.get(1));
|
||||
colorData = new ColorData(ColorData.ColorMode.XY, current);
|
||||
} else if (ct != null && ct != 0) {
|
||||
colorData = new ColorData(ColorData.ColorMode.CT, ct);
|
||||
} else if (ctInc != null && ctInc != 0) {
|
||||
colorData = new ColorData(ColorData.ColorMode.CT, state.getCt() + ctInc);
|
||||
}
|
||||
if(colorData != null)
|
||||
isColorRequest = true;
|
||||
}
|
||||
|
||||
if (body.contains("\"on\"")) {
|
||||
isOnRequest = true;
|
||||
}
|
||||
|
||||
if(isOnRequest || (isDimRequest && device.isOnFirstDim() && !device.getDeviceState().isOn())) {
|
||||
if (theStateChanges.isOn()) {
|
||||
url = device.getOnUrl();
|
||||
} else if (!theStateChanges.isOn()) {
|
||||
url = device.getOffUrl();
|
||||
}
|
||||
}
|
||||
|
||||
// code for backwards compatibility
|
||||
if(device.getMapType() != null && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
if(url == null)
|
||||
url = device.getOnUrl();
|
||||
}
|
||||
if (url != null && !url.equals("")) {
|
||||
if (!url.startsWith("[")) {
|
||||
if (url.startsWith("{\"item"))
|
||||
url = "[" + url + "]";
|
||||
else {
|
||||
if(url.startsWith("{"))
|
||||
url = "[{\"item\":" + url + "}]";
|
||||
else
|
||||
url = "[{\"item\":\"" + url + "\"}]";
|
||||
}
|
||||
} else if(!url.startsWith("[{\"item\""))
|
||||
url = "[{\"item\":" + url + "}]";
|
||||
|
||||
log.debug("Decode Json for url items: " + url);
|
||||
CallItem[] callItems = null;
|
||||
try {
|
||||
callItems = aGsonHandler.fromJson(url, CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
log.warn("Could not decode Json for url items: " + lightId + " for hue state change request: " + userId + " from "
|
||||
+ ipAddress + " body: " + body + " url items: " + url);
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/lights/" + lightId,
|
||||
"Could decode json in request", "/lights/" + lightId, null, null).getTheErrors(), HueError[].class);
|
||||
// code for backwards compatibility
|
||||
if(device.getMapType() != null && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
if(url == null)
|
||||
url = device.getOnUrl();
|
||||
}
|
||||
|
||||
for (int i = 0; callItems != null && i < callItems.length; i++) {
|
||||
if (!ignoreRequester) {
|
||||
if(!filterByRequester(device.getRequesterAddress(), ipAddress) || !filterByRequester(callItems[i].getFilterIPs(), ipAddress)) {
|
||||
log.warn("filter for requester address not present in: (device)" + device.getRequesterAddress() + " OR then (item)" + callItems[i].getFilterIPs() + " with request ip of: " + ipAddress);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (callItems[i].getCount() != null && callItems[i].getCount() > 0)
|
||||
aMultiUtil.setSetCount(callItems[i].getCount());
|
||||
else
|
||||
aMultiUtil.setSetCount(1);
|
||||
// code for backwards compatibility
|
||||
if((callItems[i].getType() == null || callItems[i].getType().trim().isEmpty())) {
|
||||
if(validMapTypes.validateType(device.getMapType()))
|
||||
callItems[i].setType(device.getMapType().trim());
|
||||
else if(validMapTypes.validateType(device.getDeviceType()))
|
||||
callItems[i].setType(device.getDeviceType().trim());
|
||||
else
|
||||
callItems[i].setType(DeviceMapTypes.CUSTOM_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}
|
||||
|
||||
if (callItems[i].getType() != null) {
|
||||
for (int x = 0; x < aMultiUtil.getSetCount(); x++) {
|
||||
if (x > 0 || i > 0) {
|
||||
try {
|
||||
Thread.sleep(aMultiUtil.getTheDelay());
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (callItems[i].getDelay() != null && callItems[i].getDelay() > 0)
|
||||
aMultiUtil.setTheDelay(callItems[i].getDelay());
|
||||
else
|
||||
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
|
||||
|
||||
ColorData colorData = null;
|
||||
List<Double> xy = theStateChanges.getXy();
|
||||
List<Double> xyInc = theStateChanges.getXy_inc();
|
||||
Integer ct = theStateChanges.getCt();
|
||||
Integer ctInc = theStateChanges.getCt_inc();
|
||||
if (xy != null && xy.size() == 2) {
|
||||
colorData = new ColorData(ColorData.ColorMode.XY, xy);
|
||||
} else if (xyInc != null && xyInc.size() == 2) {
|
||||
List<Double> current = state.getXy();
|
||||
current.set(0, current.get(0) + xyInc.get(0));
|
||||
current.set(1, current.get(1) + xyInc.get(1));
|
||||
colorData = new ColorData(ColorData.ColorMode.XY, current);
|
||||
} else if (ct != null && ct != 0) {
|
||||
colorData = new ColorData(ColorData.ColorMode.CT, ct);
|
||||
} else if (ctInc != null && ctInc != 0) {
|
||||
colorData = new ColorData(ColorData.ColorMode.CT, state.getCt() + ctInc);
|
||||
}
|
||||
log.debug("Calling Home device handler for type : " + callItems[i].getType().trim());
|
||||
responseString = homeManager.findHome(callItems[i].getType().trim()).deviceHandler(callItems[i], aMultiUtil, lightId, state.getBri(), targetBri, targetBriInc, colorData, device, body);
|
||||
if(responseString != null && responseString.contains("{\"error\":")) {
|
||||
x = aMultiUtil.getSetCount();
|
||||
}
|
||||
if (url != null && !url.equals("")) {
|
||||
responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, targetBriInc, colorData);
|
||||
} else {
|
||||
log.warn("Could not find on/off url: " + lightId + " for hue state change request: " + userId + " from "
|
||||
+ ipAddress + " body: " + body);
|
||||
responseString = aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/lights/" + lightId,
|
||||
"Could not find on/off url.", "/lights/" + lightId, null, null).getTheErrors(), HueError[].class);
|
||||
previousError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDimRequest && !previousError) {
|
||||
if(!device.isOnFirstDim() )
|
||||
url = device.getDimUrl();
|
||||
|
||||
if (url == null || url.length() == 0)
|
||||
url = device.getOnUrl();
|
||||
|
||||
// code for backwards compatibility
|
||||
if(device.getMapType() != null && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
if(url == null)
|
||||
url = device.getOnUrl();
|
||||
}
|
||||
|
||||
if (url != null && !url.equals("")) {
|
||||
if(isOnRequest) {
|
||||
try {
|
||||
Thread.sleep(bridgeSettings.getButtonsleep());
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
else
|
||||
log.warn("Call Items type is null <<<" + callItems[i] + ">>>");
|
||||
responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, targetBriInc, colorData);
|
||||
} else {
|
||||
log.warn("Could not find dim url: " + lightId + " for hue state change request: " + userId + " from "
|
||||
+ ipAddress + " body: " + body);
|
||||
responseString = aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/lights/" + lightId,
|
||||
"Could not find dim url.", "/lights/" + lightId, null, null).getTheErrors(), HueError[].class);
|
||||
previousError = true;
|
||||
}
|
||||
|
||||
if(callItems.length == 0)
|
||||
log.warn("No call items were available: <<<" + url + ">>>");
|
||||
} else {
|
||||
log.warn("Could not find url: " + lightId + " for hue state change request: " + userId + " from "
|
||||
+ ipAddress + " body: " + body);
|
||||
responseString = aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/lights/" + lightId,
|
||||
"Could not find url.", "/lights/" + lightId, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
|
||||
if (isColorRequest && !previousError) {
|
||||
url = device.getColorUrl();
|
||||
// code for backwards compatibility
|
||||
if(device.getMapType() != null && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
if(url == null)
|
||||
url = device.getOnUrl();
|
||||
}
|
||||
|
||||
if (url != null && !url.equals("")) {
|
||||
if((isOnRequest && !isDimRequest) || isDimRequest) {
|
||||
try {
|
||||
Thread.sleep(bridgeSettings.getButtonsleep());
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, targetBriInc, colorData);
|
||||
} else {
|
||||
log.warn("Could not find color url: " + lightId + " for hue state change request: " + userId + " from "
|
||||
+ ipAddress + " body: " + body);
|
||||
responseString = aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/lights/" + lightId,
|
||||
"Could not find color url.", "/lights/" + lightId, null, null).getTheErrors(), HueError[].class);
|
||||
previousError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (responseString == null || !responseString.contains("[{\"error\":")) {
|
||||
log.debug("Response is in error: " + ((responseString == null) ? "null" : responseString));
|
||||
if(!device.isNoState()) {
|
||||
@@ -1375,4 +1367,87 @@ public class HueMulator {
|
||||
|
||||
return aGsonHandler.toJson(theErrors);
|
||||
}
|
||||
|
||||
protected String callUrl(String url, DeviceDescriptor device, String userId, String lightId, String body, String ipAddress, boolean ignoreRequester, Integer targetBri, Integer targetBriInc, ColorData colorData) {
|
||||
String responseString = null;
|
||||
MultiCommandUtil aMultiUtil = new MultiCommandUtil();
|
||||
aMultiUtil.setTheDelay(bridgeSettings.getButtonsleep());
|
||||
aMultiUtil.setDelayDefault(bridgeSettings.getButtonsleep());
|
||||
aMultiUtil.setSetCount(1);
|
||||
|
||||
if (!url.startsWith("[")) {
|
||||
if (url.startsWith("{\"item"))
|
||||
url = "[" + url + "]";
|
||||
else {
|
||||
if(url.startsWith("{"))
|
||||
url = "[{\"item\":" + url + "}]";
|
||||
else
|
||||
url = "[{\"item\":\"" + url + "\"}]";
|
||||
}
|
||||
} else if(!url.startsWith("[{\"item\""))
|
||||
url = "[{\"item\":" + url + "}]";
|
||||
|
||||
log.debug("Decode Json for url items: " + url);
|
||||
CallItem[] callItems = null;
|
||||
try {
|
||||
callItems = aGsonHandler.fromJson(url, CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
log.warn("Could not decode Json for url items: " + lightId + " for hue state change request: " + userId + " from "
|
||||
+ ipAddress + " body: " + body + " url items: " + url);
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/lights/" + lightId,
|
||||
"Could decode json in request", "/lights/" + lightId, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
|
||||
for (int i = 0; callItems != null && i < callItems.length; i++) {
|
||||
if (!ignoreRequester) {
|
||||
if(!filterByRequester(device.getRequesterAddress(), ipAddress) || !filterByRequester(callItems[i].getFilterIPs(), ipAddress)) {
|
||||
log.warn("filter for requester address not present in: (device)" + device.getRequesterAddress() + " OR then (item)" + callItems[i].getFilterIPs() + " with request ip of: " + ipAddress);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (callItems[i].getCount() != null && callItems[i].getCount() > 0)
|
||||
aMultiUtil.setSetCount(callItems[i].getCount());
|
||||
else
|
||||
aMultiUtil.setSetCount(1);
|
||||
// code for backwards compatibility
|
||||
if((callItems[i].getType() == null || callItems[i].getType().trim().isEmpty())) {
|
||||
if(validMapTypes.validateType(device.getMapType()))
|
||||
callItems[i].setType(device.getMapType().trim());
|
||||
else if(validMapTypes.validateType(device.getDeviceType()))
|
||||
callItems[i].setType(device.getDeviceType().trim());
|
||||
else
|
||||
callItems[i].setType(DeviceMapTypes.CUSTOM_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}
|
||||
|
||||
if (callItems[i].getType() != null) {
|
||||
for (int x = 0; x < aMultiUtil.getSetCount(); x++) {
|
||||
if (x > 0 || i > 0) {
|
||||
try {
|
||||
Thread.sleep(aMultiUtil.getTheDelay());
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (callItems[i].getDelay() != null && callItems[i].getDelay() > 0)
|
||||
aMultiUtil.setTheDelay(callItems[i].getDelay());
|
||||
else
|
||||
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
|
||||
|
||||
log.debug("Calling Home device handler for type : " + callItems[i].getType().trim());
|
||||
responseString = homeManager.findHome(callItems[i].getType().trim()).deviceHandler(callItems[i], aMultiUtil, lightId, device.getDeviceState().getBri(), targetBri, targetBriInc, colorData, device, body);
|
||||
if(responseString != null && responseString.contains("{\"error\":")) {
|
||||
x = aMultiUtil.getSetCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
log.warn("Call Items type is null <<<" + callItems[i] + ">>>");
|
||||
}
|
||||
|
||||
if(callItems.length == 0)
|
||||
log.warn("No call items were available: <<<" + url + ">>>");
|
||||
|
||||
return responseString;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public class FHEMHome implements Home {
|
||||
List<FHEMDevice> deviceList = new ArrayList<FHEMDevice>();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
theResponse = fhemMap.get(key).getDevices(httpClient);
|
||||
theResponse = fhemMap.get(key).testGetDevices(httpClient);
|
||||
if(theResponse != null)
|
||||
addFHEMDevices(deviceList, theResponse, key);
|
||||
else {
|
||||
|
||||
@@ -88,6 +88,275 @@ public class FHEMInstance {
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
public List<FHEMDevice> testGetDevices(HTTPHandler httpClient) {
|
||||
String TestData = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" +
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
|
||||
" <head root=\"/fhem\">\n" +
|
||||
" <title>Home, Sweet Home</title>\n" +
|
||||
" <link rel=\"shortcut icon\" href=\"/fhem/icons/favicon\" />\n" +
|
||||
" <meta charset=\"UTF-8\">\n" +
|
||||
" <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n" +
|
||||
" <link href=\"/fhem/pgm2/style.css?v=1513026539\" rel=\"stylesheet\"/>\n" +
|
||||
" <link href=\"/fhem/pgm2/jquery-ui.min.css\" rel=\"stylesheet\"/>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/jquery.min.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/jquery-ui.min.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_colorpicker.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_fbcalllist.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_knob.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_readingsGroup.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_readingsHistory.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_sortable.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_uzsu.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_weekprofile.js\"></script>\n" +
|
||||
" </head>\n" +
|
||||
" <body name='Home, Sweet Home' fw_id='7880' generated=\"1513272732\" longpoll=\"1\" data-confirmDelete='1' data-confirmJSError='1' data-webName='haBridgeWeb '>\n" +
|
||||
" <div id=\"menuScrollArea\">\n" +
|
||||
" <div>\n" +
|
||||
" <a href=\"/fhem?\">\n" +
|
||||
" <div id=\"logo\"></div>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" <div id=\"menu\">\n" +
|
||||
" <table>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <table class=\"room roomBlock1\">\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Save_config\">\n" +
|
||||
" <a href=\"/fhem?cmd=save\">Save config</a>\n" +
|
||||
" <a id=\"saveCheck\" class=\"changed\" style=\"visibility:visible\">?</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <table class=\"room roomBlock2\">\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Alexa\">\n" +
|
||||
" <a href=\"/fhem?room=Alexa\">Alexa</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_System\">\n" +
|
||||
" <a href=\"/fhem?room=System\">System</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_WG_Zimmer\">\n" +
|
||||
" <a href=\"/fhem?room=WG%2dZimmer\">WG-Zimmer</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_habridge\">\n" +
|
||||
" <a href=\"/fhem?room=habridge\">habridge</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Everything\">\n" +
|
||||
" <a href=\"/fhem?room=all\">\n" +
|
||||
" <img class='icon icoEverything' src=\"/fhem/images/default/icoEverything.png\" alt=\"icoEverything\" title=\"icoEverything\"> Everything\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <table class=\"room roomBlock3\">\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Logfile\">\n" +
|
||||
" <a href=\"/fhem/FileLog_logWrapper?dev=Logfile&type=text&file=fhem-2017-12.log\">Logfile</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div>\n" +
|
||||
" <a href=\"/fhem/docs/commandref.html\" target=\"_blank\" >Commandref</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div>\n" +
|
||||
" <a href=\"http://fhem.de/fhem.html#Documentation\" target=\"_blank\" >Remote doc</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Edit_files\">\n" +
|
||||
" <a href=\"/fhem?cmd=style%20list\">Edit files</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Select_style\">\n" +
|
||||
" <a href=\"/fhem?cmd=style%20select\">Select style</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Event_monitor\">\n" +
|
||||
" <a href=\"/fhem?cmd=style%20eventMonitor\">Event monitor</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div id=\"hdr\">\n" +
|
||||
" <table border=\"0\" class=\"header\">\n" +
|
||||
" <tr>\n" +
|
||||
" <td style=\"padding:0\">\n" +
|
||||
" <form method=\"post\" action=\"/fhem\">\n" +
|
||||
" <input type=\"hidden\" name=\"fw_id\" value=\"7880\"/>\n" +
|
||||
" <input type=\"text\" name=\"cmd\" class=\"maininput\" size=\"40\" value=\"\"/>\n" +
|
||||
" </form>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </div>\n" +
|
||||
" <div id='content' >\n" +
|
||||
" <pre>{ \n" +
|
||||
" \"Arg\":\"room=habridge\", \n" +
|
||||
" \"Results\": [ \n" +
|
||||
" { \n" +
|
||||
" \"Name\":\"Arbeitslicht\", \n" +
|
||||
" \"PossibleSets\":\"on off\", \n" +
|
||||
" \"PossibleAttrs\":\"alias comment:textField-long eventMap group room suppressReading userReadings:textField-long verbose:0,1,2,3,4,5 readingList setList useSetExtensions disable disabledForIntervals event-on-change-reading event-on-update-reading event-aggregator event-min-interval stateFormat:textField-long timestamp-on-change-reading alexaName alexaRoom cmdIcon devStateIcon devStateStyle fhem_widget_command fhem_widget_command_2 fhem_widget_command_3 genericDeviceType:security,ignore,switch,outlet,light,blind,thermometer,thermostat,contact,garage,window,lock homebridgeMapping:textField-long icon sortby webCmd widgetOverride userattr\", \n" +
|
||||
" \"Internals\": { \n" +
|
||||
" \"NAME\": \"Arbeitslicht\", \n" +
|
||||
" \"NR\": \"28\", \n" +
|
||||
" \"STATE\": \"-\", \n" +
|
||||
" \"TYPE\": \"dummy\" \n" +
|
||||
" }, \n" +
|
||||
" \"Readings\": { \"state\": { \"Value\":\"on\", \"Time\":\"2017-12-14 15:41:05\" } }, \n" +
|
||||
" \"Attributes\": { \n" +
|
||||
" \"alexaName\": \"Arbeitslicht\", \n" +
|
||||
" \"alexaRoom\": \"alexaroom\", \n" +
|
||||
" \"fhem_widget_command\": \"{ \\u0022allowed_values\\u0022 : [ \\u0022on\\u0022 ], \\u0022order\\u0022 : 0}\", \n" +
|
||||
" \"icon\": \"scene_office\", \n" +
|
||||
" \"room\": \"Alexa,habridge\", \n" +
|
||||
" \"setList\": \"on off\", \n" +
|
||||
" \"stateFormat\": \"-\", \n" +
|
||||
" \"webCmd\": \"on\" \n" +
|
||||
" } \n" +
|
||||
" }, \n" +
|
||||
" { \n" +
|
||||
" \"Name\":\"DeckenlampeLinks\", \n" +
|
||||
" \"PossibleSets\":\"on off dim dimup dimdown HSV RGB sync pair unpair\", \n" +
|
||||
" \"PossibleAttrs\":\"alias comment:textField-long eventMap group room suppressReading userReadings:textField-long verbose:0,1,2,3,4,5 gamma dimStep defaultColor defaultRamp colorCast whitePoint event-on-change-reading event-on-update-reading event-aggregator event-min-interval stateFormat:textField-long timestamp-on-change-reading alexaName alexaRoom cmdIcon devStateIcon devStateStyle fhem_widget_command fhem_widget_command_2 fhem_widget_command_3 genericDeviceType:security,ignore,switch,outlet,light,blind,thermometer,thermostat,contact,garage,window,lock homebridgeMapping:textField-long icon sortby webCmd widgetOverride \n" +
|
||||
" <a href=\"/fhem?detail=AlleLampen\">AlleLampen</a> AlleLampen_map\n" +
|
||||
" <a href=\"/fhem?detail=DeckenLampen\">DeckenLampen</a> DeckenLampen_map structexclude userattr\", \n" +
|
||||
" \"Internals\": { \n" +
|
||||
" \"CONNECTION\": \"bridge-V3\", \n" +
|
||||
" \"DEF\": \"RGBW2 bridge-V3:10.2.3.3\", \n" +
|
||||
" \"IP\": \"10.2.3.3\", \n" +
|
||||
" \"LEDTYPE\": \"RGBW2\", \n" +
|
||||
" \"NAME\": \"DeckenlampeLinks\", \n" +
|
||||
" \"NR\": \"18\", \n" +
|
||||
" \"NTFY_ORDER\": \"50-DeckenlampeLinks\", \n" +
|
||||
" \"PORT\": \"8899\", \n" +
|
||||
" \"PROTO\": \"0\", \n" +
|
||||
" \"SLOT\": \"5\", \n" +
|
||||
" \"STATE\": \"off\", \n" +
|
||||
" \"TYPE\": \"WifiLight\" \n" +
|
||||
" }, \n" +
|
||||
" \"Readings\": { \n" +
|
||||
" \"RGB\": { \"Value\":\"000000\", \"Time\":\"2017-12-14 15:41:10\" }, \n" +
|
||||
" \"brightness\": { \"Value\":\"0\", \"Time\":\"2017-12-14 15:41:10\" }, \n" +
|
||||
" \"hue\": { \"Value\":\"0\", \"Time\":\"2017-12-14 15:41:10\" }, \n" +
|
||||
" \"saturation\": { \"Value\":\"0\", \"Time\":\"2017-12-14 15:41:10\" }, \n" +
|
||||
" \"state\": { \"Value\":\"off\", \"Time\":\"2017-12-14 15:41:10\" } \n" +
|
||||
" }, \n" +
|
||||
" \"Attributes\": { \n" +
|
||||
" \"AlleLampen\": \"AlleLampen\", \n" +
|
||||
" \"DeckenLampen\": \"DeckenLampen\", \n" +
|
||||
" \"fhem_widget_command\": \"{ \\u0022locations\\u0022 : [ \\u0022APP\\u0022, \\u0022WATCH\\u0022, \\u0022WIDGET\\u0022 ], \\u0022allowed_values\\u0022 : [ \\u0022off\\u0022, \\u0022on\\u0022 ], \\u0022order\\u0022 : 6}\", \n" +
|
||||
" \"room\": \"habridge,Alexa,WG-Zimmer\", \n" +
|
||||
" \"userattr\": \"AlleLampen AlleLampen_map\n" +
|
||||
" <a href=\"/fhem?detail=DeckenLampen\">DeckenLampen</a> DeckenLampen_map structexclude\", \n" +
|
||||
" \"webCmd\": \"RGB\", \n" +
|
||||
" \"widgetOverride\": \"RGB:colorpicker,RGB\" \n" +
|
||||
" } \n" +
|
||||
" } ], \n" +
|
||||
" \"totalResultsReturned\":2 \n" +
|
||||
"}\n" +
|
||||
" </pre>\n" +
|
||||
" </div>\n" +
|
||||
" </body>\n" +
|
||||
"</html>";
|
||||
|
||||
String TestData2 = " <div id='content' >\n" +
|
||||
" <pre>\n" + "{ \"Arg\":\"room=HaBridge\", \"Results\": [ { \"Name\":\"wifi_steckdose3\", \"PossibleSets\":\"on:noArg off:noArg off on toggle\", \"PossibleAttrs\":\"alias comment:textField-long eventMap group room suppressReading userReadings:textField-long verbose:0,1,2,3,4,5 IODev qos retain publishSet publishSet_.* subscribeReading_.* autoSubscribeReadings event-on-change-reading event-on-update-reading event-aggregator event-min-interval stateFormat:textField-long timestamp-on-change-reading alarmDevice:Actor,Sensor alarmSettings cmdIcon devStateIcon devStateStyle icon lightSceneParamsToSave lightSceneRestoreOnlyIfChanged:1,0 sortby structexclude webCmd webCmdLabel:textField-long widgetOverride userattr\", \"Internals\": { \"CHANGED\": \"null\", \"NAME\": \"wifi_steckdose3\", \"NR\": \"270\", \"STATE\": \"off\", \"TYPE\": \"MQTT_DEVICE\", \"retain\": \"*:1 \" }, \"Readings\": { \"state\": { \"Value\":\"OFF\", \"Time\":\"2018-01-01 23:01:21\" }, \"transmission-state\": { \"Value\":\"subscription acknowledged\", \"Time\":\"2018-01-03 22:34:00\" } }, \"Attributes\": { \"IODev\": \"myBroker\", \"alias\": \"Stecki\", \"devStateIcon\": \"on:black_Steckdose.on off:black_Steckdose.off\", \"event-on-change-reading\": \"state\", \"eventMap\": \"ON:on OFF:off\", \"publishSet\": \"on off toggle /SmartHome/az/stecker/cmnd/POWER\", \"retain\": \"1\", \"room\": \"HaBridge,Arbeitszimmer,mqtt\", \"stateFormat\": \"state\", \"subscribeReading_state\": \"/SmartHome/az/stecker/stat/POWER\", \"webCmd\": \"on:off:toggle\" } } ], \"totalResultsReturned\":1 }" +
|
||||
" </pre>\n" +
|
||||
" </div>\n" +
|
||||
" </body>\n" +
|
||||
"</html>";
|
||||
List<FHEMDevice> deviceList = null;
|
||||
FHEMItem theFhemStates;
|
||||
String theUrl = null;
|
||||
String theData;
|
||||
NameValue[] headers = null;
|
||||
if(theFhem.getSecure() != null && theFhem.getSecure())
|
||||
theUrl = "https://";
|
||||
else
|
||||
theUrl = "http://";
|
||||
if(theFhem.getUsername() != null && !theFhem.getUsername().isEmpty() && theFhem.getPassword() != null && !theFhem.getPassword().isEmpty()) {
|
||||
theUrl = theUrl + theFhem.getUsername() + ":" + theFhem.getPassword() + "@";
|
||||
}
|
||||
theUrl = theUrl + theFhem.getIp() + ":" + theFhem.getPort() + "/fhem?cmd=jsonlist2";
|
||||
if(theFhem.getWebhook() != null && !theFhem.getWebhook().trim().isEmpty())
|
||||
theUrl = theUrl + "%20room=" + theFhem.getWebhook().trim();
|
||||
// theData = httpClient.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, headers);
|
||||
theData = TestData;
|
||||
if(theData != null) {
|
||||
log.debug("GET FHEM States - data: " + theData);
|
||||
theData = getJSONData(theData);
|
||||
theFhemStates = new Gson().fromJson(theData, FHEMItem.class);
|
||||
if(theFhemStates == null) {
|
||||
log.warn("Cannot get any devices for FHEM " + theFhem.getName() + " as response is not parsable.");
|
||||
}
|
||||
else {
|
||||
deviceList = new ArrayList<FHEMDevice>();
|
||||
|
||||
for (Result aResult:theFhemStates.getResults()) {
|
||||
FHEMDevice aNewFhemDeviceDevice = new FHEMDevice();
|
||||
aNewFhemDeviceDevice.setItem(aResult);
|
||||
aNewFhemDeviceDevice.setAddress(theFhem.getIp() + ":" + theFhem.getPort());
|
||||
aNewFhemDeviceDevice.setName(theFhem.getName());
|
||||
deviceList.add(aNewFhemDeviceDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
log.warn("Cannot get an devices for FHEM " + theFhem.getName() + " http call failed.");
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
public String getJSONData(String response) {
|
||||
String theData;
|
||||
theData = response.substring(response.indexOf("<pre>") + 4);
|
||||
|
||||
@@ -103,9 +103,10 @@ public class HTTPHandler {
|
||||
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());
|
||||
+ response.getStatusLine() + " with the content of <<<" + theContent + ">>>");
|
||||
if (response.getStatusLine().getStatusCode() == 504) {
|
||||
log.warn("HTTP response code was 504, retrying...");
|
||||
log.debug("The 504 error content is <<<" + theContent + ">>>");
|
||||
} else
|
||||
retryCount = 2;
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ public class SomfyInfo {
|
||||
urlEncodedFormEntity.writeTo(bos);
|
||||
String body = bos.toString();
|
||||
String response = httpClient.doHttpRequest(BASE_URL + "json/login",HttpPost.METHOD_NAME, "application/x-www-form-urlencoded", body,httpHeader);
|
||||
log.debug(response);
|
||||
log.debug("Somfy login response <<<" + response + ">>>");
|
||||
}
|
||||
|
||||
private NameValue[] getHttpHeaders() {
|
||||
@@ -89,7 +89,7 @@ public class SomfyInfo {
|
||||
NameValue[] httpHeader = getHttpHeaders();
|
||||
log.info("Making SOMFY http setup call");
|
||||
String response = httpClient.doHttpRequest(BASE_URL + "json/getSetup", HttpGet.METHOD_NAME, "", "", httpHeader );
|
||||
log.debug(response);
|
||||
log.debug("Somfy getSetup response <<<" + response + ">>>");
|
||||
GetSetup setupData = new Gson().fromJson(response, GetSetup.class);
|
||||
return setupData;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public class SomfyInfo {
|
||||
login(namedIP.getUsername(), namedIP.getPassword());
|
||||
log.info("Making SOMFY http exec call");
|
||||
String response = httpClient.doHttpRequest(BASE_URL_ENDUSER + "exec/apply", HttpPost.METHOD_NAME, "application/json;charset=UTF-8", jsonToPost, getHttpHeaders());
|
||||
log.info(response);
|
||||
log.debug("Somfy exec reply response <<<" + response + ">>>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
1
src/main/resources/public/css/colorpicker.min.css
vendored
Normal file
1
src/main/resources/public/css/colorpicker.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
src/main/resources/public/img/alpha.png
Normal file
BIN
src/main/resources/public/img/alpha.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
src/main/resources/public/img/hue.png
Normal file
BIN
src/main/resources/public/img/hue.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 506 B |
BIN
src/main/resources/public/img/saturation.png
Normal file
BIN
src/main/resources/public/img/saturation.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
@@ -15,6 +15,7 @@
|
||||
<link href="css/ngDialog-theme-default.min.css" rel="stylesheet">
|
||||
<link href="css/scrollable-table.css" rel="stylesheet">
|
||||
<link href="css/strength-meter.min.css" rel="stylesheet">
|
||||
<link href="css/colorpicker.min.css" rel="stylesheet">
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<script type="text/javascript" src="js/html5shiv.min.js"></script>
|
||||
@@ -88,6 +89,7 @@
|
||||
<script src="js/angular-base64.min.js"></script>
|
||||
<script src="js/angular-resource.min.js"></script>
|
||||
<script src="js/ngStorage.min.js"></script>
|
||||
<script src="js/bootstrap-colorpicker-module.min.js"></script>
|
||||
<script src="scripts/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
1
src/main/resources/public/js/bootstrap-colorpicker-module.min.js
vendored
Normal file
1
src/main/resources/public/js/bootstrap-colorpicker-module.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
var app = angular.module ('habridge', ['ngRoute', 'ngToast', 'rzModule', 'ngDialog', 'base64', 'scrollable-table', 'ngResource', 'ngStorage']);
|
||||
var app = angular.module ('habridge', ['ngRoute', 'ngToast', 'rzModule', 'ngDialog', 'base64', 'scrollable-table', 'ngResource', 'ngStorage', 'colorpicker.module']);
|
||||
|
||||
app.config (function ($locationProvider, $routeProvider) {
|
||||
$locationProvider.hashPrefix('!');
|
||||
@@ -1303,18 +1303,53 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
self.state.device = device;
|
||||
};
|
||||
|
||||
this.testUrl = function (device, type, value) {
|
||||
this.toXY = function (red, green, blue) {
|
||||
//Gamma corrective
|
||||
red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
|
||||
green = (green > 0.04045) ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : (green / 12.92);
|
||||
blue = (blue > 0.04045) ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : (blue / 12.92);
|
||||
|
||||
//Apply wide gamut conversion D65
|
||||
var X = red * 0.664511 + green * 0.154324 + blue * 0.162028;
|
||||
var Y = red * 0.283881 + green * 0.668433 + blue * 0.047685;
|
||||
var Z = red * 0.000088 + green * 0.072310 + blue * 0.986039;
|
||||
|
||||
var fx = X / (X + Y + Z);
|
||||
var fy = Y / (X + Y + Z);
|
||||
if (isNaN(fx)) {
|
||||
fx = 0.0;
|
||||
}
|
||||
if (isNaN(fy)) {
|
||||
fy = 0.0;
|
||||
}
|
||||
|
||||
return [fx.toPrecision(4),fy.toPrecision(4)];
|
||||
};
|
||||
|
||||
this.testUrl = function (device, type, value, valueType) {
|
||||
var msgDescription = "unknown";
|
||||
self.getTestUser();
|
||||
var testUrl = this.state.huebase + "/" + this.state.testuser + "/lights/" + device.id + "/state";
|
||||
var testBody = "{\"on\":";
|
||||
var addComma = false;
|
||||
var testBody = "{";
|
||||
if (type === "off") {
|
||||
testBody = testBody + "false";
|
||||
} else {
|
||||
testBody = testBody + "true";
|
||||
testBody = testBody + "\"on\":false";
|
||||
addComma = true
|
||||
}
|
||||
if (value) {
|
||||
testBody = testBody + ",\"bri\":" + value;
|
||||
if (type === "on") {
|
||||
testBody = testBody + "\"on\":true";
|
||||
addComma = true
|
||||
}
|
||||
if (valueType === "dim" && value) {
|
||||
if(addComma)
|
||||
testBody = testBody + ",";
|
||||
testBody = testBody + "\"bri\":" + value;
|
||||
addComma = true
|
||||
}
|
||||
if (valueType === "color" && value) {
|
||||
if(addComma)
|
||||
testBody = testBody + ",";
|
||||
testBody = testBody + "\"xy\": [" + value[0] +"," + value[1] + "]";
|
||||
}
|
||||
testBody = testBody + "}";
|
||||
$http.put(testUrl, testBody).then(
|
||||
@@ -1940,7 +1975,7 @@ app.controller('ViewingController', function ($scope, $location, bridgeService,
|
||||
var dialogNeeded = false;
|
||||
if ((type === "on" && device.onUrl !== undefined && bridgeService.aContainsB(device.onUrl, "${intensity")) ||
|
||||
(type === "off" && device.offUrl !== undefined && bridgeService.aContainsB(device.offUrl, "${intensity")) ||
|
||||
(type === "dim" && device.dimUrl !== undefined) || (type === "color" && device.colorUrl !== undefined)) {
|
||||
(type === "dim" && device.dimUrl !== undefined)) {
|
||||
$scope.bridge.device = device;
|
||||
$scope.bridge.type = type;
|
||||
ngDialog.open({
|
||||
@@ -1949,8 +1984,19 @@ app.controller('ViewingController', function ($scope, $location, bridgeService,
|
||||
className: 'ngdialog-theme-default'
|
||||
});
|
||||
}
|
||||
else if ((type === "on" && device.onUrl !== undefined && bridgeService.aContainsB(device.onUrl, "${color")) ||
|
||||
(type === "off" && device.offUrl !== undefined && bridgeService.aContainsB(device.offUrl, "${color")) ||
|
||||
(type === "color" && device.colorUrl !== undefined)) {
|
||||
$scope.bridge.device = device;
|
||||
$scope.bridge.type = type;
|
||||
ngDialog.open({
|
||||
template: 'colorDialog',
|
||||
controller: 'ColorDialogCtrl',
|
||||
className: 'ngdialog-theme-default'
|
||||
});
|
||||
}
|
||||
else
|
||||
bridgeService.testUrl(device, type);
|
||||
bridgeService.testUrl(device, type, null, type);
|
||||
};
|
||||
$scope.deleteDevice = function (device) {
|
||||
$scope.bridge.device = device;
|
||||
@@ -2039,7 +2085,28 @@ app.controller('ValueDialogCtrl', function ($scope, bridgeService, ngDialog) {
|
||||
theValue = Math.round(($scope.slider.value * .01) * 255);
|
||||
else
|
||||
theValue = $scope.slider.value;
|
||||
bridgeService.testUrl($scope.bridge.device, $scope.bridge.type, theValue);
|
||||
bridgeService.testUrl($scope.bridge.device, $scope.bridge.type, theValue, "dim");
|
||||
$scope.bridge.device = null;
|
||||
$scope.bridge.type = "";
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('ColorDialogCtrl', function ($scope, bridgeService, ngDialog) {
|
||||
$scope.rgbPicker = {
|
||||
color: 'rgb(255,255,255)'
|
||||
};
|
||||
|
||||
$scope.bridge = bridgeService.state;
|
||||
$scope.setValue = function () {
|
||||
ngDialog.close('ngdialog1');
|
||||
var next = $scope.rgbPicker.color.substr($scope.rgbPicker.color.indexOf('(') + 1);
|
||||
var red = next.substr(0, next.indexOf(','));
|
||||
next = next.substr(next.indexOf(',') + 1);
|
||||
var green = next.substr(0, next.indexOf(','));
|
||||
next = next.substr(next.indexOf(',') + 1);
|
||||
var blue = next.substr(0, next.indexOf(')'));
|
||||
var theValue = bridgeService.toXY(red, green, blue);
|
||||
bridgeService.testUrl($scope.bridge.device, $scope.bridge.type, theValue, "color");
|
||||
$scope.bridge.device = null;
|
||||
$scope.bridge.type = "";
|
||||
};
|
||||
@@ -2232,6 +2299,7 @@ app.controller('FibaroController', function ($scope, $location, bridgeService, n
|
||||
};
|
||||
|
||||
$scope.buildDeviceUrls = function (fibarodevice, dim_control, buildonly) {
|
||||
var dimpayload = null;
|
||||
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)
|
||||
dimpayload = "http://" + fibarodevice.fibaroaddress + ":" + fibarodevice.fibaroport + "/api/callAction?deviceID=" + fibarodevice.id + "&name=setValue&arg1=" + dim_control;
|
||||
|
||||
@@ -2248,6 +2316,8 @@ app.controller('FibaroController', function ($scope, $location, bridgeService, n
|
||||
};
|
||||
|
||||
$scope.buildSceneUrls = function (fibaroscene) {
|
||||
var onpayload = null;
|
||||
var offpayload = null;
|
||||
onpayload = "http://" + fibaroscene.fibaroaddress + ":" + fibaroscene.fibaroport + "/api/sceneControl?id=" + fibaroscene.id + "&action=start";
|
||||
offpayload = "http://" + fibaroscene.fibaroaddress + ":" + fibaroscene.fibaroport + "/api/sceneControl?id=" + fibaroscene.id + "&action=stop";
|
||||
|
||||
@@ -3533,7 +3603,7 @@ app.controller('SomfyController', function ($scope, $location, bridgeService, ng
|
||||
|
||||
$scope.buildDeviceUrls = function (somfydevice, dim_control, buildonly) {
|
||||
//TODO - support partial window opening - add back 'dim_control' second param in here, and in somfydevice.html
|
||||
dimpayload = "";
|
||||
dimpayload = null;
|
||||
onpayload = "{\"label\":\"Label that is ignored probably\",\"actions\":[{\"deviceURL\":\""+ somfydevice.deviceUrl+"\",\"commands\":[{\"name\":\"open\",\"parameters\":[]}]}]}";
|
||||
offpayload = "{\"label\":\"Label that is ignored probably\",\"actions\":[{\"deviceURL\":\""+ somfydevice.deviceUrl+"\",\"commands\":[{\"name\":\"close\",\"parameters\":[]}]}]}";
|
||||
|
||||
@@ -3800,28 +3870,24 @@ app.controller('FhemController', function ($scope, $location, bridgeService, ngD
|
||||
};
|
||||
|
||||
$scope.buildDeviceUrls = function (fhemdevice, dim_control, ondeviceaction, oninputdeviceaction, offdeviceaction, offinputdeviceaction, buildonly) {
|
||||
var preCmd = "/fhem?cmd=set%20" + fhemdevice.item.name + "%20";
|
||||
if(fhemdevice.item.possibleSets.indexOf("dim" >= 0)) {
|
||||
var preCmd = "/fhem?cmd=set%20" + fhemdevice.item.Name + "%20";
|
||||
if(fhemdevice.item.PossibleSets.indexOf("dim") >= 0) {
|
||||
if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)) {
|
||||
dimpayload = "{\"url\":\"http://" + fhemdevice.address + preCmd + "\",\"command\":\"dim%20" + dim_control + "\"}";
|
||||
}
|
||||
else
|
||||
dimpayload = null;
|
||||
dimpayload = "{\"url\":\"http://" + fhemdevice.address + preCmd + "\",\"command\":\"dim%20${intensity.percent}\"}";
|
||||
}
|
||||
else
|
||||
dimpayload = null;
|
||||
if(fhemdevice.item.possibleSets.indexOf("RGB" >= 0)) {
|
||||
if((dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)) {
|
||||
colorpayload = "{\"url\":\"http://" + fhemdevice.address + preCmd + "\",\"command\":\"RGB%20${color.rgbx}\"}";
|
||||
}
|
||||
else
|
||||
colorpayload = null;
|
||||
if(fhemdevice.item.PossibleSets.indexOf("RGB") >= 0) {
|
||||
colorpayload = "{\"url\":\"http://" + fhemdevice.address + preCmd + "\",\"command\":\"RGB%20${color.rgbx}\"}";
|
||||
}
|
||||
else
|
||||
colorpayload = null;
|
||||
onpayload = "{\"url\":\"http://" + fhemdevice.address + preCmd + "\",\"command\":\"on\"}";
|
||||
offpayload = "{\"url\":\"http://" + fhemdevice.address + preCmd + "\",\"command\":\"off\"}";
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, colorpayload, true, fhemdevice.item.name + "-" + fhemdevice.name, fhemdevice.item.name, fhemdevice.name, fhemdevice.item.type, "fhemDevice", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, colorpayload, true, fhemdevice.item.Name + "-" + fhemdevice.name, fhemdevice.item.Name, fhemdevice.name, fhemdevice.item.type, "fhemDevice", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<td>{{device.id}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
<td class="cr">{{device.description}}</td>
|
||||
<td class="cr">on={{device.deviceState.on}},bri={{device.deviceState.on}},hue={{device.deviceState.hue}},sat={{device.deviceState.sat}},effect={{device.deviceState.effect}},ct={{device.deviceState.ct}},alert={{device.deviceState.alert}},colormode={{device.deviceState.colormode}},reachable={{device.deviceState.reachable}},XYList={{device.deviceState.xy}}</td>
|
||||
<td class="cr">on={{device.deviceState.on}},bri={{device.deviceState.bri}},hue={{device.deviceState.hue}},sat={{device.deviceState.sat}},effect={{device.deviceState.effect}},ct={{device.deviceState.ct}},alert={{device.deviceState.alert}},colormode={{device.deviceState.colormode}},reachable={{device.deviceState.reachable}},XYList={{device.deviceState.xy}}</td>
|
||||
<td>{{device.deviceType}}</td>
|
||||
<td>{{device.targetDevice}}</td>
|
||||
<td>{{device.inactive}}</td>
|
||||
@@ -91,6 +91,8 @@
|
||||
ng-click="testUrl(device, 'dim')">Test Dim</button>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'off')">Test OFF</button>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'color')">Test Color</button>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="editDevice(device)">Edit/Copy</button>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
@@ -161,6 +163,17 @@
|
||||
<button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="setValue()">Set</button>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/ng-template" id="colorDialog">
|
||||
<div class="ngdialog-message">
|
||||
<h2>Select Color</h2>
|
||||
<p>
|
||||
<input colorpicker="rgb" ng-model="rgbPicker.color" type="text">
|
||||
</p>
|
||||
</div>
|
||||
<div class="ngdialog-buttons mt">
|
||||
<button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="setValue()">Set</button>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/ng-template" id="deleteDialog">
|
||||
<div class="ngdialog-message">
|
||||
<h2>Device to Delete?</h2>
|
||||
|
||||
@@ -93,6 +93,12 @@
|
||||
ng-model="device.offState" ng-true-value=true
|
||||
ng-false-value=false> {{device.offState}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>On with First Dim (If the device is not on in the ha-bridge state, it will send on instead of the dim.)</label></td>
|
||||
<td><input type="checkbox"
|
||||
ng-model="device.onFirstDim" ng-true-value=true
|
||||
ng-false-value=false> {{device.onFirstDim}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Filter Address (comma separated list)</label></td>
|
||||
<td><input type="text" class="form-control" id="device-requester-addr"
|
||||
|
||||
@@ -72,9 +72,9 @@
|
||||
value="{{fhemdevice.item.name}}"
|
||||
ng-checked="bulk.devices.indexOf(fhemdevice.item.name) > -1"
|
||||
ng-click="toggleSelection(fhemdevice.item.name)">
|
||||
{{fhemdevice.item.name}}</td>
|
||||
{{fhemdevice.item.Name}}</td>
|
||||
<td>{{fhemdevice.name}}</td>
|
||||
<td>{{fhemdevice.item.possibleSets}}</td>
|
||||
<td>{{fhemdevice.item.PossibleSets}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(fhemdevice, device_dim_control, false)">Build Item</button>
|
||||
|
||||
@@ -231,6 +231,12 @@ public class FHEMInstanceConstructor {
|
||||
" </body>\n" +
|
||||
"</html>";
|
||||
|
||||
public final static String TestData2 = " <div id='content' >\n" +
|
||||
" <pre>\n" + "{ \"Arg\":\"room=HaBridge\", \"Results\": [ { \"Name\":\"wifi_steckdose3\", \"PossibleSets\":\"on:noArg off:noArg off on toggle\", \"PossibleAttrs\":\"alias comment:textField-long eventMap group room suppressReading userReadings:textField-long verbose:0,1,2,3,4,5 IODev qos retain publishSet publishSet_.* subscribeReading_.* autoSubscribeReadings event-on-change-reading event-on-update-reading event-aggregator event-min-interval stateFormat:textField-long timestamp-on-change-reading alarmDevice:Actor,Sensor alarmSettings cmdIcon devStateIcon devStateStyle icon lightSceneParamsToSave lightSceneRestoreOnlyIfChanged:1,0 sortby structexclude webCmd webCmdLabel:textField-long widgetOverride userattr\", \"Internals\": { \"CHANGED\": \"null\", \"NAME\": \"wifi_steckdose3\", \"NR\": \"270\", \"STATE\": \"off\", \"TYPE\": \"MQTT_DEVICE\", \"retain\": \"*:1 \" }, \"Readings\": { \"state\": { \"Value\":\"OFF\", \"Time\":\"2018-01-01 23:01:21\" }, \"transmission-state\": { \"Value\":\"subscription acknowledged\", \"Time\":\"2018-01-03 22:34:00\" } }, \"Attributes\": { \"IODev\": \"myBroker\", \"alias\": \"Stecki\", \"devStateIcon\": \"on:black_Steckdose.on off:black_Steckdose.off\", \"event-on-change-reading\": \"state\", \"eventMap\": \"ON:on OFF:off\", \"publishSet\": \"on off toggle /SmartHome/az/stecker/cmnd/POWER\", \"retain\": \"1\", \"room\": \"HaBridge,Arbeitszimmer,mqtt\", \"stateFormat\": \"state\", \"subscribeReading_state\": \"/SmartHome/az/stecker/stat/POWER\", \"webCmd\": \"on:off:toggle\" } } ], \"totalResultsReturned\":1 }" +
|
||||
" </pre>\n" +
|
||||
" </div>\n" +
|
||||
" </body>\n" +
|
||||
"</html>";
|
||||
public static void main(String[] args){
|
||||
FHEMInstanceConstructor aTestService = new FHEMInstanceConstructor();
|
||||
if(aTestService.validateStructure())
|
||||
@@ -243,7 +249,7 @@ public class FHEMInstanceConstructor {
|
||||
anAddress.setName("testName");
|
||||
anAddress.setIp("10.0.0.1");
|
||||
FHEMInstance anInstance = new FHEMInstance(anAddress);
|
||||
String decodeData = anInstance.getJSONData(TestData);
|
||||
String decodeData = anInstance.getJSONData(TestData2);
|
||||
try {
|
||||
aGson = new GsonBuilder()
|
||||
.create();
|
||||
|
||||
Reference in New Issue
Block a user