alarmsapp_h

// C++ mod of alarms_app.h
#ifndef _ALARMSAPP_INCLUDED_
#define _ALARMSAPP_INCLUDED_

//if no version defined, define & use one
#if !(defined __edp_version_one__ || defined __edp_version_two__)
#define __edp_version_two__
#endif
//
//if both versions defined, undef two & use one
#if (defined __edp_version_one__ && defined __edp_version_two__)
#undef __edp_version_two__
#endif
//
#include <iostream>
#include <vector>
#include <map>
#include <list>
//
#include <cstdarg>
#include <string>
//
#include "stdio.h"
#include "cnsparam.h"
#include "cns_data_structs.h"
#include "acnet_errors.h"
#include "fermilib.h"
//
#ifdef __edp_version_one__
#define EDPNAMESIZ  10
#define EDPXNAMESIZ 16
#define EDPTEXTSIZ  50
#define EDPXTEXTSIZ 64
#else
#define EDPNAMESIZ  16
#define EDPXNAMESIZ 10
#define EDPTEXTSIZ  64
#define EDPXTEXTSIZ 50
#endif
//
#define EDPFULLNAMESIZ 64
#define EDMHDSIZ     8
#define ALMLOGID     2
#define ALARMSID     1
#define PBUFQSIZ    12
#define ALMLOGINITTIME 1600
#define ALMLOGCURRTIME 1601
#define ALARMSINITTIME 1602
#define ALARMSCURRTIME 1603

const int DMON_TCP_PORT = 4003;  //DAEMON TCP port */
const int UTIL_TCP_PORT = 4004;  //Utility port(for aux data) */
#define _EndOfData_  "endofdata" //end of data transfer for one request
#define _Quit_         "quit"    //TCP quits, socket closes w/o confirm

//typecode used by apps(daemon, server and driver)
const int ERPMsgType_c=0; // edp
const int SRPMsgType_c=1; //
const int eventDisplayMsg_c=1; // edp

//app sends/receives the following type codes
#define clr1DeviceCmd_c          3   /* same as ATC_K_CLR1 */
#define multClearCmd_c          10   /* same as ATC_K_MCLR */

//app only receives the following type codes
#define bigClearCmd_c            2   /* same as ATC_K_BIGC */
#define FrontEndBootCmd_c        9   /* same as ATC_K_FEBT */
#define almHeartBeat_c          33
#define almclearall             35   // clear all alarms
#define almStart_c              34   /* server starts */

//app may send the following type codes
#define almTerminate_c          31  /* terminate daemon, size=2 */
#define almSendACK_c            32  /* ACK alarm notification */
#define almSetTimeOut_c         36  /* not implemented */
#define almClientList_c         37  /* client list */
#define almSendActiveEvent_c    38  /* TCP msg size must be 2 */
#define almSendActiveAlarm_c    39  /* TCP msg size must be 2 */
#define almActiveAlarm_c        40  /* sent by daemon */
#define almActiveEvent_c        41  /* sent by daemon */
#define almAlarmCount_c         42  /* TCP msg size must be 2 */
#define almSendFEList_c         43  /* FE boot time, must send 2 bytes */
#define almGetAppList_c         44  /* TCP msg size must be 2 */

//app must honor the following type codes
#define almAppRegister_c        45  /* App registration form */
#define almDisplayMessage_c     46  /* alarms display shows this message */
#define almAddNodeDisplay_c     47  /* add a new node to display */
#define almUpdate_c             48  //send all new alarms

//app may make periodic request to DAEMON utility
#define almGroupMsg_c           51 // alarm group message
#define almDevicePeriodicData_c 52 /* answer from util */
#define almGetAlarmHistory_c    53
#define almGetCurrentAlarm_c    54
#define almGetDeviceAlarm_c     54
#define almAlarmText_c          55

//end of data transmission; indicates the end of a potentially 
//large message that has no predetermined end of message. 
//For now it is used to send active alarm list.
#define almEndOfData_c          63
#define almDriverMclr_c         90

typedef struct endOfDataTransStruct /* end of data transmission */
{
  unsigned char typcode;   /* = 63 always */
  unsigned char unused[3]; /* they are all 63 */
  int seq;
  int sec;
  int par1;
  int par2;
} endofdatatrans_t;
/*
 * app can only ignore the unknown type code
 */
#define almUnknown_c           127
/* 
 * Event Display Packet
 */
#define isBadRemove_c    -2  /* bad digital removed, implicitly */
#define isBad_c          -1
#define isGood_c          1 
#define isCleared_c       2  /* cleared by apps, CLR1 or MCLR */
#define isEvent_c         0 
#define isException_c     1  /* internal to ALARMS */

#define isBypassed_c    127  /* apps don't see this EDP */
#define isFEReboot_c    0xfeba  /* reason for MCLR */
#define isFEDead_c      0xdead  /* reason for MCLR */

//raw data stored in memory as byte stream form
//vector<edp_u> is stored in memory

