[KNX] Virtual Device


I few years ago, I developed a full KNX Stack for Python¹, in order to make virtual devices. The goal was to map any hardware on the KNX bus, in order to use them with all my KNX buttons, screens, and so.

One of the devices I mapped is my vent unit Helios KWL-500 via EasyControl Modbus/Tcp.

I recently decided to use openHAB, and I added the EasyControl binding. It works, but it seems that the Modbus server does not like having 2 clients: it sometimes fails reading with my Python stack, and sometimes fails reading with openHAB.

As my goal is to drop pKNyX, I would like to use openHAB as a gateway between the vent unit and the KNX bus, and be able to read/write from both sides.

Is that possible? If yes, how to do that?



¹ Fred / pKNyX · GitLab

Sure, openHAB is meant to be a gateway between incompatible systems.

Simply use the knx binding and create a generic knx thing. Then create *-control channels and link them with the corresponding helios items.
As I don’t know about the helios, I can only guess… but as an example:

Thing device myswitch "wallswitch" [] {
    Type number-control : level [ga="1/1/1+1/1/2"]

1/1/1 is the status GA for sending the current level to the switch(!) 1/1/2 is the control GA to send a command from knx to the helios.

Number heliosLevel "Vent level" {channel="modbus...",channel="knx:device:bridge:myswitch:level"}

When openHAB reveived a command via 1/1/2, it will send the level as a command to Item heliosLevel, which will send the command to the modbus binding (which then will send it to the helios device). The device will answer with the new level as a status update, which will update the Item. the control channel will get the update, too and will send it to knx via 1/1/1.

Maybe you have to change some data, then it’s better to use a rule set. Let’s say you have wall switches, but it’s only up/down and it’s a switch, so there is a 1 for each up and a 0 for each down.

Thing device myswitch "wallswitch" [] {
    Type switch-control : upDown [ga="1/1/1"]

linked to a Switch Item knxWallSwitchUpDown. Helios Item is the same (Number Item)

Rule (DSL, but you can use the other options, too):

rule "set helios level"
    Item knxWallSwitchUpDown received command
    val iLevel = if(heliosLevel.state instanceof Number) (heliosLevel.state as Number).intValue else 2
    var newLevel = iLevel
    newLevel = newLevel + if(receivedCommand == ON) 1 else -1
    if(newLevel < 0)
        newLevel = 0
    if(newLevel > 3)
        newLevel = 3
    if(iLevel != newLevel)

The rule checks if heliosLevel is of type Number. if yes, it takes the value into iLevel, if not, it uses 2 as a default level.
The newLevel variable is set to the same value.
Now, if the command was ON (aka 1 in knx) the rule adds 1 to newLevel. For every other command (OFF is the only possible command here) it subtracts 1.
Check the borders to prevent commands which are not allowed.
Last step: check if the new level is different from the current level, if not, set the new Level.

Thanks Udo!

Do I also have to make a rule triggered by Helios, and sending the value to the KNX binding, in order to refresh the KNX screen?


It depends :slight_smile: on which kind of Channels and Items are used and if you need some transformation between helios and knx.


But I found that the Modbus/Tcp Slave binding doesn’t want to refresh more often than 30s :face_with_raised_eyebrow: Not a big deal for temperatures, but for fan stage or operating mode (auto/manu), it is way to slow!

Don’t know if I can patch that in the code without recompiling…


It is completely configurable, to sub-second polling intervals.

Well, not Helios-EasyControl Modbus/Tcp slave… Minimum is 30’000ms.

Stuck with what the Helios extension author gave you, then. There’s a good reason, perhaps.

You could experiment with generic Modbus config to see if it works at faster poll rates.

Helios Modbus usage is totally insane!

Instead of using coils, inputRegisters, holdingRegisters and so as normal registers, they use them as a mailbox! You put the name and value of the param you want to set, as ascii (using a register per char) then validate. Why on earth use Modbus to do that!?!?!!!

I implemented that in Python, but I’m unable (for now) to do that in OH…