Skip to content

Commit

Permalink
First Checkin of bluesound api
Browse files Browse the repository at this point in the history
  • Loading branch information
venjum committed Dec 5, 2016
1 parent 9936b76 commit c038b4f
Showing 1 changed file with 207 additions and 0 deletions.
207 changes: 207 additions & 0 deletions bluesound_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
"""
Bluesound API
This file implements HTML requests that can be sent to a Bluesound player
Future implementation:
Most of the API are based on this link:
https://helpdesk.bluesound.com/discussions/viewtopic.php?f=4&t=2293
-- Grouping and Ungrouping
You can group player together
https://192.168.1.38:11000/AddSlave?slave=192.168.1.41&group=Study%20Player
(Study Player is the group name)
https://192.168.1.38:11000/RemoveSlave?slave=192.168.1.41
-- Get list of services
You can get the list of Services that the player can use using
https://192.168.1.38:11000/Services
Or browse through the Radio Service using
https://192.168.1.38:11000/RadioBrowse
-- Jump to
https://192.168.1.38:11000/Playlists
https://192.168.1.38:11000/Genres?service=LocalMusic (Library)
https://192.168.1.38:11000/RadioBrowse?service=TuneIn (TuneIn Radio)
This command appears to provide a list of all the Inputs
https://192.168.1.38:11000/RadioBrowse?service=Capture
Then you can switch to them using
https://192.168.1.38:11000/Play?url=Capture%3Ahw%3A1%2C0%2F1%2F25%2F2&preset_id&image=/images/inputIcon.png (Optical Input)
https://192.168.1.38:11000/Play?url=Capture%3Abluez%3Abluetooth&preset_id&image=/images/BluetoothIcon.png (Bluetooth Input)
"""
from enum import Enum
import urllib.request
import xmltodict


class RepeatOption(Enum):
"""
Repeat option for repeat command
"""
on = "0"
track = "1"
off = "2"


class BluesoundApi:
"""
Bluesound API for sending commands and receiving status from Bluesound devices.
"""

def __init__(self, ip_address):
self.baseUrl = "https://" + ip_address + ":11000/"

def play(self, id=None, seek=None):
"""
Send Play command to Bluesound player
Arguments:
No arguments: Continue playing after a pause.
id: Start playing track id + 1 (id=o, starts track 1 from playlist)
seek: Jumps to seek number of seconds in to current track.
Do have some problem with Spotify
"""
play = self.baseUrl + "Play"
if id:
play += ("?id=" + str(id))
elif seek:
play += ("?seek=" + str(seek))

urllib.request.urlopen(play)

def pause(self):
"""
Send pause command to Bluesound player
"""
urllib.request.urlopen(self.baseUrl + "Pause")

def skip(self):
"""
Send skip command to Bluesound player
Can be used to skip to next song
"""
urllib.request.urlopen(self.baseUrl + "Skip")

def back(self):
"""
Send back command to Bluesound player
Can be used to start current track at the beginning
"""
urllib.request.urlopen(self.baseUrl + "Back")

def volume(self, level):
"""
Send volume command to Bluesound player
Arguments:
level: Volume to set in percent. 0 is mute
Note:
Can set limits for what 100% means, thus not with this API yet.
"""
urllib.request.urlopen(self.baseUrl + "Volume?level=" + str(level))

def repeat(self, state):
"""
Send Repeat command to Bluesound player
Arguments:
state: Use RepeatOption enum
Note:
Do have some problem with Spotify
"""
urllib.request.urlopen(self.baseUrl + "Repeat?state=" + state.value)

def shuffle(self, shuffleOn):
"""
Send Shuffle command to Bluesound player
Arguments:
shuffleOn: True shuffle on, False Shuffle off
Note:
Do have some problem with Spotify
"""
urllib.request.urlopen(self.baseUrl + "Shuffle?state=" + str(int(shuffleOn)))

def getSyncStatus(self):
"""
Request Sync Status from Bluesound player
Can be called every second to get player information
Return:
Dict(String)
SyncStatus([
('@icon', '/images/players/C390DD_nt.png'),
('@volume', '50'),
('@modelName', 'C390'),
('@name', 'NAD C390'),
('@model', 'C390'),
('@brand', 'NAD'),
('@etag', '11'),
('@schemaVersion', '15'),
('@syncStat', '11'),
('@id', '192.168.1.8:11000'),
('@mac', 'xx:xx:xx:xx:xx:xx')
])
Raises:
RuntimeError if it can't connect to player
"""
with urllib.request.urlopen(self.baseUrl + "SyncStatus") as respons:
return xmltodict.parse(respons.read())

raise RuntimeError("Could not get SyncStatus from Bluesound device")

def getStatus(self):
"""
Request Status from Bluesound player
Can be called every second to get player information
Return:
Dict(String) with status. The dict will vary depending on chosen input channel.
This example is with TuneIn
status([
('@etag', '3b85bc61da52c3341aa12c66eddbbd91'),
('canMovePlayback', 'true'),
('canSeek', '0'),
('cursor', '0'),
('image', 'https://cdn-radiotime-logos.tunein.com/s84118q.png'),
('indexing', '0'),
('is_preset', '1'),
('mid', '1'),
('mode', '1'),
('pid', '1'),
('preset_id', 's84118'),
('preset_name', '103.9 | Radio Norge'),
('prid', '0'),
('quality', '128000'),
('repeat', '0'),
('service', 'TuneIn'),
('shuffle', '0'),
('sid', '5'),
('sleep', None),
('song', '0'),
('state', 'stream'),
('stationImage', 'https://cdn-radiotime-logos.tunein.com/s84118q.png'),
('streamFormat', 'MP3 128 kb/s'),
('streamUrl', 'URL to stream'),
('syncStat', '13'),
('title1', 'Variert Musikk Fra De 4 Siste Tiaar - ' 'Oslo'),
('title2', 'Golden Brown - The Stranglers'),
('title3', 'Radio Norge'),
('volume', '88'),
('secs', '5')
])
Raises:
RuntimeError if it can't connect to player
"""
with urllib.request.urlopen(self.baseUrl + "Status") as respons:
return xmltodict.parse(respons.read())

raise RuntimeError("Could not get Status from Bluesound device")

0 comments on commit c038b4f

Please sign in to comment.