Sonos Sub Audio Level

The ability to control a Sonos Subwoofer’s volume (The actual Sonos self-powered version) was added in March of 22, but there is no control for the similarly named “Sub Audio Level” which is a control in the Sonos app which controls the audio level of the “Subwoofer” Audio output on the back of the Sonos Amp and Sonos Amp2. This level controls the volume of an “Add On”, wired (not Sonos Branded) powered subwoofer. This would be a HUGE win.

Don’t forget to vote for your own request!

This is likely straightforward to add, but I unfortunately do not have a device to test with. Would you be able to provide info and run scripts to help move this along?

@rosshenning If you can run this script and adjust the “Sub Audio Level” in the Sonos app to its min & max values, hopefully this will print out what we need to get started.

Make sure to change the IP address to the Amp before running. The script will listen for updates for 30 seconds and then exit.

sub_test.py

import asyncio
from datetime import datetime
from pprint import pformat

import soco
import soco.config
from soco import events_asyncio

soco.config.EVENTS_MODULE = events_asyncio

# SET ME
amp = soco.SoCo("10.6.9.224")


def print_event(event):
    print(
        "{} - {} [{}]:\n{}".format(
            datetime.now(),
            event.service.soco.ip_address,
            event.service.service_type,
            pformat(event.variables, indent=4, width=180, compact=True),
        )
    )


async def main():
    sub = await amp.renderingControl.subscribe()
    sub.callback = print_event
    await asyncio.sleep(30)
    await sub.unsubscribe()
    await events_asyncio.event_listener.async_stop()


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Save the above in a file like sub_test.py and run it with python sub_test.py. You’ll need the soco package installed. That can likely be installed with pip install soco if it’s not already available.

Hi jjlawren,
My apologies for not seeing this sooner. My notifications must be going to spam or something. I just happened upon this answer. I’m not familiar with running a script like this. I’m an “old school” guy who learned Basic, Java, C# back in the day, but python is something I haven’t tackled. Would I run this on my HA Device, or would I need to install Python somewhere else?

Thanks

Hi jjlawren,
Okay…after I played with it a few minutes, I figured it out. Here’s the output you requested:

2023-03-01 12:51:39.037327 - 192.168.1.202 [RenderingControl]:
{ ‘audio_delay’: ‘0’,
‘audio_delay_left_rear’: ‘1’,
‘audio_delay_right_rear’: ‘1’,
‘bass’: ‘10’,
‘dialog_level’: ‘0’,
‘height_channel_level’: ‘0’,
‘loudness’: {‘Master’: ‘1’},
‘music_surround_level’: ‘0’,
‘mute’: {‘LF’: ‘0’, ‘Master’: ‘0’, ‘RF’: ‘0’},
‘night_mode’: ‘0’,
‘output_fixed’: ‘0’,
‘preset_name_list’: ‘FactoryDefaults’,
‘sonar_calibration_available’: ‘0’,
‘sonar_enabled’: ‘0’,
‘speaker_size’: ‘1’,
‘sub_crossover’: ‘80’,
‘sub_enabled’: ‘1’,
‘sub_gain’: ‘11’,
‘sub_polarity’: ‘0’,
‘surround_enabled’: ‘0’,
‘surround_level’: ‘3’,
‘surround_mode’: ‘0’,
‘treble’: ‘10’,
‘volume’: {‘LF’: ‘100’, ‘Master’: ‘19’, ‘RF’: ‘100’}}
2023-03-01 12:51:54.325275 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘11’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:54.624547 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:54.879164 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:55.558797 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:55.862212 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘5’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:56.078208 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-1’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:56.374836 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:56.612679 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-14’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:56.884506 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:57.138630 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:58.299701 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-14’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:58.553346 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-3’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:58.807031 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘1’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:59.059443 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘6’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:59.314020 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘8’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:59.570828 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:51:59.821469 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)
handle: <Handle _ProactorBasePipeTransport._call_connection_lost(None)>
Traceback (most recent call last):
File “C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2800.0_x64__qbz5n2kfra8p0\lib\asyncio\events.py”, line 80, in _run
self._context.run(self._callback, *self._args)
File “C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2800.0_x64__qbz5n2kfra8p0\lib\asyncio\proactor_events.py”, line 165, in _call_connection_lost
self._sock.shutdown(socket.SHUT_RDWR)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
2023-03-01 12:52:01.065528 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:01.324556 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘91’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:01.576634 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘97’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:01.829675 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘103’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:02.080524 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘106’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:02.336738 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘109’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:02.592335 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘110’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:02.846189 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘110’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:03.105013 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘105’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:03.357477 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘94’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:03.655515 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘84’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:03.911808 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘78’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:04.167277 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘75’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:04.374521 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘65’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:04.678006 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘59’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:04.890955 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘55’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:05.188887 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘50’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:05.419789 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘50’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:05.698839 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘50’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}

