[nanoleaf] More color for less network calls (#13893)
* [nanoleaf] More color for less network calls This is a refactoring that moves the "get panel color" out of the panel handler and into a separate class, with callbacks. This makes us do only one REST call to get colors instead of one per panel that is a thing. It also lets us retrieve colors for all panels - also those that doesn't have a thing in OpenHAB, While testing this out, I found a bug where solid colors set in the app wasn't reflected in neither the controller nor panel channels, and that should also be fixed now. Signed-off-by: Jørgen Austvik <jaustvik@acm.org>
This commit is contained in:
parent
1dbcaf8f0c
commit
70cca8fc77
|
@ -91,7 +91,8 @@ public class NanoleafBindingConstants {
|
|||
public static final String SERVICE_TYPE = "_nanoleafapi._tcp.local.";
|
||||
|
||||
// Effect/scene name for static color
|
||||
public static final String EFFECT_NAME_STATIC_COLOR = "*Dynamic*";
|
||||
public static final String EFFECT_NAME_STATIC_COLOR = "*Static*";
|
||||
public static final String EFFECT_NAME_SOLID_COLOR = "*Solid*";
|
||||
|
||||
// Color channels increase/decrease brightness step size
|
||||
public static final int BRIGHTNESS_STEP_SIZE = 5;
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.nanoleaf.internal.colors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* A listener used to notify panels when they change color.
|
||||
*
|
||||
* @author Jørgen Austvik - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public interface NanoleafControllerColorChangeListener {
|
||||
|
||||
/**
|
||||
* This method is called after any panel changes its color.
|
||||
*/
|
||||
void onPanelChangedColor();
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.nanoleaf.internal.colors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
|
||||
/**
|
||||
* A listener used to notify panels when they change color.
|
||||
*
|
||||
* @author Jørgen Austvik - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public interface NanoleafPanelColorChangeListener {
|
||||
|
||||
/**
|
||||
* This method is called after a panel changes its color
|
||||
*
|
||||
* @param newColor the new color of the panel
|
||||
*/
|
||||
void onPanelChangedColor(HSBType newColor);
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.nanoleaf.internal.colors;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.nanoleaf.internal.handler.NanoleafPanelHandler;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Stores information about panels and their colors, while sending notifications to panels and controllers
|
||||
* about updated states.
|
||||
*
|
||||
* @author Jørgen Austvik - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class NanoleafPanelColors {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(NanoleafPanelColors.class);
|
||||
|
||||
// holds current color data per panel
|
||||
private final Map<Integer, HSBType> panelColors = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, NanoleafPanelColorChangeListener> panelChangeListeners = new ConcurrentHashMap<>();
|
||||
private @Nullable NanoleafControllerColorChangeListener controllerListener;
|
||||
|
||||
private boolean updatePanelColorNoController(Integer panelId, HSBType color) {
|
||||
boolean updatePanel = false;
|
||||
if (panelColors.containsKey(panelId)) {
|
||||
HSBType existingColor = panelColors.get(panelId);
|
||||
if (existingColor != null && !existingColor.equals(color)) {
|
||||
// Color change - update the panel thing
|
||||
updatePanel = true;
|
||||
}
|
||||
} else {
|
||||
// First time we see this panels color - update the panel thing
|
||||
updatePanel = true;
|
||||
}
|
||||
|
||||
panelColors.put(panelId, color);
|
||||
|
||||
if (updatePanel) {
|
||||
@Nullable
|
||||
NanoleafPanelColorChangeListener panelHandler = panelChangeListeners.get(panelId);
|
||||
if (panelHandler != null) {
|
||||
panelHandler.onPanelChangedColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
return updatePanel;
|
||||
}
|
||||
|
||||
private void updatePanelColor(Integer panelId, HSBType color) {
|
||||
boolean updatePanel = updatePanelColorNoController(panelId, color);
|
||||
if (updatePanel) {
|
||||
notifyControllerListener();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyControllerListener() {
|
||||
NanoleafControllerColorChangeListener privateControllerListener = controllerListener;
|
||||
if (privateControllerListener != null) {
|
||||
privateControllerListener.onPanelChangedColor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the color of the panel. Used by the panels to read their state.
|
||||
*
|
||||
* @param panelId The id of the panel
|
||||
* @return The color of the panel
|
||||
*/
|
||||
public @Nullable HSBType getPanelColor(Integer panelId) {
|
||||
return panelColors.get(panelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from panels to update the state.
|
||||
*
|
||||
* @param panelId The panel that received the update
|
||||
* @param color The new color of the panel
|
||||
*/
|
||||
public void setPanelColor(Integer panelId, HSBType color) {
|
||||
updatePanelColor(panelId, color);
|
||||
}
|
||||
|
||||
public void registerChangeListener(Integer panelId, NanoleafPanelHandler panelListener) {
|
||||
logger.trace("Adding color change listener for panel {}", panelId);
|
||||
panelChangeListeners.put(panelId, panelListener);
|
||||
}
|
||||
|
||||
public void unregisterChangeListener(Integer panelId) {
|
||||
logger.trace("Removing color change listener for panel {}", panelId);
|
||||
panelChangeListeners.remove(panelId);
|
||||
}
|
||||
|
||||
public void registerChangeListener(NanoleafControllerColorChangeListener controllerListener) {
|
||||
logger.trace("Setting color change listener for controller");
|
||||
this.controllerListener = controllerListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color of a panel.
|
||||
*
|
||||
* @param panelId The panel
|
||||
* @param defaultColor Default color if panel is missing color information
|
||||
* @return Color of the panel
|
||||
*/
|
||||
public HSBType getColor(Integer panelId, HSBType defaultColor) {
|
||||
return panelColors.getOrDefault(panelId, defaultColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we have color information for the given panel.
|
||||
*
|
||||
* @param panelId The panel to check if has color
|
||||
* @return true if we have color information about the panel
|
||||
*/
|
||||
public boolean hasColor(Integer panelId) {
|
||||
return panelColors.containsKey(panelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all panels to the same color. This will make controller repaint only once.
|
||||
*
|
||||
* @param panelIds Panels to update
|
||||
* @param color The color for all panels
|
||||
*/
|
||||
public void setMultiple(List<Integer> panelIds, HSBType color) {
|
||||
logger.debug("Setting all panels to color {}", color);
|
||||
boolean updatePanel = false;
|
||||
for (Integer panelId : panelIds) {
|
||||
updatePanel |= updatePanelColorNoController(panelId, color);
|
||||
}
|
||||
|
||||
if (updatePanel) {
|
||||
notifyControllerListener();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,8 @@ import static org.openhab.binding.nanoleaf.internal.NanoleafBindingConstants.*;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -36,15 +38,21 @@ import org.eclipse.jetty.client.api.Request;
|
|||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafBadRequestException;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafBindingConstants;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafControllerListener;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafException;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafNotFoundException;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafUnauthorizedException;
|
||||
import org.openhab.binding.nanoleaf.internal.OpenAPIUtils;
|
||||
import org.openhab.binding.nanoleaf.internal.colors.NanoleafControllerColorChangeListener;
|
||||
import org.openhab.binding.nanoleaf.internal.colors.NanoleafPanelColors;
|
||||
import org.openhab.binding.nanoleaf.internal.commanddescription.NanoleafCommandDescriptionProvider;
|
||||
import org.openhab.binding.nanoleaf.internal.config.NanoleafControllerConfig;
|
||||
import org.openhab.binding.nanoleaf.internal.discovery.NanoleafPanelsDiscoveryService;
|
||||
import org.openhab.binding.nanoleaf.internal.layout.ConstantPanelState;
|
||||
import org.openhab.binding.nanoleaf.internal.layout.LayoutSettings;
|
||||
import org.openhab.binding.nanoleaf.internal.layout.LivePanelState;
|
||||
import org.openhab.binding.nanoleaf.internal.layout.NanoleafLayout;
|
||||
import org.openhab.binding.nanoleaf.internal.layout.PanelState;
|
||||
import org.openhab.binding.nanoleaf.internal.model.AuthToken;
|
||||
|
@ -58,10 +66,12 @@ import org.openhab.binding.nanoleaf.internal.model.IntegerState;
|
|||
import org.openhab.binding.nanoleaf.internal.model.Layout;
|
||||
import org.openhab.binding.nanoleaf.internal.model.On;
|
||||
import org.openhab.binding.nanoleaf.internal.model.PanelLayout;
|
||||
import org.openhab.binding.nanoleaf.internal.model.PositionDatum;
|
||||
import org.openhab.binding.nanoleaf.internal.model.Rhythm;
|
||||
import org.openhab.binding.nanoleaf.internal.model.Sat;
|
||||
import org.openhab.binding.nanoleaf.internal.model.State;
|
||||
import org.openhab.binding.nanoleaf.internal.model.TouchEvents;
|
||||
import org.openhab.binding.nanoleaf.internal.model.Write;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
@ -96,7 +106,7 @@ import com.google.gson.JsonSyntaxException;
|
|||
* @author Kai Kreuzer - refactoring, bug fixing and code clean up
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class NanoleafControllerHandler extends BaseBridgeHandler {
|
||||
public class NanoleafControllerHandler extends BaseBridgeHandler implements NanoleafControllerColorChangeListener {
|
||||
|
||||
// Pairing interval in seconds
|
||||
private static final int PAIRING_INTERVAL = 10;
|
||||
|
@ -110,6 +120,7 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
|||
private @Nullable Request sseTouchjobRequest;
|
||||
private final List<NanoleafControllerListener> controllerListeners = new CopyOnWriteArrayList<NanoleafControllerListener>();
|
||||
private PanelLayout previousPanelLayout = new PanelLayout();
|
||||
private final NanoleafPanelColors panelColors = new NanoleafPanelColors();
|
||||
|
||||
private @NonNullByDefault({}) ScheduledFuture<?> pairingJob;
|
||||
private @NonNullByDefault({}) ScheduledFuture<?> updateJob;
|
||||
|
@ -154,6 +165,7 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
|||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing the controller (bridge)");
|
||||
this.panelColors.registerChangeListener(this);
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
NanoleafControllerConfig config = getConfigAs(NanoleafControllerConfig.class);
|
||||
setAddress(config.address);
|
||||
|
@ -582,7 +594,7 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
|||
if (panelHandler != null) {
|
||||
logger.trace("Checking available panel -{}- versus event panel -{}-", panelHandler.getPanelID(),
|
||||
event.getPanelId());
|
||||
if (panelHandler.getPanelID().equals(event.getPanelId())) {
|
||||
if (panelHandler.getPanelID().equals(Integer.valueOf(event.getPanelId()))) {
|
||||
logger.debug("Panel {} found. Triggering item with gesture {}.", panelHandler.getPanelID(),
|
||||
event.getGesture());
|
||||
panelHandler.updatePanelGesture(event.getGesture());
|
||||
|
@ -648,34 +660,52 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
|||
|
||||
Brightness stateBrightness = state.getBrightness();
|
||||
int brightness = stateBrightness != null ? stateBrightness.getValue() : 0;
|
||||
HSBType stateColor = new HSBType(new DecimalType(hue), new PercentType(saturation),
|
||||
new PercentType(powerState == OnOffType.ON ? brightness : 0));
|
||||
|
||||
updateState(CHANNEL_COLOR, new HSBType(new DecimalType(hue), new PercentType(saturation),
|
||||
new PercentType(powerState == OnOffType.ON ? brightness : 0)));
|
||||
updateState(CHANNEL_COLOR, stateColor);
|
||||
updateState(CHANNEL_COLOR_MODE, new StringType(state.getColorMode()));
|
||||
updateState(CHANNEL_RHYTHM_ACTIVE, controllerInfo.getRhythm().getRhythmActive() ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(CHANNEL_RHYTHM_MODE, new DecimalType(controllerInfo.getRhythm().getRhythmMode()));
|
||||
updateState(CHANNEL_RHYTHM_STATE,
|
||||
controllerInfo.getRhythm().getRhythmConnected() ? OnOffType.ON : OnOffType.OFF);
|
||||
|
||||
// update the color channels of each panel
|
||||
getThing().getThings().forEach(child -> {
|
||||
NanoleafPanelHandler panelHandler = (NanoleafPanelHandler) child.getHandler();
|
||||
if (panelHandler != null) {
|
||||
logger.debug("Update color channel for panel {}", panelHandler.getThing().getUID());
|
||||
panelHandler.updatePanelColorChannel();
|
||||
updatePanelColors();
|
||||
if (EFFECT_NAME_SOLID_COLOR.equals(controllerInfo.getEffects().getSelect())) {
|
||||
setSolidColor(stateColor);
|
||||
}
|
||||
});
|
||||
|
||||
updateProperties();
|
||||
updateConfiguration();
|
||||
updateLayout(controllerInfo.getPanelLayout());
|
||||
updateVisualState(controllerInfo.getPanelLayout());
|
||||
updateVisualState(controllerInfo.getPanelLayout(), powerState);
|
||||
|
||||
for (NanoleafControllerListener controllerListener : controllerListeners) {
|
||||
controllerListener.onControllerInfoFetched(getThing().getUID(), controllerInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSolidColor(HSBType color) {
|
||||
// If the panels are set to solid color, they are read from the state
|
||||
PanelLayout panelLayout = controllerInfo.getPanelLayout();
|
||||
Layout layout = panelLayout.getLayout();
|
||||
|
||||
if (layout != null) {
|
||||
List<PositionDatum> positionData = layout.getPositionData();
|
||||
if (positionData != null) {
|
||||
List<Integer> allPanelIds = new ArrayList<>(positionData.size());
|
||||
for (PositionDatum pd : positionData) {
|
||||
allPanelIds.add(pd.getPanelId());
|
||||
}
|
||||
|
||||
panelColors.setMultiple(allPanelIds, color);
|
||||
} else {
|
||||
logger.debug("Missing position datum when setting solid color for {}", getThing().getUID());
|
||||
}
|
||||
} else {
|
||||
logger.debug("Missing layout when setting solid color for {}", getThing().getUID());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateConfiguration() {
|
||||
// only update the Thing config if value isn't set yet
|
||||
if (getConfig().get(NanoleafControllerConfig.DEVICE_TYPE) == null) {
|
||||
|
@ -711,20 +741,20 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateVisualState(PanelLayout panelLayout) {
|
||||
private void updateVisualState(PanelLayout panelLayout, OnOffType powerState) {
|
||||
ChannelUID stateChannel = new ChannelUID(getThing().getUID(), CHANNEL_VISUAL_STATE);
|
||||
|
||||
Bridge bridge = getThing();
|
||||
List<Thing> things = bridge.getThings();
|
||||
if (things == null) {
|
||||
logger.trace("No things to get state from!");
|
||||
return;
|
||||
try {
|
||||
PanelState panelState;
|
||||
if (OnOffType.OFF.equals(powerState)) {
|
||||
// If powered off: show all panels as black
|
||||
panelState = new ConstantPanelState(HSBType.BLACK);
|
||||
} else {
|
||||
// Static color for panels, use it
|
||||
panelState = new LivePanelState(panelColors);
|
||||
}
|
||||
|
||||
try {
|
||||
LayoutSettings settings = new LayoutSettings(false, true, true, true);
|
||||
logger.trace("Getting panel state for {} things", things.size());
|
||||
PanelState panelState = new PanelState(things);
|
||||
byte[] bytes = NanoleafLayout.render(panelLayout, panelState, settings);
|
||||
if (bytes.length > 0) {
|
||||
updateState(stateChannel, new RawType(bytes, "image/png"));
|
||||
|
@ -756,11 +786,9 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
Bridge bridge = getThing();
|
||||
List<Thing> things = bridge.getThings();
|
||||
try {
|
||||
LayoutSettings settings = new LayoutSettings(true, false, true, false);
|
||||
byte[] bytes = NanoleafLayout.render(panelLayout, new PanelState(things), settings);
|
||||
byte[] bytes = NanoleafLayout.render(panelLayout, new LivePanelState(panelColors), settings);
|
||||
if (bytes.length > 0) {
|
||||
updateState(layoutChannel, new RawType(bytes, "image/png"));
|
||||
logger.trace("Rendered layout of panel {} in updateState has {} bytes", getThing().getUID(),
|
||||
|
@ -799,6 +827,7 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
|||
h.setValue(((HSBType) command).getHue().intValue());
|
||||
s.setValue(((HSBType) command).getSaturation().intValue());
|
||||
b.setValue(((HSBType) command).getBrightness().intValue());
|
||||
setSolidColor((HSBType) command);
|
||||
stateObject.setState(h);
|
||||
stateObject.setState(s);
|
||||
stateObject.setState(b);
|
||||
|
@ -919,6 +948,126 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean hasStaticEffect() {
|
||||
return EFFECT_NAME_STATIC_COLOR.equals(controllerInfo.getEffects().getSelect())
|
||||
|| EFFECT_NAME_SOLID_COLOR.equals(controllerInfo.getEffects().getSelect());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if we are in a mode where color changes should be rendered.
|
||||
*
|
||||
* @return True if a color change on a panel should be rendered
|
||||
*/
|
||||
private boolean showsUpdatedColors() {
|
||||
if (!hasStaticEffect()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
State state = controllerInfo.getState();
|
||||
OnOffType powerState = state.getOnOff();
|
||||
return OnOffType.ON.equals(powerState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPanelChangedColor() {
|
||||
if (showsUpdatedColors()) {
|
||||
// Update the visual state if a panel has changed color
|
||||
updateVisualState(controllerInfo.getPanelLayout(), controllerInfo.getState().getOnOff());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For individual panels to get access to the panel colors.
|
||||
*
|
||||
* @return Information about colors of panels.
|
||||
*/
|
||||
public NanoleafPanelColors getColorInformation() {
|
||||
return panelColors;
|
||||
}
|
||||
|
||||
private void updatePanelColors() {
|
||||
// get panel color data from controller
|
||||
try {
|
||||
Effects effects = new Effects();
|
||||
Write write = new Write();
|
||||
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);
|
||||
}
|
||||
}
|
||||
} catch (NanoleafNotFoundException nfe) {
|
||||
logger.debug("Panel data could not be retrieved as no data was returned (static type missing?) : {}",
|
||||
nfe.getMessage());
|
||||
} catch (NanoleafBadRequestException nfe) {
|
||||
logger.debug(
|
||||
"Panel data could not be retrieved as request not expected(static type missing / dynamic type on) : {}",
|
||||
nfe.getMessage());
|
||||
} catch (NanoleafException nue) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/error.nanoleaf.panel.communication");
|
||||
logger.debug("Panel data could not be retrieved: {}", nue.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void parsePanelData(NanoleafControllerConfig config, ContentResponse panelData) {
|
||||
// panelData is in format (numPanels, (PanelId, 1, R, G, B, W, TransitionTime) * numPanel)
|
||||
@Nullable
|
||||
Write response = null;
|
||||
|
||||
String panelDataContent = panelData.getContentAsString();
|
||||
try {
|
||||
response = gson.fromJson(panelDataContent, Write.class);
|
||||
} catch (JsonSyntaxException jse) {
|
||||
logger.warn("Unable to parse panel data information from Nanoleaf", jse);
|
||||
logger.trace("Panel Data which couldn't be parsed: {}", panelDataContent);
|
||||
}
|
||||
|
||||
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])));
|
||||
}
|
||||
}
|
||||
} 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])));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
|
|
@ -16,23 +16,18 @@ import static org.openhab.binding.nanoleaf.internal.NanoleafBindingConstants.*;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafBadRequestException;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafException;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafNotFoundException;
|
||||
import org.openhab.binding.nanoleaf.internal.NanoleafUnauthorizedException;
|
||||
import org.openhab.binding.nanoleaf.internal.OpenAPIUtils;
|
||||
import org.openhab.binding.nanoleaf.internal.colors.NanoleafPanelColorChangeListener;
|
||||
import org.openhab.binding.nanoleaf.internal.config.NanoleafControllerConfig;
|
||||
import org.openhab.binding.nanoleaf.internal.model.Effects;
|
||||
import org.openhab.binding.nanoleaf.internal.model.Write;
|
||||
|
@ -50,6 +45,7 @@ import org.openhab.core.thing.ThingStatusDetail;
|
|||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.BridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -65,7 +61,7 @@ import com.google.gson.Gson;
|
|||
* @author Stefan Höhn - Canvas Touch Support
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class NanoleafPanelHandler extends BaseThingHandler {
|
||||
public class NanoleafPanelHandler extends BaseThingHandler implements NanoleafPanelColorChangeListener {
|
||||
|
||||
private static final PercentType MIN_PANEL_BRIGHTNESS = PercentType.ZERO;
|
||||
private static final PercentType MAX_PANEL_BRIGHTNESS = PercentType.HUNDRED;
|
||||
|
@ -75,9 +71,7 @@ public class NanoleafPanelHandler extends BaseThingHandler {
|
|||
private final HttpClient httpClient;
|
||||
// JSON parser for API responses
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
// holds current color data per panel
|
||||
private final Map<String, HSBType> panelInfo = new HashMap<>();
|
||||
private HSBType currentPanelColor = HSBType.BLACK;
|
||||
|
||||
private @NonNullByDefault({}) ScheduledFuture<?> singleTapJob;
|
||||
private @NonNullByDefault({}) ScheduledFuture<?> doubleTapJob;
|
||||
|
@ -141,6 +135,14 @@ public class NanoleafPanelHandler extends BaseThingHandler {
|
|||
@Override
|
||||
public void handleRemoval() {
|
||||
logger.debug("Nanoleaf panel {} removed", getThing().getUID());
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler instanceof NanoleafControllerHandler) {
|
||||
((NanoleafControllerHandler) handler).getColorInformation().unregisterChangeListener(getPanelID());
|
||||
}
|
||||
}
|
||||
|
||||
super.handleRemoval();
|
||||
}
|
||||
|
||||
|
@ -166,21 +168,27 @@ public class NanoleafPanelHandler extends BaseThingHandler {
|
|||
|
||||
private void initializePanel(ThingStatusInfo panelStatus) {
|
||||
updateStatus(panelStatus.getStatus(), panelStatus.getStatusDetail());
|
||||
updateState(CHANNEL_PANEL_COLOR, currentPanelColor);
|
||||
logger.debug("Panel {} status changed to {}-{}", this.getThing().getUID(), panelStatus.getStatus(),
|
||||
panelStatus.getStatusDetail());
|
||||
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler instanceof NanoleafControllerHandler) {
|
||||
((NanoleafControllerHandler) handler).getColorInformation().registerChangeListener(getPanelID(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendRenderedEffectCommand(Command command) throws NanoleafException {
|
||||
logger.debug("Command Type: {}", command.getClass());
|
||||
HSBType currentPanelColor = getPanelColor();
|
||||
if (currentPanelColor != null) {
|
||||
logger.debug("currentPanelColor: {}", currentPanelColor.toString());
|
||||
}
|
||||
HSBType newPanelColor = new HSBType();
|
||||
logger.debug("currentPanelColor: {}", currentPanelColor);
|
||||
|
||||
HSBType newPanelColor = new HSBType();
|
||||
if (command instanceof HSBType) {
|
||||
newPanelColor = (HSBType) command;
|
||||
} else if (command instanceof OnOffType && (currentPanelColor != null)) {
|
||||
} else if (command instanceof OnOffType) {
|
||||
if (OnOffType.ON.equals(command)) {
|
||||
newPanelColor = new HSBType(currentPanelColor.getHue(), currentPanelColor.getSaturation(),
|
||||
MAX_PANEL_BRIGHTNESS);
|
||||
|
@ -188,11 +196,11 @@ public class NanoleafPanelHandler extends BaseThingHandler {
|
|||
newPanelColor = new HSBType(currentPanelColor.getHue(), currentPanelColor.getSaturation(),
|
||||
MIN_PANEL_BRIGHTNESS);
|
||||
}
|
||||
} else if (command instanceof PercentType && (currentPanelColor != null)) {
|
||||
} else if (command instanceof PercentType) {
|
||||
PercentType brightness = new PercentType(
|
||||
Math.max(MIN_PANEL_BRIGHTNESS.intValue(), ((PercentType) command).intValue()));
|
||||
newPanelColor = new HSBType(currentPanelColor.getHue(), currentPanelColor.getSaturation(), brightness);
|
||||
} else if (command instanceof IncreaseDecreaseType && (currentPanelColor != null)) {
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
int brightness = currentPanelColor.getBrightness().intValue();
|
||||
if (command.equals(IncreaseDecreaseType.INCREASE)) {
|
||||
brightness = Math.min(MAX_PANEL_BRIGHTNESS.intValue(), brightness + BRIGHTNESS_STEP_SIZE);
|
||||
|
@ -209,8 +217,8 @@ public class NanoleafPanelHandler extends BaseThingHandler {
|
|||
return;
|
||||
}
|
||||
// store panel's new HSB value
|
||||
logger.trace("Setting new color {}", newPanelColor);
|
||||
panelInfo.put(getThing().getConfiguration().get(CONFIG_PANEL_ID).toString(), newPanelColor);
|
||||
logger.trace("Setting new color {} to panel {}", newPanelColor, getPanelID());
|
||||
setPanelColor(newPanelColor);
|
||||
// transform to RGB
|
||||
PercentType[] rgbPercent = newPanelColor.toRGB();
|
||||
logger.trace("Setting new rgbpercent {} {} {}", rgbPercent[0], rgbPercent[1], rgbPercent[2]);
|
||||
|
@ -258,15 +266,6 @@ public class NanoleafPanelHandler extends BaseThingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void updatePanelColorChannel() {
|
||||
@Nullable
|
||||
HSBType panelColor = getPanelColor();
|
||||
logger.trace("updatePanelColorChannel: panelColor: {}", panelColor);
|
||||
if (panelColor != null) {
|
||||
updateState(CHANNEL_PANEL_COLOR, panelColor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the gesture to the panel
|
||||
*
|
||||
|
@ -286,98 +285,32 @@ public class NanoleafPanelHandler extends BaseThingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public String getPanelID() {
|
||||
String panelID = getThing().getConfiguration().get(CONFIG_PANEL_ID).toString();
|
||||
return panelID;
|
||||
public Integer getPanelID() {
|
||||
return (Integer) getThing().getConfiguration().get(CONFIG_PANEL_ID);
|
||||
}
|
||||
|
||||
public @Nullable HSBType getColor() {
|
||||
String panelID = getPanelID();
|
||||
return panelInfo.get(panelID);
|
||||
}
|
||||
|
||||
private @Nullable HSBType getPanelColor() {
|
||||
String panelID = getPanelID();
|
||||
|
||||
// get panel color data from controller
|
||||
try {
|
||||
Effects effects = new Effects();
|
||||
Write write = new Write();
|
||||
write.setCommand("request");
|
||||
write.setAnimName("*Static*");
|
||||
effects.setWrite(write);
|
||||
private void setPanelColor(HSBType color) {
|
||||
Integer panelId = getPanelID();
|
||||
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(panelID, config, panelData);
|
||||
}
|
||||
}
|
||||
} catch (NanoleafNotFoundException nfe) {
|
||||
logger.debug("Panel data could not be retrieved as no data was returned (static type missing?) : {}",
|
||||
nfe.getMessage());
|
||||
} catch (NanoleafBadRequestException nfe) {
|
||||
logger.debug(
|
||||
"Panel data could not be retrieved as request not expected(static type missing / dynamic type on) : {}",
|
||||
nfe.getMessage());
|
||||
} catch (NanoleafException nue) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/error.nanoleaf.panel.communication");
|
||||
logger.debug("Panel data could not be retrieved: {}", nue.getMessage());
|
||||
}
|
||||
|
||||
return panelInfo.get(panelID);
|
||||
}
|
||||
|
||||
void parsePanelData(String panelID, NanoleafControllerConfig config, ContentResponse panelData) {
|
||||
// panelData is in format (numPanels, (PanelId, 1, R, G, B, W, TransitionTime) * numPanel)
|
||||
@Nullable
|
||||
Write response = gson.fromJson(panelData.getContentAsString(), Write.class);
|
||||
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) {
|
||||
String id = panelDataPoints[i];
|
||||
if (id.equals(panelID)) {
|
||||
// found panel data - store it
|
||||
panelInfo.put(panelID,
|
||||
HSBType.fromRGB(Integer.parseInt(panelDataPoints[i + 2]),
|
||||
Integer.parseInt(panelDataPoints[i + 3]),
|
||||
Integer.parseInt(panelDataPoints[i + 4])));
|
||||
}
|
||||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler instanceof NanoleafControllerHandler) {
|
||||
((NanoleafControllerHandler) handler).getColorInformation().setPanelColor(panelId, color);
|
||||
} else {
|
||||
logger.debug("Couldn't find handler for panel {}", panelId);
|
||||
}
|
||||
} 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;
|
||||
if (String.valueOf(idNum).equals(panelID)) {
|
||||
// found panel data - store it
|
||||
panelInfo.put(panelID,
|
||||
HSBType.fromRGB(Integer.parseInt(panelDataPoints[i + 3]),
|
||||
Integer.parseInt(panelDataPoints[i + 4]),
|
||||
Integer.parseInt(panelDataPoints[i + 5])));
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.debug("Couldn't find bridge for panel {}", panelId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPanelChangedColor(HSBType newColor) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("updatePanelColorChannel: panelColor: {} for panel {}", newColor, getPanelID());
|
||||
}
|
||||
|
||||
currentPanelColor = newColor;
|
||||
updateState(CHANNEL_PANEL_COLOR, newColor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
|
||||
package org.openhab.binding.nanoleaf.internal.layout;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
|
||||
/**
|
||||
* Always returns the same color for all panels.
|
||||
*
|
||||
* @author Jørgen Austvik - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ConstantPanelState implements PanelState {
|
||||
private final HSBType color;
|
||||
|
||||
public ConstantPanelState(HSBType color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HSBType getHSBForPanel(Integer panelId) {
|
||||
return color;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
|
||||
package org.openhab.binding.nanoleaf.internal.layout;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.nanoleaf.internal.colors.NanoleafPanelColors;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Stores the state of the panels.
|
||||
*
|
||||
* @author Jørgen Austvik - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LivePanelState implements PanelState {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(LivePanelState.class);
|
||||
private final NanoleafPanelColors panelColors;
|
||||
|
||||
public LivePanelState(NanoleafPanelColors panelColors) {
|
||||
this.panelColors = panelColors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HSBType getHSBForPanel(Integer panelId) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (!panelColors.hasColor(panelId)) {
|
||||
logger.trace("Failed to get color for panel {}, falling back to black", panelId);
|
||||
}
|
||||
}
|
||||
|
||||
return panelColors.getColor(panelId, HSBType.BLACK);
|
||||
}
|
||||
}
|
|
@ -10,21 +10,10 @@
|
|||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
|
||||
package org.openhab.binding.nanoleaf.internal.layout;
|
||||
|
||||
import static org.openhab.binding.nanoleaf.internal.NanoleafBindingConstants.CONFIG_PANEL_ID;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.nanoleaf.internal.handler.NanoleafPanelHandler;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Stores the state of the panels.
|
||||
|
@ -32,37 +21,7 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Jørgen Austvik - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PanelState {
|
||||
public interface PanelState {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PanelState.class);
|
||||
private final Map<Integer, HSBType> panelStates = new HashMap<>();
|
||||
|
||||
public PanelState(List<Thing> panels) {
|
||||
for (Thing panel : panels) {
|
||||
Integer panelId = Integer.valueOf(panel.getConfiguration().get(CONFIG_PANEL_ID).toString());
|
||||
NanoleafPanelHandler panelHandler = (NanoleafPanelHandler) panel.getHandler();
|
||||
if (panelHandler != null) {
|
||||
HSBType c = panelHandler.getColor();
|
||||
|
||||
if (c == null) {
|
||||
logger.trace("Panel {}: Failed to get color", panelId);
|
||||
}
|
||||
|
||||
HSBType color = (c == null) ? HSBType.BLACK : c;
|
||||
panelStates.put(panelId, color);
|
||||
} else {
|
||||
logger.trace("Panel {}: Couldn't find handler", panelId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HSBType getHSBForPanel(Integer panelId) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (!panelStates.containsKey(panelId)) {
|
||||
logger.trace("Failed to get color for panel {}, falling back to black", panelId);
|
||||
}
|
||||
}
|
||||
|
||||
return panelStates.getOrDefault(panelId, HSBType.BLACK);
|
||||
}
|
||||
HSBType getHSBForPanel(Integer panelId);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.ArrayDeque;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
@ -36,7 +37,7 @@ public class PanelFactory {
|
|||
List<Panel> result = new ArrayList<>(panels.size());
|
||||
Deque<PositionDatum> panelStack = new ArrayDeque<>(panels);
|
||||
while (!panelStack.isEmpty()) {
|
||||
PositionDatum panel = panelStack.peek();
|
||||
PositionDatum panel = Objects.requireNonNull(panelStack.peek());
|
||||
final ShapeType shapeType = ShapeType.valueOf(panel.getShapeType());
|
||||
Panel shape = createPanel(shapeType, takeFirst(shapeType.getNumLightsPerShape(), panelStack));
|
||||
result.add(shape);
|
||||
|
|
|
@ -18,7 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
@ -70,14 +69,10 @@ public class NanoleafLayoutTest {
|
|||
// Files.write(permanentOutFile, result);
|
||||
}
|
||||
|
||||
private class TestPanelState extends PanelState {
|
||||
private class TestPanelState implements PanelState {
|
||||
private final HSBType testColors[] = { HSBType.fromRGB(160, 120, 40), HSBType.fromRGB(80, 60, 20),
|
||||
HSBType.fromRGB(120, 90, 30), HSBType.fromRGB(200, 150, 60) };
|
||||
|
||||
public TestPanelState() {
|
||||
super(Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HSBType getHSBForPanel(Integer panelId) {
|
||||
return testColors[panelId % testColors.length];
|
||||
|
|
Loading…
Reference in New Issue