From ea276d2147d557e9880503d5e479c9fe0c49253d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Austvik?= Date: Sun, 25 Dec 2022 20:56:04 +0100 Subject: [PATCH] [nanoleaf] More robust caching of layout (#13998) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [nanoleaf] More robust caching of layout This is a bugfix/enhancement to make sure the caching of the layout (to save it from being recalculated) works better: - Only save previous layout if indeed painted - Only save layout from the layout update, not the display state - Recalculate anyway if current state is null * Bugfix: Update colors When Stefan runs, the getBridge() returns null, when Jørgen runs, is doesn't. But it isn't needed, because we are already in the handler, so just call own methods. Improvement: Less draws when updating colors Instead of drawing the picture for each panel (which gave a cool effect), draw only once when we have parsed all color data. Signed-off-by: Jørgen Austvik --- .../handler/NanoleafControllerHandler.java | 96 ++++++++++--------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/handler/NanoleafControllerHandler.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/handler/NanoleafControllerHandler.java index a9ee48e0c66f4..54c8bd6266a17 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/handler/NanoleafControllerHandler.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/handler/NanoleafControllerHandler.java @@ -123,6 +123,8 @@ public class NanoleafControllerHandler extends BaseBridgeHandler implements Nano private final List controllerListeners = new CopyOnWriteArrayList(); private PanelLayout previousPanelLayout = new PanelLayout(); private final NanoleafPanelColors panelColors = new NanoleafPanelColors(); + private boolean updateVisualLayout = true; + private byte @Nullable [] layoutImage; private @NonNullByDefault({}) ScheduledFuture pairingJob; private @NonNullByDefault({}) ScheduledFuture updateJob; @@ -765,8 +767,6 @@ private void updateVisualState(PanelLayout panelLayout, OnOffType powerState) { } else { logger.debug("Visual state of {} failed to produce any image", getThing().getUID()); } - - previousPanelLayout = panelLayout; } catch (IOException ioex) { logger.warn("Failed to create state image", ioex); } @@ -782,7 +782,7 @@ private void updateLayout(PanelLayout panelLayout) { } } - if (previousPanelLayout.equals(panelLayout)) { + if (layoutImage != null && previousPanelLayout.equals(panelLayout)) { logger.trace("Not rendering panel layout for {} as it is the same as previous rendered panel layout", getThing().getUID()); return; @@ -793,13 +793,14 @@ private void updateLayout(PanelLayout panelLayout) { byte[] bytes = NanoleafLayout.render(panelLayout, new LivePanelState(panelColors), settings); if (bytes.length > 0) { updateState(layoutChannel, new RawType(bytes, "image/png")); + layoutImage = bytes; + previousPanelLayout = panelLayout; logger.trace("Rendered layout of panel {} in updateState has {} bytes", getThing().getUID(), bytes.length); } else { logger.debug("Layout of {} failed to produce any image", getThing().getUID()); } - previousPanelLayout = panelLayout; } catch (IOException ioex) { logger.warn("Failed to create layout image", ioex); } @@ -972,6 +973,7 @@ private boolean hasStaticEffect() { */ private boolean showsUpdatedColors() { if (!hasStaticEffect()) { + logger.trace("Not updating colors as the device doesnt have a static/solid effect"); return false; } @@ -982,9 +984,11 @@ private boolean showsUpdatedColors() { @Override public void onPanelChangedColor() { - if (showsUpdatedColors()) { + if (updateVisualLayout && showsUpdatedColors()) { // Update the visual state if a panel has changed color updateVisualState(controllerInfo.getPanelLayout(), controllerInfo.getState().getOnOff()); + } else { + logger.trace("Not updating colors. Update visual layout: {}", updateVisualLayout); } } @@ -1005,21 +1009,15 @@ private void updatePanelColors() { write.setCommand("request"); write.setAnimName(EFFECT_NAME_STATIC_COLOR); effects.setWrite(write); - Bridge bridge = getBridge(); - if (bridge != null) { - NanoleafControllerHandler handler = (NanoleafControllerHandler) bridge.getHandler(); - if (handler != null) { - NanoleafControllerConfig config = handler.getControllerConfig(); - logger.debug("Sending Request from Panel for getColor()"); - Request setPanelUpdateRequest = OpenAPIUtils.requestBuilder(httpClient, config, API_EFFECT, - HttpMethod.PUT); - setPanelUpdateRequest.content(new StringContentProvider(gson.toJson(effects)), "application/json"); - ContentResponse panelData = OpenAPIUtils.sendOpenAPIRequest(setPanelUpdateRequest); - // parse panel data - - parsePanelData(config, panelData); - } - } + + NanoleafControllerConfig config = getControllerConfig(); + logger.debug("Sending Request from Panel for getColor()"); + Request setPanelUpdateRequest = OpenAPIUtils.requestBuilder(httpClient, config, API_EFFECT, HttpMethod.PUT); + setPanelUpdateRequest.content(new StringContentProvider(gson.toJson(effects)), "application/json"); + ContentResponse panelData = OpenAPIUtils.sendOpenAPIRequest(setPanelUpdateRequest); + // parse panel data + parsePanelData(config, panelData); + } catch (NanoleafNotFoundException nfe) { logger.debug("Panel data could not be retrieved as no data was returned (static type missing?) : {}", nfe.getMessage()); @@ -1048,34 +1046,42 @@ void parsePanelData(NanoleafControllerConfig config, ContentResponse panelData) } if (response != null) { - String[] tokenizedData = response.getAnimData().split(" "); - if (config.deviceType.equals(CONFIG_DEVICE_TYPE_LIGHTPANELS) - || config.deviceType.equals(CONFIG_DEVICE_TYPE_CANVAS)) { - // panelData is in format (numPanels (PanelId 1 R G B W TransitionTime) * numPanel) - String[] panelDataPoints = Arrays.copyOfRange(tokenizedData, 1, tokenizedData.length); - for (int i = 0; i < panelDataPoints.length; i++) { - if (i % 7 == 0) { - // found panel data - store it - panelColors.setPanelColor(Integer.valueOf(panelDataPoints[i]), - HSBType.fromRGB(Integer.parseInt(panelDataPoints[i + 2]), - Integer.parseInt(panelDataPoints[i + 3]), - Integer.parseInt(panelDataPoints[i + 4]))); + try { + updateVisualLayout = false; + String[] tokenizedData = response.getAnimData().split(" "); + if (config.deviceType.equals(CONFIG_DEVICE_TYPE_LIGHTPANELS) + || config.deviceType.equals(CONFIG_DEVICE_TYPE_CANVAS)) { + // panelData is in format (numPanels (PanelId 1 R G B W TransitionTime) * numPanel) + String[] panelDataPoints = Arrays.copyOfRange(tokenizedData, 1, tokenizedData.length); + for (int i = 0; i < panelDataPoints.length; i++) { + if (i % 7 == 0) { + // found panel data - store it + panelColors.setPanelColor(Integer.valueOf(panelDataPoints[i]), + HSBType.fromRGB(Integer.parseInt(panelDataPoints[i + 2]), + Integer.parseInt(panelDataPoints[i + 3]), + Integer.parseInt(panelDataPoints[i + 4]))); + } } - } - } else { - // panelData is in format (0 numPanels (quotient(panelID) remainder(panelID) R G B W 0 - // quotient(TransitionTime) remainder(TransitionTime)) * numPanel) - String[] panelDataPoints = Arrays.copyOfRange(tokenizedData, 2, tokenizedData.length); - for (int i = 0; i < panelDataPoints.length; i++) { - if (i % 8 == 0) { - Integer idQuotient = Integer.valueOf(panelDataPoints[i]); - Integer idRemainder = Integer.valueOf(panelDataPoints[i + 1]); - Integer idNum = idQuotient * 256 + idRemainder; - // found panel data - store it - panelColors.setPanelColor(idNum, HSBType.fromRGB(Integer.parseInt(panelDataPoints[i + 3]), - Integer.parseInt(panelDataPoints[i + 4]), Integer.parseInt(panelDataPoints[i + 5]))); + } else { + // panelData is in format (0 numPanels (quotient(panelID) remainder(panelID) R G B W 0 + // quotient(TransitionTime) remainder(TransitionTime)) * numPanel) + String[] panelDataPoints = Arrays.copyOfRange(tokenizedData, 2, tokenizedData.length); + for (int i = 0; i < panelDataPoints.length; i++) { + if (i % 8 == 0) { + Integer idQuotient = Integer.valueOf(panelDataPoints[i]); + Integer idRemainder = Integer.valueOf(panelDataPoints[i + 1]); + Integer idNum = idQuotient * 256 + idRemainder; + // found panel data - store it + panelColors.setPanelColor(idNum, + HSBType.fromRGB(Integer.parseInt(panelDataPoints[i + 3]), + Integer.parseInt(panelDataPoints[i + 4]), + Integer.parseInt(panelDataPoints[i + 5]))); + } } } + } finally { + updateVisualLayout = true; + onPanelChangedColor(); } } }