mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-16 18:24:36 +00:00
Huemulator state fixes
draft active logger control
This commit is contained in:
@@ -4,7 +4,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.api.hue.HueConstants;
|
||||
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
|
||||
|
||||
@@ -108,6 +108,9 @@ public class BridgeSettingsDescriptor {
|
||||
@SerializedName("fhemaddress")
|
||||
@Expose
|
||||
private IpList fhemaddress;
|
||||
@SerializedName("activeloggers")
|
||||
@Expose
|
||||
private List<NameValue> activeloggers;
|
||||
|
||||
private boolean settingsChanged;
|
||||
private boolean veraconfigured;
|
||||
@@ -155,6 +158,7 @@ public class BridgeSettingsDescriptor {
|
||||
this.webaddress = "0.0.0.0";
|
||||
this.hubversion = HueConstants.HUB_VERSION;
|
||||
this.hubmac = null;
|
||||
this.activeloggers = null;
|
||||
this.upnpsenddelay = 1500;
|
||||
}
|
||||
public String getUpnpConfigAddress() {
|
||||
@@ -463,6 +467,12 @@ public class BridgeSettingsDescriptor {
|
||||
public void setFhemconfigured(boolean fhemconfigured) {
|
||||
this.fhemconfigured = fhemconfigured;
|
||||
}
|
||||
public List<NameValue> getActiveloggers() {
|
||||
return activeloggers;
|
||||
}
|
||||
public void setActiveloggers(List<NameValue> activeloggers) {
|
||||
this.activeloggers = activeloggers;
|
||||
}
|
||||
public Boolean isValidVera() {
|
||||
if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
|
||||
@@ -14,15 +14,19 @@ import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Timer;
|
||||
import java.util.Base64;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
|
||||
import com.bwssystems.HABridge.dao.BackupFilename;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
@@ -36,6 +40,7 @@ import com.google.gson.reflect.TypeToken;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.classic.spi.LoggingEvent;
|
||||
import ch.qos.logback.core.Appender;
|
||||
import ch.qos.logback.core.read.CyclicBufferAppender;
|
||||
|
||||
public class SystemControl {
|
||||
@@ -55,7 +60,7 @@ public class SystemControl {
|
||||
this.version = theVersion;
|
||||
this.lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
this.dateFormat = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss.SSS");
|
||||
reacquireCBA();
|
||||
setupLoggerSettings();
|
||||
theLogServiceMgr = new LoggingManager();
|
||||
theLogServiceMgr.init();
|
||||
}
|
||||
@@ -88,7 +93,7 @@ public class SystemControl {
|
||||
String logMsgs;
|
||||
int count = -1;
|
||||
if(cyclicBufferAppender == null)
|
||||
reacquireCBA();
|
||||
setupLoggerSettings();
|
||||
if (cyclicBufferAppender != null) {
|
||||
count = cyclicBufferAppender.getLength();
|
||||
}
|
||||
@@ -356,6 +361,8 @@ public class SystemControl {
|
||||
log.debug("bridge settings requested from " + request.ip());
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.type("application/json");
|
||||
if(bridgeSettings.getBridgeSettingsDescriptor().getActiveloggers() == null)
|
||||
bridgeSettings.getBridgeSettingsDescriptor().setActiveloggers(getLogAppenders());
|
||||
return bridgeSettings.getBridgeSettingsDescriptor();
|
||||
}, new JsonTransformer());
|
||||
|
||||
@@ -484,11 +491,42 @@ public class SystemControl {
|
||||
}, new JsonTransformer());
|
||||
}
|
||||
|
||||
void reacquireCBA() {
|
||||
cyclicBufferAppender = (CyclicBufferAppender<ILoggingEvent>) lc.getLogger(
|
||||
private void setupLoggerSettings() {
|
||||
final ch.qos.logback.classic.Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
|
||||
cyclicBufferAppender = (CyclicBufferAppender<ILoggingEvent>) lc.getLogger(
|
||||
Logger.ROOT_LOGGER_NAME).getAppender(CYCLIC_BUFFER_APPENDER_NAME);
|
||||
cyclicBufferAppender.setMaxSize(bridgeSettings.getBridgeSettingsDescriptor().getNumberoflogmessages());
|
||||
}
|
||||
if(bridgeSettings.getBridgeSettingsDescriptor().getActiveloggers() != null) {
|
||||
for (NameValue temp : bridgeSettings.getBridgeSettingsDescriptor().getActiveloggers()) {
|
||||
if(temp.getValue().equals("false"))
|
||||
logger.detachAppender(temp.getName());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private List<NameValue> getLogAppenders() {
|
||||
final ch.qos.logback.classic.Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
|
||||
final Iterator<Appender<ILoggingEvent>> it = logger.iteratorForAppenders();
|
||||
|
||||
List<NameValue> theLoggers = new ArrayList<NameValue>();
|
||||
|
||||
while (it.hasNext()) {
|
||||
|
||||
final Appender<ILoggingEvent> appender = it.next();
|
||||
|
||||
if (!(appender instanceof CyclicBufferAppender)) {
|
||||
NameValue theLogger = new NameValue();
|
||||
theLogger.setName(appender.getName());
|
||||
theLogger.setValue("true");
|
||||
theLoggers.add(theLogger);
|
||||
}
|
||||
}
|
||||
|
||||
return theLoggers;
|
||||
}
|
||||
|
||||
protected void pingListener() {
|
||||
try {
|
||||
|
||||
@@ -445,8 +445,9 @@ public class HueMulator {
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private String formatSuccessHueResponse(StateChangeBody stateChanges, String body, String lightId,
|
||||
DeviceState deviceState, Integer targetBri, Integer targetBriInc, boolean offState) {
|
||||
DeviceState deviceState, Integer targetBri, Integer targetBriInc, ColorData colorData, boolean offState) {
|
||||
|
||||
String responseString = "[";
|
||||
boolean notFirstChange = false;
|
||||
@@ -534,7 +535,7 @@ public class HueMulator {
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/xy_inc\":"
|
||||
+ stateChanges.getXy_inc() + "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setXy(stateChanges.getXy());
|
||||
deviceState.setXy((List<Double>) colorData.getData());
|
||||
notFirstChange = true;
|
||||
} else if (body.contains("\"ct_inc\"")) {
|
||||
if (notFirstChange)
|
||||
@@ -1047,16 +1048,17 @@ public class HueMulator {
|
||||
DeviceState state = null;
|
||||
Integer targetBri = null;
|
||||
Integer targetBriInc = null;
|
||||
ColorData colorData = null;
|
||||
|
||||
log.debug("Update state requested: " + userId + " from " + ipAddress + " body: " + body);
|
||||
|
||||
HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors != null)
|
||||
return aGsonHandler.toJson(theErrors);
|
||||
|
||||
try {
|
||||
theStateChanges = aGsonHandler.fromJson(body, StateChangeBody.class);
|
||||
} catch (Exception e) {
|
||||
theStateChanges = null;
|
||||
}
|
||||
if (theStateChanges == null) {
|
||||
log.warn("Could not parse state change body. Light state not changed.");
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("2", "/lights/" + lightId,
|
||||
"Could not parse state change body.", null, null, null).getTheErrors(), HueError[].class);
|
||||
@@ -1080,7 +1082,26 @@ public class HueMulator {
|
||||
if (state == null)
|
||||
state = DeviceState.createDeviceState(device.isColorDevice());
|
||||
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, device.isOffState());
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, colorData, device.isOffState());
|
||||
device.setDeviceState(state);
|
||||
|
||||
return responseString;
|
||||
@@ -1099,7 +1120,6 @@ public class HueMulator {
|
||||
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());
|
||||
@@ -1199,21 +1219,14 @@ public class HueMulator {
|
||||
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;
|
||||
log.info("On/off url not available for state change, lightId: " + lightId + ", userId: " + userId + ", from IP: "
|
||||
+ ipAddress + ", body: " + body);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDimRequest && !previousError) {
|
||||
if (isDimRequest) {
|
||||
log.debug("Calling dim as requested.");
|
||||
if(!device.isOnFirstDim() )
|
||||
url = device.getDimUrl();
|
||||
|
||||
if (url == null || url.length() == 0)
|
||||
url = device.getOnUrl();
|
||||
url = device.getDimUrl();
|
||||
|
||||
// code for backwards compatibility
|
||||
if(device.getMapType() != null && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
@@ -1231,15 +1244,12 @@ public class HueMulator {
|
||||
}
|
||||
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;
|
||||
log.info("Dim url not available for state change, lightId: " + lightId + ", userId: " + userId + ", from IP: "
|
||||
+ ipAddress + ", body: " + body);
|
||||
}
|
||||
}
|
||||
|
||||
if (isColorRequest && !previousError) {
|
||||
if (isColorRequest) {
|
||||
log.debug("Calling color as requested.");
|
||||
url = device.getColorUrl();
|
||||
// code for backwards compatibility
|
||||
@@ -1258,21 +1268,18 @@ public class HueMulator {
|
||||
}
|
||||
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;
|
||||
log.info("Color url not available for state change, lightId: " + lightId + ", userId: " + userId + ", from IP: "
|
||||
+ ipAddress + ", body: " + body);
|
||||
}
|
||||
}
|
||||
|
||||
if (responseString == null || !responseString.contains("[{\"error\":")) {
|
||||
if(!device.isNoState()) {
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, device.isOffState());
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, colorData, device.isOffState());
|
||||
device.setDeviceState(state);
|
||||
} else {
|
||||
DeviceState dummyState = DeviceState.createDeviceState(device.isColorDevice());
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, dummyState, targetBri, targetBriInc, device.isOffState());
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, dummyState, targetBri, targetBriInc, colorData, device.isOffState());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1283,6 +1290,7 @@ public class HueMulator {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private String changeGroupState(String userId, String groupId, String body, String ipAddress, boolean fakeLightResponse) {
|
||||
ColorData colorData = null;
|
||||
log.debug("PUT action to group " + groupId + " from " + ipAddress + " user " + userId + " with body " + body);
|
||||
HueError[] theErrors = null;
|
||||
theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
@@ -1363,7 +1371,7 @@ public class HueMulator {
|
||||
// construct success response: one success message per changed property, but not per light
|
||||
if (group != null) { // if not group 0
|
||||
String response = formatSuccessHueResponse(theStateChanges, body, String.valueOf(Integer.parseInt(groupId) + 10000),
|
||||
state, targetBri, targetBriInc, true);
|
||||
state, targetBri, targetBriInc, colorData, true);
|
||||
group.setAction(state);
|
||||
if (fakeLightResponse) {
|
||||
return response;
|
||||
|
||||
@@ -742,6 +742,27 @@
|
||||
ng-model="bridge.settings.numberoflogmessages" min="100"
|
||||
max="65535"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Log Output Control</td>
|
||||
<td><table
|
||||
class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Active</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="thePair in bridge.settings.activeloggers">
|
||||
<td><input id="bridge-settings-next-logger-name"
|
||||
class="form-control" type="text" ng-model="thePair.name"
|
||||
disabled></td>
|
||||
<td><input type="checkbox"
|
||||
ng-model="thePair.value" ng-true-value="'true'"
|
||||
ng-false-value="'false'"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Trace UPNP Calls</td>
|
||||
<td><input type="checkbox"
|
||||
|
||||
Reference in New Issue
Block a user