Skip to content

Latest commit

 

History

History
989 lines (726 loc) · 38.2 KB

interface_openhab.rst

File metadata and controls

989 lines (726 loc) · 38.2 KB

openHAB

Additional configuration

For optimal performance it is recommended to use Basic Auth (available from openHAB 3.1 M3 on). It can be enabled through GUI or through textual configuration.

Textual configuration

The settings are in the runtime.cfg. Remove the # before the entry to activate it.

################ REST API ###################
org.openhab.restauth:allowBasicAuth=true

GUI

It can be enabled through the gui in settings -> API Security -> Allow Basic Authentication.

image

openHAB item types

Description and example

Items that are created from openHAB inherit all from ~HABApp.openHAB.items.OpenhabItem and provide convenience functions which simplify many things.

Example:

NumberItem

HABApp.openhab.items.NumberItem

HABApp.openhab.items.NumberItem

ContactItem

HABApp.openhab.items.ContactItem

HABApp.openhab.items.ContactItem

SwitchItem

HABApp.openhab.items.SwitchItem

HABApp.openhab.items.SwitchItem

DimmerItem

HABApp.openhab.items.DimmerItem

HABApp.openhab.items.DimmerItem

DatetimeItem

HABApp.openhab.items.DatetimeItem

HABApp.openhab.items.DatetimeItem

RollershutterItem

HABApp.openhab.items.RollershutterItem

HABApp.openhab.items.RollershutterItem

ColorItem

HABApp.openhab.items.ColorItem

HABApp.openhab.items.ColorItem

StringItem

HABApp.openhab.items.StringItem

HABApp.openhab.items.StringItem

LocationItem

HABApp.openhab.items.LocationItem

HABApp.openhab.items.LocationItem

PlayerItem

HABApp.openhab.items.PlayerItem

HABApp.openhab.items.PlayerItem

GroupItem

HABApp.openhab.items.GroupItem

HABApp.openhab.items.GroupItem

ImageItem

HABApp.openhab.items.ImageItem

HABApp.openhab.items.ImageItem

CallItem

HABApp.openhab.items.CallItem

HABApp.openhab.items.CallItem

Thing

HABApp.openhab.items.Thing

HABApp.openhab.items.Thing

Interaction with a openHAB

All interaction with the openHAB is done through the self.oh or self.openhab object in the rule or through an OpenhabItem.

image

Function parameters

HABApp.openhab.interface_sync

openHAB event types

openHAB produces various events that are mapped to the internal event bus. On the openHAB page there is an explanation for the various events.

Item events

ItemStateEvent

Since this event inherits from ~HABApp.core.events.ValueUpdateEvent you can listen to ~HABApp.core.events.ValueUpdateEvent and it will also trigger for ~HABApp.openhab.events.ItemStateEvent.

HABApp.openhab.events.ItemStateEvent

HABApp.openhab.events.ItemStateEvent

ItemStateChangedEvent

Since this event inherits from ~HABApp.core.events.ValueChangeEvent you can listen to ~HABApp.core.events.ValueChangeEvent and it will also trigger for ~HABApp.openhab.events.ItemStateChangedEvent.

HABApp.openhab.events.ItemStateChangedEvent

HABApp.openhab.events.ItemStateChangedEvent

ItemCommandEvent

HABApp.openhab.events.ItemCommandEvent

HABApp.openhab.events.ItemCommandEvent

ItemAddedEvent

HABApp.openhab.events.ItemAddedEvent

HABApp.openhab.events.ItemAddedEvent

ItemUpdatedEvent

HABApp.openhab.events.ItemUpdatedEvent

HABApp.openhab.events.ItemUpdatedEvent

ItemRemovedEvent

HABApp.openhab.events.ItemRemovedEvent

HABApp.openhab.events.ItemRemovedEvent

ItemStatePredictedEvent

HABApp.openhab.events.ItemStatePredictedEvent

HABApp.openhab.events.ItemStatePredictedEvent

GroupStateChangedEvent

HABApp.openhab.events.GroupStateChangedEvent

HABApp.openhab.events.GroupStateChangedEvent

Channel events

ChannelTriggeredEvent

HABApp.openhab.events.ChannelTriggeredEvent

HABApp.openhab.events.ChannelTriggeredEvent

Thing events

ThingAddedEvent

