util - helpers and utilities

The util package contains useful classes which make rule creation easier.

Functions

min

This function is very useful together with the all possible functions of ValueMode for the MultiModeItem. For example it can be used to automatically disable or calculate the new value of the ValueMode It behaves like the standard python function except that it will ignore None values which are sometimes set as the item state.

from HABApp.util.functions import min

print(min(1, 2, None))
min(*args, default=None)

Behaves like the built in min function but ignores any None values. e.g. min([1, None, 2]) == 1. If the iterable is empty default will be returned.

Parameters
  • args – Single iterable or 1..n arguments

  • default – Value that will be returned if the iterable is empty

Returns

min value

max

This function is very useful together with the all possible functions of ValueMode for the MultiModeItem. For example it can be used to automatically disable or calculate the new value of the ValueMode It behaves like the standard python function except that it will ignore None values which are sometimes set as the item state.

from HABApp.util.functions import max

print(max(1, 2, None))
max(*args, default=None)

Behaves like the built in max function but ignores any None values. e.g. max([1, None, 2]) == 2. If the iterable is empty default will be returned.

Parameters
  • args – Single iterable or 1..n arguments

  • default – Value that will be returned if the iterable is empty

Returns

max value

rgb_to_hsb

Converts a rgb value to hsb color space

from HABApp.util.functions import rgb_to_hsb

print(rgb_to_hsb(224, 201, 219))
rgb_to_hsb(r, g, b, max_rgb_value=255, ndigits=2)

Convert from rgb to hsb/hsv

Parameters
  • r (Union[int, float]) – red value

  • g (Union[int, float]) – green value

  • b (Union[int, float]) – blue value

  • max_rgb_value (int) – maximal possible rgb value (e.g. 255 for 8 bit or 65.535 for 16bit values)

  • ndigits (Optional[int]) – Round the hsb values to the specified digits, None to disable rounding

Return type

Tuple[float, float, float]

Returns

Values for hue, saturation and brightness / value

hsb_to_rgb

Converts a hsb value to the rgb color space

from HABApp.util.functions import hsb_to_rgb

print(hsb_to_rgb(150, 40, 100))
hsb_to_rgb(h, s, b, max_rgb_value=255)

Convert from rgb to hsv/hsb

Parameters
  • h – hue

  • s – saturation

  • b – brightness / value

  • max_rgb_value – maximal value for the returned rgb values (e.g. 255 for 8 bit or 65.535 16bit values)

Return type

Tuple[int, int, int]

Returns

Values for red, green and blue

Statistics

Example

s = Statistics(max_samples=4)
for i in range(1,4):
    s.add_value(i)
    print(s)
<Statistics sum: 1.0, min: 1.00, max: 1.00, mean: 1.00, median: 1.00>
<Statistics sum: 3.0, min: 1.00, max: 2.00, mean: 1.50, median: 1.50>
<Statistics sum: 6.0, min: 1.00, max: 3.00, mean: 2.00, median: 2.00>

Documentation

class Statistics(max_age=None, max_samples=None)

Calculate mathematical statistics of numerical values.

Variables
  • sum – sum of all values

  • min – minimum of all values

  • max – maximum of all values

  • mean – mean of all values

  • median – median of all values

  • last_value – last added value

  • last_change – timestamp the last time a value was added

update()

update values without adding a new value

add_value(value)

Add a new value and recalculate statistical values

Parameters

value – new value

Fade

Fade is a helper class which allows to easily fade a value up or down.

Example

This example shows how to fade a Dimmer from 0 to 100 in 30 secs

from HABApp import Rule
from HABApp.openhab.items import DimmerItem
from HABApp.util import Fade

class FadeExample(Rule):
    def __init__(self):
        super().__init__()
        self.dimmer = DimmerItem.get_item('Dimmer1')
        self.fade = Fade(callback=self.fade_value)  # self.dimmer.percent would also be a good callback in this example

        # Setup the fade and schedule its execution
        # Fade from 0 to 100 in 30s
        self.fade.setup(0, 100, 30).schedule_fade()

    def fade_value(self, value):
        self.dimmer.percent(value)

