I’m trying to build an own alarm-system with openhab. My experience with openhab is not very extensive, so I’ve a simple question to rules. I’ve build a rule with the UI but my problem now is that my Nuki lock sends a state like this: 4,0,95763,0,1. For my rule I only need the first number. I’ve found some posts here ( [SOLVED] How to split a string in a rule ), but I’m not able to implement it to my own code. Can somebody help me please?
In this example the state of id:2 Haustuer_Schloss_actionevent is what I need. I need a state 4, but I get 4,0,95763,0,1. I think I can get the first part with the following command
Haustuer_Schloss_actionevent.split(’ , ').get(0)”
but can I create a variable and an if-function at the conditions part?
You will need to pick the language you want to use (all except DSL which is more legacy) are good choices with the first Blockly being a good choice for beginners and for those not familiar with coding or the other languages because it provides a drag and drop approach. Rules Blockly | openHAB
blockly is also a good choice because it will allow you to see the code that it has generated
You can already do the splitting with a transformation in the profile (between item and channel). If you have to change “SCRIPT Rule DSL (v1)” to “Thing to Item Transformation” | input.split(',').get(0);
I’ve tried it with javascript, without Blockly, but I don’t know how my core.ItemStateCondition does now the variable from the script part. The variable is not defined global. How do I define it global, if I only can use scripting in a single function?
Perhaps I have an error in my (thinking) logic, but from programming languages I now a little bit, a variable defined in an function is only local to this function.
Sorry for my stupid questions, but I try understand how it works with rules.
When defining a rule using the UI you can only add scripts or script-like functions to specific script elements (such as the inline script action). All other values are static.
All of the different components of the rule that do include lines of script (either script actions or script conditions) run in their own context. It is possible to use the shared cache to set values that can be accessed by multiple scripts, but that, again, is only available between scripts, it is not something you can access in the other UI configured rule parts like a Item action.
Conditions are evaluated only to determine if the rules actions should be run. Not to pass values to other parts of the rule. If a condition is a script, then the rules engine will run that script and wait for it to return a value that is either true or false. If the value is true the then the rule execution continues (either to the next condition or to the first action), if it is false then the rule execution halts at that point and no further actions are taken.
With those things in mind you have two options here:
You can process the incoming value of your lock before the rule ever begins to run and then have a simple rule built completely in the UI with a condition that checks the single already processed value of the lock. There are numerous ways to transform the value depending on the binding/channel your item is linked to, but this what a transform profile could do for you.
If you are going to keep the full 4,0,95763,0,1 state of the lock then you will have to do most of the work of the rule in the script action and not bother with a separate condition. In this case you would still have the same rule triggers you have configured, but then you will just have a single inline script action. Then within that script you will:
Extract the value you need from the lock’s state
Test that value
Send a command or not to the target item based on the result of the test.
Any of the available scripting languages can handle this basic script.
I don’t use blockly enough to know whether it is even possible to return a value from a blockly script, but yours certainly doesn’t appear to. There are some other issues with the script as well from looking at the few lines of javascript is has produced. For example, there’s no actual test of the value of your lock state after you set the set from the character value in the state string, but that can be cleaned up later.
More relevant is the fact that putting a script in a condition is a little hit or miss right now because of recent changes to how js script conditions (which includes blockly) are processed. So exactly what form the script should take depends a little on what version of OH you are using and whether or not you have changed a particular setting.
Short version: Old conditions needed to end with a line that evaluated to true/false and the rule engine would use that final evaluation as the result of the condition. New conditions are wrapped in an invisible function (unless you have turned this option off) which means that a return {some value here} statement is required or the result of the condition function is null which is a false value (what I suspect is going on here).
This is partly why, in my answer above I said that if you are going to go with a script to process your Item state, don’t even bother with a condition. Just check the state as part of the rule action script. It should be easier for you to work out the blockly blocks to check the state (you have most of that already) and then just send a command to your other item within the action script. Then you don’t need to worry about conditions at all.
The only reason you may want to keep the condition and the action separate is if you every intend to call this rule from some other rule. In that case, it is possible to specify whether the condition should be taken into account, so you could have cases where the action is taken regardless of the test condition. If you don’t need that complexity, then just make the action a script and gorget trying to get the separate condition to work.
that’s what I’ve read and why I’ve used the following line at the end
Lock_state = Lock_Info.charAt(0);
I didn’t know/find that, much thanks for clarification.
You’re right, I should write one script for the rule.
Also I debt you an explanation what I want to realise in detail
My Nuki Lock should activate an alarm system by leaving my home (Lock’n’go state)
If a door or window is open, openhab should send a message by telegram and let speak an alexa which window is open
The sensor of the open window will be excluded from from the rule till the alarm system will be activated the next time
If another door/window sensor will send an open signal after the alarm system is activated, all Alexas should play a sound, all lights should be turned on, all cameras should record permanently and I will get an alarm on my mobile phone
The alarm can only be disabled with a mobile phone of my family, if somebody tries to stop Alexa, it will always reactivate automatically
Without an alarm the system should be deactivated by unlocking the door (unlock state)
If the door will be locked (lock state), a restricted alarm system will be activated, not every door/window sensor will be used
I think I will need more than one rule, but I’m not sure yet.
I’d like to advocate for the transformation here again. If you create an additional Item of type NUMBER in the channel using “Add Link to Item…” and “Create a new Item”, you only need to select the Parent Groups and Script. One advantage of Number is persistence.
Theoretically, you should be able to do everything with just one rule, but I advise against it. With that volume of tasks, it quickly gets cluttered in Blockly. Break it down into individual tasks and use functions, scripts, or rules for each. For example, one rule triggered by the Nuki that arms/disarms the alarm system, saves the contacts when leaving, and outputs a message for any that are already open. Another rule triggered by the Contacts group reacts when the alarm system is armed, and so on…
If you create multiple Blockly scripts for a single rule, you can give them a title and description within the script. To do this, click on ⌃ in the bottom right corner.
I agree with @Tschetan this looks like several rules.
You have at least two rules but probably better as four because you have several different triggering conditions:
You could combine 2 or all 3 of the door based rules, but you gain very little from that and only increase the complexity of the rule code, troubleshooting, and maintenance.
You do have a situation where you want to share information between rules
For this you will want to use the public cache which will hold values in an object that can be accessed by all rules. Blockly rules have access to the public cache using blocks in the openHAB → Value storage group.
Hi, I’ve tried this way, but have still aproblem.
Can you please explain how to do?
Here’s the way I’ve tried to do.
I’ve created an Item of type number by using link to Item (Actionevent) and named it Haustuer_Schloss_lock_state, selected the parent group and chose script ECMA…
At the thing to item transformation I’ve put in your code of your first post. I think I did something wrong, because the result is NULL.
Thanks for your fast answer, but the result is unfortunately the same.
I’m not sure if I have chosen the right transformation.
Sorry I really have not so much experience with openhab.
This can never happen. An Item always has a state. That state may be "NULL" or "UNDEF" but it will never be null nor false nor 0. !"NULL" or !"UNDEF" will always return false so this check effectively does nothing.
It’s better to replace this with:
if(item.isUninitialized)
console.log("Rule triggered, but item state is undefined – ignoring");
return;
}