KNX - Different DPT for rollershutter position set and read GA

Hello,

I’m new to OpenHAB and KNX, so perhaps there is an easy solution to my problem.

I have an old KNX shutter actuator, which is only capable of sending out the position in the form of three integer values (encoded in 1 byte just like DPT 5.001):

0 - moving/stopped in between
1 - Fully open
2 - Fully closed

Sadly, there is no update for it according to the manufacturer, so unless I’d were to replace all those actuators I have no chance of getting a percent value (0-100%) as the position information.

For the last two days I’ve looked into a solution for at least displaying the available data.

What does not work:

Keeping the default DPT 5.001 for the position parameter in my KNX .things file, as it maps

0 to 0%
1 to 0%
2 to 1%

This is due to the percentage interpretation of the raw data. Then I’d be down to two states.

DPT 5.005 does not work either, as it causes an error for the value 2, the rest would be fine:

java.lang.IllegalArgumentException: Value must be between 0 and 100
        at org.eclipse.smarthome.core.library.types.PercentType.validateValue(PercentType.java:58) ~[?:?]
        at org.eclipse.smarthome.core.library.types.PercentType.<init>(PercentType.java:53) ~[?:?]
        at org.eclipse.smarthome.core.library.types.DecimalType.as(DecimalType.java:160) ~[?:?]
        at org.eclipse.smarthome.core.internal.items.ItemStateConverterImpl.convertToAcceptedState(ItemStateConverterImpl.java:58) ~[?:?]
        at org.eclipse.smarthome.core.thing.internal.profiles.ProfileCallbackImpl.sendUpdate(ProfileCallbackImpl.java:135) ~[?:?]
        at org.eclipse.smarthome.core.thing.internal.profiles.SystemDefaultProfile.onStateUpdateFromHandler(SystemDefaultProfile.java:54) ~[?:?]
        at org.eclipse.smarthome.core.thing.internal.CommunicationManager.lambda$9(CommunicationManager.java:477) ~[?:?]
        at org.eclipse.smarthome.core.thing.internal.CommunicationManager.lambda$11(CommunicationManager.java:497) ~[?:?]
        at java.lang.Iterable.forEach(Iterable.java:75) ~[?:?]
        at org.eclipse.smarthome.core.thing.internal.CommunicationManager.handleCallFromHandler(CommunicationManager.java:493) ~[?:?]
        at org.eclipse.smarthome.core.thing.internal.CommunicationManager.stateUpdated(CommunicationManager.java:475) ~[?:?]
        at org.eclipse.smarthome.core.thing.internal.ThingManagerImpl$1.stateUpdated(ThingManagerImpl.java:167) ~[?:?]
        at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.updateState(BaseThingHandler.java:287) ~[?:?]
        at org.openhab.binding.knx.internal.handler.DeviceThingHandler.processDataReceived(DeviceThingHandler.java:399) ~[?:?]
        at org.openhab.binding.knx.internal.handler.DeviceThingHandler.lambda$11(DeviceThingHandler.java:352) ~[?:?]
        at org.openhab.binding.knx.internal.handler.DeviceThingHandler.withKNXType(DeviceThingHandler.java:128) ~[?:?]
        at org.openhab.binding.knx.internal.handler.DeviceThingHandler.onGroupWrite(DeviceThingHandler.java:331) ~[?:?]
        at org.openhab.binding.knx.internal.client.AbstractKNXClient$1.lambda$0(AbstractKNXClient.java:111) ~[?:?]
        at org.openhab.binding.knx.internal.client.AbstractKNXClient.lambda$8(AbstractKNXClient.java:258) ~[?:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:?]
        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) [?:?]

Last I tried DPT 5.004, which works. It successfully parses the values the way they are sent.

0 to 0
1 to 1
2 to 2

The KNX2 binding however only allows a change of DPT value if it matches the following format:

position="5.004:GA-SET+<GA-READ"

and stops reading the position if I try either of the following

5.001:GA-SET+5.004:<GA-READ
5.001:GA-SET+<5.004:GA-READ

As a result I now have to use the values 0-255 for moving the rollershutter to 0-100%, which fails for another reason, even if I adjust the Slider element with maxValue=255 to set values between 0 and 255:

$ openhab-cli console smarthome:send myrollershutter 120

