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 hereHere 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_data
Here 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.cssFeature_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}