[SOLVED] How to check if two items change in 5 seconds? (Presence detection + alexa)

So it would seem. Try adding Antje half second to see if it works more reliably. In that run it was only off by about 100 msec.

I will try 6 secs.

thank you VERY MUCH for your help during this troubleshooting … I’ve learned more than in 2 years with OH :slight_smile: Thank you!!!

two more questions:

  • how to solve this cosmetic?
2019-02-01 09:20:05.096 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'alexa.rules', using it anyway:
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
  • how to learn more about the language used in OH rules? what language I need to study more?

thank you!!!

Andrea

It’s complaining about the arguments passed to a lambda. I recommend loading the file in VSCode to tell you which one it is complaining about. Then give those lambdas a type. I suspect it’s the map so you would use

.reduce[ String list, String name |

Well, some of this could be learned by looking at the language docs, like the map reduce filter forEach like stuff to do with Lists, but Design Pattern: Working with Groups in Rules is a little better than the official docs.

The timing issue has nothing to do with the language and everything to do with the timing and how OH itself works and you won’t find any docs that help you with that.

The best place to start is the OH Rules docs page. There is a link to the Xtend Docs on the Rules Doc page, so go there to review how to do things like the switch statement and such. Finally, review the Design Patterns for tested generic approaches to solve common problems.

1 Like

ciao Rik,

I’m already working with VSCode, all my files are open via VSCode, but I don’t see any warning or problem or output at all. Do I need to debug somehow?

All I can recommend then is to keep adding the Types to the variables to the left of the | in all the [ ] until the warning goes away.

like “p”? may I ask you an example?

I gave you an example above. Here it is again with the full line.

cameHome.members.reduce[ list, name | list + ", " + name ]

For the filter, you would use GenericItem as the type for p.

The map doesn’t have arguments (i.e. no |) so it wouldn’t be complaining about that.

Found it, it was in reduce as you said.

Sorry, I didn’t understand first time I read. THANK YOU !!!

Andrea

@rlkoshak

just studying the rule, in order to simplify other my if/else super-nested rules :slight_smile:

why here we are using “.size”?

switch(cameHome.size)

is because in this case we should have “0” or “1” right (and at the beginning we were also thinking about using a case 2 as well)?

Otherwise, if for example I have to say “if a switch changes OFF, please modify also another switch accordingly” I should simply use:

switch setAway {
        case setAway.get(0) == "Andrea": sendCommand(Andrea_Presence, OFF)
        case setAway.get(0) == "Cate": sendCommand(Cate_Presence, OFF)
    }

of couse, if I have just 2 cases, I can use if/else as well. But switch can be useful if I need to add more cases in the future right?

Thanks for your guidance

Andrea

Because the size of the list tells you how many people just came home. Before you had the additional requirements that the message is in Italian and therefore the gender changes the message, it was the simplest way to decide between the messages. Now that the “who” has come home is important, it may not be the best choice. But you still need to take it into consideration so you can handle the case where more than one person comes home.

1 Like

@rlkoshak sorry to bother you again, but …

this morning I’ve tested when two people join the network simultaneously. But the result was unexpected: Alexa reply with two messages instead of the “default” message.

I was expected “Benvenuti a casa, Andrea e Cate”. But I hear “Benvenuto a casa, Andrea” and then after a while “Benvenuta a casa, Caterina”.

Here the log:

2019-02-11 09:04:18.126 [INFO ] [.eclipse.smarthome.model.script.test] - Rule triggered by Andrea_Phone_Home_Unifi_online at 2019-02-11T09:04:18.085+01:00
2019-02-11 09:04:23.181 [INFO ] [.eclipse.smarthome.model.script.test] - Values for Andrea_Phone_Home_Unifi_online
State = ON
LastUpdate = 2019-02-11T09:04:17.815+01:00
2019-02-11 09:04:23.187 [INFO ] [.eclipse.smarthome.model.script.test] - Values for Cate_Phone_Home_Unifi_online
State = OFF
LastUpdate = 2019-02-11T08:05:47.176+01:00
2019-02-11 09:04:23.201 [INFO ] [smarthome.model.script.check message] - message is: Benvenuto a casa, Andrea
2019-02-11 09:04:38.245 [INFO ] [.eclipse.smarthome.model.script.test] - Rule triggered by Cate_Phone_Home_Unifi_online at 2019-02-11T09:04:38.245+01:00
2019-02-11 09:04:43.272 [INFO ] [.eclipse.smarthome.model.script.test] - Values for Andrea_Phone_Home_Unifi_online
State = ON
LastUpdate = 2019-02-11T09:04:17.815+01:00
2019-02-11 09:04:43.298 [INFO ] [.eclipse.smarthome.model.script.test] - Values for Cate_Phone_Home_Unifi_online
State = ON
LastUpdate = 2019-02-11T09:04:38.246+01:00
2019-02-11 09:04:43.334 [INFO ] [smarthome.model.script.check message] - message is: Benvenuta a casa, Caterina

As you can see, it seems the second phone joins 20 secs after the first one.

I think I have two options: wait more than 20 secs, or change the mechanism. It seems quite unreliable, isn’t it?

My current rule is:

// Presence (Home) Unifi in

rule "Welcome home my dear"
when
    Member of gPhones 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 = gPhones.members.filter[ p | p.state == ON && (p.name == triggeringItem.name || (p.lastUpdate !== null && p.lastUpdate.isAfter(now.minusSeconds(6)))) ].map[ name.replace("_Phone_Home_Unifi_online", "") ]

        gPhones.members.forEach[ p | logInfo("test", "Values for " + p.name + "\n" + "State = " + p.state.toString + "\n" + "LastUpdate = " + p.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) == "Andrea": message = "Benvenuto a casa, Andrea"
            case cameHome.size == 1 && cameHome.get(0) == "Cate": message = "Benvenuta a casa, Caterina"
            case cameHome.size == 1 && cameHome.get(0) == "Sofia": message = "Benvenuta a casa, Sofia"
            case cameHome.size == 1 && cameHome.get(0) == "Edo": message = "Benvenuto a casa, Edoardo"
            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)

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

Since that is the case the Rule performed correctly.

If you mean change the mechanism for detecting when a phone is detected home then yes, either of those approaches are what you will need to do.

The problem isn’t the Rule. The problem is the delay for when the phones are detected home.