[nanoleaf] CODEOWNERs, add Shapes Support, beta-firmware support (#10029)
Signed-off-by: Stefan Höhn <stefan@andreaundstefanhoehn.de>
This commit is contained in:
parent
f9a982e548
commit
570f86d043
@ -170,7 +170,7 @@
|
||||
/bundles/org.openhab.binding.mqtt.homeassistant/ @davidgraeff
|
||||
/bundles/org.openhab.binding.mqtt.homie/ @davidgraeff
|
||||
/bundles/org.openhab.binding.mystrom/ @pail23
|
||||
/bundles/org.openhab.binding.nanoleaf/ @raepple
|
||||
/bundles/org.openhab.binding.nanoleaf/ @raepple @stefan-hoehn
|
||||
/bundles/org.openhab.binding.neato/ @jjlauterbach
|
||||
/bundles/org.openhab.binding.neeo/ @tmrobert8
|
||||
/bundles/org.openhab.binding.neohub/ @andrewfg
|
||||
|
||||
@ -11,8 +11,10 @@ The binding uses the [Nanoleaf OpenAPI](https://forum.nanoleaf.me/docs/openapi),
|
||||
|
||||
## Supported Things
|
||||
|
||||
Nanoleaf provides a bunch of devices of which some are connected to Wifi whereas other use the new Thread Technology. This binding only supports devices that are connected to Wifi.
|
||||
|
||||
Currently Nanoleaf's "Light Panels" and "Canvas" devices are supported.
|
||||
Note that only the canvas type does support the touch functionality.
|
||||
Note that only specific types do support the touch functionality, so the binding needs to check these types.
|
||||
|
||||
The binding supports two thing types: controller and lightpanel.
|
||||
|
||||
@ -23,6 +25,17 @@ The lightpanel (singular) thing controls one of the individual panels/canvas tha
|
||||
Each individual panel has therefore its own id assigned to it.
|
||||
You can set the **color** for each panel or turn it on (white) or off (black) and in the case of a nanoleaf canvas you can even detect single and double **touch events** related to an individual panel which opens a whole new world of controlling any other device within your openHAB environment.
|
||||
|
||||
|
||||
| Nanoleaf Name | Type | Description | supported | touch support |
|
||||
| ---------------------- | ---- | ---------------------------------------------------------- | --------- | ------------- |
|
||||
| Light Panels | NL22 | Triangles 1st Generation | X | (-) |
|
||||
| Shapes Triangle | NL42 | Triangles 2nd Generation (rounded edges) | X | X |
|
||||
| Shapes Hexagon | NL42 | Triangles 2nd Generation (rounded edges) | (X) | (X) |
|
||||
| Shapes Mini Triangles | ?? | Mini Triangles | ? | ? |
|
||||
| Canvas | NL29 | Squares | X | X |
|
||||
|
||||
x = Supported (x) = Supported but only tested by community (-) = unknown (no device available to test)
|
||||
|
||||
Note: In case of major changes of a binding (like adding more features to a thing) it becomes necessary to delete your things due to the things not being compatible anymore.
|
||||
Don't worry too much though as they will be easily redetected and nothing really is lost.
|
||||
Just make sure that you delete them and rediscover as described below.
|
||||
|
||||
@ -12,6 +12,9 @@
|
||||
*/
|
||||
package org.openhab.binding.nanoleaf.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
@ -71,9 +74,12 @@ public class NanoleafBindingConstants {
|
||||
public static final String API_MIN_FW_VER_LIGHTPANELS = "1.5.0";
|
||||
public static final String API_MIN_FW_VER_CANVAS = "1.1.0";
|
||||
public static final String MODEL_ID_LIGHTPANELS = "NL22";
|
||||
public static final String MODEL_ID_CANVAS = "NL29";
|
||||
|
||||
public static final List<String> MODELS_WITH_TOUCHSUPPORT = Arrays.asList("NL29", "NL42");
|
||||
public static final String DEVICE_TYPE_LIGHTPANELS = "lightPanels";
|
||||
public static final String DEVICE_TYPE_CANVAS = "canvas";
|
||||
public static final String DEVICE_TYPE_TOUCHSUPPORT = "canvas"; // we need to keep this enum for backward
|
||||
// compatibility even though not only canvas type
|
||||
// support touch
|
||||
|
||||
// mDNS discovery service type
|
||||
// see http://forum.nanoleaf.me/docs/openapi#_gf9l5guxt8r0
|
||||
|
||||
@ -49,6 +49,7 @@ public class OpenAPIUtils {
|
||||
|
||||
// Regular expression for firmware version
|
||||
private static final Pattern FIRMWARE_VERSION_PATTERN = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)");
|
||||
private static final Pattern FIRMWARE_VERSION_PATTERN_BETA = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)-(\\d+)");
|
||||
|
||||
public static Request requestBuilder(HttpClient httpClient, NanoleafControllerConfig controllerConfig,
|
||||
String apiOperation, HttpMethod method) throws NanoleafException {
|
||||
@ -162,11 +163,21 @@ public class OpenAPIUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int[] getFirmwareVersionNumbers(String firmwareVersion) throws IllegalArgumentException {
|
||||
public static int[] getFirmwareVersionNumbers(String firmwareVersion) throws IllegalArgumentException {
|
||||
LOGGER.debug("firmwareVersion: {}", firmwareVersion);
|
||||
Matcher m = FIRMWARE_VERSION_PATTERN.matcher(firmwareVersion);
|
||||
if (!m.matches()) {
|
||||
throw new IllegalArgumentException("Malformed controller firmware version");
|
||||
|
||||
if (m.matches()) {
|
||||
return new int[] { Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)),
|
||||
Integer.parseInt(m.group(3)) };
|
||||
} else {
|
||||
m = FIRMWARE_VERSION_PATTERN_BETA.matcher(firmwareVersion);
|
||||
if (m.matches()) {
|
||||
return new int[] { Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)),
|
||||
Integer.parseInt(m.group(3)), Integer.parseInt(m.group(4)) };
|
||||
} else {
|
||||
throw new IllegalArgumentException("Malformed controller firmware version " + firmwareVersion);
|
||||
}
|
||||
}
|
||||
return new int[] { Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)), Integer.parseInt(m.group(3)) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ public class NanoleafMDNSDiscoveryParticipant implements MDNSDiscoveryParticipan
|
||||
properties.put(Thing.PROPERTY_MODEL_ID, modelId);
|
||||
properties.put(Thing.PROPERTY_VENDOR, "Nanoleaf");
|
||||
String qualifiedName = service.getQualifiedName();
|
||||
logger.debug("AVR found: {}", qualifiedName);
|
||||
logger.debug("Device found: {}", qualifiedName);
|
||||
|
||||
logger.trace("Discovered nanoleaf host: {} port: {} firmWare: {} modelId: {} qualifiedName: {}", host, port,
|
||||
firmwareVersion, modelId, qualifiedName);
|
||||
|
||||
@ -17,10 +17,7 @@ import static org.openhab.binding.nanoleaf.internal.NanoleafBindingConstants.*;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Scanner;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
@ -132,8 +129,8 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
||||
|
||||
Map<String, String> properties = getThing().getProperties();
|
||||
String propertyModelId = properties.get(Thing.PROPERTY_MODEL_ID);
|
||||
if (MODEL_ID_CANVAS.equals(propertyModelId)) {
|
||||
config.deviceType = DEVICE_TYPE_CANVAS;
|
||||
if (hasTouchSupport(propertyModelId)) {
|
||||
config.deviceType = DEVICE_TYPE_TOUCHSUPPORT;
|
||||
} else {
|
||||
config.deviceType = DEVICE_TYPE_LIGHTPANELS;
|
||||
}
|
||||
@ -334,9 +331,9 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
||||
|
||||
private synchronized void startTouchJob() {
|
||||
NanoleafControllerConfig config = getConfigAs(NanoleafControllerConfig.class);
|
||||
if (!config.deviceType.equals(DEVICE_TYPE_CANVAS)) {
|
||||
if (!config.deviceType.equals(DEVICE_TYPE_TOUCHSUPPORT)) {
|
||||
logger.debug("NOT starting TouchJob for Panel {} because it has wrong device type '{}' vs required '{}'",
|
||||
this.getThing().getUID(), config.deviceType, DEVICE_TYPE_CANVAS);
|
||||
this.getThing().getUID(), config.deviceType, DEVICE_TYPE_TOUCHSUPPORT);
|
||||
return;
|
||||
} else {
|
||||
logger.debug("Starting TouchJob for Panel {}", this.getThing().getUID());
|
||||
@ -353,6 +350,10 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasTouchSupport(@Nullable String deviceType) {
|
||||
return (MODELS_WITH_TOUCHSUPPORT.contains(deviceType));
|
||||
}
|
||||
|
||||
private synchronized void stopTouchJob() {
|
||||
if (touchJob != null && !touchJob.isCancelled()) {
|
||||
logger.debug("Stop touch job");
|
||||
@ -636,9 +637,9 @@ public class NanoleafControllerHandler extends BaseBridgeHandler {
|
||||
|
||||
Configuration config = editConfiguration();
|
||||
|
||||
if (MODEL_ID_CANVAS.equals(controllerInfo.getModel())) {
|
||||
config.put(NanoleafControllerConfig.DEVICE_TYPE, DEVICE_TYPE_CANVAS);
|
||||
logger.debug("Set to device type {}", DEVICE_TYPE_CANVAS);
|
||||
if (hasTouchSupport(controllerInfo.getModel())) {
|
||||
config.put(NanoleafControllerConfig.DEVICE_TYPE, DEVICE_TYPE_TOUCHSUPPORT);
|
||||
logger.debug("Set to device type {}", DEVICE_TYPE_TOUCHSUPPORT);
|
||||
} else {
|
||||
config.put(NanoleafControllerConfig.DEVICE_TYPE, DEVICE_TYPE_LIGHTPANELS);
|
||||
logger.debug("Set to device type {}", DEVICE_TYPE_LIGHTPANELS);
|
||||
|
||||
@ -318,7 +318,7 @@ public class NanoleafPanelHandler extends BaseThingHandler {
|
||||
}
|
||||
}
|
||||
} catch (NanoleafNotFoundException nfe) {
|
||||
logger.warn("Panel data could not be retrieved as no data was returned (static type missing?) : {}",
|
||||
logger.debug("Panel data could not be retrieved as no data was returned (static type missing?) : {}",
|
||||
nfe.getMessage());
|
||||
} catch (NanoleafBadRequestException nfe) {
|
||||
logger.debug(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
binding.nanoleaf.name = Nanoleaf Binding
|
||||
binding.nanoleaf.description = Integrates the Nanoleaf Light Panels (v150320)
|
||||
binding.nanoleaf.description = Integrates the Nanoleaf Light Panels (v010221)
|
||||
|
||||
# thing types
|
||||
thing-type.nanoleaf.controller.name = Nanoleaf Controller
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
binding.nanoleaf.name = Nanoleaf Binding
|
||||
binding.nanoleaf.description = Binding für die Integration des Nanoleaf Light Panels (v150320)
|
||||
binding.nanoleaf.description = Binding für die Integration des Nanoleaf Light Panels (Ein mit dem Controller verbundenes Paneel)
|
||||
|
||||
# thing types
|
||||
thing-type.nanoleaf.controller.name = Nanoleaf Controller
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test Firmware check
|
||||
*
|
||||
* @author Stefan Höhn - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class OpenAPUUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testStateOn() {
|
||||
int[] versions = OpenAPIUtils.getFirmwareVersionNumbers("5.1.2");
|
||||
assertThat(versions[0], is(5));
|
||||
assertThat(versions[1], is(1));
|
||||
assertThat(versions[2], is(2));
|
||||
int[] versions2 = OpenAPIUtils.getFirmwareVersionNumbers("5.1.2-4");
|
||||
assertThat(versions2[0], is(5));
|
||||
assertThat(versions2[1], is(1));
|
||||
assertThat(versions2[2], is(2));
|
||||
assertThat(versions2[3], is(4));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user