Logo Search packages:      
Sourcecode: nut version File versions

apcsmart.h

/* apcsmart.h - command table for APC smart protocol units

   Copyright (C) 1999  Russell Kroll <rkroll@exploits.org>
             (C) 2000  Nigel Metheringham <Nigel.Metheringham@Intechnology.co.uk>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <ctype.h>
#include <sys/ioctl.h>
#include "serial.h"
#include "timehead.h"

#define APC_TABLE_VERSION     "version 2.0"

/* Basic UPS reply line structure */
#define ENDCHAR 10            /* APC ends responses with LF */

/* these two are only used during startup */
#define IGNCHARS "\015+$|!~%?=*#&"  /* special characters to ignore */
#define MINIGNCHARS "\015+$|!"      /* minimum set of special characters to ignore */

/* normal polls: characters we don't want to parse (including a few alerts) */
#define POLL_IGNORE "\015?=*&|"

/* alert characters we care about - OL, OB, LB, not LB, RB */
#define POLL_ALERT "$!%+#"

#define UPSDELAY    50000     /* slow down multicharacter commands        */
#define CMDLONGDELAY    1500000     /* some commands need a 1.5s gap for safety */

#define SER_WAIT_SEC    3     /* wait up to 3.0 sec for ser_get calls */
#define SER_WAIT_USEC   0

/* dangerous instant commands must be reconfirmed within a 12 second window */
#define MINCMDTIME      3
#define MAXCMDTIME      15

/* it only does two strings, and they're both the same length */
#define APC_STRLEN      8

/* --------------- */

/* status bits */

#define APC_STAT_CAL    1     /* calibration */
#define APC_STAT_TRIM   2     /* SmartTrim */
#define APC_STAT_BOOST  4     /* SmartBoost */
#define APC_STAT_OL     8     /* on line */
#define APC_STAT_OB     16    /* on battery */
#define APC_STAT_OVER   32    /* overload */
#define APC_STAT_LB     64    /* low battery */
#define APC_STAT_RB     128   /* replace battery */

/* serial protocol: special commands - initialization and such */
#define APC_STATUS      'Q'
#define APC_GOSMART     'Y'
#define APC_GODUMB      'R'
#define APC_CMDSET      'a'
#define APC_CAPABILITY  26    /* ^Z */
#define APC_NEXTVAL     '-'

/* --------------- */

/* Driver command table flag values */

#define APC_POLL  0x0001      /* Poll this variable regularly           */
#define APC_IGNORE      0x0002      /* Never poll this                  */
#define APC_PRESENT     0x0004      /* Capability seen on this UPS            */

#define APC_RW          0x0010      /* read-write variable              */
#define APC_ENUM  0x0020      /* enumerated type                  */
#define APC_STRING      0x0040      /* string                     */

#define APC_NASTY 0x0100      /* Nasty command - take care        */
#define APC_REPEAT      0x0200      /* Command needs sending twice            */

#define APC_FORMATMASK  0xFF0000 /* Mask for apc data formats */

#define APC_F_PERCENT   0x020000 /* Data in a percent format */
#define APC_F_VOLT      0x030000 /* Data in a voltage format */
#define APC_F_AMP 0x040000 /* Data in a current/amp format */
#define APC_F_CELSIUS   0x050000 /* Data in a temp/C format */
#define APC_F_HEX 0x060000 /* Data in a hex number format */
#define APC_F_DEC 0x070000 /* Data in a decimal format */
#define APC_F_SECONDS   0x100000 /* Time in seconds */
#define APC_F_MINUTES   0x110000 /* Time in minutes */
#define APC_F_HOURS     0x120000 /* Time in hours */
#define APC_F_LEAVE     0     /* Just pass this through */

