iTach Integration

BTW, been meaning to test this and I did and verified the device network parameter is optional.
The device type can’t receive the call back anyway, which is what that parameter is for as far as I know.

Mike,
Are you issuing the hubaction from a smartapp? I have a device defined, let’s say RECEIVER as a SWITCH with the device network id as IP:PORT. I can’t seem to get the switch to fire the event i need in the app to issue the hubaction.

I have been talking specifically talking about using hubAction from within a device type. If you are running the device from a smart app then you’re better off following the service manager strategy.

If you’re trying to get the device type to fire the hub action, get it working first before trying to run the thing from a smart app.

Here’s a working example that I’m working on for my Onkyo…

/**
 *  Onkyo
 *
 *  Copyright 2014 Mike Maxwell
 *
 *  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.
 *
 */

metadata {
	definition (name: "onkyoIP", namespace: "MikeMaxwell", author: "Mike Maxwell") {
		capability "Switch"
        capability "Music Player"
		
		command "makeNetworkId", ["string","string"]
        
	}

	simulator {
		// TODO: define status and reply messages here
	}

	tiles {
		standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
        	state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
        	state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
   		}
        standardTile("mute", "device.switch", inactiveLabel: false, decoration: "flat") {
			state "unmuted", label:"", action:"mute", icon:"st.custom.sonos.unmuted", backgroundColor:"#ffffff", nextState:"muted"
			state "muted", label:"", action:"unmute", icon:"st.custom.sonos.muted", backgroundColor:"#ffffff", nextState:"unmuted"
		}

	}
    main "switch"
    details(["switch","mute"])
}

// 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)
}
//device.deviceNetworkId should be writeable now..., and its not...
def makeNetworkId(ipaddr, port) { 
	 String hexIp = ipaddr.tokenize('.').collect {String.format('%02X', it.toInteger()) }.join() 
     String hexPort = String.format('%04X', port.toInteger()) 
     return "${hexIp}:${hexPort}" 
}
def updated() {
	//device.deviceNetworkId = makeNetworkId(settings.deviceIP,settings.devicePort)	
}
def mute(){
	sendEvent(name: "switch", value: "muted")
	def msg = getEiscpMessage("AMT01")
    def ha = new physicalgraph.device.HubAction(msg,physicalgraph.device.Protocol.LAN )
    return ha
}

def unmute(){
	sendEvent(name: "switch", value: "unmuted")
	def msg = getEiscpMessage("AMT00")
    def ha = new physicalgraph.device.HubAction(msg,physicalgraph.device.Protocol.LAN )
    return ha
}

def on() {
	sendEvent(name: "switch", value: "on")
    def msg = getEiscpMessage("PWR01")
    def ha = new physicalgraph.device.HubAction(msg,physicalgraph.device.Protocol.LAN)
    return ha
}
def off() {
	sendEvent(name: "switch", value: "off")
    def msg = getEiscpMessage("PWR00")
	def ha = new physicalgraph.device.HubAction(msg,physicalgraph.device.Protocol.LAN)
    return ha
}

def getEiscpMessage(command){
  	def sb = StringBuilder.newInstance()
    def eiscpDataSize = command.length() + 2  // 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)
    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()
}

Mike - with some customization for my device type it seems to work from the IDE. Thanks much. Let me see if i can fire it up from a smartapp now. thanks for the help!

Hey Mike, I’ve got a TX-NR626, and being able to integrate it with SmartThings is the last step to automation nirvana.

I need to be able to turn the receiver on/off, as well as turning the second zone on/off. I also need to be able to set source for the primary and secondary zone, and ideally control the volume in each zone as well.

Have you made it any further with the code you were working on? Anywhere close to being able to do what I’m trying to?

I started playing with the code that @Mike_Maxwell posted in here (thanks Mike!). I wouldn’t really call myself a programmer by any stretch, but I’ve cobbled something that works to change inputs, set volume and turn zone 2 on and off (I think, I don’t have Zone 2 speakers right now). Now, it doesn’t read in anything to do with current state as that’s a bit beyond my skills at this point, so the volume slider is always at zero but it does adjust when you move the slider. You can adjust the button labels as I set mine to what they are in my house. If anyone has any suggestions on how to improve, feel free to make adjustment or suggestions as I haven’t got much of a clue on what I’m doing.

1 Like

This certainly SOUNDS like it does what I need, thanks!
I confess to not being sure how to set it up though. I created a device handler using your code, and then created a device and set it to use your handler. How do I point the device to the IP of the receiver though?

You need to set the value of the device network ID to the hex IP and port number. You should give your receiver a static IP to make sure it doesn’t change.

For example, mine is C0A801DE:EAE0 which translates to 192.168.1.222:60128.

If you don’t know how to do that, here’s a website that will convert the IP for you: http://www.miniwebtool.com/ip-address-to-hex-converter/

The port portion EAE0 converts to 60128 which I believe is the default Onkyo port so you can probably leave that as is.

Huh. I set a static IP for the Onkyo, made sure it was actually getting that IP, ran it through the hex converter and used its IP in hex : 60128 (in hex) and still no response with the device. Even ran a port scan against the Onkyo, and it’s definitely listening on 60128. Any other ideas?

No idea. Works for me. Maybe a dumb question, but does the Onkyo app on Android/iOS work for you?

Yup. oRemote app on iOS works as well

Same response for me on my TX NR525. I checked that th NR525 uses the same port, but not sure why its not answering.

I just came across this thread today and decided to give ST integration with my Onkyo receiver a try. I first created a device handler using the Github code and then created a device using this new device handler. I first set the device ID to the hex value from the converter and didn’t get any response either. My receiver IP address is set at 192.168.1.44, and the hex converter provided me the value ‘0xC0A80128’, which didn’t work. However, upon closer inspection I noticed Allan used the hex value ‘C0A801DE’ for the IP address 192.168.1.222. Since the only difference between the IP addresses was the last piece, I compared the hex values and noticed mine had the extra characters ‘0x’ as a prefix. I removed those two characters and voila! I can now perform basic controls of my Onkyo receiver via ST! :grinning:

Just got this working today. Do you have it set up for integrated Github repo updates? Also, have you looked at adding feedback for current status? I’m not a developer either, so I’m impressed with what you’ve done so far. Thanks!