Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 172 additions & 3 deletions configuration/jsr223.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,23 +236,27 @@ Note that prior to openHAB 3, script ordering was performed alphanumerically bas

To facilitate JSR223 scripting, several openHAB-related variables are automatically predefined within `ScriptExtension` presets.
They can be loaded into the script context using `scriptExtension.importPreset(String preset)`, e.g. `scriptExtension.importPreset("RuleSimple")`.
The `default` preset is preloaded, so it does not require importing.
The `default`, `lifecycle` and `media` presets are preloaded, so they do not require importing.
With `scriptExtension.get("automationManager")` the `automationManager` can be made available without loading a preset.

- [Overview](#overview)
- [Example rules for a first impression](#example-rules-for-a-first-impression)
- [Script Locations](#script-locations)
- [`ScriptExtension` Objects (all JSR223 languages)](#scriptextension-objects-all-jsr223-languages)
- [Default Preset (`importPreset` not required)](#default-preset-importpreset-not-required)
- [`default` Preset (`importPreset` not required)](#default-preset-importpreset-not-required)
- [`events` operations](#events-operations)
- [`lifecycle` Preset (`importPreset` not required)](#lifecycle-preset-importpreset-not-required)
- [`media` Preset (`importPreset` not required)](#media-preset-importpreset-not-required)
- [`RuleSimple` Preset](#rulesimple-preset)
- [`RuleSupport` Preset](#rulesupport-preset)
- [`RuleFactories` Preset](#rulefactories-preset)
- [`ScriptAction` Preset](#scriptaction-preset)
- [`cache` Preset](#cache-preset)
- [`provider` Preset](#provider-preset)
- [`TriggerType` Objects (all JSR223 languages)](#triggertype-objects-all-jsr223-languages)
- [The `scriptLoaded` and `scriptUnloaded` functions](#the-scriptloaded-and-scriptunloaded-functions)

#### Default Preset (`importPreset` not required)
#### `default` Preset (`importPreset` not required)

| Variable | Description |
|-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
Expand Down Expand Up @@ -335,6 +339,24 @@ With `scriptExtension.get("automationManager")` the `automationManager` can be m
- `events.storeStates(Item...)`
- `events.restoreStates(Map<Item, State>)`

#### `lifecycle` Preset (`importPreset` not required)

It provides a mechanism to execute code, when the script is deleted.
Modifying a script deletes it and creates it again.

| Variable | Description |
|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `lifecycleTracker` | [`org.openhab.core.automation.module.script.LifecycleScriptExtensionProvider.LifecycleTracker`](https://www.openhab.org/javadoc/latest/org/openhab/core/automation/module/script/lifecyclescriptextensionprovider.lifecycletracker) |

This is demonstrated in [The `scriptLoaded` and `scriptUnloaded` functions](#the-scriptloaded-and-scriptunloaded-functions) section.

#### `media` Preset (`importPreset` not required)

| Variable | Description |
|----------|---------------------------------------------------------------------------------------------------------------------|
| `audio` | [`org.openhab.core.audio.AudioManager`](https://www.openhab.org/javadoc/latest/org/openhab/core/audio/audiomanager) |
| `voice` | [`org.openhab.core.voice.VoiceManager`](https://www.openhab.org/javadoc/latest/org/openhab/core/voice/voicemanager) |

#### `RuleSimple` Preset

These variables and classes are loaded using:
Expand Down Expand Up @@ -532,6 +554,25 @@ Both caches implement the `org.openhab.core.automation.module.script.rulesupport
- `Object get(String key)`: Get the value for the given key from the cache. Non-existent keys return `null`.
- `Object get(String key, Supplier<Object> supplier`: Get the value for the given key. If no value is present, add the value that is return from the `supplier`.

#### `provider` Preset

The preset is available since openHAB 5.0.

| Variable | Description |
|---------------------------| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `itemRegistry` | [`org.openhab.core.automation.module.script.providersupport.shared.ProviderItemRegistryDelegate`](https://www.openhab.org/javadoc/latest/org/openhab/core/automation/module/script/providersupport/shared/provideritemregistrydelegate) |
| `metadataRegistry` | [`org.openhab.core.automation.module.script.providersupport.shared.ProviderMetadataRegistryDelegate`](https://www.openhab.org/javadoc/latest/org/openhab/core/automation/module/script/providersupport/shared/providermetadataregistrydelegate) |
| `thingRegistry` | [`org.openhab.core.automation.module.script.providersupport.shared.ProviderThingRegistryDelegate`](https://www.openhab.org/javadoc/latest/org/openhab/core/automation/module/script/providersupport/shared/providerthingregistrydelegate) |
| `itemChannelLinkRegistry` | [`org.openhab.core.automation.module.script.providersupport.shared.ProviderItemChannelLinkRegistry`](https://www.openhab.org/javadoc/latest/org/openhab/core/automation/module/script/providersupport/shared/provideritemchannellinkregistry) |

The above instances provide implementations of the interfaces [`org.openhab.core.items.ItemRegistry`](https://www.openhab.org/javadoc/latest/org/openhab/core/items/itemregistry), [`org.openhab.core.items.MetadataRegistry`](https://www.openhab.org/javadoc/latest/org/openhab/core/items/metadataregistry) and [`org.openhab.core.thing.ThingRegistry`](https://www.openhab.org/javadoc/latest/org/openhab/core/thing/thingregistry) respectively.
The `itemChannelLinkRegistry` does not provide the same methods as the [`org.openhab.core.thing.link.ItemChannelLinkRegistry`](https://www.openhab.org/javadoc/latest/org/openhab/core/thing/link/itemchannellinkregistry) interface.

All instances from this preset have an `addPermanent(…)` method, in addition to `add(…)`.
With the `add(…)` method, elements added over the above instances are removed, when the script, which inserted the elements, is deleted or changed.
When `addPermanent(…)` is used, the inserted elements are … not removed.
`itemRegistry.addPermanent(…)`/`thingRegistry.addPermanent(…)` from this preset offer the same functionality as `itemRegistry.add(…)`/`things.add(…)` from the `default` preset.

### `TriggerType` Objects (all JSR223 languages)

The following trigger types are defined by openHAB (custom triggers can also be defined) and take the specified configuration parameters.
Expand Down Expand Up @@ -666,3 +707,131 @@ Read the JSR223 language specific documentation for examples of using these `Tri
| `startlevel` | The system `StartLevel` |

:::

### The `scriptLoaded` and `scriptUnloaded` functions

When a JSR223 script is created or changed and it contains the `scriptLoaded(String)` function, OpenHAB executes it, and passes as parameter the path of the loaded script.
Similarly, when a script is changed or deleted, and the script contained the `scriptUnloaded()` function, it is invoked.
`scriptLoaded(String)` is only executed when a script from the automation add-on directory, like `${OPENHAB_CONF}/automation/jsr223/`, is loaded.
It is not executed in transformations, UI rules with Inline Script action, UI scripts.
The [`lifecycleTracker`](#lifecycle-preset-importpreset-not-required) object and the `scriptUnloaded()` function serve similar purposes.
When a script is executed several times, on each execution it adds a Disposable, and then the script is changed, its `scriptUnloaded()` is executed once and each added Disposable is also `dispose()`d.

:::: tabs

::: tab Groovy

```groovy
static @groovy.transform.Field logger = org.slf4j.LoggerFactory.getLogger("org.openhab.automation.example")

lifecycleTracker.addDisposeHook(new org.openhab.core.automation.module.script.LifecycleScriptExtensionProvider.Disposable() {
public void dispose() {
logger.error("I am logged fourth.")
}
})

lifecycleTracker.addDisposeHook{ logger.error("I am logged fifth. Bye!") }

void scriptLoaded(String filename) { // can be static
logger.error("I am logged second and I am from ${filename}.")
}

static void scriptUnloaded() { // can be non-static
logger.error("I am logged third.")
}
logger.error("I am logged first.")
```

:::

::: tab JS&nbsp;Nashorn

```js
var logger = Java.type('org.slf4j.LoggerFactory').getLogger("org.openhab.core.automation.examples")
lifecycleTracker.addDisposeHook(function() {
logger.error("I am logged fourth. Bye!")
})
function scriptLoaded(filename) {
logger.error("I am logged second and I am from " + filename + ".")
}
function scriptUnloaded() {
logger.error("I am logged third.")
}
logger.error("I am logged first.")
```

:::

::: tab JS&nbsp;Scripting

```js
require('@runtime').lifecycleTracker.addDisposeHook( () => console.log("I am logged fourth. Bye!") )

const scriptUnloaded = () => console.log("I am logged third.")

function scriptLoaded(filename) {
console.log(`I am logged second and I am from ${filename}.`)
}

console.log("I am logged first.")
```

:::

::: tab Jython

```python
from org.slf4j import LoggerFactory

logger = LoggerFactory.getLogger("org.openhab.core.automation.examples")

def scriptUnloaded():
logger.error("I am logged third.")

def scriptLoaded(filename):
logger.error("I am logged second and I am from " + filename + ".")

lifecycleTracker.addDisposeHook(lambda : logger.error("I am logged fourth. Bye!"))
logger.error("I am logged first.")
```

:::

::: tab Python

When the setting “Use scope and import wrapper” is on, the `scope` module is enabled:

```python
import sys
import scope

def scriptUnloaded():
print("I am logged third.")

def scriptLoaded(filename):
print("I am logged second and I am from " + filename + ".")

scope.lifecycleTracker.addDisposeHook(lambda : print("I am logged fourth. Bye!"))

print("I am logged first.")
```

When the `scope` module is disabled:

```python
import sys

def scriptUnloaded():
print("I am logged third.")

def scriptLoaded(filename):
print("I am logged second and I am from " + filename + ".")

lifecycleTracker.addDisposeHook(lambda : print("I am logged fourth. Bye!"))

print("I am logged first.")
```

:::

::::