Hi Matt … Welcome to the conversation: We really value SmartThings’s internal input here, and you’re an especially good candidate .
Disclaimer: Please note that I have not had the pleasure of meeting you in person nor one-one chat/conversation, so there is some risk in a Forum discussion that I may sound a little judgemental or even aggressive. That’s certainly not my intent, and I try to frame my questions and arguments appropriately – but in the interest of being efficient, I sometimes cut “right-to-the-point” … the “point” being my own personal opinion on the way I feel something is not quite right or a recommendation for something, but with nothing personal intended whatsoever. I don’t know all the internal history or cross-linked architecture stuff behind the scenes, so I can only comment from a black-box perspective, but do so with the utmost respect and recognition that things are always more complicated than they seem. The platform is based on excellent principals and must have gone through a lot of thought and debate and require compromise and flexibility. – TL;DR: If I say “WTF” or “that’s crazy” or some other sarcasm; it is just my folksy point-of-view language, not a judgement on the design or efforts of SmartThings’s team whatsoever!
Wow…, incredible growth and a testament to the power and potential of the SmartThings platform: 12,000 SmartDevice Types!? …
… and yet … The Capabilities Taxonomy has barely changed in 3 years. How is this possible?
Seriously … how is this possible?
- The rather short Capabilities list was and is so brilliantly conceived that it really does cover such an incredible number of devices.
and/or - You’ve added new Capabilities that have not been published and shared with us.
and/or - A significant number of those 12,000 SmartDevice Types are using one-off
attributes
,commands
, and/or ad hocevent Types
in order to represent the unique interfaces of the physical world things.
Item #1 is beyond belief. #2 is partially fixed by documenting and sharing the new Caps, though these Caps must vary in maturity and rigor.
I fear, however, that the most common situation must be #3, and I can understand why:
- As far as I know, Attributes are not only required by SmartApps and Services, but are required for the GUI (mobile app). If a certain brand of thermostat has a feature “highest temperature of the last 24 hours” and the coder needed to represent this in a tile, then they would have been unlikely to request a new Cap for this one new
attribute
, since, heck, SmartThings allows you to add Attributes on the fly, there’s no friction to doing the QUOTE “wrong thing” UNQUOTE.
and/or - The new device type was being added at the same time as one or more somewhat “tightly-coupled” SmartApps were being coded (i.e., SmartApps which are rather unlikely to be used with alternative devices of even similar capabilities, possibly because there aren’t any similar devices in existence yet, or there is tight coupling to the brand, or patent, etc.). In this case, these SmartApp(s) needed to use some unique Attributes and/or Commands and/or Events from this unique device, that did not fit in any existing Caps and, as this was a “one-off” Device Type, did not “justify” creating a new Cap.
Solution(s)?
Well… that’s where the discussion of granularity (ref: @thegibertchan) comes in; and I eventually get to in if you manage to stay awake through a few more paragraphs…
If a new SmartDevice Type requires special attributes or commands (NB: or Event Types – I have make this implied until further notice: I don’t understand if/how/why Event Types are being used as part of the device interface that isn’t defined with attributes and commands), then I think we have two options:
- If there is a need for urgency, and/or if the new attributes and commands are difficult to comprehend outside the context of this particular device type, then it should be flagged with “
capability.extended
” or some similar{metadata}
that distinguishes and identifies the variances from the applied standard official Caps.
This seems safe for “added” attributes or commands, but is still unsafe with respect to the standard attributes and command. e.g., if the device hascapability.switch
, then all SmartApps and Services that use the device will expecton/off/on()/off()
, and there’s NO currently existing way around this without the real risk of making entire bunches of SmartApps fail – i.e., ALL attributes and commands must be implemented, because some SmartApp may, and is legally allowed to, get/set any of those Cap associated attributes and/or call any of those Cap associated commands.
In other words; this quote from your post makes no sense to me:
What do you mean? How can a SmartDevice Type with a particular Capability not implement all of the commands [or attributes] of that Capability? That is a non-sequitur, and can be resolved. Either completely remove the claimed but unfulfilled Capability from the SmartDevice Type (and replace it with a new claimed Capability), or, at the very least, populate the missing commands and attributes with “safe” stubs and defaults.
So to give an example based on your posting: You mention the context of non-published/non-shared devices, and give the example:
OK… Well… first of all, I would say this device is NOT a Switch. It does not have capability.switch
.
BUT: I totally understand that there are countless unpredictable scenarios in which it is useful to call this a Switch so that (among other reasons?) SmartApps that offer a list of devices with capability.switch
can will include instances of this SmartDevice Type. Yet … non-sequitur – most of those SmartApps are likely to fail, since they will most likely try to call the expected “command: off()
”.
Sub-Conclusion: At the very least, if a SmartDevice Type claims a Cap, then it must have safe dummy-stub commands and safe default attributes. The non-off-able “Switch” here, can have a blank off(){}
command, and should, apparently, permanently set Attribute switch = off
.
Implementation Alternative: Some Attributes and Commands of any Capability could be explicitly declared “optional
”. Again, I am suggesting this possibility for the Capability definition, not the Device Type definition. For the latter case, if you demand maximum flexibility, all ad hoc Attributes and/or Commands defined in a SmartDevice Type are implicitly and unavoidably “optional
”. The behavior of this could be handled in one of two ways:
-
(a) Optional attributes and commands will automagically return default values and safe-null actions, saving coders the responsibility from writing stubs. The syntax:
optional attribute weirdVar String default "off"
could be used to set that “meaningful default”
OR -
(b) All SmartApps and Services that wish to use any Attribute or Command that is documented (and declared in the Capability or Device Type) as “
optional
”, should do an “if exists( Device.attribute)
” and “if exists( Device.command)
” prior to using those optional characteristics, and/or usetry/catch
or some other exception handling mechanism – i.e., SmartApps and Services can use optional attributes if they know about them AND if they confirm that the individual Device Instances they are using actually have them implemented.
(NB: I am not particularly enamored to this particular Implementation Alternative; heck, I don’t like partially implemented or ad hoc exceptions to Capabilities in any form, but, it’s fun to theorize.)
While I’m still “unsure” as to why such a weird “Switch” would be created, the use of stubs and defaults probably help.
Proposed Rigorous Solution and
New Suggestion: “Optional Characteristics”:
-
I think it is obvious that if Capability are extremely granular, then quite a few problems go away: There is much less risk of having a SmartDevice Type that cannot implement a particular Attribute or Command, because an extremely granular Capability will have: as few attributes and commands as possible (i.e., the minimal set, not the optimal set).
-
Proposal #1 works well in the existing platform (phasing out non-granular Caps) … almost. The problem: “
SmartApp.preferences{input(capability.x)}
” only accepts a single “capability.x
”. A complex SmartApp really may require a particular set of Capabilities from each Device. Thus, a change is required so that the Capability filter ofSmartApp.preferences
can use operator “AND” (i.e., An extreme and unlikely example of granularity:capability.on AND capability.off
).
NB: It would be nice to also support an OR operator, but code that uses a Device List would no longer be able to reliably iterate a single command over that single combined Device List – unless SmartThings also implements the miracle of Polymorphism (e.g.,capability.switch
hason()/off()
, butcapability.lock
hasunlock()/lock()
– both are binary actions, therefore, a Device List made up ofcapability.switch OR capability.lock
could be iterated over with commandsactivate()/deactivate()
inherited fromcapability.binary
. This is worth a spin-off Topic, no? -
If Capabilities are granular, even if “reasonably granular” (i.e.,
.switch
is good, but.on
and.off
is probably overkill…), then the platform would really benefit from the ability to pre-define compound capabilities (e.g.,capability.dimmableLight = capability.switch + capability.switchLevel
), so that each of hundreds of very similar non-trivial Device Types do not need to manually include the possibly very long list of individual granular Capabilities.
NB: I still see this as a possible step to true Inheritance (and Polymorphism), as discussed at length elsewhere (i.e.,capability.switch
extends
capability.binary
); but that is, admittedly, not a “baby step”.
Conclusion: I think my post covers some important material about the nature of Capabilities that is important to settle before we add any more Capabilities:
The discussion as to “What process, forum, committee should be used to officially add (and, sometimes delete or modify) standard Capabilities” is certainly important – but, IMHO, that can’t proceed with any sanity if the issues I’ve raised here (and, certainly some small and big stuff I’ve missed) are not settled first.
Respectfully,
…CP / Terry.