This tutorial will provide one possibility how to integrate Hoppe SecuSignal FHFS-vw window handles (EEP F61000) into your openHAB installation.
If you followed the instructions how to set up EnOcean via Homegear, your window handles are working properly. However, to use them in a comfortable way in OH2, you need to do some further adjustments in order to show the states properly on your sitemap or work with states in your rules.
While a regular contact item in openHAB knows two states (OPEN
and CLOSED
), a window handle does effectively have three states, that is CLOSED
, OPEN
, and AJAR
(TILTED). Homegear does provide these three states, however, it sends these states to openHAB in the form of integers (0=CLOSED
, 1=OPEN
, and 2=AJAR
). openHAB then internally transforms these states. Unfortunately, thereâs something weird going on during this transformation. The incoming values in openHAB are UNDEFINED
, CLOSED
, and OPEN
. The following table summarizes the states in Homegear and openHAB.
Real state window handle | Homegear | openHAB 2
closed | 0| UNDEFINED
open | 1 | CLOSED
ajar (tilted) | 2 | OPEN
When putting your window handles on your sitemap, you may want to define your devices as STRING
items. That will allow you to show the appropriate states. In addition, you may want to use a <CONTACT>
icon, as this icon (ironically) supports all three window handle states (in contrast to a CONTACT
item). However, the state of an icon will be determined by the raw state of the item (in contrast to the label, see documentation). That means, we need to perform a âraw state transformationâ. That part is a bit tricky (and a detailed discussion can be found here), but we could use some form of the proxy item design pattern described by @rlkoshak.
What we effectively need to do is to write a rule that takes these incorrect states of the original items, transforms them and assigns the new, correct states to proxy items. That means, in your items file you need to define two items:
- The real window handle with the correct EnOcean/HomeMatic channel
- A proxy item with a highly related name (that will make life easier further down the road)
Part of my windowHandle item file looks like shown below. The group definition and the label transformation will be described later. What you can see is that the real devices will be assigned a channel while the virtual devices naturally do not have any real channels. One word regarding my name convention: The âsâ in âsFensterâ stands for âsensorâ, while the âvâ in âvFensterâ stands for âvirtualâ. This helps me to easily identify the functionality of an item when working with it within rule files.
// Real devices
Group:Contact:AND(CLOSED,OPEN) g_sFenster "Fenster" <contact>
String ug_buero_sFenster <contact> (g_sFenster) {channel='homematic:HG-F6-10-00:6e230a45:EOD01A93E7E:1#STATE'}
String eg_wz_sFenster1 <contact> (g_sFenster) {channel='homematic:HG-F6-10-00:6e230a45:EOD01A956AA:1#STATE'}
String eg_wz_sFenster2 <contact> (g_sFenster) {channel='homematic:HG-F6-10-00:6e230a45:EOD01A6E747:1#STATE'}
// Virtual devices
Group:Contact:AND(CLOSED,OPEN) g_vFenster "Fenster" <contact>
String ug_buero_vFenster "BĂŒro [MAP(EnOceanWindowHandle_label.map):%s]" <contact> (g_vFenster)
String eg_wz_vFenster1 "Wohnzimmer 1 [MAP(EnOceanWindowHandle_label.map):%s]" <contact> (g_vFenster)
String eg_wz_vFenster2 "Wohnzimmer 2 [MAP(EnOceanWindowHandle_label.map):%s]" <contact> (g_vFenster)
Now, letâs turn our attention to the rules file. First we take a look at an individual window handle. Whenever a window handle receives an update, the raw state transformation needs to be done. For this to take place, we take advantage of the SWITCH command. You could use IF-THEN-ELSE, but in cases like this, I prefer SWITCH as it makes the code easier to read (and understand). Now, if the window handle item ug_buero_sFenster
receives an update, its state will be analyzed and a transformed version will be assigned to the proxy device ug_buero_vFenster
. Please note that all new states have to be put in quotation marks ("") due to the fact that we are working with STRING
items. Itâs the virtual device that you subsequently put on your sitemap where it will correctly signal via <contact>
icon its three states: âClosedâ, âOpenâ, and âAjarâ.
rule "ug_buero_sFenster transformation"
when
Item ug_buero_sFenster received update
then
switch(ug_buero_sFenster.state) {
case "Undefined": ug_buero_vFenster.postUpdate("CLOSED")
case "Closed": ug_buero_vFenster.postUpdate("OPEN")
case "Open": ug_buero_vFenster.postUpdate("AJAR")
}
end
rule "eg_wz_sFenster1 transformation"
when
Item eg_wz_sFenster1 received update
then
switch(eg_wz_sFenster1.state) {
case "Undefined": eg_wz_vFenster1.postUpdate("CLOSED")
case "Closed": eg_wz_vFenster1.postUpdate("OPEN")
case "Open": eg_wz_vFenster1.postUpdate("AJAR")
}
end
rule "eg_wz_sFenster2 transformation"
when
Item eg_wz_sFenster2 received update
then
switch(eg_wz_sFenster2.state) {
case "Undefined": eg_wz_vFenster2.postUpdate("CLOSED")
case "Closed": eg_wz_vFenster2.postUpdate("OPEN")
case "Open": eg_wz_vFenster2.postUpdate("AJAR")
}
end
In a last step, letâs try to streamline our rules file. The disadvantage of the code above is that you have to code a rule for every window handle in your house. For illustration purposes I showed only three window handle rules. In reality, I have ten window handles, i.e. this would produce large amounts of redundant code. This makes the rules file less readable, and - more important - less maintenance-friendly. If you take a closer look at the individual rules, you will observe that the only differences are the item names. The intention for every rule is essentially the same.
Now, the group contact (which I defined at the very beginning of the items file) comes into play. This approach is again heavily based on another excellent design pattern described by @rlkoshak (Design Pattern: Working with Groups in Rules). I encourage every reader to take a look as I wonât repeat the concept here, but simply show how I transferred the approach to streamline my code. I just would like to mention that this concept requires some kind of persistence (such as mapdb), which I wonât describe here.
rule "sFenster transformation"
when
Item ug_buero_sFenster changed or
Item eg_wz_sFenster1 changed or
Item eg_wz_sFenster2 changed or
then
Thread::sleep(100) // give persistence time to catch up
// Acquire the window that triggered the rule
// - use filter remove the windows that are not saved to persitence yet (i.e. lastUpdate returns null)
// - use sortBy to order the members by lastUpdate, the most recent will be last
// - get the last updated Item, window contatcs are unlikely to change within 100 msec of each other so this approach works
// If they are likely to change that close together this approach will fail
val sFenster = g_sFenster.members.filter[s|s.lastUpdate("mapdb") != null].sortBy[lastUpdate("mapdb")].last as StringItem
// Replace the part of the name ("_sFenster" vs "_vFenster")
var vFenster = sFenster.name.replace("_sFenster","_vFenster")
switch(sFenster.state) {
case "Undefined": vFenster.postUpdate("CLOSED")
case "Closed": vFenster.postUpdate("OPEN")
case "Open": vFenster.postUpdate("AJAR")
}
end
You may have noticed that I defined the group as being of type CONTACT
, while the individual group items are of type STRING
. It is my understanding that a groupâs function (such as AND
, OR
etc.) only can take exactly two input parameter, such as ON
and OFF
in the case of a group switch or OPEN
and CLOSED
in the case of a group contact (as stated in the documentation). I defined the group contact in a way that itâs state will be OPEN
if not ALLwindows are closed. That implies that the group contact wonât distinguish between OPEN
and AJAR
. However, in my point of view, this is not critical as AJAR
is also a state that can be described as OPEN
.
Hereâs the relevant part of my sitemap. It shows the group state on the main page and its individual members on a subpage.
Text item=g_vFenster {
Frame {
Default item=ug_buero_vFenster
Default item=eg_wz_vFenster1
Default item=eg_wz_vFenster2
}
}
Last but not least, Iâll show my label transformation file, which translates the states into German. Information about label transformation can be found here.
EnOceanWindowHandle_label.map
-=N/A
NULL=N/A
CLOSED=geschlossen
OPEN=offen
AJAR=gekippt
Any suggestions for improvement? Just leave a commentâŠ