Skip to content

Commit

Permalink
[items] Item: Add increaseValueTo/decreaseValueTo methods (#371)
Browse files Browse the repository at this point in the history
Closes #369.

Also:
- Make `Item::getToggleState` method private.
- Adjust `Item::getToggleState`/`Item::sendToggleCommand` method to `Item.type` changes from a previous PR
- Use brightness value of Color Items for `Item::numericState`.

---------

Signed-off-by: Florian Hotze <[email protected]>
  • Loading branch information
florian-h05 authored Sep 18, 2024
1 parent a16729f commit 2348409
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 33 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ Calling `getItem(...)` or `...` returns an `Item` object with the following prop
- .removeMetadata(namespace) ⇒ `object|null`
- .sendCommand(value): `value` can be a string, a [`time.ZonedDateTime`](#time) or a [`Quantity`](#quantity)
- .sendCommandIfDifferent(value) ⇒ `boolean`: `value` can be a string, a [`time.ZonedDateTime`](#time) or a [`Quantity`](#quantity)
- .sendIncreaseCommand(value) ⇒ `boolean`: `value` can be a number, or a [`Quantity`](#quantity)
- .sendDecreaseCommand(value) ⇒ `boolean`: `value` can be a number, or a [`Quantity`](#quantity)
- .sendToggleCommand(): Sends a command to flip the Item's state (e.g. if it is 'ON' an 'OFF' command is sent).
- .postUpdate(value): `value` can be a string, a [`time.ZonedDateTime`](#time) or a [`Quantity`](#quantity)
- .addGroups(...groupNamesOrItems)
- .removeGroups(...groupNamesOrItems)
Expand Down
88 changes: 74 additions & 14 deletions src/items/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const log = require('../log')('items');
const { _toOpenhabPrimitiveType, _isQuantity, _isItem } = require('../helpers');
const { getQuantity, QuantityError } = require('../quantity');

const { UnDefType, OnOffType, events, itemRegistry } = require('@runtime');
const { OnOffType, PercentType, UnDefType, events, itemRegistry } = require('@runtime');

const metadata = require('./metadata/metadata');
const ItemPersistence = require('./item-persistence');
Expand Down Expand Up @@ -124,7 +124,9 @@ class Item {
* @type {number|null}
*/
get numericState () {
const numericState = parseFloat(this.rawState.toString());
let state = this.rawState.toString();
if (this.type === 'Color') state = this.rawItem.getStateAs(PercentType).toString();
const numericState = parseFloat(state);
return isNaN(numericState) ? null : numericState;
}

Expand Down Expand Up @@ -247,7 +249,7 @@ class Item {
sendCommandIfDifferent (value) {
// value and current state both are Quantity and have equal value
if (_isQuantity(value) && this.quantityState !== null) {
if (this.quantityState.equal(value)) {
if (value.equal(this.quantityState)) {
return false;
}
}
Expand All @@ -271,20 +273,79 @@ class Item {
}

/**
* Calculates the toggled state of this Item. For Items like Color and
* Dimmer, getStateAs(OnOffType) is used and the toggle calculated off
* of that.
* Increase the value of this Item to the given value by sending a command, but only if the current state is less than that value.
*
* @param {number|Quantity|HostState} value the value of the command to send, such as 'ON'
* @return {boolean} true if the command was sent, false otherwise
*/
sendIncreaseCommand (value) {
// value and current state both are Quantity and value is less than or equal current state
if (_isQuantity(value) && this.quantityState !== null) {
if (value.lessThanOrEqual(this.quantityState)) {
log.debug('sendIncreaseCommand: Ignoring command {} for Item {} with state {}', value, this.name, this.state);
return false;
}
}

// value and current state are both numeric and value is less than or equal current state
if (typeof value === 'number' && this.numericState !== null) {
if (value <= this.numericState) {
log.debug('sendIncreaseCommand: Ignoring command {} for Item {} with state {}', value, this.name, this.state);
return false;
}
}

// else send the command
log.debug('sendIncreaseCommand: Sending command {} to Item {} with state {}', value, this.name, this.state);
this.sendCommand(value);
return true;
}

/**
* Decreases the value of this Item to the given value by sending a command, but only if the current state is greater than that value.
*
* @param {number|Quantity|HostState} value the value of the command to send, such as 'ON'
* @return {boolean} true if the command was sent, false otherwise
*/
sendDecreaseCommand (value) {
// value and current state both are Quantity and value is greater than or equal current state
if (_isQuantity(value) && this.quantityState !== null) {
if (value.greaterThanOrEqual(this.quantityState)) {
log.debug('sendDecreaseCommand: Ignoring command {} for Item {} with state {}', value, this.name, this.state);
return false;
}
}

// value and current state are both numeric and value is greater than or equal current state
if (typeof value === 'number' && this.numericState !== null) {
if (value >= this.numericState) {
log.debug('sendDecreaseCommand: Ignoring command {} for Item {} with state {}', value, this.name, this.state);
return false;
}
}

// else send the command
log.debug('sendDecreaseCommand: Sending command {} to Item {} with state {}', value, this.name, this.state);
this.sendCommand(value);
return true;
}

/**
* Calculates the toggled state of this Item.
* For Items like Color and Dimmer, getStateAs(OnOffType) is used and the toggle calculated of that.
*
* @private
* @returns the toggled state (e.g. 'OFF' if the Item is 'ON')
* @throws error if the Item is uninitialized or is a type that doesn't make sense to toggle
*/
getToggleState () {
#getToggleState () {
if (this.isUninitialized) {
throw Error('Cannot toggle uninitialized Items');
}
switch (this.type) {
case 'PlayerItem' :
case 'Player' :
return this.state === 'PAUSE' ? 'PLAY' : 'PAUSE';
case 'ContactItem' :
case 'Contact' :
return this.state === 'OPEN' ? 'CLOSED' : 'OPEN';
default: {
const oldState = this.rawItem.getStateAs(OnOffType);
Expand All @@ -298,15 +359,14 @@ class Item {
}

/**
* Sends a command to flip the Item's state (e.g. if it is 'ON' an 'OFF'
* command is sent).
* Sends a command to flip the Item's state (e.g. if it is 'ON' an 'OFF' command is sent).
* @throws error if the Item is uninitialized or a type that cannot be toggled or commanded
*/
sendToggleCommand () {
if (this.type === 'ContactItem') {
if (this.type === 'Contact') {
throw Error('Cannot command Contact Items');
}
this.sendCommand(this.getToggleState());
this.sendCommand(this.#getToggleState());
}

/**
Expand All @@ -315,7 +375,7 @@ class Item {
* @throws error if the Item is uninitialized or a type that cannot be toggled
*/
postToggleUpdate () {
this.postUpdate(this.getToggleState());
this.postUpdate(this.#getToggleState());
}

/**
Expand Down
22 changes: 14 additions & 8 deletions types/items/items.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,16 +254,21 @@ export class Item {
*/
sendCommandIfDifferent(value: string | number | time.ZonedDateTime | Quantity | HostState): boolean;
/**
* Calculates the toggled state of this Item. For Items like Color and
* Dimmer, getStateAs(OnOffType) is used and the toggle calculated off
* of that.
* @returns the toggled state (e.g. 'OFF' if the Item is 'ON')
* @throws error if the Item is uninitialized or is a type that doesn't make sense to toggle
* Increase the value of this Item to the given value by sending a command, but only if the current state is less than that value.
*
* @param {number|Quantity|HostState} value the value of the command to send, such as 'ON'
* @return {boolean} true if the command was sent, false otherwise
*/
sendIncreaseCommand(value: number | Quantity | HostState): boolean;
/**
* Decreases the value of this Item to the given value by sending a command, but only if the current state is greater than that value.
*
* @param {number|Quantity|HostState} value the value of the command to send, such as 'ON'
* @return {boolean} true if the command was sent, false otherwise
*/
getToggleState(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendDecreaseCommand(value: number | Quantity | HostState): boolean;
/**
* Sends a command to flip the Item's state (e.g. if it is 'ON' an 'OFF'
* command is sent).
* Sends a command to flip the Item's state (e.g. if it is 'ON' an 'OFF' command is sent).
* @throws error if the Item is uninitialized or a type that cannot be toggled or commanded
*/
sendToggleCommand(): void;
Expand Down Expand Up @@ -312,6 +317,7 @@ export class Item {
*/
removeTags(...tagNames: string[]): void;
toString(): any;
#private;
}
import metadata = require("./metadata/metadata");
import TimeSeries = require("./time-series");
Expand Down
2 changes: 1 addition & 1 deletion types/items/items.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion types/items/metadata/itemchannellink.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export type Item = {
};
sendCommand(value: any): void;
sendCommandIfDifferent(value: any): boolean;
getToggleState(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendIncreaseCommand(value: any): boolean;
sendDecreaseCommand(value: any): boolean;
"__#5@#getToggleState"(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendToggleCommand(): void;
postToggleUpdate(): void;
postUpdate(value: any): void;
Expand Down
2 changes: 1 addition & 1 deletion types/items/metadata/itemchannellink.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion types/items/metadata/metadata.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ export type Item = {
removeMetadata(namespace?: string): ItemMetadata;
sendCommand(value: any): void;
sendCommandIfDifferent(value: any): boolean;
getToggleState(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendIncreaseCommand(value: any): boolean;
sendDecreaseCommand(value: any): boolean;
"__#5@#getToggleState"(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendToggleCommand(): void;
postToggleUpdate(): void;
postUpdate(value: any): void;
Expand Down
2 changes: 1 addition & 1 deletion types/items/metadata/metadata.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion types/quantity.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export type Item = {
rawItem: HostItem;
persistence: import("./items/item-persistence");
/**
* QuantityError is thrown when {@link Quantity} creation or operation fails.
* It is used to wrap the underlying Java Exceptions and add some additional information and a JS stacktrace to it.
*/
semantics: import("./items/item-semantics");
readonly type: string;
readonly name: string;
Expand Down Expand Up @@ -31,7 +35,9 @@ export type Item = {
};
sendCommand(value: any): void;
sendCommandIfDifferent(value: any): boolean;
getToggleState(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendIncreaseCommand(value: any): boolean;
sendDecreaseCommand(value: any): boolean;
"__#5@#getToggleState"(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendToggleCommand(): void;
postToggleUpdate(): void;
postUpdate(value: any): void;
Expand Down
2 changes: 1 addition & 1 deletion types/quantity.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion types/rules/operation-builder.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export type Item = {
};
sendCommand(value: any): void;
sendCommandIfDifferent(value: any): boolean;
getToggleState(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendIncreaseCommand(value: any): boolean;
sendDecreaseCommand(value: any): boolean;
"__#5@#getToggleState"(): "PAUSE" | "PLAY" | "OPEN" | "CLOSED" | "ON" | "OFF";
sendToggleCommand(): void;
postToggleUpdate(): void;
postUpdate(value: any): void;
Expand Down
Loading

0 comments on commit 2348409

Please sign in to comment.