# openhomedevice
Library to provide an API to an existing openhome device. The device needs to have been discovered first by something like netdisco (https://github.com/home-assistant/netdisco).
The underlying UPnP client library used is https://github.com/StevenLooman/async_upnp_client
* Tested against [Linn Products Ltd](https://www.linn.co.uk/uk/) devices running Davaar 80 (thought expected to work on earlier variants)
* Tested against [OpenHome Player](http://openhome.org/) devices
## Installation
`pip install openhomedevice`
## API
### Constructor
```python
device = Device(location)
await device.init()
```
### Methods
#### Control
```python
await set_standby(standbyRequested) #bool
await play() #starts playback
await play_media(track_details) #start playing `track_details`
await stop() #stops playback
await pause() #pauses playback
await skip(offset) #positive or negative integer
await set_volume(volume_level) #positive number
await increase_volume() #increase volume by 1
await decrease_volume() #decrease volume by 1
await set_mute(muteRequested) #bool
await set_source(index) #positive integer (use Sources() for indices)
await invoke_pin(index) #positive integer (use Pins() for indices)
```
#### Firmware
```python
await check_latest_firmware() #check for the latest firmware
await update_firmware() #update the device firmware
await software_status() #returns a dictionary with information about the current software
```
#### Informational
```python
uuid() #Unique identifier
manufacturer() #Manufacturer
model_name() #Model Name
friendly_name() #Friendly Name
await name() #Name of device
await room() #Name of room
await is_in_standby() #returns true if in standby
await transport_state() #returns one of Stopped, Playing, Paused or Buffering.
volume_enabled #property true if the volume service is available
await volume_level() #returns the volume setting or None if disabled
await is_muted() #returns true if muted or None if disabled
await source() #returns the currently connected source as a dictionary
await sources() #returns an array of source dictionaries with indices
await track_info() #returns a track dictionary
await pins() #returns an array of pin dictionaries with indices
pins_enabled #property true if the pins service is available
```
##### Source Response
```python
{
'type': 'Playlist',
'name': 'Playlist'
}
```
##### Sources Response
```python
[
{ 'index': 0, 'type': 'Playlist', 'name': 'Playlist' },
{ 'index': 1, 'type': 'Radio', 'name': 'Radio' },
{ 'index': 3, 'type': 'Receiver', 'name': 'Songcast' },
{ 'index': 6, 'type': 'Analog', 'name': 'Front Aux' }
]
```
##### Pins Response
```python
[
{'index': 1, 'title': 'Playstation 4', 'artworkUri': 'external:///source?type=Hdmi&systemName=HDMI3'}
{'index': 4, 'title': 'Classic FM', 'artworkUri': 'http://cdn-profiles.tunein.com/s8439/images/logoq.png?t=1'}
{'index': 6, 'title': 'Chillout Playlist', 'artworkUri': 'http://media/artwork/chillout-playlist.png'}
]
```
##### TrackInfo Response
```python
{
"mimeType": "http-get:*:audio/x-flac:DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01700000000000000000000000000000",
"rating": None,
"performer": [
"Fahmi Alqhai, Performer - Johann Sebastian Bach, Composer"
],
"bitDepth": 16,
"channels": 2,
"disc": None,
"composer": [],
"year": 2017,
"duration": 460,
"author": [],
"albumArtist": [],
"type": "object.item.audioItem.musicTrack",
"narrator": [],
"description": None,
"conductor": [],
"albumArtwork": "http://static.qobuz.com/images/covers/58/20/8424562332058_600.jpg",
"track": 2,
"tracks": None,
"artwork": None,
"genre": [
"Klassiek"
],
"publisher": "Glossa",
"albumGenre": [
"Klassiek"
],
"artist": [
"Fahmi Alqhai"
],
"bitRate": None,
"albumTitle": "The Bach Album",
"uri": "http://192.168.0.110:58050/stream/audio/b362f0f7a1ff33b176bcf2adde75af96.flac",
"discs": None,
"published": None,
"title": "Violin Sonata No. 2 in A Minor, BWV 1003 (Arr. for Viola da gamba) : Violin Sonata No. 2 in A Minor, BWV 1003 (Arr. for Viola da gamba): II. Fuga",
"sampleRate": 44100
}
```
##### SoftwareStatus response
When an update is available:
```python
{
"status":"update_available",
"current_software":{
"version":"4.99.491",
"topic":"main",
"channel":"release"
},
"update_info":{
"legal":{
"licenseurl":"http://products.linn.co.uk/VersionInfo/licenseV2.txt",
"privacyurl":"https://www.linn.co.uk/privacy",
"privacyuri":"https://products.linn.co.uk/VersionInfo/PrivacyV1.json",
"privacyversion":1
},
"releasenotesuri":"http://docs.linn.co.uk/wiki/index.php/ReleaseNotes",
"updates":[
{
"channel":"release",
"date":"07 Jun 2023 12:29:48",
"description":"Release build version 4.100.502 (07 Jun 2023 12:29:48)",
"exaktlink":"3",
"manifest":"https://cloud.linn.co.uk/update/components/836/4.100.502/manifest.json",
"topic":"main",
"variant":"836",
"version":"4.100.502"
}
],
"exaktUpdates":[]
}
}
```
When the system is on the latest firmware:
```python
{
"status":"on_latest",
"current_software":{
"version":"4.100.502",
"topic":"main",
"channel":"release"
}
}
```
##### Upgrading Firmware
Use this to check if an update is required and then instruct the device to apply it
```python
await openhomeDevice.check_latest_firmware()
await openhomeDevice.update_firmware()
```
##### Playing A Track
Use this to play a short audio track, a podcast Uri or radio station Uri. The audio will be played using the radio source of the device. The `trackDetails` object should be the same as the one described in the `TrackInfo` section above.
```python
track_details = {}
track_details["uri"] = "http://opml.radiotime.com/Tune.ashx?id=s122119"
track_details["title"] = 'Linn Radio (Eclectic Music)'
track_details["albumArtwork"] = 'http://cdn-radiotime-logos.tunein.com/s122119q.png'
openhomeDevice.PlayMedia(track_details)
```
## Example
```python
python3 demo.py
```
## Running Tests
```bash
PYTHONPATH=. pytest ./tests/*
```
## Uploading Package
Following guide from https://packaging.python.org/tutorials/packaging-projects/
Update version in `setup.py`
```sh
python3 setup.py sdist
twine upload dist/*
```
Raw data
{
"_id": null,
"home_page": "https://github.com/bazwilliams/openhomedevice",
"name": "openhomedevice",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": "upnp, dlna, openhome, linn, ds, music, render, async",
"author": "Barry John Williams",
"author_email": "barry@bjw.me.uk",
"download_url": "https://files.pythonhosted.org/packages/93/25/f621c4ccc79e20c8816225512f77b1c35ad91661469370d9d8fe2c12533d/openhomedevice-2.3.1.tar.gz",
"platform": null,
"description": "# openhomedevice\n\nLibrary to provide an API to an existing openhome device. The device needs to have been discovered first by something like netdisco (https://github.com/home-assistant/netdisco).\n\nThe underlying UPnP client library used is https://github.com/StevenLooman/async_upnp_client\n\n* Tested against [Linn Products Ltd](https://www.linn.co.uk/uk/) devices running Davaar 80 (thought expected to work on earlier variants)\n* Tested against [OpenHome Player](http://openhome.org/) devices\n\n## Installation\n\n`pip install openhomedevice`\n\n## API\n\n### Constructor\n\n```python\ndevice = Device(location)\nawait device.init()\n```\n\n### Methods\n\n#### Control\n\n```python\n await set_standby(standbyRequested) #bool\n await play() #starts playback\n await play_media(track_details) #start playing `track_details`\n await stop() #stops playback\n await pause() #pauses playback\n await skip(offset) #positive or negative integer\n await set_volume(volume_level) #positive number\n await increase_volume() #increase volume by 1\n await decrease_volume() #decrease volume by 1\n await set_mute(muteRequested) #bool\n await set_source(index) #positive integer (use Sources() for indices)\n await invoke_pin(index) #positive integer (use Pins() for indices)\n```\n\n#### Firmware\n\n```python\n await check_latest_firmware() #check for the latest firmware\n await update_firmware() #update the device firmware\n await software_status() #returns a dictionary with information about the current software\n```\n\n#### Informational\n\n```python\n uuid() #Unique identifier\n manufacturer() #Manufacturer\n model_name() #Model Name\n friendly_name() #Friendly Name\n await name() #Name of device\n await room() #Name of room\n await is_in_standby() #returns true if in standby\n await transport_state() #returns one of Stopped, Playing, Paused or Buffering.\n volume_enabled #property true if the volume service is available\n await volume_level() #returns the volume setting or None if disabled\n await is_muted() #returns true if muted or None if disabled\n await source() #returns the currently connected source as a dictionary\n await sources() #returns an array of source dictionaries with indices\n await track_info() #returns a track dictionary\n await pins() #returns an array of pin dictionaries with indices\n pins_enabled #property true if the pins service is available\n```\n\n##### Source Response\n\n```python\n{\n 'type': 'Playlist',\n 'name': 'Playlist'\n}\n```\n\n##### Sources Response\n\n```python\n[\n { 'index': 0, 'type': 'Playlist', 'name': 'Playlist' },\n { 'index': 1, 'type': 'Radio', 'name': 'Radio' },\n { 'index': 3, 'type': 'Receiver', 'name': 'Songcast' },\n { 'index': 6, 'type': 'Analog', 'name': 'Front Aux' }\n]\n```\n\n##### Pins Response\n\n```python\n[\n {'index': 1, 'title': 'Playstation 4', 'artworkUri': 'external:///source?type=Hdmi&systemName=HDMI3'}\n {'index': 4, 'title': 'Classic FM', 'artworkUri': 'http://cdn-profiles.tunein.com/s8439/images/logoq.png?t=1'}\n {'index': 6, 'title': 'Chillout Playlist', 'artworkUri': 'http://media/artwork/chillout-playlist.png'}\n]\n```\n\n##### TrackInfo Response\n\n```python\n{\n \"mimeType\": \"http-get:*:audio/x-flac:DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01700000000000000000000000000000\",\n \"rating\": None,\n \"performer\": [\n \"Fahmi Alqhai, Performer - Johann Sebastian Bach, Composer\"\n ],\n \"bitDepth\": 16,\n \"channels\": 2,\n \"disc\": None,\n \"composer\": [],\n \"year\": 2017,\n \"duration\": 460,\n \"author\": [],\n \"albumArtist\": [],\n \"type\": \"object.item.audioItem.musicTrack\",\n \"narrator\": [],\n \"description\": None,\n \"conductor\": [],\n \"albumArtwork\": \"http://static.qobuz.com/images/covers/58/20/8424562332058_600.jpg\",\n \"track\": 2,\n \"tracks\": None,\n \"artwork\": None,\n \"genre\": [\n \"Klassiek\"\n ],\n \"publisher\": \"Glossa\",\n \"albumGenre\": [\n \"Klassiek\"\n ],\n \"artist\": [\n \"Fahmi Alqhai\"\n ],\n \"bitRate\": None,\n \"albumTitle\": \"The Bach Album\",\n \"uri\": \"http://192.168.0.110:58050/stream/audio/b362f0f7a1ff33b176bcf2adde75af96.flac\",\n \"discs\": None,\n \"published\": None,\n \"title\": \"Violin Sonata No. 2 in A Minor, BWV 1003 (Arr. for Viola da gamba) : Violin Sonata No. 2 in A Minor, BWV 1003 (Arr. for Viola da gamba): II. Fuga\",\n \"sampleRate\": 44100\n}\n```\n\n##### SoftwareStatus response\n\nWhen an update is available:\n\n```python\n{\n \"status\":\"update_available\",\n \"current_software\":{\n \"version\":\"4.99.491\",\n \"topic\":\"main\",\n \"channel\":\"release\"\n },\n \"update_info\":{\n \"legal\":{\n \"licenseurl\":\"http://products.linn.co.uk/VersionInfo/licenseV2.txt\",\n \"privacyurl\":\"https://www.linn.co.uk/privacy\",\n \"privacyuri\":\"https://products.linn.co.uk/VersionInfo/PrivacyV1.json\",\n \"privacyversion\":1\n },\n \"releasenotesuri\":\"http://docs.linn.co.uk/wiki/index.php/ReleaseNotes\",\n \"updates\":[\n {\n \"channel\":\"release\",\n \"date\":\"07 Jun 2023 12:29:48\",\n \"description\":\"Release build version 4.100.502 (07 Jun 2023 12:29:48)\",\n \"exaktlink\":\"3\",\n \"manifest\":\"https://cloud.linn.co.uk/update/components/836/4.100.502/manifest.json\",\n \"topic\":\"main\",\n \"variant\":\"836\",\n \"version\":\"4.100.502\"\n }\n ],\n \"exaktUpdates\":[]\n }\n}\n```\n\nWhen the system is on the latest firmware:\n\n```python\n{\n \"status\":\"on_latest\",\n \"current_software\":{\n \"version\":\"4.100.502\",\n \"topic\":\"main\",\n \"channel\":\"release\"\n }\n}\n```\n\n##### Upgrading Firmware\n\nUse this to check if an update is required and then instruct the device to apply it\n\n```python\n await openhomeDevice.check_latest_firmware()\n await openhomeDevice.update_firmware()\n```\n\n##### Playing A Track\n\nUse this to play a short audio track, a podcast Uri or radio station Uri. The audio will be played using the radio source of the device. The `trackDetails` object should be the same as the one described in the `TrackInfo` section above.\n\n```python\n track_details = {}\n track_details[\"uri\"] = \"http://opml.radiotime.com/Tune.ashx?id=s122119\"\n track_details[\"title\"] = 'Linn Radio (Eclectic Music)'\n track_details[\"albumArtwork\"] = 'http://cdn-radiotime-logos.tunein.com/s122119q.png'\n\n openhomeDevice.PlayMedia(track_details)\n```\n\n## Example\n\n```python\npython3 demo.py\n```\n\n## Running Tests\n\n```bash\nPYTHONPATH=. pytest ./tests/*\n```\n\n## Uploading Package\n\nFollowing guide from https://packaging.python.org/tutorials/packaging-projects/\n\nUpdate version in `setup.py`\n\n```sh\npython3 setup.py sdist\ntwine upload dist/*\n```\n",
"bugtrack_url": null,
"license": null,
"summary": "Provides an API for requesting information from an Openhome device",
"version": "2.3.1",
"project_urls": {
"Download": "https://github.com/bazwilliams/openhomedevice/tarball/2.1",
"Homepage": "https://github.com/bazwilliams/openhomedevice"
},
"split_keywords": [
"upnp",
" dlna",
" openhome",
" linn",
" ds",
" music",
" render",
" async"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9325f621c4ccc79e20c8816225512f77b1c35ad91661469370d9d8fe2c12533d",
"md5": "cdf32dd4e058ece1784a3395e9dd71d2",
"sha256": "94784c9b790ab6329d09df07f6e57c007301e86894887c9e3eb083fb498049b8"
},
"downloads": -1,
"filename": "openhomedevice-2.3.1.tar.gz",
"has_sig": false,
"md5_digest": "cdf32dd4e058ece1784a3395e9dd71d2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 10832,
"upload_time": "2024-08-09T16:39:58",
"upload_time_iso_8601": "2024-08-09T16:39:58.237216Z",
"url": "https://files.pythonhosted.org/packages/93/25/f621c4ccc79e20c8816225512f77b1c35ad91661469370d9d8fe2c12533d/openhomedevice-2.3.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-09 16:39:58",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "bazwilliams",
"github_project": "openhomedevice",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "openhomedevice"
}