FadeExample()

This example shows how to fade three values together (e.g. for an RGB strip)

from HABApp import Rule
from HABApp.openhab.items import DimmerItem
from HABApp.util import Fade

class Fade3Example(Rule):
    def __init__(self):
        super().__init__()
        self.fade1 = Fade(callback=self.fade_value)
        self.fade2 = Fade()
        self.fade3 = Fade()

        # Setup the fades and schedule the execution of one fade where the value gets updated every sec
        self.fade3.setup(0, 100, 30)
        self.fade2.setup(0, 50, 30)
        self.fade1.setup(0, 25, 30, min_step_duration=1).schedule_fade()

    def fade_value(self, value):
        value1 = value
        value2 = self.fade2.get_value()
        value3 = self.fade3.get_value()

Fade3Example()

Documentation

class Fade(callback=None, min_value=0, max_value=100)

Helper to easily fade values up/down

Variables
  • min_value – minimum valid value for the fade value

  • max_value – maximum valid value for the fade value

  • callback – Function with one argument that will be automatically called with the new values when the scheduled fade runs

setup(start_value, stop_value, duration, min_step_duration=0.2, now=None)

Calculates everything that is needed to fade a value

Parameters
  • start_value (Union[int, float]) – Start value

  • stop_value (Union[int, float]) – Stop value

  • duration (Union[int, float, timedelta]) – How long shall the fade take

  • min_step_duration (float) – minimum step duration (min 0.2 secs)

  • now (Optional[float]) – time.time() timestamp to sync multiple fades together

Return type

Fade

get_value(now=None)

Returns the current value. If the fade is finished it will always return the stop value.

Parameters

now (Optional[float]) – time.time() timestamp for which the value shall be returned. Can be used to sync multiple fades together. Not required.

Return type

float

Returns

current value

property is_finished: bool

True if the fade is finished

Return type

bool

schedule_fade()

Automatically run the fade with the Scheduler. The callback can be used to set the current fade value e.g. on an item. Calling this on a running fade will restart the fade

Return type

Fade

stop_fade()

Stop the scheduled fade. This can be called multiple times without error

EventListenerGroup

EventListenerGroup is a helper class which allows to subscribe to multiple items at once. All subscriptions can be canceled together, too. This is useful if e.g. something has to be done once after a sensor reports a value.

Example

This is a rule which will turn on the lights once (!) in a room on the first movement in the morning. The lights will only turn on after 4 and before 8 and two movement sensors are used to pick up movement.

from datetime import time

from HABApp import Rule
from HABApp.core.events import ValueChangeEvent
from HABApp.openhab.items import SwitchItem, NumberItem
from HABApp.util import EventListenerGroup


class EventListenerGroupExample(Rule):
    def __init__(self):
        super().__init__()
        self.lights = SwitchItem.get_item('RoomLights')
        self.sensor_move_1 = NumberItem.get_item('MovementSensor1')
        self.sensor_move_2 = NumberItem.get_item('MovementSensor2')

        # use a list of items which will be subscribed with the same callback and event
        self.listeners = EventListenerGroup().add_listener(
            [self.sensor_move_1, self.sensor_move_2], self.sensor_changed, ValueChangeEvent)

        self.run.on_every_day(time(4), self.listen_sensors)
        self.run.on_every_day(time(8), self.sensors_cancel)

    def listen_sensors(self):
        self.listeners.listen()

    def sensors_cancel(self):
        self.listeners.cancel()

    def sensor_changed(self, event):
        self.listeners.cancel()
        self.lights.on()

EventListenerGroupExample()

Documentation

class EventListenerGroup

Helper to create/cancel multiple event listeners simultaneously

property active: bool
Return type

bool

Returns

True if the listeners are currently active

listen()

Create all event listeners. If the event listeners are already active this will do nothing.

cancel()

Cancel the active event listeners. If the event listeners are not active this will do nothing.

activate_listener(name)

Resume a previously deactivated listener creator in the group.

Parameters

name (str) – item name or alias of the listener

Returns

True if it was activated, False if it was already active

deactivate_listener(name, cancel_if_active=True)

