This short article describes how to send email alerts when one of the gateway driver encounters issues causing it to crash and try to restart. In the article below, the monitored gateway is a Modbus gateway called MCR (Measure Control Regulation), but the principles shown in the article can apply to any other type of gateway.
In order to send email alerts, the SMTP client can be configured. The SMTP parameters will depend on your email provider (Host, Port, and Secure parameters) and your email account (Username and Password parameters).

In the route you have to set the route Type to gateway status. The Source Gateway is in this example is a modbus gateway named MCR. When this gateway status (disconnected, pending, connecting, connected) changes, it triggers the execution of the route, and the routing function is called. Finally the Destination Address is the email address of the alert recipient.

The routing function defined in the route Source Value transforms the status of the gateway (here the Modbus gateway) into an email object containing the subject property and the text property.
function (status, source, dest, info) {
// The info.context variable is kept between each execution of the function
// and permits to store the previous status.
// Here it is useful to avoid spamming repetitive email alerts.
// Defines the new status
let status_new = (status === "connected");
// Verifies if the status changed, or if it is is a routing reprod (retry).
// Routing reprods might happen due to driver errors or internal routing congestion.
if (info.context.mcr_status !== status_new || info.reprod) {
info.context.mcr_status = status_new;
// gets the device VPN IP address (if the "system" gateway is started).
let vpnIp = this.getLastValue('#network/weble/inet_addr') || "26.x.x.x";
// If the communication is back
if (status_new) {
return {
subject: "Alert - communication is restored",
text: "Communication between the KNX installation and MCR is reestablished \n\nTo connect to the box (only if The Weble Connect VPN client is active), click here: http://" + vpnIp
};
} else {
// If the driver tries to restart due to some failure
return {
subject: "Alert - communication interrupted",
text: "Communication between the KNX installation and MCR is interrupted \n\nTo connect to the box (only if the Weble Connect VPN client is active), click here: http://" + vpnIp
};
}
}
}
It can be interesting not only to send alerts when the driver status changes from connected, disconnected, pending, connecting, connected, etc.. but also to check if the gateway driver crashed with a specific error and eventually send this error by email. Here is the routing function to do so. Note that if the same crash log is recurring periodically, it is only renewed by the system every 24 hours. So the same recurring crash log can only generate maximum one alarm per day.
function (status, source, callback) {
if (status == "disconnected") { // If the status is disconnected
this.getCrashLog(source, function(err, log) { // Gets the last crash log of the gateway to check.
if (log && Math.abs(log.ts - Date.now()) < 5000) {
// A crash log exists and it is recent (less than 5 seconds).
let text = "Driver " + source.name + " crashed at " + new Date().toLocaleString() + " with error: \n\n" + JSON.stringify(log, null, 2)
callback(null, {
subject: "crash of " + source.name,
text
})
} else {
// Either the driver never crashed, or the crash is old, do not route anything.
callback()
}
})
} else { // If the status is not disconnected
return null // Do not route anything ( here same as calling callback() )
}
}
In some protocols such as modbus RTU master, if one slave device does not reply it will not cause the whole driver to crash. In this case in order to generate alarms, it is possible to use the address status of one slave register that is regularly polled / read by the modbus master driver.
The route should look like the example below, with route type set to status.

And the Source value routing function can be as follow
function(status,source,destination,options){
if(status.startsWith("!")){
// if the address status starts with !, this is an error such as !timeout
var slaveId = (source.name.match(/%(?:M|Q|MX|QX)(\d+)-/) || [])[1] || ''
// source.name is "%M2-1". Extracts the slave id (here 2) if it is specified.
if(!options.context.lastAlarmTs){ // keep in memory the date of the last sent alarm by slave id.
options.context.lastAlarmTs = {}
}
if(!options.context.lastAlarmTs[slaveId] || Date.now() - options.context.lastAlarmTs[slaveId] > 1000*60*60){
// if no alarms where sent before or if the alarm is older than one hour (to avoid spamming emails)
options.context.lastAlarmTs[slaveId] = Date.now()
return {
"text" : "error when reading modbus register " + source.name + ": " + status,
"subject" : "modbus slave alert " + slaveId
}
}
}
}