#ifdef __edp_version_one__ //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#define EDPDATSIZ 108
#define EDPXDATSIZ 192
typedef struct EDPstruct
{
  unsigned char typcode; //1
  unsigned char priority; //2
  unsigned char trunk; //3
  unsigned char node; //4
  unsigned char ssn; //5
  char     erpType; //6
  unsigned short status; //8
  int      di; //12
  int      devClass; //16
  int      devType; //20
  char     digital; //21
  unsigned char bs; //22
  char     isBroken; //23
  unsigned char unused; //24
  char     name[EDPNAMESIZ];//34
  unsigned short  alarmListId;//36
  time_t   sec;//40
  int      seq;//44
  char     text[EDPTEXTSIZ];//94
  unsigned int rawdat; //98
  unsigned short handler_code;//100
  int      sound_id;//104
  int      speech_id;//108
} __attribute__((packed)) edp_t;
//
typedef struct EDPstructX
{
  unsigned char typcode; //1
  unsigned char priority; //2
  unsigned char trunk; //3
  unsigned char node; //4
  unsigned char ssn; //5
  unsigned char bs;  //6
  char erpType; //7
  char digital; //8
  char isBroken; //9
  unsigned char unused;//10
  //
  unsigned short status; //12
  unsigned short handler_code;//14
  unsigned short alarmListId;//16
  //
  int di; //20
  int devClass; //24
  int devType; //28
  time_t sec; //32
  int seq; //36
  int sound_id; //40
  int speech_id;//44
  unsigned int rawdat; //48
  char name[EDPXNAMESIZ];//64
  char fullname[EDPFULLNAMESIZ]; //128 [new]
  char text[EDPXTEXTSIZ]; //192
} __attribute__((packed)) edp_x;
#endif
//
#ifdef __edp_version_two__ //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//
#define EDPDATSIZ 192
#define EDPXDATSIZ 108
typedef struct EDPstruct
{
  unsigned char typcode; //1
  unsigned char priority; //2
  unsigned char trunk; //3
  unsigned char node; //4
  unsigned char ssn; //5
  unsigned char bs;  //6
  char erpType; //7
  char digital; //8
  char isBroken; //9
  unsigned char unused; //10
  //
  unsigned short status; //12
  unsigned short handler_code;//14
  unsigned short alarmListId;//16
  //
  int di; //20
  int devClass; //24
  int devType; //28
  time_t sec; //32
  int seq; //36
  int sound_id; //40
  int speech_id;//44
  unsigned int rawdat; //48
  //
  char name[EDPNAMESIZ];//64
  char fullname[EDPFULLNAMESIZ]; //128 [new]
  char text[EDPTEXTSIZ]; //192
} __attribute__((packed)) edp_t;
//
typedef struct EDPstructX
{
  unsigned char typcode;
  unsigned char priority;
  unsigned char trunk;
  unsigned char node;
  unsigned char ssn;
  char     erpType;
  unsigned short status; //8
  int      di;
  int      devClass;
  int      devType; //20
  char     digital;
  unsigned char bs;
  char     isBroken;
  unsigned char unused; //24
  char     name[EDPXNAMESIZ];//34
  unsigned short  alarmListId;//36
  time_t   sec;
  int      seq;//44
  char     text[EDPXTEXTSIZ];//94
  unsigned int rawdat; //98
  unsigned short handler_code;//100
  int      sound_id;
  int      speech_id;//108
} __attribute__((packed)) edp_x;
//
#endif
//
// app must register itself to issue any command
typedef struct appRegistrationStructure 
{
  unsigned char typcode;   /* =almAppRegister_c, always */
  unsigned char srcnode;   /* set/used by daemon */
  unsigned char taskid;    /* set/used by daemon */
  unsigned char locid;     /* set/used by daemon */
  char user[32];           /* account name, e.g., "OPER" */
  char physLoc[32];        /* physical location, e.g., "MCR" */
  char program[32];        /* name of the program, e.g., "PA772" */
  time_t sec;              /* set/used by daemon */

} app_register_t;

//app may send CLR1(=clr1DeviceCmd_c) command to daemon. 
//Only DI is needed for now. The rest is stuffed by daemon.

// srcnode = nn of CLXnn or CNSnn
// taskid = 0,1,2 one of the 3 console instances, 0 for non-console
// srcnode & taskid is determined by the "user" var in REGISTERdata
// user="CLX234" yields srcnode=34, taskid=2
// user="CNS123" yields scrnode=23, taskid=101 (add 100 for VMS)

typedef struct clr1CommandStructure /* clear 1 device command */
{
  unsigned char typcode;   /* =3(clr1DeviceCmd_c), always */
  unsigned char console;   /* for a historical reason */
  unsigned char unused[2];
  int  di;                 /* DI, must be network byte ordered */
  unsigned char bs;        /* basic status */
  unsigned char srcnode;   /* source node, daemon id as in ALARM.INI */
  unsigned char taskid;    /* task id, app id number for each daemon */
  unsigned char locid;     /* location id number, of app */
  time_t sec;              /* sec from epoch, given by ALARMS */
  int seq;                 /* abs seq number, given by ALARMS */

} clr1_cmd_t;

/* 
 * daemon will ignore CLR SubSystem command from app.
 */
typedef struct clrSSCommandStructure /* clear SubSystem Command */
{
  unsigned char typcode;   /* =2(bigClearCmd_c), always */
  unsigned char console;   /* for a historical reason */
  unsigned char trunk;
  unsigned char node;
  unsigned char ssn;
  unsigned char srcnode;   /* source node, daemon id as in ALARM.INI */
  unsigned char taskid;    /* task id, app id number for each daemon */
  unsigned char locid;     /* location id number, of app */
  time_t sec;              /* sec from epoch, given by ALARMS */
  int seq;                 /* abs seq number, given by ALARMS */

} clrSS_cmd_t;

/* 
 * app may send MCLR command to daemon 
 * Only trunk,node,ssn are needed for now. The rest is stuffed by daemon.
 */
typedef struct mclrCommandStructure /* clear SubSystem Command */
{
  unsigned char typcode;   /* = 10, always */
  unsigned char console;   /* for a historical reason */
  unsigned char count;     /* number of node-ssn to clear */
  unsigned char trunk[16]; /* up to 16 trunk-node-ssn */
  unsigned char node[16];  /* up to 16 trunk-node-ssn */
  unsigned char ssn[16];   /* up to 16 trunk-node-ssn */
  unsigned char srcnode;   /* source node, daemon id as in ALARM.INI */
  unsigned char taskid;    /* task id, app id number for each daemon */
  unsigned char locid;     /* location id number, of app */
  unsigned char unused[2];
  time_t sec;              /* sec from epoch, given by ALARMS */
  int seq;                 /* abs seq number, given by ALARMS */

} mclr_cmd_t;
/* 
 * daemon will ignore FEBT command from app.
 */
typedef struct febtCommandStructure /* frontend boot request */
{
  unsigned char typcode;   /* =9(FrontEndBootCmd_c), always */
  unsigned char unused;
  unsigned char minBSN;
  unsigned char maxBSN;
  unsigned char node;
  unsigned char trunk;
  unsigned char srcnode;
  unsigned char taskid;
  time_t sec;              /* sec from epoch, given by ALARMS */
  int seq;                 /* abs seq number, given by ALARMS */

} febt_cmd_t;
//
typedef struct modgrpStructure
{
  unsigned char typcode;
  unsigned char unused;
  int di;
  int diaux;
} modgrp_t;
/* 
 * daemon will ignore SERVER START command from app.
 */
typedef struct serverStartStructure //server starts
{
  unsigned char typcode; //almStart_c or almclearall
  char source; //
  char unused[2];
  time_t sec; //sec, alarms generated
  int seq; //seq, alarms generated

} svrstart_t;

#ifndef edpSize_c
#define edpSize_c 12 //4KB max long message, wrong! 1448 bytes max
#endif

typedef struct EventDisplayMessage 
{
  /* ipheader_t header; */ /* currently not used */
  unsigned char typcode;   /* 0=edm, >0 some other tasks */
  unsigned char edpcount;  /* Number of EDP */
  unsigned char version;
  unsigned char unused;
  int  seq;                /* sequential number of this EDM */
  edp_t edp[edpSize_c];
}  __attribute__((packed)) edm_t;

typedef struct HeartBeatMessage 
{
  /* ipheader_t header; */ /* currently not used */
  unsigned char typcode;   /* almHeartBeat_c, always */
  unsigned char unused[3]; /* for long int alignment */
  time_t sec;              /* seconds from Epoch */
  time_t dt;               /* heartbeat interval */
  int    lastEdp;          /* serial number of last sent Edp */
  int    eventRem;         /* event seq number(<eventRem) to remove */
} __attribute__((packed)) heartbeat_t;

typedef char string16[16];

/* stdio.h defines BUFSIZ = 512(VMS), 1024(Unix) */

//#define BUF_SIZE     1024
#define SHORTBUFSIZ   255
#define LONGBUFSIZ (edpSize_c*EDPDATSIZ+8)
#if 0
#ifdef __edp_version_one__
#define LONGBUFSIZ   1448
#else
#define LONGBUFSIZ   2400
#endif
#endif
//
typedef union ClientRequestDataUnion 
{
  unsigned char msg[SHORTBUFSIZ];  /* almSendActiveAlarm_c for example */

  struct {
    unsigned char typcode; /* = almSetTimeOut_c */
    unsigned char spare[3];
    time_t sec;
  } timeout;

} clientdata_u;

typedef struct AlarmCountStructure 
{
  unsigned char typcode;   /* = almAlarmCount_c */
  unsigned char unused[3]; 
  int  alarms;             /* number of active alarms */
  int  events;             /* number of active events */
  int  backlog;            /* number of backlog edp's */
} alarmcount_t;

typedef union LongClientListUnion 
{ 
  unsigned char msg[LONGBUFSIZ];
  edm_t edm; /* event display message */
} clientlong_u;

typedef struct DeviceAlarmDataStructure
{
  unsigned char typcode; //[<] =54
  char digital; //[<<] 0=analog, 1=digital
  char cond; //[<<] 0=ANY, 1=bad, 2=good. most recent occurance
  char mode; //[<<] 0=DI, otherwise name
  int count; //[<>] up to this many requested. reports this many found
              //checks only if >1, then cond=0 enforced 
              //searches backward from the most recent
  int  DI; //[<>] device index
  char name[8]; //[<>>] device name, like X:123456
  char text[32]; //[>>] alarm text
  unsigned int rawdata; //[>>] raw data
  time_t sec; //[>>] time of occurrance
} device_alarm_t;
//
typedef struct SendACKMessageStructure
{
  unsigned char typcode;
  char unused;
  int  vmstate;
  int  senderclass;

} __attribute__((packed)) sendackmsg_t;