struct apc_vartab_t {
      const char  *name;            /* the variable name */
      unsigned int      flags;            /* various flags        */
      char        cmd;        /* command character */

} apc_vartab[] = {

      { "ups.firmware",       0,                'b' },
      { "ups.firmware.aux",   0,                'v' },
      { "ups.model",          0,                0x01 },

/* FUTURE: depends on variable naming scheme */
#if 0
      { "ups.model.code",     0,                'V' },
#endif

      { "ups.serial",         0,                'n' },
      { "ups.mfr.date",       0,                'm' },

      { "ups.temperature",    APC_POLL|APC_F_CELSIUS, 'C' },
      { "ups.load",           APC_POLL|APC_F_PERCENT, 'P' },

      { "ups.test.interval",  APC_F_HOURS,            'E' },
      { "ups.test.result",    APC_POLL,               'X' },

      { "ups.delay.start",    APC_F_SECONDS,          'r' },
      { "ups.delay.shutdown", APC_F_SECONDS,          'p' },

      { "ups.id",             APC_STRING,       'c' },

      { "ups.contacts",       APC_POLL|APC_F_HEX,     'i' },
      { "ups.display.language",
                        0,                0x0C },

      { "input.voltage",      APC_POLL|APC_F_VOLT,    'L' },
      { "input.frequency",    APC_POLL|APC_F_DEC,     'F' },
      { "input.sensitivity",  0,                's' },
      { "input.quality",      APC_POLL|APC_F_HEX,     '9' },

      { "input.transfer.low", APC_F_VOLT,       'l' },
      { "input.transfer.high",
                        APC_F_VOLT,       'u' },
      { "input.transfer.reason", 
                        APC_POLL,         'G' },

      { "input.voltage.maximum",
                        APC_POLL|APC_F_VOLT,    'M' },
      { "input.voltage.minimum",
                        APC_POLL|APC_F_VOLT,    'N' },

      { "output.current",     APC_POLL|APC_F_AMP,     '/' },
      { "output.voltage",     APC_POLL|APC_F_VOLT,    'O' },
      { "output.voltage.nominal",  
                        APC_F_VOLT,       'o' },

      { "ambient.humidity",   APC_POLL|APC_F_PERCENT, 'h' },
      { "ambient.humidity.alarm.maximum", 
                        APC_F_PERCENT,          '{' },
      { "ambient.humidity.alarm.minimum", 
                        APC_F_PERCENT,          '}' },

      { "ambient.temperature",      
                        APC_POLL|APC_F_CELSIUS, 't' },
      { "ambient.temperature.alarm.maximum",    
                        APC_F_CELSIUS,          '[' },
      { "ambient.temperature.alarm.minimum",    
                        APC_F_CELSIUS,          ']' },

      { "battery.date", APC_STRING,       'x' },

      { "battery.charge",     APC_POLL|APC_F_PERCENT, 'f' },
      { "battery.charge.restart",  
                        APC_F_PERCENT,          'e' },

      { "battery.voltage",    APC_POLL|APC_F_VOLT,    'B' },
      { "battery.voltage.nominal", 
                        0,                'g' },

      { "battery.runtime",    APC_POLL|APC_F_MINUTES, 'j' },
      { "battery.runtime.low",
                        APC_F_MINUTES,          'q' },

      { "battery.packs",      APC_F_DEC,        '>' },
      { "battery.packs.bad",  APC_F_DEC,        '<' },
      { "battery.alarm.threshold", 
                        0,                'k' },
      /* todo:

         I = alarm enable (hex field) - split into alarm.n.enable
         J = alarm status (hex field) - split into alarm.n.status

      0x15 = output voltage selection (APC_F_VOLT)
      0x5C = load power (APC_POLL|APC_F_PERCENT)

       */

      {NULL,            0,                      0},
};

/* ------ instant commands ------ */

#define APC_CMD_FPTEST        'A'
#define APC_CMD_CALTOGGLE     'D'
#define APC_CMD_SHUTDOWN      'K'
#define APC_CMD_SOFTDOWN      'S'
#define APC_CMD_SIMPWF        'U'
#define APC_CMD_BTESTTOGGLE   'W'
#define APC_CMD_OFF           'Z'

#define APC_CMD_ON            0x0E        /* ^N */
#define APC_CMD_BYPTOGGLE     '^'

struct apc_cmdtab_t {
      const char  *name;
      int   flags;
      char  cmd;
} apc_cmdtab[] =
{
      { "load.off",           APC_NASTY|APC_REPEAT,   APC_CMD_OFF       },
      { "load.on",            APC_REPEAT,       APC_CMD_ON        },

      { "test.panel.start",   0,                APC_CMD_FPTEST      },

      { "test.failure.start", 0,                APC_CMD_SIMPWF    },

      { "test.battery.start", 0,                APC_CMD_BTESTTOGGLE },
      { "test.battery.stop",  0,                APC_CMD_BTESTTOGGLE },

      { "shutdown.return",    APC_NASTY,        APC_CMD_SOFTDOWN  },
      { "shutdown.stayoff",   APC_NASTY|APC_REPEAT,   APC_CMD_SHUTDOWN  },

      { "calibrate.start",    0,                APC_CMD_CALTOGGLE },
      { "calibrate.stop",     0,                APC_CMD_CALTOGGLE },

      { "bypass.start", 0,                APC_CMD_BYPTOGGLE },
      { "bypass.stop",  0,                APC_CMD_BYPTOGGLE },

      { NULL, 0, 0                              }
};

/* things to ignore in protocol_verify - useless variables, etc. */
#define CMD_IGN_CHARS "\032-78@.,~\047\177QHRTYayz)1IJ"

/* compatibility with hardware that doesn't do APC_CMDSET ('a') */

struct {
      const char  *firmware;
      const char  *cmdchars;
      int   flags;
} compat_tab[] =
{
      /* APC600 */
      { "6QD",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
      { "6TI",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
      { "6QI",        "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
      /* CS 350 */
      { "5.4.D",  "\1ABPQRSUYbdfgjmnx9",  0 },
      /* Smart-UPS 600 */
      { "D6",         "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
      { "D5",         "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
      { "D4",         "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
      /* SmartUPS 1250. */
      { "8QD",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },

      { NULL,           NULL,             0 },
};

Generated by  Doxygen 1.6.0   Back to index