Last active
February 1, 2021 01:17
-
-
Save soberstadt/6e53d693cdc777575b0a4185100b08bd to your computer and use it in GitHub Desktop.
Home Assistant Roku Remote (requires HA 0.62)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
homeassistant: | |
customize: | |
script.roku_button: | |
# using https://github.com/c727/home-assistant-tiles | |
custom_ui_state_card: state-card-tiles | |
config: | |
columns: 3 | |
column_width: 75px | |
row_height: 75px | |
entities: | |
- entity: script.roku_button | |
icon: mdi:power | |
column_span: 3 | |
data: { button: power } | |
- entity: script.roku_button | |
icon: mdi:backburger | |
data: { button: back } | |
- entity: script.roku_button | |
icon: mdi:home-outline | |
column: 3 | |
data: { button: home } | |
- entity: script.roku_button | |
icon: mdi:arrow-up-thick | |
column: 2 | |
data: { button: up } | |
- entity: script.roku_button | |
icon: mdi:arrow-left-thick | |
column: 1 | |
data: { button: left} | |
- entity: script.roku_button | |
label: "OK" | |
column: 2 | |
data: { button: select } | |
- entity: script.roku_button | |
icon: mdi:arrow-right-thick | |
column: 3 | |
data: { button: right } | |
- entity: script.roku_button | |
icon: mdi:arrow-down-thick | |
column: 2 | |
data: { button: down } | |
- entity: script.roku_button | |
icon: mdi:replay | |
column: 1 | |
data: { button: replay } | |
- entity: script.roku_button | |
icon: mdi:information-outline | |
column: 3 | |
data: { button: info } | |
- entity: script.roku_button | |
icon: mdi:rewind | |
column: 1 | |
data: { button: reverse } | |
- entity: script.roku_button | |
icon: mdi:play-pause | |
column: 2 | |
data: { button: play } | |
- entity: script.roku_button | |
icon: mdi:fast-forward | |
column: 3 | |
data: { button: forward } | |
- entity: script.roku_button | |
icon: mdi:volume-plus | |
column: 4 | |
column_span: 1 | |
row: 1 | |
row_span: 2 | |
data: { button: volume_up } | |
- entity: script.roku_button | |
icon: mdi:volume-minus | |
column: 4 | |
column_span: 1 | |
row: 3 | |
row_span: 2 | |
data: { button: volume_down } | |
- entity: script.roku_button | |
icon: mdi:volume-mute | |
column: 4 | |
column_span: 1 | |
row: 5 | |
data: { button: volume_mute } | |
frontend: | |
extra_html_url: | |
- /local/custom_ui/state-card-tiles.html | |
extra_html_url_es5: | |
- /local/custom_ui/state-card-tiles.html | |
group: | |
Living Room TV: | |
entities: | |
- script.roku_button | |
script: | |
roku_button: | |
sequence: | |
service: roku_remote.press_button | |
data_template: | |
button: "{{ button }}" | |
python_script: | |
input_text: | |
roku_remote_ip: | |
name: Roku Remote IP | |
roku_remote: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file must be placed in | |
# {config-dir}/custom_components | |
# requires python-roku v3.1.5 which will be released with HA 0.62 | |
DOMAIN = 'roku_remote' | |
LAST_BUTTON_TOPIC = 'last_button' | |
from roku import Roku | |
import logging | |
def setup(hass, config): | |
roku = None | |
last_ip_state_name = 'input_text.roku_remote_ip' | |
def find_roku(): | |
logging.info('[roku_remote] looking for devices') | |
devices = Roku.discover(timeout=5) | |
logging.info('[roku_remote] found: ') | |
logging.info(devices) | |
found = None; | |
for d in devices: | |
if d.port == 8060: found = d | |
if found != None: break | |
if found != None: | |
roku = found | |
hass.states.set(last_ip_state_name, roku.host) | |
logging.info('[roku_remote] selected:') | |
logging.info(roku) | |
else: | |
logging.error('[roku_remote] no roku found') | |
return found | |
find_roku() | |
if roku == None: | |
roku = Roku(hass.states.get(last_ip_state_name).state) | |
def button_press(call): | |
button_name = call.data.get('button', '') | |
hass.states.set("{0}.{1}".format(DOMAIN, LAST_BUTTON_TOPIC), button_name) | |
try: | |
getattr(roku, button_name)() | |
except Exception as e: | |
if find_roku() != None: getattr(roku, button_name)() | |
hass.services.async_register(DOMAIN, 'press_button', button_press) | |
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file must be placed in | |
# {config-dir}/python_scripts | |
# | |
# Some extra fun, since there is no api for setting tv volume, instead we can turn it down a whole bunch | |
# and then go up for the number of times specificed in service call. | |
for x in range(0, 50): | |
hass.services.call('roku_remote', 'press_button', service_data={ 'button': "volume_down" }, blocking=True) | |
level = data.get('level', 15) | |
for x in range(0, level): | |
hass.services.call('roku_remote', 'press_button', service_data={ 'button': "volume_up" }, blocking=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
This file must be placed in | |
{config-dir}/www/custom_ui/ | |
Created by @c727 | |
https://github.com/c727/home-assistant-tiles | |
--> | |
<dom-module id="state-card-tiles"> | |
<template> | |
<style> | |
.grid { | |
display: grid; | |
grid-template-columns: repeat(var(--tiles-columns), var(--tiles-column-width)); | |
grid-auto-rows: var(--tiles-row-height); | |
grid-gap: var(--tiles-gap); | |
width: 100%; | |
} | |
paper-button { | |
box-shadow: none !important; | |
margin: 0 !important; | |
background-color: var(--tiles-color); | |
color: #fff; | |
} | |
paper-button.on { | |
background-color: var(--tiles-color-on); | |
} | |
paper-button.off { | |
background-color: var(--tiles-color-off); | |
} | |
</style> | |
<paper-button-group class="grid" on-tap="stopPropagation"> | |
<template is="dom-repeat" items="[[config.entities]]" as="entity"> | |
<paper-button raised class$="[[computeTileClass(hass, entity)]]" style$="[[computeTileStyle(entity)]]" | |
on-tap="callService" > | |
<template is="dom-if" if="[[entity.icon]]"> | |
<iron-icon icon="[[entity.icon]]"></iron-icon> | |
</template> | |
[[entity.label]] | |
</paper-button> | |
</template> | |
</paper-button-group> | |
</template> | |
</dom-module> | |
<script> | |
const VERSION = '2017113'; | |
var timeout = 0; | |
Polymer({ | |
is: 'state-card-tiles', | |
properties: { | |
hass: { | |
type: Object, | |
}, | |
stateObj: { | |
type: Object, | |
}, | |
config: { | |
type: Object, | |
computed: 'computeConfig(stateObj)', | |
}, | |
}, | |
computeConfig: function (stateObj) { | |
return stateObj.attributes.config; | |
}, | |
ready: function () { | |
var config = this.config; | |
this.updateStyles({ | |
'--tiles-columns': config.columns ? config.columns : '3', | |
'--tiles-column-width': config.column_width ? config.column_width : '100px', | |
'--tiles-row-height': config.row_height ? config.row_height : '100px', | |
'--tiles-gap': config.gap ? config.gap : '4px', | |
'--tiles-color': config.color ? config.color : 'var(--primary-color)', | |
'--tiles-color-on': config.color_on ? config.color_on : 'var(--google-green-500)', | |
'--tiles-color-off': config.color_off ? config.color_off : 'var(--google-red-500)', | |
}); | |
}, | |
computeTileClass: function (hass, entity) { | |
var domain = entity.entity.split('.')[0]; | |
if (domain === 'script') return ''; | |
return (hass.states[entity.entity].state === 'on') ? 'on' : 'off'; | |
}, | |
computeTileStyle: function (entity) { | |
var c = entity.column ? entity.column : 'auto'; | |
var cs = entity.column_span ? entity.column_span : 1; | |
var r = entity.row ? entity.row : 'auto'; | |
var rs = entity.row_span ? entity.row_span : 1; | |
var img = entity.image ? ' background-image: url("' + entity.image + '");' : ''; | |
return 'grid-column: ' + c + ' / span ' + cs + '; grid-row: ' + r + ' / span ' + rs + ';' + img; | |
}, | |
callService: function (e) { | |
var entity = e.model.entity.entity; | |
var domain = entity.split('.')[0]; | |
if (domain === 'script') { | |
var service = entity.split('.')[1]; | |
var data = e.model.entity.data ? (e.model.entity.data) : {}; | |
} else { | |
var service = 'toggle'; | |
var data = { 'entity_id': entity }; | |
} | |
this.hass.callService(domain, service, data); | |
}, | |
stopPropagation: function (e) { | |
e.stopPropagation(); | |
}, | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have this added to HA and I have verified that the configuration is "good" from within HA, but where do I go inside of HA to add the remote?