Messing with bitpacked messages in Rules DSL is a pain. What Rules are you using, Rules DSL or Scripted Automation (Python or JavaScript)?
Hi rlkoshak ,
Thanks for your reply, I think is DSL ( the default language ) , the controller sends MQTT message like PA=255 cos it has 4 ports PA,PB,PC,PD what i have done till now is a string item that displays this data
now what i need to do is some string manipulation in the rules for example:
when string change , check if string contains “PA=” if yes extract the number after "PA= "
then example i have a value of 255 convert that in to a binary string of 8 characters , then
pic the character i am interested in check if 1 or 0 , if 1 then the switch is ON if 0 put it off
, but as i said i am new to dsl i know some cpp and php but never dsl ,
also what programming languages are accepted in the rules files ?
-
Use MQTT 2.5 M1+ How to implement the equivalent to MQTT1 REGEX filters to filter to just those messages that have the PA and chain it to a REGEX transformation to extract the number. The Channel should be a Number type Channel.
-
Link the Channel to a Number Item
-
Trigger a Rule when the Number Item changes.
val checkKthBit = [ Integer num, Integer bit |
val n = num.intValue
val k = bit.intValue
if ((n & (1 << (k - 1))) == 1) True else False // shift to the kth bit and check if it's 1
]
if(checkKthBit.apply(MyItem.state, 0)) // device from first bit is ON
if(checkKthBit.apply(MyItem.state, 1)) // device from second bit is ON
...
I am not at all certain that the above will work. I think Xtend will let us use the Java binary shift operators. If not I’m not sure how to do this.
If you use Scripted Automation you can use Python (specifically Jython 2.7), JavaScript (specifically Nashorn), or Groovy. See [beta testers wanted!] Jython addon w/ helper libraries (requires OH 2.5.x) to get started with Python.
Thanks very much for your help,
I will try it and let you know that would be tomorrow cos now here is 12:33 AM
thanks again Good day
Hi , I have started to experiment some code with regex , when i test the regex on simulator it
it works but in rules file dose not , what am i doing wrong ?
I want to extract only whats after “PA=” in item PORTA
val str1 = transform(“REGEX”, “(?<=PA=).*”, PORTA.state.toString)
also how you convert string to int please ?
In OH, the REGEX must match the entire string and the first matching group is what gets returned.
Hi Rich, thanks for your reply.
it seems that in my case regex is useless cos if I know the whole string i wouldn’t be needing it.
but I am a beginner maybe I am missing something.
Python seems to be popular and a lot of help is available on the web will try to see how I can use it
to create rules.
also, I know you suggested a number item but because the controller sends all data in the same topic
inspecting the string is the only way I have to distinguish the data.
Consider if you know (or want to see if it is present) “wildcard - magicword - wildcard”. That’s the whole string.
Thanks Rossko ,
it finally worked like you suggested:
but it’s a long way to victory i have to convert str1 to int and figure out how checkKthBit is going to work
is checkKthBit part of the standard DSL or i have to install it? like transform Regex
That’s Rule code that you will need to copy and paste into a Rule and very likely debug it as I have no way to really test that it works as written above.
Once you have the value stored in an integer you might want to implement something like this in the rule instead of checkKthBit.
Items:
Switch Port8 "Port 8"
Switch Port7 "Port 7"
Switch Port6 "Port 6"
Switch Port5 "Port 5"
Switch Port4 "Port 4"
Switch Port3 "Port 3"
Switch Port2 "Port 2"
Switch Port1 "Port 1"
Rule:
// AllBits must be defined as an integer. The value from MQTT will be store here
var Integer AllBits
when ???? changed
then
// Place the value from the REGEX in AllBits (possibly converting to an integer beforehand)
if (AllBits >= 128 ) {
Port8.postUpdate(ON)
AllBits = AllBits - 128
}
else {
Port8.postUpdate(OFF)
}
if (AllBits >= 64 ) {
Port7.postUpdate(ON)
AllBits = AllBits - 64
}
else {
Port7.postUpdate(OFF)
}
if (AllBits >= 32 ) {
Port6.postUpdate(ON)
AllBits = AllBits - 32
}
else {
Port6.postUpdate(OFF)
}
}if (AllBits >= 16 ) {
Port5.postUpdate(ON)
AllBits = AllBits - 16
}
else {
Port5.postUpdate(OFF)
}
if (AllBits >= 8 ) {
Port4.postUpdate(ON)
AllBits = AllBits - 8
}
else {
Port4.postUpdate(OFF)
}
if (AllBits >= 4 ) {
Port3.postUpdate(ON)
AllBits = AllBits - 4
}
else {
Port3.postUpdate(OFF)
}
if (AllBits >= 2 ) {
Port2.postUpdate(ON)
AllBits = AllBits - 2
}
else {
Port2.postUpdate(OFF)
}
if (AllBits >= 1 ) {
Port1.postUpdate(ON)
AllBits = AllBits - 1
}
else {
Port1.postUpdate(OFF)
}
end
I haven’t tested this but VSC shows no syntax errors. Its not as elegant as checkKthBit but easier to understand (IMO)
HI thanks to All, for your reply’s to Help.
Yes, it seems that your approach Jim is more suitable for a beginner I can clearly understand what’s happening and will surely implement that.
Once I feel more fluent in this language will also try checkKthBit which really looks elegant.
searching the forum was not able to find a simple syntax to convert a string to int.
In c++ i use to do it :
int = stoi (string) ;
is there something simple like this in DSL?
like
Hi Rosko, yes it worked regex converted it into an integer
NumberOutput = new Integer(transform(“REGEX”, “([0-9]+)”, StringInput))
var String X_Topic = "uart_rx"
var String Broker = "mqtt:systemBroker:embedded-mqtt-broker"
var String str1 = ""
var int AllBits = 0
rule XC1_PA_UPD
when
Item PORTA received update
then
str1 = transform("REGEX", ".*(?<=PA=)(.*)", PORTA.state.toString) // remove PA= & put value in to str1
AllBits = new Integer(transform("REGEX", "([0-9]+)", str1)) // Convert String to int
PAVAL.sendCommand(AllBits) // Update PAVAL
val mqttActions = getActions("mqtt", Broker) mqttActions.publishMQTT(X_Topic, "|ssd0clr|SSD0:X1,Y1,F0,T1,S[" + str1 + "]|") // Print received data on LCD.
// Update Switches Status //
if (AllBits >= 128 ) { PA8.sendCommand(ON) AllBits = AllBits - 128 } else { PA8.sendCommand(OFF) }
if (AllBits >= 64 ) { PA7.sendCommand(ON) AllBits = AllBits - 64 } else { PA7.sendCommand(OFF) }
if (AllBits >= 32 ) { PA6.sendCommand(ON) AllBits = AllBits - 32 } else { PA6.sendCommand(OFF) }
if (AllBits >= 16 ) { PA5.sendCommand(ON) AllBits = AllBits - 16 } else { PA5.sendCommand(OFF) }
if (AllBits >= 8 ) { PA4.sendCommand(ON) AllBits = AllBits - 8 } else { PA4.sendCommand(OFF) }
if (AllBits >= 4 ) { PA3.sendCommand(ON) AllBits = AllBits - 4 } else { PA3.sendCommand(OFF) }
if (AllBits >= 2 ) { PA2.sendCommand(ON) AllBits = AllBits - 2 } else { PA2.sendCommand(OFF) }
if (AllBits >= 1 ) { PA1.sendCommand(ON) AllBits = AllBits - 1 } else { PA1.sendCommand(OFF) }
end
This DSL language … lest just say I don’t like it at all, there must be a better way.
Without your help guys, I would have given up so thanks very much.
As I indicated above, there is the option to use Python, JavaScript or Groovy.
Hi Rich,
Yes i will do that , is it done via the Exec Transformation Add-on ?
You can call external scripts using the Exec binding or from Rules DSL Rules using the executecommandLine
Action, but that’s not what I’m referring to. I’m referring to writing openHAB Rules using these other languages instead of Rules DSL.
See [beta testers wanted!] Jython addon w/ helper libraries (requires OH 2.5.x) to get started with Python.
Just for completeness I was able to get the checkKthBit routine working in a .rules file.
// The variable "num" must be between 0 and 255.
// The variable "bit" must be between 1 (the rightmost bit) and 8 (the leftmost bit)
val checkKthBit = [ Integer num, Integer bit |
var n = num
var s = 1 << (bit - 1)
if (n.bitwiseAnd(s) > 0) {
true
}
else {
false
}
]
Assuming AllBits is a number item
if (checkKthBit.apply(AllBits.state,8)) {
Port8.postUpdate(ON)
}
else {
Port8.postUpdate(OFF)
}
if (checkKthBit.apply(AllBits.state,7)) {
Port7.postUpdate(ON)
}
else {
Port7.postUpdate(OFF)
}
....
....
Hi Jim .
Yes i can confirm it works 100% Thanks
This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.