HABApp.openhab.events.ThingAddedEvent

HABApp.openhab.events.ThingAddedEvent

ThingUpdatedEvent

HABApp.openhab.events.ThingUpdatedEvent

HABApp.openhab.events.ThingUpdatedEvent

ThingRemovedEvent

HABApp.openhab.events.ThingRemovedEvent

HABApp.openhab.events.ThingRemovedEvent

ThingStatusInfoEvent

HABApp.openhab.events.ThingStatusInfoEvent

HABApp.openhab.events.ThingStatusInfoEvent

ThingStatusInfoChangedEvent

HABApp.openhab.events.ThingStatusInfoChangedEvent

HABApp.openhab.events.ThingStatusInfoChangedEvent

ThingFirmwareStatusInfoEvent

HABApp.openhab.events.ThingFirmwareStatusInfoEvent

HABApp.openhab.events.ThingFirmwareStatusInfoEvent

Event filters

ItemStateUpdatedEventFilter

HABApp.openhab.events.ItemStateUpdatedEventFilter

HABApp.openhab.events.ItemStateUpdatedEventFilter

ItemStateChangedEventFilter

HABApp.openhab.events.ItemStateChangedEventFilter

HABApp.openhab.events.ItemStateChangedEventFilter

ItemCommandEventFilter

HABApp.openhab.events.ItemCommandEventFilter

HABApp.openhab.events.ItemCommandEventFilter

Transformations

From openHAB 4 on it's possible to use the existing transformations in HABApp. Transformations are loaded every time when HABApp connects to openHAB. OpenHAB does not issue an event when the transformations change so in order for HABApp to pick up the changes either HABApp or openHAB has to be restarted. Available transformations are logged on connect.

map

The map transformation is returned as a dict. If the map transformation is defined with a default the default is used accordingly.

Example:

Textual thing configuration

Description

HABApp offers a special mechanism to textually define thing configuration parameters and linked items for things which have been added through the gui. This combines the best of both worlds: auto discovery, easy and fast sharing of parameters and items across things.

Configuration is done in the thing_your_name.yml file in the config folder (see configuration). Every file that starts with thing_ has the .yml ending will be loaded.

The Parameters and items will be checked/set when HABApp connects to openHAB or whenever the corresponding file gets changed.

Principle of operation

All existing things from openHAB can be filtered by different criteria. For each one of these remaining things it is then possible to

  • Set thing parameters
  • Create items with values taken from the thing fields
  • Apply filters to the channels of the thing
    For each matching channel it is possible to create and link items with values taken from the thing and the matching channel values

There is also a test mode which prints out all required information and does not make any changes.

A valid .items file will automatically be created next to the .yml file containing all created items. It can be used to get a quick overview what items (would) have been created or copied into the items folder.

File Structure

Configuration is done through a .yml file.

Example

The following example will show how to set the Z-Wave Parameters 4, 5, 6 and 8 for a Philio PST02A Z-Wave sensor and how to automatically link items to it.

Tip

Integer values can be specified either as integer (20) or hex (0x14)

The entries thing config, create items and channels are optional and can be combined as desired.

# Test mode: will not do anything but instead print out information
test: True

# Define filters which will reduce the number of things,
# all defined filters have to match for further processing
filter:
  thing_type: zwave:philio_pst02a_00_000

# Set this configuration every matching thing. HABApp will automatically only
# change the values which are not already correct.
# Here it is the z-wave parameters which are responsible for the device behaviour
thing config:
  4: 99     # Light Threshold
  5: 8      # Operation Mode
  6: 4      # MultiSensor Function Switch
  7: 20     # Customer Function

# Create items for every matching thing
create items:
 - type: Number
   name: '{thing_label, :(.+)$}_MyNumber'          # Use the label from the thing as an input for the name,
   label: '{thing_label, :(.+)$} MyNumber [%d]'    # the regex will take everything from the ':' on until the end
   icon: battery

channels:
  # reduce the channels of the thing with these filters
  # and link items to it
  - filter:
      channel_type: zwave:alarm_motion
    link items:
      - type: Number
        name: '{thing_label, :(.+)$}_Movement'           # Use the label from the thing as an input for the name,
        label: '{thing_label, :(.+)$} Movement [%d %%]'  # the regex will take everything from the ':' on until the end
        icon: battery
        groups: ['group1', 'group2']
        tags: ['tag1']

  - filter:
      channel_type: zwave:sensor_temperature
    link items:
      - type: Number
        name: '{thing_label, :(.+)$}_Temperature'
        label: '{thing_label, :(.+)$} Temperature [%d %%]'
        icon: battery

