[nanoleaf] CODEOWNERs, add Shapes Support, beta-firmware support (#10029)

Signed-off-by: Stefan Höhn <stefan@andreaundstefanhoehn.de>
This commit is contained in:
stefan-hoehn 2021-02-03 21:26:13 +01:00 committed by GitHub
parent f9a982e548
commit 570f86d043
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 115 additions and 42 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

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

View File

@ -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);

View File

@ -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);

View File

@ -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(

View File

@ -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

View File

@ -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

View File

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