Integrating Enocean window/door Ccntacts

I have window/door contacts from Eltako of type TF-FKE. They use EEP F6:10:00 which is the same as for Hoppe window handle sensors.
The TF-FKE has only two states (Down, Middle), while the Hoppe has three (Up additionally).

As I found the integration not so straightforward I will describe it for the TF-FKE, which you may be able to adopt to the Hoppe sensor.

The key for the solution is to not use Switch or Contact type for the items, as openHAB has no matching conversion from WindowHandleState of the Enocean item to this types.

So I use the String type and the window handle states map to String as follows:

Down -> CLOSED
Middle -> OPEN
Up -> AJAR

My enocean.items looks as follows:

Group:String:AND(CLOSED, OPEN) Fenster_Group "Fenster [MAP(fenster.map):%s]" <window> 
String Fenster_SZ "Fenster Schlafzimmer [MAP(fenster.map):%s]"  <window> (All, Fenster_Group) {enocean="{id=xx:xx:xx:xx, eep=F6:10:00, parameter=CONTACT_STATE}"}
String Fenster_Bad "Fenster Bad [MAP(fenster.map):%s]"  <window> (All, Fenster_Group) {enocean="{id=xx:xx:xx:xx, eep=F6:10:00, parameter=CONTACT_STATE}"}
String Fenster_KiZ "Fenster Kinderzimmer [MAP(fenster.map):%s]"  <window> (All, Fenster_Group) {enocean="{id=xx:xx:xx:xx, eep=F6:10:00, parameter=CONTACT_STATE}"}

The fenster.map is only used for translation and has this content:

OPEN=Offen
CLOSED=Geschlossen
NULL=Unbekannt

With this definition of the Fenster_Group it has the state OPEN as long as one of the windows is OPEN.

Then I use a rule to trigger some other actions if any of the window states changes:

rule "Fenster Änderung"
when
    Item Fenster_Group received update
then {
    Thread::sleep(1000) // wait for persistence update
    val fensterChanged = Fenster_Group.allMembers.filter[item | item.lastUpdate !== null].sortBy[lastUpdate].last
    var String fensterLabel = fensterChanged.getLabel();
    logInfo("Fenster", String::format("fensterLabel %s fensterState %s ", fensterLabel, fensterChanged.state.toString))
    switch fensterChanged.state.toString {
        case "OPEN": {
            // do what you like here
        }
        case "CLOSED": {
            // do what you like here
        }
    }
}
end

The rule will trigger if any of the windows in the group changes its state. To find out what exactly happened, the first lines following “then” find the last changed member (window) of the group and it’s state.