Kodi/XBMC light control - a (relatively) simple how-to

Ever since discovering SmartThings during the initial Kickstarter event, I’ve been following along as SmartThings has grown from an idea into a robust product.
I bought my first Z-Wave devices two months ago to replace my existing X-10 home automation network and I’ve never looked back.

My biggest issue to date has been trying to find a way to integrate Kodi/XBMC with ST in order to control the lights during media playback.

As a hardware guy with absolutely no development skills, I struggled with this for quite a while before finally figuring it out. While my way may give a true developer the heebiest of jeebies, this is meant to provide an easy method for non-developers to add scripted lighting control to their home theater systems.

My wife has never really seen the value of home automation, and it has always been a struggle for me to justify my various purchases and modifications to the home to her.
We are massive media consumers, so when I got the lights to interface with the movies, she suddenly LOVED the system.

On with the show!

I run Kodi on several Windows systems at home with a centralized shared database. These instructions should work for you even if you are on one of the various linux or embedded distros such as RPi, etc.

You will need the following:
KenV99’s xbmc.callbacks2 service plugin for Kodi/XBMC (based on pilluli’s original callbacks)
wget for Windows (this is included in linux distros for both PC and embedded solutions)
REST Endpoint and the PHP file created by @Ben

Follow the REST Endpoint tutorial, being sure to enable OAuth.
I have discovered that using the hosted PHP file in the tutorial works just fine in order to get the URLs needed to trigger the on/off functionality so you should not need to roll your own. I highly recommend that you do though as you never know when or if the hosted one will suffer from link-rot.

Once you have the REST endpoint created and visiting your PHP shows you the on/off/toggle buttons for the various devices you have authorized, you can move on to the next step.

Install wget for Windows from the link above.

You will need to create a folder on your hard drive to store your scripts.
I placed mine at C:\Batch and all of my files go into this.

Open Notepad (or your favorite editor).
Go back to the PHP site from the REST Tutorial showing all of your devices.
For the devices you would like to turn off when media playback begins, find the device in the PHP site, right click on the Off button, and select Copy Link Address (Chrome) or Copy Shortcut (IE), or the equivalent in any browser you are using.
This will give you a link with the following format: http://graph.api.smartthings.com/api/smartapps/installations/(installation-ID)/switches/(switch-ID)/off?access_token=(access-token)
Note the word Off in the URL. This is the actual command being sent to the device.
Paste the URL into the new text document you have opened in Notepad.
Do the same for any other devices you want to shut off when you hit Play or Resume in Kodi/XBMC, placing each new URL on a separate line.

When you have everything you want in here, save the file to the Scripts folder you created, and name it something like Off.txt.
I have all of my interior lights turn off in this file.

Create a new txt file using the same process, but use the On command buttons to get your links, and label the file as On.txt.
I have only my living room lamps turn on in this file.

Finally, using Notepad or other text editor, create a new file with the following line in it:
“C:\program files (x86)\gnuwin32\bin\wget.exe” --no-check-certificate -i c:\batch\off.txt

What this does: The first part in quotes is the path to the wget executable. This may vary on your system. If you have a Windows 32 bit system, it will be under “C:\Program Files”. The quotes are needed due to spaces in the path.
Linux distributions will not need to use the absolute path, and Windows systems can add this path to the system path variables if desired.
The second part ignores any certificate inconsistencies when requesting the URL in the txt file. I have found this is needed even with http requests.
The third item, -i, tells wget to process a file for commands, and the last is the path to the text file we just created for shutting lights off.
Save this file as moviestart.cmd, being sure that the file does not save as a text file named moviestart.cmd.txt.

Perform the same above steps with the same line of text, only change the path to the txt file to C:\batch\On.txt and save the file as moviestop.cmd

These above steps can be repeated for various control functions, as the next process can control more than just two discreet lighting modes.

