[![Build Status](https://travis-ci.org/flyte/upnpclient.svg?branch=develop)](https://travis-ci.org/flyte/upnpclient)
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](https://github.com/fboender/pyupnpclient) and his blog post entitled [Exploring UPnP with Python](https://www.electricmonk.nl/log/2016/07/05/exploring-upnp-with-python/).
### Installation
```bash
pip install upnpclient
```
### Usage
Typical usage:
```python
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.
```python
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:
```python
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:
```python
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:
```python
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:
```python
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](http://docs.python-requests.org/en/master/user/authentication/)
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:
```python
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:
```python
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`.
Raw data
{
"_id": null,
"home_page": "https://github.com/flyte/upnpclient",
"name": "upnpclient",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.6,<4.0",
"maintainer_email": "",
"keywords": "upnp",
"author": "Ellis Percival",
"author_email": "flyte@failcode.co.uk",
"download_url": "https://files.pythonhosted.org/packages/dd/69/4d38d9fa757c328df93e7037eb8c1da8ca48e62828c23ba3c421e9335e30/upnpclient-1.0.3.tar.gz",
"platform": "",
"description": "[![Build Status](https://travis-ci.org/flyte/upnpclient.svg?branch=develop)](https://travis-ci.org/flyte/upnpclient)\n\nuPnPclient\n============\n\n_uPnP client library for Python 3._\n\nThis library can be used to discover and consume uPnP devices and their services.\n\nIt's originally based on [Ferry Boender's work](https://github.com/fboender/pyupnpclient) and his blog post entitled [Exploring UPnP with Python](https://www.electricmonk.nl/log/2016/07/05/exploring-upnp-with-python/).\n\n### Installation\n\n```bash\npip install upnpclient\n```\n\n### Usage\n\nTypical usage:\n\n```python\nIn [1]: import upnpclient\n\nIn [2]: devices = upnpclient.discover()\n\nIn [3]: devices\nOut[3]: \n[<Device 'OpenWRT router'>,\n <Device 'Harmony Hub'>,\n <Device 'walternate: root'>]\n\nIn [4]: d = devices[0]\n\nIn [5]: d.WANIPConn1.GetStatusInfo()\nOut[5]: \n{'NewConnectionStatus': 'Connected',\n 'NewLastConnectionError': 'ERROR_NONE',\n 'NewUptime': 14851479}\n\nIn [6]: d.WANIPConn1.GetNATRSIPStatus()\nOut[6]: {'NewNATEnabled': True, 'NewRSIPAvailable': False}\n\nIn [7]: d.WANIPConn1.GetExternalIPAddress()\nOut[7]: {'NewExternalIPAddress': '123.123.123.123'}\n```\n\nIf you know the URL for the device description XML, you can access it directly.\n\n```python\nIn [1]: import upnpclient\n\nIn [2]: d = upnpclient.Device(\"http://192.168.1.1:5000/rootDesc.xml\")\n\nIn [3]: d.services\nOut[3]: \n[<Service service_id='urn:upnp-org:serviceId:Layer3Forwarding1'>,\n <Service service_id='urn:upnp-org:serviceId:WANCommonIFC1'>,\n <Service service_id='urn:upnp-org:serviceId:WANIPConn1'>]\n\nIn [4]: d.Layer3Forwarding1.actions\nOut[4]: \n[<Action 'SetDefaultConnectionService'>,\n <Action 'GetDefaultConnectionService'>]\n\nIn [5]: d.Layer3Forwarding1.GetDefaultConnectionService()\nOut[5]: {'NewDefaultConnectionService': 'uuid:46cb370a-d7f2-490f-ac01-fb0db6c8b22b:WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1'}\n```\n\nSometimes the service or action name isn't a valid property name. In which case, service and actions can be accessed other ways:\n\n```python\nIn [1]: d[\"Layer3Forwarding1\"][\"GetDefaultConnectionService\"]()\nOut[1]: {'NewDefaultConnectionService': 'uuid:46cb370a-d7f2-490f-ac01-fb0db6c8b22b:WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1'}\n```\n\nTo view the arguments required to call a given action:\n\n```python\nIn [1]: d.WANIPConn1.AddPortMapping.argsdef_in\nOut[1]: \n[('NewRemoteHost',\n {'allowed_values': set(), 'datatype': 'string', 'name': 'RemoteHost'}),\n ('NewExternalPort',\n {'allowed_values': set(), 'datatype': 'ui2', 'name': 'ExternalPort'}),\n ('NewProtocol',\n {'allowed_values': {'TCP', 'UDP'},\n 'datatype': 'string',\n 'name': 'PortMappingProtocol'}),\n ('NewInternalPort',\n {'allowed_values': set(), 'datatype': 'ui2', 'name': 'InternalPort'}),\n ('NewInternalClient',\n {'allowed_values': set(), 'datatype': 'string', 'name': 'InternalClient'}),\n ('NewEnabled',\n {'allowed_values': set(),\n 'datatype': 'boolean',\n 'name': 'PortMappingEnabled'}),\n ('NewPortMappingDescription',\n {'allowed_values': set(),\n 'datatype': 'string',\n 'name': 'PortMappingDescription'}),\n ('NewLeaseDuration',\n {'allowed_values': set(),\n 'datatype': 'ui4',\n 'name': 'PortMappingLeaseDuration'})]\n```\n\nand then to call the action using those arguments:\n\n```python\nIn [1]: d.WANIPConn1.AddPortMapping(\n ...: NewRemoteHost='0.0.0.0',\n ...: NewExternalPort=12345,\n ...: NewProtocol='TCP',\n ...: NewInternalPort=12345,\n ...: NewInternalClient='192.168.1.10',\n ...: NewEnabled='1',\n ...: NewPortMappingDescription='Testing',\n ...: NewLeaseDuration=10000)\nOut[1]: {}\n```\n\nSimilarly, the arguments you can expect to receive in response are listed:\n\n```python\nIn [1]: d.WANIPConn1.GetGenericPortMappingEntry.argsdef_out\nOut[1]: \n[('NewRemoteHost',\n {'allowed_values': set(), 'datatype': 'string', 'name': 'RemoteHost'}),\n ('NewExternalPort',\n {'allowed_values': set(), 'datatype': 'ui2', 'name': 'ExternalPort'}),\n ('NewProtocol',\n {'allowed_values': {'TCP', 'UDP'},\n 'datatype': 'string',\n 'name': 'PortMappingProtocol'}),\n ('NewInternalPort',\n {'allowed_values': set(), 'datatype': 'ui2', 'name': 'InternalPort'}),\n ('NewInternalClient',\n {'allowed_values': set(), 'datatype': 'string', 'name': 'InternalClient'}),\n ('NewEnabled',\n {'allowed_values': set(),\n 'datatype': 'boolean',\n 'name': 'PortMappingEnabled'}),\n ('NewPortMappingDescription',\n {'allowed_values': set(),\n 'datatype': 'string',\n 'name': 'PortMappingDescription'}),\n ('NewLeaseDuration',\n {'allowed_values': set(),\n 'datatype': 'ui4',\n 'name': 'PortMappingLeaseDuration'})]\n```\n\n#### HTTP Auth/Headers\n\nYou may pass a\n[requests compatible](http://docs.python-requests.org/en/master/user/authentication/)\nauthentication object and/or a dictionary containing headers to use on the HTTP\ncalls to your uPnP device.\n\nThese may be set on the `Device` itself on creation for use with every HTTP\ncall:\n\n```python\ndevice = upnpclient.Device(\n \"http://192.168.1.1:5000/rootDesc.xml\"\n http_auth=('myusername', 'mypassword'),\n http_headers={'Some-Required-Header': 'somevalue'}\n)\n```\n\nOr on a per-call basis:\n\n```python\ndevice.Layer3Forwarding1.GetDefaultConnectionService(\n http_auth=('myusername', 'mypassword'),\n http_headers={'Some-Required-Header': 'somevalue'}\n)\n```\n\nIf you've set either at `Device` level, they can be overridden per-call by\nsetting them to `None`.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Python 3 library for accessing uPnP devices.",
"version": "1.0.3",
"project_urls": {
"Homepage": "https://github.com/flyte/upnpclient"
},
"split_keywords": [
"upnp"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f2af6e2365c5955b7b006b95b5e9e0e2f278c310ed56ed7768a7a4fc1d66e01a",
"md5": "e50b09ba2c022ab32105299f03a65bbc",
"sha256": "1fb1b58af8eae9bb31758152e762f13aaf8608c89110e6d1a1d7d979677ac0df"
},
"downloads": -1,
"filename": "upnpclient-1.0.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e50b09ba2c022ab32105299f03a65bbc",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6,<4.0",
"size": 18127,
"upload_time": "2020-12-04T15:51:39",
"upload_time_iso_8601": "2020-12-04T15:51:39.680397Z",
"url": "https://files.pythonhosted.org/packages/f2/af/6e2365c5955b7b006b95b5e9e0e2f278c310ed56ed7768a7a4fc1d66e01a/upnpclient-1.0.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "dd694d38d9fa757c328df93e7037eb8c1da8ca48e62828c23ba3c421e9335e30",
"md5": "f936c8de89705555f6bd736a66d3af5d",
"sha256": "641f05fa4b8e5c5b5cc4561dab49fe5c4774d26e51378671efad4023249e69b8"
},
"downloads": -1,
"filename": "upnpclient-1.0.3.tar.gz",
"has_sig": false,
"md5_digest": "f936c8de89705555f6bd736a66d3af5d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6,<4.0",
"size": 17503,
"upload_time": "2020-12-04T15:51:40",
"upload_time_iso_8601": "2020-12-04T15:51:40.973380Z",
"url": "https://files.pythonhosted.org/packages/dd/69/4d38d9fa757c328df93e7037eb8c1da8ca48e62828c23ba3c421e9335e30/upnpclient-1.0.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2020-12-04 15:51:40",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "flyte",
"github_project": "upnpclient",
"travis_ci": true,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "requests",
"specs": []
},
{
"name": "six",
"specs": []
},
{
"name": "python-dateutil",
"specs": []
},
{
"name": "lxml",
"specs": []
},
{
"name": "ifaddr",
"specs": []
}
],
"tox": true,
"lcname": "upnpclient"
}