Smarter SmartThings with MQTT and Home Assistant

This is a guest post by Home Assistant users Jeremiah Wuenschel and St. John Johnson.

So you own a SmartThings Hub. You probably bought it when you were looking to get into the whole Home Automation hobby because it worked with pretty much everything and offered you the ability to automate anything. After a week of ownership, you realized that building dashboards and automating required writing way more Groovy then you expected. Then one day you were browsing reddit and discovered the amazingness that is Home Assistant! A solution that offered dashboards, graphs, working support for Nest, and REAL EASY automation!

You spent your weekend getting everything set up, showing it off to your significant other, but in the end you got stumped when it came to integrating with all your existing SmartThings toys. What do I do now? Should I buy another hub? Should I just buy a Z-Wave stick?

That’s where we came in. We wanted a solution that can bridge the awesomeness of Home Assistant with the SmartThings hub that works with almost everything.

![](upload://i1cvR7jBrc41AWHCosY4JuLsQax.png)

Glossary

This is going to be a pretty detailed tutorial on setting up our SmartThings bridge. However, there are a couple key terms that might be new to you:

  • MQTT: A lightweight message protocol for listening and publishing events that happen. Many home automation platforms have built in support for this (especially Home Assistant).
  • Docker: A tool for running applications that are self-contained. No need for installing any dependencies or worrying about conflicts. Installs easily on Linux and OSX.

Setting up the Bridge

MQTT

Assuming that you already have Home Assistant and Smart Things running, you will first want to get an MQTT broker running. There are a handful of MQTT brokers available in Open Source land. We chose Mosca for its simplicity.

There is very little you need to do to get Mosca running. The easiest approach is to use Docker, and run a command like the following:

$ docker run \
    -d \
    --name="mqtt" \
    -v /opt/mosca:/db \
    -p 1883:1883 \
    matteocollina/mosca

This will start Mosca up inside of a docker container, while keeping persistent storage for Mosca in /opt/mosca. The default configuration is the only thing we need to get things up and running.

If you don’t want to mess with Docker and can get node.js installed without trouble, the standalone instructions are all you need.

MQTT Bridge

This is the small piece of magic that bridges the gap between MQTT and SmartThings. It is a node.js app, and like Mosca it is probably easiest to install with Docker:

$ docker run \
    -d \
    --name="mqtt-bridge" \
    -v /opt/mqtt-bridge:/config \
    -p 8080:8080 \
    stjohnjohnson/smartthings-mqtt-bridge

The code for this bridge is on Github if you want to start it up independently.

The MQTT Bridge only needs to know where your MQTT broker lives. If you are using these docker commands as-is, edit /opt/mqtt-bridge/config.yml to look like this:

---
mqtt:
    host: <IP of the host>

Restart the bridge, and you are ready to go:

$ docker restart mqtt-bridge

SmartThings Device

The next step (and possibly the most confusing) is the device type. Go to the Smart Things Device IDE and Create New Device Handler. Choose From Code and paste in the MQTT Bridge Device Code. Click Save, Publish, and then For Me.

Now to install your new Device Handler. Go back to My Devices in the IDE, and click New Device. Enter a name, and pick any random set of characters for the Device Network Id (this will automatically update later). For Type, scroll to the bottom of the list and find your newly created MQTT Bridge. Fill in the other boxes however you like.

Go back to My Devices, and click on your new device in the list. This will bring up a page that allows you to edit your device’s Preferences. Click edit and fill in the 3 pieces of information it asks for.

  • MQTT Bridge IP Address: <IP address of the MQTT Bridge from the previous step>
  • MQTT Bridge Port: <8080 if you have changed nothing in the previous commands>
  • MQTT Bridge MAC Address: <Mac address of machine running the Bridge code>

This will create the link between SmartThings and the MQTT Bridge.

SmartThings App

The last step is to setup the SmartApp. After this, any registered devices will start sending their events to MQTT.

Go to the Smart App IDE. Click New SmartApp, followed by From Code. Paste in the MQTT Bridge SmartApp code and click Save. Click Publish and then For Me. In the SmartThings mobile app, add the new SmartApp and configure it with your devices and MQTT Bridge device. Clicking done will subscribe SmartThings to your MQTT broker and begin 2-way propagation of events.

Configure Home Assistant

To add SmartThings devices to Home Assistant over MQTT, first enable MQTT in Home Assistant:

mqtt:
  broker: localhost

Replace localhost with the location of the running MQTT Broker. Devices from the MQTT Bridge are published to the path smartthings/<Device Name>/<Attribute>

For example, my Dimmer Z-Wave Lamp is called “Fireplace Lights” in SmartThings. The following topics are published:

Topic Description smartthings/Fireplace Lights/level Brightness (0-99) smartthings/Fireplace Lights/switch Switch State (on/off)

Here is an example Home Assistant config:

switch:
  platform: mqtt
  name: "Fireplace Lights"
  state_topic: "smartthings/Fireplace Lights/switch"
  command_topic: "smartthings/Fireplace Lights/switch"
  brightness_state_topic: "smartthings/Fireplace Lights/level"
  brightness_command_topic: "smartthings/Fireplace Lights/level"
  payload_on: "on"
  payload_off: "off"
  retain: true

We recommend retain: true for every MQTT device in order to keep states in sync when things become disconnected.

Start digging through the MQTT Components in Home Assistant to find which components map to the new events being published to MQTT.

Configuring with Docker-Compose

Our personal preference for starting the whole suite of software is to use a single Docker-Compose file. Just create a file called docker-compose.yml like this:

mqtt:
    image: matteocollina/mosca
    ports:
        - 1883:1883
mqttbridge:
    image: stjohnjohnson/smartthings-mqtt-bridge
    volumes:
        - ./mqtt-bridge:/config
    ports:
        - 8080:8080
    links:
        - mqtt
homeassistant:
    image: homeassistant/home-assistant:latest
    ports:
        - 80:80
    volumes:
        - ./home-assistant:/config
        - /etc/localtime:/etc/localtime:ro
    links:
        - mqtt

This will start home-assistant, MQTT, and the Bridge, in dependency order. All config can reference the name of the docker container instead of using IP addresses (e.g. mqtt for the broker host in Home Assistant).

How it works

HTTP Endpoint: There are really only 2 ways to communicate with the SmartThings hub that we could find. The easiest approach is to create a RESTful SmartApp authenticated with OAuth that provides state changes via HTTP directly. This approach is pretty straightforward to implement, but it requires communication with the SmartThings cloud service, and can’t be done entirely on your LAN. We hoped to keep all communication internal, and came up with a second approach.

Custom Device Type: SmartThings custom device types allow developers to define handlers for HTTP events received directly over the local network by the SmartThings hub. Messages received are authenticated by MAC address, and can contain arbitrary strings in their payload. Since a Device Type is only ever tied to a single device, we need to add a SmartApp to the mix in order to translate events between individual devices and our special Home Assistant Bridge device. Here is what we have so far:

Z-Wave Switch        |
Zigbee motion sensor |<---> Bridge App <---> Bridge Device Type <---> <Local network>
Z-Wave light bulb    |

On the Home Assistant side, there is a powerful platform available based on the MQTT lightweight message bus protocol. Everything from lights to switches to temperature sensors can be defined in Home Assistant as an MQTT component, so it makes for a convenient integration point. This requires an MQTT broker for handling the message bus, and one last piece to translate between the HTTP that SmartThings supports and MQTT.

Here is the final sequence of events:

![](upload://7MQtggVYjON2BayRSnelERtiens.png) SmartThings Bridge Sequence

There are a lot of stops along the way for these events, but each piece is a simple translation layer to shuttle the events between systems.

Future Improvements

  • Raspberry Pi: There is a lot of interest in getting this running on the Raspberry Pi. It only requires binaries compiled for ARM, so we plan to get ARM-compatible versions of the containers going at some point.
  • Authentication for MQTT: At the moment, the MQTT bridge doesn’t understand how to authenticate to MQTT, so only unauthenticated MQTT is supported. This is mitigated to some degree if you use our Docker Compose config, because MQTT’s port is not actually shared publicly.
  • Authentication for MQTT Bridge: Right now the bridge expects that anyone subscribing is the SmartThings hub. This could use proper authentication.

This is a companion discussion topic for the original entry at https://home-assistant.io/blog/2016/02/09/Smarter-Smart-Things-with-MQTT-and-Home-Assistant/
3 Likes

Hi there,
thanks a lot for this. I was wondering if there is anyway to bypass the ST hub. I want to use RPi and zigbee usb stick and smartthings multisensor.
appreciate if any help could be provided.
Thanks
Ali

@Ali_Kiaie yes you want to use the zha or deconz components.

I am totally new. Trying to decide what is best. I live in Australia so limited on Zwave. My research says smartthings window sensors are very good

How can I monitor a ST Sensor in HA, I tried binary_sensor but does not pick up motion.

Thank you for this. I am working through the instructions and have got to adding a new device on the Smartthings IDE. I have completed the fields as instructed but when I click the CREATE button I get the following error - ‘A Device must have either a Location or a Hub.’ The form is then reset. I have filled in the fields once again but find that there is no way to either enter or select a value for the Location or Hub fields.

Can anyone help?

Thank you

Sorry, my mistake, I had not selected the location and hub in the IDE. Must be the effect of a busy week. It is now working as expected. DOH!

Hello,

Thanks for creating this, I was teetering back and forth of switching over and this made the decision easy. One issue I have, and I think its related to my having the nvidia shield smartthings stick is that the incoming messages are not working. The info panel shows ip/mac/port as all 0 in smartthings so I hardcoded it in the code to no avail.

Data streams from smartthings to the bridge, that all looks good. But when I click a button in home assistant I get:

mqttbridge_1     | info: Incoming message from MQTT: smartthings/Dehumidifier/switch = on
mqttbridge_1     | error: Error from SmartThings Hub: Error: connect ECONNREFUSED 192.168.1.241:39500
mqttbridge_1     | error: {
mqttbridge_1     |     "errno": "ECONNREFUSED",
mqttbridge_1     |     "code": "ECONNREFUSED",
mqttbridge_1     |     "syscall": "connect",
mqttbridge_1     |     "address": "192.168.1.241",
mqttbridge_1     |     "port": 39500
mqttbridge_1     | }
mqttbridge_1     | error:

Anyone know where I should go from here?

Thanks,

looks like the shield is the problem; replacing it with a non-shield.

I’m having one HELL of a time getting this to work. Bought a smarthings hub yesterday, spent all night last night (literally about 7 hours), and the better part of today trying to get this to work. No dice.

I’m running kubernetes, so it’s a little different than docker, but shouldn’t be hard. From what i can see, HA hits the mqtt and bridge, but never makes it to Smartthings, and vice versa (using smart things app doesn’t update HA)

Bridge logs:

Info: Incoming message from SmartThings: smartthings/Front Door Lock/lock = unlocked
info: Incoming message from MQTT: smartthings/Front Door Lock/lock = unlocked
info: Skipping duplicate message from: smartthings/Front Door Lock/lock = unlocked
info: Incoming message from SmartThings: smartthings/Front Door Lock/lock = locked
info: Incoming message from MQTT: smartthings/Front Door Lock/lock = locked
info: Skipping duplicate message from: smartthings/Front Door Lock/lock = locked
info: Incoming message from MQTT: smartthings/Front Door Lock/lock = unlocked
info: Incoming message from MQTT: smartthings/Front Door Lock/lock = locked
error: Error from SmartThings Hub: Error: connect EHOSTUNREACH 192.168.1.88:39500
error: {
    "errno": "EHOSTUNREACH",
    "code": "EHOSTUNREACH",
    "syscall": "connect",
    "address": "192.168.1.88",
    "port": 39500
}
error:
error: Error from SmartThings Hub: Error: connect EHOSTUNREACH 192.168.1.88:39500
error: {
    "errno": "EHOSTUNREACH",
    "code": "EHOSTUNREACH",
    "syscall": "connect",
    "address": "192.168.1.88",
    "port": 39500
}

the changes are me hitting the button lock/unlock in HA

mqtt-bridge config:

mqtt:
# Specify your MQTT Broker's hostname or IP address here
host: 192.168.1.20
# Preface for the topics $PREFACE/$DEVICE_NAME/$PROPERTY
preface: smartthings

# The write and read suffixes need to be different to be able to differentiate when state comes from SmartThings or when its coming from the physical device/application

# Suffix for the topics that receive state from SmartThings $PREFACE/$DEVICE_NAME/$PROPERTY/$STATE_READ_SUFFIX
# Your physical device or application should subscribe to this topic to get updated status from SmartThings
# state_read_suffix: state

# Suffix for the topics to send state back to SmartThings $PREFACE/$DEVICE_NAME/$PROPERTY/$STATE_WRITE_SUFFIX
# your physical device or application should write to this topic to update the state of SmartThings devices that support setStatus
# state_write_suffix: set_state

# Suffix for the command topics $PREFACE/$DEVICE_NAME/$PROPERTY/$COMMAND_SUFFIX
# command_suffix: cmd

# Other optional settings from https://www.npmjs.com/package/mqtt#mqttclientstreambuilder-options
# username: AzureDiamond
# password: hunter2

# Port number to listen on
port: 8080

192.168.1.20 is the ip of the first K8s host, running mosquitto (i tried both in a k8s container but had the same results, so i tried bare metal…no change

my HA “lock.yaml” file

- platform: mqtt
name: "Front Door Lock"
state_topic: "smartthings/Front Door Lock/lock"
command_topic: "smartthings/Front Door Lock/lock"
payload_lock: "locked"
payload_unlock: "unlocked"
retain: true

my HA config

mqtt:
broker: 192.168.1.20
#port: 1883
protocol: 3.1
client_id: home-asssistant-1
keepalive: 60
username: hass
password: password

It seems like both ends work, they just can’t talk in the middle.

I had this problem after I changed my STHub IP. Check state.json in the mqtt-bridge config directory. I just changed the ip to the new one and restarted mqtt-bridge.

It is trying to callback to the hub and can’t.

Are you using the SmartThings “Classic” app with a SmartThings account or are you migrated to a Samsung account and using the “Connect” app. The new Samsung accounts and Connect app crippled SmartThings and does NOT support custom device handlers. Such as the MQTT bridge device handler. You may want to check on the SmartThings community site there’s a lot of noise about the DTH issue and the Samsung conversion.

I’m using the classic app on my phone, but not sure how the phone app affects MQTT bridge and/or smartthings hub?

The app itself doesn’t affect things, however if your account was migrated to the “new” Samsung account then you can’t (currently) use third party SmartApps like the MQTT app. Lots of things over there are breaking with the Samsung account changes.

is there a way to go back to the smartthings account insted of the samsung account?

This writeup seems to focus largely on publishing a SmartThings device to Home Assistant. I’m trying to publish a set of RPi GPIO binary sensors from Home Assistant to SmartThings. Everything is working up to the point where there doesn’t seem to be any device handlers to publish from Home Assistant. Am I correct in thinking this is not possible with the pieces assembled here to date? If it is, I don’t see it.

There appears to be a bug.

The MQTT-Bridge clearly state:
“Suffix for the topics to send state back to SmartThings $PREFACE/$DEVICE_NAME/$PROPERTY/$STATE_WRITE_SUFFIX”
“Suffix for the command topics $PREFACE/$DEVICE_NAME/$PROPERTY/$COMMAND_SUFFIX”

However, if $DEVICE_NAME is something like “thirdbedroom/outlet” nothings gets set in SmartThings as the Device Handler’s events list in the ST IDE says:

MQTT Device message is {“name”:“thirdbedroom”,“command”:true,“value”:“off”,“type”:“outlet”}

Instead of:
MQTT Device message is {“name”:“thirdbedroom/outlet”,“command”:true,“value”:“off”,“type”:“switch”}

If I changed the device name to thirdbedroom.outlet things work fine so it is likely some regex issue. I am not using Home Assistant, so I don’t know if forward slashes are allowed in the names or not.

If the bridge could be made to list the location before the device name as an option, that would be great for my use case. However, I just wanted to post this just in case someone else spends a few hours only to discover this small bug.

Irregardless, this is a very neat project, so please keep up the great work :slight_smile:

I wonder, am I able to connect the HA with Alexa or Google Assistant that run on ST?

I’ve got the bridge installed, all the code in to SmartThings IDE, in the ST app, I’ve selected the bridge, I’ve enabled a couple of switches and motion sensors but HomeAssistant is still saying: “This integration has no devices.”

I can see and control devices that I manually add in configuration.yaml

Any pointers on how to diagnose the failing discovery process?

Did you go into the smartthings app, click on a device, click on SmartApps, then add the device to the Mqtt App?