Onkyo Receiver Custom Driver

I'm trying to port my ST DTH for an Onkyo receiver to Hubitat. I've started by replacing every instance of 'physicalgraph' with 'hubitat'. When I click on a device command it shows an event occurred but nothing happens with the receiver. It works with ST, so any thoughts on what I may be missing in Hubitat would be appreciated.

/**
 *  Onkyo IP Control Device Type for Hubitat
 *  Carson Dallum (@cdallum)
 *  Originally based on: Mike Maxwell's and Allan Klein's code
 *
 *  Usage:
 *  1. Be sure you have enabled control of the receiver via the network under the settings on your receiver.
 *  2. Add this code as a device handler in the Hubitat Drivers Code section
 *  3. Create a device using OnkyoIP as the device handler using a hexadecimal representation of IP:port as the device network ID value
 *  For example, a receiver at 192.168.1.222:60128 would have a device network ID of C0A801DE:EAE0
 *  Note: Port 60128 is the default Onkyo eISCP port so you shouldn't need to change anything after the colon
 * 
 *  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.
 *
 * Some future commands that might be useful to incorporate reading:
 * Power Status: PWRQSTN
 * Input Selected: SLIQSTN
 * Volume Level: MVLQSTN (value in hex)
 * Artist Name: NATQSTN
 * Track Name: NTIQSTN
 * Zone 2 Mute: ZMTQSTN
 * Zone 2 Volume: ZVLQSTN
 * Zone 2 Input Selected: SLZQSTN
 * ISCP commands were found at https://github.com/miracle2k/onkyo-eiscp/blob/master/eiscp-commands.yaml
 */

metadata {
	definition (name: "Onkyo Receiver", namespace: "cdallum", author: "Carson Dallum") {
	capability "Switch"
	command "cable"
	command "stb"
	command "pc"
	}
    main "switch"
    details(["switch","cable","stb","pc"])
}

// parse events into attributes
def parse(description) {
    def msg = parseLanMessage(description)
    def headersAsString = msg.header // => headers as a string
    def headerMap = msg.headers      // => headers as a Map
    def body = msg.body              // => request body as a string
    def status = msg.status          // => http status code of the response
    def json = msg.json              // => any JSON included in response body, as a data structure of lists and maps
    def xml = msg.xml                // => any XML included in response body, as a document tree structure
    def data = msg.data              // => either JSON or XML in response body (whichever is specified by content-type header in response)
}

def on() {
	log.debug "Powering on receiver"
	sendEvent(name: "switch", value: "on")
	def msg = getEiscpMessage("PWR01")
	def ha = new hubitat.device.HubAction(msg,hubitat.device.Protocol.LAN)
	return ha
	}

def off() {
	log.debug "Powering off receiver"
	sendEvent(name: "switch", value: "off")
	def msg = getEiscpMessage("PWR00")
	def ha = new hubitat.device.HubAction(msg,hubitat.device.Protocol.LAN)
	return ha
	}

def cable() {
	log.debug "Setting input to Cable"
	def msg = getEiscpMessage("SLI01")
	def ha = new hubitat.device.HubAction(msg,hubitat.device.Protocol.LAN)
	return ha
	}

def stb() {
	log.debug "Setting input to STB"
	def msg = getEiscpMessage("SLI02")
	def ha = new hubitat.device.HubAction(msg,hubitat.device.Protocol.LAN)
	return ha
	}

def pc() {
	log.debug "Setting input to PC"
	def msg = getEiscpMessage("SLI05")
	def ha = new hubitat.device.HubAction(msg,hubitat.device.Protocol.LAN)
	return ha
	}

def getEiscpMessage(command){
	def sb = StringBuilder.newInstance()
	def eiscpDataSize = command.length() + 3  // this is the eISCP data size
	def eiscpMsgSize = eiscpDataSize + 1 + 16  // this is the size of the entire eISCP msg

	/* This is where I construct the entire message
        character by character. Each char is represented by a 2 disgit hex value */
	sb.append("ISCP")
	// the following are all in HEX representing one char

	// 4 char Big Endian Header
	sb.append((char)Integer.parseInt("00", 16))
	sb.append((char)Integer.parseInt("00", 16))
	sb.append((char)Integer.parseInt("00", 16))
	sb.append((char)Integer.parseInt("10", 16))

	// 4 char  Big Endian data size
	sb.append((char)Integer.parseInt("00", 16))
	sb.append((char)Integer.parseInt("00", 16))
	sb.append((char)Integer.parseInt("00", 16))
	// the official ISCP docs say this is supposed to be just the data size  (eiscpDataSize)
	// ** BUT **
	// It only works if you send the size of the entire Message size (eiscpMsgSize)
	// Changing eiscpMsgSize to eiscpDataSize for testing
	sb.append((char)Integer.parseInt(Integer.toHexString(eiscpDataSize), 16))
	//sb.append((char)Integer.parseInt(Integer.toHexString(eiscpMsgSize), 16))

	// eiscp_version = "01";
	sb.append((char)Integer.parseInt("01", 16))

	// 3 chars reserved = "00"+"00"+"00";
	sb.append((char)Integer.parseInt("00", 16))
	sb.append((char)Integer.parseInt("00", 16))
	sb.append((char)Integer.parseInt("00", 16))

	//  eISCP data
	// Start Character
	sb.append("!")

	// eISCP data - unittype char '1' is receiver
	sb.append("1")

	// eISCP data - 3 char command and param    ie PWR01
	sb.append(command)

	// msg end - this can be a few different cahrs depending on you receiver
	// my NR5008 works when I use  'EOF'
	//OD is CR
	//0A is LF
	/*
	[CR]			Carriage Return					ASCII Code 0x0D			
	[LF]			Line Feed						ASCII Code 0x0A			
	[EOF]			End of File						ASCII Code 0x1A			
	*/
	//works with cr or crlf
	sb.append((char)Integer.parseInt("0D", 16)) //cr
	//sb.append((char)Integer.parseInt("0A", 16))

	return sb.toString()
	}
