Alright, had a think and a play.
Change of method means change of infrastructure.
Revised Things
// poll reg Do
Bridge poller Thing_Do [ start=0016, length=8, refresh=500, type="coil" ] {
//Flutlicht Innenhof
Thing data Thing_Do00 [ readStart="0016", readValueType="bit"]
etc.
Mostly okay as it was, I think you can afford to poll more often.
but
Do change these DO to read-only, we want to ignore commands here.
// poll reg Vlag
Bridge poller wh01 [ start=300, length=6, refresh=0, type="holding" ] {
// read/write Vlag as whole register, we will write bits from rule
Thing data vlags [ writeStart="304", writeValueType="uint16", writeType="holding" ]
} // end of poller Vlag
In contrast, we need not poll at all here - unless you want to look at any of the other holding registers.
Nothing else is changing vlag but us, so we need never read it back.
Change the data Thing to write-only.
Revised Items
We need to introduce Group Items, which allows us to easily use one rule to deal with a group of similar Items. All light zones in one group, all pulse-pushbuttons in another
We’re going to use one Item to keep an image of the 16-bit Vlag register. This gets updated by a rule as bits are written.
A big change in the naming pattern. The methods used here are the same as the “Modbus bitwise” posting linked to earlier. But the rule there is just a demo, not really suitable for expanding to 16 Items with the switch/case, and it would require hardcoding Item names into the rule.
We can avoid that by hardcoding the bit number used by this button into the name of the pulse-pushbutton Item. Much easier to add/amend Items.
// modbus lighting items
Group gAdamLights "for light zones"
Group gVlags "for pulses"
Number VlagReg "for vlag register image" {channel="modbus:data:wohnhaus01:wh01:vlags:number"}
// Item representing a lighting zone
Switch FlutInnenh "Flutlicht Innenhof" (gAdamLights) {channel="modbus:data:wohnhaus01:Thing_Do:Thing_Do00:switch", autoupdate="false"}
// each zone partnered with a simulated pushbutton
Switch FlutInnenh_pulse_00 "FlutInnenh push" (gVlags) {autoupdate="false", expire="1s,command=OFF"}
Switch FlutPferd "Flutlicht Pferde" (gAdamLights) {channel="modbus:data:wohnhaus01:Thing_Do:Thing_Do01:switch", autoupdate="false"}
Switch FlutPferd_pulse_01 "FlutPferd push" (gVlags) {autoupdate="false", expire="1s,command=OFF"}
etc.
So, Light Items are linked to read-only modbus channels to monitor light states…
Note that autoupdate is disabled - we don’t want commands interfering with Item state, because our rule needs accurate state.
These are the Items to put on your UI with on/off switches, and to command from other rules like motion activated lighting.
Simulated pushbutton Items are not linked to anything, all managed by rule.
We don’t care about Item state here, it is all about commands. So we can disable autoupdate to reduce workload.
Expire is used to automatically “un-push” a button after 1 second. I think that will be fast enough for you (it’s as fast as expire goes). If it isn’t, we can change something else later.
Rules
Everything is done by two rules.
I’ve written in file-based DSL, it should be possible to convert to other languages and/or UI.
One rule manages the pushing of the buttons, writing bits to vlag register while preserving state of all other bits.
The other rule manages if and when to push a button at all, to toggle a light on or off.
import java.math.BigInteger // we need this for set/clearBit()
rule "simulate vlag pushbutton"
// this rule pushes and releases buttons
when
Member of gVlags received command
then
var register = BigInteger.valueOf(0) // we need BigInteger type to use setBit
if ( VlagReg.state != NULL && VlagReg.state != UNDEF) { // avoid using invalid register image
register = (VlagReg.state as DecimalType).toBigDecimal.toBigInteger // use existing image
}
// relies on Item name like FlutPferd_pulse_01
val bitnum = Integer.parseInt(triggeringItem.name.split("_").get(2)) // get the 01 part
if (receivedCommand == ON) {
register = register.setBit(bitnum)
} else if (receivedCommand == OFF) { // by testing both, we will ignore REFRESH commands etc.
register = register.clearBit(bitnum)
}
// at last, write image to Modbus
VlagReg.sendCommand(register)
end
rule "control pushbutton Items"
// this rule converts on/off commands to buttons
when
Member of gAdamLights received command
then
// check if action needed first
if ((receivedCommand ==ON && triggeringItem.state != ON) ||
(receivedCommand == OFF && triggeringItem.state != OFF)) {
val template = triggeringItem.name + "_pulse_"
// find partner pushbutton in group, but we don't know suffix like _01
val button = gVlags.members.findFirst[i | i.name.contains(template)]
if (button === null) {
logWarn("ERROR", "config missing " + template)
} else {
button.sendCommand(ON) // push the button for change
// relying on expire to un-push later, but we could use timer here
}
} // else no change needed
end