Skip to content
This repository has been archived by the owner on Oct 1, 2021. It is now read-only.

Commit

Permalink
Fixed discovery for Yamaha RX-V481 Receiver (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
brburns authored and balloob committed Mar 8, 2017
1 parent 84a6b1a commit 3d01cb5
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 5 deletions.
17 changes: 13 additions & 4 deletions netdisco/discoverables/yamaha.py
Expand Up @@ -5,14 +5,23 @@
class Discoverable(SSDPDiscoverable):
"""Add support for discovering Yamaha Receivers."""

REMOTE_CONTROL_SPEC_TYPE =\
'urn:schemas-yamaha-com:service:X_YamahaRemoteControl:1'

def info_from_entry(self, entry):
"""Return the most important info from a uPnP entry."""
yam = entry.description['X_device']
services = yam['X_serviceList']['X_service']
if isinstance(services, list):
service = next(
(s for s in services
if s['X_specType'] == self.REMOTE_CONTROL_SPEC_TYPE),
services[0])
else:
service = services
# do a slice of the second element so we don't have double /
ctrlurl = (yam['X_URLBase'] +
yam['X_serviceList']['X_service']['X_controlURL'][1:])
descurl = (yam['X_URLBase'] +
yam['X_serviceList']['X_service']['X_unitDescURL'][1:])
ctrlurl = (yam['X_URLBase'] + service['X_controlURL'][1:])
descurl = (yam['X_URLBase'] + service['X_unitDescURL'][1:])
device = entry.description['device']

return (device['friendlyName'], device['modelName'], ctrlurl, descurl)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -9,5 +9,5 @@
license='Apache License 2.0',
install_requires=['netifaces>=0.10.0', 'requests>=2.0',
'zeroconf==0.17.6'],
packages=find_packages(),
packages=find_packages(exclude=['tests', 'tests.*']),
zip_safe=False)
1 change: 1 addition & 0 deletions tests/__init__.py
@@ -0,0 +1 @@
"""Tests for NetDisco."""
52 changes: 52 additions & 0 deletions tests/discoverables/test_yamaha.py
@@ -0,0 +1,52 @@
"""The tests for discovering Yamaha Receivers."""
import unittest
import xml.etree.ElementTree as ElementTree

from netdisco.discoverables.yamaha import Discoverable
from netdisco.util import etree_to_dict


class MockUPNPEntry(object):
"""UPNPEntry backed by a description file."""

def __init__(self, name):
"""Read and parse a MockUPNPEntry from a file."""
with open('tests/discoverables/yamaha_files/%s' % name,
encoding='utf-8') as content:
self.description = etree_to_dict(
ElementTree.fromstring(content.read())).get('root', {})

class TestYamaha(unittest.TestCase):
"""Test the Yamaha Discoverable."""

def test_info_from_entry_rx_v481(self):
self.assertEqual(
("RX-V481 XXXXXX", "RX-V481",
"http://192.168.XXX.XXX:80/YamahaRemoteControl/ctrl",
"http://192.168.XXX.XXX:80/YamahaRemoteControl/desc.xml"),
Discoverable(None).info_from_entry(
MockUPNPEntry("desc_RX-V481.xml")))

def test_info_from_entry_single_service(self):
self.assertEqual(
("single service friendly name", "single service model name",
"http://192.168.1.2:80/YamahaRemoteControl/single_ctrl",
"http://192.168.1.2:80/YamahaRemoteControl/single_desc.xml"),
Discoverable(None).info_from_entry(
MockUPNPEntry("desc_single_service.xml")))

def test_info_from_entry_multiple_services_remote_control_last(self):
self.assertEqual(
("multi service friendly name", "multi service model name",
"http://192.168.1.2:80/YamahaRemoteControl/multi_ctrl",
"http://192.168.1.2:80/YamahaRemoteControl/multi_desc.xml"),
Discoverable(None).info_from_entry(MockUPNPEntry(
"desc_multiple_services_remote_control_last.xml")))