Logging in as openhab
Error: Command '120' is not valid for item 'myrollershutter'
Valid command types are:
  UpDownType: UP DOWN
  StopMoveType: STOP MOVE
  PercentType
  RefreshType: REFRESH

Or if triggered via the mentioned Slider in basicui:

Received HTTP POST request at 'items/myrollershutter' with an invalid status value '221'.

The only values allowed are 0-100.

At this point I don’t know what else to try. The best way I can think of to solve this, is to allow two different DPT values for rollershutter position set and read GA.

The current source code of the knx binding does not seem to support this, so it would not help if I were to update to the SNAPSHOT release. I tried both 2.4.0 and 2.5.0-M1.

Could someone please take a look?

What I forgot to mention was, that the rollershutters are not exclusively controlled by using OpenHAB, therefore I can’t use the autoupdate feature, which would set the status of the rollershutter to the same value provided by the Slider. Also Switch sitemap elements are also used in OpenHAB, so the rollershutters are mainly controlled using UP/DOWN/STOP.

My item is therefore defined with

autoupdate="false"

Edit1: Fix formatting.
Edit2: Added info regarding autoupdate=false and stopping rollershutters manually.

I don’t know anythng about KNX and rollershutters always give me a headache, but you have a clear understanding of the problem.

Seems to me that you need to separate out your non-standard feedback data, and bring it out to another Item. Number probably. You can then write a rule that responds to a change to fully open/closed position by updating your “real” roller Item to 0/100%.

You may need to make your roller Item into a dimmer type Item so that KNX binding allows you to configure it simpler?

You may misunderstand autoupdate. It acts like a psuedo-binding - it listens for commands (not updates) and has an educated guess at the result of that command.
So it is not influenced at all by external movement of the roller.

A desirable effect for you, where you have no real position feedback; sending a 75% command from UI slider results in an autoupdate of the Item to 75%, which in turn gets reflected in your UI.

Some external change 75%->50% will not get reflected in your UI, but that’s not about autoupdate, you simply don’t have positional feedback. There’s no way round that.

A possibly undesirable affect - if you command UP, autoupdate can only guess the result at fully open. 0% is that? It’s a better guess than fully closed.

Thank you for answering.

From what I understand of your suggestion:

  1. I’d have to create a second things definition, that only reads the non-standard feedback data, as I can then set it to only listen to GA-READ with DPT 5.004. Then the standard things entry can remain default with omitted DPT 5.001 but removed read GA in the position="…" setting.
  2. That would make sure that I can still control the rollershutter in the standard 0-100% way and Sliders as well as console smarthome:send commands should work fine.
  3. I create a Number item that is linked to the second things definition and only helps with storing the non-standard feedback data.
  4. A rule is needed per rollershutter that listens to a change in the state of the Number item, which then does a postUpdate to the real roller item.

Seems a bit inelegant, but if the feature is not added again to the knx binding - knx1 was able to have separate DPT values if I correctly understood past forum entries that showed that feature - this may be the only solution.

Could you please take a look if I understand that correctly, before I go ahead and try implementing it?

Regarding autoupdate=“false”:

I think I understand how it works. If I set it to false for an item it stops commands with value sent (be they from the UI or console) from setting the status to that value. As you said, use a Slider to set it to 75% and the label would show 75%, no matter what actually happens.

This is exactly the behavior that I don’t want, as the rollershutter is moved manually quite a lot and I want the status of it to be reliable, even if is “inaccurate” with regard to the shutter position while in between.

At least this is the effect that autoupdate=“false” seems to have from my tests, so I’d better use your first suggestion.

I don’t really know enough about KNX to comment further.
In the first case, just testing if you are able to get your numeric feedback into an Item is a showstopper.

You can always make an enhancement request, it seems reasonable to support older equipment types, doubly so if “used to work”.

Well, that can be automated in a single rule by using group functions and “associated Items”, but get one working first.

Yes, that is exactly it.

Which way is best for you is your choice here :grinning:

So this is working now:

things:

Type rollershutter : myrollershutter          "Rollershutter"    [ upDown="3/1/2", stopMove="3/2/2", position="3/3/2" ]
Type number        : myrollershutterRead      "Rollershutter"    [ ga="5.005:<3/5/6" ]


