I am looking to setup a TV with a Roku, and backhauling the audio to a receive in another location.
Therefore, the user needs to be able to trigger volume up and down. Ideally they would be using the Roku remote.
Any suggestions for detecting volume up / down from the Roku remote. A bit logically, the Roku integration does not fire an event on volume up / down.
A couple thoughts:
- IR to IP receiver (boring)
- Select a TV that will report volume events. However, this may be difficult if the TV audio is set to external (the TV generally doesn’t maintain a volume state).
- Somehow intercept the HDMI CEC volume commands and send over IP. I haven’t found a solution for this.
- Use a universal remote with wifi that can talk to Home Assistant. It appears there aren’t great solutions out there for this.
Ideas?
Hello!
I ran across your post here and was wondering if you found a solution to this problem. I’m running into the same situation and am looking for options.
I did!
I set the Roku to control volume via HDMI-CEC. I think connected an ESP to the TV and catch the volume commands. It works well.
Let me know and I can post more details.
Yes, if you don’t mind. I found a clear explanation about enabling the HDMI-CEC on the Roku. I’m not familiar with ESP devices but I have read about the ESP home integration. If you can post your solution to that I would be immensely grateful. I don’t have and ESP devices but if this fixes the volume control that would be AMAZING.
I just installed ceiling speakers and my amplifier is home assistant friendly. The only problem is volume control and I don’t want to have to use my phone to control volume.
My documentation is poor, but I’ll get you started.
Hardware
ESP32-POE-ISO: ESP32-POE-ISO - Open Source Hardware Board
HDMI: https://www.amazon.com/dp/B0CB33FGG2?psc=1&ref=ppx_yo2ov_dt_b_product_details
GPIO of your choice (GPIO05) to HDMI pin 13
GND from the ESP board to HDMI pin 17 (DDC/CEC Ground)
5V from the ESP board to HDMI pin 18 (typically how the HDMI device knows something is connected)
ESP Yaml
substitutions:
name: "volumepoe"
friendly_name: volumepoe
esphome:
name: ${name}
friendly_name: ${friendly_name}
min_version: 2024.6.0
name_add_mac_suffix: false
project:
name: esphome.web
version: '1.0'
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
# Allow Over-The-Air updates
ota:
- platform: esphome
ethernet:
type: LAN8720
mdc_pin: GPIO23
mdio_pin: GPIO18
clk_mode: GPIO17_OUT
phy_addr: 0
power_pin: GPIO12
dashboard_import:
package_import_url: github://esphome/example-configs/esphome-web/esp32.yaml@main
import_full_config: true
## THIS IS THE IMPORTANT STUFF. USE TEMPLATE ABOVE
external_components:
- source: github://Palakis/esphome-hdmi-cec
hdmi_cec:
# Pick a GPIO pin that can do both input AND output
pin: GPIO05 # Required
# The address can be anything you want. Use 0xF if you only want to listen to the bus and not act like a standard device
address: 0x05 # Required
# Physical address of the device. In this case: 4.0.0.0 (HDMI4 on the TV)
# DDC support is not yet implemented, so you'll have to set this manually.
physical_address: 0x4000 # Required
# The name that will we displayed in the list of devices on your TV/receiver
osd_name: "my device" # Optional. Defaults to "esphome"
# By default, promiscuous mode is disabled, so the component only handles directly-address messages (matching
# the address configured above) and broadcast messages. Enabling promiscuous mode will make the component
# listen for all messages (both in logs and the on_message triggers)
promiscuous_mode: true # Optional. Defaults to false
# By default, monitor mode is disabled, so the component can send messages and acknowledge incoming messages.
# Enabling monitor mode lets the component act as a passive listener, disabling active manipulation of the CEC bus.
monitor_mode: true # Optional. Defaults to false
# List of triggers to handle specific commands. Each trigger has the following optional filter parameters:
# - "source": match messages coming from the specified address
# - "destination": match messages meant for the specified address
# - "opcode": match messages bearing the specified opcode
# - "data": exact-match on message content
# Actions called from these triggers is called with "source", "destination" and "data" as parameters
on_message:
# - opcode: 0xC3 # Request ARC start
# then:
# - hdmi_cec.send: # Report ARC started
# destination: 0x0
# data: [ 0xC1 ]
# - opcode: 0x71 # Give audio status
# source: 0x0 # From the TV
# then:
# - hdmi_cec.send:
# destination: 0x0
# data: [ 0x7A, 0x7F ]
# - opcode: 0x46 # Give OSD name
# then:
# - hdmi_cec.send:
# destination: 0x0
# data: [0x47, 0x65, 0x73, 0x70, 0x68, 0x6F, 0x6D, 0x65]
- data: [0x44, 0x41] # User control pressed: volume up
then:
- logger.log: "Volume up"
- homeassistant.service:
service: media_player.volume_up
data:
entity_id: media_player.family_room
- homeassistant.service:
service: media_player.volume_mute
data:
entity_id: media_player.family_room
is_volume_muted: "False"
- data: [0x44, 0x42] # User control pressed: volume up
then:
- logger.log: "Volume Down"
- homeassistant.service:
service: media_player.volume_down
data:
entity_id: media_player.family_room
- data: [0x44, 0x43] # User control pressed: volume up
then:
- logger.log: "Volume Mute"
- homeassistant.service:
service: media_player.volume_mute
data:
entity_id: media_player.family_room
is_volume_muted: "True"
# - opcode: 0x04 # Roku requesting TV On
# then:
# - logger.log: "TV On"
# - homeassistant.service:
# service: light.turn_on
# data:
# entity_id: light.kitchen_breakfast
# - opcode: 0x36 # Roku requesting TV Off
# then:
# - logger.log: "TV Off"
# - homeassistant.service:
# service: light.turn_off
# data:
# entity_id: light.kitchen_breakfast
This is for PoE. You can change it if you’d like for wireless.
I also 3D printed a case I can share if you’d like.