Binding Request: Nanoleaf Aurora (LED Design Triangle)

I have found a workaround for getting the Aurora to work with OpenHab and Alexa.

I installed the Alexa Control binding and that has a feature to run a scene. Since Aurora is native with Alexa, I can have it “run the scene” at sunset.

The whole API was release now, and it seem we have all we need for a good binding.
http://forum.nanoleaf.me/docs/openapi
I’m not be able to achieve this, but I’ve managed to get it working with a rule, only a Dimmer control for the moment.
If it help someone, this is how I done it :

First of all, you need a auth token :

  1. Holding the on-off button down for 5-7 seconds until the LED starts flashing in a pattern

  2. Sending a POST request to the authorization endpoint : http://NANOLEAF-IP:16021/api/v1/new

within 30 seconds of activating pairing.

  1. If 2 is achieved, the POST response will contain a randomly generated authorization token:
    {“auth_token” : “xxxxxxxxxxxxxxxxxxxxx … xxx”}

Next, set up a Dummy Dimmer item :

Dimmer NANOLEAF 

and this is my rule :

rule "Nanoleaf"

when
    Item NANOLEAF received command
then

var String command = receivedCommand.toString.lowerCase
val String MY_URL = 'http://NANOLEAF-IP:16021/api/v1/AUTH-TOKEN/state'
var String myData

if (command == "on") {
	myData = '{"on" : {"value":true}}'

} else if (command == "off") {
	myData = '{"on" : {"value":false}}'

} else {
	myData = '{"brightness" : {"value":' + command + '}}'
}

sendHttpPutRequest(MY_URL, "application/x-www-form-urlencoded", myData)

end

Don’t forget to replace NANOLEAF-IP and AUTH-TOKEN with your proper values in the MY_URL String.

Next I will look how to trigger scenes, and I’ll post progress if some peoples are interested.

Best regards,

Mac_Fly.

Hi MacFly,
your rule Definition works perfectly. I implemented it a couple days ago in my Setup, works fine, even in Habpanel Setups. Please keep us updated on your Progress, I’ ll want to try and contribute to it.

Best regards,
Kai

Hi folks,
I did some fiddling with my nanoleaf and modified the example given above. It is possible to send a “direct” brightness value to a panel. It will then turn on with the given brightness value. I implemented some cron based rules to switch on my panels to 30% brightness at 06:00 in the moring on weekdays and on 07:30 on weekends. Here is my rule definition:

rule "Nanoleaf turns on"
when 
	Time cron "0 0 6 ? * MON-FRI" or //weekdays at 06:00
	Time cron "0 30 7 ? * SAT-SUN" //weekends at 07:30
then
        val String MY_URL = 'http://NANOLEAF-IP:16021/api/v1/AUTH-TOKEN/state'
	myData = '{"brightness" : 30}' //anschalten, 30% Helligkeit
	sendHttpPutRequest(MY_URL, "application/x-www-form-urlencoded", myData)
	logInfo("wohnzimmer.rules","Nanoleaf turns on")
	Nanoleaf_Flur.postUpdate(30)
end

The last line with Nanoleaf_Flur.postUpdate(30) updates an Dimmer Item used in my Habpanel to the correct value. Hope that helps!
Best regards,
Kai

I’ve seen this java api that looks quite simple to integrate

bump nanoleaf

Hi guys,

I have started a Nanoleaf binding. Could you perhaps hop over to my new thread and help collect use cases and requirements?

1 Like

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