Optional capabilities and meta code

Ok, I’ve read some long threads about it such as:

But I wanted to create another one on new ideas about how to implement extra capabilities.

I will try to give concrete examples in order to be clear for everybody. I will use the examples of the existing thermostat capabilities because I know these capabilities very well (i.e., My custom ecobee device type).

Another reason for using the existing thermostat capabilities as example is that this set is the most detailed and decomposed of all the device types out there (why? unknown).

First, to set the context, do we consider the existing thermostat capabilities a minimum set of characteristics and methods that each thermostat must implement?

Looking at the capability taxonomy right now, yes, it does look as the existing capabilities are the minimum set that a thermostat device type must implement.

For a thermostat device type developer, it means creating a bunch of capabilities ( you may forget one as ST restructures them as they did in the past).

On top of it, all these capabilities are in fact a set of the lowest common denominator for all thermostats out there.

Z-wave thermostats (such as the CT30, CT100) and wi-fi thermostats (such as ecobee, Next, Honewell Lyric, and even the Honeywell Smart Wi-Fi thermostat) are totally different breeds of thermostats.

Z-wave thermostats are just plain dumb: they don’t have any scheduling capabilities as soon as you connect them to a hub.

One cannot create any ‘hold’ events (such as ‘away’ or ‘present’ and even custom ones) at z-wave thermostats, and ‘resume’ their normal scheduled programs once this event is over.

For example, based on the ecobee thermostat, I created a smartapp that can create ‘away’ hold events when all presence sensors are gone, and ‘resume’ the normal scheduling when one presence is back home. Another smartapp that I created does a similar logic, but based on indoor motion sensors. Sadly, the smartapps that I created are specific to ecobee, and there is no way for me (at the moment) to generalize them for other smart thermostats out there (i.e., for the Nest or Lyric).

So, what do we do for the ‘smart’ thermostats?

a) Do we add another set of ‘regular’ capabilities such as ‘capability.thermostatSetHold’ and ‘capability.thermostatResumeProgram’ only valid for smart thermostats?

Z-wave thermostats then won’t be able to implement them, so that goes against everything that has been done so far in ST.


b) Do we create a brand new set of ‘optional’ capabilities for the smart thermostats?

And, how to generalize these optional capabilities given the fact that each smart thermostat has
a different way to create hold events and resume them (with different attributes potentially)?

My thoughts are the following: if we can find a way to create metacode templates (with generic commands such as setHold & resumeProgram) which could be customized by each smart thermostat device type into their real implementation (using their own attributes), then we’d be able to achieve a higher level of reuse.

I’d like to exchange ideas about how to create metacode, but I’d like to know if it’s something ST developers are interested in or it’s just me (b/c of my SW architecture background)…


Really excellent idea(s), Yves! (especially thanks for considering this in the context of the Capability Guidelines which illustrate some of the limitations of that concept in the current Platform’s implementation).

This new Topic almost fits under the Category for New Capabilities.

There are lots of possible ways to fix, improve, and extend stuff that is helpful or critical in Device Type definition. It will be fun to explore ideas.

@tgauchat, well, I’m just trying to expand the concept of Capabilities. I understand the concept of functional capabilities (as you can see by my previous posts).

As an architect, I’d like also to have access to non functional capabilities (let’s call them annotations or hints for the moment) for better performance, security, reliability, high availability, and so on in some device types and some smartapps (I’ve given examples in my non functional capability posts earlier) that I feel will be CPU or data intensive. Standard non functional requirements would be applied by the hub/cloud by default (so that, in general, developers would not need to worry about them).

Now, the problem with functional capabilities is that the taxonomy is not well understood by all the developers out there. Some device types implement them totally, others not. I think that most of the times, the developers are not even aware of them. That happened to me when ST restructured the thermostat capabilities and decomposed them further.

So, as developers, we need Capability templates where the taxonomy is full expanded for each device type (ideally). If a developer wants to create a new thermostat device type, she/he would just then need to click the thermostat capability in the IDE to include all the required subCapabilities associated with it. Also, any new capabilities could also be automatically added in the IDE following some capability taxonomy changes.

I suggest a new “metacode” section within a device type (automatically added). The new section may
include keywords to determine if a capability has been implemented or not by the developer.

There may be mandatory capabilities and optional ones. See an example below.

By doing so, we can achieve a higher level of reuse and maybe reduce the number of customized device types out there that have only slight variations.

metacode {

/#Mandatory thermostat.capabilities

//# thermostat.setHeatingSetpoint capability

void setHeatingSetpoint(temp) {
	// call this thermostat implementation of the method	
//# thermostat.setCoolingSetpoint capability

void setCoolingSetpoint(temp) {
	// call this thermostat implementation of the method	


//# thermostat.setThermostatMode capability
void setThermostatMode(mode) {
	// call this thermostat implementation of the method	
	sendEvent(name: 'thermostatMode', value: mode)

//# thermostat.off capability

void off() {
//# thermostat.auto capability

void auto() {
//# thermostat.heat capability

void heat() {
//# thermostat.emergencyHeat capability

void emergencyHeat() {

//# thermostat.cool capability

void cool() {

//# thermostat.setThermostatFanMode capability

void setThermostatFanMode(mode) {
	// call this thermostat implementation of the method	
	sendEvent(name: 'thermostatFanMode', value: mode)

//# thermostat.fanOn capability

void fanOn() {
//# thermostat.fanAuto capability

void fanAuto() {

//# thermostat.fanOff capability

void fanOff() { // fanOff is not supported, setting it to 'auto' instead.

//# thermostat.fanCirculate capability

def fanCirculate() {
	// call this thermostat implementation of the method	

/#Optional thermostat.capabilities

//# thermostat.away capability

void away() {
	// call this thermostat implementation of the method	

	sendEvent(name: "presence", value: "not present")

//# thermostat.present capability

void present() {
	// call this thermostat implementation of the method	
	sendEvent(name: "presence", value: "present")

//# thermostat.awake capability
void awake() {
	// call this thermostat implementation of the method	


//# thermostat.sleep capability

void sleep() {
	// call this thermostat implementation of the method	


//# thermostat.auxHeatOnly capability
void auxHeatOnly() {

//# thermostat.resumeProgram capability

void resumeProgram() {

	// call this thermostat implementation of the method	


} /* end of metacode */

Bye for now.