SmartApps™ Developer Overview

September 2012, Version 1.0.1 by the SmartThings Cloud Development Team



Calling All Developers

You’ve heard about SmartApps. You’ve even seen a demo of a simple SmartApp. But what are SmartApps exactly and how do they work? We know you have lots of questions, and we’re going to answer some of them right now! This is still just a preview, we aren’t telling you everything quite yet, but I think that this will answer many of your questions and give us all something to chat about!

SmartApps are real software applications, written in a real programming language, and we need real developers to participate in our developer eco-system to build up the catalog of available SmartApps.

SmartApps are written in our own programming language, called SMART (Semantic Modular Application Result Triggers).

At initial launch, SMART (Seriously Mashable Automated Reality Triggers) applications run mostly in the SmartThings Cloud, but with support for simple “wiring” (more about this below) in the hub itself. Then at some point in the future we will support the concept of fully distributed SmartApps that can run either in the Cloud or in our Hub.


How Do People Use SmartApps?

You’ve probably seen this in the videos on KickStarter, but here is how it is going to work. We want you to see how easy it will be for people to install and use the SmartApps that YOU are going to write!

End-users will browse our application catalog, find an application they like, setup their preferences for how they want to use the application, and install it. It goes something like this!

Step 1

From within the IOS, a user clicks “+” to add something new.

Step 2

The new thing can be for a SmartApp or to add a new SmartThing, so they click on “Browser SmartApps” to go to our catalog.

Step 3

They select from a list of application categories (or search, or see most popular – all the standard stuff will be there).

Step 4

They select a SmartApp to see the details about that app.

Step 5

They click “Install”.

Step 6

They configure the SmartApp (and click Install again – working on that).

Once a SmartApp is installed, it just works! Does what it is supposed to do, makes your life more awesome, etc.


What is a SmartApp?

So a SmartApp is written in SMART (Self-Motivating Automated Robotic Toaster), but what is it exactly?

Think of a SmartApp as being a collection of methods (handlers) that respond to events within the SmartThings Cloud.

Things (switches, sensors, locks, etc) generate events. SmartApps can handle those events and then take actions on those (or other) Things as needed.

Let’s get more specific …

The Language

The SMART (Somewhat Miniature Applications Radio Things) programming language is a dynamic, object-oriented programming language similar to Ruby (as in Ruby-on-Rails) or Groovy (as in Groovy and Grails).

It supports the definition of object classes and methods just like Ruby, though in the initial release of the SmartThings platform there may not be much call for creating your own classes since the scope of object is limited to the specific invocation of an event handler.

As we go forward, we envision the ability to create and publish libraries and services for other SmartApps developers to use however. In any case, we know that you will be quick to tell us what you need if we’ve missed something, and we will be anxiously awaiting your feedback!

SmartApp Capabilities

A SmartApp, written in SMART (So Many Amazing Real Things) will have the following capabilities:

  • Define Preferences that are used by our mobile (IOS, Android, future) applications in order to collect information needed to install the application
  • Subscribe (and Unsubscribe) to Events associated with Things (e.g. contactSensorOpen), People, and Locations
  • Set Timers and Alarms to Allow for Periodic Processing
  • Handle/Process Events
  • Define and Raise Custom Events
  • Issue Commands or Set Attributes on Things (e.g. Turn light on)
  • Send Notifications to Users
  • Access People and Presence Information
  • Access Location, Group, and Device Information
  • Access Location Mode Information
  • Initiate a Change in Location Mode(s)
  • Consume External Web Services
  • Expose External Web Services
  • Persist information in Application State storage that is available across instantiations of the application
  • Log debug and trace information for diagnosing problems

Show Me An Example Already!

Okay okay, we know you’re a developer so you don’t want to hear about it, you just want to look at the code.

So here is a small example (more below) of a SMART (Seriously Magical Applications Running Things) Event Handler that responds to a specific “openedContactSensor” event:

def openedContactSensor(evt, settings) {
	def light = settings.switch1
	if(evt == Event.ContactSensor.opened)
	{
		light.on()
	}
}

In this example, the event handler receives an event (the openedContactSensor event), accesses a device (called switch1) through the application settings, verifies that the event is what it expects, and then turns on the switch (light).

Pretty simple huh?

That’s why we call our programming language SMART! (Seriously Magical Awesome Reality Technology).

