From 27dd8475e9d2208d39ab577459e9ce3c61d1fb57 Mon Sep 17 00:00:00 2001 From: bsamuels Date: Tue, 16 Jan 2018 13:20:49 -0600 Subject: [PATCH] Huemulator state fixes draft active logger control --- .../HABridge/BridgeSettingsDescriptor.java | 12 +++- .../bwssystems/HABridge/SystemControl.java | 48 +++++++++++-- .../bwssystems/HABridge/hue/HueMulator.java | 72 ++++++++++--------- src/main/resources/public/views/system.html | 21 ++++++ 4 files changed, 115 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java index 2549e68..7dd7178 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java @@ -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 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 getActiveloggers() { + return activeloggers; + } + public void setActiveloggers(List activeloggers) { + this.activeloggers = activeloggers; + } public Boolean isValidVera() { if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0) return false; diff --git a/src/main/java/com/bwssystems/HABridge/SystemControl.java b/src/main/java/com/bwssystems/HABridge/SystemControl.java index 9503d91..a6eafeb 100644 --- a/src/main/java/com/bwssystems/HABridge/SystemControl.java +++ b/src/main/java/com/bwssystems/HABridge/SystemControl.java @@ -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) lc.getLogger( + private void setupLoggerSettings() { + final ch.qos.logback.classic.Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + cyclicBufferAppender = (CyclicBufferAppender) 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 getLogAppenders() { + final ch.qos.logback.classic.Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + + final Iterator> it = logger.iteratorForAppenders(); + + List theLoggers = new ArrayList(); + + while (it.hasNext()) { + + final Appender 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 { diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index 9edc78a..c106b2f 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -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) 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 xy = theStateChanges.getXy(); + List 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 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; diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index 77853cd..e164fbf 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -742,6 +742,27 @@ ng-model="bridge.settings.numberoflogmessages" min="100" max="65535"> + + Log Output Control + + + + + + + + + + + +
NameActive
+ + Trace UPNP Calls