[nanoleaf] Nanoleaf Aurora binding (just started development, collecting requirements)

I have not defined anything in .things. (auto-discover only)

My .items looks like:

Switch CanvasKitchenPower       (kitchen) { channel = "nanoleaf:controller:9F276836E179:power" }
Color CanvasKitchenColor                  { channel = "nanoleaf:controller:9F276836E179:color" }
Dimmer CanvasKitchenTempSlider            { channel = "nanoleaf:controller:9F276836E179:colorTemperature" }
Number CanvasKitchenTempAbs               { channel = "nanoleaf:controller:9F276836E179:colorTemperatureAbs" }
String CanvasKitchenColorMode             { channel = "nanoleaf:controller:9F276836E179:colorMode" }
String CanvasKitchenEffect                { channel = "nanoleaf:controller:9F276836E179:effect" }
Switch CanvasKitchenRhythmState           { channel = "nanoleaf:controller:9F276836E179:rhythmState" }
Switch CanvasKitchenRhythmActive          { channel = "nanoleaf:controller:9F276836E179:rhythmActive" }
Number CanvasKitchenRhythmMode            { channel = "nanoleaf:controller:9F276836E179:rhythmMode" }

Number CanvasTouchId      (canvasTouch)
Number CanvasTouchGesture (canvasTouch) 

Example rule:

rule "Nanoleaf touch"
when
    Member of canvasTouch received update
then
    logInfo("CanvasTouch", triggeringItem.name + " State=" + triggeringItem.state)

    switch(triggeringItem.name) {
        case "CanvasTouchId":{  
          logInfo("CanvasTouch", "PanelId=" + triggeringItem.state + " gesture=" + CanvasTouchGesture.state)
          switch(triggeringItem.state) {
              case 22092: {
                  CanvasKitchenPower.sendCommand(if (CanvasKitchenPower.state==ON) OFF else ON)
                  if (CanvasKitchenPower.state==OFF) {
                      CanvasKitchenColor.sendCommand(100)
                      CanvasKitchenEffect.sendCommand("Fray")
                  }
              }
              case 15141: {
                  CanvasKitchenColor.sendCommand(25)
                  CanvasKitchenEffect.sendCommand("WhiteDimmed")
              }
              case 42426: {
                  BuildInKjokkenBench.sendCommand(if (BuildInKjokkenBench.state==ON) OFF else ON)
              }
              case 42633: {
                  if (CanvasKitchenEffect.state != "Meteor Shower") {
                    CanvasKitchenEffect.sendCommand("Meteor Shower")
                    BuildInKjokkenBench.sendCommand(OFF)
                  } else {
                    CanvasKitchenColor.sendCommand(25)
                    CanvasKitchenEffect.sendCommand("WhiteDimmed")
                  }
              }
              case 38949: {
                  var HSBType currentState
                  currentState = CanvasKitchenColor.state as HSBType
                  var DecimalType new_H = currentState.hue
                  var PercentType new_S = currentState.saturation
                  var PercentType new_B = new PercentType(currentState.brightness as Number + 10)
                  logInfo("File", "color test: hue = {} sat = {} bright = {}", new_H, new_S, new_B)
                  var HSBType newState = new HSBType(new_H, new_S, new_B)
                  logInfo("File", "color test: hue = {} sat = {} bright = {}", new_H, new_S, new_B)
                  CanvasKitchenColor.sendCommand(newState)
                  logInfo("CanvasTouch", "CanvasKitchenColor=" + CanvasKitchenColor.state)
              }
              case 20017: {
                  var HSBType currentState
                  currentState = CanvasKitchenColor.state as HSBType
                  var DecimalType new_H = currentState.hue
                  var PercentType new_S = currentState.saturation
                  var PercentType new_B = new PercentType(currentState.brightness as Number - 10)
                  logInfo("File", "color test: hue = {} sat = {} bright = {}", new_H, new_S, new_B)
                  var HSBType newState = new HSBType(new_H, new_S, new_B)
                  logInfo("File", "color test: hue = {} sat = {} bright = {}", new_H, new_S, new_B)
                  CanvasKitchenColor.sendCommand(newState)
                  logInfo("CanvasTouch", "CanvasKitchenColor=" + CanvasKitchenColor.state)
              }
          }
        } 
        default: {
        }
    }
end

rule "Nanoleaf color"
when
    Item CanvasKitchenColor changed
then
    logInfo("CanvasTouch", CanvasKitchenColor.name + " State=" + CanvasKitchenColor.state)
end

rule "Nanoleaf effect"
when
    Item CanvasKitchenEffect changed
