Samsung JS9000 Smart TV Integration

Hi All,

I can’t get this TV integration to work via the Samsung Smart TV (connect) smart app. I first had a child object null issue but I seem to of got passed that by manually installing a Samsung smart TV device from a template then when the auto discovery in the smart app scans it finds the TV, I can add it successfully as a device, the correct hex IP values are added etc just none of the commands work and the debugging window doesn’t give much away. Has anyone else managed to successfully connect a JS9000 series tv? (UE65JS9000)

Thanks
Adrian

I don’t remember this being a supported device, what code are you using to get it going? I have the smaller version showing up in a few days, so I’m kinda curious what the 2 can do together.

Hi sidjohn1,

Thanks for getting back to me

I found the code using the smart app from the templates in the ST labs category

> /**
>  *  Copyright 2015 SmartThings
>  *
>  *  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.
>  *
>  *  Samsung TV Service Manager
>  *
>  *  Author: SmartThings (Juan Risso)
>  */

> definition(
> 	name: "Samsung TV (Connect)",
> 	namespace: "smartthings",
> 	author: "SmartThings",
> 	description: "Allows you to control your Samsung TV from the SmartThings app. Perform basic functions like power Off, source, volume, channels and other remote control functions.",
> 	category: "SmartThings Labs",
>     iconUrl: "https://s3.amazonaws.com/smartapp-icons/Samsung/samsung-remote%402x.png",
>     iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Samsung/samsung-remote%403x.png"
> )

> preferences {
> 	page(name:"samsungDiscovery", title:"Samsung TV Setup", content:"samsungDiscovery", refreshTimeout:5)
> }

> def getDeviceType() {
> 	return "urn:samsung.com:device:RemoteControlReceiver:1"
> }

> //PAGES
> def samsungDiscovery()
> {
> 	if(canInstallLabs())
> 	{	
> 		int samsungRefreshCount = !state.samsungRefreshCount ? 0 : state.samsungRefreshCount as int
> 		state.samsungRefreshCount = samsungRefreshCount + 1
> 		def refreshInterval = 3

> 		def options = samsungesDiscovered() ?: []

> 		def numFound = options.size() ?: 0

> 		if(!state.subscribe) {
> 			log.trace "subscribe to location"
> 			subscribe(location, null, locationHandler, [filterEvents:false])
> 			state.subscribe = true
> 		}

> 		//samsung discovery request every 5 //25 seconds
> 		if((samsungRefreshCount % 5) == 0) {
>         	log.trace "Discovering..."
> 			discoversamsunges()
> 		}

> 		//setup.xml request every 3 seconds except on discoveries
> 		if(((samsungRefreshCount % 1) == 0) && ((samsungRefreshCount % 8) != 0)) {
>             log.trace "Verifing..."
> 			verifysamsungPlayer()
> 		}

> 		return dynamicPage(name:"samsungDiscovery", title:"Discovery Started!", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) {
> 			section("Please wait while we discover your Samsung TV. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") {
> 				input "selectedsamsung", "enum", required:false, title:"Select Samsung TV (${numFound} found)", multiple:true, options:options
> 			}
> 		}
> 	}
> 	else
> 	{
> 		def upgradeNeeded = """To use SmartThings Labs, your Hub should be completely up to date.

> To update your Hub, access Location Settings in the Main Menu (tap the gear next to your location name), select your Hub, and choose "Update Hub"."""

> 		return dynamicPage(name:"samsungDiscovery", title:"Upgrade needed!", nextPage:"", install:true, uninstall: true) {
> 			section("Upgrade") {
> 				paragraph "$upgradeNeeded"
> 			}
> 		}
> 	}
> }

> def installed() {
> 	log.trace "Installed with settings: ${settings}"
> 	initialize()
> }

> def updated() {
> 	log.trace "Updated with settings: ${settings}"
> 	unschedule()
> 	initialize()
> }

> def uninstalled() {
> 	def devices = getChildDevices()
> 	log.trace "deleting ${devices.size()} samsung"
> 	devices.each {
> 		deleteChildDevice(it.deviceNetworkId)
> 	}
> }

> def initialize() {
> 	// remove location subscription afterwards
> 	if (selectedsamsung) {
> 		addsamsung()
> 	}
>     //Check every 5 minutes for IP change
> 	runEvery5Minutes("discoversamsunges")
> }

