pybeoplay 2.3.0__tar.gz → 2.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pybeoplay
3
- Version: 2.3.0
3
+ Version: 2.4.0
4
4
  Summary: BeoPlay API for Python
5
5
  Home-page: https://github.com/giachello/pybeoplay
6
- Download-URL: https://github.com/giachello/pybeoplay/tarball/2.3.0
6
+ Download-URL: https://github.com/giachello/pybeoplay/tarball/2.4.0
7
7
  Author: Giovanni Iachello
8
8
  Author-email: giovanni.iachello@gmail.com
9
9
  License: MIT License
@@ -1,12 +1,13 @@
1
- #
2
- # BeoPlay JSON interface for Bang & Olufsen Speakers, TVs and other NL devices
3
- # Reference: https://documenter.getpostman.com/view/1053298/T1LTe4Lt#intro
4
- # Reference: https://raw.githubusercontent.com/PolyPv/BeoRemote/master/BeoRemote.txt
5
- # Lifted a lot of code from marton borzak's ha-beoplay
6
- #
7
- #
8
- # https://widdowquinn.github.io/coding/update-pypi-package/
9
- #
1
+ """
2
+
3
+ BeoPlay JSON interface for Bang & Olufsen Speakers, TVs and other NL devices
4
+ Reference: https://documenter.getpostman.com/view/1053298/T1LTe4Lt#intro
5
+ Reference: https://raw.githubusercontent.com/PolyPv/BeoRemote/master/BeoRemote.txt
6
+ Lifted a lot of code from marton borzak's ha-beoplay
7
+
8
+ https://widdowquinn.github.io/coding/update-pypi-package/
9
+
10
+ """
10
11
 
11
12
  import requests
12
13
  import aiohttp
@@ -25,7 +26,8 @@ class BeoPlay(object):
25
26
  """Initializes a BeoPlay connection to the speaker / TV
26
27
  Host: the IP address of the speaker
27
28
  Session (optional): a asyncio client session to be used for async
28
- communication with the speaker (if not provided, only blocking calls using Requests will work
29
+ communication with the speaker (if not provided, only blocking calls
30
+ using Requests will work)
29
31
  """
30
32
  # network information
31
33
  self._host = host
@@ -34,6 +36,7 @@ class BeoPlay(object):
34
36
  )
35
37
  self._connfail = 0
36
38
  self._clientsession = session
39
+ # The following are only going ot be valid after a call to getDeviceInfo
37
40
  # device information
38
41
  self._name = None
39
42
  self._serialNumber = None
@@ -42,6 +45,10 @@ class BeoPlay(object):
42
45
  self._typeName = None
43
46
  self._softwareVersion = None
44
47
  self._hardwareVersion = None
48
+ # The following are only going ot be valid after a call to getMediaInfo, getStandby
49
+ # Or, they are updated by the Notifications task. The actual field updated by
50
+ # Notifications varies by device. Some devices for example provide notifications when
51
+ # Sound mode changes (e.g., Stage), others (e.g., BeoVision Avant 55) don't.
45
52
  # State and Media information
46
53
  self.on = None
47
54
  self.min_volume = None
@@ -57,14 +64,17 @@ class BeoPlay(object):
57
64
  self.media_country = None
58
65
  self.media_languages = None
59
66
  self.primary_experience = None
67
+ # The following are only going ot be valid after a call to getSources
60
68
  # Sources
61
69
  self.source = None
62
70
  self.sources = []
63
71
  self.sourcesID = []
64
72
  self.sourcesBorrowed = []
73
+ # The following are only going ot be valid after a call to getSoundModes
65
74
  # Sound modes
66
- self.soundMode = None
75
+ self._soundMode = None
67
76
  self._soundModes = {}
77
+ # The following are only going ot be valid after a call to getStandPosition
68
78
  # Stand control
69
79
  self.standPosition = None
70
80
  self.standPositions = []
@@ -120,6 +130,11 @@ class BeoPlay(object):
120
130
  """Get the list of available digits"""
121
131
  return BEOPLAY_DIGITS
122
132
 
133
+ @property
134
+ def soundMode(self):
135
+ """Get the current sound modes"""
136
+ return self._soundMode
137
+
123
138
  @property
124
139
  def soundModes(self):
125
140
  """Get the list of available sound modes"""
@@ -127,7 +142,7 @@ class BeoPlay(object):
127
142
 
128
143
  @property
129
144
  def soundModesID(self):
130
- """Get the list of available sound modes"""
145
+ """Get the list of available sound mode IDs"""
131
146
  return list(self._soundModes.values())
