nut/drivers/mge-utalk.h
2013-11-24 16:00:12 +01:00

235 lines
9.1 KiB
C

/* mge-utalk.h - monitor MGE UPS for NUT with UTalk protocol
*
* Copyright (C) 2002 - 2005
* Arnaud Quette <arnaud.quette@free.fr> & <arnaud.quette@mgeups.com>
* Hans Ekkehard Plesser <hans.plesser@itf.nlh.no>
* Martin Loyer <martin@degraaf.fr>
* Patrick Agrain <patrick.agrain@alcatel.fr>
* Nicholas Reilly <nreilly@magma.ca>
* Dave Abbott <d.abbott@dcs.shef.ac.uk>
* Marek Kralewski <marek@mercy49.de>
*
* This driver is a collaborative effort by the above people,
* Sponsored by MGE UPS SYSTEMS <http://opensource.mgeups.com/>
*
* 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
*
*/
/* --------------------------------------------------------------- */
/* Default Values for UPS Variables */
/* --------------------------------------------------------------- */
#define DEFAULT_LOWBATT 30 /* low battery level, in % */
/* delay between return of utility power and powering up of load (in MINUTES) */
#define DEFAULT_ONDELAY 1
#define DEFAULT_OFFDELAY 20 /* delay before power off, in SECONDS */
#define MIN_CONFIRM_TIME 3 /* shutdown must be confirmed in */
#define MAX_CONFIRM_TIME 15 /* this interval */
/* --------------------------------------------------------------- */
/* Model Name formating entries */
/* --------------------------------------------------------------- */
typedef struct {
const char *basename; /* as returned by Si 1 <data 2> */
const char *finalname;
} models_name_t;
models_name_t Si1_models_names [] =
{
/* Pulsar EX */
{ "Pulsar EX7", "Pulsar EX 7" },
{ "Pulsar EX10", "Pulsar EX 10" },
{ "Pulsar EX15", "Pulsar EX 15" },
{ "Pulsar EX20", "Pulsar EX 20" },
{ "Pulsar EX30", "Pulsar EX 30" },
{ "Pulsar EX40", "Pulsar EX 40" },
/* Pulsar ES+ */
{ "Pulsar ES2+", "Pulsar ES 2+" },
{ "Pulsar ES5+", "Pulsar ES 5+" },
/* Pulsar ESV+ */
{ "Pulsar ESV5+", "Pulsar ESV 5+" },
{ "Pulsar ESV8+", "Pulsar ESV 8+" },
{ "Pulsar ESV11+", "Pulsar ESV 11+" },
{ "Pulsar ESV14+", "Pulsar ESV 14+" },
{ "Pulsar ESV22+", "Pulsar ESV 22+" },
/* Pulsar EXtreme */
{ "EXTREME 1500", "Pulsar EXtreme 1500" },
{ "EXTREME 2000", "Pulsar EXtreme 2000" },
{ "EXTREME 2500", "Pulsar EXtreme 2500" },
{ "EXTREME 3000", "Pulsar EXtreme 3000" },
/* Comet EXtreme */
{ "EXTREME 4.5", "Comet EXtreme 4.5" },
{ "EXTREME 6", "Comet EXtreme 6" },
{ "EXTREME 9", "Comet EXtreme 9" },
{ "EXTREME 12", "Comet EXtreme 12" },
/* Comet */
{ "COMET 5", "Comet 5" },
{ "COMET 7", "Comet 7.5" },
{ "COMET 10", "Comet 10" },
{ "COMET 15", "Comet 15" },
{ "COMET 20", "Comet 20" },
{ "COMET 30", "Comet 30" },
{ "COMET 12", "Comet 12" },
{ "COMET 18", "Comet 18" },
{ "COMET 24", "Comet 24" },
{ "COMET 36", "Comet 36" },
/* FIXME: complete with Pulsar ?EL 2/4/7?, EXL, SX, PSX/CSX, Evolution?,... */
/* end of structure. */
{ NULL, "Generic UTalk model" }
};
/* --------------------------------------------------------------- */
/* Model Information for legacy models */
/* --------------------------------------------------------------- */
/* Structure defining how to get name and model for a particular Si output
* This is for older UPS (Pulsar ESV,SV) which don't support Plug'n'Play 'Si 1' command
*/
typedef struct {
int Data1; /* Data1, Family model */
int Data2; /* Data2, Type */
/* Data3, SoftLevel is not implemented here, while it's always null or zero.*/
const char *name; /* ASCII model name (like 'Si 1' output */
} mge_model_info_t;
/* Array containing Model information for legacy models
* NOTE:
* - Array is terminated by element with type NULL.
*/
static mge_model_info_t mge_model[] = {
/* Pulsar SV page */
{ 3000, 5, "Pulsar SV3" },
{ 3000, 6, "Pulsar SV5/8/11" },
{ 3000, 7, "Pulsar SV3" },
{ 3000, 8, "Pulsar SV5/8" },
{ 3000, 10, "Pulsar SV11/ESV13" },
/* Pulsar ESV page */
{ 3000, 11, "Pulsar ESV17" },
{ 3000, 12, "Pulsar ESV20" },
{ 3000, 13, "Pulsar ESV13" },
{ 3000, 14, "Pulsar ESV17" },
{ 3000, 15, "Pulsar ESV20" },
{ 3000, 17, "Pulsar ESV8" },
/* Pulsar ESV+ compatibility (though these support Si1) */
{ 3000, 51, "Pulsar ESV 11+" },
{ 0, 0, NULL }
};
/* --------------------------------------------------------------- */
/* Multiplier Tables */
/* --------------------------------------------------------------- */
/* First index : Table number, fetched with "Ai" command
* Second index: unit, as in enum above
* NOTE:
* - to make the table index the same as the MGE table number,
* dummy table row multiplier[0][] is inserted
* - unit MIN2SEC is used to convert values in minutes sent by
* the UPS (WAKEDELAY) to seconds
* - the final column corresponds to unit NONE
*/
/* units in multiplier table */
typedef enum eunits
{ VOLT = 0, AMPERE, HERTZ, VOLTAMP, WATT, DEGCELS, MIN2SEC, NONE } units_t;
static const double multiplier[4][8] = {
/* V A Hz VA W C MIN2SEC NONE */
{ 1 , 1 , 1 , 1, 1, 1, 60, 1 },
{ 1 , 1 , 0.1 , 1000, 1000, 1, 60, 1 },
{ 0.01, 0.01, 1 , 1, 1, 1, 60, 1 },
{ 1 , 0.01, 0.1 , 1, 1, 1, 60, 1 }
};
/* --------------------------------------------------------------- */
/* Explicit Booleans */
/* --------------------------------------------------------------- */
/* use explicit booleans */
#ifdef FALSE
#undef FALSE
#endif /* FALSE */
#ifdef TRUE
#undef TRUE
#endif /* TRUE */
typedef enum ebool { FALSE=0, TRUE } bool_t;
/* --------------------------------------------------------------- */
/* Query Commands and their Mapping to INFO_ Variables */
/* --------------------------------------------------------------- */
/* Structure defining how to query UPS for a variable and write
information to INFO structure.
*/
typedef struct {
const char *type; /* INFO_* element */
int flags; /* INFO-element flags to set in addinfo */
int length; /* INFO-element length of strings */
const char *cmd; /* UPS command string to requets element */
const char *fmt; /* printf format string for INFO entry */
units_t unit; /* unit of measurement, or NONE */
bool_t ok; /* flag indicating if item is available */
} mge_info_item_t;
/* Array containing information to translate between UTalk and NUT info
* NOTE:
* - Array is terminated by element with type NULL.
* - Essential INFO items (_MFR, _MODEL, _FIRMWARE, _STATUS) are
* handled separately.
* - Array is NOT const, since "ok" can be changed.
*/
static mge_info_item_t mge_info[] = {
/* Battery page */
{ "battery.charge", 0, 0, "Bl", "%05.1f", NONE, TRUE },
{ "battery.runtime", 0, 0, "Bn", "%05d", NONE, TRUE },
{ "battery.voltage", 0, 0, "Bv", "%05.1f", VOLT, TRUE },
{ "battery.charge.low", ST_FLAG_RW | ST_FLAG_STRING, 2, "Bl ?", "%02d", NONE, TRUE },
{ "battery.voltage.nominal", 0, 0, "Bv ?", "%05.1f", VOLT, TRUE },
/* UPS page */
{ "ups.temperature", 0, 0, "St", "%05.1f", DEGCELS, TRUE },
{ "ups.load", 0, 0, "Ll", "%05.1f", NONE, TRUE },
{ "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 5, "Sm ?", "%03d", NONE, TRUE },
{ "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 5, "Sn ?", "%03d", NONE, TRUE },
{ "ups.test.interval", ST_FLAG_RW | ST_FLAG_STRING, 5, "Bp ?", "%03d", NONE, TRUE },
/* Output page */
{ "output.voltage", 0, 0, "Lv", "%05.1f", VOLT, TRUE },
{ "output.current", 0, 0, "Lc", "%05.1f", AMPERE, TRUE },
/* Input page */
{ "input.voltage", 0, 0, "Uv", "%05.1f", VOLT, TRUE },
{ "input.frequency", 0, 0, "Uf", "%05.2f", HERTZ, TRUE },
/* same as LOBOOSTXFER */
{ "input.transfer.low", ST_FLAG_RW | ST_FLAG_STRING, 5, "Ee ?", "%05.1f", VOLT, TRUE },
{ "input.transfer.boost.low", ST_FLAG_RW | ST_FLAG_STRING, 5, "Ee ?", "%05.1f", VOLT, TRUE },
{ "input.transfer.boost.high", ST_FLAG_RW | ST_FLAG_STRING, 5, "Eo ?", "%05.1f", VOLT, TRUE },
{ "input.transfer.trim.low", ST_FLAG_RW | ST_FLAG_STRING, 5, "Ea ?", "%05.1f", VOLT, TRUE },
/* same as HITRIMXFER */
{ "input.transfer.high", ST_FLAG_RW | ST_FLAG_STRING, 5, "Eu ?", "%05.1f", VOLT, TRUE },
{ "input.transfer.trim.high", ST_FLAG_RW | ST_FLAG_STRING, 5, "Eu ?", "%05.1f", VOLT, TRUE },
/* terminating element */
{ NULL, 0, 0, "\0", "\0", NONE, FALSE }
};