> //CHILD DEVICE METHODS
> def addsamsung() {
> 	def players = getVerifiedsamsungPlayer()
>     log.trace "Adding childs" 
> 	selectedsamsung.each { dni ->
> 		def d = getChildDevice(dni)
> 		if(!d) {
> 			def newPlayer = players.find { (it.value.ip + ":" + it.value.port) == dni }
> 			log.trace "newPlayer = $newPlayer"
> 			log.trace "dni = $dni"
> 			d = addChildDevice("smartthings", "Samsung Smart TV", dni, newPlayer?.value.hub, [label:"${newPlayer?.value.name}"])
> 			log.trace "created ${d.displayName} with id $dni"

> 			d.setModel(newPlayer?.value.model)
> 			log.trace "setModel to ${newPlayer?.value.model}"
> 		} else {
> 			log.trace "found ${d.displayName} with id $dni already exists"
> 		}
> 	}
> }

> private tvAction(key,deviceNetworkId) {
>     log.debug "Executing ${tvCommand}"

> 	def tvs = getVerifiedsamsungPlayer()
> 	def thetv = tvs.find { (it.value.ip + ":" + it.value.port) == deviceNetworkId }

>     // Standard Connection Data
>     def appString = "iphone..iapp.samsung"
>     def appStringLength = appString.getBytes().size()

>     def tvAppString = "iphone.UN60ES8000.iapp.samsung"
>     def tvAppStringLength = tvAppString.getBytes().size()

>     def remoteName = "SmartThings".encodeAsBase64().toString()
>     def remoteNameLength = remoteName.getBytes().size()

>     // Device Connection Data
>     def ipAddress = convertHexToIP(thetv?.value.ip).encodeAsBase64().toString()
>     def ipAddressHex = deviceNetworkId.substring(0,8)
>     def ipAddressLength = ipAddress.getBytes().size()

>     def macAddress = thetv?.value.mac.encodeAsBase64().toString()
>     def macAddressLength = macAddress.getBytes().size()

>     // The Authentication Message
>     def authenticationMessage = "${(char)0x64}${(char)0x00}${(char)ipAddressLength}${(char)0x00}${ipAddress}${(char)macAddressLength}${(char)0x00}${macAddress}${(char)remoteNameLength}${(char)0x00}${remoteName}"
>     def authenticationMessageLength = authenticationMessage.getBytes().size()

>     def authenticationPacket = "${(char)0x00}${(char)appStringLength}${(char)0x00}${appString}${(char)authenticationMessageLength}${(char)0x00}${authenticationMessage}"

>     // If our initial run, just send the authentication packet so the prompt appears on screen
>     if (key == "AUTHENTICATE") {
> 	    sendHubCommand(new physicalgraph.device.HubAction(authenticationPacket, physicalgraph.device.Protocol.LAN, "${ipAddressHex}:D6D8"))
>     } else {
>         // Build the command we will send to the Samsung TV
>         def command = "KEY_${key}".encodeAsBase64().toString()
>         def commandLength = command.getBytes().size()

>         def actionMessage = "${(char)0x00}${(char)0x00}${(char)0x00}${(char)commandLength}${(char)0x00}${command}"
>         def actionMessageLength = actionMessage.getBytes().size()

>         def actionPacket = "${(char)0x00}${(char)tvAppStringLength}${(char)0x00}${tvAppString}${(char)actionMessageLength}${(char)0x00}${actionMessage}"

>         // Send both the authentication and action at the same time
>         sendHubCommand(new physicalgraph.device.HubAction(authenticationPacket + actionPacket, physicalgraph.device.Protocol.LAN, "${ipAddressHex}:D6D8"))
>     }
> }

> private discoversamsunges()
> {
> 	sendHubCommand(new physicalgraph.device.HubAction("lan discovery ${getDeviceType()}", physicalgraph.device.Protocol.LAN))
> }


> private verifysamsungPlayer() {
> 	def devices = getsamsungPlayer().findAll { it?.value?.verified != true }

> 	if(devices) {
> 		log.warn "UNVERIFIED PLAYERS!: $devices"
> 	}

> 	devices.each {
> 		verifysamsung((it?.value?.ip + ":" + it?.value?.port), it?.value?.ssdpPath)
> 	}
> }