132
147
 
133
148
  ###############################################################
@@ -236,9 +251,16 @@ class BeoPlay(object):
236
251
  # GET ATTRIBUTES FROM THE SPEAKER - NON-BLOCKING CALLS
237
252
  ###############################################################
238
253
 
254
+ async def async_get_source(self):
255
+ self.source = None
256
+ r = await self.async_getReq(BEOPLAY_URL_ACTIVE_SOURCES)
257
+ if r:
258
+ self.source = r["primaryExperience"]["source"]["friendlyName"] if "friendlyName" in r["primaryExperience"]["source"] else None
259
+ return self.source
260
+
239
261
  # edited to only include in Use sources
240
262
  async def async_get_sources(self):
241
- r = await self.async_getReq("BeoZone/Zone/Sources")
263
+ r = await self.async_getReq(BEOPLAY_URL_GET_SOURCES)
242
264
  if r:
243
265
  # clear previously stored sources
244
266
  self.sources = []
@@ -257,7 +279,7 @@ class BeoPlay(object):
257
279
 
258
280
  async def async_get_standby(self) -> bool:
259
281
  """Returns True of the device is on, False if off."""
260
- r = await self.async_getReq("BeoDevice/powerManagement/standby")
282
+ r = await self.async_getReq(BEOPLAY_URL_STANDBY)
261
283
  if r:
262
284
  if r["standby"]["powerState"] == "on":
263
285
  self.on = True
@@ -267,25 +289,29 @@ class BeoPlay(object):
267
289
  return
268
290
 
269
291
  async def async_get_sound_mode(self):
270
- r = await self.async_getReq(BEOPLAY_URL_GET_SOUND_MODE)
271
- if r:
272
- self.soundMode = r["mode"]["active"]
273
- return self.soundMode
274
- return
292
+ """Returns the current sound mode, or None if not retrieved."""
293
+ self._soundMode = None
294
+ await self.async_get_sound_modes()
295
+ return self._soundMode
275
296
 
276
297
  async def async_get_sound_modes(self):
298
+ """Returns a dictionary of available sound modes, or None if not retrieved."""
277
299
  r = await self.async_getReq(BEOPLAY_URL_GET_SOUND_MODE)
278
300
  if r:
279
301
  r = r.get("mode", {"list": []})
280
- r = r.get("list", [])
281
- for element in r:
302
+ l = r.get("list", [])
303
+ a = r.get("active", None)
304
+ for element in l:
282
305
  self._soundModes[element["friendlyName"]] = element["id"]
306
+ if a and a == element["id"]:
307
+ self._soundMode = element["friendlyName"]
283
308
  return self._soundModes
284
309
  return
285
310
 
286
311
  async def async_get_stand_position(self):
287
312
  """Returns the stand position, or None if not retrieved."""
288
- r = await self.async_getReq("BeoZone/Zone/Stand/Active")
313
+ self._standPosition = None
314
+ r = await self.async_getReq(BEOPLAY_URL_STAND_ACTIVE)
289
315
  if r:
290
316
  if r["active"] is not None:
291
317
  self._standPosition = r["active"]
@@ -293,11 +319,11 @@ class BeoPlay(object):
293
319
  return
294
320
 
295
321
  async def async_get_stand_positions(self):
296
- r = await self.async_getReq("BeoZone/Zone/Stand")
322
+ # clear previous stand positions
323
+ self.standPositions = []
324
+ self.standPositionsID = []
325
+ r = await self.async_getReq(BEOPLAY_URL_STAND)
297
326
  if r:
298
- # clear previous stand positions
299
- self.standPositions = []
300
- self.standPositionsID = []
301
327
  for elements in r:
302
328
  i = 0
303
329
  while i < len(r[elements]):
@@ -383,7 +409,7 @@ class BeoPlay(object):
383
409
  chosenSource = self.sourcesID[i]
384
410
  await self.async_postReq(
385
411
  "POST",
386
- BEOPLAY_URL_SET_SOURCE,
412
+ BEOPLAY_URL_ACTIVE_SOURCES,
387
413
  {"primaryExperience": {"source": {"id": chosenSource}}},
388
414
  )
389
415
  i += 1
@@ -407,7 +433,7 @@ class BeoPlay(object):
407
433
  if self.standPositions[i] == standPosition:
408
434
  chosenStandPosition = self.standPositionsID[i]
409
435
  await self.async_postReq(
410
- "PUT", BEOPLAY_URL_SET_STAND, {"active": chosenStandPosition}
436
+ "PUT", BEOPLAY_URL_STAND_ACTIVE, {"active": chosenStandPosition}
411
437
  )
