I / O module bit masks

Tags: #<Tag:0x00007f616afe4980>

Good day!
I have an I / O module that is connected to MQTT. It has 24 outputs which are controlled by a bit mask. What is the correct way to implement turning on / off of I / O module outputs? Example:

  1. Switch on 1 output 0001
  2. Switch on 2 output 0010
  3. Switch on both outputs 0011
  4. Switch on 3 output 0111
    etc.

How to determine what has already been included?
For example: outputs 1 and 2 were turned on, but you only need to turn off the first. Those. the bit mask was 0011 and you need to write it down to leave the second output 0010 instead of 0011.

Tell me where to look.

Thank.

PS Google Translate

If it‘s not possible to switch ON/OFF each I/O individually, I think you have to do the switching in several steps:

  1. Read the current state
  2. make a bitwise OR for each Output which should be switched ON.
  3. make a bitwise AND for each Output which should be switched OFF
  4. Write the new state

How do I implement this in openhab?

What have you tried? This is not a HelpDesk providing complete supported solutions. He work to help you troubleshoot and debug your configuration.

If it is not important enough for you to show effort it is not important enough for volunteers here to assist.

I’m not asking you to do it for me.
Please specify where to look in openhab.
I did the following:

  1. Connected the I/o module to electricity
  2. Connected the I/o module to the MQTT server.
  3. Tried bitmasks 0111 0110 0001 and so on.

And here I stopped, because I don’t know how to implement bitmask saving in openhab. I.e. how to bind the switch exactly to my bit in the mask.

PS Google Translate

The solution presented was to write a rule. OpenHAB is flexible enough that there are many ways to do this.
It may not be possible to do exactly what you envision. There are sometimes many ways to get the same end result.

Is there no binding on bitmasks?

I presume you tried this using something outside of openHAB? And it all works outside openHAB?

If so, then I think the next step is to use the MQTT binding so that you can subscribe and publish to the relevant topics. You will need to create a ‘bridge’ thing to connect to your MQTT broker, and then a ‘device’ thing to subscribe and publish to the relevant topics.

Then you attach your device thing channels to items, after which you can perform rules which use those items, as outlined by @Udo_Hartmann.

Yes, I switched bitmasks in the program from the I/o module. In MQTT, the I / o module has a single DO/SET theme with a bit mask value of 0000 0000 0000 0000 0000 0000, 24 outputs, i.e. numbers from 0 to 16,777,215. To enable 1 output you need a mask 0000 0000 0000 0000 0000 0001 to enable 2 output 0000 0000 0000 0000 0000 0010, that would be 1 and 2 0000 0000 0000 0000 0000 0000 0011. Here’s how to enable disable one bit without touching the others. Here is the question of how to make sure that if 1 output is enabled, it remains enabled while the second one is switched, i.e. the 0011 mask is changed to 0010. MQTT is connected to it. And all outputs on 1 topic

PS Google Translate

Thank you, I’ll try to move on.

Something that might helpful is to show what you are trying to achieve from the openHAB end e.g. a sample MQTT payload. Does it look like “4356” or “EA92” or "1000110’. We don’t know, you do.

Can you read back the existing status from your device over MQTT? Would it help if we knew what the mystery device was?

This does a similar job with a different technology, might give you some ideas

I want to turn outputs on and off independently. The developer of the I / o module implemented a connection to MQTT where there are two themes, the first for reading the bit mask for 24 outputs , the second for writing the bit mask for 24 outputs.

  1. MX210/Output/GET/DO/STATE
    2.MX210/Output/SET/DO/MASK.
    To write the mask, a number is passed, for example 15 = 1111, which is equivalent to turning on the first four outputs, i.e. to turn off only the third output, you need to send the number 11 = 1011. I don’t understand how to implement reading, comparing, and writing back yet.

The brand of the device I don’t think will tell you anything.

PS Google Translate

Ok, so you need at least the mqtt binding and a mqtt broker. given, the broker is already online, you need a mqtt broker thing in openHAB to connect to the broker (this thing is called a bridge. Please don’t create a system broker thing but only a broker thing).
Now, to represent your device, you need a generic mqtt thing, linked to the mqtt broker bridge.
In the generic mqtt thing, you need one channel, which is bidirectional. As you get a number, the channel is of type number.
stateTopic is (in your case) MX210/Output/GET/DO/STATE and commandTopic is MX210/Output/SET/DO/MASK.