Exempt the listener creator from further listener/cancel calls

Parameters
  • name (str) – item name or alias of the listener

  • cancel_if_active – Cancel the listener if it is active

Returns

True if it was deactivated, False if it was already deactivated

add_listener(item, callback, event_filter, alias=None)

Add an event listener to the group

Parameters
  • item (Union[TypeVar(HINT_ITEM_OBJ, bound= BaseItem), Iterable[TypeVar(HINT_ITEM_OBJ, bound= BaseItem)]]) – Single or multiple items

  • callback (Callable[[Any], Any]) – Callback for the item(s)

  • event_filter (TypeVar(HINT_EVENT_FILTER_OBJ, bound= EventFilterBase)) – Event filter for the item(s)

  • alias (Optional[str]) – Alias if an item with the same name does already exist (e.g. if different callbacks shall be created for the same item)

Return type

EventListenerGroup

Returns

self

add_no_update_watcher(item, callback, seconds, alias=None)
Add an no update watcher to the group. On listen this will create a no update watcher and

the corresponding event listener that will trigger the callback

Parameters
  • item (Union[TypeVar(HINT_ITEM_OBJ, bound= BaseItem), Iterable[TypeVar(HINT_ITEM_OBJ, bound= BaseItem)]]) – Single or multiple items

  • callback (Callable[[Any], Any]) – Callback for the item(s)

  • seconds (Union[int, float, timedelta]) – No update time for the no update watcher

  • alias (Optional[str]) – Alias if an item with the same name does already exist (e.g. if different callbacks shall be created for the same item)

Return type

EventListenerGroup

Returns

self

add_no_change_watcher(item, callback, seconds, alias=None)
Add an no change watcher to the group. On listen this this will create a no change watcher and

the corresponding event listener that will trigger the callback

Parameters
  • item (Union[TypeVar(HINT_ITEM_OBJ, bound= BaseItem), Iterable[TypeVar(HINT_ITEM_OBJ, bound= BaseItem)]]) – Single or multiple items

  • callback (Callable[[Any], Any]) – Callback for the item(s)

  • seconds (Union[int, float, timedelta]) – No update time for the no change watcher

  • alias (Optional[str]) – Alias if an item with the same name does already exist (e.g. if different callbacks shall be created for the same item)

Return type

EventListenerGroup

Returns

self

MultiModeItem

Prioritizer item which automatically switches between values with different priorities. Very useful when different states or modes overlap, e.g. automatic and manual mode. etc.

Basic Example

import HABApp
from HABApp.core.events import ValueUpdateEventFilter
from HABApp.util.multimode import MultiModeItem, ValueMode

class MyMultiModeItemTestRule(HABApp.Rule):
    def __init__(self):
        super().__init__()

        # create a new MultiModeItem
        item = MultiModeItem.get_create_item('MultiModeTestItem')
        item.listen_event(self.item_update, ValueUpdateEventFilter())

        # create two different modes which we will use and add them to the item
        auto = ValueMode('Automatic', initial_value=5)
        manu = ValueMode('Manual', initial_value=0)
        item.add_mode(0, auto).add_mode(10, manu)

        # This shows how to enable/disable a mode and how to get a mode from the item
        print('disable/enable the higher priority mode')
        item.get_mode('manual').set_enabled(False)  # disable mode
        item.get_mode('manual').set_value(11)       # setting a value will enable it again

        # This shows that changes of the lower priority is only shown when
        # the mode with the higher priority gets disabled
        print('')
        print('Set value of lower priority')
        auto.set_value(55)
        print('Disable higher priority')
        manu.set_enabled(False)

    def item_update(self, event):
        print(f'State: {event.value}')

MyMultiModeItemTestRule()
disable/enable the higher priority mode
State: 5
State: 11

Set value of lower priority
State: 11
Disable higher priority
State: 55

Advanced Example

import logging
import HABApp
from HABApp.core.events import ValueUpdateEventFilter
from HABApp.util.multimode import MultiModeItem, ValueMode

