Skip to content

Commit

Permalink
[nanoleaf] More robust caching of layout (openhab#13998)
Browse files Browse the repository at this point in the history
* [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 <[email protected]>
  • Loading branch information
austvik authored Dec 25, 2022
1 parent 0357049 commit 6cd59e4
Showing 1 changed file with 51 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ public class NanoleafControllerHandler extends BaseBridgeHandler implements Nano
private final List<NanoleafControllerListener> controllerListeners = new CopyOnWriteArrayList<NanoleafControllerListener>();
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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
}
}

Expand All @@ -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());
Expand Down Expand Up @@ -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();
}
}
}
Expand Down

0 comments on commit 6cd59e4

Please sign in to comment.