Custom Alarm Hook API
To add extra functionality to an alarm action, create an alarm hook module. If your application contains a module with a name that matches one of the hook names defined within the Alarm Manager then your module will be called just before the transaction is logged, allowing you to perform extra work.
An alarm hook may not return INVALID. It should return TRUE to allow the transaction to proceed and be logged. Alarm hooks that return FALSE will stop the transaction from proceeding.
The hook module may be defined with one parameter, which VTScada will use to pass in the fully-populated Alarm Transaction Structure structure.
In versions of VTScada prior to release 11.2, developers who wanted to add custom functionality to an alarm event would override a module of the Alarm Manager to add their code. That technique is now obsolete. Many existing overrides will continue to work, but should be tested before being put into production use with version 11.2 or later.
1) Numbers following a hook name refer to notes that come after the lists.
2) A star following a hook name means that it appears in one of the examples later in this topic.
Standard alarm hooks:
These are the most common. All of the standard hooks take an alarm transaction as an argument and return TRUE or FALSE to allow or ban that transaction.
- AlarmAckHook {*}
- AlarmActiveHook
- AlarmCommissionHook
- AlarmDecommissionHook
- AlarmDisableHook
- AlarmEnableHook
- AlarmEventHook
- AlarmModifyHook
- AlarmNormalHook {*}
- AlarmNormalAckHook {2}
- AlarmNormalTripHook {2}
- AlarmOffNormalHook {3}
- AlarmPurgeHook
- AlarmRearmHook
- AlarmShelveHook
- AlarmTripHook
- AlarmUnshelveHook
Non-standard hooks:
These must be script safe.
- AlarmAckAllHook {1}
- AlarmEnableAckUIHook {5}{*}
- AlarmEnableShelveUIHook {5}
- AlarmEnableUnshelveUIHook {5}
- AlarmPlaySoundFilterHook {4}{*}
- AlarmPrintListHook {6}
Deprecated hooks:
- AlarmCellAckHook - Use AlarmEnableAckUIHook instead.
- AlarmCellUnshelveHook - Use AlarmEnableUnshelveUIHook instead.
{1} AlarmAckAllHook is unlike the other alarm hooks. The other hooks are called at the time the alarm transaction takes place, can alter the transaction structure, and can return true or false depending on whether they want the transaction to be logged or not. The AlarmAckAllHook will be called before the acknowledgment transactions take place. It will not be able to alter any transaction structures. If AlarmAckAllHook returns TRUE or Invalid, the alarms will all be acknowledged. If it returns FALSE, the alarms will not be acknowledged.
Note that AlarmAckAllHook is called only on the workstation where Ack All is pressed. If this needs to be shared via remote procedure calls to a different workstation, then your module to implement AlarmAckAllHook must include that feature.
{2} If AlarmNormalAckHook is not defined, AlarmNormalHook will be called instead.
{3} If AlarmOffNormalHook is not defined, AlarmActiveHook will be called instead.
{4} AlarmPlaySoundFilterHook is run whenever a new alarm comes up. It will run again if the alarm is already sounding, and it will also run if the alarms are muted. It takes an alarm record rather than an alarm transaction, and needs to be script safe.
{5} These disable alarm user interface (UI) actions based on the rules in your module. (One use case might be to disable alarm acknowledgment for someone who does not have the appropriate Control Tokens.) They take an alarm record structure as an argument and return TRUE or FALSE to enable or disable UI for acknowledging, shelving, or unshelving. They must be both script and steady state safe. These will also be called for alarms that are being acknowledged by an Ack All and will be able to stop those alarms from being acknowledged, but they will not be able to disable Ack All buttons.
{6} If AlarmPrintListHook is defined, it will be called by the alarm page printing module. Your hook module must format the entire print output including headers, body and footers. Further notes follow:
Returns:
A Buffer that will be directly written to the printer or chosen file
Usage:
Script Only
Parameters:
RecordArray - An array of AlarmRecord structures to be printed. Labels should have already been translated and processed to contain almost all useful information one might need to know about a record. The records will be the same that the Alarm List would show if it could show all, and they will be filtered according to current filter in the Alarm List.
Comments:
The AlarmPrintListHook module must return a text stream of the entire text to print. The RecordArray is a "friendly" version of an AlarmRecord, useful for displaying or printing alarms. The structure follows:
AlarmRecordInfo Struct [ Action { Translated Action }; AlarmType { Translated AlarmType }; Area { Translated Area }; Custom { Custom }; DateTime { Formatted date and time in user's time zone }; Deadband { Deadband }; Description { Translated Description }; Device { Device }; ExpiryTime { ExpiryTime in user's time zone }; FriendlyName { Alarm's friendly name }; Function { Function }; GenTimestamp { GenTimestamp in user's time zone }; GUID { GUID }; IsActive { TRUE if alarm is active; When viewing history, TRUE if alarm activated or tripped }; IsDisabled { TRUE if alarm is disabled }; IsHistory { TRUE if viewing history list }; IsShelved { TRUE if alarm is shelved }; IsUnacked { TRUE if alarm is unacked }; MessageID { OBSOLETE: stores the tag type }; Name { Alarm's uniqueID name }; OffDelay { OffDelay }; OnDelay { OnDelay }; Popup { PopupEnable }; Priority { Priority }; PriorityEvent { TRUE if Priority is 0 }; PriorityText { Translated Priority label }; RearmDelay { RearmDelay }; Record { Original Record }; RelativeName { Alarm's friendly name relative to a parent tag}; Root { Alarm tag object }; Session { User session }; Setpoint { Setpoint }; SetpointLabel { Translated Setpoint label }; TagDescription { Alarm tag's current Description }; Timestamp { Timestamp in user's time zone }; Units { Translated Units }; UserID { User's AccountID }; UserName { Friendly username }; ValueLabel { Translated Value label }; ValueLabels { Array of translated ValueLabels }; Value { Value }; Workstation { Friendly workstation name from MachineID }; ];
General Alarm Hook Examples:
Do something extra when the alarm closes:
<
AlarmNormalHook
(
{ parameter not required }
)
[
{ ... local variables ... }
]
Main
[
If 1;
[
{ Do something like write out a value to a PLC }
DoSomething();
{ Returning Invalid or TRUE allows the AlarmManager to log the Transaction when we’re done }
Return(TRUE);
]
]
>
Clear the alarm when it is acknowledged:
<
AlarmAckHook
(
TransactionStruct { transaction structure };
)
Main
[
If 1;
[
{ Acknowledge and Clear the alarm }
TransactionStruct\Transaction = Concat(TransactionStruct\Transaction, "Active-");
{ The additional transaction text is added to any that already exist. }
Return(TRUE);
]
]
>
To mute a subset of alarms, add a hook module named AlarmPlaySoundFilterHook.SRC to your application, declaring it in the AppRoot.SRC file. If this hook module exists in the application, it will be passed an alarm record for every alarm that could potentially be played. If the hook returns TRUE or Invalid, the alarm will be played, so long as the global Mute is not enabled. If it returns FALSE it will not be played. The parameter, Record, is documented in Alarm API Structure Definitions
The test within the hook might resemble the following generic example, where the Area property of the alarm record structure is being examined along with the name of the workstation. Alarms in the West area sound only on Server1 and alarms in the East area sound only on Server2.
<
AlarmPlaySoundFilterHook
(
Record { Alarm record };
)
Main
[
If 1;
[ CanPlay = Record.Area == "WEST" && WkStaInfo(0) == "SERVER1" || Record.Area == "EAST" && WkStaInfo(0) == "SERVER2";
Return(CanPlay); ] ] >
Allow alarm acknowledgment only after 4pm
{============================ AlarmEnableAckUIHook ===========================} < AlarmEnableAckUIHook ( AlarmRec; ) [ AllowAck; ] Main [ AllowAck = Now(1) > 16 * 3600 { Only allow acking after 4 PM }; If Watch(1, AllowAck); [ Return(AllowAck); ] ] >
Alarm API Structure Definitions - Includes the transaction structure.