I’ve thrown together a esphome device with rotary encoder and oled screen to show/control the volume on my surround receiver.
The meat of it is:
sensor:
- platform: rotary_encoder
name: "volume"
id: rcvolume
pin_a: D3
pin_b: D2
min_value: 0
max_value: 200
on_value:
then:
- script.execute: pagetimeout
# Sensor from home assistant showing onkyo volume.
- platform: homeassistant
name: "Onkyo Volume Acording to home assistant"
id: "vknob_onkyo_volume"
entity_id: media_player.onkyoreceiver
attribute: volume_level
accuracy_decimals: 0
filters:
- calibrate_linear:
# Map values from 0-1 to 0-200
- 0.0 -> 0.0
- 1.0 -> 200
- debounce: 1s #attempt but not solving issue
- throttle: 3s #attempt but not solving issue
on_value:
- sensor.rotary_encoder.set_value:
id: rcvolume
value: !lambda |-
return id(vknob_onkyo_volume).state;
- script.execute: pagetimeout
Changing the value from the device works great, but when I change the volume from the receiver the value propagates to the device and updates the view, it updates the rotary encoder steps so that turning the knob will always be in reference to the current volume so the volume doesn’t jump around.
Is there some way to update the rotary encoder steps without sending the value back out to HA? The main issue is if I slowly hunt the volume on the receiver, it tells home assistant, which tells my esphome device, that then tells HA which sets the volume in a constant loop until the value settles. Which is not desirable. I just want want them to stay in sync based on the last one to cause the change.
I considered having the device just send up/down commands and using the media_player sensor for the feedback, but its too slow to feel good.
debounce sounded like all I need but I tried debouncing for 1, 3, 5, 15 seconds and it didn’t seem to keep the issue of the volume sometimes jumping back to an old value sometimes.
The only think I can think of is fork the project and modify the rotary_encoder lib to have a setValueLocally which isn’t the answer I’d really like to choose.
I’ve tried hiding the rotary encoder sensor and using a template sensor and manually sending the data when it changes for any reason other than data coming back from home assistant using a global variable. It does seem to work most of the time, though occasionally it does seem to still push an old value from HA through causing non-smooth volume changing using the the receiver it’s self.
I completely decoupled the encoder value from the stored value and now manually send the template sensor on encoder events but not when it changes. This seems to work without any weird jank.
what isn’t exactly clear form the code snippets is that I’m using an OLED to show the volume as the goal is to be able to control the volume when I can’t see/reach the avreceiver. The on_clockwise, call media_player.volume_up in HA, HA->avreciever, media_player.attributes.volume_level triggering the espdevice to draw the OLED screen feedback loop is a terrible user experience. I need all the updates to be optimistic for the display.
Waiting for the value to be sent to the server validated and come back to update the number (that’s how the esphome sensor values operate) prevents it from smoothly changing the value.
Optimistic updates means the display changes the value to what I want it to be, not what it currently is, provided I am still interacting with the knob.
This solution worked acceptably but putting home assistant in between the the receiver and the esp was unnecessary lag and traffic, I ended up replacing it with custom sketch that connects directly to the receiver.