C:\Users\rossh\Documents>python sonos-sub.py
2023-03-01 12:52:17.029124 - 192.168.1.202 [RenderingControl]:
{ ‘audio_delay’: ‘0’,
‘audio_delay_left_rear’: ‘1’,
‘audio_delay_right_rear’: ‘1’,
‘bass’: ‘10’,
‘dialog_level’: ‘0’,
‘height_channel_level’: ‘0’,
‘loudness’: {‘Master’: ‘1’},
‘music_surround_level’: ‘0’,
‘mute’: {‘LF’: ‘0’, ‘Master’: ‘0’, ‘RF’: ‘0’},
‘night_mode’: ‘0’,
‘output_fixed’: ‘0’,
‘preset_name_list’: ‘FactoryDefaults’,
‘sonar_calibration_available’: ‘0’,
‘sonar_enabled’: ‘0’,
‘speaker_size’: ‘1’,
‘sub_crossover’: ‘95’,
‘sub_enabled’: ‘1’,
‘sub_gain’: ‘10’,
‘sub_polarity’: ‘0’,
‘surround_enabled’: ‘0’,
‘surround_level’: ‘3’,
‘surround_mode’: ‘0’,
‘treble’: ‘10’,
‘volume’: {‘LF’: ‘100’, ‘Master’: ‘19’, ‘RF’: ‘100’}}
2023-03-01 12:52:18.973951 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘1’}
2023-03-01 12:52:21.964114 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:25.794801 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:26.048878 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:26.261905 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:26.793480 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:27.086520 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘11’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:27.295550 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘9’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:27.551072 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:27.805638 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-14’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:28.060370 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-15’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:29.017947 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:29.274485 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-9’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:29.529782 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-5’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:29.781808 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-3’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:30.031332 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘-2’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:30.283859 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘0’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:30.539264 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘1’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:30.796132 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘3’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:31.050946 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘6’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:31.308725 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘8’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:31.560934 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘10’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:31.815462 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘11’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:32.069480 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:32.322667 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘95’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:32.834669 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘92’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:33.090243 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘69’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:33.346762 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘55’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:33.643817 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘50’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:34.349140 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘50’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:34.583028 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘64’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:34.856703 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘84’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:35.111268 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘87’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:35.321827 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘90’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:36.574960 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘79’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:36.848766 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘78’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:37.772350 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘78’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:38.030373 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘66’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:40.020075 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘68’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:40.271670 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘88’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:40.525694 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘92’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:41.318764 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘90’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:41.575790 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘82’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:41.831825 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘81’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:42.082745 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘81’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:42.337053 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:42.588712 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘1’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}
2023-03-01 12:52:44.471534 - 192.168.1.202 [RenderingControl]:
{‘speaker_size’: ‘1’, ‘sub_crossover’: ‘80’, ‘sub_enabled’: ‘0’, ‘sub_gain’: ‘12’, ‘sub_polarity’: ‘0’}

C:\Users\rossh\Documents>

Can you explain what you were adjusting in the Sonos app during these tests? I see both sub_crossover and sub_gain changing at different times.

Also if you’re able to share a screenshot of the adjustment slider it would be interesting to see.

Sure thing. There’s actually two sliders for the subwoofer output. Gain and Crossover point. I thought you’d probably want to see values for both being generated, so I moved both sliders.

Okay, that wasn’t clear from the original post and I don’t have a sub myself to test with. Thanks for the explanation and screenshot, those make things much clearer.

What are the upper and lower limits for each slider in the Sonos app? Is it 50-110Hz on the crossover and -15 to +15 on the gain?

You have the limits correct on both…I just double-checked.

Now that I’ve had a chance to sit down and look/remember, “sub gain” controls were added to the underlying library and HA integration about a year ago. Is this different from what you’re looking for?

The crossover controls can still be added.

@rosshenning can you see if this script changes the subwoofer crossover level? It’s a guess so I’ll need a tester.

import soco

# SET ME
amp = soco.SoCo("10.6.9.224")
frequency = 110

amp.renderingControl.SetEQ(
    [
        ("InstanceID", 0),
        ("EQType", "SubCrossover"),
        ("DesiredValue", int(frequency)),
    ]
)

Run a couple times with different frequency values and see if it changes as expected in the native Sonos app.

Also, if would be interesting if you could attach the XML returned by the Amp which has a paired sub: http://<AMP_IP_HERE>:1400/xml/RenderingControl1.xml

Sub gain isn’t showing up as entities for any of my Sonos units and all of mine have third party subs. I have a feeling the sub gain that is published is for Sonos branded subs, which seem to be addressed differently than third party.

The new script works correctly. I am able to change the subwoofer crossover frequency with no errors.

Here is the output from the render:

<scpd xmlns="urn:schemas-upnp-org:service-1-0">
    <specVersion>
        <major>1</major>
        <minor>0</minor>
    </specVersion>
    <serviceStateTable>
        <stateVariable sendEvents="yes">
            <name>LastChange</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Mute</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Volume</name>
            <dataType>ui2</dataType>
            <allowedValueRange>
                <minimum>0</minimum>
                <maximum>100</maximum>
                <step>1</step>
            </allowedValueRange>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_LeftVolume</name>
            <dataType>ui2</dataType>
            <allowedValueRange>
                <minimum>0</minimum>
                <maximum>100</maximum>
                <step>1</step>
            </allowedValueRange>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_RightVolume</name>
            <dataType>ui2</dataType>
            <allowedValueRange>
                <minimum>0</minimum>
                <maximum>100</maximum>
                <step>1</step>
            </allowedValueRange>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>VolumeDB</name>
            <dataType>i2</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Bass</name>
            <dataType>i2</dataType>
            <allowedValueRange>
                <minimum>-10</minimum>
                <maximum>10</maximum>
                <step>1</step>
            </allowedValueRange>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Treble</name>
            <dataType>i2</dataType>
            <allowedValueRange>
                <minimum>-10</minimum>
                <maximum>10</maximum>
                <step>1</step>
            </allowedValueRange>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>EQValue</name>
            <dataType>i2</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_EQType</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Loudness</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SupportsOutputFixed</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>OutputFixed</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>HeadphoneConnected</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_Channel</name>
            <dataType>string</dataType>
            <allowedValueList>
                <allowedValue>Master</allowedValue>
                <allowedValue>LF</allowedValue>
                <allowedValue>RF</allowedValue>
            </allowedValueList>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_MuteChannel</name>
            <dataType>string</dataType>
            <allowedValueList>
                <allowedValue>Master</allowedValue>
                <allowedValue>LF</allowedValue>
                <allowedValue>RF</allowedValue>
            </allowedValueList>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_InstanceID</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_VolumeAdjustment</name>
            <dataType>i4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_RampType</name>
            <dataType>string</dataType>
            <allowedValueList>
                <allowedValue>SLEEP_TIMER_RAMP_TYPE</allowedValue>
                <allowedValue>ALARM_RAMP_TYPE</allowedValue>
                <allowedValue>AUTOPLAY_RAMP_TYPE</allowedValue>
            </allowedValueList>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_RampTimeSeconds</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_ResetVolumeAfter</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_ProgramURI</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>A_ARG_TYPE_ChannelMap</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>AudioDelay</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>AudioDelayLeftRear</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>AudioDelayRightRear</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>DialogLevel</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SpeakerSize</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SubCrossover</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SubEnabled</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SubGain</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SubPolarity</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SurroundLevel</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>MusicSurroundLevel</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>NightMode</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SurroundEnabled</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>SurroundMode</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>PresetNameList</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>RoomCalibrationID</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>RoomCalibrationCoefficients</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>RoomCalibrationCalibrationMode</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>RoomCalibrationEnabled</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>RoomCalibrationAvailable</name>
            <dataType>boolean</dataType>
        </stateVariable>
    </serviceStateTable>
    <actionList>
        <action>
            <name>GetMute</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_MuteChannel</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentMute</name>
                    <direction>out</direction>
                    <relatedStateVariable>Mute</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetMute</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_MuteChannel</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredMute</name>
                    <direction>in</direction>
                    <relatedStateVariable>Mute</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>ResetBasicEQ</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Bass</name>
                    <direction>out</direction>
                    <relatedStateVariable>Bass</relatedStateVariable>
                </argument>
                <argument>
                    <name>Treble</name>
                    <direction>out</direction>
                    <relatedStateVariable>Treble</relatedStateVariable>
                </argument>
                <argument>
                    <name>Loudness</name>
                    <direction>out</direction>
                    <relatedStateVariable>Loudness</relatedStateVariable>
                </argument>
                <argument>
                    <name>LeftVolume</name>
                    <direction>out</direction>
                    <relatedStateVariable>A_ARG_TYPE_LeftVolume</relatedStateVariable>
                </argument>
                <argument>
                    <name>RightVolume</name>
                    <direction>out</direction>
                    <relatedStateVariable>A_ARG_TYPE_RightVolume</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>ResetExtEQ</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>EQType</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_EQType</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetVolume</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentVolume</name>
                    <direction>out</direction>
                    <relatedStateVariable>Volume</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetVolume</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredVolume</name>
                    <direction>in</direction>
                    <relatedStateVariable>Volume</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetRelativeVolume</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>Adjustment</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_VolumeAdjustment</relatedStateVariable>
                </argument>
                <argument>
                    <name>NewVolume</name>
                    <direction>out</direction>
                    <relatedStateVariable>Volume</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetVolumeDB</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentVolume</name>
                    <direction>out</direction>
                    <relatedStateVariable>VolumeDB</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetVolumeDB</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredVolume</name>
                    <direction>in</direction>
                    <relatedStateVariable>VolumeDB</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetVolumeDBRange</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>MinValue</name>
                    <direction>out</direction>
                    <relatedStateVariable>VolumeDB</relatedStateVariable>
                </argument>
                <argument>
                    <name>MaxValue</name>
                    <direction>out</direction>
                    <relatedStateVariable>VolumeDB</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetBass</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentBass</name>
                    <direction>out</direction>
                    <relatedStateVariable>Bass</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetBass</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredBass</name>
                    <direction>in</direction>
                    <relatedStateVariable>Bass</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetTreble</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentTreble</name>
                    <direction>out</direction>
                    <relatedStateVariable>Treble</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetTreble</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredTreble</name>
                    <direction>in</direction>
                    <relatedStateVariable>Treble</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetEQ</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>EQType</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_EQType</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentValue</name>
                    <direction>out</direction>
                    <relatedStateVariable>EQValue</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetEQ</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>EQType</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_EQType</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredValue</name>
                    <direction>in</direction>
                    <relatedStateVariable>EQValue</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetLoudness</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentLoudness</name>
                    <direction>out</direction>
                    <relatedStateVariable>Loudness</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetLoudness</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredLoudness</name>
                    <direction>in</direction>
                    <relatedStateVariable>Loudness</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetSupportsOutputFixed</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentSupportsFixed</name>
                    <direction>out</direction>
                    <relatedStateVariable>SupportsOutputFixed</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetOutputFixed</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentFixed</name>
                    <direction>out</direction>
                    <relatedStateVariable>OutputFixed</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetOutputFixed</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredFixed</name>
                    <direction>in</direction>
                    <relatedStateVariable>OutputFixed</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetHeadphoneConnected</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>CurrentHeadphoneConnected</name>
                    <direction>out</direction>
                    <relatedStateVariable>HeadphoneConnected</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>RampToVolume</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
                <argument>
                    <name>RampType</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_RampType</relatedStateVariable>
                </argument>
                <argument>
                    <name>DesiredVolume</name>
                    <direction>in</direction>
                    <relatedStateVariable>Volume</relatedStateVariable>
                </argument>
                <argument>
                    <name>ResetVolumeAfter</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_ResetVolumeAfter</relatedStateVariable>
                </argument>
                <argument>
                    <name>ProgramURI</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_ProgramURI</relatedStateVariable>
                </argument>
                <argument>
                    <name>RampTime</name>
                    <direction>out</direction>
                    <relatedStateVariable>A_ARG_TYPE_RampTimeSeconds</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>RestoreVolumePriorToRamp</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>Channel</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetChannelMap</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>ChannelMap</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_ChannelMap</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetRoomCalibrationStatus</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>RoomCalibrationEnabled</name>
                    <direction>out</direction>
                    <relatedStateVariable>RoomCalibrationEnabled</relatedStateVariable>
                </argument>
                <argument>
                    <name>RoomCalibrationAvailable</name>
                    <direction>out</direction>
                    <relatedStateVariable>RoomCalibrationAvailable</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetRoomCalibrationStatus</name>
            <argumentList>
                <argument>
                    <name>InstanceID</name>
                    <direction>in</direction>
                    <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
                </argument>
                <argument>
                    <name>RoomCalibrationEnabled</name>
                    <direction>in</direction>
                    <relatedStateVariable>RoomCalibrationEnabled</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
    </actionList>