Multiple filters and filter definitions in one file

It is possible to add multiple thing processors into one file. To achieve this the root entry is now a list.

Filters can also be lists e.g. if the have to be applied multiple times to the same filed.

- test: True
  filter:
    thing_type: zwave:philio_pst02a_00_000
  ...

- test: True
  # multiple filters on the same field, all have to match
  filter:
  - thing_type: zwave:fibaro.+
  - thing_type: zwave:fibaro_fgrgbw_00_000
  ...

Thing configuration

With the thing config block it is possible to set a configuration for each matching thing. If the parameters are already correct, they will not be set again.

Warning

The value of the configuration parameters will not be checked and will be written as specified. It is recommended to use HABmin or PaperUI to generate the initial configuration and use this mechanism to spread it to things of the same type.

Example

thing config:
  4: 99     # Light Threshold
  5: 8      # Operation Mode
  6: 4      # MultiSensor Function Switch
  7: 20     # Customer Function

References to other parameters

It is possible to use references to mathematically build parameters from other parameters. Typically this would be fade duration and refresh interval. References to other parameter values can be created with $. Example:

thing config:
  5: 8
  6: '$5 / 2'       # Use value from parameter 5 and divide it by two.
  7: 'int($5 / 2)'  # it is possible to use normal python data conversions

Item configuration

Items can be configured under create items -> [] and channels -> [] -> link items -> [].

Structure

Mandatory values are type and name, all other values are optional.

type: Number
name: my_name
label: my_label
icon: my_icon
groups: ['group1', 'group2']
tags: ['tag1', 'tag1']

Metadata

It is possible to add metadata to the created items through the optional metadata entry in the item config.

There are two forms how metadata can be set. The implicit form for simple key-value pairs (e.g. autoupdate) or the explicit form where the entries are under value and config (e.g. alexa)

- type: Number
  name: '{thing_label, :(.+)$}_Temperature'
  label: '{thing_label, :(.+)$} Temperature [%d %%]'
  icon: battery
  metadata:
    autoupdate: 'false'
    homekit: 'TemperatureSensor'
    alexa:
      'value': 'Fan'
      'config':
        'type': 'oscillating'
        'speedSteps': 3

The config is equivalent to the following item configuration:

Number MyLabel_Temperature  "MyLabel Temperature [%d %%]" { autoupdate="false", homekit="TemperatureSensor", alexa="Fan" [ type="oscillating", speedSteps=3 ] }

Fields

Filtering things/channels

The filter value can be applied to any available field from the Thing/Channel. The filter value is a regex that has to fully match the value.

Syntax:

filter:
  FIELD_NAME: REGULAR_EXPRESSION

e.g.

filter:
  thing_uid: zwave:device:controller:node35

If multiple filters are specified all have to match to select the Thing or Channel.

# Multiple filters on different columns
filter:
  thing_type: zwave:fibaro.+
  thing_uid: zwave:device:controller:node35

# Multiple filters on the same columns (rarely needed)
filter:
- thing_type: zwave:fibaro.+
- thing_type: zwave:fibaro_fgrgbw_00_000

Field values as inputs

Filed values are available for item configuration and can be applied to all fields in the item configuration except for type and metadata.

Syntax

Macros that select field values are framed with {} so the containing string has to be put in annotation marks. There are three modes of operation with wildcards:

  1. Just insert the value from the field:
    {field}
  2. Insert a part of the value from the field. A regular expression is used to extract the part and therefore has to contain a capturing group.
    {field, regex(with_group)}
  3. Do a regex replace on the value from the field and use the result
    {field, regex, replace}

Available fields

Tip

Test mode will show a table with all available fields and their value

The following fields are available for things:

  • thing_uid
  • thing_type
  • thing_location
  • thing_label
  • bridge_uid

Additional available fields for channels:

  • channel_uid
  • channel_type
  • channel_label
  • channel_kind

Example

Log output

This will show the output for the example from File Structure

