[WITHDRAWN] Yamaha RX-V Network Receivers

Kristopher, thanks for writing this – it’s exactly what I was looking for. I was wondering if there was any trick to getting the code to be accepted into the “new app” interface – I get this error when submitting. I know you’re not tech support, I was just wondering if there was something obviously wrong. It seems you’re the only one that has written such a comprehensive app for Yamaha receivers…

No signature of method: script1459549364784272445578.metadata() is applicable for argument types: (script1459549364784272445578$_run_closure2) values: [script1459549364784272445578$_run_closure2@3b7e5130] Possible solutions: getMetadata(), getState(), setState(java.lang.Object), metaClass(groovy.lang.Closure)

Are you adding as a device type or smart app? Sounds like you are adding as smart app but this is a device type, you will need to edit the device type preferences with the IP address for your receiver after assigning the device type to a virtual device you setup.

@Motley You’re right, I was trying to add it as a smart app… I’ve added it as a device. Now I just need to find where I can manage it in the app. Thanks for the clarification on this.

I think you will need to add a virtual device by going into the IDE under Devices and manually creating a new device, set the device type to the Yamaha device type that you installed and then once you save that you should see some preferences on the device detail page where you can set the IP data. The virtual device you setup in the IDE will show up in the phone app.

Thanks @Moteley ! I’ll give that a shot.

Thank you! I bought a yamaha 479 (Newegg sale for $299) , because I saw it supported this and DLNA. Works great turning it on and off, but set volume doesn’t work. Perhaps because it’s a newer one and yamaha changed xpath? (saw you mention on github). Could you post the alternate, so I could try that?
Thanks so much!

Hi All,

Thank you very much for all of you who contributed and forked the project. You will ultimately be the ones to carry it forward on ST. Unfortunately, after much deliberation I have decided to pull the project from ST at this time.

Kristopher

1 Like

I used this code to fix my problems. Everything works, and I fixed a bunch of exceptions that I found. Used both the code from top post, as well as the fork for second zone. However, that didn’t work for me, and I hardcoded a lot of that to be main_zone only (I don’t have a 2nd zone).

/**
 *  Yamaha Network Receiver
 *     Works on RX-V*
 *    SmartThings driver to connect your Yamaha Network Receiver to SmartThings
 *
 *  Loosely based on: https://github.com/BirdAPI/yamaha-network-receivers
 *   and: http://openremote.org/display/forums/Controlling++RX+2065+Yamaha+Amp
 */

preferences {
	input("destIp", "text", title: "IP", description: "The device IP")
    input("destPort", "number", title: "Port", description: "The port you wish to connect")
    input("inputChan","enum", title: "Input Control", description: "Select the inputs you want to use", options: ["TUNER","MULTI CH","PHONO","HDMI1","HDMI2","HDMI3","HDMI4","HDMI5","HDMI6","AV1","AV2","AV3","AV4","V-AUX","AUDIO1","AUDIO2","NET","Rhapsody","SIRIUS IR","Pandora","SERVER","NET RADIO","USB","iPod (USB)","AirPlay"],multiple: true,required: true)
    input("Zone","enum", title: "Zone", description: "Select the Zone you want to use", options: ["Main_Zone","Zone_2"],multiple: false,required: true)
}
 

metadata {
	definition (name: "Yamaha Network Receiver2", namespace: "KristopherKubicki", 
    	author: "kristopher@acm.org") {
        capability "Actuator"
	capability "Switch" 
        capability "Polling"
        capability "Switch Level"
        
        attribute "mute", "string"
        attribute "input", "string"
        attribute "inputChan", "enum"

        command "mute"
        command "unmute"
        command "inputSelect", ["string"]
        command "inputNext"
        command "toggleMute"

      	}

	simulator {
		// TODO-: define status and reply messages here
	}
	tiles {
		standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: false, canChangeBackground: true) {
            state "on", label: '${name}', action:"switch.off", backgroundColor: "#79b821", icon:"st.Electronics.electronics16"
            state "off", label: '${name}', action:"switch.on", backgroundColor: "#ffffff", icon:"st.Electronics.electronics16"
        }
		standardTile("poll", "device.poll", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false) {
			state "poll", label: "", action: "polling.poll", icon: "st.secondary.refresh", backgroundColor: "#FFFFFF"
		}
        standardTile("input", "device.input", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false) {
			state "input", label: '${currentValue}', action: "inputNext", icon: "", backgroundColor: "#FFFFFF"
		}
        standardTile("mute", "device.mute", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false) {
            state "muted", label: '${name}', action:"unmute", backgroundColor: "#79b821", icon:"st.Electronics.electronics13"
            state "unmuted", label: '${name}', action:"mute", backgroundColor: "#ffffff", icon:"st.Electronics.electronics13"
		}
        controlTile("level", "device.level", "slider", height: 1, width: 2, inactiveLabel: false, range: "(0..100)") {
			state "level", label: '${name}', action:"setLevel"
		}

		main "switch"
        details(["switch","input","mute","level","poll"])
	}
}



