update esppilight lib

content of the library is not filtered on 433mhz only
This commit is contained in:
Florian committed 2018-11-28 20:41:37 +01:00
1 parent a275e48ee1
commit 67dd7ac078
1030 files changed
+203335 -116

No files matched your search

@@ -0,0 +1,76 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Dim
===
.. rubric:: Description
Dims a device to a dimlevel or starts a sequence from one dimlevel to another.
.. rubric:: Options
+----------+------------------+---------------------+-------------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+-------------------------------------------------------+
| DEVICE | |yes| | |yes| | Device(s) to change |
+----------+------------------+---------------------+-------------------------------------------------------+
| TO | |yes| | |no| | New dimlevel |
+----------+------------------+---------------------+-------------------------------------------------------+
.. versionadded:: 7.0
+----------+------------------+---------------------+-------------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+-------------------------------------------------------+
| FOR | |no| | |no| | | Determine how long this new state lasts before |
| | | | | we change back to the previous dimlevel and state |
+----------+------------------+---------------------+-------------------------------------------------------+
| AFTER | |no| | |no| | After how long do we want the new state to be set |
+----------+------------------+---------------------+-------------------------------------------------------+
| IN | |no| | |no| | | To be combined with FROM. In what time do we want |
| | | | | to change the dimlevel FROM x TO y |
+----------+------------------+---------------------+-------------------------------------------------------+
| FROM | |no| | |no| | | To be combined with IN. From what dimlevel do we |
| | | | | want to start a sequence to the target dimlevel |
+----------+------------------+---------------------+-------------------------------------------------------+
.. note:: Units for ``FOR``, ``AFTER``, and ``IN``
- MILLISECOND
- SECOND
- MINUTE
- HOUR
- DAY
.. rubric:: Examples
.. code-block:: console
IF 1 == 1 THEN dim DEVICE mainlight TO 15
IF 1 == 1 THEN dim DEVICE mainlight AND bookshelve AND hall TO 10
.. versionadded:: 7.0
.. code-block:: console
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FOR 10 MINUTE
IF 1 == 1 THEN dim DEVICE mainlight TO 15 AFTER 30 SECOND
IF 1 == 1 THEN dim DEVICE mainlight TO 15 AFTER 30 SECOND FOR 10 MINUTE
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FROM 0 IN 45 MINUTE
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FROM 0 IN 45 MINUTE FOR 15 MINUTE AFTER 5 MINUTE
IF 1 == 1 THEN switch DEVICE light TO off FOR 10 SECOND AFTER 30 MINUTE
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FOR '10 MINUTE'
IF 1 == 1 THEN dim DEVICE mainlight TO 15 AFTER '30 SECOND'
IF 1 == 1 THEN dim DEVICE mainlight TO 15 AFTER '30 SECOND' FOR '10 MINUTE'
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FROM 0 IN '45 MINUTE'
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FROM 0 IN '45 MINUTE' FOR '15 MINUTE' AFTER '5 MINUTE'
IF 1 == 1 THEN switch DEVICE light TO off FOR '10 SECOND' AFTER '30 MINUTE'
@@ -0,0 +1,21 @@
Actions
=======
.. versionadded:: 6.0
.. toctree::
:maxdepth: 1
dim
pushover
switch
toggle
.. versionadded:: 7.0
.. toctree::
:maxdepth: 1
label
pushbullet
sendmail
@@ -0,0 +1,59 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Label
=====
.. rubric:: Description
Changes the text and color of a generic label device.
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| DEVICE | |yes| | |yes| | Device(s) to change |
+----------+------------------+---------------------+---------------------------------------------------+
| TO | |yes| | |no| | New text |
+----------+------------------+---------------------+---------------------------------------------------+
| COLOR | |no| | |no| | New color. If omitted, color is set to black |
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| FOR | |no| | |no| | | Determine how long this new label lasts |
| | | | | before we change back to the previous label |
+----------+------------------+---------------------+---------------------------------------------------+
| AFTER | |no| | |no| | After how long do we want the new label to be set |
+----------+------------------+---------------------+---------------------------------------------------+
.. note:: Units for ``FOR`` and ``AFTER``
- MILLISECOND
- SECOND
- MINUTE
- HOUR
- DAY
.. rubric:: Examples
.. code-block:: console
IF 1 == 1 THEN label DEVICE tempLabel TO on
IF 1 == 1 THEN label DEVICE tempLabel AND humiLabel TO No information
IF 1 == 1 THEN label DEVICE tempLabel TO 23.5 FOR 10 SECOND
IF 1 == 1 THEN label DEVICE tempLabel TO Bell rang AFTER 30 SECOND
IF 1 == 1 THEN label DEVICE tempLabel TO None FOR 10 MINUTE AFTER 30 SECOND
.. versionchanged:: 8.1.0.
.. code-block:: console
IF 1 == 1 THEN label DEVICE tempLabel TO on
IF 1 == 1 THEN label DEVICE tempLabel AND humiLabel TO 'No information'
IF 1 == 1 THEN label DEVICE tempLabel TO 23.5 FOR '10 SECOND'
IF 1 == 1 THEN label DEVICE tempLabel TO 'Bell rang' AFTER '30 SECOND'
IF 1 == 1 THEN label DEVICE tempLabel TO None FOR '10 MINUTE' AFTER '30 SECOND'
@@ -0,0 +1,38 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Pushbullet
==========
.. rubric:: Description
Send a message to your mobile phone with the pushbullet API
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| TITLE | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| BODY | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| TOKEN | |yes| | |no| | Unique pushbullet user account token |
+----------+------------------+---------------------+---------------------------------------------------+
| TYPE | |yes| | |no| | Message type |
+----------+------------------+---------------------+---------------------------------------------------+
.. rubric:: Example
.. code-block:: console
IF 1 == 1 THEN pushbullet TITLE Doorbell rang BODY Doorbell rang TOKEN abcd123abc TYPE note
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN pushbullet TITLE 'Doorbell rang' BODY 'Doorbell rang' TOKEN abcd123abc TYPE note
@@ -0,0 +1,38 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Pushover
========
.. rubric:: Description
Send a message to your mobile phone with the pushover API
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| TITLE | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| MESSAGE | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| TOKEN | |yes| | |no| | Unique pushover user account token |
+----------+------------------+---------------------+---------------------------------------------------+
| USER | |yes| | |no| | Unique pushover username |
+----------+------------------+---------------------+---------------------------------------------------+
.. rubric:: Example
.. code-block:: console
IF 1 == 1 THEN pushover TITLE Doorbell rang MESSAGE Doorbell rang TOKEN abcd123abc USER pilight
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN pushover TITLE 'Doorbell rang' MESSAGE 'Doorbell rang' TOKEN abcd123abc USER pilight
@@ -0,0 +1,52 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Sendmail
========
.. rubric:: Description
Send a message to any e-mail address
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| TO | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| SUBJECT | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| MESSAGE | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
.. note::
The ``sendmail`` action requires some additional settings in the pilight configuration:
.. code-block:: json
{
"settings": {
"smtp-sender": "sender@domain.com",
"smtp-host": "smtp.smtphost.com",
"smtp-port": 465,
"smtp-user": "smtpuser@domain.com",
"smtp-password": "password"
}
}
.. rubric:: Examples
.. code-block:: console
IF 1 == 1 THEN sendmail SUBJECT Doorbell rang MESSAGE Doorbell rang TO someone@somewhere.com
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN sendmail SUBJECT 'Doorbell rang' MESSAGE 'Doorbell rang' TO someone@somewhere.com
@@ -0,0 +1,64 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Switch
======
.. rubric:: Description
Changes the state of a switch, relay or dimmer.
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| DEVICE | |yes| | |yes| | Device(s) to change |
+----------+------------------+---------------------+---------------------------------------------------+
| TO | |yes| | |no| | New state |
+----------+------------------+---------------------+---------------------------------------------------+
.. versionadded:: 7.0
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| FOR | |no| | |no| | | Determine how long this new state lasts |
| | | | | before we change back to the previous state |
+----------+------------------+---------------------+---------------------------------------------------+
| AFTER | |no| | |no| | After how long do we want the new state to be set |
+----------+------------------+---------------------+---------------------------------------------------+
.. note:: Units for ``FOR`` and ``AFTER``
- MILLISECOND
- SECOND
- MINUTE
- HOUR
- DAY
.. rubric:: Examples
.. code-block:: console
IF 1 == 1 THEN switch DEVICE light TO on
IF 1 == 1 THEN switch DEVICE mainlight AND bookshelve AND hall TO on
.. versionadded:: 7.0
.. code-block:: console
IF 1 == 1 THEN switch DEVICE light TO on FOR 10 MINUTE
IF 1 == 1 THEN switch DEVICE light TO on AFTER 30 MILLISECOND
IF 1 == 1 THEN switch DEVICE light TO off FOR 10 SECOND AFTER 30 MINUTE
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN switch DEVICE light TO on FOR '10 MINUTE'
IF 1 == 1 THEN switch DEVICE light TO on AFTER '30 MILLISECOND'
IF 1 == 1 THEN switch DEVICE light TO off FOR '10 SECOND' AFTER '30 MINUTE'
@@ -0,0 +1,30 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Toggle
======
.. rubric:: Description
Toggles a device between state X and state Y. This action is especially made for ``one-shot`` devices such as a remote control button where a normal separate 'switch-on' and separate 'switch-off' rule doesn't apply. This action will check what the current state of a device is, and will change it to the non-current state.
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| DEVICE | |yes| | |yes| | Device(s) to change |
+----------+------------------+---------------------+---------------------------------------------------+
| BETWEEN | |yes| | |no| | State 1 |
+----------+------------------+---------------------+---------------------------------------------------+
| AND | |no| | |no| | State 2 |
+----------+------------------+---------------------+---------------------------------------------------+
.. rubric:: Example
.. code-block:: console
IF 1 == 1 THEN toggle DEVICE television BETWEEN on AND off
@@ -0,0 +1,12 @@
Examples
========
.. toctree::
:maxdepth: 1
ir
kodi
mail
mail1
sunriseset
time
@@ -0,0 +1,62 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
IR Remote
=========
.. rubric:: Description
Switch devices based on your IR remote buttons
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"devices": {
"television": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 0
}],
"state": "off"
},
"remote": {
"protocol": [ "lirc" ],
"id": [{
"remote": "logitech"
}],
"code": "000000000000e290",
"repeat": 2,
"button": "KEY_P"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"remote-television-switch": {
"rule": "IF remote.button IS KEY_P AND remote.repeat == 0 THEN toggle DEVICE television BETWEEN on AND off",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"remote-television-switch": {
"rule": "IF remote.button == KEY_P AND remote.repeat == 0 THEN toggle DEVICE television BETWEEN on AND off",
"active": 1
}
}
@@ -0,0 +1,69 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
XBMC / Kodi
===========
.. rubric:: Description
Execute rules based on XBMC / KODI based events
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"xbmcControls": {
"protocol": [ "xbmc" ],
"id": [{
"server": "127.0.0.1",
"port": 9090
}],
"action": "home",
"media": "none"
},
"speakers": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 4
}],
"state": "off"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"speakers-on": {
"rule": "IF xbmcControls.action IS play THEN switch DEVICE speakers TO on",
"active": 1
},
"speakers-off": {
"rule": "IF xbmcControls.action IS pause OR xbmcControls.action IS home THEN switch DEVICE speakers TO off AFTER 3 MINUTES",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"speakers-on": {
"rule": "IF xbmcControls.action == play THEN switch DEVICE speakers TO on",
"active": 1
},
"speakers-off": {
"rule": "IF xbmcControls.action == pause OR xbmcControls.action == home THEN switch DEVICE speakers TO off AFTER '3 MINUTES'",
"active": 1
}
}
@@ -0,0 +1,67 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Mail on contact trigger
=======================
.. rubric:: Description
Sending a mail based on a contact device trigger including the time when it happened.
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"currentdatetime": {
"protocol": [ "datetime" ],
"id": [{
"longitude": 1.2345,
"latitude": 12.3456
}],
"year": 2015,
"month": 1,
"day": 27,
"hour": 14,
"minute": 37,
"second": 8,
"weekday": 3,
"dst": 1
},
"frontdoor-contact": {
"protocol": [ "kaku_contact" ],
"id": [{
"id": 123456,
"unit": 0
}],
"state": "opened"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"frontdoor-contact-mail": {
"rule": "IF frontdoor-contact.state IS opened THEN sendmail TO foo@bar.com SUBJECT Frontdoor was opened at DATE_FORMAT(currentdatetime, %c) MESSAGE .",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"frontdoor-contact-mail": {
"rule": "IF frontdoor-contact.state == opened THEN sendmail TO foo@bar.com SUBJECT 'Frontdoor was opened at ' . DATE_FORMAT(currentdatetime, %c) MESSAGE ..",
"active": 1
}
}
@@ -0,0 +1,67 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Mail on computer disconnection
==============================
.. rubric:: Description
Send a mail when one of the computer goes offline.
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"currentdatetime": {
"protocol": [ "datetime" ],
"id": [{
"longitude": 1.2345,
"latitude": 12.3456
}],
"year": 2015,
"month": 1,
"day": 27,
"hour": 14,
"minute": 37,
"second": 8,
"weekday": 3,
"dst": 1
},
"nasPing": {
"protocol": [ "arping" ],
"id": [{
"mac": "aa:bb:cc:dd:00:11"
}],
"ip": "192.168.1.1",
"state": "connected"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"nas-mail": {
"rule": "IF nasPing.state IS disconnected THEN sendmail TO foo@bar.com SUBJECT NAS is offline since DATE_FORMAT(currentdatetime, %c) MESSAGE .",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"nas-mail": {
"rule": "IF nasPing.state IS disconnected THEN sendmail TO foo@bar.com SUBJECT 'NAS is offline since ' . DATE_FORMAT(currentdatetime, %c) MESSAGE ..",
"active": 1
}
}
@@ -0,0 +1,147 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Sunrise / Sunset Event
======================
.. rubric:: Description
This rule executes when the sun sets or rises.
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"devices": {
"currentdatetime": {
"protocol": [ "datetime" ],
"id": [{
"longitude": 1.2345,
"latitude": 12.3456
}],
"year": 2015,
"month": 1,
"day": 27,
"hour": 14,
"minute": 37,
"second": 8,
"weekday": 3,
"dst": 1
},
"sunrisesetdevice": {
"protocol": [ "sunriseset" ],
"id": [{
"longitude": 1.234567,
"latitude": 12.123456
}],
"sunrise": 6.40,
"sunset": 18.50,
"sun": "rise"
},
"light": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 0
}],
"state": "off"
}
}
}
.. rubric:: Rule
By using math
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF ((sunrisesetdevice.sunset == (currentdatetime.hour + (currentdatetime.minute / 100)) AND light.state IS off) AND currentdatetime.second == 0) THEN switch DEVICE light TO on",
"active": 1
},
"sunrise": {
"rule": "IF ((sunrisesetdevice.sunrise == (currentdatetime.hour + (currentdatetime.minute / 100)) AND light.state IS off) AND currentdatetime.second == 0) THEN switch DEVICE light TO on",
"active": 1
}
}
By using the DATE_FORMAT function
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF (sunrisesetdevice.sunset == DATE_FORMAT(currentdatetime, %H.%M)) AND light.state IS off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
},
"sunrise": {
"rule": "IF (sunrisesetdevice.sunrise == DATE_FORMAT(currentdatetime, %H.%M)) AND light.state IS off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
}
}
Or an hour before the sun sets:
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF (sunrisesetdevice.sunset == DATE_FORMAT(DATE_ADD(currentdatetime, +1 HOUR), \"%Y-%m-%d %H:%M:%S\", %H.%M)) AND light.state IS off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
}
}
.. versionchanged:: 8.1.0
By using math
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF ((sunrisesetdevice.sunset == (currentdatetime.hour + (currentdatetime.minute / 100)) AND light.state == off) AND currentdatetime.second == 0) THEN switch DEVICE light TO on",
"active": 1
},
"sunrise": {
"rule": "IF ((sunrisesetdevice.sunrise == (currentdatetime.hour + (currentdatetime.minute / 100)) AND light.state == off) AND currentdatetime.second == 0) THEN switch DEVICE light TO on",
"active": 1
}
}
By using the DATE_FORMAT function
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF (sunrisesetdevice.sunset == DATE_FORMAT(currentdatetime, %H.%M)) AND light.state == off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
},
"sunrise": {
"rule": "IF (sunrisesetdevice.sunrise == DATE_FORMAT(currentdatetime, %H.%M)) AND light.state == off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
}
}
Or an hour before the sun sets:
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF (sunrisesetdevice.sunset == DATE_FORMAT(DATE_ADD(currentdatetime, '+1 HOUR'), '%Y-%m-%d %H:%M:%S', %H.%M)) AND light.state == off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
}
}
@@ -0,0 +1,67 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Time based
==========
.. rubric:: Description
Trigger events based on time
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"currentdatetime": {
"protocol": [ "datetime" ],
"id": [{
"longitude": 1.2345,
"latitude": 12.3456
}],
"year": 2015,
"month": 1,
"day": 27,
"hour": 14,
"minute": 37,
"second": 8,
"weekday": 3,
"dst": 1
},
"outsidelight": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 0
}],
"state": "off"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"christmass-tree-off": {
"rule": "IF DATE_FORMAT(currentdatetime, %H.%M%S) == 23.0000 THEN switch DEVICE outsidelight TO on AFTER RANDOM(0, 90) MINUTE FOR RANDOM(5, 15) MINUTE",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"christmass-tree-off": {
"rule": "IF DATE_FORMAT(currentdatetime, %H.%M%S) == 23.0000 THEN switch DEVICE outsidelight TO on AFTER RANDOM(0, 90) . ' MINUTE' FOR RANDOM(5, 15) . ' MINUTE'",
"active": 1
}
}
@@ -0,0 +1,56 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
date_add
========
.. rubric:: Description
Calculations with date and time values.
.. rubric:: Arguments
+----------+------------------+------------------------------------------+
| **#** | **Required** | **Description** |
+----------+------------------+------------------------------------------+
| 1 | |yes| | | A datetime device or a datetime string |
| | | | The datetime string must be in the |
| | | | format YYYY-MM-DD HH:MM:SS. |
+----------+------------------+------------------------------------------+
| 2 | |yes| | | A number and unit. The number can be |
| | | | either positive or negative. |
| | | | The unit can be |
| | | | - SECOND |
| | | | - MINUTE |
| | | | - HOUR |
| | | | - DAY |
| | | | - MONTH |
| | | | - YEAR |
+----------+------------------+------------------------------------------+
.. rubric:: Return value
The returned datetime string is always in the format ``%Y-%m-%d %H:%M:%S``. So in case of the third example, the output will be ``"2016-01-01 00:00:00"``.
.. rubric:: Examples
.. code-block:: console
IF DATE_ADD(datetime, +1 HOUR) == ...
IF DATE_ADD(datetime, -1 DAY) == ...
IF DATE_ADD(2015-12-31, 23:59:59, +1 SECOND) == ...
IF DATE_ADD(datetime, RANDOM(-3, +3) DAY) == ...
IF DATE_FORMAT(DATE_ADD(2015-01-01 21:00:00, RANDOM(0, 120) MINUTE), \"%Y-%m-%d %H:%M:%S\", %H.%M) == ...
.. versionchanged:: 8.1.0
.. code-block:: console
IF DATE_ADD(datetime, '+1 HOUR') == ...
IF DATE_ADD(datetime, '-1 DAY') == ...
IF DATE_ADD('2015-12-31, 23:59:59', '+1 SECOND') == ...
IF DATE_ADD(datetime, RANDOM(-3, +3) . ' DAY') == ...
IF DATE_FORMAT(DATE_ADD('2015-01-01 21:00:00', RANDOM(0, 120) . ' MINUTE'), '%Y-%m-%d %H:%M:%S', %H.%M) == ...
@@ -0,0 +1,152 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
date_format
===========
.. rubric:: Description
Reformat date and time values
.. rubric:: Arguments
+----------+------------------+------------------------------------------+
| **#** | **Required** | **Description** |
+----------+------------------+------------------------------------------+
| **Using two parameters** |
+----------+------------------+------------------------------------------+
| 1 | |yes| | A datetime device |
+----------+------------------+------------------------------------------+
| 2 | |yes| | Output format (see below) |
+----------+------------------+------------------------------------------+
| **Using three parameters** |
+----------+------------------+------------------------------------------+
| 1 | |yes| | A datetime string |
+----------+------------------+------------------------------------------+
| 2 | |yes| | Input format (see below) |
+----------+------------------+------------------------------------------+
| 3 | |yes| | Output format (see below) |
+----------+------------------+------------------------------------------+
.. note:: **Input / output**
Consider that the flexibility of the function depends on the input. If you input just ``%H:%M:%S``, the DATE_FORMAT can't output a format like this ``%Y-%m-%d``, because the function didn't receive any date information. It only received time information. So, DATE_FORMAT can't be used to exterpolate information that's not present.
.. rubric:: Return value
The function will output the exact format as requested in the last (second or third argument). There are a few things you must consider when working with the DATE_FORMAT function. The types of operators you can use with DATE_FORMAT depends on the output format requested. If you want to compare the output format ``%c`` you can only use the ``IS`` operator, because the final output will be interpreted as a string value. If you want to compare ``%H.%M``, you will need numeric operators like ``==``, ``>``, or ``<``, because the output will be evaluated as a number.
Also consider the usage of quotes. The flexibility in which DATE_FORMAT can format date and time values isn't always accepted by pilight. For example: ``DATE_FORMAT(datetime, %c)`` outputs ``Fri Apr 24 11:35:36 2015`` which pilight subsequently can't handle. If you want to output string like this, use quotes ``DATE_FORMAT(datetime, "%c")``, which will output as ``"Fri Apr 24 11:35:36 2015"``.
.. rubric:: Examples
.. code-block:: console
IF DATE_ADD(datetime, +1 HOUR) == ...
IF DATE_ADD(datetime, -1 DAY) == ...
IF DATE_ADD(2015-12-31, 23:59:59, +1 SECOND) == ...
IF DATE_ADD(datetime, RANDOM(-3, +3) DAY) == ...
IF DATE_FORMAT(DATE_ADD(2015-01-01 21:00:00, RANDOM(0, 120) MINUTE), \"%Y-%m-%d %H:%M:%S\", %H.%M) == ...
.. versionchanged:: 8.1.0
.. code-block:: console
IF DATE_ADD(datetime, '+1 HOUR') == ...
IF DATE_ADD(datetime, '-1 DAY') == ...
IF DATE_ADD(2015-12-31, 23:59:59, '+1 SECOND') == ...
IF DATE_ADD(datetime, RANDOM(-3, +3) . ' DAY') == ...
IF DATE_FORMAT(DATE_ADD('2015-01-01 21:00:00', RANDOM(0, 120) . ' MINUTE'), '%Y-%m-%d %H:%M:%S', %H.%M) == ...
.. note:: **DATE_ADD as an argument**
When you use DATE_ADD as the first argument, you should consider the return value of DATE_ADD, because that's what DATE_FORMAT will eventually receive. The output format of DATE_ADD is ``"%Y-%m-%d %H:%M:%S"``, so the input format for DATE_FORMAT should be the same.
.. rubric:: Formatting characters
+---------------+------------------------------------------------------------------------+--------------------------+
| **Specifier** | **Replaced by** | **Example** |
+---------------+------------------------------------------------------------------------+--------------------------+
| %a | Abbreviated weekday name [#f1]_ | Thu |
+---------------+------------------------------------------------------------------------+--------------------------+
| %A | Full weekday name [#f1]_ | Thursday |
+---------------+------------------------------------------------------------------------+--------------------------+
| %b %h | Abbreviated month name [#f1]_ | Aug |
+---------------+------------------------------------------------------------------------+--------------------------+
| %B | Full month name [#f1]_ | August |
+---------------+------------------------------------------------------------------------+--------------------------+
| %c | Date and time representation [#f1]_ | Thu Aug 23 14:55:02 2001 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %C | Year divided by 100 and truncated to integer (00-99) | 20 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %d | Day of the month, zero-padded (01-31) | 23 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %D | Short MM/DD/YY date, equivalent to %m/%d/%y | 08/23/01 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %e | Day of the month, space-padded (1-31) | 23 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %F | Short YYYY-MM-DD date, equivalent to %Y-%m-%d | 2001-08-23 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %g | Week-based year, last two digits (00-99) | 01 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %G | Week-based year | 2001 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %g | Week-based year | 2001 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %H | Hour in 24h format (00-23) | 14 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %I | Hour in 12h format (01-12) | 02 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %j | Day of the year (001-366) | 235 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %m | Month as a decimal number (01-12) | 08 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %M | Minute (00-59) | 55 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %n | New-line character ('\n') | |
+---------------+------------------------------------------------------------------------+--------------------------+
| %p | AM or PM designation | PM |
+---------------+------------------------------------------------------------------------+--------------------------+
| %r | 12-hour clock time [#f1]_ | 02:55:02 pm |
+---------------+------------------------------------------------------------------------+--------------------------+
| %R | 24-hour HH:MM time, equivalent to %H:%M | 14:55 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %S | Second (00-61) | 02 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %t | Horizontal-tab character ('\t') | |
+---------------+------------------------------------------------------------------------+--------------------------+
| %T | ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S | 14:55:02 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %u | ISO 8601 weekday as number with Monday as 1 (1-7) | 4 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %U | Week number with the first Sunday as the first day of week one (00-53) | 33 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %V | ISO 8601 week number (01-53) | 34 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %w | Weekday as a decimal number with Sunday as 0 (0-6) | 4 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %W | Week number with the first Monday as the first day of week one (00-53) | 34 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %x | Date representation [#f1]_ | 08/23/01 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %X | Time representation [#f1]_ | 14:55:02 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %y | Year, last two digits (00-99) | 01 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %Y | Year | 2001 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %z | | ISO 8601 offset from UTC in timezone (1 minute=1, 1 hour=100) | +100 |
| | | If timezone cannot be determined, no characters | |
+---------------+------------------------------------------------------------------------+--------------------------+
| %Z | | Timezone name or abbreviation [#f1]_ | CDT |
| | | If timezone cannot be determined, no characters | |
+---------------+------------------------------------------------------------------------+--------------------------+
| %% | A ``%`` sign | % |
+---------------+------------------------------------------------------------------------+--------------------------+
Copied from http://www.cplusplus.com/reference/ctime/strftime/
.. [#f1] These specifiers are locale-dependent.
@@ -0,0 +1,11 @@
Functions
=========
.. versionadded:: 7.0
.. toctree::
:maxdepth: 1
random
date_add
date_format
@@ -0,0 +1,34 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
random
======
.. rubric:: Description
Generate a random number.
.. rubric:: Parameters
+----------+------------------+---------------------+
| **#** | **Required** | **Description** |
+----------+------------------+---------------------+
| 1 | |yes| | Lower boundary |
+----------+------------------+---------------------+
| 2 | |yes| | Higher boundary |
+----------+------------------+---------------------+
.. rubric:: Return value
A random number
.. rubric:: Examples
.. code-block:: console
IF RANDOM(0, 10) == 5 THEN ...
IF RANDOM(1, 100) == 10 THEN ...
IF RANDOM(randomLow.dimlevel, randomHigh.dimlevel) == 10 THEN ...
@@ -0,0 +1,11 @@
Eventing
========
.. toctree::
:maxdepth: 2
syntax
operators
actions/index
functions/index
examples/index
@@ -0,0 +1,106 @@
Operators
=========
.. rubric:: Arithmetic
+--------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+--------------+-------------------------------------------------+--------------------------+
| \+ | Adds two operands. | 10 + 20 = 30 |
+--------------+-------------------------------------------------+--------------------------+
| − | Subtracts second operand from the first. | 10 − 20 = -10 |
+--------------+-------------------------------------------------+--------------------------+
| \* | Multiplies both operands. | 10 * 20 = 200 |
+--------------+-------------------------------------------------+--------------------------+
| / | Divides numerator by de-numerator. | | 10 / 20 = 2 |
| | | | 10 / 3 = 3.333... |
+--------------+-------------------------------------------------+--------------------------+
| \\ [#f1]_ | Integer divides numerator by de-numerator. | 10 \\ 3 = 3 |
+--------------+-------------------------------------------------+--------------------------+
| % | Remainder after an integer division. | | 20 % 10 = 0 |
| | | | 11 % 3 = 2 |
+--------------+-------------------------------------------------+--------------------------+
.. [#f1] The backslash is also used as an ``escape`` character. So if you want to use the intdivide operator inside a rule you must write your rulses like this:
.. code-block:: json
{
"rules": {
"rule": "IF 3 \\ 2 = 1 THEN switch DEVICE light TO on",
"active": 1
}
}
.. rubric:: Relational
+--------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+--------------+-------------------------------------------------+--------------------------+
| == | | Checks if the first and second (nummeric) | | 20 == 10 = false |
| | | operand are equal. | | 10 == 10 = true |
+--------------+-------------------------------------------------+--------------------------+
| != | | Checks if the first and second (nummeric) | | 20 != 10 = true |
| | | operand are unequal. | | 10 != 10 = false |
+--------------+-------------------------------------------------+--------------------------+
| IS | | Checks if the first and second (character) | | a IS b = false |
| | | operand are equal. | | a IS a = true |
+--------------+-------------------------------------------------+--------------------------+
| >= | | Checks if the first operand is greater or | | 20 >= 10 = true |
| | | equal to the second operand. | | 10 >= 20 = false |
| | | | 10 >= 10 = true |
+--------------+-------------------------------------------------+--------------------------+
| > | | Checks if the first operand is greater than | | 20 > 10 = true |
| | | the second operand. | | 10 > 20 = false |
| | | | 10 > 10 = false |
+--------------+-------------------------------------------------+--------------------------+
| <= | | Checks if the first operand is smaller or | | 20 <= 10 = false |
| | | equal to the second operand. | | 10 <= 20 = true |
| | | | 10 <= 10 = true |
+--------------+-------------------------------------------------+--------------------------+
| < | | Checks if the first operand is smaller than | | 20 < 10 = false |
| | | the second operand. | | 10 < 20 = true |
| | | | 10 < 10 = false |
+--------------+-------------------------------------------------+--------------------------+
.. versionadded:: 8.0 ISNOT operator added
.. deprecated:: 8.1.0
+--------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+--------------+-------------------------------------------------+--------------------------+
| ISNOT | | Checks if the first and second (character) | | a ISNOT b = true |
| | | operand are equal. | | a ISNOT a = false |
+--------------+-------------------------------------------------+--------------------------+
.. rubric:: Logical
+--------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+--------------+-------------------------------------------------+--------------------------+
| AND | | Checks if the first and second operands are | | 1 AND 1 = true |
| | | true. | | 1 AND 0 = false |
| | | - values greater of smaller then 0 are true | | foo AND false = true |
| | | - strings equals to ``0`` are false | | true AND true = true |
| | | - strings other than ``0`` are true | | false AND false = true |
+--------------+-------------------------------------------------+--------------------------+
| OR | | Checks if the first or second operands are | | 0 OR 0 = false |
| | | true. | | 1 OR 0 = true |
| | | - values greater of smaller then 0 are true | | foo OR false = true |
| | | - strings equals to ``0`` are false | | true OR true = true |
| | | - strings other than ``0`` are true | | false OR false = true |
+--------------+-------------------------------------------------+--------------------------+
.. rubric:: Other
.. versionadded:: 8.1.0
+----------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+----------------+-------------------------------------------------+--------------------------+
| | . | Concatenates two strings | | a . b == 'ab' |
| | (single dot) | | | a . ' ' . b == 'a b' |
| | | | RANDOM(1, 2) . '34' |
+----------------+-------------------------------------------------+--------------------------+
@@ -0,0 +1,366 @@
.. role:: event-success
.. role:: event-fail
Syntax
======
- `Introduction`_
- `Rule Parsing`_
- `Basic Structure`_
- `True or False`_
- `AND and OR`_
- `Hooks`_
- `Operator`_
- `String and Concatenation`_
- `Devices`_
- `Functions`_
- `Actions`_
- `Using Device Parameters`_
Introduction
------------
The pilight eventing library allows you to automate your house by writing event rules. These rules tell pilight what should happen at a given time or at a given event. pilight event rules follow the regular mathematical conventions and because you can work with an infinite number of hooks, they can become highly complex but are also highly flexible.
As with everything inside pilight, the eventing library is also highly modular. This means that the operators, actions, and functions are external modules that can be easily extended. Developers and users do not have to touch the core of the eventing library to add additional features.
Rule Parsing
------------
There are few things that are useful to know before working with pilight event rules. When you better understand how pilight parses the rules, you can write really efficient and advanced rules.
.. _Basic Structure:
.. rubric:: Basic Structure
All rules basically consist of the same structure:
.. code-block:: guess
IF ... THEN ...
A rule always start with the IF, followed by the rule logic, and is closed by a THEN. All actions are put after the THEN.
.. versionadded:: 8.1.0
The IF / THEN logic can be expanded by an ELSE. The actions written after the ELSE will be executed if the logic contained in the first if block is false.
.. code-block:: guess
IF ... THEN ... ELSE ...
Or you can nest an infinite number of IF/ELSE conditions by using adding the END keyword
.. code-block:: guess
IF ... THEN IF ... THEN ... ELSE ... END ELSE IF ... THEN ... ELSE ... END END
.. _True or False:
.. rubric:: True or False
Let us start with how pilight handles succeeding or failing conditions. pilight converts each logical mathematical and logical step into a true or false. The final condition must be true before triggering an action. If the final result is false, the action is skipped. These two examples will both succeed:
:event-success:`Succeeds`
.. code-block:: guess
IF (1 == 1) == True THEN
:event-success:`Succeeds`
.. code-block:: guess
IF (1 == 1) != False THEN
These two examples will both fail:
:event-fail:`Fails`
.. code-block:: guess
IF (1 == 0) IS True THEN
:event-fail:`Fails`
.. code-block:: guess
IF (1 != 1) IS False THEN
.. _AND and OR:
.. rubric:: AND and OR
In the first examples we only used one condition but this does not allow us to make very advanced and flexible rules. Therefore we need to be able to combine several conditions in a single rule. This is possible by combining them with AND and OR operators. Let us take a look at some basic examples:
:event-fail:`Fails`
.. code-block:: guess
IF 1 == 1 AND 1 == 2 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 1 == 1 OR 1 == 2 THEN ...
:event-fail:`Fails`
.. code-block:: guess
IF 1 == 2 OR 1 == 1 AND 2 == 3 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 1 == 1 OR 1 == 1 AND 2 == 3 THEN ...
:event-fail:`Fails`
.. code-block:: guess
IF 1 == 2 AND 1 == 1 OR 2 == 3 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 1 == 1 AND 2 == 2 OR 2 == 3 THEN ...
In the first two examples only a single AND and OR operator is used. In the rest of the examples we see multiple AND and OR operators. pilight follows standard operator associativity rules in parsing AND and OR operators.
.. _Hooks:
.. rubric:: Hooks
As we saw in our first examples, hooks can be used inside pilight rules. This can be useful to better structure and combine the various conditions of our rules. Let us create even more complex rules and see how hooks can change the outcome of a rule without changing the conditions.
:event-success:`Succeeds`
.. code-block:: guess
IF 1 == 2 OR 2 == 3 AND 2 == 3 OR 1 == 1 THEN ...
:event-fail:`Fails`
.. code-block:: guess
IF (1 == 2 OR 2 == 3) AND (2 == 3 OR 1 == 1) THEN ...
Operator
--------
Various mathematical operators can be used to do calculations inside our rules. A list of these operators can be found further on in this manual. pilight follows standard operator associativity rules in parsing mathematical operators. Let us just show some basic self-explanatory examples:
:event-success:`Succeeds`
.. code-block:: guess
IF 1 + 1 == 2 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 2 % 2 == 0 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 1 < 10 THEN ...
:event-fail:`Fails`
.. code-block:: guess
IF 10 / 2 == 4 THEN ...
String and Concatenation
------------------------
.. versionadded:: 8.1.0
pilight parses individual components inside a rule by looking at queues like spaces, comma's, hooks, and preserved words (e.g. actions or functions). In any case, pilight can be forces to parse any of these components as strings by enclosing them into quotes.
:event-success:`Succeeds`
.. code-block:: guess
IF 1 + 1 == 3 - 1 THEN ...
In this case, pilight will compare the outcome of both formulas (which is 2) with each other for further parsing. We can also tell pilight to compare the same formula but now with strings:
:event-fail:`Fails`
.. code-block:: guess
IF '1 + 1' == '3 - 1' THEN ...
The same formula parsed with two strings will now fail because both strings are not equal anymore.
It is important to understand how to enforce string parsing when working with functions. The following example with give a syntax error, because the DATE_ADD function only expects two arguments delimited by a comma when the first argument is a datetime device. However, pilight sees the ``+1`` and ``HOUR`` as two separate string that normally should be delimited by a comma. Would be add that comma, we would still call the DATE_ADD function with the wrong parameter count.
.. code-block:: guess
IF DATE_ADD(datetime, +1 HOUR) == ...
The rule above should be written like this instead so the ``+1`` and ``HOUR`` are parsed like ``+1 HOUR``.
.. code-block:: guess
IF DATE_ADD(datetime, '+1 HOUR') == ...
Another issue arises when strings and device values or functions need to be combined like in this example:
.. code-block:: guess
IF ... THEN label DEVICE alarm TO the alarm was trigger at DATE_FORMAT(datetime, %Y-%m-%d)
This rule will trigger a syntax error because the TO argument only expects one string, but five strings and a function were given. To make this into one string we need to use quotes and the concatenate ``.`` operator:
.. code-block:: guess
IF ... THEN label DEVICE alarm TO 'the alarm was trigger at' . DATE_FORMAT(datetime, %Y-%m-%d)
Another scenario in which we want to explicitly cast a keyword into a string is given in this example:
.. code-block:: guess
IF ... THEN label DEVICE label TO on
The ``label`` device is parsed by pilight as the label action because it's a reserved keyword. pilight does allow using label as a device name when casting it as a string like this:
.. code-block:: guess
IF ... THEN label DEVICE 'label' TO on
As shown above, keywords or operators can be parsed into strings so pilight will ignore their default meaning.
Devices
-------
pilight rules are quite useless if we cannot work with live data. This live data comes from our devices in and around the house. So let us say we have a switch called switch and we use this configured device to create a rule like this:
.. code-block:: guess
IF switch.state IS on THEN ...
Depending on the actual state of the switch this rule will succeed or fail. Let us now use a dimmer device called *dimmer*.
.. code-block:: guess
IF dimmer.dimlevel > 10 THEN ...
Again, this rule will succeed or fail depending on the actual dimlevel of the configured dimmer device. These two examples can of course be combined:
.. code-block:: guess
IF switch.state IS on AND dimmer.dimlevel > 10 THEN ...
As you can also see, the fields (*state* or *dimlevel*) we can use depends on the device we are using inside our rules. A switch does not have a *dimlevel* field but a dimmer does have a *state* field.
.. versionadded:: 8.0 rules based on received codes
Some devices are only used inside rules. Configuring them as explicit devices might sometimes feel a bit bloated. Therefor, pilight allows you to trigger rules based on received codes instead of device updates:
.. deprecated:: 8.1.0
.. code-block:: guess
IF archtech_switch.state IS on AND archtech_switch.id == 123456 AND arctech_switch.unit == 0 THEN ...
.. versionadded:: 8.1.0
.. code-block:: guess
IF archtech_switch.state == on AND archtech_switch.id == 123456 AND arctech_switch.unit == 0 THEN ...
In this case, an action will be triggered as soon as an ``archtech_switch`` code is received with a specific state, id, and unitcode. The ``arctech_switch`` doesn't have to be configured as an explicit device for this rule to work.
Functions
---------
In some cases, standard operators limit us in writing our rules. For example, calculating with time is a hideous task considering that hours do not go above 24, minute and seconds do not go above 60, and there are no negative numbers. Other functionality like randomization are also not possible in the standard event operators. This more advanced functionality is added in the form of function. A simple example:
.. code-block:: guess
IF datetime.hour == RANDOM(21, 23) THEN ...
As we can see in this example we use the RANDOM function to check if the hour is either 21, 22, or 23. This allows us to trigger an action on random hours each day. Actions can also be nested for more advanced logic:
.. code-block:: guess
IF datetime.hour == RANDOM(RANDOM(21, 22), RANDOM(22, 23)) THEN ...
The output of this RANDOM function is the same as with the previous example, but the idea should be clear.
Actions
-------
Actions are the final goal of our rules. These actions tell pilight what should happen when certain conditions have been met. A rule can contain unlimited number of actions and each action can trigger an unlimited number of devices. First two examples of basic actions triggering a switch called *lamp* and a dimmer called *ambientLight*:
.. code-block:: guess
IF ... THEN switch DEVICE lamp TO on
IF ... THEN dim DEVICE ambientLight TO 10
Both actions only trigger a single device. However, if we wanted to trigger both device to just on we can combine them in a single action:
.. code-block:: guess
IF ... THEN switch DEVICE lamp AND ambientLight TO on
As we can see here, the switch action takes at least the DEVICE and TO parameters. In case of the switch action, several values (as in devices) can be combined by separating them with ANDs. We can also combine dim and switch action would we want to switch the *lamp* to on and dim the *ambientLight* to dimlevel 10 based on the same condition:
.. code-block:: guess
IF ... THEN switch DEVICE lamp TO on AND dim DEVICE ambientLight TO 10
We can combine an unlimited number of actions like this. Again we see that we use the AND to combine several actions. We can also switch several devices across several actions in a single rule. Let's say we have a relay connected to our television set called television that we want to turn on as well.
.. code-block:: guess
IF ... THEN switch DEVICE lamp AND television TO on AND dim DEVICE ambientLight TO 10
.. versionadded:: 8.1.0
As described earlier, actions can also be trigger based on a false condition like this:
.. code-block:: guess
IF ... THEN switch DEVICE lamp AND television TO on ELSE dim DEVICE ambientLight TO 10 END
Using Device Parameters
-----------------------
Device parameters can be used as rule input almost everywhere. Let us look at a few examples to demonstrate this:
.. code-block:: guess
IF 1 == 1 THEN dim DEVICE dimmer TO dimmerMax.dimlevel FOR dimmerDuration.dimlevel
In this case we use three dimmer devices. One dimmer called dimmer that we actually want to dim, and two dimmers that changes the way this rule behaves. The dimmerMax device tells pilight to what value the dimmer should dim. The dimmerDuration device tells pilight how long it should take to reach that dimlevel. Another example:
.. code-block:: guess
IF 1 == 1 THEN switch DEVICE lamp1 TO lamp2.state
In this case we want to switch the device lamp1 to the same state as the device lamp2.
Device parameters can also be used in function:
.. code-block:: guess
IF RANDOM(randomLow.dimlevel, randomHigh.dimlevel) == 10 THEN switch DEVICE lamp1 TO on
In this case we use two dimmers called randomLow and randomHigh to dynamically change the input of the RANDOM function used in this rule. A comprehensive and advanced example:
.. code-block:: guess
IF sunriseset.sunset == DATE_FORMAT(DATE_ADD(datetime, +1 HOUR), \"%Y-%m-%d %H:%M:%S\", %H.%M) THEN switch DEVICE lamp1 TO on
.. versionchanged:: 8.1.0
.. code-block:: guess
IF sunriseset.sunset == DATE_FORMAT(DATE_ADD(datetime, '+1 HOUR'), '%Y-%m-%d %H:%M:%S', %H.%M) THEN switch DEVICE lamp1 TO on