# \[SOLVED\] Issues in a rule

**URL:** <https://community.openhab.org/t/solved-issues-in-a-rule/166917>\
**Category:** Beginners\
**Tags:** rules, rules-dsl\
**Created:** [October 23, 2025, 6:49am UTC](https://community.openhab.org/t/solved-issues-in-a-rule/166917 "2025-10-23T06:49:50Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ariela](https://community.openhab.org/user_avatar/community.openhab.org/ariela/32/18303_2.png) [@ariela](https://community.openhab.org/u/ariela)\
**Post date:** [October 23, 2025, 6:49am UTC](https://community.openhab.org/t/solved-issues-in-a-rule/166917/1 "2025-10-23T06:49:51Z")

</div>

Hello

I’ve found this message in my logs, but I don’t understand. Can you please help me?

```yaml
2025-10-23 08:37:49.525 [WARN] [el.core.internal.ModelRepositoryImpl] - DSL model 'presence.rules' has errors, therefore ignoring it: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.

```

Here my rule:

```php
// Global variables

var Timer cameHomeTimer = null

// Presence (Home) Unifi in

rule "Set Home"
when
    Member of gPhones changed to ON
then
    val setHome = gPhones.members.filter[p | p.state == ON && p.name == triggeringItem.name].map[name.replace("_Phone_Home_Unifi_online", "")]

    switch setHome {
        case setHome.get(0) == "Axxxxx": {
            if (A_Presence.state == OFF) {
                A_Presence.sendCommand(ON)
            }
        }
        case setHome.get(0) == "Cxxx": {
            if (C_Presence.state == OFF) {
                C_Presence.sendCommand(ON)
            }
        }
        //case setHome.get(0) == "Cxxx": C_Presence.sendCommand(ON)
    }
end

// Presence (Home) welcome message

rule "Welcome home my dear"
when
    Member of gPresence changed to ON
then
    if(cameHomeTimer !== null) {
        return; // do nothing if there is already a Timer
    }
    
    logInfo("test", "Rule triggered by " + triggeringItem.name + " at " + now.toString)
    cameHomeTimer = createTimer(now.plusSeconds(5), [ |

        val cameHome = gPresence.members.filter[h | h.state == ON && (h.name == triggeringItem.name || (h.lastUpdate !== null && h.lastUpdate.isAfter(now.minusSeconds(6))))].map[name.replace("_Presence", "")]

        gPresence.members.forEach[h | logInfo("test", "Values for " + h.name + "\n" + "State = " + h.state.toString + "\n" + "LastUpdate = " + h.lastUpdate.toString)]

        var String message = "Benvenuti a casa: "

        switch(cameHome.size) {
            case 0: {
                logError("came home", "Unexpected number of phones: " + cameHome.size)
                return;
            }
            case cameHome.size == 1 && cameHome.get(0) == "Axxxxx": message = "Benvenuto a casa, Axxxxxx"
            case cameHome.size == 1 && cameHome.get(0) == "Cxxx": message = "Benvenuta a casa, Cxxx"
            case cameHome.size == 1 && cameHome.get(0) == "Sxxx": message = "Benvenuta a casa, Sxxxx"
            case cameHome.size == 1 && cameHome.get(0) == "Exx": message = "Benvenuto a casa, Exxxxx"
            case cameHome.size == 1 && cameHome.get(0) == "Axx": message = "Welcome home, Axx"
            case cameHome.size == 1 && cameHome.get(0) == "Cxxxx": message = "Welcome home, Cxxxx"
            default: {
                message = message + cameHome.reduce[String list, String name | list + ", " + name]
                val ind = message.lastIndexOf(",").toString
                //message = new StringBuilder(str).replace(ind, ind+1," e").toString();
                message = message.replace(ind, " e ").toString();
            }
        }
        logInfo("check message", "message is: " + message)

        Echo1_TTS_Volume.sendCommand('90')
        //Echo_Living_Room_TTS.sendCommand('<speak><break time="2s"/>' + message + '</speak>')
        Echo1_TTS.sendCommand(message)      
        cameHomeTimer = null
    ])
end

// Presence (Away) GPS out

rule "Set Away"
when
    Member of gPGPS changed to OFF
then
    val setAway = gPGPS.members.filter[a | a.state == OFF && a.name == triggeringItem.name].map[name.replace("_Presence_GPS", "")]

    switch setAway {
        case setAway.get(0) == "Axxxx": A_Presence.sendCommand(OFF)
        case setAway.get(0) == "Cxxx": C_Presence.sendCommand(OFF)
    }
end

```

thanks for helping me

Andrea

---

<div class="post-metadata">

**Author:** ![Udo\_Hartmann](https://community.openhab.org/user_avatar/community.openhab.org/udo_hartmann/32/70871_2.png) [@Udo\_Hartmann](https://community.openhab.org/u/Udo_Hartmann)\
**Post date:** [October 23, 2025, 10:43am UTC](https://community.openhab.org/t/solved-issues-in-a-rule/166917/2 "2025-10-23T10:43:44Z")

</div>

As there are three rules in the file, the first step would be to separate them (temporarily) into three files.  
What do the groups look like? I don’t get the point what the code is supposed for, I mean, e.g. the first rule:

```auto
rule "Set Home"
when
    Member of gPhones changed to ON
then
    val setHome = gPhones.members.filter[ p | 
		p.state == ON && 
		p.name == triggeringItem.name
	].map[name.replace("_Phone_Home_Unifi_online", "")]

    switch setHome {
        case setHome.get(0) == "Axxxxx": {
            if (A_Presence.state == OFF) {
                A_Presence.sendCommand(ON)
            }
        }
        case setHome.get(0) == "Cxxx": {
            if (C_Presence.state == OFF) {
                C_Presence.sendCommand(ON)
            }
        }
        //case setHome.get(0) == "Cxxx": C_Presence.sendCommand(ON)
    }
end

```

why don’t do it this way?

```auto
rule "Set Home"
when
    Member of gPhones changed to ON
then
    val String setHome = triggeringItem.name.replace("_Phone_Home_Unifi_online", "")
    switch(setHome) {
        case "Axxxxx": if(A_Presence.state == OFF) A_Presence.sendCommand(ON)
        case "Cxxx" : if(C_Presence.state == OFF) C_Presence.sendCommand(ON)
    }
end

```

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [October 23, 2025, 2:07pm UTC](https://community.openhab.org/t/solved-issues-in-a-rule/166917/3 "2025-10-23T14:07:25Z")

</div>

A closure is sometimes called a lambda and sometimes called a function. In Rules DSL any time you have `[|]` you are defining a closure.

That should help narrow down which lines of code the error is coming from.

The arguments passed to a closure are the stuff before the `|` which further narrows the problem down.

The specific problem, reworded in more generic terms is “I can’t figure out what these arguments are, consider telling me.” You actually do this for one of the closures.

```
message = message + cameHome.reduce[String list, String name | list + ", " + name]

```

There you are telling the language parser that `list` is a `String` and `name` is a `String`.

So you just need to do that for the other lambdas in the rule where it’s complaining.

```
val setHome = gPhones.members.filter[ GenericItem p | p.state == ON...

```

Though, as @Udo_Hartmann points out, you can likely eliminate a bunch of these closures entirely.

---

<div class="post-metadata">

**Author:** ![ariela](https://community.openhab.org/user_avatar/community.openhab.org/ariela/32/18303_2.png) [@ariela](https://community.openhab.org/u/ariela)\
**Post date:** [October 23, 2025, 9:28pm UTC](https://community.openhab.org/t/solved-issues-in-a-rule/166917/4 "2025-10-23T21:28:55Z")

</div>

Thank you so much @Udo_Hartmann @rlkoshak for your example and explanation.

I’ve understood, and now I’ve fixed/optimized the rule.

thanks again

Andrea