#define	ALARM_TEXT_ENTRY_LEN	25		/* length of an alarm text string (not null terminated) */

//
typedef struct alarmtextstruct
{
  char adtype; //1=analog, 2=digital
  char text[ALARM_TEXT_ENTRY_LEN]; //not null-terminated
  int mask; //digital mask, meaningless for analog
  int rawdata;//raw data
  int sec; //time
} __attribute__((packed)) alarmtext_t;
//
#define EDPFORMATSIZ 32
//
typedef struct alarmdbdatastruct 
{
  short err;
  unsigned char priority;
  unsigned char broken;
  //
  unsigned short alarmListId;
  unsigned short handler_code;
  int  sound_id;
  int  speech_id;
  unsigned short digital; //0=analog, 1=digital
  unsigned short dbMask; //obtained from alarmblk_t
  unsigned int emc[2];
  int di; //device index
  int devClass;
  int devType;
  //
  char name[EDPNAMESIZ];
  char text[EDPFORMATSIZ];
  char fullname[DEVICE_FULL_NAME_LEN];
  //
  union analog_or_digital
  {
    struct 
    {
      PDB_RS pdb; /* conversion factors, units, 36 bytes long */
    }  __attribute__((packed)) /* Added by the PACKINATOR(tm) */ a;
    //
    struct 
    {
      int mask;
      int condition;
      int nextmask;
      int nummask;
      int wasbad;
    }  __attribute__((packed)) /* Added by the PACKINATOR(tm) */ d;
    //
    struct 
    {
      int reading;
      int cnvtype;
      float result;
      char units[8];
    }  __attribute__((packed)) /* Added by the PACKINATOR(tm) */ s;
  } u; //analog, digital or scale
}  __attribute__((packed)) /* Added by the PACKINATOR(tm) */ almdbdata_t;
//
#define dbpipe_digital 1
#define dbpipe_analog  2
#define dbpipe_scale   3
#define dbpipe_nodedb  4
#define dbpipe_group   5
#define dbpipe_conaddr 6
#define dbpipe_env     7
#define dbpipe_hb      63
//
typedef struct dbpipehbstruct
{
  char typcode; //63
  char subtype; //
  int dat[1023];
} __attribute__((packed)) almpipehb_t;
//
typedef struct dbpipemsgstruct
{
  char typcode; //1:digital,2:analog,3:scale
  char count; //numbde of devices
  almdbdata_t data[32]; //up to 32 devices
}  __attribute__((packed)) /* Added by the PACKINATOR(tm) */ almpipedata_t;
//
typedef struct nodeinfostruct
{
  char name[6];
  unsigned char trunk;
  unsigned char node;
} __attribute__((packed)) /* Added by the PACKINATOR(tm) */ nodedata_t;

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//
// Classes
//
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class ENDOFTRANSdata //end of data transmission */
{
  static const unsigned char typcode=almEndOfData_c;
 public:
  unsigned char unused[3]; /* they are all 63 */

 public:
  ENDOFTRANSdata() 
  { 
    unused[1]=typcode; unused[2]=typcode; 
  }
  ENDOFTRANSdata(char *buf);
  int intval() { return 0x3f3f3f3f; }
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class REGISTERdata
{
  static const unsigned char typcode=almAppRegister_c; 
 public:
  unsigned char srcnode;   /* set/used by daemon */
  unsigned char taskid;    /* set/used by daemon */
  unsigned char locid;     /* set/used by daemon */
  char user[32];           /* account name, e.g., "OPER" */
  char physLoc[32];        /* physical location, e.g., "MCR" */
  char program[32];        /* name of the program, e.g., "PA772" */
  time_t sec;              /* set/used by daemon */

 public:
  REGISTERdata();
  REGISTERdata(char *raw);
  //void setbuf(char *buf);
  //std::string textstr(void);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class DEVICEALARMdata
{
  static const unsigned char typcode=54; //almGetDeviceAlarm_c
 public:
  char digital; //<<. 0=analog, 1=digital
  char cond; //<<. 0=ANY, 1=bad, 2=good. most recent occurance
  char mode; //<<. 0=DI, otherwise name
  int count; //<>. up to this many requested. reports this many found
              //checks only if >1, then cond=0 enforced 
              //searches backward from the most recent
  int  DI; //<>. device index
  char name[8]; //<>. device name, like X:123456
  char text[32]; //>>. alarm text
  unsigned int rawdata; //>>. raw data
  time_t sec; //>>. time of occurrance
  //
 public:

  DEVICEALARMdata() {}
  DEVICEALARMdata(unsigned char *dat);
  void init(unsigned char *dat);
  void init(edp_t *buf);
  void setbuf(device_alarm_t *buf);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#define	ALARM_TEXT_TYPE_BOTH	0 /* either analog or digital alarm text */
#define	ALARM_TEXT_TYPE_ANALOG	1 /* analog alarm text */
#define	ALARM_TEXT_TYPE_DIGITAL	2 /* digital alarm text */
#define	ALARM_TEXT_MAX_ENTRIES	33 /* maximum number of alarm text entries */

typedef struct ALARM_TEXT_ENTRY_DATA
{
  int alarm_type;
  char text[ALARM_TEXT_ENTRY_LEN+2];
  unsigned int	mask;
} __attribute__((packed)) ALARM_TEXT_ENTRY_DATA;

class ALARMTEXTdata
{
  static const char typcode=almAlarmText_c; //55
 public:
  char ad; // 1=analog, 2=digital, 0=any(both, default).
  char count; // number of alarm texts returned.
  char unused; // unused, to make the basic size nice 12 bytes.
  char name[DEVICE_NAME_LEN];	// device name, not null-terminated.
  alarmtext_t data[ALARM_TEXT_MAX_ENTRIES]; // "count" is the actual size
  //
 public:

  ALARMTEXTdata(); //default constructor
  ALARMTEXTdata(char* _name, char opt); 
  void setname(char* _name);
  int setalarmtype(char opt); //set alarm type
  int req2buf(char* buf); //make request to network buffer
  void fixname(void); //fix device name
  void add(char* str, int rawdata, int sec); //add text (by producer)
  void add(char* str, int mask, int rawdata, int sec); //add text (by producer)
  int buf2dat(char* buf, int siz); //convert network buffer to data
  int dat2buf(char* buf); //convert data to network buffer
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class CLR1data //CLR1 command
{
  static const unsigned char typcode=3;   // =3(clr1DeviceCmd_c), always */
 public:
  // unsigned char console;
  // unsigned char unused[2];
  int di; // DI, must be network byte ordered
  unsigned char bs; // basic status
  unsigned char srcnode; // source node, daemon id as in ALARM.INI
  unsigned char taskid; // task id, app id number for each daemon
  unsigned char locid; // location id number, of app */
  time_t sec; // sec from epoch, set by ALARMS
  int seq;// abs seq number, set by ALARMS

 public:

  CLR1data() {}
  CLR1data(unsigned char *dat);
  void init(unsigned char *dat); //initializer
  void init(unsigned char *dat, char opt); //initializer
  int dibs();
  bool operator==(const CLR1data that)
  {
    return (di==that.di && bs==that.bs);
  }
  CLR1data& operator = (const CLR1data& clr1)
  {
    di=clr1.di;
    bs=clr1.bs;
    sec=clr1.sec;
    return *this;
  }
  void print(void);
  std::string textstr(void);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class BIGCdata //BIGC command
{
  static const unsigned char typcode=2; //=2(bigClearCmd_c)
 public:
  // unsigned char console;   // for a historical reason */
  unsigned char trunk;
  unsigned char node;
  unsigned char ssn;
  unsigned char srcnode;   // source node, daemon id as in ALARM.INI */
  unsigned char taskid;    // task id, app id number for each daemon */
  unsigned char locid;     // location id number, of app */
  time_t sec;              // sec from epoch, given by ALARMS */
  int seq;                 // abs seq number, given by ALARMS */

 public:

  BIGCdata() {}
  //BIGCdata(char *raw);
  void init(unsigned char *dat); //initializer
  void init(unsigned char *dat, char opt); //initializer
  void print(void);
  std::string textstr(void);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class MCLRdata // clear SubSystem Command */
{
  static const unsigned char typcode=10;
 public:
  unsigned char console;   //unused, only for historical reason
  unsigned char count;     //number of node/ssn to clear */
  unsigned char trunk[16]; //up to 16 trunk/node/ssn */
  unsigned char node[16];  //up to 16 trunk/node/ssn */
  unsigned char ssn[16];   //up to 16 trunk/node/ssn */
  unsigned char srcnode;   //source node, daemon id as in ALARM.INI */
  unsigned char taskid;    //task id, app id number for each daemon */
  unsigned char locid;     //location id number, of app */
  unsigned char unused[2];
  time_t sec;              //sec from epoch, set by ALARMS
  int seq;                 //abs seq number, set by ALARMS

 public:

  MCLRdata() {}
  //MCLRdata(unsigned char *raw)
  void init(unsigned char *dat);
  void init(unsigned char *dat, char opt);
  std::string textstr(void);
  void print(void);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class FEBTdata //frontend boot request */
{
  static const unsigned char typcode=9;   /* =9(FrontEndBootCmd_c), always */
 public:
  unsigned char unused;
  unsigned char minBSN;
  unsigned char maxBSN;
  unsigned char node;
  unsigned char trunk;
  unsigned char srcnode;
  unsigned char taskid;
  time_t sec;
  int seq;

 public:

  FEBTdata() {}
  void init(unsigned char *buf);
  void init(unsigned char *buf, char opt);
  short trunknode();
  std::string textstr(void);
  void print(void);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class STARTdata // server starts Command
{
  static const unsigned char typcode=almStart_c; 
 public:
  char source;
  char unused[2];
  time_t sec;
  int seq;

 public:
  STARTdata() {}
  STARTdata(unsigned char *raw);
  void init(unsigned char *raw);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class COUNTdata
{
  static const unsigned char typcode=almAlarmCount_c;
 public:
  unsigned char unused[3]; 
  int alarms; //alarm count
  int events; //event count
  int backlog; //backlog count

 public:
  COUNTdata() {}
  COUNTdata(int a, int e, int b): alarms(a), events(e), backlog(b) {}
  void setbuf(char *dat);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class HEARTBEATdata
{
  /* ipheader_t header; */ /* currently not used */
  static const unsigned char typcode=almHeartBeat_c; 
 public:
  time_t sec;
  int seq; //seq of last sent edp

 public:

  HEARTBEATdata() {}
  void setbuf(unsigned char *dat);
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class EDPraw
{
 public:
  unsigned char data[EDPDATSIZ];

 public:
  EDPraw() {}
  EDPraw(unsigned char* in);
  EDPraw& operator=(const unsigned char *in);
  void setbuf(unsigned char* out);
  void copy(unsigned char* in, int siz);
};

//void EDPraw::copy(unsigned char* in, int siz)
//EDPraw& EDPraw::operator=(const unsigned char *in)

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

class EDPdata
{
 public:
  unsigned char typcode;  // 0 or 1 
  unsigned char priority; // priority
  unsigned char trunk; // trunk
  unsigned char node;  // node
  unsigned char ssn;   // subsystem, obsolete
  char erpType; // 2=cleared, 1=good, 0=event, -1=bad
  // DAEMON sets "2" to handle CLR1/MCLR by modifying existing EDP's 
  // text, sec & seq. Digital alarms generate multiple CLR for each mask
  unsigned short status;  // alarm block, the copy of event_t
  int      di;       // Device Index
  int      devClass; // Device class
  int      devType;  // Device type
  char     digital;  // 1=digital, 0=analog
  unsigned char bs;  // see ACNET Design Note 39.3, page 3-7
  char     isBroken; // 1=broken, 0=not broken
  unsigned char unused; // spare, made for long int alignment
  std::string name; // Device name
  unsigned short alarmListId; // alarm list id, used for display
  time_t   sec;     // alarm reception time, seconds from epoch
  int      seq;     // sequential number given by alarm sytem */
  std::string text; // fixed sized text, with '  ' -> ' '
  unsigned int rawdat;
  unsigned short handler_code;
  int      sound_id;
  int      speech_id;
  std::string fullname;

 public:

  EDPdata() 
  { 
    name.reserve(EDPNAMESIZ); 
    text.reserve(EDPTEXTSIZ);
    fullname.reserve(EDPFULLNAMESIZ);
  }
  //
  EDPdata(unsigned char* dat);
  //
  void init() { trunk=0; node=0; di=0; sec=0; seq=0;}
  void init(unsigned char* dat);
  void init(edp_t *edp);
  void setbuf(unsigned char* dat);
  void zero();
  //
  int  dibs() { if(digital) return (0x1000000+di); else return di;}
  bool is_good() const { return erpType==1; }
  bool is_bad() const { return erpType==(-1); }
  bool is_event() const { return erpType==0; }
  bool is_clear() const { return erpType==2; }
  bool is_digital() const  {return (digital!=0);}
  bool is_analog() const {return (digital==0);}
  short trunknode() const { return (((short)trunk)*0x100+(short)node);}
  //
  bool operator==(const EDPdata that)
  {
    return (di==that.di && digital==that.digital);
  }

  EDPdata& operator = (const EDPdata& edp)
  {
    typcode=edp.typcode;
    priority=edp.priority;
    trunk=edp.trunk;
    node=edp.node;
    ssn=edp.ssn;
    erpType=edp.erpType;
    status=edp.status;
    di=edp.di;
    devClass=edp.devClass;
    devType=edp.devType;
    digital=edp.digital;
    bs=edp.bs;
    isBroken=edp.isBroken;
    unused=edp.unused;
    name=edp.name;
    alarmListId=edp.alarmListId;
    sec=edp.sec;
    seq=edp.seq;
    text=edp.text;
    rawdat=edp.rawdat;
    handler_code=edp.handler_code;
    sound_id=edp.sound_id;
    speech_id=edp.speech_id;
    fullname=edp.fullname;
    return *this;
  }
  //
  std::string textstr(void); //typcode, priority, name,text, time, seq
  void print(void); //print textstr()
};
/*
EDPdata::EDPdata(unsigned char* dat)
EDPdata& EDPdata::operator=(const EDPdata& edp)
inline bool EDPdata::operator== (const EDPdata that)
void EDPdata::init(unsigned char* dat)
void EDPdata::setbuf(unsigned char* dat)
std::string EDPdata::textstr(void)
void EDPdata::print(void)
*/

class PRINTopt
{
 public:
  int debugprint;
  //
  int acnet;
  int dbnews;
  int bigc;
  int beamabort;
  int frontend;
  //
  int xdbpipe;
  int xdbgroup;
  int xdbnews;
  int xdbmsg;
  //
  int _prtbit5;
  int _prtbit6;
  int _prtbit7;
  int _prtbit8;
  int _prtbit9;
  int _prtbit10;
  int _prtbit11;
  int _prtbit12;
  int _prtbit13;
  int _prtbit14;
  int _prtbit15;
  int _prtbit20;
  int _prtbit21;
  int _prtbit22;
  int _prtbit23;
  int _prtbit24;
  int _prtbit25;
  int _prtbit26;
  int _prtbit27;
  int _prtbit28;
  int _prtbit29;
  int _prtbit30;
  int _prtbit31;

  //  3.........2.........1..........
  // 10987654321098765432109876543210
  //    |   |   |   |   |   |   |   |
  /* |||||||||||||||||||||||||||||||+- 1:*/#define prtacnet       0x01
  /* ||||||||||||||||||||||||||||||+-- 2:*/#define prtdbnews      0x02
  /* |||||||||||||||||||||||||||||+--- 4:*/#define prtbigc        0x04
  /* ||||||||||||||||||||||||||||+---- 8:*/#define prtbeamabort   0x08
  /* |||||||||||||||||||||||||||+---- 10:*/#define prtfrontend    0x10
  /* ||||||||||||||||||||||||||+----- 20:*/#define prtbit5        0x20
  /* |||||||||||||||||||||||||+------ 40:*/#define prtbit6        0x40
  /* ||||||||||||||||||||||||+------- 80:*/#define prtbit7        0x80
  /* |||||||||||||||||||||||+------- 100:*/#define prtbit8       0x100
  /* ||||||||||||||||||||||+-------- 200:*/#define prtbit9       0x200
  /* |||||||||||||||||||||+--------- 400:*/#define prtbit10      0x400
  /* ||||||||||||||||||||+---------- 800:*/#define prtbit11      0x800
  /* |||||||||||||||||||+---------- 1000:*/#define prtbit12     0x1000
  /* ||||||||||||||||||+----------- 2000:*/#define prtbit13     0x2000
  /* |||||||||||||||||+------------ 4000:*/#define prtbit14     0x4000
  /* ||||||||||||||||+------------- 8000:*/#define prtbit15     0x8000
  /* |||||||||||||||+------------- 10000:*/#define prtxdbpipe  0x10000
  /* ||||||||||||||+-------------- 20000:*/#define prtxdbgroup 0x20000
  /* |||||||||||||+--------------- 40000:*/#define prtxdbnews  0x40000
  /* ||||||||||||+---------------- 80000:*/#define prtxdbmsg   0x80000
  /* |||||||||||+---------------- 100000:*/#define prtbit20   0x100000
  /* ||||||||||+----------------- 200000:*/#define prtbit21   0x200000
  /* |||||||||+------------------ 400000:*/#define prtbit22   0x400000
  /* ||||||||+------------------- 800000:*/#define prtbit23   0x800000
  /* |||||||+------------------- 1000000:*/#define prtbit24  0x1000000
  /* ||||||+-------------------- 2000000:*/#define prtbit25  0x2000000
  /* |||||+--------------------- 4000000:*/#define prtbit26  0x4000000
  /* ||||+---------------------- 8000000:*/#define prtbit27  0x8000000
  /* |||+---------------------- 10000000:*/#define prtbit28 0x10000000
  /* ||+----------------------- 20000000:*/#define prtbit29 0x20000000
  /* |+------------------------ 40000000:*/#define prtbit30 0x40000000
  /* +------------------------- 80000000:*/#define prtbit31 0x80000000
  //
 public:
  //
  PRINTopt() { debugprint=0;};
  //
  void get(int val) 
  {
    char *c;
    int sts __attribute__((unused));
    if(val==0)
    {
      c=getlnm("ALMDEBUGPRINT");
      if(c!=NULL)
	sts=sscanf(c,"%x",&debugprint);
    }
    else
      debugprint=val;
    //
    acnet=(((debugprint & prtacnet)==0)?0:1);
    dbnews=(((debugprint & prtdbnews)==0)?0:1);
    bigc=(((debugprint & prtbigc)==0)?0:1);
    beamabort=(((debugprint & prtbeamabort)==0)?0:1);
    frontend=(((debugprint & prtfrontend)==0)?0:1);
    //
    xdbpipe=(((debugprint & prtxdbpipe)==0)?0:1);
    xdbgroup=(((debugprint & prtxdbgroup)==0)?0:1);
    xdbnews=(((debugprint & prtxdbnews)==0)?0:1);
    xdbmsg=(((debugprint & prtxdbmsg)==0)?0:1);
    //
    _prtbit5=(((debugprint & prtbit5)==0)?0:1);
    _prtbit6=(((debugprint & prtbit6)==0)?0:1);
    _prtbit7=(((debugprint & prtbit7)==0)?0:1);
    _prtbit8=(((debugprint & prtbit8)==0)?0:1);
    _prtbit9=(((debugprint & prtbit9)==0)?0:1);
    _prtbit10=(((debugprint & prtbit10)==0)?0:1);
    _prtbit11=(((debugprint & prtbit11)==0)?0:1);
    _prtbit12=(((debugprint & prtbit12)==0)?0:1);
    _prtbit13=(((debugprint & prtbit13)==0)?0:1);
    _prtbit14=(((debugprint & prtbit14)==0)?0:1);
    _prtbit15=(((debugprint & prtbit15)==0)?0:1);
    _prtbit20=(((debugprint & prtbit20)==0)?0:1);
    _prtbit21=(((debugprint & prtbit21)==0)?0:1);
    _prtbit22=(((debugprint & prtbit22)==0)?0:1);
    _prtbit23=(((debugprint & prtbit23)==0)?0:1);
    _prtbit24=(((debugprint & prtbit24)==0)?0:1);
    _prtbit25=(((debugprint & prtbit25)==0)?0:1);
    _prtbit26=(((debugprint & prtbit26)==0)?0:1);
    _prtbit27=(((debugprint & prtbit27)==0)?0:1);
    _prtbit28=(((debugprint & prtbit28)==0)?0:1);
    _prtbit29=(((debugprint & prtbit29)==0)?0:1);
    _prtbit30=(((debugprint & prtbit30)==0)?0:1);
    _prtbit31=(((debugprint & prtbit31)==0)?0:1);
  };
  //
  void set() 
  {
    int sts,val;
    char str[20];
    //
    val=
      ((int)acnet)*prtacnet+
      ((int)bigc)*prtbigc+
      ((int)dbnews)*prtdbnews+
      ((int)beamabort)*prtbeamabort+
      ((int)frontend)*prtfrontend+
      //
      ((int)xdbpipe)*prtxdbpipe+
      ((int)xdbgroup)*prtxdbgroup+
      ((int)xdbnews)*prtxdbnews+
      ((int)xdbmsg)*prtxdbmsg;
    //
    val=val+
      _prtbit5*prtbit5+
      _prtbit6*prtbit6+
      _prtbit7*prtbit7+
      _prtbit8*prtbit8+
      _prtbit9*prtbit9+
      _prtbit10*prtbit10+
      _prtbit11*prtbit11+
      _prtbit12*prtbit12+
      _prtbit13*prtbit13+
      _prtbit14*prtbit14+
      _prtbit15*prtbit15;
    //
    val=val+
      _prtbit20*prtbit20+
      _prtbit21*prtbit21+
      _prtbit22*prtbit22+
      _prtbit23*prtbit23+
      _prtbit24*prtbit24+
      _prtbit25*prtbit25+
      _prtbit26*prtbit26+
      _prtbit27*prtbit27+
      _prtbit28*prtbit28+
      _prtbit29*prtbit29+
      _prtbit30*prtbit30+
      _prtbit31*prtbit31;
      //
    debugprint=val;
    sprintf(str,"%x",val);
    sts=setlnm("ALMDEBUGPRINT",str);
    if(sts)
      std::cout << "error setting logical for ALMDEBPRINT";
  };
  //
  void show(int p)
  {
    if(p==0 || p==1)
    {
      std::cout << "alarms.acnet:" << (int)acnet << std::endl;
      std::cout << "alarms.dbnews:" << (int)dbnews << std::endl;
      std::cout << "alarms.bigc:" << (int)bigc << std::endl;
      std::cout << "alarms.beamabort:" << (int)beamabort << std::endl;
      std::cout << "alarms.frontend:" << (int)frontend << std::endl;
    }
    if(p==0 || p==2)
    {
      std::cout << "xdb.pipe:" << (int)xdbpipe << std::endl;
      std::cout << "xdb.group:" << (int)xdbgroup << std::endl;
      std::cout << "xdb.dbnews:" << (int)xdbnews << std::endl;
      std::cout << "xdb.msg:" << (int)xdbmsg << std::endl;
    }
  };
  void mod(int p)
  {
    if(p==0 || p==1)
    {
      std::cout << "acnet(" << acnet << "): "; std::cin >> acnet;
      std::cout << "dbnews(" << dbnews << "): "; std::cin >> dbnews;
      std::cout << "bigc(" << bigc << "): "; std::cin >> bigc;
      std::cout << "beamabort(" << beamabort << "): "; std::cin >> beamabort;
      std::cout << "frontend(" << frontend << "): "; std::cin >> frontend;
      show(1);
    }
    if(p==0 || p==2)
    {
      std::cout << "pipe(" << xdbpipe << "): "; std::cin >> xdbpipe;
      std::cout << "group(" << xdbgroup << "): "; std::cin >> xdbgroup;
      std::cout << "dbnews(" << xdbnews << "): "; std::cin >> xdbnews;
      std::cout << "msg(" << xdbmsg << "): "; std::cin >> xdbmsg;
      show(2);
    }
    set();
  };
#undef prtacnet
#undef prtdbnews
#undef prtbigc
#undef prtbeamabort
#undef prtfrontend
#undef prtbit5
#undef prtbit6
#undef prtbit7
#undef prtbit8
#undef prtbit9
#undef prtbit10
#undef prtbit11
#undef prtbit12
#undef prtbit13
#undef prtbit14
#undef prtbit15
#undef prtxdbpipe
#undef prtxdbgroup
#undef prtxdbnews
#undef prtxdbmsg
#undef prtbit20
#undef prtbit21
#undef prtbit22
#undef prtbit23
#undef prtbit24
#undef prtbit25
#undef prtbit26
#undef prtbit27
#undef prtbit28
#undef prtbit29
#undef prtbit30
#undef prtbit31
};

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//end of listing
#endif