Binding Request: Nanoleaf Aurora (LED Design Triangle)

I’ve started developing a binding for the Nanoleaf Light Panels over the holidays. A first working version can be found at https://github.com/raepple/nanoleaf-binding.

A jar file to play with is here.

Curious for any feedback. See the README file for more details on the current features.

Best regards

Interesting how great minds think alike :smile:

My code is very similiar to yours, the main differences are how we model the nanloeaf.

I will go with a “bridge”, a Thing for the controller and several Things for the leafs, similar to what the hue binding does. The main reason being that this way, I can address individual panels. Let’s see how it goes.

I did further testing of my binding on an openHAB 2.3 instance and applied some minor changes in the handler to make it also work for this release. Changes are merged in the master branch, and JAR file is updated.

Hi Martin and thanks you for sharing this with us.

Do you think is possible to have a Color Channel for the nanoleaf that can be linked to a ColorPicker ?

I just installed it and I’m not at home, so I can’t pair and test it now. I’ll report my tests later.

Best regards

Excellent idea. I think this could be achieved by setting the panels to an effect of animation type “solid” where they should hold a static color. To avoid saving this effect on the device, there is a “display” command available. A sample request to be sent via PUT to /api/v1/<auth_token>/effects should be as follows:

{"write" : {
	 "command": "display",                     
	 "animType": "solid",
	 "palette": [{
	 "hue": < user > ,
	 "saturation": < user > ,
	 "brightness": < user >
	 }],
	 "colorType": "HSB"
}}

I will give it a try this evening :wink:

This seem to be perfect !

Works like a charm :+1:

I’ve added a “color” channel to the binding which uses the “display” command with animType “solid” to set all panels to the same color. Color channel is of item type “Color”.

Master and README are updated with the new channel, JAR file as well.

Here is a short video showing the binding in action:

1 Like

Hi Martin,

This is great, I’ve tested this new feature with HabPanel and it works perfectly.
Just one thing, with a regular Dimmer, it react to the ON/OFF command and DIM value. This seem to not be the case for the Brightness channel, it don’t react to ON or OFF. Do you think this can be improved ?
Anyway thanks for your works !

Hi!

First of all thanks a lot for testing the new binding with your Nanoleaf.

I’ve played a bit with HabPanel (I am not using it for my home automation) and configured a dimmer widget for the Brightness channel and a switch widget for the Power channel. When the panels are in OFF state and I turn the dimmer wheel, the panels turn on and a second or so later the switch turns on as well. This may be delayed by the refresh period configurable on the thing level.

Is that what you mean? Or did I got it wrong…? :thinking:

Yes, you’re right, let me explain a little bit more.

