Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tradfri][WIP] Adds basic support for IKEA smart blinds FYRTUR and KADRILJ #6167

Closed
wants to merge 2 commits into from

Conversation

manraf
Copy link

@manraf manraf commented Oct 3, 2019

Recently, IKEA released two new, rechargeable smart blinds "FYRTUR" and "KADRILJ" (first one is lightproof, second one slightly translucent). The changes in this PR add basic support for those blinds to the binding with the possibility to open and close the blinds as well as set the to a specific position (percentage between 0 and 100). Furthermore, the current battery level of the blind is exposed and also the "battery low" status which is triggered if the level is below 10 percent.

The PR is marked [WIP] because the new thing is of type "Rollershutter" and therefore should support Stop/Move commands as well, which have not been implemented yet. Maybe someone can figure this out faster than me. Also, I guess the additions and adjustments of the README and language files could be better. As "blinds" are not mentioned in the "ZigBee LightLink" document, which apparently is the source for all thing type ids, a temporary id of "0999" was used for them. A final id needs to be figured out somehow.

* adds the "blind" thing and associated data
* temporarily assigned zigbee id "0999", needs review

Signed-off-by: Manuel Raffel <manidu@outlook.com>
@TravisBuddy
Copy link

Travis tests were successful

Hey @manraf,
we found no major flaws with your code. Still you might want to look at this logfile, as we usually suggest some optional improvements.

@TravisBuddy
Copy link

Travis tests were successful

Hey @manraf,
we found no major flaws with your code. Still you might want to look at this logfile, as we usually suggest some optional improvements.

Comment on lines 2 to 3
binding.tradfri.name = TRÅDFRI Binding
binding.tradfri.description = Dieses Binding integriert das IKEA TRÅDFRI System. Durch dieses können die TRÅDFRI Lampen und Leuchten gesteuert werden.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes in this file (apart from the obviously blind-related ones) result from me storing the file with UTF8-encoding, as the special characters where not shown on my PC.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's wrong. Since we use Java 8 the .properties files need ISO-8859-1 encoding, please revert that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the information, committed with ISO 8859-1.

@openhab-bot
Copy link
Collaborator

This pull request has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/ikea-tradri-roller-blind-via-openhab/82977/4

@@ -48,6 +50,10 @@
public static final Set<ThingTypeUID> SUPPORTED_PLUG_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_ONOFF_PLUG).collect(Collectors.toSet()));

public static final Set<ThingTypeUID> SUPPORTED_BLIND_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_BLIND).collect(Collectors.toSet()));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line

Signed-off-by: Manuel Raffel <manidu@outlook.com>
@TravisBuddy
Copy link

Travis tests were successful

Hey @manraf,
we found no major flaws with your code. Still you might want to look at this logfile, as we usually suggest some optional improvements.

@wborn wborn added enhancement An enhancement or new feature for an existing add-on work in progress A PR that is not yet ready to be merged labels Oct 6, 2019
@J-N-K
Copy link
Member

J-N-K commented Oct 6, 2019

The thing-id is the only whing that is missing, or are there other points? @cdjackson, since you are a ZigBee expert, how can we proceed here, what do you suggest?

@cdjackson
Copy link

Isn't this related to the Tradfri binding? I'm not really sure who this binding manages its thing ids - I don't know if it's in any way linked to ZigBee or if the Tradfri gateway provides some sort of abstraction?

ZigBee exposes a string "Model ID" parameter which may be used - or as I said, maybe the gateway does all the detection to decide what the device is and then exposes something completely different...

@manraf
Copy link
Author

manraf commented Oct 6, 2019

The thing-id is the only whing that is missing, or are there other points?

