Here's what I'm trying to do. I have a media device (AVR) with an input. When the input changes, I need to do something based on what it USED TO be, not the new value. Seems simple enough, but when I look at the Device object I see events()
eventsSince()
and currentValue()
. No way to do something like event(-1, "input")
to get the previous. No previousValue("input")
am I missing something obvious? Yes, I know that I can create a state variable and store the old value there to compare it. That just seems like a waste since clearly HE has the event history already stored since I can retrieve it with events()
. The problem is, events()
doesn't let me filter by an event type so it will be super inefficient. Before I wasted storage and created a bunch of state variables, I figured I'd see if there was an API I'm not seeing that already exposes this.
It's in the device events, like this:
dev.events().find{it.name == "input"}.value
Assuming "input" is the name of the attribute. You can do this:
dev.events(max: 2).find{it.name == "input"}.value
to get the last two event values, etc.
Yeah I see I can do that. But, I assumed that would be inefficient. Meaning, what if the last time "input" was changed (super exaggerated unrealistic example) 1200 events ago because I almost always leave my AVR on input 1 but I turn it on/off multiple times a day. So there are a ton of "switch" events that all occur after the last "input" event. So to grab it I'd have to call dev.events(max: 1200).find{it.name == "input"}
but now I'm searching through a list of 1200 values. And it assumes I know 1200 is the theoretical max, what if the last "input" change was at 1201, now I'd miss it. I suppose I was expecting a dev.events(max:2, event: "input")
yeah, you'd still need to do a search, but (I assume) you'd do that in SQL rather than me having to pull a much larger list out of the DB and then searching through it in Groovy.
Like I said, easy enough to do with a simple state variable, I just figured it was worth asking
dev.events().find{it.name == "input" && it.value != latestValue}.value
But, what if your events don't go back far enough? You already know the answer. RM implements *changed*
(et al) using state to keep the prior value. Not seeing how this is a burden.
Didn't say it was a burden, in fact I said it was easy But easy doesn't always make it best. If the data's already stored, I figured it made more sense to access that stored data instead of creating duplicate data] unnecessarily. Duplicate data almost always leads to data inconsistencies (exactly why so much research exists on database normalization!) Also, your example would only go back 10 events according to the document.
Could also look at something like
stateList = device.statesSince(attributeName,startDate)
I don't think it keeps duplicate event values unless isStateChange:true
is forced, which ordinarily it is not. Events that don't represent a state change are discarded. So events(max: 2) should get you the most recent and second most recent value. But, can't say I've spent any time looking at this.
Yeah but it's the last 2 of ALL events, right, not a specific event type? So meaning if I had on/off/on/off/on/off/on/off........../input2 well then input2 wouldn't come back with a max:2. In any case, it's a moot point. If a state variable is the best way to go, that's what I'll do.