Custom Alarm Hook API

To add extra functionality to an alarm transaction, create an alarm hook module. A set of hook names has been defined within the Alarm Manager. If your application contains a module with a matching name, it 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 module may be defined with one parameter, which VTScada will use to pass in the fully-populated transaction 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.

Defined alarm hooks:

  • AlarmAckHook
  • AlarmAckAllHook {1}
  • AlarmActiveHook
  • AlarmCellAckHook
  • AlarmCommissionHook
  • AlarmDecommissionHook
  • AlarmDisableHook
  • AlarmEnableHook
  • AlarmEventHook
  • AlarmModifyHook
  • AlarmNormalHook
  • AlarmNormalAckHook {2}
  • AlarmNormalTripHook {2}
  • AlarmOffNormalHook {3}
  • AlarmPlaySoundFilterHook
  • AlarmPrintListHook {4}
  • AlarmPurgeHook
  • AlarmRearmHook
  • AlarmShelveHook
  • AlarmTripHook
  • AlarmUnshelveHook

{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 this hook is not defined, AlarmNormalHook will be called instead.

{3} If this hook is not defined, AlarmActiveHook will be called instead.

{4} 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.

Returns:

A Buffer that will be directly written to the printer or chosen file

Usage:

Script Only

Format:

\AlarmPrintListHook(RecordArray)

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:

This 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);
  ]
]
>

Mute a subset of alarms

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); ] ] >