Bridge mqtt:broker:myBroker [
    host="192.168.178.99"  // ip or fqdn of your mqtt broker
] {
    Thing topic myDevice
    Channels:
        Type number : IO "In/Out" [
              stateTopic="MX210/Output/GET/DO/STATE",
            commandTopic="MX210/Output/SET/DO/MASK"
        ]
}

Now link the channel to a Number Item (let’s call it DeviceIO)
As you have 24 individual channels, we need 24 additional Switch Items. And as there are 24 of them, let’s create an additional Group Item. Let’s call them Switch_1 to Switch_24 and gSwitches.

Number DeviceIO "In/Out" { channel="mqtt:topic:myBroker:myDevice:IO", autoupdate="false" }
Group gSwitches { autoupdate="false" }
Switch Switch_1  "Out  1 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_2  "Out  2 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_3  "Out  3 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_4  "Out  4 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_5  "Out  5 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_6  "Out  6 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_7  "Out  7 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_8  "Out  8 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_9  "Out  9 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_10 "Out 10 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_11 "Out 11 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_12 "Out 12 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_13 "Out 13 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_14 "Out 14 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_15 "Out 15 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_16 "Out 16 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_17 "Out 17 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_18 "Out 18 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_19 "Out 19 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_20 "Out 20 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_21 "Out 21 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_22 "Out 22 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_23 "Out 23 [%s]" (gSwitches) { autoupdate="false" }
Switch Switch_24 "Out 24 [%s]" (gSwitches) { autoupdate="false" }

Now to the rules:

import java.lang.Math

rule "Device in"
when
    Item DeviceIO changed
then
    var BigInteger register = (DeviceIO.state as DecimalType).toBigDecimal.toBigInteger
    gSwitches.members.forEach[i |
        val Integer nBit = Integer::parseInt(i.name.split("_").get(1)) - 1
        i.postUpdate(if(register.testBit(nBit) == 1) ON else OFF)
    ]
end

rule "Device out"
when
    Member of gSwitches received command
then
    var BigInteger register = (DeviceIO.state as DecimalType).toBigDecimal.toBigInteger
    val Integer nBit = Integer::parseInt(triggeringItem.name.split("_").get(1)) - 1
    if(receivedCommand == ON)
        register = register.setBit(nBit)
    else
        register = register.clearBit(nBit)
    DeviceIO.sendCommand(register)
end

I did not test this code, so it’s very likely to fail :wink: at first attempt, but I’m pretty sure you get the idea.
Every time, you switch one of the 24 switches, the second rule is triggered.
The rule gets the state of the device and creates a variable called register. then it determines which switch was switched. this is the second part of the item name, split by “_”. We do need this value as an integer, so we need to parse the string to integer.
If the received command was ON, we set the bit, else we clear the bit.
As a last step, we send the whole number to the devices.

If the device state was changed (the change came from mqtt), all 24 switches are switched to their correct state (ON or OFF) through the first rule.

2 Likes

I understood the idea, tried to do it failed. I’ll figure it out.

Good work! When you get it working, please do post your solution in this thread for others to learn from! Good luck!

while it does not work, I think I have to switch to modbus :slight_smile:

Which part does not work?

I think that in the rules. If you look at the data from MQTT DeviceIO gets. It doesn’t go any further. Can’t there be a problem with converting from one format to another?

Any error message in openhab.log?

    020-07-19 19:29:33.653 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'output.rules'
2020-07-19 19:29:33.987 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:29:34.284 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:29:34.823 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:30:00.890 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'clearBit' is not a member of 'BigInteger'; line 23, column 9, length 23
2020-07-19 19:30:01.224 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'clearBit' is not a member of 'BigInteger'; line 23, column 9, length 23
2020-07-19 19:30:01.515 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'clearBit' is not a member of 'BigInteger'; line 23, column 9, length 23
2020-07-19 19:30:01.917 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'clearBit' is not a member of 'BigInteger'; line 23, column 9, length 23
2020-07-19 19:30:02.444 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:30:02.628 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'clearBit' is not a member of 'BigInteger'; line 23, column 9, length 23
2020-07-19 19:30:02.910 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:30:03.253 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'clearBit' is not a member of 'BigInteger'; line 23, column 9, length 23
2020-07-19 19:30:03.503 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:30:03.674 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'clearBit' is not a member of 'BigInteger'; line 23, column 9, length 23
2020-07-19 19:45:41.354 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:45:42.357 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:45:42.710 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21
2020-07-19 19:45:43.671 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Device out': 'setBit' is not a member of 'BigInteger'; line 21, column 9, length 21