The "official" ZigBee thing id (if there is such a thing - apparently the first version of the binding used some proprietary device's documentation that only applies to lights?) and the Stop/Move command logic.

Using the remote, when the blind is moving and any button is pressed, it stops. However, I have no idea how to find the correct CoAP command to send to the Tradfri gateway for this case. Judging from the IKEA app, a "move" (in the sense of "continue the movement you did before receiving a stop") is not naturally supported, but can be implemented in the binding with some custom logic.

@J-N-K
Copy link
Member

J-N-K commented Oct 6, 2019

Isn't this related to the Tradfri binding? I'm not really sure who this binding manages its thing ids - I don't know if it's in any way linked to ZigBee or if the Tradfri gateway provides some sort of abstraction?

Thanks. My understanding was that this model-id is somehow universally used. Probably the Tradfri gateway is different then.

@cdjackson
Copy link

The "official" ZigBee thing id

There is no such thing - at least not at the ZigBee level. I assume that this comes from the Tradfri gateway and not ZigBee.

ZigBee defines a number of parameters that could be used to derive a thing ID, but this derivation will be dependant on the ZigBee gateway. For example there are attributes for model ID and manufacturer - these could be used in some way, but there's no "official" ZigBee thing ID.

Move...

I don't know what clusters this is supporting - I assume the window covering cluster, but maybe it's the ZLL level control rather than the HA Window Covering.

Sorry - without having one it's hard really to provide a lot of support.

@cweitkamp
Copy link
Contributor

I assume the window covering cluster

Yes, that is correct.

According to the Zigbee 3.0 Cluster Library the cluster identifier is 0x0102 for Window covering devices. We tried to stick to those cluster ids for our thing type definitions.

@cdjackson
Copy link

It seems strange to me to use the cluster ID for the thing type. The cluster is used for transferring commands, and typically a device will support multiple clusters and different devices will support the same clusters.

So if you are using the cluster ID to define your thing type, how do you differentiate between different devices that may need to be supported that all use the same clusters? Ie there may be different window covering devices that ultimately need to be supported - they could work differently, but I'm unclear how you will differentiate them if you use the cluster ID as the thing type?

I would have expected you to use something that defines the device - eg the device model?

Copy link
Contributor

@cweitkamp cweitkamp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for your first contribution over here. I added some comments.

@@ -137,6 +137,25 @@
<config-description-ref uri="thing-type:tradfri:device" />
</thing-type>

<thing-type id="0999">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change the id to "0102" and its label to "Window Covering Device".

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that a "Window Covering Device" is device type 0x202. The "Window Covering" cluster is 0x102, but really it seems very strange to use the cluster ID as a device ID.

Up to you though, but there are other devices that will use this cluster - eg window covering controller has device type 0x203

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. I mixed it up here. The device id should be used: "0202".

if(StopMoveType.STOP.equals(command)) {
// setPosition(state.getPosition());
} else {
// (what) TODO (?)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good question. I am not sure if we are able to interrupt an previous command sent to TRADFRI gateway. I hence suggest to ignore these commands and log a info / warning / debug for the user.

According to the Zigbee Cluster Library is should be possible to send a "stop" on protocol level. Do you know if there is another property beside the position ("5536") available in the TRADFRI COAP interface?

@@ -27,6 +27,8 @@ thing-type.tradfri.0820.label = Kabelloser Dimmer
thing-type.tradfri.0820.description = Der Kabellose Dimmer liefert Daten wie z.B. die Batterieladung.
thing-type.tradfri.0830.label = Fernbedienung
thing-type.tradfri.0830.description = Die Fernbedienung liefert Daten wie z.B. die Batterieladung.
thing-type.tradfri.0999.label = Rollo
thing-type.tradfri.0999.description = Akkubetriebene Rollo mit einstellbarer Position. Liefert au�erdem Daten wie z.B. die Akkuladung.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Batteriebetriebenes Rollo ...

@cweitkamp
Copy link
Contributor

@cdjackson To be honest I do not know the exact reason why. I would assume the Hue binding started with this while Zigbee 1.0 and ZLL were state of the art. For the lights there were specific Zigbee device ids which are reflected into the thing type ids. Later we / l introduced cluster ids when support for sensors (ZHA) has been implemented. Nowadays with Zigbee 3.0 the type will make much more sense. In some bindings the discovery already uses these types to identify the correct thing type.

You have to keep in mind that most of the bindings depend on a vendor specific layer between the Zigbee protocol and openHAB (e.g. Hue -> HTTP REST API, deCONZ -> HTTP REST API and websocket REST API, TRADFRI -> COAP REST API, and so on). They all have their "own" interpretation / ideas and have to be handled slightly different. It is sometimes hard to align them back in OH.

@cdjackson
Copy link

cdjackson commented Oct 13, 2019 via email

@cweitkamp
Copy link
Contributor

That is not my intention. Indeed my vision would be to have a unique thing type registery - maybe the one from your binding - for all other bindings based on Zigbee protocol and different handlers to delegate commands from OH to the specific interface and handle data provided by them ...

@cweitkamp
Copy link
Contributor

We tried to stick to those cluster ids for our thing type definitions.

I will revoke this statement. It seems that I mixed it up. We tried to stick to the device ids for the thing types.

@cdjackson
Copy link

cdjackson commented Oct 13, 2019 via email

@AlexKay88
Copy link

Had a look at my Tradfri gateway with pytradfri, but was not able to find out more as you already know.

{'15015': [{'5536': 100.0, '9003': 0}],
 '3': {'0': 'IKEA of Sweden',
       '1': 'FYRTUR block-out roller blind',
       '2': '',
       '3': '2.2.009',			#firmware version
       '6': 3,
       '9': 100},			#battery level
 '5750': 7,
 '9001': 'My Fyrtur Blind',		#label
 '9002': 1571170307,			#creation date
 '9003': 65559,				#tradfri ID
 '9019': 1,
 '9020': 1571249756,			#last seen date
 '9054': 0},

Only differences after using remote control:

{'15015': [{'5536': 0.0, '9003': 0}],	#blind fully up (bright)
{'15015': [{'5536': 76.0, '9003': 0}],	#blind 76% down (dark)
{'15015': [{'5536': 100.0, '9003': 0}],	#blind fully down (dark)

IKEA Tradfri app shows a "pause" icon while moving to desired position, but I have no idea how to sniff whats sent on the wire when button is pressed.

If you need complete pytradfri output of

'15009': 'TRADFRI open/close remote'
'15014': 'TRADFRI Signal Repeater'

just let me know...
Would be great to test tradfri binding as soon as you got a jar file prepared for OH 2.4.

@AlexKay88
Copy link

Spent some time to analyze my complete environment with pytradfri...
I would suggest to add further constants to TradfriBindingConstants.java for future use:

public static final String REPEATER = "15014";
public static final String TYPE_REPEATER = "6";

5750:6 = REPEATER verified for my repeater (while 5750:0 = SWITCH, 5750:2 = LIGHT, 5750:3 = PLUG, 5750:4 = SENSOR, 5750:7 = BLIND is already known)

public static final String DEVICE_POWER_SOURCE = "6";

3:{0:VENDOR,1:MODEL,3:FIRMWARE,6:3,9:BATTERY_LEVEL} --> 6:3 = 'BATTERY' (verified for my remote controls, on/off switches, wireless dimmers, open/close remotes and roller blinds)

3:{0:VENDOR,1:MODEL,3:FIRMWARE,6:1 (9:DOESN'T EXIST)} --> 6:1 = 'AC' (verified for my bulbs, panels, transformers and repeaters)

DEVICE_BATTERY_LEVEL is only available with 6:3

@sehroriginell
Copy link

Can someone please provide a jar to manually install this version of the binding for testing? Thanks so much!

@AlexKay88
Copy link

I would like to kindly ask for progress here, although I do not understand what is needed to pursue.
Thanks in advance!

@Patrick-L
Copy link

Can someone please provide a jar to manually install this version of the binding for testing? Thanks so much!

Hi
First of all: I have no experience in this field and there are probably leaner JARs than the following one.
But today I made it work with the following Jar. Maybe it will help you too.

org.openhab.binding.tradfri-3.0.0-SNAPSHOT.zip

Kind regards!

@sehroriginell
Copy link

Can someone please provide a jar to manually install this version of the binding for testing? Thanks so much!

Hi
First of all: I have no experience in this field and there are probably leaner JARs than the following one.
But today I made it work with the following Jar. Maybe it will help you too.

org.openhab.binding.tradfri-3.0.0-SNAPSHOT.zip

Kind regards!

Works perfectly! Thanks a lot!

However, I can only set up the things in PaperUI, not manually.

@cweitkamp
Copy link
Contributor

@manraf Are you still around and able to finalize this PR? If not please let me know and I will pick it up.

@sveatlo
Copy link

sveatlo commented Dec 31, 2019

Thanks a lot for this! Really hope to see this merged soon.
I just tried it out and it generally works, but I found a couple of problems.

First of all, I have the same problem as @sehroriginell. When added via configuration files I'm getting a communication error. No further information in logs (maybe i have to up the log level?) or in thing detail (in paper ui).

Second, when the blinds start moving up/down I'm getting a lot (almost on every position update) of errors about value not being between 0 and 100.

==> /var/log/openhab2/events.log <==
2019-12-31 09:43:23.660 [vent.ItemStateChangedEvent] - BlindsPosition changed from 95 to 99
2019-12-31 09:43:24.700 [vent.ItemStateChangedEvent] - BlindsPosition changed from 99 to 100

==> /var/log/openhab2/openhab.log <==
2019-12-31 09:43:24.695 [ERROR] [alifornium.core.network.CoapEndpoint] - Exception in protocol stage thread: Value must be between 0 and 100
java.lang.IllegalArgumentException: Value must be between 0 and 100
	at org.eclipse.smarthome.core.library.types.PercentType.validateValue(PercentType.java:57) ~[bundleFile:?]
	at org.eclipse.smarthome.core.library.types.PercentType.<init>(PercentType.java:52) ~[bundleFile:?]
	at org.eclipse.smarthome.core.library.types.DecimalType.as(DecimalType.java:152) ~[bundleFile:?]
	at org.eclipse.smarthome.core.internal.items.ItemStateConverterImpl.convertToAcceptedState(ItemStateConverterImpl.java:64) ~[?:?]
	at org.eclipse.smarthome.core.thing.internal.profiles.ProfileCallbackImpl.sendUpdate(ProfileCallbackImpl.java:134) ~[bundleFile:?]
	at org.eclipse.smarthome.core.thing.internal.profiles.SystemDefaultProfile.onStateUpdateFromHandler(SystemDefaultProfile.java:53) ~[bundleFile:?]
	at org.eclipse.smarthome.core.thing.internal.CommunicationManager.lambda$9(CommunicationManager.java:467) ~[bundleFile:?]
	at org.eclipse.smarthome.core.thing.internal.CommunicationManager.lambda$11(CommunicationManager.java:487) ~[bundleFile:?]
	at java.lang.Iterable.forEach(Iterable.java:75) ~[?:1.8.0_222]
	at org.eclipse.smarthome.core.thing.internal.CommunicationManager.handleCallFromHandler(CommunicationManager.java:483) ~[bundleFile:?]
	at org.eclipse.smarthome.core.thing.internal.CommunicationManager.stateUpdated(CommunicationManager.java:465) ~[bundleFile:?]
	at org.eclipse.smarthome.core.thing.internal.ThingManagerImpl$1.stateUpdated(ThingManagerImpl.java:168) ~[bundleFile:?]
	at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.updateState(BaseThingHandler.java:257) ~[bundleFile:?]
	at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.updateState(BaseThingHandler.java:276) ~[bundleFile:?]
	at org.openhab.binding.tradfri.internal.handler.TradfriBlindHandler.onUpdate(TradfriBlindHandler.java:60) ~[bundleFile:?]
	at org.openhab.binding.tradfri.internal.TradfriCoapHandler.onLoad(TradfriCoapHandler.java:72) ~[bundleFile:?]
	at org.eclipse.californium.core.CoapClient$ObserveMessageObserverImpl.deliver(CoapClient.java:1068) ~[bundleFile:?]
	at org.eclipse.californium.core.CoapClient$MessageObserverImpl.succeeded(CoapClient.java:996) ~[bundleFile:?]
	at org.eclipse.californium.core.CoapClient$MessageObserverImpl.onResponse(CoapClient.java:975) ~[bundleFile:?]
	at org.eclipse.californium.core.coap.Request.setResponse(Request.java:509) ~[bundleFile:?]
	at org.eclipse.californium.core.network.EndpointManager$ClientMessageDeliverer.deliverResponse(EndpointManager.java:267) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.CoapStack$StackTopAdapter.receiveResponse(CoapStack.java:193) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.AbstractLayer.receiveResponse(AbstractLayer.java:98) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.ObserveLayer.receiveResponse(ObserveLayer.java:137) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.AbstractLayer.receiveResponse(AbstractLayer.java:98) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.BlockwiseLayer.receiveResponse(BlockwiseLayer.java:324) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.AbstractLayer.receiveResponse(AbstractLayer.java:98) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.ReliabilityLayer.receiveResponse(ReliabilityLayer.java:269) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.AbstractLayer.receiveResponse(AbstractLayer.java:98) ~[bundleFile:?]
	at org.eclipse.californium.core.network.stack.CoapStack.receiveResponse(CoapStack.java:135) ~[bundleFile:?]
	at org.eclipse.californium.core.network.CoapEndpoint$InboxImpl.receiveMessage(CoapEndpoint.java:656) ~[bundleFile:?]
	at org.eclipse.californium.core.network.CoapEndpoint$InboxImpl.access$700(CoapEndpoint.java:562) ~[bundleFile:?]
	at org.eclipse.californium.core.network.CoapEndpoint$InboxImpl$1.run(CoapEndpoint.java:574) ~[bundleFile:?]
	at org.eclipse.californium.core.network.CoapEndpoint$5.run(CoapEndpoint.java:721) [bundleFile:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_222]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_222]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_222]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_222]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_222]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_222]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_222]

And the last problem I bumped into is that the blinds cannot be stop midway. The item receives the position, but doesn't act on it.

BlindsPosition changed from 59 to 64
Item 'BlindsPosition' received command STOP
Item 'BlindsPosition' received command STOP
Item 'BlindsPosition' received command STOP
Item 'BlindsPosition' received command STOP
Item 'BlindsPosition' received command STOP
Item 'BlindsPosition' received command STOP
Item 'BlindsPosition' received command STOP
BlindsPosition changed from 64 to 69

@manraf
Copy link
Author

manraf commented Dec 31, 2019

@cweitkamp I'm currently busy with work and holidays. If you've got the time feel free to pick it up, otherwise I might be able to continue end of January...

@KevinHubert-Dev
Copy link

KevinHubert-Dev commented Jan 31, 2020

Any news on this? I am about to buy multiple of those and would love to integrate into my openHab setup. Saw it is only 1 reviewer pending. Looking forward.

The Prerelease provided above won't work in my case, the *.jar is in my addon-folder but openhab does not show it in the bindings.

@cweitkamp
Copy link
Contributor

I rebased this branch and did some minor modifications and tweaks (see 2.5.x...cweitkamp:pr-6167). @manraf How should we continue? I can create a new PR to supersed yours or create a PR against your branch.

Attached you can find a test version for OH 2.5.X or higher: org.openhab.binding.tradfri-2.5.2-SNAPSHOT.zip

@sehroriginell @sveatlo Some questions? When adding the thing via Paper UI does it change its status to ONLINE?

Regarding the IAE: In general it will be thrown if the value is less than 0 or greater than 100. I added a check for those thresholds. I hope it will help.

IKEA Tradfri app shows a "pause" icon while moving to desired position, but I have no idea how to sniff whats sent on the wire when button is pressed.

And the last problem I bumped into is that the blinds cannot be stop midway.

I have to admit that I currently have no idea either. And I am not able to test it. Thus handling of STOP / MOVE command will not work at the moment. May I ask anyone of you to try sending e.g. a negative position ("-1") while the blinds are moving?

@AlexKay88 I am not sure if it makes sense to add the Signal Repeater because there is absolutely not way to interact with it or any sensor data to read from it. Isn't it?

@cweitkamp
Copy link
Contributor

Superseded by #6977

@cweitkamp cweitkamp closed this Feb 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement An enhancement or new feature for an existing add-on work in progress A PR that is not yet ready to be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet