Hi, I’ve been wanting to assign physical buttons to locally control volume up & down on Sonos speakers. I recently found the command is available on the device page on my.smartthings.com/advanced, but there’s no way to use it in a routine via the app.
Is the only way to use a JSON rule? If so does anyone have the command in a rule that you could share? I’m not a developer at all, so I previously tried using ChatGPT but it didn’t work as it’s not up to date with the latest standard.
Yes, it is a bit of a head scratcher why they’d only have one of the three commands in the device presentation. As a rule in JSON format you will need something like:
{
"name": "Using a button to raise the volume.",
"actions": [
{
"if": {
"equals": {
"left": {
"device": {
"devices": [
"The deviceId of the button in UUID form"
],
"component": "main",
"capability": "button",
"attribute": "button"
}
},
"right": {
"string": "pushed"
}
},
"then": [
{
"command": {
"devices": [
"The deviceId of the Sonos in UUID form"
],
"commands": [
{
"component": "main",
"capability": "audioVolume",
"command": "volumeUp"
}
]
}
}
]
}
}
]
}
Today I learned that the volumeUp button on the Sonos driver uses 5% increments.
3 Likes
JKnight
(Keeping SmartThings limping along since 2013.)
3
I am using a JSON file myself, ironically with the help of ChatGPT, but I had to teach her all about Rules API first to get any useful help. I had hoped that my experience would somehow help her help others in the future… I guess not yet.
Anyway, you also have the option to set the volume in a routine by selecting “Control Devices” and picking your Sonos, instead of choosing “Play Message on Speaker”, for example. This would allow you to adjust the volume using a routine by a set amount with each button press on a SmartThings button device, but not with the physical volume buttons on the Sonos device(s). Here are the options I see:
Where it says “The deviceId of the button in UUID form”, replace this with the Device ID from SmartThings advanced web app device page for the button device you want to use (the 32 digit string)
The “component” needs to match the component id listed under Attributes in the device page for the specific button on the device you wish to assign to change the volume
Paste in the deviceid for the Sonos speaker where it states in the code
Use the API Browser+ following the instructions to obtain a Personal Access Token and paste it where prompted on the browser page
Go to Automations → Rules → Create and upload the JSON file
For decreasing the volume, simply change volumeUp to volumeDown in the “command”.
You can indeed set the volume in a Routine action but only to a specific integer percentage. What you can’t do is increment and decrement the volume relative to the current percentage.
1 Like
JKnight
(Keeping SmartThings limping along since 2013.)
6
Yes, sorry. If I remember correctly, that was one of the reasons I went with using JSON and not a routine, because of the silly limitations in routines. The one that bothered me the most was the inability to temporarily set the volume for announcements. I may post my JSON code here later when I am back at my computer so others can learn from my struggles.
JKnight
(Keeping SmartThings limping along since 2013.)
7
Sorry to hijack the topic a bit, just wanted to share… and I think it is loosely related to OP’s post and could also be beneficial to others who stumble in here.
At the time, I was trying to have announcements (alarm, mail, door, washer, etc.) broadcast via Sonos, but could not find a way to adjust the Sonos volume up to a reasonable level in conjunction with the announcement, than back down to the previous volume after the announcement. Sure seems like setting the volume of an announcement should be included with the “Play message on speaker” option, but don’t get me started on all the issues with the Sonos integration, especially compared to what we all had working great with groovy.
Anyway, this was particularly a problem because for whatever reason the announcement volume/voice seems to be much lower then any playing media. Also, my wife and kids often leave the Sonos volume much lower for music then needed for any announcements (for example: they were listening to light music or white noise prior to turning it off). I know I could maybe compensate for this by programmatically resetting the Sonos volume at some set interval, but that has the potential for a rude awakening if someone is trying to relax at the reset time(s).
I first attempted to use the option to set the volume in a routine by selecting “Control Devices” and setting my Sonos volume to 65, followed by setting and playing the announcement, and then setting the Sonos back to a static volume level appropriate for music… but because of the delay, it would momentarily blast any music playing at 65, speak the announcement, blast the music again for a moment before resetting the volume. It also took 2 or more routines for each announcement because you can’t pick the Sonos device to set or reset the volume more then once per routine. This method was also not ideal because, at the end, it reset the volume to a static number and not the previous volume prior to the announcement.
I thought about pausing any music that might be playing prior to the announcement and un-pausing it following the announcement, but if music wasn’t playing prior, un-pausing after any announcements would have the unexpected behavior of starting the last played and stopped music from hours or days earlier. Man, is anyone else terribly missing Webcore and the ability to set and use variables?
Obviously setting the volume of announcements and returning the Sonos to it’s previous volume should be included and standard within the “Play message on speaker” option, but since it is not for some odd reason, here is how I hacked it with some minor help from ChatGPT on the code formatting. My hack is also relevant here because it shows another example and unique use of the solution recommended by @orangebucket above.
Due to the lack of ability to natively store and use variables in rules, I installed @Mariano_Colmenarejo’s “Aplicaciones Virtuales Mc”, which has the ability to create a “Number Field (Stored Variables)” device.
Using @TAustin’s “vEdge Creator: a virtual device generator for end users”, I created 2 virtual momentary buttons.
One that I named “Get Sonos Volume (Rules API)”, and the second “Reset Sonos Volume (Rules API)”. I then used @TAustin’s “API Browser+” to create/publish 2 new rules.
The first rule garbs the current Sonos Volume (both groupVolume and the regular Volume) when the corresponding virtual momentary button is pressed. It then stores for later use the values of the groupVolume and Volume in the 1st and 2nd slots of the “Number Field (Stored Variables)” device. I also added a brief delay/sleep to account for some system latency when using the momentary button/rule in my routines. Here is my JSON code (I had a tiny bit of help from ChatGPT on structure):
{
"name": "Get Sonos Volume",
"actions": [
{
"if": {
"equals": {
"left": {
"string": "pushed"
},
"right": {
"device": {
"devices": [
"Device ID for the momentary button titled Get Sonos Volume (Rules API)"
],
"component": "main",
"capability": "button",
"attribute": "button"
}
}
},
"then": [
{
"command": {
"devices": [
"Device ID for the Number Field (Stored Variables) device"
],
"commands": [
{
"component": "main",
"capability": "legendabsolute60149.numberFieldOne",
"command": "setNumberFieldOne",
"arguments": [
{
"device": {
"devices": [
"Device ID for the Sonos device"
],
"component": "main",
"capability": "mediaGroup",
"attribute": "groupVolume"
}
}
]
}
]
}
},
{
"command": {
"devices": [
"Device ID for the Number Field (Stored Variables) device"
],
"commands": [
{
"component": "main",
"capability": "legendabsolute60149.numberFieldTwo",
"command": "setNumberFieldTwo",
"arguments": [
{
"device": {
"devices": [
"Device ID for the Sonos device"
],
"component": "main",
"capability": "audioVolume",
"attribute": "volume"
}
}
]
}
]
}
},
{
"sleep": {
"duration": {
"value": {
"integer": 1
},
"unit": "Second"
}
}
}
]
}
}
]
}
The second rule resets the Sonos Volume back (both groupVolume and the regular Volume) when the corresponding virtual momentary button is pressed. It pulls the previously stored values of the groupVolume and Volume from the 1st and 2nd slots of the “Number Field (Stored Variables)” device and resets both on the Sonos. I also added a brief delay/sleep to account for some system latency here as well when using the momentary button/rule in my routines. Here is my JSON code (I had a tiny bit of help from ChatGPT on structure):
{
"name": "Reset Sonos Volume",
"actions": [
{
"if": {
"equals": {
"left": {
"string": "pushed"
},
"right": {
"device": {
"devices": [
"Device ID for the momentary button titled Reset Sonos Volume (Rules API)"
],
"component": "main",
"capability": "button",
"attribute": "button"
}
}
},
"then": [
{
"sleep": {
"duration": {
"value": {
"integer": 2
},
"unit": "Second"
}
}
},
{
"command": {
"devices": [
"Device ID for the Sonos device"
],
"commands": [
{
"component": "main",
"capability": "mediaGroup",
"command": "setGroupVolume",
"arguments": [
{
"device": {
"devices": [
"Device ID for the Number Field (Stored Variables) device"
],
"component": "main",
"capability": "legendabsolute60149.numberFieldOne",
"attribute": "numberFieldOne"
}
}
]
}
]
}
},
{
"command": {
"devices": [
"Device ID for the Sonos device"
],
"commands": [
{
"component": "main",
"capability": "audioVolume",
"command": "setVolume",
"arguments": [
{
"device": {
"devices": [
"Device ID for the Number Field (Stored Variables) device"
],
"component": "main",
"capability": "legendabsolute60149.numberFieldTwo",
"attribute": "numberFieldTwo"
}
}
]
}
]
}
}
]
}
}
]
}
Now, in any routines for my announcements, I just add a “Get Sonos Volume (Rules API)” virtual momentary button press right before the “Play message on speaker”, and a “Reset Sonos Volume (Rules API)” virtual momentary button press right after.
Whew! Now that I have memorialized this all here for anyone else who may be trying to accomplish something similar, watch the next Sonos beta driver add the ability to temporarily adjust announcement volume. Fingers crossed!
I had wondered what the playTrackAndRestore command did in relation to the audioNotification capability. Seems you can set a level when a specific track is played, but I’m not clear what the restore part is i.e. playback status or volume? Granted even if it does restore previous volume it’s not very handy if you just want to play a text to speech message.
I just tried it with a Spotify URI but nothing happened.
Not relevant now but guess you could have a virtual switch mirror the playback status of the speaker, but on a delay of say 10 seconds. So after the message has played and IF the switch is on i.e. music was playing, then play
1 Like
JKnight
(Keeping SmartThings limping along since 2013.)
9
I had also wondered what the playTrackAndRestore command and the playTrackAndResume command did in relation to the audioNotification capability. Somewhere in the middle of my previously outlined struggles, I attempted to use the playTrackAndRestore and playTrackAndResume commands in my Rules. I could not find any way to host my notification audio files directly on my hub, so they would need to be hosted on the LAN or somewhere on the internet.
I figured out how I could host the files on Google Drive, and the URI worked perfectly with both the playTrackAndRestore and the playTrackAndResume commands. Because you can set the volume level for the track/URI (announcement), if low volume music was playing at the time of any announcement or the Sonos volume was left at a low level, playTrackAndRestore and/or playTrackAndResume would play the announcement at the level selected and then resume/restore the music playing or Sonos device to its prior level.
Perfect… that is exactly the expected behavior of the rather useless Play message on speaker option, with one big drawback: you have to host all of your announcements somewhere on the network/internet where SmartThings can see the files. I do plan to use this method in the future, once I can figure out a clean way to pass a variable of the device/contact sensor name that triggered an alarm, so I can include that in my announcements like in the good old Webcore days (seems so long ago).
As far as hosting your own files on Google Drive, you have to “share the file(s) to anyone with the link” so SmartThings can see them. The URI formatting is a bit wonky, so let me try to explain:
The share link Google Drive generates looks like this: https://drive.google.com/file/d/1Zv4IyqhAfiVfAiOQ2KnOJ3pEiMKUd4gO/view?usp=sharing
The important part is the file ID marked with XXXXXX here: https://drive.google.com/file/d/XXXXXX/view?usp=sharing
Copy and paste the ID to the end of this properly formatted URI: https://drive.google.com/uc?export=download&id=1Zv4IyqhAfiVfAiOQ2KnOJ3pEiMKUd4gO
I currently have the above example URI shared from my Google Drive (if you wanted to try it), but I may take that down if it gets overloaded.
Separately, using the CLI logs, I was able to see that the Play message on speaker method actually creates an mp3 file of my announcement that I can use in the playTrackAndRestore and playTrackAndResume commands… no need for my own file hosting… or, so I thought. Unfortunately, the stored mp3 files are not persistent and get deleted within a few hours or sometimes days. I tried to Play message on speaker on a set schedule to keep the files alive, but they eventually got deleted and replaced with a new file name. From the CLI logs, here is where one of my announcement files was temporarily located/hosted before it was automatically and subsequently deleted (I removed My-Unique-File-ID because I was not sure if it might reveal private info): https://audionotification-na04.smartthings.com/My-Unique-File-ID.mp3
Very nice, this is another elegant solution to a problem that really shouldn’t exist. I love it!
I’ve tried this for an hour in different types of format with help from ChatGpt. But no luck.
It looks like Samsung account has been updated since this solution. Maybe that is why?
JKnight
(Keeping SmartThings limping along since 2013.)
11
Not sure what you mean by “Samsung account has been updated”, but this is still working fine for me.
My experience with ChatGPT is that it doesn’t quite get you all the way there on things it knows very little about, so it takes some tweaking to get the formatting correct.
If you post more about the issue you are experiencing, and perhaps some code snippets, we can help you diagnose the issue.
I mean my. smartthings .com/ advanced looks updated since this thread was active back in 2023.
I see no way of uploading the .json file. Only way is to write the code directly on the page
I’m trying to use the code posted here but i get error messages when i try adding rule.
When in smartthings advanced - rules - Add rule - Actions, using the script i get the following error message:
Error adding rule “Name of rule”. 422 The request is malformed. Unknown target: Malformed body on line 1:41
Paste the JSON inside the brackets that appear when you create a new rule, so the first character is “[” and the last is “]”. If you delete them it fails.
Also don’t forget to replace the device ID.
Edit: Oh, I see, you are pasting everything, only paste what is inside the actions section, would be like this:
[
{
"if": {
"equals": {
"left": {
"device": {
"devices": [
"The deviceId of the button in UUID form"
],
"component": "main",
"capability": "button",
"attribute": "button"
}
},
"right": {
"string": "pushed"
}
},
"then": [
{
"command": {
"devices": [
"The deviceId of the Sonos in UUID form"
],
"commands": [
{
"component": "main",
"capability": "audioVolume",
"command": "volumeUp"
}
]
}
}
]
}
}
]
If you are getting malformed Json/body error then the issue is with the Json syntax rather than anything else. As @mocelet says, brackets, and spaces*, matter
(* for example and, depending on the parser, 4 spaces will differ from a tab even though they ‘look’ identical…)
Hi, I am jumping on this thread, hoping that somebody can help. I tried to use an Aeotec Smart Button to play/stop a sonos speaker, increase the volume and decrease the volume. For the play/pause, I am relying on the status of the speaker (I’ll post the json at the end). However, suddenly the status of the speaker showing in the advanced view of smartthings is “UNDEFINED”. That obviously is a problem for my logic… Does anbyody have any idea on how to fix that?
@JKnight
Would you mind sharing the exact JSON you’re using when adding the Rule via Web interface for playing a locally hosted file to Sonos? I’m looking to play a sound file (based on a motion sensor trigger), and it seems like “playTrackAndResume” is the right command to use.