Preferences

As a SMART (Sensual Massage And Rotating Triceratops) developer, you need to be able to write generalized applications that end-users will install from our application catalog. But this is different than your typical iPhone or Android mobile application, because SmartApps work with Things. And that means that the SmartApps that you write need a way to know what Things they should be working with.

That is where preferences come in. As a SmartApps developer, you will define preferences that tell us what kind of Things and other information you need in order for the application to be able to run. We’ll then use that preferences meta-data to collect that information from the end-user at the time of installation for the SmartApp.

Let’s look at an example definition of preferences:

def preferences()
{
	return [
		sections: [
			[
				title: "When the door opens/closes...",
				input: [
					[
						name: "contact1",
						title: "Where?",
						type: "device.contactSensor",
						description: "Tap to set",
						multiple: false
					]
				]
			],
			[
			title: "Turn on/off a light...",
			input: [
					[
						name: "switch1",
						title: "Which?",
						type: "device.switch",
						description: "Tap to set",
						multiple: true
					]
				]
			]
		]
	]
}

This preferences definition will ask the user for two bits of information: a contact sensor to use and an on-off switch to use.

And here is how that preferences meta-data is used to render the user experience in the SmartThings app on your phone.

The preferences meta-data defined in the application itself provides all of the information we need to render and collect these preferences from the end-user at the time they install (and configure) the application.

Of course users can change their preferences later as well, and applications need to know how to react to those changes.

Notice also that the preferences gave internal (app-specific) names to the Things that are used by the application (e.g. contact1 for the contact sensor and switch1 for the on-off switch).

As a developer, you don’t know or care what the end-user called their devices. You get to name them within the scope of your application so that you can use those names whenever you reference the device.

Now that we have a basic understanding of preferences, lets go back to event handlers and event subscriptions and see how they work.

Event Subscriptions & Handlers

The SmartThings Cloud is all about events. Gazillions of them flowing through our Cloud all the time. This switch turned on, temperature went up, yada yada yada. But as a SmartApps developer you don’t get all the events. You get the events that you subscribe to, and you can only subscribe to events for devices that you are allowed to see (more about security later).

You can subscribe and unsubscribe to events as you see fit in your application, but there are two specific places where this will almost always make sense. Those places are the “Installed” and the “Updated” event handlers.

The “Installed” and “Updated” event handlers are places where you can write code that is invoked when an application is installed or when the preferences (settings) are updated.

Here is an example of both an “Installed” and “Updated” SMART (Southern Musical Artwork Rascal Tomato) event handler:

def installed(settings)
{
	subscribe([device:settings.contact1])
}
	def updated(settings)
{
	unsubscribe()
	subscribe([device:settings.contact1])
}

You can see in the example above, that the “installed” event handler is subscribing to all events for the contact sensor device “settings.contact1″. And then in the “updated” event handler, it is unsubscribing to all events, and then re-subscribing again to all events for the device “settings.contact1″. That’s because the user preferences might have changed what device “contact1″ is pointing to – so the app needs to re-establish the subscription.

You’ll also be able to subscribe to specific events for a device (e.g. just the openContactSensor event instead of all events), and you’ll be able to unsubscribe to just specific subscriptions if needed.

Device Capabilities, Attributes, & Events

Every SmartThing will generally support capabilities (meaning commands) and/or attributes (meaning information that it reports). Some SmartThings will only support attributes (e.g. a temperature sensor), while devices that support commands (e.g. a simple on-off switch) are likely to support both capabilities (“On” and “Off”) as well as attributes (current state=On).

As an example, our SmartTag provides the following sensors:

  • Presence Sensor
  • 3-Axis Accelerometer
  • Temperature Sensor

The SmartTag doesn’t actually support any commands or capabilities, because it doesn’t control anything. Commands (aka capabilities) are reserved for devices that actual control stuff. We saw an example of commands earlier like ‘switch1.on()’. Command are generally that easy, although sometimes they will accept values like:

dimmerSwitch1.on(50) // turn the dimmer switch on at 50%

So while the SmartTag doesn’t support any commands, it does support a number of Read/Write attributes that can be used to configure the behavior of the tag itself. If you think that sounds kind of like a capability, you are right, but we use writable attributes for configuration of our devices, and capabilities to refer to control signals that actually integrate with other devices to control them (e.g. turn on the dishwasher is a capability).