items:

Rollershutter    myrollershutter        "Rollershutter [MAP(knx.map):%s]"  <rollershutter>  (gRollershutters,gOldActuator) { channel="knx:device:bridge:generic:myrollershutter", autoupdate="false" }
Rollershutter    myrollershutterSlider  "Rollershutter [%d %%]"            <rollershutter>  (gHelperItems)    { channel="knx:device:bridge:generic:myrollershutter" }
Number           myrollershutterRead    "Rollershutter"                    <rollershutter>  (gHelperItems)    { channel="knx:device:bridge:generic:myrollershutterRead" }


rules:

rule myrollershutter
when
    Item myrollershutterRead changed
then
    val readValue = myrollershutterRead.state as Number
    myrollershutter.postUpdate(readValue.intValue)
end


sitemap:

Switch item=myrollershutter
Slider item=myrollershutterSlider


knx.map:

0=In between
1=Open
2=Closed
-=-

Thanks for your help! :grinning:

Now I’d really like to put everything in a single rule, so I don’t have to create one for each rollershutter. Could you please explain what you meant by group functions and “associated items” ?

Edit: Fixed a mistake in the code.

Edit2: Does someone know why the status label, the content inside [] is not displayed in the iOS app?

Gist is here


and see related design patterns like

You might end up with a group of rollers each named someroller , otherroller etc.
and a group of properties someroller_feedback , otherroler_feedback
You can write a rule triggered by a member of the properties group changing.
The rule can find out the name of the triggering member - someroller_feedback - work out the associated roller - someroller - and access that by name for a postUpdate

Like this ?

things:

Type rollershutter : myrollershutter          "Rollershutter"    [ upDown="3/1/2", stopMove="3/2/2", position="3/3/2" ]
Type number        : myrollershutterRead      "Rollershutter"    [ ga="5.005:<3/5/6" ]


items:


Group gRollershuttersOldActuator          "Rollershutters - Old Actuators"
Group gRollershuttersOldActuatorFeedback  "Rollershutters - Old Actuators - Feedback Helper Items"

Rollershutter    myrollershutter        "Rollershutter [%d %%]"            <rollershutter>  (gRollershutters,gRollershuttersOldActuator) { channel="knx:device:bridge:generic:myrollershutter", autoupdate="false" }
Rollershutter    myrollershutterSlider  "Rollershutter [%d %%]"            <rollershutter>  (gHelperItems)    { channel="knx:device:bridge:generic:myrollershutter" }
Number           myrollershutterRead    "Rollershutter"                    <rollershutter>  (gHelperItems,gRollershuttersOldActuatorFeedback)    { channel="knx:device:bridge:generic:myrollershutterRead" }


rules:

rule rollershuttersOldActuators
when
    Member of rollershuttersOldActuatorsFeedback changed
then
    val actuatorFeedback = triggeringItem
    val actuator = rollershuttersOldActuators.members.findFirst[ t | t.name+"Read" == actuatorFeedback.name ]
    val readValue = actuatorFeedback.state as Number
    switch (readValue.intValue) {
        case 0: {
            actuator.postUpdate(50)
        }
        case 1: {
            actuator.postUpdate(0)
        }
        case 2: {
            actuator.postUpdate(100)
        }
    }
end


sitemap:

Switch item=myrollershutter
Slider item=myrollershutterSlider

Edit1: Fixed code.
Edit2: Removed MAP(knx.map) and used switch/case to map 0-1-2 to 0-50-100% instead.

Well, something like.
You probably want to massage the 0-1-2 into 0-50-100% or whatever before updating the real roller Item with it.

That is what I have the MAP(knx.map) for, to rewrite these values for the real rollershutter item. Or is there something wrong with that?

Edit:

No you are right, it is better to remove the MAP stuff and use 0-50-100% so that the icon is showing the correct position.

Thanks again for all your help, it is finally working like it should!

1 Like

The MAP part you showed us is only about display text. It does not, is not intended to, alter the state of the Item held in openHAB. It just gives you a nice display, like changing ON/OFF to Aus/Ein or somesuch.

You might have a use for that, with mapping 0 to “Open”, 100 to “Closed”, and default (anyting else) to “Ajar”.
Adding a MAP to a labl won’t affect your rules.