As you can see in the OpenHAB documentation, a Dimmer item must understand OnOff, Increase / Decrease and Percent command type (https://www.openhab.org/docs/configuration/items.html#type).
And of course, in HABPanel, you can link a switch widget to a Dimmer Item because it can understand ON and OFF command and use it like a standard switch.

I think that if the device can dim, we should use only a Dimmer Item, and the switch item is intended to be used only with non dimmable device.

So, I’m used to setup my switch widgets to a dimmer channel even if a switch channel exist, and, with this, I don’t need to setup 2 Items to do approximately the same things. (a Switch and a Dimmer).

Of course, I can adapt my setup to reach my need, but if it can be improved without much pain, that would be very nice and more OpenHAB compliant.

Best regards.

Thanks for the explanation. I’ve tested the new color channel with basic UI, and when pressing the up/down buttons next to the palette symbol, the handler receives indeed an OnOff command. This is now also properly handled by the binding.
JAR file is updated (as always :wink: )

Martin, did you try control each pannel separately? :face_with_raised_eyebrow:

as each pannel have own ID …

I’ve tested ON/OFF command on the Color channel and it works, but each command I’ve got the following error in the openhab.log :
2019-01-18 18:01:51.361 [ERROR] [nal.common.AbstractInvocationHandler] - An error occurred while calling method 'ThingHandler.handleCommand()' on 'org.openhab.binding.nanoleaf.internal.handler.NanoleafHandler@35a8b80c': Failed to send OpenAPI request: org.eclipse.jetty.client.HttpResponseException: HTTP protocol violation: bad response on HttpConnectionOverHTTP@1bfaf522(l:/192.168.0.100:36630 &lt;-&gt; r:/192.168.0.106:16021,closed=false)=&gt;HttpChannelOverHTTP@48a112d5(exchange=HttpExchange@484f14b req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@de2b60e(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@2b0df80b{s=START}],recv=HttpReceiverOverHTTP@6bfa6005(rsp=IDLE,failure=null)[HttpParser{s=CLOSE,0 of -1}]]&lt;-SocketChannelEndPoint@48d7ca98{/192.168.0.106:16021&lt;-&gt;/192.168.0.100:36630,OPEN,fill=-,flush=-,to=1/0}{io=1/0,kio=1,kro=1}-&gt;HttpConnectionOverHTTP@1bfaf522(l:/192.168.0.100:36630 &lt;-&gt; r:/192.168.0.106:16021,closed=false)=&gt;HttpChannelOverHTTP@48a112d5(exchange=HttpExchange@484f14b req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@de2b60e(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@2b0df80b{s=START}],recv=HttpReceiverOverHTTP@6bfa6005(rsp=IDLE,failure=null)[HttpParser{s=CLOSE,0 of -1}]]

org.openhab.binding.nanoleaf.internal.NanoleafException: Failed to send OpenAPI request: org.eclipse.jetty.client.HttpResponseException: HTTP protocol violation: bad response on HttpConnectionOverHTTP@1bfaf522(l:/192.168.0.100:36630 &lt;-&gt; r:/192.168.0.106:16021,closed=false)=&gt;HttpChannelOverHTTP@48a112d5(exchange=HttpExchange@484f14b req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@de2b60e(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@2b0df80b{s=START}],recv=HttpReceiverOverHTTP@6bfa6005(rsp=IDLE,failure=null)[HttpParser{s=CLOSE,0 of -1}]]&lt;-SocketChannelEndPoint@48d7ca98{/192.168.0.106:16021&lt;-&gt;/192.168.0.100:36630,OPEN,fill=-,flush=-,to=1/0}{io=1/0,kio=1,kro=1}-&gt;HttpConnectionOverHTTP@1bfaf522(l:/192.168.0.100:36630 &lt;-&gt; r:/192.168.0.106:16021,closed=false)=&gt;HttpChannelOverHTTP@48a112d5(exchange=HttpExchange@484f14b req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@de2b60e(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@2b0df80b{s=START}],recv=HttpReceiverOverHTTP@6bfa6005(rsp=IDLE,failure=null)[HttpParser{s=CLOSE,0 of -1}]] at org.openhab.binding.nanoleaf.internal.handler.NanoleafHandler.sendOpenAPIRequest(NanoleafHandler.java:417) ~[?:?] at org.openhab.binding.nanoleaf.internal.handler.NanoleafHandler.sendEffectCommand(NanoleafHandler.java:148) ~[?:?] at org.openhab.binding.nanoleaf.internal.handler.NanoleafHandler.handleCommand(NanoleafHandler.java:181) ~[?:?] at sun.reflect.GeneratedMethodAccessor114.invoke(Unknown Source) ~[?:?] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?] at org.eclipse.smarthome.core.internal.common.AbstractInvocationHandler.invokeDirect(AbstractInvocationHandler.java:153) [102:org.eclipse.smarthome.core:0.10.0.oh240] at org.eclipse.smarthome.core.internal.common.InvocationHandlerSync.invoke(InvocationHandlerSync.java:59) [102:org.eclipse.smarthome.core:0.10.0.oh240] at com.sun.proxy.$Proxy200.handleCommand(Unknown Source) [275:org.openhab.binding.nanoleaf:2.5.0.201901172300] at org.eclipse.smarthome.core.thing.internal.profiles.ProfileCallbackImpl.handleCommand(ProfileCallbackImpl.java:75) [109:org.eclipse.smarthome.core.thing:0.10.0.oh240] at org.eclipse.smarthome.core.thing.internal.profiles.SystemDefaultProfile.onCommandFromItem(SystemDefaultProfile.java:49) [109:org.eclipse.smarthome.core.thing:0.10.0.oh240] at sun.reflect.GeneratedMethodAccessor113.invoke(Unknown Source) ~[?:?] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?] at org.eclipse.smarthome.core.internal.common.AbstractInvocationHandler.invokeDirect(AbstractInvocationHandler.java:153) [102:org.eclipse.smarthome.core:0.10.0.oh240] at org.eclipse.smarthome.core.internal.common.Invocation.call(Invocation.java:53) [102:org.eclipse.smarthome.core:0.10.0.oh240] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?] at java.lang.Thread.run(Thread.java:748) [?:?]

