Capabilities: Existing and Process to Add New. Note: Capabilities ~= Interfaces?: Capabilities MUST be very strictly defined and enforced (attributes / commands / events)?

I’m more concerned that:

  1. The ‘V’ is capitalized in capabiilty.tV.
  2. Commands channelUp() / channelDown() are provided, but no setChannel()setVolume()

That second one is an across-the-board beef, namely:

All public attributes should come with setter methods commands. Heck, there also should be getters, but since attributes are generally passed by Event statements, setEvent() and parse() (and the special variables… <attribute name>State, … getters don’t make sense here (?).

That’s an interesting question, and one that might even apply today. How do we handle a single z-wave switch that has multiple switches? I’d guess that you’d need to have a generic device type tied to the hardware that sends events to multiple virtual devices - one for each switch…

Of course, that doesn’t handle the case of doors on a car. It would be clumsy to have a “car” device and 4 virtual “door” devices, wouldn’t it?

How would ST handle one of those higher end weather station devices that reads both inside and outside temperate? Is there a capability that supports multiple temp readings?

Okay - so I agree that the “combine multiple capabilities to create a device type with all those capabilities” has some shortcomings. Yet, that’s what it is today. My z-wave wall switch has a “switch” capability for the on/off, and an “indicator” capability for the little indicator light on it.

It appears that the ST dev’s haven’t yet considered the case of a device type that has multiple capabilities of the same type (such as a “car” with multiple doors.)

Actually, I might be wrong in that last statement. It’s possible that ST would want to NOT have a “car” device at all. Instead, “car” would be a group containing all the parts? If so, you’d have 4 different “door” devices, all with (likely) the same device type.

1 Like

While I was building device type for RainMachine, I did somewhat encounter this problem. Irrigation systems are just a bunch of “valves” group together, but they need to work together as one group. When I stop the sprinklers, all of the valves must shut down. When I start, they must not start each zone

Contrary to what SmartThings beliefs, I think devices needs to have some level of “intelligence” e.g irrigation controller would group valves and make sure that the valves don’t open more than one at the same time. SmartThings Hub/Cloud would then be the brain of knowing other events are happening at the same time e.g I’m in bathroom showering and I don’t want sprinklers to bog down the water pressure. SmartThings would then delegate the controlling of each valves to irrigation controller instead of micro managing each valve as a “primitive” device.

I know this is off the original topic. So @garyd9, looks like I did you some revenge.

1 Like

Thanks for asking :wink: The world I’m describing here is actually just a “moon” of planet “Java” (in the “Object Oriented” solar system!). NB: Other OO languages can be selected in place of Java, but I figure Java is appropriate analogy because we are coding in Groovy.

I am basing my wishlist and thesis on the assumption that the OO concepts of Abstract Class, Interface, Inheritance (Extension), and Polymorphism are applicable to SmartThings, with reasonable customizations. I’m not pulling these concepts out-of-my-a$$ (I hope). So as these questions come up, the first reference point is to ask “how is this handled in OO Interfaces?”.

The disclaimer here is that Java Interfaces enforce the implementation of all of the public methods only … public attributes are not a part of the Interface concept; but I (we?) extend it here for Capabilities, as Capabilities are a special variation on Interface.


For Aaron’s Example:

(1). The Best Practice to consider for capability.temperatureMeasurement, is that it should really have been designed with some more proactive thinking. Temperature is analog, so using an integer instead of a float was a poor choice. If float was impractical, then adding a fractional attribute temperatureTenths would have been an excellent idea, and is probably still reasonable to add.

Reference: http://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html

Try to anticipate all uses for your interface and specify it completely from the beginning. If you want to add additional methods to an interface, you have several options…

(2). The next best option, in OO, is to extend the Interface. That requires Inheritance (sub-Capabilities?).

Reference: http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

MountainBike inherits all the fields and methods of Bicycle and adds the field seatHeight and a method to set it. Except for the constructor, it is as if you had written a new MountainBike class entirely from scratch, with four fields and five methods.

So that’s why I’m tempted to modify the title of this Topic to include Inheritance: Inheritance (in some mutation applicable to this context), is not a mandatory feature for the implementation of strict Capabilities, but, since OO uses Inheritance as the de facto way of extending Interfaces; ergo, it is be beneficial to explore that applicability to Capabilities.

Next:

That is an excellent question; and, I have already fretted over this for the current implementations of “capability.button” (i.e., Aeon Minimote 4-Button, ZWN-SC7 Enerwave 7-Button, …).

These are multi-button devices. They are not exactly devices of capability.button; they are either devices of capability.buttons (capability.buttonPad?), or, indeed, a group of capability.button.

The former choice (i.e., a new capability.buttonPad), is attractive, since it accurately reflects the nature of the overall device. It is bad, though, because a SmartApp that only needs a single button can’t automagically use it. Well … too late: These two current multi-button implementations of capability.button are perversions and do not work “as-is” with SmartApps that expect a single button. They require a special SmartApp to attach actions to each button. Boo. Bad.

Without a new capability.buttonPad The best I can think of based on the current implementation of SmartThings, is that these multi-button devices should be 4 or 7 individual Device instances!

How to clean this up … well, the latter option (i.e., a multi of identical capabilities and/or a group of diverse capabilities) would give us the best of both worlds: Individual Device instances, each with the “singular” form of capability (e.g., door), but in some structure that combines them into a "combo"-capability.car.

At this point in a long post, I can’t decide whether these “combos” should be restricted to parts of all the same Capability or if we can mix and match to form arbitrary complex devices, or both, but with different implementation rules: But I think either is preferable and more beneficial than the use of plural capabilities (i.e., we should avoid capability.buttonPad or capability.buttons to maximize compatibility; except when it gets into the absurd, such as “capability.keyboard” which contains over a 100 keys, and calling each a “button” is a stretch.).


…CP / Terry.

I’m not sure if it is. The original topic was (I think) a discussion on custom capabilities vs custom attributes/events/command vs inheritance. Your post forces us to consider another possibility: “has a” vs “is a”.

Most of the device types have a “is a” relationship with the caps. A “z-wave light switch” IS A switch. In fact, outside of object orienting thinking, ST forces all device types to have a IS A relationship with capabilities. You must only have on cap of any type, and you must implement commands/attributes for that cap.

However, as we’ve discussed…

A car HAS 4 doors. That rain machine HAS many valves.

So, to implement HAS A, we’d need a way to define a single door. Then, the “car” device type would have 4 attributes, each of the type “car_door”. This isn’t supported by ST today. :frowning:

So, now I’m sure @tgauchat is going to have a field day with this. Actually, I see he’s already started while I was typing…

1 Like

You’re missing the point, who the hell these days is actually using the tv’s built in tuner???

Okay, so you are thinking of capabilities as interfaces and device types as being classes? I was trying to think of capabilities as being more like classes (which can be instantiated) as opposed to interfaces which can’t.

I’ll use some non-existant OO language that’s a perversion of Java and C++…

interface door;
class car_door : public door;

class car
{
car_door leftFront;
car_door rightFront;
car_door leftRear;
car_door rightRear;
}

A light switch would be…

interface switch;
interface indicator;

class z-wave_light_switch : public switch, public indicator;

// actually, I’d prefer to create a “on_off_indicator” class that implements indicator, and then class z-wave_light_switch would have an instance of that class (not inherit from it.) A “light switch” IS A switch, but it HAS A indicator.

Perhaps the SmartThings Reference Documentation has been hacked, since, no insult intended to the PTB (Powers-That-Be) that may be viewing this thread, but capability.tV as it is published at this time seems very hastily defined.

Considering what a TV Device Type would look like, and what Capabilities it could provide, is a wonderful exercise; but published already?

BTW: TV channels are probably a reasonable concept to include in this Capability … though maybe it is a distinct and inheritable “capability.tvTuner”.

OK. I agree with this. So, what does the process look like to get ST to add temperatureInTenths to capability.temperatureMeasurement ? Probably not a fair question for the community to address. . . .

1 Like

umm… I do? At least for one of my TV’s, I pop in a cable card and… (the rest all have TiVo’s attached.)

Anyway, it isn’t about if one person might use it, it’s about supporting it’s use. Should thermostat devices have the “heat set point” related commands and attributes removed just because someone who live’s in FL would never use the heater?

1 Like

Just because you’re in the new era with new way of consuming entertainment on TV, you can’t assume that there’s no one still on TV tuner. The world population is 7 billion, and a small fraction of it would easily sum it up to millions.

According to Wikipedia, the viewership on OTA are still in millions too.

As the fallback I suggested, let’s reference the Java documentation:

http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html

In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces.

In other words, an Interface is really only a set of rules for the Classes that implement it. Conveniently, Interface definitions look a lot like Abstract Class definitions.

Thus, in SmartThings, a Capability is just a set of rules for the Device Types that implement them.

For your car example…

Before we create “class car”, we start with “interface car” (i.e., an interface can inherit other interfaces, just as a sub-class can).

Translate to SmartThings:
interface car { includes door, includes steering, includes seat, car attributes, car methods }

Now any device type that implements capability.car, must implement all of the included (inherited?) capabilities.

Ummm… I’m deferring more “grouping” concepts at the moment, because we need to figure out the difference between Inheritance, multi-instantiation (i.e., groups of same capability), and other types of Groups.

yes I get what @garyd9 and @copyninja are saying, however doesn’t explain the lack of on() and off(), which every TV in existence has…
My point here is the tV device is half baked at best, hopefully this device got half completed today, and the remainder of the more useful commands will show up tomorrow…

2 Likes

Regardless, in order to solve all the current problems/limitation at once, SmartThings would need to change the platform, which means impact to the the way of coding SmartDevices.

or they continue with current mess…

With minimal snark, I’ll point out that SmartThings can’t even “handle” the “SmartSense Multiproperly, because it provides 4 potential readouts (open/close, activity, orientation, temperature), and yet there can only be one Main Tile visible in the mobile app at a time.

Discussed this in the “Label” topic (i.e., SmartThings should allow shortcuts everywhere to sub-tiles, or add “soft tiles”; but this might also be solvable if multi-Capability Device Types just instantiated a Device for each capability; with some sort of sophisticated grouping, It’s the details of Grouping that’s got me stumped at the moment.

The SmartSense multi is actually a live example of grouping multiple capabilities. Worth keeping in mind.

Well… Some of the issues are workable in the current platform, some are not.

  1. I think we can defer Inheritance, but Capabilities must be strictly enforced (i.e., no arbitrary attributes and/or methods, and no cheating using undefined events). Without inheritance, it means that we should avoid including redundant methods in each Capability, and Device Types should just stack up a long list of Capabilities (e.g., the Device Type must including both capability.lock and capability.lockControl if lock/unlock is required, rather than the mess that just got created with Thermostat.

  2. I have a harder time living with the singular/plural cases (button vs. buttons). The implementation of Aeon Minimote 4-Button is wrong, and yet, very close to being ok.

  3. Other kinds of grouping … dunno.

1 Like

This is, I think, where we can start to think of Polymorphism (on top of Inheritance).

To toss a quick example:

  • capability.switch is a capability.binary
    But so is:
  • capability.contactSensor is a capability.binary

Just basic OO stuff … every Class Interface Capability is quite possibly based on something closer to the root Capability.

Thus, SmartApps and external apps that request a Capability should use the root-most capability applicable, and let the Devices poly-“morph” into the applicable form.

Gets complicated and abstract, but I try to make an example here:

As a follow up to last night’s developer call, I wanted to add my two cents here.

In general, thinking of a capability like a Java/OO interface is good. In an ideal world, a device type that implements a capability would implement all of the commands and create events for all the attributes. For all published device types, we should probably be ensuring that they do meet this contract.

However, we’ve always known that we have to be flexible to handle all the individual situations we can’t think of. In the last 30 days developers have added over 2500 new custom devices to the platform, bringing the total to over 12,000. I don’t know what any of those devices do, but I bet at least some of them implement capabilities but don’t implement all the commands. In fact, I’m willing to bet that some don’t implement methods on purpose because it doesn’t make sense for their custom device. On a similiar note, many of these custom devices probably have custom commands and attributes and developers are writing corresponding SmartApps to take advantage of of these.

I think the bottom line is that I feel custom devices fall into two groupings. First, there are devices that are published/shared for everyone. These probably should meet the contract of capabilities since lots of people could depend on them to work in a certain way. Second, there are devices that are never meant for wide distribution that individual developers create for themselves. These should have the flexibility to work in unique ways. If you want to create a switch that doesn’t turn off for whatever reason, we want you to be able to do that.

Going forward, we are going to be making developer tools more of a priority. I think the first step will be to document capabilities better.

After that, what do you all feel would be the best way to add new capabilities? Perhaps a tool to suggest/vote on them? Or maybe being able to create your private capabilities that you could publish like device types and SmartApps? I’m not actually sure how we’d do either of those, but we could certainly look into it.

Thanks everyone for thinking about this and helping us find these pain points and suggesting ways to improve them.

2 Likes

I didn’t participate in the developer meeting so I’m probably missing some background but I do like the idea of a tool to propose a new capability, expose for discussion/collaboration/debate, then implement in some reasonably formal way.

Would we also consider the same or similar approach for new attributes of existing capabilities? As has been noted, changing current attributes would break things - a bad thing - but I would think that we should consider a process to add new attributes to existing capabilities in a thoughtful way. Existing SmartApps that utilize existing attributes would not be broken but new SmartApps that wanted to leverage some new functionality made possible by a new attribute could do so.

This would break the idea that a device type must handle all attributes - if I’m interpreting some of what I’ve read above. Maybe the solution to this is some sort of ‘required’ and ‘optional’ structure sort of like what Z-wave uses. . . . . FWIW

1 Like

I’m not sure “private” capabilities are the best way. How would that really be different from existing code that has custom attribs and cmds? In either case, for anything else to make use of the additions, they’d have to have that “private” knowledge.

One of the benefits of capabilities is that it’s an established contract. It’s a way for a smartApp to have some knowledge of a device, without knowing the details. If a device type claims “switch”, the entire system knows that the device is claiming an on and off ability. If a device type claims “battery”, the entire system knows that this device can report a battery level as a percentage. It’s my opinion that this is one of the things that makes ST really expandable and flexible.

I don’t know what device type “foobar” is, but I know I can turn it on and off! Now any smartapp can include a foobar as a target to turn on or off (without really knowing - or caring - what a foobar really is.)

So, a tool to suggest capabilities (AND to have fairly responsive reaction from ST) would be more useful, I think. However, in doing that, certain guidelines would have to be made, and adhered to in both the suggested capabilities, AND in whatever ST decides to add. Here are some suggestions for those guidelines:

  1. A capability can not reproduce the functionality of another capability. So, the existing “lockCodes” would be rejected as it reproduces the functionality of “lock.” “lockCode” should only contain attribs and cmds related to the codes, and devices should include both “lock” and “lockCode” if they support both locking functionality AND lock CODE functionality. It is completely realistic to have a device that supports locking codes, but doesn’t actually support a lock mechanism. Perhaps it requires a code to turn on a switch instead, or a code to turn on an alarm system, etc.

  2. A capability should serve some purpose beyond just cluttering up namespace. If it doesn’t provide any attribute or command, what purpose does it serve? (relates to #3)

  3. Capabilities should define capabilities, not devices. “switch” and “relaySwitch” define the exact same attributes and commands. They should NOT be two unique capabilities. (Unless, of course, you want to have “lightSwitch”, “tvSwitch”, “computerSwitch”, and “vibratorSwitch” all as new capabilities.) At the same time, what capability does “actuator” provide?

Being that I used so many existing capabilities as “bad examples”, some poor ST employee should really refactor the existing capabilities and fix things. That would be a slow process of first undocumenting things that shouldn’t exist (or documenting them as “legacy”) and then fixing existing device types and smartapps that make use of these things. For example, mark “relaySwitch” as legacy, and then fix any code using that cap to use “switch” (with the eventual goal of removing relaySwitch.)
Anything that uses the legacy flagged items should generate a warning in the log, and after a year the legacy stuff should be dropped.

2 Likes