Download the xbmc.callbacks2 plugin from the link above. Save the zip file to your hard drive in a location you can find it.
Open Kodi/XBMC, and go to the Settings menu and select the Add-Ons option.
Choose Install from Zip File, and then browse to the downloaded zip file you saved.
When the installation is finished, go back to Add-Ons and select Enabled Add-ons from the list.

Browse to the Services menu item, and look for xbmc.callbacks2 to confirm it is installed.
Select the xbmc.callbacks2 plugin, and select Configure.

Under the Playback menu you’ll see multiple options.
Set the options as follows:
On Playback Started (And the On Playback Resumed option)
Type = Script
Script Executable = C:\Batch\moviestart.cmd (or your path where your files are)
Parameters = blank
Requires Shell? = On

On Playback Stopped (And the On Playback Paused option)
Type = Script
Script Executable = C:\Batch\moviestop.cmd (or your path where your files are)
Parameters = blank
Requires Shell? = On

Click OK at the bottom to save these settings.

If you click the Test Command option after saving the settings, you will see a diagnostic feedback of the script you created running.
Your lights should react as you commanded them to. Click OK on the diagnostics, and go watch a movie.

Note: The .txt and .cmd file creation process will work for a variety of different things… You can make this work however you see fit.

One thing I am trying to figure out, not having development skills, is how to dim lights down and back up rather than perform a hard on/off command. I have yet to figure that out. :frowning:

1 Like

Thank @Synthesis! Will try this for sure. As for Dimming. You can use virtual switches. That way you will only need just one switch to control the level of multiple switches.

Thanks Ray, the problem I’m having is I don’t know the syntax for sending a dim command via the wget URL.
There has to be a way to setLevel via the URL. I’m not sure how a virtual switch would work with that since I still need the ability to setLevel.

It will probably require a few minor changes to the Endpoint Example code, but it shouldn’t be too hard.

If you look at this code by @jody.albritton, it includes dimming ability (and so much more)

Thank you for the response @kevintierney.
Unfortunately, my lack of development skills means I’m completely at a loss on how to do any of the necessary things to make it work.
My current skill level is “Copy/Paste” and that is about it.