def parse(String description) {
 	def map = stringToMap(description)
    log.debug ("Parse started")
    if(!map.body) { return }
	def body = new String(map.body.decodeBase64())

	def statusrsp = new XmlSlurper().parseText(body)
    log.debug ("Parse got body ${body}...")
	def power = statusrsp.Main_Zone.Basic_Status.Power_Control.Power.text()
    log.debug ("$Zone Power - ${power}")
    if(power == "On") { 
    	sendEvent(name: "switch", value: 'on')
    }
    if(power != "" && power != "On") { 
    	sendEvent(name: "switch", value: 'off')
    }
  
    def inputChan = statusrsp.Main_Zone.Basic_Status.Input.Input_Sel.text()
    log.debug ("$Zone Input - ${inputChan}")
 	if(inputChan != "") { 
    	sendEvent(name: "input", value: inputChan)
	}

    def muteLevel = statusrsp.Main_Zone.Basic_Status.Volume.Mute.text()
    log.debug ("$Zone Mute - ${muteLevel}")
    if(muteLevel == "On") { 
    	sendEvent(name: "mute", value: 'muted')
	}
    if(muteLevel != "" && muteLevel != "On") {
	    sendEvent(name: "mute", value: 'unmuted')
    }

    if(statusrsp.Main_Zone.Basic_Status.Volume.Lvl.Val.text()) { 
    	def int volLevel = statusrsp.Main_Zone.Basic_Status.Volume.Lvl.Val.toInteger() ?: -250        
        volLevel = ((((volLevel + 800) / 9)/5)*5).intValue()
   		def int curLevel = 65
        try {
        	curLevel = device.currentValue("level")
        } catch(NumberFormatException nfe) { 
        	curLevel = 65
        }
        if(curLevel != volLevel) {
           log.debug ("$Zone level - ${volLevel}")
    		sendEvent(name: "level", value: volLevel)
        }
    }

}

// Needs to round to the nearest 5
def setLevel(val) {
	sendEvent(name: "mute", value: "unmuted")     
    sendEvent(name: "level", value: val)
    
    	def scaledVal = (val * 9 - 800).toInteger()//sprintf("%d",val * 9 - 800)
    	scaledVal = (((scaledVal as Integer)/5) as Integer) * 5
    	request("<YAMAHA_AV cmd=\"PUT\"><$Zone><Volume><Lvl><Val>$scaledVal</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></$Zone></YAMAHA_AV>")
}

def on() {
    log.debug "on"
	sendEvent(name: "switch", value: 'on')
	request("<YAMAHA_AV cmd=\"PUT\"><$Zone><Power_Control><Power>On</Power></Power_Control></$Zone></YAMAHA_AV>")
}

def off() {
    log.debug "off"
	sendEvent(name: "switch", value: 'off')
	request("<YAMAHA_AV cmd=\"PUT\"><$Zone><Power_Control><Power>Standby</Power></Power_Control></$Zone></YAMAHA_AV>")
}

def toggleMute(){
    if(device.currentValue("mute") == "muted") { unmute() }
	else { mute() }
}

def mute() { 
	sendEvent(name: "mute", value: "muted")
	request("<YAMAHA_AV cmd=\"PUT\"><$Zone><Volume><Mute>On</Mute></Volume></$Zone></YAMAHA_AV>")
}

