/************************************************************************/
/* Copyright 1998 MBARI							*/
/************************************************************************/
#ifndef _ALARM_H
#define _ALARM_H
static char Alarm_h_id[] = "$Header: /u/oreilly/rov/tmacs/RCS/Alarm.h,v 1.8 1998/12/18 21:07:21 oreilly Exp $";

/*
$Log: Alarm.h,v $
Revision 1.8  1998/12/18 21:07:21  oreilly
Added documentation

Revision 1.7  1997/10/03 09:22:55  oreilly
Added PSU alarms

 * Revision 1.6  97/08/12  14:14:06  14:14:06  oreilly (Thomas C. O'Reilly)
 * Added thresholds and monitor items to GraduatedAlarm
 * 
 * Revision 1.5  97/06/16  16:01:00  16:01:00  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.4  97/05/28  15:16:48  15:16:48  oreilly (Thomas C. O'Reilly)
 * Added StickyAlarms to alarm actions. Added indexPriority() function.
 * 
 * Revision 1.3  97/05/20  16:41:24  16:41:24  oreilly (Thomas C. O'Reilly)
 * NoPriority is defined as Priority3 + 1
 * 
 * Revision 1.2  97/03/20  12:32:38  12:32:38  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.1  96/10/28  09:13:09  09:13:09  oreilly (Thomas C. O'Reilly)
 * Initial revision
 * 
*/

#include "DataManager.h"
#include "microdef.h"
#include "gf5vDef.h"
// #include "moogdef.h"
#include "array.h"

#define PriorityMnem          "priority"
#define MnemonicMnem          "mnemonic"
#define AckAllMnem            "ackAllChanges"
#define OnePriorityMnem       "onePriority"

#define AlarmNameSuffix "_ALARM"
#define GfCurrentSuffix "_CURRENT"

/* Non-abstract alarm types */
typedef enum
{
  MotorStatusAlarmType, 
  IbcAlarmType, 
  GfAlarmType, 
  GfTestAlarmType, 
  Gf5vTestAlarmType,
  BooleanAlarmType, 
  QuadSerPsuAlarmType, 
  NavPsuAlarmType, 
  VmePsuAlarmType, 
  TelemPsuAlarmType, 
  EventAlarmType,

  UnkAlarmType,             // This MUST be last type in enum!

} AlarmType;

#define NAlarmActions 4
#define BeepOnce 01
#define BeepTilAck 02
#define PopupList 04
#define StickyAlarms 010

inline char *alarmActionName(int bit)
{
  switch (bit)
  {
    case 0:
    return "beepOnce";
    
    case 1:
    return "beepTilAck";

    case 2:
    return "popupList";

    case 3:
    return "stickyAlarms";

    default:
    return "UnknownAction";
  }
}

// Number of priority levels (excluding NoPriority) 
#define NPriorityLevels 3

/* Priority levels MUST start at 1 (excluding NoPriority).
   NoPriority is set at 1 more than the maximum priority value; this
   makes handling of arrays easier.
*/
typedef enum
{
  Priority1 = 1, Priority2, Priority3, NoPriority

} Priority;


inline Priority lowestPriority()
{
  return Priority3;
}


inline Priority highestPriority()
{
  return Priority1;
}

inline Priority higherPriority(Priority p1, Priority p2)
{
  return MIN(p1, p2);
}


inline MBool validPriority(int priority)
{
  if ((priority >= Priority1 && priority <= Priority3) 
      || priority == NoPriority)
    return TRUE;
  else
    return FALSE;
}


inline int priorityIndex(Priority p)
{
  return p - 1;
}


inline Priority indexPriority(int p)
{
  return (Priority )(p + 1);
}


struct ValuePriority
{
  ValuePriority(int v, Priority p)
  {
    value = v;
    priority = p;
  }
  
  Nat16 value;
  Priority priority;
};

inline MBool psuAlarm(AlarmType type)
{
  if (type == QuadSerPsuAlarmType ||
      type == NavPsuAlarmType ||
      type == VmePsuAlarmType ||
      type == TelemPsuAlarmType)

    return TRUE;

  else

    return FALSE;
}