class MyMultiModeItemTestRule(HABApp.Rule):
    def __init__(self):
        super().__init__()

        # create a new MultiModeItem
        item = MultiModeItem.get_create_item('MultiModeTestItem')
        item.listen_event(self.item_update, ValueUpdateEventFilter())

        # helper to print the heading so we have a nice output
        def print_heading(_heading):
            print('')
            print('-' * 80)
            print(_heading)
            print('-' * 80)
            for p, m in item.all_modes():
                print(f'Prio {p:2d}: {m}')
            print('')


        log = logging.getLogger('AdvancedMultiMode')

        # create modes and add them
        auto = ValueMode('Automatic', initial_value=5, logger=log)
        manu = ValueMode('Manual', initial_value=10, logger=log)
        item.add_mode(0, auto).add_mode(10, manu)


        # it is possible to automatically disable a mode
        # this will disable the manual mode if the automatic mode
        # sets a value greater equal manual mode
        print_heading('Automatically disable mode')

        # A custom function can also disable the mode:
        manu.auto_disable_func = lambda low, own: low >= own

        auto.set_value(11) # <-- manual now gets disabled because
        auto.set_value(4)  #     the lower priority value is >= itself


        # It is possible to use functions to calculate the new value for a mode.
        # E.g. shutter control and the manual mode moves the shades. If it's dark the automatic
        # mode closes the shutter again. This could be achieved by automatically disabling the
        # manual mode or if the state should be remembered then the max function should be used

        # create a move and use the max function for output calculation
        manu = ValueMode('Manual', initial_value=5, logger=log, calc_value_func=max)
        item.add_mode(10, manu)    # overwrite the earlier added mode

        print_heading('Use of functions')

        auto.set_value(7)   # manu uses max, so the value from auto is used
        auto.set_value(3)

    def item_update(self, event):
        print(f'Item value: {event.value}')

MyMultiModeItemTestRule()
--------------------------------------------------------------------------------
Automatically disable mode
--------------------------------------------------------------------------------
Prio  0: <ValueMode Automatic enabled: True, value: 5>
Prio 10: <ValueMode Manual enabled: True, value: 10>

[AdvancedMultiMode]     INFO | [x] Automatic: 11
[AdvancedMultiMode]     INFO | [ ] Manual (function)
Item value: 11
[AdvancedMultiMode]     INFO | [x] Automatic: 4
Item value: 4

--------------------------------------------------------------------------------
Use of functions
--------------------------------------------------------------------------------
Prio  0: <ValueMode Automatic enabled: True, value: 4>
Prio 10: <ValueMode Manual enabled: True, value: 5>

[AdvancedMultiMode]     INFO | [x] Automatic: 7
Item value: 7
[AdvancedMultiMode]     INFO | [x] Automatic: 3
Item value: 5

Example SwitchItemValueMode

The SwitchItemMode is same as ValueMode but enabled/disabled of the mode is controlled by a openHAB SwitchItem. This is very useful if the mode shall be deactivated from the openHAB sitemaps.

import HABApp
from HABApp.openhab.items import SwitchItem
from HABApp.util.multimode import MultiModeItem, SwitchItemValueMode, ValueMode

class MyMultiModeItemTestRule(HABApp.Rule):
    def __init__(self):
        super().__init__()

        # create a new MultiModeItem
        item = MultiModeItem.get_create_item('MultiModeTestItem')

        # this switch allows to enable/disable the mode
        switch = SwitchItem.get_item('Automatic_Enabled')
        print(f'Switch is {switch}')

        # this is how the switch gets linked to the mode
        # if the switch is on, the mode is on, too
        mode = SwitchItemValueMode('Automatic', switch)
        print(mode)

        # Use invert_switch if the desired behaviour is
        # if the switch is off, the mode is on
        mode = SwitchItemValueMode('AutomaticOff', switch, invert_switch=True)
        print(mode)

        # This shows how the SwitchItemValueMode can be used to disable any logic except for the manual mode.
        # Now everything can be enabled/disabled from the openHAB sitemap
        item.add_mode(100, mode)
        item.add_mode(101, ValueMode('Manual'))

