Skip to content

Commit

Permalink
[rules] SwitchableJSRule: Add ability to specify name of Switch Item (
Browse files Browse the repository at this point in the history
#325)

This adds an option to the rule config for `SwitchableJSRule` to specify
the name of the Switch Item, which enables and disables the rule.
If no `switchItemName` is provided, the Item name will be generated as
before.
If the `switchItemName` is specified but no Item with the specified name
exists, an Item with that name is created, else the existing Item with
this name is used.

---------

Signed-off-by: Florian Hotze <[email protected]>
  • Loading branch information
florian-h05 authored Mar 24, 2024
1 parent 7dcd7ef commit 6ac82b1
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 41 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ See [openhab-js : items](https://openhab.github.io/openhab-js/items.html) for fu

- items : `object`
- .NAME ⇒ `Item`
- .existsItem(name) ⇒ `boolean`
- .getItem(name, nullIfMissing) ⇒ `Item`
- .getItems() ⇒ `Array[Item]`
- .getItemsByTag(...tagNames) ⇒ `Array[Item]`
Expand Down Expand Up @@ -1092,7 +1093,7 @@ See [openhab-js : rules](https://openhab.github.io/openhab-js/rules.html) for fu
### JSRule
JSRules provides a simple, declarative syntax for defining rules that will be executed based on a trigger condition
`JSRule` provides a simple, declarative syntax for defining rules that will be executed based on a trigger condition:
```javascript
var email = "[email protected]"
Expand Down Expand Up @@ -1156,6 +1157,9 @@ triggers.DateTimeTrigger('MyDateTimeItem');
You can use `null` for a trigger parameter to skip its configuration.
You may use `SwitchableJSRule` to create a rule that can be enabled and disabled with a Switch Item.
As an extension to `JSRule`, its syntax is the same, however you can specify an Item name (using the `switchItemName` rule config property) if you don't like the automatically created Item's name.
See [openhab-js : triggers](https://openhab.github.io/openhab-js/triggers.html) in the API documentation for a full list of all triggers.
### Rule Builder
Expand Down
22 changes: 19 additions & 3 deletions src/items/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class Item {
* @type {string}
*/
get type () {
return this.rawItem.getClass().getSimpleName();
return this.rawItem.getType().toString();
}

/**
Expand Down Expand Up @@ -460,8 +460,8 @@ function _createItem (itemConfig) {
* @memberof items
* @param {ItemConfig} itemConfig the Item config describing the Item
* @returns {Item} {@link Items.Item}
* @throws {Error} {@link ItemConfig}.name or {@link ItemConfig}.type not set
* @throws failed to create Item
* @throws {Error} if {@link ItemConfig}.name or {@link ItemConfig}.type is not set
* @throws {Error} if failed to create Item
*/
function addItem (itemConfig) {
const item = _createItem(itemConfig);
Expand Down Expand Up @@ -562,6 +562,21 @@ function replaceItem (itemConfig) {
return item;
}

/**
* Whether an Item with the given name exists.
* @memberof items
* @param {string} name the name of the Item
* @returns {boolean} whether the Item exists
*/
function existsItem (name) {
try {
itemRegistry.getItem(name);
return true;
} catch (e) {
return false;
}
}

/**
* Gets an openHAB Item.
* @memberof items
Expand Down Expand Up @@ -614,6 +629,7 @@ const safeItemName = (s) => s

const itemProperties = {
safeItemName,
existsItem,
getItem,
getItems,
addItem,
Expand Down
51 changes: 26 additions & 25 deletions src/rules/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
* @property {string[]} [tags] tags for the rule (used in UI)
* @property {string} [ruleGroup] name of rule group to use
* @property {boolean} [overwrite=false] whether to overwrite an existing rule with the same UID
* @property {string} [switchItemName] (optional and only for {@link SwitchableJSRule}) name of the switch Item, which will get created automatically if it is not existent
*/

const GENERATED_RULE_ITEM_TAG = 'GENERATED_RULE_ITEM';
Expand All @@ -62,14 +63,6 @@ const { automationManager, ruleRegistry } = require('@runtime/RuleSupport');

const RuleManager = osgi.getService('org.openhab.core.automation.RuleManager');

/**
* Generates an Item name given the rule configuration.
*
* @private
* @param {object} ruleConfig The rule config
*/
const _itemNameForRule = (ruleConfig) => 'vRuleItemFor' + items.safeItemName(ruleConfig.name);

/**
* Links an Item to a rule. When the Item is switched on or off, so will the rule be.
*
Expand All @@ -78,6 +71,9 @@ const _itemNameForRule = (ruleConfig) => 'vRuleItemFor' + items.safeItemName(rul
* @param {items.Item} item the Item to link to the rule.
*/
function _linkItemToRule (rule, item) {
if (item.type !== 'Switch') {
throw new Error('The linked Item for SwitchableJSRule must be a Switch Item!');
}
JSRule({
name: 'vProxyRuleFor' + rule.getName(),
description: 'Generated Rule to toggle real rule for ' + rule.getName(),
Expand Down Expand Up @@ -286,28 +282,33 @@ function JSRule (ruleConfig) {
}

/**
* Creates a rule, with an associated SwitchItem that can be used to toggle the rule's enabled state.
* The rule will be created and immediately available.
*
* @memberof rules
* @param {RuleConfig} ruleConfig The rule config describing the rule
* @returns {HostRule} the created rule
* @throws {Error} an error is a rule with the given UID already exists.
*/
* Creates a rule, with an associated Switch Item that can be used to toggle the rule's enabled state.
* The rule will be created and immediately available.
* The Switch Item will be created automatically unless you pass a {@link RuleConfig}`switchItemName` and an Item with that name already exists.
*
* @memberof rules
* @param {RuleConfig} ruleConfig The rule config describing the rule
* @returns {HostRule} the created rule
* @throws {Error} an error is a rule with the given UID already exists.
*/
function SwitchableJSRule (ruleConfig) {
if (!ruleConfig.name) {
throw Error('No name specified for rule!');
}

// First create a toggling Item
const itemName = _itemNameForRule(ruleConfig);
const item = items.replaceItem({
name: itemName,
type: 'Switch',
groups: [_getGroupForItem(ruleConfig)],
label: ruleConfig.description,
tags: [GENERATED_RULE_ITEM_TAG]
});
const itemName = ruleConfig.switchItemName || 'vRuleItemFor' + items.safeItemName(ruleConfig.name);
if (!items.existsItem(itemName)) {
log.info(`Creating Item: ${itemName}`);
items.addItem({
name: itemName,
type: 'Switch',
groups: [_getGroupForItem(ruleConfig)],
label: ruleConfig.description,
tags: [GENERATED_RULE_ITEM_TAG]
});
}
const item = items.getItem(itemName);

// create the real rule
const rule = JSRule(ruleConfig);
Expand All @@ -321,7 +322,7 @@ function SwitchableJSRule (ruleConfig) {
try {
historicState = item.history.latestState();
} catch (e) {
log.warn(`Failed to get historic state of ${itemName} for rule ${ruleConfig.name}: ${e}`);
log.warn(`Failed to get historic state of ${item.name} for rule ${ruleConfig.name}: ${e}`);
}

if (historicState !== null) {
Expand Down
11 changes: 9 additions & 2 deletions types/items/items.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ export type ItemConfig = {
* @returns {string} a valid Item name
*/
export function safeItemName(s: string): string;
/**
* Whether an Item with the given name exists.
* @memberof items
* @param {string} name the name of the Item
* @returns {boolean} whether the Item exists
*/
export function existsItem(name: string): boolean;
/**
* Gets an openHAB Item.
* @memberof items
Expand All @@ -76,8 +83,8 @@ export function getItems(): Item[];
* @memberof items
* @param {ItemConfig} itemConfig the Item config describing the Item
* @returns {Item} {@link Items.Item}
* @throws {Error} {@link ItemConfig}.name or {@link ItemConfig}.type not set
* @throws failed to create Item
* @throws {Error} if {@link ItemConfig}.name or {@link ItemConfig}.type is not set
* @throws {Error} if failed to create Item
*/
export function addItem(itemConfig: ItemConfig): Item;
/**
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.

21 changes: 13 additions & 8 deletions types/rules/rules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ export type RuleConfig = {
* whether to overwrite an existing rule with the same UID
*/
overwrite?: boolean;
/**
* (optional and only for {@link SwitchableJSRule }) name of the switch Item, which will get created automatically if it is not existent
*/
switchItemName?: string;
};
/**
* Remove a rule when it exists. The rule will be immediately removed.
Expand Down Expand Up @@ -183,13 +187,14 @@ export function setEnabled(uid: string, isEnabled: boolean): void;
*/
export function JSRule(ruleConfig: RuleConfig): HostRule;
/**
* Creates a rule, with an associated SwitchItem that can be used to toggle the rule's enabled state.
* The rule will be created and immediately available.
*
* @memberof rules
* @param {RuleConfig} ruleConfig The rule config describing the rule
* @returns {HostRule} the created rule
* @throws {Error} an error is a rule with the given UID already exists.
*/
* Creates a rule, with an associated Switch Item that can be used to toggle the rule's enabled state.
* The rule will be created and immediately available.
* The Switch Item will be created automatically unless you pass a {@link RuleConfig}`switchItemName` and an Item with that name already exists.
*
* @memberof rules
* @param {RuleConfig} ruleConfig The rule config describing the rule
* @returns {HostRule} the created rule
* @throws {Error} an error is a rule with the given UID already exists.
*/
export function SwitchableJSRule(ruleConfig: RuleConfig): HostRule;
//# sourceMappingURL=rules.d.ts.map
2 changes: 1 addition & 1 deletion types/rules/rules.d.ts.map

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

0 comments on commit 6ac82b1

Please sign in to comment.