def test_info_from_entry_multiple_services_no_remote_control(self):
self.assertEqual(
("multi service friendly name", "multi service model name",
"http://192.168.1.2:80/YamahaNewControl/ctrl",
"http://192.168.1.2:80/YamahaNewControl/desc.xml"),
Discoverable(None).info_from_entry(MockUPNPEntry(
"desc_multiple_services_no_remote_control.xml")))
92 changes: 92 additions & 0 deletions tests/discoverables/yamaha_files/desc_RX-V481.xml
@@ -0,0 +1,92 @@
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:yamaha="urn:schemas-yamaha-com:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<device>
<dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMR-1.50</dlna:X_DLNADOC>
<deviceType>urn:schemas-upnp-org:device:MediaRenderer:1</deviceType>
<friendlyName>RX-V481 XXXXXX</friendlyName>
<manufacturer>Yamaha Corporation</manufacturer>
<manufacturerURL>http://www.yamaha.com/</manufacturerURL>
<modelDescription>AV Receiver</modelDescription>
<modelName>RX-V481</modelName>
<modelNumber>V481</modelNumber>
<modelURL>http://www.yamaha.com/</modelURL>
<serialNumber>XXXXXXXX</serialNumber>
<UDN>uuid:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</UDN>
<iconList>
<icon>
<mimetype>image/jpeg</mimetype>
<width>48</width>
<height>48</height>
<depth>24</depth>
<url>/Icons/48x48.jpg</url>
</icon>
<icon>
<mimetype>image/jpeg</mimetype>
<width>120</width>
<height>120</height>
<depth>24</depth>
<url>/Icons/120x120.jpg</url>
</icon>
<icon>
<mimetype>image/png</mimetype>
<width>48</width>
<height>48</height>
<depth>24</depth>
<url>/Icons/48x48.png</url>
</icon>
<icon>
<mimetype>image/png</mimetype>
<width>120</width>
<height>120</height>
<depth>24</depth>
<url>/Icons/120x120.png</url>
</icon>
</iconList>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType>
<serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>
<SCPDURL>/AVTransport/desc.xml</SCPDURL>
<controlURL>/AVTransport/ctrl</controlURL>
<eventSubURL>/AVTransport/event</eventSubURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:RenderingControl:1</serviceType>
<serviceId>urn:upnp-org:serviceId:RenderingControl</serviceId>
<SCPDURL>/RenderingControl/desc.xml</SCPDURL>
<controlURL>/RenderingControl/ctrl</controlURL>
<eventSubURL>/RenderingControl/event</eventSubURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType>
<serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
<SCPDURL>/ConnectionManager/desc.xml</SCPDURL>
<controlURL>/ConnectionManager/ctrl</controlURL>
<eventSubURL>/ConnectionManager/event</eventSubURL>
</service>
</serviceList>
<presentationURL>http://192.168.XXX.XXX/</presentationURL>
</device>
<yamaha:X_device>
<yamaha:X_URLBase>http://192.168.XXX.XXX:80/</yamaha:X_URLBase>
<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_service>
<yamaha:X_specType>
urn:schemas-yamaha-com:service:X_YamahaExtendedControl:1
</yamaha:X_specType>
<yamaha:X_yxcControlURL>/YamahaExtendedControl/v1/</yamaha:X_yxcControlURL>
<yamaha:X_yxcVersion>1131</yamaha:X_yxcVersion>
</yamaha:X_service>
</yamaha:X_serviceList>
</yamaha:X_device>
</root>
@@ -0,0 +1,25 @@
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:yamaha="urn:schemas-yamaha-com:device-1-0">
<device>
<friendlyName>multi service friendly name</friendlyName>
<modelName>multi service model name</modelName>
</device>
<yamaha:X_device>
<yamaha:X_URLBase>http://192.168.1.2:80/</yamaha:X_URLBase>
<yamaha:X_serviceList>
<yamaha:X_service>
<yamaha:X_specType>
urn:schemas-yamaha-com:service:X_YamahaNewControl:1
</yamaha:X_specType>
<yamaha:X_controlURL>/YamahaNewControl/ctrl</yamaha:X_controlURL>
<yamaha:X_unitDescURL>/YamahaNewControl/desc.xml</yamaha:X_unitDescURL>
</yamaha:X_service>
<yamaha:X_service>
<yamaha:X_specType>
urn:schemas-yamaha-com:service:X_YamahaExtendedControl:1
</yamaha:X_specType>
<yamaha:X_yxcControlURL>/YamahaExtendedControl/v1/</yamaha:X_yxcControlURL>
<yamaha:X_yxcVersion>1131</yamaha:X_yxcVersion>
</yamaha:X_service>
</yamaha:X_serviceList>
</yamaha:X_device>
</root>
@@ -0,0 +1,25 @@
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:yamaha="urn:schemas-yamaha-com:device-1-0">
<device>
<friendlyName>multi service friendly name</friendlyName>
<modelName>multi service model name</modelName>
</device>
<yamaha:X_device>
<yamaha:X_URLBase>http://192.168.1.2:80/</yamaha:X_URLBase>
<yamaha:X_serviceList>
<yamaha:X_service>
<yamaha:X_specType>
urn:schemas-yamaha-com:service:X_YamahaExtendedControl:1
</yamaha:X_specType>
<yamaha:X_yxcControlURL>/YamahaExtendedControl/v1/</yamaha:X_yxcControlURL>
<yamaha:X_yxcVersion>1131</yamaha:X_yxcVersion>
</yamaha:X_service>
<yamaha:X_service>
<yamaha:X_specType>
urn:schemas-yamaha-com:service:X_YamahaRemoteControl:1
</yamaha:X_specType>
<yamaha:X_controlURL>/YamahaRemoteControl/multi_ctrl</yamaha:X_controlURL>
<yamaha:X_unitDescURL>/YamahaRemoteControl/multi_desc.xml</yamaha:X_unitDescURL>
</yamaha:X_service>
</yamaha:X_serviceList>
</yamaha:X_device>
</root>
22 changes: 22 additions & 0 deletions tests/discoverables/yamaha_files/desc_single_service.xml
@@ -0,0 +1,22 @@
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:yamaha="urn:schemas-yamaha-com:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<device>
<friendlyName>single service friendly name</friendlyName>
<modelName>single service model name</modelName>
</device>
<yamaha:X_device>
<yamaha:X_URLBase>http://192.168.1.2:80/</yamaha:X_URLBase>
<yamaha:X_serviceList>
<yamaha:X_service>
<yamaha:X_specType>
urn:schemas-yamaha-com:service:X_YamahaRemoteControl:1
</yamaha:X_specType>
<yamaha:X_controlURL>/YamahaRemoteControl/single_ctrl</yamaha:X_controlURL>
<yamaha:X_unitDescURL>/YamahaRemoteControl/single_desc.xml</yamaha:X_unitDescURL>
</yamaha:X_service>
</yamaha:X_serviceList>
</yamaha:X_device>
</root>

0 comments on commit 3d01cb5

Please sign in to comment.