412
438
  i += 1
413
439
 
@@ -554,7 +580,7 @@ class BeoPlay(object):
554
580
 
555
581
  # edited to only include in Use sources
556
582
  def getSources(self):
557
- r = self._getReq("BeoZone/Zone/Sources")
583
+ r = self._getReq(BEOPLAY_URL_GET_SOURCES)
558
584
  if r:
559
585
  for elements in r:
560
586
  i = 0
@@ -565,8 +591,15 @@ class BeoPlay(object):
565
591
  self.sourcesID.append(r[elements][i][0])
566
592
  i += 1
567
593
 
594
+ def getSource(self):
595
+ self.source = None
596
+ r = self._getReq(BEOPLAY_URL_ACTIVE_SOURCES)
597
+ if r:
598
+ self.source = r["primaryExperience"]["source"]["friendlyName"] if "friendlyName" in r["primaryExperience"]["source"] else None
599
+ return self.source
600
+
568
601
  def getStandby(self):
569
- r = self._getReq("BeoDevice/powerManagement/standby")
602
+ r = self._getReq(BEOPLAY_URL_STANDBY)
570
603
  if r:
571
604
  if r["standby"]["powerState"] == "on":
572
605
  self.on = True
@@ -574,26 +607,38 @@ class BeoPlay(object):
574
607
  self.on = False
575
608
 
576
609
  def getSoundMode(self):
577
- r = self._getReq(BEOPLAY_URL_GET_SOUND_MODE)
578
- if r:
579
- self.soundMode = r["mode"]["active"]
610
+ """ Get sound mode. Return the current active sound mode or None if not retreived."""
611
+ self._soundMode = None
612
+ self.getSoundModes()
613
+ return self._soundMode
580
614
 
581
615
  def getSoundModes(self):
616
+ """ Get sound modes. You need to call this before reading soundMode or soundModes."""
582
617
  r = self._getReq(BEOPLAY_URL_GET_SOUND_MODE)
583
618
  if r:
584
619
  r = r.get("mode", {"list": []})
585
- r = r.get("list", [])
586
- for element in r:
620
+ l = r.get("list", [])
621
+ a = r.get("active", None)
622
+ for element in l:
587
623
  self._soundModes[element["friendlyName"]] = element["id"]
624
+ if a and a == element["id"]:
625
+ self._soundMode = element["friendlyName"]
626
+ return self._soundModes
627
+ return None
588
628
 
589
629
  def getStandPosition(self):
590
- r = self._getReq("BeoZone/Zone/Stand/Active")
630
+ self._standPosition = None
631
+ r = self._getReq(BEOPLAY_URL_STAND_ACTIVE)
591
632
  if r:
592
633
  if r["active"] is not None:
593
- self._standPosition = r["active"]
634
+ self._standPosition = r["active"]
635
+ return self._standPosition
636
+ return None
594
637
 
595
638
  def getStandPositions(self):
596
- r = self._getReq("BeoZone/Zone/Stand")
639
+ self.standPositions = []
640
+ self.standPositionsID = []
641
+ r = self._getReq(BEOPLAY_URL_STAND)
597
642
  if r:
598
643
  for elements in r:
599
644
  i = 0
@@ -601,6 +646,7 @@ class BeoPlay(object):
601
646
  self.standPositions.append(r[elements][i][1]["friendlyName"])
602
647
  self.standPositionsID.append(r[elements][i][0])
603
648
  i += 1
649
+ return self.standPositions
604
650
 
605
651
  def getDeviceInfo(self):
606
652
  r = self._getReq("BeoDevice")
@@ -674,7 +720,7 @@ class BeoPlay(object):
674
720
  chosenSource = self.sourcesID[i]
675
721
  self._postReq(
676
722
  "POST",
677
- BEOPLAY_URL_SET_SOURCE,
723
+ BEOPLAY_URL_ACTIVE_SOURCES,
678
724
  {"primaryExperience": {"source": {"id": chosenSource}}},
679
725
  )
680
726
  i += 1
@@ -697,7 +743,7 @@ class BeoPlay(object):
697
743
  if self.standPositions[i] == standPosition:
698
744
  chosenStandPosition = self.standPositionsID[i]
699
745
  self._postReq(
700
- "PUT", BEOPLAY_URL_SET_STAND, {"active": chosenStandPosition}
746
+ "PUT", BEOPLAY_URL_STAND_ACTIVE, {"active": chosenStandPosition}
701
747
  )
702
748
  i += 1
703
749
 