MyMultiModeItemTestRule()
Switch is ON
<SwitchItemValueMode Automatic enabled: True, value: None>
<SwitchItemValueMode AutomaticOff enabled: False, value: None>

Documentation

MultiModeItem

class MultiModeItem(name, initial_value=None)

Prioritizer Item

classmethod get_create_item(name, logger=None, initial_value=None)

Creates a new item in HABApp and returns it or returns the already existing one with the given name

Parameters
  • name (str) – item name

  • initial_value – state the item will have if it gets created

Returns

item

remove_mode(name)

Remove mode if it exists

Parameters

name (str) – name of the mode (case insensitive)

Return type

bool

Returns

True if something was removed, False if nothing was found

add_mode(priority, mode)

Add a new mode to the item, if it already exists it will be overwritten

Parameters
  • priority (int) – priority of the mode

  • mode (BaseMode) – instance of the MultiMode class

Return type

MultiModeItem

all_modes()

Returns a sorted list containing tuples with the priority and the mode

Return type

List[Tuple[int, BaseMode]]

Returns

List with priorities and modes

get_mode(name)

Returns a created mode

Parameters

name (str) – name of the mode (case insensitive)

Return type

BaseMode

Returns

The requested MultiModeValue

calculate_value()

Recalculate the output value and post the state to the event bus (if it is not None)

Return type

Any

Returns

new value

ValueMode

class ValueMode(name, initial_value=None, enabled=None, enable_on_value=True, logger=None, auto_disable_after=None, auto_disable_func=None, calc_value_func=None)
Variables
  • last_update (datetime.datetime) – Timestamp of the last update/enable of this value

  • auto_disable_after (Optional[datetime.timedelta]) – Automatically disable this mode after a given timedelta on the next recalculation

  • auto_disable_func (Optional[Callable[[Any, Any], bool]]) – Function which can be used to disable this mode. Any function that accepts two Arguments can be used. First arg is value with lower priority, second argument is own value. Return True to disable this mode.

  • calc_value_func (Optional[Callable[[Any, Any], Any]]) – Function to calculate the new value (e.g. min or max). Any function that accepts two Arguments can be used. First arg is value with lower priority, second argument is own value.

property value

Returns the current value

property enabled: bool

Returns if the value is enabled

Return type

bool

set_value(value, only_on_change=False)

Set new value and recalculate overall value. If enable_on_value is set, setting a value will also enable the mode.

Parameters
  • value – new value

  • only_on_change (bool) – will set/enable the mode only if value differs or the mode is disabled

set_enabled(value, only_on_change=False)

Enable or disable this value and recalculate overall value

Parameters
  • value (bool) – True/False

  • only_on_change (bool) – enable only on change

Returns

cancel()

Remove the mode from the parent MultiModeItem and stop processing it

SwitchItemValueMode

class SwitchItemValueMode(name, switch_item, invert_switch=False, initial_value=None, logger=None, auto_disable_after=None, auto_disable_func=None, calc_value_func=None)

SwitchItemMode, same as ValueMode but enabled/disabled of the mode is controlled by a OpenHAB SwitchItem

Variables
  • last_update (datetime.datetime) – Timestamp of the last update/enable of this value

  • auto_disable_after (Optional[datetime.timedelta]) – Automatically disable this mode after a given timedelta on the next recalculation

  • auto_disable_func (Optional[Callable[[Any, Any], bool]]) – Function which can be used to disable this mode. Any function that accepts two Arguments can be used. First arg is value with lower priority, second argument is own value. Return True to disable this mode.

  • calc_value_func (Optional[Callable[[Any, Any], Any]]) – Function to calculate the new value (e.g. min or max). Any function that accepts two Arguments can be used. First arg is value with lower priority, second argument is own value.

cancel()

Remove the mode from the parent MultiModeItem and stop processing it

property enabled: bool

Returns if the value is enabled

Return type

bool

set_value(value, only_on_change=False)

Set new value and recalculate overall value. If enable_on_value is set, setting a value will also enable the mode.

Parameters
  • value – new value

  • only_on_change (bool) – will set/enable the mode only if value differs or the mode is disabled

property value

Returns the current value