diff --git a/README.md b/README.md index 12eba47..5cf3b9f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![GitHub Release][releases-shield]][releases] [![hacs_badge](https://img.shields.io/badge/HACS-default-orange.svg?style=for-the-badge)](https://github.com/custom-components/hacs) -A button card with integrated slider for `automation, light, switch, fan, cover, input_boolean, input_number, media_player, climate, lock` entities. +A button card with integrated slider for `automation, light, switch, fan, cover, input_boolean, input_number, media_player, number, climate, lock` entities. ![Preview][preview] ![Preview 2][preview-2] @@ -71,7 +71,7 @@ Slider Button Card supports Lovelace's Visual Editor. | Name | Type | Requirement | Description | Default | | ----------------- | ------- | ------------ | ------------------------------------------- | ------------------- | | type | string | **Required** | `custom:slider-button-card` | -| entity | string | **Required** | HA entity ID from domain `automation, light, switch, fan, cover, input_boolean, input_number, media_player, climate, lock` | | +| entity | string | **Required** | HA entity ID from domain `automation, light, switch, fan, cover, input_boolean, input_number, media_player, number climate, lock` | | | name | string | **Optional** | Name | `entity.friendly_name` | | show_attribute | boolean | **Optional** | Show attribute | `false` (except for `media_player` entities) | | show_name | boolean | **Optional** | Show name | `true` | @@ -713,8 +713,9 @@ Mixed `group` entities are not supported, if you want to control multiple ## Known issues When you discover any bugs please open an [issue](https://github.com/custom-cards/slider-button-card/issues). -### Input Numbers +### Input Number & Number entities - If the `input_number.entity.min value` is not cleanly divisible by the `input_number.entity.step value`, then the slider card is off by an amount. If your `input_number` has `min = 5`, `max = 25`, `step = 5` then it will work just fine. But if the `step` is 2, then it will be off. This also has the side effect of changing the `input_number` to an "out of bounds" value when modified via this card. Using `step = 1` avoids this problem. +- The same limitation applies to `number` entities. ## Languages diff --git a/src/controllers/controller.ts b/src/controllers/controller.ts index 4bfa030..1e80c74 100644 --- a/src/controllers/controller.ts +++ b/src/controllers/controller.ts @@ -242,7 +242,7 @@ export abstract class Controller { moveSlider(event: any, {left, top, width, height}): number { let percentage = this.calcMovementPercentage(event, {left, top, width, height}); - //percentage = this.applyStep(percentage); + percentage = this.applyStep(percentage); percentage = normalize(percentage, 0, 100); if (!this.isValuePercentage) { percentage = percentageToValue(percentage, this.min, this.max); @@ -299,10 +299,7 @@ export abstract class Controller { } applyStep(value: number): number { - this.log("applyStep value", value); - let rounded = Math.round(value / this.step) * this.step; - this.log("applyStep round", rounded); - return rounded; + return Math.round(value / this.step) * this.step; } log(name = '', value: string | number | object = ''): void { diff --git a/src/controllers/get-controller.ts b/src/controllers/get-controller.ts index 55f0ca0..e13cf98 100644 --- a/src/controllers/get-controller.ts +++ b/src/controllers/get-controller.ts @@ -11,6 +11,7 @@ import { LightController } from './light-controller'; import { LockController } from './lock-controller'; import { MediaController } from './media-controller'; import { SwitchController } from './switch-controller'; +import { NumberController } from './number-controller'; export class ControllerFactory { static getInstance(config: SliderButtonCardConfig): Controller { @@ -24,6 +25,7 @@ export class ControllerFactory { [Domain.INPUT_BOOLEAN]: InputBooleanController, [Domain.INPUT_NUMBER]: InputNumberController, [Domain.MEDIA_PLAYER]: MediaController, + [Domain.NUMBER]: NumberController, [Domain.CLIMATE]: ClimateController, [Domain.LOCK]: LockController, }; diff --git a/src/controllers/input-number-controller.ts b/src/controllers/input-number-controller.ts index 47e902f..21ca5aa 100644 --- a/src/controllers/input-number-controller.ts +++ b/src/controllers/input-number-controller.ts @@ -1,6 +1,4 @@ import { Controller } from './controller'; -import { normalize, percentageToValue, toPercentage } from '../utils'; -import { SliderConfig } from '../types'; export class InputNumberController extends Controller { _targetValue; diff --git a/src/controllers/number-controller.ts b/src/controllers/number-controller.ts new file mode 100644 index 0000000..c87bd7a --- /dev/null +++ b/src/controllers/number-controller.ts @@ -0,0 +1,39 @@ +import { Controller } from './controller'; + +export class NumberController extends Controller { + _targetValue; + _invert = false; + + get _value(): number { + return this.stateObj.state; + } + + set _value(value) { + this._hass.callService('number', 'set_value', { + // eslint-disable-next-line @typescript-eslint/camelcase + entity_id: this.stateObj.entity_id, + value: value, + }); + } + + get _min(): number { + return this.stateObj.attributes.min; + } + + get _max(): number { + return this.stateObj.attributes.max; + } + + get isValuePercentage(): boolean { + return false; + } + + get _step(): number { + return this.stateObj.attributes.step; + } + + get label(): string { + return this.stateObj.attributes.unit_of_measurement ? `${this.targetValue} ${this.stateObj.attributes.unit_of_measurement}` : `${this.targetValue}`; + } + +} diff --git a/src/types.ts b/src/types.ts index 38888b4..75d32d3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -82,6 +82,7 @@ export enum Domain { INPUT_BOOLEAN = 'input_boolean', INPUT_NUMBER = 'input_number', MEDIA_PLAYER = 'media_player', + NUMBER = 'number', CLIMATE = 'climate', LOCK = 'lock', AUTOMATION = 'automation',