There are two ways you might control this device:
- UPnP, which doesn't seem to work properly as far any attempt to play music from computer failed.
- YNC (Yamaha network control), unfortunatly I didn't find any official documentation about this protocol from Yamaha, however devices hold this documentation them self, it's basically extension of UPnP.
Bellow is part of UPnP specification showing controlURL and SCPDURL, SCPDURL is path xml definition of function provided by the service. (More on UPnP here)
<yamaha:X_device> <yamaha:X_serviceList> <yamaha:X_service> <yamaha:X_specType>urn:schemas-yamaha-com:service:X_YamahaRemoteControl:1</yamaha:X_specType> <yamaha:X_controlURL>/YamahaRemoteControl/ctrl</yamaha:X_controlURL> <yamaha:X_unitDescURL>/YamahaRemoteControl/desc.xml</yamaha:X_unitDescURL> </yamaha:X_service> </yamaha:X_serviceList> </yamaha:X_device>I also find that somebody collect those and transform them into excel file which, might be more readble here
Here is backup in cause the original link doesn't work.
Based on the specification in picture we created the sample message to increase volume level
<YAMAHA_AV cmd="PUT"> <Main_Zone> <Volume> <Lvl> <Val>Up 1 dB</Val> <Exp></Exp> <Unit></Unit> </Lvl> </Volume> </Main_Zone> </YAMAHA_AV>And here is piece of python code to send it.
#! /usr/bin/python import httplib, urllib import re conn = httplib.HTTPConnection("10.0.0.36:80") xml_data='<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>Up 1 dB</Val><Exp></Exp><Unit></Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>' params = urllib.urlencode({'q': 'set'}) headers = { 'Content-Type': 'application/xml', "Content-Length": "%d" % len(xml_data)} conn.request("POST", "/YamahaRemoteControl/ctrl", "", headers) conn.send(xml_data) response = conn.getresponse() #FOR DEBUG #print response.status, response.reason #print response.read() conn.close()As far as YNC returns XML you can use CSS to display the information return on web, below is python code requesting information about media curently played. As well as CSS code to display it.
HTR-4065_PlayInfo.py
#! /usr/bin/python import sqlite3 import sys import httplib, urllib import re from xml.dom import minidom from xml.parsers.expat import ExpatError conn = httplib.HTTPConnection("10.0.0.36:80") xml_play_info = '<?xml version="1.0" encoding="utf-8"?><YAMAHA_AV cmd="GET"><SERVER><Play_Info<GetParam</Play_Info></SERVER></YAMAHA_AV>' params = urllib.urlencode({'q': 'set'}) headers = { 'Content-Type': 'application/xml', "Content-Length": "%d" % len(xml_play_info)} conn.request("POST", "/YamahaRemoteControl/ctrl", "", headers) conn.send(xml_play_info) response = conn.getresponse() #print response.status, response.reason response_data = response.read() print response_dataHere is the response
<YAMAHA_AV rsp="GET" RC="0"> <SERVER> <Play_Info> <Feature_Availability>Ready</Feature_Availability> <Playback_Info>Play</Playback_Info> <Play_Mode> <Repeat>Off</Repeat> <Shuffle>Off</Shuffle> </Play_Mode> <Meta_Info> <Artist>Enya</Artist> <Album>Paint The Sky With Stars</Album> <Song>Boadicea</Song> </Meta_Info> <Album_ART> <URL>/YamahaRemoteControl/AlbumART/AlbumART.ymf</URL> <ID>243</ID> <Format>YMF</Format> </Album_ART> </Play_Info> </SERVER> </YAMAHA_AV>yncPlayInfo.css
Feature_Availability, Album_ART, Playback_Info {display: none} Meta_Info, Play_Mode {display: block} Meta_Info:before {content: "Currently Playing:"; font-weight: bold} Play_Mode:before {content: "Play mode:"; font-weight: bold} Artist, Album, Song {display: list-item; list-style-type: none} Artist:before {content: "Artist: "; margin-left: 10px; font-weight: bold} Album:before {content: "Album: "; margin-left: 10px; font-weight: bold} Song:before {content: "Song: "; margin-left: 10px; font-weight: bold} Repeat, Shuffle {display: list-item} Repeat:before {content: "Repeat: "; margin-left: 10px; font-weight: bold} Shuffle:before {content: "Shuffle: "; margin-left: 10px; font-weight: bold} menu_status, menu_layer, attribute {display: none} menu_name {font-weight: bold} current_list {display: block} txt {display: list-item; list-style-type: none; margin-left: 10px}