@@ -854,6 +900,11 @@ class BeoPlay(object):
854
900
  + data["notification"]["data"]["name"]
855
901
  )
856
902
 
903
+ def _processSoundMode(self, data):
904
+ if data["notification"]["type"] == "SOUND_ACTIVE_MODE_CHANGED":
905
+ self.soundMode = data["notification"]["data"]["friendlyName"]
906
+
907
+
857
908
  def _processNotification(self, data):
858
909
  """Cumulative process all the potential notification information."""
859
910
  try:
@@ -865,5 +916,7 @@ class BeoPlay(object):
865
916
  self._processState(data)
866
917
  # get currently playing music info
867
918
  self._processMusicInfo(data)
919
+ # get sound mode
920
+ self._processSoundMode(data)
868
921
  except KeyError:
869
922
  LOG.debug("Malformed notification: %s", str(data))
@@ -5,16 +5,15 @@
5
5
  # Lifted a lot of code from marton borzak's ha-beoplay
6
6
  #
7
7
  #
8
- # pybeoplay constants
9
- #
10
-
11
8
 
9
+ # Connection constants
12
10
  BASE_URL = 'http://{0}:8080/{1}'
13
11
  TIMEOUT = 5.0
14
12
  CONNFAILCOUNT = 5
15
13
 
16
-
14
+ # BeoPlay constants
17
15
  BEOPLAY_URL_NOTIFICATIONS = 'BeoNotify/Notifications'
16
+
18
17
  BEOPLAY_URL_SET_VOLUME = 'BeoZone/Zone/Sound/Volume/Speaker/Level'
19
18
  BEOPLAY_URL_MUTE = 'BeoZone/Zone/Sound/Volume/Speaker/Muted'
20
19
  BEOPLAY_URL_PLAY = 'BeoZone/Zone/Stream/Play'
@@ -28,10 +27,15 @@ BEOPLAY_URL_STEPDOWN = 'BeoZone/Zone/List/StepDown'
28
27
  BEOPLAY_URL_SHUFFLE = 'BeoZone/Zone/List/Shuffle'
29
28
  BEOPLAY_URL_REPEAT = 'BeoZone/Zone/List/Repeat'
30
29
  BEOPLAY_URL_STANDBY = 'BeoDevice/powerManagement/standby'
31
- BEOPLAY_URL_SET_SOURCE = 'BeoZone/Zone/ActiveSources'
32
- BEOPLAY_URL_SET_STAND = 'BeoZone/Zone/Stand/Active'
30
+
31
+ BEOPLAY_URL_GET_SOURCES = 'BeoZone/Zone/Sources'
32
+ BEOPLAY_URL_ACTIVE_SOURCES = 'BeoZone/Zone/ActiveSources'
33
+
34
+ BEOPLAY_URL_STAND_ACTIVE = 'BeoZone/Zone/Stand/Active'
35
+ BEOPLAY_URL_STAND = 'BeoZone/Zone/Stand'
33
36
  BEOPLAY_URL_GET_SOUND_MODE = 'BeoZone/Zone/Sound/Mode'
34
37
  BEOPLAY_URL_SET_SOUND_MODE = 'BeoZone/Zone/Sound/Mode/Active'
38
+
35
39
  BEOPLAY_URL_JOIN_EXPERIENCE = 'BeoZone/Zone/Device/OneWayJoin'
36
40
  BEOPLAY_URL_LEAVE_EXPERIENCE = 'BeoZone/Zone/ActiveSources/primaryExperience'
37
41
  BEOPLAY_URL_PLAYQUEUE = 'BeoZone/Zone/PlayQueue'
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pybeoplay
3
- Version: 2.3.0
3
+ Version: 2.4.0
4
4
  Summary: BeoPlay API for Python
5
5
  Home-page: https://github.com/giachello/pybeoplay
6
- Download-URL: https://github.com/giachello/pybeoplay/tarball/2.3.0
6
+ Download-URL: https://github.com/giachello/pybeoplay/tarball/2.4.0
7
7
  Author: Giovanni Iachello
8
8
  Author-email: giovanni.iachello@gmail.com
9
9
  License: MIT License
@@ -7,7 +7,7 @@ def readme():
7
7
 
8
8
  PACKAGE_NAME = 'pybeoplay'
9
9
  HERE = os.path.abspath(os.path.dirname(__file__))
10
- VERSION = '2.3.0'
10
+ VERSION = '2.4.0'
11
11
 
12
12
  PACKAGES = find_packages(exclude=['tests', 'tests.*', 'dist', 'ccu', 'build'])
13
13
 
File without changes
File without changes
File without changes