The table below provides the details (as best as we know them) on the supported SmartTag attributes.

Attribute Name Read/Write Data Type Details/Comments
isPresent Read Boolean Indicates that the device is currently connected and reported data.
ftemp Read Float Temperature in Fahrenheit
ctemp Read Float Temperature in Celcius
X Read Float Accelerometer X-Axis Value
Y Read Float Accelerometer Y-Axis Value
Z Read Float Accelerometer Z-Axis Value
reportTemp Read/Write Boolean Used to tell the SmartTag to report or not to report temperature data
reportAccelerometer Read/Write Boolean Used to tell the SmartTag to report or not to report accelerometer data
reportPresence Read/Write Boolean Used to tell the SmartTag to report or not to report presence data
reportInterval Read/Write Integer The reporting interface in seconds. Minimum value is 5 seconds.
tempDelta Read/Write Float Defines the min change in temperature value that will result in an temperatureChanged event
accelerometerData Read/Write Float Defines the min change in any accelerometer axis that will result in an accelerometerChanged event
reportOnlyChanges Read/Write Boolean Used to tell the SmartHub/SmartTag only to report when data (attributes) have changed. This can be combined with the ‘reportMinimumInterval’ attribute to force a report every N seconds even if nothing has changed.
reportMinimumInterval Read/Write Integer Used to tell the SmartHub/SmartTag to report every N seconds even if nothing has changed. Not used unless ‘reportOnlyChanges’ is true.

The SmartTag also generates events to the SmartThings Cloud. The following events are currently supported:

Event Name Event Description
presenceDetected Raised when SmartTag presence changes from “not present” to “present”
presenceLost Raised when SmartTag presence changes from “present” to “not present”
presenceChange Raised in either of the above two cases. Event attributes allow the developer to understand the details.
temperatureChanged Raised when the temperature value changes by more than a preset amount. See capabiliites.
temperatureReport Raised every time the device reports its current temperature
accelerometerChanged Raised when the X, Y, or Z values of the accelerometer change by more than a preset amount. See capabilities.
accelerometerReport Raised every time the device reports its current accelerometer values.

Now lets look at an example of how we might use a combination of attributes and events on the SmartTag.

First, lets define an ‘install’ event handler that is going to adjust some of the SmartTag properties on install of the SmartApp.

def installed(settings)
{
	settings.tag1.reportTemp = false
	settings.tag1.reportPresence = false
	settings.tag1.reportAccelerometer = true
	settings.tag1.accelerometerDelta = .8
	settings.tag1.reportOnlyChanges = true
	settings.tag1.writeAttributes()
	subscribe([device:settings.tag1],accelerometerChanged)
}

Now we’ve configured the tag for only accelerometer data with a minimum change value for any axis of .8 or more, and we’ve told the tag to only report changes that meet that criteria. We also subscribed to ‘accelerometerChanged’ events, so now we need an event handler.

def accelerometerChanged (evt, settings)
{
	def tag1 = settings.tag1
	if (tag1.Z > .8) {
	// garage door is open
	}
}

Yeah we know, the garage door scenario where we use the tag to determine if the door is open or closed is little more complicated than that (though not much), but we wanted to keep the example here simple.

In a real SmartApp for the garage door we would also likely make some decisions based on how long it has been open, or what time it is, or the presence of any cars in the garage, etc.

Composite Devices

One of the coolest things we are working on is the concept of composite devices. In the example above, we showed (at a high level) how we would use our SmartTag to know if the garage door was open or closed.

But of course what we really want to be able to do is both detect the current state of the door, and the control it!

For most people, this will be done using a composite device that consists of a SmartTag and a SmartButton device that will replace your garage door button (you know, the one mounted on the wall just inside your garage).

We’re going to make that a reality, but we will also need to combine these two devices into one logical (composite) device to make the experience easy.

More to come on composite devices, but get ready because they are going to make the world go round!

REST APIs

We’ve had a number of questions about APIs and how people can integrate with the SmartThings Cloud using them.

We believe that all Things should be URL addressable and should support RESTful APIs, and that is what we’ve built.

Our SmartThings IOS application is already using our APIs (so we know they work, yeah!), and the APIs support access to both the attributes and the capabilities of your Things. They also support access to Groups, Locations, etc.

