-
Notifications
You must be signed in to change notification settings - Fork 1
Configuration Reference Guide
This page is a comprehensive documentation of the Xml configuration of Homewatcher.
The most usual way to proceed is to save the Xml data to a file whose name is given as an argument of the Homewatcher daemon. Please refer to the Getting Started page for details. Advanced user may prefer to start a daemon from a Python script. In that case, creating an instance of homewatcher.configuration.Configuration
programmatically may be suitable as well.
Before reading a configuration example, the user should note that part of the internal state of a running instance of Homewatcher is stored in Linknx objects. Such objects are referred to with their identifier specified in attributes that end with "objectId". Few of them are mandatory, most are optional but in both cases, this is up to the end-user to define the appropriate objects in its Linknx configuration to make things work. Those objects reflects the state of the alarm system that may be of interest for the end-user (like whether a sensor is enabled or whether an alert has already been raised, for instance) and may be helpful to link Homewatcher with a supervisor application.
In a future release, some bindings with Linknx objects may become optional without losing the associated functionality. For instance, if knowing if a sensor is enabled or not is not of interest for you, you may want to get rid of the enabledObjectId attribute in your configuration. As of version 1, this attribute is mandatory. See issue #14 for details.
As a general rule, a configuration that is incomplete or inconsistent will be rejected by Homewatcher at startup with a message explaining the problem. That should limit the risk of setting up an unsupported configuration.
Let's consider and detail the following configuration sample that covers the most commonly used features of Homewatcher.
<?xml version="1.0" ?>
<config>
<services>
<linknx host="127.0.0.1" port="1030"/>
<daemon host="127.0.0.1" port="1031"/>
</services>
<modes objectId="Mode">
<mode name="Presence" value="1">
<sensor>GarageTemperatureProbe</sensor>
<event type="left">
<action type="set-value" id="AllLights" value="off"/>
</event>
</mode>
<mode name="Away" value="2">
<sensor>EntranceDoor</sensor>
<sensor>GarageDoor</sensor>
<sensor>GarageTemperatureProbe</sensor>
</mode>
<mode name="Night" value="3">
<sensor>EntranceDoor</sensor>
<sensor>GarageTemperatureProbe</sensor>
</mode>
<event type="entered">
<action type="send-email" to="[email protected]">
<subject>Entered mode <context type="mode.current"/></subject>
<body>Mode has changed.</body>
</action>
<action type="copy-value" from="Mode" to="AppliedMode"/>
</event>
<event type="left">
<action type="copy-value" from="AppliedMode" to="PreviousMode"/>
</event>
</modes>
<alerts>
<alert name="Intrusion" persistenceObjectId="IntrusionPersistence" inhibitionObjectId="IntrusionInhibition">
<event type="activated">
<action type="send-email" to="[email protected]" subject="Intrusion!">Intrusion alert!</action>
<action type="set-value" id="Siren" value="on"/>
</event>
<event type="paused">
<action type="set-value" id="Siren" value="off"/>
</event>
</alert>
<alert name="Temperature" persistenceObjectId="TemperaturePersistence">
<event type="activated">
<action type="set-value" id="GarageFan" value="on"/>
</event>
<event type="paused">
<action type="set-value" id="GarageFan" value="off"/>
</event>
</alert>
</alerts>
<sensors>
<sensor name="EntranceDoor" type="boolean" watchedObjectId="EntranceDoorTrigger" enabledObjectId="EntranceDoorEnabled" alert="Intrusion" activationDelay="60" prealertDuration="30" alertDuration="300"/>
<sensor name="GarageDoor" type="boolean" watchedObjectId="GarageDoorTrigger" enabledObjectId="GarageDoorEnabled" alert="Intrusion" activationDelay="10" prealertDuration="0" alertDuration="300">
<activationCriterion type="and">
<activationCriterion type="sensor" sensor="EntranceDoor" whenTriggered="false"/>
<activationCriterion type="sensor" sensor="GarageDoor" whenTriggered="false"/>
</activationCriterion>
</sensor>
<sensor name="GarageTemperatureProbe" alert="Temperature" type="float" watchedObjectId="GarageTemperatureValue" enabledObjectId="GarageTemperatureProbeEnabled" activationDelay="0" prealertDuration="0" alertDuration="0" upperBound="45" hysteresis="2"/>
</sensors>
</config>
Xml element: <services/>
Declares services that are connected to Homewatcher.
Xml element: <linknx/>
Declares the connection with the Linknx daemon.
Attributes:
- host: name or IP address of the server machine running the Linknx daemon
- port: TCP port the XML server of Linknx is listening on (see xmlserver directive in Linknx configuration)
This element is optional and defaults to <linknx host="127.0.0.1" port="1028"/>
.
Xml element: <daemon/>
Homewatcher is built on top of a Pyknx communicator to interact bidirectionally with Linknx. This section configures how Linknx will connect to this Pyknx communicator when the Homewatcher daemon is running (see hwdaemon.py).
- host: name or IP address of the network interface the Homewatcher daemon listens on.
- port: port the daemon binds to for incoming requests from Linknx.
This element is optional and defaults to <daemon host="127.0.0.1" port="1029"/>
.
Xml element: <modes/>
The alarm system can run in various modes, to reflect the different use cases of your installation. For instance, you may want to define a mode to use when you are not at home so that your windows and doors can be monitored and another mode when you are at home.
Attributes:
- objectId: declares the name of the Linknx object that will store the integer value associated with the active mode.
Children elements:
-
<event/>
(new in v1.1): declaration of events that are global to all modes. The syntax of this section is the same as for events defined inside a mode object. Declaring an event here is strictly equivalent as defining it in every mode object and is only provided for convenience.
Xml element: <mode/>
Attributes:
- name: a string of characters that uniquely identifies the mode.
-
value: an integer value that is stored in the object referred to by
<modes objectId="xxx"/>
when the mode is the active one.
Children elements:
-
<sensor/>
: define the names of sensors to be active when the mode is active. -
<event/>
: declares the actions to be executed when mode is switched on or off. See Mode Events
Xml element: <event/>
Attributes:
- type: defines when this event is raised. It is either entered or left to execute actions when the mode becomes respectively active and inactive
Children elements:
-
<action/>
: declaration of the action to execute when event is fired. Action's execution is delegated to Linknx, therefore the syntax for actions is the same as for Linknx actions.
Xml element: <alerts/>
This section declares the various types of alerts that can be raised by Homewatcher and the actions to execute on each states of those alerts.
Children elements:
-
<event/>
(new in v1.1): declaration of events that are global to all alerts. The syntax of this section is the same as for events defined inside an alert object. Declaring an event here is strictly equivalent as defining it in every alert object and is only provided for convenience.
Xml element: <alert/>
Attributes:
- name: a string of characters that uniquely identifies the alert.
- persistenceObjectId: the name of the Linknx 1.001 object to use to store the fact that the alert has been active in the past. This object is optional and is used to keep track of alerts even when they have left their 'active' state. This object is put to "on" by Homewatcher when the alert first enters in the "active" state. Then it remains "on" until the object is manually switched off in Linknx. Please note that defining this object is mandatory to benefit from the "resumed" status of the alert. If not defined, when the alert reaches its "paused" state, it goes immediately to the "stopped" one. If not defined and a sensor associated with this alert is triggered in the future, this will be considered a new alert, not the continuation of the previous one.
- inhibitionObjectId: this optional attribute refers to the name of the Linknx 1.001 object that makes the alert ignore sensors that are triggered after it has been set to True. This is useful to temporarily deactivate an alert. Note that for the inhibition to have an effect, the inhibition object must be set to True before the sensor is actually triggered. Once the process of prealert is started, this object cannot be used to abort it.
Children elements:
-
<event/>
: declares the actions to be executed when alert's status changes. See alert events.
Xml element: <event/>
Attributes:
- type: string of characters that identifies the status change to hook on. It is one of prealert started, sensor joined, sensor left, activated, deactivated, paused, resumed, stopped. Refer to the alert lifecycle flowchart to determine the position of those events in the alert lifecycle.
Children elements:
-
<action/>
: declaration of the action to execute when event is fired. Action's execution is delegated to Linknx
Xml element: <action/>
Actions' execution is delegated to Linknx, therefore the syntax for actions is the same as for Linknx actions.
If your syntax works in the Linknx's configuration file, then it should work here.
Parameterizable "send-email" or "send-sms" Actions (added in v1.1), and "shell-cmd" (added in v1.3.0)
Homewatcher provides a few enhancements to the syntax supported by Linknx for both "send-email" and "send-sms" actions, in order to define context-dependent messages in your configuration file.
For instance, the following piece of configuration sends an email that lists the sensors currently enabled and shows the current mode's name in its subject:
<action type="send-email" to="[email protected]">
<subject>Entered mode <context type="mode.current"/></subject>
<body>New mode. <context type="mode.enabled-sensors"/></body>
</action>
Notice that the subject attribute expected by Linknx is replaced with a <subject>
element whose content is parameterizable with optional <context/>
elements. You can find more details about those <context/>
elements below.
Similarly, Linknx expects the message body to be written as a text child node of the <action/>
element. Alternatively, you can define it in a <body/>
element that in turn can contain context-specific child elements.
For text messages (SMS), the syntax has been enhanced quite the same way:
<action type="send-sms">
<value>Current mode is now <context type="mode.current"/></value>
</action>
As for emails, the value attribute can be replaced with a <value/>
element filled with a mix of static text and child <context/>
elements.
Since version 1.3.0, the same logic is used for shell commands:
<action type="shell-cmd">
<cmd>echo "Current mode is now <context type="mode.current"/>"</cmd>
</action>
Xml element: <context/>
Attributes:
-
type: this attribute defines the contextual information to print.
There may be additional attributes depending on the type of context. Moreover, plugins may extend the list of built-in context handler types.
Out of the box and without any plugin, the type attribute can be one of {alert.name, alert.sensors-status, mode.current, mode.enabled-sensors}. More details below.
Other context information can be quite easy to retrieve. You can either try to add a context handler of your own by means of a plugin or request this new feature.
This context prints the name of the alert related to the event. This context type is only valid in an alert event.
There is no additional attribute for this handler.
This context prints the list of sensors in prealert, in alert and in pause. Thus, it is valid only in an alert event.
This type supports additional optional attributes:
- format: one of {bulleted, inline} to format sensor names in a bullet list or a comma-separated list.
- inAlert, inPrealert, inPause: when set to "true", these attributes make sensors respectively in alert, in prealert or paused appear in the generated text. These attributes defaults to "true", set them to "false" to filter the output text.
Prints the list of sensors that are currently enabled. There is no specific attribute for this handler. This type supports additional optional attributes:
- includesPending: one of {true, false} to include in the list the sensors that are currently running their activation timer. These are not enabled yet but are scheduled to be enabled shortly. This attribute defaults to false.
Prints the name of the mode currently active. There is no specific attribute for this handler.
Xml element: <sensors/>
This section declares all sensors of the Homewatcher instance. The concept of sensor is quite virtual and some sensors may even not correspond to real, concrete KNX devices of your installation. For instance, with some additional scripts and binding, it is possible to use a simple video device connected to a motion detection software as a motion detection sensor.
Xml element: <sensor/>
There are two built-in types of sensors: boolean and float.
This type represents a sensor that has a binary state: it is on or off. It is designed to work with a Linknx object of type 1.001, though other types that may be interpreted as boolean values may work as well. By default, the sensor is assumed to be triggered when its underlying Linknx object is set to on but this can be tuned by means of the triggerValue attribute.
This type represents a sensor based on a Linknx object that provides a floating point real value (integers work fine as well, of course). This is a kind of probe that gets triggered when the value goes beyond either the upper or lower bound.
- name: a string of characters that uniquely identifies the sensor.
- type: type of sensor. This value rules the behaviour of the sensor. It is one of boolean or float. Both types are described below.
For advanced usage, it is also possible to set this attribute to the name of any other
<sensor isClass="true"/>
declaration. Please refer to the advanced configuration features section for details.
- alert: name of the alert object this sensor is associated with. Each sensor is related to one and only one alert type. When the sensor is triggered, it raises this alert.
-
enabledObjectId: identifier of the Linknx object of type 1.001 that is used to store the current enabled state of the sensor. If a sensor is triggered while it is enabled, it raises its corresponding alert. When disabled, it does not raise the alert. Sensors are automatically enabled and disabled according to the mode object currently active. See the
<sensor/>
inner element of a mode definition for details. Please note that this attribute is mandatory even if you are not interested in getting access to this enabled state with a supervisor, for instance. This limitation may be removed in future versions (see issue #14). - watchedObjectId: identifier of the Linknx object that provides the sensor with a value to monitor. For a boolean sensor, this object must be of type 1.001 (for instance, the one that reflects the current status of a KNX opening sensor in your house). For a float sensor, it must contain a numerical value.
- activationDelay: number of seconds to wait to activate this sensor after a mode that includes it has become active. This attributes defaults to "0". For instance, if the mode is changed with a device inside the protected area, it is advisable to set the activation delay to at least a few seconds, to let you get out of it without firing the alert.
- prealertDuration: after the sensor has been triggered (if it is enabled), this attribute defines the number of seconds to wait before alert should become active. This attribute is optional and defaults to "0". Refer to the alert lifecycle flow chart for details. Once a sensor has been triggered and has entered its prealert phase, it will raise the alert once prealertDuration is reached, unless it is disabled meanwhile (either by switching to another mode that does not include it or by setting the alert's persistence object to off). Note that releasing the sensor's trigger during the prealert does not cancel the pending alert.
- alertDuration: this attribute defines the number of seconds the sensor's alert phase lasts. It is optional and defaults to "0". The corresponding alert will stick to its activated status as long as at least one of its related sensors is running its alert phase. Once all sensors have reached their respective alertDuration, the alert goes either to the paused status if the persistent alert feature is available or directly to the stopped status otherwise.
There is much to learn about activationDelay, prealertDuration and alertDuration by using their Xml element equivalents. See at the end of this section.
- persistenceObjectId: this optional attribute plays a role similar to the persistence object for alerts, but this one is changed on a per-sensor basis. If defined, the Linknx object referred to by the name in the attribute is set to on when the sensor enters its alert phase. It is switched back off either manually or when the alert's persistence object is switched off.
- triggerValue: this attribute is meaningful for boolean sensors only. It is optional and defaults to true. If its value is true (resp. false), the sensor is triggered when the watchedObject is on (resp. off).
- lowerBound and upperBound: those attributes apply to float sensors. At least one of them must be defined. They represent the lower and upper bounds of an acceptable watched real value. If the watched value goes out of any defined bound, the sensor is triggered.
- hysteresis: this attribute is meaningful for float sensors only. It represents the "neutral zone" of the sensor around its bounds, once it is triggered. For instance, if the upper bound is 30 and hysteresis is 2, once sensor is triggered, the monitored value must become less than 30-2=28 for the sensor to be released.
-
<activationCriterion/>
: optional element that allows to prevent sensor from being enabled until a given criterion is not satisfied. If the criterion is not satisfied, the delay specified with activationDelay is not consumed. This delay starts as soon as the criterion is valid and aborts if it gets invalid before the activationDelay timeout is reached.
By default, a sensor always defines a criterion that is equivalent to<activationCriterion type="sensor" sensor="{name}" whenTriggered="false"/>
where {name} is replaced with the sensor's name. That means that sensor cannot be enabled if it is triggered at the time it should be activated. That prevents alert from being immediately raised because of sensors that were already triggered before changing the alarm mode. Defining an explicit activation criterion for a sensor disables the default behaviour. That is why the "GarageDoor" sensor in the sample configuration redefines the default criterion.
There are additional recognized children elements that can be used to replace their simplistic attribute equivalent:
<activationDelay/>
<prealertDuration/>
<alertDuration/>
Those elements allow for type-dependent values thanks to a more verbose syntax:
<activationDelay>
<value>0</value>
<value mode="Away">12</value>
<value mode="Night">10</value>
</activationDelay>
This sample declares an activation delay that should last 12 seconds when switching to a mode named "Away", 10 seconds when switching to "Night" and 0 second for all other modes.
Both attribute-style and element-style definitions can be mixed. In that case, the attribute definition declares the value to apply to all modes and <value/>
children must all define the mode to override.
In a non-trivial configuration, it is very likely that some sensors have similar definitions. For instance, if all windows and doors are equipped with opening sensor devices, each of them is quite identical to the others in terms of behaviour and so is the definition in the Xml. Duplicating Xml lines may sound acceptable when designing the installation but it will lead to a kind of maintenance hell is you have ten or more sensors that behave the same.
The answer to this problem is class inheritance. Software developers would certainly have already understood what it is all about. For normal people, let me explain that with an example:
<config>
<sensors>
<sensor name="EntranceDoor" type="boolean" watchedObjectId="EntranceDoorTrigger" enabledObjectId="EntranceDoorEnabled" alert="Intrusion" activationDelay="60" prealertDuration="30" alertDuration="300"/>
<sensor name="GardenDoor" type="boolean" watchedObjectId="GardenDoorTrigger" enabledObjectId="GardenDoorEnabled" alert="Intrusion" activationDelay="60" prealertDuration="30" alertDuration="300"/>
<sensor name="GarageDoor" type="boolean" watchedObjectId="GarageDoorTrigger" enabledObjectId="GarageDoorEnabled" alert="Intrusion" activationDelay="10" prealertDuration="0">
<alertDuration>
<value>300</value>
<value mode="Night">100</value>
</alertDuration>
<activationCriterion type="and">
<activationCriterion type="sensor" sensor="EntranceDoor" whenTriggered="false"/>
<activationCriterion type="sensor" sensor="GarageDoor" whenTriggered="false"/>
</activationCriterion>
</sensor>
</sensors>
</config>
Note: for simplicity sake, the sample above is not a valid configuration as it does only contain the section dedicated to sensors declaration, which is the one for which the concept of sensor classes apply.
In this example, sensors EntranceDoor, GardenDoor and GarageDoor are very similar. Same type, same delays and the Linknx objects they are bound to have names built on the same pattern. This can be simplified to:
<config>
<sensors>
<sensor isClass="true" name="Door" type="boolean" watchedObjectId="{name}Trigger" enabledObjectId="{name}Enabled" alert="Intrusion" activationDelay="60" prealertDuration="30" alertDuration="300"/>
<sensor name="EntranceDoor" type="Door"/>
<sensor name="GardenDoor" type="Door"/>
<sensor name="GarageDoor" type="Door" activationDelay="10" prealertDuration="0">
<alertDuration>
<value mode="Night">100</value>
</alertDuration>
<activationCriterion type="and">
<activationCriterion type="sensor" sensor="EntranceDoor" whenTriggered="false"/>
<activationCriterion type="sensor" sensor="GarageDoor" whenTriggered="false"/>
</activationCriterion>
</sensor>
</sensors>
</config>
This sample is strictly equivalent to the previous one once loaded in Homewatcher. Here are some details:
- isClass attribute: this optional attribute defaults to false. When true, it declares a sensor that is aimed at being a template for the definition of other concrete sensors. Such class sensors are not concrete sensors that can be enabled to participate in an alert. As a consequence, they are not required to define all mandatory attributes. Other sensor that specify this sensor class in their type attribute inherit the attributes of this class, unless they explicitly redefine them. And of course, sensor classes can be themselves based on other sensor classes (anyway, the built-in boolean and float types are nothing but classes!)
- type=Door: Entrancedoor (as well as GardenDoor and GarageDoor) is now based on the "Door" sensor class, which is in turn based on the built-in "boolean" class. This implies that EntranceDoor inherits its attributes from its base class "Door", unless it redefines the attributes (which is not the case for EntranceDoor). GarageDoor inherits all attributes from Door except activationDelay, prealertDuration and the definition of the activationCriterion which are overriden for this very sensor.
- GarageDoor does not have to redefine the alert duration of 300s since it is inherited from Door. Its declaration is limited to specifying a shorter timeout when in Night mode.
- watchedObjectId="{name}Trigger": in the value of this attribute, {name} is replaced with the value of the attribute name of the concrete sensor. For the sensor named "EntranceDoor", this attributes evaluates to "EntranceDoorTrigger" and so on. Any Xml attribute defined on the concrete sensor can be used as a parameter for other attributes, even custom attributes that do not have a real meaning for Homewatcher. For instance, the sample below is still equivalent to the previous ones:
<config>
<sensors>
<sensor isClass="true" name="Door" type="boolean" watchedObjectId="{location}DoorTrigger" enabledObjectId="{location}Enabled" alert="Intrusion" activationDelay="60" prealertDuration="30" alertDuration="300"/>
<sensor name="EntranceDoor" type="Door" location="Entrance"/>
<sensor name="GardenDoor" type="Door" location="Garden"/>
<sensor name="GarageDoor" type="Door" location="Garage" activationDelay="10" prealertDuration="0">
<alertDuration>
<value mode="Night">100</value>
</alertDuration>
<activationCriterion type="and">
<activationCriterion type="sensor" sensor="EntranceDoor" whenTriggered="false"/>
<activationCriterion type="sensor" sensor="GarageDoor" whenTriggered="false"/>
</activationCriterion>
</sensor>
</sensors>
</config>
Notice the attribute location that is not recognized as a configuration keyword by Homewatcher but that can be used as a parameter for other attributes.
If you use the inheritance mechanism, it can be of help to see what the actual configuration understood by Homewatcher looks like. That can help diagnose mistakes in the configuration. To do so, you can use the hwresolve.py utility script.