The state channel shows an image of the panels on the wall.
You have to configure things for each panel to get the correct color.
Since the colors of the panels can make it difficult to see the panel ids, please use the layout channel where the background color is always white to identify them.
+For state to work, you need to set static colors to your panel.
+This is because Nanoleaf does not return updates on colors for dynamic effects and animations.

public static final String CHANNEL_SWIPE_EVENT_LEFT = "LEFT";
public static final String CHANNEL_SWIPE_EVENT_RIGHT = "RIGHT";
public static final String CHANNEL_LAYOUT = "layout";
- public static final String CHANNEL_STATE = "state";
+ public static final String CHANNEL_VISUAL_STATE = "visualState";
// List of light panel channels
public static final String CHANNEL_PANEL_COLOR = "color";
updateProperties();
updateConfiguration();
updateLayout(controllerInfo.getPanelLayout());
- updateState(controllerInfo.getPanelLayout());
+ updateVisualState(controllerInfo.getPanelLayout());
for (NanoleafControllerListener controllerListener : controllerListeners) {
controllerListener.onControllerInfoFetched(getThing().getUID(), controllerInfo);
}
}
- private void updateState(PanelLayout panelLayout) {
- ChannelUID stateChannel = new ChannelUID(getThing().getUID(), CHANNEL_STATE);
+ private void updateVisualState(PanelLayout panelLayout) {
+ 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 {
LayoutSettings settings = new LayoutSettings(false, true, true, true);
- byte[] bytes = NanoleafLayout.render(panelLayout, new PanelState(things), settings);
+ 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"));
+ logger.trace("Rendered visual state of panel {} in updateState has {} bytes", getThing().getUID(),
+ bytes.length);
+ } else {
+ logger.debug("Visual state of {} failed to produce any image", getThing().getUID());
}
previousPanelLayout = panelLayout;
}
if (previousPanelLayout.equals(panelLayout)) {
- logger.trace("Not rendering panel layout as it is the same as previous rendered panel layout");
+ logger.trace("Not rendering panel layout for {} as it is the same as previous rendered panel layout",
+ getThing().getUID());
return;
}
byte[] bytes = NanoleafLayout.render(panelLayout, new PanelState(things), settings);
if (bytes.length > 0) {
updateState(layoutChannel, new RawType(bytes, "image/png"));
+ 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;
import org.openhab.binding.nanoleaf.internal.model.Layout;
import org.openhab.binding.nanoleaf.internal.model.PanelLayout;
import org.openhab.binding.nanoleaf.internal.model.PositionDatum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Renders the Nanoleaf layout to an image.
@NonNullByDefault
public class NanoleafLayout {
+ private static final Logger logger = LoggerFactory.getLogger(NanoleafLayout.class);
private static final Color COLOR_BACKGROUND = Color.WHITE;
public static byte[] render(PanelLayout panelLayout, PanelState state, LayoutSettings settings) throws IOException {
Layout layout = panelLayout.getLayout();
if (layout == null) {
+ logger.warn("Returning no image as we don't have any layout to render");
return new byte[] {};
}
List<PositionDatum> positionDatums = layout.getPositionData();
if (positionDatums == null) {
+ logger.warn("Returning no image as we don't have any position datums to render");
return new byte[] {};
}
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.
@NonNullByDefault
public class PanelState {
+ private static final Logger logger = LoggerFactory.getLogger(PanelState.class);
private final Map<Integer, HSBType> panelStates = new HashMap<>();
public PanelState(List<Thing> panels) {
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);
}
}
channel-type.nanoleaf.swipe.description = Swipe over the panels
channel-type.nanoleaf.layout.label = Layout
channel-type.nanoleaf.layout.description = Layout of the panels
-channel-type.nanoleaf.state.label = State
-channel-type.nanoleaf.state.description = Current state of the panels
+channel-type.nanoleaf.state.label = Visual State
+channel-type.nanoleaf.state.description = Current visual state of the panels
# error messages
error.nanoleaf.controller.noIp = IP/host address and/or port are not configured for the controller.
<channel id="rhythmMode" typeId="rhythmMode"/>
<channel id="swipe" typeId="swipe"/>
<channel id="layout" typeId="layout"/>
- <channel id="currentState" typeId="state"/>
+ <channel id="visualState" typeId="visualState"/>
</channels>
<properties>
<description>@text/channel-type.nanoleaf.layout.description</description>
</channel-type>
- <channel-type id="state">
+ <channel-type id="visualState">
<item-type>Image</item-type>
<label>@text/channel-type.nanoleaf.state.label</label>
<description>@text/channel-type.nanoleaf.state.description</description>