That said, access to everything through our API is restricted in a number of ways:

  • Based on a revocable security token that is associated with a specific user account
  • The user account associated with the token has specific permissions to all devices, groups, locations, etc through Access Control Lists (ACLs), and API calls are similarly restricted
  • Certain information about devices (and all of the other objects) will not be available through the API in the interest of privacy and security. Nuff said.

In addition, we will ultimately allow for SmartApps to have their own endpoints for exposing application/service specific APIs. That likely won’t make the initial release, but it is on the roadmap.

Event Wiring

SmartApps event wiring provides the capability for a developer to “hard wire” a specific event (on a specific device) to a specific command to be issued on a specific device.

The purpose of SmartApps Wiring is to handle the case where a specific event (such as a motion detected event) on a specific device always results in the same response (such as turning on a light).

The benefit of SmartApps Wiring is that once defined, the wiring takes place in the hub and does not have to wait for an event to go all the way to the SmartApps Executor and then wait for the resulting command to return.

Applications create the hard wiring by creating the “Wiring” object, passing in the right parameters, and then calling the “Save” method on the object.

This is shown in the sample code below, which first checks to see if the incoming event (motionDetected) has already been processed by hard wiring, and if not, responds to the event and then creates the wiring so that it will take effect going forward.

def motionDetected (evt, settings) {
	if (!evt.handled) { // #1 - my app has not already handled
	settings.light1.on() // #2 - turn on the light
	wiring = new Wiring(evt.device, // #3 - wiring
	evt.eventType,
	settings.light1,
	settings.light1.commands.on)
	wiring.save() // #4 - Save the wiring
	}
}

All that being said, our vision is to support a distributed environment where SmartApps can execute in a variety of places: across multiple Cloud data centers (for high availability), but also in the hub itself.

Once we make that vision a reality, we could write an event handler without concern for “wiring” since the application could run locally on the hub, but there might be cases where an application actually needs to run in one place or another, so we would support meta-data adornments of event handlers to tell us where they can run. Again, not for the initial launch, but we wanted you to know that we get it.

{Cloud, Hub}
	def motionDetected (evt, settings) {
	settings.light1.on
}

Calling Web Services from SmartApps

We want you to be able to integrate your SmartApps with external web services in order to do COOL THINGS! (e.g. Apps that check the weather, Apps that send text messages, Apps that execute stock trades! No not really).

So we know that SmartApps must support the ability for developers to integrate with external web services. That said, we also have to make sure that the SmartThings Cloud and SmartApps specifically aren’t negatively impacted by things like long-running web-service calls, or calls that return large amounts of data.

So while we intend to support a generalized ability to call virtually any kind of web service in the long-term, at launch we will likely only support specific pre-integrated web services that we make accessible.

For external services that have been pre-integrated, the SmartApps developer won’t need to understand that they are making a web-service call, but will simply use service classes provided by the SmartApps platform that make calling the specific service stupid easy to do.

For example, we’ve already integrated an SMS text messaging capability, so that all you have to do to send an SMS message is:

sendSms(phoneNumber, "Your ${device.label} was opened")

And yes, we are working through all of the security, denial of service, and privacy concerns with even allowing you to do things like that.

Accordingly, one area where we need your help is to give us feedback on what web services you want to see pre-integrated into SMART (Seven Monkeys Acting Really Testy). Give us your ideas and help us prioritize!

SmartApp Security

Yes we know. Security is a big, big deal here. We’ve heard lots of scenarios for how bad things could happen. So we are putting a lot of energy into creating the right security boundaries, thinking about privacy considerations, figuring out what SmartApps should and should not be able to see, do, think, feel (okay not yet on the last two).

We aren’t going to lay it all out here, but understand that for SmartApps developers, we are thinking about security both in terms of how to protect your applications so that your intellectual property is safe, but also how to protect users from any possible malicious use of SmartApps.

Accordingly, you should expect that the developer experience for writing and publishing a SmartApp is going to be more like the IOS AppStore with respect to a review and approval process on all SmartApps.


Becoming a SmartApps Developer

We are shooting for December for the full launch of the developer program, SDK, etc. But we are going to do a number of things in advance of that, like launching our Developer Community so that we can keep the communication flowing and get your ideas about things.

Then once we are ready to launch the SDK (SmartApps Developers Kit), we will make it available to everyone who is signed-up for the community.

