Home2L - Python API  v1.2-2-ga4fe (2023-04-15)
Smart Tools for a Private Home
Functions
Rules

Description

Running functions on resource updates, on events or at certain times.

Collaboration diagram for Rules:

Functions

def RunOnEvent (func, rcSet, data=None, subscrId=None)
 Define a function to be called on events. More...
 
def onEvent (*rcSet)
 Decorator to define a function to be called on events. More...
 
def RunOnUpdate (func, rcSet, data=None, subscrId=None)
 Define a function to be called on value/state changes of resources. More...
 
def onUpdate (*rcSet)
 Decorator to define a function to be called on value/state changes. More...
 
def Connect (target, rcSet, func=lambda x:x, attrs=None, id=None, priority=None, t0=None, hysteresis=None, delDelay=None, subscrId=None)
 Define a connector between resources. More...
 
def connect (target, rcSet, attrs=None, id=None, priority=None, t0=None, hysteresis=None, delDelay=None)
 Decorator to define a connector. More...
 
def RunAt (func, t=0, dt=0, args=None, subscrId=None)
 Let a function be called at a given time or periodically. More...
 
def at (t=0, dt=0, args=None)
 Decorator to let a function be called at a given time or periodically. More...
 
def RunDaily (func, hostSet=None, data=None, subscrId=None)
 Let a function be called daily for setting permanent requests. More...
 
def daily (*hostSet)
 Decorator to let a function be called daily for setting permanent requests. More...
 

Function Documentation

◆ RunOnEvent()

def home2l.RunOnEvent (   func,
  rcSet,
  data = None,
  subscrId = None 
)

Define a function to be called on events.

Define a function to be called whenever an event for a set of
resources occurs.

'rcSet' can either be a 'CResource' object, an URI string or a tuple
or a list of any of those. 'data' is an optional reference to user
data that will be passed unchanged to any 'func' invocations.

For each event encountered, the function 'func' will be called as follows:

    func (ev, rc, vs [ , data ] )

where '(ERcEventType) ev' is the type of event, 'rc' is the affected
resource, and, if applicable, 'vs' is the new value and state that
has been reported for the resource.

The event type 'ev' can be one of the following:
    rceValueStateChanged : The value or state has changed.
    rceConnected         : The connection has been (re-)established.
    rceDisconnected      : The connection has been lost.

Unlike 'RunOnUpdate', the function 'func' will be called for each single
event in the correct order in time, so that no temporary value changes
get lost.

The parameter 'subscrId' sets the subscriber ID. It can usually be left
unspecified, in which case, the function name is used as an identifier.

◆ onEvent()

def home2l.onEvent ( rcSet)

Decorator to define a function to be called on events.

Decorator variant of 'RunOnEvent()'.

This decorator allows to easily let a function be executed on given events
as follows:

|   @onEvent (<resource set>)
|   def MyFunc (ev, rc, vs):
|     ...

◆ RunOnUpdate()

def home2l.RunOnUpdate (   func,
  rcSet,
  data = None,
  subscrId = None 
)

Define a function to be called on value/state changes of resources.

Define a function to be called on value/state changes of resources.

'rcSet' can either be a 'CResource' object, an URI string or a tuple
or a list of any of those. 'data' is an optional reference to user
data that will be passed unchanged to any 'func' invocations.

If any of the specified resources changes its value or state,
the function 'func' will be called as follows

    func (a, b, c, ... [ , data ] )

where "a, b, c, ..." are arbitrary positional arguments, which (if present)
are filled with the current values of the resources specified by 'rcSet'.
The arguments are optional, and their names can be chosen arbitratily.
Values are filled in in the same order as the ordering of the resources
specified by 'rcSet'. The values are obtained by calling 'CResource.Value()'.

Unlike 'RunOnEvent', only 'rceValueStateChanged' events cause
invocations of 'func', and multiple events quickly following each
other may be merged to a single invocation, so that only the last value
is actually reported. For this reason, this mechanism is generally more
efficient and should be preferred if short intermediate value changes
are not of interest.

Important: Resource states and values may change any time. If resource
values (or states) are queried again within the function, they may differ
from the result of a previous query.

The parameter 'subscrId' sets the subscriber ID. It can usually be left
unspecified, in which case, the function name is used as an identifier.

◆ onUpdate()

def home2l.onUpdate ( rcSet)

Decorator to define a function to be called on value/state changes.

Decorator variant of 'RunOnUpdate()'.

This decorator allows to easily define a function executed on value changes
as follows:

|   @onUpdate ( <resource set> )
|   def MyFunc ():
|     ...

◆ Connect()

def home2l.Connect (   target,
  rcSet,
  func = lambda x: x,
  attrs = None,
  id = None,
  priority = None,
  t0 = None,
  hysteresis = None,
  delDelay = None,
  subscrId = None 
)

Define a connector between resources.

Connect source (sensor) resource(s) to a target (actor) resource.

This creates a connector, which continuously updates requests for the target
resource 'target' based on a transfer function depending on the values of
the resources given by 'rcSet'.

'target' specifies the target resource - either by its URI or by a
'CResource' reference.

'rcSet' specifies the source (sensor) resource(s). It may be a single
resource or a tuple or list of multiple resources.

'func' is the transfer function transforming source (sensor) values into
request values for the target resource. It is called as:

    value = func (a, b, c, ...)

'a, b, c, ...' are positional arguments with arbitrary names by which the
values of the 'rcSet' resources are passed. The function must return the actual
value requested for 'target'. If 'None' is returned, the request is deleted
(eventually after a delay specified by 'delDelay'). The default for 'func' is
the identiy function, transporting source values directly without modifications.

