Capabilities, Attributes and Values for Hubitat

Ummm...respectfully, null HAS TO BE a valid value (and not just because SmartThings implemented it that way) - null is the value of an attribute before it has been set - and its what currentValue() of an unset attribute will return.

I'm simply trying to find a way to get an attribute BACK to the original null value...

ok, but why?
We haven't identified a need for this in apps or drivers...

BTW null isn't an original value, it's what a database returns when a record set is empty...

1 Like

Also curious as to why null is displayed in the device's page after a sendEvent with value: "", and then why does it restore the old values when I refresh that device page?

It seems to me an incomplete implementation...I'd prefer it work like SmartThings (I know - sacrilege, sorry if I insulted anyone).

Use case: I have a device driver that manages a network-connected device. This device has numerous attributes (settings and states) that I'm trying to reflect in the device driver. I get them from the device in JSON format, and some of these attributes are occasionally (frequently) null, dependent upon the physical device. For example, if the device has an event running, it will provide me with the event_endDate in the JSON; when there is NO event running, this event_endDate will be null (meaning, there is no event running, so there is no end date). I want to present the event_endDate as an attribute, but when the event is over I need a way to set it back to the original null state.

Further, your documentation states that all event values sent using sendEvent must be Strings, and (respectfully) "" is a valid (empty) String. Nowhere can I find documentation that says an attribute cannot be null (or the null String "").

I'm sure you can work around this using other means.
Events (attribute state values) are not a display replacement for the tiles in smartthings...

Generating events that have no purpose other than an informational display should be discouraged as they use unnecessary resources.

Hubitat's event system is designed to trigger automations.

1 Like

OK, I see that you are digging in your heels on this one.

I'm not trying to replace tiles - I am trying to communicate information to the user or programmer. There is no other means for either persona to see what is going on inside a device except for attributes (end-users can't access dataValues in Dashboards or Rules).

Imagine a simple Hubitat Dashboard (or Rule Engine Rule) that displays the event_name that is running, and it also wants to display the event_endDate beside it. How else would I be able to get this information into the Dashboard, if not through an attribute? And while I could send a space " ", the result would not be a valid date if another App (or Rule) was trying to use that information.

There is a reason why null (undefined) exists in Groovy, and why null is a valid value for a String (and an Integer, and a BigDecimal, and a Boolean, and ...). There is a also reason that Hubitat will return null when asked for the currentValue() of an attribute that hasn't been initialized yet - it isn't true or false - it's null (aka undefined). There's probably even a reason that Hubitat's Device page shows the word "null" for such values, albeit momentarily (and incorrectly, I guess, because the underlying value has not been actually changed).

Frankly, I don't get why the push-back.

Hubitat clearly understands when an attribute is null, because it will return null when asked for the currentValue of an uninitialized attribute. It is is also clear that at least SOME code (device display page) understands how to display null values. Somewhere, the code is indeed letting "null" into the device (perhaps only into some cache, I guess), but that code isn't overriding the attribute value when it goes to unload the cache (I'm just guessing here).

And yes, while I can code around your chosen implementation, it requires code to do excess work on Hubitat than should be necessary - I really should only have to test if the returned value is null or not:

Hubitat code

    def event_endDate = theDevice.currentValue("event_endDate", true)  // force reading the cache
    if (event_endDate)    // verify the response isn't null because it hasn't been initialized yet
    {
        if (event_endDate != 'null') // check if it has been set to literal `null`
        {
              // Handle the actual end-date
        }
        else
        {
            // There is no event running
        }
    }
    else
    {
        // The attribute hasn't been initialized yet
    }

verses SmartThings code

    def event_endDate = theDevice.currentValue("event_endDate", true)  // force reading the cache
    if (event_endDate)    // verify the response isn't null because it hasn't been initialized yet
    {
        // Handle the actual end-date
    }
    else
    {
        // There is no event running
    }

what?, that's the whole point of the live logs accessible via log.debug | trace | info | warn | error ect...
you can dump whatever you want as often as you want there...

1 Like

Rhetorical Question: And then how do I get a value from the Live Log into the Dashboard or a Rule?

I honestly feel like you're disagreeing just to disagree...

So, riddle me this, how come isStateChange(device, "foo", "") returns true when "foo" is "some string", although I can't actually change the value of "foo" to ""?

Seriously, I think if you step back, take a breath, and think about it, you will realize that you have an incomplete implementation. null is a valid attribute value, and you should finish your implementation such that the updates to null actually get pushed into the attribute's value.

if the goal of Hubitat was to match ST byte for byte, then yes, the implementation would be incomplete...

and I feel like you're not listening to what I'm saying...

1 Like

So what is it that you are saying "you have decided that null is not a valid attribute state, even though Hubitat partially supports null as a valid attribute state?

Or, are you saying "that's the way it is, and I'm not changing it, even though it appears that the current implementation partially supports it."?

Or, are you saying "just because SmartThings does the logical thing and accepts null as an valid attribute value, doesn't mean Hubitat should do the same."

Or, are you saying "you don't need to use attributes to carry information that might ever be null or undefined."

In any event, I humbly suggest you need to do something to fix your implementation:

  1. Allow the null string ("") as a valid value for attributes (at least the user/programmer created ones)

  2. Fix the current implementation to be consistent

    • device.sendEvent(name: attribute, value: "") should indicate failure somehow, since it is (silently) currently ignoring the call. Since sendEvent() is declared as void, I guess you'll have to throw an error (illegal argument, perhaps). (Note that this could be disruptive to existing code)

    • isStateChange(device, attribute, "") should always return FALSE (currently returns TRUE if the attribute actually has a non-null value)

    • The device page should NEVER show an attribute's value as null (as it currently does, making it appear that things actually worked like they do on SmartThings). To be consistent, the device page should ALWAYS show the true underlying value for all attributes (updated in real time, as they are currently).

    • Document this significant incompatibility with SmartThings somewhere, so that developers understand why their code doesn't work (this is currently very confusing because of the prior 3 things that need to be fixed).

    • Include in the updated documentation the exception that uninitialized attributes WILL return null to the getCurrentValue()/getCurrentState() calls, even though there is no way for a developer to change the value to null.

Or maybe you said something different, and I truly am not listening...

I can find no detailed documentation of sendEvent() in the Hubitat Documentation Wiki - the arguments are never defined.

Follows the documentation of sendEvent from SmartThings documentation. Given how Groovy documentation is written, this says that sendEvent will accept ANY object for the value, but that it will be stored as a String.

It would seem that Hubitat has redefined the definition of the value argument to be "Accepts only non-null Strings".


Signature:

void sendEvent(Map properties)

void sendEvent(Device device, Map properties)

Parameters:

Map properties - The properties of the Event to create and send.

Here are the available properties:

Property Description
name (required) String - The name of the Event. Typically corresponds to an attribute name of a capability.
value (required) The value of the Event. The value is stored as a string, but you can pass numbers or other objects.
descriptionText String - The description of this Event. This appears in the mobile application activity for the device. If not specified, this will be created using the Event name and value.
displayed Pass true to display this Event in the mobile application activity feed, false to not display. Defaults to true .
linkText String - Name of the Event to show in the mobile application activity feed.
isStateChange true if this Event caused a device attribute to change state. Typically not used, since it will be set automatically.
unit String - a unit string, if desired. This will be used to create the descriptionText if it (the descriptionText option) is not specified.
Device device - The device for which this Event is created for.
data A map of additional information to store with the Event
1 Like

The same seems to be true with data values in a device. If I set them and then want to invalidate that value I have resorted to writing a space character or the text ‘null’ which is a kludge.

Null is not a value. Null is the opposite of a value... any value.

1 Like

OK, you got me on a technicality. But when device.getCurrentValue("foo") returns null, then null is indeed the CurrentValue...

No, it's saying there isn't a value. It's not a technicality, it's an important distinction. This is why sending an event to say that an attribute doesn't have a value is a non-event.

1 Like

I'm sorry, but I will have to disagree with you there. The fact that the device no longer knows what the value of an attribute is, is precisely why Java/Groovy/et al support the notion of a variable (attribute) being in a null state.

The SmartThings implementation is far more robust in this manner, as it allows the developer to RETURN an attribute to the unknown state (which is where it started when it was originally created).

As an example, strictly speaking, there is no valid value for a date that does not exist (e.g., my "event_endDate" example). What should the attribute be set to in that case? A Space isn't a valid date, nor is the String "null". The answer: it's a null date - any date/every date/not a date ...whatever you want to call a null date - that's what it is.

Matters not - Mike isn't going to fix change his implementation, not after he's lived with the decision for this long. I was just hoping not to have to code around yet-another-incompatibility... Oddly, there aren't that many, and most of them are reasonable. This one, well...

This is not a reasonable conclusion to draw from what Mike has said. Your perspective is not his perspective, and he doesn't have these sort of "investments" in the way things are implemented. It's hard to tell what you expect to accomplish with this line of discussion.

Compatibility with SmartThings is not what drives our engineering decisions.

2 Likes

HE has blown past ST in what is capable in driver and app space..

Take it from someone who recently had to convert drivers from HE code to ST.. ST feels like an outdated kludge now..

I wish people would stop comparing, because they are very different... And complete code compatibility shouldn’t be a concern.. It’s time to leave ST in the dust

I have to agree with Barry here. I think supporting a null value seems a useful and valid ask.
This is not based on ST compatibility.

What's the use case?