What is in the SDK?

The SDK will consist of the following:

  • A SmartApps Developer Account
  • Documentation
  • Access to Source Code for Sample SmartApps
  • Access to the SmartApps IDE
  • Access to the SmartApps Sandbox
  • Access to the SmartApps Developer Community

The SmartApps IDE

Our plan is to make the SmartApps IDE available as soon as possible to provide, wait for it, an “Integrated Development Environment” for SmartApps development. In this case, the term “integrated” really does have a lot of meaning. Our IDE will be integrated with a fully operational sandbox environment so that you can:

  • Assign your hub and things to the sandbox
  • Develop and application and deploy it to the sandbox
  • Test and yes, debug it in the sandbox
  • Document and submit the application for release into our catalog
  • Manage support cases for your app

We can promise that the initial release likely won’t do everything listed above (sorry), but we want you to know the vision, and that vision is to make your life as a SmartApps developer as friction-free as possible!


Terminology and Concepts

When we talk about building Smart Things – or SmartThings, it helps if you have some concepts and terminology straight. Not all of these features will be available at the initial launch. We may even change some of the names. But just reading through the definitions will give you some insight into the direction we are headed.

Things – Anything. Just a thing. A pencil. A coffee cup. A pool filter, etc.

Devices – A thing that supports specific capabilities and attributes. All devices are things. Not all things are devices. For example, a pencil has the capability to write, erase, or be chewed on (capabilities). It also has attributes like how long it is, how much eraser is left, how many bite marks are on the outside.

Composite Devices – A device that is logically made up of other devices. It has their capabilities and attributes, but may also support unique capabilities and attributes of its own.

Groups – A logical grouping of devices. A group can represent a room (e.g. “Living Room”), or any other logical grouping that makes sense to you (e.g. “Outdoor Lights”). Things can be in more than one group at the same time.

Locations – A geographic location that has zero or more SmartHubs. For example a location might be “Home” or “Work”.

Capabilities – A description of the actions that can be performed by a device.

Attributes – A collection of data values that collectively tell us the current state of the device.

SmartThings – A device that is integrated with the SmartThings platform. Why didn’t we call it a SmartDevice? Because the domain name was better this way. So there.

Commands – An instruction to a device to perform one of its capabilities.

Events – A report of a change in or update to one of a device’s attributes.

Standard Events – Events related to standard device types, or the SmartThings Cloud itself.

Custom Events – Custom events generated by SmartApps developers, SmartService developers, or SmartDriver developers.

ThingModule – A Land Grid Array (LGA) module that can be mounted to a Printed Circuit Board (PCB) that has all of the required hardware and firmware to turn a device into a SmartThing.

ThingShield – A ThingModule integrated into an Arduino shield to make it easy to build SmartThings prototypes using Arduino.

Device Type – A device has a specific type in the SmartThings Cloud, e.g. a “Switch” (meaning on-off Switch).

Device Type Bindings – Meta-data instructions that define the capabilities and attributes of a specific type of device.

Dynamic Bindings – Device Type Bindings that can be applied to a ThingModule dynamically to define the capabilities and attributes of the device and allow control of the device through the ThingModule.

SmartDriver – A virtual device driver in the Cloud that sends commands to a SmartThing and generates events on behalf of the SmartThing based on reported attribute changes.

SmartApp – An Internet-of-Things application that does stuff with one or more SmartThings. In its simplest form, a SmartApp is a collection of Event Handlers that are automatically executed when a specific Event (from a device, an external event, etc) occurs.

Preferences – Define the information that is needed by the application at runtime that must be collected from the user in the setting of preferences (in the Smart Phone application)

Modes – A declaration of whether the application should run in all modes or whether the user should enable the application for each available mode.

Event Subscriptions - A set of subscriptions that determines what events will invoke the applications various event handlers.

Event Handlers – The actual code for the various event handlers that will service the events to which the application is subscribed

Application State – Applications will use specific methods/objects in order to persist information into the Application State, which is persisted by the Executor from one instantiation of the application to the next.

Event Wiring – The definition of any application “wiring” which supports the direct wiring of an event (on a specific device) to a specific action on a specific device.

SmartService – A service running in the SmartThings Cloud that provides services to SmartApps. For example, the Twilio SmartThings service provides two-way integration between a SmartApp and Twilio.