Desc: How to make a new module to support another UPS
File: new-modules.txt
Date: 30 May 1999

The basic premise used to pass data between a module and the upsd is a 
state file that usually lives in /var/state/ups.  The module should update
that file whenever the status of the UPS changes, and probably even if it
doesn't.  The file mtime should always be relatively recent - within 5
minutes or so - or a "staleness" check in upsd will flag it unusable.

Updates to the state file should be completed in one operation.  This is
done to ensure that the data collected doesn't represent part of the
previous poll and part of the current poll.  This is relatively easy to do
- just use write() to store the entire array in one call.

The data itself lives in an array of type "itype" as defined in shared.h.
This array has no set upper limit, but should be have as many elements as
there are variables to store.  The first member of this array MUST be type
INFO_MEMBERS and the value MUST be equal to the number of members
including that first one.  In other words, if you use positions 0 through
3, store 4 in there.

This "count as first member" is done so that upsd knows how much memory
to set aside for your array.  If you put too much, upsd will malloc a ton
and waste memory.  If you put in too little, it will miss some of your
variables.  So, get it right.

All of the other types are optional.  Don't include them unless the UPS
you are monitoring actually supports that value in some way.  Some things
can't be determined by the UPS itself but should still be reported if you
can.  For example, the APC Back-UPS driver has no idea that it's really
talking to one of those, but it hardcodes it anyway.  This has the effect
of allowing it to look nice in multimon and other programs.

So, if you have a reasonable idea of what is out there, hardcoding the
value is probably better than not including it at all, especially for
something fairly important like the model string.

The general logic for your module should be as follows:

 1. Setup the array
 2. Fill it with data from the UPS in the proper format
 3. Write it to the disk
 4. Goto 2

It's that easy.

Formatting
----------

The data contained in the value for each member of the array must conform
to the standard or it will be impossible for client programs to parse.  
All values are stored in string form and should be null terminated.

 Name         | Format details 
--------------+--------------------------------------------------------------
INFO_MEMBERS  | Defines how many members of the array exist including the
              | one containing INFO_MEMBERS.  Must be stored in position 0.
--------------+--------------------------------------------------------------
INFO_MFR      | Manufacturer's name.  Example: APC
--------------+--------------------------------------------------------------
INFO_MODEL    | UPS model name.  Example: SMART-UPS 700
--------------+--------------------------------------------------------------
INFO_UTILITY  | Voltage that UPS is receiving - nnn[.n] format  Ex: 116.7
--------------+--------------------------------------------------------------
INFO_BATTPCT  | UPS battery charge in percent - nnn[.n] format  Ex: 056.5
--------------+--------------------------------------------------------------
INFO_STATUS   | Current internal UPS power status - contains abbreviations
              | separated by spaces when necessary
              |
              | OFF   - UPS is off (not supplying power)
              | OL    - UPS is online (supplying power from the line/mains)
              | OB    - UPS is on battery
              | LB    - UPS battery is low (with OB = shutdown situation)
              | CAL   - UPS is performing calibration
              | TRIM  - UPS is trimming incoming voltage (APC "SmartTrim")
              | BOOST - UPS is boosting incoming voltage (APC "SmartBoost")
              | OVER  - UPS is overloaded
              | RB    - UPS battery needs to be replaced
              |
              | Things like "OL" and "OB" should not ever occur together.
              | Likewise, "OFF" and "OL" or "OB" are also mutually exclusive.
              |
              | Example for on battery + low battery: OB LB
--------------+--------------------------------------------------------------
INFO_UPSTEMP  | UPS internal temperature in degrees C - nnn[.n] format
              | Example: 037.0
--------------+--------------------------------------------------------------
INFO_ACFREQ   | Incoming frequency in Hz - nn[.nn] format   Example: 60.00
--------------+--------------------------------------------------------------
INFO_LOADPCT  | Load on UPS in percent - nnn[.n] format     Example: 023.4
--------------+--------------------------------------------------------------
INFO_LOWXFER  | UPS transfers to battery when incoming voltage drops below
              | this value - nnn[.n] format                 Example: 103
--------------+--------------------------------------------------------------
INFO_HIGHXFER | UPS transfers to battery when incoming voltage rises above
              | this value - nnn[.n] format                 Example: 132
--------------+--------------------------------------------------------------

New variable support
--------------------

To add support for a new variable, the following changes must happen:

1. Edit shared.h to give it an INFO_* identifier for the itype array

2. Edit upsd.h to match the INFO_* identifier to a text name

For sanity's sake, all variables have INFO_ as a prefix as their itype
array identifier.  A variable called FOO would be type INFO_FOO in the
array.

To keep things together, new variables should be submitted for inclusion
into the main source tree.

The future
----------

For speed and efficiency, this array will be stored in a shared memory
segment and upsd will attach to it for reading.  This feature is not yet
implemented but there are hooks that will allow it to be added later.
