Updated 04/02/2021
Advanced Power Control - Notification
DLI Power controllers can send a notification of an event Add custom notifications using the built-in simple Lua scripting language.Hardware Requirements
This page describes the Lua based scripting language used in DLI products with WiFi.Certain power controller events can trigger configurable notifications over a variety of media:
- email;
- XMPP (Jabber, Google Talk, etc.);
- SNMPv1, SNMPv2c and SNMPv3 TRAPs;
- SNMPv2c and SNMPv3 INFORMs;
- webhook.
Notification is based on the Lua programming language.
Find some event notification examples here
Notification context
When an event happens, a notification thread is started, with event's properties being copied to global variables (and thus constituting the context of further notification code snippets).
The most important of the rule action context (see below) is the
notify
function, which sends the current notification
context to matching targets.
All kinds of events share the following properties:
id
— the event type identifier,message
— a human-readable message,severity
— the event severity level.
By manipulating the context, rules can check for and adjust the event's properties and prepare it for sending.
For example, you can have a rule with an empty condition and an action altering the 'message' variable like this:
message="Server room power: "..message
All the following rules will include the "Server room power:" prefix in the generated notifications.
Some properties, e.g. message_short
or
message_long
, are supported by notification targets but aren't
generated by any events; it's up to the action code to set them if
necessary.
It's important to note that rules are processed linearly: adjustment of properties doesn't cause preceding rules to be re-examined.
Additionally, different event types have more specific properties. All event properties can be checked for or adjusted.
The following convenience severity level constants are defined:
EMERG
,EMERGENCY
— "emergency" severity level,ALERT
— "alert" severity level,CRIT
,CRITICAL
— "critical" severity level,ERR
,ERROR
— "error" severity level,WARNING
,WARN
— "warning" severity level,NOTICE
— "notice" severity level,INFO
,INFORMATION
,INFORMATIONAL
— "informational" severity level,DEBUG
— "debug" severity level.
Their numeric values are defined so that a higher severity is larger,
so condition like severity>=CRITICAL
behaves like what
you'd expect.
The core Lua functions are accessible from the context as well, should you need them.
Notification targets
The targets are a list of configurations which can deliver
preprocessed messages to concrete recipients. Each target has a name,
which needn't be unique. When a rule action calls
notify("target_name")
, all targets which have "target_name"
specified as name are triggered.
Other target properties depend on the kind of the target.
Email notifications
Email notification targets have the following parameters:
- recipient email address (RFC 822);
- sender email address (RFC 822);
- server (hostname or IP address);
- server port (usually 465, 587 or 25 for unencrypted operations);
- username (for authenticating to the server);
- password (for authenticating to the server);
- transport encryption:
- "smtps" for SMTP wrapped completely in TLS;
- "starttls" for SMTP+STARTTLS command;
- "" (the empty string) for no encryption.
Some fields are autofilled for popular email services once you enter the sender's address.
If present, the message_short
event property is used for
the email subject; otherwise, message
is used.
If present, the message_long
event property is used for
the email body; otherwise, message
is used.
XMPP notifications
XMPP notification targets have the following parameters:
- recipient XMPP ID (RFC822-like);
- sender XMPP ID (RFC822-like);
- password (for authenticating to the server).
If present, the message_short
event property is used for
the message; otherwise, message
is used.
SNMP notifications
The notification system supports sending:
- SNMPv1 TRAPs;
- SNMPv2c TRAPs and INFORMs;
- SNMPv3 TRAPs and INFORMs.
The difference between a TRAP and an INFORM is that an INFORM requires confirmation of receipt. Thus, the target test function can tell if the message has been delivered.
Trap OIDs
The type of a TRAP or INFORM is indicated by its OID. SNMPv2c and SNMPv3 include the full OID in the message; SNMPv1 is different.
SNMPv1 traps are identified by the generic trap type (and correspond to the following trap OIDs):
- 0 - cold start (1.3.6.1.6.3.1.1.5.1),
- 1 - warm start (1.3.6.1.6.3.1.1.5.2),
- 2 - link down (1.3.6.1.6.3.1.1.5.3),
- 3 - link up (1.3.6.1.6.3.1.1.5.4),
- 4 - authentication failure (1.3.6.1.6.3.1.1.5.5),
- 5 - EGP neighbor loss (1.3.6.1.6.3.1.1.5.6).
If the generic trap type is 6, the trap is enterprise-specific (and is usually taken to correspond to OIDs using the template "1.3.6.1.4.1.ENTERPRISE-OID.0.SPECIFIC-TRAP-TYPE").
Unless you send only generic traps or have a OID tree registered to
you, you may want to send 'user-configured' traps which carry no
additional semantics other than the variable bindings. The
dlinGeneric
user-configured trap type is designed for that. Its
OID is 1.3.6.1.4.1.45770.0.1; this can be specified directly for SNMPv2c
or SNMPv3, or as an enterprise-specific (generic trap type=6) DLI
("enterprise OID"=45770) trap #1 (specific trap type=1).
Security settings
SNMPv1 and SNMPv2c use the 'community' security model which essentially identifies users by a shared secret which is sent over the network in plain text ('public' and 'private' being the most popular 'secrets'). That means that they are very insecure and shouldn't be deployed over an untrusted network. SNMPv3 has a more reasonable security model.
Variable bindings
All SNMP TRAPs and INFORMs accept the snmp_values
event
property to send extra values in the message. The property, if not nil,
must be an array of the following shape:
{{oid1,value1,type1},{oid2,value2,type2},...}
The order may be important; you may want to consult the MIB. The following types are supported:
- "integer",
- "unsigned",
- "counter32",
- "string",
- "hex string",
- "decimal string",
- "nullobj",
- "objid" or "oid",
- "timeticks",
- "ipaddress" or "ip",
- "bits".
Type names are case-insensitive. A type may be omitted, in that case it will be inferred (nil values will be encoded as null objects, strings as octet strings, numbers as integers, "true" values as integer 1, and "false" values as integer 2 as per SMIv2).
SNMPv1 settings
SNMPv1 trap targets have the following parameters:
- server address (hostname or IP address of management station),
- community string (the shared secret for authentication to server),
- enterprise OID (number),
- default generic trap type (number 0..6),
- default specific trap type (number 0..2147483647).
SNMP v1 accepts snmp_enterprise_oid
,
snmp_generic_trap_type
and snmp_specific_trap_type
event properties to override the trap OID; they must be integers or
string representations thereof. It also accepts the snmp_values
event property as described above.
SNMPv2c settings
SNMPv2c TRAP and INFORM targets have the following parameters:
- server address (hostname or IP address of management station),
- community string (the shared secret for authentication to server),
- trap OID (string)
SNMP v2c TRAPs and INFORMs accept an snmp_trap_oid
event
property to override the trap OID; it must be a string. They also accept
the snmp_values
event property as described
above.
SNMPv3 settings
SNMPv3 TRAP and INFORM targets have the following parameters:
- server address (hostname or IP address of management station),
- security name (username to authenticate as),
- security engine ID (leave empty for default),
- context name (leave empty for default),
- context engine ID (leave empty for default),
- authentication protocol ("MD5" and "SHA" are supported, leave empty "" for no authentication),
- privacy protocol ("DES" and "AES" are supported, leave empty "" for no encryption),
- authentication passphrase (should be at least 8 characters long, or empty if no authentication),
- privacy passphrase (should be at least 8 characters long, or empty if no encryption),
- trap OID (string)
You can either disable authentication and encryption, enable only authentication, or enable both. An encrypted, but not authenticated configuration is invalid.
SNMP v3 TRAPs and INFORMs accept an snmp_trap_oid
event
property to override the trap OID; it must be a string. They also accept
the snmp_values
event property as described
above.
WebHook notifications
Web hooks notifications send preconfigured POST HTTP requests to URLs.
- recipient URL — the URL to send a request to (must be an HTTP or HTTPS URL);
- content type — the type of content representation to use (must be "json" for JSON or "urlencoded" for URL-encoded).
The request payload (content) is a key-value map with the following keys:
type
— theid
of the event type;severity
— the severity label for the event (one of the strings "emergency", "alert", "critical", "error", "warning", "notice", "info" or "debug");message
— the human-readable message of the event type;
If present, the properties
event property is used to
populate the payload with additional items; for instance, an action
properties={time=os.time()}
will result in a time
key being added. Non-string values will be JSON-encoded (regardless of
the content type).
If present, the headers
event property is used to add
HTTP headers to the request being sent.
If present, the message_short
event property is used for
the message; otherwise, message
is used.
Notification rules
The rule system is centered around two kinds of entities:
- condition, which determines if a rule is matched, and
- action, which determines what happens if it matches.
A condition is a Lua expression, while rules are Lua blocks (may contain several statements).
Roughly, the condition/action table is equivalent to:
if condition1 then action1 end if condition2 then action2 end if condition3 then action3 end ...
Notifying of a failed login attempt
NOTICE login denied for auth_login@auth_ip (auth_method): auth_reason
id="dli.auth.login_denied"
auth_allowed=false
This means that when login is denied, a NOTICE-level message formatted as shown is sent, with the mentioned extra attributes. So what we want is to create a notification rule which matches such messages and notifies the administrator. Among other things, it's possible to match it in the notification rule condition by ID
id=="dli.auth.login_denied"
or, to be more generic and not rely on a specific ID, match the auth_allowed property which is equal to false only for this event type:
auth_allowed==false
It doesn't really matter which option you choose in this particular case.
These example conditions use the event IDs in the notification section. System log fragment: Feb 1 13:09:54 LPC959 user.notice autoping[1441]: item item0 (192.168.11.30) failed [1/2]:[2/4] The condition id=="dli.autoping.item_failure" will identify a failure. in the condition below, we require the IP address to be present as well: id=="dli.autoping.item_failure" and ping_item_addrs == "192.168.0.30" In the notification area: This makes a purely custom message message="PRO at Building 1: Server .30 autoping failed"; notify("IT-Alert") This appends your custom message to the original message: message=message .. "PRO at Building 1: Server .30 autoping failed"; notify("IT-Alert")
However, an important difference is that if a condition would cause an error, the condition is considered false instead; the corresponding action not taken, but the rule check goes on.
Additionally, an empty condition is equivalent to true
,
and the corresponding action is unconditionally taken. To disable an
action without deleting it, you can use an explicitly false condition
false
or a condition that's not a valid Lua expression,
e.g. -
. To keep the condition text, you can wrap it with
false and (...)
.
Rules are applied from the first one to the last one, so order is important. The "Operations" column contains buttons which make manipulating rule order easier.
Though you can filter events by the type identifier, it's not
necessary in many cases. For example, the condition
auth_allowed==false
will match only dli.auth.login_denied
events, as auth_allowed
is set to false
for
those events only. This is notably distinct from a not
auth_allowed
condition, which will match all sorts of messages
which don't have an auth_allowed
property.
Tricks which allow running code in the condition (as opposed to the action) are possible but discouraged.
Notification event types
Miscellaneous servers expose the types of events they can produce; they are presented on the notification configuration page in a compact form. Here's an example:
Underlined items (both in the message and in the 'extra properties' column) specify properties which can be checked for. You can hover them for more detailed descriptions.
Examples:
Condition | Action | Explanation |
unit_id="PRO at-Skylab " | Create the variable "unit_id" to use later in notifications. This must be above (before) any notification that uses it. | |
outlet==1 and physical_state==true | message="Outlet 1 is ON"; notify("Brian") | Outlet 1 was turned on |
outlet==1 and physical_state==false | message="Outlet 1 is OFF"; notify("Brian") | Outlet 1 was turned off |
outlet==2 and physical_state~= nil | message="Outlet 2 switched"; notify("Brian") | Outlet 2 was switched on or off |
auth_allowed==false | notify("admin") | Someone failed to login |
auth_allowed==true | notify("admin") | Someone successfully logged in |
auth_allowed==true or auth_allowed==false | message_short=severity_string(severity)..unit_id;notify("admin") | Notify of all login attempts. Set the subject line of the email to the unit_id and severity_string. (severity_string is available in firmware 1.9.7.0+) |
id=="dli.autoping.item_failure" | notify("admin") | An autoping failed and an autoping script was run |
id=="dli.autoping.item_consecutive_failure" | message=unit_id..message;notify("alert-IT") | An autoping completely failed and autoping was disabled. Notify the IT department and prepend the message with the unit_id |
id=="dli.autoping.item_failure" and ping_item_addrs == "8.8.8.8" | notify("alert-IT") | An autoping script was run and the autoping target was 8.8.8.8 |
id=="dli.autoping.item_consecutive_failure" and ping_item_addrs == "8.8.8.8" | notify("alert-IT") | An autoping completely failed autoping target was 8.8.8.8 |
id=="dli.autoping.item_failure" and ping_item_addrs == "8.8.8.8,1.1.1.1" | notify("alert-IT") | An autoping script was run and the autoping target was 8.8.8.8 and 1.1.1.1 |
id=="dli.script.script_event" and script_data.net_index==1 | message_short = unit_id.." alert!" ;message_long = script_message; notify("alert-IT") |
An script generated an event where a created net_index was set to 1 and the message text was specfied in the script*. |
physical_state~=nil | snmp_values={{string.format('1.3.6.1.2.1.229.1.2.1.8.%d', outlet-1), 'integer', state and (259 or 257)}}; notify("snmp-target") | Send an SNMP inform or trap of any outlet changing state. |
bus_powered==false | message_short=unit_id;notify("it-admin") | Send a notification that the EPCR controller has lost main power. |
*in the script: event.send("Network was rebooted",{net_index=1}) -- Trigger the notification event
Back to top
Have a smart script or unique way to use your switch? Let us know!
engineering@digital-loggers.com