Digital Loggers

Customize event notifications.


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.

notification_sinks.png
Notification target configuration

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 — the id 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.
notification_rules.png
Notification rule configuration

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:

notification_reference.png
Notification event types

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 ActionExplanation
  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