Code Monkey home page Code Monkey logo

upnpclient's Introduction

Build Status

uPnPclient

uPnP client library for Python 3.

This library can be used to discover and consume uPnP devices and their services.

It's originally based on Ferry Boender's work and his blog post entitled Exploring UPnP with Python.

Installation

pip install upnpclient

Usage

Typical usage:

In [1]: import upnpclient

In [2]: devices = upnpclient.discover()

In [3]: devices
Out[3]: 
[<Device 'OpenWRT router'>,
 <Device 'Harmony Hub'>,
 <Device 'walternate: root'>]

In [4]: d = devices[0]

In [5]: d.WANIPConn1.GetStatusInfo()
Out[5]: 
{'NewConnectionStatus': 'Connected',
 'NewLastConnectionError': 'ERROR_NONE',
 'NewUptime': 14851479}

In [6]: d.WANIPConn1.GetNATRSIPStatus()
Out[6]: {'NewNATEnabled': True, 'NewRSIPAvailable': False}

In [7]: d.WANIPConn1.GetExternalIPAddress()
Out[7]: {'NewExternalIPAddress': '123.123.123.123'}

If you know the URL for the device description XML, you can access it directly.

In [1]: import upnpclient

In [2]: d = upnpclient.Device("http://192.168.1.1:5000/rootDesc.xml")

In [3]: d.services
Out[3]: 
[<Service service_id='urn:upnp-org:serviceId:Layer3Forwarding1'>,
 <Service service_id='urn:upnp-org:serviceId:WANCommonIFC1'>,
 <Service service_id='urn:upnp-org:serviceId:WANIPConn1'>]

In [4]: d.Layer3Forwarding1.actions
Out[4]: 
[<Action 'SetDefaultConnectionService'>,
 <Action 'GetDefaultConnectionService'>]

In [5]: d.Layer3Forwarding1.GetDefaultConnectionService()
Out[5]: {'NewDefaultConnectionService': 'uuid:46cb370a-d7f2-490f-ac01-fb0db6c8b22b:WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1'}

Sometimes the service or action name isn't a valid property name. In which case, service and actions can be accessed other ways:

In [1]: d["Layer3Forwarding1"]["GetDefaultConnectionService"]()
Out[1]: {'NewDefaultConnectionService': 'uuid:46cb370a-d7f2-490f-ac01-fb0db6c8b22b:WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1'}

To view the arguments required to call a given action:

In [1]: d.WANIPConn1.AddPortMapping.argsdef_in
Out[1]: 
[('NewRemoteHost',
  {'allowed_values': set(), 'datatype': 'string', 'name': 'RemoteHost'}),
 ('NewExternalPort',
  {'allowed_values': set(), 'datatype': 'ui2', 'name': 'ExternalPort'}),
 ('NewProtocol',
  {'allowed_values': {'TCP', 'UDP'},
   'datatype': 'string',
   'name': 'PortMappingProtocol'}),
 ('NewInternalPort',
  {'allowed_values': set(), 'datatype': 'ui2', 'name': 'InternalPort'}),
 ('NewInternalClient',
  {'allowed_values': set(), 'datatype': 'string', 'name': 'InternalClient'}),
 ('NewEnabled',
  {'allowed_values': set(),
   'datatype': 'boolean',
   'name': 'PortMappingEnabled'}),
 ('NewPortMappingDescription',
  {'allowed_values': set(),
   'datatype': 'string',
   'name': 'PortMappingDescription'}),
 ('NewLeaseDuration',
  {'allowed_values': set(),
   'datatype': 'ui4',
   'name': 'PortMappingLeaseDuration'})]

and then to call the action using those arguments:

In [1]: d.WANIPConn1.AddPortMapping(
   ...:     NewRemoteHost='0.0.0.0',
   ...:     NewExternalPort=12345,
   ...:     NewProtocol='TCP',
   ...:     NewInternalPort=12345,
   ...:     NewInternalClient='192.168.1.10',
   ...:     NewEnabled='1',
   ...:     NewPortMappingDescription='Testing',
   ...:     NewLeaseDuration=10000)
