Yeah, that part is working. Each button has an on-tap set and is updating the speed. But when clicking a button, it executes the on-tap function but also launches the “more info” or “detail” modal, here:
In the event handler call stopPropagation
…
func(ev) {
…
ev.stopPropagation()
}
Awesome, thanks!
Any way to limit what bits show up in the “more info” modal without creating a custom version?
bits? If you mean buttons - you can use the inDialog
param. It is true
in more-info mode and false
otherwise.
Would you mind sharing your progress with the code ?
Thinking about quick-select buttons for my media_player,source
Sure - I attempted to follow @andrey format and my plan is to eventually add customization like has been done for the light/brightness slider. Some of the UI also isn’t as responsive as it should be… so it needs work. But I like it so far. Also of note, on a mobile device, when selecting a button the “more info” dialog still opens (doesn’t on a desktop) and the information in the dialog still needs limiting/adjusting.
here it is:
fan-model.html
<script>
(function () {
window.FanEntity = function (hass, stateObj) {
this.hass = hass;
this.stateObj = stateObj;
};
function addGetter(name, getter) {
Object.defineProperty(window.FanEntity.prototype, name,
{ get: getter });
}
addGetter('isOff', function () {
return this.stateObj.state === 'off';
});
addGetter('getSpeed', function () {
if (this.stateObj.attributes.speed !== undefined && this.stateObj.state != 'off') {
return this.stateObj.attributes.speed;
}
return 'off';
});
addGetter('isLowSpeed', function () {
if (this.stateObj.attributes.speed !== undefined && this.stateObj.state != 'off') {
return this.stateObj.attributes.speed === 'low';
}
});
addGetter('isMedSpeed', function () {
if (this.stateObj.attributes.speed !== undefined && this.stateObj.state != 'off') {
return this.stateObj.attributes.speed === 'medium';
}
});
addGetter('isHighSpeed', function () {
if (this.stateObj.attributes.speed !== undefined && this.stateObj.state != 'off') {
return this.stateObj.attributes.speed === 'high';
}
});
/* eslint-enable no-bitwise */
Object.assign(window.FanEntity.prototype, {
setSpeed(speedVal, ev) {
if (speedVal == 'off')
{
this.callService('turn_off');
}
else
{
if (this.stateObj.state != 'on'){
this.callService('turn_on');
}
this.callService('set_speed', {speed: speedVal});
}
ev.stopPropagation();
},
// helper method
callService(service, data) {
var serviceData = data || {};
serviceData.entity_id = this.stateObj.entity_id;
this.hass.callService('fan', service, serviceData);
},
});
}());
</script>
state-card-with-speed.html
<link rel="import" href="fan-model.html">
<dom-module id="state-card-with-speed">
<template>
<style is="custom-style"></style>
<style>
.state {
white-space: nowrap;
}
.speed {
min-width: 0;
}
ha-entity-toggle {
margin-left: 16px;
}
</style>
<div class='state'>
<paper-button-group
in-dialog='[[inDialog]]'
selected='[[entityObj.getSpeed]]'>
<!--<paper-button class='speed'
toggles name="off"
on-tap='onOffTap'
disabled='[[entityObj.isOff]]'>Off</paper-button>-->
<paper-button
in-dialog='[[inDialog]]'
class='speed'
toggles name="low"
on-tap='onLowTap'
disabled='[[entityObj.isLowSpeed]]'>Low</paper-button>
<paper-button
in-dialog='[[inDialog]]'
class='speed'
toggles name="medium"
on-tap='onMedTap'
disabled='[[entityObj.isMedSpeed]]'>Med</paper-button>
<paper-button
in-dialog='[[inDialog]]'
class='speed'
toggles name="high"
on-tap='onHighTap'
disabled='[[entityObj.isHighSpeed]]'>High</paper-button>
</paper-button-group>
</div>
</template>
</dom-module>
<script>
Polymer({
is: 'state-card-with-speed',
properties: {
hass: {
type: Object,
},
inDialog: {
type: Boolean,
value: false,
},
stateObj: {
type: Object,
},
entityObj: {
type: Object,
computed: 'computeEntityObj(hass, stateObj)',
},
},
computeEntityObj: function (hass, stateObj) {
return new window.FanEntity(hass, stateObj);
},
onOffTap: function (ev) {
this.entityObj.setSpeed('off', ev);
},
onLowTap: function (ev) {
this.entityObj.setSpeed('low', ev);
},
onMedTap: function (ev) {
this.entityObj.setSpeed('medium', ev);
},
onHighTap: function (ev) {
this.entityObj.setSpeed('high', ev);
},
});
</script>
state-card-custom_fan.html
<link rel="import" href="state-card-with-speed.html">
<dom-module id="state-card-custom_fan">
<template>
<style is="custom-style" include="iron-flex iron-flex-alignment"></style>
<style>
:host {
line-height: 1.5;
}
</style>
<div class='horizontal justified layout'>
<state-info state-obj="[[stateObj]]" in-dialog='[[inDialog]]'></state-info>
<state-card-with-speed hass="[[hass]]" state-obj="[[stateObj]]" in-dialog='[[inDialog]]'></state-card-with-speed>
<ha-entity-toggle state-obj='[[stateObj]]' hass='[[hass]]' in-dialog='[[inDialog]]'></ha-entity-toggle>
</div>
</template>
</dom-module>
<script>
Polymer({
is: 'state-card-custom_fan',
properties: {
hass: {
type: Object,
},
inDialog: {
type: Boolean,
value: false,
},
stateObj: {
type: Object,
},
},
});
</script>
and last, configuration.yaml
homeassistant:
customize:
fan.master_bedroom_fan:
custom_ui_state_card: custom_fan
Which should give you:
thx, let me take a stab at this and see how it goes…
@kylerw, I sent a link to this thread to @balloob and he blessed the concept, so it would be great if you could make a PR agains the main repo with this UI.
@kylerw, With regards to your query on responsiveness , i don’t see any issues with the buttons here:
Here goes the code - i’ve put everything into one file.
state-card-custom_light.html
<dom-module id="state-card-custom_light">
<template>
<style is="custom-style" include="iron-flex iron-flex-alignment"></style>
<style>
:host {
line-height: 1.5;
}
paper-button {
min-width: 30px;
height: 20px;
margin: 10px 2px 10px 2px;
padding: 0 0 0 0;
}
</style>
<div class='horizontal justified layout'>
<state-info state-obj="[[stateObj]]"></state-info>
<paper-button-group>
<paper-button style="background-color:#74e7ff" on-tap="btntap1"></paper-button>
<paper-button style="background-color:#74ffc2" on-tap="btntap2"></paper-button>
<paper-button style="background-color:#ffd574" on-tap="btntap3"></paper-button>
<paper-button style="background-color:#eaeae1" on-tap="btntap4"></paper-button>
</paper-button-group>
<ha-entity-toggle state-obj="[[stateObj]]" hass="[[hass]]"></ha-entity-toggle>
</div>
</template>
</dom-module>
<script>
Polymer({
is: 'state-card-custom_light',
properties: {
hass: {
type: Object,
},
stateObj: {
type: Object,
},
},
btntap1: function (ev) {
this.setColor(116, 231, 255, 200, ev);
},
btntap2: function (ev) {
this.setColor(116, 255, 194, 200, ev);
},
btntap3: function (ev) {
this.setColor(255, 213, 116, 200, ev);
},
btntap4: function (ev) {
this.setColor(255, 225, 255, 255, ev);
},
setColor(r,g,b,br,ev) {
var serviceData = {entity_id: this.stateObj.entity_id, rgb_color: [r, g, b], brightness: br, transition: 1} || {};
this.hass.callService('light', 'turn_on', serviceData);
ev.stopPropagation();
},
});
</script>
configuration.yaml
homeassistant:
customize:
light.entrance:
custom_ui_state_card: custom_light
light.bedroom:
custom_ui_state_card: custom_light
By responsive I meant adjustments with the UI. In certain states, the buttons push the toggle off the card. Are you seeing that here?
Not really, it has been stable with my usage so far.
How does the receivinig work. Awesome UI, but when you press ‘MED’ what exactly happens… I am very new with this and i want to use RF transmitter to send a signal to my RF box in my fan
should be in a www folder in your root home assistant folder (where your configuration.yaml is located).
It is changing the fan speed to medium - if you can setup your RF fan and establish the low/med/high then it should work as expected.
The custom ui html files are in <config_dir>/www/custom_ui/
thanks for the correction!
Thanks to both of you, I was trying to use a config ui in the wrong folder. I just needed to add the www. Thanks
Hey @andrey - My latest updates seemed to have broken it and my ability/availability to debug quickly is limited. If you or anyone else wants to take what I’ve got and submit to main repo, please feel free.