SONOS control using API requests to run HA scripts

Hi all,
After finding a solution to select a source from the SONOS favourites (SONOS: The easiest way of setting playlist or radio streams), I am trying to find a flexible way of controlling SONOS speakers using API requests to run HA scripts.
The following is a working solution:
script.yml

sonos_guestroom:
  alias: SONOS favourite in guestroom
  sequence:
  - service: sonos.join
    data:
      master: media_player.guest_room
  - service: media_player.volume_set
    data_template:
      entity_id:
      - media_player.guest_room
      volume_level: 0.4
  - service: media_player.volume_mute
    data_template:
      entity_id:
      - media_player.guest_room
      is_volume_muted: no
  - service: media_player.select_source
    data:
      entity_id: media_player.guest_room
      source: "Jazz"

Then I call this HA script:

curl --location --request POST "http://#{ip}:8123/api/services/script/turn_on" \
    -d '{"entity_id": "script.sonos_guestroom"}' \
    -H 'Authorization: Bearer #{api_token}'

My goal would be to have a much more flexible HA script using variables for the source and the volume:

sonos_guestroom_flexible:
  alias: SONOS favourite in guestroom
  sequence:
  - service: sonos.join
    data:
      master: media_player.guest_room
  - service: media_player.volume_set
    data_template:
      entity_id:
      - media_player.guest_room
      volume_level: {{ volume }}
  - service: media_player.volume_mute
    data_template:
      entity_id:
      - media_player.guest_room
      is_volume_muted: no
  - service: media_player.select_source
    data:
      entity_id: media_player.guest_room
      source: {{ source }}

Then I would like to call this HA script may be in this way (not working):

curl --location --request POST "http://#{ip}:8123/api/services/script/sonos_guestroom_flexible" \
    -d '{"volume": 0.4' \
    -d '{"source": "Jazz"}' \
    -H 'Authorization: Bearer #{api_token}'

Does anybody have an idea about how to call the HA script by specifying variables at the same time?

From where are you making this API request?

This API request is called from an own Ruby application, which I call myhome_central_api. This Ruby application is able to call various API requests to systems like DigitalStrom, HomeAssistant and Z-way. I use Node-Red to define Alexa commands that call HA rest_commands. These HA rest_commands then call myhome_central_api API requests, which can be scenes combining different systems (DSS, HA, Z-way) to control lights, vacuum cleaners, door locks, smart switches, SONOS speakers and alike.
Because I didn’t get the Alexa skill Plex working in my local environment (it is not connected directly to the Internet), I am trying to achieve my music control in the same way as described above (Alexa -> Node-Red -> HA -> myhome_central_api -> HA -> SONOS).
The working Ruby function calling the HA script to play a certain SONOS favourite in a certain room looks like this:

def sonos_guestroom(hass_script_name, source)
  # API call to Home-assistant - sonos guestroom
  # curl -X POST -H “Content-Type: application/json” -H “x-ha-access:1234”
  # -d ‘{“entity_id”:“script.sonos_guestroom}’ http://hassio:8123/api/services/script/turn_on
  url = URI("http://#{@hass_ip}:#{@hass_port}/api/services/script/turn_on")
  %x( curl --location --request POST '#{url}' \
      -d '{"entity_id": "script.#{hass_script_name}"}' \
      -H 'Authorization: Bearer #{@hass_api_token}' )
  puts "hass_api_script_turn_on #{hass_script_name} playing #{source}"
  return "hass_api_script_turn_on #{hass_script_name} playing #{source}"
end# hass_api_sonos_guestroom

As I mentioned in my initial post, I would like to make this Ruby function more flexible by providing source and volume to the HA script (not working):

def sonos_guestroom_wip(hass_script_name, source)
  # API call to Home-assistant - sonos guestroom
  # curl -X POST -H “Content-Type: application/json” -H “x-ha-access:1234”
  # -d ‘{“entity_id”:“script.sonos_guestroom}’ http://hassio:8123/api/services/script/turn_on
  url = URI("http://#{@hass_ip}:#{@hass_port}/api/services/script/turn_on")
  %x( curl --location --request POST '#{url}' \
      -d '{"entity_id": "script.#{hass_script_name}"}' \
      -d '{"source": "#{source}"}' \
      -H 'Authorization: Bearer #{@hass_api_token}' )
  puts "hass_api_script_turn_on #{hass_script_name} playing #{source}"
  return "hass_api_script_turn_on #{hass_script_name} playing #{source}"
end# hass_api_sonos_guestroom

Did it get any clearer or did I confuse you more?

Sounds pretty complicated, but whatever floats your boat :slight_smile:

But this I don’t understand:

HA has support for Sonos, Alexa and Node-RED, so I don’t get why you need the intermediate step going to your myhome_central_api. But it’s probably part of a scene that calls different systems as well.

Anyway, to your non-working API call. Not 100% sure, but I think the issue is that you use a separate -d flag for each element of the data for your service instead of combining them into one element. Try this:

def sonos_guestroom_wip(hass_script_name, source)
  # API call to Home-assistant - sonos guestroom
  # curl -X POST -H “Content-Type: application/json” -H “x-ha-access:1234”
  # -d ‘{“entity_id”:“script.sonos_guestroom}’ http://hassio:8123/api/services/script/turn_on
  url = URI("http://#{@hass_ip}:#{@hass_port}/api/services/script/turn_on")
  %x( curl --location --request POST '#{url}' \
      -d '{"entity_id": "script.#{hass_script_name}", "source": "#{source}"}' \
      -H 'Authorization: Bearer #{@hass_api_token}' )
  puts "hass_api_script_turn_on #{hass_script_name} playing #{source}"
  return "hass_api_script_turn_on #{hass_script_name} playing #{source}"
end# hass_api_sonos_guestroom