Loading /config/thing_philio.yml!
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                                                   Thing overview                                                                                 |
+---------------------------------+----------------------------+----------------+----------------------------------------+----------------------------------------------+----------+
|           thing_uid             |         thing_type         | thing_location |            thing_label                 |                  bridge_uid                  | editable |
+---------------------------------+----------------------------+----------------+----------------------------------------+----------------------------------------------+----------+
| zwave:device:controller:node32  | zwave:fibaro_fgrgbw_00_000 | Room1          | Fibaro RGBW (Node 32): Room1 RGBW      | zwave:serial_zstick:controller               | True     |
| zwave:device:controller:node7   | zwave:fibaro_fgrgbw_00_000 | Room2          | Fibaro RGBW (Node 07): Room2 RGBW      | zwave:serial_zstick:controller               | True     |
| zwave:device:controller:node23  | zwave:fibaro_fgrgbw_00_000 | Room3          | Fibaro RGBW (Node 23): Room3 RGBW      | zwave:serial_zstick:controller               | True     |
| zwave:device:controller:node35  | zwave:philio_pst02a_00_000 | Room1          | Philio PST02A (Node 35): Room1 Door    | zwave:serial_zstick:controller               | True     |
| zwave:device:controller:node15  | zwave:philio_pst02a_00_000 | Room2          | Philio PST02A (Node 15): Room2 Window  | zwave:serial_zstick:controller               | True     |
| zwave:device:controller:node17  | zwave:philio_pst02a_00_000 | Room3          | Philio PST02A (Node 17): Room3 Window  | zwave:serial_zstick:controller               | True     |
| zwave:device:controller:node3   | zwave:philio_pst02a_00_000 | Room1          | Philio PST02A (Node 03): Room1 Window  | zwave:serial_zstick:controller               | True     |
| zwave:device:controller:node5   | zwave:philio_pst02a_00_000 | Room4          | Philio PST02A (Node 05): FrontDoor     | zwave:serial_zstick:controller               | True     |
| zwave:serial_zstick:controller  | zwave:serial_zstick        |                | ZWave Controller                       |                                              | False    |
+---------------------------------+----------------------------+----------------+----------------------------------------+----------------------------------------------+----------+
thing_type "zwave:philio_pst02a_00_000" matches for zwave:device:controller:node35!
thing_type "zwave:philio_pst02a_00_000" matches for zwave:device:controller:node15!
thing_type "zwave:philio_pst02a_00_000" matches for zwave:device:controller:node17!
thing_type "zwave:philio_pst02a_00_000" matches for zwave:device:controller:node3!
thing_type "zwave:philio_pst02a_00_000" matches for zwave:device:controller:node5!
+---------------------------------------------------------------------------------------------------------------------------+
|                                                   Current configuration                                                   |
+-------------------------+-------------------+-------------------+-------------------+------------------+------------------+
|        Parameter        | controller:node35 | controller:node15 | controller:node17 | controller:node3 | controller:node5 |
+-------------------------+-------------------+-------------------+-------------------+------------------+------------------+
| 2                       | -1                | -1                | -1                | -1               | -1               |
| 3                       | 80                | 80                | 80                | 80               | 80               |
| 4                       | 99                | 99                | 99                | 99               | 99               |
| 5                       | 0                 | 8                 | 8                 | 8                | 8                |
| 6                       | 4                 | 0                 | 0                 | 0                | 0                |
| 7                       | 22                | 20                | 20                | 20               | 20               |
| 8                       | 3                 | 3                 | 3                 | 3                | 3                |
| 9                       | 4                 | 0                 | 4                 | 4                | 4                |
| 10                      | 12                | 12                | 12                | 12               | 12               |
| 11                      | 12                | 12                | 12                | 12               | 12               |
| 12                      | 12                | 12                | 2                 | 12               | 4                |
| 13                      | 12                | 12                | 2                 | 12               | 4                |
| 20                      | 30                | 30                | 30                | 30               | 30               |
| 21                      | 1                 | 0                 | 0                 | 0                | 0                |
| 22                      | 0                 | 0                 | 0                 | 0                | 0                |
| Group1                  | ['controller']    | ['controller']    | ['controller']    | ['controller']   | ['controller']   |
| Group2                  | []                | []                | []                | []               | []               |
| binding_cmdrepollperiod | 1500              | 1500              | 1500              | 1500             | 1500             |
| binding_pollperiod      | 86400             | 86400             | 86400             | 86400            | 86400            |
| wakeup_interval         | 86400             | 86400             | 86400             | 86400            | 86400            |
+-------------------------+-------------------+-------------------+-------------------+------------------+------------------+
Would set {5: 8, 7: 20} for zwave:device:controller:node35
Would set {6: 4} for zwave:device:controller:node15
Would set {6: 4} for zwave:device:controller:node17
Would set {6: 4} for zwave:device:controller:node3
Would set {6: 4} for zwave:device:controller:node5
+----------------------------------------------------------------------------------------------------------------------+
|                                       Channels for zwave:philio_pst02a_00_000                                        |
+---------------------------------------------------+--------------------------+------------------------+--------------+
|                    channel_uid                    |       channel_type       |     channel_label      | channel_kind |
+---------------------------------------------------+--------------------------+------------------------+--------------+
| zwave:device:controller:node35:sensor_door        | zwave:sensor_door        | Door/Window Sensor     | STATE        |
| zwave:device:controller:node35:alarm_motion       | zwave:alarm_motion       | Motion Sensor          | STATE        |
| zwave:device:controller:node35:alarm_tamper       | zwave:alarm_tamper       | Tamper Alarm           | STATE        |
| zwave:device:controller:node35:sensor_luminance   | zwave:sensor_luminance   | Sensor (luminance)     | STATE        |
| zwave:device:controller:node35:sensor_temperature | zwave:sensor_temperature | Sensor (temperature)   | STATE        |
| zwave:device:controller:node35:alarm_access       | zwave:alarm_access       | Alarm (Access Control) | STATE        |
| zwave:device:controller:node35:alarm_burglar      | zwave:alarm_burglar      | Alarm (Burglar)        | STATE        |
| zwave:device:controller:node35:battery-level      | system:battery-level     | Batterieladung         | STATE        |
+---------------------------------------------------+--------------------------+------------------------+--------------+
channel_type "zwave:alarm_motion" matches for zwave:device:controller:node35:alarm_motion!
channel_type "zwave:sensor_temperature" matches for zwave:device:controller:node35:sensor_temperature!