</scpd>

You’re not going to believe this, but I played with it and found a way to adjust the subwoofer level. Here’s your original code with my copy/change. This works:

import soco

SET ME

amp = soco.SoCo(“192.168.1.139”)
frequency = 80
level = 10

amp.renderingControl.SetEQ(
[
(“InstanceID”, 0),
(“EQType”, “SubGain”),
(“DesiredValue”, int(level)),
]
)

amp.renderingControl.SetEQ(
[
(“InstanceID”, 0),
(“EQType”, “SubCrossover”),
(“DesiredValue”, int(frequency)),
]
)

amp.renderingControl.SetEQ(
[
(“InstanceID”, 0),
(“EQType”, “SubPolarity”),
(“DesiredValue”, ‘0’), # Set to 0 or 180
]
)

I’ve not been able to get “SubEnabled” to work the same way.

It appears that the API to control the sub is identical, but we probably just need to detect 3rd party external subs in a different way.

Thanks for confirming that the proposed API calls work. Lucky guess. :stuck_out_tongue:

@rosshenning are you able to attach a diagnostics dump from the Sonos integration? It should contain the info we would need to understand how mark your system as containing a subwoofer.

Happy to attach a diagnostics dump, but I’m not sure how to obtain that?

Three dots on the Sonos card in Settings > Devices & Services > Download diagnostics.