Another way to approach the ability to dim lights could be using the Big Switch app that would trigger Hello, Home phrases.

  1. Create a virtual on/off switch in the IDE

  2. Install the following SmartApp

        	name: "The Big Switch HHE",
        	namespace: "smartthings",
        	author: "Ben Goodman",
        	description: "Executes a Hello Home Phrase based on the state of a specific switch.",
        	category: "Convenience",
        	iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/light_outlet.png",
        	iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/light_outlet@2x.png"
        preferences {
        	page(name: "selectPhrases")
        def selectPhrases() {
        	def configured = (settings.HHPhraseOff && settings.HHPhraseOn)
            dynamicPage(name: "selectPhrases", title: "Configure", nextPage:"Settings", uninstall: true) {		
        		section("When this switch is turned on or off") {
        			input "master", "capability.switch", title: "Where?"
        		section("Run These Hello Home Phrases When...") {
        			log.trace phrases
        			input "HHPhraseOn", "enum", title: "The Switch Turns On", required: true, options: phrases, refreshAfterSelection:true
        			input "HHPhraseOff", "enum", title: "The Switch Turns Off", required: true, options: phrases, refreshAfterSelection:true
        def installed(){
        subscribe(master, "switch.on", onHandler)
        subscribe(master, "switch.off", offHandler)
        def updated(){
        subscribe(master, "switch.on", onHandler)
        subscribe(master, "switch.off", offHandler)
        def onHandler(evt) {
        log.debug evt.value
        log.info("Running Light On Event")
        def offHandler(evt) {
        log.debug evt.value
        log.info("Running Light Off Event")

.3. Create a new mode called “Movie Mode” in the mobile app

.4. Create Hello, Home phrase(s) that would be triggered by the SmartApp when XBMC/Kodi starting Playing/Pause/Stop

So when this is all setup it will do the following:

When a movie starts playing in Kodi, the virtual switch will turn on. When the virtual switch turns on, then a Hello, Home phrase will be invoked. The Hello, Home phrase will handle the dimming of the lights and will also put you into “Movie Mode”.

When a movie is stopped in Kodi, the virtual switch will turn off. When the virtual switch turns off, then a Hello, Home phrase will be invoked. The Hello, Home phrase will handle the bring you back into “Home Mode” or whatever other mode you prefer.

You could then setup additional smartapps that would handle dimming levels and restrict them to running only when the mode is Movie Mode.


Here’s an updated version that should work with the command (where XX is the dimmer level)


 *  EndpointEx
 *  Copyright 2015 Kevin Tierney
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
    name: "EndpointEx",
    namespace: "",
    author: "Kevin Tierney",
    description: "Testing Dimmer",
    category: "",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
    iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
    oauth: true)

preferences {
	section("Allow Endpoint to Control These Things...") {
		input "switches", "capability.switch", title: "Which Switches?", multiple: true
        input "locks", "capability.lock", title: "Which Locks?", multiple: true

mappings {

	path("/switches") {
		action: [
			GET: "listSwitches"
	path("/switches/:id") {
		action: [
			GET: "showSwitch"
	path("/switches/:id/:command") {
		action: [
			GET: "updateSwitch"
    path("/switches/:id/:command/:level") {
        action: [
            GET: "updateSwitch"
	path("/locks") {
		action: [
			GET: "listLocks"
	path("/locks/:id") {
		action: [
			GET: "showLock"
	path("/locks/:id/:command") {
		action: [
			GET: "updateLock"


def installed() {}

def updated() {}

def listSwitches() {

def showSwitch() {
	show(switches, "switch")
void updateSwitch() {

def listLocks() {

def showLock() {
	show(locks, "lock")

void updateLock() {

def deviceHandler(evt) {}

private void update(devices) {
	log.debug "update, request: params: ${params}, devices: $devices.id"

	//def command = request.JSON?.command
    def command = params.command
    def level = params.level
    //let's create a toggle option here
	if (command)
		def device = devices.find { it.id == params.id }
		if (!device) {
			httpError(404, "Device not found")
		} else {
        	if(command == "toggle")
            	if(device.currentValue('switch') == "on")
       		} else if (command == "level"){
            } else {

private show(devices, type) {
	def device = devices.find { it.id == params.id }
	if (!device) {
		httpError(404, "Device not found")
	else {
		def attributeName = type == "motionSensor" ? "motion" : type
		def s = device.currentState(attributeName)
		[id: device.id, label: device.displayName, value: s?.value, unitTime: s?.date?.time, type: type]

private device(it, type) {
	it ? [id: it.id, label: it.label, type: type] : null


I get the following error when attempting to set level.

{“error”:true,“type”:“SmartAppException”,“message”:“Not Found”}

If I haven’t already said so, thank you for your help with this. :smile:

I’ll have to give this a try. Thank you for the great documentation!

Hmm, not sure. Did you publish after saving changes? Are you putting this in a browser or some other app?

Yes, I saved then published. Visited the php file from the REST tutorial and authorized devices, then used your link format with my installation ID, switch ID and token in a browser window. This did not work, though the original on/off works without issue.

I’m really not sure then. I just double checked and it worked for me. Make sure you are using the new installation id and access token. From what I can tell that not found error you are getting usually refers to the app id

Did you ever get the dimmer to work? I’m having the same issue with the not found. The on/off works just fine but once I put /level/25 in there then it fails.

@TheFuzz4 I was having the same problem. So I submitted a support ticket. The response is that level is not working and this is a known problem. They believe they have a fix for it and it will be going out in the next firmware release.

Also @Synthesis I may have a simpler solution for this setup. Instead of having to have a text file and a command file. I have installed curl for Windows and I am executing curl commands directly in the command file.

So my command file just has
Curl -h

Can you provide a sanitized copy of your command file and an example of how your config is set up?

My primary HTPC Kodi install went wonky a while back and I have yet to revisit this, though I have my config backed up.
If I can simplify things, then that would be awesome.

So I was able to accomplish what I wanted it to do be it a little messy. Per the other thread I created 3 virtual switches named like Kodi Living Room Play, Pause, Stop. Then I also per the other thread set them up with the smart lights app so that when this switch is called it will adjust the actual light that I want. I also told the app to not turn off.

So then on the Kodi backend I was having issues with calling the python scripts so I just wrote some bash scripts that basically look like this (I tried to use curl but was not getting anywhere with it)

wget http://graph.api.smartthings.com/api/smartapps/installations/(installation ID)/switches/(switch ID)/off?access_token=(access token) && wget http://graph.api.smartthings.com/api/smartapps/installations/(installation ID)/switches/(switch ID)/on?access_token=(access token) 

Ok so now I’m sure that you’re wondering why do I call two wget’s? Well the problem was that once the switch was on it never turned off so if I paused it the lights wouldn’t come up to the pause level. So in each of my scripts I make a call to ensure that the other kodi virtual switch is actually off before turning on the next one.

So in my play script I first make sure that the pause is off

My pause script makes sure that the play is off

My stop script makes sure that my play and pause are off it then turns itself on to bring the lights back to 100% then I have one last wget in there that then turns the stop off as well.

Let me know if this doesn’t make sense :). Basically just make sure that you copy and paste the right URL from each of the virtual switches states that you want it to use into the script.

Here is what the file looks like:

curl https://api.particle.io/v1/devices/your device id here/led \ -d access_token=yuor access token\ -d params=1
curl https://api.particle.io/v1/devices/your device id here/led \ -d access_token=your access token \ -d params=1
curl https://api.particle.io/v1/devices/your device id here/led \ -d access_token=your access token\ -d params=1

Right now I am using it to control home theater sconces and platform lights that are all run off of Particle Photons as documented here:

I will setup the curl commands for smartthings when I get confirmation that the set level command is working properly.

Curl for windows can be picked up here:

Let me know if you have any other questions.


I have refined this a little more as I didn’t like the waterfall effect of lights turning on/off/dimming.

Here is how I set this up:
I have 3 commands that I call from callbacks moviestart.cmd (for start/resume) moviestop.cmd and moviepause.cmd.

For moviestart.cmd now contains the following:

Start /B “moviestartHTPlatform” "C:\Batch\moviestartHTPlatform.cmd"
Start /B “moviestartHTSconce” "C:\Batch\moviestartHTSconce.cmd"
Start /B “moviestartHTSconce2” “C:\Batch\movestartHTSconce2.cmd”

The moviestart.cmd will kick off in the background in parallel the three commands
Within C:\Batch\moviestartHTPlatform.cmd I have placed the curl command from above:
curl https://api.particle.io/v1/devices/your device id here/led \ -d access_token=yuor access token\ -d params=1
One curl command in each .cmd that you want to kick off (for each device).

Thanks for the information.

I’ll likely pick your brain in-depth once setLevel is working, as I’m really hoping to get things moving with this in the near future.

Right now my Kodi install crashes on launch, and I’m not 100% sure why, but haven’t had much desire to investigate either.

Eh, I’ll get it sorted.

I can’t wait till the set level is working. I just added in smart switches over the weekend to my basement so I can dim out the ceiling lights and then drop the level of the wall lights. Sadly the switch app lowest setting is only 10% and well I want to go down to 2% like I do with plex.
I’d also like the the set limit because it will really simplify my setup. Instead of having Kodi make a call to my virtual switch which then calls the smart light app to lower the level, I can just set it with one api call. Would be nice if I could also set a mood with an api call as well.