channel_type "zwave:alarm_motion" matches for zwave:device:controller:node15:alarm_motion!
channel_type "zwave:sensor_temperature" matches for zwave:device:controller:node15:sensor_temperature!

channel_type "zwave:alarm_motion" matches for zwave:device:controller:node17:alarm_motion!
channel_type "zwave:sensor_temperature" matches for zwave:device:controller:node17:sensor_temperature!

channel_type "zwave:alarm_motion" matches for zwave:device:controller:node3:alarm_motion!
channel_type "zwave:sensor_temperature" matches for zwave:device:controller:node3:sensor_temperature!

channel_type "zwave:alarm_motion" matches for zwave:device:controller:node5:alarm_motion!
channel_type "zwave:sensor_temperature" matches for zwave:device:controller:node5:sensor_temperature!

Would create Item(type='Number', name='Room1_Door_MyNumber', label='Room1 Door MyNumber [%d]', icon='battery', groups=[], tags=[], link=None)
Would create Item(type='Number', name='Room1_Door_Movement', label='Room1 Door Movement [%d %%]', icon='battery', groups=['group1', 'group2'], tags=['tag1'], link='zwave:device:controller:node35:alarm_motion')
Would create Item(type='Number', name='Room1_Door_Temperature', label='Room1 Door Temperature [%d %%]', icon='battery', groups=[], tags=[], link='zwave:device:controller:node35:sensor_temperature')
Would create Item(type='Number', name='Room2_Window_MyNumber', label='Room2 Window MyNumber [%d]', icon='battery', groups=[], tags=[], link=None)
Would create Item(type='Number', name='Room2_Window_Movement', label='Room2 Window Movement [%d %%]', icon='battery', groups=['group1', 'group2'], tags=['tag1'], link='zwave:device:controller:node15:alarm_motion')
Would create Item(type='Number', name='Room2_Window_Temperature', label='Room2 Window Temperature [%d %%]', icon='battery', groups=[], tags=[], link='zwave:device:controller:node15:sensor_temperature')
Would create Item(type='Number', name='Room3_Window_MyNumber', label='Room3 Window MyNumber [%d]', icon='battery', groups=[], tags=[], link=None)
Would create Item(type='Number', name='Room3_Window_Movement', label='Room3 Window Movement [%d %%]', icon='battery', groups=['group1', 'group2'], tags=['tag1'], link='zwave:device:controller:node17:alarm_motion')
Would create Item(type='Number', name='Room3_Window_Temperature', label='Room3 Window Temperature [%d %%]', icon='battery', groups=[], tags=[], link='zwave:device:controller:node17:sensor_temperature')
Would create Item(type='Number', name='Room1_Window_MyNumber', label='Room1 Window MyNumber [%d]', icon='battery', groups=[], tags=[], link=None)
Would create Item(type='Number', name='Room1_Window_Movement', label='Room1 Window Movement [%d %%]', icon='battery', groups=['group1', 'group2'], tags=['tag1'], link='zwave:device:controller:node3:alarm_motion')
Would create Item(type='Number', name='Room1_Window_Temperature', label='Room1 Window Temperature [%d %%]', icon='battery', groups=[], tags=[], link='zwave:device:controller:node3:sensor_temperature')
Would create Item(type='Number', name='FrontDoor_MyNumber', label='FrontDoor MyNumber [%d]', icon='battery', groups=[], tags=[], link=None)
Would create Item(type='Number', name='FrontDoor_Movement', label='FrontDoor Movement [%d %%]', icon='battery', groups=['group1', 'group2'], tags=['tag1'], link='zwave:device:controller:node5:alarm_motion')
Would create Item(type='Number', name='FrontDoor_Temperature', label='FrontDoor Temperature [%d %%]', icon='battery', groups=[], tags=[], link='zwave:device:controller:node5:sensor_temperature')