There’s a lot of non Sonos stuff in the file that I don’t want to post out to the world, but here’s a section for one of the units:

      "RINCON_B8E937AB5E2E01400": {
        "available": true,
        "battery_info": {},
        "hardware_version": "1.17.3.1-1.1",
        "household_id": "Sonos_6l1WB964izNxwxoBYJajfV0sJC",
        "is_coordinator": true,
        "model_name": "Sonos Connect:Amp",
        "model_number": "ZP120",
        "software_version": "71.1-38080",
        "sonos_group_entities": [
          "media_player.master_bath_sonos"
        ],
        "subscription_address": "192.168.1.21:1400",
        "subscriptions_failed": false,
        "version": "15.1",
        "zone_name": "Master Bath",
        "_group_members_missing": [],
        "_last_activity": 507662.736595229,
        "_last_event_cache": {
          "DeviceProperties": {
            "zone_name": "Master Bath",
            "icon": null,
            "configuration": "1",
            "invisible": "0",
            "is_zone_bridge": "0",
            "wireless_mode": "0",
            "wireless_leaf_only": "0",
            "channel_freq": "2437",
            "behind_wifi_extender": "0",
            "wifi_enabled": "0",
            "eth_link": "1",
            "settings_replication_state": "RINCON_B8E937AB5E2E01400,23,RINCON_FFFFFFFFFFFF99999,0,RINCON_B8E937AB5E2E01400,24,RINCON_B8E9379D29D601400,1,RINCON_C438755A444E01400,361,RINCON_C438755A442A01400,4,RINCON_B8E937AB5E2E01400,449,RINCON_FFFFFFFFFFFF99999,0,RINCON_000E582CAE7E01400,8,RINCON_B8E937AB5E2E01400,0,RINCON_B8E937AB5E2E01400,102,RINCON_C438755A445101400,299,RINCON_C438755A442A01400,5,RINCON_C438755A445101400,6,RINCON_C438755A43BE01400,2,RINCON_B8E937AB5E2E01400,103,RINCON_B8E937AB5E2E01400,26",
            "secure_reg_state": "3",
            "is_idle": "1",
            "more_info": "TargetRoomName:Master Bath",
            "channel_map_set": null,
            "ht_sat_chan_map_set": null,
            "ht_bonded_zone_commit_state": "0",
            "orientation": "0",
            "last_changed_play_state": "STOPPED,,,",
            "available_room_calibration": null,
            "room_calibration_state": "4",
            "config_mode": null,
            "supports_audio_in": "1",
            "supports_audio_clip": "1"
          },
          "ContentDirectory": {
            "system_update_id": "4",
            "container_update_i_ds": "R:,1",
            "radio_location_update_id": "RINCON_C438755A444E01400,361"
          },
          "AVTransport": {
            "transport_state": "STOPPED",
            "current_play_mode": "REPEAT_ALL",
            "current_crossfade_mode": "1",
            "number_of_tracks": "9",
            "current_track": "1",
            "current_section": "0",
            "current_track_uri": "x-sonos-http:track%2f3003206.flac?sid=174&flags=24616&sn=10",
            "current_track_duration": "0:04:19",
            "current_track_meta_data": {
              "title": "Amie (Remastered  January 1992)",
              "parent_id": "-1",
              "item_id": "-1",
              "restricted": true,
              "resources": [
                {
                  "__type": "<class 'soco.data_structures.DidlResource'>",
                  "repr": "<DidlResource 'x-sonos-http:track%2f3003206.flac?sid=174&flags=24616&sn=10' at 0x7fbd5ade6530>"
                }
              ],
              "desc": null,
              "creator": "Pure Prairie League",
              "stream_content": "",
              "radio_show": "",
              "album_art_uri": "/getaa?s=1&u=x-sonos-http%3atrack%252f3003206.flac%3fsid%3d174%26flags%3d24616%26sn%3d10",
              "album": "Aimee And Other Hits"
            },
            "next_track_uri": "x-sonos-http:track%2f68709636.flac?sid=174&flags=24616&sn=10",
            "next_track_meta_data": {
              "title": "The Best of My Love (2013 Remaster)",
              "parent_id": "-1",
              "item_id": "-1",
              "restricted": true,
              "resources": [
                {
                  "__type": "<class 'soco.data_structures.DidlResource'>",
                  "repr": "<DidlResource 'x-sonos-http:track%2f68709636.flac?sid=174&flags=24616&sn=10' at 0x7fbd5ade42b0>"
                }
              ],
              "desc": null,
              "creator": "Eagles",
              "album_art_uri": "/getaa?s=1&u=x-sonos-http%3atrack%252f68709636.flac%3fsid%3d174%26flags%3d24616%26sn%3d10",
              "album": "On the Border (2013 Remaster)"
            },
            "enqueued_transport_uri": "file:///jffs/settings/trackqueue.rsq#0",
            "enqueued_transport_uri_meta_data": "",
            "playback_storage_medium": "NETWORK",
            "av_transport_uri": "x-rincon-queue:RINCON_B8E937AB5E2E01400#0",
            "av_transport_uri_meta_data": "",
            "next_av_transport_uri": "",
            "next_av_transport_uri_meta_data": "",
            "current_transport_actions": "Set, Stop, Pause, Play, X_DLNA_SeekTime, Next, Previous, X_DLNA_SeekTrackNr",
            "current_valid_play_modes": "SHUFFLE,REPEAT,REPEATONE,CROSSFADE",
            "direct_control_client_id": "",
            "direct_control_is_suspended": "0",
            "direct_control_account_id": "",
            "transport_status": "OK",
            "sleep_timer_generation": "0",
            "alarm_running": "0",
            "snooze_running": "0",
            "restart_pending": "0",
            "transport_play_speed": "NOT_IMPLEMENTED",
            "current_media_duration": "NOT_IMPLEMENTED",
            "record_storage_medium": "NOT_IMPLEMENTED",
            "possible_playback_storage_media": "NONE, NETWORK",
            "possible_record_storage_media": "NOT_IMPLEMENTED",
            "record_medium_write_status": "NOT_IMPLEMENTED",
            "current_record_quality_mode": "NOT_IMPLEMENTED",
            "possible_record_quality_modes": "NOT_IMPLEMENTED"
          },
          "AlarmClock": {
            "time_zone": "012c0b000102000003000202ffc4",
            "time_server": "0.sonostime.pool.ntp.org,1.sonostime.pool.ntp.org,2.sonostime.pool.ntp.org,3.sonostime.pool.ntp.org",
            "time_generation": "20000001",
            "alarm_list_version": "RINCON_000E58AF974601400:0",
            "time_format": "INV",
            "date_format": "INV",
            "daily_index_refresh_time": null
          },
          "ZoneGroupTopology": {
            "third_party_media_servers_x": "2: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"
          },
          "RenderingControl": {
            "volume": {
              "Master": "20",
              "LF": "100",
              "RF": "100"
            },
            "mute": {
              "Master": "0",
              "LF": "0",
              "RF": "0"
            },
            "bass": "3",
            "treble": "10",
            "loudness": {
              "Master": "0"
            },
            "output_fixed": "0",
            "speaker_size": "-1",
            "sub_gain": "0",
            "sub_crossover": "0",
            "sub_polarity": "0",
            "sub_enabled": "1",
            "sonar_enabled": "0",
            "sonar_calibration_available": "0",
            "preset_name_list": "FactoryDefaults"
          }
        },
        "enabled_entities": [
          "media_player.master_bath_sonos",
          "switch.master_bath_sonos_crossfade",
          "switch.master_bath_sonos_loudness",
          "number.master_bath_sonos_bass",
          "number.master_bath_sonos_treble"
        ],
        "media": {
          "album_name": "Aimee And Other Hits",
          "artist": "Pure Prairie League",
          "channel": null,
          "duration": 259,
          "image_url": "http://192.168.1.234:1400/getaa?s=1&u=x-sonos-http%3atrack%252f3003206.flac%3fsid%3d174%26flags%3d24616%26sn%3d10",
          "queue_position": 1,
          "playlist_name": null,
          "source_name": null,
          "title": "Amie (Remastered  January 1992)",
          "uri": "x-sonos-http:track%2f3003206.flac?sid=174&flags=24616&sn=10",
          "current_track_poll": {
            "Track": "1",
            "TrackDuration": "0:04:19",
            "TrackMetaData": "<DIDL-Lite xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" xmlns:r=\"urn:schemas-rinconnetworks-com:metadata-1-0/\" xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\"><item id=\"-1\" parentID=\"-1\" restricted=\"true\"><res protocolInfo=\"sonos.com-http:*:audio/flac:*\" duration=\"0:04:19\">x-sonos-http:track%2f3003206.flac?sid=174&amp;flags=24616&amp;sn=10</res><r:streamContent></r:streamContent><upnp:albumArtURI>/getaa?s=1&amp;u=x-sonos-http%3atrack%252f3003206.flac%3fsid%3d174%26flags%3d24616%26sn%3d10</upnp:albumArtURI><dc:title>Amie (Remastered  January 1992)</dc:title><upnp:class>object.item.audioItem.musicTrack</upnp:class><dc:creator>Pure Prairie League</dc:creator><upnp:album>Aimee And Other Hits</upnp:album></item></DIDL-Lite>",
            "TrackURI": "x-sonos-http:track%2f3003206.flac?sid=174&flags=24616&sn=10",
            "RelTime": "0:00:00",
            "AbsTime": "NOT_IMPLEMENTED",
            "RelCount": "2147483647",
            "AbsCount": "2147483647"
          }
        },
        "activity_stats": {
          "DeviceProperties subscription": {
            "count": 9,
            "last_seen": 505156.822676048
          },
          "ContentDirectory subscription": {
            "count": 4,
            "last_seen": 505156.845502008
          },
          "AVTransport subscription": {
            "count": 2,
            "last_seen": 489062.255595483
          },
          "SonosMedia.poll_track_info": {
            "count": 2,
            "last_seen": 489062.276172919
          },
          "AlarmClock subscription": {
            "count": 2,
            "last_seen": 489062.263354354
          },
          "ZoneGroupTopology subscription": {
            "count": 12,
            "last_seen": 489642.151554212
          },
          "RenderingControl subscription": {
            "count": 2,
            "last_seen": 489062.298646543
          },
          "discovery": {
            "count": 641,
            "last_seen": 507662.736595229
          }
        },
        "event_stats": {
          "DeviceProperties": {
            "received": 9,
            "duplicates": 0,
            "processed": 9
          },
          "ContentDirectory": {
            "received": 4,
            "duplicates": 0,
            "processed": 0
          },
          "AVTransport": {
            "received": 2,
            "duplicates": 0,
            "processed": 2
          },
          "AlarmClock": {
            "received": 2,
            "duplicates": 1,
            "processed": 0
          },
          "ZoneGroupTopology": {
            "received": 12,
            "duplicates": 0,
            "processed": 2
          },
          "RenderingControl": {
            "received": 2,
            "duplicates": 1,
            "processed": 1
          },
          "soco:from_didl_string": [
            19,
            22,
            128,
            22
          ],
          "soco:parse_event_xml": [
            113,
            284,
            128,
            128
          ]
        },
        "zone_group_state_stats": {
          "processed": 30,
          "total_requests": 178
        }
      }