Out[1]: {}

Similarly, the arguments you can expect to receive in response are listed:

In [1]: d.WANIPConn1.GetGenericPortMappingEntry.argsdef_out
Out[1]: 
[('NewRemoteHost',
  {'allowed_values': set(), 'datatype': 'string', 'name': 'RemoteHost'}),
 ('NewExternalPort',
  {'allowed_values': set(), 'datatype': 'ui2', 'name': 'ExternalPort'}),
 ('NewProtocol',
  {'allowed_values': {'TCP', 'UDP'},
   'datatype': 'string',
   'name': 'PortMappingProtocol'}),
 ('NewInternalPort',
  {'allowed_values': set(), 'datatype': 'ui2', 'name': 'InternalPort'}),
 ('NewInternalClient',
  {'allowed_values': set(), 'datatype': 'string', 'name': 'InternalClient'}),
 ('NewEnabled',
  {'allowed_values': set(),
   'datatype': 'boolean',
   'name': 'PortMappingEnabled'}),
 ('NewPortMappingDescription',
  {'allowed_values': set(),
   'datatype': 'string',
   'name': 'PortMappingDescription'}),
 ('NewLeaseDuration',
  {'allowed_values': set(),
   'datatype': 'ui4',
   'name': 'PortMappingLeaseDuration'})]

HTTP Auth/Headers

You may pass a requests compatible authentication object and/or a dictionary containing headers to use on the HTTP calls to your uPnP device.

These may be set on the Device itself on creation for use with every HTTP call:

device = upnpclient.Device(
    "http://192.168.1.1:5000/rootDesc.xml"
    http_auth=('myusername', 'mypassword'),
    http_headers={'Some-Required-Header': 'somevalue'}
)

Or on a per-call basis:

device.Layer3Forwarding1.GetDefaultConnectionService(
    http_auth=('myusername', 'mypassword'),
    http_headers={'Some-Required-Header': 'somevalue'}
)

If you've set either at Device level, they can be overridden per-call by setting them to None.

upnpclient's People

Contributors

fboender avatar flyte avatar kolpa avatar maiermic avatar rytilahti avatar smailee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

upnpclient's Issues

feat: record the IP of the interface that receive the SSDP discover response

I find this is useful when I am working on a project that is to stream resources on my PC to DLNA supported TV. In this case I need to know the IP address of my PC which is accessible by the TV.

The IP address can be find in ssdp.scan but it was dropped in the current implementation. A simple modification can make it work and I would like to send a PR to support this feature.

Activity of this project

Hello guys and especially @flyte

Lately I experimented with UPnP stuff and found this library which already does a lot of stuff I needed.
Sadly the project seems a little bit stalled, the last official release was at the beginning of 2018 (!) and code improvements are very rare.
I found quite a few bugs and weird code choices in the current develop branch of this project and have to ask the question if this project is currently, actively maintained?

I would love to tackle some issues and bugs in this project, but if this repository is basically dead, I would just develop stuff on my own fork of this project and create my own PIP entry.

Long story short: What is the future of this project?

No newer releases than 0.0.8 on PyPi

According to Github this package has a 1.0.2 release, but the latest one on PyPi is 0.0.8. Please update the PyPi package.

Also, setup.py seems to have dissapeared so I'm not sure how this should now be installed.

EDIT: Never mind I figured out how to install this thing. For any future distro packagers:

poetry build --format wheel
pip install --isolated --root="<location to install>" --ignore-installed --no-deps dist/*.whl

brainstorming. possible suggestions.

I just found this library after I had already spent some time building one. It appears as tho there is not a whole lot out there for UPNP for python. Not sure as to why.

I thought you may want to have a look at what I have done thus far. I didn't see any place that specifically dealt with any vendor xml name spaces. did you do anything to handle this? I am not sure as to how to parse for namespaces other then just doing string searching. I do not know if there is a better way or not.

maybe you would be willing to have a look see and if there is something I have missed you can point it out. I think my biggest thing at this point are the schemas.

https://github.com/kdschlosser/UPNP_Device

I did add a nice little printout that can display any part of the UPNP structure by simply printing that part. or you can print out the whole thing as well.

code is as simple as this

import UPNP_Device

for device in UPNP_Device.discover(timeout=3):
    print(device)

Timeouts in Infinite Loop when Discovering

Firstly, thanks for taking the time to write this great library!

I'm not sure if this is a bug or not, but I followed Ferry Boender's original tutorial and discovered two UPNP devices on my network. However, an infinite loop occurs when I use this library:

import upnpclient


devices = upnpclient.discover()
print(devices)
Error fetching description at http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.120', port=8080): Max retries exceeded with url: /description.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103063978>, 'Connection to 192.168.1.120 timed out. (connect timeout=10)'))' for http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.120', port=8080): Max retries exceeded with url: /description.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103089ba8>, 'Connection to 192.168.1.120 timed out. (connect timeout=10)'))' for http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.120', port=8080): Max retries exceeded with url: /description.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x1031ed2b0>, 'Connection to 192.168.1.120 timed out. (connect timeout=10)'))' for http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.120', port=8080): Max retries exceeded with url: /description.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x1031ed978>, 'Connection to 192.168.1.120 timed out. (connect timeout=10)'))' for http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.120', port=8080): Max retries exceeded with url: /description.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103a0e080>, 'Connection to 192.168.1.120 timed out. (connect timeout=10)'))' for http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.120', port=8080): Max retries exceeded with url: /description.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x1031edcc0>, 'Connection to 192.168.1.120 timed out. (connect timeout=10)'))' for http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.120', port=8080): Max retries exceeded with url: /description.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x1031ed6a0>, 'Connection to 192.168.1.120 timed out. (connect timeout=10)'))' for http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.120', port=8080): Max retries exceeded with url: /description.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x1013aa860>, 'Connection to 192.168.1.120 timed out. (connect timeout=10)'))' for http://192.168.1.120:8080/description.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x1030899e8>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103063710>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103a0e780>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103063f28>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x1030898d0>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103089fd0>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103a0e240>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103a670b8>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103a67780>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103a67e48>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103089dd8>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x1030637b8>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103a677b8>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml
Error 'HTTPConnectionPool(host='192.168.1.1', port=2555): Max retries exceeded with url: /upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103a920b8>, 'Connection to 192.168.1.1 timed out. (connect timeout=10)'))' for http://192.168.1.1:2555/upnp/f541be8e-de74-32a1-8d5b-9a03a85ccd5d/desc.xml

example from README.md does not run

I use Debian GNU/Linux 9.4 (stretch), cloned upnpclient and installed packets following requirements.txt. As said in README.md the library is running with Python 2 and Python 3, so I installed both versions:

~$ git clone https://github.com/flyte/upnpclient.git
~$ sudo apt install --install-recommends python-requests
~$ sudo apt install --install-recommends python3-requests
~$ sudo apt install --install-recommends python-six
~$ sudo apt install --install-recommends python3-six
~$ pip3 install netdisco
~$ sudo apt install --install-recommends python-dateutil
~$ sudo apt install --install-recommends python3-dateutil
~$ sudo apt install --install-recommends python-lxml
~$ sudo apt install --install-recommends python3-lxml

Now tried to use the first example with python3:

~$ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
>>> import upnpclient
>>> devices = upnpclient.discover()
Error 'empty namespace prefix is not supported in ElementPath' for http://192.168.10.119:49153/nmrDescription.xml
Error 'empty namespace prefix is not supported in ElementPath' for http://192.168.10.119:49153/nmrDescription.xml
Error 'empty namespace prefix is not supported in ElementPath' for http://192.168.10.119:49153/nmrDescription.xml
[...]

And many more lines like that.

Trying python 2 I get this:

~$ python
Python 2.7.13 (default, Nov 24 2017, 17:33:09)
>>> import upnpclient
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "upnpclient/__init__.py", line 143, in <module>
    from upnpclient import const, errors, marshal, soap, ssdp, upnp, util  # noqa: F401
  File "upnpclient/ssdp.py", line 1, in <module>
    from netdisco.ssdp import scan
ImportError: No module named netdisco.ssdp
>>>

I want to use python3. How can I fix the error messages?

Travis build fails for Python 2.7

In Python 2.7 netdisco version 1.5.0 is installed, which seems to be missing its requirement netifaces, which leads to a build error in Travis

ImportError while importing test module '/home/travis/build/maiermic/upnpclient/tests/test_upnpclient.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_upnpclient.py:15: in <module>
    import upnpclient as upnp
upnpclient/__init__.py:143: in <module>
    from upnpclient import const, errors, marshal, soap, ssdp, upnp, util  # noqa: F401
upnpclient/ssdp.py:1: in <module>
    from netdisco.ssdp import scan
.tox/py27/lib/python2.7/site-packages/netdisco/ssdp.py:11: in <module>
    from netdisco.util import etree_to_dict, interface_addresses
.tox/py27/lib/python2.7/site-packages/netdisco/util.py:4: in <module>
    import netifaces
E   ImportError: No module named netifaces

ValueError: empty namespace prefix is not supported in ElementPath

Hello, I want to open port by UPnP.

import upnpclient
print(upnpclient.Device("http://192.168.1.1:8000/Public_UPNP_gatedesc.xml"))

I use softbank rooter.
I try to open port. but, xml error occur.

Traceback (most recent call last):
  File "C:\Users\aaa\PycharmProjects\nem-chatto\test_upnp.py", line 7, in <module>
    devices = [upnpclient.Device("http://192.168.3.1:8000/Public_UPNP_gatedesc.xml")]
  File "C:\Users\aaa\Anaconda3\lib\site-packages\upnpclient\upnp.py", line 102, in __init__
    self.device_type = findtext('device/deviceType')
  File "src\lxml\lxml.etree.pyx", line 1550, in lxml.etree._Element.findtext (src\lxml\lxml.etree.c:58721)
  File "C:\Users\aaa\Anaconda3\lib\site-packages\lxml\_elementpath.py", line 306, in findtext
    el = find(elem, path, namespaces)
  File "C:\Users\aaa\Anaconda3\lib\site-packages\lxml\_elementpath.py", line 288, in find
    it = iterfind(elem, path, namespaces)
  File "C:\Users\aaa\Anaconda3\lib\site-packages\lxml\_elementpath.py", line 277, in iterfind
    selector = _build_path_iterator(path, namespaces)
  File "C:\Users\aaa\Anaconda3\lib\site-packages\lxml\_elementpath.py", line 234, in _build_path_iterator
    raise ValueError("empty namespace prefix is not supported in ElementPath")
ValueError: empty namespace prefix is not supported in ElementPath

I read error message. I check what make error.
I find findtext() (lxml) do not work correctly.
The error do not occur on Linux, only on Windows.
What is wrong?

SOAP argument order is important

I have an IGD that expects the AppPortMapping arguments to be in the same order as listed in argsdef_in. However, upnpclient can mix them up. As a result, my IGD returns error 402 (invalid args) and an HTTP Status of 500.

I've verified this by capturing/taking the POST that upnpclient generates, fixing the argument order (and changing nothing else), and sending this modified POST request. It works perfectly.

installation error with command: `pip3 install upnpclient`

When I try to install, an error comes out:

user-home{~}:pip3 install upnpclient
Collecting upnpclient
  Downloading https://files.pythonhosted.org/packages/d9/6d/a0ae6fe6886152e0fd3dee74dfa4f86eb497b88ccb611c410ea9b7065b6f/uPnPClient-0.0.8.tar.gz
Collecting requests (from upnpclient)
  Downloading https://files.pythonhosted.org/packages/45/1e/0c169c6a5381e241ba7404532c16a21d86ab872c9bed8bdcd4c423954103/requests-2.24.0-py2.py3-none-any.whl (61kB)
    100% |████████████████████████████████| 71kB 876kB/s 
Collecting six (from upnpclient)
  Downloading https://files.pythonhosted.org/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl
Collecting netdisco (from upnpclient)
  Downloading https://files.pythonhosted.org/packages/0b/92/6c5de8c7607a3a9c39cf600a961328b2efa9ad93bd60be61f7816d4cafc9/netdisco-2.7.1-py3-none-any.whl (46kB)
    100% |████████████████████████████████| 51kB 2.6MB/s 
Collecting python-dateutil (from upnpclient)
  Downloading https://files.pythonhosted.org/packages/d4/70/d60450c3dd48ef87586924207ae8907090de0b306af2bce5d134d78615cb/python_dateutil-2.8.1-py2.py3-none-any.whl (227kB)
    100% |████████████████████████████████| 235kB 1.7MB/s 
Collecting lxml (from upnpclient)
  Downloading https://files.pythonhosted.org/packages/55/6f/c87dffdd88a54dd26a3a9fef1d14b6384a9933c455c54ce3ca7d64a84c88/lxml-4.5.1-cp36-cp36m-manylinux1_x86_64.whl (5.5MB)
    100% |████████████████████████████████| 5.5MB 279kB/s 
Collecting certifi>=2017.4.17 (from requests->upnpclient)
  Downloading https://files.pythonhosted.org/packages/5e/c4/6c4fe722df5343c33226f0b4e0bb042e4dc13483228b4718baf286f86d87/certifi-2020.6.20-py2.py3-none-any.whl (156kB)
    100% |████████████████████████████████| 163kB 2.7MB/s 
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests->upnpclient)
  Downloading https://files.pythonhosted.org/packages/e1/e5/df302e8017440f111c11cc41a6b432838672f5a70aa29227bf58149dc72f/urllib3-1.25.9-py2.py3-none-any.whl (126kB)
    100% |████████████████████████████████| 133kB 2.5MB/s 
Collecting chardet<4,>=3.0.2 (from requests->upnpclient)
  Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 2.9MB/s 
Collecting idna<3,>=2.5 (from requests->upnpclient)
  Downloading https://files.pythonhosted.org/packages/89/e3/afebe61c546d18fb1709a61bee788254b40e736cff7271c7de5de2dc4128/idna-2.9-py2.py3-none-any.whl (58kB)
    100% |████████████████████████████████| 61kB 3.1MB/s 
Collecting zeroconf>=0.27.1 (from netdisco->upnpclient)
  Downloading https://files.pythonhosted.org/packages/27/83/7ccfd01d25576a370640bf7fcf9d040f201b0309f945f668b07ffc171bf5/zeroconf-0.27.1-py3-none-any.whl (50kB)
    100% |████████████████████████████████| 51kB 9.5MB/s 
Collecting ifaddr (from zeroconf>=0.27.1->netdisco->upnpclient)
  Downloading https://files.pythonhosted.org/packages/92/0f/a577a724c03982b800232713874e805c8fcc14f4a2c3060902ed20b50da8/ifaddr-0.1.7-py2.py3-none-any.whl
Building wheels for collected packages: upnpclient
  Running setup.py bdist_wheel for upnpclient ... error
  Complete output from command /usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-mxvi9dau/upnpclient/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" bdist_wheel -d /tmp/tmpwbfy_i_mpip-wheel- --python-tag cp36:
  WARNING: The wheel package is not available.
  usage: -c [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
     or: -c --help [cmd1 cmd2 ...]
     or: -c --help-commands
     or: -c cmd --help
  
  error: invalid command 'bdist_wheel'
  
  ----------------------------------------
  Failed building wheel for upnpclient
  Running setup.py clean for upnpclient
Failed to build upnpclient
Installing collected packages: certifi, urllib3, chardet, idna, requests, six, ifaddr, zeroconf, netdisco, python-dateutil, lxml, upnpclient
  Running setup.py install for upnpclient ... done
Successfully installed certifi-2020.6.20 chardet-3.0.4 idna-2.9 ifaddr-0.1.7 lxml-4.5.1 netdisco-2.7.1 python-dateutil-2.8.1 requests-2.24.0 six-1.15.0 upnpclient-0.0.8 urllib3-1.25.9 zeroconf-0.27.1

image

Class for statevars and argsdef as dict

What do you think about a class for representing statevars?
Currently they are just a dict in another dict Service.statevars

And another related wish:
Statevars are held in argsdef_in and argsdef_out as a list of tuples of arg_name and the actual statevar.
Would you mind if I change argsdef_in and _out to dictionaries of { arg_name: statevar }
This would make processing of an action result simpler (currently I have to convert the argsdef_out to a dict first).

space before urn ' urn:microsoft-com:wmc-1-0' is not a valid URI

When I run:

import upnpclient as upnp
devices = upnp.discover()

I get these errors regarding my Marantz SR5008:

Error 'xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40 (<string>, line 4)' for http://192.168.1.xxx:8080/description.xml
Error 'xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40 (<string>, line 4)' for http://192.168.1.xxx:8080/description.xml
Error 'xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40 (<string>, line 4)' for http://192.168.1.xxx:8080/description.xml
Error 'xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40 (<string>, line 4)' for http://192.168.1.xxx:8080/description.xml
Error 'xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40 (<string>, line 4)' for http://192.168.1.xxx:8080/description.xml
Error 'xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40 (<string>, line 4)' for http://192.168.1.xxx:8080/description.xml

If I then run devices, I do get a list summing up some devices I have on my network but the Marantz is not in there, probably because of those errors mentioned above....

If I look at http://192.168.1.xxx:8080/description.xml I get the following XML:

<?xml version="1.0"?>
<root
  xmlns="urn:schemas-upnp-org:device-1-0"
  xmlns:ms=" urn:microsoft-com:wmc-1-0"
  xmlns:smsc="www.smsc.com"
  xmlns:qq="http://www.tencent.com"
  xmlns:pnpx="http://schemas.microsoft.com/windows/pnpx/2005/11"
  xmlns:df="http://schemas.microsoft.com/windows/2008/09/devicefoundation">
	<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>
		<pnpx:X_compatibleId>MS_DigitalMediaDeviceClass_DMR_V001
				</pnpx:X_compatibleId>
		<pnpx:X_deviceCategory>MediaDevices
				</pnpx:X_deviceCategory>
		<pnpx:X_hardwareId>VEN_0126&amp;DEV_0022&amp;REV_01
				</pnpx:X_hardwareId>
		<df:X_deviceCategory>Multimedia.DMR
				</df:X_deviceCategory>
		<deviceType>urn:schemas-upnp-org:device:MediaRenderer:1</deviceType>
		<friendlyName>?</friendlyName>
		<manufacturer>Marantz</manufacturer>
		<manufacturerURL>http://www.marantz.com</manufacturerURL>
		<modelDescription>AV SURROUND RECEIVER</modelDescription>
		<modelName>*SR5008</modelName>
		<modelNumber>5008</modelNumber>
		<modelURL>http://www.marantz.com</modelURL>
		<serialNumber>?</serialNumber>
		<UDN>?</UDN>
		<UPC>?</UPC>
		<iconList>
			<icon>
				<mimetype>image/jpeg</mimetype>
				<width>48</width>
				<height>48</height>
				<depth>24</depth>
				<url>/BCO_device_sm_icon.jpg</url>
			</icon>
			<icon>
				<mimetype>image/jpeg</mimetype>
				<width>120</width>
				<height>120</height>
				<depth>24</depth>
				<url>/BCO_device_lrg_icon.jpg</url>
			</icon>
			<icon>
				<mimetype>image/png</mimetype>
				<width>48</width>
				<height>48</height>
				<depth>24</depth>
				<url>/BCO_device_sm_icon.png</url>
			</icon>
			<icon>
				<mimetype>image/png</mimetype>
				<width>120</width>
				<height>120</height>
				<depth>24</depth>
				<url>/BCO_device_lrg_icon.png</url>
			</icon>
		</iconList>
		<serviceList>
			<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/evt</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/evt</eventSubURL>
			</service>
			<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/evt</eventSubURL>
			</service>
		</serviceList>
		<presentationURL>http://192.168.1.xxx</presentationURL>
	</device>
</root>

Note that I replaced IP with xxx and some unimportant info with ?

I am pretty sure the problem is the space " " in the urn in line 4:
xmlns:ms=" urn:microsoft-com:wmc-1-0"

Does anyone have an idea how to fix this?

Remove netdisco dependancy?

It seems that it's deprecated. Would it make sense to just copy and paste the relevant parts in? It's not much code, and I'd imagine it's not going to get any updates.

Discovery Timeout Doesn't Work In All Cases

I have a handful of Sonos equipment, which under normal circumstances is discoverable almost immediately. However, every once in a while, a Sonos device will "crash", whereupon it disappears from the Sonos app. When this happens, the device is still pingable, but any HTTP requests to port 1400 (HTTP) or 1443 (HTTPS) just time out.

Further, upnpclient.discover() starts taking about 5 minutes to complete (even calling it with discover(1) will take the same amount of time). Some sleuthing shows that it is repeatedly trying to contact the dead Sonos device, with the wrong timeout:

2022-04-07 14:40:32,475 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fda00>
2022-04-07 14:40:42,489 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fda30>
2022-04-07 14:40:52,504 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fda60>
2022-04-07 14:41:02,524 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fda90>
2022-04-07 14:41:12,544 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdac0>
2022-04-07 14:41:29,772 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdaf0>
2022-04-07 14:41:39,787 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdb20>
2022-04-07 14:41:49,839 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdb50>
2022-04-07 14:41:59,859 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdb80>
2022-04-07 14:42:09,878 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdbb0>
2022-04-07 14:42:19,897 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdbe0>
2022-04-07 14:42:29,917 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdc10>
2022-04-07 14:42:39,937 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdc40>
2022-04-07 14:42:49,951 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdc70>
2022-04-07 14:42:59,965 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdca0>
2022-04-07 14:43:09,971 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdcd0>
2022-04-07 14:43:19,982 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdd00>
2022-04-07 14:43:29,997 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdd30>
2022-04-07 14:43:40,018 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdd60>
2022-04-07 14:43:50,036 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fdd90>
2022-04-07 14:44:00,054 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fddc0>
2022-04-07 14:44:10,068 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fddf0>
2022-04-07 14:44:20,083 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fde20>
2022-04-07 14:44:30,097 - ssdp - ERROR - Error 'HTTPConnectionPool(host='10.20.1.227', port=1400): Read timed out. (read timeout=10)' for <upnpclient.ssdp.Entry object at 0xb10fde50>

After the above, it seems to give up and discovery completes with anything else that was found, but not the troublesome Sonos device. In short, it works correctly, but does not honour its timeout (note the about 4 minutes, where the default timeout is 5 seconds).

If I reboot the Sonos device, it re-appears in the Sonos app, and discover() starts working correctly again.

Travis build fails for Python 3.4

Running pip install upnpclient in a fresh Python 3.4.* environment tries to install lxml version 4.4.0 (as requirement), but

This lxml version requires Python 2.7, 3.5 or later.

Hence, the Travis build (of branch develop) fails for Python 3.4 in the meantime.

exception due to whitespace in text of tags

For example, whitespace in relatedStateVariable tag

<argument xmlns="urn:schemas-upnp-org:service-1-0">
		    <name>pairingDeviceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>
                       A_ARG_TYPE_pairingDeviceID
                    </relatedStateVariable>
		</argument>

causes KeyError when its text is used as key (see upnpclient/upnp.py#L300)

arg_statevar = self.statevars[findtext('relatedStateVariable')]

since it contains whitespace. Similar issues occur if text of other tags is used with whitespace.

SOAP Envelope Namespace URI should be terminated with a trailing '/'

I believe NS_SOAP_ENV in soap.py line 10 should be terminated with an '/'.

From:

NS_SOAP_ENV = 'http://schemas.xmlsoap.org/soap/envelope'

To:

NS_SOAP_ENV = 'http://schemas.xmlsoap.org/soap/envelope/'

At least that is an issue for one of my devices, which returns a 402 error without the trailing slash.

Hopefully adding the trailing slash does not brake other devices.

Can't follow typical usage examples from readme

After installing with pip as user, I get the following when trying the usage examples:


Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import upnpclient
>>> devices = upnpclient.discover()
>>> devices
[<Device 'PiFi (UpMpd AV)'>, <Device 'Focal UpMpd AV'>, <Device 'Plex Media Server: odroid'>, <Device 'PiFi (UpMpd OH)'>, <Device 'WFADevice'>, <Device 'BT Home Hub 6.0A'>, <Device 'Focal UpMpd OH'>]
>>> d = devices[0]
>>> d.WANIPConn1.GetStatusInfo()
Traceback (most recent call last):
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 148, in __getattr__
    return self.service_map[name]
KeyError: 'WANIPConn1'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 150, in __getattr__
    raise AttributeError("No attribute or service found with name %r." % name)
AttributeError: No attribute or service found with name 'WANIPConn1'.
>>> d.services
[<Service service_id='urn:upnp-org:serviceId:AVTransport'>, <Service service_id='urn:upnp-org:serviceId:RenderingControl'>, <Service service_id='urn:upnp-org:serviceId:ConnectionManager'>]
>>> d.Layer3Forwarding1.actions
Traceback (most recent call last):
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 148, in __getattr__
    return self.service_map[name]
KeyError: 'Layer3Forwarding1'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 150, in __getattr__
    raise AttributeError("No attribute or service found with name %r." % name)
AttributeError: No attribute or service found with name 'Layer3Forwarding1'.

Tests does not run

I'm quite new to github and python but want to investigate UPnP. So I cloned the upnpclient and of course run the tests first but get the error message "ImportError: No module named 'mock". Isn't it unittest.mock? I use Python3. What I'm missing?

Doesn't add UPNP nat mapping to pfSense

Been testing with pfSense which uses miniupnpd and so far adding a port mapping does not show up under the list of added port mappings however if I GetGenericPortMappingEntry and specify an index it will show its there, any ideas ?

non-compliant device : DENON/Marantz streamers

Well, no a real issue, but it took me some time to figure out how to use this library with
a DENON streamer ...

In order to use this Library in python 3,

I have encoutered this issue:

non-comploant device

which I have rapidly corrected with a hack ...

I also had to replace in :
upnpclient/soap.py

on line 99
"SOAPAction": '"%s#%s"' % (self.service_type, action_name)
to :
"SOAPAction": '"{}#{}"'.format(self.service_type, action_name)

on line 101
"Content-Type": "text/xml",
to :
"Content-Type": "text/xml; charset=utf-8",

Now, it works fine ... maybe can it help someone ?...

Error 404 Client Error

I have the following simple code

import upnpclient
def findWiiM():
    WiiMServer = None
    devices = upnpclient.discover()
    for dev in devices:
        if dev.friendly_name == 'WiiM Mini':
            WiiMServer = dev.location
    return WiiMServer

print(findWiiM())

and when I run it I get the following error?

Error '404 Client Error: Not Found for url: http[:]//192.168.1.220:8060/dial/ecp_SCPD.xml' for <upnpclient.ssdp.Entry object at 0x000001F68CB1E310>

Any ideas on how to ignore and/or fix it?

Event subscriptions

First of all: Nice work!

Your client doesn't know anything about events, right? Or did I just miss this in code?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.