UNPKG

@hotzware/openhab-tools

Version:

Tools for the openHAB JavaScript Automation Add-On.

206 lines (194 loc) 9.07 kB
/** * Copyright (c) 2023 Florian Hotze * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 * * SPDX-License-Identifier: EPL-2.0 */ const { actions, cache, items, rules, things, triggers } = require('openhab'); /** * Get a Thing's UID from Item name by replacing patterns with replacements. * If patterns is an Array, replacements must be an Array and search-replace pairs must have the same index. * This method is using {@link replaceAll}. * * @example * _getThingNameFromStateItemName('KNX_FF_Lights_state', ['_state', 'KNX_'], ['', 'knx:device:bridge:']); * // Returns: knx:device:bridge:FF_Lights * * @private * @param {string} itemName Item's name * @param {string|Array<string>} patterns Pattern(s) to replace. * @param {string|Array<string>} replacements String(s) that is/are used for replacing. */ function _getThingNameFromStateItemName (itemName, patterns, replacements) { if (typeof patterns === 'string' && typeof replacements === 'string') return itemName.replaceAll(patterns, replacements); // If patterns and replacements are Arrays: let thingUID = itemName; if (typeof patterns === 'object') { for (const i in patterns) { thingUID = thingUID.replaceAll(patterns[i], replacements[i]); } return thingUID; } } /** * Re-enables a Thing by disabling, and then enabling it again. * * @memberof thingsx * @param {string} thingUID */ function reEnableThing (thingUID) { const thing = things.getThing(thingUID); thing.setEnabled(false); setTimeout(() => { thing.setEnabled(true); }, 1000); } /** * Creates a rule that posts Thing statuses to String Items. * The rule takes the name of a group of String Items, generates a Thing UID for each member Item using string replace operations, and then posts the Thing status on every Thing status change to the Items. * The rule also runs when start level 100 is reached and regularly (every 5 minutes, starting with minute 0). * * @example * thingsx.createThingStatusRule('gYamahaState', ['_state', '_'], ['', ':']); * // This removes "_state" from the Item name and replaces all "_" with ":" to get the Thing UID from the members of the "gYamahaState" group members. * * @memberof thingsx * @param {string} groupName * @param {string|Array<string>} patterns Pattern(s) to replace. * @param {string|Array<string>} replacements String(s) that is/are used for replacing. */ function createThingStatusToItemRule (groupName, patterns, replacements) { // Set up default triggers for thing status rules. const triggersList = [ triggers.SystemStartlevelTrigger('100'), triggers.GenericCronTrigger('0 0/5 * ? * * *') ]; // Add ThingStatusChangeTrigger for the matching Thing of each group member // Translates from Item name to Thing UID using replace based on patterns and replacements const members = items.getItem(groupName).members.map(item => item.name); const pairs = new Map(); for (const i in members) { const thingUID = _getThingNameFromStateItemName(members[i], patterns, replacements); triggersList.push(triggers.ThingStatusChangeTrigger(thingUID)); // Store the pairs, so we don't have to get the Thing names again later. pairs.set(members[i], thingUID); } // Create the rule. rules.JSRule({ name: 'Thing states to Item group ' + groupName, description: 'Send the Thing\'s states on change to the according String Items which hold the state.', triggers: triggersList, execute: (event) => { // Update the state of each member Item with the matching Thing's state. for (const i in members) { const thingUID = pairs.get(members[i]); const thingStatus = String(actions.Things.getThingStatusInfo(thingUID)); items.getItem(members[i]).postUpdate(thingStatus); } }, id: 'thing-status-to-items-of-group-' + groupName, tags: ['@hotzware/openhab-tools', 'createThingStatusToItemRule'] }); } /** * Creates a rule that posts Thing statuses to String Items. * The rule takes the name of a group of String Items, generates a Thing UID for each member Item using string replace operations, and then posts the Thing status on every Thing status change to the Items. * The rule also runs when start level 100 is reached and regularly (every 5 minutes, starting with minute 0). * * @example * thingsx.createThingStatusRule('gYamahaState', ['_state', '_'], ['', ':']); * // This removes "_state" fromt the Item name and replaces all "_" with ":" to get the Thing UID from the members of the "gYamahaState" group members. * * @memberof thingsx * @param {string} thingUID * @param {string|Array<string>} patterns Pattern(s) to replace. * @param {string|Array<string>} replacements String(s) that is/are used for replacing. */ /** * Creates a rule that sends a notification if a Thing goes offline and another one if it goes back online. * * @memberof thingsx * @param {string} thingUID * @param {string[]} [recipients] the recipients of the notification: leave empty to send a broadcast notification or put the email addresses of the openHAB Cloud users to receive the notification * @param {number} [offlineDuration=60] the duration to wait for the Thing to come back online before sending the offline notification * @param {number} [onlineDuration=30] the duration to wait for the Thing to stay online before sending the online notification * @param {string} [offlineMessage='WARNUNG: %LABEL nicht mehr erreichbar (%STATUS)!'] the message to send when the Thing goes offline: use %UID, %LABEL, and %STATUS as placeholders for the respective values * @param {string} [onlineMessage='%LABEL wieder erreichbar.'] the message to send when the Thing goes back online: use %UID and %LABEL as placeholders for the respective values */ function createThingStatusNotificationRule (thingUID, recipients = [], offlineDuration = 60, onlineDuration = 30, offlineMessage = 'WARNUNG: %LABEL nicht mehr erreichbar (%STATUS)!', onlineMessage = '%LABEL wieder erreichbar.') { const cacheKey = `${thingUID}-offlineNotificationReferenceId`; rules.JSRule({ name: `Thing ${thingUID} status notification`, description: 'Send a broadcast notification if the Thing goes offline and if it goes back online', triggers: [ triggers.ThingStatusChangeTrigger(thingUID, undefined, 'ONLINE'), triggers.ThingStatusChangeTrigger(thingUID, 'ONLINE') ], execute: (event) => { if (event.newStatus !== 'ONLINE') { if (cache.private.exists(cacheKey)) return; setTimeout(() => { const thing = things.getThing(thingUID); if (thing.status === 'ONLINE') return; if (cache.private.exists(cacheKey)) return; const builder = actions.notificationBuilder(offlineMessage.replace('%UID', thingUID).replace('%LABEL', thing.label).replace('%STATUS', event.newStatus)) .withIcon('error').withTitle('Thing offline'); for (const recipient of recipients) { builder.addUserId(recipient); } builder.send(); const referenceId = builder.send(); cache.private.put(cacheKey, referenceId); }, offlineDuration * 1000); } else { if (!cache.private.exists(cacheKey)) return; setTimeout(() => { const thing = things.getThing(thingUID); if (thing.status !== 'ONLINE') return; if (!cache.private.exists(cacheKey)) return; const referenceId = cache.private.get(cacheKey); const builder = actions.notificationBuilder(onlineMessage.replace('%UID', thingUID).replace('%LABEL', thing.label)) .withIcon('error').withTitle('Thing wieder online').withReferenceId(referenceId); for (const recipient of recipients) { builder.addUserId(recipient); } builder.send(); cache.private.remove(cacheKey); }, onlineDuration * 1000); } }, id: 'thing-status-notification-' + thingUID, tags: ['@hotzware/openhab-tools', 'createThingStatusNotificationRule'] }); } /** * Creates a rule that re-enables a Thing on command ON to a given Item. * * @memberof thingsx * @param {string} itemName * @param {string} thingUID */ function createReEnableThingWithItemRule (itemName, thingUID) { rules.JSRule({ name: 'Re-enable ' + thingUID + ' with ' + itemName, description: 'Disables and then enables a Thing again on command ON.', triggers: triggers.ItemCommandTrigger(itemName, 'ON'), execute: (event) => { reEnableThing(thingUID); // Set command Item to OFF. items.getItem(itemName).postUpdate('OFF'); }, id: 're-enable-' + thingUID + '-with-' + itemName, tags: ['@hotzware/openhab-tools', 'createReEnableThingWithItemRule'] }); } module.exports = { reEnableThing, createThingStatusToItemRule, createThingStatusNotificationRule, createReEnableThingWithItemRule };