then
    logInfo("CanvasTouch", CanvasKitchenEffect.name + " State=" + CanvasKitchenEffect.state)
end

@OMR Can you explain the setup to get it running?

@mraepple Do you plan to support touches with the binding?

cheers
Stefan

I’m having this issue:

Is there any work around other than actually fixing the bug? How have everyone else got it running?

Hi - I submitted this pull request which fixes the issue. Tested successfully on OH 2.4 and 2.5 (latest snapshot).

Hi Stefan, no, because I don’t own a Canvas/touch device for testing. However, based on the API documentation, I started this branch which may be a good start for somebody owning a Canvas to continue testing and developing :slight_smile:

Best regards
Martin

Hi @mraepple,

I am happy to help you even with programming. Also I have two panel Panels with which I can try out the implementation.

Did you see @OMR 's implementation in python here? Nanoleaf Canvas, capturing Touch Events

Just tell me what I should do with the branch and how I could build the binding out of it to deploy it on my openhab installation.

cheers
Stefan

Hi Stefan,

No - not yet, but looks like a nice solution when using the Canvas as stylish switches! As mentioned by @OMR , it would be great to have this functionality integrated in the binding one day.

This is great. I can only fly blind when developing against the API documentation.

I’ve forked the current OH2 addon repo (which now contains the latest bug fixes for the binding) and created a new feature branch for the Canvas device support. You can clone it from here. After that, just go into the bundles\org.openhab.binding.nanoleaf subdirectory, and run mvn clean install -DskipTests. This should build in the target directory a JAR file you can use for testing with your devices.

After you have deployed the new JAR file to your OpenHAB (test) instance, go to the binding configuration (e.g. in PaperUI). There you will see a new configuration parameter for the “Device Type”, which allows you to switch between “Light Panels” and “Canvas” device.

If you want to see my initial changes made to the current version of the binding to support the Canvas device, you can use this view on GitHub.

Hope this helps to get you started, and let me know if you have any questions.

Cheers
Martin

After giving up the last time, I tried it again tonight, but still ran into the same problem with auto discovery. So now, I removed everything and added all 21 panels as items by hand, using the template from the readme. Once done, I opened the site map in the basic UI and tried the controller first … on/off … not working. No errors in log. I tried changing the color of a single panel … nothing. Only errors from missing mappings (Null, - ) in the log. I checked the .items file twice for proper IP, port and auth … all good. This is the last thing in my home that I haven’t integrated and I’m quite frustrated. There are so many possibilities for using the lightpanels as status indicators/output for various processes around the home. Or for simply displaying the weather forecast …

But is this being developed anymore, besides canvas? It seems the last commit to the master branch was in January…

Yes, it is. I picked it up by adding the canvas and it is working fine for that and it is working well for light panels on Martin’s side. Do you mind to wait until the latest version with my addition has been made available and we then start debugging it.

I have also made the documentation a bit more elaborate how to solve some common problems which might help you.

Here is the link to the unreleased documentation:
https://github.com/raepple/openhab2-addons/blob/canvas_touch_support/bundles/org.openhab.binding.nanoleaf/README.me

Please use autodiscovery only. I described it in detail as it wasn’t completely clear to me as well in the beginning.

In the meantime: you know how set the logging of the binding to debug and could you provide the logs to me?

Cheers
Stefan

Hey guys,
I can also only control the whole Aurora but not every single tile. Since Nanoleaf firmware updates frequently change the API i was reluctant to update in the past . I would be happy to also test once the new version is out.

Sebastian, I had the same issue as I didn’t really understood how to setup the tiles (we call them lightpanels). Please follow the new instructions that I have posted above and see if the controller is discovered. Then run a second discovery which should discover the lightpanels (hence tiles). Only then try to access them. Note that accessing (general) settings at the controller may overwrite the settings on a single lightpanel.

Hope that helps
Stefan

Oh so I should check out the canvas branch? Yes, I have set it to debug already. I’d be happy to test the new Version as well. With some luck, I’ll be able to do some testing on Wednesday.

Is there a snapshot ready for check out? The link to the new docu is not working for me (404).
I guess you mean this?

It doesn’t seem much different than the previous docu, just the touch stuff is new :slight_smile:

  • Yes, that’s the link and the readme.
  • From an implementation perspective in terms of discovery, nothing really has changed.
  • However I wrote a lot around how you should do the discovery. Please follow exactly the way it is described here.

And no, you should not checkout the new branch (nor any new artifact) there as it is still under development and review - I only provided it as a reference to the Readme.

