Battling With Samsung SmartThings IoT: A Lesson In the Importance of Terminology & Lessening The Pain

Battling With Samsung SmartThings IoT: A Lesson In the Importance of Terminology & Lessening The Pain

You've suffered. You've gone round in circles. You've re-read the same page multiple times. You've even drawn it out on a few whiteboards. You've read it again. You've tried to code around it. You've discussed it. Then you came back round and had to study it again. You even gave it your own name to try and make it make sense. No, you're not going crazy. You're like every other SmartThings developer. Welcome.

Many have come before you. Many will come after you.

Let's start at the beginning.

What is SmartThings, And That Hub?

SmartThings is one mega-company's realisation that the next logical step in the web's ascendancy is that ordinary devices and appliances need to be Internet-connected: the fridge, the coffee machine, your car radio, the lights, your blinds, everything. It's that mega-company's attempt to rule, like Sauron in Lord of the Rings.

Internet of Things devices are formalising around 2 lightweight mesh network radio communications standards: Z-Wave (https://z-wavealliance.org/, 1999) and Zigbee (https://zigbeealliance.org/, 2004).  

"Z-Wave is a wireless communications protocol used primarily for home automation. It is a mesh network using low-energy radio waves to communicate from appliance to appliance, allowing for wireless control of residential appliances and other devices, such as lighting control, security systems, thermostats, windows, locks, swimming pools and garage door openers."

https://en.wikipedia.org/wiki/Z-Wave

And...

"Zigbee is an IEEE 802.15.4-based specification for a suite of high-level communication protocols used to create personal area networks with small, low-power digital radios, such as for home automation, medical device data collection, and other low-power low-bandwidth needs, designed for small scale projects which need wireless connection. Hence, Zigbee is a low-power, low data rate, and close proximity (i.e., personal area) wireless ad hoc network."

https://en.wikipedia.org/wiki/Zigbee

The Samsung SmartThings hub is a radio transmitter/receiver for these two protocols you can put in your house which aims to coordinate all your devices, and connect them to the Internet. It does that through an Ethernet or Wifi connection.

The idea: you talk to the hub; it talks to the appliances.

From thereon in, it's a real mess.

Where Do I Start?

SmartThings is actually 6 things. It's a bunch of things for SmartThings which add smartness to your things. Yes, that's why you need to get the language straight in your head.

If only it were actually this simple.


1. Your Samsung account (personal or group/company)

2. Your developer workspace (for creating, debugging, and publishing apps)

3. The documentation and community forums (for sanity)

4. The 2 REST APIs (for device status and commands)

5. A Github repo of public open source cloud drivers:

6. A web-based console/studio (for debugging, publishing handlers etc)

First things first, get a Samsung account. Then register an organisation. Then go and do something else involving alcohol.

Understanding Cloud Drivers

Ask anyone who has been in this mess for a while, and they'll tell you the best way to understand SmartThings is to understand the "Classic" version, as it's become mixed up with the new one. There's some truth to that, but the honest perspective is you're just going to get even more confused.

NB: This isn't the most technically accurate way to describe the way SmartThings actually works, but it's a useful means to conceptualise it when developing.

When you connect and register a new device to your SmartThings hub - for example, a smart lock - it is linked/associated with a "cloud driver". SmartThings chooses this for the device and calls it a "device type handler" (DTH).

Your code is talking to the cloud driver, which in turn is talking to the device. It's a middleman. which is brokering your instructions onto the little device itself.

For example, adding a Yale Smart Lock means it could be assigned this "driver": https://github.com/SmartThingsCommunity/SmartThingsPublic/tree/master/devicetypes/smartthings/zwave-lock.src

All of these are in the public Github repo and written in Apache Groovy, which is a more fun version of Java: https://en.wikipedia.org/wiki/Apache_Groovy.

What you can do with the device is defined by this "driver". Here's the code for the commands lock and unlock you can send to it via the API:

/**
 * Executes lock command on a lock
 */
def lock() {
	log.trace "[DTH] Executing lock() for device ${device.displayName}"
	lockAndCheck(DoorLockOperationSet.DOOR_LOCK_MODE_DOOR_SECURED)
}

/**
 * Executes unlock command on a lock
 */
def unlock() {
	log.trace "[DTH] Executing unlock() for device ${device.displayName}"
	lockAndCheck(DoorLockOperationSet.DOOR_LOCK_MODE_DOOR_UNSECURED)
}

Anyone can write a cloud driver for a device, or assign one - in fact to do that you have to fork their repo (wtf?). The primary place for doing that is the web console (https://graph.api.smartthings.com/ide/devices) which is unhelpfully named an "IDE".

It's obviously not an IDE. It's a dashboard.

First: once you've plugged your devices into the SmartThings hub, go into the web console and make a list of the "driver" each one has been assigned. Find it in the SmartThings Github repo (devicetypes/smartthings folder, .src extension).

Sharing Your Devices With Other People

It took a frustrated call to Samsung Support to work out a problem which a 5 year-old would know the answer to: what if you share a house or office, and you want to give someone else access to the devices there? It's rather tricky, because the Hub is all originally installed under one person's account.

You can quickly do this by sharing/scanning a QR code.

Assuming you both have the SmartThings app on your phones:

  1. The owner needs to go to "Members", and hit "Add Member" --> Generate QR code.
  2. The person who wants access needs to go to "Members" too, and select "Accept Invitation (QR Code)" to scan it in.

Boom. The "location" and its devices appear in the other person's phone.

Note to Samsung: your family aren't "members" of an "organisation".

First Tentative Steps Into Chaos

There's no way around it: you're going to have to read the (very attractive) documentation. Do not despair.

  1. Get the SmartThings app on your phone: https://play.google.com/store/apps/details?id=com.samsung.android.oneconnect&hl=en_US
  2. Link your devices as per instructions. Get familiar with it.
  3. Go to Settings. Press "About SmartThings" for 20 seconds, and restart. That will switch on Developer Mode. Which means absolutely nothing other than it will show your apps from your workspace.
  4. Go to https://graph.api.smartthings.com/ and look around "My Locations" and "My Devices".
  5. Get a personal OAuth2 access token and make some example API calls using Postman or Insomnia: https://account.smartthings.com/tokens

No, there is no web UI for SmartThings itself. It's all done via the phone app. This is a problem, as user orangebucket points out:

"That’s one of the reasons I find it frustrating that the primary UI to SmartThings isn’t web based. With a web based UI you are clearly working with a front end to something. Whatever that something is, you know you aren’t installing stuff in your web browser. When you use a mobile app it can create the illusion that the app itself is more than just a front end and you are creating or installing things in the app itself. You see endless comments about how such and such a device handler or app only works or doesn’t work with the classic app or new app. The apps have become conflated with the backend."

There is also no sandbox.

There is also no emulator.

Ready to dive in?

It's Not An App, It's A Plugin

Imagine this conversation with your boss:

"So we’re building this app, which talks to a smartapp which you install into the SmartThings phone app. It’s kinda like a Facebook app."

Yeah. It's probably a good idea to figure out how to explain this. Your first step is understanding this is wildly over-engineered and over-abstracted.

Can you make out what this is?

A "SmartApp"? It's not an app. It's a plugin. No, really. It's a plugin, for a phone app which has backend webhooks. It kinda looks like a Facebook app because it works in the same way, but it only works within the Samsung SmartThings app you put on your phone. What?

Really?


You're not "installing" anything.

Erick from Samsung support: "You can think of a SmartApp as an interface where you can monitor and customize the behavior of your devices."

According to veteran developer JDRoberts: "SmartApp” is a term inherited from the previous version of the platform when all the customer-contributed code was groovy code that ran in the smartthings cloud."

Nobody seems to know what it is.

This is the "classic" overview. Can you even imagine being in this guy's head?

As forum user orangebucket explains:

The documentation for the Classic environment was incomplete, and worked more like reading chapters in a book. It did sort of tell you stuff, though. The documentation for the ‘new’ environment is a bit all over the place with links flying everywhere and sending you in circles. You have to fluke finding useful stuff and if feels like those building the Developer Workspace and doing the documentation have different ideas on terminology and the architecture.
An example is the ‘SmartApp’. If you use the DevWS the flow starts with device integrations or automations. Device integrations leads you into Schema connections, direct and cloud connected connections using the API (AWS / webhooks), and hub connected devices using the Groovy IDE. Automations is all about AWS / webhooks apps. SmartApps aren’t mentioned.
Yet in the documentation you can find yourself on a SmartApp page and there they say they are AWS / webhook apps for cloud connected devices or automations. Which is just how it always was in the Classic environment. SmartApps were both automations (webCore, Smart Lighting) and connectors (Alexa, Google). In the ‘new app’ UI these got divided up into SmartApps and Connected Services (ideally SmartApps would be called Automations and the built in automation creator would be called something more distinctive).

So SmartApps are:

Classic environment - Automations and connectors (but not Routines).

New app - Automations, but not Automations in the sense of the Automation Creator, and not Connectors.

New documentation - Automations and Connectors, or unheard of, depending on which page you are on.

Developer Workspace - what’s a SmartApp?

As I have said elsewhere. It’s like the ‘new’ environment has been steered in a new direction and not everything has caught up.

A much longer explanation is from JDRoberts again, in historical context: https://community.smartthings.com/t/faq-an-overview-of-using-custom-code-in-smartthings-smartthings-classic/16772

Almost everyone will disagree, and there are plenty of valid reasons from the theory and documentation, but the best way to conceptualise it, for now, is...

A "SmartApp", for all intents and purposes  - nowadays - when it comes to most developers, is a plugin for the SmartThings phone app.

How Do I Find A Device's Capabilities?

The official line from Samsung is a device's capabilities are here: https://smartthings.developer.samsung.com/docs/api-ref/capabilities.html

This is not helpful. This is a list of the possible capabilities, and an attempt by Samsung to standardise them. The web console reports measurements and states, not the required capabilities. SmartThings tells you what capabilities a device can have, but not what your device does have.

Only, it's not. SmartThings "Classic" has a totally different list: https://docs.smartthings.com/en/latest/capabilities-reference.html

To discover your device's capabilities, use the API with a personal access token:

> GET /devices/ HTTP/1.1
> Host: api.smartthings.com
> User-Agent: insomnia/7.1.1
> Authorization: Bearer XXXXX
> Accept: */*

Here's an example for a Soundtouch speaker (GET /devices/{device_id}):

    {
      "deviceId": "[redacted]",
      "name": "Soundtouch",
      "label": "Soundtouch",
      "locationId": "[redacted]",
      "roomId": "[redacted]",
      "deviceTypeId": "[redacted]",
      "deviceTypeName": "LAN Bose SoundTouch",
      "deviceNetworkType": "UNKNOWN",
      "components": [
        {
          "id": "main",
          "label": "Soundtouch",
          "capabilities": [
            {
              "id": "switch",
              "version": 1
            },
            {
              "id": "refresh",
              "version": 1
            },
            {
              "id": "musicPlayer",
              "version": 1
            },
            {
              "id": "healthCheck",
              "version": 1
            },
            {
              "id": "audioNotification",
              "version": 1
            },
            {
              "id": "mediaPresets",
              "version": 1
            }
          ]
        }
      ],
      "dth": {
        "deviceTypeId": "[redacted]",
        "deviceTypeName": "LAN Bose SoundTouch",
        "deviceNetworkType": "UNKNOWN",
        "completedSetup": true,
        "networkSecurityLevel": "UNKNOWN",
        "hubId": "[redacted]"
      },
      "type": "DTH"
    },

What do you notice? musicPlayer , audioNotification and mediaPresets are NOT in the capabilities list. They are morphed into the newer mediaPlayback group.

Official status - "proposed"

Many devices will have packaging advertising things their capabilities don't report, or Samsung does not have in its list.

If the web driver supports them (check the Groovy code), you can (arguably) still use them. Bose, in this example, is reporting different Z-Wave/Zigbee capabilities.

Your devices may not be in sync with SmartThings at all. To find their capabilities, make a GET call to the device's API endpoint. Note them for each.

How Do I Find A Device's Commands?

If you thought capabilities were bad, just wait until you get a load of commands. Commands are essentially calling a function within the cloud driver your device has been associated with.

To save yourself a whole world of pain and lost time, know this: Samsung does not publish a list of a device's functions/commands like they do for capabilities. They provide some.

This code is from the public SmartThings github repo.

To understand what functions/commands you can send to your device, you need to look at the underlying Apache Groovy code of the associated cloud driver - hence why you noted it down earlier. Let's go back to our Z-Wave Lock example here:

https://github.com/SmartThingsCommunity/SmartThingsPublic/blob/master/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy

This is what it is in the "IDE".

According to the SmartThings documentation, there are only 2 functions: lock and unlock. However, this is NOT the case, as we have many others, such as:

  • unlockWithTimeout
  • ping
  • stateCheck
  • refresh
  • poll
  • reloadAllCodes
  • setCodeLength

If we want to program a code into a lock, we can call setCode from line 1334, like so:

> POST /devices/{device_id}/commands HTTP/1.1
> Host: api.smartthings.com
> User-Agent: insomnia/7.1.1
> Content-Type: application/json
> Authorization: Bearer your_access_token
> Accept: */*
> Content-Length: 169

{
	"commands" : [
		{
			"component": "main",
			"capability" : "lockCodes",
      "command": "setCode",
      "arguments": [
        5, "12345","My New Code"
      ]
		}
	]
}

In this example, we are calling the setCode function in the web driver and supplying the 3 arguments we found in the code - an index for the code (5), the code itself (12345), and a name for it ("My New Code").

If we want to remove that code, we can use the deleteCode function from line 1435 just specifying the ID we have it before (5):

> POST /devices/{device_id}/commands HTTP/1.1
> Host: api.smartthings.com
> User-Agent: insomnia/7.1.1
> Content-Type: application/json
> Authorization: Bearer your_access_token
> Accept: */*
> Content-Length: 169

{
	"commands" : [
		{
			"component": "main",
			"capability" : "lockCodes",
      "command": "deleteCode",
      "arguments": [
        5
      ]
		}
	]
}

When issuing a command to a device via the API, the "command" in the JSON is the function in the cloud driver. The arguments are those supplied to the function. To work out what they are, you need to look at the .groovy source code for the driver your device is using.

Pro-Tip: you can get the JSON structure for posts by playing with the API reference docs, which allow you to expand/collapse object syntax.

Ye Who Enter Here: Starting A Project

Whoever came up with the "lifecycle" idea needs a talking to, but they're almost certainly the type of person who could never understand why their idea was bad. The first thing to understand is you can do most things with your own devices via the API with your own personal access token. If you can, avoid working with any of this.

"Deployed to test". How helpful.

Hopefully by now you've made it into the workspace, and created a "SmartApp". These request access to other people's devices. Unless they're your own devices, as SmartThings can't detect you authorising access from your own app, to your own device.

Samsung's thinking here is you are like an Android/iOS developer, and are going to make apps for their SmartThings phone app the way you make them for the entire phone. Why they think this is anyone's guess, as is why they think the SmartThings app is going to take off as an "app store".

It all seems so simple. At least it was to the designer of these graphics, anyway.

You might also be thinking that your "SmartApp" is merely a method of connecting 3rd party devices to your software, as Facebook etc do. Wrong. It's a way of connecting them through Samsung's app. To do anything, the person needs to have their own copy of the SmartThings app, with their own Samsung account. See where this is going?

We we really need to go into what a well-presented mess this is? Why isn't this and the web console the same thing? Is this revenge for Bixby?

Device Integration
Connect a device directly to SmartThings or through another cloud. Allow SmartThings users to access and control the device through the SmartThings app.
Automation for the SmartThings App
Create a SmartApp to automate and orchestrate devices. Make the Automation available on the SmartThings app.

What on earth are you talking about?

This is going to get worse, so strap in. The workspace is so awful it'll give you an idea of what's to come: see if you can switch projects!

An automation is what you generally want. It has a name, ID, client ID, client secret, crypto keypair, scopes, and a callback URL. It exists in "testing" mode or "published".

Github's take on an OAuth app. See why this is confusing?

What does that sound like? Yes, Samsung have "rebranded" OAuth2.  It's a bloody OAuth2 app flow like Facebook, Twitter, Google etc all have. They've just given it a new name. So your OAuth app is to give access to a plugin for a phone app. If you're thinking at this point this whole SmartThings thing isn't worth it, no-one would blame you.

It's like they decided Facebook apps weren't confusing enough and wanted to add their cloud jargon in to make it worse.

Why God, why?

Get into the left column, and under "Test" make sure live logging is enabled. This is the only place to figure out why SmartThings hated your webhook: when it does a POST to your backend app, or tries to process your app's response, it will crash here with validation errors and generally unpredictable chaos.

Good luck understanding it: https://smartthings.developer.samsung.com/docs/workspace/general-tools/logger.html

Don't attempt to put your callback URL in yet. It HAS to exist and response to a challenge code when you try to add it. This is a truly idiotic piece of the ecosystem: you have to understand the "lifecycle" nonsense before you can write code to interact with it, and to interact with it, you need to be able to add a URL and receive POSTs from your Samsung master.

The "Lifecycle" Idea: Oh Dear God

Someone drunk far too much coffee and went on a jihad after reading about state machines. What's a state machine?

"A state machine is a concept used in designing computer programs or digital logic. There are two types of state machines: finite and infinite state machines. The former is comprised of a finite number of states, transitions, and actions that can be modeled with flow graphs, where the path of logic can be detected when conditions are met."

https://en.wikipedia.org/wiki/Finite-state_machine

Sigh.

Is this really necessary for doing webhook callbacks? Really?

Isn't this supposed to simplify the way things work?

Wikipedia gives a nice example to describe a state machine - of a turnstile. One person inserts a token, pushes, and moves through. It resets for the next person. Each turn of the spokes is a state. Kinda. Ish.

Again, can you understand this simplification diagram?

This is an example snippet from the custom OAuth page in the documentation:

"When your SmartApp Connector receives the device list from the third-party device cloud with a GET request, the SmartApp Connector should then issue requests to create a device in SmartThings Cloud for each device in that list."

What. In. The. Hell. Are. You. Talking. About?

For all this jabber, what happens is this: SmartThings makes POSTs to your webhook endpoint in a sequence. They usually break, they give no feedback, and they're very difficult to work with.

For help on these, go to the SmartApps API reference: https://smartthings.developer.samsung.com/docs/api-ref/smartapps-v1.html

  • When you first set your plugin's webhook URL, to test it's responding OK (PING)
  • When it needs to know how to display the pages and form fields your plugin needs, within its own app screens (CONFIGURATION)
  • When it's given your plugin access to the other person's devices, and shows it in their SmartThings app menu (INSTALL)
  • When something changes or a device does something (EVENT).
  • When that person has bought a new device and wants to add it to your plugin  (UPDATE)
  • When they inevitably grow wise and get rid of your plugin (UNINSTALL)
  • Something to do with OAuth nobody quite understands.

These stages don't occur separately. PING happens once, CONFIGURATION and INSTALL happen together as linked sequence, and the others can happen any time at all.

WTF

Why not do this in a web screen where you can preview and test? Nobody knows.

What this means in practice is - and you can watch this in the "Live Logging" console as it goes on:

  1. A user presses your plugin from the "internal store" ("SmartApps" section).
  2. A new screen appears with a spinning wheel, where SmartThings is POSTing to your webhook to retrieve what it should show. If there's a problem, you'll get a useless, uninformative "network error occurred" dialogue. Go to the "Live Logging" console in your workspace to catch the error.
  3. A screen is displayed, with form fields and lists of devices to select. The user fills them out and selects some. They press "next".
  4. A familiar OAuth screen is displayed, explaining the plugin wants to permission to a/b/c. The user again presses "next".
  5. A new screen appears with a spinning wheel, where SmartThings is POSTing to your webhook to give you all the information it has collected.  If there's a problem, you'll get a useless, uninformative "network error occurred" dialogue. Go to the "Live Logging" console in your workspace to catch the error.
  6. The screen returns to the "My SmartApps" list with yours in there.

Samsung do not provide a simulator or a sandbox to develop against, despite how useful it would be.

Log what the POST sends, constantly. Use ngrok for a tunnel to your local code if necessary in the first instance.

So, build your own simulator. Let's say that again: build your own simulator.

Back to Mr orangebucket:

"There is an advantage to having played with device handlers in the ‘classic’ environment. You get to know how stuff is put together and it provides you with a base of knowledge. If I’d started with the ‘new’ documentation and the Developer Workspace I’d have just given up, same I would have done had I started, as recommended, with the ‘new’ app. I was lucky, in a way, that the new app was so demanding of resources that it took me two years before I had a device that could run it.
The Groovy IDE does have a simulator but it is rumoured to be more trouble than it is worth. I’ve never bothered to use it. There are plenty of device handlers for virtual/simulated devices available. How you are supposed to know they exist is another matter."

That's one point, and the second, is watch it happen visually yourself to understand what's going on. Install some plugins into your copy of the SmartThings app to see how it works.

Lifecycle Gotchas That Will Make You Scream

Why God, why? It will become familiar. Do as us Brits do: drink your way through it. You're not the first; and you won't be the last.

  • WHY do you have to develop blind not knowing what SmartThings will POST to your endpoint?
  • WHY isn't there a web UI to design how your plugin will look with the JSON you send back?
  • WHY is OAuth2 being renamed instead of just being OAuth?
  • WHY is there no web dashboard to do this in, and everyone forced to do inside a phone app?
  • WHY do you have to continually "install" and "uninstall"your "SmartApp" when it breaks or doesn't complete its setup?
  • WHY do you have to check the "Live Logging" for the "network error" details when you are in "Developer Mode"?
  • WHY is there no multi-language support?
  • WHY is there no connection between a personal access token and a "SmartApp" access token?
  • WHY is an access token only valid for 5 minutes?
  • WHY are "configuration" and "healthcheck" some form of "capability" you can add during CONFIGURATION?
  • WHY is the documentation so full of mindless abstract jargon and Samsung unable to ever commit to when they will be updating it?
  • WHY is the SmartThings Hub listed as a device you can talk when ... you can't?
  • WHY do you have to delete subscriptions to update them?

There are simple things that just make you want to punch the screen. For example, the documentation:

  • The JSON examples don't work in any JSON linter. They're invalid syntax - e.g. many have trailing commas.
  • The API requires posts as JSON objects, not url-encoded form fields: not a bad thing in itself, but it's not exactly clear.
  • The permissions are wrong: although it might state to include i:deviceprofiles as a scope, the actual one is i:deviceprofiles:* (note the asterisk). That's why configuration screens crash without explanation.
  • The capabilities aren't as stated - many have a status of proposed .
  • Just take a look here: https://community.smartthings.com/t/globe-suite-and-st-integration-is-broken/181888/158

The most important things you want to do as a plugin developer are:

a) Get EVENT postbacks when something happens - in real-time, and
b) Set scheduled tasks to run when something is triggered (e.g. "at 6am, open the blinds, turn on the coffee maker, and play soothing music").

Here's the catch: you can only subscribe to events and schedules during the INSTALL and UPDATE stages. That's because....

A 3rd party "SmartApp" plugin - even yours - has its own access token and refresh token and this is when they are supplied. The access token is only valid for 5 minutes. The refresh token is valid for 30 days, and there is no way to renew a refresh token (page bottom: https://smartthings.developer.samsung.com/docs/auth-and-permissions.html).

No, really.

Even if you are installing a plugin talking to your own devices for which you have a personal access token, there is no interplay between these.

Theoretically, you could just keep refreshing the access token every minute. You have to do with that every 2 weeks with the refresh token or you're screwed.

Once you've been sent the INSTALL payload with the access token, you have 5 minutes to make all your even subscription and schedule calls. Realistically, if you have 10 devices with 3 capabilities each, that's 30 POST requests, and maybe the same number of schedules.

That's great if you're the only user. But the API has a limit of 1 query per second (60ish/minute, see: https://smartthings.developer.samsung.com/docs/rate-limits.html), so just pray 100 people don't add your plugin at the same time.

If a user decides to revoke a permission, it will trigger an UPDATE cycle. Your code to handle the INSTALL event is going to be somewhat duplicated here, so you need to plan accordingly... with a process you've never seen and can't tell what you'll receive in the POST, which you can't add because it does a PING as soon as you want to, to a thing you haven't built.

A Simple Terminology Guide

There's a problem with software engineers when they get too abstract: their descriptions and structure lose all meaning and comprehensibility.

  • (SmartThings) API - one of 2 REST APIs
  • Alcoholism - temporary side-effect of attempting to work with SmartThings
  • Automation - webhook POST to your callback URL
  • Bixby - Samsung's version of Alexa which no human has ever used
  • Capability - something Samsung states a device should say it can do, which other device vendors completely ignore
  • Classic - the first version of SmartThings, which was worse
  • Color Map: a dictionary/list
  • Command - a remote procedure call (RPC) to a horribly-written function found inside a cloud driver
  • Community - internet forum
  • Deployed to Test - not published in Samsung's phone app yet
  • Device Handler - cloud driver
  • Device Profile - totally useless thing you will never use
  • Developer Mode - the SmartThings app showing your workspace projects
  • Dynamic Enum - a list, the same as an enum
  • Ecosystem - the chaos we call our stuff
  • Event - measurement/state
  • Groovy IDE - web console (network explorer) where there's also an obscure section for pasting in Apache Groovy code
  • Lifecycle - a POST request we will send to your callback URL, which will crash on our end
  • Location - your house, where Samsung thinks "members" of an "organisation" live
  • OAuth - something we wish we could just buy, but had to rename instead
  • Publish - make a plugin available in the SmartThings app, for Samsung to be sued
  • Room - something the web console calls a "group", but humans realise has a windows, a roof, and a door
  • Rule - condition (if/then/else, do this)
  • Scene - preset
  • Scope - permission
  • SmartApp - plugin for the Samsung SmartThings phone app
  • SmartThings App - Samsung's free phone app
  • SmartThings Hub - a Z-Wave/Zigbee router
  • Subscription - agreement to send events to your callback URL
  • Therapist - someone tired of hearing about Samsung
  • Unsupported - we haven't written that bit yet
  • Vector3 - a dictionary/list

Rounding Up: How To Do This Without Going Insane

If you have to jump into this madness, heed these tips with your life - particularly if you are on a deadline.

The idea is sound: we'll register devices for you to do all the heavy lifting, and you/your trusted 3rd parties can talk to them via our API. Where Samsung have gone hopelessly wrong with this is putting it all through their SmartThings phone app, not making it simple for developers, and not consolidating their tools.

Credit where credit is due: the SmartThings support guys are nice people, and they are probably doing their best against a slurry of internal politics. They genuinely want to help and believe in the product.

  1. SmartThings is a mess. It's was half-formed in its "Classic" edition, and to be fair, it's better with a REST API. But this one is also half-formed, mixed in with the older half-formed thing.
  2. It looks impressive visually, and shouldn't be a mess because of its maturity, consumer reach, and it being developed by a multi-billion-dollar company.
  3. Samsung are good at making and selling electronics. They are not exactly great at making software or working with developers. They invented Bixby: the assistant nobody wanted, which no-one can get rid of.
  4. It kinda looks like OAuth and social media OAuth apps, but it's not. They've tried to make it like that, but it's gone badly wonky.
  5. The forum is an essential place to get information from people who have already built things. It's like a private club of IoT veterans who are on their way to being a secret society.
  6. Start by understanding Z-Wave/Zigbee, and what the SmartThings Hub is trying to do.
  7. Go on to studying the idea of "cloud drivers" ("device type handlers") written in Apache Groovy, and how they work.
  8. Realise there is a serious problem with jargon terminology and engineers who have gone completely over the top with abstraction. There's going to be a cognitive load which is higher than usual.
  9. This is all done through their phone app. Use it, install some plugins ("SmartApps") and get a feel for how it's put together. Get to know the app as an expert: members, organisations, "scenes", etc and more.
  10. Get a list of a device's capabilities through the REST API, and the list of available commands/functions through its cloud driver (Groovy source code).
  11. You have an access token, and your plugin has one. Yours is a normal type, and the plugin's makes no sense at all. Yours can't subscribe to events and schedules; the plugin's can't create "scenes", If in doubt, drink.
  12. The "lifecycle" where your code needs to receive POST callbacks is hacky. Aim to build a local "simulator" for it, rather than a script or some other spaghetti. You need a bot to simulate what SmartThings is sending, so your code can be unit-testable and ready to deploy.
  13. Similarly, aim to build your responses to the POST callbacks as a reusable library you can configure for multiple apps. You're essentially doing content management, and there is a lot of duplication.
  14. Keep an eye on the "Live Logging" in your workspace to find out what on earth is going on at the remote end.
  15. Remember to refresh your plugin's refresh tokens.

Dear Samsung, Can't We Just Get Along?

The idea of SmartThings is phenomenal. The reliability of it is good. The people behind it are ambitious and well-meaning. The developer community are more patient than any other.

How can this thing be such a mess?

You can't just s**t all over a platform you like or are invested in without doing it the courtesy of suggesting improvements you should also equally take the same degree of s**t for.

  1. Decide whether you like developers or not. The first step is admitting you have a problem;
  2. Ditch the phone app "plugin store" idea and go with a web-centered UI;
  3. Consolidate all the "tools" (for lack of a better word) into a single online "studio";
  4. Completely revise and simplify the concepts and terminology;
  5. If you're going with OAuth, standardise with it other platforms so it's easy to cross over (hint: access token lifetimes);
  6. Provide a REST sandbox (see Twilio and Stripe);
  7. Provide a REST emulator (or a local testing suite);
  8. Reward your incredibly loyal developer forum members (of which the author is NOT one), who should have run away a long time ago;
  9. Integrate with the larger open-source network, such as OpenHAB;
  10. Invest in providing simple, human-friendly tutorials for the humans trying to work out what they should humanly do with your technology platform.

It's like that quintessential break-up cliche: it's not you, it's me. That's all you need to know that it really it is ... you.