def unmute() { 
	sendEvent(name: "mute", value: "unmuted")
	request("<YAMAHA_AV cmd=\"PUT\"><$Zone><Volume><Mute>Off</Mute></Volume></$Zone></YAMAHA_AV>")
}

def inputNext() { 

	def cur = device.currentValue("input")
	// modify your inputs right here! 
    def selectedInputs = ["HDMI1","HDMI2","Pandora","HDMI1"]
    
    
    def semaphore = 0
    for(selectedInput in selectedInputs) {
    	if(semaphore == 1) { 
        	return inputSelect(selectedInput)
        }
    	if(cur == selectedInput) { 
        	semaphore = 1
        }
    }
}


def inputSelect(channel) {
 	sendEvent(name: "input", value: channel	)
    log.debug "Input $channel"
	request("<YAMAHA_AV cmd=\"PUT\"><$Zone><Input><Input_Sel>$channel</Input_Sel></Input></$Zone></YAMAHA_AV>")
}

def poll() { 
	refresh()
}

def refresh() {
    log.debug ("Refresh")
    request("<YAMAHA_AV cmd=\"GET\"><$Zone><Basic_Status>GetParam</Basic_Status></$Zone></YAMAHA_AV>")
}

def request(body) { 

    def hosthex = convertIPtoHex(destIp)
    def porthex = convertPortToHex(destPort)
    device.deviceNetworkId = "$hosthex:$porthex" 

    def hubAction = new physicalgraph.device.HubAction(
   	 		'method': 'POST',
    		'path': "/YamahaRemoteControl/ctrl",
        	'body': body,
        	'headers': [ HOST: "$destIp:$destPort" ]
		) 
        
    hubAction    
        
    hubAction
}


private String convertIPtoHex(ipAddress) { 
    String hex = ipAddress.tokenize( '.' ).collect {  String.format( '%02X', it.toInteger() ) }.join()
    return hex
}

private String convertPortToHex(port) {
	String hexport = port.toString().format( '%04X', port.toInteger() )
    return hexport
}

EDIT: had to also change setlevel so alexa would work to change my volume since she passed doubles or something. Also got code mode to work for easier viewing.

1 Like

@jjoshua2 what do you say to alexa to get her to control the volume? i used your code to get the volume control working (thanks!) but the echo seems to treat the receive as a dimmable light switch, so only commands like “dim the receiver”, or “dim the receiver to 20%” are working. functional, but a little weird.

Thanks for letting me know, and glad to be of service to the community. I say “Alexa, set the receiver to sixty-one”. I made my receiver not go above 0.0 reference since I think 100 would be. You don’t need to use dim or percent (just like lights). Alexa is in the other room, so if I say 60, I think sometimes she hears it as 16.

I couldn’t get it to work with my Onkyo TX-NR525. Surprised that more people are using a smarthings interface to these connected receivers.

It stopped working for me as well. I guess one of ST updates broke it

I’ve got a Yamaha avr 1050 receiver. Is there a chance I can get it to work through Google home and smart things?

I have a harmony hub and I can run all the activities,etc. Id like to be able to adjust the receiver volume and maybe mute it.
Thanks

I’m new to the community. I have a Google Home, Smartthing, and Yamaha RX-V3900 I followed the directions and have created a SmartApp and Device handler, and added the Smartapp Yamaha to a room. I can’t get the app to turn on the receiver or perform any other features. The name is correct and the IP. Any advice would be appreciated. Thanks

how do you invoke input change through Alexa?

I think I made a button so I can say - Alexa, turn on the ps3. That turns on the receiver, changes the input to the ps3 and dims the lights to 10 in that room. I made the button turn off automatically after 60 seconds.

So, when you say make a button, you mean you created a skill or routine in Smartthings? Just learning all this stuff, so just catching up on the lingo.

Volume works great, muting works, powers on and off. Thanks for you work on the device code.

You can add a virtual button in smartthings somehow. And I believe I used rule machine to hook it up to the receiver. I set it all up so long ago I can’t remember anything hardly. I might upgrade my receiver on black friday and have to re-set everything up.

I think I actually used something called av. button on. Under smartapps.
more