Discovery works well for both panel types with the official latest version as it has been tested by Martin and me. So if you encounter any issues, please explain in details how you did the discovery (please use autodiscovery) and the log files.

  • Did you pair the controller?
  • Do the logs say that pairing went well?
  • Is the controller online?
  • Can you power on / off the whole nanoleaf via OH with the controller items?
  • Did you run a second discovery?

cheers
Stefan

i cant find the nanoleaf binding !?
( openhabian 2.4 )

You mean in general or the one who supports the canvas touch support? The touch support version is still under review (@mraepple and I are currently finalizing it).

Cheers
Stefan

yes, the general one, for the triangles. no touch
cant find it in PaperUI > Addons > Bindings

If you look at the post above at Jan 11 @mraepple announced it to be on 2.5. So unfortunately you need upgrade to 2.5 to have it.

Stefan

thank you, danke stefan. I’ll wait for the stable version :wink:

If you don’t require touch support the current version is stable. I have been using it myself for many weeks before I started contributing to it to allow touch support. Even though it wasn’t designed specifically for the nanoleaf canvas, it works pretty well as there no specifics that wouldn’t let it run smoothly.

Hi Stefan,

sorry it took me some time to get back to it. So here’s what I did today.

I removed the old nanoleaf thing. Then I noticed there were still some items left. I couldn’t remove them from paper UI. So I tried from habmin:

2019-12-03 21:53:23.795 [INFO ] [rest.core.internal.item.ItemResource] - Received HTTP DELETE request at 'items/AuroraWohnzimmer_Brightness' for the unknown item 'AuroraWohnzimmer_Brightness'.

Weird … but I’d guess it’s not a problem. So I restarted the openhab service to get a clean start. The apprently “unknown item” was still present after the restart.

So here the log after the restart and accepting the Nanoleaf Controller from the Inbox with the default name.

2019-12-03 21:58:01.206 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Nanoleaf found: 192.168.0.40 16021
2019-12-03 21:58:01.209 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Adding Nanoleaf light panels to inbox: 62D0E39E8239 at 192.168.0.40
2019-12-03 21:58:01.211 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Nanoleaf Type: NL22
2019-12-03 21:58:02.694 [INFO ] [thome.model.lsp.internal.ModelServer] - Started Language Server Protocol (LSP) service on port 5007
2019-12-03 21:58:03.898 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'nanoleaf:lightpanels:62D0E39E8239' to inbox.
2019-12-03 21:58:04.773 [INFO ] [.dashboard.internal.DashboardService] - Started Dashboard at http://192.168.0.199:8080
2019-12-03 21:58:04.777 [INFO ] [.dashboard.internal.DashboardService] - Started Dashboard at https://192.168.0.199:8443
2019-12-03 21:58:05.241 [INFO ] [arthome.ui.paper.internal.PaperUIApp] - Started Paper UI at /paperui
2019-12-03 21:58:06.503 [INFO ] [ui.habmin.internal.servlet.HABminApp] - Started HABmin servlet at /habmin
2019-12-03 21:58:06.733 [INFO ] [.transport.mqtt.MqttBrokerConnection] - Starting MQTT broker connection to 'localhost' with clientid paho4519767739041426 and file store '/var/lib/openhab2/mqtt/localhost'
2019-12-03 22:00:17.816 [WARN ] [.core.thing.binding.BaseThingHandler] - Handler NanoleafHandler tried updating the thing status although the handler was already disposed.
2019-12-03 22:00:17.821 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Start pairing job, interval=25 sec
2019-12-03 22:00:17.902 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=10<=40,i=0,q=3}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-92,5,main]
2019-12-03 22:00:17.906 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=10<=40,i=0,q=3}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-93,5,main]
2019-12-03 22:00:18.315 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Auth token response code: 403

This went on for some time, as I got distracted. Then I pressed the power button to allow pairing:

2019-12-03 22:06:59.292 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=20<=40,i=0,q=15}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-93,5,main]
2019-12-03 22:06:59.330 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Auth token response code: 403
2019-12-03 22:06:59.671 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Nanoleaf 62D0E39E8239 updated
2019-12-03 22:06:59.675 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Stop pairing job
2019-12-03 22:06:59.678 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Start initializing light panels
2019-12-03 22:06:59.698 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Start pairing job, interval=25 sec
2019-12-03 22:06:59.731 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=20<=40,i=0,q=7}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-92,5,main]
2019-12-03 22:06:59.735 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=20<=40,i=0,q=7}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-93,5,main]
2019-12-03 22:06:59.913 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Auth token response code: 403
2019-12-03 22:07:24.926 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=17<=40,i=16,q=14}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-92,5,main]
2019-12-03 22:07:24.930 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=17<=40,i=16,q=14}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-526,5,main]
2019-12-03 22:07:24.934 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=17<=40,i=0,q=12}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-525,5,]
2019-12-03 22:07:24.938 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=17<=40,i=0,q=12}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-529,5,]
2019-12-03 22:07:24.941 [WARN ] [e.jetty.util.thread.QueuedThreadPool] - QueuedThreadPool[ESH-httpClient-common]@fbab2{STOPPING,10<=17<=40,i=0,q=12}[org.eclipse.jetty.util.thread.TryExecutor$$Lambda$116/8106205@15ee4a5] Couldn't stop Thread[ESH-httpClient-common-93,5,main]
2019-12-03 22:07:25.005 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Auth token response code: 200
2019-12-03 22:07:25.018 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Pairing succeeded.

After that the controller is shown as “online”. The things are created and the channels linked.

I can switch the panels on and off. I cannot change effects (nothing to choose). I can change the overall brightness/color for all panels at once. I can change the audio source for the rhythm (probably … not tested if it has an effect).

At some point while playing with the controls, I got this exception (not sure when exactly it happened though)

2019-12-03 22:11:16.903 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Received channel: nanoleaf:lightpanels:62D0E39E8239:color, command: 70
2019-12-03 22:11:16.906 [ERROR] [eaf.internal.handler.NanoleafHandler] - Unhandled command type: org.eclipse.smarthome.core.library.types.PercentType
2019-12-03 22:11:16.909 [ERROR] [nal.common.AbstractInvocationHandler] - An error occurred while calling method 'ThingHandler.handleCommand()' on 'org.openhab.binding.nanoleaf.internal.handler.NanoleafHandler@8be0d1': Unhandled command type
org.openhab.binding.nanoleaf.internal.NanoleafException: Unhandled command type
        at org.openhab.binding.nanoleaf.internal.handler.NanoleafHandler.sendEffectCommand(NanoleafHandler.java:148) ~[?:?]
        at org.openhab.binding.nanoleaf.internal.handler.NanoleafHandler.handleCommand(NanoleafHandler.java:189) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
        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.$Proxy138.handleCommand(Unknown Source) [212:org.openhab.binding.nanoleaf:2.5.0.201901190212]
        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.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
        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) [?:?]
2019-12-03 22:11:19.683 [DEBUG] [eaf.internal.handler.NanoleafHandler] - Received channel: nanoleaf:lightpanels:62D0E39E8239:color, command: 177,100,70
2019-12-03 22:11:19.989 [DEBUG] [eaf.internal.handler.NanoleafHandler] - API response code: 204

When I look at configuration -> things, I only have the one nanoleaf thing

Light Panels 52:44:31

Nanoleaf Light Panels

nanoleaf:lightpanels:62D0E39E8239

So I go to the Inbox - and it’s empty
I click the scan button on the top right corner and choose the nanoleaf binding … nothing happens. Nothing in the log.
I press the “search for things” button at the bottom of the inbox and choose nanoleaf again.

Now this is in the log:

2019-12-03 22:17:50.067 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Nanoleaf Type: NL22
2019-12-03 22:17:50.070 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Nanoleaf found: 192.168.0.40 16021
2019-12-03 22:17:50.072 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Adding Nanoleaf light panels to inbox: 62D0E39E8239 at 192.168.0.40
2019-12-03 22:17:50.075 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Nanoleaf Type: NL22
2019-12-03 22:18:03.128 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Nanoleaf Type: NL22
2019-12-03 22:18:03.131 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Nanoleaf found: 192.168.0.40 16021
2019-12-03 22:18:03.133 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Adding Nanoleaf light panels to inbox: 62D0E39E8239 at 192.168.0.40
2019-12-03 22:18:03.136 [DEBUG] [ery.NanoleafMDNSDiscoveryParticipant] - Nanoleaf Type: NL22

But when I go to the inbox, it’s still empty.
When I go to things … it’s still only the controller.

Not sure what I’m doing wrong … hope the logs help!

[edit]
tried a few more things

  • removed thing, restart service. add thing again from inbox, don’t play with it, so I didn’t get an exception. try scanning … same as above
  • removed thing, restarted service and brought nanoleaf into pairing mode. thing shows up in inbox, I press the ok button and it’s paired (as the log indicates, while adding it, the auth token box was still empty). sadly no changes
  • after the thing was authenticated, i brought the nanoleaf into pairing mode again before starting the second scan from the inbox. no change either.