The remaining arguments ('attrs', 'id', ..., 'delDelay') specify the request
attributes used for placing the respective requests. See RcSetRequest() for
details. Multiple connectors can be defined with different request IDs
and priorities, and the request resolution mechanism will resolve them
properly. This way, complex automation rules can be specified (one example is
given below).

Notes on writing transfer functions ('func'):

1. Any of the arguments 'a, b, c, ...' may also be 'None' if the respective
   resource has a state of 'rcsUnkown'. This must be considered when writing
   transfer functions. For example, to check whether a Boolean resource x is
   known and false, the expression should be 'if x == False: ...' instead of
   'if not x: ...', since in the latter case 'not x' would evaluate as true,
   if x is 'None'. In general, Boolean resource values should always be used
   in conjunction with a comparision. For example, an expression like
   'a and b' may be written as '(a == True) and (b != False)', which implies,
   that a value of 'None' is treated like 'False' for 'a', but like 'True'
   for 'b'.

2. To facilitate function writing, especially if the source resources have
   numerical types, 'TypeError' exceptions are caught by the caller and result
   in a return value of 'None'. 'TypeError' exceptions are typically raised
   if one of the arguments of an arithmetic exception is 'None'.

3. The transfer function is evaluated whenever a value/state change occurs for
   any of the resources of 'rcSet', but only then. If resources are read
   inside the gate function, they usually must be contained in 'rcSet'.
   It is good practice to not read out resources directly, but only rely
   on the arguments passed to the gate function.

Examples:

- Let a light be switched on for 5 seconds if a motion sensor is activated, but only
  at night time:

  |   rcLight = RcGet ('/alias/light')  # get reference to the light resource
  |   rcLight.SetDefault (0)            # set default request: light off (0)
  |   Connect (rcLight, '/alias/day', lamda x: 0 if x == True else None, attrs = '#daytime *3')
  |     # keep light off (0) at day time (True) at high priority (*3)
  |   Connect (rcLight, '/alias/motion', lamda x: 1 if x == True else None, attrs = '#motion *2', delDelay = '5s')
  |     # switch light on (1) if the motion detector is active at a lower
  |     # priority (*2); after the motion sensor becomes inactive, the request
  |     # is deleted with a delay of 5 seconds ('5s')

- Force the light off at day time, but during rainy weather:

  |   Connect (rcLight, ('/alias/motion', '/alias/rain'), lamda m, r: 0 if m == True and not r == True else None)

  or alternatively (decorator variant):

  |   @connect (rcLight, ('/alias/motion', '/alias/rain')):
  |   def LightOffDuringDayAndGoodWeather (motion, rain):
  |     # (some additional code may be added here)
  |     if motion == True and not rain == True: return 0
  |     else: return None

◆ connect()

def home2l.connect (   target,
  rcSet,
  attrs = None,
  id = None,
  priority = None,
  t0 = None,
  hysteresis = None,
  delDelay = None 
)

Decorator to define a connector.

Decorator variant of 'Connect()'.

This allows to decorate a transfer function, thus creating a connector,
which continuously updates requests for the target resource 'target' depending
on the values of the resources given by 'rcSet':

|   @connect ( <target>, <rcSet> [, <request attrs>] )
|   def TransferFunc (a, b, c, ...):
|     ...
|     return <value>

◆ RunAt()

def home2l.RunAt (   func,
  t = 0,
  dt = 0,
  args = None,
  subscrId = None 
)

Let a function be called at a given time or periodically.

Define a function to be called at a given time, optionally repeated
at regular intervals.

The starting time 't' can be specified by anything accepted by 'TicksAbsOf()'.
The interval 'dt' (if given) can be anything accepted by 'TicksRelOf()'.
If 'dt' <= 0, the timer is executed once and then deactivated. Otherwise,
the function is repeated regularly.

The function 'func' will be called as follows:

    func (<args>)

where <args> is the 'args' object passed to 'RunAt()', if 'func' has just one
argument and 'args' it is neither a tuple nor a dictionary.
If 'func' has at least two arguments and 'args' is a tuple or a dictionary,
its components are passed as individual arguments to 'func', either as
positional (tuple) or keyword (dictionary) arguments, respectively.

If 'subscrId' is not set, the function name will be used as an ID.
Calling this function again with the same ID causes the old timer to be deleted.
Presently, there is no mechanism to delete a previously defined timer.

◆ at()

def home2l.at (   t = 0,
  dt = 0,
  args = None 
)

Decorator to let a function be called at a given time or periodically.

Decorator variant of 'RunAt()'.

This decorator allows to execute a function at given times
as follows:

|   @at ( t = <t> [, dt = <interval>] [, args = <args>] )
|   def MyTimedFunc ( [<args>] ):
|     ...

◆ RunDaily()

def home2l.RunDaily (   func,
  hostSet = None,
  data = None,
  subscrId = None 
)

Let a function be called daily for setting permanent requests.

Define a function to be called daily or whenever one of the hosts becomes
reachable (again).

This can be used to set and keep persistent permanent requests in rules scripts.
'hostSet' can either be a single string or a tuple or a list of strings.
'data' is an optional reference to user data that will be passed unchanged to
any 'func' invocations.

Whenever a host or a set of hosts becomes reachable, the function 'func' will
be called as follows:

    func ( [host [ , data ] ] )

'host' is the host name for which rules must be updated.

Important: On each host in the set, the 'timer' driver must be enabled.

The parameter 'subscrId' can usually be left unspecified. In this case, the function
names are used as identifiers.

◆ daily()

def home2l.daily ( hostSet)

Decorator to let a function be called daily for setting permanent requests.

Decorator variant of 'RunDaily'.

This decorator allows to easily define a function executed daily or whenever
a host becomes reachable (again) as follows:

|   @daily ( [ <host set> ] )
|   def MyFunc (host):
|     ...