Rules and special variable forms

Hi,

in Design Pattern: Motion Sensor Timer @rlkoshak use in the Comprehensive Example two code pattern I didn´t understand and I hope somebody could explain.

val sw = gMotionDetectors.members.sortBy[lastUpdate].last as SwitchItem

What I could read is:

Define variable sw as a Switch and fill it with the last member from from group “gMotionDetectors” which was sorted by column “lastUpdate”

Is that right? So the variable sw will filled with a Item name, right?

A the top of the rule there will be define something

import java.util.Map
val Map<String, Timer> timers = newHashMap

and later inside the rule there are following lines

if(timers.get(sw.name) == null){
   timers.put(sw.name, createTimer(now.plusMinutes(timeOutMinutes), [|
   sw.sendCommand(OFF)
   timers.put(sw.name, null)
 ]))

What are doing the following “commands”?

timers.get(sw.name)

timers.put(sw.name, createTimer…)

timers.put(sw.name, null)

Why not define a Timer like in the Simple Example?

I hope somebody could give me some explaination :slight_smile:

Best wishes,
Michael

Not quite. ‘sw’ here will be a copy of the OH Item that you correctly identified as selected from a Group.

So you can treat it like an Item to get at its various properies, using sw.state to see its value, or sw.name to get its name.


timers here is a ‘map’, which if you are familiar with other programming languages you might think of as an array.

Ok, understood. Is there a documentation which kind of property I could get from an Item/Contact/…?

Ah, so the big advantage is, that I only have to declare one timer map regardless how many timer I need at all? I only have to fill/read the map with

timer.get(ItemName)

?

So i try to show you the light as understand it. There is no guarantee that i am right.

1.) The switch thing

val sw = gMotionDetectors.members.sortBy[lastUpdate].last as SwitchItem

You are very close, but not precise enough. So letzt go trough the statement.

val

Defines a value that could not be changed (Constant). var is the other option. This defines a value that could be altered. I am not in the design pattern, but i assume the the val is choosen, because it is used inside a lambda

gMotionDectectors

This is a group off all motion detector switches. Typically if a motion detector tripped as swicth is triggered

members

This selects all members of this group. If i remeber right you get some kind of list with all the members

sortBy[lastUpdate]

This sorts you member list by the key “lastupdate”

last

And the last selects the last element is the list. so this ist the one which is last updated. Unfortunately OH ist currently not able to tell which item within a group has triggered rule. And with this statement you get the triggering item.

as SwitchItem

Defines the returned item as a switch.

As you see more or less the same, but a little bit more precise. Now the next parts

2.) The Map part

import java.util.Map
val Map<String, Timer> timers = newHashMap

Because OH does not know directly all thing of stuff, we have to import some “constructs”. Here we improt a type called Map. A Map is a collection of key/value pairs like (Thomas->52; Geord->23; Charles->22). Here the Name is the key and with the key you are able to acces the age. The secondline creates a variable named timers. timers stores Timer connected to a String

timers.get(sw.name)

This line of code retrieves a timer from the map timer by using the key sw.name. Remeber sw ist our switch item and with the .name we acces the name of the item. Maybe something like “MotionDetectorMainEntry”

timers.put(sw.name, createTimer…)

this is the opposite of getting the timer. put puts a new timer into the map with the key “sw.name”. the createTimer create the Timer in the fly

timers.put(sw.name, null)

the null puts the map entry into a defined state after the timer has expired. so you can check if the timer is not null, it should be running

Hope this helps a little bit.

Cheers
Thomas

1 Like

Thank you very much @Dibbler42 for the explanations - I think I understand now.

What do you mean with

puts timer into the map

? A timer is a changing object - will it constantly update the map with the current value?

And a more generally questions: How could I learn more about rules syntax? Is it possible to execute a rule line by line to see what happens? Is is possible with the karaf console? What happens if I use the command createTimer and which parameter could I use?

Sorry, questions after questions :slight_smile:

Hey questions are good, becaus thats shows to the community that you are willing to learn. OK lets start with the timer thing.

If you create a timer with

var Timer myTimer = null

myTimer = createTimer(now.plusMinutes(5)) [|
                        // Do something
                ]

myTimer only is a handle to the timer. So you can store this handle in a variable or within a map or an array or something else.

How to learn the syntax is a good question. Study the examples here and in other forums and wikis. Try to understand the code, build you own code and start slow and easy.

Thomas

Well, to explain my goal it will link to my other post. You´ve wrote, that myTimer is a handle to the timer. But how could I handle it? How could I get the current state/count?

Especially to my problem I think I´ve read the most of all but I can´t find out how it should work (or I looked for the wrong words).

Everything is right until the very last thing you say. sw IS the Item, not just its name.

A Map stores key/value pairs. You use the key to get the value associated with it. In this case, the Map is defined to use a String for the key and Timer for the value.

To that line gets the Timer object associated with sw.name (i.e. the name of the Item extracted from the line starting with val sw ....

Creates a Timer and stores it in the Map using sw.name as the key.

Sets the place in the Map associated with sw.name to null, essentially throwing out the reference to the Timer that was previously stored there.

Because you need a separate Timer for each Item. You therefore, need a way to store and recall the Timer.

Probably not the best way to think about it. Maybe think of it as an array that using anything as the index rather than just integers. There are some massive changes in how they work and are stored and such as well, but for these purposes we can ignore those.

Everything in a Rule is an Object. An Object is a collection of values and methods.

A variable is a pointer to something in memory. Another way to say this is a variable has a handle on an Object in memory.

So when you call sw.name, you are getting the name data field from the Item Object pointed to by the variable sw.

A Timer is just an Object. When you call createTimer it returns a Timer Object and myTimer points to it.

I think before you will be able to understand the syntax you need a bit more of an understanding about how programming languages work because everything I said above is basic programming stuff and is true for pretty much all programming languages. I recommend taking one of the many online courses that provide an introduction to programming; the course from MIT Open Courseware is particularly good.

Once you are armed with some of the basic concepts of how programming languages work in general you can use VSCode with the openHAB Extension. This is a great way to learn the syntax because you can start to type something and it will list all the legal ways to complete what you typed at that point. Before too long you will remember everything and will have the language figured out.

@rlkoshak: Thank you very much. You´re right - I have to learn a lot about programming. I could understand the most of the example rules but from time to time a special code line I don´t understand (and I want to understand :slight_smile: )