Total overhaul!
This commit is contained in:
parent
46be70ee49
commit
1d29e2365f
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
slider-entity-row.js binary
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
node_modules/
|
||||||
|
package-lock.json
|
||||||
|
package.json
|
||||||
|
webpack.config.js
|
42
Makefile
Normal file
42
Makefile
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
AUTHOR := Thomas Lovén
|
||||||
|
CARD_TOOLS := $(PWD)/../card-tools
|
||||||
|
|
||||||
|
PACKAGE := $(shell basename $(CURDIR))
|
||||||
|
PACKAGE := $(PACKAGE:lovelace-%=%)
|
||||||
|
DOCKER_CMD:=docker run --rm -v $(CARD_TOOLS):/card-tools:ro -v $(PWD):/usr/src/$(PACKAGE) -w="/usr/src/$(PACKAGE)" node:11
|
||||||
|
|
||||||
|
build: setup
|
||||||
|
$(DOCKER_CMD) npm run build
|
||||||
|
|
||||||
|
dev: setup
|
||||||
|
$(DOCKER_CMD) npm run watch
|
||||||
|
|
||||||
|
setup: package.json package-lock.json webpack.config.js
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm package.json package-lock.json webpack.config.js
|
||||||
|
rm -r node_modules
|
||||||
|
rm $(PACKAGE).js
|
||||||
|
|
||||||
|
define WEBPACK_CONFIG
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: './src/main.js',
|
||||||
|
mode: 'production',
|
||||||
|
output: {
|
||||||
|
filename: '$(PACKAGE).js',
|
||||||
|
path: path.resolve(__dirname)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
endef
|
||||||
|
export WEBPACK_CONFIG
|
||||||
|
webpack.config.js:
|
||||||
|
echo "$$WEBPACK_CONFIG" >> $@
|
||||||
|
|
||||||
|
package-lock.json:
|
||||||
|
$(DOCKER_CMD) npm install webpack webpack-cli --save-dev
|
||||||
|
|
||||||
|
package.json:
|
||||||
|
$(DOCKER_CMD) /bin/bash -c "npm set init.license 'MIT' && npm set init.author.name '$(AUTHOR)' && npm init -y"
|
||||||
|
$(DOCKER_CMD) sed -E -i -e '/^ +"main"/d' -e '/^ +"scripts"/a\ "build": "webpack",' -e '/^ +"scripts"/a\ "watch": "webpack --watch --mode=development",' -e '2a\ "private": true,' $@
|
129
README.md
129
README.md
@ -1,105 +1,80 @@
|
|||||||
slider-entity-row
|
slider-entity-row
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Add a slider to rows in lovelace entity cards
|
Add a slider to rows in lovelace [entities](https://www.home-assistant.io/lovelace/entities/) cards.
|
||||||
|
|
||||||
This works for:
|
For installation instructions [see this guide](https://github.com/thomasloven/hass-config/wiki/Lovelace-Plugins).
|
||||||
|
|
||||||
|
Install `slider-entity-row.js` as a `module`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Add this to an entities card:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
type: entities
|
||||||
|
entities:
|
||||||
|
- light.bed_light
|
||||||
|
- type: custom:slider-entity-row
|
||||||
|
entity: light.kitchen_lights
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Currenly supported entity domains:
|
||||||
|
|
||||||
- `light` - set brightness
|
- `light` - set brightness
|
||||||
- `media_player` - set volume
|
- `media_player` - set volume
|
||||||
- `climate` - set temperature
|
- `climate` - set temperature
|
||||||
- `cover` - set position
|
- `cover` - set position
|
||||||
- `fan` - set speed (assumes first setting is `off`)
|
- `fan` - set speed (assumes first setting is `off`)
|
||||||
- `input_number`
|
- `input_number` - set value (only if `mode: slider`)
|
||||||
- `input_select`
|
- `input_select` - select option
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
- `toggle: true` - Show a toggle instead of current state
|
||||||
|
- `hide_state: true` - Do not display current state
|
||||||
|
- `hide_when_off: true` - Hide the slider when state is `off`
|
||||||
|
- `full_row: true` - Hide icon and name and stretch slider to full width
|
||||||
|
- `min: <value>` - Set minimum value of slider
|
||||||
|
- `max: <value>` - Set maximum value of slider
|
||||||
|
- `step: <value>` - Set step size of slider
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- title: slider-entity-row
|
type: entities
|
||||||
cards:
|
title: Options
|
||||||
- type: entities
|
|
||||||
title: Domains
|
|
||||||
show_header_toggle: false
|
|
||||||
entities:
|
entities:
|
||||||
- input_number.slider
|
|
||||||
|
|
||||||
- type: section
|
|
||||||
label: light
|
|
||||||
- type: custom:slider-entity-row
|
- type: custom:slider-entity-row
|
||||||
entity: light.bed_light
|
entity: light.bed_light
|
||||||
|
name: Default
|
||||||
|
- type: custom:slider-entity-row
|
||||||
|
entity: light.bed_light
|
||||||
|
name: toggle
|
||||||
|
toggle: true
|
||||||
|
- type: custom:slider-entity-row
|
||||||
|
entity: light.bed_light
|
||||||
|
name: hide_state
|
||||||
|
hide_state: true
|
||||||
- type: custom:slider-entity-row
|
- type: custom:slider-entity-row
|
||||||
entity: light.ceiling_lights
|
entity: light.ceiling_lights
|
||||||
|
name: hide_when_off
|
||||||
|
hide_when_off: true
|
||||||
- type: custom:slider-entity-row
|
- type: custom:slider-entity-row
|
||||||
entity: light.kitchen_lights
|
entity: light.ceiling_lights
|
||||||
|
name: hide_when_off + toggle
|
||||||
- type: section
|
hide_when_off: true
|
||||||
label: media_player
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: media_player.bedroom
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: media_player.living_room
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: media_player.lounge_room
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: media_player.walkman
|
|
||||||
|
|
||||||
- type: section
|
|
||||||
label: cover
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: cover.hall_window
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: cover.garage_door
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: cover.living_room_window
|
|
||||||
|
|
||||||
- type: entities
|
|
||||||
title: Options
|
|
||||||
show_header_toggle: false
|
|
||||||
entities:
|
|
||||||
- type: section
|
|
||||||
label: default
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: light.bed_light
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: media_player.bedroom
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: cover.hall_window
|
|
||||||
|
|
||||||
- type: section
|
|
||||||
label: "toggle: true"
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: light.bed_light
|
|
||||||
toggle: true
|
toggle: true
|
||||||
|
|
||||||
- type: section
|
- type: section
|
||||||
label: "full_row: true"
|
label: full_row
|
||||||
- entity: light.bed_light
|
|
||||||
- type: custom:slider-entity-row
|
- type: custom:slider-entity-row
|
||||||
entity: light.bed_light
|
entity: light.bed_light
|
||||||
full_row: true
|
name: hide_state
|
||||||
- entity: media_player.bedroom
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: media_player.bedroom
|
|
||||||
full_row: true
|
|
||||||
- entity: cover.hall_window
|
|
||||||
- type: custom:slider-entity-row
|
|
||||||
entity: cover.hall_window
|
|
||||||
full_row: true
|
full_row: true
|
||||||
```
|
```
|
||||||
|
|
||||||
### Extra options
|

|
||||||
`hide_state` - (default: false) Set to true to hide the percentage display.
|
|
||||||
|
|
||||||
`min` - (default: 0) Minimum value of slider
|
|
||||||
|
|
||||||
`max` - (default: 100) Maximum value of slider
|
|
||||||
|
|
||||||
`step` - (default: 5) Step size of slider
|
|
||||||
Note that slider values are in percent and will be rescaled e.g. for lights which require a brightness setting between 0 and 255.
|
|
||||||
|
|
||||||
`hide_when_off` - Hide the slider when entity is off.
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
Thanks to Gabe Cook (@gabe565) for help with fan and input_select support.
|
<a href="https://www.buymeacoffee.com/uqD6KHCdJ" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/white_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>
|
||||||
|
File diff suppressed because one or more lines are too long
35
src/climate-controller.js
Normal file
35
src/climate-controller.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import {Controller} from "./controller.js";
|
||||||
|
|
||||||
|
export class ClimateController extends Controller {
|
||||||
|
|
||||||
|
get _value() {
|
||||||
|
return this.stateObj.attributes.temperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
set _value(value) {
|
||||||
|
this._hass.callService("climate", "set_temperature", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
temperature: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get string() {
|
||||||
|
if (this.stateObj.attributes.operation_mode === "off")
|
||||||
|
return this._hass.localize("state.climate.off");
|
||||||
|
return `${this.value} ${this._hass.config.unit_system.temperature}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOff() {
|
||||||
|
return this.stateObj.attributes.operation_mode === "off";
|
||||||
|
}
|
||||||
|
|
||||||
|
get _min() {
|
||||||
|
return this.stateObj.attributes.min_temp;
|
||||||
|
}
|
||||||
|
get _max() {
|
||||||
|
return this.stateObj.attributes.max_temp;
|
||||||
|
}
|
||||||
|
get _step() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
59
src/controller.js
Normal file
59
src/controller.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
export class Controller {
|
||||||
|
constructor(config) {
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
set hass(hass) {
|
||||||
|
this._hass = hass;
|
||||||
|
this.stateObj = this._config.entity in hass.states ? hass.states[this._config.entity] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
if(this._value)
|
||||||
|
return Math.round(this._value/this.step)*this.step;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
set value(value) {
|
||||||
|
if (value !== this.value)
|
||||||
|
this._value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get string() {
|
||||||
|
return `${this.value}`;
|
||||||
|
}
|
||||||
|
get hidden() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
get hasSlider() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
get hasToggle() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOff() {
|
||||||
|
return this.value === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get min() {
|
||||||
|
if (this._config.min !== undefined)
|
||||||
|
return this._config.min;
|
||||||
|
if (this._min !== undefined)
|
||||||
|
return this._min;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
get max() {
|
||||||
|
if (this._config.max !== undefined)
|
||||||
|
return this._config.max;
|
||||||
|
if (this._max !== undefined)
|
||||||
|
return this._max;
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
get step() {
|
||||||
|
if (this._config.step !== undefined)
|
||||||
|
return this._config.step;
|
||||||
|
if (this._step !== undefined)
|
||||||
|
return this._step;
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
40
src/cover-controller.js
Normal file
40
src/cover-controller.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import {Controller} from "./controller.js";
|
||||||
|
|
||||||
|
export class CoverController extends Controller {
|
||||||
|
|
||||||
|
get _value() {
|
||||||
|
return this.stateObj.state === "open"
|
||||||
|
? this.stateObj.attributes.current_position
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
set _value(value) {
|
||||||
|
this._hass.callService("cover", "set_cover_position", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
position: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get string() {
|
||||||
|
if (!this.hasSlider)
|
||||||
|
return "";
|
||||||
|
if (this.stateObj.state === "closed")
|
||||||
|
return this._hass.localize("state.cover.closed");
|
||||||
|
return `${this.value} %`
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasToggle() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasSlider() {
|
||||||
|
if ("current_position" in this.stateObj.attributes) return true;
|
||||||
|
if (("supported_features" in this.stateObj.attributes) &&
|
||||||
|
(this.stateObj.attributes.supported_features & 4)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get _step() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
43
src/fan-controller.js
Normal file
43
src/fan-controller.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import {Controller} from "./controller.js";
|
||||||
|
|
||||||
|
export class FanController extends Controller {
|
||||||
|
|
||||||
|
get _value() {
|
||||||
|
return (this.stateObj.state !== "off")
|
||||||
|
? this.stateObj.attributes.speed_list.indexOf(this.stateObj.attributes.speed)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
set _value(value) {
|
||||||
|
if (value in this.stateObj.attributes.speed_list) {
|
||||||
|
this._hass.callService("fan", "turn_on", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
speed: this.stateObj.attributes.speed_list[value],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._hass.callService("fan", "turn_off", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get string() {
|
||||||
|
if (this.stateObj.state === "off")
|
||||||
|
return this._hass.localize("state.default.off");
|
||||||
|
return this.stateObj.attributes.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasSlider() {
|
||||||
|
if ("speed" in this.stateObj.attributes) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get _max() {
|
||||||
|
return this.stateObj.attributes.speed_list.length -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get _step() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
src/input-number-controller.js
Normal file
44
src/input-number-controller.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import {Controller} from "./controller.js";
|
||||||
|
|
||||||
|
export class InputNumberController extends Controller {
|
||||||
|
|
||||||
|
get _value() {
|
||||||
|
return this.stateObj.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
set _value(value) {
|
||||||
|
this._hass.callService("input_number", "set_value", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
value: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get string() {
|
||||||
|
return `${Math.round(this.stateObj.state)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOff() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasToggle() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasSlider() {
|
||||||
|
return this.stateObj.attributes.mode === "slider";
|
||||||
|
}
|
||||||
|
|
||||||
|
get _min() {
|
||||||
|
return this.stateObj.attributes.min;
|
||||||
|
}
|
||||||
|
|
||||||
|
get _max() {
|
||||||
|
return this.stateObj.attributes.max;
|
||||||
|
}
|
||||||
|
|
||||||
|
get _step() {
|
||||||
|
return this.stateObj.attributes.step;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
src/input-select-controller.js
Normal file
41
src/input-select-controller.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import {Controller} from "./controller.js";
|
||||||
|
|
||||||
|
export class InputSelectController extends Controller {
|
||||||
|
|
||||||
|
get _value() {
|
||||||
|
return this.stateObj.attributes.options.indexOf(this.stateObj.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
set _value(value) {
|
||||||
|
if (value in this.stateObj.attributes.options)
|
||||||
|
this._hass.callService("input_select", "select_option", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
option: this.stateObj.attributes.options[value],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get string() {
|
||||||
|
return this.stateObj.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOff() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasToggle() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasSlider() {
|
||||||
|
return this.stateObj.attributes.options && this.stateObj.attributes.options.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get _max() {
|
||||||
|
return this.stateObj.attributes.options.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get _step() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
src/light-controller.js
Normal file
37
src/light-controller.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import {Controller} from "./controller.js";
|
||||||
|
|
||||||
|
export class LightController extends Controller {
|
||||||
|
|
||||||
|
get _value() {
|
||||||
|
return (this.stateObj.state === "on")
|
||||||
|
? Math.ceil(this.stateObj.attributes.brightness*100.0/255)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
set _value(value) {
|
||||||
|
value = Math.ceil(value/100.0*255);
|
||||||
|
if (value) {
|
||||||
|
this._hass.callService("light", "turn_on", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
brightness: value,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._hass.callService("light", "turn_off", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get string() {
|
||||||
|
if (this.stateObj.state === "off")
|
||||||
|
return this._hass.localize("state.default.off");
|
||||||
|
return `${this.value} %`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasSlider() {
|
||||||
|
if ("brightness" in this.stateObj.attributes) return true;
|
||||||
|
if (("supported_features" in this.stateObj.attributes) &&
|
||||||
|
(this.stateObj.attributes.supported_features & 1)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
119
src/main.js
Normal file
119
src/main.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import {LitElement, html, css} from "/card-tools/lit-element.js";
|
||||||
|
|
||||||
|
import { Controller } from "./controller.js";
|
||||||
|
import { LightController } from "./light-controller.js";
|
||||||
|
import { MediaPlayerController } from "./media-player-controller.js";
|
||||||
|
import { ClimateController } from "./climate-controller.js";
|
||||||
|
import { CoverController } from "./cover-controller.js";
|
||||||
|
import { FanController } from "./fan-controller.js";
|
||||||
|
import { InputNumberController } from "./input-number-controller.js";
|
||||||
|
import { InputSelectController } from "./input-select-controller.js";
|
||||||
|
|
||||||
|
const controllers = {
|
||||||
|
light: LightController,
|
||||||
|
media_player: MediaPlayerController,
|
||||||
|
climate: ClimateController,
|
||||||
|
cover: CoverController,
|
||||||
|
fan: FanController,
|
||||||
|
input_number: InputNumberController,
|
||||||
|
input_select: InputSelectController,
|
||||||
|
};
|
||||||
|
|
||||||
|
class SliderEntityRow extends LitElement {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
hass: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig(config) {
|
||||||
|
this._config = config;
|
||||||
|
const domain = config.entity.split('.')[0];
|
||||||
|
const ctrlClass = controllers[domain];
|
||||||
|
if(!ctrlClass)
|
||||||
|
throw new Error(`Unsupported entity type: ${domain}`);
|
||||||
|
this.ctrl = new ctrlClass(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const c = this.ctrl;
|
||||||
|
c.hass = this.hass;
|
||||||
|
const slider = html`
|
||||||
|
<ha-slider
|
||||||
|
.min=${c.min}
|
||||||
|
.max=${c.max}
|
||||||
|
.step=${c.step}
|
||||||
|
.value=${c.value}
|
||||||
|
pin
|
||||||
|
@change=${(ev) => c.value = this.shadowRoot.querySelector("ha-slider").value}
|
||||||
|
class=${this._config.full_row ? "full" : ""}
|
||||||
|
></ha-slider>
|
||||||
|
`;
|
||||||
|
const toggle = html`
|
||||||
|
<ha-entity-toggle
|
||||||
|
.stateObj=${this.hass.states[this._config.entity]}
|
||||||
|
.hass=${this.hass}
|
||||||
|
></ha-entity-toggle>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const content = html`
|
||||||
|
<div class="wrapper" @click=${(ev) => ev.stopPropagation()}>
|
||||||
|
${(c.stateObj.state === "unavailable")
|
||||||
|
? html`
|
||||||
|
<span class="state">
|
||||||
|
unavailable
|
||||||
|
</span>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
${((this._config.hide_when_off && c.isOff)
|
||||||
|
|| !c.hasSlider)
|
||||||
|
? ""
|
||||||
|
: slider }
|
||||||
|
${(this._config.hide_state || this._config.toggle)
|
||||||
|
? ""
|
||||||
|
: html`
|
||||||
|
<span class="state">
|
||||||
|
${c.string}
|
||||||
|
</span>
|
||||||
|
`}
|
||||||
|
${this._config.toggle
|
||||||
|
&& c.hasToggle
|
||||||
|
? toggle
|
||||||
|
: ""}
|
||||||
|
`}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (this._config.full_row)
|
||||||
|
return content;
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<hui-generic-entity-row
|
||||||
|
.hass=${this.hass}
|
||||||
|
.config=${this._config}
|
||||||
|
> ${content} </hui-generic-entity-row>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
.state {
|
||||||
|
min-width: 45px;
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
ha-entity-toggle {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
ha-slider.full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('slider-entity-row', SliderEntityRow);
|
34
src/media-player-controller.js
Normal file
34
src/media-player-controller.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import {Controller} from "./controller.js";
|
||||||
|
|
||||||
|
export class MediaPlayerController extends Controller {
|
||||||
|
|
||||||
|
get _value() {
|
||||||
|
return (this.stateObj.is_volume_muted === "on")
|
||||||
|
? 0
|
||||||
|
: Math.ceil(this.stateObj.attributes.volume_level*100.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
set _value(value) {
|
||||||
|
value = value/100.0;
|
||||||
|
this._hass.callService("media_player", "volume_set", {
|
||||||
|
entity_id: this.stateObj.entity_id,
|
||||||
|
volume_level: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOff() {
|
||||||
|
return this.stateObj.state === "off";
|
||||||
|
}
|
||||||
|
|
||||||
|
get string() {
|
||||||
|
if (this.stateObj.attributes.is_volume_muted)
|
||||||
|
return "-";
|
||||||
|
return !!this.stateObj.attributes.volume_level
|
||||||
|
? `${this.value} %`
|
||||||
|
: this._hass.localize("state.media_player.off");
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasToggle() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user