vsslctrl 0.1.10.dev1__tar.gz → 0.1.12.dev1__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.
Files changed (32) hide show
  1. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/PKG-INFO +86 -91
  2. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/README.md +85 -90
  3. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/pyproject.toml +1 -1
  4. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/tests/test_integration.py +364 -277
  5. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/tests/test_settings.py +3 -2
  6. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/tests/test_zone.py +3 -3
  7. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/__init__.py +1 -1
  8. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/api_alpha.py +357 -253
  9. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/core.py +84 -97
  10. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/data_structure.py +64 -18
  11. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/decorators.py +54 -0
  12. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/device.py +70 -15
  13. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/event_bus.py +4 -4
  14. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/group.py +4 -6
  15. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/io.py +88 -23
  16. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/settings.py +36 -15
  17. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/track.py +3 -4
  18. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/transport.py +1 -1
  19. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/utils.py +11 -0
  20. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/zone.py +25 -11
  21. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl.egg-info/PKG-INFO +86 -91
  22. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/LICENSE +0 -0
  23. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/setup.cfg +0 -0
  24. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/tests/test_event_bus.py +0 -0
  25. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/api_base.py +0 -0
  26. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/api_bravo.py +0 -0
  27. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/discovery.py +0 -0
  28. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl/exceptions.py +0 -0
  29. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl.egg-info/SOURCES.txt +0 -0
  30. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl.egg-info/dependency_links.txt +0 -0
  31. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl.egg-info/requires.txt +0 -0
  32. {vsslctrl-0.1.10.dev1 → vsslctrl-0.1.12.dev1}/vsslctrl.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vsslctrl
3
- Version: 0.1.10.dev1
3
+ Version: 0.1.12.dev1
4
4
  Summary: Package for controlling VSSL's range of streaming amplifiers
5
5
  Author-email: vsslctrl <vsslcontrolled@proton.me>
6
6
  Classifier: Development Status :: 4 - Beta
@@ -21,28 +21,44 @@ Requires-Dist: zeroconf==0.132.2; extra == "optional"
21
21
 
22
22
  # vsslctrl
23
23
 