… but it works :slight_smile:

Do you plan to add this code to the Brightness channel also or must I change my HABPanel config to send switchs commands to the Color Channel ?

Best regards

Yes, I’ve added the OnOff command type handling to all remaining channels of type dimmer (brightness and saturation), so I hope you won’t need to change your config in HABPanel.

I’ve checked my logs for similar exceptions but couldn’t find any. May be you can give the updated binding JAR a chance and check the logs again.

Best regards

I just didn’t tested it because you wrote about Color channel :slight_smile:
To be sure, I deleted my thing, deleted the jar file, downloaded the latest release, scanned for nanoleaf thing, added it and checked that my items were linked correctly.
And it works like a charm ! ON/OFF command on Brightness channel didn’t throw any errors but same command to the Color channel gave me the same error as before, but it also works.
I also tested with OpenHAB REST API just to be sure this is not a HABPanel behavior.

Thanks you so much !

Yes, the API would allow us to control each panel separately - I’ve tested that. So it should be possible to keep the binding as it is today with all the channels (brightness, hue, effects …) for the controller (probably becoming a thing of type bridge then), and handle each panel as a separate thing, e.g. with just a color channel.

Honestly I thought to get started simple with one thing only, and then explore further extensions if needed. In general I believe that the native Nanoleaf app is still the better tool for designing new scenes/effects. It nicely illustrates the currently chosen layout of the panels in the scene editor where you can configure the individual panels. I don’t know if something similar could be done in any of the openHAB UIs, but even if it were possible, I think that “design” should remain with the native app, but “control” should be possible with openHAB.

On the other side, I can imagine that you want to dynamically set a static color per panel out of your rules, e.g. to display a visual message depending on some event that happend. One could certainly just design a scene with the native app, and then set it via the effect channel of the binding. But I still see that controlling individual panels could be of value. If you have other ideas/use cases in mind, please me/us know.

Best regards
Martin

This is actually why I started modeling my binding with a Bridge thing (and then the panels as distinct Things, if required by the user). Basically following the hue model.

Hi Nanoleaf-enthusiasts ;-),

I’ve picked up on @CoolTom’s and @hakan’s idea and played a bit with my existing binding. I enhanced it with a second thing: “lightpanel”. I renamed the existing thing type to “controller”. So we now have two types, representing the light panels controller (similar to a bridge) and the individual light panel(s) connected to it.

The controller thing got a new configuration parameter “discoverPanels” which can be turned on and off. If turned on for a controller which is online (i.e. has a valid auth token, ip address etc.), all connected panels will be added to the inbox as new things. In my case, I have 13 panels connected to my controller, so I end up with 14 things (1 for the controller, 13 for the panels).

The channels on the controller did not change - effect, brightness etc. remained the same as before. An individual panel exposes one channel of type Color to set the color with a ColorPicker. When sending On or Off to it, the panel turns dark or white.

If you want to play with the extended version, you can get a new JAR from here. The source code is in a new branch in my git repo. The README is updated with an example for the new setup.

@hakan: Hope this goes into the same direction as you proposed initially. Again, curious for any feedback :wink:

This version is still not tested very well and the code could be beautified, but I hope this goes to the right direction.

Best regards
Martin

1 Like

WOW, very nice. I will try and let you know. Thanks for very fast changes.

I’m very curious to give his a test run. Tomorrow maybe, if my Octoprint stops throwing monkey wrenches into my best laid plans :grin: