Attributes - Questions on characteristics

I think I at least partially understand Attributes. Can someone tell me if I am correct?

  1. Attributes are not like program variables, they are a location in the Hubitat database created when the driver is paired with the device.

  2. For a location to be created, the Attribute must be defined in the "metadata" section.

  3. Attribute will never be in the parsed device message as the device has not knowledge that it exists.

  4. You can only set the Attributes value by a "sendEvent" action.

Thanks

John

2 Likes
  1. Attributes are just a special variation of a Variable. They get allocated and are modified using specific methods but they otherwise exist in the same way a Variable does. Note that I'm considering Objects, like Date, etc that are large collections of values to be under the same sort of 'umbrella' as Variable.

  2. Yes to the Metadata definition.

  3. An Event comes from the Device, It contains values that will be splattered across one or more Attributes. Two sides of the same coin. An 'attribute' out on the device was transported across the Mesh as an event and then turned back into an Attribute.

  4. yes. It's the specific method for altering Attributes.

All my answers are my own interpretation and I've specifically taken a viewpoint that I hope adds "color and depth" to the response. In general, you probably are correct enough, but I wanted to try and give future readers somethings to think about too. :smiley:

3 Likes

Sort of: you only need to specifically define custom attributes, which means ones that are not a standard part of any Capability. If you declare a Capability, it means two things (you didn't ask for both, but I like to be thorough :slight_smile: ):

  1. You agree to implement all the methods (commands) it specifies
  2. You do not have to explicitly declare any attributes that are part of the Capability (and unofficially, you should populate all attributes with something, perhaps as part of your device initialization or refresh; some apps behave wonky if it's looking for something that should be there as part of some capability but isn't; officially, you should make sure they are populated with the right type of data--e..g, string vs. number, units or not [usually not--those are usually just part of the event], etc.)

Regarding sendEvent, you are correct, as stated. Events are how you modify attributes. Technically, there is also createEvent, but it is only usable in parse() methods of drivers and returns a sendEvent wrapper for you, and I just prefer to do it myself (partly because I remember how sendEvent works off the top of my head and can't say the same for createEvent).

Further, you are correct that attributes and values are persisted to Hubitat's database. Coupled with the fact that it creates an event, I consider this to mean that I should be careful when using custom attributes. If it's not something an app (so ultimately the user) is going to want to subscribe to--e.g., to trigger an app/rule--then it's likely it doesn't need to be an event/attribute. If you're trying to persist data in your driver for your own sake, state is likely a better place (but not usably accessible to the end user). I also consider it to mean that I should think twice about updating attributes like crazy (say, every second)--or using devices that try to do the same (cough, cough, default settings on some power meters, though that's an entire other story on the network side, too).

2 Likes

Just to clarify...you "should" implement all of the methods for that capability. Not even all the built-in Hubitat drivers follow this 100% of the time. You shouldn't miss any if you can but sometimes certain ones don't make any sense. In that case, it would be nice if you simply implemented an empty method to avoid errors but again, not even all Hubitat drivers follow this 100% of the time. From anecdotal observation it's probably north of 95% but it's not quite 100.

Another note about events...events are only generated, by default, when the value for the attribute changes. So, if you have a switch that is on and send another event of on for the switch attribute an event will not be generated. You can override this in your driver by using "isStateChange: true" to force an event to occur no matter what. Also, you should always use that parameter for button events, since the same value (the button number) is always an event.

1 Like

I agree with the original statement above...

Not including a command defeats the purpose of capabilities and the command's button will appear in the UI even when the method isn't defined so implementing all of a capability's commands is required.

I think the most common approach for commands that don't make sense is to make them log a message saying the command isn't supported.

I've seen some of the built-in drivers display unsupported messages for commands that don't make sense, but I've never seen a built-in z-wave driver that was missing a command.

If there are some built-in drivers that are missing commands then Hubitat most likely didn't notice they were missing.

Thank you for your insight. I didn't state such but I assumed the only reason to declare an Attribute would be because it is not already part of an capability.

Could you expand on your statement "You agree to implement all the methods (commands) it specifies". I'm not sure what you mean my "implement all" and what it are you referring to in "it specifies"

I now feel I have a better understanding of how the attribute works, this makes it much easier for me to remember.

Should I assume createEvent will create an "attribute" location in the Hub DB even if it wasn't declared in the metadata?

John

All (well most of) HE's capabilities are listed here, and in each it tells you which commands and attributes are involved.

https://docs.hubitat.com/index.php?title=Driver_Capability_List

Look at the Chromecast driver.

Who said anything about z-wave?

I linked to the docs for Capabilities and you'll find another reply that did, too, so hopefully that helps! But perhaps it's a terminology thing: "implement" basically just means that if, say, the capability has an "on" command (see the docs), then you have a method ("function" in some programming languages) called on(), too. (I didn't mean to start a debate on whether this is truly required, but if you find that one doesn't make sense for you to implement for a specific device, I suggest considering whether you really should have that Capability or at least logging a warning so users don't get a missing method exception.)

The best advice is probably not to try this since the behavior is undefined. :slight_smile: I think I did it by accident once and it was more or less ignored. If you want an attribute that is not part of a capability you claim to implement, you should declare it as a custom attribute.

1 Like

Thanks again, I understand both parts of your reply.

I am familiar with the Driver Capability list. However when I responded I did not refer back to the list and had it in my head the a device capability could have multiple (sub) capabilities but now I see that is not the case.

Which commands are missing?

I said "z-wave" to specify that I was basing my comment off of the z-wave handlers I've used and I don't know if there are zigbee and WiFi drivers that are missing commands.

I stand corrected...the volume commands that didn't work must have been fixed at some point.

1 Like

One more question:

In a custom attribute, what defines the key/values MAP?

For instance I've seen one example where the attribute had Keys for name, value, description.
Are these predetermined by Hubitat? They weren't defined in the metadata.

I've also seen other keys in some attributes like display: t/f or isStateChanged: t/f are these like language defined and can be used or not?

Thanks again
John

I think you might be talking about two different things:

  1. the data type of the custom attribute, which is defined in the metadata according to your needs, e.g., attribute "myFancyCustomAttribute", "string" for a value that accepts string (text) values

  2. the properties map that gets passed to sendEvent, the only official documentation we have for which specifies, unhelpfully, that the signature is void sendEvent(Map properties) (in their defense, it is under the "Additional to be documented" section). In that regard, it is nearly identical to the SmartThings method of the same name, which they have documented. (The only difference I can remember off the top of my head is that Hubitat doesn't use displayed.) Here is a concrete example of a typical Map that you might pass:
    sendEvent(name: "level", value: 50, descriptionText: "${device.displayName} level is 50%, unit: "%")

1 Like

That is the sendEvent command....not the attribute itself. For example:
sendEvent(name: "switch", value:"on", descriptionText: "The switch turned on.")

The attribute can take any form you want but most of them are strings or numbers and a few are ENUM. There are a couple built-in attributes that have JSON format also, but the particulars of what has to be in that JSON object are not defined and there is no standard.

You can find more details on the capabilities reference.

Most is documented here on the event object.. That’s what I have used as a reference for sending events..

https://docs.hubitat.com/index.php?title=Event_Object

1 Like

Thanks again. Your example and Smartthings reference did the trick :slight_smile:

John

1 Like