1 Like

Just started to look over the code and I don't have a receiver to test with so...
I'll start by stating that Hubitat doesn't support tiles so I would remove the entire tiles{} section.

Also, did you see this thread?
https://community.hubitat.com/t/app-and-driver-porting-to-hubitat/812

I thought that code looked familar...
I may have a tip or two, let me look at what I have.

The only other thing I have to offer is the link I posted mentioned:

Replace variables beginning with data with device.data

So perhaps replace def data = msg.data with def data = msg.device.data
Other than that, I see that @mike.maxwell has responded so perhaps he will find it if it's not this or the tiles section.

I hope my reference to you in the comments section is enough. If not feel free to provide any suggestions on how to appropriately reference your work. Thanks!

1 Like

I started dinking with my original code in Hubitat over a year ago, and haven't had time to mess with it since.
The good news is that we have a telnet interface, which allows the onkyo to send status updates to the driver without being polled.
The bad news is that the telnet interface isn't well documented yet and I've done nothing more with the driver since getting telnet running on it.
I'll install the driver tomorrow, if it works I'll probably have some info for you.

1 Like

It is, and appreciated!

Other than the clutter the tiles section induces, it will do no harm as we just ignore it. From a sharing and clarity standpoint in hubitats forums its a nice section to remove as drivers are confusing enough for new folks, even without that section...

1 Like

Thanks for the clarification @mike.maxwell
I was going on this post in the App and driver porting to Hubitat topic:

1 Like

Thanks for the recommendations to clean up the Hubitat version of the code. I've updated the code in my original insert above with extraneous sections (e.g. tiles) removed.

Unsolicited onkyo data comming in via our telnet implementation into a telnet enabled driver.
I'll post up some info when I'm able to poke some commands to it. The driver telnet session is connected to the onkyo eiscp port.

3 Likes

Curious if you've had any luck submitting commands via the hub. Thanks!

Curious if anyone has gotten the Onkyo receivers working yet with Hubitat and what specifically you can do with this connection besides turn on or off the receiver? Thanks.

I'd be curious too. I use an Onkyo 555.

I'm wondering if it might allow for a universal "play/pause" command, which could then be used to dim lights. I've fooled around with connecting my Sony TV in the past using some Kodi integration. It worked when I was playing videos from Kodi, but obviously couldn't work if I was using Netflix. I wonder if going directly through the Onkyo receiver would work.

I also have a Remotec remote attached to the wall next to the couch. This can control various lights in the room, and in the past I've had four buttons control Play/pause/forward/backward when using Kodi. This is just for convenience, but it's an example of something else you might do with a connected theater system.

1 Like

If you use onkyo's EISCP protocol which works with our telnet capability, you can do anything the device supports, on,off, mute, read and set volume, change inputs, the lot.
Also when you use telnet, any changes made to the receiver via IR or physical interaction are sent over the telnet connection...

1 Like

Should they also be cautious about multiple telnet connections? Is this confirmed an issue until the fix coming soon (tomorrow?)

Multiple telnet connections (1 from each device) isn't an issue, I have three of them running 24/7
2 for two separate Lutron Pro bridges, and then one for the Onkyo...
Attempting to run multiple telnet connections from the same driver, due to an incorrect implementation?, sure, I can't imagine that would go over well...

1 Like

I noticed the new Onkyo's are advertised on the Onkyo website to have Sonos integration. Looks like if they detect input from a sonos play, they turn themselves on, set the input, and volume to a configured volume so that you can use the Sonos app to control volume! Im thinking about picking up a TX-RZ830

Mike could you please provide an example? I would love to integrate HE with my Denon receiver that also supports a telnet interface. I got it to work in the past via HTTP but I had to poll the receiver for updates.

Does the Dennon support telnet?