24
- Package for controlling [VSSL's](https://www.vssl.com/) range of streaming amplifiers.
24
+ Package for controlling [VSSL's](https://www.vssl.com/) range of streaming amplifiers.
25
25
 
26
- **`vsslctrl` is not endorsed or affiliated with [VSSL](https://www.vssl.com/) in any manner.**
26
+ ## Coverage
27
+
28
+ Tested on:
29
+
30
+ | Model | Software Version | Note |
31
+ | ------------|--------- | -------------
32
+ | A.3x | p15305.016.3701 |
33
+
34
+
35
+ Home Assistant [integration](https://github.com/vsslctrl/integration.home-assistant) with basic functionality working on:
27
36
 
28
- ## Help
37
+ | Model | Software Version | User Reported |
38
+ | ------------|--------- | -------------
39
+ | A.1 | p15265.033.3703 | ✔️
40
+ | A.3 | p12013.141.3703 | ✔️
41
+ | A.3x | p15305.016.3701 |
42
+ | A.6x | p15305.017.3701 | ✔️
43
+
44
+
45
+ ## Testers Needed
29
46
 
30
47
  I am looking for testers with any VSSL amplifier models, please get in touch if you interested in helping. <vsslcontrolled@proton.me>
31
48
 
32
- Tested on:
33
- - **A.1** software version **p15265.033.3703** via Home Assistant [integration](https://github.com/vsslctrl/integration.home-assistant) (reported)
34
- - **A.3** software version **p12013.141.3703** via Home Assistant [integration](https://github.com/vsslctrl/integration.home-assistant) (reported)
35
- - **A.3x** software version **p15305.016.3701**
36
- - **A.6x** software version **p15305.017.3701** via Home Assistant [integration](https://github.com/vsslctrl/integration.home-assistant) (reported)
49
+
37
50
 
38
51
  ## Important
39
52
 
40
- There should not be any *[VSSL Agent's](https://vssl.gitbook.io/vssl-rest-api/getting-started/start)* running on the same network. If you dont know what this is, then you can ignore this notice.
53
+ There should not be any *[VSSL Agent's](https://vssl.gitbook.io/vssl-rest-api/getting-started/start)* running on the network. If you dont know what this is, then you can ignore this notice.
54
+
55
+ **`vsslctrl` is not endorsed or affiliated with [VSSL](https://www.vssl.com/) in any manner.**
41
56
 
42
57
  ## TODOs
43
58
 
44
- * **A.1(x)** specific control e.g bluetooth
45
59
  * Better test coverage
60
+ * A.1(x) testing - e.g output settings
61
+ * More controls - e.g IR Control
46
62
 
47
63
  ## Basic Usage
48
64
 
@@ -58,7 +74,7 @@ async def main():
58
74
 
59
75
  # Represents a physical VSSL amplifier
60
76
  vssl = Vssl(DeviceModels.A1)
61
- a1 = vssl.add_zone(ZoneIDs.A1, '192.168.1.10')
77
+ a1 = vssl.add_zone('192.168.1.10')
62
78
 
63
79
  # Connect and initiate zones.
64
80
  await vssl.initialise()
@@ -88,14 +104,13 @@ from vsslctrl import Vssl, DeviceModels, Zone, ZoneIDs
88
104
  async def main():
89
105
 
90
106
  # Represents a physical VSSL amplifier
91
- # If no DeviceModels is passed, vsslctrl will default to the feature set of the X series amps
92
107
  vssl = Vssl(DeviceModels.A3X)
93
108
 
94
109
  # Add each you wish to control
95
- zone1 = vssl.add_zone(ZoneIDs.ZONE_1, '192.168.1.10')
96
- zone2 = vssl.add_zone(ZoneIDs.ZONE_2, '192.168.1.11')
97
- zone3 = vssl.add_zone(ZoneIDs.ZONE_3, '192.168.1.12')
98
- #... up to 6 zones
110
+ zone1 = vssl.add_zone('192.168.1.10', ZoneIDs.ZONE_1)
111
+ zone2 = vssl.add_zone('192.168.1.11', ZoneIDs.ZONE_2)
112
+ zone3 = vssl.add_zone('192.168.1.12', ZoneIDs.ZONE_3)
113
+ #... up to 6 zones for A.6(x)
99
114
 
100
115
  # Connect and initiate zones.
101
116
  await vssl.initialise()
@@ -119,9 +134,36 @@ async def main():
119
134
  asyncio.run(main())
120
135
  ```
121
136
 
137
+ # `DeviceModels`
138
+
139
+ A device model has to be passed to VSSL so it knows internally what features are supported by the device.
140
+ This might be removed in the future if we can differentiate different models from the API.
141
+
142
+ | Property | Description |
143
+ | ------------|--------- |
144
+ | `A1X` | A.1x |
145
+ | `A3X` | A.3x |
146
+ | `A6X` | A.6x |
147
+ | `A1` | A1 |
148
+ | `A3` | A3 |
149
+ | `A6` | A6 |
150
+
151
+ # `ZoneIDs`
152
+
153
+ | Property | Description |
154
+ | ------------|--------- |
155
+ | `A1` | A.1(x) Only |
156
+ | `ZONE_1` | Zone 1 of A.3(x) and A.6(x) |
157
+ | `ZONE_2` | Zone 2 of A.3(x) and A.6(x) |
158
+ | `ZONE_3` | Zone 3 of A.3(x) and A.6(x) |
159
+ | `ZONE_4` | Zone 4 of A.6(x) |
160
+ | `ZONE_5` | Zone 5 of A.6(x) |
161
+ | `ZONE_6` | Zone 6 of A.6(x) |
162
+
163
+
122
164
  # API
123
165
 
124
- Most functionality is achived via `getters` and `setters` of the two main classes `Vssl`, `Zone`.
166
+ Most functionality is achieved via `getters` and `setters` of the two main classes `Vssl`, `Zone`.
125
167
 
126
168
  The classes will update the physical VSSL device when setting a property and once feedback has been received, the classes internal state will be updated. For example:
127
169
 
@@ -138,7 +180,6 @@ print(zone_name)
138
180
 
139
181
  **Important** in the above example, `zone1.settings.name` wont be set to its new value until after the VSSL device has changed the name and the `Zone` class has received confirmation feedback. If you need to wait for the value change, you can await a `[property_name]_CHANGE` events.
140
182
 
141
-
142
183
  # `Vssl`
143
184
 
144
185
  | Property | Description | Type |
@@ -160,19 +201,20 @@ vssl.factory_reset()
160
201
 
161
202
  ## `Vssl.settings`
162
203
 
163
- | Property | Description | Type |
164
- | ---------------------- | ----------- | ----------- |
165
- | `name` | Device name | `str`
166
- | `optical_input_name` | Name of the optical input | `str`
167
- | `bluetooth` | Bluetooth enabled / disabled | `bool`
204
+ | Property | Description | Type | Model: Default |
205
+ | ---------------------- | ----------- | ----------- | ----------- |
206
+ | `name` | Device name | `str` |
207
+ | `bus_1_name` | Name of Bus 1 | `str` | <ul><li>A.1: Optical Input</li><li>A.3x/6x: Not Used</li></ul>
208
+ | `bus_2_name` | Name of Bus 2 | `str` | <ul><li>A.1: Coax Input</li><li>A.3x/6x: Optical Input</li></ul>
209
+ | `bluetooth` | Bluetooth enabled / disabled | `bool` |
168
210
  | `bluetooth_toggle()` | Toggle Bluetooth | `func` |
169
211
 
170
212
  ```python
171
213
  """Example"""
172
214
  # Setting device name
173
215
  vssl.settings.name = 'My House'
174
- # Setting optical input name
175
- vssl.settings.optical_input_name = 'Optical Input 1'
216
+ # Setting bus 2 name
217
+ vssl.settings.bus_2_name = 'Optical Input'
176
218
  # Enable Bluetooth
177
219
  vssl.settings.bluetooth = True
178
220
  # Toggle Bluetooth
@@ -283,28 +325,38 @@ zone1.transport.state = ZoneTransport.States.PAUSE
283
325
 
284
326
  | Property | Description | Type | Values |
285
327
  | ---------------------- | ----------- | ----------- |----------- |
286
- | `source` | Change input source | `int` | `InputRouter.Sources`
287
- | `priority` | Change input priority. Stream or analog in higher priority | `int` | `InputRouter.Priorities`
328
+ | `source` | Change input source.<br/>Source to be played out the zones speakers | `int` | `InputRouter.Sources`
329
+ | `priority` | Change input priority.<br/>Stream or local to have precedence | `int` | `InputRouter.Priorities`
288
330
 
289
- ### Priority Order:
331
+
332
+ ### A.1(x) Source Routing Order
333
+ A.1 and A.1x don't support manually changing the input source. Instead a fixed source routing order is used:
334
+
335
+ 1. Optical Input
336
+ 2. Coaxial Input
337
+ 3. Analog Input
338
+
339
+ Input `InputRouter.Priorities` still apply.
340
+
341
+ ### Input Priority / Precedence
290
342
 
291
343
  | `InputRouter.Priorities` | Priority Order |
292
344
  | ---------------------- | ----------- |
293
- | **`STREAM`** | <ol><li>Stream</li><li>Party Zone</li><li>Bus 1 In</li><li>Bus 2 In</li><li>Analog Input</li></ol>
294
- | **`LOCAL`** | <ol><li>Bus 1 In</li><li>Bus 2 In</li><li>Analog Input</li><li>Stream</li><li>Party Zone</li></ol>
345
+ | **`STREAM`** | <ol><li>Stream</li><li>Party Zone</li><li>Bus 1</li><li>Bus 2</li><li>Optical</li><li>Coaxial</li><li>Analog</li></ol>
346
+ | **`LOCAL`** | <ol><li>Bus 1</li><li>Bus 2</li><li>Optical</li><li>Coaxial</li><li>Analog</li><li>Stream</li><li>Party Zone</li></ol>
295
347
 
296
348
  ```python
297
349
  """Example"""
298
350
  # Change zone 1 to listen to analog input 4
299
351
  zone1.input.source = InputRouter.Sources.ANALOG_IN_4
300
352
 
301
- # Change zone 1 to perfer analog input (local) over stream
353
+ # Change zone 1 to perfer local inputs over stream
302
354
  zone1.input.priority = InputRouter.Priorities.LOCAL
303
355
  ```
304
356
 
305
357
  ## `Zone.group`
306
358
 
307
- Officially unsupported in X series amplifiers.
359
+ Unsupported on X series amplifiers.
308
360
 
309
361
  | Property | Description | Type | Values |
310
362
  | ---------------------- | ----------- | ----------- |----------- |
@@ -335,7 +387,7 @@ zone1.group.is_party_zone_member_toggle()
335
387
 
336
388
  | Property | Description | Type | Values | Default |
337
389
  | ---------------------- | ----------- | ----------- |----------- |----------- |
338
- | `source` | Where the AO is routed from. i.e a zone, optical input or off | `int` | `AnalogOutput.Sources` | `Off`
390
+ | `source` | Where the AO is routed from. i.e stream, optical input or off | `int` | `AnalogOutput.Sources` | `Off`
339
391
  | `is_fixed_volume` | Fix the output volume. Output wont respond to volume control | `bool` | |`False`
340
392
  | `is_fixed_volume_toggle()` | Toggle fixed volume | `func` |
341
393
 
@@ -443,55 +495,6 @@ zone1.settings.eq.khz1_db = -2
443
495
  zone1.settings.subwoofer.crossover = 100
444
496
  ```
445
497
 
446
-
447
-
448
- ## Another (Lite) Way
449
-
450
- If you perfer to not run the complete intergration, you can send basic HEX commands to the VSSL device using [Netcat](https://nc110.sourceforge.io/) (or any network tool) on port `50002`.
451
-
452
- | HEX | Description |
453
- | ---------------------- | ----------- |
454
- | `\x10\x05\x03\x0{Zone Number}\xff\x03` | Volume Up
455
- | `\x10\x05\x03\x0{Zone Number}\xfe\x03` | Volume Down
456
- | `\x10\x11\x02\x0{Zone Number}\x01` | Mute
457
- | All commands can be found by looking [here](https://github.com/vsslctrl/vsslctrl/blob/2c43c2f2393b94bc0e062d2ab90144343eca16ef/vsslctrl/api_alpha.py) |
458
-
459
-
460
- The `volume up` HEX command for `Zone 2` would be `\x10\x05\x03\x02\xff\x03`
461
-
462
- Now send the raw HEX using Netcat to the device using this syntax:
463
-
464
- `echo -e "{HEX Command}" | nc {IP Address} 50002`
465
-
466
- For example to send `volume up` to `Zone 2`:
467
-
468
- `echo -e "\x10\x05\x03\x02\xff\x03" | nc 192.168.1.11 50002`
469
-
470
- Home Assistant `Configuration.yaml` example:
471
-
472
- ```ymal
473
- ...
474
-
475
- shell_command:
476
- #Zone 1
477
- vssl_zone_1_volume_up: 'echo -e "\x10\x05\x03\x01\xff\x03" | nc 192.168.1.10 50002'
478
- vssl_zone_1_volume_down: 'echo -e "\x10\x05\x03\x01\xfe\x03" | nc 192.168.1.10 50002'
479
- vssl_zone_1_mute: 'echo -e "\x10\x11\x02\x01\x01" | nc 192.168.1.10 50002'
480
- vssl_zone_1_unmute: 'echo -e "\x10\x11\x02\x01\x00" | nc 192.168.1.10 50002'
481
- #Zone 2
482
- vssl_zone_2_volume_up: 'echo -e "\x10\x05\x03\x02\xff\x03" | nc 192.168.1.11 50002'
483
- vssl_zone_2_volume_down: 'echo -e "\x10\x05\x03\x02\xfe\x03" | nc 192.168.1.11 50002'
484
- vssl_zone_2_mute: 'echo -e "\x10\x11\x02\x02\x01" | nc 192.168.1.11 50002'
485
- vssl_zone_2_unmute: 'echo -e "\x10\x11\x02\x02\x00" | nc 192.168.1.11 50002'
486
- #Zone 3
487
- vssl_zone_3_volume_up: 'echo -e "\x10\x05\x03\x03\xff\x03" | nc 192.168.1.12 50002'
488
- vssl_zone_3_volume_down: 'echo -e "\x10\x05\x03\x03\xfe\x03" | nc 192.168.1.12 50002'
489
- vssl_zone_3_mute: 'echo -e "\x10\x11\x02\x03\x01" | nc 192.168.1.12 50002'
490
- vssl_zone_3_unmute: 'echo -e "\x10\x11\x02\x03\x00" | nc 192.168.1.12 50002'
491
-
492
- ...
493
- ```
494
-
495
498
  ## Credit
496
499
 
497
500
  Thanks to [@dj-jam](https://github.com/dj-jam) for the continued testing.
@@ -505,17 +508,9 @@ Motivation for this project was to integrate VSSLs amplifiers into [Home Assista
505
508
  * Not tested on A.1x or original A series range of amplifiers (testers welcome)
506
509
  * VSSL can not start a stream except for playing a URL directly. This is a limitation of the hardware itself.
507
510
  * Not all sources set the volume to 0 when the zone is muted
508
- * Grouping feedback is flaky on the X series amplifiers
509
511
  * Airplay `Zone.track.progress` is not available.
510
512
  * Cant stop a URL playback, feedback is worng at least
511
513
  * VSSL likes to cache old track metadata. For example when playing a URL after Spotify, often the device will respond with the previous (Spotify) tracks metadata
512
514
  * `stop()` is intended to disconnect the client and pause the stream. Doesn’t always function this way, depending on stream source
513
515
  * Occasionally a zones might stop responding to certain commands, issuing the `reboot` command generally corrects
514
516
 
515
- ## Future
516
-
517
- * A.1(x) coverage i.e Bluetooth
518
- * REST API / Web App
519
- * Save and recall EQ
520
- * IR Control
521
-
@@ -1,27 +1,43 @@
1
1
  # vsslctrl
2
2
 
3
- Package for controlling [VSSL's](https://www.vssl.com/) range of streaming amplifiers.
3
+ Package for controlling [VSSL's](https://www.vssl.com/) range of streaming amplifiers.
4
4
 
5
- **`vsslctrl` is not endorsed or affiliated with [VSSL](https://www.vssl.com/) in any manner.**
5
+ ## Coverage
6
+
7
+ Tested on:
8
+
9
+ | Model | Software Version | Note |
10
+ | ------------|--------- | -------------
11
+ | A.3x | p15305.016.3701 |
12
+
13
+
14
+ Home Assistant [integration](https://github.com/vsslctrl/integration.home-assistant) with basic functionality working on:
6
15
 
7
- ## Help
16
+ | Model | Software Version | User Reported |
17
+ | ------------|--------- | -------------
18
+ | A.1 | p15265.033.3703 | ✔️
19
+ | A.3 | p12013.141.3703 | ✔️
20
+ | A.3x | p15305.016.3701 |
21
+ | A.6x | p15305.017.3701 | ✔️
22
+
23
+
24
+ ## Testers Needed
8
25
 
9
26
  I am looking for testers with any VSSL amplifier models, please get in touch if you interested in helping. <vsslcontrolled@proton.me>
10
27
 
11
- Tested on:
12
- - **A.1** software version **p15265.033.3703** via Home Assistant [integration](https://github.com/vsslctrl/integration.home-assistant) (reported)
13
- - **A.3** software version **p12013.141.3703** via Home Assistant [integration](https://github.com/vsslctrl/integration.home-assistant) (reported)
14
- - **A.3x** software version **p15305.016.3701**
15
- - **A.6x** software version **p15305.017.3701** via Home Assistant [integration](https://github.com/vsslctrl/integration.home-assistant) (reported)
28
+
16
29
 
17
30
  ## Important
18
31
 
19
- There should not be any *[VSSL Agent's](https://vssl.gitbook.io/vssl-rest-api/getting-started/start)* running on the same network. If you dont know what this is, then you can ignore this notice.
32
+ There should not be any *[VSSL Agent's](https://vssl.gitbook.io/vssl-rest-api/getting-started/start)* running on the network. If you dont know what this is, then you can ignore this notice.
33
+
34
+ **`vsslctrl` is not endorsed or affiliated with [VSSL](https://www.vssl.com/) in any manner.**
20
35
 
21
36
  ## TODOs
22
37
 
23
- * **A.1(x)** specific control e.g bluetooth
24
38
  * Better test coverage
39
+ * A.1(x) testing - e.g output settings
40
+ * More controls - e.g IR Control
25
41
 
26
42
  ## Basic Usage
27
43
 
@@ -37,7 +53,7 @@ async def main():
37
53
 
38
54
  # Represents a physical VSSL amplifier
39
55
  vssl = Vssl(DeviceModels.A1)
40
- a1 = vssl.add_zone(ZoneIDs.A1, '192.168.1.10')
56
+ a1 = vssl.add_zone('192.168.1.10')
41
57
 
42
58
  # Connect and initiate zones.
43
59
  await vssl.initialise()
@@ -67,14 +83,13 @@ from vsslctrl import Vssl, DeviceModels, Zone, ZoneIDs
67
83
  async def main():
68
84
 
69
85
  # Represents a physical VSSL amplifier
70
- # If no DeviceModels is passed, vsslctrl will default to the feature set of the X series amps
71
86
  vssl = Vssl(DeviceModels.A3X)
72
87
 
73
88
  # Add each you wish to control
74
- zone1 = vssl.add_zone(ZoneIDs.ZONE_1, '192.168.1.10')
75
- zone2 = vssl.add_zone(ZoneIDs.ZONE_2, '192.168.1.11')
76
- zone3 = vssl.add_zone(ZoneIDs.ZONE_3, '192.168.1.12')
77
- #... up to 6 zones
89
+ zone1 = vssl.add_zone('192.168.1.10', ZoneIDs.ZONE_1)
90
+ zone2 = vssl.add_zone('192.168.1.11', ZoneIDs.ZONE_2)
91
+ zone3 = vssl.add_zone('192.168.1.12', ZoneIDs.ZONE_3)
92
+ #... up to 6 zones for A.6(x)
78
93
 
79
94
  # Connect and initiate zones.
80
95
  await vssl.initialise()
@@ -98,9 +113,36 @@ async def main():
98
113
  asyncio.run(main())
99
114
  ```
100
115
 
116
+ # `DeviceModels`
117
+
118
+ A device model has to be passed to VSSL so it knows internally what features are supported by the device.
119
+ This might be removed in the future if we can differentiate different models from the API.
120
+
121
+ | Property | Description |
122
+ | ------------|--------- |
123
+ | `A1X` | A.1x |
124
+ | `A3X` | A.3x |
125
+ | `A6X` | A.6x |
126
+ | `A1` | A1 |
127
+ | `A3` | A3 |
128
+ | `A6` | A6 |
129
+
130
+ # `ZoneIDs`
131
+
132
+ | Property | Description |
133
+ | ------------|--------- |
134
+ | `A1` | A.1(x) Only |
135
+ | `ZONE_1` | Zone 1 of A.3(x) and A.6(x) |
136
+ | `ZONE_2` | Zone 2 of A.3(x) and A.6(x) |
137
+ | `ZONE_3` | Zone 3 of A.3(x) and A.6(x) |
138
+ | `ZONE_4` | Zone 4 of A.6(x) |
139
+ | `ZONE_5` | Zone 5 of A.6(x) |
140
+ | `ZONE_6` | Zone 6 of A.6(x) |
141
+
142
+
101
143
  # API
102
144
 
103
- Most functionality is achived via `getters` and `setters` of the two main classes `Vssl`, `Zone`.
145
+ Most functionality is achieved via `getters` and `setters` of the two main classes `Vssl`, `Zone`.
104
146
 
105
147
  The classes will update the physical VSSL device when setting a property and once feedback has been received, the classes internal state will be updated. For example:
106
148
 
@@ -117,7 +159,6 @@ print(zone_name)
117
159
 
118
160
  **Important** in the above example, `zone1.settings.name` wont be set to its new value until after the VSSL device has changed the name and the `Zone` class has received confirmation feedback. If you need to wait for the value change, you can await a `[property_name]_CHANGE` events.
119
161
 
120
-
121
162
  # `Vssl`
122
163
 
123
164
  | Property | Description | Type |
@@ -139,19 +180,20 @@ vssl.factory_reset()
139
180
 
140
181
  ## `Vssl.settings`
141
182
 
142
- | Property | Description | Type |
143
- | ---------------------- | ----------- | ----------- |
144
- | `name` | Device name | `str`
145
- | `optical_input_name` | Name of the optical input | `str`
146
- | `bluetooth` | Bluetooth enabled / disabled | `bool`
183
+ | Property | Description | Type | Model: Default |
184
+ | ---------------------- | ----------- | ----------- | ----------- |
185
+ | `name` | Device name | `str` |
186
+ | `bus_1_name` | Name of Bus 1 | `str` | <ul><li>A.1: Optical Input</li><li>A.3x/6x: Not Used</li></ul>
187
+ | `bus_2_name` | Name of Bus 2 | `str` | <ul><li>A.1: Coax Input</li><li>A.3x/6x: Optical Input</li></ul>
188
+ | `bluetooth` | Bluetooth enabled / disabled | `bool` |
147
189
  | `bluetooth_toggle()` | Toggle Bluetooth | `func` |
148
190
 
149
191
  ```python
150
192
  """Example"""
151
193
  # Setting device name
152
194
  vssl.settings.name = 'My House'
153
- # Setting optical input name
154
- vssl.settings.optical_input_name = 'Optical Input 1'
195
+ # Setting bus 2 name
196
+ vssl.settings.bus_2_name = 'Optical Input'
155
197
  # Enable Bluetooth
156
198
  vssl.settings.bluetooth = True
157
199
  # Toggle Bluetooth
@@ -262,28 +304,38 @@ zone1.transport.state = ZoneTransport.States.PAUSE
262
304
 
263
305
  | Property | Description | Type | Values |
264
306
  | ---------------------- | ----------- | ----------- |----------- |
265
- | `source` | Change input source | `int` | `InputRouter.Sources`
266
- | `priority` | Change input priority. Stream or analog in higher priority | `int` | `InputRouter.Priorities`
307
+ | `source` | Change input source.<br/>Source to be played out the zones speakers | `int` | `InputRouter.Sources`
308
+ | `priority` | Change input priority.<br/>Stream or local to have precedence | `int` | `InputRouter.Priorities`
267
309
 
268
- ### Priority Order:
310
+
311
+ ### A.1(x) Source Routing Order
312
+ A.1 and A.1x don't support manually changing the input source. Instead a fixed source routing order is used:
313
+
314
+ 1. Optical Input
315
+ 2. Coaxial Input
316
+ 3. Analog Input
317
+
318
+ Input `InputRouter.Priorities` still apply.
319
+
320
+ ### Input Priority / Precedence
269
321
 
270
322
  | `InputRouter.Priorities` | Priority Order |
271
323
  | ---------------------- | ----------- |
272
- | **`STREAM`** | <ol><li>Stream</li><li>Party Zone</li><li>Bus 1 In</li><li>Bus 2 In</li><li>Analog Input</li></ol>
273
- | **`LOCAL`** | <ol><li>Bus 1 In</li><li>Bus 2 In</li><li>Analog Input</li><li>Stream</li><li>Party Zone</li></ol>
324
+ | **`STREAM`** | <ol><li>Stream</li><li>Party Zone</li><li>Bus 1</li><li>Bus 2</li><li>Optical</li><li>Coaxial</li><li>Analog</li></ol>
325
+ | **`LOCAL`** | <ol><li>Bus 1</li><li>Bus 2</li><li>Optical</li><li>Coaxial</li><li>Analog</li><li>Stream</li><li>Party Zone</li></ol>
274
326
 
275
327
  ```python
276
328
  """Example"""
277
329
  # Change zone 1 to listen to analog input 4
278
330
  zone1.input.source = InputRouter.Sources.ANALOG_IN_4
279
331
 
280
- # Change zone 1 to perfer analog input (local) over stream
332
+ # Change zone 1 to perfer local inputs over stream
281
333
  zone1.input.priority = InputRouter.Priorities.LOCAL
282
334
  ```
283
335
 
284
336
  ## `Zone.group`
285
337
 
286
- Officially unsupported in X series amplifiers.
338
+ Unsupported on X series amplifiers.
287
339
 
288
340
  | Property | Description | Type | Values |
289
341
  | ---------------------- | ----------- | ----------- |----------- |
@@ -314,7 +366,7 @@ zone1.group.is_party_zone_member_toggle()
314
366
 
315
367
  | Property | Description | Type | Values | Default |
316
368
  | ---------------------- | ----------- | ----------- |----------- |----------- |
317
- | `source` | Where the AO is routed from. i.e a zone, optical input or off | `int` | `AnalogOutput.Sources` | `Off`
369
+ | `source` | Where the AO is routed from. i.e stream, optical input or off | `int` | `AnalogOutput.Sources` | `Off`
318
370
  | `is_fixed_volume` | Fix the output volume. Output wont respond to volume control | `bool` | |`False`
319
371
  | `is_fixed_volume_toggle()` | Toggle fixed volume | `func` |
320
372
 
@@ -422,55 +474,6 @@ zone1.settings.eq.khz1_db = -2
422
474
  zone1.settings.subwoofer.crossover = 100
423
475
  ```
424
476
 
425
-
426
-
427
- ## Another (Lite) Way
428
-
429
- If you perfer to not run the complete intergration, you can send basic HEX commands to the VSSL device using [Netcat](https://nc110.sourceforge.io/) (or any network tool) on port `50002`.
430
-
431
- | HEX | Description |
432
- | ---------------------- | ----------- |
433
- | `\x10\x05\x03\x0{Zone Number}\xff\x03` | Volume Up
434
- | `\x10\x05\x03\x0{Zone Number}\xfe\x03` | Volume Down
435
- | `\x10\x11\x02\x0{Zone Number}\x01` | Mute
436
- | All commands can be found by looking [here](https://github.com/vsslctrl/vsslctrl/blob/2c43c2f2393b94bc0e062d2ab90144343eca16ef/vsslctrl/api_alpha.py) |
437
-
438
-
439
- The `volume up` HEX command for `Zone 2` would be `\x10\x05\x03\x02\xff\x03`
440
-
441
- Now send the raw HEX using Netcat to the device using this syntax:
442
-
443
- `echo -e "{HEX Command}" | nc {IP Address} 50002`
444
-
445
- For example to send `volume up` to `Zone 2`:
446
-
447
- `echo -e "\x10\x05\x03\x02\xff\x03" | nc 192.168.1.11 50002`
448
-
449
- Home Assistant `Configuration.yaml` example:
450
-
451
- ```ymal
452
- ...
453
-
454
- shell_command:
455
- #Zone 1
456
- vssl_zone_1_volume_up: 'echo -e "\x10\x05\x03\x01\xff\x03" | nc 192.168.1.10 50002'
457
- vssl_zone_1_volume_down: 'echo -e "\x10\x05\x03\x01\xfe\x03" | nc 192.168.1.10 50002'
458
- vssl_zone_1_mute: 'echo -e "\x10\x11\x02\x01\x01" | nc 192.168.1.10 50002'
459
- vssl_zone_1_unmute: 'echo -e "\x10\x11\x02\x01\x00" | nc 192.168.1.10 50002'
460
- #Zone 2
461
- vssl_zone_2_volume_up: 'echo -e "\x10\x05\x03\x02\xff\x03" | nc 192.168.1.11 50002'
462
- vssl_zone_2_volume_down: 'echo -e "\x10\x05\x03\x02\xfe\x03" | nc 192.168.1.11 50002'
463
- vssl_zone_2_mute: 'echo -e "\x10\x11\x02\x02\x01" | nc 192.168.1.11 50002'
464
- vssl_zone_2_unmute: 'echo -e "\x10\x11\x02\x02\x00" | nc 192.168.1.11 50002'
465
- #Zone 3
466
- vssl_zone_3_volume_up: 'echo -e "\x10\x05\x03\x03\xff\x03" | nc 192.168.1.12 50002'
467
- vssl_zone_3_volume_down: 'echo -e "\x10\x05\x03\x03\xfe\x03" | nc 192.168.1.12 50002'
468
- vssl_zone_3_mute: 'echo -e "\x10\x11\x02\x03\x01" | nc 192.168.1.12 50002'
469
- vssl_zone_3_unmute: 'echo -e "\x10\x11\x02\x03\x00" | nc 192.168.1.12 50002'
470
-
471
- ...
472
- ```
473
-
474
477
  ## Credit
475
478
 
476
479
  Thanks to [@dj-jam](https://github.com/dj-jam) for the continued testing.
@@ -484,17 +487,9 @@ Motivation for this project was to integrate VSSLs amplifiers into [Home Assista
484
487
  * Not tested on A.1x or original A series range of amplifiers (testers welcome)
485
488
  * VSSL can not start a stream except for playing a URL directly. This is a limitation of the hardware itself.
486
489
  * Not all sources set the volume to 0 when the zone is muted
487
- * Grouping feedback is flaky on the X series amplifiers
488
490
  * Airplay `Zone.track.progress` is not available.
489
491
  * Cant stop a URL playback, feedback is worng at least
490
492
  * VSSL likes to cache old track metadata. For example when playing a URL after Spotify, often the device will respond with the previous (Spotify) tracks metadata
491
493
  * `stop()` is intended to disconnect the client and pause the stream. Doesn’t always function this way, depending on stream source
492
494
  * Occasionally a zones might stop responding to certain commands, issuing the `reboot` command generally corrects
493
495
 
494
- ## Future
495
-
496
- * A.1(x) coverage i.e Bluetooth
497
- * REST API / Web App
498
- * Save and recall EQ
499
- * IR Control
500
-
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vsslctrl"
7
- version = "0.1.10.dev1"
7
+ version = "0.1.12.dev1"
8
8
  description = "Package for controlling VSSL's range of streaming amplifiers"
9
9
  authors = [
10
10
  { name="vsslctrl", email="vsslcontrolled@proton.me" },