Created items file

Number   Room1_Door_MyNumber         "Room1 Door MyNumber [%d]"             <battery>
Number   Room1_Door_Movement         "Room1 Door Movement [%d %%]"          <battery>    (group1, group2)     [tag1]   {channel = "zwave:device:controller:node35:alarm_motion"}
Number   Room1_Door_Temperature      "Room1 Door Temperature [%d %%]"       <battery>                                  {channel = "zwave:device:controller:node35:sensor_temperature"}
Number   Room2_Window_MyNumber       "Room2 Window MyNumber [%d]"           <battery>
Number   Room2_Window_Movement       "Room2 Window Movement [%d %%]"        <battery>    (group1, group2)     [tag1]   {channel = "zwave:device:controller:node15:alarm_motion"}
Number   Room2_Window_Temperature    "Room2 Window Temperature [%d %%]"     <battery>                                  {channel = "zwave:device:controller:node15:sensor_temperature"}
Number   Room3_Window_MyNumber       "Room3 Window MyNumber [%d]"           <battery>
Number   Room3_Window_Movement       "Room3 Window Movement [%d %%]"        <battery>    (group1, group2)     [tag1]   {channel = "zwave:device:controller:node17:alarm_motion"}
Number   Room3_Window_Temperature    "Room3 Window Temperature [%d %%]"     <battery>                                  {channel = "zwave:device:controller:node17:sensor_temperature"}
Number   Room1_Window_MyNumber       "Room1 Window MyNumber [%d]"           <battery>
Number   Room1_Window_Movement       "Room1 Window Movement [%d %%]"        <battery>    (group1, group2)     [tag1]   {channel = "zwave:device:controller:node3:alarm_motion"}
Number   Room1_Window_Temperature    "Room1 Window Temperature [%d %%]"     <battery>                                  {channel = "zwave:device:controller:node3:sensor_temperature"}
Number   FrontDoor_MyNumber          "FrontDoor MyNumber [%d]"              <battery>
Number   FrontDoor_Movement          "FrontDoor Movement [%d %%]"           <battery>    (group1, group2)     [tag1]   {channel = "zwave:device:controller:node5:alarm_motion"}
Number   FrontDoor_Temperature       "FrontDoor Temperature [%d %%]"        <battery>                                  {channel = "zwave:device:controller:node5:sensor_temperature"}

Example openHAB rules

Example 1

../run/conf/rules/openhab_rule.py

Check status of things

This rule prints the status of all Things and shows how to subscribe to events of the Thing status

../run/conf/rules/openhab_things.py

Check status if thing is constant

Sometimes Things recover automatically from small outages. This rule only triggers when the Thing is constant for 60 seconds.