> private verifysamsung(String deviceNetworkId, String devicessdpPath) {
> 	log.trace "dni: $deviceNetworkId, ssdpPath: $devicessdpPath"
> 	String ip = getHostAddress(deviceNetworkId)
> 	log.trace "ip:" + ip
> 	sendHubCommand(new physicalgraph.device.HubAction("""GET ${devicessdpPath} HTTP/1.1\r\nHOST: $ip\r\n\r\n""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}"))
> }

> Map samsungesDiscovered() {
> 	def vsamsunges = getVerifiedsamsungPlayer()
> 	def map = [:]
> 	vsamsunges.each {
> 		def value = "${it.value.name}"
> 		def key = it.value.ip + ":" + it.value.port
> 		map["${key}"] = value
> 	}
>     log.trace "Devices discovered $map"
> 	map
> }

> def getsamsungPlayer()
> {
> 	state.samsunges = state.samsunges ?: [:]
> }

> def getVerifiedsamsungPlayer()
> {
> 	getsamsungPlayer().findAll{ it?.value?.verified == true }
> }

> def locationHandler(evt) {
> 	def description = evt.description
> 	def hub = evt?.hubId
> 	def parsedEvent = parseEventMessage(description)
> 	parsedEvent << ["hub":hub] 
>     log.trace "${parsedEvent}"
>     log.trace "${getDeviceType()} - ${parsedEvent.ssdpTerm}"
> 	if (parsedEvent?.ssdpTerm?.contains(getDeviceType()))
> 	{ //SSDP DISCOVERY EVENTS

> 		log.trace "TV found"
> 		def samsunges = getsamsungPlayer()

> 		if (!(samsunges."${parsedEvent.ssdpUSN.toString()}"))
> 		{ //samsung does not exist
>         	log.trace "Adding Device to state..."
> 			samsunges << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
> 		}
> 		else
> 		{ // update the values

> 			log.trace "Device was already found in state..."

> 			def d = samsunges."${parsedEvent.ssdpUSN.toString()}"
> 			boolean deviceChangedValues = false

> 			if(d.ip != parsedEvent.ip || d.port != parsedEvent.port) {
> 				d.ip = parsedEvent.ip
> 				d.port = parsedEvent.port
> 				deviceChangedValues = true
> 				log.trace "Device's port or ip changed..."
> 			}

> 			if (deviceChangedValues) {
> 				def children = getChildDevices()
> 				children.each {
> 					if (it.getDeviceDataByName("mac") == parsedEvent.mac) {
> 						log.trace "updating dni for device ${it} with mac ${parsedEvent.mac}"
> 						it.setDeviceNetworkId((parsedEvent.ip + ":" + parsedEvent.port)) //could error if device with same dni already exists
> 					}
> 				}
> 			}
> 		}
> 	}
> 	else if (parsedEvent.headers && parsedEvent.body)
> 	{ // samsung RESPONSES
>     	def deviceHeaders = parseLanMessage(description, false)
> 		def type = deviceHeaders.headers."content-type" 
> 		def body
> 		log.trace "REPONSE TYPE: $type"
> 		if (type?.contains("xml"))
> 		{ // description.xml response (application/xml)
> 			body = new XmlSlurper().parseText(deviceHeaders.body)
> 			log.debug body.device.deviceType.text()
> 			if (body?.device?.deviceType?.text().contains(getDeviceType()))
> 			{
> 				def samsunges = getsamsungPlayer()
> 				def player = samsunges.find {it?.key?.contains(body?.device?.UDN?.text())}
> 				if (player)
> 				{
> 					player.value << [name:body?.device?.friendlyName?.text(),model:body?.device?.modelName?.text(), serialNumber:body?.device?.serialNum?.text(), verified: true]
> 				}
> 				else
> 				{
> 					log.error "The xml file returned a device that didn't exist"
> 				}
> 			}
> 		}
> 		else if(type?.contains("json"))
> 		{ //(application/json)
> 			body = new groovy.json.JsonSlurper().parseText(bodyString)
> 			log.trace "GOT JSON $body"
> 		}

> 	}
> 	else {
> 		log.trace "TV not found..."
> 		//log.trace description
> 	}
> }

> private def parseEventMessage(String description) {
> 	def event = [:]
> 	def parts = description.split(',')
> 	parts.each { part ->
> 		part = part.trim()
> 		if (part.startsWith('devicetype:')) {
> 			def valueString = part.split(":")[1].trim()
> 			event.devicetype = valueString
> 		}
> 		else if (part.startsWith('mac:')) {
> 			def valueString = part.split(":")[1].trim()
> 			if (valueString) {
> 				event.mac = valueString
> 			}
> 		}
> 		else if (part.startsWith('networkAddress:')) {
> 			def valueString = part.split(":")[1].trim()
> 			if (valueString) {
> 				event.ip = valueString
> 			}
> 		}
> 		else if (part.startsWith('deviceAddress:')) {
> 			def valueString = part.split(":")[1].trim()
> 			if (valueString) {
> 				event.port = valueString
> 			}
> 		}
> 		else if (part.startsWith('ssdpPath:')) {
> 			def valueString = part.split(":")[1].trim()
> 			if (valueString) {
> 				event.ssdpPath = valueString
> 			}
> 		}
> 		else if (part.startsWith('ssdpUSN:')) {
> 			part -= "ssdpUSN:"
> 			def valueString = part.trim()
> 			if (valueString) {
> 				event.ssdpUSN = valueString
> 			}
> 		}
> 		else if (part.startsWith('ssdpTerm:')) {
> 			part -= "ssdpTerm:"
> 			def valueString = part.trim()
> 			if (valueString) {
> 				event.ssdpTerm = valueString
> 			}
> 		}
> 		else if (part.startsWith('headers')) {
> 			part -= "headers:"
> 			def valueString = part.trim()
> 			if (valueString) {
> 				event.headers = valueString
> 			}
> 		}
> 		else if (part.startsWith('body')) {
> 			part -= "body:"
> 			def valueString = part.trim()
> 			if (valueString) {
> 				event.body = valueString
> 			}
> 		}
> 	}
> 	event
> }

> def parse(childDevice, description) {
> 	def parsedEvent = parseEventMessage(description)

> 	if (parsedEvent.headers && parsedEvent.body) {
> 		def headerString = new String(parsedEvent.headers.decodeBase64())
> 		def bodyString = new String(parsedEvent.body.decodeBase64())
> 		log.trace "parse() - ${bodyString}"

> 		def body = new groovy.json.JsonSlurper().parseText(bodyString)
> 	} else {
> 		log.trace "parse - got something other than headers,body..."
> 		return []
> 	}
> }

> private Integer convertHexToInt(hex) {
> 	Integer.parseInt(hex,16)
> }

> private String convertHexToIP(hex) {
> 	[convertHexToInt(hex[0..1]),convertHexToInt(hex[2..3]),convertHexToInt(hex[4..5]),convertHexToInt(hex[6..7])].join(".")
> }

> private getHostAddress(d) {
> 	def parts = d.split(":")
> 	def ip = convertHexToIP(parts[0])
> 	def port = convertHexToInt(parts[1])
> 	return ip + ":" + port
> }

> private Boolean canInstallLabs()
> {
> 	return hasAllHubsOver("000.011.00603")
> }

> private Boolean hasAllHubsOver(String desiredFirmware)
> {
> 	return realHubFirmwareVersions.every { fw -> fw >= desiredFirmware }
> }

> private List getRealHubFirmwareVersions()
> {
> 	return location.hubs*.firmwareVersionString.findAll { it }
> }

However it always failed on line 125 with child device is null until I added a device type which is also in templates.

The smartview app that is a Samsung app and outside of ST is very powerful, it can control via Ethernet and even stream TV picture to phone/pc in excellent quality, but really all I am after is automatic change source and on/off, on maybe an issue if older models are to go by although I have seen an option in the menu that says something like Resume Quicker from Standby so I’m outside hoping this mean WOL or something similar, and change source etc. A bonus would be smart app notifications on the TV itself.

can you post the device code as well? it’s totally not on my list, I’ve checked the ide and the app… and it looks like they are doing some interesting things in the code. @Kristopher is it just me or are they using tcp sockets to communicate to the TV?

I found this as well googling around, the code looks similar, and might work better.

Here’s the device code I am using but for the life of me I can’t find it now in templates. The smart app is still there but no device type (maybe I got it elsewhere I can’t remember now).

    /**
 *  Copyright 2015 SmartThings
 *
 *  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.
 *
 *  Samsung TV
 *
 *  Author: SmartThings (juano23@gmail.com)
 *  Date: 2015-01-08
 */
 
metadata {
	definition (name: "Samsung Smart TV", namespace: "smartthings", author: "SmartThings") {
    		capability "switch" 
            
			command "mute" 
			command "source"
			command "menu"    
            command "tools"           
			command "HDMI"    
            command "Sleep"
            command "Up"
            command "Down"
            command "Left"
            command "Right" 
			command "chup" 
 			command "chdown"               
			command "prech"
			command "volup"    
            command "voldown"           
            command "Enter"
            command "Return"
            command "Exit"
            command "Info"            
            command "Size"
	}

    standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
        state "default", label:'TV', action:"switch.off", icon:"st.Electronics.electronics15", backgroundColor:"#ffffff"
    }
    standardTile("power", "device.switch", width: 1, height: 1, canChangeIcon: false) {
        state "default", label:'', action:"switch.off", decoration: "flat", icon:"st.thermostat.heating-cooling-off", backgroundColor:"#ffffff"
    }    
    standardTile("mute", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Mute', action:"mute", icon:"st.custom.sonos.muted", backgroundColor:"#ffffff"
    }    
	standardTile("source", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Source', action:"source", icon:"st.Electronics.electronics15"
    }
	standardTile("tools", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Tools', action:"tools", icon:"st.secondary.tools"
    }
	standardTile("menu", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Menu', action:"menu", icon:"st.vents.vent"
    }
	standardTile("HDMI", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Source', action:"HDMI", icon:"st.Electronics.electronics15"
    }
    standardTile("Sleep", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Sleep', action:"Sleep", icon:"st.Bedroom.bedroom10"
    }
    standardTile("Up", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Up', action:"Up", icon:"st.thermostat.thermostat-up"
    }
    standardTile("Down", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Down', action:"Down", icon:"st.thermostat.thermostat-down"
    }
    standardTile("Left", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Left', action:"Left", icon:"st.thermostat.thermostat-left"
    }
    standardTile("Right", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Right', action:"Right", icon:"st.thermostat.thermostat-right"
    }  
	standardTile("chup", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'CH Up', action:"chup", icon:"st.thermostat.thermostat-up"
    }
	standardTile("chdown", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'CH Down', action:"chdown", icon:"st.thermostat.thermostat-down"
    }
	standardTile("prech", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Pre CH', action:"prech", icon:"st.secondary.refresh-icon"
    }
    standardTile("volup", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Vol Up', action:"volup", icon:"st.thermostat.thermostat-up"
    }
    standardTile("voldown", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Vol Down', action:"voldown", icon:"st.thermostat.thermostat-down"
    }
    standardTile("Enter", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Enter', action:"Enter", icon:"st.illuminance.illuminance.dark"
    }
    standardTile("Return", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Return', action:"Return", icon:"st.secondary.refresh-icon"
    }
    standardTile("Exit", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Exit', action:"Exit", icon:"st.locks.lock.unlocked"
    }    
    standardTile("Info", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Info', action:"Info", icon:"st.motion.acceleration.active"
    }    
    standardTile("Size", "device.switch", decoration: "flat", canChangeIcon: false) {
        state "default", label:'Picture Size', action:"Size", icon:"st.contact.contact.open"
    }      
    main "switch"
    details (["power","HDMI","Sleep","chup","prech","volup","chdown","mute","voldown", "menu", "Up", "tools", "Left", "Enter", "Right", "Return", "Down", "Exit", "Info","Size"])	
}

def parse(String description) {
	return null
}

def off() {
	log.debug "Turning TV OFF"
    parent.tvAction("POWEROFF",device.deviceNetworkId) 
    sendEvent(name:"Command", value: "Power Off", displayed: true) 
}

def mute() {
	log.trace "MUTE pressed"
    parent.tvAction("MUTE",device.deviceNetworkId) 
    sendEvent(name:"Command", value: "Mute", displayed: true) 
}

def source() {
	log.debug "SOURCE pressed"
    parent.tvAction("SOURCE",device.deviceNetworkId) 
    sendEvent(name:"Command", value: "Source", displayed: true) 
}

def menu() {
	log.debug "MENU pressed"
    parent.tvAction("MENU",device.deviceNetworkId) 
}

def tools() {
	log.debug "TOOLS pressed"
    parent.tvAction("TOOLS",device.deviceNetworkId) 
    sendEvent(name:"Command", value: "Tools", displayed: true)     
}

def HDMI() {
	log.debug "HDMI pressed"
    parent.tvAction("HDMI",device.deviceNetworkId) 
    sendEvent(name:"Command sent", value: "Source", displayed: true)
}

def Sleep() {
	log.debug "SLEEP pressed"
    parent.tvAction("SLEEP",device.deviceNetworkId) 
    sendEvent(name:"Command", value: "Sleep", displayed: true)
}

def Up() {
	log.debug "UP pressed"
    parent.tvAction("UP",device.deviceNetworkId)
}

def Down() {
	log.debug "DOWN pressed"
    parent.tvAction("DOWN",device.deviceNetworkId) 
}

def Left() {
	log.debug "LEFT pressed"
    parent.tvAction("LEFT",device.deviceNetworkId) 
}

def Right() {
	log.debug "RIGHT pressed"
    parent.tvAction("RIGHT",device.deviceNetworkId) 
}

def chup() {
	log.debug "CHUP pressed"
    parent.tvAction("CHUP",device.deviceNetworkId)
    sendEvent(name:"Command", value: "Channel Up", displayed: true)         
}

def chdown() {
	log.debug "CHDOWN pressed"
    parent.tvAction("CHDOWN",device.deviceNetworkId) 
    sendEvent(name:"Command", value: "Channel Down", displayed: true)     
}

def prech() {
	log.debug "PRECH pressed"
    parent.tvAction("PRECH",device.deviceNetworkId)
    sendEvent(name:"Command", value: "Prev Channel", displayed: true)       
}

def Exit() {
	log.debug "EXIT pressed"
    parent.tvAction("EXIT",device.deviceNetworkId) 
}

def volup() {
	log.debug "VOLUP pressed"
    parent.tvAction("VOLUP",device.deviceNetworkId)
    sendEvent(name:"Command", value: "Volume Up", displayed: true)         
}

def voldown() {
	log.debug "VOLDOWN pressed"
    parent.tvAction("VOLDOWN",device.deviceNetworkId) 
    sendEvent(name:"Command", value: "Volume Down", displayed: true)         
}

def Enter() {
	log.debug "ENTER pressed"
    parent.tvAction("ENTER",device.deviceNetworkId) 
}

def Return() {
	log.debug "RETURN pressed"
    parent.tvAction("RETURN",device.deviceNetworkId) 
}

def Info() {
	log.debug "INFO pressed"
    parent.tvAction("INFO",device.deviceNetworkId) 
	sendEvent(name:"Command", value: "Info", displayed: true)    
}

def Size() {
	log.debug "PICTURE_SIZE pressed"
    parent.tvAction("PICTURE_SIZE",device.deviceNetworkId) 
    sendEvent(name:"Command", value: "Picture Size", displayed: true)
}

I did notice that as well, maybe I assumed wrong but as it was similar and older and the one I used was written as a connect app that it was the more appropriate one to use.

I’ll give it a go when I am next near the device

Everything looks OK on the surface at least. I know on some models you have to enable remote management, so you might have to do that here too.

I got them both installed, but since i don’t actually have one yet i get as far as Select Samsung TV (0 found) it should be here by friday to play with more.

Whaaaaaaaaaaaaaaaaaaaaaat?! Need to investigate to see what TV’s this can work on… @AutomateEverything you see this?

I’m using the @NickW version of the app from the link below with success.

If its the remote over IP then yeah ive used it for a while to mute my tv when the doorbell rings n stuff like that

Is that for a JS9000 series TV? think its different software to other sets, new version of Tizen or something like that

Im not sure if mine is the same code, found mine agea ago and tou put in the tvs ip and mac address etc . . . My tv in a 2013 samsung smart 40inch led . . . So not tizen, whats the sifference in apps? What can you do with this you could with the older samsung remote over ip smartapp - im intreagued :slight_smile:

I couldn’t tell you as I haven’t got it working but I think its just the same kind of thing on/off .mute etc, once I’m back home I’ll test the older code by Brad or Nick but I don’t hold out much hope, there’s not even a serial connection on this new set, I feel they are beginning to lock things down more.

I may get out wireshark to see what the smartview app is sending out to control it adn see if it matches the commands sent in the code, there is some PIN based authentication for the smartview app so I am beginning to think this is the reason.

I also installed it and get the same error or at line 125 on both my Samsung TVs. Please share is you find a solution.

Hi Ron,

I found if you install the device type Samsung Smart TV (included in this post) the smart app will then find and detect your TV. The device for me just doesn’t do anything. I believe its to do with some PIN based authentication that has to happen but that’s just a guess at this stage.

I am new to this and I can’t seem to connect my Samsung TV with the Smart TV (Connect) app. It finds my device, but it keeps failing with a “Cannot get property ‘hub’ on null object @ line 126”

I am also unable to install a devicetype with Brad’s file. I always get an error metadata definition not found.

I was just searching for the JS9000 TV integration with ST and found this thread. Does anyone who have samsung JS9000 TV had their TV integration with ST working? I’m unable to detect my JS9000 TV.

I need some help if anyone did this integration successfully.

Thanks in advance.