Is template sensor the best option to solve my problem?

it doesn’t allow me to make specific jumps in volume (ie +10, -10, +5, -5) which i need to work for google assistant integration.

our previous amp had direct +10/-10/+5/-5 commands which made life real easy and we got used to it.

as for the 100% volume thing - this was prior to any automation or scripts. I’d load up the HA app on my phone and see the volume slider sitting at max volume and try to drag it down only to have the amp receive the max volume command and almost blow our ears off. The platform driver is very limited with our receiver hence the wasting of time :confused:

Yah, but you can limit the volume slider by wrapping it against a numerical slider and constrain the numerical slider to values that you want. That’s what I did, I allow mine to go between -80 and -10 db. Anytime a move over (under) -10 forces it to -10 without sending the signal to the receiver. Just hide the media control in the UI and it won’t ever be a problem.

Beauty of this setup is that it inverts the slider. So when the system starts up, it will be low worse case scenario. The input slider also store’s the volume of your slider if you remove initial -80 and use restore state.

  yamaha_receiver:
    name: Zone 1 Volume
    initial: -80
    min: -80
    max: 0
    step: 5
    unit_of_measurement: dB
- alias: Zone 1 Volume (Media to Slider)
  trigger:
    - platform: state
      entity_id: media_player.yamaha_receiver
  condition:
    - condition: template
      value_template: >
        # convert to decibel.
        {% set converted = ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 | round(0.0) %}
        # Removes feedback loop
        {{ converted != states('input_number.yamaha_receiver') | float }}
  action:
     service: input_number.set_value
     data_template:
       entity_id: input_number.yamaha_receiver
       value: >
          {{ ( ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 ) | round(0.0) }}
- alias: Zone 1 Volume (Slider to Media)
  trigger:
    - platform: state
      entity_id: input_number.yamaha_receiver
  condition:
    - condition: template
      value_template: >
        # convert from decibel.
        {% set converted = (1.0 - trigger.to_state.state | float / 100.0) | round(2) %}
        # Removes feedback loop
        {{ converted != state_attr('media_player.yamaha_receiver','volume_level') | float }}
  action:
    - service: media_player.volume_set
      data_template:
        entity_id: media_player.yamaha_receiver
        volume_level: >
          {{ (1.0 - trigger.to_state.state | float / 100.0) | round(2) }}

In case you’re interested, I had a PR a few days ago that added template functionalities to input_number that allowed its value to be updated based on a template, and allowed for running a script (or sequence of services) when its value is changed via input_number.set_value. It didn’t get merged, but you could use or adapt the code if you’d like. I think it would enable you to accomplish this without having to define those automations.

Pull request

input_number/__init__.py

Thanks. I actually don’t use those automations anymore, moved over to appdeamon a few years ago. I just dug em up from when I used the built in automations.

thanks a bunch @petro. I’ve tried to apply your code to my config but for whatever reason, the automations aren’t being triggered on either slider change or receiver volume change:

last_triggered: null
id: denon_media_to_slider
friendly_name: Zone 1 Volume (Media to Slider)

last_triggered: null
id: denon_slider_to_media
friendly_name: Zone 1 Volume (Slider to Media)

They’re both enabled and there’s no errors in the log. Might need to enable debugging.

automation:

#### PETROS AWESOME VOLUME AUTOMATION ###
- id: denon_media_to_slider
  alias: Zone 1 Volume (Media to Slider)
  trigger:
    - platform: state
      entity_id: media_player.denon_avr_3310
  condition:
    - condition: template
      value_template: >
        # convert to decibel.
        {% set converted = ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 | round(0.0) %}
        # Removes feedback loop
        {{ converted != states('input_number.denon1_receiver') | float }}
  action:
     service: input_number.set_value
     data_template:
       entity_id: input_number.denon1_receiver
       value: >
          {{ ( ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 ) | round(0.0) }}

- id: denon_slider_to_media
  alias: Zone 1 Volume (Slider to Media)
  trigger:
    - platform: state
      entity_id: input_number.denon1_receiver
  condition:
    - condition: template
      value_template: >
        # convert from decibel.
        {% set converted = (1.0 - trigger.to_state.state | float / 100.0) | round(2) %}
        # Removes feedback loop
        {{ converted != state_attr('media_player.denon_avr_3310','volume_level') | float }}
  action:
    - service: media_player.volume_set
      data_template:
        entity_id: media_player.denon_avr_3310
        volume_level: >
          {{ (1.0 - trigger.to_state.state | float / 100.0) | round(2) }}

this is probably the most complex code i’ve got in my config! a little over my head :grin:

Do you have the input number configured?

Also, in my case, the media player had to be on for it to work.

yeah of course:

  denon1_receiver:
    name: Zone 1 Volume
    initial: -80
    min: -80
    max: -10
    step: 5
    unit_of_measurement: dB

Receiver is rarely off. The denon platform volume slider works ok but neither of the automations have triggered no matter what i change (input slider or amp vol).

I can see the input number change in the dev tools, as well as the volume.

Ok, try to remove the condition in the center of the automations.

Also, take a screenshot of the media player’s attributes when on and the input number. This was an old automation and I’m wondering if things changed.

I also have a Denon, created a script to send +3 or -3, you can choose the value …
That script I call with a template switch I use in Google assistant

If interested in the script?

Thanks @petro

Removing the conditions in both automations shows the automations being triggered in dev states panel now.

Heres what the input number and denon media player look like in the states window:

The receiver doesn’t respond to any number input from the slider unless the slider hits 0, to which the receiver is then set to 0dB (assumingly due to the conditions templates not doing the conversion to/from -dB?)

hi @pergola.fabio

Thanks for the offer - id love to see yours too. This is a great community :slight_smile:

I am using this script, but be careful with volume, I use 0.03 for instance , to increase with 3
I also have sliders in my config in Lovelace, that actually read current value , and also set the value if you’re change the slider …

This script I use for increase/decrease

I have something similar with my lights at home. I have set up telegram to work with my HA and when I send the command “brighter” (it’s a bit more complicated) it makes my lights brighter. Same for darker.
I am sure you can adapt that for your use. Especialy when you combine it with input_number, set as slider!

So what I would do is the following:

  1. (Optional)
    Create an automation that triggers when your Receiver turns on. No condition. Action is to read the current volume and set the input_number accordingly. (add a delay in case your receiver takes some time to turn on)
    This is optional since once you change your slider, it’s updated anyway - but it’s a nice way to be percise in control!

  2. Make an automation, that triggers when input_number state changes. Your input_number is the desired volume. -> when you change the input value, the automation sends the new volume to your receiver. If you want you can set a condition checking if the receiver is on.

  3. As you want -10 -5 +5 + 10 dB, you want 4 automations/scripts. Scripts are provably easier here.
    The action is a simple math operation. You grab the current input_number and add/subtract the desired value to it. Since you change the state of input_number, the second automation should trigger! (If it does not, don’t worry! Just add the set_volume action in your script too. So the script updates input_number AND media_player.volume!)
    The line for my setup is

    action:
    lights.turn_on:
    entity_id: MY_LIGHT
    data_template:
    brightness: {{ states.lights.MY_LIGHT.attributes.brightness | int + 10 }}

You need to adapt it for your setup, but that’s what should work and be easy to use.
I’m typing from my phone, so sorry for not providing more accurate info.

template_number:
  denon1_receiver:
    name: Zone 1 Volume
    initial: -80
    min: -80
    max: -10
    step: 5
    unit_of_measurement: dB
    value_template: >
      {% if state_attr('media_player.denon_avr_3310', 'volume_level') %}
        {{ ( ( -1.0 + state_attr('media_player.denon_avr_3310', 'volume_level') | float ) * 100.0 ) | round(0.0) }}
      {% endif %}
    set_value_script:
    - service: media_player.volume_set
      data_template:
        entity_id: media_player.denon_avr_3310
        volume_level: "{{ (1.0 - value | float / 100.0) | round(2) }}"
    entity_id: media_player.denon_avr_3310

Try this template_number component. Just copy the folder I linked to your custom_components folder. I think the above configuration will work, no automations needed.

It’s odd that your state is set to -65.8392874932874 or whatever when the slider is constrained to increments of 5.

Anyways, the root cause is because your equations are different than mine. I reworked them. Change your conversion lines to this:

#### PETROS AWESOME VOLUME AUTOMATION ###
- id: denon_media_to_slider
  alias: Zone 1 Volume (Media to Slider)
  trigger:
    - platform: state
      entity_id: media_player.denon_avr_3310
  condition:
    - condition: template
      value_template: >
        # convert to decibel.
        {% set converted = ( -1.0 + trigger.to_state.attributes.volume_level | float ) * 100.0 | round(0) %}
        # Removes feedback loop
        {{ converted != states('input_number.denon1_receiver') | float }}
  action:
     service: input_number.set_value
     data_template:
       entity_id: input_number.denon1_receiver
       value: >
          {{ ( (-1.0 + trigger.to_state.attributes.volume_level | float ) * 100 ) | round(0) }}

- id: denon_slider_to_media
  alias: Zone 1 Volume (Slider to Media)
  trigger:
    - platform: state
      entity_id: input_number.denon1_receiver
  condition:
    - condition: template
      value_template: >
        # convert from decibel.
        {% set converted = (1.0 + trigger.to_state.state | float / 100) | round(2) %}
        # Removes feedback loop
        {{ converted != state_attr('media_player.denon_avr_3310','volume_level') | float }}
  action:
    - service: media_player.volume_set
      data_template:
        entity_id: media_player.denon_avr_3310
        volume_level: >
          {{ (1.0 + trigger.to_state.state | float / 100) | round(2) }}

unfortunately, still not working. as soon as the conditions are in place, the automations never get triggered

can you call the service to set the volume level of the slider to an increment of 5? I still find it odd that it’s set to a random level inside your env. Mine is constrained to the 5’s with a near configuration. I think that may be the problem.

You can always remove the condition too. It won’t do much other than make a second post of your volume level.

hashing out both the condition blocks seems to get me closer… but im wondering if the conditions are failing due to the calculation of -dB not being quite right:

You’ll see in the image that dragging the slider to 45 doesn’t set the amp to 45, but 42. The scrape sensor is getting the actual dB level via http.

It seems like that would be the problem. And it seems like the problem is on Denon side. That volume level should be perfectly on the 0.0x decimal place. It’s no where near that. Sometimes it falls perfectly, it’s odd. Removing the condition would keep it working. If you’re interested in making it perfect, I need you to get a list of numbers in db, and match it to a list of volume_levels. From there we can tailor the equation to match better. You want to span the whole range. So from min volume to max volume.

thanks @petro. i’ve taken a slightly different route which seems to be exactly what i was after:

i’ve got my input_number as it was:

  denon1_receiver:
    name: Zone 1 Volume
    initial: -80
    min: -80
    max: 0
    step: 5
    unit_of_measurement: dB

but the automation for volume control using the slider now triggers the curl command that sends the input_number directly to the receiver without any changes:

- id: denon_vol
  alias: denon_vol
  trigger: 
    platform: state
    entity_id: input_number.denon1_receiver
  action:
    service: shell_command.set_denon_vol

and the shell command that calls:

set_denon_vol: '/usr/bin/curl "http://192.168.1.113/MainZone/index.put.asp?cmd0=PutMasterVolumeSet%2F{{ states.input_number.denon1_receiver.state }}"'

so the setting of the volume is instant and can keep up with very quick changes. perfect!

and to have the receiver’s volume change the input_slider, i’m still using the curl command to grab the value and this updates the slider:

- id: denon_media_to_slider
  alias: Zone 1 Volume (Media to Slider)
  trigger:
    - platform: state
      entity_id: sensor.denon_volume
  action:
     service: input_number.set_value
     data_template:
       entity_id: input_number.denon1_receiver
       value: '{{ trigger.to_state.state | int }}'

so thanks to everyone for their input - it all helped me get to this outcome!