Am facing a very weird situation, in my SmartApp now() is an object of type java.lang.Long
For another user, @Manhmai612, it’s returning a BigDecimal, how it is this possible?
Here the code that works fine for me:
atomicState."lastMotionCheck${camera.id}" = now()
log.trace "Initializing last motion event checked at ${new Date(atomicState."lastMotionCheck${camera.id}").format("EEE MMM dd yyyy HH:mm:ss z", timeZone)}"
May I recommend using a variable instead of the atomicState? Two reasons. Efficiency and Consistency - looks like the atomicState is messing with your data type.
long time = now()
atomicState."lastMotionCheck${camera.id}" = time
log.trace "Initializing last motion event checked at ${new Date(time).format("EEE MMM dd yyyy HH:mm:ss z", timeZone)}"
Using atomicState will force a db read which means time/resources. You don’t need to read from atomicState, since you just set it. Use a temp variable instead.
1 Like
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
3
Doesn’t work, there’s a bug in the state variable (see my other thread) because of which only atomicState works when working in a Parent SmartApp - Child DH relationship.
This variable is accessed from the SA while context of the DH calling the parent SA method, only atomicState works and I need it stored for future access.
I really need an answer from ST on why now() returns BigDecimal for some users and Long for some. It’s really messing things up.
state.variable <<< this is a state variable
def variable <<< this is a local variable (memory allocated throughout the execution of the current method)
But regardless, you should still use a variable, rather than that second atomicState (the read) - you’re wasting time and resources reading a value from the db which you just set and could already have. (unless the code above is only as an example to replicate the issue)
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
8
Honestly? Why have specifications? If objects can return random values I’m just going to give up on this platform. I have a simple question for ST, what is the return type for now()? Long or BigInteger?
How many places am I going to start putting checks and for what values? What if it returns a Double tomorrow?
2 Likes
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
9
Was it to do with now()?
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
10
I have a feeling this is a ST Database issue, see this:
It’s not that now() is returning a BigInteger, when storing it in the database it’s storing it or retrieving it as a BigInteger instead of a long.
@ady624 to your point, if this is a DB bug are you going to typecast every value returned from state and atomicState? It could convert an double to BigDecimal, what then? I don’t think it’s reasonable to start checking the value returned by the ST DB. This is clear bug with the platform and it only seems to be affecting some instance/users.
Just for context/explanation, yes now() does indeed return a long.
When saved to state or atomic state, the values are serialized to a JSON string using groovy’s JsonSlurper. When pulled back out of state, the values are “inflated” back into one of the following types:
"true" or "false" values returned as Boolean "null" values returned as null
any decimal values returned as BigDouble
any other numeric values returned as BigInteger
3 Likes
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
12
Hey thanks for that Jim, that was super helpful. So in context of this line, you’re saying that any value that is stored as Long in state/atomicState will be returned as BigInteger.
If so how has my original code been working for the past few months. Date() only takes Long and it’s been working fine (and actually continues to work for 99.9% of the users). Just trying to understand this so that it can handled correctly going forward.
I meant to ask/confirm that it was something you’re seeing recently, sorry about that! When about did you notice a change?
1 Like
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
14
I haven’t noticed a change personally. Two users who’re using the Blink app have noticed the changes recently (can’t pin point the date since the apps have been running and when they reinitialized their apps today it threw the error).
But so far only 2 users have reported this issue. So just to be clear, what the app has been doing is:
Save the Long value returned by now() into an atomicState variable
Use that atomicState variable to instantiate a new Date() object
The above has been working fine for everyone until recently, even now it’s working for 99.9% of the users just 2 users have reported that Date() is now throwing an exception about the BigInteger. There could be others but until they hit that code likely on a reinitialization of the app, we won’t know.
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
15
Jim check this out, I just did a quick test on my setup here. Here’s the code used to test the value:
log.warn "LONGVALUE: ${atomicState."lastMotionCheck${camera.id}".longValue()}"
if (atomicState."lastMotionCheck${camera.id}" instanceof Long)
log.warn "It's LONG"
if (atomicState."lastMotionCheck${camera.id}" instanceof BigInteger)
log.warn "It's BigInteger"
It appears to be returning a Long and not a BigInteger as you had indicated. However the Long does appear to have a longValue() method to it.
So I’m a little confused now. Is it supposed to be Long or BigInteger?
EDIT: I’m also wondering if it’s a shard thing. Maybe some shards are returning Long and possibly after the recent Grails upgrade some shards are returning BigInteger?
Yeah I may be wrong, or looking at newer code than is deployed, or a bit of both
I tested and see the same thing as you. Will follow up when I know more.
1 Like
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
17
Okay and I was just looking at a lot of the code out there using state and atomicState, if it now starts returning BigDecimal and BigInteger it’s going to mess up a lot of the code. There are all kinds of stuff being being stored in state/atomicState including maps. This would require a major rewrite of a lot the code since many API like Date() don’t accept BigInteger/BigDecimal
Coming back to your point, yes please do let us know and if the “newer” code deployed is returning BigInteger instead of Long maybe please revert back to the Long. Either way until this is resolved I can’t provide a reliable solution the users so I’m just going to wait for you. Thanks.
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
18
Jim, another 2 more just reported the same issue. That’s 4 now and I suspect it’s going to start going up real quick
RBoy
(www.rboyapps.com - Making SmartThings Easy!)
20
Thank you for the update Ryan. I will ask the users to check again.
So for clarification if a Long is stored in state and atomicState then a Long will be returned. Can you please clarify for future reference the expected behavior of state and atomicState when storing and retrieving different types of objects and data types.