#define NoAlarmValue -1
/*
CLASS 
Alarm

DESCRIPTION
Anomalous conditions are monitored via Alarm objects. Alarm contains
a DmObject, whose value indicates the alarm state. Each alarm state can
be assigned a "priority". When the object's value is okayValue(), the 
Alarm is said to be "inactive"; otherwise it is "active".
User can "acknowledge" an active alarm through GUIs such as AlarmLight.
(EventAlarm objects have no value, and are handled somewhat differently.)

AUTHOR
Tom O'Reilly
*/
class Alarm 
{
  public:

  Alarm();
  ~Alarm();

  char *name()
  {
    return (char *)_dmObject->getName();
  }
  
  ///////////////////////////////////////////////////////////////////
  // Read DM item and update internal state of alarm
  virtual int update() = 0;

  ///////////////////////////////////////////////////////////////////
  // Return TRUE if alarm is "active", else FALSE
  virtual MBool active() = 0;

  ///////////////////////////////////////////////////////////////////
  // Return TRUE if alarm was "active", else FALSE
  virtual MBool wasActive() = 0;

  ///////////////////////////////////////////////////////////////////
  // Return alarm value
  virtual int value() = 0;

  ///////////////////////////////////////////////////////////////////
  // Return value which signifies "OK"
  virtual int okayValue() = 0;
  
  ///////////////////////////////////////////////////////////////////
  // Return TRUE if alarm has been acknowledged
  MBool acknowledged() {
    return _acknowledged;
  }

  ///////////////////////////////////////////////////////////////////
  // Return TRUE if alarm was acknowledged
  MBool wasAcknowledged()
  {
    return _prevAcknowledged;
  }
  
  ///////////////////////////////////////////////////////////////////
  // Acknowledge/unacknowledge alarm
  void acknowledge(MBool acknowledge = TRUE);
  
  ///////////////////////////////////////////////////////////////////
  // Return pointer to alarm DmObject
  DmObject *dmObject()
  {
    return _dmObject;
  }

  ///////////////////////////////////////////////////////////////////
  // Indicates if alarm is an EventAlarm
  virtual MBool eventAlarm() = 0;

  ///////////////////////////////////////////////////////////////////
  // Return TRUE if alarm can take more than 2 values
  virtual MBool multiValued()
  {
    return FALSE;
  }
  
  
  ///////////////////////////////////////////////////////////////////
  // Return time of last update
  void writeTime(DM_Time *t)
  {
    t->tv_sec = _writeTime.tv_sec;
    t->tv_usec = _writeTime.tv_usec;
  }

  ///////////////////////////////////////////////////////////////////
  // Set mnemonic for alarm
  void setItemMnemonic(char *mnemonic);

  ///////////////////////////////////////////////////////////////////
  // Return mnemonic for item, or if it doesn't have one, DM item name
  char *itemMnemonic();
  
  ///////////////////////////////////////////////////////////////////
  // Set default priority
  void setPriority(Priority priority)
  {
    _priority = priority;

    if (_dmForward)
      forward();
  }

  ///////////////////////////////////////////////////////////////////
  // Set priority for specified alarm value
  virtual void setPriority(int value, Priority priority) = 0;

  ///////////////////////////////////////////////////////////////////
  // Set whether user must acknowledge all state changes (including
  // change to OK state)    
  virtual void setAckAllChanges(MBool yesNo) = 0;

  ///////////////////////////////////////////////////////////////////
  // Indicate if user must acknowledge all changes
  virtual MBool ackAllChanges() = 0;
  
  ///////////////////////////////////////////////////////////////////
  // Return mnemonic for given alarm type
  static char *typeMnemonic(AlarmType type);
  
  ///////////////////////////////////////////////////////////////////
  // Return AlarmType corresponding to specified mnemonic
  static AlarmType mnemonicType(char *mnemonic);

  ///////////////////////////////////////////////////////////////////
  // Return internal value corresponding to specified type and mnemonic
  static int mnemonicValue(AlarmType type, char *mnemonic);

  ///////////////////////////////////////////////////////////////////
  // Return mnemonic corresponding to specified type and value
  static char *valueMnemonic(AlarmType type, int value);
  
  ///////////////////////////////////////////////////////////////////
  // Return type of alarm
  virtual AlarmType type() = 0;

  ///////////////////////////////////////////////////////////////////
  // Set "threshold" item corresponding to alarm alarm
  virtual int setThresholdItem(int value, char *itemName)
  {
    return -1;
  }

  ///////////////////////////////////////////////////////////////////
  // Return TRUE if other DM_Items associated with Alarm have been 
  // specified
  virtual MBool complete(char *errorBuf)
  {
    return TRUE;
  }


  ///////////////////////////////////////////////////////////////////
  // Specify name of DM_Item which whose value is monitored by this alarm
  virtual void setMonitoredItem(char *itemName)
  {
  }

  static const char *const UnkValueMnem;
  static const char *const MotorStatusTypeMnem;
  static const char *const IbcTypeMnem;
  static const char *const GfTypeMnem;
  static const char *const GfTestTypeMnem;
  static const char *const Gf5vTestTypeMnem;
  static const char *const BooleanTypeMnem;
  static const char *const QuadSerPsuTypeMnem;
  static const char *const NavPsuTypeMnem;
  static const char *const VmePsuTypeMnem;
  static const char *const TelemPsuTypeMnem;
  static const char *const EventTypeMnem;

  ///////////////////////////////////////////////////////////////////
  // Return Priority
  virtual Priority priority(int value)
  {
    return _priority;
  }

  ///////////////////////////////////////////////////////////////////
  // Set name of associated item
  void setAssociatedItem(char *itemName)
  { 
    _associatedItem = strdup(itemName);
  }

  ///////////////////////////////////////////////////////////////////
  // Return name of associated data manager item
  char *associatedItem()
  {
    return _associatedItem;
  }

  ///////////////////////////////////////////////////////////////////
  // Determine whether to "forward" alarm info via datamanager
  // (for use by other apps, such as video overlay)
  int setForwarding(MBool forward);

  ///////////////////////////////////////////////////////////////////
  // Return TRUE if alarm info is forwarded
  MBool forwarding();

  ///////////////////////////////////////////////////////////////////
  // Return TRUE if alarm is GraduatedAlarm
  virtual MBool graduated()
  {
    return FALSE;
  }
  
  protected:

  ///////////////////////////////////////////////////////////////////
  // _dmObject points to DmObject of appropriate type
  DmObject *_dmObject;

  ///////////////////////////////////////////////////////////////////
  // _dmForward is used to communicate alarm ack status (and priority) to
  // other processes (e.g. video overlay)
  DmNat16Object *_dmForward;

  MBool _acknowledged;
  MBool _prevAcknowledged;

  ///////////////////////////////////////////////////////////////////
  // Time DM_Item was last written
  DM_Time _writeTime;

  ///////////////////////////////////////////////////////////////////
  // DM item mnemonic
  char *_itemMnemonic;

  Priority _priority;

  char *_associatedItem;
 
  // Forward information
  int forward();
};


/*
CLASS 
EventAlarm

DESCRIPTION
An EventAlarm is "valueless"; i.e. this alarm just indicates that
"something" happened, but the event has no value associated with it.

AUTHOR
Tom O'Reilly
*/
class EventAlarm : public Alarm
{
  public:
  EventAlarm(const char *name);
  ~EventAlarm();

  AlarmType type()
  {
    return EventAlarmType;
  }
  
  ///////////////////////////////////////////////////////////////////
  // This function should only be called if update has actually 
  // occurred
  virtual int update();

  ///////////////////////////////////////////////////////////////////
  // EventAlarm is NEVER active
  virtual MBool active()
  {  
    return FALSE;
  }
  
  ///////////////////////////////////////////////////////////////////
  // EventAlarm is NEVER active
  virtual MBool wasActive()
  {
    return FALSE;
  }
  
  ///////////////////////////////////////////////////////////////////
  // Set priority for specified alarm value;
  // Does nothing for EventAlarm, since EventAlarm has no associated value
  virtual void setPriority(int value, Priority priority)
  {
    return;
  }

  ///////////////////////////////////////////////////////////////////
  // Of course return TRUE
  MBool eventAlarm()
  {
    return TRUE;
  }

  ///////////////////////////////////////////////////////////////////
  // Set whether user must acknowledge all state changes (including
  // change to OK state)
  // This function does nothing for EventAlarm
  void setAckAllChanges(
			MBool yesNo
			)
  {
    return;
  }

  MBool ackAllChanges()
  {
    return TRUE;
  }
  
  ///////////////////////////////////////////////////////////////////
  // EventAlarm is valueless
  int value() 
  {
    return NoAlarmValue;
  }
  
  ///////////////////////////////////////////////////////////////////
  // EventAlarm is valueless
  virtual int okayValue()
  {
    return NoAlarmValue;
  }
  
  protected:
  DmEmptyObject *_dmEmptyObject;
};


/*
CLASS 
ValueAlarm

DESCRIPTION
ValueAlarm has a set of associated values 

AUTHOR
Tom O'Reilly
*/
class ValueAlarm : public Alarm
{
  public:

  ValueAlarm();
  ~ValueAlarm();
  

  // Return current alarm state
  virtual MBool active()
  {
    if (_value != okayValue())
      return TRUE;
    else
      return FALSE;
  }

  virtual MBool wasActive()
  {
    if (_prevValue != okayValue())
      return TRUE;
    else
      return FALSE;
  }
  

  ///////////////////////////////////////////////////////////////////
  // This is not an EventAlarm
  MBool eventAlarm()
  {
    return FALSE;
  }

  ///////////////////////////////////////////////////////////////////
  // Set whether user must acknowledge all state changes (including
  // change to OK state)
  void setAckAllChanges(
			MBool yesNo
			)
  {
    _ackAllChanges = yesNo;
  }
  
  MBool ackAllChanges()
  {
    return _ackAllChanges;
  }
  
  ///////////////////////////////////////////////////////////////////
  // Return current internal value
  int value() 
  {
    return _value;
  }
  
  ///////////////////////////////////////////////////////////////////
  // Set priority for specified alarm value;
  virtual void setPriority(int value, Priority priority);
  
  ///////////////////////////////////////////////////////////////////
  // Return priority for specified value
  Priority priority(int value);

  ///////////////////////////////////////////////////////////////////
  // Return highest set priority
  Priority highestSetPriority();
  
  protected:
  int _value;
  int _prevValue;
  
  MBool _active;
  MBool _ackAllChanges;

  DynArray<ValuePriority *> _valuePriority;  
};


/*
CLASS 
BooleanAlarm

DESCRIPTION
BooleanAlarm can take one of two values, True or False

AUTHOR
Tom O'Reilly
*/
class BooleanAlarm : public ValueAlarm
{
  public:
  
  BooleanAlarm(const char *name);
  ~BooleanAlarm();
  
  AlarmType type()
  {
    return BooleanAlarmType;
  }

  virtual int update();

  virtual int okayValue()
  {
    return 0;
  }
  
  ///////////////////////////////////////////////////////////////////
  // Return mnemonic string for specified value
  static char *valueMnemonic(int value);

  ///////////////////////////////////////////////////////////////////
  // Return internal value of specified mnemonic string
  static int mnemonicValue(char *mnemonic);

  static const char *const TrueMnem;
  static const char *const FalseMnem;

  protected:

  Priority _priority;
  DmBooleanObject *_dmBooleanObject;
};


/*
CLASS 
PsuAlarm

DESCRIPTION
Indicates power supply status 

AUTHOR
Tom O'Reilly
*/
class PsuAlarm : public ValueAlarm
{
  public:
  
  PsuAlarm(const char *name);
  ~PsuAlarm();
  
  virtual int update();

  virtual int okayValue()
  {
    return 0xffff;
  }
  
  ///////////////////////////////////////////////////////////////////
  // Return mnemonic string for specified value
  static char *valueMnemonic(int value);

  ///////////////////////////////////////////////////////////////////
  // Return internal value of specified mnemonic string
  static int mnemonicValue(char *mnemonic);

  ///////////////////////////////////////////////////////////////////
  // Return expanded alarm state description
  virtual const char *valueDescription() = 0;

  static const char *const TrueMnem;
  static const char *const FalseMnem;

  ///////////////////////////////////////////////////////////////////
  // Return current internal value
  int value() 
  {
    return _value;
  }

  ///////////////////////////////////////////////////////////////////
  // Return current alarm state
  virtual MBool active()
  {
    if (_value != okayValue())
      return TRUE;
    else
      return FALSE;
  }

  virtual MBool wasActive()
  {
    if (_prevValue != okayValue())
      return TRUE;
    else
      return FALSE;
  }
  
  virtual Nat16 validBits() = 0;
  
  protected:

  Nat16 _value;
  Nat16 _prevValue;
  Priority _priority;
  DmNat16Object *_dmNat16Object;
};


/*
CLASS 
QuadSerPsuAlarm

DESCRIPTION
PsuAlarm for quad serial board

AUTHOR
Tom O'Reilly
*/
class QuadSerPsuAlarm : public PsuAlarm
{
  public:
  
  QuadSerPsuAlarm(const char *name);
  ~QuadSerPsuAlarm();
  
  AlarmType type()
  {
    return QuadSerPsuAlarmType;
  }

  virtual int okayValue();
  
  virtual const char *valueDescription();

  virtual Nat16 validBits();
};


/*
CLASS 
NavPsuAlarm

DESCRIPTION
PsuAlarm for Nav board

AUTHOR
Tom O'Reilly
*/
class NavPsuAlarm : public PsuAlarm
{
  public:
  
  NavPsuAlarm(const char *name);
  ~NavPsuAlarm();
  
  AlarmType type()
  {
    return NavPsuAlarmType;
  }

  virtual const char *valueDescription();
  virtual Nat16 validBits();
};


/*
CLASS 
VmePsuAlarm

DESCRIPTION
PsuAlarm for Vme IBC

AUTHOR
Tom O'Reilly
*/
class VmePsuAlarm : public PsuAlarm
{
  public:
  
  VmePsuAlarm(const char *name);
  ~VmePsuAlarm();
  
  AlarmType type()
  {
    return VmePsuAlarmType;
  }

  virtual const char *valueDescription();
  virtual Nat16 validBits();
};


/*
CLASS 
TelemPsuAlarm

DESCRIPTION
PsuAlarm for Telemetry micro

AUTHOR
Tom O'Reilly
*/
class TelemPsuAlarm : public PsuAlarm
{
  public:
  
  TelemPsuAlarm(const char *name);
  ~TelemPsuAlarm();
  
  AlarmType type()
  {
    return TelemPsuAlarmType;
  }

  virtual const char *valueDescription();
  virtual Nat16 validBits();
};



/*
CLASS 
EnumAlarm

DESCRIPTION
Takes enumerated values 

AUTHOR
Tom O'Reilly
*/
class EnumAlarm : public ValueAlarm
{
  public:
  EnumAlarm(const char *name);
  ~EnumAlarm();
  
  virtual int update();

  MBool multiValued()
  {
    return TRUE;
  }

  protected:

  DmEnumObject *_dmEnumObject;
};


/*
CLASS 
GfTestAlarm

DESCRIPTION
Alarm for test of ground fault card

AUTHOR
Tom O'Reilly
*/
class GfTestAlarm : public EnumAlarm 
{
  public:
  GfTestAlarm(const char *name);
  
  AlarmType type()
  {
    return GfTestAlarmType;
  }
  
  static const char *const OkMnem;
  static const char *const FailOnMnem;
  static const char *const FailOffMnem;

  // Return mnemonic string for specified value
  static char *valueMnemonic(int value);

  // Return internal value of specified mnemonic string
  static int mnemonicValue(char *mnemonic);

  virtual int okayValue()
  {
    return GF_TEST_OK;
  }

  MBool multiValued()
  {
    return TRUE;
  }

};


/*
CLASS 
Gf5vTestAlarm

DESCRIPTION
Alarm for test of 5 volt ground fault card

AUTHOR
Tom O'Reilly
*/
class Gf5vTestAlarm : public EnumAlarm
{
  public:
  Gf5vTestAlarm(const char *name);
  
  AlarmType type()
  {
    return Gf5vTestAlarmType;
  }

  static const char *const NotRunMnem;
  static const char *const AtodFailedMnem;
  static const char *const SelfTestFailedMnem;
  static const char *const SelfTestPassedMnem;

  // Return mnemonic string for specified value
  static char *valueMnemonic(int value);

  // Return internal value of specified mnemonic string
  static int mnemonicValue(char *mnemonic);

  virtual int okayValue()
  {
    return GF_SELFTEST_PASSED;
  }

  MBool multiValued()
  {
    return TRUE;
  }

};


/*
CLASS 
MotorStatusAlarm

DESCRIPTION
Motor status

AUTHOR
Tom O'Reilly
*/
class MotorStatusAlarm : public EnumAlarm
{
  public:
  MotorStatusAlarm(const char *name);

  AlarmType type()
  {
    return MotorStatusAlarmType;
  }

  static const char *const UnkStatusMnem;
  static const char *const NoFaultMnem;
  static const char *const ControlVoltMnem;
  static const char *const ControlTempMnem;
  static const char *const StallMnem;
  static const char *const ResolverMnem;
  static const char *const OverCurrMnem;
  static const char *const FaultMnem;
  
  // Return mnemonic string for specified value
  static char *valueMnemonic(int value);

  // Return internal value of specified mnemonic string
  static int mnemonicValue(char *mnemonic);

  virtual int okayValue();

  MBool multiValued()
  {
    return TRUE;
  }
};


/*
CLASS 
GraduatedAlarm

DESCRIPTION
GraduatedAlarm has values which indicate progressively more
severe or dangerous states

AUTHOR
Tom O'Reilly
*/
class GraduatedAlarm : public EnumAlarm
{
  public:
  GraduatedAlarm(const char *name);
  ~GraduatedAlarm();

  virtual MBool graduated()
  {
    return TRUE;
  }
  
  virtual MBool complete(char *errorBuf);
  virtual void setMonitoredItem(char *itemName);
  const char *monitoredItem();

  MBool multiValued()
  {
    return TRUE;
  }
  
  protected:

  // Name of monitored DM Item
  char *_monitoredItem;     

};


/*
CLASS 
IbcAlarm

DESCRIPTION
GraduatedAlarm for IBCs

AUTHOR
Tom O'Reilly
*/
class IbcAlarm : public GraduatedAlarm
{
  public:
  IbcAlarm(const char *name);
  ~IbcAlarm();
  
  AlarmType type()
  {
    return IbcAlarmType;
  }
  
  static const char *const AlarmMnem;
  static const char *const WarningMnem;
  static const char *const OkMnem;
  static const char *const WarningThresholdSuffix;
  static const char *const AlarmThresholdSuffix;

  // Return mnemonic string for specified value
  static char *valueMnemonic(int value);

  // Return internal value of specified mnemonic string
  static int mnemonicValue(char *mnemonic);

  virtual int okayValue()
  {
    return MICRO_ALARM_OK;
  }

  virtual int setThresholdItem(int value, char *itemName);
  virtual MBool complete(char *errorBuf);

  const char *warningThresholdItem();
  const char *alarmThresholdItem();
  
  protected:

  char *_warningThresholdItem;
  char *_alarmThresholdItem;
};


/*
CLASS 
GfAlarm

DESCRIPTION
Indicates ground fault 

AUTHOR
Tom O'Reilly
*/
class GfAlarm : public GraduatedAlarm 
{
  public:
  GfAlarm(const char *name);
  ~GfAlarm();
  
  AlarmType type()
  {
    return GfAlarmType;
  }
  
  static const char *const NormalMnem;
  static const char *const AdvisoryMnem;
  static const char *const WarningMnem;
  static const char *const CriticalMnem;

  // Return mnemonic string for specified value
  static char *valueMnemonic(int value);

  // Return internal value of specified mnemonic string
  static int mnemonicValue(char *mnemonic);

  virtual int okayValue()
  {
    return GF_NORMAL;
  }
};


inline double tval2sec(DM_Time *t)
{
  return t->tv_sec + 0.000001 * (double )t->tv_usec;
}


/* Prototypes */
int alarmFileLineNo();

#endif


