Fix documentation, grammar, and spelling in addons IO / Persistence -Transform (#19611)

Signed-off-by: Leo Siepel <leosiepel@gmail.com>
This commit is contained in:
lsiepel
2026-02-03 21:45:57 +01:00
committed by GitHub
parent 7a00c38d54
commit 677459cc79
76 changed files with 888 additions and 842 deletions
+149 -149
View File
@@ -65,7 +65,7 @@ HomeKit integration supports following accessory types:
![ios_add_accessory.png](doc/ios_add_accessory.png)
- scan QR code from UI->Setting-HomeKit Integration
- scan QR code from UI->Settings->HomeKit Integration
![ios_scan_qrcode.png](doc/ios_scan_qrcode.png)
@@ -81,11 +81,11 @@ Add metadata to more items or fine-tune your configuration using further setting
## Global Configuration
You can define HomeKit settings either via mainUI or via `$OPENHAB_CONF/services/homekit.cfg`.
HomeKit works with default settings, but we recommend changing the pin for the bridge.
This will be used in iOS when pairing without QR Code. The pin code is in the form "###-##-###".
Requirements beyond this are not clear, and Apple enforces limitations on eligible pins within iOS.
At the very least, you cannot use repeating (111-11-111) or sequential (123-45-678) pin codes.
You can define HomeKit settings either via Main UI or via `$OPENHAB_CONF/services/homekit.cfg`.
HomeKit works with default settings, but we recommend changing the PIN for the bridge.
This will be used in iOS when pairing without QR code. The PIN code is in the form "###-##-###".
Requirements beyond this are not clear, and Apple enforces limitations on eligible PINs within iOS.
At the very least, you cannot use repeating (111-11-111) or sequential (123-45-678) PIN codes.
Other settings, such as using Fahrenheit temperatures and specifying the interface to advertise the HomeKit bridge are also illustrated in the following sample:
@@ -109,9 +109,9 @@ Some settings are only visible in UI if the checkbox "Show advanced" is activate
|:-------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------|
| networkInterface | IP address or domain name under which the HomeKit bridge can be reached. If no value is configured, the add-on uses the primary IP address configured for openHAB. If unsure, keep it empty | (none) |
| port | Port under which the HomeKit bridge can be reached. | 9123 |
| useOHmDNS | mDNS service is used to advertise openHAB as HomeKit bridge in the network so that HomeKit clients can find it. openHAB has already mDNS service running. This option defines whether the mDNS service of openHAB or a separate service should be used. | false |
| blockUserDeletion | Blocks HomeKit user deletion in openHAB and as result unpairing of devices. If you experience an issue with accessories becoming non-responsive after some time, try to enable this setting. You can also enable this setting if your HomeKit setup is done and you will not re-pair ios devices. | false |
| pin | Pin code used for pairing with iOS devices. Apparently, pin codes are provided by Apple and represent specific device types, so they cannot be chosen freely. The pin code 031-45-154 is used in sample applications and known to work. | 031-45-154 |
| useOHmDNS | mDNS service is used to advertise openHAB as HomeKit bridge in the network so that HomeKit clients can find it. openHAB already has an mDNS service running. This option defines whether the mDNS service of openHAB or a separate service should be used. | false |
| blockUserDeletion | Blocks HomeKit user deletion in openHAB and as a result unpairing of devices. If you experience an issue with accessories becoming non-responsive after some time, try to enable this setting. You can also enable this setting if your HomeKit setup is done and you will not re-pair iOS devices. | false |
| pin | PIN code used for pairing with iOS devices. Apparently, PIN codes are provided by Apple and represent specific device types, so they cannot be chosen freely. The PIN code 031-45-154 is used in sample applications and known to work. | 031-45-154 |
| useFahrenheitTemperature | Set to true to use Fahrenheit degrees, or false to use Celsius degrees. Note if an item has a QuantityType as its state, this configuration is ignored and it's always converted properly. | false |
| name | Name under which this HomeKit bridge is announced on the network. This is also the name displayed on the iOS device when searching for available bridges. | openHAB |
| instances | Defines how many bridges to expose. Necessary if you have more than 149 accessories. Accessories must be assigned to additional instances via metadata. Additional bridges will use incrementing port numbers. | 1 |
@@ -119,24 +119,24 @@ Some settings are only visible in UI if the checkbox "Show advanced" is activate
## Item Configuration
After setting the global configuration, you will need to tag your [openHAB items](https://www.openhab.org/docs/configuration/items.html) for HomeKit with accessory type.
After setting the global configuration, you will need to tag your [openHAB items](https://www.openhab.org/docs/configuration/items.html) for HomeKit with an accessory type.
For our purposes, you may consider HomeKit accessories to be of two types: simple and complex.
A simple accessory will be mapped to a single openHAB item, e.g. HomeKit lighting can represent an openHAB Switch, Dimmer, or Color item.
A complex accessory will be made up of multiple openHAB items, e.g. HomeKit Thermostat can be composed of mode, and current & target temperature.
A simple accessory will be mapped to a single openHAB item, e.g., HomeKit lighting can represent an openHAB Switch, Dimmer, or Color item.
A complex accessory will be made up of multiple openHAB items, e.g., HomeKit Thermostat can be composed of mode, and current & target temperature.
Complex accessories require a tag on a Group Item indicating the accessory type, as well as tags on the items it composes.
A HomeKit accessory has mandatory and optional characteristics (listed below in the table).
The mapping between openHAB items and HomeKit accessory and characteristics is done by means of [metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata)
The mapping between openHAB items and HomeKit accessory and characteristics is done by means of [metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata).
If the first word of the item name match the room name in Home app, Home app will hide it.
E.g. item with the name "Kitchen Light" will be shown in "Kitchen" room as "Light". This is recommended naming convention for HomeKit items and rooms.
If the first word of the item name matches the room name in the Home app, the Home app will hide it.
E.g., an item with the name "Kitchen Light" will be shown in the "Kitchen" room as "Light". This is the recommended naming convention for HomeKit items and rooms.
### UI based Configuration
### UI Based Configuration
In order to add metadata to an item:
- select desired item in mainUI
- select the desired item in Main UI
- click on "Add Metadata"
![item_add_metadata_button.png](doc/item_add_metadata_button.png)
@@ -149,7 +149,7 @@ In order to add metadata to an item:
![add_homekit_tag.png](doc/add_homekit_tag.png)
- select required HomeKit accessory type or characteristic
- select the required HomeKit accessory type or characteristic
![select_homekit_accessory_type.png](doc/select_homekit_accessory_type.png)
@@ -163,21 +163,21 @@ Switch leaksensor_metadata "Leak Sensor" {homekit="LeakSensor"}
The tag can be:
- full qualified: i.e. with accessory type and characteristic, e.g. "LeakSensor.LeakDetectedState"
- shorthand version: with only either accessory type or characteristic, e.g. "LeakSensor", "LeakDetectedState".
- fully qualified: i.e., with accessory type and characteristic, e.g., "LeakSensor.LeakDetectedState"
- shorthand version: with only either accessory type or characteristic, e.g., "LeakSensor", "LeakDetectedState".
if shorthand version has only accessory type, then HomeKit will automatically link _all_ mandatory characteristics of this accessory type to the openHAB item.
e.g. HomeKit window covering has 3 mandatory characteristics: CurrentPosition, TargetPosition, PositionState.
Following are equal configuration:
If the shorthand version has only an accessory type, then HomeKit will automatically link _all_ mandatory characteristics of this accessory type to the openHAB item.
E.g., HomeKit window covering has 3 mandatory characteristics: CurrentPosition, TargetPosition, PositionState.
The following are equal configurations:
```java
Rollershutter window_covering "Window Rollershutter" {homekit="WindowCovering"}
Rollershutter window_covering "Window Rollershutter" {homekit="WindowCovering, WindowCovering.CurrentPosition, WindowCovering.TargetPosition, WindowCovering.PositionState"}
```
If the shorthand version has only a characteristic then it must be a part of a group which has a HomeKit accessory type.
You can use openHAB group to define complex accessories. The group item must indicate the HomeKit accessory type,
e.g. LeakSensor definition
If the shorthand version has only a characteristic, then it must be part of a group which has a HomeKit accessory type.
You can use an openHAB group to define complex accessories. The group item must indicate the HomeKit accessory type,
e.g., LeakSensor definition
```java
Group gLeakSensor "Leak Sensor Group" {homekit="LeakSensor"}
@@ -187,10 +187,10 @@ Switch leaksensor_battery "Leak Sensor Battery"
### Complex Multiple Service Accessories
Alternatively, you may want to have a choice of controlling the items individually, OR as a group, from HomeKit.
The following examples defines a single HomeKit accessory _with multiple services_ that the Home app will allow you to control together, or drill down and control individually.
Note that `AccessoryGroup` doesn't expose any services itself, but allows you to group other services together underneath it.
Also note that when nesting accessories, you cannot use the shorthand of naming only a characteristic, and not its accessory type, since it would be ambiguous if that item belongs to a secondary service, or to the primary service it's nested under.
Alternatively, you may want to have a choice of controlling the items individually, or as a group, from HomeKit.
The following example defines a single HomeKit accessory _with multiple services_ that the Home app will allow you to control together, or drill down and control individually.
Note that `AccessoryGroup` doesn't expose any services itself but allows you to group other services together underneath it.
Also note that when nesting accessories, you cannot use the shorthand of naming only a characteristic and not its accessory type, since it would be ambiguous whether that item belongs to a secondary service or to the primary service it's nested under.
```java
Group:Switch:OR(ON,OFF) gLight "Light Group" {homekit="AccessoryGroup"}
@@ -202,7 +202,7 @@ Switch light2 "Light 2" (gLight) {homekit="Lighting"}
You can also group additional accessories directly under another accessory.
In this example, HomeKit will show three separate light controls.
As this is somewhat confusing that Home will allow controlling all members as a group, and you also have the group as a distinct switch inside the HomeKit accessory, this is not a recommended configuration.
As this is somewhat confusing (Home will allow controlling all members as a group, and you also have the group as a distinct switch inside the HomeKit accessory), this is not a recommended configuration.
```java
Group:Switch:OR(ON,OFF) gLight "Light Group" {homekit="Lighting"}
@@ -222,8 +222,8 @@ Switch fan1_light "Fan Light" (gFan) {homekit="Lighting"}
![Fan With Light](doc/fan_with_light.png)
Another way to build complex accessories is to associate multiple accessory types with the root group, and then define all of the individual characteristics on group members.
When using this style, you cannot have multiple instance of the same accessory type.
Another way to build complex accessories is to associate multiple accessory types with the root group and then define all of the individual characteristics on group members.
When using this style, you cannot have multiple instances of the same accessory type.
```java
Group FanWithLight "Fan with Light" {homekit = "Fan,Lighting"}
@@ -245,7 +245,7 @@ Switch occupancy_and_motion_sensor "Occupancy and Motion Sensor Tag" {hom
```
You can even form complex sensors this way.
Just be sure that you fully specify additional characteristics, so that the addon knows which root service to add it to.
Just be sure that you fully specify additional characteristics so that the add-on knows which root service to add it to.
```java
Group eBunkAirthings "Bunk Room Airthings Wave Plus" { homekit="AirQualitySensor,TemperatureSensor,HumiditySensor" }
@@ -261,18 +261,18 @@ A sensor with a battery configured in MainUI:
![ui_sensor_with_battery.png](doc/ui_sensor_with_battery.png)
The Home app uses the first accessory in a group as the icon for the group as a whole.
E.g. an accessory defined as `homekit="Fan,Light"` will be shown as a fan and an accessory defined as `homekit="Light,Fan"` will be shown as a light in the Home app.
You can also override the primary service by using adding `primary=<type>` to the HomeKit metadata configuration:
E.g., an accessory defined as `homekit="Fan,Light"` will be shown as a fan and an accessory defined as `homekit="Light,Fan"` will be shown as a light in the Home app.
You can also override the primary service by adding `primary=<type>` to the HomeKit metadata configuration:
```java
Group FanWithLight "Fan with Light" {homekit = "Light,Fan" [primary = "Fan"]}
```
on in MainUI:
or in Main UI:
![ui_fan_with_light_primary.png](doc/ui_fan_with_light_primary.png)
Unusual combinations are also possible, e.g. you can combine temperature sensor with blinds and light.
Unusual combinations are also possible, e.g., you can combine a temperature sensor with blinds and light.
It will be represented by the Home app as follows:
@@ -285,48 +285,48 @@ Note that for sensors that aren't interactive, the Home app will show the consti
## Dummy Accessories
OpenHAB is a highly dynamic system, and prone to occasional misconfigurations where items can't be loaded for various reasons, especially if you're using something besides the UI to manage your items.
This is a problem for HomeKit because if the bridge makes a connection, but accessories are missing, then the HomeKit database will simply remove that accessory.
When the accessory does come back (i.e. because you corrected a syntax error in an .items file, or openHAB completes booting), all customization of that accessory will be lost - the room assignment, customized name, custom icon, status/home screen/favorite preferences, etc.
In order to work around this, the HomeKit addon can create dummy accessories for any accessory it has previously published to HomeKit.
openHAB is a highly dynamic system and prone to occasional misconfigurations where items can't be loaded for various reasons, especially if you're using something besides the UI to manage your items.
This is a problem for HomeKit because if the bridge makes a connection but accessories are missing, then the HomeKit database will simply remove that accessory.
When the accessory does come back (i.e., because you corrected a syntax error in an .items file, or openHAB completes booting), all customization of that accessory will be lost - the room assignment, customized name, custom icon, status/home screen/favorite preferences, etc.
In order to work around this, the HomeKit add-on can create dummy accessories for any accessory it has previously published to HomeKit.
To enable this behavior, turn on the `useDummyAccessories` setting.
OpenHAB will then simply present a non-interactive accessory for any that are missing.
openHAB will then simply present a non-interactive accessory for any that are missing.
The openHAB log will also contain information whenever a dummy accessory is created.
If the item backing the accessory is later re-created, everything will sync back up and nothing will be lost.
If the item backing the accessory is later re-created, everything will sync back up, and nothing will be lost.
You can also run the console command `openhab:homekit listDummyAccessories` to see which items are missing.
Apple devices may or may not show "Not Responding" for some or all accessories when there are dummy accessories, since they will no longer be backed by actual items with state.
It's recommended that you resolve this state as soon as possible, since HomeKit may decide your entire bridge is being uncooperative, and remove everything itself.
Apple devices may or may not show "Not Responding" for some or all accessories when there are dummy accessories since they will no longer be backed by actual items with state.
It's recommended that you resolve this state as soon as possible since HomeKit may decide your entire bridge is being uncooperative and remove everything itself.
If you actually meant to remove an item, you will need to purge the dummy items from the database so that they'll disappear from the Home app altogether.
In order to do so, run the console command `openhab:homekit pruneDummyAccessories`.
Alternatively, disabling, saving, and then re-enabling `useDummyAccessories` in the addon settings will have the same effect.
Alternatively, disabling, saving, and then re-enabling `useDummyAccessories` in the add-on settings will have the same effect.
## Accessory Configuration Details
This section provides examples widely used accessory types.
For complete list of supported accessory types and characteristics please see section [Supported accessory type](#Supported accessory type)
This section provides examples of widely used accessory types.
For a complete list of supported accessory types and characteristics, please see section [Supported accessory type](#Supported accessory type).
### Dimmers
The way HomeKit handles dimmer devices can be different to the actual dimmers' way of working.
HomeKit Home app sends following commands/update:
The way HomeKit handles dimmer devices can be different from the actual dimmers' way of working.
The HomeKit Home app sends the following commands/updates:
- On brightness change Home app sends "ON" event along with target brightness, e.g. "Brightness = 50%" + "State = ON".
- On "ON" event Home app sends "ON" along with brightness 100%, i.e. "Brightness = 100%" + "State = ON"
- On "OFF" event Home app sends "OFF" without brightness information.
- On brightness change, the Home app sends "ON" event along with target brightness, e.g., "Brightness = 50%" + "State = ON".
- On "ON" event, the Home app sends "ON" along with brightness 100%, i.e., "Brightness = 100%" + "State = ON"
- On "OFF" event, the Home app sends "OFF" without brightness information.
However, some dimmer devices for example do not expect brightness on "ON" event, some others do not expect "ON" upon brightness change.
In order to support different devices HomeKit integration can filter some events. Which events should be filtered is defined via dimmerMode configuration.
However, some dimmer devices, for example, do not expect brightness on "ON" event; some others do not expect "ON" upon brightness change.
In order to support different devices, the HomeKit integration can filter some events. Which events should be filtered is defined via the dimmerMode configuration.
```java
Dimmer dimmer_light "Dimmer Light" {homekit="Lighting, Lighting.Brightness" [dimmerMode="<mode>"]}
```
Following modes are supported:
The following modes are supported:
- "normal" - no filtering. The commands will be sent to device as received from HomeKit. This is default mode.
- "filterOn" - ON events are filtered out. only OFF events and brightness information are sent
- "filterBrightness100" - only Brightness=100% is filtered out. everything else sent unchanged. This allows custom logic for soft launch in devices.
- "filterOnExceptBrightness100" - ON events are filtered out in all cases except of brightness = 100%.
- "normal" - no filtering. The commands will be sent to the device as received from HomeKit. This is the default mode.
- "filterOn" - ON events are filtered out. Only OFF events and brightness information are sent.
- "filterBrightness100" - only Brightness=100% is filtered out. Everything else is sent unchanged. This allows custom logic for soft launch in devices.
- "filterOnExceptBrightness100" - ON events are filtered out in all cases except for brightness = 100%.
Examples:
@@ -415,18 +415,18 @@ Dimmer Television_Volume "Volume" (gTelevisionSpeaker) { homekit="TelevisionSpea
```
Note that seemingly most of these characteristics are not accessible from the Home app.
At the least, you should be able to edit names, control main power, switch inputs, alter input visibility, and be notified when the user wants to open the TV's menu.
At the very least, you should be able to edit names, control main power, switch inputs, alter input visibility, and be notified when the user wants to open the TV's menu.
### Windows Covering (Blinds) / Window / Door
### Window Covering (Blinds) / Window / Door
HomeKit Windows Covering, Window and Door accessory types have following mandatory characteristics:
HomeKit Window Covering, Window, and Door accessory types have the following mandatory characteristics:
- CurrentPosition (0-100% of current window covering position)
- TargetPosition (0-100% of target position)
- PositionState (DECREASING,INCREASING or STOPPED as state). If no state provided, HomeKit will send STOPPED
- PositionState (DECREASING, INCREASING, or STOPPED as state). If no state is provided, HomeKit will send STOPPED.
These characteristics can be mapped to a single openHAB rollershutter item. In such case currentPosition will always equal target position, means if you request to close a blind/window/door, HomeKit will immediately report that the blind/window/door is closed.
As discussed above, one can use full or shorthand definition. Following two definitions are equal:
These characteristics can be mapped to a single openHAB rollershutter item. In such a case, currentPosition will always equal target position, meaning if you request to close a blind/window/door, HomeKit will immediately report that the blind/window/door is closed.
As discussed above, one can use full or shorthand definition. The following two definitions are equal:
```java
Rollershutter window "Window" {homekit = "Window"}
@@ -437,16 +437,16 @@ Rollershutter window_covering_long "Window Rollershutter long" {homekit = "W
openHAB Rollershutter is defined by default as:
- OPEN if position is 0%,
- CLOSED if position is 100%.
- OPEN if position is 0%
- CLOSED if position is 100%
In contrast, HomeKit window covering/door/window have inverted mapping
In contrast, HomeKit window covering/door/window have inverted mapping:
- OPEN if position 100%
- OPEN if position is 100%
- CLOSED if position is 0%
Therefore, HomeKit integration inverts by default the values between openHAB and HomeKit, e.g. if openHAB current position is 30% then it will send 70% to HomeKit app.
In case you need to disable this logic you can do it with configuration parameter inverted=false, e.g.
Therefore, the HomeKit integration inverts by default the values between openHAB and HomeKit, e.g., if the openHAB current position is 30%, then it will send 70% to the HomeKit app.
In case you need to disable this logic, you can do it with the configuration parameter inverted=false, e.g.:
```java
Rollershutter window_covering "Window Rollershutter" {homekit = "WindowCovering" [inverted=false]}
@@ -454,30 +454,30 @@ Rollershutter window "Window" {homekit = "Window" [invert
Rollershutter door "Door" {homekit = "Door" [inverted=false]}
```
HomeKit home app never sends "STOP" but only the target position.
If you add configuration parameter "stop=true", openHAB will emulate stop and send "STOP" command to rollershutter item if you click on the blind icon in the iOS home app while the blind is moving.
The HomeKit Home app never sends "STOP" but only the target position.
If you add the configuration parameter "stop=true", openHAB will emulate stop and send the "STOP" command to the rollershutter item if you click on the blind icon in the iOS Home app while the blind is moving.
```java
Rollershutter window_covering "Window Rollershutter" {homekit = "WindowCovering" [stop=true]}
```
Some blinds devices do support "STOP" command but would stop if they receive UP/DOWN while moving om the same direction. In order to support such devices add "stopSameDirection" parameter.
Some blinds devices do support the "STOP" command but would stop if they receive UP/DOWN while moving in the same direction. In order to support such devices, add the "stopSameDirection" parameter.
```java
Rollershutter window_covering "Window Rollershutter" {homekit = "WindowCovering" [stop=true, stopSameDirection=true]}
```
Some blinds devices do not support going to a specific position, even though they are modeled as Rollershutter items.
The Home App only sends exact percentages by default.
To avoid creating a rule, you can have the HomeKit addon translate 0%/100% to UP/DOWN commands.
The Home app only sends exact percentages by default.
To avoid creating a rule, you can have the HomeKit add-on translate 0%/100% to UP/DOWN commands.
```java
Rollershutter window_covering "Window Rollershutter" {homekit = "WindowCovering" [sendUpDownForExtents=true]}
```
Window covering can have a number of optional characteristics like horizontal & vertical tilt, obstruction status and hold position trigger.
If your blind supports tilt, and you want to control tilt via HomeKit you need to define blind as a group.
e.g.
Window covering can have a number of optional characteristics like horizontal & vertical tilt, obstruction status, and hold position trigger.
If your blind supports tilt and you want to control tilt via HomeKit, you need to define the blind as a group.
E.g.:
```java
Group gBlind "Blind with tilt" {homekit = "WindowCovering"}
@@ -487,7 +487,7 @@ Dimmer window_covering_vtilt "Blind vertical tilt" (gBlind)
```
Current and Target Position characteristics can be linked to Rollershutter but also to Number or Dimmer item types.
e.g.
E.g.:
```java
Group gBlind "Blinds" {homekit = "WindowCovering"}
@@ -498,14 +498,14 @@ String blind_position (gBlind) {homekit = "PositionSta
### Thermostat
A HomeKit thermostat has following mandatory characteristics:
A HomeKit thermostat has the following mandatory characteristics:
- CurrentTemperature
- TargetTemperature
- CurrentHeatingCoolingMode
- TargetHeatingCoolingMode
In order to define a thermostat you need to create a group with at least these 4 items.
In order to define a thermostat, you need to create a group with at least these 4 items.
Example:
```java
@@ -546,15 +546,15 @@ Number thermostat_cool_thrs "Thermostat Cool Threshold Temp [%.1f
Number thermostat_heat_thrs "Thermostat Heat Threshold Temp [%.1f °C]" (gThermostat) {homekit = "HeatingThresholdTemperature"}
```
#### Min / max temperatures
#### Min/Max Temperatures
Current and target temperatures have default min and max values. Any values below or above max limits will be replaced with min or max limits.
Default limits are:
Current and target temperatures have default min and max values. Any values below or above the max limits will be replaced with min or max limits.
The default limits are:
- current temperature: min value = 0 °C, max value = 100 °C
- target temperature: min value = 10 °C, max value = 38 °C
You can overwrite default values using minValue and maxValue configuration at item level, e.g.
You can overwrite default values using minValue and maxValue configuration at the item level, e.g.:
```java
Number thermostat_current_temp "Thermostat Current Temp [%.1f °C]" (gThermostat) {homekit = "CurrentTemperature" [minValue=5, maxValue=30]}
@@ -563,15 +563,15 @@ Number thermostat_target_temp "Thermostat Target Temp[%.1f °C]"
If "useFahrenheitTemperature" is set to true, the min and max temperature must be provided in Fahrenheit.
#### Thermostat modes
#### Thermostat Modes
HomeKit thermostat supports following modes
The HomeKit thermostat accessory supports the following modes:
- CurrentHeatingCoolingMode: OFF, HEAT, COOL
- TargetHeatingCoolingMode: OFF, HEAT, COOL, AUTO
These modes are mapped to string values of openHAB items using configuration at the item level.
e.g. if your current mode item can have following values: "OFF", "HEATING", "COOLING" then you need following mapping at item level
E.g., if your current mode item can have the following values: "OFF", "HEATING", "COOLING", then you need the following mapping at the item level:
```java
String thermostat_current_mode "Thermostat Current Mode" (gThermostat) {homekit = "CurrentHeatingCoolingMode" [OFF="OFF", HEAT="HEATING", COOL="COOLING"]}
@@ -579,34 +579,34 @@ String thermostat_current_mode "Thermostat Current Mode" (gThermost
You can provide mapping for target mode in a similar way.
The custom mapping can be also used to reduce number of modes shown in Home app.
The modes can be only reduced, but not added, i.e. it is not possible to add a new custom mode to HomeKit thermostat.
The custom mapping can also be used to reduce the number of modes shown in the Home app.
The modes can only be reduced, but not added, i.e., it is not possible to add a new custom mode to the HomeKit thermostat.
Example: if your thermostat does not support cooling, then you need to limit mapping to OFF and HEAT values only:
Example: if your thermostat does not support cooling, then you need to limit the mapping to OFF and HEAT values only:
```java
String thermostat_current_mode "Thermostat Current Mode" (gThermostat) {homekit = "CurrentHeatingCoolingMode" [HEAT="HEATING", OFF="OFF"]}
String thermostat_target_mode "Thermostat Target Mode" (gThermostat) {homekit = "TargetHeatingCoolingMode" [HEAT="HEATING", OFF="OFF"]}
```
The mapping using main UI looks like following:
The mapping using Main UI looks like the following:
![mode_mapping.png](doc/mode_mapping.png)
### Valve
The HomeKit valve accessory supports following 2 optional characteristics:
The HomeKit valve accessory supports the following 2 optional characteristics:
- duration: this describes how long the valve should set "InUse" once it is activated. The duration changes will apply to the next operation. If valve is already active then duration changes have no effect.
- duration: this describes how long the valve should be set to "InUse" once it is activated. The duration changes will apply to the next operation. If the valve is already active, then duration changes have no effect.
- remaining duration: this describes the remaining duration on the valve. Notifications on this characteristic must only be used if the remaining duration increases/decreases from the accessoryʼs usual countdown of remaining duration.
- remaining duration: this describes the remaining duration on the valve. Notifications on this characteristic must only be used if the remaining duration increases/decreases from the accessory's usual countdown of remaining duration.
Upon valve activation in Home app, Home app starts to count down from the "duration" to "0" without contacting the server. Home app also does not trigger any action if it remaining duration get 0.
It is up to valve to have an own timer and stop valve once the timer is over.
Some valves have such timer, e.g. pretty common for sprinklers.
In case the valve has no timer capability, openHAB can take care on this - start an internal timer and send "Off" command to the valve once the timer is over.
Upon valve activation in the Home app, the Home app starts to count down from the "duration" to "0" without contacting the server. The Home app also does not trigger any action if the remaining duration reaches 0.
It is up to the valve to have its own timer and stop the valve once the timer is over.
Some valves have such a timer, e.g., it is pretty common for sprinklers.
In case the valve has no timer capability, openHAB can take care of this - start an internal timer and send an "Off" command to the valve once the timer is over.
configuration for these two cases looks as follow:
The configuration for these two cases looks as follows:
- valve with timer:
@@ -654,21 +654,22 @@ Number valve2RemainingDuration (gValve2) { homekit="RemainingDuration" }
### Sensors
Sensors have typically one mandatory characteristic, e.g. temperature or lead trigger, and several optional characteristics which are typically used for battery powered sensors and/or wireless sensors.
Following table summarizes the optional characteristics supported by sensors.
Sensors typically have one mandatory characteristic, e.g., temperature or leak trigger, and several optional characteristics which are typically used for battery-powered sensors and/or wireless sensors.
The following table summarizes the optional characteristics supported by sensors.
| Characteristics | Supported openHAB items | Description |
|:-----------------------------|:-------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Name | String | Name of the sensor. This characteristic is interesting only for very specific cases in which the name of accessory is dynamic. if you not sure then you don't need it. |
| Name | String | Name of the sensor. This characteristic is interesting only for very specific cases in which the name of the accessory is dynamic. If you are not sure, then you don't need it. |
| ActiveStatus | Switch, Contact | Accessory current working status. "ON"/"OPEN" indicates that the accessory is active and is functioning without any errors. |
| FaultStatus | Switch, Contact | Accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. |
| TamperedStatus | Switch, Contact | Accessory tampered status. "ON"/"OPEN" indicates that the accessory has been tampered. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. |
| TamperedStatus | Switch, Contact | Accessory tampered status. "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. |
| BatteryLowStatus | Switch, Contact, Number | Accessory battery status. "ON"/"OPEN" indicates that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level that's above the low threshold. Alternatively, you can give a Number item that's the battery level, and if it's lower than the lowThreshold configuration, it will report low. |
Switch and Contact items support inversion of the state mapping, e.g. by default the openHAB switch state "ON" is mapped to HomeKit contact sensor state "Open", and "OFF" to "Closed".
The configuration "inverted=true" inverts this mapping, so that "ON" will be mapped to "Closed" and "OFF" to "Open".
Switch and Contact items support inversion of the state mapping, e.g., by default the openHAB switch state "ON" is mapped to HomeKit contact sensor state "Open", and "OFF" to "Closed".
The configuration "inverted=true" inverts this mapping so that "ON" will be mapped to "Closed" and "OFF" to "Open".
Examples of sensor definitions:
Examples of sensor definitions.
Sensors without optional characteristics:
```java
@@ -707,8 +708,8 @@ or using UI
### Stateless Programmable Switch Groups
To expose multiple Stateless Programmable Switches as a single accessory with multiple buttons (aka a scene controller), you need to configure ServiceLabel on the accessory group and ServiceIndex on each switch.
Note that in the Home app, the individual switch names will be ignored, and will simply be displayed as "Button 1", "Button 2", etc. (for ARABIC_NUMERALS style).
To expose multiple Stateless Programmable Switches as a single accessory with multiple buttons (a.k.a. a scene controller), you need to configure ServiceLabel on the accessory group and ServiceIndex on each switch.
Note that in the Home app, the individual switch names will be ignored and will simply be displayed as "Button 1", "Button 2", etc. (for ARABIC_NUMERALS style).
```java
Group gSceneController "Scene Controller" { homekit="AccessoryGroup"[ServiceLabel="ARABIC_NUMERALS"] }
@@ -722,15 +723,15 @@ Switch Button4 "Switch D" (gSceneController) { homekit="StatelessProgrammableSwi
For configuration options, the default values are in parentheses.
For enum values, the parentheses indicate the default values if the item is a Number or a Switch.
All enum values can be customized via item metadata. I.e. `HEAT="heating", COOL="cooling"`, or `HEAT=5, COOL=7` for a Number.
All enum values can be customized via item metadata, i.e., `HEAT="heating", COOL="cooling"`, or `HEAT=5, COOL=7` for a Number.
<a name="customizable-enum">Some enums can have the list of valid values customized, meaning that if you customize the mapping, any value that is missing will not be presented to the user.</a>
They are appropriately marked.
Enums that are linked to Switches or Contacts have an `inverted` param that will reverse the sense of `ON`/`OFF` or `OPEN`/`CLOSED`.
Enums that are linked to Switches or Contacts have an `inverted` parameter that will reverse the sense of `ON`/`OFF` or `OPEN`/`CLOSED`.
Enum mappings can have multiple values for a single key.
These must be an array, not a comma separated string.
These must be an array, not a comma-separated string.
If the characteristic can be set by HomeKit, the first value will be used when sending the command to the linked item.
Such a mapping can be configured manually in MainUI on HomeKit metadata in the Code editor:
Such a mapping can be configured manually in Main UI on HomeKit metadata in the Code editor:
```yaml
value: "Lock"
@@ -1081,8 +1082,8 @@ Number cooler_heat_thrs "Cooler Heat Threshold Temp [%.1f °C
HomeKit has a limitation of 150 accessories per bridge.
The bridge itself counts as an accessory, so in practice it's 149.
In order to overcome this limitation, you can instruct openHAB to expose multiple bridges to HomeKit, and then manually assign specific accessories to different instances.
You will need to manually add each additional bridge in the Home app, since the QR Code in settings will only be for the primary bridge; however the same PIN is still used.
In order to overcome this limitation, you can instruct openHAB to expose multiple bridges to HomeKit and then manually assign specific accessories to different instances.
You will need to manually add each additional bridge in the Home app since the QR code in settings will only be for the primary bridge; however, the same PIN is still used.
In order to assign a particular accessory to a different bridge, set the `instance` metadata parameter:
```java
@@ -1109,8 +1110,8 @@ To do this, you can issue the command `openhab:homekit clearPairings` from the [
After doing this, you may need to remove the file `$OPENHAB_USERDATA/jsondb/homekit.json` and restart openHAB.
HomeKit requires a unique identifier for each accessory advertised by the bridge.
This unique identifier is hashed from the Item's name.
For that reason, it is important that the name of your Items exposed to HomeKit remain consistent.
This unique identifier is hashed from the item's name.
For that reason, it is important that the names of your items exposed to HomeKit remain consistent.
HomeKit listens by default on port 9124.
Java prefers the IPv6 network stack by default.
@@ -1141,30 +1142,30 @@ openhab> log:tail org.openhab.io.homekit.internal
## Troubleshooting
### openHAB is not listed in Home app
### openHAB is not listed in the Home app
if you don't see openHAB in the Home app, probably multicast DNS (mDNS) traffic is not routed correctly from openHAB to Home app device or openHAB is already in paired state.
You can verify this with [Discovery DNS iOS app](https://apps.apple.com/us/app/discovery-dns-sd-browser/id305441017) as follow:
If you don't see openHAB in the Home app, probably multicast DNS (mDNS) traffic is not routed correctly from openHAB to the Home app device, or openHAB is already in a paired state.
You can verify this with the [Discovery DNS iOS app](https://apps.apple.com/us/app/discovery-dns-sd-browser/id305441017) as follows:
- install discovery dns app from app store
- start discovery app
- find `_hap._tcp` in the list of service types
- if you don't find _hap._tcp on the list, probably the traffic is blocked.
- to confirm this, check whether you can find _openhab-server._tcp. if you don't see it as well, traffic is blocked. check your network router/firewall settings.
- if you found _hap._tcp, open it. you should see the name of your openHAB HomeKit bridge (default name is openHAB)
- install the Discovery DNS app from the App Store
- start the Discovery app
- find `_hap._tcp` in the list of service types
- if you don't find _hap._tcp on the list, the traffic is probably blocked.
- to confirm this, check whether you can find _openhab-server._tcp. If you don't see it as well, traffic is blocked. Check your network router/firewall settings.
- if you found _hap._tcp, open it. You should see the name of your openHAB HomeKit bridge (the default name is openHAB)
![discovery_hap_list.png](doc/discovery_hap_list.png)
- if you don't see openHAB bridge name, the traffic is blocked
- if you see openHAB HomeKit bridge, open it
- if you don't see the openHAB bridge name, the traffic is blocked
- if you see the openHAB HomeKit bridge, open it
![discovery_openhab_details.png](doc/discovery_openhab_details.png)
- verify the IP address. it must be the IP address of your openHAB server, if not, set the correct IP address using `networkInterface` settings
- verify the IP address. It must be the IP address of your openHAB server; if not, set the correct IP address using the `networkInterface` settings
- verify the flag "sf".
- if sf is equal 1, openHAB is accepting pairing from new iOS device.
- if sf is equal 0 (as on screenshot), openHAB is already paired and does not accept any new pairing request. you can reset pairing using `openhab:homekit clearPairings` command in karaf console.
- if you see openHAB bridge and sf is equal to 1 but you dont see openHAB in the Home app, the Home app probably still thinks it is already paired with openHAB. remove your home from the Home app and restart the iOS device.
- if sf is equal to 1, openHAB is accepting pairing from a new iOS device.
- if sf is equal to 0 (as in the screenshot), openHAB is already paired and does not accept any new pairing request. You can reset pairing using the `openhab:homekit clearPairings` command in the Karaf console.
- if you see the openHAB bridge and sf is equal to 1 but you don't see openHAB in the Home app, the Home app probably still thinks it is already paired with openHAB. Remove your home from the Home app and restart the iOS device.
### Re-adding the openHAB HomeKit bridge reports that a bridge is already added, even though it has clearly been removed.
@@ -1172,13 +1173,13 @@ There are various reasons this may happen.
Try the following:
- In [openhab-cli](https://www.openhab.org/docs/administration/console.html), run `openhab:homekit clearPairings`.
Try again.
- In the HomeKit settings, change the port, setupId, and pin.
Save the settings, then re-open the settings so as to refresh the QR code.
Re-add the device.
- Remove HomeKit state in `${OPENHAB_USERDATA}/jsondb/homekit.json`, and HomeKit config in `${OPENHAB_USERDATA}/config/org/openhab/homekit.config`.
Try again.
- In the HomeKit settings, change the port, setupId, and PIN.
Save the settings, then re-open the settings to refresh the QR code.
Re-add the device.
- Remove HomeKit state in `${OPENHAB_USERDATA}/jsondb/homekit.json` and HomeKit config in `${OPENHAB_USERDATA}/config/org/openhab/homekit.config`.
Restart openHAB.
Reboot iPhone.
Reboot your iPhone.
Try again.
### A stale HomeKit accessory will not go away after deleting the related item.
@@ -1188,22 +1189,21 @@ See the [Dummy Accessories](#dummy-accessories) section in the help, above.
### I added an accessory as the wrong type in Home, and updating the item configuration does not cause the change to reflect in the Home app
HomeKit remembers certain configurations about an accessory, from its name to its fundamental type (i.e. fan, light or
switch?).
HomeKit remembers certain configurations about an accessory, from its name to its fundamental type (i.e., fan, light, or switch?).
If you added it incorrectly, simply updating the item type will not cause Home to update the type.
To resolve:
1. If using text configuration: Comment out the HomeKit metadata for an accessory.
If in the GUI, delete the HomeKit metadata for all items associated with the accessory.
If in the GUI, delete the HomeKit metadata for all items associated with the accessory.
1. If you have `useDummyAccessories` enabled, open the
[openhab-cli](https://www.openhab.org/docs/administration/console.html).
Run `openhab:homekit listDummyAccessories` and
confirm your item is in the list.
Once you've confirmed, clear it with `openhab:homekit clearDummyAccessories`.
[openhab-cli](https://www.openhab.org/docs/administration/console.html).
Run `openhab:homekit listDummyAccessories` and
confirm your item is in the list.
Once you've confirmed, clear it with `openhab:homekit clearDummyAccessories`.
1. Kill your Home app on your iOS device.
Re-open it, and confirm that the accessory is gone.
Re-open it and confirm that the accessory is gone.
1. Uncomment the HomeKit metadata or re-add it via the UI.
@@ -7,17 +7,17 @@
<config-description uri="io:homekit">
<parameter-group name="core">
<label>Core Configuration.</label>
<label>Core Configuration</label>
<advanced>false</advanced>
</parameter-group>
<parameter-group name="thermostat">
<label>Thermostat Settings</label>
<description>Advanced thermostat settings.</description>
<description>Advanced thermostat settings</description>
<advanced>true</advanced>
</parameter-group>
<parameter-group name="network">
<label>Network Settings</label>
<description>Advanced network settings.</description>
<description>Advanced network settings</description>
<advanced>true</advanced>
</parameter-group>
<parameter name="name" type="text" required="false" groupName="core">
@@ -28,7 +28,7 @@
<parameter name="qrCode" type="text" required="false" groupName="core">
<label>HomeKit QR Code</label>
<context>qrcode</context>
<description>Scan QR code with home app to add openHAB as HomeKit bridge.</description>
<description>Scan QR code with Home app to add openHAB as HomeKit bridge.</description>
</parameter>
<parameter name="port" type="integer" required="true" groupName="network">
<label>Port</label>
@@ -44,8 +44,8 @@
<advanced>true</advanced>
</parameter>
<parameter name="pin" type="text" pattern="\d{3}-\d{2}-\d{3}" required="true" groupName="core">
<label>Pin</label>
<description>Defines the pin, used for pairing, in the form ###-##-###.</description>
<label>PIN</label>
<description>Defines the PIN used for pairing in the form ###-##-###.</description>
<default>031-45-154</default>
</parameter>
<parameter name="setupId" type="text" pattern="[0-9A-Z]{4}" required="false" groupName="core">
@@ -60,23 +60,22 @@
</parameter>
<parameter name="useDummyAccessories" type="boolean" required="true" groupName="core">
<label>Use Dummy Accessories</label>
<description><![CDATA[Create dummy accessories when an item is missing. See <a href="https://www.openhab.org/addons/integrations/homekit/#dummy-accessories">the documentation</a> for more information.
]]></description>
<description><![CDATA[Create dummy accessories when an item is missing. See <a href="https://www.openhab.org/addons/integrations/homekit/#dummy-accessories">the documentation</a> for more information.]]></description>
<default>false</default>
</parameter>
<parameter name="useFahrenheitTemperature" type="boolean" required="true" groupName="thermostat">
<label>Use Fahrenheit Temperature</label>
<description>Defines whether or not to direct HomeKit clients to use fahrenheit temperatures instead of celsius.</description>
<description>Defines whether or not to direct HomeKit clients to use Fahrenheit temperatures instead of Celsius.</description>
<default>false</default>
</parameter>
<parameter name="useOHmDNS" type="boolean" required="false" groupName="network">
<label>Use openHAB mDNS service</label>
<description>Defines whether mDNS service of openHAB or a separate instance of mDNS should be used.</description>
<label>Use openHAB mDNS Service</label>
<description>Defines whether the mDNS service of openHAB or a separate instance of mDNS should be used.</description>
<default>false</default>
<advanced>true</advanced>
</parameter>
<parameter name="blockUserDeletion" type="boolean" required="false" groupName="core">
<label>Block deletion of the HomeKit user</label>
<label>Block Deletion of the HomeKit User</label>
<description>Block deletion of the HomeKit user information from openHAB and the unpairing of devices.</description>
<default>false</default>
<advanced>true</advanced>
@@ -3,30 +3,32 @@
addon.homekit.name = HomeKit
addon.homekit.description = Exposes openHAB to HomeKit.
io.config.homekit.blockUserDeletion.label = Block deletion of the HomeKit user
# add-on config
io.config.homekit.blockUserDeletion.label = Block Deletion of the HomeKit User
io.config.homekit.blockUserDeletion.description = Block deletion of the HomeKit user information from openHAB and the unpairing of devices.
io.config.homekit.group.core.label = Core Configuration.
io.config.homekit.group.core.label = Core Configuration
io.config.homekit.group.network.label = Network Settings
io.config.homekit.group.network.description = Advanced network settings.
io.config.homekit.group.network.description = Advanced network settings
io.config.homekit.group.thermostat.label = Thermostat Settings
io.config.homekit.group.thermostat.description = Advanced thermostat settings.
io.config.homekit.group.thermostat.description = Advanced thermostat settings
io.config.homekit.instances.label = Instances
io.config.homekit.instances.description = Defines how many bridges to expose. Necessary if you have more than 149 accessories. Accessories must be assigned to additional instances via metadata. Additional bridges will use incrementing port numbers.
io.config.homekit.name.label = Bridge name
io.config.homekit.name.description = Name of the HomeKit bridge.
io.config.homekit.networkInterface.label = Network Interface
io.config.homekit.networkInterface.description = Defines the IP address of the network interface to expose the HomeKit integration on.
io.config.homekit.pin.label = Pin
io.config.homekit.pin.description = Defines the pin, used for pairing, in the form ###-##-###.
io.config.homekit.pin.label = PIN
io.config.homekit.pin.description = Defines the PIN used for pairing in the form ###-##-###.
io.config.homekit.port.label = Port
io.config.homekit.port.description = Defines the port the HomeKit integration listens on.
io.config.homekit.qrCode.label = HomeKit QR Code
io.config.homekit.qrCode.description = Scan QR code with home app to add openHAB as HomeKit bridge.
io.config.homekit.qrCode.description = Scan QR code with Home app to add openHAB as HomeKit bridge.
io.config.homekit.setupId.label = Setup ID
io.config.homekit.setupId.description = Setup ID used for pairing using QR Code. Alphanumeric code of length 4.
io.config.homekit.useDummyAccessories.label = Use Dummy Accessories
io.config.homekit.useDummyAccessories.description = Create dummy accessories when an item is missing. See <a href="https://www.openhab.org/addons/integrations/homekit/#dummy-accessories">the documentation</a> for more information.
io.config.homekit.useFahrenheitTemperature.label = Use Fahrenheit Temperature
io.config.homekit.useFahrenheitTemperature.description = Defines whether or not to direct HomeKit clients to use fahrenheit temperatures instead of celsius.
io.config.homekit.useOHmDNS.label = Use openHAB mDNS service
io.config.homekit.useOHmDNS.description = Defines whether mDNS service of openHAB or a separate instance of mDNS should be used.
io.config.homekit.useFahrenheitTemperature.description = Defines whether or not to direct HomeKit clients to use Fahrenheit temperatures instead of Celsius.
io.config.homekit.useOHmDNS.label = Use openHAB mDNS Service
io.config.homekit.useOHmDNS.description = Defines whether the mDNS service of openHAB or a separate instance of mDNS should be used.
+47 -47
View File
@@ -1,9 +1,9 @@
# openHAB Hue Emulation Service
Hue Emulation exposes openHAB items as Philips Hue lights to Hue APIcompatible applications such as Amazon Echo, Google Home, and other Hue-compatible apps.
Hue Emulation exposes openHAB items as Philips Hue lights to Hue API-compatible applications like Amazon Echos, Google Homes, or any other Hue-compatible application.
Because Amazon Echo and Google Home communicate with openHAB locally via the Hue API, this provides a fast and reliable way to control your installation using voice commands.
See the Troubleshoot section down below though.
See the Troubleshooting section below though.
This service is independent of the also available Hue binding!
@@ -94,46 +94,46 @@ Hue bridges are using the Universal Plug and Play (UPnP) protocol for discovery.
Like the real Hue bridge the service must be put into pairing mode before other applications can access it.
By default the pairing mode disables itself after 1 minute (can be configured).
## Classic mapping
## Classic Mapping
### Exposed lights
### Exposed Lights
This section applies only when semantic model mapping is disabled.
It is important to note that Hue Emulation exposes _Items_, not _Things_ or _Channels_.
Only Color, Dimmer, Rollershutter, Switch and Group type _Items_ are supported.
Group type items require the "Huelight" tag to be exposed as devices instead of Groups.
It is important to note that you are exposing _Items_, not _Things_ or _Channels_.
Only Color, Dimmer, Rollershutter, Switch, and Group type _Items_ are supported.
Group type Items require the "Huelight" tag to be exposed as devices instead of groups.
This service can emulate three different devices:
- An OSRAM SMART+ Plug
- a dimmable white color Philips A19 bulb
- a Philips Gen 3 LCT010 extended color bulb
- A dimmable white color Philips A19 bulb
- A Philips Gen 3 LCT010 extended color bulb
The exposed Hue-type depends on some criteria:
The exposed Hue type depends on some criteria:
- If the item has the category "ColorLight": It will be exposed as a color bulb
- If the item has the category "Light": It will be exposed as a switch.
- If the Item has the category "ColorLight": It will be exposed as a color bulb.
- If the Item has the category "Light": It will be exposed as a switch.
This initial type determination is overridden if the item is tagged.
This initial type determination is overridden if the Item is tagged.
The following default tags are setup:
The following default tags are set up:
- "Switchable": Item will be exposed as an OSRAM SMART+ Plug
- "Lighting": Item will be exposed as a dimmable white bulb
- "ColorLighting": Item will be exposed as a color bulb
- "Switchable": Item will be exposed as an OSRAM SMART+ Plug.
- "Lighting": Item will be exposed as a dimmable white bulb.
- "ColorLighting": Item will be exposed as a color bulb.
It is the responsibility of binding developers to categories and default tag their available _Channels_, so that linked Items are automatically exposed with this service.
It is the responsibility of binding developers to categorize and default-tag their available _Channels_ so that linked Items are automatically exposed with this service.
You can tag items manually though as well.
You can tag Items manually as well.
### Exposed names
This section applies only when semantic model mapping is disabled.
Your items labels are used for exposing!
The default naming schema for automatically linked items unfortunately names _Items_ like their Channel names,
so usually "Brightness" or "Color". You want to rename those.
Your Item labels are exposed.
The default naming schema for automatically linked items unfortunately names _Items_ like their channel names, so usually "Brightness" or "Color".
You will want to rename those.
### Migrating from classic mapping
@@ -172,7 +172,7 @@ org.openhab.hueemulation:pairingTimeout=60
Enable the following option in combination with pairing to create a new API key on the fly on every API endpoint, not only via the new-user-create API.
Necessary for Amazon Echos and other devices where the API key cannot be reset.
After a new installation of openHAB or a configuration pruning the old API keys are gone but Amazon Echos will keep trying with their old, invalid keys.
After a new installation of openHAB or a configuration pruning, the old API keys are gone, but Amazon Echos will keep trying with their old, invalid keys.
```ini
org.openhab.hueemulation:createNewUserOnEveryEndpoint=false
@@ -193,22 +193,21 @@ Permanent V1 bridge emulation (no obvious reason to enable that):
org.openhab.hueemulation:permanentV1bridge=false
```
The hue emulation service will announce its existence via UPnP on every
of the openHAB configured primary addresses (IPv4 and IPv6).
The Hue emulation service will announce its existence via UPnP on every openHAB-configured primary address (IPv4 and IPv6).
Usually you do not want to set this option, but change the primary address configuration of openHAB.
Usually, you do not want to set this option but change the primary address configuration of openHAB.
This option allows you to override what addresses are used for the announcement.
You can have multiple comma separated entries.
You can have multiple comma-separated entries.
```ini
org.openhab.hueemulation:discoveryIp=192.168.1.100,::FFFF:A9DB:0D85
```
The hue emulation service supports three types of emulated bulbs.
You need to tell the service which item tag corresponds to which emulated bulb type.
One of the comma separated tags must match for the item to be exposed.
Can be empty to match an item based on other criteria.
The Hue emulation service supports three types of emulated bulbs.
You need to tell the service which Item tag corresponds to which emulated bulb type.
One of the comma-separated tags must match for the item to be exposed.
Can be empty to match an Item based on other criteria.
```ini
org.openhab.hueemulation:restrictToTagsSwitches=Switchable
@@ -225,8 +224,9 @@ org.openhab.hueemulation:restrictToTagsWhiteLights=Lighting,Switchable
org.openhab.hueemulation:restrictToTagsColorLights=ColorLighting
```
The service tries to expose as much items as possible (greedy), based on some criteria as explained in the section above.
If you want to exclude items, you need to tag them. Define the tags with the following option:
The service tries to expose as many Items as possible (greedy), based on some criteria as explained in the section above.
If you want to exclude Items, you need to tag them.
Define the tags with the following option:
```ini
org.openhab.hueemulation:ignoreItemsWithTags=internal
@@ -237,12 +237,12 @@ You want this tag for all items that are purely used for rules, as proxy items e
## Troubleshooting
Some devices like Amazon Echo, Google Home and all Philips devices (TVs, Apps) expect a Hue bridge to run on port 80.
You must either
Some devices like Amazon Echo, Google Home, and all Philips devices (TVs, apps) expect a Hue bridge to run on port 80.
You must either:
- port forward your openHAB installation to port 80,
- Port forward your openHAB installation to port 80
(`iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080`)
- install a reverse proxy on port 80, for example nginx with the following configuration:
- Install a reverse proxy on port 80, for example, nginx with the following configuration:
```text
server {
@@ -257,9 +257,9 @@ You must either
}
```
- or let openHAB run on port 80 (the entire java process requires elevated privileges).
- Or let openHAB run on port 80 (the entire Java process requires elevated privileges).
- For Amazon Echo the pairing process may fail due to a 302 response from openHAB, this can be resolved by using a reverse proxy to change the request url from `/api` to `/api/`, for example nginx with the following configuration:
- For Amazon Echo, the pairing process may fail due to a 302 response from openHAB. This can be resolved by using a reverse proxy to change the request URL from `/api` to `/api/`, for example, nginx with the following configuration:
```text
server {
@@ -270,9 +270,9 @@ You must either
}
```
Please open port 80 tcp and port 1900 udp in your firewall installation.
Please open port 80 TCP and port 1900 UDP in your firewall installation.
You can test if the hue emulation does its job by enabling pairing mode including the option "Amazon Echo device discovery fix".
You can test if the Hue emulation does its job by enabling pairing mode, including the option "Amazon Echo device discovery fix".
1. Navigate with your browser to `http://your-openhab-ip/description.xml` to check the discovery response.
Check the IP address in there.
@@ -284,12 +284,12 @@ A reverse proxy is recommended.
Depending on the firmware version of your Amazon Echo, it may not support colored bulbs or switches.
Please assign "ColorLighting" and "Switchable" to the `WhiteLights` type as explained above.
Also note that Amazon Echos are stubborn as.
You might need to remove all former recognized devices multiple times and perform the search via different Echos and also the web or mobile application.
Also note that Amazon Echos can be stubborn.
You might need to remove all formerly recognized devices multiple times and perform the search via different Echos and also via the web or mobile application.
It might help to (temporarly) lower the emulated bridge version in the configuration as described above.
It might help to (temporarily) lower the emulated bridge version in the configuration as described above.
## Text configuration example
## Text Configuration Example
### Semantic model mapping
@@ -315,8 +315,8 @@ Color TestColor "Color" (GamingLightStrip) ["Control", "Color"]
### Classic mapping
The item label will be used as the Hue device name.
Please be aware that textual defined items are generally a bad idea.
In this case renaming items in Hue compatible Apps will fail.
Please be aware that textually defined items are generally a bad idea.
In this case, renaming items in Hue-compatible apps will fail.
```java
Switch TestSwitch "Kitchen spots" [ "Switchable" ] {channel="..."}
@@ -66,7 +66,7 @@
</parameter>
<parameter name="ignoreItemsWithTags" type="text" required="false">
<label>Ignore Items by Tag</label>
<description>All items that are tagged with the given tags are ignore by the Hue Emulation Service. Use commas to
<description>All items that are tagged with the given tags are ignored by the Hue Emulation Service. Use commas to
separate multiple entries.</description>
<default>internal</default>
</parameter>
@@ -77,10 +77,9 @@
</parameter>
<parameter name="discoveryHttpPort" type="integer" required="false">
<label>Optional Discovery Web Port</label>
<description>Some Hue applications require a different port (80) then what openHAB runs on by default (8080). This
option will only advertise a different port then what we are listening on. Useful if you have an iptables rule
redirect traffic from this port to the openHAB port.
</description>
<description>Some Hue applications require a different port (80) than what openHAB runs on by default (8080). This
option will only advertise a different port than what we are listening on. Useful if you have an iptables rule that
redirects traffic from this port to the openHAB port.</description>
<advanced>true</advanced>
</parameter>
<parameter name="uuid" type="text" required="false">
@@ -8,11 +8,11 @@ addon.hueemulation.description = Exposes openHAB as Hue Devices.
io.config.hueemulation.createNewUserOnEveryEndpoint.label = Pairing: Add Unknown User-keys
io.config.hueemulation.createNewUserOnEveryEndpoint.description = Set this option to create new users on the fly during the next pairing mode period. This helps with Amazon Echo device discovery. This option is automatically switched off after the timeout.
io.config.hueemulation.discoveryHttpPort.label = Optional Discovery Web Port
io.config.hueemulation.discoveryHttpPort.description = Some Hue applications require a different port (80) then what openHAB runs on by default (8080). This option will only advertise a different port then what we are listening on. Useful if you have an iptables rule redirect traffic from this port to the openHAB port.
io.config.hueemulation.discoveryHttpPort.description = Some Hue applications require a different port (80) than what openHAB runs on by default (8080). This option will only advertise a different port than what we are listening on. Useful if you have an iptables rule that redirects traffic from this port to the openHAB port.
io.config.hueemulation.discoveryIp.label = Optional Discovery Address
io.config.hueemulation.discoveryIp.description = If your host has multiple IP addresses you may specify the IP(s) you would like to advertise in the UPnP discovery process. You may safely leave this empty on most systems. Use commas to separate multiple entries.
io.config.hueemulation.ignoreItemsWithTags.label = Ignore Items by Tag
io.config.hueemulation.ignoreItemsWithTags.description = All items that are tagged with the given tags are ignore by the Hue Emulation Service. Use commas to separate multiple entries.
io.config.hueemulation.ignoreItemsWithTags.description = All items that are tagged with the given tags are ignored by the Hue Emulation Service. Use commas to separate multiple entries.
io.config.hueemulation.pairingEnabled.label = Device Pairing
io.config.hueemulation.pairingEnabled.description = Pairing must be enabled to connect a new device. Pairing is automatically disabled after the configured pairing time (usually 60 seconds).
io.config.hueemulation.pairingTimeout.label = Pairing Timeout
+32 -32
View File
@@ -1,51 +1,51 @@
# Metrics service
# Metrics Service
The metrics service provides:
The Metrics service provides:
- an additional REST endpoint to retrieve openHAB core metrics from. This can be used as scrape target for pull-based monitoring systems like [Prometheus](https://prometheus.io/).
- optionally configurable services to export openHAB core metrics to push-based monitoring systems like [InfluxDB](https://www.influxdata.com/).
- An additional REST endpoint to retrieve openHAB core metrics from. This can be used as a scrape target for pull-based monitoring systems like [Prometheus](https://prometheus.io/).
- Optionally configurable services to export openHAB core metrics to push-based monitoring systems like [InfluxDB](https://www.influxdata.com/).
## Provided metrics
## Provided Metrics
Currently the following metrics are provided:
Currently, the following metrics are provided:
- openHAB events counts (per topic)
- openHAB event counts (per topic)
- openHAB bundle states
- openHAB thing states
- openHAB rule runs (per rule)
- openHAB threadpool stats (per scheduler)
- JVM stats including metrics of
- class loader
- memory
- GarbageCollector
- openHAB thread pool stats (per scheduler)
- JVM stats including metrics of:
- Class loader
- Memory
- Garbage collector
- OS (system load, CPU)
- thread metrics
- Thread metrics
## Configuration
The configuration for the metrics service is available in the openHAB UI under Settings | Other Services | Metrics service.
Support for pull-based monitoring systems (e. g. Prometheus) is always enabled, since it doesn't imply any significant overhead when not used.
Support for push-based monitoring systems (e. g. InfluxDB) have to be enabled separately.
The configuration for the Metrics service is available in the openHAB UI under Settings | Other Services | Metrics service.
Support for pull-based monitoring systems (e.g., Prometheus) is always enabled since it doesn't imply any significant overhead when not used.
Support for push-based monitoring systems (e.g., InfluxDB) has to be enabled separately.
The following configuration parameters can be set:
| Config param | Description | Default value |
|----------------------|-----------------------------------------------------------------------------------------------------------|---------------|
| influxMetricsEnabled | Enable the Influx (<www.influxdata.com>) metrics. Further configuration of the InfluxDB instance necessary. | false |
| influxMetricsEnabled | Enable the Influx (<www.influxdata.com>) metrics. Further configuration of the InfluxDB instance is necessary. | false |
| jmxMetricsEnabled | Enable the Java Management Extensions (JMX) metrics. | false |
Refer to the corresponding monitoring system sections for monitoring system specific configuration parameters.
### Supported monitoring systems
### Supported Monitoring Systems
For a start, the following formats are supported:
### Prometheus
Once the IO addon is installed, the Prometheus endpoint will be available under:
Once the IO add-on is installed, the Prometheus endpoint will be available under:
_<openhab_host>:8080/rest/metrics/prometheus_
Refer to the [Prometheus](https://prometheus.io/) documentation on how to setup a Prometheus instance and add a scrape configuration. A typical scrape config could look like this (excerpt from `/etc/prometheus/prometheus.yml`):
Refer to the [Prometheus](https://prometheus.io/) documentation on how to set up a Prometheus instance and add a scrape configuration. A typical scrape config could look like this (excerpt from `/etc/prometheus/prometheus.yml`):
````shell
scrape_configs:
@@ -60,23 +60,23 @@ scrape_configs:
Replace `openhab.local` by the openHAB host.
#### Available configuration parameters
#### Available Configuration Parameters
There are no Prometheus specific configuration parameters.
There are no Prometheus-specific configuration parameters.
### InfluxDB
The InfluxDB exporter service will start as soon as the _influxMetricsEnabled_ configuration parameter is set to true.
#### Available configuration parameters
#### Available Configuration Parameters
| Config param | Description | Default value |
|-------------------------------|-----------------------------------------------------------------------------------|-----------------------|
| influxURL | The URL of the InfluxDB instance. Defaults to <http://localhost:8086> | `http://localhost:8086` |
| influxURL | The URL of the InfluxDB instance. Defaults to <http://localhost:8086>. | `http://localhost:8086` |
| influxDB | The name of the database to use. Defaults to "openhab". | openHAB |
| influxUsername | InfluxDB user name | n/a |
| influxUsername | InfluxDB user name. | n/a |
| influxPassword | The InfluxDB password (no default). | n/a |
| influxUpdateIntervalInSeconds | Controls how often metrics are exported to InfluxDB (in seconds). Defaults to 300 | 300 |
| influxUpdateIntervalInSeconds | Controls how often metrics are exported to InfluxDB (in seconds). Defaults to 300. | 300 |
### JMX
@@ -86,7 +86,7 @@ You can monitor the JMX metrics using a tool like [JConsole](https://docs.oracle
When the JMX exporter is enabled, the metrics will be available under the "metrics" MBean.
JConsole and VisualVM will only be able to connect using JMX when openHAB is started in debug mode (use `start_debug.sh` or `start_debug.bat`).
## Configuration file example
## Configuration File Example
The example below shows how to configure the Metrics service using a file.
@@ -103,17 +103,17 @@ influxUpdateIntervalInSeconds=60
jmxMetricsEnabled=false
```
## Additional metric formats
## Additional Metric Formats
The metrics service was implemented using [Micrometer](https://micrometer.io), which supports a number of [monitoring systems](https://micrometer.io/docs)
The Metrics service was implemented using [Micrometer](https://micrometer.io), which supports a number of [monitoring systems](https://micrometer.io/docs).
It should be possible to add any of these, especially the ones using a pull mechanism ("scraping") like Prometheus does.
## Grafana
You can now visualize the results in Grafana. Micrometer provides a public [Grafana dashboard here](https://grafana.com/grafana/dashboards/4701).
I adapted it a little bit to include the openHAB metrics.
You can download it here [Dashboard](./doc/dashboard.json).
This has been tested with Prometheus - for other monitoring systems adaptions to the dashboard might be necessary.
It has been adapted a little to include the openHAB metrics.
You can download it here: [Dashboard](./doc/dashboard.json).
This has been tested with Prometheus - for other monitoring systems, adaptations to the dashboard might be necessary.
Here are some screenshots:
@@ -14,38 +14,38 @@
<parameter name="influxMetricsEnabled" type="boolean" groupName="influx">
<label>Enabled</label>
<description>Enable the Influx (www.influxdata.com) Metrics. Further Configuration of the InfluxDB Instance
Necessary.</description>
<description>Enable the Influx (www.influxdata.com) metrics. Further configuration of the InfluxDB instance is
necessary.</description>
<default>false</default>
</parameter>
<parameter name="influxURL" type="text" groupName="influx">
<label>URL</label>
<description>The URL of the InfluxDB Instance. Defaults to http://localhost:8086</description>
<description>The URL of the InfluxDB instance. Defaults to http://localhost:8086.</description>
<default>http://localhost:8086</default>
</parameter>
<parameter name="influxDB" type="text" groupName="influx">
<label>Database Name</label>
<description>The Name of the Database to Use. Defaults to "openhab".</description>
<description>The name of the database to use. Defaults to "openhab".</description>
<default>openhab</default>
</parameter>
<parameter name="influxUsername" type="text" groupName="influx">
<label>User Name</label>
<description>The InfluxDB User Name (No Default).</description>
<description>The InfluxDB user name (no default).</description>
</parameter>
<parameter name="influxPassword" type="text" groupName="influx">
<label>Password</label>
<description>The InfluxDB Password (No Default).</description>
<description>The InfluxDB password (no default).</description>
<context>password</context>
</parameter>
<parameter name="influxUpdateIntervalInSeconds" type="integer" unit="s" min="1" groupName="influx">
<label>Update Interval in Seconds</label>
<description>Controls How Often Metrics Are Exported to InfluxDB (in Seconds). Defaults to 300</description>
<description>Controls how often metrics are exported to InfluxDB (in seconds). Defaults to 300.</description>
<default>300</default>
</parameter>
<parameter name="jmxMetricsEnabled" type="boolean" groupName="jmx">
<label>Enabled</label>
<description>Enable the Java Management Extensions (JMX) Metrics.</description>
<description>Enable the Java Management Extensions (JMX) metrics.</description>
<default>false</default>
</parameter>
</config-description>
@@ -3,19 +3,21 @@
addon.metrics.name = Metrics
addon.metrics.description = An additional REST endpoint to retrieve openHAB core metrics.
# add-on config
io.config.metrics.group.influx.label = Influx Metrics
io.config.metrics.group.jmx.label = JMX Metrics
io.config.metrics.influxDB.label = Database Name
io.config.metrics.influxDB.description = The Name of the Database to Use. Defaults to "openhab".
io.config.metrics.influxDB.description = The name of the database to use. Defaults to "openhab".
io.config.metrics.influxMetricsEnabled.label = Enabled
io.config.metrics.influxMetricsEnabled.description = Enable the Influx (www.influxdata.com) Metrics. Further Configuration of the InfluxDB Instance Necessary.
io.config.metrics.influxMetricsEnabled.description = Enable the Influx (www.influxdata.com) metrics. Further configuration of the InfluxDB instance is necessary.
io.config.metrics.influxPassword.label = Password
io.config.metrics.influxPassword.description = The InfluxDB Password (No Default).
io.config.metrics.influxPassword.description = The InfluxDB password (no default).
io.config.metrics.influxURL.label = URL
io.config.metrics.influxURL.description = The URL of the InfluxDB Instance. Defaults to http://localhost:8086
io.config.metrics.influxURL.description = The URL of the InfluxDB instance. Defaults to http://localhost:8086.
io.config.metrics.influxUpdateIntervalInSeconds.label = Update Interval in Seconds
io.config.metrics.influxUpdateIntervalInSeconds.description = Controls How Often Metrics Are Exported to InfluxDB (in Seconds). Defaults to 300
io.config.metrics.influxUpdateIntervalInSeconds.description = Controls how often metrics are exported to InfluxDB (in seconds). Defaults to 300.
io.config.metrics.influxUsername.label = User Name
io.config.metrics.influxUsername.description = The InfluxDB User Name (No Default).
io.config.metrics.influxUsername.description = The InfluxDB user name (no default).
io.config.metrics.jmxMetricsEnabled.label = Enabled
io.config.metrics.jmxMetricsEnabled.description = Enable the Java Management Extensions (JMX) Metrics.
io.config.metrics.jmxMetricsEnabled.description = Enable the Java Management Extensions (JMX) metrics.
+60 -61
View File
@@ -1,14 +1,14 @@
# openHAB NEEO Integration
This integration will allow openHAB things/items to be exposed to the NEEO Brain and allow the NEEO smart remote to control them.
NEEO is a smart home solution that includes an IP based remote.
NEEO is a smart home solution that includes an IP-based remote.
More information can be found at [NEEO](https://neeo.com) or in the forums at [NEEO Planet](https://planet.neeo.com).
**This integration was not developed by NEEO** - so please don't ask questions on the NEEO forums.
The openHAB NEEO integration allows mapping of openHAB things/item to a NEEO device/capabilities (see Mappings below).
The openHAB NEEO integration allows mapping of openHAB Things/Items to a NEEO device/capabilities (see Mappings below).
Additionally, this integration provides full two-way communication between an openHAB instance and a NEEO Brain.
This integration compliments the NEEO binding by exposing a brain's devices to all other brains as well (allowing you to create multi-brain recipes).
This integration complements the NEEO binding by exposing a brain's devices to all other brains as well (allowing you to create multi-brain recipes).
## Features
@@ -17,9 +17,9 @@ The openHAB NEEO Integration will provide the following:
- Automatic discovery of NEEO brains on the network and automatic registering of the openHAB as an SDK.
- A NEEO dashboard tile that will show the status of NEEO Brain connections and provide the ability to customize the mapping between openHAB things/item and NEEO device/capabilities.
- Discovery of openHAB things on the NEEO app.
- Full two-way communcation between openHAB and brain.
- Full two-way communication between openHAB and brain.
Item changes in openHAB will appear in NEEO and vice-versa.
Item changes in openHAB will appear in NEEO and vice versa.
## Troubleshooting
@@ -27,8 +27,8 @@ If searching for openHAB devices on the NEEO Brain is always returning nothing,
1. Read sections IP Address and openHAB Primary Address below.
1. Make sure the openHAB primary address is set to an address that is reachable from the NEEO Brain (see openHAB Primary Address section below).
1. Make sure your firewall is not blocking access to the openHAB server
1. Your search criteria has included too many openHAB devices (especially if "Expose ALL" setting has been turned on).
1. Make sure your firewall is not blocking access to the openHAB server.
1. Your search criteria has included too many openHAB devices (especially if "Expose All" setting has been turned on).
The NEEO brain has an (unknown) size limit to the amount of items that can be returned for a search and you may be going beyond that limit.
Narrow your search to a specific item to see if you were hitting that search limit.
@@ -48,7 +48,7 @@ If you change the primary address option, this binding will de-register the old
For openHAB things/items to appear on the NEEO system, you must create mappings between openHAB and NEEO.
To accomplish this, go to the NEEO Integration dashboard (typically <http://localhost:8080/neeo/index.html>).
This will open up a screen similar to the following
This will open up a screen similar to the following:
![Configuration](doc/dashboardmain.png)
@@ -72,7 +72,7 @@ You will be prompted for the Brain's IP address and once entered, the brain shou
1. The 'phone' icon will bring up the EUI associated with the NEEO Brain.
1. The 'file' icon will allow you to view the associated NEEO Brain's log.
1. The 'dot' icon will blink the LED on the associate NEEO Brain (allowing you to identify the brain if you have multiple ones).
1. The 'dot' icon will blink the LED on the associated NEEO Brain (allowing you to identify the brain if you have multiple ones).
1. The 'trash' icon will disconnect from the related Brain.
This will allow you to remove a stale (no longer used) Brain or remove the Brain to be rediscovered again (which may fix a communication issue with the brain).
@@ -87,17 +87,17 @@ The Things tab is where you specify the mappings.
There are two types of devices listed here:
1. openHAB things - any OH2 thing in the openHAB system and optionally (see configuration), any NEEO binding thing.
1. virtual things - these are things you defined that can mix/match any OH1 or OH2 item.
1. openHAB things - any openHAB 2 Thing in the openHAB system and optionally (see configuration), any NEEO binding Thing.
1. virtual things - these are things you defined that can mix/match any openHAB 1 or openHAB 2 item.
openHAB things can be mapped to a NEEO device and the items within the thing can be mapped to NEEO device capabilities (buttons, lists, switches, sliders, etc).
openHAB things can be mapped to a NEEO device and the items within the thing can be mapped to NEEO device capabilities (buttons, lists, switches, sliders, etc.).
Virtual things represent a 'thing' that doesn't exist in openHAB but that you would like to define as a NEEO device.
You can then add OH1/OH2 items to that virtual thing and those items will be mapped to a NEEO device capabilities.
You can then add openHAB 1/openHAB 2 items to that virtual thing and those items will be mapped to NEEO device capabilities.
There are two types of items supported:
1. Any valid openHAB item (OH1 or OH2).
1. Trigger channels - any trigger channel defined in an openHAB thing or any trigger channel that you add to an existing thing (regardless if it is an openHAB thing or a virtual thing).
1. Any valid openHAB item (openHAB 1 or openHAB 2).
1. Trigger channels - any trigger channel defined in an openHAB thing or any trigger channel that you add to an existing thing (regardless of whether it is an openHAB thing or a virtual thing).
Trigger channels are useful to add to an existing thing if you want to add a button on NEEO that when pushed, can perform some rule that you have defined on a trigger.
@@ -110,20 +110,20 @@ Mappings consist of two parts:
1. Mapping of an openHAB thing to a NEEO device or the creation of a new virtual thing.
1. Mapping of an openHAB item or trigger channels to one or more NEEO capabilities.
Please see this screen shot for reference to the next two sections.
This screen show partially shows the setup of my Russound (whole house music system):
Please see this screenshot for reference to the next two sections.
This screen partially shows the setup of my Russound (whole house music system):
![Configuration](doc/dashboardthings.png)
#### NEEO Text Label
The NEEO text label type will allow you to specify showing the label and text or just the text.
To show both a label and the text on the NEEO remote, uncheck the check mark next the the associated label field and enter in the label you wish to assign to the text.
To show both a label and the text on the NEEO remote, uncheck the check mark next to the associated label field and enter the label you wish to assign to the text.
By turning off the label and specifying the format of the text field, you will be able to create your own custom label then.
##### NEEO List
You can now specify a LIST type for items.
A list is simply a list of labels and associated values that the user can choose from on the remote (similar, in concept, to a drop down).
A list is simply a list of labels and associated values that the user can choose from on the remote (similar, in concept, to a dropdown).
Simply choose the LIST type and press the icon that appears next to the label.
You can then build the list by specifying:
@@ -141,7 +141,7 @@ There is no need to drop and re-add the device if you make changes (even though
#### Thing to Device
The first step in mapping is to map an openHAB thing to a NEEO device type.
You may either choose an existing openHAB item or create a new 'virtual' thing by pressing the "+ Virtual" button and assign a name to it.
You may either choose an existing openHAB item or create a new 'virtual' thing by pressing the "+ Virtual" button and assigning a name to it.
The following action can then be performed:
@@ -156,14 +156,14 @@ The following action can then be performed:
1. [openHAB things] Press the RESTORE icon to restore the mapping to its original content (discarding any pending changes).
1. [Virtual things] Press the DELETE icon to delete the thing.
1. [things with trigger channel(s)] Press the RULES icon to download an example .rules file for the triggers.
1. [NON ACCESSORIE/LIGHT] Specify device timings (see below).
1. [NON-ACCESSORIE/LIGHT] Specify device timings (see below).
The list of device types is unknown, must match those that NEEO expects (such as "ACCESSORIE", "AUDIO", etc) and you have the ability to enter the device type directly or select from a list of device types that have been discovered (although all may not be functional on the NEEO brain yet).
The list of device types is unknown, must match those that NEEO expects (such as "ACCESSORIE", "AUDIO", etc.), and you have the ability to enter the device type directly or select from a list of device types that have been discovered (although all may not be functional on the NEEO brain yet).
Please review the NEEO SDK documentation for hints on what device types are supported and what capabilities are supported by each device type.
Please note that "ACCESSORIE" is not a misspelling.
That is how the NEEO brain expects it.
You may specify a type of "ACCESSORY" when defining a new type, but after saving - the type will switch back to "ACCESSORIE"
You may specify a type of "ACCESSORY" when defining a new type, but after saving, the type will switch back to "ACCESSORIE".
#### Properties Page
@@ -171,11 +171,11 @@ The properties page (accessible via the gear icon) will present properties speci
##### Advanced Properties
1. The driver version can be used to override the driver version sent to the brain. Please note that this number is automatically incremented by one whenever you save the device definition.
1. The driver version can be used to override the driver version sent to the brain. Please note that this number is automatically incremented by one whenever you save the device definition.
1. The 'Specific name' can be used to override the thing name presented to the NEEO Brain.
1. The 'Custom Icon' can be used to assign a custom icon to the device (if left blank, the icon is assigned by the NEEO Brain according to the NEEO Type).
The only 'officially' supported custom icon is "sonos" however you can assign any variety of icons available on the brain.
The only 'officially' supported custom icon is "sonos"; however, you can assign any variety of icons available on the brain.
A list of some of the icons that can be assigned: ![Configuration](doc/icons.png)
##### Device Timings
@@ -190,7 +190,7 @@ If the device does not have power state or doesn't support input switching, the
##### Device Capabilities
This following device capabilities are available:
The following device capabilities are available:
1. "Always On" - check if there is no power management for the device.
@@ -208,9 +208,9 @@ Any device type that is marked with any type will be visible to the NEEO App whe
### Format
When you have a text label, you can specify the text format to use and will be prefilled if the channel provides a default.
You can use any standard java string format for the value.
You may also provide a transformation format (in the same format as in .items file).
Example: "MAP(stuff.map):%s" will use the MAP tranformation file "stuff.map" to convert the value to a string.
You can use any standard Java string format for the value.
You may also provide a transformation format (in the same format as in an .items file).
Example: "MAP(stuff.map):%s" will use the MAP transformation file "stuff.map" to convert the value to a string.
#### Items to Capabilities
@@ -227,21 +227,21 @@ For each item, you may:
At the time of this writing, the following NEEO capability types are supported:
1. Text Label - this will simply take the toString() of the item value and optionally format via the Java String Format found in the "Format/Command" field before sending it to the NEEO brain.
1. Button - this will create virtual button with the text from the "NEEO Label".
1. Button - this will create a virtual button with the text from the "NEEO Label".
Upon pressing the button, the specified command in the "Format/Command" will be sent to the item (or ON will be sent if nothing has been specified).
Please note that you can also specify a hard button in the "NEEO Label" - in which case nothing will appear on the NEEO remote screen and the action will occur from the NEEO remote hard button.
Please note that you can also specify a hard button in the "NEEO Label"; in which case, nothing will appear on the NEEO remote screen and the action will occur from the NEEO remote hard button.
You must specify all the hard buttons for a capability (as specified in the NEEO SDK documentation) for the button to work.
Example: if you only defined VOLUME DOWN but not VOLUME UP - the button will not work on the remote.
Example: if you only defined VOLUME DOWN but not VOLUME UP, the button will not work on the remote.
Likewise, which hard buttons are active or not additionally depends on the NEEO device type.
1. Switch - this will create a virtual switch with the text from the "NEEO Label" and will send an ON or OFF command to the associated item.
Additionally, a switch can be bound to hard button pairs (the VOLUME keys, the POWER ON/OFF, the CHANNELS, etc).
The command that is sent is dependent on the KEYS chosen (POWER ON/OFF will send ON/OFF to the underlying item, all others will send an INCREASE/DECREASE).
Similar to the "Button" type - please review the NEEO SDK documentation.
The command that is sent is dependent on the KEYS chosen (POWER ON/OFF will send ON/OFF to the underlying item; all others will send an INCREASE/DECREASE).
Similar to the "Button" type, please review the NEEO SDK documentation.
1. Slider - this will create a virtual slider that will send the associated value to the item.
The value sent will always be between 0 and 100.
1. ImageURL - this will create an image on the remote from the toString() of the item value (assuming it is a URL to an image).
1. Sensor - this will create a sensor (non-visual) that can be used in recipes on the brain.
1. Power - this will create a powerstate sensor on the brain that can be used to stop/start the device.
1. Power - this will create a power state sensor on the brain that can be used to stop/start the device.
NOTE: you MUST also assign a POWER OFF/POWER ON for this to work.
1. List - this will create a directory on the brain that can be used to show a list.
@@ -264,13 +264,13 @@ The following chart shows what openHAB command types are supported for each NEEO
##### HSBType
HSBType has three attributes - Hue, Brightness and Saturation.
This type is special in that the integration will create 4 capabilities for it:
HSBType has three attributes: Hue, Brightness, and Saturation.
This type is special in that the integration will create four capabilities for it:
1. The first capability will you to control the on/off and will be named simply "item".
1. The first capability will allow you to control the on/off and will be named simply "item".
1. The second capability will allow you to control the HUE and will be named "item (Hue)".
1. The third capability will allow you to control the brightness and will be named "item (Bri)".
1. The forth capability will allow you to control the saturation and will be named "item (Sat)".
1. The fourth capability will allow you to control the saturation and will be named "item (Sat)".
If you are trying to bind a LIFX or HUE bulb, here are the following channels you need to create to enable the NEEO Light capability:
@@ -281,10 +281,10 @@ If you are trying to bind a LIFX or HUE bulb, here are the following channels yo
1. Set the HUE/SATURATION/TEMPERATURE to a NEEO type of "Slider" (you can set the BRIGHTNESS as well - but NEEO will automatically assign that for you).
Please note that NEEO will automatically combine all your "LIGHT" types into a single light on the remote (not ideal).
You will get a single screen with all lights listed with a power toggle and slider for brightness.
You will get a single screen with all lights listed, with a power toggle and slider for brightness.
You will need to add the HUE/SATURATION/TEMPERATURE as shortcuts.
##### Power State Capability type
##### Power State Capability Type
The power state capability type _REQUIRES_ a POWER ON and POWER OFF button to be assigned as well.
This is a NEEO Brain requirement for the power state.
@@ -292,22 +292,21 @@ Sending ON to the power state item will start the device (similar to POWER ON bu
##### Virtual Device Items
When you press the "+" icon (on the device) to add new items to the virtual device.
You will be presented with a screen that will allow you to:
When you press the "+" icon (on the device) to add new items to the virtual device, you will be presented with a screen that will allow you to:
1. Add a new item by pressing the "Add Item" button.
1. Delete all your items by pressing the "Delete All" button.
1. Import OH1 items from an .item files by pressing the "Import Item" button.
1. Import openHAB 1 items from .item files by pressing the "Import Item" button.
The items section then provide a list of the items you have specified.
To specify a new item, simply click on the line in question - and then enter the item name.
All item names (OH1 and OH2) are shown in the dropdown (and will allow you to search/choose from that dropdown).
The items section then provides a list of the items you have specified.
To specify a new item, simply click on the line in question and then enter the item name.
All item names (openHAB 1 and openHAB 2) are shown in the dropdown (and will allow you to search/choose from that dropdown).
You will NOT be able to select an item not shown in this list - all items must be valid openHAB items.
You can delete individual items by pressing the "-" key next to it.
Press OK will add those items to the virtual thing.
Pressing cancel will simply dismiss the window without doing any action.
Pressing OK will add those items to the virtual thing.
Pressing Cancel will simply dismiss the window without performing any action.
#### Trigger Channels
@@ -333,14 +332,14 @@ When the volumes keys are pressed, a "INCREASE" or "DECREASE" will be sent to th
### Integration Storage
All data used by the integration is stored under the "userdata/neeo" directory (please note that this directory is shared with the NEEO binding).
All data used by the integration is stored under the "userdata/neeo" directory (please note that this directory is shared with the NEEO binding).
You may backup and restore these files as needed.
If you restore the directory, you will likely need to restart openHAB for the new file contents to be applied.
There are two files being stored by the integration:
1. discoveredbrains.json will contain the brains that are discovered or manually added from the 'brains' tab.
As brains are discovered, manually added or removed, this file will be updated.
As brains are discovered, manually added, or removed, this file will be updated.
1. neeodefinitions.json will contain the device mappings defined on the 'things' tab.
As definitions are saved, this file will be updated.
@@ -353,8 +352,8 @@ The following are notes on some of the NEEO Firmwares:
The following changes have occurred:
1. Added support for driver version
1. Added support for UI actions on lists
1. Added support for driver version.
1. Added support for UI actions on lists.
### 51.1
@@ -364,11 +363,11 @@ The following changes have occurred:
1. Changed internals to reflect new naming standards enforced by NEEO.
1. Updated search to provide better results (matches NEEO search perfectly now).
As of this firmware, NEEO is enforcing some internal naming standards (sdk name, device name and sensor names).
It is **STRONGLY** recommended that you delete and readd all the devices you have after upgrading to this version.
The old devices will still work but there is one danger to leaving them.
As part of this firmware, there is a new "SDK Integeration" found on the NEEO Brain.
Within this screen, there is a button the "Cleanup unused adapters" that will remove SDK's that have no references to them.
As of this firmware, NEEO is enforcing some internal naming standards (SDK name, device name, and sensor names).
It is **STRONGLY** recommended that you delete and re-add all the devices you have after upgrading to this version.
The old devices will still work, but there is one danger to leaving them.
As part of this firmware, there is a new "SDK Integration" found on the NEEO Brain.
Within this screen, there is a button, "Cleanup unused adapters", that will remove SDKs that have no references to them.
Unfortunately this functionality depends on the new naming standards and existing devices will be 'stranded' (and rendered non-working) since the openHAB SDK name did not match that naming standard.
According to NEEO, there is a chance that future firmware changes will continue looking for these naming standards and there may be additional issues with these devices.
@@ -387,7 +386,7 @@ The following changes have occurred:
1. SKIP FORWARD should be changed to NEXT.
1. ENTER should be changed to CURSOR ENTER.
1. Added support for 'specificname' (allowing you to override the name shown in NEEO).
1. Added support for HSBType channels (creates 4 channels: overall, hue, brightness and saturation).
1. Added support for HSBType channels (creates four channels: overall, hue, brightness, and saturation).
1. Added NEEO Brain name to the Brain tab.
## Configuration
@@ -404,7 +403,7 @@ Alternatively, you can configure the settings in the file `conf/services/neeo.cf
# Default is 'false'.
#exposeAll=true|false
# Whether to automatically expose things from NEEO Binding
# Whether to automatically expose things from NEEO Binding.
# Default is 'true'
#exposeNeeoBinding=true|false
@@ -414,7 +413,7 @@ Alternatively, you can configure the settings in the file `conf/services/neeo.cf
#searchLimit=10
# The interval (in seconds) to check the status of the brain to determine if the
# brain is reachable or not
# brain is reachable or not.
# Default is 10
#checkStatusInterval=10
```
@@ -6,23 +6,23 @@
<config-description uri="io:neeo">
<parameter name="exposeAll" type="boolean" required="false">
<label>Expose All</label>
<description>Expose all things</description>
<description>Expose all things.</description>
<default>false</default>
</parameter>
<parameter name="exposeNeeoBinding" type="boolean" required="false">
<label>Expose NEEO Binding</label>
<description>Expose things found by the NEEO Binding</description>
<description>Expose things found by the NEEO binding.</description>
<default>true</default>
</parameter>
<parameter name="searchLimit" type="integer" required="false" min="1">
<label>Search Limit</label>
<description>The maximum number of results to return for a search</description>
<description>The maximum number of results to return for a search.</description>
<advanced>true</advanced>
<default>12</default>
</parameter>
<parameter name="checkStatusInterval" type="integer" required="false" min="1">
<label>Check Status Interval (seconds)</label>
<description>The interval (in seconds) to check the status of the brain</description>
<label>Check Status Interval</label>
<description>The interval (in seconds) to check the status of the brain.</description>
<advanced>true</advanced>
<default>10</default>
</parameter>
@@ -3,11 +3,13 @@
addon.neeo.name = Neeo
addon.neeo.description = The openHAB NEEO integration allows mapping of openHAB things/item to a NEEO device/capabilities.
io.config.neeo.checkStatusInterval.label = Check Status Interval (seconds)
io.config.neeo.checkStatusInterval.description = The interval (in seconds) to check the status of the brain
# add-on config
io.config.neeo.checkStatusInterval.label = Check Status Interval
io.config.neeo.checkStatusInterval.description = The interval (in seconds) to check the status of the brain.
io.config.neeo.exposeAll.label = Expose All
io.config.neeo.exposeAll.description = Expose all things
io.config.neeo.exposeAll.description = Expose all things.
io.config.neeo.exposeNeeoBinding.label = Expose NEEO Binding
io.config.neeo.exposeNeeoBinding.description = Expose things found by the NEEO Binding
io.config.neeo.exposeNeeoBinding.description = Expose things found by the NEEO binding.
io.config.neeo.searchLimit.label = Search Limit
io.config.neeo.searchLimit.description = The maximum number of results to return for a search
io.config.neeo.searchLimit.description = The maximum number of results to return for a search.
+16 -16
View File
@@ -5,7 +5,7 @@ openHAB Cloud service hosted by the [openHAB Foundation](https://www.openhabfoun
## Features
The openHAB Cloud service (and thus the connector to it) is useful for different use cases:
The openHAB Cloud service (and thus, the connector to it) is useful for different use cases:
- It allows remote access to local openHAB instances without having to expose ports to the Internet or to require a complex VPN setup.
- It serves as a connector to Firebase Cloud Messaging (FCM) for pushing notifications to mobile phone apps.
@@ -28,7 +28,7 @@ One can think of it as something similar like a username for the cloud authentic
The second one is a random secret key which serves as a password.
Both values are written to the local file system.
If you loose these files for some reason, openHAB will automatically generate new ones.
If you lose these files for some reason, openHAB will automatically generate new ones.
You will then have to reconfigure UUID and secret in the openHAB Cloud service under the _My account_ section.
You will need these values to register on the website before connection is accepted.
@@ -49,10 +49,10 @@ By default, both remote access and push notifications are enabled.
### Advanced Configuration
For private hosted myopenHAB installations, the base URL can be changed to point another cloud instance.
For privately hosted myopenHAB installations, the base URL can be changed to point to another cloud instance.
Private hosted myopenHAB installations may enable selected items in openHAB to have their state updates pushed to the cloud service for integrations with services like IFTTT.
Note that this is not supported on the community hosted myopenHAB service due to high load concerns and will have no effect if enabled with the default URL configured.
Privately hosted myopenHAB installations may enable selected items in openHAB to have their state updates pushed to the cloud service for integrations with services like IFTTT.
Note that this is not supported on the community-hosted myopenHAB service due to high load concerns and will have no effect if enabled with the default URL configured.
This is also not required for remote access through the cloud service to function.
Alternatively, you can configure the settings in the file `conf/services/openhabcloud.cfg`:
@@ -103,7 +103,7 @@ For each of the three actions, there's another variant accepting an icon name an
- `sendBroadcastNotification(message, icon, tag)`
- `sendLogNotification(message, icon, tag)`
Icon and tag can potentially be used by cloud instance clients (such as the openHAB apps for Android or iOS) to be displayed in the notification itself and the list of notifications.
Icon and tag can potentially be used by cloud instance clients (such as the openHAB apps for Android or iOS) to be displayed in the notification itself and in the list of notifications.
The parameters for these actions have the following meaning:
@@ -140,7 +140,7 @@ The additional parameter for these variants have the following meaning:
- `title`: The title of the notification. Defaults to "openHAB" inside the Android and iOS apps.
- `referenceId`: A user supplied id to both replace existing messages when pushed, and later remove messages with the `hideNotificationByReferenceId` actions.
- `onClickAction`: The action to be performed when the user clicks on the notification. Specified using the [action syntax](#action-syntax).
- `mediaAttachmentUrl`: The URL of the media attachment to be displayed with the notification. This can either be a fully qualified URL, prefixed with `http://` or `https://` and reachable by the client device, a relative path on the user's openHAB instance starting with `/`, or an image item with the format `item:MyImageItem`. If the media attachment URL is not reachable by the client device (ie. the URL is not available on the public internet), use the `setImage` action to set the image item to the URL first then use `item:MyImageItem` as the media attachment URL. See [example](#examples) for more details.
- `mediaAttachmentUrl`: The URL of the media attachment to be displayed with the notification. This can either be a fully qualified URL, prefixed with `http://` or `https://` and reachable by the client device, a relative path on the user's openHAB instance starting with `/`, or an image item with the format `item:MyImageItem`. If the media attachment URL is not reachable by the client device (i.e., the URL is not available on the public internet), use the `setImage` action to set the image item to the URL first, then use `item:MyImageItem` as the media attachment URL. See [example](#examples) for more details.
- `actionButton1`: The action to be performed when the user clicks on the first action button. Specified as `Title=$action`, where `$action` follows the [action syntax](#action-syntax).
- `actionButton2`: The action to be performed when the user clicks on the second action button. Specified as `Title=$action`, where `$action` follows the [action syntax](#action-syntax).
- `actionButton3`: The action to be performed when the user clicks on the third action button. Specified as `Title=$action`, where `$action` follows the [action syntax](#action-syntax).
@@ -155,7 +155,7 @@ There are several types of actions available:
- `command`: Sends a command to an Item by using the following syntax: `command:$itemName:$commandString` where `$itemName` is the name of the Item and `$commandString` is the command to be sent.
- `ui`: Controls the UI in two possible ways:
- `ui:$path` where `$path` is either `/basicui/app?...` for navigating sitemaps (using the native renderer) or `/some/absolute/path` for navigating (using the web view).
- `ui:$path` where `$path` is either `/basicui/app?...` for navigating sitemaps (using the native renderer) or `/some/absolute/path` for navigating (using the webview).
- `ui:$commandItemSyntax` where `$commandItemSyntax` is the same syntax as used for the [UI Command Item]({{base}}/mainui/about.html#ui-command-item).
- `http:` or `https:`: Opens the fully qualified URL in an embedded browser on the device.
- `rule` (currently only on iOS): Runs a rule by using the following syntax: `rule:$ruleId:$prop1Key=$prop1Value,$prop2Key=$prop2Value,...` where `$ruleId` is the id of the rule, and optional properties to send to the rule are in the format `name=value` separated by commas. Most rules can omit the properties.
@@ -166,16 +166,16 @@ Examples:
- `command:KitchenLights:ON`
- `command:KitchenBlinds:50`
- `ui:/basicui/app?w=0000&sitemap=main` (use Basic UI to get sitemap URL locations)
- `ui:/some/absolute/path`: Navigates to the absolut path `/some/absolute/path`.
- `ui:/some/absolute/path`: Navigates to the absolute path `/some/absolute/path`.
- `ui:navigate:/page/my_floorplan_page`: Navigates Main UI to the page with the ID `my_floorplan_page`.
- `ui:popup:oh-clock-card`: Opens a popup with `oh-clock-card`.
- `https://openhab.org`: Opens an embedded browser to the site `https://openhab.org`
- `rule:02ffc3a297:prop1=foo`: Runs the rule with an id of `02ffc3a297` passing in an optional parameter named `prop1` with a value of `foo`
- `app:android=com.sonos.acr2,ios=sonos-2://`: Opens the Sonos app depending on the device type (Android or iOS)
- `https://openhab.org`: Opens an embedded browser to the site `https://openhab.org`.
- `rule:02ffc3a297:prop1=foo`: Runs the rule with an ID of `02ffc3a297`, passing in an optional parameter named `prop1` with a value of `foo`.
- `app:android=com.sonos.acr2,ios=sonos-2://`: Opens the Sonos app depending on the device type (Android or iOS).
### Hide Notification Actions
There are also actions to hide existing notifications, either by `referenceId` or `tag` (formerly severity):
There are also actions to hide existing notifications, either by `referenceId` or `tag` (formerly "severity"):
- `hideNotificationByReferenceId(emailAddress, referenceId)`
- `hideBroadcastNotificationByReferenceId(referenceId)`
@@ -336,7 +336,7 @@ end
::::
Notify all openHAB Cloud users that motion was detected, attach a camera snapshot from a network local camera using an image item and add an action button to turn on the light:
Notify all openHAB Cloud users that motion was detected, attach a camera snapshot from a local network camera using an image item, and add an action button to turn on the light:
:::: tabs
@@ -360,7 +360,7 @@ end
```javascript
rules.when().item('Apartment_MotionSensor').changed().to('ON').then(() => {
actions.HTTP.setImage("Apartment_Camera_Snapshot", "http://camera.local/camera-snapshot.jpg");
actions.HTTP.setImage('Apartment_Camera_Snapshot', 'http://camera.local/camera-snapshot.jpg');
actions.notificationBuilder('Motion detected in the apartment!')
.withIcon('motion')
.withTag('Motion Tag')
@@ -380,7 +380,7 @@ rules.when().item('Apartment_MotionSensor').changed().to('ON').then(() => {
rule "Motion Detected Notification" do
changed Apartment_MotionSensor, to: ON
run do
HTTP.setImage("Apartment_Camera_Snapshot", "http://camera.local/camera-snapshot.jpg");
HTTP.setImage("Apartment_Camera_Snapshot", "http://camera.local/camera-snapshot.jpg")
Notification.send "Motion detected in the apartment!",
icon: "motion",
tag: "Motion Tag",
@@ -7,7 +7,7 @@
<config-description uri="io:openhabcloud">
<parameter name="mode" type="text" required="true">
<label>Mode</label>
<description>What features of the openHAB Cloud service should be used.</description>
<description>Features of the openHAB Cloud service that should be used.</description>
<options>
<option value="notification">Notifications</option>
<option value="remote">Notifications &amp; Remote Access</option>
@@ -3,11 +3,13 @@
addon.openhabcloud.name = openHAB Cloud
addon.openhabcloud.description = Connects local instance to the openHAB cloud.
# add-on config
io.config.openhabcloud.baseURL.label = Base URL
io.config.openhabcloud.baseURL.description = Base URL for the openHAB Cloud server.
io.config.openhabcloud.expose.label = Items to Expose
io.config.openhabcloud.expose.description = List of items that are made accessible to IFTTT and similar services. Only supported on private cloud installations.
io.config.openhabcloud.mode.label = Mode
io.config.openhabcloud.mode.description = What features of the openHAB Cloud service should be used.
io.config.openhabcloud.mode.description = Features of the openHAB Cloud service that should be used.
io.config.openhabcloud.mode.option.notification = Notifications
io.config.openhabcloud.mode.option.remote = Notifications & Remote Access
@@ -35,25 +35,25 @@ Please also note possible [Free Tier](https://aws.amazon.com/free/) benefits.
- Select the AWS region in the [AWS console](https://console.aws.amazon.com/) using [these instructions](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/getting-started.html#select-region). Note the region identifier in the URL (e.g. `https://eu-west-1.console.aws.amazon.com/console/home?region=eu-west-1` means that region id is `eu-west-1`).
<!-- markdownlint-disable-next-line no-emphasis-as-heading -->
**Create policy controlling permissions for AWS user**
**Create a policy controlling permissions for AWS user**
Here we create AWS IAM Policy to limit exposure to AWS resources.
This way, openHAB DynamoDB addon has limited access to AWS, even if credentials would be compromised.
Here we create an AWS IAM Policy to limit exposure to AWS resources.
This way, the openHAB DynamoDB add-on has limited access to AWS, even if credentials were to be compromised.
**Note:** this policy is only valid for the new table schema.
New table schema is the default for fresh openHAB installations and for users that are taking DynamoDB into use for the first time.
For users with old table schema, one can use pre-existing policy `AmazonDynamoDBFullAccess` (although it gives wider-than-necessary permissions).
1. Open Services menu, and search for _IAM_.
1. From top right, press the small arrow on top right corner close to your name. Copy the _Account ID_ to clipboard by pressing the small "copy" icon
1. Open the Services menu and search for _IAM_.
1. From the top right, press the small arrow in the top right corner close to your name. Copy the _Account ID_ to the clipboard by pressing the small "copy" icon.
![AWS Account ID](doc/aws_account_id.png)
1. In IAM dialog, select _Policies_ from the menu on the left
1. Click _Create policy_
1. Open _JSON_ tab and input the below policy code.
1. Make the below the changes to the policy JSON `Resource` section
1. In the IAM dialog, select _Policies_ from the menu on the left.
1. Click _Create policy_.
1. Open the _JSON_ tab and input the below policy code.
1. Make the below changes to the policy JSON `Resource` section:
- Modify the AWS account id from `055251986555` to to the one you have on clipboard (see step 2 above)
- If you are on some other region than `eu-west-1`, change the entry accordingly
- Modify the AWS account ID from `055251986555` to the one you have on the clipboard (see step 2 above).
- If you are on some other region than `eu-west-1`, change the entry accordingly.
```json
{
@@ -98,24 +98,24 @@ For users with old table schema, one can use pre-existing policy `AmazonDynamoDB
}
```
<!-- markdownlint-disable ol-prefix -->
4. Click _Next: Tags_
5. Click _Next: Review_
6. Enter `openhab-dynamodb-policy` as the _Name_
7. Click _Create policy_ to finish policy creation
4. Click _Next: Tags_.
5. Click _Next: Review_.
6. Enter `openhab-dynamodb-policy` as the _Name_.
7. Click _Create policy_ to finish policy creation.
<!-- markdownlint-enable ol-prefix -->
<!-- markdownlint-disable-next-line no-emphasis-as-heading -->
**Create user for openHAB**
**Create a user for openHAB**
Here we create AWS user with programmatic access to the DynamoDB.
Here we create an AWS user with programmatic access to DynamoDB.
We associate the user with the policy created above.
1. Open _Services_ -> _IAM_ -> _Users_ -> _Add users_. Enter `openhab` as _User name_, and tick _Programmatic access_
1. Click _Next: Permissions_
1. Select _Attach existing policies directly_, and search policies with `openhab-dynamodb-policy`. Tick the `openhab-dynamodb-policy` and proceed with _Next: Tags_
1. Click _Next: review_
1. Click _Create user_
1. Record the _Access key ID_ and _Secret access key_
1. Open _Services_ -> _IAM_ -> _Users_ -> _Add users_. Enter `openhab` as _User name_, and tick _Programmatic access_.
1. Click _Next: Permissions_.
1. Select _Attach existing policies directly_, and search policies with `openhab-dynamodb-policy`. Tick `openhab-dynamodb-policy` and proceed with _Next: Tags_.
1. Click _Next: review_.
1. Click _Create user_.
1. Record the _Access key ID_ and _Secret access key_.
## Configuration
@@ -125,7 +125,7 @@ In order to configure the persistence service, you need to configure AWS credent
For new users, the other default settings are OK.
For DynamoDB persistence users with data stored with openHAB 3.1.0 or earlier, you need to decide whether you opt in to "new" more optimized table schema, or stay with "legacy".
For DynamoDB persistence users with data stored with openHAB 3.1.0 or earlier, you need to decide whether you opt in to the "new" more optimized table schema, or stay with "legacy".
See below for details.
### Table schema
@@ -136,32 +136,32 @@ All users are advised to transition to "new" table schema, which is more optimiz
At this moment there is no supported way to migrate data from old format to new.
#### New table schema
#### New Table Schema
Configure the addon to use new schema by setting `table` parameter (name of the table).
Configure the add-on to use the new schema by setting the `table` parameter (name of the table).
Only one table will be created for all data. The table will have the following fields
Only one table will be created for all data. The table will have the following fields:
| Attribute | Type | Data type | Description |
| --------- | ------ | --------- | --------------------------------------------- |
| `i` | String | Yes | Item name |
| `t` | Number | Yes | Timestamp in milliepoch |
| `s` | String | Yes | State of the item, stored as DynamoDB string. |
| `n` | Number | Yes | State of the item, stored as DynamoDB number. |
| `s` | String | Yes | State of the item, stored as DynamoDB string |
| `n` | Number | Yes | State of the item, stored as DynamoDB number |
| `exp` | Number | Yes | Expiry date for item, in epoch seconds |
Other notes
<!-- markdownlint-disable ul-style -->
- `i` and `t` forms the composite primary key (partition key, sort key) for the table
- Only one of `s` or `n` attributes are specified, not both. Most items are converted to number type for most compact representation.
- Compared to legacy format, data overhead is minimizing by using short attribute names, number timestamps and having only single table.
- `exp` attribute is used with DynamoDB Time To Live (TTL) feature to automatically delete old data
- `i` and `t` form the composite primary key (partition key, sort key) for the table.
- Only one of `s` or `n` attributes is specified, not both. Most items are converted to number type for the most compact representation.
- Compared to the legacy format, data overhead is minimized by using short attribute names, number timestamps, and having only a single table.
- The `exp` attribute is used with the DynamoDB Time To Live (TTL) feature to automatically delete old data.
<!-- markdownlint-enable ul-style -->
#### Legacy schema
#### Legacy Schema
Configure the addon to use legacy schema by setting `tablePrefix` parameter.
Configure the add-on to use the legacy schema by setting the `tablePrefix` parameter.
<!-- markdownlint-disable ul-style -->
- When an item is persisted via this service, a table is created (if necessary).
@@ -184,8 +184,8 @@ Alternatively, instead of specifying `accessKey` and `secretKey`, one can config
| Property | Default | Required | Description |
| ------------------ | ------- | :------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| profilesConfigFile | | Yes | path to the credentials file. For example, `/etc/openhab2/aws_creds`. Please note that the user that runs openHAB must have approriate read rights to the credential file. For more details on the Amazon credential file format, see [Amazon documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html). |
| profile | | Yes | name of the profile to use |
| profilesConfigFile | | Yes | Path to the credentials file. For example, `/etc/openhab2/aws_creds`. Please note that the user that runs openHAB must have appropriate read rights to the credential file. For more details on the Amazon credential file format, see [Amazon documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html). |
| profile | | Yes | Name of the profile to use |
| region | | Yes | AWS region ID as described in Step 2 in [Setting up Amazon account](#setting-up-an-amazon-account). The region needs to match the region that was used to create the user. |
Example of service configuration file (`services/dynamodb.cfg`):
@@ -211,11 +211,11 @@ In addition to the configuration properties above, the following are also availa
| Property | Default | Required | Description |
| ------------------ | ------- | :------: | ----------------------------------------------------------- |
| expireDays | (null) | No | Expire time for data in days (relative to stored timestamp) |
| readCapacityUnits | 1 | No | read capacity for the created tables |
| writeCapacityUnits | 1 | No | write capacity for the created tables |
| readCapacityUnits | 1 | No | Read capacity for the created tables |
| writeCapacityUnits | 1 | No | Write capacity for the created tables |
Refer to Amazon documentation on [provisioned throughput](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ProvisionedThroughput.html) for details on read/write capacity.
In case you have not reserved enough capacity for write and/or read, you will notice error messages in openHAB logs.
Refer to the Amazon documentation on [provisioned throughput](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ProvisionedThroughput.html) for details on read/write capacity.
If you have not reserved enough capacity for write and/or read, you will notice error messages in the openHAB logs.
DynamoDB Time to Live (TTL) setting is configured using `expireDays`.
All item- and event-related configuration is done in the file `persistence/dynamodb.persist`.
@@ -234,24 +234,24 @@ Similar caveat applies for DynamoDB Time to Live (TTL) setting `expireDays`.
### Updating Amazon SDK
1. Update SDK version and `netty-nio-client` version in `scripts/fetch_sdk_pom.xml`. You can use the [maven online repository browser](https://mvnrepository.com/artifact/software.amazon.awssdk/dynamodb-enhanced) to find the latest version available online.
1. Update SDK version and `netty-nio-client` version in `scripts/fetch_sdk_pom.xml`. You can use the [Maven online repository browser](https://mvnrepository.com/artifact/software.amazon.awssdk/dynamodb-enhanced) to find the latest version available online.
1. `scripts/fetch_sdk.sh`
1. Copy printed dependencies to `pom.xml`. If necessary, adjust feature.xml, bnd.importpackage and dep.noembedding as well (probably rarely needed but [it happens](https://aws.amazon.com/blogs/developer/the-aws-sdk-for-java-2-17-removes-its-external-dependency-on-jackson/)).
1. Copy printed dependencies to `pom.xml`. If necessary, adjust `feature.xml`, `bnd.importpackage`, and `dep.noembedding` as well (probably rarely needed, but [it happens](https://aws.amazon.com/blogs/developer/the-aws-sdk-for-java-2-17-removes-its-external-dependency-on-jackson/)).
1. Check & update `NOTICE` file with all the updated, new and removed dependencies.
After these changes, it's good practice to run integration tests (against live AWS DynamoDB) in `org.openhab.persistence.dynamodb.test` bundle.
See README.md in the test bundle for more information how to execute the tests.
After these changes, it's good practice to run integration tests (against live AWS DynamoDB) in the `org.openhab.persistence.dynamodb.test` bundle.
See README.md in the test bundle for more information on how to execute the tests.
### Running integration tests
### Running Integration Tests
When running integration tests, local temporary DynamoDB server is used, emulating the real AWS DynamoDB API.
One can configure AWS credentials to run the test against real AWS DynamoDB for most realistic tests.
When running integration tests, a local temporary DynamoDB server is used, emulating the real AWS DynamoDB API.
One can configure AWS credentials to run the test against real AWS DynamoDB for the most realistic tests.
Eclipse instructions
Eclipse instructions:
1. Run all tests (in package org.openhab.persistence.dynamodb.internal) as JUnit Tests
1. Configure the run configuration, and open Arguments sheet
1. In VM arguments, provide the credentials for AWS
1. Run all tests (in package org.openhab.persistence.dynamodb.internal) as JUnit Tests.
1. Configure the run configuration and open the Arguments sheet.
1. In VM arguments, provide the credentials for AWS:
```bash
-DDYNAMODBTEST_REGION=REGION-ID
@@ -70,46 +70,46 @@
-->
<parameter name="region" type="text" required="true">
<label>AWS region ID</label>
<description><![CDATA[AWS region ID<br />
<label>AWS Region ID</label>
<description><![CDATA[AWS region ID.<br />
The region needs to match the region of the AWS user that will access Amazon DynamoDB.<br />
For example, eu-west-1.]]></description>
</parameter>
<parameter name="accessKey" type="text" required="false">
<label>AWS access key</label>
<description><![CDATA[AWS access key<br />
Give either 1) access key and secret key, or 2) credentials file and profile name.
<label>AWS Access Key</label>
<description><![CDATA[AWS access key.<br />
Provide either 1) access key and secret key, or 2) credentials file and profile name.
]]></description>
</parameter>
<parameter name="secretKey" type="text" required="false">
<label>AWS secret key</label>
<description><![CDATA[AWS secret key<br />
Give either 1) access key and secret key, or 2) credentials file and profile name.
<label>AWS Secret Key</label>
<description><![CDATA[AWS secret key.<br />
Provide either 1) access key and secret key, or 2) credentials file and profile name.
]]></description>
</parameter>
<parameter name="profilesConfigFile" type="text" required="false">
<label>AWS credentials file</label>
<description><![CDATA[Path to the AWS credentials file. <br />
For example, /etc/openhab/aws_creds. Please note that the user that runs openHAB must have approriate read rights to the credential file. <br />
Give either 1) access key and secret key, or 2) credentials file and profile name.
<label>AWS Credentials File</label>
<description><![CDATA[Path to the AWS credentials file.<br />
For example, /etc/openhab/aws_creds. Please note that the user that runs openHAB must have appropriate read rights to the credential file.<br />
Provide either 1) access key and secret key, or 2) credentials file and profile name.
]]></description>
</parameter>
<parameter name="profile" type="text" required="false">
<label>Profile name</label>
<description><![CDATA[Profile name in AWS credentials file. <br />
Give either 1) access key and secret key, or 2) credentials file and profile name.
<label>Profile Name</label>
<description><![CDATA[Profile name in AWS credentials file.<br />
Provide either 1) access key and secret key, or 2) credentials file and profile name.
]]></description>
</parameter>
<parameter name="table" type="text" required="false">
<label>Table</label>
<description><![CDATA[Table name. <br />
Specify this parameter over Table Prefix to use the new optimized table format.]]></description>
<description><![CDATA[Table name.<br />
Specify this parameter instead of Table Prefix to use the new optimized table format.]]></description>
<default>openhab</default> <!-- set by default, preferring new schema format -->
</parameter>
@@ -130,7 +130,7 @@
<parameter name="expireDays" type="integer" required="false" min="1">
<label>Data Expiry, in Days</label>
<description><![CDATA[Expire time for data.<br />
Data older than this is automatically removed by DynamoDB Time to Live (TTL) feature. Use empty value to disable data expiration.
Data older than this is automatically removed by the DynamoDB Time to Live (TTL) feature. Use an empty value to disable data expiration.
]]></description>
<advanced>true</advanced>
<default></default> <!-- empty by default, giving preference to new table schema -->
@@ -138,8 +138,8 @@
<parameter name="tablePrefix" type="text" required="false">
<label>Table Prefix</label>
<description><![CDATA[Legacy: Table prefix used in the name of created tables. <br />
Default is "openhab-"]]></description>
<description><![CDATA[Legacy: Table prefix used in the name of created tables.<br />
Default is "openhab-".]]></description>
<advanced>true</advanced>
<default></default> <!-- empty by default, giving preference to new table schema -->
</parameter>
@@ -3,25 +3,25 @@
addon.dynamodb.name = DynamoDB Persistence
addon.dynamodb.description = This is the persistence add-on for DynamoDB.
# add-on
# add-on config
persistence.config.dynamodb.accessKey.label = AWS access key
persistence.config.dynamodb.accessKey.description = AWS access key<br /> Give either 1) access key and secret key, or 2) credentials file and profile name.
persistence.config.dynamodb.accessKey.label = AWS Access Key
persistence.config.dynamodb.accessKey.description = AWS access key.<br /> Provide either 1) access key and secret key, or 2) credentials file and profile name.
persistence.config.dynamodb.expireDays.label = Data Expiry, in Days
persistence.config.dynamodb.expireDays.description = Expire time for data.<br /> Data older than this is automatically removed by DynamoDB Time to Live (TTL) feature. Use empty value to disable data expiration.
persistence.config.dynamodb.profile.label = Profile name
persistence.config.dynamodb.profile.description = Profile name in AWS credentials file. <br /> Give either 1) access key and secret key, or 2) credentials file and profile name.
persistence.config.dynamodb.profilesConfigFile.label = AWS credentials file
persistence.config.dynamodb.profilesConfigFile.description = Path to the AWS credentials file. <br /> For example, /etc/openhab/aws_creds. Please note that the user that runs openHAB must have approriate read rights to the credential file. <br /> Give either 1) access key and secret key, or 2) credentials file and profile name.
persistence.config.dynamodb.expireDays.description = Expire time for data.<br /> Data older than this is automatically removed by the DynamoDB Time to Live (TTL) feature. Use an empty value to disable data expiration.
persistence.config.dynamodb.profile.label = Profile Name
persistence.config.dynamodb.profile.description = Profile name in AWS credentials file.<br /> Provide either 1) access key and secret key, or 2) credentials file and profile name.
persistence.config.dynamodb.profilesConfigFile.label = AWS Credentials File
persistence.config.dynamodb.profilesConfigFile.description = Path to the AWS credentials file.<br /> For example, /etc/openhab/aws_creds. Please note that the user that runs openHAB must have appropriate read rights to the credential file.<br /> Provide either 1) access key and secret key, or 2) credentials file and profile name.
persistence.config.dynamodb.readCapacityUnits.label = Read Capacity
persistence.config.dynamodb.readCapacityUnits.description = Provisioned read capacity.<br /> Default is 1.
persistence.config.dynamodb.region.label = AWS region ID
persistence.config.dynamodb.region.description = AWS region ID<br /> The region needs to match the region of the AWS user that will access Amazon DynamoDB.<br /> For example, eu-west-1.
persistence.config.dynamodb.secretKey.label = AWS secret key
persistence.config.dynamodb.secretKey.description = AWS secret key<br /> Give either 1) access key and secret key, or 2) credentials file and profile name.
persistence.config.dynamodb.region.label = AWS Region ID
persistence.config.dynamodb.region.description = AWS region ID.<br /> The region needs to match the region of the AWS user that will access Amazon DynamoDB.<br /> For example, eu-west-1.
persistence.config.dynamodb.secretKey.label = AWS Secret Key
persistence.config.dynamodb.secretKey.description = AWS secret key.<br /> Provide either 1) access key and secret key, or 2) credentials file and profile name.
persistence.config.dynamodb.table.label = Table
persistence.config.dynamodb.table.description = Table name. <br /> Specify this parameter over Table Prefix to use the new optimized table format.
persistence.config.dynamodb.table.description = Table name.<br /> Specify this parameter instead of Table Prefix to use the new optimized table format.
persistence.config.dynamodb.tablePrefix.label = Table Prefix
persistence.config.dynamodb.tablePrefix.description = Legacy: Table prefix used in the name of created tables. <br /> Default is "openhab-"
persistence.config.dynamodb.tablePrefix.description = Legacy: Table prefix used in the name of created tables.<br /> Default is "openhab-".
persistence.config.dynamodb.writeCapacityUnits.label = Write Capacity
persistence.config.dynamodb.writeCapacityUnits.description = Provisioned write capacity.<br /> Default is 1.
@@ -1,22 +1,22 @@
# InfluxDB (0.9 and newer) Persistence
This service allows you to persist and query states using the [InfluxDB](https://www.influxdata.com/products/influxdb-overview/) and [InfluxDB 2.0](https://v2.docs.influxdata.com/v2.0/) time series database. The persisted values can be queried from within openHAB.
There also are nice tools on the web for visualizing InfluxDB time series, such as [Grafana](https://grafana.com/) and new Influx DB 2.0 version introduces [powerful data processing features.](https://docs.influxdata.com/influxdb/v2.0/process-data/get-started/)
There are also nice tools on the web for visualizing InfluxDB time series, such as [Grafana](https://grafana.com/), and the new InfluxDB 2.0 version introduces [powerful data processing features](https://docs.influxdata.com/influxdb/v2.0/process-data/get-started/).
## Database Structure
- This service allows you to persist and query states using the time series database.
- The states of an item are persisted in _measurements_ points with names equal to the name of the item, its alias, or from some metadata depending on the configuration. In all variants, a tag named "item" is added, containing the item name.
- The states of an item are persisted in _measurement_ points with names equal to the name of the item, its alias, or from some metadata depending on the configuration. In all variants, a tag named "item" is added, containing the item name.
All values are stored in a _field_ called "value" using the following types:
- **float** for DecimalType and QuantityType
- **integer** for `OnOffType` and `OpenClosedType` (values are stored using 0 or 1) and `DateTimeType` (milliseconds since 1970-01-01T00:00:00Z)
- **string** for the rest of types
- If configured, extra tags for item category, label or type can be added fore each point.
- **string** for the rest of the types
- If configured, extra tags for item category, label, or type can be added for each point.
Some example entries for an item with the name "speedtest" without any further configuration would look like this:
```flux
> Query using Influx DB 2.0 syntax for 1.0 is different
> Query using InfluxDB 2.0 syntax (syntax for 1.0 is different)
> from(bucket: "default")
|> range(start: -30d)
|> filter(fn: (r) => r._measurement == "speedtest")
@@ -30,9 +30,9 @@ Some example entries for an item with the name "speedtest" without any further c
## Prerequisites
First of all, you have to setup and run an InfluxDB 1.X or 2.X server.
This is very easy and you will find good documentation on it on the
[InfluxDB web site for 2.X version](https://v2.docs.influxdata.com/v2.0/get-started/) and [InfluxDB web site for 1.X version](https://docs.influxdata.com/influxdb/v1.7/).
First of all, you have to set up and run an InfluxDB 1.X or 2.X server.
This is very easy, and you will find good documentation on the
[InfluxDB website for the 2.X version](https://v2.docs.influxdata.com/v2.0/get-started/) and [InfluxDB website for the 1.X version](https://docs.influxdata.com/influxdb/v1.7/).
## Configuration
@@ -41,29 +41,29 @@ Attention: The file-based configuration overrides the UI configuration.
| Property | Default | Required | Description |
| --------------- | --------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| version | V1 | No | InfluxDB database version V1 for 1.X and V2 for 2.x |
| url | <http://127.0.0.1:8086> | No | database URL |
| user | openhab | No | name of the database user, e.g. `openhab` |
| password | | No(\*) | password of the database user you choose |
| token | | No(\*) | token to authenticate the database (only for V2) [Intructions about how to create one](https://v2.docs.influxdata.com/v2.0/security/tokens/create-token/) |
| db | openhab | No | name of the database for V1 and name of the organization for V2 |
| retentionPolicy | autogen | No | name of the retention policy for V1 and name of the bucket for V2 |
| version | V1 | No | InfluxDB database version: V1 for 1.X and V2 for 2.X |
| url | <http://127.0.0.1:8086> | No | Database URL |
| user | openhab | No | Name of the database user, e.g., `openhab` |
| password | | No(\*) | Password of the database user you choose |
| token | | No(\*) | Token to authenticate to the database (only for V2). [Instructions on how to create one](https://v2.docs.influxdata.com/v2.0/security/tokens/create-token/) |
| db | openhab | No | Name of the database for V1 and name of the organization for V2 |
| retentionPolicy | autogen | No | Name of the retention policy for V1 and name of the bucket for V2 |
(\*) For 1.X version you must provide user and password, for 2.X you can use user and password or a token. That means
that if you use all default values at minimum you must provide a password or a token.
(\*) For the 1.X version, you must provide user and password; for 2.X, you can use user and password or a token.
That means that if you use all default values, at minimum you must provide a password or a token.
All item- and event-related configuration is defined in the file `persistence/influxdb.persist`.
Please consider [persistence documentation](https://www.openhab.org/docs/configuration/persistence.html#persistence) for further information.
### Additional configuration for customized storage options in InfluxDB
By default, the plugin writes the data to a `measurement` name equals to the `item's name` and adds a tag with key item and value `item's name` as well.
You can customize that behavior and use a single measurement for several items using item metadata.
By default, the plugin writes the data to a `measurement` name equal to the `item's name` and adds a tag with key "item" and value `item's name` as well.
You can customize that behavior and use a single measurement for several items by using item metadata.
#### Measurement name by Item Metadata
#### Measurement Name by Item Metadata
By setting the `influxdb` metadata key you can change the name of the measurement by setting the desired name as metadata value.
You can also add additional tags for structuring your data. For example, you can add a floor tag to all sensors to filter all sensors from the first floor or combine all temperature sensors into one measurement.
By setting the `influxdb` metadata key, you can change the name of the measurement by setting the desired name as the metadata value.
You can also add additional tags for structuring your data. For example, you can add a floor tag to all sensors to filter all sensors from the first floor, or combine all temperature sensors into one measurement.
The item configuration will look like this:
@@ -77,9 +77,9 @@ Number:Temperature tempBedRoom (gTempSensors) { influxdb="temperature" [floor="f
Number:Temperature tempBath (gTempSensors) { influxdb="temperature" [floor="firstfloor"] }
```
You can also set the `influxdb` metadata using the UI. From each item configuration screen do:
You can also set the `influxdb` metadata using the UI. From each item configuration screen:
`Metadata``Add Metadata``Enter Custom Namespace` → Enter `influxdb` as namespace name → And enter your desired item name in value field. i.e.:
`Metadata``Add Metadata``Enter Custom Namespace` → Enter `influxdb` as namespace name → Enter your desired item name in the value field, e.g.:
```yaml
value: temperature
@@ -95,23 +95,23 @@ temperature,item=tempBedRoom,floor=firstfloor
temperature,item=tempBath,floor=firstfloor
```
You can now easily select all temperatures of the firstfloor or the average temperature of the groundfloor.
You can now easily select all temperatures of the first floor or the average temperature of the ground floor.
_Warning:_ Do **not** override the tag `item` within the metadata. This tag is used internally by openHAB and changing it will lead to problems querying the persisted datapoints.
_Warning:_ Do **not** override the tag `item` within the metadata. This tag is used internally by openHAB, and changing it will lead to problems querying the persisted data points.
#### Extended automatic tagging
#### Extended Automatic Tagging
Besides the metadata tags, there are additional configuration parameters to activate different automatic tags generation.
Besides the metadata tags, there are additional configuration parameters to activate different automatic tag generation.
| Property | Default | Required | Description |
| -------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------- |
| addCategoryTag | false | no | Should the category of the item be included as tag "category"? If no category is set, "n/a" is used. |
| addTypeTag | false | no | Should the item type be included as tag "type"? |
| addLabelTag | false | no | Should the item label be included as tag "label"? If no label is set, "n/a" is used. |
| addCategoryTag | false | No | Should the category of the item be included as tag "category"? If no category is set, "n/a" is used. |
| addTypeTag | false | No | Should the item type be included as tag "type"? |
| addLabelTag | false | No | Should the item label be included as tag "label"? If no label is set, "n/a" is used. |
### Connect to InfluxDB via TLS
InfluxDB supports TLS encryption to secure the communication with clients.
InfluxDB supports TLS encryption to secure communication with clients.
If you use a self-signed certificate for your InfluxDB instance (which is very likely), you need to add the certificate itself or your internal CA's certificate to the Java keystore:
@@ -55,28 +55,27 @@
<parameter name="token" type="text" required="false" groupName="connection">
<label>Authentication Token</label>
<description>The token to authenticate to database (alternative to username/password for InfluxDB 2.0)
<description>The token to authenticate to the database (alternative to username/password for InfluxDB 2.0).
</description>
</parameter>
<parameter name="db" type="text" required="true" groupName="connection">
<label>Database/Organization</label>
<description>The name of the database (InfluxDB 1.0) or Organization for (InfluxDB 2.0)</description>
<description>The name of the database (InfluxDB 1.0) or organization (InfluxDB 2.0).</description>
<default>openhab</default>
</parameter>
<parameter name="retentionPolicy" type="text" required="true" groupName="connection">
<label>Retention Policy / Bucket</label>
<description>The name of the retention policy (Influx DB 1.0) or bucket (InfluxDB 2.0) to write data
<label>Retention Policy/Bucket</label>
<description>The name of the retention policy (InfluxDB 1.0) or bucket (InfluxDB 2.0) to write data.
</description>
<default>autogen</default>
</parameter>
<parameter name="replaceUnderscore" type="boolean" required="true" groupName="misc">
<label>Replace Underscore</label>
<description>Whether underscores "_" in item names should be replaced by a dot "." ("test_item" ->
"test.item"). Only
for measurement name, not for tags. Also applies to alias names.
<description>Whether underscores "_" in item names should be replaced by a dot "." ("test_item" becomes "test.item").
Only applies to measurement names, not tags. Also applies to alias names.
</description>
<default>false</default>
</parameter>
@@ -3,7 +3,7 @@
addon.influxdb.name = InfluxDB Persistence
addon.influxdb.description = This is the persistence add-on for InfluxDB.
# add-on
# add-on config
persistence.config.influxdb.addCategoryTag.label = Add Category Tag
persistence.config.influxdb.addCategoryTag.description = Should the category of the item be included as tag "category"? If no category is set, "n/a" is used.
@@ -12,7 +12,7 @@ persistence.config.influxdb.addLabelTag.description = Should the item label be i
persistence.config.influxdb.addTypeTag.label = Add Type Tag
persistence.config.influxdb.addTypeTag.description = Should the item type be included as tag "type"?
persistence.config.influxdb.db.label = Database/Organization
persistence.config.influxdb.db.description = The name of the database (InfluxDB 1.0) or Organization for (InfluxDB 2.0)
persistence.config.influxdb.db.description = The name of the database (InfluxDB 1.0) or organization (InfluxDB 2.0).
persistence.config.influxdb.group.connection.label = Connection
persistence.config.influxdb.group.connection.description = This group defines connection parameters.
persistence.config.influxdb.group.misc.label = Miscellaneous
@@ -22,11 +22,11 @@ persistence.config.influxdb.group.tags.description = This group defines addition
persistence.config.influxdb.password.label = Database Password
persistence.config.influxdb.password.description = Database password
persistence.config.influxdb.replaceUnderscore.label = Replace Underscore
persistence.config.influxdb.replaceUnderscore.description = Whether underscores "_" in item names should be replaced by a dot "." ("test_item" -> "test.item"). Only for measurement name, not for tags. Also applies to alias names.
persistence.config.influxdb.retentionPolicy.label = Retention Policy / Bucket
persistence.config.influxdb.retentionPolicy.description = The name of the retention policy (Influx DB 1.0) or bucket (InfluxDB 2.0) to write data
persistence.config.influxdb.replaceUnderscore.description = Whether underscores "_" in item names should be replaced by a dot "." ("test_item" becomes "test.item"). Only applies to measurement names, not tags. Also applies to alias names.
persistence.config.influxdb.retentionPolicy.label = Retention Policy/Bucket
persistence.config.influxdb.retentionPolicy.description = The name of the retention policy (InfluxDB 1.0) or bucket (InfluxDB 2.0) to write data.
persistence.config.influxdb.token.label = Authentication Token
persistence.config.influxdb.token.description = The token to authenticate to database (alternative to username/password for InfluxDB 2.0)
persistence.config.influxdb.token.description = The token to authenticate to the database (alternative to username/password for InfluxDB 2.0).
persistence.config.influxdb.url.label = Database URL
persistence.config.influxdb.url.description = The database URL, e.g. http://127.0.0.1:8086
persistence.config.influxdb.user.label = Username
@@ -1,14 +1,14 @@
# InMemory Persistence
The InMemory persistence service provides a volatile storage, i.e. it is cleared on shutdown.
Because of that the `restoreOnStartup` strategy is not supported for this service.
The InMemory persistence service provides volatile storage, i.e., it is cleared on shutdown.
Because of that, the `restoreOnStartup` strategy is not supported for this service.
The main use-case is to store data that is needed during runtime, e.g. temporary storage of forecast data that is retrieved from a binding.
The main use case is to store data that is needed during runtime, e.g., temporary storage of forecast data that is retrieved from a binding.
The default strategy for this service is `forecast`.
Unlike other persistence services, you MUST add a configuration, otherwise no data will be persisted.
To avoid excessive memory usage, it is recommended to persist only a limited number of items and use a strategy that stores only data that is actually needed.
The service has a global configuration option `maxEntries` to limit the number of datapoints per item, the default value is `512`.
When the number of datapoints is reached and a new value is persisted, the oldest (by timestamp) value will be removed.
The service has a global configuration option `maxEntries` to limit the number of data points per item; the default value is `512`.
When the number of data points is reached and a new value is persisted, the oldest (by timestamp) value will be removed.
A `maxEntries` value of `0` disables automatic purging.
+13 -13
View File
@@ -108,7 +108,7 @@ user=openhab
password=openhab_password
```
The `TNS_ADMIN` parameter points to the directory where the the `tnsnames.ora`file, `ojdbc.properties` file and key files (from the ADB wallet download) are located.
The `TNS_ADMIN` parameter points to the directory where the `tnsnames.ora` file, `ojdbc.properties` file and key files (from the ADB wallet download) are located.
Other Oracle DB setups may require different connection parameters.
It is advised to create a specific user with sufficient permissions and space for openHAB persistence.
@@ -159,7 +159,7 @@ tableUseRealItemNames=false
tableIdDigitCount=0
```
Remember to install and uninstall the services you want, and rename `persistence/mysql.persist` to `persistence/jdbc.persist`.
Remember to install and uninstall the services you want and rename `persistence/mysql.persist` to `persistence/jdbc.persist`.
## Technical Notes
@@ -179,16 +179,16 @@ If this is changed, the table must be renamed manually according to new configur
### Number Precision
Default openHAB number items are persisted with SQL datatype `double`.
Internally openHAB uses `BigDecimal`.
If better numerical precision is needed, for example set `sqltype.NUMBER = DECIMAL(max digits, max decimals)`, then on the Java side, the service works with `BigDecimal` without type conversion.
If more come decimals as `max decimals` provides, this persisted value is rounded mathematically correctly.
Default openHAB number items are persisted with SQL data type `double`.
Internally, openHAB uses `BigDecimal`.
If better numerical precision is needed, for example, set `sqltype.NUMBER = DECIMAL(max digits, max decimals)`, then on the Java side, the service works with `BigDecimal` without type conversion.
If more decimals come than `max decimals` provides, this persisted value is rounded mathematically correctly.
The SQL types `DECIMAL` or `NUMERIC` are precise, but to work with `DOUBLE` is faster.
### Rounding results
The results of database queries of number items are rounded to three decimal places by default.
With `numberDecimalcount` decimals can be changed.
With `numberDecimalcount`, decimals can be changed.
Especially if sql types `DECIMAL` or `NUMERIC` are used for `sqltype.NUMBER`, rounding can be disabled by setting `numberDecimalcount=-1`.
### Maintenance
@@ -198,7 +198,7 @@ Some maintenance tools are provided as console commands.
#### List Tables
Tables and corresponding items can be listed with the command `jdbc tables list`.
Per default only tables with some kind of problem are listed.
By default, only tables with some kind of problem are listed.
To list all tables, use the command `jdbc tables list all`.
The list contains table name, item name, row count and status, which can be one of:
@@ -259,10 +259,10 @@ Use the command `jdbc schema check` to perform an integrity check of the schema.
Identified issues can be fixed automatically using the command `jdbc schema fix` (all items having issues) or `jdbc schema fix <itemName>` (single item).
Issues than can be identified and possibly fixed:
Issues that can be identified and possibly fixed:
- Wrong column name case (`time` and `name`).
- Wrong column type. Before fixing this, make sure that time-zone is correctly configured.
- Wrong column type. Before fixing this, make sure that time zone is correctly configured.
- Unexpected column (identify only).
### For Developers
@@ -284,9 +284,9 @@ Not necessarily representative of the performance you may experience.
| postgresql | 8.147 | 7.072 | 6.895 | - | ext. Server VM |
| sqlite | 2.406 | 1.249 | 1.137 | 0.28 MB | local embedded |
- Each test ran about 20 Times every 30 seconds.
- openHAB 1.x has ready started for about a Minute.
- the data in seconds for the evaluation are from the console output.
- Each test ran about 20 times every 30 seconds.
- openHAB 1.x had already started for about a minute.
- The data in seconds for the evaluation are from the console output.
Used a script like this:
@@ -14,7 +14,7 @@
jdbc:oracle
#
# derby, h2, hsqldb, sqlite can be embedded,
# If no database is available it will be created, for example the url 'jdbc:h2:./testH2' creates a new DB in OpenHab Folder.
# If no database is available it will be created, for example the url 'jdbc:h2:./testH2' creates a new DB in openHAB folder.
#
# Create new database, for example on a MySQL-Server use:
# CREATE DATABASE 'yourDB' CHARACTER SET utf8 COLLATE utf8_general_ci;
@@ -163,17 +163,17 @@
-->
<parameter name="itemsManageTable" type="text">
<label>Items Manage Table</label>
<description><![CDATA[Items Manage Table <br>(optional, default: "items"). <br>
For migration from MYSQL-Bundle set to 'Items'.]]></description>
<description><![CDATA[Items manage table <br>(optional, default: "items"). <br>
For migration from MySQL bundle set to 'Items'.]]></description>
</parameter>
<parameter name="tableNamePrefix" type="text">
<label>Tablename Prefix String</label>
<description><![CDATA[Tablename prefix string <br>(optional, default: "item"). <br>
For migration from MYSQL-Bundle set to 'Item'.]]></description>
For migration from MySQL bundle set to 'Item'.]]></description>
</parameter>
<parameter name="tableUseRealItemNames" type="text">
<label>Tablename Realname Generation</label>
<description><![CDATA[Enables Tablename prefix generation per Items realname <br>(optional, default: disabled -> "Tablename Prefix String" is used). <br>
<description><![CDATA[Enables tablename prefix generation per items realname <br>(optional, default: disabled -> "Tablename Prefix String" is used). <br>
If true, 'Tablename Prefix String' is ignored.]]></description>
<options>
<option value="true">Enable</option>
@@ -182,8 +182,8 @@
</parameter>
<parameter name="tableCaseSensitiveItemNames" type="text">
<label>Tablename Case Sensitive</label>
<description><![CDATA[Enables Tablename generation with case sensitive item names case when "Tablename Realname Generation" is enabled <br>
If true, no suffix is used. (optional, default: disabled -> table names are lower cased with numeric suffix appended).]]></description>
<description><![CDATA[Enables tablename generation with case-sensitive item names when "Tablename Realname Generation" is enabled <br>
If true, no suffix is used. (optional, default: disabled -> table names are lowercased with numeric suffix appended).]]></description>
<options>
<option value="true">Enable</option>
<option value="false">Disable</option>
@@ -191,8 +191,8 @@
</parameter>
<parameter name="tableIdDigitCount" type="text">
<label>Tablename Suffix ID Count</label>
<description><![CDATA[Tablename Suffix ID Count <br>(optional, default: 4 -> 0001-9999). <br>
For migration from MYSQL-Bundle set to 0.]]></description>
<description><![CDATA[Tablename suffix ID count <br>(optional, default: 4 -> 0001-9999). <br>
For migration from MySQL bundle set to 0.]]></description>
</parameter>
<parameter name="rebuildTableNames" type="text">
<label>Tablename Rebuild</label>
@@ -207,7 +207,7 @@
<!--
# D A T A B A S E C O N N E C T I O N S
# Some embeded Databases can handle only one Connection (optional, default: configured per database in packet org.openhab.persistence.jdbc.db.*
# Some embedded databases can handle only one connection (optional, default: configured per database in packet org.openhab.persistence.jdbc.db.*
)
# see: https://github.com/brettwooldridge/HikariCP/issues/256
# maximumPoolSize = 1
@@ -231,7 +231,7 @@
-->
<parameter name="enableLogTime" type="text">
<label>Timekeeping Enable</label>
<description><![CDATA[Enables a time, performance measurement. <br>(optional, default: disabled)]]></description>
<description><![CDATA[Enables a time/performance measurement. <br>(optional, default: disabled)]]></description>
<options>
<option value="true">Enable</option>
<option value="false">Disable</option>
+14 -16
View File
@@ -1,15 +1,15 @@
# Java Persistence API (JPA) Persistence
This service allows you to persist state updates using a SQL or NoSQL database through the [Java Persistence API](https://en.wikipedia.org/wiki/Java_Persistence_API).
The service uses an abstraction layer that theoretically allows it to support many available SQL or NoSQL databases.
This service allows you to persist state updates using an SQL or NoSQL database through the [Java Persistence API](https://en.wikipedia.org/wiki/Java_Persistence_API).
The service uses an abstraction layer that allows it to support many available SQL or NoSQL databases.
It will create one table named `historic_item` where all item states are stored.
It creates a table named `historic_item` where all item states are stored.
The item state is stored in a string representation.
The service currently supports Apache Derby, MariaDB, MySQL and PostgreSQL databases.
The service currently supports Apache Derby, MariaDB, MySQL, and PostgreSQL databases.
Only the embedded Apache Derby database driver is included.
Other drivers must be installed manually.
(See below for more information on that.)
Drivers for other databases must be installed manually.
See below for details.
## Configuration
@@ -17,27 +17,25 @@ This service can be configured in the file `services/jpa.cfg`.
| Property | Default | Required | Description |
| ------------ | ------- | :-------: | ------------------------------------------------------------ |
| url | | Yes | JDBC connection URL. Examples:<br/><br/>`jdbc:derby://hab.local:1527/openhab;create=true`<br/>`jdbc:mariadb://localhost:3306/openhab`<br/>`jdbc:mysql://localhost:3306/openhab`<br/>`jdbc:postgresql://hab.local:5432/openhab` |
| driver | | Yes | database driver. Examples:<br/><br/>`com.mysql.jdbc.Driver`<br/>`org.apache.derby.jdbc.ClientDriver`<br/>`org.mariadb.jdbc.Driver`<br/>`org.postgresql.Driver`<br/></br>Only the Apache Derby driver is included with the service. Drivers for other databases must be installed manually. This is a trivial process. Normally JDBC database drivers are packaged as OSGi bundles and can just be dropped into the `addons` folder. This has the advantage that users can update their drivers as needed. The following database drivers are known to work:<br/><br/>`postgresql-9.4-1203-jdbc41.jar`<br/>`postgresql-9.4-1206-jdbc41.jar` |
| user | | if needed | database user name for connection |
| password | | if needed | database user password for connection |
| url | | Yes | JDBC connection URL. Examples:<br/><br/>`jdbc:derby://hab.local:1527/openhab;create=true`<br/>`jdbc:mariadb://localhost:3306/openhab`<br/>`jdbc:mysql://localhost:3306/openhab`<br/>`jdbc:postgresql://hab.local:5432/openhab` |
| driver | | Yes | Database driver. Examples:<br/><br/>`com.mysql.jdbc.Driver`<br/>`org.apache.derby.jdbc.ClientDriver`<br/>`org.mariadb.jdbc.Driver`<br/>`org.postgresql.Driver`<br/><br/>Only the Apache Derby driver is included with the service. Drivers for other databases must be installed manually. Normally, JDBC database drivers are packaged as OSGi bundles and can be dropped into the `addons` folder. This has the advantage that users can update their drivers as needed. The following database drivers are known to work:<br/><br/>`postgresql-9.4-1203-jdbc41.jar`<br/>`postgresql-9.4-1206-jdbc41.jar` |
| user | | if needed | Database user name for connection |
| password | | if needed | Database user password for connection |
| syncmappings | | if needed | The OpenJPA synchronize mappings configuration |
## Adding support for other JPA supported databases
## Adding support for other JPA-supported databases
All item- and event-related configuration is done in the file `persistence/jpa.persist`.
If a database driver is not an OSGi bundle, the technique below can be used to extend the openHAB classpath.
If a database driver is not provided as an OSGi bundle, the technique below can be used to extend the openHAB classpath.
Other database drivers can be added by expanding the openHAB classpath.
Use the following classpath setup in start.sh / start_debug.sh of openHAB:
Use the following classpath setup in `start.sh` or `start_debug.sh` of openHAB:
```bash
cp=$(echo lib/*.jar | tr ' ' ':'):$(find $eclipsehome -name "org.eclipse.equinox.launcher_*.jar" | sort | tail -1);
```
This will add all .jar files in a folder "lib" in the root of openhab.
This will add all `.jar` files in a folder `lib` in the root of openHAB.
All databases that are supported by JPA can be added.
@@ -11,9 +11,9 @@ This service can be configured in the file `services/mongodb.cfg`.
| ---------- | ------- | :------: | ---------------------------------------------------------------------------- |
| url | | Yes | connection URL to address MongoDB. For example, `mongodb://localhost:27017` |
| database | | Yes | database name |
| collection | | Yes | set collection to "" if it shall generate a collection per item |
| collection | | Yes | Set collection to "" if it shall generate a collection per item |
If you have a username and password it looks like this: url = mongodb://[username]:[password]@[localhost]:27017/[database]
If you have a username and password, it looks like this: url = mongodb://[username]:[password]@[localhost]:27017/[database]
The database is required: <https://mongodb.github.io/mongo-java-driver/3.9/javadoc/com/mongodb/MongoClientURI.html>
All item and event related configuration is done in the file `persistence/mongodb.persist`.
+27 -27
View File
@@ -1,33 +1,33 @@
# rrd4j Persistence
# RRD4J Persistence
The [rrd4j](https://github.com/rrd4j/rrd4j) persistence service is based on a round-robin database.
In contrast to a "normal" database such as db4o, a round-robin database does not grow in size - it has a fixed allocated size.
This is accomplished by saving a fixed amount of datapoints and by doing data compression, which means that the older the data is, the less values are available.
This is accomplished by saving a fixed amount of data points and by doing data compression, which means that the older the data is, the fewer values are available.
The data is kept in several "archives", each holding the data for its set timeframe at a defined level of granularity.
The starting point for all archives is the actually saved data sample (Item value).
The starting point for all archives is the actual saved data sample (Item value).
So while you might store a sample value every minute for the last 8 hours, you might store the average per day for the last year.
This service cannot be directly queried, because of its data compression, which means that it cannot provide precise answers to all queries.
This service cannot be queried directly due to its data compression and cannot provide precise answers to all queries.
NOTE: rrd4j is for storing numerical data only.
NOTE: RRD4J is for storing numeric data only.
It cannot store complex data types.
The supported item types are therefore only `Switch` (internally mapped to 0/1), `Dimmer`, `Number`, `Contact` (internally mapped to 0/1), `Rollershutter` and `Color` (only brightness component stored).
## Configuration
The rrd4j persistence services comes with a default persistence strategy which persists every Item on every state change and at least once a minute.
The RRD4J persistence service comes with a default persistence strategy which persists every Item on every state change and at least once a minute.
Additionally, it restores the last stored value at system startup.
If you want to define a custom behavior, you will need to create a `rrd4j.persist` file in the `persistence` configuration folder.
## Persistence Process
Round-robin databases (RRDs) have fixed length so called "archives" for storing values.
Round-robin databases (RRDs) have fixed-length, so-called "archives" for storing values.
Think of an archive as a "drawer" with a fixed number of "storage boxes" in it.
The persistence service reads data "samples" from the openHAB core at regular intervals, and these are then put into the storage boxes.
Either a) the samples are stored singly directly into a box, or b) multiple samples are consolidated (using a consolidation function) into a box.
Either the samples are stored directly into a box, or multiple samples are consolidated (using a consolidation function) into a box.
The service starts by storing samples in the leftmost box in the drawer.
Once the leftmost box is full, the service starts filling the next box to the right; and so on.
@@ -55,7 +55,7 @@ The various datasource property values are explained in the table below.
| `<dsName>`.archives | List of archives to be created. Each archive defines which subset of data samples shall be archived, and for how long. Consists of one or more archive entries separated by a ":" character. The format for one archive entry is `<consolidationFunction>,<xff>,<samplesPerBox>,<boxCount>` |
| `<dsName>`.items | List of Items whose values shall be sampled and stored in the archive. The format is `Item1,Item2` _**Note: the same Item is not allowed to be listed in more than one datasource!**_ |
For example..
For example:
```ini
ctr24h.def=COUNTER,900,0,U,60
@@ -75,19 +75,19 @@ It must be an alphanumeric string.
Defines the type of data to be stored.
It must be one of the following string values:
- **COUNTER** represents an ever-incrementing value (historically this was used for packet counters or traffic counters on network interfaces, a typical home-automation application would be your electricity meter). If you store the values of this counter in a simple database and make a chart of that, you'll most likely see a nearly flat line, because the increments per time are small compared to the absolute value (e.g. your electricity meter reads 60567 kWh, and you add 0.5 kWh per hour, than your chart over the whole day will show 60567 at the start and 60579 at the end of your chart. That is nearly invisible. RRD4J helps you out and will display the difference from one stored value to the other (depending on the selected size). Please note that the persistence extensions will return difference instead of the actual values if you use this type; this especially leads to wrong values if you try to restoreOnStartup!
- **GAUGE** represents the reading of e.g. a temperature sensor. You'll see only small deviation over the day and your values will be within a small range, clearly visible within a chart.
- **COUNTER** represents an ever-incrementing value (historically this was used for packet counters or traffic counters on network interfaces; a typical home-automation application would be your electricity meter). If you store the values of this counter in a simple database and make a chart of that, you'll most likely see a nearly flat line, because the increments per time are small compared to the absolute value (e.g., your electricity meter reads 60567 kWh, and you add 0.5 kWh per hour, then your chart over the whole day will show 60567 at the start and 60579 at the end of your chart. That is nearly invisible). RRD4J helps you out and will display the difference from one stored value to the next (depending on the selected granularity). Please note that the persistence extensions will return the difference instead of the actual values if you use this type; this can especially lead to wrong values if you try to restoreOnStartup!
- **GAUGE** represents the reading of, e.g., a temperature sensor. You'll see only small deviations over the day, and your values will be within a small range, clearly visible in a chart.
- **ABSOLUTE** is like a counter, but RRD4J assumes that the counter is reset when the value is read. So these are basically the delta values between the reads.
- **DERIVE** is like a counter, but it can also decrease and therefore have a negative delta.
### `<heartBeat>` (Heart Beat)
### `<heartBeat>` (Heartbeat)
The heartbeat parameter helps the database to detect missing values.
i.e. if no new sample is stored after "heartBeat" seconds, the value is considered missing when charting.
It must be a positive integer value.
### `<minValue> / <maxValue>` (Minimum resp. Maximum Value)
### `<minValue> / <maxValue>` (Minimum and Maximum Value)
These parameters define the range of acceptable sample values for that datasource.
They must be either:
@@ -101,8 +101,8 @@ The time interval (seconds) between reading consecutive samples from the openHAB
It must be a positive integer value.
Relation between the sample intervall and openHABs persistence strategy.
The persistence strategy determines on which events (time, change, startUp) a new value is provided to the persistence service, the sample intervall determines at which time steps the actually provided value is being read (i.e an everyMinute strategy provides a new value at every full minute, a sample intervall of 10 seconds would use such a provided value 6 times).
Relation between the sample interval and openHAB's persistence strategy:
The persistence strategy determines on which events (time, change, startup) a new value is provided to the persistence service; the sample interval determines at which time steps the provided value is read (i.e., an everyMinute strategy provides a new value at every full minute; a sample interval of 10 seconds would use such a provided value six times).
### `<consolidationFunction>` (Consolidation Function)
@@ -144,9 +144,9 @@ It must be a positive integer value.
### Multiple Possible Archives
As already said, each datasource can have one or more archives.
The purpose of having several archives is that it allows a different granularity of data storage over different timespans.
The purpose of having several archives is that it allows a different granularity of data storage over different time spans.
In the example below..
In the example below:
```ini
ctr24h.def=COUNTER,900,0,U,60
@@ -154,9 +154,9 @@ ctr24h.archives=AVERAGE,0.5,1,480:AVERAGE,0.5,10,144
ctr24h.items=Item1,Item2
```
The `ctr24.def` defines a datasource which is using a COUNTER, a `<hearBeat>` of 900 seconds, a `<minValue>` of 0, a `<maxValue>` of unlimited and a `<sampleInterval>` of 60 seconds.
The `ctr24h.def` defines a datasource that uses a COUNTER, a `<heartBeat>` of 900 seconds, a `<minValue>` of 0, a `<maxValue>` of unlimited, and a `<sampleInterval>` of 60 seconds.
The first archive entry in the `ctr24.archives` parameter has `480` boxes each containing `1` sample (or to be exact the `AVERAGE` of `1` sample).
The first archive entry in the `ctr24h.archives` parameter has `480` boxes, each containing `1` sample (or to be exact the `AVERAGE` of `1` sample).
So it covers `480 X 60` seconds of data (8 hours) at a granularity of one minute.
As a general rule the first archive (and maybe the only one) should have `<samplesPerBox> = 1` so that each sample is stored in one box.
@@ -168,19 +168,19 @@ So it covers `144 X 10 X 60` seconds of data (24 hours) at a granularity of ten
The service automatically creates three default datasources with the properties below.
There is no `.items` parameter for the default datasources.
This means that any Item with an allocated strategy in the `rrd4j.persist` file is persisted using one the default settings, unless the Item is explicitly listed in an `.items` property value of a datasource in the `rrd4j.cfg` file.
This means that any Item with an allocated strategy in the `rrd4j.persist` file is persisted using one of the default settings, unless the Item is explicitly listed in an `.items` property value of a datasource in the `rrd4j.cfg` file.
### default_numeric
This datasource is used for plain `Number` items.
It does not build averages over values, so that it is ensured that discrete values are kept when being read (e.g. an Item which has only states 0 and 1 will not be set to 0.5).
It does not build averages over values, ensuring that discrete values are preserved when read (e.g., an Item which has only states 0 and 1 will not be set to 0.5).
```ini
default_numeric.def=GAUGE,600,U,U,10
default_numeric.archives=LAST,0.5,1,360:LAST,0.5,6,10080:LAST,0.5,90,36500:LAST,0.5,360,43800:LAST,0.5,8640,3650
```
It uses 10 seconds as a step size for numeric values and allows a 10 minute silence between updates.
It uses 10 seconds as a step size for numeric values and allows a 10-minute silence between updates.
It defines 5 archives:
@@ -200,7 +200,7 @@ default_quantifiable.def=GAUGE,600,U,U,10
default_quantifiable.archives=AVERAGE,0.5,1,360:AVERAGE,0.5,6,10080:AVERAGE,0.5,90,36500:AVERAGE,0.5,360,43800:AVERAGE,0.5,8640,3650
```
It uses 10 seconds as a step size for numeric values and allows a 10 minute silence between updates.
It uses 10 seconds as a step size for numeric values and allows a 10-minute silence between updates.
It defines 5 archives:
@@ -213,14 +213,14 @@ It defines 5 archives:
### default_other
This datasource is used for any other items.
Their values are considered to be discrete, similar to the `default_numeric` datasource, but it keeps the data in more fine-granular archives.
Their values are considered to be discrete, similar to the `default_numeric` datasource, but it keeps the data in more fine-grained archives.
```ini
default_other.def=GAUGE,3600,U,U,5
default_other.archives=LAST,0.5,1,720:LAST,0.5,12,10080:LAST,0.5,180,35040:LAST,0.5,2880,21900
```
It uses 5 seconds as a step size for discrete values and allows a 1h silence between updates.
It uses 5 seconds as a step size for discrete values and allows a 1-hour silence between updates.
It defines 4 archives:
@@ -261,6 +261,6 @@ When creating a custom datasource in the `rrd4j.cfg` file the used [sample inter
## Troubleshooting
From time to time, you may find that if you change the Item type of a persisted data point, you may experience charting or other problems. To resolve this issue, remove the old `<item_name>`.rrd file in the `${openhab_home}/userdata/persistence/rrd4j` folder or `/var/lib/openhab/persistence/rrd4j` folder for apt-get installed openHABs.
From time to time, you may find that if you change the Item type of a persisted data point, you may experience charting or other problems. To resolve this issue, remove the old `<item_name>`.rrd file in the `${openhab_home}/userdata/persistence/rrd4j` folder or in `/var/lib/openhab/persistence/rrd4j` for APT installations of openHAB.
Restoring Item values after startup takes some time. Rules may already have started to run in parallel. Especially in rules that are started via the "System started" trigger, it may happen that the restore has not yet completed resulting in non-defined Item values. In these cases the use of restored Item values should be delayed by a couple of seconds. This delay has to be determined experimentally.
Restoring Item values after startup takes some time. Rules may already have started to run in parallel. Especially in rules that are started via the "System started" trigger, it may happen that the restore has not yet completed, resulting in undefined Item values. In these cases the use of restored Item values should be delayed by a couple of seconds. This delay has to be determined experimentally.
@@ -1,31 +1,31 @@
# Basic Profiles
This bundle provides a list of useful Profiles:
This bundle provides a list of useful profiles:
| Profile | Description |
| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| [Generic Command Profile](#generic-command-profile) | Sends a Command towards the Item when an event is triggered |
| [Generic Toggle Switch Profile](#generic-toggle-switch-profile) | Toggles a Switch Item when an event is triggered |
| [Debounce (Counting) Profile](#debounce-counting-profile) | Counts and skip a number of State changes |
| [Debounce (Time) Profile](#debounce-time-profile) | Reduces the frequency of commands/state updates |
| [Invert / Negate Profile](#invert-negate-profile) | Inverts or negate a Command / State |
| [Round Profile](#round-profile) | Reduces the number of decimal places from input data |
| [Threshold Profile](#threshold-profile) | Translates numeric input data to `ON` or `OFF` based on a threshold value |
| [Time Range Command Profile](#time-range-command-profile) | An enhanced implementation of a follow profile which converts `OnOffType` to a `PercentType` |
| [State Filter Profile](#state-filter-profile) | Filters input data using arithmetic comparison conditions |
| [Inactivity Profile](#inactivity-profile) | Sets the linked Item On or Off depending whether the Channel has recently produced data |
| [Time-weighted Average Profile](#time-weighted-average-profile) | Collects updates for given duration to calculate time-weighted average value |
| Profile | Description |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| [Generic Command Profile](#generic-command-profile) | Sends a command to the Item when an event is triggered |
| [Generic Toggle Switch Profile](#generic-toggle-switch-profile) | Toggles a Switch Item when an event is triggered |
| [Debounce (Counting) Profile](#debounce-counting-profile) | Counts and skips a number of state changes |
| [Debounce (Time) Profile](#debounce-time-profile) | Reduces the frequency of commands or state updates |
| [Invert / Negate Profile](#invert-negate-profile) | Inverts or negates a command or state |
| [Round Profile](#round-profile) | Reduces the number of decimal places from input data |
| [Threshold Profile](#threshold-profile) | Translates numeric input data to `ON` or `OFF` based on a threshold value |
| [Time Range Command Profile](#time-range-command-profile) | An enhanced implementation of a follow profile which converts `OnOffType` to a `PercentType` |
| [State Filter Profile](#state-filter-profile) | Filters input data using arithmetic comparison conditions |
| [Inactivity Profile](#inactivity-profile) | Sets the linked Item to ON or OFF depending on whether the channel has recently produced data |
| [Time-weighted Average Profile](#time-weighted-average-profile) | Collects updates for given duration to calculate time-weighted average value |
## Generic Command Profile
This Profile can be used to send a Command towards the Item when one event of a specified event list is triggered.
The given Command value is parsed either to `IncreaseDecreaseType`, `NextPreviousType`, `OnOffType`, `PlayPauseType`, `RewindFastforwardType`, `StopMoveType`, `UpDownType` or a `StringType` is used.
This profile can be used to send a command to the Item when one event from a specified event list is triggered.
The given command value is parsed to one of `IncreaseDecreaseType`, `NextPreviousType`, `OnOffType`, `PlayPauseType`, `RewindFastforwardType`, `StopMoveType`, or `UpDownType`; otherwise, a `StringType` is used.
### Generic Command Profile Configuration
| Configuration Parameter | Type | Description |
|-------------------------|------|----------------------------------------------------------------------------------|
| `events` | text | Comma separated list of events to which the profile should listen. **mandatory** |
| `events` | text | Comma-separated list of events to which the profile should listen. **mandatory** |
| `command` | text | Command which should be sent if the event is triggered. **mandatory** |
### Generic Command Profile Example
@@ -39,13 +39,13 @@ Switch lightsStatus {
## Generic Toggle Switch Profile
The Generic Toggle Switch Profile is a specialization of the Generic Command Profile and toggles the State of a Switch Item whenever one of the specified events is triggered.
The Generic Toggle Switch Profile is a specialization of the Generic Command Profile and toggles the state of a Switch Item whenever one of the specified events is triggered.
### Generic Toggle Switch Profile Configuration
| Configuration Parameter | Type | Description |
|-------------------------|------|----------------------------------------------------------------------------------|
| `events` | text | Comma separated list of events to which the profile should listen. **mandatory** |
| `events` | text | Comma-separated list of events to which the profile should listen. **mandatory** |
### Generic Toggle Switch Profile Example
@@ -58,8 +58,8 @@ Switch lightsStatus {
## Debounce (Counting) Profile
This Profile counts and skips a user-defined number of State changes before it sends an update to the Item.
It can be used to debounce Item States.
This profile counts and skips a user-defined number of state changes before it sends an update to the Item.
It can be used to debounce Item states.
### Debounce (Counting) Profile Configuration
@@ -75,10 +75,10 @@ Switch debouncedSwitch { channel="xxx" [profile="basic-profiles:debounce-countin
## Debounce (Time) Profile
In `LAST` mode this profile delays commands or state updates for a configured number of milliseconds and only send the value if no other value is received with that timespan.
In `LAST` mode this profile delays commands or state updates for a configured number of milliseconds and only sends the value if no other value is received within that time span.
In `FIRST` mode this profile discards values for the configured time after a value is sent.
It can be used to debounce Item States/Commands or prevent excessive load on networks.
It can be used to debounce Item states/commands or prevent excessive load on networks.
### Debounce (Time) Profile Configuration
@@ -96,10 +96,10 @@ Number:Temperature debouncedSetpoint { channel="xxx" [profile="basic-profiles:de
## Invert / Negate Profile<a id="invert-negate-profile"></a>
The Invert / Negate Profile inverts or negates a Command / State.
The Invert / Negate Profile inverts or negates a command or state.
It requires no specific configuration.
The values of `QuantityType`, `PercentType` and `DecimalTypes` are negated (multiplied by `-1`).
The values of `QuantityType`, `PercentType`, and `DecimalType` are negated (multiplied by `-1`).
Otherwise the following mapping is used:
| Type | Inversion |
@@ -121,9 +121,9 @@ Switch invertedSwitch { channel="xxx" [profile="basic-profiles:invert"] }
## Round Profile
The Round Profile scales the State to a specific number of decimal places based on the power of ten.
The Round Profile scales the state to a specific number of decimal places based on the power of ten.
Optionally the [Rounding mode](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/math/RoundingMode.html) can be set.
Source Channels should accept Item Type `Number`.
Source channels should accept Item type `Number`.
### Round Profile Configuration
@@ -141,7 +141,7 @@ Number:Temperature roundedTemperature { channel="xxx" [profile="basic-profiles:r
## Threshold Profile
The Threshold Profile triggers `ON` or `OFF` behavior when being linked to a Switch item if value is below a given threshold (default: 10).
The Threshold Profile triggers `ON` or `OFF` behavior when linked to a Switch Item if the value is below a given threshold (default: 10).
A good use case for this Profile is a battery low indication.
Source Channels should accept Item Type `Dimmer` or `Number`.
@@ -165,7 +165,7 @@ Switch thresholdItem { channel="xxx" [profile="basic-profiles:threshold", thresh
This is an enhanced implementation of a follow profile which converts `OnOffType` to a `PercentType`.
The value of the percent type can be different between a specific time of the day.
A possible use-case is switching lights (using a presence detector) with different intensities at day and at night.
A possible use case is switching lights (using a presence detector) with different intensities during the day and at night.
Be aware: a range beyond midnight (e.g. start="23:00", end="01:00") is not yet supported.
### Time Range Profile Configuration
@@ -196,20 +196,20 @@ Switch motionSensorFirstFloor {
## State Filter Profile
This filter passes on state updates from the (binding) handler to the item if and only if all listed conditions are met (conditions are ANDed together).
This filter passes on state updates from the (binding) handler to the Item if and only if all listed conditions are met (conditions are ANDed together).
In case the conditions are not met, a fixed predefined state can be passed to the item instead of ignoring the update.
Use cases:
- Ignore values from the binding unless some other item(s) have a specific state.
- Ignore values from the binding unless some other Item(s) have a specific state.
- Filter out invalid values from the binding.
### State Filter Configuration
| Configuration Parameter | Type | Description |
| ----------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `conditions` | text | A list of conditions to check before posting an update from the binding to the item. When all the conditions are met, the update from the binding is passed to the item. |
| `mismatchState` | text | What to pass to the item when `conditions` aren't met. Use single quotes to treat as `StringType`. When undefined (the default), updates from the binding are ignored. |
| `conditions` | text | A list of conditions to check before posting an update from the binding to the Item. When all the conditions are met, the update from the binding is passed to the Item. |
| `mismatchState` | text | What to pass to the Item when `conditions` aren't met. Use single quotes to treat as `StringType`. When undefined (the default), updates from the binding are ignored. |
| `separator` | text | Optional separator string to separate multiple expressions. Defaults to `,`. |
#### State Filter Conditions
@@ -246,17 +246,17 @@ The `LHS_OPERAND` and the `RHS_OPERAND` can be either one of these:
This can be customized by specifying the "window size" or sample count applicable to the function, e.g. `$MEDIAN(10)` will return the median of the last 10 values.
All the functions except `$DELTA` support a custom window size.
In the case of comparisons and calculations involving `QuantityType` values, both operands, whether they are Item states, the incoming value, or constants, must be of the same type and have compatible units.
In other words a comparison between a `QuantityType` operand and an incoming `DecimalType` value (or vice versa) will fail.
All `QuantityType` values are converted to the Unit of the linked Item before the calculation and/or comparison is done.
So if the binding sends a value that cannot be converted to the Unit of the linked Item, then that value is excluded.
e.g. if the linked item has a Unit of `Units.METRE` and the binding sends a value of `Units.CELSIUS` then the value is ignored.
In the case of comparisons and calculations involving `QuantityType` values, both operandswhether they are Item states, the incoming value, or constantsmust be of the same type and have compatible units.
In other words, a comparison between a `QuantityType` operand and an incoming `DecimalType` value (or vice versa) will fail.
All `QuantityType` values are converted to the unit of the linked Item before the calculation and/or comparison is done.
So if the binding sends a value that cannot be converted to the unit of the linked Item, then that value is excluded.
For example, if the linked Item has a unit of `Units.METRE` and the binding sends a value of `Units.CELSIUS`, then the value is ignored.
The state of one item can be compared against the state of another item by having item names on both sides of the comparison, e.g.: `Item1 > Item2`.
When `LHS_OPERAND` is omitted, e.g. `> 10, < 100`, the comparisons are applied against the input data from the binding.
The state of one Item can be compared against the state of another Item by having Item names on both sides of the comparison, e.g., `Item1 > Item2`.
When `LHS_OPERAND` is omitted, e.g., `> 10, < 100`, the comparisons are applied against the input data from the binding.
The `RHS_OPERAND` can be any of the valid values listed above.
In this case, the value can also be replaced with an item name, which will result in comparing the input state against the state of that item, e.g. `> LowerLimitItem, < UpperLimitItem`.
This can be used to filter out unwanted data, e.g. to ensure that incoming data are within a reasonable range.
In this case, the value can also be replaced with an Item name, which will result in comparing the input state against the state of that Item, e.g., `> LowerLimitItem, < UpperLimitItem`.
This can be used to filter out unwanted data, e.g., to ensure that incoming data are within a reasonable range.
##### State Filter Operators
@@ -341,15 +341,15 @@ Number:Power PowerUsage {
## Inactivity Profile
This profile sets the state of the item to `ON` if the binding has not provided any new data values within a given timeout period.
This profile sets the state of the Item to `ON` if the binding has not provided any new data values within a given timeout period.
The purpose is to indicate an alarm condition if the binding is no longer providing values for the given channel.
### Inactivity Profile Configuration
| Configuration Parameter | Type | Description |
|-------------------------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `timeout` | text | Duration after which the item's state is updated if no data is received from the binding. The default is 1h. The format is the same as used in the [expire parameter](https://www.openhab.org/docs/configuration/items). |
| `inverted` | boolean | Optional. If false (default), the item's state is initially OFF, and changes to ON after the timeout. If true, the behavior is reversed: the initial state is ON, and it changes to OFF after the timeout. |
| `timeout` | text | Duration after which the Item's state is updated if no data is received from the binding. The default is 1h. The format is the same as used in the [expire parameter](https://www.openhab.org/docs/configuration/items). |
| `inverted` | boolean | Optional. If false (default), the Item's state is initially OFF and changes to ON after the timeout. If true, the behavior is reversed: the initial state is ON, and it changes to OFF after the timeout. |
### Inactivity Profile Example
@@ -6,8 +6,8 @@
<config-description uri="profile:basic-profiles:debounce-counting">
<parameter name="numberOfChanges" type="integer" min="0" step="1">
<label>Number Of Changes</label>
<description>Number of changes before updating Item State.</description>
<label>Number of Changes</label>
<description>Number of changes before updating the Item state.</description>
<default>1</default>
</parameter>
</config-description>
@@ -15,12 +15,12 @@
<config-description uri="profile:basic-profiles:debounce-time">
<parameter name="toItemDelay" type="integer" min="0" step="1" unit="ms">
<label>To Item Delay</label>
<description>Timespan before an value is forwarded to the item (or discarded after the first value).</description>
<description>Time span before a value is forwarded to the Item (or discarded after the first value).</description>
<default>0</default>
</parameter>
<parameter name="toHandlerDelay" type="integer" min="0" step="1" unit="ms">
<label>To Handler Delay</label>
<description>Timespan before an value is forwarded to the handler (or discarded after the first value).</description>
<description>Time span before a value is forwarded to the handler (or discarded after the first value).</description>
<default>0</default>
</parameter>
<parameter name="mode" type="text">
@@ -7,11 +7,11 @@
<config-description uri="profile:basic-profiles:generic-command">
<parameter name="events" type="text" required="true" multiple="true">
<label>Events</label>
<description>Comma separated list of events to which the profile should listen.</description>
<description>Comma-separated list of events to which the profile should listen.</description>
</parameter>
<parameter name="command" type="text" required="true">
<label>Command</label>
<description>Command which should be sent if the event is triggered.</description>
<description>Command to send when the event is triggered.</description>
<limitToOptions>false</limitToOptions>
<options>
<option value="INCREASE">INCREASE</option>
@@ -7,13 +7,13 @@
<config-description uri="profile:basic-profiles:inactivity">
<parameter name="timeout" type="text">
<label>Timeout</label>
<description>Duration after which the item's state is updated if no data is received from the binding. The default is
<description>Duration after which the Item's state is updated if no data is received from the binding. The default is
1h. The format is the same as used in the expire parameter.</description>
<default>1h</default>
</parameter>
<parameter name="inverted" type="boolean" required="false">
<label>Inverted</label>
<description>Optional. If false (default), the item's state is initially OFF, and changes to ON after the timeout. If
<description>Optional. If false (default), the Item's state is initially OFF and changes to ON after the timeout. If
true, the behavior is reversed: the initial state is ON, and it changes to OFF after the timeout.</description>
<default>false</default>
</parameter>
@@ -11,8 +11,7 @@
</parameter>
<parameter name="mode" type="text">
<label>Rounding Mode</label>
<description>Rounding mode to be used (e.g. "UP", "DOWN", "CEILING", "FLOOR", "HALF_UP" or "HALF_DOWN").
</description>
<description>Rounding mode to be used (e.g., "UP", "DOWN", "CEILING", "FLOOR", "HALF_UP", or "HALF_DOWN").</description>
<default>HALF_UP</default>
<options>
<option value="UP">UP</option>
@@ -7,13 +7,13 @@
<config-description uri="profile:basic-profiles:state-filter">
<parameter name="conditions" type="text" required="true" multiple="true">
<label>Conditions</label>
<description><![CDATA[List of expressions in the format [ITEM_NAME] OPERATOR VALUE_OR_ITEM_NAME, e.g. "MyItem == OFF".
Use quotes around VALUE_OR_ITEM_NAME to perform string comparison e.g. "'OFF'".
<description><![CDATA[List of expressions in the format [ITEM_NAME] OPERATOR VALUE_OR_ITEM_NAME, e.g., "MyItem == OFF".
Use quotes around VALUE_OR_ITEM_NAME to perform string comparison, e.g., "'OFF'".
VALUE can be a DecimalType or a QuantityType with a unit.
When ITEM_NAME is omitted, the comparisons are done against the input state from the channel.
<br /><br />
Multiple conditions can be specified by writing each expression on a separate line, or
when specified in the same line, separated by the separator character (default: ",").
when specified on the same line, separated by the separator character (default: ",").
All the conditions are ANDed to determine the result.
<br /><br />
The following operators are supported:
@@ -26,10 +26,9 @@
]]></description>
</parameter>
<parameter name="mismatchState" type="text">
<label>State for filter rejects</label>
<description>State to pass to item instead if conditions are NOT met. Use quotes to treat as `StringType`. If
not
defined, the state update will not be passed to the item when conditions are not met.</description>
<label>State for Filter Rejects</label>
<description>State to pass to the Item if conditions are NOT met. Use quotes to treat as `StringType`. If not
defined, the state update will not be passed to the Item when conditions are not met.</description>
</parameter>
<parameter name="separator" type="text">
<advanced>true</advanced>
@@ -7,7 +7,7 @@
<config-description uri="profile:basic-profiles:threshold">
<parameter name="threshold" type="integer" min="0" max="100" step="1">
<label>Threshold</label>
<description>Triggers ON if value is below the given threshold, otherwise OFF.</description>
<description>Triggers ON if the value is below the given threshold; otherwise OFF.</description>
<default>10</default>
</parameter>
</config-description>
@@ -7,14 +7,14 @@
<config-description uri="profile:basic-profiles:time-range-command">
<parameter name="inRangeValue" type="integer" min="0" max="100" step="1">
<label>In Range Value</label>
<description>The value which will be send when the profile detects ON and current time is between start time and end
time.</description>
<description>The value that will be sent when the profile detects ON and the current time is between the start time
and the time.</description>
<default>100</default>
</parameter>
<parameter name="outOfRangeValue" type="integer" min="0" max="100" step="1">
<label>Out Of Range Value</label>
<description>The value which will be send when the profile detects ON and current time is NOT between start time and
end time.</description>
<description>The value that will be sent when the profile detects ON and the current time is NOT between the start
time and end time.</description>
<default>30</default>
</parameter>
<parameter name="start" type="text" pattern="^([0-1][0-9]|2[0-3])(:[0-5][0-9])$" required="true">
@@ -7,7 +7,7 @@
<config-description uri="profile:basic-profiles:toggle-switch">
<parameter name="events" type="text" required="true" multiple="true">
<label>Events</label>
<description>Comma separated list of events to which the profile should listen.</description>
<description>Comma-separated list of events to which the profile should listen.</description>
</parameter>
</config-description>
</config-description:config-descriptions>
@@ -3,17 +3,17 @@
addon.basicprofiles.name = Basic Profiles
addon.basicprofiles.description = A set of profiles with basic functionality.
profile.config.basic-profiles.debounce-counting.numberOfChanges.label = Number Of Changes
profile.config.basic-profiles.debounce-counting.numberOfChanges.description = Number of changes before updating Item State.
profile.config.basic-profiles.debounce-counting.numberOfChanges.label = Number of Changes
profile.config.basic-profiles.debounce-counting.numberOfChanges.description = Number of changes before updating the Item state.
profile.config.basic-profiles.debounce-time.mode.label = Mode
profile.config.basic-profiles.debounce-time.mode.option.FIRST = Send first value
profile.config.basic-profiles.debounce-time.mode.option.LAST = Send last value
profile.config.basic-profiles.debounce-time.toHandlerDelay.label = To Handler Delay
profile.config.basic-profiles.debounce-time.toHandlerDelay.description = Timespan before an value is forwarded to the handler (or discarded after the first value).
profile.config.basic-profiles.debounce-time.toHandlerDelay.description = Time span before a value is forwarded to the handler (or discarded after the first value).
profile.config.basic-profiles.debounce-time.toItemDelay.label = To Item Delay
profile.config.basic-profiles.debounce-time.toItemDelay.description = Timespan before an value is forwarded to the item (or discarded after the first value).
profile.config.basic-profiles.debounce-time.toItemDelay.description = Time span before a value is forwarded to the Item (or discarded after the first value).
profile.config.basic-profiles.generic-command.command.label = Command
profile.config.basic-profiles.generic-command.command.description = Command which should be sent if the event is triggered.
profile.config.basic-profiles.generic-command.command.description = Command to send when the event is triggered.
profile.config.basic-profiles.generic-command.command.option.INCREASE = INCREASE
profile.config.basic-profiles.generic-command.command.option.DECREASE = DECREASE
profile.config.basic-profiles.generic-command.command.option.NEXT = NEXT
@@ -29,13 +29,13 @@ profile.config.basic-profiles.generic-command.command.option.MOVE = MOVE
profile.config.basic-profiles.generic-command.command.option.UP = UP
profile.config.basic-profiles.generic-command.command.option.DOWN = DOWN
profile.config.basic-profiles.generic-command.events.label = Events
profile.config.basic-profiles.generic-command.events.description = Comma separated list of events to which the profile should listen.
profile.config.basic-profiles.generic-command.events.description = Comma-separated list of events to which the profile should listen.
profile.config.basic-profiles.inactivity.inverted.label = Inverted
profile.config.basic-profiles.inactivity.inverted.description = Optional. If false (default), the item's state is initially OFF, and changes to ON after the timeout. If true, the behavior is reversed: the initial state is ON, and it changes to OFF after the timeout.
profile.config.basic-profiles.inactivity.inverted.description = Optional. If false (default), the Item's state is initially OFF and changes to ON after the timeout. If true, the behavior is reversed: the initial state is ON, and it changes to OFF after the timeout.
profile.config.basic-profiles.inactivity.timeout.label = Timeout
profile.config.basic-profiles.inactivity.timeout.description = Duration after which the item's state is updated if no data is received from the binding. The default is 1h. The format is the same as used in the expire parameter.
profile.config.basic-profiles.inactivity.timeout.description = Duration after which the Item's state is updated if no data is received from the binding. The default is 1h. The format is the same as used in the expire parameter.
profile.config.basic-profiles.round.mode.label = Rounding Mode
profile.config.basic-profiles.round.mode.description = Rounding mode to be used (e.g. "UP", "DOWN", "CEILING", "FLOOR", "HALF_UP" or "HALF_DOWN").
profile.config.basic-profiles.round.mode.description = Rounding mode to be used (e.g., "UP", "DOWN", "CEILING", "FLOOR", "HALF_UP", or "HALF_DOWN").
profile.config.basic-profiles.round.mode.option.UP = UP
profile.config.basic-profiles.round.mode.option.DOWN = DOWN
profile.config.basic-profiles.round.mode.option.CEILING = CEILING
@@ -45,19 +45,19 @@ profile.config.basic-profiles.round.mode.option.HALF_DOWN = HALF_DOWN
profile.config.basic-profiles.round.scale.label = Scale
profile.config.basic-profiles.round.scale.description = Scale to indicate the resulting number of decimal places.
profile.config.basic-profiles.state-filter.conditions.label = Conditions
profile.config.basic-profiles.state-filter.conditions.description = List of expressions in the format [ITEM_NAME] OPERATOR VALUE_OR_ITEM_NAME, e.g. "MyItem == OFF". Use quotes around VALUE_OR_ITEM_NAME to perform string comparison e.g. "'OFF'". VALUE can be a DecimalType or a QuantityType with a unit. When ITEM_NAME is omitted, the comparisons are done against the input state from the channel. <br /><br /> Multiple conditions can be specified by writing each expression on a separate line, or when specified in the same line, separated by the separator character (default: ","). All the conditions are ANDed to determine the result. <br /><br /> The following operators are supported: <code>EQ</code> or <code>==</code>, <code>NE</code>, <code>!=</code>, or <code>&lt;&gt;</code>, <code>GT</code> or <code>&gt;</code>, <code>GTE</code> or <code>&gt;=</code>, <code>LT</code> or <code>&lt;</code>, and <code>LTE</code> or <code>&lt;=</code>.
profile.config.basic-profiles.state-filter.mismatchState.label = State for filter rejects
profile.config.basic-profiles.state-filter.mismatchState.description = State to pass to item instead if conditions are NOT met. Use quotes to treat as `StringType`. If not defined, the state update will not be passed to the item when conditions are not met.
profile.config.basic-profiles.state-filter.conditions.description = List of expressions in the format [ITEM_NAME] OPERATOR VALUE_OR_ITEM_NAME, e.g., "MyItem == OFF". Use quotes around VALUE_OR_ITEM_NAME to perform string comparison, e.g., "'OFF'". VALUE can be a DecimalType or a QuantityType with a unit. When ITEM_NAME is omitted, the comparisons are done against the input state from the channel. <br /><br /> Multiple conditions can be specified by writing each expression on a separate line, or when specified on the same line, separated by the separator character (default: ","). All the conditions are ANDed to determine the result. <br /><br /> The following operators are supported: <code>EQ</code> or <code>==</code>, <code>NE</code>, <code>!=</code>, or <code>&lt;&gt;</code>, <code>GT</code> or <code>&gt;</code>, <code>GTE</code> or <code>&gt;=</code>, <code>LT</code> or <code>&lt;</code>, and <code>LTE</code> or <code>&lt;=</code>.
profile.config.basic-profiles.state-filter.mismatchState.label = State for Filter Rejects
profile.config.basic-profiles.state-filter.mismatchState.description = State to pass to the Item if conditions are NOT met. Use quotes to treat as `StringType`. If not defined, the state update will not be passed to the Item when conditions are not met.
profile.config.basic-profiles.state-filter.separator.label = Expression Separator
profile.config.basic-profiles.state-filter.separator.description = The character/string used to separate multiple conditions in a single line. Defaults to ",".
profile.config.basic-profiles.threshold.threshold.label = Threshold
profile.config.basic-profiles.threshold.threshold.description = Triggers ON if value is below the given threshold, otherwise OFF.
profile.config.basic-profiles.threshold.threshold.description = Triggers ON if the value is below the given threshold; otherwise OFF.
profile.config.basic-profiles.time-range-command.end.label = End Time
profile.config.basic-profiles.time-range-command.end.description = The end time of the day (hh:mm).
profile.config.basic-profiles.time-range-command.inRangeValue.label = In Range Value
profile.config.basic-profiles.time-range-command.inRangeValue.description = The value which will be send when the profile detects ON and current time is between start time and end time.
profile.config.basic-profiles.time-range-command.inRangeValue.description = The value that will be sent when the profile detects ON and the current time is between the start time and the time.
profile.config.basic-profiles.time-range-command.outOfRangeValue.label = Out Of Range Value
profile.config.basic-profiles.time-range-command.outOfRangeValue.description = The value which will be send when the profile detects ON and current time is NOT between start time and end time.
profile.config.basic-profiles.time-range-command.outOfRangeValue.description = The value that will be sent when the profile detects ON and the current time is NOT between the start time and end time.
profile.config.basic-profiles.time-range-command.restoreValue.label = Restore Value
profile.config.basic-profiles.time-range-command.restoreValue.description = Select what should happen when the profile detects OFF again.
profile.config.basic-profiles.time-range-command.restoreValue.option.OFF = Off
@@ -70,7 +70,7 @@ profile.config.basic-profiles.time-weighted-average.delta.description = If state
profile.config.basic-profiles.time-weighted-average.duration.label = Duration
profile.config.basic-profiles.time-weighted-average.duration.description = Duration of the time frame to collect state updates
profile.config.basic-profiles.toggle-switch.events.label = Events
profile.config.basic-profiles.toggle-switch.events.description = Comma separated list of events to which the profile should listen.
profile.config.basic-profiles.toggle-switch.events.description = Comma-separated list of events to which the profile should listen.
# add-on
@@ -1,14 +1,14 @@
# Binary To JSON Transformation Service
# Binary to JSON Transformation Service
Transforms the input by Java Binary Block Parser syntax.
Transforms input using the Java Binary Block Parser (JBBP) syntax.
See details about syntax from [JBBP homepage](https://github.com/raydac/java-binary-block-parser)
See details about the syntax on the [JBBP homepage](https://github.com/raydac/java-binary-block-parser).
## Example
Let's assume we have received string containing bytes in hexa string format `03FAFF` and we want to convert binary data to JSON format. Binary data contains 3 bytes and strict data format is following `byte a; byte b; ubyte c;`.
Let's assume we have received a string containing bytes in hexadecimal string format `03FAFF` and we want to convert the binary data to JSON. The binary data contains 3 bytes and the strict data format is the following: `byte a; byte b; ubyte c;`.
Binary to JSON converter will return following result `{"a":3,"b":-6,"c":255}`
The Binary to JSON converter will return the following result: `{"a":3,"b":-6,"c":255}`
## Usage as a Profile
@@ -4,8 +4,8 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>BIN2JSON transformation</name>
<description>Transforms the input by Java Binary Block Parser syntax.</description>
<name>BIN2JSON Transformation</name>
<description>Transforms input using the Java Binary Block Parser (JBBP) syntax.</description>
<connection>none</connection>
</addon:addon>
@@ -0,0 +1,4 @@
# add-on
addon.bin2json.name = BIN2JSON Transformation
addon.bin2json.description = Transforms input using the Java Binary Block Parser (JBBP) syntax.
+14 -14
View File
@@ -1,17 +1,17 @@
# Exec Transformation Service
Transforms an input string with an external program.
Transforms an input string using an external program.
Executes an external program and returns the output as a string.
In the given command line the placeholder `%s` is substituted with the input value.
In the given command line, the placeholder `%s` is substituted with the input value.
The provided command line is split on spaces before it is passed to the shell.
Using single quotes (`'`) splitting can be avoided (e.g. `'%s'` would prevent splitting on spaces within the input value).
Using single quotes (`'`), splitting can be avoided (e.g., `'%s'` would prevent splitting on spaces within the input value).
The surrounding single quotes are removed.
The external program must either be in the executable search path of the server process, or an absolute path has to be used.
The external program must either be in the executable search path of the server process, or an absolute path must be used.
For security reasons all commands need to be whitelisted.
For security reasons, all commands must be whitelisted.
Allowed commands need to be added to the `misc/exec.whitelist` file in the configuration directory.
Every command needs to be on a separate line.
@@ -29,7 +29,7 @@ numfmt --to=iec-i --suffix=B --padding=7 %s
#### Item
This will replace the visible label in the UI with the transformation you apply with the command <TransformProgram>.
This will replace the visible label in the UI with the transformation you apply with the command `<TransformProgram>`.
```java
String yourItem "Some info [EXEC(/absolute/path/to/your/<TransformProgram> %s):%s]"
@@ -55,7 +55,7 @@ Substitute the `/absolute/path/to/your/<TransformProgram>` with
/bin/date -v1d -v+1m -v-1d -v-%s
```
When the input argument for `%s` is `fri` the execution returns a string with the last weekday of the month, formated as readable text.
When the input argument for `%s` is `fri`, the execution returns a string with the last weekday of the month, formatted as readable text.
```shell
Fri 31 Mar 2017 13:58:47 IST`
@@ -67,7 +67,7 @@ Or replace it with
numfmt --to=iec-i --suffix=B --padding=7 %s
```
When the input argument for `%s` is 1234567 it will return the bytes formatted in a better readable form
When the input argument for `%s` is `1234567`, it will return the bytes formatted in a more readable form
```shell
1.2MiB
@@ -82,13 +82,13 @@ To do so, it can be configured in the `.items` file as follows:
String <itemName> { channel="<channelUID>"[profile="transform:EXEC", function="<shellcommand>", sourceFormat="<valueFormat>"]}
```
The shell command to be executed has to be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, i.e. `%.3f`.
If omitted the default is `%s`, so the input value will be put into the transformation without any format changes.
The shell command to be executed must be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, e.g., `%.3f`.
If omitted, the default is `%s`, so the input value will be passed to the transformation without any format changes.
Please note: This profile is a one-way transformation, i.e. only values from a device towards the item are changed, the other direction is left untouched.
Please note: This profile is a one-way transformation, i.e., only values from a device towards the Item are changed; the other direction is left untouched.
## Further Reading
- [Manual](http://man7.org/linux/man-pages/man1/date.1.html) and [tutorial](https://linode.com/docs/tools-reference/tools/use-the-date-command-in-linux/) for date.
- [Manual](http://man7.org/linux/man-pages/man1/numfmt.1.html) and [tutorial](https://www.pixelbeat.org/docs/numfmt.html) for numfmt.
- [Manual](http://man7.org/linux/man-pages/man1/date.1.html) and [tutorial](https://linode.com/docs/tools-reference/tools/use-the-date-command-in-linux/) for `date`.
- [Manual](http://man7.org/linux/man-pages/man1/numfmt.1.html) and [tutorial](https://www.pixelbeat.org/docs/numfmt.html) for `numfmt`.
@@ -4,7 +4,7 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>Exec transformation</name>
<name>Exec Transformation</name>
<description>Transforms an input string with an external program.</description>
<connection>none</connection>
@@ -7,12 +7,12 @@
<config-description uri="profile:transform:EXEC">
<parameter name="function" type="text" required="true">
<label>Command</label>
<description>Command to be executed on the command line. It should contain %s which will be substituted with the
<description>Command to be executed on the command line. It should contain %s, which will be substituted with the
state.</description>
</parameter>
<parameter name="sourceFormat" type="text" required="false">
<label>State Formatter</label>
<description>How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).</description>
<description>How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,7 +1,12 @@
# add-on
addon.exec.name = Exec Transformation
addon.exec.description = Transforms an input string with an external program.
profile.config.transform.EXEC.function.label = Command
profile.config.transform.EXEC.function.description = Command to be executed on the command line. It should contain %s which will be substituted with the state.
profile.config.transform.EXEC.function.description = Command to be executed on the command line. It should contain %s, which will be substituted with the state.
profile.config.transform.EXEC.sourceFormat.label = State Formatter
profile.config.transform.EXEC.sourceFormat.description = How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).
profile.config.transform.EXEC.sourceFormat.description = How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).
# profile type
+11 -10
View File
@@ -1,9 +1,10 @@
# Jinja Transformation Service
Transforms a value using a jinja template.
Transforms a value using a Jinja template.
The main purpose of this transformer is the use in the home assistant discovery. Therfore not all features of the home assistant templating are supported.
Basically on [Processing incoming data](https://www.home-assistant.io/docs/configuration/templating/#processing-incoming-data)
The main purpose of this transformer is use in Home Assistant discovery.
Therefore, not all features of the Home Assistant templating engine are supported.
See also: [Processing incoming data](https://www.home-assistant.io/docs/configuration/templating/#processing-incoming-data).
## Available variables
@@ -27,14 +28,14 @@ Given the value
the template
```text
{{value_json['AM2301'].Temperature}}`
{{ value_json['AM2301'].Temperature }}
```
extracts the string `4.7`.
#### Outgoing data
The JINJA transformation can be used to publish simple JSON strings through, for example, the HTTP Binding's `commandTransformation` parameter.
The JINJA transformation can be used to publish simple JSON strings through, for example, the HTTP bindings `commandTransformation` parameter.
Say we have a String Item which holds the following value:
@@ -42,13 +43,13 @@ Say we have a String Item which holds the following value:
This is my string
```
Adding the following into the `commandTransformation` parameter of your HTTP Thing Channel
Adding the following into the `commandTransformation` parameter of your HTTP Thing channel
```text
JINJA:{"msgtype":"m.text", "body":"{{value}}"}
```
will send the following string out of openHAB
will send the following string out of openHAB:
```json
{"msgtype":"m.text", "body":"This is my string"}
@@ -56,7 +57,7 @@ will send the following string out of openHAB
`{{value}}` will be replaced by whatever the value of your Item is.
Note that if using \*.things files you must escape quotation marks, for example:
Note that if using .things files you must escape quotation marks, for example:
```text
commandTransformation = "JINJA:{\"msgtype\":\"m.text\", \"body\":\"{{value}}\"}"
@@ -65,5 +66,5 @@ commandTransformation = "JINJA:{\"msgtype\":\"m.text\", \"body\":\"{{value}}\"}"
## Further Reading
- Wikipedia on [Jinja](https://en.wikipedia.org/wiki/Jinja_%28template_engine%29).
- Home assistant [discovery](https://www.home-assistant.io/docs/mqtt/discovery/).
- Home assistant [templating](https://www.home-assistant.io/docs/configuration/templating/).
- Home Assistant [discovery](https://www.home-assistant.io/docs/mqtt/discovery/).
- Home Assistant [templating](https://www.home-assistant.io/docs/configuration/templating/).
@@ -5,7 +5,7 @@
<type>transformation</type>
<name>Jinja Transformation</name>
<description>Transforms a value using a jinja template.</description>
<description>Transforms a value using a Jinja template.</description>
<connection>none</connection>
</addon:addon>
@@ -12,7 +12,7 @@
</parameter>
<parameter name="sourceFormat" type="text" required="false">
<label>State Formatter</label>
<description>How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).</description>
<description>How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,7 +1,12 @@
# add-on
addon.jinja.name = Jinja Transformation
addon.jinja.description = Transforms a value using a Jinja template.
profile.config.transform.JINJA.function.label = Jinja Template
profile.config.transform.JINJA.function.description = Template to be evaluated. For example: {{ value_json.device.status.temperature }}
profile.config.transform.JINJA.sourceFormat.label = State Formatter
profile.config.transform.JINJA.sourceFormat.description = How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).
profile.config.transform.JINJA.sourceFormat.description = How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).
# profile type
@@ -8,8 +8,7 @@ Given the following JSON string:
[{ "device": { "location": "Outside", "status": { "temperature": 23.2 }}}]
```
The expression `$.device.location` extracts the string `Outside`.
The JsonPath expression `$.device.status.temperature` extracts the string `23.2`.
The expression `$.device.location` extracts the string `Outside`, and the expression `$.device.status.temperature` extracts the string `23.2`.
## Examples
@@ -40,7 +39,7 @@ Now the resulting Number can also be used in the label to [change the color](htt
## Differences to standard JsonPath
Compared to standard JsonPath, the transformation returns single values instead of arrays.
The transformation also will not ever return `null`.
The transformation will never return `null`.
This makes it possible to use the transform in labels or output channels of Things.
If the JsonPath expression provided results in no matches, the transformation will return the entire original JSON string.
@@ -55,11 +54,11 @@ One example for configuring it in the `.items` file:
String <itemName> { channel="<channelUID>"[profile="transform:JSONPATH", function="<jsonPath>", sourceFormat="<valueFormat>"]}
```
The JsonPath expression to be used has to be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, i.e. `%.3f`.
The JsonPath expression to be used must be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, e.g., `%.3f`.
If omitted, the default is `%s`, so the input value will be returned from the transformation without any format changes.
This profile is a one-way transformation; only values from a device toward the item are changed.
This profile is a one-way transformation; only values from a device toward the Item are changed.
## Further Reading
@@ -4,8 +4,8 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>JSONPATH transformation</name>
<description>Extracts values from a JSON string using a JSONPATH expression.</description>
<name>JSONPATH Transformation</name>
<description>Extracts values from a JSON string using a JSONPath expression.</description>
<connection>none</connection>
</addon:addon>
@@ -11,7 +11,7 @@
</parameter>
<parameter name="sourceFormat" type="text" required="false">
<label>State Formatter</label>
<description>How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).</description>
<description>How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,7 +1,12 @@
# add-on
addon.jsonpath.name = JSONPATH Transformation
addon.jsonpath.description = Extracts values from a JSON string using a JSONPath expression.
profile.config.transform.JSONPATH.function.label = JSONPath Expression
profile.config.transform.JSONPATH.function.description = Expression to be applied on the state. For example: $.device.status.temperature
profile.config.transform.JSONPATH.sourceFormat.label = State Formatter
profile.config.transform.JSONPATH.sourceFormat.description = How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).
profile.config.transform.JSONPATH.sourceFormat.description = How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).
# profile type
+5 -5
View File
@@ -21,7 +21,7 @@ To organize the various transformations one might use subfolders.
## Inline Map
Instead of providing the file name from which to load, the mapping table can be specified inline by prefixing it with the pipe character `|` .
Instead of providing the file name from which to load, the mapping table can be specified inline by prefixing it with the pipe character `|`.
The inline map entries are delimited with semicolons (`;`) by default.
For example, the following map function translates open/closed to ON/OFF: `|open=ON; closed=OFF`
@@ -66,11 +66,11 @@ To do so, it can be configured in the `.items` file as follows:
String <itemName> { channel="<channelUID>" [profile="transform:MAP", function="<filename>", sourceFormat="<valueFormat>" ] }
```
The mapping filename (within the `transform` folder) has to be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, i.e. `%.3f`.
If omitted the default is `%s`, so the input value will be put into the transformation without any format changes.
The mapping filename (within the `transform` folder) must be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, e.g., `%.3f`.
If omitted, the default is `%s`, so the input value will be passed to the transformation without any format changes.
Please note: This profile is a one-way transformation, i.e. only values from a device towards the item are changed, the other direction is left untouched.
Please note: This profile is a one-way transformation, i.e., only values from a device towards the Item are changed; the other direction is left untouched.
To use an inline map in the profile:
@@ -4,7 +4,7 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>MAP transformation</name>
<name>MAP Transformation</name>
<description>Transforms the input by mapping it to another string.</description>
<connection>none</connection>
@@ -21,7 +21,7 @@
</parameter>
<parameter name="sourceFormat" type="text">
<label>State Formatter</label>
<description>How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s)</description>
<description>How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,12 +1,13 @@
# add-on
addon.map.name = MAP transformation
addon.map.name = MAP Transformation
addon.map.description = Transforms the input by mapping it to another string.
profile.config.transform.MAP.function.label = Filename
profile.config.transform.MAP.function.description = Filename containing the mapping information. <br /><br /> Inline map is supported, e.g. "|online=ON;offline=OFF". <br /><br /> The inline map entries are delimited with semicolons ("<code>;</code>") by default. <br /> To use a different delimiter, for example a comma: "<code>|?delimiter=,;online=ON,offline=OFF</code>" <br /> To use "<code>?delimiter</code>" as an actual map key, do not place it at the beginning of the map.
profile.config.transform.MAP.sourceFormat.label = State Formatter
profile.config.transform.MAP.sourceFormat.description = How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).
# bundle config
profile-type.transform.MAP.label = MAP
profile.config.transform.MAP.function.label = Filename
profile.config.transform.MAP.function.description = Filename containing the mapping information.<br /><br />Inline map is supported, e.g. "|online=ON;offline=OFF".<br /><br />The inline map entries are delimited with semicolons ("<code>;</code>") by default. <br /> To use a different delimiter, for example a comma: "<code>|?delimiter=,;online=ON,offline=OFF</code>" <br /> To use "<code>?delimiter</code>" as an actual map key, do not place it at the beginning of the map.
profile.config.transform.MAP.sourceFormat.label = State Formatter
profile.config.transform.MAP.sourceFormat.description = How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).
+31 -31
View File
@@ -1,18 +1,18 @@
# RegEx Transformation Service
# Regex Transformation Service
Transforms a source string on basis of the regular expression (regex) search pattern to a defined result string.
Transforms a source string based on a regular expression (regex) search pattern into a defined result string.
The simplest regex is in the form `<regex>` and transforms the input string on basis of the regex pattern to a result string.
A full regex is in the form `s/<regex>/<substitution>/g` whereat the delimiter `s` and the regex flag `g` have a special meaning.
The simplest regex is of the form `<regex>` and transforms the input string based on the regex pattern to a result string.
A full regex is of the form `s/<regex>/<substitution>/g`, where `s` denotes substitution and the flag `g` applies it globally.
The regular expression in the format `s/<regex>/result/g`, replaces all occurrences of `<regex>` in the source string with `result`.
The regular expression in the format `s/<regex>/result/` (without `g`), replaces the first occurrence of `<regex>` in the source string with `result`.
The regular expression in the format `s/<regex>/result/g` replaces all occurrences of `<regex>` in the source string with `result`.
The regular expression in the format `s/<regex>/result/` (without `g`) replaces only the first occurrence of `<regex>` in the source string with `result`.
If the regular expression contains a [capture group](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/regex/Pattern.html#cg) defined by `()`, it returns the captured string.
Multiple capture groups can be used to retrieve multiple strings and can be combined as a result string defined in the `substitution`.
Multiple capture groups can be used to retrieve multiple strings and can be combined in the `substitution`.
The transformation can be set to be restricted to only match if the input string begins with a character by prepending `^` to the beginning of a pattern or to only match if the input string ends with a specified character by appending `$` at the end.
So the regex `^I.*b$` only matches when the input string starts with `I` and ends with `b`, like in `I'm Bob`. Both can be used alone or in combination.
Use anchors to restrict where a match can occur: prepend `^` to anchor at the start of the input and append `$` to anchor at the end.
So the regex `^I.*b$` only matches when the input string starts with `I` and ends with `b`, like in `I'm Bob`. Both anchors can be used alone or in combination.
The special characters `\.[]{}()*+-?^$|` have to be escaped when they should be used as literal characters.
@@ -20,14 +20,14 @@ The special characters `\.[]{}()*+-?^$|` have to be escaped when they should be
### Basic Examples
| Input String | Regular Expression | Output String | Explanation |
| --------------------------- | ------------------------ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `My network does not work.` | `s/work/cast/g` | `"My netcast does not cast."` | Replaces all matches of the string "work" with the string "cast". |
| `My network does not work.` | `.*(\snot).*` | `" not"` | Returns only the first match and strips of the rest, "\s" defines a whitespace. |
| `temp=44.0'C` | `temp=(.*?)'C` | `44.0` | Matches whole string and returns the content of the captcha group `(.?)`. |
| `48312` | `s/(.{2})(.{3})/$1.$2/g` | `48.312` | Captures 2 and 3 character, returns first capture group adds a dot and the second capture group. This divides by 1000. |
| Input String | Regular Expression | Output String | Explanation |
|-----------------------------|--------------------------|-----------------------------|----------------------------------------------------------------------------------------------------------------|
| `My network does not work.` | `s/work/cast/g` | `My netcast does not cast.` | Replaces all matches of the string "work" with the string "cast". |
| `My network does not work.` | `.*(\snot).*` | not (leading space) | Returns the first capture group (" not"); `\s` matches a whitespace. |
| `temp=44.0'C` | `temp=(.*?)'C` | `44.0` | Matches the whole string and returns the content of the capture group `(.*?)`. |
| `48312` | `s/(.{2})(.{3})/$1.$2/g` | `48.312` | Captures two and three characters, returns the first capture group, adds a dot, then the second capture group. |
### Example In Setup
### Example setup
#### Input String
@@ -35,7 +35,7 @@ The special characters `\.[]{}()*+-?^$|` have to be escaped when they should be
temp=44.0'C
```
the regex transformation can be used to extract the value to display it on the label.
The regex transformation can be used to extract the value to display it on the label.
#### `example.items`
@@ -44,7 +44,7 @@ String Temperature_str "Temperature [REGEX(.*=(\\d*\\.\\d*).*):%s °C]" {...}
Number Temperature "Temperature [%.1f °C]"
```
The regex pattern is is defined as follows:
The regex pattern is defined as follows:
- `.*` match any character, zero and unlimited times
- `=` match the equal sign literally, used to find the position
@@ -54,10 +54,10 @@ The regex pattern is is defined as follows:
- `\w*` match a word character (equal to [a-zA-Z_0-9]), zero and unlimited times
- `.*` match any character, zero and unlimited times
Note, the backslashes have to be escaped. See [string vs plain](#differences-to-plain-regex)
Note: the backslashes have to be escaped. See [string vs plain](#differences-to-plain-regex).
The result will be `44.0` and displayed on the label as `Temperature 44.0 °C`.
A better solution would be to use the regex on the result from the binding either in a rule or when the binding allows it on the output channel.
A better solution would be to apply the regex to the result from the bindingeither in a rule or, when the binding allows it, on the output channel.
Thus the value `44.0` would be saved as a number.
#### .rules
@@ -75,15 +75,15 @@ then
end
```
Now the resulting Number can also be used in the label to [change the color](https://docs.openhab.org/configuration/sitemaps.html#label-and-value-colors) or in a rule as value for comparison.
Now the resulting Number can also be used in the label to [change the color](https://www.openhab.org/docs/ui/sitemaps.html#label-value-and-icon-colors) or in a rule as a value for comparison.
## Differences to plain Regex
## Differences to Plain Regex
The regex is embedded in a string so when double quotes `"` are used in a regex they need to be escaped `\"` to keep the string intact.
As the escape character of strings is the backslash this has to be escaped additionally.
To use a dot as literal in the regex it has to be escape `\.`, but in a string it has to be escaped twice `"\\."`.
The regex is embedded in a string, so when double quotes `"` are used in a regex they need to be escaped as `\"` to keep the string intact.
Because the escape character in strings is the backslash, it must itself be escaped.
To use a dot as a literal in the regex, escape it as `\.`; in a string this becomes `"\\."`.
The first backslash escapes the second backslash in the string so it can be used in the regex.
Using a backslash in a Regex as literal `\\` will have this form `"\\\\"`.
Using a backslash in a regex as a literal `\\` becomes `"\\\\"` in the string.
## Usage as a Profile
@@ -95,15 +95,15 @@ String <itemName> { channel="<channelUID>"[profile="transform:REGEX", function="
```
The regular expression to be executed has to be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, i.e. `%.3f`.
If omitted the default is `%s`, so the input value will be put into the transformation without any format changes.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, e.g., `%.3f`.
If omitted, the default is `%s`, so the input value will be put into the transformation without any format changes.
Please note: This profile is a one-way transformation, i.e. only values from a device towards the item are changed, the other direction is left untouched.
Please note: This profile is a one-way transformation, i.e., only values from a device towards the item are changed; the other direction is left untouched.
## Further Reading
- A full [introduction](https://www.w3schools.com/jsref/jsref_obj_regexp.asp) for regular expression is available at W3School.
- Online validator help to check the syntax of a regex and give information how to design it.
- A full [introduction](https://www.w3schools.com/jsref/jsref_obj_regexp.asp) to regular expressions is available at W3Schools.
- Online validators help check the syntax of a regex and provide hints on how to design it.
- [Regex 101](https://regex101.com/)
- [Regex R](https://regexr.com/)
- [ExtendsClass](https://extendsclass.com/regex-tester.html)
@@ -4,8 +4,8 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>Regex transformation</name>
<description>Transforms a source string on basis of the regular expression (regex) search pattern.</description>
<name>Regex Transformation</name>
<description>Transforms a source string based on a regular expression (regex) search pattern.</description>
<connection>none</connection>
</addon:addon>
@@ -7,12 +7,12 @@
<config-description uri="profile:transform:REGEX">
<parameter name="function" type="text" required="true">
<label>Regular Expression</label>
<description>Regular expression to be applied on the state. Should contain a capture group whose outcome will be the
result. For example: .*=(\\d*.\\d*).* extracts the 23.5 from temp=23.5°C</description>
<description>Regular expression to be applied to the state. It should contain a capture group whose outcome will be
the result. For example: .*=(\\d*\\.\\d*).* extracts 23.5 from temp=23.5°C.</description>
</parameter>
<parameter name="sourceFormat" type="text" required="false">
<label>State Formatter</label>
<description>How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).</description>
<description>How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,7 +1,12 @@
# add-on
addon.regex.name = Regex Transformation
addon.regex.description = Transforms a source string based on a regular expression (regex) search pattern.
profile.config.transform.REGEX.function.label = Regular Expression
profile.config.transform.REGEX.function.description = Regular expression to be applied on the state. Should contain a capture group whose outcome will be the result. For example: .*=(\\d*.\\d*).* extracts the 23.5 from temp=23.5°C
profile.config.transform.REGEX.function.description = Regular expression to be applied to the state. It should contain a capture group whose outcome will be the result. For example: .*=(\\d*\\.\\d*).* extracts 23.5 from temp=23.5°C.
profile.config.transform.REGEX.sourceFormat.label = State Formatter
profile.config.transform.REGEX.sourceFormat.description = How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).
profile.config.transform.REGEX.sourceFormat.description = How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).
# profile type
+39 -34
View File
@@ -1,22 +1,25 @@
# Scale Transformation Service
The Scale Transformation Service is an easy to handle tool that can help you with the discretization of number inputs.
The Scale Transformation Service is an easy-to-use tool that helps with the discretization of numeric inputs.
It transforms a given input by matching it to specified ranges.
The input string must be in numerical format.
The input must represent a numeric value.
The file is expected to exist in the `transform` configuration directory and its ending has to be `.scale`.
It should follow the format given in the table below.
The file must exist in the `transform` configuration directory and have the `.scale` extension.
It should follow the format shown in the table below.
Range expressions always contain two parts.
The range to scale on, which is located left from the equality sign and the corresponding output string on the right of it.
A range consists of two bounds. Both are optional, the range is then open. Both bounds can be inclusive or exclusive.
Range expressions always contain two parts:
| Scale Expression | Returns XYZ when the given value is |
|------------------|------------------------------------------------------------|
| `[12..23]=XYZ` | `between (or equal to) 12 and 23` |
| `]12..23[=XYZ` | `between 12 and 23 (12 and 23 are excluded in this case.)` |
| `[..23]=XYZ` | `lower than or equal to 23` |
| `]12..]=XYZ` | `greater than 12` |
- the range to scale on (left of the equals sign), and
- the corresponding output string (right of it).
A range consists of two bounds. Each bound is optional (making the range open-ended when omitted). Each bound can be inclusive or exclusive.
| Scale Expression | Returns XYZ when the given value is |
|------------------|---------------------------------------------------|
| `[12..23]=XYZ` | between (or equal to) 12 and 23 |
| `]12..23[=XYZ` | between 12 and 23 (12 and 23 are excluded) |
| `[..23]=XYZ` | less than or equal to 23 |
| `]12..]=XYZ` | greater than 12 |
These expressions are evaluated from top to bottom.
The first range that includes the value is selected.
@@ -25,35 +28,37 @@ The first range that includes the value is selected.
Some special entries can be used in the scale file.
### Catchall Entry
### Catch-all Entry
`[..]=Catchall`
This entry will match all numeric values not met by a previous range. Obviously, this one should be put at the very end of the scale definition file.
This entry matches all numeric values not matched by a previous range. It should be placed at the end of the scale file.
### Not A Number
### Not a Number
Scale transform is designed to work with numeric or quantity states. When the value presented to scale transform does not match this (most of the time with NULL or UNDEF states) it will not be handled and a warning is raised in the openhab.log . This case can be smoothly avoided with a
The Scale transform is designed to work with numeric or quantity states.
If the value presented to the Scale transform is not numeric (often NULL or UNDEF), it will not be handled and a warning is written to openhab.log.
You can handle this case with:
`NaN=Non Numeric State presented`
`NaN=Non-numeric state presented`
### Formatting output
At last, Scale transform can take care of formatting an output with this entry:
The Scale transform can also format the output using this entry:
`format=%label% (%value%) !`
Where:
- `%label%` will be replaced by transformed value and
- `%value%` is the numeric value presen
- `%label%` will be replaced by the transformed value, and
- `%value%` is the original numeric value presented
## Example
The following example shows how to break down numeric UV values into fixed UV index categories.
The following example shows how to break down numeric UV values into fixed UV Index categories.
We have an example UV sensor that sends numeric values from `0` to `100`, which we then want to scale into the [UV Index](https://en.wikipedia.org/wiki/Ultraviolet_index) range.
Example item:
Example Item:
```java
Number Uv_Sensor_Level "UV Level [SCALE(uvindex.scale):%s]"
@@ -61,7 +66,7 @@ Number Uv_Sensor_Level "UV Level [SCALE(uvindex.scale):%s]"
Referenced scale file `uvindex.scale` in the `transform` folder:
```python
```text
[..3]=1
]3..6]=2
]6..8]=3
@@ -69,14 +74,14 @@ Referenced scale file `uvindex.scale` in the `transform` folder:
]10..100]=5
```
Each value the item receives, will be categorized to one of the five given ranges.
Values **lower than or equal to 3** are matched with `[..3]=1`.
Greater values are catched in ranges with 2 values as criteria.
The only condition here is that the received value has to be lower or equal than `100` in our example, since we haven't defined other cases yet.
If **none** of the configured conditions matches the given value, the response will be empty.
Each value the Item receives will be categorized into one of the five given ranges.
Values less than or equal to 3 are matched by `[..3]=1`.
Greater values are matched by the subsequent ranges.
The only condition here is that the received value has to be less than or equal to `100` in our example, since we haven't defined other cases.
If none of the configured conditions match the given value, the response will be empty.
Please note that all ranges for values above **3** are opened with a `]`.
So the border values (3, 6, 8 and 10) are always transformed to the lower range, since the `]` excludes the given critera.
Please note that all ranges for values above 3 start with a `]`.
So the boundary values (3, 6, 8, and 10) are always transformed to the lower range, since `]` excludes the lower bound.
## Usage as a Profile
@@ -88,7 +93,7 @@ String <itemName> { channel="<channelUID>"[profile="transform:SCALE", function="
```
The filename (within the `transform` folder) of the scale file has to be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, i.e. `%.3f`.
If omitted the default is `%s`, so the input value will be put into the transformation without any format changes.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, e.g., `%.3f`.
If omitted, the default is `%s`, so the input value will be put into the transformation without any format changes.
Please note: This profile is a one-way transformation, i.e. only values from a device towards the item are changed, the other direction is left untouched.
Please note: This profile is a one-way transformation, i.e., only values from a device towards the Item are changed; the other direction is left untouched.
@@ -4,8 +4,8 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>Scale transformation</name>
<description>Transforms a numerical input to a string.</description>
<name>Scale Transformation</name>
<description>Transforms a numeric input to a string using range-based mappings.</description>
<connection>none</connection>
</addon:addon>
@@ -12,7 +12,7 @@
</parameter>
<parameter name="sourceFormat" type="text">
<label>State Formatter</label>
<description>How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).</description>
<description>How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,7 +1,12 @@
# add-on
addon.scale.name = Scale Transformation
addon.scale.description = Transforms a numeric input to a string using range-based mappings.
profile.config.transform.SCALE.function.label = Filename
profile.config.transform.SCALE.function.description = Filename containing the scale mappings.
profile.config.transform.SCALE.sourceFormat.label = State Formatter
profile.config.transform.SCALE.sourceFormat.description = How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).
profile.config.transform.SCALE.sourceFormat.description = How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).
# profile type
+2 -2
View File
@@ -1,7 +1,7 @@
# VAT Transformation Service
The VAT Transformation Service adds VAT (Value-Added Tax) to a given input amount.
The input string must be either an ISO 3166 alpha-2 country code or a percentage, i.e. numerical format.
The input string must be either an ISO 3166 alpha-2 country code or a percentage (i.e., in numeric format).
## Examples
@@ -70,4 +70,4 @@ Number CurrentSpotPrice "Current Spot Price" <price> { channel="<channelUID>" [p
If VAT is not known for the configured country or the provided percentage is invalid, the default is 0%, so the input value will be put into the transformation without any changes.
Please note: This profile is a one-way transformation, i.e. only values from a device towards the item are changed, the other direction is left untouched.
Please note: This profile is a one-way transformation, i.e., only values from a device towards the Item are changed; the other direction is left untouched.
@@ -4,8 +4,8 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>VAT transformation</name>
<description>Transforms the input by adding Value-Added Tax according to configured country or percentage.</description>
<name>VAT Transformation</name>
<description>Transforms the input by adding Value-Added Tax according to a configured country or percentage.</description>
<connection>none</connection>
</addon:addon>
@@ -7,7 +7,7 @@
<config-description uri="profile:transform:VAT">
<parameter name="percentage" type="text">
<label>VAT Percentage</label>
<description>Manually configured VAT percentage (overriding VAT rate for configured country).</description>
<description>Manually configured VAT percentage, overriding the VAT rate for the configured country.</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,10 +1,11 @@
# add-on
addon.vat.name = VAT transformation
addon.vat.description = Transforms the input by adding Value-Added Tax according to configured country or percentage.
addon.vat.name = VAT Transformation
addon.vat.description = Transforms the input by adding Value-Added Tax according to a configured country or percentage.
profile.config.transform.VAT.percentage.label = VAT Percentage
profile.config.transform.VAT.percentage.description = Manually configured VAT percentage, overriding the VAT rate for the configured country.
# profile
profile-type.transform.VAT.label = Value-Added Tax
profile.config.transform.VAT.percentage.label = VAT Percentage
profile.config.transform.VAT.percentage.description = Manually configured VAT percentage (overriding VAT rate for configured country).
+13 -13
View File
@@ -19,7 +19,7 @@ Given a retrieved XML
</PTZStatus>
```
The XPath `/PTZStatus/AbsoluteHigh/azimuth/text()` returns the document
The XPath `/PTZStatus/AbsoluteHigh/azimuth/text()` returns
```text
450
@@ -27,7 +27,7 @@ The XPath `/PTZStatus/AbsoluteHigh/azimuth/text()` returns the document
## Advanced Example
Given a retrieved XML (e.g. from an HIK Vision device with the namespace `xmlns="http://www.hikvision.com/ver20/XMLSchema"`):
Given a retrieved XML (e.g., from a Hikvision device with the namespace `xmlns="http://www.hikvision.com/ver20/XMLSchema"`):
```xml
<?xml version="1.0" encoding="UTF-8"?>
@@ -40,12 +40,12 @@ Given a retrieved XML (e.g. from an HIK Vision device with the namespace `xmlns=
</PTZStatus>
```
A simple xpath query to fetch the Azimut value does not work as it does not address the namespace.
A simple XPath query to fetch the azimuth value does not work because it does not address the namespace.
There are two ways to address the namespace.
There are two ways to address the namespace:
- Simple path which may not work in complex XML.
- With full qualified path.
- Simple path, which may not work in complex XML.
- Fully qualified path.
The XPath
@@ -58,12 +58,12 @@ returns
<azimuth>450</azimuth>
```
### In Setup
### Example Setup
#### .items
```java
String Temperature_xml "Temperature [XPATH(/*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/):%s °C]" {...}
String Temperature_xml "Temperature [XPATH(/*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/text()):%s °C]" {...}
Number Temperature "Temperature [%.1f °C]"
```
@@ -93,7 +93,7 @@ then
end
```
Now the resulting Number can also be used in the label to [change the color](https://docs.openhab.org/configuration/sitemaps.html#label-and-value-colors) or in a rule as value for comparison.
Now the resulting Number can also be used in the label to [change the color](https://www.openhab.org/docs/ui/sitemaps.html#label-value-and-icon-colors) or in a rule as a value for comparison.
## Usage as a Profile
@@ -105,13 +105,13 @@ String <itemName> { channel="<channelUID>"[profile="transform:XPATH", function="
```
The XPath expression to be executed has to be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, i.e. `%.3f`.
If omitted the default is `%s`, so the input value will be put into the transformation without any format changes.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, e.g., `%.3f`.
If omitted, the default is `%s`, so the input value will be put into the transformation without any format changes.
Please note: This profile is a one-way transformation, i.e. only values from a device towards the item are changed, the other direction is left untouched.
Please note: This profile is a one-way transformation, i.e., only values from a device towards the item are changed; the other direction is left untouched.
## Further Reading
- An [introduction](https://www.w3schools.com/xml/xpath_intro.asp) to XPath at W3School
- An [introduction](https://www.w3schools.com/xml/xpath_intro.asp) to XPath at W3Schools.
- An informative explanation of [common mistakes](https://qxf2.com/blog/common-xpath-mistakes/).
- Online validation tools like [this](https://www.freeformatter.com/xpath-tester.html) to check the syntax.
@@ -4,8 +4,8 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>XPATH transformation</name>
<description>Extracts values from an XML string with the XPATH syntax.</description>
<name>XPath Transformation</name>
<description>Extracts values from an XML string using XPath expressions.</description>
<connection>none</connection>
</addon:addon>
@@ -7,12 +7,12 @@
<config-description uri="profile:transform:XPATH">
<parameter name="function" type="text" required="true">
<label>XPath Expression</label>
<description>XPath expression to be applied on the state: For example:
/*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/</description>
<description>XPath expression to be applied to the state. For example:
/*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/text()</description>
</parameter>
<parameter name="sourceFormat" type="text" required="false">
<label>State Formatter</label>
<description>How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).</description>
<description>How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,7 +1,12 @@
# add-on
addon.xpath.name = XPath Transformation
addon.xpath.description = Extracts values from an XML string using XPath expressions.
profile.config.transform.XPATH.function.label = XPath Expression
profile.config.transform.XPATH.function.description = XPath expression to be applied on the state: For example: /*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/
profile.config.transform.XPATH.function.description = XPath expression to be applied to the state. For example: /*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/text()
profile.config.transform.XPATH.sourceFormat.label = State Formatter
profile.config.transform.XPATH.sourceFormat.description = How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).
profile.config.transform.XPATH.sourceFormat.description = How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).
# profile type
+22 -22
View File
@@ -1,11 +1,11 @@
# XSLT Transformation Service
Transform input using the XML Stylesheet Language for Transformations (XSLT).
Transforms input using the XML Stylesheet Language for Transformations (XSLT).
XSLT is a standard method to transform an XML structure from one document into a new document with a different structure.
The transformation expects the rule to be read from a file which is stored under the `transform` folder.
To organize the various transformations one should use subfolders.
The transformation expects the rule to be read from a file stored under the `transform` folder.
To organize the various transformations, use subfolders.
General transformation rule summary:
@@ -13,16 +13,16 @@ General transformation rule summary:
- The directive `xsl:template` specifies matching attributes for the XML node to find.
- The `xsl:template` tag contains the rule which specifies what should be done.
The Rule uses XPath to gather the XML node information.
For more information have a look at the [XPath transformation](https://docs.openhab.org/addons/transformations/xpath/readme.html) .
The rule uses XPath to gather the XML node information.
For more information, see the [XPath transformation](https://www.openhab.org/addons/transformations/xpath/).
## Examples
### Basic Example
A simple but complete XSLT transformation looks like in the following example, which was taken from [this Wikipedia article](https://en.wikipedia.org/wiki/Java_API_for_XML_Processing#Example).
A simple but complete XSLT transformation looks like the following example, which was taken from [this Wikipedia article](https://en.wikipedia.org/wiki/Java_API_for_XML_Processing#Example).
#### input XML
#### Input XML
```xml
<?xml version='1.0' encoding='UTF-8'?>
@@ -31,9 +31,9 @@ A simple but complete XSLT transformation looks like in the following example, w
#### transform/helloworld.xsl
- `xsl:output`: transform incoming document into another XML-like document, without indentation.
- `xsl:template`: `match="/"` "any type of node", so the whole document.
- The `xsl` rule does `select` the node `/root/node` and extracts the `value-of` attribute `val`.
- `xsl:output`: Transforms the incoming document into another XML-like document, without indentation.
- `xsl:template`: `match="/"` matches any type of node, so the whole document.
- The `xsl` rule selects the node `/root/node` and extracts the `value-of` attribute `val`.
```xml
<?xml version='1.0' encoding='UTF-8'?>
@@ -53,7 +53,7 @@ A simple but complete XSLT transformation looks like in the following example, w
### Advanced Example
This example has a namespace defined, as you would find in real world applications, which has to be matched in the rule.
This example has a namespace defined, as you would find in real-world applications, which has to be matched in the rule.
#### Input XML
@@ -70,17 +70,17 @@ This example has a namespace defined, as you would find in real world applicatio
</PTZStatus>
```
#### transform/azimut.xsl
#### transform/azimuth.xsl
In the rule, the tag `<xsl:stylesheet>` has to have an attribute `xmlns:xsl="http://www.w3.org/1999/XSL/Transform"` and a second attribute `xmlns:`.
This attribute has to be the same as the namespace for the input document.
In the rule each step traversed along the path to the next tag has to be prepended with the `xmlns` namespace, here defined as `h`.
In the rule, each step traversed along the path to the next tag has to be prepended with the `xmlns` namespace, here defined as `h`.
- `xsl:output` transform incoming document into another XML-like document, no indentation, **without XML**.
- `xsl:template`: `match="/"` whole document.
- Full path to node `azimuth` reading out `date` attribute.
- Add a linebreak by setting `&#10;` as text.
- Search for node `azimuth` by prepending `//` and get the `text`.
- `xsl:output`: Transforms the incoming document into another XML-like document, no indentation, **without XML declaration**.
- `xsl:template`: `match="/"` matches the whole document.
- Full path to node `azimuth` reading out the `date` attribute.
- Adds a line break by setting `&#10;` as text.
- Searches for node `azimuth` by prepending `//` and gets the text.
```xml
<?xml version="1.0" encoding="UTF-8"?>
@@ -113,14 +113,14 @@ String <itemName> { channel="<channelUID>"[profile="transform:XSLT", function="<
```
The XSLT file (from within the `transform` folder) to be used has to be set in the `function` parameter.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, i.e. `%.3f`.
If omitted the default is `%s`, so the input value will be put into the transformation without any format changes.
The parameter `sourceFormat` is optional and can be used to format the input value **before** the transformation, e.g., `%.3f`.
If omitted, the default is `%s`, so the input value will be put into the transformation without any format changes.
Please note: This profile is a one-way transformation, i.e. only values from a device towards the item are changed, the other direction is left untouched.
Please note: This profile is a one-way transformation, i.e., only values from a device towards the Item are changed; the other direction is left untouched.
## Further Reading
- Extended introduction and more [examples](https://en.wikipedia.org/wiki/XSLT#XSLT_examples) at Wikipedia.
- A good [introduction](https://www.w3schools.com/xml/xsl_intro.asp) and [tutorial](https://www.w3schools.com/xml/xsl_transformation.asp) at W3School.
- A good [introduction](https://www.w3schools.com/xml/xsl_intro.asp) and [tutorial](https://www.w3schools.com/xml/xsl_transformation.asp) at W3Schools.
- An informative [tutorial](https://www.ibm.com/developerworks/library/x-xsltmistakes/) of common mistakes.
- Online XSL transformer tools like [this](https://www.freeformatter.com/xsl-transformer.html) to check the syntax.
@@ -4,8 +4,8 @@
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>transformation</type>
<name>XSLT transformation</name>
<description>Transform input using the XML Stylesheet Language for Transformations (XSLT).</description>
<name>XSLT Transformation</name>
<description>Transforms input using the XML Stylesheet Language for Transformations (XSLT).</description>
<connection>none</connection>
</addon:addon>
@@ -11,7 +11,7 @@
</parameter>
<parameter name="sourceFormat" type="text" required="false">
<label>State Formatter</label>
<description>How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).</description>
<description>How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).</description>
<advanced>true</advanced>
</parameter>
</config-description>
@@ -1,7 +1,12 @@
# add-on
addon.xslt.name = XSLT Transformation
addon.xslt.description = Transforms input using the XML Stylesheet Language for Transformations (XSLT).
profile.config.transform.XSLT.function.label = XSL Filename
profile.config.transform.XSLT.function.description = XSL file name in transform folder, containing the transformation expression.
profile.config.transform.XSLT.sourceFormat.label = State Formatter
profile.config.transform.XSLT.sourceFormat.description = How to format the state on the channel before transforming it, i.e. %s or %.1f °C (default is %s).
profile.config.transform.XSLT.sourceFormat.description = How to format the state on the channel before transforming it, e.g., %s or %.1f °C (default is %s).
# profile type