new upstream 2.8.0

This commit is contained in:
lagertonne 2022-06-29 12:37:36 +02:00
parent fc7f4b43c1
commit b2b0c9995a
836 changed files with 137090 additions and 30018 deletions

View file

@ -1,11 +1,17 @@
# Network UPS Tools: drivers
# Make sure out-of-dir dependencies exist (especially when dev-building parts):
$(top_builddir)/common/libcommon.la \
$(top_builddir)/common/libparseconf.la \
$(top_builddir)/clients/libupsclient.la: dummy
@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
# by default, link programs in this directory with libcommon.la
# (libtool version of the static lib, in order to access LTLIBOBJS)
#FIXME: SERLIBS is only useful for LDADD_DRIVERS_SERIAL not for LDADD_COMMON
LDADD_COMMON = ../common/libcommon.la ../common/libparseconf.la
LDADD_DRIVERS = $(LDADD_COMMON) main.o dstate.o
LDADD_DRIVERS_SERIAL = $(LDADD_DRIVERS) $(SERLIBS) serial.o
LDADD_COMMON = $(top_builddir)/common/libcommon.la $(top_builddir)/common/libparseconf.la
LDADD_DRIVERS = libdummy.la $(LDADD_COMMON)
LDADD_DRIVERS_SERIAL = libdummy_serial.la $(LDADD_DRIVERS) $(SERLIBS)
# most targets are drivers, so make this the default
LDADD = $(LDADD_DRIVERS_SERIAL)
@ -16,9 +22,6 @@ AM_CFLAGS = -I$(top_srcdir)/include
if WITH_USB
AM_CFLAGS += $(LIBUSB_CFLAGS)
endif
if WITH_SNMP
AM_CFLAGS += $(LIBNETSNMP_CFLAGS)
endif
if WITH_NEON
AM_CFLAGS += $(LIBNEON_CFLAGS)
endif
@ -28,26 +31,34 @@ endif
if WITH_IPMI
AM_CFLAGS += $(LIBIPMI_CFLAGS)
endif
if WITH_MODBUS
AM_CFLAGS += $(LIBMODBUS_CFLAGS)
endif
SERIAL_DRIVERLIST = al175 bcmxcp belkin belkinunv bestfcom \
bestfortress bestuferrups bestups dummy-ups etapro everups \
gamatronic genericups isbmex liebert liebert-esp2 masterguard metasys \
oldmge-shut mge-utalk microdowell mge-shut oneac optiups powercom rhino \
safenet skel solis tripplite tripplitesu upscode2 victronups powerpanel \
blazer_ser clone clone-outlet ivtscd apcsmart apcsmart-old apcupsd-ups riello_ser \
nutdrv_qx
mge-utalk microdowell microsol-apc mge-shut oneac optiups powercom rhino \
safenet nutdrv_siemens-sitop skel solis tripplite tripplitesu upscode2 victronups powerpanel \
blazer_ser clone clone-outlet ivtscd apcsmart apcsmart-old apcupsd-ups riello_ser
SNMP_DRIVERLIST = snmp-ups
USB_LIBUSB_DRIVERLIST = usbhid-ups bcmxcp_usb tripplite_usb \
blazer_usb richcomm_usb riello_usb \
nutdrv_atcl_usb \
nutdrv_qx
nutdrv_atcl_usb
USB_DRIVERLIST = $(USB_LIBUSB_DRIVERLIST)
SERIAL_USB_DRIVERLIST = \
nutdrv_qx
NEONXML_DRIVERLIST = netxml-ups
MACOSX_DRIVERLIST = macosx-ups
LINUX_I2C_DRIVERLIST = asem
MODBUS_DRIVERLIST = phoenixcontact_modbus generic_modbus huawei-ups2000 socomec_jbus adelsystem_cbi
LINUX_I2C_DRIVERLIST = asem pijuice
POWERMAN_DRIVERLIST = powerman-pdu
IPMI_DRIVERLIST = nut-ipmipsu
# distribute all drivers, even ones that are not built by default
EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(SNMP_DRIVERLIST) $(USB_DRIVERLIST) $(NEONXML_DRIVERLIST) $(MACOSX_DRIVERLIST)
EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(USB_DRIVERLIST) $(SERIAL_USB_DRIVERLIST)
EXTRA_PROGRAMS += $(SNMP_DRIVERLIST) $(NEONXML_DRIVERLIST) $(MACOSX_DRIVERLIST)
EXTRA_PROGRAMS += $(LINUX_I2C_DRIVERLIST)
# construct the list of drivers to build
if SOME_DRIVERS
@ -55,7 +66,11 @@ if SOME_DRIVERS
else
driverexec_PROGRAMS =
if WITH_SERIAL
driverexec_PROGRAMS += $(SERIAL_DRIVERLIST)
driverexec_PROGRAMS += $(SERIAL_DRIVERLIST) $(SERIAL_USB_DRIVERLIST)
else
if WITH_USB
driverexec_PROGRAMS += $(SERIAL_USB_DRIVERLIST)
endif
endif
if WITH_SNMP
driverexec_PROGRAMS += $(SNMP_DRIVERLIST)
@ -67,10 +82,10 @@ if WITH_NEON
driverexec_PROGRAMS += $(NEONXML_DRIVERLIST)
endif
if WITH_LIBPOWERMAN
driverexec_PROGRAMS += powerman-pdu
driverexec_PROGRAMS += $(POWERMAN_DRIVERLIST)
endif
if WITH_IPMI
driverexec_PROGRAMS += nut-ipmipsu
driverexec_PROGRAMS += $(IPMI_DRIVERLIST)
endif
if WITH_MACOSX
driverexec_PROGRAMS += $(MACOSX_DRIVERLIST)
@ -78,6 +93,9 @@ endif
if WITH_LINUX_I2C
driverexec_PROGRAMS += $(LINUX_I2C_DRIVERLIST)
endif
if WITH_MODBUS
driverexec_PROGRAMS += $(MODBUS_DRIVERLIST)
endif
else
driverexec_PROGRAMS += skel
endif
@ -101,6 +119,7 @@ bcmxcp_LDADD = $(LDADD) -lm
belkin_SOURCES = belkin.c
belkinunv_SOURCES = belkinunv.c
bestfcom_SOURCES = bestfcom.c
bestfortress_SOURCES = bestfortress.c
bestuferrups_SOURCES = bestuferrups.c
bestups_SOURCES = bestups.c
blazer_ser_SOURCES = blazer.c blazer_ser.c
@ -116,9 +135,11 @@ liebert_SOURCES = liebert.c
liebert_esp2_SOURCES = liebert-esp2.c
masterguard_SOURCES = masterguard.c
metasys_SOURCES = metasys.c
oldmge_shut_SOURCES = mge-shut.c hidparser.c
metasys_LDADD = $(LDADD) -lm
mge_utalk_SOURCES = mge-utalk.c
microdowell_SOURCES = microdowell.c
microsol_apc_SOURCES = microsol-apc.c microsol-common.c
microsol_apc_LDADD = $(LDADD) -lm
oneac_SOURCES = oneac.c
optiups_SOURCES = optiups.c
powercom_SOURCES = powercom.c
@ -128,6 +149,7 @@ powerpanel_LDADD = $(LDADD) -lm
rhino_SOURCES = rhino.c
rhino_LDADD = $(LDADD) -lm
safenet_SOURCES = safenet.c
nutdrv_siemens_sitop_SOURCES = nutdrv_siemens_sitop.c
solis_SOURCES = solis.c
solis_LDADD = $(LDADD) -lm
tripplite_SOURCES = tripplite.c
@ -144,7 +166,7 @@ riello_ser_LDADD = $(LDADD) -lm
# dummy
dummy_ups_SOURCES = dummy-ups.c
dummy_ups_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/clients
dummy_ups_LDADD = $(LDADD_DRIVERS) ../clients/libupsclient.la
dummy_ups_LDADD = $(LDADD_DRIVERS) $(top_builddir)/clients/libupsclient.la
if WITH_SSL
dummy_ups_CFLAGS += $(LIBSSL_CFLAGS)
dummy_ups_LDADD += $(LIBSSL_LIBS)
@ -165,20 +187,26 @@ skel_SOURCES = skel.c
skel_LDADD = $(LDADD_DRIVERS)
# USB
USBHID_UPS_SUBDRIVERS = apc-hid.c belkin-hid.c cps-hid.c explore-hid.c \
if WITH_LIBUSB_0_1
LIBUSB_IMPL = libusb0.c
endif
if WITH_LIBUSB_1_0
LIBUSB_IMPL = libusb1.c
endif
USBHID_UPS_SUBDRIVERS = apc-hid.c arduino-hid.c belkin-hid.c cps-hid.c explore-hid.c \
liebert-hid.c mge-hid.c powercom-hid.c tripplite-hid.c idowell-hid.c \
openups-hid.c
usbhid_ups_SOURCES = usbhid-ups.c libhid.c libusb.c hidparser.c \
openups-hid.c powervar-hid.c delta_ups-hid.c ever-hid.c legrand-hid.c salicru-hid.c
usbhid_ups_SOURCES = usbhid-ups.c libhid.c $(LIBUSB_IMPL) hidparser.c \
usb-common.c $(USBHID_UPS_SUBDRIVERS)
usbhid_ups_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS)
usbhid_ups_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm
tripplite_usb_SOURCES = tripplite_usb.c libusb.c usb-common.c
tripplite_usb_SOURCES = tripplite_usb.c $(LIBUSB_IMPL) usb-common.c
tripplite_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm
bcmxcp_usb_SOURCES = bcmxcp_usb.c bcmxcp.c usb-common.c
bcmxcp_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm
blazer_usb_SOURCES = blazer.c blazer_usb.c libusb.c usb-common.c
blazer_usb_SOURCES = blazer.c blazer_usb.c $(LIBUSB_IMPL) usb-common.c
blazer_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm
nutdrv_atcl_usb_SOURCES = nutdrv_atcl_usb.c usb-common.c
@ -187,22 +215,37 @@ nutdrv_atcl_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS)
richcomm_usb_SOURCES = richcomm_usb.c usb-common.c
richcomm_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS)
riello_usb_SOURCES = riello.c riello_usb.c libusb.c usb-common.c
riello_usb_SOURCES = riello.c riello_usb.c $(LIBUSB_IMPL) usb-common.c
riello_usb_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm
# HID-over-serial
mge_shut_SOURCES = usbhid-ups.c libshut.c libhid.c hidparser.c mge-hid.c
# per-target CFLAGS are necessary here
mge_shut_CFLAGS = $(AM_CFLAGS) -DSHUT_MODE
mge_shut_LDADD = $(LDADD)
mge_shut_CFLAGS = $(AM_CFLAGS) -DSHUT_MODE=1
mge_shut_LDADD = $(LDADD) -lm
# SNMP
snmp_ups_SOURCES = snmp-ups.c apc-mib.c baytech-mib.c compaq-mib.c eaton-mib.c \
ietf-mib.c mge-mib.c netvision-mib.c powerware-mib.c raritan-pdu-mib.c \
bestpower-mib.c cyberpower-mib.c delta_ups-mib.c xppc-mib.c huawei-mib.c \
eaton-ats-mib.c apc-ats-mib.c
snmp_ups_LDADD = $(LDADD_DRIVERS) $(LIBNETSNMP_LIBS)
# Please keep the MIB table below sorted roughly alphabetically (incidentally
# by vendor too) to ease maintenance and codebase fork resynchronisations
snmp_ups_SOURCES = snmp-ups.c snmp-ups-helpers.c \
apc-mib.c apc-pdu-mib.c \
baytech-mib.c bestpower-mib.c \
compaq-mib.c cyberpower-mib.c \
delta_ups-mib.c \
eaton-pdu-genesis2-mib.c eaton-pdu-marlin-mib.c eaton-pdu-marlin-helpers.c \
eaton-pdu-pulizzi-mib.c eaton-pdu-revelation-mib.c \
eaton-ats16-nmc-mib.c eaton-ats16-nm2-mib.c apc-ats-mib.c eaton-ats30-mib.c \
emerson-avocent-pdu-mib.c \
hpe-pdu-mib.c huawei-mib.c \
ietf-mib.c \
mge-mib.c \
netvision-mib.c \
powerware-mib.c \
raritan-pdu-mib.c raritan-px2-mib.c \
xppc-mib.c
snmp_ups_CFLAGS = $(AM_CFLAGS)
snmp_ups_CFLAGS += $(LIBNETSNMP_CFLAGS)
snmp_ups_LDADD = $(LDADD_DRIVERS) $(LIBNETSNMP_LIBS) -lm
# NEON XML/HTTP
netxml_ups_SOURCES = netxml-ups.c mge-xml.c
@ -215,8 +258,11 @@ powerman_pdu_LDADD = $(LDADD) $(LIBPOWERMAN_LIBS)
# IPMI PSU
nut_ipmipsu_SOURCES = nut-ipmipsu.c
if WITH_FREEIPMI
nut_ipmipsu_SOURCES += nut-libfreeipmi.c
nut_ipmipsu_SOURCES += nut-libfreeipmi.c
endif
# FIXME: Hacky hot-fix for build agents of varying OS generations:
# Different versions of IPMI libs requested 'unsigned int *' or 'int *' args:
#nut_ipmipsu_CFLAGS = $(AM_CFLAGS) -Wno-pointer-sign
nut_ipmipsu_LDADD = $(LDADD) $(LIBIPMI_LIBS)
# Mac OS X metadriver
@ -224,9 +270,29 @@ macosx_ups_LDADD = $(LDADD_DRIVERS)
macosx_ups_LDFLAGS = $(LDFLAGS) -framework IOKit -framework CoreFoundation
macosx_ups_SOURCES = macosx-ups.c
# Asem
# Modbus drivers
phoenixcontact_modbus_SOURCES = phoenixcontact_modbus.c
phoenixcontact_modbus_LDADD = $(LDADD_DRIVERS) $(LIBMODBUS_LIBS)
generic_modbus_SOURCES = generic_modbus.c
generic_modbus_LDADD = $(LDADD_DRIVERS) $(LIBMODBUS_LIBS)
adelsystem_cbi_SOURCES = adelsystem_cbi.c
adelsystem_cbi_LDADD = $(LDADD_DRIVERS) $(LIBMODBUS_LIBS)
# Huawei UPS2000 driver
# (this is both a Modbus and a serial driver)
huawei_ups2000_SOURCES = huawei-ups2000.c
huawei_ups2000_LDADD = $(LDADD_DRIVERS_SERIAL) $(LIBMODBUS_LIBS)
# Socomec JBUS driver
# (this is a Modbus driver)
socomec_jbus_SOURCES = socomec_jbus.c
socomec_jbus_LDADD = $(LDADD_DRIVERS_SERIAL) $(LIBMODBUS_LIBS)
# Linux I2C drivers
asem_LDADD = $(LDADD_DRIVERS)
asem_SOURCES = asem.c
pijuice_LDADD = $(LDADD_DRIVERS)
pijuice_SOURCES = pijuice.c
# nutdrv_qx USB/Serial
nutdrv_qx_SOURCES = nutdrv_qx.c
@ -234,17 +300,19 @@ nutdrv_qx_LDADD = $(LDADD_DRIVERS) -lm
nutdrv_qx_CFLAGS = $(AM_CFLAGS)
if WITH_SERIAL
nutdrv_qx_CFLAGS += -DQX_SERIAL
nutdrv_qx_LDADD += $(SERLIBS) serial.o
nutdrv_qx_LDADD += libdummy_serial.la $(SERLIBS)
endif
if WITH_USB
nutdrv_qx_CFLAGS += -DQX_USB
nutdrv_qx_SOURCES += libusb.c usb-common.c
nutdrv_qx_SOURCES += $(LIBUSB_IMPL) usb-common.c
nutdrv_qx_LDADD += $(LIBUSB_LIBS)
endif
NUTDRV_QX_SUBDRIVERS = nutdrv_qx_bestups.c nutdrv_qx_blazer-common.c \
nutdrv_qx_masterguard.c \
nutdrv_qx_mecer.c nutdrv_qx_megatec.c nutdrv_qx_megatec-old.c \
nutdrv_qx_mustek.c nutdrv_qx_q1.c nutdrv_qx_voltronic.c \
nutdrv_qx_voltronic-qs.c nutdrv_qx_voltronic-qs-hex.c nutdrv_qx_zinto.c
nutdrv_qx_voltronic-qs.c nutdrv_qx_voltronic-qs-hex.c nutdrv_qx_zinto.c \
nutdrv_qx_hunnox.c nutdrv_qx_ablerex.c
nutdrv_qx_SOURCES += $(NUTDRV_QX_SUBDRIVERS)
# ----------------------------------------------------------------------
@ -252,22 +320,44 @@ nutdrv_qx_SOURCES += $(NUTDRV_QX_SUBDRIVERS)
# tracking (which is automatic), but to ensure these files are
# distributed by "make dist".
dist_noinst_HEADERS = apc-mib.h apc-hid.h baytech-mib.h bcmxcp.h \
bcmxcp_io.h belkin.h belkin-hid.h bestpower-mib.h blazer.h cps-hid.h dstate.h \
dummy-ups.h eaton-mib.h explore-hid.h gamatronic.h genericups.h \
hidparser.h hidtypes.h ietf-mib.h libhid.h libshut.h libusb.h liebert-hid.h \
main.h mge-hid.h mge-mib.h mge-shut.h mge-utalk.h \
mge-xml.h microdowell.h netvision-mib.h netxml-ups.h nut-ipmi.h oneac.h \
dist_noinst_HEADERS = apc-mib.h apc-iem-mib.h apc-hid.h arduino-hid.h baytech-mib.h bcmxcp.h bcmxcp_ser.h \
bcmxcp_io.h belkin.h belkin-hid.h bestpower-mib.h blazer.h cps-hid.h dstate.h \
dummy-ups.h explore-hid.h gamatronic.h genericups.h \
hidparser.h hidtypes.h ietf-mib.h libhid.h libshut.h nut_libusb.h liebert-hid.h \
main.h mge-hid.h mge-mib.h mge-utalk.h \
mge-xml.h microdowell.h microsol-apc.h microsol-common.h netvision-mib.h netxml-ups.h nut-ipmi.h oneac.h \
powercom.h powerpanel.h powerp-bin.h powerp-txt.h powerware-mib.h raritan-pdu-mib.h \
safenet.h serial.h snmp-ups.h solis.h tripplite.h tripplite-hid.h \
upshandler.h usb-common.h usbhid-ups.h powercom-hid.h compaq-mib.h idowell-hid.h \
apcsmart.h apcsmart_tabs.h apcsmart-old.h apcupsd-ups.h cyberpower-mib.h riello.h openups-hid.h \
delta_ups-mib.h nutdrv_qx.h nutdrv_qx_bestups.h nutdrv_qx_blazer-common.h nutdrv_qx_mecer.h \
nutdrv_qx_megatec.h nutdrv_qx_megatec-old.h nutdrv_qx_mustek.h nutdrv_qx_q1.h \
delta_ups-mib.h nutdrv_qx.h nutdrv_qx_bestups.h nutdrv_qx_blazer-common.h \
nutdrv_qx_masterguard.h \
nutdrv_qx_mecer.h nutdrv_qx_ablerex.h \
nutdrv_qx_megatec.h nutdrv_qx_megatec-old.h nutdrv_qx_mustek.h nutdrv_qx_q1.h nutdrv_qx_hunnox.h \
nutdrv_qx_voltronic.h nutdrv_qx_voltronic-qs.h nutdrv_qx_voltronic-qs-hex.h nutdrv_qx_zinto.h \
xppc-mib.h huawei-mib.h eaton-ats-mib.h apc-ats-mib.h
xppc-mib.h huawei-mib.h eaton-ats16-nmc-mib.h eaton-ats16-nm2-mib.h apc-ats-mib.h raritan-px2-mib.h eaton-ats30-mib.h \
apc-pdu-mib.h ever-hid.h eaton-pdu-genesis2-mib.h eaton-pdu-marlin-mib.h eaton-pdu-marlin-helpers.h \
eaton-pdu-pulizzi-mib.h eaton-pdu-revelation-mib.h emerson-avocent-pdu-mib.h legrand-hid.h \
hpe-pdu-mib.h powervar-hid.h delta_ups-hid.h generic_modbus.h salicru-hid.h adelsystem_cbi.h
# Define a dummy library so that Automake builds rules for the
# corresponding object files. This library is not actually built,
EXTRA_LIBRARIES = libdummy.a
libdummy_a_SOURCES = main.c dstate.c serial.c
# as a final product. It was necessary for Automake-technical reasons,
# because per-object CFLAGS can only be specified for libraries, not
# for object files. This library is used during the build process,
# and is not meant to be installed.
EXTRA_LTLIBRARIES = libdummy.la libdummy_serial.la
libdummy_la_SOURCES = main.c dstate.c
libdummy_la_LDFLAGS = -no-undefined -static
libdummy_serial_la_SOURCES = serial.c
libdummy_serial_la_LDFLAGS = -no-undefined -static
dummy:
CLEANFILES = $(EXTRA_LTLIBRARIES) $(EXTRA_PROGRAMS)
MAINTAINERCLEANFILES = Makefile.in .dirstamp
# NOTE: Do not clean ".deps" in SUBDIRS of the main project,
# the root Makefile.am takes care of that!
#clean-local:
# rm -rf $(builddir)/.deps

File diff suppressed because it is too large Load diff

1344
drivers/adelsystem_cbi.c Normal file

File diff suppressed because it is too large Load diff

531
drivers/adelsystem_cbi.h Normal file
View file

@ -0,0 +1,531 @@
/* adelsystem_cbi.h - Driver for ADELSYSTEM CB/CBI DC-UPS
*
* Copyright (C)
* 2022 Dimitris Economou <dimitris.s.economou@gmail.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
*
*/
/*
* code indentation with tabstop=4
*/
#ifndef ADELSYSTEM_CBI_H
#define ADELSYSTEM_CBI_H
#include <stdint.h>
/* UPS device details */
#define DEVICE_MFR "ADELSYSTEM"
#define DEVICE_TYPE "DC-UPS"
#define DEVICE_MODEL "CBI2801224A"
/* serial access parameters */
#define BAUD_RATE 9600
#define PARITY 'N'
#define DATA_BIT 8
#define STOP_BIT 1
/*
* modbus response and byte timeouts
* us: 1 - 999999
*/
#define MODRESP_TIMEOUT_s 0
#define MODRESP_TIMEOUT_us 200000
#define MODBYTE_TIMEOUT_s 0
#define MODBYTE_TIMEOUT_us 50000
/* modbus access parameters */
#define MODBUS_SLAVE_ID 5
/* number of modbus registers */
#define MODBUS_NUMOF_REGS 98
/* max HOLDING registers */
#define MAX_H_REGS 120
/* start HOLDING register index */
#define H_REG_STARTIDX 0
/* read all regs preprocessor flag */
#ifndef READALL_REGS
#define READALL_REGS 1
#endif
/* number of device models */
#define DEV_NUMOF_MODELS 10
/* shutdown repeat on error */
#define FSD_REPEAT_CNT 3
/* shutdown repeat interval in ms */
#define FSD_REPEAT_INTRV 1500
/* definition of register type */
enum regtype {
COIL = 0,
INPUT_B,
INPUT_R,
HOLDING
};
typedef enum regtype regtype_t;
/* product name info, "device.model" */
struct prodname {
uint16_t val;
char *name;
};
typedef struct prodname prodname_t;
static prodname_t prdnm_i[] = {
{1, "CBI1235A"},
{2, "CBI2420A"},
{3, "CBI4810A"},
{4, "CBI2801224"},
{7, "CBI480W"},
{8, "CB122410A"},
{9, "CB480W"},
{11, "CB12245AJ"},
{12, "CB1235A"},
{13, "CB2420A"},
{14, "CB4810A"}
};
/* charging status info, "battery.charger.status" */
static char *chrgs_i[] = {
"none",
"resting", /* recovering */
"charging", /* bulk */
"charging", /* absorb */
"floating" /* float */
};
struct chrgs {
int state;
char *info;
};
typedef struct chrgs chrgs_t;
/* power management info, "ups.status", "battery.charger.status" */
static char *pwrmng_i[] = {
"backup", /* "OB", "discharging" */
"charging", /* "OL" */
"boost",
"not charging"
};
struct pwrmng {
int state;
char *info;
};
typedef struct pwrmng pwrmng_t;
/* general modbus register value */
struct reg {
union val {
uint16_t ui16;
uint8_t ui8;
} val;
char *strval;
};
typedef struct reg reg_t;
/* general alarm struct */
struct alrm {
int actv; /* active flag */
char *descr; /* description field */
};
typedef struct alrm alrm_t;
/* general alarm array */
struct alrm_ar {
int alrm_c; /* alarm count */
alrm_t *alrm; /* alarm array */
};
typedef struct alrm_ar alrm_ar_t;
/*
* BIT MASKS and VALUES
*/
/* Charging status */
#define CHRG_NONE 0
#define CHRG_RECV 1
#define CHRG_BULK 2
#define CHRG_ABSR 3
#define CHRG_FLOAT 4
/* power management */
#define PMNG_BCKUP 0
#define PMNG_CHRGN 1
#define PMNG_BOOST 2
#define PMNG_NCHRG 3
/* product name */
#define PRDN_MAX 14
/* Mains alarm masks */
#define MAINS_AVAIL_M 0x0001 /* 0: available (OL) 1: not available (OB) */
#define SHUTD_REQST_M 0x0002 /* shutdown requested */
/* Mains alarm indices */
#define MAINS_AVAIL_I 0 /* 0: available (OL) 1: not available (OB) */
#define SHUTD_REQST_I 1 /* shutdown requested */
/* AC input voltage alarm masks */
#define VACA_HIALRM_M 0x0001 /* high alarm */
#define VACA_LOALRM_M 0x0002 /* low alarm */
/* AC input voltage alarm indices */
#define VACA_HIALRM_I 0 /* high alarm */
#define VACA_LOALRM_I 1 /* low alarm */
/* Onboard temperature alarm value */
#define OBTA_HIALRM_V 1 /* high alarm */
/* Onboard temperature alarm index */
#define OBTA_HIALRM_I 0 /* high alarm */
/* Device failure alarm masks */
#define DEVF_RCALRM_M 0x0001 /* rectifier failure */
#define DEVF_INALRM_M 0x0006 /* internal failure */
#define DEVF_LFNAVL_M 0x0008 /* lifetest not available */
/* Device failure alarm indices */
#define DEVF_RCALRM_I 0 /* rectifier failure */
#define DEVF_INALRM_I 1 /* internal failure */
#define DEVF_LFNAVL_I 2 /* lifetest not available */
/* Battery temp sensor failure alarm masks */
#define BTSF_FCND_M 0x0001 /* connection fault */
#define BTSF_NCND_M 0x0002 /* not connected */
/* Battery temp sensor failure alarm indices */
#define BTSF_FCND_I 0 /* connection fault */
#define BTSF_NCND_I 1 /* not connected */
/* Battery voltage alarm masks */
#define BVAL_HIALRM_M 0x0001 /* high voltage */
#define BVAL_LOALRM_M 0x0002 /* low voltage */
#define BVAL_BSTSFL_M 0x0004 /* battery start with battery flat */
/* Battery voltage alarm indices */
#define BVAL_HIALRM_I 0 /* high voltage */
#define BVAL_LOALRM_I 1 /* low voltage */
#define BVAL_BSTSFL_I 2 /* battery start with battery flat */
/* SoH and SoC alarm masks */
#define SHSC_HIRESI_M 0x0001 /* high internal resistance */
#define SHSC_LOCHEF_M 0x0002 /* low charge efficiency */
#define SHSC_LOEFCP_M 0x0004 /* low effective capacity */
#define SHSC_LOWSOC_M 0x0040 /* low state of charge */
/* SoH and SoC alarm indices */
#define SHSC_HIRESI_I 0 /* high internal resistance */
#define SHSC_LOCHEF_I 1 /* low charge efficiency */
#define SHSC_LOEFCP_I 2 /* low effective capacity */
#define SHSC_LOWSOC_I 3 /* low state of charge */
/* Battery status alarm masks */
#define BSTA_REVPOL_M 0x0001 /* reversed polarity */
#define BSTA_NOCNND_M 0x0002 /* not connected */
#define BSTA_CLSHCR_M 0x0004 /* cell short circuit */
#define BSTA_SULPHD_M 0x0008 /* sulphated */
#define BSTA_CHEMNS_M 0x0010 /* chemistry not supported */
#define BSTA_CNNFLT_M 0x0020 /* connection fault */
/* Battery status alarm indices */
#define BSTA_REVPOL_I 0 /* reversed polarity */
#define BSTA_NOCNND_I 1 /* not connected */
#define BSTA_CLSHCR_I 2 /* cell short circuit */
#define BSTA_SULPHD_I 3 /* sulphated */
#define BSTA_CHEMNS_I 4 /* chemistry not supported */
#define BSTA_CNNFLT_I 5 /* connection fault */
/* Allocate alarm arrays */
static inline
alrm_ar_t *alloc_alrm_ar(int as, size_t n)
{
alrm_ar_t *ret = xcalloc(sizeof(alrm_t) + n, 1);
if (ret) {
memcpy(ret,
&(alrm_ar_t const) {
.alrm_c = as
},
sizeof(alrm_ar_t)
);
}
return ret;
}
/* Initialize alarm arrays */
static inline
void alrm_ar_init(alrm_ar_t *ar_ptr, alrm_t *a_ptr, int as)
{
ar_ptr->alrm_c = as;
ar_ptr->alrm = a_ptr;
}
/* input mains and shutdown alarms */
static alrm_t mains_ar[] = {
{0, "input voltage not available"},
{0, "ups shutdown requested"}
};
static int mains_c = 2;
static alrm_ar_t *mains;
/* AC input voltage alarms */
static alrm_t vaca_ar[] = {
{0, "input voltage high alarm"},
{0, "input voltage low alarm"}
};
static int vaca_c = 2;
static alrm_ar_t *vaca;
/* device failure alarms */
static alrm_t devf_ar[] = {
{0, "UPS rectifier failure"},
{0, "UPS internal failure"},
{0, "UPS lifetest not available"}
};
static int devf_c = 3;
static alrm_ar_t *devf;
/* battery sensor failure alarms */
static alrm_t btsf_ar[] = {
{0, "battery temp sensor connection fault"},
{0, "battery temp sensor not connected"}
};
static int btsf_c = 2;
static alrm_ar_t *btsf;
/* battery voltage alarms */
static alrm_t bval_ar[] = {
{0, "battery high voltage"},
{0, "battery low voltage"},
{0, "battery start with battery flat"}
};
static int bval_c = 3;
static alrm_ar_t *bval;
/* battery SoH and SoC alarms */
static alrm_t shsc_ar[] = {
{0, "battery high internal resistance"},
{0, "battery low charge efficiency"},
{0, "battery low effective capacity"},
{0, "battery low state of charge"}
};
static int shsc_c = 4;
static alrm_ar_t *shsc;
/* battery status alarm */
static alrm_t bsta_ar[] = {
{0, "battery reversed polarity"},
{0, "battery not connected"},
{0, "battery cell short circuit"},
{0, "battery sulphated"},
{0, "battery chemistry not supported"},
{0, "battery connection fault"}
};
static int bsta_c = 4;
static alrm_ar_t *bsta;
/* onboard temperature alarm */
static alrm_t obta_ar[] = {
{0, "onboard temperature high"}
};
static int obta_c = 4;
static alrm_ar_t *obta;
/* UPS device reg enum */
enum devreg {
CHRG = 4, /* Charging status, "battery.charger.status" */
BATV = 7, /* Battery voltage, "battery.voltage" */
BCEF = 18, /* Battery charge efficiency factor (CEF) */
BSOH = 20, /* Battery state-of-health */
BSOC = 22, /* Battery state-of-charge, "battery.charge" */
BTMP = 25, /* Battery temperature in Kelvin units, "battery.temperature" */
PMNG = 5, /* Power management, "ups.status" */
OTMP = 28, /* Onboard temperature, "ups.temperature" */
PRDN = 67, /* Product name, "ups.model" */
VAC = 29, /* AC voltage, "input.voltage" */
LVDC = 10, /* Load voltage, "output.voltage" */
LCUR = 19, /* Load current, "output.current" */
BINH = 87, /* Backup inhibit */
FSD = 40, /* Force shutdown */
TBUF = 103, /* Time buffering, "battery.runtime" */
BSTA = 31, /* Battery status alarms */
SCSH, /* SoH and SoC alarms */
BVAL = 34, /* Battery voltage alarm */
BTSF = 43, /* Battery temp sensor failure */
DEVF = 42, /* Device failure */
OBTA = 46, /* On board temp alarm */
VACA = 44, /* VAC alarms */
MAIN /* Mains status */
};
typedef enum devreg devreg_t;
/* UPS register attributes */
struct regattr {
int num;
int saddr; /* register start address */
int xaddr; /* register hex address */
float scale; /* scale */
regtype_t type; /* register type */
};
typedef struct regattr regattr_t;
/* UPS device state info union */
union devstate {
prodname_t product; /* ups model name */
chrgs_t charge; /* charging status */
pwrmng_t power; /* ups status */
reg_t reg; /* state register*/
alrm_ar_t *alrm; /* alarm statuses */
};
typedef union devstate devstate_t;
/* device register memory image */
static uint16_t regs_data[MAX_H_REGS];
/* ADELSYSTEM CBI registers */
static regattr_t regs[] = {
{40001, 0, 0, 1, HOLDING}, /* Address of slave unit */
{40002, 0, 0, 1, HOLDING}, /* Baud rate for serial communication */
{40003, 0, 0, 1, HOLDING}, /* Parity bit for serial communication */
{40004, 0, 0, 1, HOLDING},
{40005, 0, 0, 1, HOLDING}, /* Charging status */
{40006, 0, 0, 1, HOLDING}, /* Power management
* 0:Backup 1:Charging 2:boost 3:Not charging
*/
{40007, 0, 0, 1, HOLDING}, /* Nominal output voltage */
{40008, 0, 0, 1, HOLDING}, /* Battery voltage */
{40009, 0, 0, 1, HOLDING}, /* Parameter map version ID */
{40010, 0, 0, 1, HOLDING}, /* Software ID */
{40011, 0, 0, 1, HOLDING}, /* Output load voltage */
{40012, 0, 0, 1, HOLDING},
{40013, 0, 0, 1, HOLDING},
{40014, 0, 0, 1, HOLDING}, /* Battery charge current */
{40015, 0, 0, 1, HOLDING},
{40016, 0, 0, .1, HOLDING}, /* Battery capacity consumed */
{40017, 0, 0, 1, HOLDING}, /* Battery discharge current */
{40018, 0, 0, .1, HOLDING}, /* Effective battery capacity */
{40019, 0, 0, 1, HOLDING}, /* Battery charge efficiency factor (CEF) */
{40020, 0, 0, 1, HOLDING}, /* Output load current */
{40021, 0, 0, 1, HOLDING}, /* Battery state-of-health */
{40022, 0, 0, 1, HOLDING}, /* Time remaining to 100% discharge */
{40023, 0, 0, .1, HOLDING}, /* Battery state-of-charge */
{40024, 0, 0, 1, HOLDING}, /* Battery type currently selected */
{40025, 0, 0, 1, HOLDING},
{40026, 0, 0, 1, HOLDING}, /* Battery temperature in Kelvin units */
{40027, 0, 0, 1, HOLDING}, /* Configuration mode */
{40028, 0, 0, .1, HOLDING}, /* Battery net internal resistance */
{40029, 0, 0, 1, HOLDING}, /* On-board temperature */
{40030, 0, 0, 1, HOLDING}, /* AC input voltage */
{40031, 0, 0, 1, HOLDING},
{40032, 0, 0, 1, HOLDING}, /* Battery status alarm */
{40033, 0, 0, 1, HOLDING}, /* Battery State of Charge and State of Health */
{40034, 0, 0, 1, HOLDING}, /* Load output off duration after PC shutdown */
{40035, 0, 0, 1, HOLDING}, /* Battery voltage alarm */
{40036, 0, 0, 1, HOLDING}, /* Low AC input voltage alarm threshold */
{40037, 0, 0, 1, HOLDING}, /* High AC input voltage alarm threshold */
{40038, 0, 0, 1, HOLDING}, /* Load alarm */
{40039, 0, 0, 1, HOLDING}, /* Device variant */
{40040, 0, 0, 1, HOLDING},
{40041, 0, 0, 1, HOLDING}, /* Force shutdown */
{40042, 0, 0, 1, HOLDING},
{40043, 0, 0, 1, HOLDING}, /* Device failure */
{40044, 0, 0, 1, HOLDING}, /* Battery temperature sensor failure */
{40045, 0, 0, 1, HOLDING}, /* AC input voltage alarm */
{40046, 0, 0, 1, HOLDING}, /* Mains status */
{40047, 0, 0, 1, HOLDING}, /* On board temperature alarm */
{40048, 0, 0, 1, HOLDING}, /* Number of charge cycles completed */
{40049, 0, 0, 1, HOLDING}, /* Charge cycles not completed */
{40050, 0, 0, .1, HOLDING}, /* Ah charged */
{40051, 0, 0, 1, HOLDING}, /* Total run time */
{40052, 0, 0, 1, HOLDING}, /* Number of low battery voltage events */
{40053, 0, 0, 1, HOLDING}, /* Number of high battery voltage events */
{40054, 0, 0, 1, HOLDING}, /* Number of low VAC events at mains input */
{40055, 0, 0, 1, HOLDING}, /* Number of High VAC events at mains input */
{40056, 0, 0, 1, HOLDING}, /* Number of over temperature inside events */
{40057, 0, 0, 1, HOLDING}, /* Number of mains-backup transitions */
{40058, 0, 0, 1, HOLDING}, /* Number power boost events */
{40059, 0, 0, 1, HOLDING}, /* Highest battery voltage */
{40060, 0, 0, 1, HOLDING}, /* Highest output load voltage */
{40061, 0, 0, .1, HOLDING}, /* Maximum depth of discharge */
{40062, 0, 0, 1, HOLDING}, /* Lowest battery voltage */
{40063, 0, 0, 1, HOLDING}, /* Lowest output load voltage */
{40064, 0, 0, .1, HOLDING}, /* Average depth of discharge */
{40065, 0, 0, 1, HOLDING}, /* History clear all */
{40066, 0, 0, 1, HOLDING}, /* Factory settings */
{40067, 0, 0, 1, HOLDING}, /* Product name */
{40068, 0, 0, 1, HOLDING},
{40069, 0, 0, 1, HOLDING}, /* Reset internal battery model */
{40070, 0, 0, 1, HOLDING},
{40071, 0, 0, 1, HOLDING}, /* Deep discharge battery prevention */
{40072, 0, 0, 1, HOLDING}, /* Maximum charge current */
{40073, 0, 0, 1, HOLDING}, /* Bulk voltage */
{40074, 0, 0, 1, HOLDING}, /* Max bulk timer */
{40075, 0, 0, 1, HOLDING}, /* Min bulk timer */
{40076, 0, 0, 1, HOLDING},
{40077, 0, 0, 1, HOLDING}, /* Absorption voltage */
{40078, 0, 0, 1, HOLDING}, /* Max absorption timer */
{40079, 0, 0, 1, HOLDING}, /* Min absorption timer */
{40080, 0, 0, 1, HOLDING}, /* Return Amperes to float */
{40081, 0, 0, 1, HOLDING}, /* Return amps timer */
{40082, 0, 0, 1, HOLDING}, /* Float voltage */
{40083, 0, 0, 1, HOLDING}, /* Force boost charge */
{40084, 0, 0, 1, HOLDING}, /* Return to bulk voltage from float */
{40085, 0, 0, 1, HOLDING}, /* Return to bulk delay */
{40086, 0, 0, 1, HOLDING},
{40087, 0, 0, 1, HOLDING}, /* Switchoff voltage without mains */
{40088, 0, 0, 1, HOLDING}, /* Backup Inhibit 0 = Backup allowed
* 1 = Backup not allowed
*/
{40089, 0, 0, 1, HOLDING}, /* Number of battery cells */
{40090, 0, 0, 1, HOLDING}, /* Temperature compensation coefficient */
{40091, 0, 0, 1, HOLDING},
{40092, 0, 0, 1, HOLDING}, /* Lifetest enable */
{40093, 0, 0, 1, HOLDING}, /* Max alarm temp */
{40094, 0, 0, 1, HOLDING}, /* Min alarm temp */
{40095, 0, 0, 1, HOLDING},
{40096, 0, 0, 1, HOLDING},
{40097, 0, 0, 1, HOLDING}, /* Low battery threshold */
{40098, 0, 0, 1, HOLDING}, /* SoC/SoH test period */
{40099, 0, 0, 1, HOLDING}, /* Manual SoC/SoH test request */
{40100, 0, 0, 1, HOLDING}, /* SoC/SoH test possible */
{40101, 0, 0, .1, HOLDING}, /* Nominal battery internal resistance */
{40102, 0, 0, .1, HOLDING}, /* Nominal battery cables resistance */
{40103, 0, 0, 1, HOLDING}, /* Firmware ID */
{40104, 0, 0, 1, HOLDING}, /* Time buffering */
{40105, 0, 0, .1, HOLDING}, /* Battery capacity C20 */
{40106, 0, 0, .1, HOLDING}, /* Battery Capacity C10 */
{40107, 0, 0, 1, HOLDING}, /* Device switchoff delay */
{40108, 0, 0, .1, HOLDING}, /* Battery Capacity C5 */
{40109, 0, 0, .1, HOLDING}, /* Battery Capacity C2 */
{40110, 0, 0, 1, HOLDING},
{40111, 0, 0, 1, HOLDING}, /* PC power supply removal delay */
{40112, 0, 0, .1, HOLDING}, /* Battery Capacity C1 */
{40113, 0, 0, .1, HOLDING}, /* Low state-of-charge */
{40114, 0, 0, 1, HOLDING},
{40115, 0, 0, 1, HOLDING},
{40116, 0, 0, 1, HOLDING},
{40117, 0, 0, 1, HOLDING},
{40118, 0, 0, 1, HOLDING},
{40119, 0, 0, 1, HOLDING},
{40120, 0, 0, 1, HOLDING} /* Zero-SoC reference */
};
#endif /* ADELSYSTEM_CBI_H */

View file

@ -47,13 +47,12 @@
#include <stdio.h>
#include <unistd.h>
#include "nut_stdint.h"
typedef uint8_t byte_t;
#define DRIVER_NAME "Eltek AL175/COMLI driver"
#define DRIVER_VERSION "0.12"
#define DRIVER_VERSION "0.13"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -80,7 +79,7 @@ upsdrv_info_t upsdrv_info = {
*/
typedef struct {
byte_t *buf; /*!< the whole buffer address */
unsigned buf_size; /*!< the whole buffer size */
size_t buf_size; /*!< the whole buffer size */
byte_t *begin; /*!< begin of content */
byte_t *end; /*!< one-past-end of content */
@ -115,7 +114,7 @@ typedef struct {
* @param size size in bytes
* @return xmalloc'ed memory as raw_data
*/
raw_data_t raw_xmalloc(size_t size)
static raw_data_t raw_xmalloc(size_t size)
{
raw_data_t data;
@ -132,7 +131,7 @@ raw_data_t raw_xmalloc(size_t size)
* free raw_data buffer
* @param buf raw_data buffer to free
*/
void raw_free(raw_data_t *buf)
static void raw_free(raw_data_t *buf)
{
free(buf->buf);
@ -164,8 +163,8 @@ typedef struct {
* @see 1. INTRODUCTION
*/
typedef struct {
unsigned addr; /*!< Addr[5:8] */
unsigned len; /*!< NOB[9:10] */
size_t addr; /*!< Addr[5:8] */
size_t len; /*!< NOB[9:10] */
} io_head_t;
/**
@ -191,7 +190,7 @@ typedef struct {
/**
* convert hex string to int
* @param head input string
* @param count string length
* @param len string length
* @return parsed value (>=0) if success, -1 on error
*/
static long from_hex(const byte_t *head, unsigned len)
@ -233,7 +232,7 @@ static long from_hex(const byte_t *head, unsigned len)
static byte_t compute_bcc(const byte_t *buf, size_t count)
{
byte_t bcc=0;
unsigned i;
size_t i;
for (i=0; i<count; ++i)
bcc ^= buf[i];
@ -254,14 +253,14 @@ static void reverse_bits(byte_t *buf, size_t count)
while (count!=0) {
x = *buf;
x = ( (x & 0x80) >> 7 ) |
( (x & 0x40) >> 5 ) |
( (x & 0x20) >> 3 ) |
( (x & 0x10) >> 1 ) |
( (x & 0x08) << 1 ) |
( (x & 0x04) << 3 ) |
( (x & 0x02) << 5 ) |
( (x & 0x01) << 7 );
x = (byte_t)( (x & 0x80) >> 7 ) |
(byte_t)( (x & 0x40) >> 5 ) |
(byte_t)( (x & 0x20) >> 3 ) |
(byte_t)( (x & 0x10) >> 1 ) |
(byte_t)( (x & 0x08) << 1 ) |
(byte_t)( (x & 0x04) << 3 ) |
(byte_t)( (x & 0x02) << 5 ) |
(byte_t)( (x & 0x01) << 7 );
*buf = x;
++buf;
@ -333,7 +332,7 @@ static void comli_prepare(raw_data_t *dest, const comli_head_t *h, const void *b
fatalx(EXIT_FAILURE, "too small dest in comli_prepare\n");
out[0] = STX;
snprintf((char *)out+1, 10+1, "%02X%1i%1i%04X%02X", h->msg.id, h->msg.stamp, h->msg.type, h->io.addr, h->io.len);
snprintf((char *)out+1, 10+1, "%02X%1i%1i%04zX%02zX", h->msg.id, h->msg.stamp, h->msg.type, h->io.addr, h->io.len);
memcpy(out+11, buf, count);
reverse_bits(out+11, count);
@ -355,7 +354,7 @@ static void comli_prepare(raw_data_t *dest, const comli_head_t *h, const void *b
* @param addr start address of requested area
* @param count no. of requested bytes
*/
static void al_prep_read_req(raw_data_t *dest, unsigned addr, size_t count)
static void al_prep_read_req(raw_data_t *dest, size_t addr, size_t count)
{
comli_head_t h;
@ -393,11 +392,29 @@ static void al_prep_activate(raw_data_t *dest, byte_t cmd, byte_t subcmd, uint16
h.io.len = 8;
/* NOTE: doc says we should use ASCII coding here, but the actual
* values are > 0x80, so we use binary coding */
data[0] = cmd;
data[1] = subcmd;
* values are > 0x80, so we use binary coding. And have to
* make this "fit" into the char array required by snprintf */
data[0] = (char)cmd;
data[1] = (char)subcmd;
snprintf(data+2, 6+1, "%2X%2X%2X", pr1, pr2, pr3);
/* FIXME? One CI testcase builder claims here that
* warning: '%2X' directive output may be truncated writing
* between 2 and 4 bytes into a region of size between 3 and 5
* [-Wformat-truncation=]
* but none others do, and I can't figure out how it thinks so :/
*
* Per https://stackoverflow.com/questions/51534284/how-to-circumvent-format-truncation-warning-in-gcc
* https://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg521037.html
* and simlar googlable sources, this seems to be a bug-or-feature
* linked to non-zero optimization level and/or not checking for the
* return value (conveys runtime errors if any do happen).
*/
assert (pr1 <= UINT8_MAX);
assert (pr2 <= UINT8_MAX);
assert (pr3 <= UINT8_MAX);
if (0 > snprintf(data+2, 6+1, "%2X%2X%2X", pr1, pr2, pr3)) {
data[8] = '\0';
}
comli_prepare(dest, &h, data, 8);
}
@ -417,6 +434,9 @@ static int comli_check_frame(/*const*/ raw_data_t f)
int bcc;
byte_t *tail;
if ( (f.end - f.begin) < 2 )
return -1;
if (*f.begin!=STX)
return -1;
@ -427,7 +447,7 @@ static int comli_check_frame(/*const*/ raw_data_t f)
if (tail[0]!=ETX)
return -1;
bcc = compute_bcc(f.begin+1, (f.end - f.begin) - 2/*STX & BCC*/);
bcc = compute_bcc(f.begin+1, (size_t)(f.end - f.begin) - 2 /*STX & BCC*/);
if (bcc!= tail[1])
return -1;
@ -458,7 +478,7 @@ static int al_parse_reply_head(io_head_t *io, const raw_data_t raw_reply_head)
* begin end
*/
unsigned long io_addr, io_len;
size_t io_addr, io_len;
const byte_t *reply_head = raw_reply_head.begin - 1;
if ( (raw_reply_head.end - raw_reply_head.begin) != 10) {
@ -481,20 +501,24 @@ static int al_parse_reply_head(io_head_t *io, const raw_data_t raw_reply_head)
return -1; /* wrong type */
}
io_addr = from_hex(&reply_head[5], 4);
if (io_addr==-1UL) {
upsdebugx(3, "%s: invalid addr\t('%c%c%c%c')", __func__, reply_head[5],reply_head[6],reply_head[7],reply_head[8]);
/* Avoid signed/unsigned implicit conversion warnings
* At least, when shuffling a signed long into unsigned long,
* don't have to worry about overflows */
io_addr = (size_t)from_hex(&reply_head[5], 4);
if (io_addr == -1UL) {
upsdebugx(3, "%s: invalid addr\t('%c%c%c%c')", __func__,
reply_head[5], reply_head[6], reply_head[7], reply_head[8]);
return -1; /* wrong addr */
}
io_len = from_hex(&reply_head[9], 2);
if (io_len==-1UL) {
upsdebugx(3, "%s: invalid nob\t('%c%c')", __func__, reply_head[9],reply_head[10]);
io_len = (size_t)from_hex(&reply_head[9], 2);
if (io_len == -1UL) {
upsdebugx(3, "%s: invalid nob\t('%c%c')", __func__, reply_head[9], reply_head[10]);
return -1; /* wrong NOB */
}
if (io_len > IO_LEN_MAX) {
upsdebugx(3, "nob too big\t(%lu > %i)", io_len, IO_LEN_MAX);
upsdebugx(3, "nob too big\t(%zu > %i)", io_len, IO_LEN_MAX);
return -1; /* too much data claimed */
}
@ -530,8 +554,8 @@ static int al_parse_reply(io_head_t *io_head, raw_data_t *io_buf, /*const*/ raw_
*/
int err;
unsigned i;
const byte_t *reply = raw_reply.begin - 1;
size_t i;
const byte_t *reply = NULL;
/* 1: extract header and parse it */
/*const*/ raw_data_t raw_reply_head = raw_reply;
@ -548,7 +572,7 @@ static int al_parse_reply(io_head_t *io_head, raw_data_t *io_buf, /*const*/ raw_
reply = raw_reply.begin - 1;
if ( (raw_reply.end - raw_reply.begin) != (ptrdiff_t)(10 + io_head->len)) {
upsdebugx(3, "%s: corrupt sentence\t(%i != %i)",
upsdebugx(3, "%s: corrupt sentence\t(%i != %zi)",
__func__, (int)(raw_reply.end - raw_reply.begin), 10 + io_head->len);
return -1; /* corrupt sentence */
}
@ -556,7 +580,7 @@ static int al_parse_reply(io_head_t *io_head, raw_data_t *io_buf, /*const*/ raw_
/* extract the data */
if (io_buf->buf_size < io_head->len) {
upsdebugx(3, "%s: too much data to fit in io_buf\t(%u > %u)",
upsdebugx(3, "%s: too much data to fit in io_buf\t(%zu > %zu)",
__func__, io_head->len, io_buf->buf_size);
return -1; /* too much data to fit in io_buf */
}
@ -567,9 +591,11 @@ static int al_parse_reply(io_head_t *io_head, raw_data_t *io_buf, /*const*/ raw_
for (i=0; i<io_head->len; ++i)
*(io_buf->end++) = reply[11+i];
reverse_bits(io_buf->begin, (io_buf->end - io_buf->begin) );
assert(io_buf->end - io_buf->begin >= 0);
size_t io_buf_len = (size_t)(io_buf->end - io_buf->begin);
reverse_bits(io_buf->begin, io_buf_len );
upsdebug_hex(3, "\t\t--> payload", io_buf->begin, (io_buf->end - io_buf->begin));
upsdebug_hex(3, "\t\t--> payload", io_buf->begin, io_buf_len);
return 0; /* all ok */
}
@ -648,7 +674,11 @@ static void ser_disable_flow_control (void)
tcgetattr (upsfd, &tio);
tio.c_iflag &= ~ (IXON | IXOFF);
/* Clumsy rewrite of a one-liner
* tio.c_iflag &= ~ (IXON | IXOFF);
* to avoid type conversion warnings */
tcflag_t x = (IXON | IXOFF);
tio.c_iflag &= ~ x;
tio.c_cc[VSTART] = _POSIX_VDISABLE;
tio.c_cc[VSTOP] = _POSIX_VDISABLE;
@ -672,17 +702,20 @@ static void flush_rx_queue()
*/
static int tx(const char *dmsg, /*const*/ raw_data_t frame)
{
int err;
ssize_t err;
upsdebug_ascii(3, dmsg, frame.begin, (frame.end - frame.begin));
assert(frame.end - frame.begin >= 0);
size_t frame_len = (size_t)(frame.end - frame.begin);
err = ser_send_buf(upsfd, frame.begin, (frame.end - frame.begin) );
upsdebug_ascii(3, dmsg, frame.begin, frame_len);
err = ser_send_buf(upsfd, frame.begin, frame_len );
if (err==-1) {
upslogx(LOG_ERR, "failed to send frame to PRS: %s", strerror(errno));
return -1;
}
if (err != (frame.end - frame.begin)) {
if (err != (ssize_t)frame_len) {
upslogx(LOG_ERR, "sent incomplete frame to PRS");
return -1;
}
@ -712,7 +745,7 @@ static void io_new_transaction(int timeout)
* @return -1 (error) 0 (timeout) >0 (got it)
*
*/
static int get_char(char *ch)
static ssize_t get_char(char *ch)
{
time_t now = time(NULL);
long rx_timeout;
@ -734,7 +767,7 @@ static int get_char(char *ch)
* @return -1 (error) 0 (timeout) >0 (no. of characters actually read)
*
*/
static int get_buf(byte_t *buf, size_t len)
static ssize_t get_buf(byte_t *buf, size_t len)
{
time_t now = time(NULL);
long rx_timeout;
@ -754,7 +787,7 @@ static int get_buf(byte_t *buf, size_t len)
static int scan_for(char c)
{
char in;
int err;
ssize_t err;
while (1) {
err = get_char(&in);
@ -776,7 +809,7 @@ static int scan_for(char c)
*/
static int recv_command_ack()
{
int err;
ssize_t err;
raw_data_t ack;
byte_t ack_buf[8];
@ -798,7 +831,8 @@ static int recv_command_ack()
ack.end += 7;
/* frame constructed - let's verify it */
upsdebug_ascii(3, "rx (ack):\t\t", ack.begin, (ack.end - ack.begin));
assert (ack.end - ack.begin >= 0);
upsdebug_ascii(3, "rx (ack):\t\t", ack.begin, (size_t)(ack.end - ack.begin));
/* generic layout */
err = comli_check_frame(ack);
@ -821,11 +855,12 @@ static int recv_command_ack()
*/
static int recv_register_data(io_head_t *io, raw_data_t *io_buf)
{
int err, ret;
ssize_t err;
int ret;
raw_data_t reply_head;
raw_data_t reply;
byte_t reply_head_buf[11];
byte_t reply_head_buf[11];
/* 1: STX */
err = scan_for(STX);
@ -843,7 +878,8 @@ static int recv_register_data(io_head_t *io, raw_data_t *io_buf)
reply_head.end += 10;
upsdebug_ascii(3, "rx (head):\t", reply_head.begin, (reply_head.end - reply_head.begin));
assert (reply_head.end - reply_head.begin >= 0);
upsdebug_ascii(3, "rx (head):\t", reply_head.begin, (size_t)(reply_head.end - reply_head.begin));
/* 3: check header, extract IO info */
@ -855,18 +891,21 @@ static int recv_register_data(io_head_t *io, raw_data_t *io_buf)
reply_head.begin -= 1; /* restore STX */
upsdebugx(4, "\t\t--> addr: 0x%x len: 0x%x", io->addr, io->len);
upsdebugx(4, "\t\t--> addr: 0x%zx len: 0x%zx", io->addr, io->len);
/* 4: allocate space for full reply and copy header there */
reply = raw_xmalloc(11/*head*/ + io->len/*data*/ + 2/*ETX BCC*/);
memcpy(reply.end, reply_head.begin, (reply_head.end - reply_head.begin));
reply.end += (reply_head.end - reply_head.begin);
assert (reply_head.end - reply_head.begin >= 0);
size_t reply_head_len = (size_t)(reply_head.end - reply_head.begin);
memcpy(reply.end, reply_head.begin, reply_head_len);
reply.end += reply_head_len;
/* 5: receive tail of the frame */
err = get_buf(reply.end, io->len + 2);
if (err!=(int)(io->len+2)) {
upsdebugx(4, "rx_tail failed, err=%i (!= %i)", err, io->len+2);
upsdebugx(4, "rx_tail failed, err=%zi (!= %zi)", err, io->len+2);
ret = -1; goto out;
}
@ -874,7 +913,8 @@ static int recv_register_data(io_head_t *io, raw_data_t *io_buf)
/* frame constructed, let's verify it */
upsdebug_ascii(3, "rx (head+data):\t", reply.begin, (reply.end - reply.begin));
assert (reply.end - reply.begin >= 0);
upsdebug_ascii(3, "rx (head+data):\t", reply.begin, (size_t)(reply.end - reply.begin));
/* generic layout */
err = comli_check_frame(reply);
@ -932,7 +972,7 @@ static int al175_do(byte_t cmd, byte_t subcmd, uint16_t pr1, uint16_t pr2, uint1
* 'READ REGISTER'
*
*/
static int al175_read(byte_t *dst, unsigned addr, size_t count)
static int al175_read(byte_t *dst, size_t addr, size_t count)
{
int err;
raw_data_t REQ_frame;
@ -960,13 +1000,13 @@ static int al175_read(byte_t *dst, unsigned addr, size_t count)
if (err==-1)
return -1;
if ((rx_data.end - rx_data.begin) != (int)count)
if ((rx_data.end - rx_data.begin) < 0 ||
(size_t)(rx_data.end - rx_data.begin) != count)
return -1;
if ( (io.addr != addr) || (io.len != count) ) {
upsdebugx(3, "%s: io_head mismatch\t(%x,%x != %x,%x)",
__func__, io.addr, io.len, addr,
(unsigned int)count);
upsdebugx(3, "%s: io_head mismatch\t(%zx,%zx != %zx,%zx)",
__func__, io.addr, io.len, addr, count);
return -1;
}
@ -984,8 +1024,8 @@ static int al175_read(byte_t *dst, unsigned addr, size_t count)
* see 8. ACTIVATE COMMANDS
*/
typedef int mm_t; /* minutes */
typedef int VV_t; /* voltage */
typedef uint16_t mm_t; /* minutes */
typedef uint16_t VV_t; /* voltage */
#define Z1 , 0
#define Z2 , 0, 0
@ -993,10 +1033,30 @@ typedef int VV_t; /* voltage */
#define ACT int
/* Declare to keep compiler happy even if some routines below are not used currently */
ACT TOGGLE_PRS_ONOFF (void);
ACT CANCEL_BOOST (void);
ACT STOP_BATTERY_TEST (void);
ACT START_BATTERY_TEST (VV_t EndVolt, mm_t Minutes);
ACT SET_FLOAT_VOLTAGE (VV_t v);
ACT SET_BOOST_VOLTAGE (VV_t v);
ACT SET_HIGH_BATTERY_LIMIT (VV_t Vhigh);
ACT SET_LOW_BATTERY_LIMIT (VV_t Vlow);
ACT SET_DISCONNECT_LEVEL_AND_DELAY (VV_t level, mm_t delay);
ACT RESET_ALARMS (void);
ACT CHANGE_COMM_PROTOCOL (void);
ACT SET_VOLTAGE_AT_ZERO_T (VV_t v);
ACT SET_SLOPE_AT_ZERO_T (VV_t mv_per_degree);
ACT SET_MAX_TCOMP_VOLTAGE (VV_t v);
ACT SET_MIN_TCOMP_VOLTAGE (VV_t v);
ACT SWITCH_TEMP_COMP (uint16_t on);
ACT SWITCH_SYM_ALARM (void);
/* Implement */
ACT TOGGLE_PRS_ONOFF () { return al175_do(0x81, 0x80 Z3); }
ACT CANCEL_BOOST () { return al175_do(0x82, 0x80 Z3); }
ACT STOP_BATTERY_TEST () { return al175_do(0x83, 0x80 Z3); }
ACT START_BATTERY_TEST (VV_t EndVolt, unsigned Minutes)
ACT START_BATTERY_TEST (VV_t EndVolt, mm_t Minutes)
{ return al175_do(0x83, 0x81, EndVolt, Minutes Z1); }
ACT SET_FLOAT_VOLTAGE (VV_t v) { return al175_do(0x87, 0x80, v Z2); }
@ -1016,7 +1076,7 @@ ACT SET_SLOPE_AT_ZERO_T (VV_t mv_per_degree)
ACT SET_MAX_TCOMP_VOLTAGE (VV_t v) { return al175_do(0x8a, 0x82, v Z2); }
ACT SET_MIN_TCOMP_VOLTAGE (VV_t v) { return al175_do(0x8a, 0x83, v Z2); }
ACT SWITCH_TEMP_COMP (int on) { return al175_do(0x8b, 0x80, on Z2); }
ACT SWITCH_TEMP_COMP (uint16_t on) { return al175_do(0x8b, 0x80, on Z2); }
ACT SWITCH_SYM_ALARM () { return al175_do(0x8c, 0x80 Z3); }
@ -1203,6 +1263,9 @@ void upsdrv_updateinfo(void)
}
void upsdrv_shutdown(void)
__attribute__((noreturn));
void upsdrv_shutdown(void)
{
/* TODO use TOGGLE_PRS_ONOFF for shutdown */
@ -1247,7 +1310,7 @@ static int instcmd(const char *cmdname, const char *extra)
return (!err ? STAT_INSTCMD_HANDLED : STAT_INSTCMD_FAILED);
}
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}

396
drivers/apc-ats-mib.c Executable file → Normal file
View file

@ -24,424 +24,430 @@
#include "apc-ats-mib.h"
#define APC_ATS_MIB_VERSION "0.2"
#define APC_ATS_MIB_VERSION "0.6"
#define APC_ATS_SYSOID ".1.3.6.1.4.1.318.1.3.11"
#define APC_ATS_OID_MODEL_NAME ".1.3.6.1.4.1.318.1.1.8.1.5.0"
static info_lkp_t ats_sensitivity_info[] = {
{ 1, "high" },
{ 2, "low" },
{ 0, NULL }
static info_lkp_t apc_ats_sensitivity_info[] = {
{ 1, "high", NULL, NULL },
{ 2, "low", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ats_output_status_info[] = {
{ 1, "OFF" }, /* fail */
{ 2, "OL" }, /* ok */
{ 0, NULL }
static info_lkp_t apc_ats_output_status_info[] = {
{ 1, "OFF", NULL, NULL }, /* fail */
{ 2, "OL", NULL, NULL }, /* ok */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ats_outletgroups_name_info[] = {
{ 1, "total" },
{ 2, "bank1" },
{ 3, "bank2" },
{ 0, NULL }
static info_lkp_t apc_ats_outletgroups_name_info[] = {
{ 1, "total", NULL, NULL },
{ 2, "bank1", NULL, NULL },
{ 3, "bank2", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ats_outletgroups_status_info[] = {
{ 1, "OL" }, /* normal */
{ 2, "" }, /* lowload */
{ 3, "" }, /* nearoverload */
{ 4, "OVER" }, /* overload */
{ 0, NULL }
static info_lkp_t apc_ats_outletgroups_status_info[] = {
{ 1, "OL", NULL, NULL }, /* normal */
{ 2, "", NULL, NULL }, /* lowload */
{ 3, "", NULL, NULL }, /* nearoverload */
{ 4, "OVER", NULL, NULL }, /* overload */
{ 0, NULL, NULL, NULL }
};
/* APC ATS Snmp2NUT lookup table */
static snmp_info_t apc_ats_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device collection */
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* ats2IdentManufacturer.0 = STRING: EATON */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "APC", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "APC", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* atsIdentModelNumber.0 = STRING: "AP7724" */
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.5.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, APC_ATS_OID_MODEL_NAME, NULL, SU_FLAG_OK, NULL },
/* FIXME: RFC for device.firmware! */
/* atsIdentHardwareRev.0 = STRING: "R01" */
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.1.0", NULL, SU_FLAG_OK, NULL },
/* FIXME: RFC for device.firmware.aux! */
/* atsIdentFirmwareRev.0 = STRING: "3.0.5" */
{ "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.2.0", NULL, SU_FLAG_OK, NULL },
/* atsIdentFirmwareDate.0 = STRING: "09/13/11" */
/*{ "unmapped.atsIdentFirmwareDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.3.0", NULL, SU_FLAG_OK, NULL, NULL },*/
/*{ "unmapped.atsIdentFirmwareDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.3.0", NULL, SU_FLAG_OK, NULL },*/
/* atsIdentSerialNumber.0 = STRING: "5A1516T15268" */
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.6.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.6.0", NULL, SU_FLAG_OK, NULL },
/* FIXME: RFC for device.mfr.date! */
/* atsIdentDateOfManufacture.0 = STRING: "04/18/2015" */
{ "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.4.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.4.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigProductName.0 = STRING: "m-ups-04" */
{ "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.4.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.4.1.0", NULL, SU_FLAG_OK, NULL },
/* Input collection */
/* atsIdentNominalLineVoltage.0 = INTEGER: 230 */
{ "input.voltage.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.7.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.voltage.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.7.0", NULL, SU_FLAG_OK, NULL },
/* atsIdentNominalLineFrequency.0 = INTEGER: 50 */
{ "input.frequency.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.8.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.frequency.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.8.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusSelectedSource.0 = INTEGER: sourceB(2) */
{ "input.source", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.source", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.2.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigPreferredSource.0 = INTEGER: sourceB(2) */
{ "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.318.1.1.8.4.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.318.1.1.8.4.2.0", NULL, SU_FLAG_OK, NULL },
/* atsInputVoltage.1.1.1 = INTEGER: 216 */
{ "input.1.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.1.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputVoltage.2.1.1 = INTEGER: 215 */
{ "input.2.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.3.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.2.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.3.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputFrequency.1 = INTEGER: 50 */
{ "input.1.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.1.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* atsInputFrequency.2 = INTEGER: 50 */
{ "input.2.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.4.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.2.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.4.2", NULL, SU_FLAG_OK, NULL },
/* atsConfigVoltageSensitivity.0 = INTEGER: high(1) */
{ "input.sensitivity", ST_FLAG_RW, 1, ".1.3.6.1.4.1.318.1.1.8.4.4.0", NULL, SU_FLAG_OK, &ats_sensitivity_info[0], NULL },
{ "input.sensitivity", ST_FLAG_RW, 1, ".1.3.6.1.4.1.318.1.1.8.4.4.0", NULL, SU_FLAG_OK, &apc_ats_sensitivity_info[0] },
/* FIXME: RFC for input.count! */
/* atsNumInputs.0 = INTEGER: 2 */
{ "input.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.1.0", NULL, SU_FLAG_OK, NULL },
/* Output collection */
/* atsOutputFrequency.1 = INTEGER: 50 */
{ "output.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "output.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankOutputVoltage.1 = INTEGER: 215 */
{ "output.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.6.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "output.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.6.1", NULL, SU_FLAG_OK, NULL },
/* UPS collection */
/* FIXME: RFC for device.status! */
/* atsStatusVoltageOutStatus.0 = INTEGER: ok(2) */
{ "ups.status", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.15.0", NULL, SU_FLAG_OK, &ats_output_status_info[0], NULL },
{ "ups.status", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.15.0", NULL, SU_FLAG_OK, &apc_ats_output_status_info[0] },
/* Outlet groups collection */
/* Note: prefer the OutputBank data to the ConfigBank ones */
/* atsConfigBankTableSize.0 = INTEGER: 3 */
/*{ "outlet.group.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.13.0", NULL, SU_FLAG_OK, NULL, NULL },*/
/*{ "outlet.group.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.13.0", NULL, SU_FLAG_OK, NULL },*/
/* atsOutputBankTableSize.0 = INTEGER: 3 */
{ "outlet.group.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.4.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "outlet.group.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.4.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankTableIndex.%i = INTEGER: %i */
/*{ "outlet.group.%i.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.4.14.1.1.%i", NULL, SU_FLAG_OK, NULL, NULL },*/
/*{ "outlet.group.%i.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.4.14.1.1.%i", NULL, SU_FLAG_OK, NULL },*/
/* atsOutputBankTableIndex.%i = INTEGER: %i */
{ "outlet.group.%i.id", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.1.%i", NULL, SU_FLAG_OK | SU_OUTLET_GROUP, NULL, NULL },
{ "outlet.group.%i.id", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.1.%i", NULL, SU_FLAG_OK | SU_OUTLET_GROUP, NULL },
/* atsConfigBank.%i = INTEGER: total(1) */
/*{ "outlet.group.%i.name", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.2.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &ats_group_name_info[0], NULL },*/
/*{ "outlet.group.%i.name", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.2.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &apc_ats_group_name_info[0] },*/
/* atsOutputBank.1 = INTEGER: total(1) */
{ "outlet.group.%i.name", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.3.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &ats_outletgroups_name_info[0], NULL },
{ "outlet.group.%i.name", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.3.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &apc_ats_outletgroups_name_info[0] },
/* atsOutputBankCurrent.%i = Gauge32: 88 */
{ "outlet.group.%i.current", 0, 0.1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.4.%i", NULL, SU_OUTLET_GROUP, NULL, NULL },
{ "outlet.group.%i.current", 0, 0.1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.4.%i", NULL, SU_OUTLET_GROUP, NULL },
/* atsOutputBankState.%i = INTEGER: normal(1) */
{ "outlet.group.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.5.%i", NULL, SU_OUTLET_GROUP, &ats_outletgroups_status_info[0], NULL },
{ "outlet.group.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.5.%i", NULL, SU_OUTLET_GROUP, &apc_ats_outletgroups_status_info[0] },
/* atsOutputBankOutputVoltage.%i = INTEGER: 215 */
{ "outlet.group.%i.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.6.%i", NULL, SU_OUTLET_GROUP, NULL, NULL },
{ "outlet.group.%i.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.6.%i", NULL, SU_OUTLET_GROUP, NULL },
/* atsOutputBankPower.1 = INTEGER: 1883 */
{ "outlet.group.%i.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.15.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
{ "outlet.group.%i.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.15.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL },
#if 0 /* FIXME: Remaining data to be processed */
/* atsIdentDeviceRating.0 = INTEGER: 32 */
{ "unmapped.atsIdentDeviceRating", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.9.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsIdentDeviceRating", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.9.0", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationNumInputs.0 = INTEGER: 2 */
{ "unmapped.atsCalibrationNumInputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationNumInputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.1.0", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationNumInputPhases.0 = INTEGER: 1 */
{ "unmapped.atsCalibrationNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.2.0", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationInputTableIndex.1.1.1 = INTEGER: 1 */
{ "unmapped.atsCalibrationInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationInputTableIndex.2.1.1 = INTEGER: 2 */
{ "unmapped.atsCalibrationInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationInputPhaseTableIndex.1.1.1 = INTEGER: 1 */
{ "unmapped.atsCalibrationInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationInputPhaseTableIndex.2.1.1 = INTEGER: 1 */
{ "unmapped.atsCalibrationInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.2.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.2.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsLineVoltageCalibrationFactor.1.1.1 = INTEGER: 487 */
{ "unmapped.atsLineVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsLineVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsLineVoltageCalibrationFactor.2.1.1 = INTEGER: 488 */
{ "unmapped.atsLineVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.3.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsLineVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.3.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltages.0 = INTEGER: 5 */
{ "unmapped.atsCalibrationPowerSupplyVoltages", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltages", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.1.0", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltageTableIndex.1 = INTEGER: 1 */
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltageTableIndex.2 = INTEGER: 2 */
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltageTableIndex.3 = INTEGER: 3 */
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.3", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltageTableIndex.4 = INTEGER: 4 */
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.4", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.4", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltageTableIndex.5 = INTEGER: 5 */
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.5", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.5", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltage.1 = INTEGER: powerSupply24V(1) */
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltage.2 = INTEGER: powerSupply12V(2) */
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltage.3 = INTEGER: powerSupply(3) */
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.3", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltage.4 = INTEGER: powerSupply24VSourceB(4) */
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.4", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.4", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationPowerSupplyVoltage.5 = INTEGER: powerSupplyMinus12V(5) */
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.5", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.5", NULL, SU_FLAG_OK, NULL },
/* atsPowerSupplyVoltageCalibrationFactor.1 = INTEGER: 521 */
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* atsPowerSupplyVoltageCalibrationFactor.2 = INTEGER: 1076 */
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* atsPowerSupplyVoltageCalibrationFactor.3 = INTEGER: 2560 */
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.3", NULL, SU_FLAG_OK, NULL },
/* atsPowerSupplyVoltageCalibrationFactor.4 = INTEGER: 521 */
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.4", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.4", NULL, SU_FLAG_OK, NULL },
/* atsPowerSupplyVoltageCalibrationFactor.5 = INTEGER: 975 */
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.5", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.5", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationNumOutputs.0 = INTEGER: 1 */
{ "unmapped.atsCalibrationNumOutputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationNumOutputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.1.0", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationNumOutputPhases.0 = INTEGER: 1 */
{ "unmapped.atsCalibrationNumOutputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationNumOutputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.2.0", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationOutputTableIndex.1.phase1.1 = INTEGER: 1 */
{ "unmapped.atsCalibrationOutputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationOutputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsCalibrationOutputPhasesTableIndex.1.phase1.1 = INTEGER: phase1(1) */
{ "unmapped.atsCalibrationOutputPhasesTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsCalibrationOutputPhasesTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputCurrentCalibrationFactor.1.phase1.1 = INTEGER: 487 */
{ "unmapped.atsOutputCurrentCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputCurrentCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsControlResetATS.0 = INTEGER: none(1) */
{ "unmapped.atsControlResetATS", 0, 1, ".1.3.6.1.4.1.318.1.1.8.3.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsControlResetATS", 0, 1, ".1.3.6.1.4.1.318.1.1.8.3.1.0", NULL, SU_FLAG_OK, NULL },
/* atsControlClearAllAlarms.0 = INTEGER: -1 */
{ "unmapped.atsControlClearAllAlarms", 0, 1, ".1.3.6.1.4.1.318.1.1.8.3.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsControlClearAllAlarms", 0, 1, ".1.3.6.1.4.1.318.1.1.8.3.2.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigFrontPanelLockout.0 = INTEGER: enableFrontPanel(2) */
{ "unmapped.atsConfigFrontPanelLockout", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.3.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigFrontPanelLockout", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.3.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigTransferVoltageRange.0 = INTEGER: medium(2) */
{ "unmapped.atsConfigTransferVoltageRange", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.5.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigTransferVoltageRange", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.5.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigCurrentLimit.0 = INTEGER: 32 */
{ "unmapped.atsConfigCurrentLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.6.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigCurrentLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.6.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigResetValues.0 = INTEGER: -1 */
{ "unmapped.atsConfigResetValues", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.7.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigResetValues", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.7.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigLineVRMS.0 = INTEGER: 230 */
{ "unmapped.atsConfigLineVRMS", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.8.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigLineVRMS", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.8.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigLineVRMSNarrowLimit.0 = INTEGER: 16 */
{ "unmapped.atsConfigLineVRMSNarrowLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.9.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigLineVRMSNarrowLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.9.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigLineVRMSMediumLimit.0 = INTEGER: 23 */
{ "unmapped.atsConfigLineVRMSMediumLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.10.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigLineVRMSMediumLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.10.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigLineVRMSWideLimit.0 = INTEGER: 30 */
{ "unmapped.atsConfigLineVRMSWideLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.11.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigLineVRMSWideLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.11.0", NULL, SU_FLAG_OK, NULL },
/* atsConfigFrequencyDeviation.0 = INTEGER: two(2) */
{ "unmapped.atsConfigFrequencyDeviation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.12.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigFrequencyDeviation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.12.0", NULL, SU_FLAG_OK, NULL },
/* Outlet groups collection */
/* atsConfigBankLowLoadThreshold.1 = INTEGER: 0 */
{ "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.1", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankLowLoadThreshold.2 = INTEGER: 0 */
{ "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.2", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankLowLoadThreshold.3 = INTEGER: 0 */
{ "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.3", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankNearOverLoadThreshold.1 = INTEGER: 28 */
{ "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.1", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankNearOverLoadThreshold.2 = INTEGER: 12 */
{ "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.2", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankNearOverLoadThreshold.3 = INTEGER: 12 */
{ "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.3", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankOverLoadThreshold.1 = INTEGER: 32 */
{ "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.1", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankOverLoadThreshold.2 = INTEGER: 16 */
{ "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.2", NULL, SU_FLAG_OK, NULL },
/* atsConfigBankOverLoadThreshold.3 = INTEGER: 16 */
{ "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.3", NULL, SU_FLAG_OK, NULL },
/* atsConfigPhaseTableSize.0 = INTEGER: 0 */
{ "unmapped.atsConfigPhaseTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.15.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsConfigPhaseTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.15.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusCommStatus.0 = INTEGER: atsCommEstablished(2) */
{ "unmapped.atsStatusCommStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusCommStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.1.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusRedundancyState.0 = INTEGER: atsFullyRedundant(2) */
{ "unmapped.atsStatusRedundancyState", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.3.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusRedundancyState", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.3.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusOverCurrentState.0 = INTEGER: atsCurrentOK(2) */
{ "unmapped.atsStatusOverCurrentState", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.4.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusOverCurrentState", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.4.0", NULL, SU_FLAG_OK, NULL },
/* atsStatus5VPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */
{ "unmapped.atsStatus5VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.5.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatus5VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.5.0", NULL, SU_FLAG_OK, NULL },
/* atsStatus24VPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */
{ "unmapped.atsStatus24VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.6.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatus24VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.6.0", NULL, SU_FLAG_OK, NULL },
/* atsStatus24VSourceBPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */
{ "unmapped.atsStatus24VSourceBPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.7.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatus24VSourceBPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.7.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusPlus12VPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */
{ "unmapped.atsStatusPlus12VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.8.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusPlus12VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.8.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusMinus12VPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */
{ "unmapped.atsStatusMinus12VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.9.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusMinus12VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.9.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusSwitchStatus.0 = INTEGER: ok(2) */
{ "unmapped.atsStatusSwitchStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.10.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusSwitchStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.10.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusFrontPanel.0 = INTEGER: unlocked(2) */
{ "unmapped.atsStatusFrontPanel", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.11.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusFrontPanel", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.11.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusSourceAStatus.0 = INTEGER: ok(2) */
{ "unmapped.atsStatusSourceAStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.12.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusSourceAStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.12.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusSourceBStatus.0 = INTEGER: ok(2) */
{ "unmapped.atsStatusSourceBStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.13.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusSourceBStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.13.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusPhaseSyncStatus.0 = INTEGER: inSync(1) */
{ "unmapped.atsStatusPhaseSyncStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.14.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusPhaseSyncStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.14.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusHardwareStatus.0 = INTEGER: ok(2) */
{ "unmapped.atsStatusHardwareStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.16.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusHardwareStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.16.0", NULL, SU_FLAG_OK, NULL },
/* atsStatusResetMaxMinValues.0 = INTEGER: -1 */
{ "unmapped.atsStatusResetMaxMinValues", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.2.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsStatusResetMaxMinValues", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.2.1.0", NULL, SU_FLAG_OK, NULL },
/* atsInputTableIndex.1 = INTEGER: 1 */
{ "unmapped.atsInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputTableIndex.2 = INTEGER: 2 */
{ "unmapped.atsInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* atsNumInputPhases.1 = INTEGER: 1 */
{ "unmapped.atsNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* atsNumInputPhases.2 = INTEGER: 1 */
{ "unmapped.atsNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* atsInputVoltageOrientation.1 = INTEGER: singlePhase(2) */
{ "unmapped.atsInputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* atsInputVoltageOrientation.2 = INTEGER: singlePhase(2) */
{ "unmapped.atsInputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* atsInputType.1 = INTEGER: main(2) */
{ "unmapped.atsInputType", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.5.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputType", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.5.1", NULL, SU_FLAG_OK, NULL },
/* atsInputType.2 = INTEGER: main(2) */
{ "unmapped.atsInputType", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.5.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputType", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.5.2", NULL, SU_FLAG_OK, NULL },
/* atsInputName.1 = STRING: "Source A" */
{ "unmapped.atsInputName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.6.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.6.1", NULL, SU_FLAG_OK, NULL },
/* atsInputName.2 = STRING: "Source B" */
{ "unmapped.atsInputName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.6.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.6.2", NULL, SU_FLAG_OK, NULL },
/* atsInputPhaseTableIndex.1.1.1 = INTEGER: 1 */
{ "unmapped.atsInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputPhaseTableIndex.2.1.1 = INTEGER: 2 */
{ "unmapped.atsInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputPhaseIndex.1.1.1 = INTEGER: 1 */
{ "unmapped.atsInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputPhaseIndex.2.1.1 = INTEGER: 1 */
{ "unmapped.atsInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.2.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.2.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMaxVoltage.1.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMaxVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.4.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMaxVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.4.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMaxVoltage.2.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMaxVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.4.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMaxVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.4.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMinVoltage.1.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMinVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.5.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMinVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.5.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMinVoltage.2.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMinVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.5.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMinVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.5.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputCurrent.1.1.1 = INTEGER: -1 */
{ "unmapped.atsInputCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.6.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.6.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputCurrent.2.1.1 = INTEGER: -1 */
{ "unmapped.atsInputCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.6.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.6.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMaxCurrent.1.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.7.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.7.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMaxCurrent.2.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.7.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.7.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMinCurrent.1.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.8.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.8.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMinCurrent.2.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.8.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.8.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputPower.1.1.1 = INTEGER: -1 */
{ "unmapped.atsInputPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.9.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.9.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputPower.2.1.1 = INTEGER: -1 */
{ "unmapped.atsInputPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.9.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.9.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMaxPower.1.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.10.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.10.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMaxPower.2.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.10.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.10.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMinPower.1.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.11.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.11.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsInputMinPower.2.1.1 = INTEGER: -1 */
{ "unmapped.atsInputMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.11.2.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsInputMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.11.2.1.1", NULL, SU_FLAG_OK, NULL },
/* atsNumOutputs.0 = INTEGER: 1 */
{ "unmapped.atsNumOutputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsNumOutputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.1.0", NULL, SU_FLAG_OK, NULL },
/* atsOutputTableIndex.1 = INTEGER: 1 */
{ "unmapped.atsOutputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* atsNumOutputPhases.1 = INTEGER: 1 */
{ "unmapped.atsNumOutputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsNumOutputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputVoltageOrientation.1 = INTEGER: singlePhase(2) */
{ "unmapped.atsOutputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputPhase.1 = INTEGER: phase1(1) */
{ "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputPhase.2 = INTEGER: phase1(1) */
{ "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputPhase.3 = INTEGER: phase1(1) */
{ "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxCurrent.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxCurrent.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxCurrent.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinCurrent.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinCurrent.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinCurrent.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankLoad.1 = INTEGER: 1883 */
{ "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankLoad.2 = INTEGER: 984 */
{ "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankLoad.3 = INTEGER: 898 */
{ "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxLoad.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxLoad.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxLoad.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinLoad.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinLoad.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinLoad.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankPercentLoad.1 = INTEGER: 25 */
{ "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankPercentLoad.2 = INTEGER: 13 */
{ "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankPercentLoad.3 = INTEGER: 12 */
{ "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPercentLoad.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPercentLoad.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPercentLoad.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPercentLoad.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPercentLoad.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPercentLoad.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPower.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPower.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPower.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPower.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPower.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPower.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankPercentPower.1 = INTEGER: 25 */
{ "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankPercentPower.2 = INTEGER: 13 */
{ "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankPercentPower.3 = INTEGER: 12 */
{ "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPercentPower.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPercentPower.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMaxPercentPower.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.3", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPercentPower.1 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.1", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPercentPower.2 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.2", NULL, SU_FLAG_OK, NULL },
/* atsOutputBankMinPercentPower.3 = INTEGER: -1 */
{ "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.3", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.3", NULL, SU_FLAG_OK, NULL },
#endif /* 0 */
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t apc_ats = { "apc_ats", APC_ATS_MIB_VERSION, NULL, NULL, apc_ats_mib, APC_ATS_SYSOID };
mib2nut_info_t apc_ats = { "apc_ats", APC_ATS_MIB_VERSION, NULL, APC_ATS_OID_MODEL_NAME, apc_ats_mib, APC_ATS_SYSOID, NULL };

0
drivers/apc-ats-mib.h Executable file → Normal file
View file

View file

@ -27,21 +27,22 @@
*/
#include "main.h" /* for getval() */
#include "hidparser.h" /* for FindObject_with_ID_Node() */
#include "usbhid-ups.h"
#include "apc-hid.h"
#include "usb-common.h"
#define APC_HID_VERSION "APC HID 0.96"
#define APC_HID_VERSION "APC HID 0.98"
/* APC */
#define APC_VENDORID 0x051d
/* Tweaks */
char * tweak_max_report[] = {
static char * tweak_max_report[] = {
/* Back-UPS ES 700 does NOT overflow. */
/* Back-UPS ES 725 does NOT overflow. */
/* Back-UPS ES 525 overflows on ReportID 0x0c
(UPS.PowerSummary.RemainingCapacity).*/
(UPS.PowerSummary.RemainingCapacity). */
"Back-UPS ES 525",
/* Back-UPS CS 650 overflows on ReportID 0x46 */
"Back-UPS CS",
@ -50,7 +51,10 @@ char * tweak_max_report[] = {
/* Don't use interrupt pipe on 5G models (used by proprietary protocol) */
static void *disable_interrupt_pipe(USBDevice_t *device)
{
NUT_UNUSED_VARIABLE(device);
if (use_interrupt_pipe == TRUE) {
/* FIXME? Suggest data from "device" to help the setup below? */
upslogx(LOG_INFO, "interrupt pipe disabled (add 'pollonly' flag to 'ups.conf' to get rid of this message)");
use_interrupt_pipe= FALSE;
}
@ -92,7 +96,7 @@ static usb_device_id_t apc_usb_device_table[] = {
{ USB_DEVICE(APC_VENDORID, 0x0003), disable_interrupt_pipe },
/* Terminating entry */
{ -1, -1, NULL }
{ 0, 0, NULL }
};
/* returns statically allocated string - must not use it again before
@ -124,53 +128,69 @@ static const char *apc_date_conversion_fun(double value)
return buf;
}
info_lkp_t apc_date_conversion[] = {
{ 0, NULL, apc_date_conversion_fun }
static double apc_date_conversion_reverse(const char *date_string)
{
int year, month, day;
long date;
sscanf(date_string, "%04d/%02d/%02d", &year, &month, &day);
if(year >= 2070 || month > 12 || day > 31)
return 0;
year %= 100;
date = ((year / 10 & 0x0F) << 4) + (year % 10);
date += ((month / 10 & 0x0F) << 20) + ((month % 10) << 16);
date += ((day / 10 & 0x0F) << 12) + ((day % 10) << 8);
return (double) date;
}
static info_lkp_t apc_date_conversion[] = {
{ 0, NULL, apc_date_conversion_fun, apc_date_conversion_reverse }
};
/* This was determined empirically from observing a BackUPS LS 500 */
static info_lkp_t apcstatusflag_info[] = {
{ 8, "!off", NULL }, /* Normal operation */
{ 16, "!off", NULL }, /* This occurs briefly during power-on, and corresponds to status 'DISCHRG'. */
{ 0, "off", NULL },
{ 0, NULL, NULL }
{ 8, "!off", NULL, NULL }, /* Normal operation */
{ 16, "!off", NULL, NULL }, /* This occurs briefly during power-on, and corresponds to status 'DISCHRG'. */
{ 0, "off", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* Reason of the last battery transfer (from apcupsd) */
static info_lkp_t apc_linefailcause_vrange_info[] = {
{ 1, "vrange", NULL }, /* Low line voltage */
{ 2, "vrange", NULL }, /* High line voltage */
{ 4, "vrange", NULL }, /* notch, spike, or blackout */
{ 8, "vrange", NULL }, /* Notch or blackout */
{ 9, "vrange", NULL }, /* Spike or blackout */
{ 0, "!vrange", NULL }, /* No transfers have ocurred */
{ 0, NULL, NULL }
{ 1, "vrange", NULL, NULL }, /* Low line voltage */
{ 2, "vrange", NULL, NULL }, /* High line voltage */
{ 4, "vrange", NULL, NULL }, /* notch, spike, or blackout */
{ 8, "vrange", NULL, NULL }, /* Notch or blackout */
{ 9, "vrange", NULL, NULL }, /* Spike or blackout */
{ 0, "!vrange", NULL, NULL }, /* No transfers have ocurred */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t apc_linefailcause_frange_info[] = {
{ 7, "frange", NULL }, /* Input frequency out of range */
{ 0, "!frange", NULL }, /* No transfers have ocurred */
{ 0, NULL, NULL }
{ 7, "frange", NULL, NULL }, /* Input frequency out of range */
{ 0, "!frange", NULL, NULL }, /* No transfers have ocurred */
{ 0, NULL, NULL, NULL }
};
#if 0
/* these input.transfer.reason can't be mapped at the moment... */
{ 3, "ripple", NULL }, /* Ripple */
{ 5, "self test", NULL }, /* Self Test or Discharge Calibration commanded
* Test usage, front button, or 2 week self test */
{ 6, "forced", NULL }, /* DelayBeforeShutdown or APCDelayBeforeShutdown */
{ 10, "forced", NULL }, /* Graceful shutdown by accessories */
{ 11, "self test", NULL }, /* Test usage invoked */
{ 12, "self test", NULL }, /* Front button initiated self test */
{ 13, "self test", NULL }, /* 2 week self test */
{ 0, NULL, NULL }
{ 3, "ripple", NULL, NULL }, /* Ripple */
{ 5, "self test", NULL, NULL }, /* Self Test or Discharge Calibration commanded
* Test usage, front button, or 2 week self test */
{ 6, "forced", NULL, NULL }, /* DelayBeforeShutdown or APCDelayBeforeShutdown */
{ 10, "forced", NULL, NULL }, /* Graceful shutdown by accessories */
{ 11, "self test", NULL, NULL }, /* Test usage invoked */
{ 12, "self test", NULL, NULL }, /* Front button initiated self test */
{ 13, "self test", NULL, NULL }, /* 2 week self test */
{ 0, NULL, NULL, NULL }
#endif
static info_lkp_t apc_sensitivity_info[] = {
{ 0, "low", NULL },
{ 1, "medium", NULL },
{ 2, "high", NULL },
{ 0, NULL, NULL }
{ 0, "low", NULL, NULL },
{ 1, "medium", NULL, NULL },
{ 2, "high", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* --------------------------------------------------------------- */
@ -314,7 +334,7 @@ static hid_info_t apc_hid2nut[] = {
{ "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.1f", 0, NULL }, /* Back-UPS 500 */
{ "battery.temperature", 0, 0, "UPS.Battery.Temperature", NULL, "%s", 0, kelvin_celsius_conversion },
{ "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", 0, stringid_conversion },
{ "battery.mfr.date", 0, 0, "UPS.Battery.ManufacturerDate", NULL, "%s", 0, date_conversion },
{ "battery.mfr.date", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Battery.ManufacturerDate", NULL, "%s", HU_FLAG_SEMI_STATIC, date_conversion },
{ "battery.mfr.date", 0, 0, "UPS.PowerSummary.APCBattReplaceDate", NULL, "%s", 0, apc_date_conversion }, /* Back-UPS 500, Back-UPS ES/CyberFort 500 */
{ "battery.date", 0, 0, "UPS.Battery.APCBattReplaceDate", NULL, "%s", 0, apc_date_conversion }, /* Observed values: 0x0 on Back-UPS ES 650, 0x92501 on Back-UPS BF500 whose manufacture date was 2005/01/20 - this makes little sense but at least it's a valid date. */
@ -382,7 +402,7 @@ static hid_info_t apc_hid2nut[] = {
{ "input.transfer.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "input.transfer.high", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "input.sensitivity", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.APCSensitivity", NULL, "%s", HU_FLAG_SEMI_STATIC, apc_sensitivity_info },
/* Output page */
{ "output.voltage", 0, 0, "UPS.Output.Voltage", NULL, "%.1f", 0, NULL },
{ "output.voltage.nominal", 0, 0, "UPS.Output.ConfigVoltage", NULL, "%.1f", 0, NULL },
@ -395,7 +415,7 @@ static hid_info_t apc_hid2nut[] = {
/*
{ "ambient.temperature", 0, 0, "UPS.APCEnvironment.APCProbe2.Temperature", NULL, "%.1f", 0, kelvin_celsius_conversion },
{ "ambient.humidity", 0, 0, "UPS.APCEnvironment.APCProbe2.Humidity", NULL, "%.1f", 0, NULL },
*/
*/
/* instant commands. */
/* test.* split into subset while waiting for extradata support
@ -429,7 +449,7 @@ static hid_info_t apc_hid2nut[] = {
{ "shutdown.reboot", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL },
/* used by APC BackUPS CS */
{ "shutdown.return", 0, 0, "UPS.Output.APCDelayBeforeReboot", NULL, "1", HU_TYPE_CMD, NULL },
{ "beeper.on", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL },
{ "beeper.off", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL },
{ "beeper.enable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL },
@ -496,6 +516,73 @@ static int apc_claim(HIDDevice_t *hd) {
}
}
/* apc_fix_report_desc
*
* The Back-UPS XS 1400U reports incorrect logical min/max values for the
* UPS.Input.ConfigVoltage and UPS.Input.Voltage when operating in a
* 220-240V region. Detect this and fix it.
* This same fix may be applicable to other APC UPS units as well, though
* the report IDs may be different.
*/
static int apc_fix_report_desc(HIDDevice_t *pDev, HIDDesc_t *pDesc_arg) {
HIDData_t *pData;
int res = 0;
int vendorID = pDev->VendorID;
int productID = pDev->ProductID;
if (vendorID != APC_VENDORID || productID != 0x0002) {
return 0;
}
upsdebugx(3, "Attempting Report Descriptor fix for UPS: Vendor: %04x, Product: %04x", vendorID, productID);
/* Look at the High Voltage Transfer logical max value:
* If the HVT logmax is greater than the configured or input voltage limit
* then the configured/input voltage limits are probably incorrect.
* Arbitrarily set the input voltage logical min/max to 0 .. 2*HVT logmax and the
* configured (nominal) input voltage logical max to 255 (it's a single byte value)
* Path: UPS.Input.ConfigVoltage, Type: Feature, ReportID: 0x30, Offset: 0, Size: 8
* Path: UPS.Input.Voltage, Type: Feature, ReportID: 0x31, Offset: 0, Size: 16
* Path: UPS.Input.HighVoltageTransfer, Type: Feature, ReportID: 0x33, Offset: 0, Size: 16
*/
if ((pData=FindObject_with_ID_Node(pDesc_arg, 0x33, USAGE_POW_HIGH_VOLTAGE_TRANSFER))) {
long hvt_logmin = pData->LogMin;
long hvt_logmax = pData->LogMax;
upsdebugx(4, "Report Descriptor: highVoltageTransfer LogMin: %ld LogMax: %ld", hvt_logmin, hvt_logmax);
if ((pData=FindObject_with_ID_Node(pDesc_arg, 0x31, USAGE_POW_VOLTAGE))) {
long voltage_logmin = pData->LogMin;
long voltage_logmax = pData->LogMax;
upsdebugx(4, "Report Descriptor: voltage LogMin: %ld LogMax: %ld",
voltage_logmin, voltage_logmax);
if (hvt_logmax > voltage_logmax) {
pData->LogMin = 0; /* a reasonable lower limit for voltage */
pData->LogMax = hvt_logmax * 2; /* it may be smoking at this point */
upsdebugx(3, "Fixing Report Descriptor. Set voltage LogMin = %ld, LogMax = %ld",
pData->LogMin , pData->LogMax);
res = 1;
}
}
if ((pData=FindObject_with_ID_Node(pDesc_arg, 0x30, USAGE_POW_CONFIG_VOLTAGE))) {
long cvoltage_logmin = pData->LogMin;
long cvoltage_logmax = pData->LogMax;
upsdebugx(4, "Report Descriptor: configVoltage LogMin: %ld LogMax: %ld",
cvoltage_logmin, cvoltage_logmax);
if (hvt_logmax > cvoltage_logmax) {
pData->LogMax = 255;
upsdebugx(3, "Fixing Report Descriptor. Set configVoltage LogMin = %ld, LogMax = %ld",
pData->LogMin , pData->LogMax);
res = 1;
}
}
}
return res;
}
subdriver_t apc_subdriver = {
APC_HID_VERSION,
apc_claim,
@ -504,4 +591,5 @@ subdriver_t apc_subdriver = {
apc_format_model,
apc_format_mfr,
apc_format_serial,
apc_fix_report_desc,
};

View file

@ -1,6 +1,6 @@
/* apc-hid.h - data to monitor APC USB/HID devices with NUT
*
* Copyright (C)
* Copyright (C)
* 2003 - 2005 Arnaud Quette <arnaud.quette@free.fr>
* 2005 John Stamp <kinsayder@hotmail.com>
* 2005 Peter Selinger <selinger@users.sourceforge.net>
@ -31,6 +31,4 @@
extern subdriver_t apc_subdriver;
extern int max_report_size;
#endif /* APC_HID_H */

19
drivers/apc-iem-mib.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef APC_IEM_MIB_H
#define APC_IEM_MIB_H
/*
* FIXME: The below is needed because the main driver body uses this to determine
* whether a conversion from Fahrenheit to Celsius is needed (which really should
* be solved in subdriver specific formatting functions, like we do in usbhid-ups
* This is used in both snmp-ups.c and apc.c logics.
*/
/* IEM ambient variables */
/* IEM: integrated environment monitor probe */
#define APCC_OID_IEM_TEMP ".1.3.6.1.4.1.318.1.1.10.2.3.2.1.4.1"
#define APCC_OID_IEM_TEMP_UNIT ".1.3.6.1.4.1.318.1.1.10.2.3.2.1.5.1"
#define APCC_IEM_FAHRENHEIT 2
#define APCC_OID_IEM_HUMID ".1.3.6.1.4.1.318.1.1.10.2.3.2.1.6.1"
#endif /* APC_IEM_MIB_H */

View file

@ -26,10 +26,14 @@
#include "apc-mib.h"
#define APCC_MIB_VERSION "1.2"
#define APCC_MIB_VERSION "1.6"
#define APC_UPS_DEVICE_MODEL ".1.3.6.1.4.1.318.1.1.1.1.1.1.0"
/* FIXME: Find a better oid_auto_check vs sysOID for this one? */
#define APC_UPS_SYSOID APC_UPS_DEVICE_MODEL
/* Other APC sysOID:
*
*
* examples found on the Net and other sources:
* 'enterprises.apc.products.system.smartUPS.smartUPS700'
* - from fence agents
@ -43,7 +47,7 @@
* .1.3.6.1.4.1.318.1.3.2.8
*/
/* TODO: find the right sysOID for this MIB
/* TODO: find the right sysOID for this MIB
* Ie ".1.3.6.1.4.1.318.1.1.1" or ".1.3.6.1.4.1.318" or? */
/* .1.3.6.1.4.1.318.1.1.1
@ -60,75 +64,75 @@
#define APCC_OID_BATT_STATUS ".1.3.6.1.4.1.318.1.1.1.2.1.1.0"
/* Defines for APCC_OID_BATT_STATUS */
static info_lkp_t apcc_batt_info[] = {
{ 1, "" }, /* unknown */
{ 2, "" }, /* batteryNormal */
{ 3, "LB" }, /* batteryLow */
{ 0, NULL }
{ 1, "", NULL, NULL }, /* unknown */
{ 2, "", NULL, NULL }, /* batteryNormal */
{ 3, "LB", NULL, NULL }, /* batteryLow */
{ 0, NULL, NULL, NULL }
} ;
#define APCC_OID_POWER_STATUS ".1.3.6.1.4.1.318.1.1.1.4.1.1.0"
/* Defines for APCC_OID_POWER_STATUS */
static info_lkp_t apcc_pwr_info[] = {
{ 1, "" }, /* unknown */
{ 2, "OL" }, /* onLine */
{ 3, "OB" }, /* onBattery */
{ 4, "OL BOOST" }, /* onSmartBoost */
{ 5, "OFF" }, /* timedSleeping */
{ 6, "OFF" }, /* softwareBypass */
{ 7, "OFF" }, /* off */
{ 8, "" }, /* rebooting */
{ 9, "BYPASS" }, /* switchedBypass */
{ 10, "BYPASS" }, /* hardwareFailureBypass */
{ 11, "OFF" }, /* sleepingUntilPowerReturn */
{ 12, "OL TRIM" }, /* onSmartTrim */
{ 0, NULL }
{ 1, "", NULL, NULL }, /* unknown */
{ 2, "OL", NULL, NULL }, /* onLine */
{ 3, "OB", NULL, NULL }, /* onBattery */
{ 4, "OL BOOST", NULL, NULL }, /* onSmartBoost */
{ 5, "OFF", NULL, NULL }, /* timedSleeping */
{ 6, "OFF", NULL, NULL }, /* softwareBypass */
{ 7, "OFF", NULL, NULL }, /* off */
{ 8, "", NULL, NULL }, /* rebooting */
{ 9, "BYPASS", NULL, NULL }, /* switchedBypass */
{ 10, "BYPASS", NULL, NULL }, /* hardwareFailureBypass */
{ 11, "OFF", NULL, NULL }, /* sleepingUntilPowerReturn */
{ 12, "OL TRIM", NULL, NULL }, /* onSmartTrim */
{ 0, NULL, NULL, NULL }
} ;
#define APCC_OID_CAL_RESULTS ".1.3.6.1.4.1.318.1.1.1.7.2.6.0"
static info_lkp_t apcc_cal_info[] = {
{ 1, "" }, /* Calibration Successful */
{ 2, "" }, /* Calibration not done, battery capacity below 100% */
{ 3, "CAL" }, /* Calibration in progress */
{ 0, NULL }
{ 1, "", NULL, NULL }, /* Calibration Successful */
{ 2, "", NULL, NULL }, /* Calibration not done, battery capacity below 100% */
{ 3, "CAL", NULL, NULL }, /* Calibration in progress */
{ 0, NULL, NULL, NULL }
};
#define APCC_OID_NEEDREPLBATT ".1.3.6.1.4.1.318.1.1.1.2.2.4.0"
static info_lkp_t apcc_battrepl_info[] = {
{ 1, "" }, /* No battery needs replacing */
{ 2, "RB" }, /* Batteries need to be replaced */
{ 0, NULL }
{ 1, "", NULL, NULL }, /* No battery needs replacing */
{ 2, "RB", NULL, NULL }, /* Batteries need to be replaced */
{ 0, NULL, NULL, NULL }
};
#define APCC_OID_TESTDIAGRESULTS ".1.3.6.1.4.1.318.1.1.1.7.2.3.0"
static info_lkp_t apcc_testdiag_results[] = {
{ 1, "Ok" },
{ 2, "Failed" },
{ 3, "InvalidTest" },
{ 4, "TestInProgress"},
{ 0, NULL }
{ 1, "Ok", NULL, NULL },
{ 2, "Failed", NULL, NULL },
{ 3, "InvalidTest", NULL, NULL },
{ 4, "TestInProgress", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
#define APCC_OID_SENSITIVITY ".1.3.6.1.4.1.318.1.1.1.5.2.7.0"
static info_lkp_t apcc_sensitivity_modes[] = {
{ 1, "auto" },
{ 2, "low" },
{ 3, "medium" },
{ 4, "high" },
{ 0, NULL }
{ 1, "auto", NULL, NULL },
{ 2, "low", NULL, NULL },
{ 3, "medium", NULL, NULL },
{ 4, "high", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
#define APCC_OID_TRANSFERREASON "1.3.6.1.4.1.318.1.1.1.3.2.5.0"
static info_lkp_t apcc_transfer_reasons[] = {
{ 1, "noTransfer" },
{ 2, "highLineVoltage" },
{ 3, "brownout" },
{ 4, "blackout" },
{ 5, "smallMomentarySag" },
{ 6, "deepMomentarySag" },
{ 7, "smallMomentarySpike" },
{ 8, "largeMomentarySpike" },
{ 9, "selfTest" },
{ 10, "rateOfVoltageChange" }
{ 1, "noTransfer", NULL, NULL },
{ 2, "highLineVoltage", NULL, NULL },
{ 3, "brownout", NULL, NULL },
{ 4, "blackout", NULL, NULL },
{ 5, "smallMomentarySag", NULL, NULL },
{ 6, "deepMomentarySag", NULL, NULL },
{ 7, "smallMomentarySpike", NULL, NULL },
{ 8, "largeMomentarySpike", NULL, NULL },
{ 9, "selfTest", NULL, NULL },
{ 10, "rateOfVoltageChange", NULL, NULL }
};
/* --- */
@ -147,6 +151,11 @@ static info_lkp_t apcc_transfer_reasons[] = {
static snmp_info_t apcc_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* info elements. */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "APC",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
@ -183,8 +192,10 @@ static snmp_info_t apcc_mib[] = {
{ "input.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.1.3.2.4.0", "", SU_FLAG_OK, NULL },
{ "input.transfer.low", ST_FLAG_STRING | ST_FLAG_RW, 3, ".1.3.6.1.4.1.318.1.1.1.5.2.3.0", "", SU_TYPE_INT | SU_FLAG_OK, NULL },
{ "input.transfer.high", ST_FLAG_STRING | ST_FLAG_RW, 3, ".1.3.6.1.4.1.318.1.1.1.5.2.2.0", "", SU_TYPE_INT | SU_FLAG_OK, NULL },
{ "input.transfer.reason", ST_FLAG_STRING, 1, APCC_OID_TRANSFERREASON, "", SU_TYPE_INT | SU_FLAG_OK, apcc_transfer_reasons },
{ "input.transfer.reason", ST_FLAG_STRING, 1, APCC_OID_TRANSFERREASON, "", SU_TYPE_INT | SU_FLAG_OK, apcc_transfer_reasons },
{ "input.sensitivity", ST_FLAG_STRING | ST_FLAG_RW, 1, APCC_OID_SENSITIVITY, "", SU_TYPE_INT | SU_FLAG_OK, apcc_sensitivity_modes },
{ "ups.power", 0, 1, ".1.3.6.1.4.1.318.1.1.1.4.2.9.0", "", SU_FLAG_OK, NULL },
{ "ups.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.1.4.2.8.0", "", SU_FLAG_OK, NULL },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, APCC_OID_POWER_STATUS, "OFF",
SU_FLAG_OK | SU_STATUS_PWR, apcc_pwr_info },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, APCC_OID_BATT_STATUS, "",
@ -198,8 +209,8 @@ static snmp_info_t apcc_mib[] = {
{ "ups.load", 0, 0.1, ".1.3.6.1.4.1.318.1.1.1.4.3.3.0", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL },
{ "ups.load", 0, 1, ".1.3.6.1.4.1.318.1.1.1.4.2.3.0", "", SU_FLAG_OK, NULL },
{ "ups.firmware", ST_FLAG_STRING, 16, ".1.3.6.1.4.1.318.1.1.1.1.2.1.0", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 3, ".1.3.6.1.4.1.318.1.1.1.5.2.10.0", "", SU_FLAG_OK, NULL },
{ "ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 3, ".1.3.6.1.4.1.318.1.1.1.5.2.9.0", "", SU_FLAG_OK, NULL },
{ "ups.delay.shutdown", ST_FLAG_RW, 3, ".1.3.6.1.4.1.318.1.1.1.5.2.10.0", "", SU_TYPE_TIME | SU_FLAG_OK, NULL },
{ "ups.delay.start", ST_FLAG_RW, 3, ".1.3.6.1.4.1.318.1.1.1.5.2.9.0", "", SU_TYPE_TIME | SU_FLAG_OK, NULL },
{ "battery.charge", 0, 0.1, ".1.3.6.1.4.1.318.1.1.1.2.3.1.0", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL },
{ "battery.charge", 0, 1, ".1.3.6.1.4.1.318.1.1.1.2.2.1.0", "", SU_FLAG_OK, NULL },
{ "battery.charge.restart", ST_FLAG_STRING | ST_FLAG_RW, 3, ".1.3.6.1.4.1.318.1.1.1.5.2.6.0", "", SU_TYPE_INT | SU_FLAG_OK, NULL },
@ -213,10 +224,10 @@ static snmp_info_t apcc_mib[] = {
{ "battery.current.total", 0, 0.1, ".1.3.6.1.4.1.318.1.1.1.2.3.6.0", "", SU_FLAG_OK, NULL },
{ "battery.packs", 0, 1, ".1.3.6.1.4.1.318.1.1.1.2.2.5.0", "", SU_FLAG_OK, NULL },
{ "battery.packs.bad", 0, 1, ".1.3.6.1.4.1.318.1.1.1.2.2.6.0", "", SU_FLAG_OK, NULL },
{ "battery.date", ST_FLAG_STRING | ST_FLAG_RW, 8, ".1.3.6.1.4.1.318.1.1.1.2.1.3.0", "", SU_FLAG_OK | SU_FLAG_STATIC | SU_TYPE_STRING, NULL },
{ "ups.id", ST_FLAG_STRING | ST_FLAG_RW, 8, ".1.3.6.1.4.1.318.1.1.1.1.1.2.0", "", SU_FLAG_OK | SU_FLAG_STATIC | SU_TYPE_STRING, NULL },
{ "battery.date", ST_FLAG_STRING | ST_FLAG_RW, 8, ".1.3.6.1.4.1.318.1.1.1.2.1.3.0", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL },
{ "ups.id", ST_FLAG_STRING | ST_FLAG_RW, 8, ".1.3.6.1.4.1.318.1.1.1.1.1.2.0", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL },
{ "ups.test.result", ST_FLAG_STRING, SU_INFOSIZE, APCC_OID_TESTDIAGRESULTS, "", SU_FLAG_OK, apcc_testdiag_results },
{ "ups.test.date", ST_FLAG_STRING | ST_FLAG_RW, 8, ".1.3.6.1.4.1.318.1.1.1.7.2.4.0", "", SU_FLAG_OK | SU_FLAG_STATIC | SU_TYPE_STRING, NULL },
{ "ups.test.date", ST_FLAG_STRING | ST_FLAG_RW, 8, ".1.3.6.1.4.1.318.1.1.1.7.2.4.0", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL },
{ "output.voltage", 0, 0.1, ".1.3.6.1.4.1.318.1.1.1.4.3.1.0", "", SU_FLAG_OK | SU_FLAG_UNIQUE, NULL },
{ "output.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.1.4.2.1.0", "", SU_FLAG_OK, NULL },
{ "output.phases", ST_FLAG_STRING, 2, ".1.3.6.1.4.1.318.1.1.1.9.3.2.1.2.1", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
@ -265,38 +276,32 @@ static snmp_info_t apcc_mib[] = {
{ "ambient.humidity", 0, 1, ".1.3.6.1.4.1.318.1.1.2.1.2.0", "", SU_FLAG_OK, NULL },
{ "ambient.1.humidity.alarm.high", 0, 1, ".1.3.6.1.4.1.318.1.1.10.1.2.2.1.6.1", "", SU_FLAG_OK, NULL },
{ "ambient.1.humidity.alarm.low", 0, 1, ".1.3.6.1.4.1.318.1.1.10.1.2.2.1.7.1", "", SU_FLAG_OK, NULL },
/* IEM ambient variables */
/* IEM: integrated environment monitor probe */
#define APCC_OID_IEM_TEMP ".1.3.6.1.4.1.318.1.1.10.2.3.2.1.4.1"
#define APCC_OID_IEM_TEMP_UNIT ".1.3.6.1.4.1.318.1.1.10.2.3.2.1.5.1"
#define APCC_IEM_FAHRENHEIT 2
#define APCC_OID_IEM_HUMID ".1.3.6.1.4.1.318.1.1.10.2.3.2.1.6.1"
{ "ambient.temperature", 0, 1, APCC_OID_IEM_TEMP, "", SU_FLAG_OK, NULL },
{ "ambient.humidity", 0, 1, APCC_OID_IEM_HUMID, "", SU_FLAG_OK, NULL },
/* instant commands. */
{ "load.off", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "load.on", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.6.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "shutdown.stayoff", 0, 3, ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "load.off", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "load.on", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.6.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "shutdown.stayoff", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* { CMD_SDRET, 0, APCC_REBOOT_GRACEFUL, APCC_OID_REBOOT, "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, */
{ "shutdown.return", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.1.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "test.failure.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.4.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "test.panel.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.5.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "bypass.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.7.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "bypass.stop", 0, 3, ".1.3.6.1.4.1.318.1.1.1.6.2.7.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "test.battery.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.7.2.2.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "calibrate.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.7.2.5.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "calibrate.stop", 0, 3, ".1.3.6.1.4.1.318.1.1.1.7.2.5.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "reset.input.minmax", 0, 2, ".1.3.6.1.4.1.318.1.1.1.9.1.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "shutdown.return", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.1.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "test.failure.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.4.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "test.panel.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.5.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "bypass.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.7.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "bypass.stop", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.7.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "test.battery.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.7.2.2.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "calibrate.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.7.2.5.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "calibrate.stop", 0, 1, ".1.3.6.1.4.1.318.1.1.1.7.2.5.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "reset.input.minmax", 0, 1, ".1.3.6.1.4.1.318.1.1.1.9.1.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t apc = { "apcc", APCC_MIB_VERSION, APCC_OID_POWER_STATUS, ".1.3.6.1.4.1.318.1.1.1.1.1.1.0", apcc_mib };
mib2nut_info_t apc = { "apcc", APCC_MIB_VERSION, APCC_OID_POWER_STATUS, APC_UPS_DEVICE_MODEL, apcc_mib, APC_UPS_SYSOID, NULL };
/*
vim:ts=4:sw=4:et:

View file

@ -3,15 +3,7 @@
#include "main.h"
#include "snmp-ups.h"
/*
* FIXME: The below is needed because the main driver body uses this to determine
* whether a conversion from Fahrenheit to Celsius is needed (which really should
* be solved in subdriver specific formatting functions, like we do in usbhid-ups
*/
#define APCC_OID_IEM_TEMP ".1.3.6.1.4.1.318.1.1.10.2.3.2.1.4.1"
#define APCC_OID_IEM_TEMP_UNIT ".1.3.6.1.4.1.318.1.1.10.2.3.2.1.5.1"
#define APCC_IEM_FAHRENHEIT 2
#include "apc-iem-mib.h"
extern mib2nut_info_t apc;

972
drivers/apc-pdu-mib.c Normal file
View file

@ -0,0 +1,972 @@
/* apc-pdu-mib.c - subdriver to monitor APC PDU using PowerNet-MIB SNMP with NUT
*
* Copyright (C) 2016 - Eaton
* Authors: Tomas Halman <TomasHalman@Eaton.com>
* Arnaud Quette <ArnaudQuette@Eaton.com>
*
* Based on initial work and data from Opengear <support@opengear.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
*/
#include "apc-pdu-mib.h"
#define APC_PDU_MIB_VERSION "0.4"
#define APC_PDU_MIB_SYSOID_RPDU ".1.3.6.1.4.1.318.1.3.4.4"
#define APC_PDU_MIB_SYSOID_RPDU2 ".1.3.6.1.4.1.318.1.3.4.5"
#define APC_PDU_MIB_SYSOID_MSP ".1.3.6.1.4.1.318.1.3.4.6"
#define APC_PDU_DEVICE_MODEL ".1.3.6.1.4.1.318.1.1.4.1.4.0"
static info_lkp_t apc_pdu_sw_outlet_status_info[] = {
{ 1, "on", NULL, NULL },
{ 2, "off", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t apc_pdu_sw_outlet_switchability_info[] = {
{ 1, "yes", NULL, NULL },
{ 2, "yes", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* POWERNET-MIB Snmp2NUT lookup table */
static snmp_info_t apc_pdu_mib[] = {
/* Device page */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "APC",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* sPDUIdentModelNumber.0 = STRING: "AP7900" */
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.4.0",
"Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL,
SU_FLAG_STALE | SU_FLAG_OK, NULL },
{ "device.description", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.5.0", NULL,
SU_FLAG_STALE | SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL,
SU_FLAG_STALE | SU_FLAG_OK, NULL },
/* FIXME: to be RFC'ed */
{ "device.uptime", 0, 1, ".1.3.6.1.2.1.1.3.0", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL },
/* sPDUIdentSerialNumber.0 = STRING: "5A1234E00874" */
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* sPDUIdentModelNumber.0 = STRING: "AP7900" */
{ "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.4.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* sPDUIdentHardwareRev.0 = STRING: "B2" */
{ "device.version", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* sPDUIdentFirmwareRev.0 = STRING: "v3.7.3" */
/* FIXME: to be moved to device.firmware */
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.2.0", NULL, SU_FLAG_OK, NULL },
/* sPDUIdentDateOfManufacture.0 = STRING: "08/13/2012" */
/* FIXME: to be moved to the device collection! */
{ "ups.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.3.0", NULL, SU_FLAG_OK, NULL },
/* Input */
/* rPDUIdentDevicePowerWatts.0 = INTEGER: 0 */
{ "input.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.16.0", NULL, SU_FLAG_OK, NULL },
/* rPDULoadStatusLoad.1 = Gauge32: 0 */
{ "input.current", 0, 0.1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.2.1", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceLinetoLineVoltage.0 = INTEGER: 120 */
{ "input.voltage.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.15.0", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL },
/* Outlets */
{ "outlet.count", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.%i", "%i",
SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, NULL },
/* sPDUOutletCtlName.%i = STRING: "Testing Name" */
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.4.2.1.4.%i", NULL,
SU_FLAG_STALE | SU_FLAG_OK | SU_OUTLET, NULL },
/* sPDUOutletCtl.1 = INTEGER: outletOn(1) */
{ "outlet.%i.status", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.4.2.1.3.%i", NULL,
SU_FLAG_OK | SU_OUTLET, &apc_pdu_sw_outlet_status_info[0] },
/* Also use this OID to determine switchability ; its presence means "yes" */
/* sPDUOutletCtl.1 = INTEGER: outletOn(1) */
{ "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.4.2.1.3.%i", "yes",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, &apc_pdu_sw_outlet_switchability_info[0] },
#if 0 /* keep following scan for future development */
/* sPDUMasterControlSwitch.0 = INTEGER: noCommand(6) */
{ "unmapped.sPDUMasterControlSwitch", 0, 1, ".1.3.6.1.4.1.318.1.1.4.2.1.0", NULL, SU_FLAG_OK, NULL },
/* sPDUMasterState.0 = STRING: "On On On On On On On On " */
{ "unmapped.sPDUMasterState", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.2.2.0", NULL, SU_FLAG_OK, NULL },
/* sPDUMasterPending.0 = STRING: "No No No No No No No No " */
{ "unmapped.sPDUMasterPending", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.2.3.0", NULL, SU_FLAG_OK, NULL },
/* sPDUMasterConfigPowerOn.0 = INTEGER: 0 */
{ "unmapped.sPDUMasterConfigPowerOn", 0, 1, ".1.3.6.1.4.1.318.1.1.4.3.1.0", NULL, SU_FLAG_OK, NULL },
/* sPDUMasterConfigReboot.0 = INTEGER: 0 */
{ "unmapped.sPDUMasterConfigReboot", 0, 1, ".1.3.6.1.4.1.318.1.1.4.3.2.0", NULL, SU_FLAG_OK, NULL },
/* sPDUMasterConfigPDUName.0 = STRING: "RackPDU" */
{ "unmapped.sPDUMasterConfigPDUName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.3.3.0", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletControlTableSize.0 = INTEGER: 8 */
/* sPDUOutletControlIndex.1 = INTEGER: 1 */
{ "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletControlIndex.2 = INTEGER: 2 */
{ "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletControlIndex.3 = INTEGER: 3 */
{ "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.3", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletControlIndex.4 = INTEGER: 4 */
{ "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.4", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletControlIndex.5 = INTEGER: 5 */
{ "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.5", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletControlIndex.6 = INTEGER: 6 */
{ "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.6", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletControlIndex.7 = INTEGER: 7 */
{ "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.7", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletControlIndex.8 = INTEGER: 8 */
{ "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.8", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPending.1 = INTEGER: noCommandPending(2) */
{ "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPending.2 = INTEGER: noCommandPending(2) */
{ "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPending.3 = INTEGER: noCommandPending(2) */
{ "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.3", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPending.4 = INTEGER: noCommandPending(2) */
{ "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.4", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPending.5 = INTEGER: noCommandPending(2) */
{ "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.5", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPending.6 = INTEGER: noCommandPending(2) */
{ "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.6", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPending.7 = INTEGER: noCommandPending(2) */
{ "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.7", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPending.8 = INTEGER: noCommandPending(2) */
{ "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.8", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigTableSize.0 = INTEGER: 8 */
{ "unmapped.sPDUOutletConfigTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.1.0", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigIndex.1 = INTEGER: 1 */
{ "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigIndex.2 = INTEGER: 2 */
{ "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigIndex.3 = INTEGER: 3 */
{ "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.3", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigIndex.4 = INTEGER: 4 */
{ "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.4", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigIndex.5 = INTEGER: 5 */
{ "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.5", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigIndex.6 = INTEGER: 6 */
{ "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.6", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigIndex.7 = INTEGER: 7 */
{ "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.7", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletConfigIndex.8 = INTEGER: 8 */
{ "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.8", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOnTime.1 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOnTime.2 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOnTime.3 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.3", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOnTime.4 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.4", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOnTime.5 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.5", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOnTime.6 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.6", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOnTime.7 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.7", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOnTime.8 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.8", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletName.1 = STRING: "Testing Name" */
{ "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletName.2 = STRING: "Testing 2" */
{ "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletName.3 = STRING: "Outlet 3" */
{ "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.3", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletName.4 = STRING: "Outlet 4" */
{ "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.4", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletName.5 = STRING: "Outlet 5" */
{ "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.5", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletName.6 = STRING: "Outlet 6" */
{ "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.6", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletName.7 = STRING: "Outlet 7" */
{ "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.7", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletName.8 = STRING: "Outlet 8" */
{ "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.8", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOffTime.1 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOffTime.2 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.2", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOffTime.3 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.3", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOffTime.4 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.4", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOffTime.5 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.5", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOffTime.6 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.6", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOffTime.7 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.7", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletPowerOffTime.8 = INTEGER: 0 */
{ "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.8", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletRebootDuration.1 = INTEGER: 5 */
{ "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.1", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletRebootDuration.2 = INTEGER: 5 */
{ "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.2", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletRebootDuration.3 = INTEGER: 5 */
{ "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.3", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletRebootDuration.4 = INTEGER: 5 */
{ "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.4", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletRebootDuration.5 = INTEGER: 5 */
{ "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.5", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletRebootDuration.6 = INTEGER: 5 */
{ "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.6", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletRebootDuration.7 = INTEGER: 5 */
{ "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.7", NULL, SU_FLAG_OK, NULL },
/* sPDUOutletRebootDuration.8 = INTEGER: 5 */
{ "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.8", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentName.0 = STRING: "RackPDU" */
{ "unmapped.rPDUIdentName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.1.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentHardwareRev.0 = STRING: "B2" */
{ "unmapped.rPDUIdentHardwareRev", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.2.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentFirmwareRev.0 = STRING: "v3.7.3" */
{ "unmapped.rPDUIdentFirmwareRev", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.3.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDateOfManufacture.0 = STRING: "08/13/2012" */
{ "unmapped.rPDUIdentDateOfManufacture", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.4.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentModelNumber.0 = STRING: "AP7900" */
{ "unmapped.rPDUIdentModelNumber", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.5.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentSerialNumber.0 = STRING: "5A1234E00874" */
{ "unmapped.rPDUIdentSerialNumber", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.6.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceRating.0 = INTEGER: 12 */
{ "unmapped.rPDUIdentDeviceRating", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.7.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceNumOutlets.0 = INTEGER: 8 */
{ "unmapped.rPDUIdentDeviceNumOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.8.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceNumPhases.0 = INTEGER: 1 */
{ "input.phases", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.9.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* rPDUIdentDeviceNumBreakers.0 = INTEGER: 0 */
{ "unmapped.rPDUIdentDeviceNumBreakers", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.10.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceBreakerRating.0 = INTEGER: 0 */
{ "unmapped.rPDUIdentDeviceBreakerRating", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.11.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceOrientation.0 = INTEGER: orientHorizontal(1) */
{ "unmapped.rPDUIdentDeviceOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.12.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceOutletLayout.0 = INTEGER: seqPhaseToNeutral(1) */
{ "unmapped.rPDUIdentDeviceOutletLayout", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.13.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceDisplayOrientation.0 = INTEGER: displayNormal(1) */
{ "unmapped.rPDUIdentDeviceDisplayOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.14.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDeviceLinetoLineVoltage.0 = INTEGER: 120 */
{ "unmapped.rPDUIdentDeviceLinetoLineVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.15.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDevicePowerFactor.0 = INTEGER: 1000 */
{ "unmapped.rPDUIdentDevicePowerFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.17.0", NULL, SU_FLAG_OK, NULL },
/* rPDUIdentDevicePowerVA.0 = INTEGER: 0 */
{ "unmapped.rPDUIdentDevicePowerVA", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.18.0", NULL, SU_FLAG_OK, NULL },
/* rPDULoadDevMaxPhaseLoad.0 = INTEGER: 12 */
{ "unmapped.rPDULoadDevMaxPhaseLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.1.0", NULL, SU_FLAG_OK, NULL },
/* rPDULoadDevNumPhases.0 = INTEGER: 1 */
{ "unmapped.rPDULoadDevNumPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.2.0", NULL, SU_FLAG_OK, NULL },
/* rPDULoadDevMaxBankLoad.0 = INTEGER: 0 */
{ "unmapped.rPDULoadDevMaxBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.3.0", NULL, SU_FLAG_OK, NULL },
/* rPDULoadDevNumBanks.0 = INTEGER: 0 */
{ "unmapped.rPDULoadDevNumBanks", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.4.0", NULL, SU_FLAG_OK, NULL },
/* rPDULoadDevBankTableSize.0 = INTEGER: 0 */
{ "unmapped.rPDULoadDevBankTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.5.0", NULL, SU_FLAG_OK, NULL },
/* rPDULoadDevMaxOutletTableSize.0 = INTEGER: 0 */
{ "unmapped.rPDULoadDevMaxOutletTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.7.0", NULL, SU_FLAG_OK, NULL },
/* rPDULoadPhaseConfigIndex.phase1 = INTEGER: phase1(1) */
{ "unmapped.rPDULoadPhaseConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* rPDULoadPhaseConfigLowLoadThreshold.phase1 = INTEGER: 0 */
{ "unmapped.rPDULoadPhaseConfigLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.2.1", NULL, SU_FLAG_OK, NULL },
/* rPDULoadPhaseConfigNearOverloadThreshold.phase1 = INTEGER: 8 */
{ "unmapped.rPDULoadPhaseConfigNearOverloadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.3.1", NULL, SU_FLAG_OK, NULL },
/* rPDULoadPhaseConfigOverloadThreshold.phase1 = INTEGER: 12 */
{ "unmapped.rPDULoadPhaseConfigOverloadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.4.1", NULL, SU_FLAG_OK, NULL },
/* rPDULoadPhaseConfigAlarm.phase1 = INTEGER: noLoadAlarm(1) */
{ "unmapped.rPDULoadPhaseConfigAlarm", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.5.1", NULL, SU_FLAG_OK, NULL },
/* rPDULoadStatusIndex.1 = INTEGER: 1 */
{ "unmapped.rPDULoadStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* rPDULoadStatusLoadState.1 = INTEGER: phaseLoadNormal(1) */
{ "unmapped.rPDULoadStatusLoadState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.3.1", NULL, SU_FLAG_OK, NULL },
/* rPDULoadStatusPhaseNumber.1 = INTEGER: 1 */
{ "unmapped.rPDULoadStatusPhaseNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.4.1", NULL, SU_FLAG_OK, NULL },
/* rPDULoadStatusBankNumber.1 = INTEGER: 0 */
{ "unmapped.rPDULoadStatusBankNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.5.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletDevCommand.0 = INTEGER: noCommandAll(1) */
{ "unmapped.rPDUOutletDevCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.1.0", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletDevColdstartDelay.0 = INTEGER: 0 */
{ "unmapped.rPDUOutletDevColdstartDelay", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.2.0", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletDevNumCntrlOutlets.0 = INTEGER: 8 */
{ "unmapped.rPDUOutletDevNumCntrlOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.3.0", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletDevNumTotalOutlets.0 = INTEGER: 8 */
{ "unmapped.rPDUOutletDevNumTotalOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.4.0", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletDevMonitoredOutlets.0 = INTEGER: 0 */
{ "unmapped.rPDUOutletDevMonitoredOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.5.0", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletPhaseIndex.phase1 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.2.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletPhaseOverloadRestriction.phase1 = INTEGER: alwaysAllowTurnON(1) */
{ "unmapped.rPDUOutletPhaseOverloadRestriction", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.2.1.1.2.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlIndex.1 = INTEGER: 1 */
{ "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlIndex.2 = INTEGER: 2 */
{ "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlIndex.3 = INTEGER: 3 */
{ "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlIndex.4 = INTEGER: 4 */
{ "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlIndex.5 = INTEGER: 5 */
{ "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlIndex.6 = INTEGER: 6 */
{ "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlIndex.7 = INTEGER: 7 */
{ "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlIndex.8 = INTEGER: 8 */
{ "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletName.1 = STRING: "Testing Name" */
{ "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletName.2 = STRING: "Testing 2" */
{ "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletName.3 = STRING: "Outlet 3" */
{ "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletName.4 = STRING: "Outlet 4" */
{ "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletName.5 = STRING: "Outlet 5" */
{ "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletName.6 = STRING: "Outlet 6" */
{ "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletName.7 = STRING: "Outlet 7" */
{ "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletName.8 = STRING: "Outlet 8" */
{ "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletPhase.1 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletPhase.2 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletPhase.3 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletPhase.4 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletPhase.5 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletPhase.6 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletPhase.7 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletPhase.8 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletCommand.1 = INTEGER: immediateOn(1) */
{ "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletCommand.2 = INTEGER: immediateOn(1) */
{ "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletCommand.3 = INTEGER: immediateOn(1) */
{ "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletCommand.4 = INTEGER: immediateOn(1) */
{ "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletCommand.5 = INTEGER: immediateOn(1) */
{ "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletCommand.6 = INTEGER: immediateOn(1) */
{ "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletCommand.7 = INTEGER: immediateOn(1) */
{ "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletCommand.8 = INTEGER: immediateOn(1) */
{ "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletBank.1 = INTEGER: 0 */
{ "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletBank.2 = INTEGER: 0 */
{ "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletBank.3 = INTEGER: 0 */
{ "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletBank.4 = INTEGER: 0 */
{ "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletBank.5 = INTEGER: 0 */
{ "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletBank.6 = INTEGER: 0 */
{ "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletBank.7 = INTEGER: 0 */
{ "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletControlOutletBank.8 = INTEGER: 0 */
{ "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigIndex.1 = INTEGER: 1 */
{ "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigIndex.2 = INTEGER: 2 */
{ "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigIndex.3 = INTEGER: 3 */
{ "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigIndex.4 = INTEGER: 4 */
{ "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigIndex.5 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigIndex.6 = INTEGER: 6 */
{ "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigIndex.7 = INTEGER: 7 */
{ "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigIndex.8 = INTEGER: 8 */
{ "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletName.1 = STRING: "Testing Name" */
{ "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletName.2 = STRING: "Testing 2" */
{ "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletName.3 = STRING: "Outlet 3" */
{ "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletName.4 = STRING: "Outlet 4" */
{ "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletName.5 = STRING: "Outlet 5" */
{ "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletName.6 = STRING: "Outlet 6" */
{ "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletName.7 = STRING: "Outlet 7" */
{ "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletName.8 = STRING: "Outlet 8" */
{ "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletPhase.1 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletPhase.2 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletPhase.3 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletPhase.4 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletPhase.5 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletPhase.6 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletPhase.7 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletPhase.8 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOnTime.1 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOnTime.2 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOnTime.3 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOnTime.4 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOnTime.5 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOnTime.6 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOnTime.7 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOnTime.8 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOffTime.1 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOffTime.2 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOffTime.3 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOffTime.4 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOffTime.5 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOffTime.6 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOffTime.7 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigPowerOffTime.8 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigRebootDuration.1 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigRebootDuration.2 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigRebootDuration.3 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigRebootDuration.4 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigRebootDuration.5 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigRebootDuration.6 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigRebootDuration.7 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigRebootDuration.8 = INTEGER: 5 */
{ "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletBank.1 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletBank.2 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletBank.3 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletBank.4 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletBank.5 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletBank.6 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletBank.7 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigOutletBank.8 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletConfigMonitoredTableSize.0 = INTEGER: 0 */
{ "unmapped.rPDUOutletConfigMonitoredTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.2.0", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusIndex.1 = INTEGER: 1 */
{ "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusIndex.2 = INTEGER: 2 */
{ "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusIndex.3 = INTEGER: 3 */
{ "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusIndex.4 = INTEGER: 4 */
{ "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusIndex.5 = INTEGER: 5 */
{ "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusIndex.6 = INTEGER: 6 */
{ "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusIndex.7 = INTEGER: 7 */
{ "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusIndex.8 = INTEGER: 8 */
{ "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletName.1 = STRING: "Testing Name" */
{ "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletName.2 = STRING: "Testing 2" */
{ "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletName.3 = STRING: "Outlet 3" */
{ "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletName.4 = STRING: "Outlet 4" */
{ "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletName.5 = STRING: "Outlet 5" */
{ "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletName.6 = STRING: "Outlet 6" */
{ "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletName.7 = STRING: "Outlet 7" */
{ "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletName.8 = STRING: "Outlet 8" */
{ "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletPhase.1 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletPhase.2 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletPhase.3 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletPhase.4 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletPhase.5 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletPhase.6 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletPhase.7 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletPhase.8 = INTEGER: phase1(1) */
{ "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletState.1 = INTEGER: outletStatusOn(1) */
{ "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletState.2 = INTEGER: outletStatusOn(1) */
{ "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletState.3 = INTEGER: outletStatusOn(1) */
{ "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletState.4 = INTEGER: outletStatusOn(1) */
{ "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletState.5 = INTEGER: outletStatusOn(1) */
{ "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletState.6 = INTEGER: outletStatusOn(1) */
{ "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletState.7 = INTEGER: outletStatusOn(1) */
{ "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletState.8 = INTEGER: outletStatusOn(1) */
{ "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusCommandPending.1 = INTEGER: outletStatusNoCommandPending(2) */
{ "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusCommandPending.2 = INTEGER: outletStatusNoCommandPending(2) */
{ "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusCommandPending.3 = INTEGER: outletStatusNoCommandPending(2) */
{ "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusCommandPending.4 = INTEGER: outletStatusNoCommandPending(2) */
{ "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusCommandPending.5 = INTEGER: outletStatusNoCommandPending(2) */
{ "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusCommandPending.6 = INTEGER: outletStatusNoCommandPending(2) */
{ "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusCommandPending.7 = INTEGER: outletStatusNoCommandPending(2) */
{ "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusCommandPending.8 = INTEGER: outletStatusNoCommandPending(2) */
{ "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletBank.1 = INTEGER: 0 */
{ "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletBank.2 = INTEGER: 0 */
{ "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletBank.3 = INTEGER: 0 */
{ "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletBank.4 = INTEGER: 0 */
{ "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletBank.5 = INTEGER: 0 */
{ "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletBank.6 = INTEGER: 0 */
{ "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletBank.7 = INTEGER: 0 */
{ "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusOutletBank.8 = INTEGER: 0 */
{ "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.8", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusLoad.1 = Gauge32: 0 */
{ "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.1", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusLoad.2 = Gauge32: 0 */
{ "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.2", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusLoad.3 = Gauge32: 0 */
{ "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.3", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusLoad.4 = Gauge32: 0 */
{ "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.4", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusLoad.5 = Gauge32: 0 */
{ "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.5", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusLoad.6 = Gauge32: 0 */
{ "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.6", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusLoad.7 = Gauge32: 0 */
{ "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.7", NULL, SU_FLAG_OK, NULL },
/* rPDUOutletStatusLoad.8 = Gauge32: 0 */
{ "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.8", NULL, SU_FLAG_OK, NULL },
/* rPDUPowerSupply1Status.0 = INTEGER: powerSupplyOneOk(1) */
{ "unmapped.rPDUPowerSupply1Status", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.1.0", NULL, SU_FLAG_OK, NULL },
/* rPDUPowerSupply2Status.0 = INTEGER: powerSupplyTwoOk(1) */
{ "unmapped.rPDUPowerSupply2Status", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.2.0", NULL, SU_FLAG_OK, NULL },
/* rPDUPowerSupplyAlarm.0 = INTEGER: allAvailablePowerSuppliesOK(1) */
{ "unmapped.rPDUPowerSupplyAlarm", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.3.0", NULL, SU_FLAG_OK, NULL },
/* rPDUStatusBankTableSize.0 = INTEGER: 0 */
{ "unmapped.rPDUStatusBankTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.1.0", NULL, SU_FLAG_OK, NULL },
/* rPDUStatusPhaseTableSize.0 = INTEGER: 1 */
{ "unmapped.rPDUStatusPhaseTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.3.0", NULL, SU_FLAG_OK, NULL },
/* rPDUStatusPhaseIndex.1 = INTEGER: 1 */
{ "unmapped.rPDUStatusPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.1.1", NULL, SU_FLAG_OK, NULL },
/* rPDUStatusPhaseNumber.1 = INTEGER: 1 */
{ "unmapped.rPDUStatusPhaseNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.2.1", NULL, SU_FLAG_OK, NULL },
/* rPDUStatusPhaseState.1 = INTEGER: phaseLoadNormal(1) */
{ "unmapped.rPDUStatusPhaseState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.3.1", NULL, SU_FLAG_OK, NULL },
/* rPDUStatusOutletTableSize.0 = INTEGER: 0 */
{ "unmapped.rPDUStatusOutletTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.5.0", NULL, SU_FLAG_OK, NULL },
/* experimental.2.1.0 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.1.0", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.1.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.2.1 = STRING: "Rack PDU_ISX" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.3.1 = STRING: "5A1234E00874" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.4.1 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.5.1 = STRING: "Rack PDU" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.5.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.6.1 = STRING: "1" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.6.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.7.1 = STRING: "Unknown" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.7.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.8.1 = INTEGER: 255 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.8.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.9.1 = STRING: "RackPDU" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.9.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.10.1 = INTEGER: 255 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.10.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.11.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.11.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.12.1 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.12.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.13.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.13.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.2.1.14.1 = STRING: "SB-1" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.14.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.3.0 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.3.0", NULL, SU_FLAG_OK, NULL },
/* experimental.2.4.1.1.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.4.1.1.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.4.1.1.2 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.4.1.1.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.4.1.2.1 = STRING: "5A1234E00874" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.2.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.4.1.2.2 = STRING: "5A1234E00874" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.2.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.4.1.3.1 = STRING: "apc_hw02_aos_373.bin" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.3.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.4.1.3.2 = STRING: "apc_hw02_rpdu_373.bin" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.3.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.4.1.4.1 = STRING: "v3.7.3" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.4.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.4.1.4.2 = STRING: "v3.7.3" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.4.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.5.0 = INTEGER: 19 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.5.0", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.2 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.3 = INTEGER: 3 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.3", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.4 = INTEGER: 4 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.4", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.5 = INTEGER: 5 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.5", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.6 = INTEGER: 6 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.6", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.7 = INTEGER: 7 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.7", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.8 = INTEGER: 8 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.8", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.9 = INTEGER: 9 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.9", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.10 = INTEGER: 10 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.10", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.11 = INTEGER: 11 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.11", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.12 = INTEGER: 12 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.12", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.13 = INTEGER: 13 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.13", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.14 = INTEGER: 14 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.14", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.15 = INTEGER: 15 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.15", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.16 = INTEGER: 16 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.16", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.17 = INTEGER: 17 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.17", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.18 = INTEGER: 18 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.18", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.1.19 = INTEGER: 19 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.19", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.2 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.3 = INTEGER: 3 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.3", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.4 = INTEGER: 4 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.4", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.5 = INTEGER: 5 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.5", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.6 = INTEGER: 6 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.6", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.7 = INTEGER: 7 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.7", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.8 = INTEGER: 8 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.8", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.9 = INTEGER: 9 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.9", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.10 = INTEGER: 10 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.10", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.11 = INTEGER: 11 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.11", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.12 = INTEGER: 12 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.12", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.13 = INTEGER: 13 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.13", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.14 = INTEGER: 14 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.14", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.15 = INTEGER: 15 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.15", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.16 = INTEGER: 16 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.16", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.17 = INTEGER: 17 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.17", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.18 = INTEGER: 18 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.18", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.2.19 = INTEGER: 19 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.19", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.1 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.2 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.3 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.3", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.4 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.4", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.5 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.5", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.6 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.6", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.7 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.7", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.8 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.8", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.9 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.9", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.10 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.10", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.11 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.11", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.12 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.12", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.13 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.13", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.14 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.14", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.15 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.15", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.16 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.16", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.17 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.17", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.18 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.18", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.3.19 = STRING: "0" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.19", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.1 = STRING: "MTYx" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.2 = STRING: "MjM=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.3 = STRING: "ODA=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.3", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.4 = STRING: "OTk1MA==" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.4", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.5 = STRING: "OTk1MA==" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.5", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.6 = STRING: "NDQz" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.6", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.7 = STRING: "MjI=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.7", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.8 = STRING: "MjI=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.8", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.9 = STRING: "MTIz" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.9", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.10 = STRING: "MjU=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.10", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.11 = STRING: "MjE=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.11", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.12 = STRING: "MjE=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.12", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.13 = STRING: "Njg=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.13", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.14 = STRING: "NTQ2" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.14", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.15 = STRING: "MTgxMg==" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.15", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.16 = STRING: "MTYx" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.16", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.17 = STRING: "MjE=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.17", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.18 = STRING: "MjE=" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.18", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.4.19 = STRING: "OTk1MQ==" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.19", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.1 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.2 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.2", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.3 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.3", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.4 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.4", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.5 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.5", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.6 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.6", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.7 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.7", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.8 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.8", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.9 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.9", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.10 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.10", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.11 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.11", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.12 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.12", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.13 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.13", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.14 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.14", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.15 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.15", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.16 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.16", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.17 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.17", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.18 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.18", NULL, SU_FLAG_OK, NULL },
/* experimental.2.6.1.5.19 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.19", NULL, SU_FLAG_OK, NULL },
/* experimental.2.7.0 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.7.0", NULL, SU_FLAG_OK, NULL },
/* experimental.2.8.1.1.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.8.1.1.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.8.1.2.1 = STRING: "power" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.2.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.8.1.3.1 = STRING: "pdu" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.3.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.8.1.4.1 = STRING: "rpdu" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.4.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.8.1.5.1 = STRING: "version7" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.5.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.8.1.6.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.8.1.6.1", NULL, SU_FLAG_OK, NULL },
/* experimental.2.9.0 = INTEGER: 0 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.9.0", NULL, SU_FLAG_OK, NULL },
/* experimental.2.10.0 = INTEGER: 0 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.10.0", NULL, SU_FLAG_OK, NULL },
/* experimental.2.12.0 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.12.0", NULL, SU_FLAG_OK, NULL },
/* experimental.4.1.0 = INTEGER: 0 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.4.1.0", NULL, SU_FLAG_OK, NULL },
/* experimental.4.3.0 = STRING: "<Host Name or IP>,<1 digit type identifier>" */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.4.3.0", NULL, SU_FLAG_OK, NULL },
/* experimental.4.4.0 = INTEGER: 0 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.4.4.0", NULL, SU_FLAG_OK, NULL },
/* experimental.5.1.0 = INTEGER: 12 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.1.0", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.1 = INTEGER: 1 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.2 = INTEGER: 2 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.3 = INTEGER: 3 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.3", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.4 = INTEGER: 4 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.4", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.5 = INTEGER: 5 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.5", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.6 = INTEGER: 6 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.6", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.7 = INTEGER: 7 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.7", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.8 = INTEGER: 8 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.8", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.9 = INTEGER: 9 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.9", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.10 = INTEGER: 10 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.10", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.11 = INTEGER: 11 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.11", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.1.12 = INTEGER: 12 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.12", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.1 = INTEGER: 3841 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.2 = INTEGER: 3843 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.3 = INTEGER: 3845 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.3", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.4 = INTEGER: 3848 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.4", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.5 = INTEGER: 3862 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.5", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.6 = INTEGER: 3864 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.6", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.7 = INTEGER: 3856 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.7", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.8 = INTEGER: 3858 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.8", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.9 = INTEGER: 3860 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.9", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.10 = INTEGER: 3871 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.10", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.11 = INTEGER: 3873 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.11", NULL, SU_FLAG_OK, NULL },
/* experimental.5.2.1.2.12 = INTEGER: 3875 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.12", NULL, SU_FLAG_OK, NULL },
/* experimental.6.1.1.0 = Hex-STRING: 07 00 00 00 */
{ "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.6.1.1.0", NULL, SU_FLAG_OK, NULL },
/* experimental.7.1.0 = INTEGER: 4 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.1.0", NULL, SU_FLAG_OK, NULL },
/* experimental.7.3.0 = INTEGER: 4 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.3.0", NULL, SU_FLAG_OK, NULL },
/* experimental.7.4.0 = INTEGER: 3 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.4.0", NULL, SU_FLAG_OK, NULL },
/* experimental.7.5.0 = INTEGER: 3 */
{ "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.5.0", NULL, SU_FLAG_OK, NULL },
#endif /* scan result */
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t apc_pdu_rpdu = { "apc_pdu", APC_PDU_MIB_VERSION, NULL, APC_PDU_DEVICE_MODEL, apc_pdu_mib, APC_PDU_MIB_SYSOID_RPDU, NULL };
mib2nut_info_t apc_pdu_rpdu2 = { "apc_pdu", APC_PDU_MIB_VERSION, NULL, APC_PDU_DEVICE_MODEL, apc_pdu_mib, APC_PDU_MIB_SYSOID_RPDU2, NULL };
mib2nut_info_t apc_pdu_msp = { "apc_pdu", APC_PDU_MIB_VERSION, NULL, APC_PDU_DEVICE_MODEL, apc_pdu_mib, APC_PDU_MIB_SYSOID_MSP, NULL };

31
drivers/apc-pdu-mib.h Normal file
View file

@ -0,0 +1,31 @@
/* powernet-mib-mib.h - subdriver to monitor PowerNet-MIB SNMP devices with NUT
*
* Copyright (C)
* 2011 - 2012 Arnaud Quette <arnaud.quette@free.fr>
*
* 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
*/
#ifndef APC_PDU_MIB_H
#define APC_PDU_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t apc_pdu_rpdu;
extern mib2nut_info_t apc_pdu_rpdu2;
extern mib2nut_info_t apc_pdu_msp;
#endif /* APC_PDU_MIB_H */

View file

@ -22,9 +22,10 @@
#include "main.h"
#include "serial.h"
#include "apcsmart-old.h"
#include "nut_stdint.h"
#define DRIVER_NAME "APC Smart protocol driver"
#define DRIVER_VERSION "2.1"
#define DRIVER_VERSION "2.2"
static upsdrv_info_t table_info = {
"APC command table",
@ -77,7 +78,7 @@ static apc_vartab_t *vartab_lookup_name(const char *var)
static const char *convert_data(apc_vartab_t *cmd_entry, const char *upsval)
{
static char tmp[128];
int tval;
long tval;
switch(cmd_entry->flags & APC_FORMATMASK) {
case APC_F_PERCENT:
@ -97,14 +98,14 @@ static const char *convert_data(apc_vartab_t *cmd_entry, const char *upsval)
tval = 60 * 60 * strtol(upsval, NULL, 10);
snprintf(tmp, sizeof(tmp), "%d", tval);
snprintf(tmp, sizeof(tmp), "%ld", tval);
return tmp;
case APC_F_MINUTES:
/* Convert to seconds - NUT standard time measurement */
tval = 60 * strtol(upsval, NULL, 10);
/* Ignore errors - Theres not much we can do */
snprintf(tmp, sizeof(tmp), "%d", tval);
snprintf(tmp, sizeof(tmp), "%ld", tval);
return tmp;
case APC_F_REASON:
@ -197,9 +198,9 @@ static void alert_handler(char ch)
ups_status_set();
}
static int read_buf(char *buf, size_t buflen)
static ssize_t read_buf(char *buf, size_t buflen)
{
int ret;
ssize_t ret;
ret = ser_get_line_alert(upsfd, buf, buflen, ENDCHAR, POLL_IGNORE,
POLL_ALERT, alert_handler, SER_WAIT_SEC, SER_WAIT_USEC);
@ -213,9 +214,9 @@ static int read_buf(char *buf, size_t buflen)
return ret;
}
static int poll_data(apc_vartab_t *vt)
static ssize_t poll_data(apc_vartab_t *vt)
{
int ret;
ssize_t ret;
char tmp[SMALLBUF];
if ((vt->flags & APC_PRESENT) == 0)
@ -251,7 +252,7 @@ static int poll_data(apc_vartab_t *vt)
/* check for support or just update a named variable */
static int query_ups(const char *var, int first)
{
int ret;
ssize_t ret;
char temp[256];
const char *ptr;
apc_vartab_t *vt;
@ -270,7 +271,7 @@ static int query_ups(const char *var, int first)
return 0;
/* empty the input buffer (while allowing the alert handler to run) */
ret = ser_get_line_alert(upsfd, temp, sizeof(temp), ENDCHAR,
ret = ser_get_line_alert(upsfd, temp, sizeof(temp), ENDCHAR,
POLL_IGNORE, POLL_ALERT, alert_handler, 0, 0);
ret = ser_send_char(upsfd, vt->cmd);
@ -280,7 +281,7 @@ static int query_ups(const char *var, int first)
return 0;
}
ret = ser_get_line_alert(upsfd, temp, sizeof(temp), ENDCHAR,
ret = ser_get_line_alert(upsfd, temp, sizeof(temp), ENDCHAR,
POLL_IGNORE, POLL_ALERT, alert_handler, SER_WAIT_SEC,
SER_WAIT_USEC);
@ -305,7 +306,9 @@ static void do_capabilities(void)
{
const char *ptr, *entptr;
char upsloc, temp[512], cmd, loc, etmp[16], *endtemp;
int nument, entlen, i, matrix, ret, valid;
int matrix, valid;
size_t i, nument, entlen;
ssize_t ret;
apc_vartab_t *vt;
upsdebugx(1, "APC - About to get capabilities string");
@ -327,7 +330,7 @@ static void do_capabilities(void)
}
/* note different IGN set since ^Z returns things like # */
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR,
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR,
MINIGNCHARS, SER_WAIT_SEC, SER_WAIT_USEC);
if ((ret < 1) || (!strcmp(temp, "NA"))) {
@ -347,7 +350,7 @@ static void do_capabilities(void)
if (temp[0] != '#') {
upsdebugx(1, "Unrecognized capability start char %c", temp[0]);
upsdebugx(1, "Please report this error [%s]", temp);
upslogx(LOG_ERR, "ERROR: unknown capability start char %c!",
upslogx(LOG_ERR, "ERROR: unknown capability start char %c!",
temp[0]);
return;
@ -375,7 +378,7 @@ static void do_capabilities(void)
if (quirk_capability_overflow)
return;
fatalx(EXIT_FAILURE,
fatalx(EXIT_FAILURE,
"Capability string has overflowed\n"
"Please report this error\n"
"ERROR: capability overflow!"
@ -384,8 +387,17 @@ static void do_capabilities(void)
cmd = ptr[0];
loc = ptr[1];
nument = ptr[2] - 48;
entlen = ptr[3] - 48;
if (ptr[2] < 48 || ptr[3] < 48) {
upsdebugx(0,
"%s: nument (%d) or entlen (%d) out of range",
__func__, (ptr[2] - 48), (ptr[3] - 48));
fatalx(EXIT_FAILURE,
"nument or entlen out of range\n"
"Please report this error\n"
"ERROR: capability overflow!");
}
nument = (size_t)ptr[2] - 48;
entlen = (size_t)ptr[3] - 48;
entptr = &ptr[4];
vt = vartab_lookup_char(cmd);
@ -393,7 +405,7 @@ static void do_capabilities(void)
/* mark this as writable */
if (valid) {
upsdebugx(1, "Supported capability: %02x (%c) - %s",
upsdebugx(1, "Supported capability: %02x (%c) - %s",
cmd, loc, vt->name);
dstate_setflags(vt->name, ST_FLAG_RW);
@ -417,7 +429,7 @@ static void do_capabilities(void)
static int update_status(void)
{
int ret;
ssize_t ret;
char buf[SMALLBUF];
upsdebugx(4, "update_status");
@ -449,7 +461,7 @@ static int update_status(void)
static void oldapcsetup(void)
{
int ret = 0;
ssize_t ret = 0;
/* really old models ignore REQ_MODEL, so find them first */
ret = query_ups("ups.model", 1);
@ -492,7 +504,7 @@ static void protocol_verify(unsigned char cmd)
/* handle special data for our two strings */
if (apc_vartab[i].flags & APC_STRING) {
dstate_setflags(apc_vartab[i].name,
dstate_setflags(apc_vartab[i].name,
ST_FLAG_RW | ST_FLAG_STRING);
dstate_setaux(apc_vartab[i].name, APC_STRLEN);
@ -524,8 +536,8 @@ static void protocol_verify(unsigned char cmd)
if (found)
return;
if (isprint(cmd))
upsdebugx(1, "protocol_verify: 0x%02x [%c] unrecognized",
if (isprint((size_t)cmd))
upsdebugx(1, "protocol_verify: 0x%02x [%c] unrecognized",
cmd, cmd);
else
upsdebugx(1, "protocol_verify: 0x%02x unrecognized", cmd);
@ -534,7 +546,7 @@ static void protocol_verify(unsigned char cmd)
/* some hardware is a special case - hotwire the list of cmdchars */
static int firmware_table_lookup(void)
{
int ret;
ssize_t ret;
unsigned int i, j;
char buf[SMALLBUF];
@ -547,7 +559,7 @@ static int firmware_table_lookup(void)
return 0;
}
ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, IGNCHARS,
ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, IGNCHARS,
SER_WAIT_SEC, SER_WAIT_USEC);
/*
@ -594,21 +606,22 @@ static int firmware_table_lookup(void)
/* matched - run the cmdchars from the table */
for (j = 0; j < strlen(compat_tab[i].cmdchars); j++)
protocol_verify(compat_tab[i].cmdchars[j]);
protocol_verify((const unsigned char)(compat_tab[i].cmdchars[j]));
return 1; /* matched */
}
}
upsdebugx(2, "Not found in table - trying normal method");
return 0;
return 0;
}
static void getbaseinfo(void)
{
unsigned int i;
int ret = 0;
char *alrts, *cmds, temp[512];
ssize_t ret = 0;
char *alrts, temp[512];
unsigned char *cmds;
/*
* try firmware lookup first; we could start with 'a', but older models
@ -630,7 +643,7 @@ static void getbaseinfo(void)
return;
}
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, IGNCHARS,
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, IGNCHARS,
SER_WAIT_SEC, SER_WAIT_USEC);
if ((ret < 1) || (!strcmp(temp, "NA"))) {
@ -652,17 +665,17 @@ static void getbaseinfo(void)
}
*alrts++ = 0;
cmds = strchr(alrts, '.');
cmds = (unsigned char*)strchr(alrts, '.');
if (cmds == NULL) {
fatalx(EXIT_FAILURE, "Unable to find APC command string");
}
*cmds++ = 0;
for (i = 0; i < strlen(cmds); i++)
for (i = 0; i < strlen((char *)cmds); i++)
protocol_verify(cmds[i]);
/* if capabilities are supported, add them here */
if (strchr(cmds, APC_CAPABILITY))
if (strchr((char *)cmds, APC_CAPABILITY))
do_capabilities();
upsdebugx(1, "APC - UPS capabilities determined");
@ -672,7 +685,8 @@ static void getbaseinfo(void)
static int do_cal(int start)
{
char temp[256];
int tval, ret;
long tval;
ssize_t ret;
ret = ser_send_char(upsfd, APC_STATUS);
@ -710,7 +724,7 @@ static int do_cal(int start)
ret = read_buf(temp, sizeof(temp));
if ((ret < 1) || (!strcmp(temp, "NA")) || (!strcmp(temp, "NO"))) {
upslogx(LOG_WARNING, "Stop calibration failed: %s",
upslogx(LOG_WARNING, "Stop calibration failed: %s",
temp);
return STAT_INSTCMD_HANDLED; /* FUTURE: failure */
}
@ -747,7 +761,8 @@ static int do_cal(int start)
/* get the UPS talking to us in smart mode */
static int smartmode(void)
{
int ret, tries;
ssize_t ret;
int tries;
char temp[256];
for (tries = 0; tries < 5; tries++) {
@ -759,7 +774,7 @@ static int smartmode(void)
return 0;
}
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR,
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR,
IGNCHARS, SER_WAIT_SEC, SER_WAIT_USEC);
if (ret > 0)
@ -778,7 +793,7 @@ static int smartmode(void)
}
/* eat the response (might be NA, might be something else) */
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR,
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR,
IGNCHARS, SER_WAIT_SEC, SER_WAIT_USEC);
}
@ -788,7 +803,7 @@ static int smartmode(void)
/*
* all shutdown commands should respond with 'OK' or '*'
*/
static int sdok(void)
static long sdok(void)
{
char temp[16];
@ -805,8 +820,10 @@ static int sdok(void)
}
/* soft hibernate: S - working only when OB, otherwise ignored */
static int sdcmd_S(int dummy)
static long sdcmd_S(long dummy)
{
NUT_UNUSED_VARIABLE(dummy);
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
upsdebugx(1, "Issuing soft hibernate");
@ -816,7 +833,7 @@ static int sdcmd_S(int dummy)
}
/* soft hibernate, hack version for CS 350 */
static int sdcmd_CS(int tval)
static long sdcmd_CS(long tval)
{
upsdebugx(1, "Using CS 350 'force OB' shutdown method");
if (tval & APC_STAT_OL) {
@ -832,9 +849,10 @@ static int sdcmd_CS(int tval)
* note: works differently for older and new models, see help function for
* detailed info
*/
static int sdcmd_ATn(int cnt)
static long sdcmd_ATn(long cnt)
{
int n = 0, mmax, ret;
long n = 0;
long mmax, ret;
const char *strval;
char timer[4];
@ -847,10 +865,13 @@ static int sdcmd_ATn(int cnt)
n = 0;
}
snprintf(timer, sizeof(timer), "%.*d", cnt, n);
if (cnt > INT_MAX || cnt < 0) {
fatalx(EXIT_FAILURE, "Error: %s: cnt (%ld) is out of range", __func__, cnt);
}
snprintf(timer, sizeof(timer), "%.*ld", (int)cnt, n);
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
upsdebugx(1, "Issuing hard hibernate with %d minutes additional wakeup delay", n*6);
upsdebugx(1, "Issuing hard hibernate with %ld minutes additional wakeup delay", n*6);
ser_send_char(upsfd, APC_CMD_GRACEDOWN);
usleep(CMDLONGDELAY);
@ -874,8 +895,10 @@ static int sdcmd_ATn(int cnt)
}
/* shutdown: K - delayed poweroff */
static int sdcmd_K(int dummy)
static long sdcmd_K(long dummy)
{
NUT_UNUSED_VARIABLE(dummy);
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
upsdebugx(1, "Issuing delayed poweroff");
@ -887,8 +910,10 @@ static int sdcmd_K(int dummy)
}
/* shutdown: Z - immediate poweroff */
static int sdcmd_Z(int dummy)
static long sdcmd_Z(long dummy)
{
NUT_UNUSED_VARIABLE(dummy);
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
upsdebugx(1, "Issuing immediate poweroff");
@ -899,7 +924,7 @@ static int sdcmd_Z(int dummy)
return sdok();
}
static int (*sdlist[])(int) = {
static long (*sdlist[])(long) = {
sdcmd_S,
sdcmd_ATn, /* for @nnn version */
sdcmd_K,
@ -917,9 +942,9 @@ static int (*sdlist[])(int) = {
#define SDCNT 6
static void upsdrv_shutdown_simple(int status)
static void upsdrv_shutdown_simple(long status)
{
unsigned int sdtype = 0;
long sdtype = 0;
char *strval;
if ((strval = getval("sdtype"))) {
@ -975,7 +1000,7 @@ static void upsdrv_shutdown_simple(int status)
}
}
static void upsdrv_shutdown_advanced(int status)
static void upsdrv_shutdown_advanced(long status)
{
const char *strval;
const char deforder[] = {48 + SDIDX_S,
@ -984,7 +1009,7 @@ static void upsdrv_shutdown_advanced(int status)
48 + SDIDX_Z,
0};
size_t i;
int n;
long n;
strval = getval("advorder");
@ -1026,7 +1051,8 @@ static void upsdrv_shutdown_advanced(int status)
void upsdrv_shutdown(void)
{
char temp[32];
int ret, status;
ssize_t ret;
long status;
if (!smartmode())
upsdebugx(1, "SM detection failed. Trying a shutdown command anyway");
@ -1066,7 +1092,7 @@ static void init_serial_0095B(void)
static void update_info_normal(void)
{
int i;
size_t i;
upsdebugx(3, "update_info_normal: starting");
@ -1086,7 +1112,7 @@ static void update_info_normal(void)
static void update_info_all(void)
{
int i;
size_t i;
upsdebugx(3, "update_info_all: starting");
@ -1103,7 +1129,8 @@ static void update_info_all(void)
static int setvar_enum(apc_vartab_t *vt, const char *val)
{
int i, ret;
int i;
ssize_t ret;
char orig[256], temp[256];
const char *ptr;
@ -1183,7 +1210,7 @@ static int setvar_enum(apc_vartab_t *vt, const char *val)
vt->name);
return STAT_SET_HANDLED; /* FUTURE: failed */
}
}
}
upslogx(LOG_ERR, "setvar: gave up after 6 tries for %s",
@ -1197,8 +1224,8 @@ static int setvar_enum(apc_vartab_t *vt, const char *val)
static int setvar_string(apc_vartab_t *vt, const char *val)
{
unsigned int i;
int ret;
size_t i;
ssize_t ret;
char temp[256];
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
@ -1232,7 +1259,7 @@ static int setvar_string(apc_vartab_t *vt, const char *val)
usleep(UPSDELAY);
for (i = 0; i < strlen(val); i++) {
ret = ser_send_char(upsfd, val[i]);
ret = ser_send_char(upsfd, (const unsigned char)(val[i]));
if (ret != 1) {
upslog_with_errno(LOG_ERR, "setvar_string: ser_send_char failed");
@ -1301,7 +1328,7 @@ static int setvar(const char *varname, const char *val)
/* actually send the instcmd's char to the ups */
static int do_cmd(apc_cmdtab_t *ct)
{
int ret;
ssize_t ret;
char buf[SMALLBUF];
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
@ -1374,13 +1401,14 @@ static int instcmd(const char *cmdname, const char *extra)
ct = &apc_cmdtab[i];
if (!ct) {
upslogx(LOG_WARNING, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_WARNING, "instcmd: unknown command [%s] [%s]",
cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}
if ((ct->flags & APC_PRESENT) == 0) {
upslogx(LOG_WARNING, "instcmd: command [%s] is not supported",
cmdname);
upslogx(LOG_WARNING, "instcmd: command [%s] [%s] is not supported",
cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}
@ -1395,7 +1423,7 @@ static int instcmd(const char *cmdname, const char *extra)
/* nothing special here */
return do_cmd(ct);
}
}
/* install pointers to functions for msg handlers called from msgparse */
static void setuphandlers(void)
@ -1439,7 +1467,7 @@ void upsdrv_initinfo(void)
const char *pmod, *pser;
if (!smartmode()) {
fatalx(EXIT_FAILURE,
fatalx(EXIT_FAILURE,
"Unable to detect an APC Smart protocol UPS on port %s\n"
"Check the cabling, port name or model name and try again", device_path
);

View file

@ -18,6 +18,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_APCSMART_OLD_H_SEEN
#define NUT_APCSMART_OLD_H_SEEN 1
#include <ctype.h>
#include <sys/ioctl.h>
#include "serial.h"
@ -57,14 +60,14 @@
/* 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 */
#define APC_STAT_CAL 1L /* calibration */
#define APC_STAT_TRIM 2L /* SmartTrim */
#define APC_STAT_BOOST 4L /* SmartBoost */
#define APC_STAT_OL 8L /* on line */
#define APC_STAT_OB 16L /* on battery */
#define APC_STAT_OVER 32L /* overload */
#define APC_STAT_LB 64L /* low battery */
#define APC_STAT_RB 128L /* replace battery */
/* serial protocol: special commands - initialization and such */
#define APC_STATUS 'Q'
@ -105,10 +108,10 @@
typedef struct {
const char *name; /* the variable name */
unsigned int flags; /* various flags */
char cmd; /* command character */
unsigned char cmd; /* command character */
} apc_vartab_t;
apc_vartab_t apc_vartab[] = {
static apc_vartab_t apc_vartab[] = {
{ "ups.firmware.old", 0, 'V' },
{ "ups.firmware", 0, 'b' },
@ -141,7 +144,7 @@ apc_vartab_t apc_vartab[] = {
{ "input.transfer.low", APC_F_VOLT, 'l' },
{ "input.transfer.high",
APC_F_VOLT, 'u' },
{ "input.transfer.reason",
{ "input.transfer.reason",
APC_POLL|APC_F_REASON, 'G' },
{ "input.voltage.maximum",
@ -151,30 +154,30 @@ apc_vartab_t apc_vartab[] = {
{ "output.current", APC_POLL|APC_F_AMP, '/' },
{ "output.voltage", APC_POLL|APC_F_VOLT, 'O' },
{ "output.voltage.nominal",
{ "output.voltage.nominal",
APC_F_VOLT, 'o' },
{ "ambient.humidity", APC_POLL|APC_F_PERCENT, 'h' },
{ "ambient.humidity.high",
{ "ambient.humidity.high",
APC_F_PERCENT, '{' },
{ "ambient.humidity.low",
{ "ambient.humidity.low",
APC_F_PERCENT, '}' },
{ "ambient.temperature",
{ "ambient.temperature",
APC_POLL|APC_F_CELSIUS, 't' },
{ "ambient.temperature.high",
{ "ambient.temperature.high",
APC_F_CELSIUS, '[' },
{ "ambient.temperature.low",
{ "ambient.temperature.low",
APC_F_CELSIUS, ']' },
{ "battery.date", APC_STRING, 'x' },
{ "battery.charge", APC_POLL|APC_F_PERCENT, 'f' },
{ "battery.charge.restart",
{ "battery.charge.restart",
APC_F_PERCENT, 'e' },
{ "battery.voltage", APC_POLL|APC_F_VOLT, 'B' },
{ "battery.voltage.nominal",
{ "battery.voltage.nominal",
0, 'g' },
{ "battery.runtime", APC_POLL|APC_F_MINUTES, 'j' },
@ -183,7 +186,7 @@ apc_vartab_t apc_vartab[] = {
{ "battery.packs", APC_F_DEC, '>' },
{ "battery.packs.bad", APC_F_DEC, '<' },
{ "battery.alarm.threshold",
{ "battery.alarm.threshold",
0, 'k' },
/* todo:
@ -215,10 +218,10 @@ apc_vartab_t apc_vartab[] = {
typedef struct {
const char *name;
int flags;
char cmd;
unsigned char cmd;
} apc_cmdtab_t;
apc_cmdtab_t apc_cmdtab[] =
static apc_cmdtab_t apc_cmdtab[] =
{
{ "load.off", APC_NASTY|APC_REPEAT, APC_CMD_OFF },
{ "load.on", APC_REPEAT, APC_CMD_ON },
@ -246,7 +249,7 @@ apc_cmdtab_t apc_cmdtab[] =
/* compatibility with hardware that doesn't do APC_CMDSET ('a') */
struct {
static struct {
const char *firmware;
const char *cmdchars;
int flags;
@ -289,3 +292,5 @@ struct {
{ NULL, NULL, 0 },
};
#endif /* NUT_APCSMART_OLD_H_SEEN */

File diff suppressed because it is too large Load diff

View file

@ -20,11 +20,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __apcsmart_h__
#define __apcsmart_h__
#ifndef NUT_APCSMART_H_SEEN
#define NUT_APCSMART_H_SEEN 1
#define DRIVER_NAME "APC Smart protocol driver"
#define DRIVER_VERSION "3.1"
#define DRIVER_VERSION "3.2"
#define ALT_CABLE_1 "940-0095B"
@ -126,14 +126,14 @@
/* status bits */
#define APC_STAT_CAL (1 << 0) /* calibration */
#define APC_STAT_TRIM (1 << 1) /* SmartTrim */
#define APC_STAT_BOOST (1 << 2) /* SmartBoost */
#define APC_STAT_OL (1 << 3) /* on line */
#define APC_STAT_OB (1 << 4) /* on battery */
#define APC_STAT_OVER (1 << 5) /* overload */
#define APC_STAT_LB (1 << 6) /* low battery */
#define APC_STAT_RB (1 << 7) /* replace battery */
#define APC_STAT_CAL (1L << 0) /* calibration */
#define APC_STAT_TRIM (1L << 1) /* SmartTrim */
#define APC_STAT_BOOST (1L << 2) /* SmartBoost */
#define APC_STAT_OL (1L << 3) /* on line */
#define APC_STAT_OB (1L << 4) /* on battery */
#define APC_STAT_OVER (1L << 5) /* overload */
#define APC_STAT_LB (1L << 6) /* low battery */
#define APC_STAT_RB (1L << 7) /* replace battery */
/*
* serial protocol: special commands - initialization and such
@ -161,12 +161,7 @@
/* advorder method regex format*/
#define APC_ADVFMT "^([0-4]{1,5}|[Nn][Oo])$"
/* error logging/debug related macros */
/* cshdelay format */
#define APC_CSHDFMT "^([0-9]\\.?|[0-9]?\\.[0-9])$"
#define fatx(fmt, ...) fatalx(EXIT_FAILURE, "%s: " fmt, __func__ , ## __VA_ARGS__)
#define fate(fmt, ...) fatal_with_errno(EXIT_FAILURE, "%s: " fmt, __func__ , ## __VA_ARGS__)
#define logx(lev, fmt, ...) upslogx(lev, "%s: " fmt, __func__ , ## __VA_ARGS__)
#define debx(lev, fmt, ...) upsdebugx(lev, "%s: " fmt, __func__ , ## __VA_ARGS__)
#endif
#endif /* NUT_APCSMART_H_SEEN */

View file

@ -23,55 +23,55 @@
/* APC_MULTI variables *must* be listed in order of preference */
apc_vartab_t apc_vartab[] = {
/* name cmd flags regex nlen0 cnt */
{ "ups.temperature", 'C', APC_POLL|APC_F_CELSIUS, NULL, 0, 0 },
{ "ups.load", 'P', APC_POLL|APC_F_PERCENT, NULL, 0, 0 },
{ "ups.test.interval", 'E', APC_F_HOURS, NULL, 0, 0 },
{ "ups.test.result", 'X', APC_POLL, NULL, 0, 0 },
{ "ups.delay.start", 'r', APC_F_SECONDS, NULL, 0, 0 },
{ "ups.delay.shutdown", 'p', APC_F_SECONDS, NULL, 0, 0 },
{ "ups.id", 'c', APC_STRING, NULL, 0, 0 },
{ "ups.contacts", 'i', APC_POLL|APC_F_HEX, NULL, 0, 0 },
{ "ups.display.language", '\014', 0, NULL, 0, 0 },
{ "input.voltage", 'L', APC_POLL|APC_F_VOLT, NULL, 0, 0 },
{ "input.frequency", 'F', APC_POLL|APC_F_DEC, NULL, 0, 0 },
{ "input.sensitivity", 's', 0, NULL, 0, 0 },
{ "input.quality", '9', APC_POLL|APC_F_HEX, NULL, 0, 0 },
{ "input.transfer.low", 'l', APC_F_VOLT, NULL, 0, 0 },
{ "input.transfer.high", 'u', APC_F_VOLT, NULL, 0, 0 },
{ "input.transfer.reason", 'G', APC_POLL|APC_F_REASON, NULL, 0, 0 },
{ "input.voltage.maximum", 'M', APC_POLL|APC_F_VOLT, NULL, 0, 0 },
{ "input.voltage.minimum", 'N', APC_POLL|APC_F_VOLT, NULL, 0, 0 },
{ "output.current", '/', APC_POLL|APC_F_AMP, NULL, 0, 0 },
{ "output.voltage", 'O', APC_POLL|APC_F_VOLT, NULL, 0, 0 },
{ "output.voltage.nominal", 'o', APC_F_VOLT, NULL, 0, 0 },
{ "ambient.humidity", 'h', APC_POLL|APC_F_PERCENT, NULL, 0, 0 },
{ "ambient.0.humidity", 'H', APC_POLL|APC_PACK|APC_F_PERCENT, NULL, 0, 0 },
{ "ambient.0.humidity.high", '{', APC_POLL|APC_PACK|APC_F_PERCENT, NULL, 0, 0 },
{ "ambient.0.humidity.low", '}', APC_POLL|APC_PACK|APC_F_PERCENT, NULL, 0, 0 },
{ "ambient.temperature", 't', APC_POLL|APC_F_CELSIUS, NULL, 0, 0 },
{ "ambient.0.temperature", 'T', APC_MULTI|APC_POLL|APC_PACK|APC_F_CELSIUS, "^[0-9]{2}\\.[0-9]{2}$", 0, 0 },
{ "ambient.0.temperature.high", '[', APC_POLL|APC_PACK|APC_F_CELSIUS, NULL, 0, 0 },
{ "ambient.0.temperature.low", ']', APC_POLL|APC_PACK|APC_F_CELSIUS, NULL, 0, 0 },
{ "battery.date", 'x', APC_STRING, NULL, 0, 0 },
{ "battery.charge", 'f', APC_POLL|APC_F_PERCENT, NULL, 0, 0 },
{ "battery.charge.restart", 'e', APC_F_PERCENT, NULL, 0, 0 },
{ "battery.voltage", 'B', APC_POLL|APC_F_VOLT, NULL, 0, 0 },
{ "battery.voltage.nominal", 'g', 0, NULL, 0, 0 },
{ "battery.runtime", 'j', APC_POLL|APC_F_MINUTES, NULL, 0, 0 },
{ "battery.runtime.low", 'q', APC_F_MINUTES, NULL, 0, 0 },
{ "battery.packs", '>', APC_F_DEC, NULL, 0, 0 },
{ "battery.packs.bad", '<', APC_F_DEC, NULL, 0, 0 },
{ "battery.alarm.threshold", 'k', 0, NULL, 0, 0 },
{ "device.uptime", 'T', APC_MULTI|APC_POLL|APC_F_HOURS, "^[0-9]{3}\\.[0-9]{1}$", 0, 0 },
{ "ups.serial", 'n', 0, NULL, 0, 0 },
{ "ups.mfr.date", 'm', 0, NULL, 0, 0 },
{ "ups.model", '\001', 0, NULL, 0, 0 },
{ "ups.firmware.aux", 'v', 0, NULL, 0, 0 },
{ "ups.firmware", 'b', APC_MULTI, "^[[:alnum:]]+\\.[[:alnum:]]+\\.[[:alnum:]]+$", 0, 0 },
{ "ups.firmware", 'V', APC_MULTI, NULL, 0, 0 },
{ "ups.temperature", 'C', APC_POLL|APC_F_CELSIUS },
{ "ups.load", 'P', APC_POLL|APC_F_PERCENT },
{ "ups.test.interval", 'E', APC_F_HOURS },
{ "ups.test.result", 'X', APC_POLL },
{ "ups.delay.start", 'r', APC_F_SECONDS },
{ "ups.delay.shutdown", 'p', APC_F_SECONDS },
{ "ups.id", 'c', APC_STRING },
{ "ups.contacts", 'i', APC_POLL|APC_F_HEX },
{ "ups.display.language", '\014' },
{ "input.voltage", 'L', APC_POLL|APC_F_VOLT },
{ "input.frequency", 'F', APC_POLL|APC_F_DEC },
{ "input.sensitivity", 's', },
{ "input.quality", '9', APC_POLL|APC_F_HEX },
{ "input.transfer.low", 'l', APC_F_VOLT },
{ "input.transfer.high", 'u', APC_F_VOLT },
{ "input.transfer.reason", 'G', APC_POLL|APC_F_REASON },
{ "input.voltage.maximum", 'M', APC_POLL|APC_F_VOLT },
{ "input.voltage.minimum", 'N', APC_POLL|APC_F_VOLT },
{ "output.current", '/', APC_POLL|APC_F_AMP },
{ "output.voltage", 'O', APC_POLL|APC_F_VOLT },
{ "output.voltage.nominal", 'o', APC_F_VOLT },
{ "ambient.humidity", 'h', APC_POLL|APC_F_PERCENT },
{ "ambient.0.humidity", 'H', APC_POLL|APC_PACK|APC_F_PERCENT },
{ "ambient.0.humidity.high", '{', APC_POLL|APC_PACK|APC_F_PERCENT },
{ "ambient.0.humidity.low", '}', APC_POLL|APC_PACK|APC_F_PERCENT },
{ "ambient.temperature", 't', APC_POLL|APC_F_CELSIUS },
{ "ambient.0.temperature", 'T', APC_MULTI|APC_POLL|APC_PACK|APC_F_CELSIUS, "^[0-9]{2}\\.[0-9]{2}$" },
{ "ambient.0.temperature.high", '[', APC_POLL|APC_PACK|APC_F_CELSIUS },
{ "ambient.0.temperature.low", ']', APC_POLL|APC_PACK|APC_F_CELSIUS },
{ "battery.date", 'x', APC_STRING },
{ "battery.charge", 'f', APC_POLL|APC_F_PERCENT },
{ "battery.charge.restart", 'e', APC_F_PERCENT },
{ "battery.voltage", 'B', APC_POLL|APC_F_VOLT },
{ "battery.voltage.nominal", 'g', },
{ "battery.runtime", 'j', APC_POLL|APC_F_MINUTES },
{ "battery.runtime.low", 'q', APC_F_MINUTES },
{ "battery.packs", '>', APC_F_DEC },
{ "battery.packs.bad", '<', APC_F_DEC },
{ "battery.alarm.threshold", 'k', },
{ "device.uptime", 'T', APC_MULTI|APC_POLL|APC_F_HOURS, "^[0-9]{3}\\.[0-9]{1}$" },
{ "ups.serial", 'n', },
{ "ups.mfr.date", 'm', },
{ "ups.model", '\001' },
{ "ups.firmware.aux", 'v', },
{ "ups.firmware", 'b', APC_MULTI, "^[[:alnum:]]+\\.[[:alnum:]]+\\.[[:alnum:]]+$" },
{ "ups.firmware", 'V', APC_MULTI },
{ NULL }
{ NULL, 0, 0, NULL, 0, 0 }
/* todo:
I = alarm enable (hex field) - split into alarm.n.enable
@ -94,19 +94,19 @@ apc_cmdtab_t apc_cmdtab[] = {
APC_CMD_GRACEDOWN, APC_NASTY },
{ "shutdown.return", "^([Cc][Ss]|)$",
APC_CMD_SOFTDOWN, APC_NASTY },
{ "shutdown.stayoff", 0, APC_CMD_SHUTDOWN, APC_NASTY|APC_REPEAT },
{ "load.off", 0, APC_CMD_OFF, APC_NASTY|APC_REPEAT },
{ "load.on", 0, APC_CMD_ON, APC_REPEAT },
{ "calibrate.start", 0, APC_CMD_CALTOGGLE, 0 },
{ "calibrate.stop", 0, APC_CMD_CALTOGGLE, 0 },
{ "test.panel.start", 0, APC_CMD_FPTEST, 0 },
{ "test.failure.start", 0, APC_CMD_SIMPWF, 0 },
{ "test.battery.start", 0, APC_CMD_BTESTTOGGLE, 0 },
{ "test.battery.stop", 0, APC_CMD_BTESTTOGGLE, 0 },
{ "bypass.start", 0, APC_CMD_BYPTOGGLE, 0 },
{ "bypass.stop", 0, APC_CMD_BYPTOGGLE, 0 },
{ "shutdown.stayoff", NULL, APC_CMD_SHUTDOWN, APC_NASTY|APC_REPEAT },
{ "load.off", NULL, APC_CMD_OFF, APC_NASTY|APC_REPEAT },
{ "load.on", NULL, APC_CMD_ON, APC_REPEAT },
{ "calibrate.start", NULL, APC_CMD_CALTOGGLE, 0 },
{ "calibrate.stop", NULL, APC_CMD_CALTOGGLE, 0 },
{ "test.panel.start", NULL, APC_CMD_FPTEST, 0 },
{ "test.failure.start", NULL, APC_CMD_SIMPWF, 0 },
{ "test.battery.start", NULL, APC_CMD_BTESTTOGGLE, 0 },
{ "test.battery.stop", NULL, APC_CMD_BTESTTOGGLE, 0 },
{ "bypass.start", NULL, APC_CMD_BYPTOGGLE, 0 },
{ "bypass.stop", NULL, APC_CMD_BYPTOGGLE, 0 },
{ NULL }
{ NULL, NULL, 0, 0 }
};
/* compatibility with hardware that doesn't do APC_CMDSET ('a') */
@ -151,11 +151,16 @@ apc_compattab_t apc_compattab[] = {
*/
{ "set\1", "@789ABCFGKLMNOPQRSUVWXYZ", 0 },
{ NULL }
{ NULL, NULL, 0 }
};
upsdrv_info_t apc_tab_info = {
"APC command table",
APC_TABLE_VERSION
APC_TABLE_VERSION,
"Russell Kroll <rkroll@exploits.org>\n" \
"Nigel Metheringham <Nigel.Metheringham@Intechnology.co.uk>\n" \
"Michal Soltys <soltys@ziu.info>",
DRV_STABLE,
{ NULL }
};

View file

@ -20,8 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __apcsmart_tabs_h__
#define __apcsmart_tabs_h__
#ifndef NUT_APCSMART_TABS_H_SEEN
#define NUT_APCSMART_TABS_H_SEEN 1
#include "main.h"
@ -103,4 +103,4 @@ extern apc_cmdtab_t apc_cmdtab[];
extern apc_compattab_t apc_compattab[];
extern upsdrv_info_t apc_tab_info;
#endif
#endif /* NUT_APCSMART_TABS_H_SEEN */

View file

@ -16,6 +16,8 @@
*/
#include "config.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
@ -24,9 +26,12 @@
#include "main.h"
#include "apcupsd-ups.h"
#include "attribute.h"
#define DRIVER_NAME "apcupsd network client UPS driver"
#define DRIVER_VERSION "0.04"
#define DRIVER_VERSION "0.6"
#define POLL_INTERVAL_MIN 10
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -37,7 +42,7 @@ upsdrv_info_t upsdrv_info = {
{ NULL }
};
static int port=3551;
static uint16_t port=3551;
static struct sockaddr_in host;
static void process(char *item,char *data)
@ -54,9 +59,8 @@ static void process(char *item,char *data)
{
case DU_FLAG_STATUS:
status_init();
if(!strcmp(data,"COMMLOST")||!strcmp(data,"SHUTTING DOWN")||
!strcmp(data,"NETWORK ERROR")||!strcmp(data,"ERROR"))
status_set("OFF");
if(!strcmp(data,"COMMLOST")||!strcmp(data,"NETWORK ERROR")||
!strcmp(data,"ERROR"))status_set("OFF");
else if(!strcmp(data,"SELFTEST"))status_set("OB");
else for(;(data=strtok(data," "));data=NULL)
{
@ -66,7 +70,8 @@ static void process(char *item,char *data)
else if(!strcmp(data,"ONLINE"))status_set("OL");
else if(!strcmp(data,"ONBATT"))status_set("OB");
else if(!strcmp(data,"OVERLOAD"))status_set("OVER");
else if(!strcmp(data,"LOWBATT"))status_set("LB");
else if(!strcmp(data,"SHUTTING DOWN")||
!strcmp(data,"LOWBATT"))status_set("LB");
else if(!strcmp(data,"REPLACEBATT"))status_set("RB");
else if(!strcmp(data,"NOBATT"))status_set("BYPASS");
}
@ -128,24 +133,41 @@ static void process(char *item,char *data)
data[(int)nut_data[i].info_len]=0;
dstate_setinfo(nut_data[i].info_type,"%s",data);
}
else dstate_setinfo(nut_data[i].info_type,
nut_data[i].default_value,
atof(data)*nut_data[i].info_len);
else
{
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
/* default_value acts as a format string in this case */
dstate_setinfo(nut_data[i].info_type,
nut_data[i].default_value,
atof(data)*nut_data[i].info_len);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
}
break;
}
}
static int getdata(void)
{
int x, fd_flags;
short n;
ssize_t x;
int fd_flags;
uint16_t n;
char *item;
char *data;
struct pollfd p;
char bfr[1024];
for(x=0;nut_data[x].info_type;x++)
if(!(nut_data[x].drv_flags&DU_FLAG_INIT))
if(!(nut_data[x].drv_flags & DU_FLAG_INIT) && !(nut_data[x].drv_flags & DU_FLAG_PRESERVE))
dstate_delinfo(nut_data[x].info_type);
if((p.fd=socket(AF_INET,SOCK_STREAM,0))==-1)
@ -192,6 +214,12 @@ static int getdata(void)
return 0;
}
else if(x<0||x>=(int)sizeof(bfr))
/* Note: LGTM.com suggests "Comparison is always false because x >= 0"
* for the line above, probably because ntohs() returns an uint type.
* I am reluctant to fix this one, because googling for headers from
* random OSes showed various types used as the return value (uint16_t,
* unsigned_short, u_short, in_port_t...)
*/
{
upsdebugx(1,"apcupsd communication error");
close(p.fd);
@ -200,7 +228,7 @@ static int getdata(void)
if(poll(&p,1,15000)!=1)break;
if(read(p.fd,bfr,x)!=x)
if(read(p.fd,bfr,(size_t)x)!=x)
{
upsdebugx(1,"apcupsd communication error");
close(p.fd);
@ -237,16 +265,21 @@ void upsdrv_initinfo(void)
if(!port)fatalx(EXIT_FAILURE,"invalid host or port specified!");
if(getdata())fatalx(EXIT_FAILURE,"can't communicate with apcupsd!");
else dstate_dataok();
poll_interval=60;
poll_interval = (poll_interval > POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval;
}
void upsdrv_updateinfo(void)
{
if(getdata())upslogx(LOG_ERR,"can't communicate with apcupsd!");
else dstate_dataok();
poll_interval=60;
poll_interval = (poll_interval > POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval;
}
void upsdrv_shutdown(void)
__attribute__((noreturn));
void upsdrv_shutdown(void)
{
fatalx(EXIT_FAILURE, "shutdown not supported");
@ -270,9 +303,11 @@ void upsdrv_initups(void)
/* TODO: fix parsing since bare IPv6 addresses contain colons */
if((p=strchr(device_path,':')))
{
int i;
*p++=0;
port=atoi(p);
if(port<1||port>65535)port=0;
i=atoi(p);
if(i<1||i>65535)i=0;
port = (uint16_t)i;
}
}
else device_path="localhost";

View file

@ -18,6 +18,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_APCUPSD_UPS_H_SEEN
#define NUT_APCUPSD_UPS_H_SEEN 1
/* from usbhid-ups.h */
/* --------------------------------------------------------------- */
/* Struct & data for ups.status processing */
@ -41,7 +44,8 @@ typedef struct {
#define STATUS_CHRG 1024 /* charging */
#define STATUS_DISCHRG 2048 /* discharging */
status_lkp_t status_info[] = {
/*
static status_lkp_t status_info[] = {
{ "CAL", STATUS_CAL },
{ "TRIM", STATUS_TRIM },
{ "BOOST", STATUS_BOOST },
@ -56,6 +60,7 @@ status_lkp_t status_info[] = {
{ "DISCHRG", STATUS_DISCHRG },
{ "NULL", 0 },
};
*/
/* from usbhid-ups.h */
typedef struct {
@ -89,6 +94,7 @@ typedef struct {
#define DU_FLAG_TIME 8
#define DU_FLAG_FW1 16
#define DU_FLAG_FW2 32
#define DU_FLAG_PRESERVE 64
/* ------------ */
/* Data table */
@ -124,14 +130,21 @@ static apcuspd_info_t nut_data[] =
{ "LINEFREQ", "input.frequency", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "OUTPUTV", "output.voltage", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "LINEFREQ", "output.frequency", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "BCHARGE", "battery.charge", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "BCHARGE", "battery.charge", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_PRESERVE, NULL },
{ "MBATTCHG", "battery.charge.low", ST_FLAG_RW, 1, "%.0f", DU_FLAG_NONE, NULL },
{ "BATTDATE", "battery.date", ST_FLAG_STRING /* | ST_FLAG_RW */, 16, NULL, DU_FLAG_DATE, NULL },
{ "BATTV", "battery.voltage", 0, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "NOMBATTV", "battery.voltage.nominal", 0, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "TIMELEFT", "battery.runtime", ST_FLAG_RW, 60, "%1.1f", DU_FLAG_NONE, NULL },
{ "TIMELEFT", "battery.runtime", ST_FLAG_RW, 60, "%1.1f", DU_FLAG_PRESERVE, NULL },
{ "MINTIMEL", "battery.runtime.low", ST_FLAG_RW, 60, "%.0f", DU_FLAG_NONE, NULL },
{ "RETPCT", "battery.charge.restart", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "NOMPOWER", "ups.realpower.nominal", 0, 1, "%1.1f", DU_FLAG_INIT, NULL },
{ "LOAD_W", "ups.realpower", 0, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "LOADAPNT", "power.percent", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "OUTCURNT", "output.current", 0, 1, "%1.2f", DU_FLAG_NONE, NULL },
{ "LOAD_VA", "ups.power", 0, 1, "%1.1f", DU_FLAG_NONE, NULL },
{ "NOMAPNT", "ups.power.nominal", 0, 1, "%.0f", DU_FLAG_INIT, NULL },
{ NULL, NULL, 0, 0, NULL, DU_FLAG_NONE, NULL }
};
#endif /* NUT_APCUPSD_UPS_H_SEEN */

148
drivers/arduino-hid.c Normal file
View file

@ -0,0 +1,148 @@
/* arduino-hid.c - subdriver to monitor Arduino USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2012 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2013 Charles Lepple <clepple+nut@gmail.com>
* 2021 Alex Bratchik <alexbratchik@yandex.com>
*
* Note: this subdriver was initially generated as a "stub" by the
* gen-usbhid-subdriver script. It must be customized.
*
* 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 "config.h" /* must be first */
#include "usbhid-ups.h"
#include "arduino-hid.h"
#include "main.h" /* for getval() */
#include "usb-common.h"
#define ARDUINO_HID_VERSION "Arduino HID 0.2"
/* FIXME: experimental flag to be put in upsdrv_info */
/* Arduino */
#define ARDUINO_VENDORID 0x2341
#define ARDUINO_VENDORID2 0x2A03
/* USB IDs device table */
static usb_device_id_t arduino_usb_device_table[] = {
/* Arduino Leonardo, Leonardo ETH and Pro Micro*/
{ USB_DEVICE(ARDUINO_VENDORID, 0x0036), NULL },
{ USB_DEVICE(ARDUINO_VENDORID, 0x8036), NULL },
{ USB_DEVICE(ARDUINO_VENDORID2, 0x0036), NULL },
{ USB_DEVICE(ARDUINO_VENDORID2, 0x8036), NULL },
{ USB_DEVICE(ARDUINO_VENDORID2, 0x0040), NULL },
{ USB_DEVICE(ARDUINO_VENDORID2, 0x8040), NULL },
/* Terminating entry */
{ 0, 0, NULL }
};
static usb_communication_subdriver_t *usb = &usb_subdriver;
/* --------------------------------------------------------------- */
/* Vendor-specific usage table */
/* --------------------------------------------------------------- */
/* ARDUINO usage table */
static usage_lkp_t arduino_usage_lkp[] = {
{ NULL, 0 }
};
static usage_tables_t arduino_utab[] = {
arduino_usage_lkp,
hid_usage_lkp,
NULL,
};
/* --------------------------------------------------------------- */
/* HID2NUT lookup table */
/* --------------------------------------------------------------- */
static hid_info_t arduino_hid2nut[] = {
/* USB HID PDC defaults */
{ "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL},
{ "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL},
{ "ups.timer.start", 0, 0, "UPS.PowerSummary.DelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL},
{ "ups.timer.shutdown", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL},
{ "ups.timer.reboot", 0, 0, "UPS.PowerSummary.DelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL},
/* USB HID PDC defaults */
{ "load.off.delay", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL },
{ "load.on.delay", 0, 0, "UPS.PowerSummary.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL },
{ "shutdown.stop", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL },
{ "shutdown.reboot", 0, 0, "UPS.PowerSummary.DelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, NULL, 0, NULL }
};
static const char *arduino_format_model(HIDDevice_t *hd) {
return hd->Product;
}
static const char *arduino_format_mfr(HIDDevice_t *hd) {
return hd->Vendor ? hd->Vendor : "Arduino";
}
static const char *arduino_format_serial(HIDDevice_t *hd) {
return hd->Serial;
}
/* this function allows the subdriver to "claim" a device: return 1 if
* the device is supported by this subdriver, else 0. */
static int arduino_claim(HIDDevice_t *hd)
{
int status = is_usb_device_supported(arduino_usb_device_table, hd);
switch (status) {
case POSSIBLY_SUPPORTED:
/* by default, reject, unless the productid option is given */
if (getval("productid")) {
usb->hid_ep_in=4;
usb->hid_ep_out=5;
usb->hid_rep_index = 2;
return 1;
}
possibly_supported("Arduino", hd);
return 0;
case SUPPORTED:
usb->hid_ep_in=4;
usb->hid_ep_out=5;
usb->hid_rep_index = 2;
return 1;
case NOT_SUPPORTED:
default:
return 0;
}
}
subdriver_t arduino_subdriver = {
ARDUINO_HID_VERSION,
arduino_claim,
arduino_utab,
arduino_hid2nut,
arduino_format_model,
arduino_format_mfr,
arduino_format_serial,
fix_report_desc,
};

31
drivers/arduino-hid.h Normal file
View file

@ -0,0 +1,31 @@
/* arduino-hid.h - subdriver to monitor Arduino USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2009 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2021 Alex Bratchik <alexbratchik@yandex.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
*/
#ifndef ARDUINO_HID_H
#define ARDUINO_HID_H
#include "usbhid-ups.h"
extern subdriver_t arduino_subdriver;
#endif /* ARDUINO_HID_H */

View file

@ -30,13 +30,34 @@
so you need to boot with acpi_enforce_resources=lax option.
*/
/* Depends on i2c-dev.h, Linux only */
#include "main.h"
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include "main.h"
/* Depends on i2c-dev.h, Linux only
* Linux I2C userland is a bit of a mess until distros refresh to
* the i2c-tools 4.x release that profides i2c/smbus.h for userspace
* instead of (re)using linux/i2c-dev.h, which conflicts with a
* kernel header of the same name.
*
* See:
* https://i2c.wiki.kernel.org/index.php/Plans_for_I2C_Tools_4
*/
#if HAVE_LINUX_SMBUS_H
# include <i2c/smbus.h>
#endif
#if HAVE_LINUX_I2C_DEV_H
# include <linux/i2c-dev.h> /* for I2C_SLAVE */
# if !HAVE_LINUX_SMBUS_H
# ifndef I2C_FUNC_I2C
# include <linux/i2c.h>
# endif
# endif
#endif
#include <sys/ioctl.h>
#ifndef __STR__
# define __STR__(x) #x
@ -46,7 +67,7 @@
#endif
#define DRIVER_NAME "ASEM"
#define DRIVER_VERSION "0.10"
#define DRIVER_VERSION "0.11"
/* Valid on ASEM PB1300 UPS */
#define BQ2060_ADDRESS 0x0B
@ -59,7 +80,7 @@
#define ACCESS_DEVICE(fd, address) \
if (ioctl(fd, I2C_SLAVE, address) < 0) { \
fatal_with_errno(EXIT_FAILURE, "Failed to acquire bus access and/or talk to slave 0x%02X", address); \
fatal_with_errno(EXIT_FAILURE, "Failed to acquire bus access and/or talk to i2c slave 0x%02X", address); \
}
static unsigned long lb_threshold = LOW_BATTERY_THRESHOLD;
@ -84,7 +105,18 @@ void upsdrv_initinfo(void)
__u8 buffer[10];
unsigned short year, month, day;
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT)
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT
# pragma GCC diagnostic ignored "-Wextra-semi-stmt"
#endif
/* Current definition of this macro ends with a brace;
* we keep the useless trailing ";" for readability */
ACCESS_DEVICE(upsfd, BQ2060_ADDRESS);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT)
# pragma GCC diagnostic pop
#endif
/* Set capacity mode in mA(h) */
i2c_status = i2c_smbus_read_word_data(upsfd, 0x03);
@ -150,7 +182,18 @@ void upsdrv_updateinfo(void)
static __s32 temperature;
static __s32 runtime_to_empty;
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT)
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT
# pragma GCC diagnostic ignored "-Wextra-semi-stmt"
#endif
/* Current definition of this macro ends with a brace;
* we keep the useless trailing ";" for readability */
ACCESS_DEVICE(upsfd, CHARGER_ADDRESS);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT)
# pragma GCC diagnostic pop
#endif
/* Charger only supplies online/offline status */
i2c_status = i2c_smbus_read_word_data(upsfd, 0x13);
if (i2c_status == -1) {
@ -161,7 +204,18 @@ void upsdrv_updateinfo(void)
online = (i2c_status & 0x8000) != 0;
upsdebugx(3, "Charger status 0x%02X, online %d", i2c_status, online);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT)
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT
# pragma GCC diagnostic ignored "-Wextra-semi-stmt"
#endif
/* Current definition of this macro ends with a brace;
* we keep the useless trailing ";" for readability */
ACCESS_DEVICE(upsfd, BQ2060_ADDRESS);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT)
# pragma GCC diagnostic pop
#endif
i2c_status = i2c_smbus_read_word_data(upsfd, 0x16);
if (i2c_status == -1) {
dstate_datastale();
@ -245,7 +299,7 @@ void upsdrv_updateinfo(void)
status_init();
status_set(online ? "OL" : "OB");
if (!discharging & !fully_charged)
if (!discharging && !fully_charged)
status_set("CHRG");
else if (discharging && current < 0)
status_set("DISCHRG");
@ -270,6 +324,9 @@ void upsdrv_updateinfo(void)
dstate_dataok();
}
void upsdrv_shutdown(void)
__attribute__((noreturn));
void upsdrv_shutdown(void)
{
/* tell the UPS to shut down, then return - DO NOT SLEEP HERE */
@ -318,7 +375,18 @@ void upsdrv_initups(void)
fatal_with_errno(EXIT_FAILURE, "Could not open device port '%s'", device_path);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT)
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT
# pragma GCC diagnostic ignored "-Wextra-semi-stmt"
#endif
/* Current definition of this macro ends with a brace;
* we keep the useless trailing ";" for readability */
ACCESS_DEVICE(upsfd, BQ2060_ADDRESS);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_EXTRA_SEMI_STMT)
# pragma GCC diagnostic pop
#endif
/* Get ManufacturerName */
memset(DeviceName_buffer, 0, 10);

View file

@ -2,7 +2,7 @@
*
* Copyright (C) 2009
* Opengear <support@opengear.com>
* Arnaud Quette <arnaud.quette@free.fr>
* Arnaud Quette <arnaud.quette@free.fr>
*
* 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
@ -23,69 +23,76 @@
#include "baytech-mib.h"
#define BAYTECH_MIB_VERSION "4032"
/* NOTE: last badly versioned release was "4032" but should be "X.Y[Z]"! */
#define BAYTECH_MIB_VERSION "0.4034"
/* Baytech MIB */
#define BAYTECH_OID_MIB ".1.3.6.1.4.1.4779"
#define BAYTECH_OID_MODEL_NAME ".1.3.6.1.4.1.4779.1.3.5.2.1.24.1"
static info_lkp_t outlet_status_info[] = {
{ -1, "error" },
{ 0, "off" },
{ 1, "on" },
{ 2, "cycling" }, /* transitional status */
{ 0, NULL }
static info_lkp_t baytech_outlet_status_info[] = {
{ -1, "error", NULL, NULL },
{ 0, "off", NULL, NULL },
{ 1, "on", NULL, NULL },
{ 2, "cycling", NULL, NULL }, /* transitional status */
{ 0, NULL, NULL, NULL }
};
/* Snmp2NUT lookup table for BayTech MIBs */
static snmp_info_t baytech_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device page */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "BayTech",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.2.1.24.1",
"Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
"Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.1.2.0", "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.2.2.1.6.2",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* UPS page */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Baytech",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.2.1.24.1",
"Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
"Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.1.3.0",
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.1.2.0", "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.1.1.0", "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "ups.temperature", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.10.2.1", NULL, 0, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.temperature", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.10.2.1", NULL, 0, NULL },
/* Outlet page */
{ "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.count", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.2.1.15.1", "0", 0, NULL },
{ "outlet.current", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.6.2.1", NULL, 0, NULL, NULL },
{ "outlet.voltage", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.8.2.1", NULL, 0, NULL, NULL },
{ "outlet.current", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.6.2.1", NULL, 0, NULL },
{ "outlet.voltage", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.8.2.1", NULL, 0, NULL },
/* outlet template definition */
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", NULL, SU_OUTLET, &outlet_status_info[0], NULL },
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.3.1.4.1.%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.6.1.3.2.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_OUTLET | SU_FLAG_OK, NULL, NULL },
{ "outlet.%i.switchable", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, NULL, NULL },
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", NULL, SU_OUTLET, &baytech_outlet_status_info[0] },
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.3.1.4.1.%i", NULL, SU_OUTLET, NULL },
{ "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.6.1.3.2.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_OUTLET | SU_FLAG_OK, NULL },
{ "outlet.%i.switchable", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, NULL },
/* instant commands. */
{ "outlet.%i.load.off", 0, 0, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL },
{ "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", "1", SU_TYPE_CMD | SU_OUTLET, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL, NULL }
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t baytech = { "baytech", BAYTECH_MIB_VERSION, NULL, BAYTECH_OID_MODEL_NAME, baytech_mib };
mib2nut_info_t baytech = { "baytech", BAYTECH_MIB_VERSION, NULL, BAYTECH_OID_MODEL_NAME, baytech_mib, BAYTECH_OID_MIB, NULL };

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
/*
* bcmxcp.h -- header for BCM/XCP module
*/
*/
#ifndef _POWERWARE_H
#define _POWERWARE_H
@ -20,9 +20,9 @@
#define PW_ANSWER_MAX_SIZE 256
/* No Autorisation required */
/* No Autorisation required */
#define PW_ID_BLOCK_REQ (unsigned char)0x31 /* Model name, ... length 1 */
#define PW_EVENT_HISTORY_LOG_REQ (unsigned char)0x32 /* List alarms that have occured. length 1 */
#define PW_EVENT_HISTORY_LOG_REQ (unsigned char)0x32 /* List alarms that have occurred. length 1 */
#define PW_STATUS_REQ (unsigned char)0x33 /* On Line, On Bypass, ... length 1-2 */
#define PW_METER_BLOCK_REQ (unsigned char)0x34 /* Current UPS status (Load, utility,...) length 1 */
#define PW_CUR_ALARM_REQ (unsigned char)0x35 /* Current alarm and event request. length 1 */
@ -355,7 +355,8 @@
#define BCMXCP_ALARM_HEATSINK_TEMP_SENSOR_FAIL 74
#define BCMXCP_ALARM_RECTIFIER_CURRENT_OVER_125 75
#define BCMXCP_ALARM_RECTIFIER_FAULT_INTERRUPT_FAIL 76
#define BCMXCP_ALARM_RECTIFIER_POWER_CAPASITOR_FAIL 77
#define BCMXCP_ALARM_RECTIFIER_POWER_CAPACITOR_FAIL 77
#define BCMXCP_ALARM_RECTIFIER_POWER_CAPASITOR_FAIL 77 /* Legacy - typo */
#define BCMXCP_ALARM_INVERTER_PROGRAM_STACK_ERROR 78
#define BCMXCP_ALARM_INVERTER_BOARD_SELFTEST_FAIL 79
#define BCMXCP_ALARM_INVERTER_AD_SELFTEST_FAIL 80
@ -411,7 +412,7 @@
#define BCMXCP_ALARM_LARGE_CHARGER_INPUT_CURRENT 130
#define BCMXCP_ALARM_INV_VOLT_TOO_LOW_FOR_RAMP_LEVEL 131
#define BCMXCP_ALARM_LOSS_OF_REDUNDANCY 132
#define BCMXCP_ALARM_LOSS_OF_SYNC_BUS 133
#define BCMXCP_ALARM_LOSS_OF_SYNC_BUS 133
#define BCMXCP_ALARM_RECTIFIER_BREAKER_SHUNT_TRIP 134
#define BCMXCP_ALARM_LOSS_OF_CHARGER_SYNC 135
#define BCMXCP_ALARM_INVERTER_LOW_LEVEL_TEST_TIMEOUT 136

View file

@ -1,6 +1,6 @@
/*
/*
* bcmxcp_io.h -- header for BCM/XCP IO module
*/
*/
#ifndef BCMXCP_IO__
#define BCMXCP_IO__
@ -8,10 +8,10 @@
#include "main.h" /* for usbdrv_info_t */
void send_read_command(unsigned char command);
void send_write_command(unsigned char *command, int command_length);
int get_answer(unsigned char *data, unsigned char command);
int command_read_sequence(unsigned char command, unsigned char *data);
int command_write_sequence(unsigned char *command, int command_length, unsigned char *answer);
void send_write_command(unsigned char *command, size_t command_length);
ssize_t get_answer(unsigned char *data, unsigned char command);
ssize_t command_read_sequence(unsigned char command, unsigned char *data);
ssize_t command_write_sequence(unsigned char *command, size_t command_length, unsigned char *answer);
void upsdrv_initups(void);
void upsdrv_cleanup(void);
void upsdrv_reconnect(void);

View file

@ -1,11 +1,12 @@
#include "main.h"
#include "bcmxcp.h"
#include "bcmxcp_io.h"
#include "bcmxcp_ser.h"
#include "serial.h"
#include "nut_stdint.h"
#define SUBDRIVER_NAME "RS-232 communication subdriver"
#define SUBDRIVER_VERSION "0.20"
#define SUBDRIVER_VERSION "0.21"
/* communication driver description structure */
upsdrv_info_t comm_upsdrv_info = {
@ -18,10 +19,8 @@ upsdrv_info_t comm_upsdrv_info = {
#define PW_MAX_BAUD 5
struct pw_baud_rate {
int rate;
int name;
} pw_baud_rates[] = {
/* NOT static: also used from nut-scanner, so extern'ed via bcmxcp_ser.h */
pw_baud_rate_t pw_baud_rates[] = {
{ B19200, 19200 },
{ B9600, 9600 },
{ B4800, 4800 },
@ -31,12 +30,19 @@ struct pw_baud_rate {
{ 0, 0 }
};
unsigned char AUT[4] = {0xCF, 0x69, 0xE8, 0xD5}; /* Autorisation command */
/* NOT static: also used from nut-scanner, so extern'ed via bcmxcp_ser.h */
unsigned char BCMXCP_AUTHCMD[4] = {0xCF, 0x69, 0xE8, 0xD5}; /* Authorisation command */
static void send_command(unsigned char *command, int command_length)
static void send_command(unsigned char *command, size_t command_length)
{
int retry = 0, sent;
unsigned char sbuf[128];
int retry = 0;
ssize_t sent;
unsigned char sbuf[1024];
if (command_length > UCHAR_MAX) {
upsdebugx (3, "%s: ERROR: command_length too long for the character protocol", __func__);
return;
}
/* Prepare the send buffer */
sbuf[0] = PW_COMMAND_START_BYTE;
@ -59,7 +65,12 @@ static void send_command(unsigned char *command, int command_length)
sent = ser_send_buf(upsfd, sbuf, command_length);
if (sent == command_length) {
if (sent < 0) {
upslogx(LOG_ERR, "%s(): error reading from ser_send_buf()", __func__);
return;
}
if ((size_t)sent == command_length) {
return;
}
}
@ -70,87 +81,90 @@ void send_read_command(unsigned char command)
send_command(&command, 1);
}
void send_write_command(unsigned char *command, int command_length)
void send_write_command(unsigned char *command, size_t command_length)
{
send_command(command, command_length);
}
/* get the answer of a command from the ups. And check that the answer is for this command */
int get_answer(unsigned char *data, unsigned char command)
ssize_t get_answer(unsigned char *data, unsigned char command)
{
unsigned char my_buf[128]; /* packet has a maximum length of 121+5 bytes */
int length, end_length = 0, res, endblock = 0, start = 0;
ssize_t res;
size_t length, end_length = 0, endblock = 0, start = 0;
unsigned char block_number, sequence, pre_sequence = 0;
while (endblock != 1){
while (endblock != 1) {
do {
/* Read PW_COMMAND_START_BYTE byte */
res = ser_get_char(upsfd, my_buf, 1, 0);
if (res != 1) {
upsdebugx(1,"Receive error (PW_COMMAND_START_BYTE): %d, cmd=%x!!!\n", res, command);
upsdebugx(1,
"Receive error (PW_COMMAND_START_BYTE): %zd, cmd=%x!!!\n",
res, command);
return -1;
}
start++;
} while ((my_buf[0] != PW_COMMAND_START_BYTE) && (start < 128));
if (start == 128) {
ser_comm_fail("Receive error (PW_COMMAND_START_BYTE): packet not on start!!%x\n", my_buf[0]);
return -1;
}
/* Read block number byte */
res = ser_get_char(upsfd, my_buf+1, 1, 0);
res = ser_get_char(upsfd, my_buf + 1, 1, 0);
if (res != 1) {
ser_comm_fail("Receive error (Block number): %d!!!\n", res);
ser_comm_fail("Receive error (Block number): %zd!!!\n", res);
return -1;
}
block_number = (unsigned char)my_buf[1];
if (command <= 0x43) {
if ((command - 0x30) != block_number){
if ((command - 0x30) != block_number) {
ser_comm_fail("Receive error (Request command): %x!!!\n", block_number);
return -1;
}
}
if (command >= 0x89) {
if ((command == 0xA0) && (block_number != 0x01)){
if ((command == 0xA0) && (block_number != 0x01)) {
ser_comm_fail("Receive error (Requested only mode command): %x!!!\n", block_number);
return -1;
}
if ((command != 0xA0) && (block_number != 0x09)){
if ((command != 0xA0) && (block_number != 0x09)) {
ser_comm_fail("Receive error (Control command): %x!!!\n", block_number);
return -1;
}
}
/* Read data length byte */
res = ser_get_char(upsfd, my_buf+2, 1, 0);
res = ser_get_char(upsfd, my_buf + 2, 1, 0);
if (res != 1) {
ser_comm_fail("Receive error (length): %d!!!\n", res);
ser_comm_fail("Receive error (length): %zd!!!\n", res);
return -1;
}
length = (unsigned char)my_buf[2];
if (length < 1) {
ser_comm_fail("Receive error (length): packet length %x!!!\n", length);
ser_comm_fail("Receive error (length): packet length %zx!!!\n", length);
return -1;
}
/* Read sequence byte */
res = ser_get_char(upsfd, my_buf+3, 1, 0);
res = ser_get_char(upsfd, my_buf + 3, 1, 0);
if (res != 1) {
ser_comm_fail("Receive error (sequence): %d!!!\n", res);
ser_comm_fail("Receive error (sequence): %zd!!!\n", res);
return -1;
}
@ -167,19 +181,23 @@ int get_answer(unsigned char *data, unsigned char command)
pre_sequence = sequence;
/* Try to read all the remainig bytes */
res = ser_get_buf_len(upsfd, my_buf+4, length, 1, 0);
/* Try to read all the remaining bytes */
res = ser_get_buf_len(upsfd, my_buf + 4, length, 1, 0);
if (res < 0) {
ser_comm_fail("%s(): ser_get_buf_len() returned error code %zd", __func__, res);
return res;
}
if (res != length) {
ser_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res, length);
if ((size_t)res != length) {
ser_comm_fail("Receive error (data): got %zd bytes instead of %zu!!!\n", res, length);
return -1;
}
/* Get the checksum byte */
res = ser_get_char(upsfd, my_buf+(4+length), 1, 0);
res = ser_get_char(upsfd, my_buf + (4 + length), 1, 0);
if (res != 1) {
ser_comm_fail("Receive error (checksum): %x!!!\n", res);
ser_comm_fail("Receive error (checksum): %zx!!!\n", res);
return -1;
}
@ -189,7 +207,7 @@ int get_answer(unsigned char *data, unsigned char command)
return -1;
}
memcpy(data+end_length, my_buf+4, length);
memcpy(data+end_length, my_buf + 4, length);
end_length += length;
}
@ -197,12 +215,14 @@ int get_answer(unsigned char *data, unsigned char command)
upsdebug_hex (5, "get_answer", data, end_length);
ser_comm_good();
return end_length;
assert(end_length < SSIZE_MAX);
return (ssize_t)end_length;
}
static int command_sequence(unsigned char *command, int command_length, unsigned char *answer)
static ssize_t command_sequence(unsigned char *command, size_t command_length, unsigned char *answer)
{
int bytes_read, retry = 0;
ssize_t bytes_read;
int retry = 0;
while (retry++ < PW_MAX_TRY) {
@ -223,9 +243,9 @@ static int command_sequence(unsigned char *command, int command_length, unsigned
}
/* Sends a single command (length=1). and get the answer */
int command_read_sequence(unsigned char command, unsigned char *answer)
ssize_t command_read_sequence(unsigned char command, unsigned char *answer)
{
int bytes_read;
ssize_t bytes_read;
bytes_read = command_sequence(&command, 1, answer);
@ -237,9 +257,9 @@ int command_read_sequence(unsigned char command, unsigned char *answer)
}
/* Sends a setup command (length > 1) */
int command_write_sequence(unsigned char *command, int command_length, unsigned char *answer)
ssize_t command_write_sequence(unsigned char *command, size_t command_length, unsigned char *answer)
{
int bytes_read;
ssize_t bytes_read;
bytes_read = command_sequence(command, command_length, answer);
@ -255,18 +275,80 @@ void upsdrv_comm_good()
ser_comm_good();
}
void pw_comm_setup(const char *port)
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic push
#endif
#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC)
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC)
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
static void pw_comm_setup(const char *port)
{
unsigned char command = PW_SET_REQ_ONLY_MODE;
unsigned char id_command = PW_ID_BLOCK_REQ;
unsigned char answer[256];
int i = 0, baud, mybaud = 0, ret = -1;
int i = 0;
ssize_t ret = -1;
speed_t mybaud = 0, baud;
if (getval("baud_rate") != NULL)
{
baud = atoi(getval("baud_rate"));
for(i = 0; i < PW_MAX_BAUD; i++) {
int br = atoi(getval("baud_rate"));
/* Note that atoi() behavior on erroneous input is undefined */
if (br < 0) {
upslogx(LOG_ERR, "baud_rate option is invalid");
return;
}
/* FIXME: speed_t does not define a SPEED_MAX value nor
* guarantee that it is an int (just a typedef from
* termios.h happens to say that on some systems)...
* But since we convert this setting from int, we assume...
*/
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
/* Note for gating macros above: unsuffixed HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP
* means support of contexts both inside and outside function body, so the push
* above and pop below (outside this finction) are not used.
*/
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS
/* Note that the individual warning pragmas for use inside function bodies
* are named without a _INSIDEFUNC suffix, for simplicity and legacy reasons
*/
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#pragma clang diagnostic ignored "-Wtautological-compare"
#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
switch(sizeof(speed_t)) {
case 8: assert (br < INT64_MAX); break;
case 4: assert (br < INT32_MAX); break;
case 2: assert (br < INT16_MAX); break;
default: assert (br < INT_MAX);
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic pop
#endif
baud = (speed_t)br;
for (i = 0; i < PW_MAX_BAUD; i++) {
if (baud == pw_baud_rates[i].name) {
mybaud = pw_baud_rates[i].rate;
break;
@ -280,7 +362,7 @@ void pw_comm_setup(const char *port)
ser_set_speed(upsfd, device_path, mybaud);
ser_send_char(upsfd, 0x1d); /* send ESC to take it out of menu */
usleep(90000);
send_write_command(AUT, 4);
send_write_command(BCMXCP_AUTHCMD, 4);
usleep(500000);
ret = command_sequence(&command, 1, answer);
if (ret <= 0) {
@ -289,11 +371,14 @@ void pw_comm_setup(const char *port)
}
if (ret > 0) {
upslogx(LOG_INFO, "Connected to UPS on %s with baudrate %d", port, baud);
/* Cast baud into max length unsigned, despite the POSIX
* standard some systems vary in definition of this type
*/
upslogx(LOG_INFO, "Connected to UPS on %s with baudrate %llu", port, (unsigned long long int)baud);
return;
}
upslogx(LOG_ERR, "No response from UPS on %s with baudrate %d", port, baud);
upslogx(LOG_ERR, "No response from UPS on %s with baudrate %llu", port, (unsigned long long int)baud);
}
upslogx(LOG_INFO, "Attempting to autodect baudrate");
@ -303,7 +388,7 @@ void pw_comm_setup(const char *port)
ser_set_speed(upsfd, device_path, pw_baud_rates[i].rate);
ser_send_char(upsfd, 0x1d); /* send ESC to take it out of menu */
usleep(90000);
send_write_command(AUT, 4);
send_write_command(BCMXCP_AUTHCMD, 4);
usleep(500000);
ret = command_sequence(&command, 1, answer);
if (ret <= 0) {
@ -312,15 +397,18 @@ void pw_comm_setup(const char *port)
}
if (ret > 0) {
upslogx(LOG_INFO, "Connected to UPS on %s with baudrate %d", port, pw_baud_rates[i].name);
upslogx(LOG_INFO, "Connected to UPS on %s with baudrate %zu", port, pw_baud_rates[i].name);
return;
}
upsdebugx(2, "No response from UPS on %s with baudrate %d", port, pw_baud_rates[i].name);
upsdebugx(2, "No response from UPS on %s with baudrate %zu", port, pw_baud_rates[i].name);
}
fatalx(EXIT_FAILURE, "Can't connect to the UPS on port %s!\n", port);
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic pop
#endif
void upsdrv_initups(void)
{

22
drivers/bcmxcp_ser.h Normal file
View file

@ -0,0 +1,22 @@
/*
* bcmxcp_ser.h -- header for BCM/XCP RS-232 module
*/
#ifndef BCMXCP_SER__
#define BCMXCP_SER__
#include "serial.h" /* pulls termios.h to define speed_t */
/* This header is needed for this line, to avoid warnings about it not
* being static in C file (can't hide, is also needed by nut-scanner)
*/
extern unsigned char BCMXCP_AUTHCMD[4];
typedef struct {
speed_t rate; /* Value like B19200 defined in termios.h; note: NOT the bitrate numerically */
size_t name; /* Actual rate... WHY is this "name" - number to print interactively? */
} pw_baud_rate_t;
extern pw_baud_rate_t pw_baud_rates[];
#endif /* BCMXCP_SER__ */

View file

@ -9,10 +9,9 @@
#include <sys/file.h>
#include <sys/types.h>
#include <unistd.h>
#include <usb.h>
#define SUBDRIVER_NAME "USB communication subdriver"
#define SUBDRIVER_VERSION "0.22"
#define SUBDRIVER_VERSION "0.27"
/* communication driver description structure */
upsdrv_info_t comm_upsdrv_info = {
@ -34,6 +33,8 @@ upsdrv_info_t comm_upsdrv_info = {
/* Hewlett Packard */
#define HP_VENDORID 0x03f0
static USBDevice_t curDevice;
/* USB functions */
usb_dev_handle *nutusb_open(const char *port);
int nutusb_close(usb_dev_handle *dev_h, const char *port);
@ -42,27 +43,36 @@ void nutusb_comm_fail(const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
void nutusb_comm_good(void);
/* function pointer, set depending on which device is used */
int (*usb_set_descriptor)(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, int size);
/* FIXME? Use usb_ctrl_* typedefs*/
static int (*usb_set_descriptor)(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, size_t size);
/* usb_set_descriptor() for Powerware devices */
static int usb_set_powerware(usb_dev_handle *udev, unsigned char type, unsigned char index, void *buf, int size)
/* FIXME? Use usb_ctrl_* typedefs*/
static int usb_set_powerware(usb_dev_handle *udev, unsigned char type, unsigned char index, void *buf, size_t size)
{
return usb_control_msg(udev, USB_ENDPOINT_OUT, USB_REQ_SET_DESCRIPTOR, (type << 8) + index, 0, buf, size, 1000);
assert (size < INT_MAX);
return usb_control_msg(udev, USB_ENDPOINT_OUT, USB_REQ_SET_DESCRIPTOR, (type << 8) + index, 0, buf, (int)size, 1000);
}
static void *powerware_ups(USBDevice_t *device) {
NUT_UNUSED_VARIABLE(device);
usb_set_descriptor = &usb_set_powerware;
return NULL;
}
/* usb_set_descriptor() for Phoenixtec devices */
static int usb_set_phoenixtec(usb_dev_handle *udev, unsigned char type, unsigned char index, void *buf, int size)
/* FIXME? Use usb_ctrl_* typedefs*/
static int usb_set_phoenixtec(usb_dev_handle *udev, unsigned char type, unsigned char index, void *buf, size_t size)
{
return usb_control_msg(udev, 0x42, 0x0d, (0x00 << 8) + 0x0, 0, buf, size, 1000);
NUT_UNUSED_VARIABLE(index);
NUT_UNUSED_VARIABLE(type);
assert (size < INT_MAX);
return usb_control_msg(udev, 0x42, 0x0d, (0x00 << 8) + 0x0, 0, buf, (int)size, 1000);
}
static void *phoenixtec_ups(USBDevice_t *device) {
NUT_UNUSED_VARIABLE(device);
usb_set_descriptor = &usb_set_phoenixtec;
return NULL;
}
@ -79,18 +89,18 @@ static usb_device_id_t pw_usb_device_table[] = {
{ USB_DEVICE(HP_VENDORID, 0x1f01), &phoenixtec_ups },
/* T750 */
{ USB_DEVICE(HP_VENDORID, 0x1f02), &phoenixtec_ups },
/* Terminating entry */
{ -1, -1, NULL }
{ 0, 0, NULL }
};
/* limit the amount of spew that goes in the syslog when we lose the UPS */
#define USB_ERR_LIMIT 10 /* start limiting after 10 in a row */
#define USB_ERR_RATE 10 /* then only print every 10th error */
#define XCP_USB_TIMEOUT 5000
#define XCP_USB_TIMEOUT 5000 /* in msec */
/* global variables */
usb_dev_handle *upsdev = NULL;
static usb_dev_handle *upsdev = NULL;
extern int exit_flag;
static unsigned int comm_failures = 0;
@ -109,7 +119,7 @@ void send_read_command(unsigned char command)
}
}
void send_write_command(unsigned char *command, int command_length)
void send_write_command(unsigned char *command, size_t command_length)
{
unsigned char sbuf[128];
@ -131,11 +141,14 @@ void send_write_command(unsigned char *command, int command_length)
#define PW_HEADER_SIZE (PW_HEADER_LENGTH + 1)
#define PW_CMD_BUFSIZE 256
/* get the answer of a command from the ups. And check that the answer is for this command */
int get_answer(unsigned char *data, unsigned char command)
ssize_t get_answer(unsigned char *data, unsigned char command)
{
unsigned char buf[PW_CMD_BUFSIZE], *my_buf = buf;
int length, end_length, res, endblock, bytes_read, ellapsed_time, need_data;
int tail;
ssize_t res;
int endblock, need_data;
long elapsed_time; /* milliseconds */
ssize_t tail;
size_t bytes_read, end_length, length;
unsigned char block_number, sequence, seq_num;
struct timeval start_time, now;
@ -147,7 +160,7 @@ int get_answer(unsigned char *data, unsigned char command)
endblock = 0; /* signal the last sequence in the block */
bytes_read = 0; /* total length of data read, including XCP header */
res = 0;
ellapsed_time = 0;
elapsed_time = 0;
seq_num = 1; /* current theoric sequence */
upsdebugx(1, "entering get_answer(%x)", command);
@ -156,17 +169,38 @@ int get_answer(unsigned char *data, unsigned char command)
gettimeofday(&start_time, NULL);
memset(&buf, 0x0, PW_CMD_BUFSIZE);
while ( (!endblock) && ((XCP_USB_TIMEOUT - ellapsed_time) > 0) ) {
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
/* Stay ahead of possible redefinitions... */
assert (XCP_USB_TIMEOUT < INT_MAX);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic pop
#endif
while ( (!endblock) && ((XCP_USB_TIMEOUT - elapsed_time) > 0) ) {
/* Get (more) data if needed */
if (need_data > 0) {
res = usb_interrupt_read(upsdev, 0x81, (char *) buf + bytes_read,
res = usb_interrupt_read(upsdev,
0x81,
(usb_ctrl_charbuf) buf + bytes_read,
128,
(XCP_USB_TIMEOUT - ellapsed_time));
(int)(XCP_USB_TIMEOUT - elapsed_time));
/* Update time */
gettimeofday(&now, NULL);
ellapsed_time = (now.tv_sec - start_time.tv_sec)*1000 +
elapsed_time = (now.tv_sec - start_time.tv_sec)*1000 +
(now.tv_usec - start_time.tv_usec)/1000;
/* Check libusb return value */
@ -185,13 +219,13 @@ int get_answer(unsigned char *data, unsigned char command)
continue;
}
/* Else, we got some input bytes */
bytes_read += res;
bytes_read += (size_t)res;
need_data -= res;
upsdebug_hex(1, "get_answer", buf, bytes_read);
}
if (need_data > 0) /* We need more data */
continue;
continue;
/* Now validate XCP frame */
/* Check header */
@ -200,7 +234,7 @@ int get_answer(unsigned char *data, unsigned char command)
/* Sometime we read something wrong. bad cables? bad ports? */
my_buf = memchr(my_buf, PW_COMMAND_START_BYTE, bytes_read);
if (!my_buf)
return -1;
return -1;
}
/* Read block number byte */
@ -209,8 +243,8 @@ int get_answer(unsigned char *data, unsigned char command)
/* Check data length byte (remove the header length) */
length = my_buf[2];
upsdebugx(3, "get_answer: data length = %d", length);
if (bytes_read - (length + PW_HEADER_SIZE) < 0) {
upsdebugx(3, "get_answer: data length = %zu", length);
if (bytes_read < (length + PW_HEADER_SIZE)) {
if (need_data < 0) --need_data; /* count zerro byte too */
need_data += length + 1; /* packet lenght + checksum */
upsdebugx(2, "get_answer: need to read %d more data", need_data);
@ -223,6 +257,11 @@ int get_answer(unsigned char *data, unsigned char command)
return -1;
}
if (bytes_read >= SSIZE_MAX) {
upsdebugx(2, "get_answer: bad length (incredibly large read)");
return -1;
}
/* Test the Sequence # */
sequence = my_buf[3];
if ((sequence & PW_SEQ_MASK) != seq_num) {
@ -257,24 +296,33 @@ int get_answer(unsigned char *data, unsigned char command)
memcpy(data+end_length, my_buf + 4, length);
/* increment pointers to process the next sequence */
end_length += length;
tail = bytes_read - (length + PW_HEADER_SIZE);
/* Work around signedness of comparison result, SSIZE_MAX checked above: */
tail = (ssize_t)bytes_read;
tail -= (ssize_t)(length + PW_HEADER_SIZE);
if (tail > 0)
my_buf = memmove(&buf[0], my_buf + length + PW_HEADER_SIZE, tail);
my_buf = memmove(&buf[0], my_buf + length + PW_HEADER_SIZE, (size_t)tail);
else if (tail == 0)
my_buf = &buf[0];
bytes_read = tail;
my_buf = &buf[0];
else { /* if (tail < 0) */
upsdebugx(1, "get_answer(): did not expect to get negative tail size: %zd", tail);
return -1;
}
bytes_read = (size_t)tail;
}
upsdebug_hex (5, "get_answer", data, end_length);
return end_length;
assert (end_length < SSIZE_MAX);
return (ssize_t)end_length;
}
/* Sends a single command (length=1). and get the answer */
int command_read_sequence(unsigned char command, unsigned char *data)
ssize_t command_read_sequence(unsigned char command, unsigned char *data)
{
int bytes_read = 0;
int retry = 0;
ssize_t bytes_read = 0;
size_t retry = 0;
while ((bytes_read < 1) && (retry < 5)) {
send_read_command(command);
bytes_read = get_answer(data, command);
@ -291,10 +339,10 @@ int command_read_sequence(unsigned char command, unsigned char *data)
}
/* Sends a setup command (length > 1) */
int command_write_sequence(unsigned char *command, int command_length, unsigned char *answer)
ssize_t command_write_sequence(unsigned char *command, size_t command_length, unsigned char *answer)
{
int bytes_read = 0;
int retry = 0;
ssize_t bytes_read = 0;
size_t retry = 0;
while ((bytes_read < 1) && (retry < 5)) {
send_write_command(command, command_length);
@ -327,6 +375,11 @@ void upsdrv_cleanup(void)
{
upslogx(LOG_ERR, "CLOSING\n");
nutusb_close(upsdev, "USB");
free(curDevice.Vendor);
free(curDevice.Product);
free(curDevice.Serial);
free(curDevice.Bus);
free(curDevice.Device);
}
void upsdrv_reconnect(void)
@ -341,6 +394,9 @@ void upsdrv_reconnect(void)
}
/* USB functions */
static void nutusb_open_error(const char *port)
__attribute__((noreturn));
static void nutusb_open_error(const char *port)
{
printf("Unable to find POWERWARE UPS device on USB bus (%s)\n\n", port);
@ -356,14 +412,59 @@ static void nutusb_open_error(const char *port)
/* FIXME: this part of the opening can go into common... */
static usb_dev_handle *open_powerware_usb(void)
{
struct usb_bus *busses = usb_get_busses();
#if WITH_LIBUSB_1_0
libusb_device **devlist;
ssize_t devcount = 0;
libusb_device_handle *udev;
struct libusb_device_descriptor dev_desc;
uint8_t bus;
int i;
devcount = libusb_get_device_list(NULL, &devlist);
if (devcount <= 0)
fatal_with_errno(EXIT_FAILURE, "No USB device found");
for (i = 0; i < devcount; i++) {
libusb_device *device = devlist[i];
libusb_get_device_descriptor(device, &dev_desc);
if (dev_desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) {
continue;
}
curDevice.VendorID = dev_desc.idVendor;
curDevice.ProductID = dev_desc.idProduct;
bus = libusb_get_bus_number(device);
curDevice.Bus = (char *)malloc(4);
if (curDevice.Bus == NULL) {
libusb_free_device_list(devlist, 1);
fatal_with_errno(EXIT_FAILURE, "Out of memory");
}
sprintf(curDevice.Bus, "%03d", bus);
/* FIXME: we should also retrieve
* dev->descriptor.iManufacturer
* dev->descriptor.iProduct
* dev->descriptor.iSerialNumber
* as in libusb.c->libusb_open()
* This is part of the things to put in common... */
if (is_usb_device_supported(pw_usb_device_table, &curDevice) == SUPPORTED) {
libusb_open(device, &udev);
libusb_free_device_list(devlist, 1);
return udev;
}
}
libusb_free_device_list(devlist, 1);
#else /* not WITH_LIBUSB_1_0 */
struct usb_bus *busses = usb_get_busses();
struct usb_bus *bus;
USBDevice_t curDevice;
for (bus = busses; bus; bus = bus->next)
{
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next)
{
if (dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE) {
@ -372,7 +473,7 @@ static usb_dev_handle *open_powerware_usb(void)
curDevice.VendorID = dev->descriptor.idVendor;
curDevice.ProductID = dev->descriptor.idProduct;
curDevice.Bus = strdup(bus->dirname);
curDevice.Bus = xstrdup(bus->dirname);
/* FIXME: we should also retrieve
* dev->descriptor.iManufacturer
@ -386,6 +487,7 @@ static usb_dev_handle *open_powerware_usb(void)
}
}
}
#endif /* WITH_LIBUSB_1_0 */
return 0;
}
@ -394,13 +496,22 @@ usb_dev_handle *nutusb_open(const char *port)
int dev_claimed = 0;
usb_dev_handle *dev_h = NULL;
int retry, errout = 0;
int ret = 0;
upsdebugx(1, "entering nutusb_open()");
warn_if_bad_usb_port_filename(device_path);
/* Initialize Libusb */
#if WITH_LIBUSB_1_0
if (libusb_init(NULL) < 0) {
libusb_exit(NULL);
fatal_with_errno(EXIT_FAILURE, "Failed to init libusb 1.0");
}
#else /* not WITH_LIBUSB_1_0 */
usb_init();
usb_find_busses();
usb_find_devices();
#endif /* WITH_LIBUSB_1_0 */
for (retry = 0; retry < MAX_TRY ; retry++)
{
@ -410,12 +521,12 @@ usb_dev_handle *nutusb_open(const char *port)
errout = 1;
}
else {
upsdebugx(1, "device %s opened successfully", usb_device(dev_h)->filename);
upsdebugx(1, "device %s opened successfully", curDevice.Bus);
errout = 0;
if (usb_claim_interface(dev_h, 0) < 0)
if ((ret = usb_claim_interface(dev_h, 0)) < 0)
{
upsdebugx(1, "Can't claim POWERWARE USB interface: %s", usb_strerror());
upsdebugx(1, "Can't claim POWERWARE USB interface: %s", nut_usb_strerror(ret));
errout = 1;
}
else {
@ -424,11 +535,11 @@ usb_dev_handle *nutusb_open(const char *port)
}
/* FIXME: the above part of the opening can go into common... up to here at least */
if (usb_clear_halt(dev_h, 0x81) < 0)
if ((ret = usb_clear_halt(dev_h, 0x81)) < 0)
{
upsdebugx(1, "Can't reset POWERWARE USB endpoint: %s", usb_strerror());
upsdebugx(1, "Can't reset POWERWARE USB endpoint: %s", nut_usb_strerror(ret));
if (dev_claimed)
usb_release_interface(dev_h, 0);
usb_release_interface(dev_h, 0);
usb_reset(dev_h);
sleep(5); /* Wait reconnect */
errout = 1;
@ -454,8 +565,7 @@ usb_dev_handle *nutusb_open(const char *port)
if (dev_h && dev_claimed)
usb_release_interface(dev_h, 0);
if (dev_h)
usb_close(dev_h);
nutusb_close(dev_h, port);
if (errout == 1)
nutusb_open_error(port);
@ -466,13 +576,21 @@ usb_dev_handle *nutusb_open(const char *port)
/* FIXME: this part can go into common... */
int nutusb_close(usb_dev_handle *dev_h, const char *port)
{
int ret = 0;
NUT_UNUSED_VARIABLE(port);
if (dev_h)
{
usb_release_interface(dev_h, 0);
return usb_close(dev_h);
#if WITH_LIBUSB_1_0
libusb_close(dev_h);
libusb_exit(NULL);
#else
ret = usb_close(dev_h);
#endif
}
return 0;
return ret;
}
void nutusb_comm_fail(const char *fmt, ...)
@ -529,4 +647,3 @@ void nutusb_comm_good(void)
upslogx(LOG_NOTICE, "Communications with UPS re-established");
comm_failures = 0;
}

View file

@ -1,7 +1,7 @@
/* belkin-hid.c - data to monitor Belkin UPS Systems USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2008 Arnaud Quette <arnaud.quette@free.fr>
* 2003 - 2008 Arnaud Quette <arnaud.quette@free.fr>
* 2005 Peter Selinger <selinger@users.sourceforge.net>
* 2011, 2014 Charles Lepple <clepple+nut@gmail>
*
@ -29,7 +29,9 @@
#include "belkin-hid.h"
#include "usb-common.h"
#define BELKIN_HID_VERSION "Belkin/Liebert HID 0.17"
#include <math.h> /* for fabs() */
#define BELKIN_HID_VERSION "Belkin/Liebert HID 0.18"
/* Belkin */
#define BELKIN_VENDORID 0x050d
@ -65,6 +67,8 @@ static usb_device_id_t belkin_usb_device_table[] = {
/* F6C1100-UNV, F6C1200-UNV */
{ USB_DEVICE(BELKIN_VENDORID, 0x1100), NULL },
/* Liebert GXT4 UPS */
{ USB_DEVICE(LIEBERT_VENDORID, 0x0004), NULL },
/* Liebert PowerSure PSA UPS */
{ USB_DEVICE(LIEBERT_VENDORID, 0x0001), NULL },
/* Liebert PowerSure PSI 1440 */
@ -73,7 +77,7 @@ static usb_device_id_t belkin_usb_device_table[] = {
{ USB_DEVICE(LIEBERT_VENDORID, 0x0008), NULL },
/* Terminating entry */
{ -1, -1, NULL }
{ 0, 0, NULL }
};
static const char *liebert_online_fun(double value);
@ -86,35 +90,35 @@ static const char *liebert_config_voltage_fun(double value);
static const char *liebert_line_voltage_fun(double value);
static info_lkp_t liebert_online_info[] = {
{ 0, NULL, liebert_online_fun }
{ 0, NULL, liebert_online_fun, NULL }
};
static info_lkp_t liebert_discharging_info[] = {
{ 0, NULL, liebert_discharging_fun }
{ 0, NULL, liebert_discharging_fun, NULL }
};
static info_lkp_t liebert_charging_info[] = {
{ 0, NULL, liebert_charging_fun }
{ 0, NULL, liebert_charging_fun, NULL }
};
static info_lkp_t liebert_lowbatt_info[] = {
{ 0, NULL, liebert_lowbatt_fun }
{ 0, NULL, liebert_lowbatt_fun, NULL }
};
static info_lkp_t liebert_replacebatt_info[] = {
{ 0, NULL, liebert_replacebatt_fun }
{ 0, NULL, liebert_replacebatt_fun, NULL }
};
static info_lkp_t liebert_shutdownimm_info[] = {
{ 0, NULL, liebert_shutdownimm_fun }
{ 0, NULL, liebert_shutdownimm_fun, NULL }
};
static info_lkp_t liebert_config_voltage_info[] = {
{ 0, NULL, liebert_config_voltage_fun },
{ 0, NULL, liebert_config_voltage_fun, NULL },
};
static info_lkp_t liebert_line_voltage_info[] = {
{ 0, NULL, liebert_line_voltage_fun },
{ 0, NULL, liebert_line_voltage_fun, NULL },
};
static double liebert_config_voltage_mult = 1.0;
@ -161,7 +165,7 @@ static const char *liebert_shutdownimm_fun(double value)
static const char *liebert_config_voltage_fun(double value)
{
if( value < 1 ) {
if( abs(value - 1e-7) < 1e-9 ) {
if( fabs(value - 1e-7) < 1e-9 ) {
liebert_config_voltage_mult = 1e8;
liebert_line_voltage_mult = 1e7; /* stomp this in case input voltage was low */
upsdebugx(2, "ConfigVoltage = %g -> assuming correction factor = %g",
@ -179,7 +183,7 @@ static const char *liebert_config_voltage_fun(double value)
static const char *liebert_line_voltage_fun(double value)
{
if( value < 1 ) {
if( abs(value - 1e-7) < 1e-9 ) {
if( fabs(value - 1e-7) < 1e-9 ) {
liebert_line_voltage_mult = 1e7;
upsdebugx(2, "Input/OutputVoltage = %g -> assuming correction factor = %g",
value, liebert_line_voltage_mult);
@ -207,7 +211,7 @@ static const char *belkin_firmware_conversion_fun(double value)
}
static info_lkp_t belkin_firmware_conversion[] = {
{ 0, NULL, belkin_firmware_conversion_fun }
{ 0, NULL, belkin_firmware_conversion_fun, NULL }
};
static const char *belkin_upstype_conversion_fun(double value)
@ -230,7 +234,7 @@ static const char *belkin_upstype_conversion_fun(double value)
}
static info_lkp_t belkin_upstype_conversion[] = {
{ 0, NULL, belkin_upstype_conversion_fun }
{ 0, NULL, belkin_upstype_conversion_fun, NULL }
};
static const char *belkin_sensitivity_conversion_fun(double value)
@ -247,17 +251,17 @@ static const char *belkin_sensitivity_conversion_fun(double value)
}
static info_lkp_t belkin_sensitivity_conversion[] = {
{ 0, NULL, belkin_sensitivity_conversion_fun }
{ 0, NULL, belkin_sensitivity_conversion_fun, NULL }
};
static info_lkp_t belkin_test_info[] = {
{ 0, "No test initiated", NULL },
{ 1, "Done and passed", NULL },
{ 2, "Done and warning", NULL },
{ 3, "Done and error", NULL },
{ 4, "Aborted", NULL },
{ 5, "In progress", NULL },
{ 0, NULL, NULL }
{ 0, "No test initiated", NULL, NULL },
{ 1, "Done and passed", NULL, NULL },
{ 2, "Done and warning", NULL, NULL },
{ 3, "Done and error", NULL, NULL },
{ 4, "Aborted", NULL, NULL },
{ 5, "In progress", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static const char *belkin_overload_conversion_fun(double value)
@ -270,7 +274,7 @@ static const char *belkin_overload_conversion_fun(double value)
}
static info_lkp_t belkin_overload_conversion[] = {
{ 0, NULL, belkin_overload_conversion_fun }
{ 0, NULL, belkin_overload_conversion_fun, NULL }
};
static const char *belkin_overheat_conversion_fun(double value)
@ -283,7 +287,7 @@ static const char *belkin_overheat_conversion_fun(double value)
}
static info_lkp_t belkin_overheat_conversion[] = {
{ 0, NULL, belkin_overheat_conversion_fun }
{ 0, NULL, belkin_overheat_conversion_fun, NULL }
};
static const char *belkin_commfault_conversion_fun(double value)
@ -296,7 +300,7 @@ static const char *belkin_commfault_conversion_fun(double value)
}
static info_lkp_t belkin_commfault_conversion[] = {
{ 0, NULL, belkin_commfault_conversion_fun }
{ 0, NULL, belkin_commfault_conversion_fun, NULL }
};
static const char *belkin_awaitingpower_conversion_fun(double value)
@ -309,7 +313,7 @@ static const char *belkin_awaitingpower_conversion_fun(double value)
}
static info_lkp_t belkin_awaitingpower_conversion[] = {
{ 0, NULL, belkin_awaitingpower_conversion_fun }
{ 0, NULL, belkin_awaitingpower_conversion_fun, NULL }
};
static const char *belkin_online_conversion_fun(double value)
@ -322,7 +326,7 @@ static const char *belkin_online_conversion_fun(double value)
}
static info_lkp_t belkin_online_conversion[] = {
{ 0, NULL, belkin_online_conversion_fun }
{ 0, NULL, belkin_online_conversion_fun, NULL }
};
static const char *belkin_lowbatt_conversion_fun(double value)
@ -335,7 +339,7 @@ static const char *belkin_lowbatt_conversion_fun(double value)
}
static info_lkp_t belkin_lowbatt_conversion[] = {
{ 0, NULL, belkin_lowbatt_conversion_fun }
{ 0, NULL, belkin_lowbatt_conversion_fun, NULL }
};
static const char *belkin_depleted_conversion_fun(double value)
@ -348,7 +352,7 @@ static const char *belkin_depleted_conversion_fun(double value)
}
static info_lkp_t belkin_depleted_conversion[] = {
{ 0, NULL, belkin_depleted_conversion_fun }
{ 0, NULL, belkin_depleted_conversion_fun, NULL }
};
static const char *belkin_replacebatt_conversion_fun(double value)
@ -361,7 +365,7 @@ static const char *belkin_replacebatt_conversion_fun(double value)
}
static info_lkp_t belkin_replacebatt_conversion[] = {
{ 0, NULL, belkin_replacebatt_conversion_fun }
{ 0, NULL, belkin_replacebatt_conversion_fun, NULL }
};
/* --------------------------------------------------------------- */
@ -637,4 +641,5 @@ subdriver_t belkin_subdriver = {
belkin_format_model,
belkin_format_mfr,
belkin_format_serial,
fix_report_desc,
};

View file

@ -1,7 +1,7 @@
/* belkin-hid.h - data to monitor Belkin UPS Systems USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2005 Arnaud Quette <arnaud.quette@free.fr>
* Copyright (C)
* 2003 - 2005 Arnaud Quette <arnaud.quette@free.fr>
* 2005 Peter Selinger <selinger@users.sourceforge.net>
*
* Sponsored by MGE UPS SYSTEMS <http://www.mgeups.com>

View file

@ -28,10 +28,10 @@
#include "belkin.h"
#define DRIVER_NAME "Belkin Smart protocol driver"
#define DRIVER_VERSION "0.24"
#define DRIVER_VERSION "0.25"
static int init_communication(void);
static int get_belkin_reply(char *buf);
static ssize_t init_communication(void);
static ssize_t get_belkin_reply(char *buf);
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -51,9 +51,10 @@ static void send_belkin_command(char cmd, const char *subcmd, const char *data)
upsdebugx(3, "Send Command: %s, %s", subcmd, data);
}
static int init_communication(void)
static ssize_t init_communication(void)
{
int i, res;
int i;
ssize_t res;
char temp[SMALLBUF];
for (i = 0; i < 10; i++) {
@ -107,9 +108,9 @@ static char *get_belkin_field(const char *in, char *out, size_t outlen, size_t n
return NULL;
}
static int get_belkin_reply(char *buf)
static ssize_t get_belkin_reply(char *buf)
{
int ret;
ssize_t ret;
long cnt;
char tmp[8];
@ -119,10 +120,11 @@ static int get_belkin_reply(char *buf)
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 2, 0);
if (ret != 7) {
ser_comm_fail("Initial read returned %d bytes", ret);
ser_comm_fail("Initial read returned %zd bytes", ret);
return -1;
}
/* cnt is <=999 so long is overkill; ok to cast into useconds_t though */
tmp[7] = 0;
cnt = strtol(tmp + 4, NULL, 10);
upsdebugx(3, "Received: %s", tmp);
@ -137,15 +139,15 @@ static int get_belkin_reply(char *buf)
}
/* give it time to respond to us */
usleep(5000 * cnt);
usleep(5000 * (useconds_t)cnt);
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 2, 0);
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, (size_t)cnt, 2, 0);
buf[cnt] = 0;
upsdebugx(3, "Received: %s", buf);
if (ret != cnt) {
ser_comm_fail("Second read returned %d bytes, expected %ld", ret, cnt);
ser_comm_fail("Second read returned %zd bytes, expected %ld", ret, cnt);
return -1;
}
@ -154,9 +156,9 @@ static int get_belkin_reply(char *buf)
return ret;
}
static int do_broken_rat(char *buf)
static ssize_t do_broken_rat(char *buf)
{
int ret;
ssize_t ret;
long cnt;
char tmp[8];
@ -166,10 +168,11 @@ static int do_broken_rat(char *buf)
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 2, 0);
if (ret != 7) {
ser_comm_fail("Initial read returned %d bytes", ret);
ser_comm_fail("Initial read returned %zd bytes", ret);
return -1;
}
/* cnt is <=999 so long is overkill; ok to cast into useconds_t though */
tmp[7] = 0;
cnt = strtol(tmp + 4, NULL, 10);
upsdebugx(3, "Received: %s", tmp);
@ -184,20 +187,20 @@ static int do_broken_rat(char *buf)
}
/* give it time to respond to us */
usleep(5000 * cnt);
usleep(5000 * (useconds_t)cnt);
/* firmware 001 only sends 50 bytes instead of the proper 53 */
if (cnt == 53) {
cnt = 50;
}
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 2, 0);
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, (size_t)cnt, 2, 0);
buf[cnt] = 0;
upsdebugx(3, "Received: %s", buf);
if (ret != cnt) {
ser_comm_fail("Second read returned %d bytes, expected %ld", ret, cnt);
ser_comm_fail("Second read returned %zd bytes, expected %ld", ret, cnt);
return -1;
}
@ -210,7 +213,7 @@ static int do_broken_rat(char *buf)
void upsdrv_updateinfo(void)
{
static int retry = 0;
int res;
ssize_t res;
char temp[SMALLBUF], st[SMALLBUF];
send_belkin_command(STATUS, STAT_STATUS, "");
@ -262,14 +265,14 @@ void upsdrv_updateinfo(void)
get_belkin_field(temp, st, sizeof(st), 10);
res = atoi(st);
get_belkin_field(temp, st, sizeof(st), 2);
if (*st == '1' || res < LOW_BAT) {
status_set("LB"); /* low battery */
}
get_belkin_field(temp, st, sizeof(st), 10);
dstate_setinfo("battery.charge", "%.0f", strtod(st, NULL));
get_belkin_field(temp, st, sizeof(st), 9);
dstate_setinfo("battery.temperature", "%.0f", strtod(st, NULL));
@ -302,7 +305,7 @@ void upsdrv_updateinfo(void)
get_belkin_field(temp, st, sizeof(st), 7);
dstate_setinfo("ups.load", "%.0f", strtod(st, NULL));
}
send_belkin_command(STATUS, TEST_RESULT, "");
res = get_belkin_reply(temp);
if (res > 0) {
@ -348,7 +351,7 @@ void upsdrv_updateinfo(void)
/* power down the attached load immediately */
void upsdrv_shutdown(void)
{
int res;
ssize_t res;
res = init_communication();
if (res < 0) {
@ -371,7 +374,7 @@ void upsdrv_shutdown(void)
/* handle "beeper.disable" */
static void do_beeper_off(void) {
int res;
ssize_t res;
char temp[SMALLBUF];
const char *arg;
@ -453,7 +456,7 @@ static int instcmd(const char *cmdname, const char *extra)
return STAT_INSTCMD_HANDLED;
}
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}
@ -482,12 +485,12 @@ void upsdrv_initups(void)
void upsdrv_initinfo(void)
{
int res;
ssize_t res;
char temp[SMALLBUF], st[SMALLBUF];
res = init_communication();
if (res < 0) {
fatalx(EXIT_FAILURE,
fatalx(EXIT_FAILURE,
"Unable to detect an Belkin Smart protocol UPS on port %s\n"
"Check the cabling, port name or model name and try again", device_path
);

View file

@ -47,7 +47,7 @@
input.voltage.nominal
output.frequency
output.voltage
ups.beeper.status (RW) enabled/disabled/muted
ups.beeper.status (RW) enabled/disabled/muted
ups.firmware
ups.load
ups.model
@ -55,12 +55,12 @@
ups.status
ups.temperature
ups.test.result
ups.delay.restart read-only: time to restart
ups.delay.shutdown read-only: time to shutdown
ups.delay.restart read-only: time to restart
ups.delay.shutdown read-only: time to shutdown
ups.type ONLINE/OFFLINE/LINEINT
COMMANDS:
beeper.disable
beeper.enable
beeper.mute
@ -94,7 +94,7 @@
#include "serial.h"
#define DRIVER_NAME "Belkin 'Universal UPS' driver"
#define DRIVER_VERSION "0.07"
#define DRIVER_VERSION "0.08"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -111,48 +111,48 @@ upsdrv_info_t upsdrv_info = {
#define MAXMSGSIZE 25
/* definitions of register numbers for Belkin UPS */
#define REG_VOLTRATING 0x01
#define REG_FREQRATING 0x02
#define REG_POWERRATING 0x03
#define REG_VOLTRATING 0x01
#define REG_FREQRATING 0x02
#define REG_POWERRATING 0x03
#define REG_BATVOLTRATING 0x04
#define REG_XFER_LO 0x06
#define REG_XFER_LO_MAX 0x07
#define REG_XFER_LO_MIN 0x08
#define REG_XFER_HI 0x09
#define REG_XFER_HI_MAX 0x0a
#define REG_XFER_HI_MIN 0x0b
#define REG_VOLTSENS 0x0c
#define REG_UPSMODEL 0x0d
#define REG_UPSMODEL2 0x0e
#define REG_FIRMWARE 0x0f
#define REG_TESTSTATUS 0x10
#define REG_ALARMSTATUS 0x11
#define REG_XFER_LO 0x06
#define REG_XFER_LO_MAX 0x07
#define REG_XFER_LO_MIN 0x08
#define REG_XFER_HI 0x09
#define REG_XFER_HI_MAX 0x0a
#define REG_XFER_HI_MIN 0x0b
#define REG_VOLTSENS 0x0c
#define REG_UPSMODEL 0x0d
#define REG_UPSMODEL2 0x0e
#define REG_FIRMWARE 0x0f
#define REG_TESTSTATUS 0x10
#define REG_ALARMSTATUS 0x11
#define REG_SHUTDOWNTIMER 0x15
#define REG_RESTARTTIMER 0x16
#define REG_INPUTVOLT 0x18
#define REG_INPUTFREQ 0x19
#define REG_TEMPERATURE 0x1a
#define REG_OUTPUTVOLT 0x1b
#define REG_OUTPUTFREQ 0x1c
#define REG_LOAD 0x1e
#define REG_BATSTAT2 0x1f
#define REG_BATVOLT 0x20
#define REG_BATLEVEL 0x21
#define REG_UPSSTATUS 0x22
#define REG_BATSTATUS 0x23
#define REG_TIMELEFT 0x3f
#define REG_INPUTVOLT 0x18
#define REG_INPUTFREQ 0x19
#define REG_TEMPERATURE 0x1a
#define REG_OUTPUTVOLT 0x1b
#define REG_OUTPUTFREQ 0x1c
#define REG_LOAD 0x1e
#define REG_BATSTAT2 0x1f
#define REG_BATVOLT 0x20
#define REG_BATLEVEL 0x21
#define REG_UPSSTATUS 0x22
#define REG_BATSTATUS 0x23
#define REG_TIMELEFT 0x3f
/* flags for REG_UPSSTATUS */
#define US_ACFAILURE 0x0001
#define US_OVERLOAD 0x0010
#define US_OFF 0x0020
#define US_OFF 0x0020
#define US_OVERHEAT 0x0040
#define US_UPSFAULT 0x0080
#define US_WAITING 0x2000
#define US_BUZZER 0x8000
/* flags for REG_BATSTATUS */
#define BS_LOW 0x04
#define BS_LOW 0x04
#define BS_CHARGING 0x10
#define BS_ONBATTERY 0x20
#define BS_DEPLETED 0x40
@ -161,24 +161,24 @@ upsdrv_info_t upsdrv_info = {
/* size of an array */
#define asize(x) ((int)(sizeof(x)/sizeof(x[0])))
const char *upstype[3] = {
"ONLINE",
"OFFLINE",
static const char *upstype[3] = {
"ONLINE",
"OFFLINE",
"LINEINT"
};
const char *voltsens[3] = {
"normal",
"medium",
static const char *voltsens[3] = {
"normal",
"medium",
"low"
};
const char *teststatus[6] = {
"no test performed",
"test passed",
"test failed",
"test failed",
"test aborted",
static const char *teststatus[6] = {
"no test performed",
"test passed",
"test failed",
"test failed",
"test aborted",
"test in progress"
};
@ -247,7 +247,7 @@ static void belkin_nut_open_tty(void)
byte, checksum). Return length of message, or -1 if not
well-formed */
static int belkin_nut_receive(unsigned char *buf, int bufsize) {
int r;
ssize_t r;
int n=0;
int len;
@ -285,7 +285,8 @@ static int belkin_nut_receive(unsigned char *buf, int bufsize) {
if (n+len > bufsize) {
return -1;
}
r = ser_get_buf_len(upsfd, &buf[4], len, 3, 0);
/* Casting is okay, len is range-limited to unsigned char */
r = ser_get_buf_len(upsfd, &buf[4], (size_t)len, 3, 0);
if (r!=len) {
upslogx(LOG_ERR, "Short read from UPS");
return -1;
@ -302,9 +303,10 @@ static int belkin_nut_receive(unsigned char *buf, int bufsize) {
/* read the value of a string register from UPS. Return NULL on
failure, else an allocated string. */
static char *belkin_nut_read_str(int reg) {
static char *belkin_nut_read_str(unsigned char reg) {
unsigned char buf[MAXMSGSIZE];
int len, r;
ssize_t r;
size_t len;
char *str;
/* send the request */
@ -335,6 +337,10 @@ static char *belkin_nut_read_str(int reg) {
}
/* convert the answer to a string */
if (buf[2] < 1) {
upslogx(LOG_ERR, "Invalid response from UPS: string too short to be true");
return NULL;
}
len = buf[2]-1;
str = (char *)xmalloc(len+1);
memcpy(str, &buf[4], len);
@ -344,9 +350,10 @@ static char *belkin_nut_read_str(int reg) {
/* read the value of an integer register from UPS. Return -1 on
failure. */
static int belkin_nut_read_int(int reg) {
static int belkin_nut_read_int(unsigned char reg) {
unsigned char buf[MAXMSGSIZE];
int len, r;
int len;
ssize_t r;
/* send the request */
buf[0] = 0x7e;
@ -389,9 +396,9 @@ static int belkin_nut_read_int(int reg) {
/* write the value of an integer register to UPS. Return -1 on
failure, else 0 */
static int belkin_nut_write_int(int reg, int val) {
static int belkin_nut_write_int(unsigned char reg, int val) {
unsigned char buf[MAXMSGSIZE];
int r;
ssize_t r;
/* send the request */
buf[0] = 0x7e;
@ -401,7 +408,7 @@ static int belkin_nut_write_int(int reg, int val) {
buf[4] = val & 0xff;
buf[5] = (val>>8) & 0xff;
buf[6] = belkin_checksum(buf, 6);
r = ser_send_buf(upsfd, buf, 7);
if (r<0) {
upslogx(LOG_ERR, "Failed write to UPS");
@ -445,14 +452,14 @@ static int belkin_std_open_tty(const char *device) {
struct termios tios;
struct flock flock;
char buf[128];
int r;
ssize_t r;
/* open the device */
fd = open(device, O_RDWR | O_NONBLOCK);
if (fd == -1) {
return -1;
}
/* set communications parameters: 2400 baud, 8 bits, 1 stop bit, no
parity, enable reading, hang up when done, ignore modem control
lines. */
@ -465,7 +472,7 @@ static int belkin_std_open_tty(const char *device) {
close(fd);
return -1;
}
/* signal the UPS to enter "smart" mode. This is done by setting RTS
and dropping DTR for at least 0.25 seconds. RTS and DTR refer to
two specific pins in the 9-pin serial connector. Note: this must
@ -482,7 +489,7 @@ static int belkin_std_open_tty(const char *device) {
close(fd);
return -1;
}
/* lock the port */
memset(&flock, 0, sizeof(flock));
flock.l_type = F_RDLCK;
@ -491,11 +498,11 @@ static int belkin_std_open_tty(const char *device) {
close(fd);
return -1;
}
/* sleep at least 0.25 seconds for the UPS to wake up. Belkin's own
software sleeps 1 second, so that's what we do, too. */
usleep(1000000);
/* flush incoming data again, and read any remaining garbage
bytes. There should not be any. */
r = tcflush(fd, TCIFLUSH);
@ -503,27 +510,27 @@ static int belkin_std_open_tty(const char *device) {
close(fd);
return -1;
}
r = read(fd, buf, 127);
if (r == -1 && errno != EAGAIN) {
close(fd);
return -1;
}
/* leave port in non-blocking state */
return fd;
}
/* blocking read with 1-second timeout (use non-blocking i/o) */
static int belkin_std_upsread(int fd, unsigned char *buf, int n) {
int count = 0;
int r;
ssize_t r;
int tries = 0;
while (count < n) {
r = read(fd, &buf[count], n-count);
if (r==-1 && errno==EAGAIN) {
r = read(fd, &buf[count], (size_t)(n-count));
if (r==-1 && errno==EAGAIN) {
/* non-blocking i/o, no data available */
usleep(100000);
tries++;
@ -542,12 +549,12 @@ static int belkin_std_upsread(int fd, unsigned char *buf, int n) {
/* blocking write with 1-second timeout (use non-blocking i/o) */
static int belkin_std_upswrite(int fd, unsigned char *buf, int n) {
int count = 0;
int r;
ssize_t r;
int tries = 0;
while (count < n) {
r = write(fd, &buf[count], n-count);
if (r==-1 && errno==EAGAIN) {
r = write(fd, &buf[count], (size_t)(n-count));
if (r==-1 && errno==EAGAIN) {
/* non-blocking i/o, no data available */
usleep(100000);
tries++;
@ -612,7 +619,7 @@ static int belkin_std_receive(int fd, unsigned char *buf, int bufsize) {
/* read the value of an integer register from UPS. Return -1 on
failure. */
static int belkin_std_read_int(int fd, int reg) {
static int belkin_std_read_int(int fd, unsigned char reg) {
unsigned char buf[MAXMSGSIZE];
int len, r;
@ -654,10 +661,10 @@ static int belkin_std_read_int(int fd, int reg) {
/* write the value of an integer register to UPS. Return -1 on
failure, else 0 */
static int belkin_std_write_int(int fd, int reg, int val) {
static int belkin_std_write_int(int fd, unsigned char reg, int val) {
unsigned char buf[MAXMSGSIZE];
int r;
/* send the request */
buf[0] = 0x7e;
buf[1] = 0x04;
@ -666,12 +673,12 @@ static int belkin_std_write_int(int fd, int reg, int val) {
buf[4] = val & 0xff;
buf[5] = (val>>8) & 0xff;
buf[6] = belkin_checksum(buf, 6);
r = belkin_std_upswrite(fd, buf, 7);
if (r<0) {
return -1;
}
/* receive the acknowledgement */
r = belkin_std_receive(fd, buf, MAXMSGSIZE);
if (r<0) {
@ -710,7 +717,19 @@ static void updatestatus(int smode, const char *fmt, ...) {
/* read formatted argument string */
va_start(ap, fmt);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
vsnprintf(buf, sizeof(buf), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
buf[sizeof(buf)-1] = 0;
va_end(ap);
@ -764,13 +783,13 @@ static int belkin_wait(void)
if (dstate_getinfo("driver.flag.flash")) {
flash = 1;
}
if (dstate_getinfo("driver.flag.silent")) {
smode = 0;
} else if (dstate_getinfo("driver.flag.dumbterm")) {
smode = 2;
}
updatestatus(smode, "Connecting to UPS...");
failcount = 0;
fd = -1;
@ -824,7 +843,7 @@ static int belkin_wait(void)
}
/* successfully got data from UPS */
failcount = 0;
if (bs & BS_ONBATTERY) {
st = ST_BATTERY;
} else if (ov>0) {
@ -907,29 +926,29 @@ void upsdrv_initinfo(void)
/* read writable values and declare them writable */
val = belkin_nut_read_int(REG_VOLTSENS);
if (val!=-1) {
dstate_setinfo("input.sensitivity", "%s", (val>=0 && val<asize(voltsens)) ? voltsens[val] : "?");
/* declare variable writable */
/* note: enumerated variables apparently don't need the ST_FLAG_STRING flag */
dstate_setflags("input.sensitivity", ST_FLAG_RW);
for (i=0; i<asize(voltsens); i++) {
dstate_addenum("input.sensitivity", "%s", voltsens[i]);
}
}
if (val!=-1) {
dstate_setinfo("input.sensitivity", "%s", (val>=0 && val<asize(voltsens)) ? voltsens[val] : "?");
/* declare variable writable */
/* note: enumerated variables apparently don't need the ST_FLAG_STRING flag */
dstate_setflags("input.sensitivity", ST_FLAG_RW);
for (i=0; i<asize(voltsens); i++) {
dstate_addenum("input.sensitivity", "%s", voltsens[i]);
}
}
val = belkin_nut_read_int(REG_ALARMSTATUS);
if (val!=-1) {
dstate_setinfo("ups.beeper.status", "%s", val==1 ? "disabled" : val&1 ? "muted" : "enabled");
if (val!=-1) {
dstate_setinfo("ups.beeper.status", "%s", (val==1) ? "disabled" : (val&1) ? "muted" : "enabled");
/* declare variable writable */
dstate_setflags("ups.beeper.status", ST_FLAG_RW);
dstate_addenum("ups.beeper.status", "enabled");
dstate_addenum("ups.beeper.status", "disabled");
dstate_addenum("ups.beeper.status", "muted");
}
/* declare variable writable */
dstate_setflags("ups.beeper.status", ST_FLAG_RW);
dstate_addenum("ups.beeper.status", "enabled");
dstate_addenum("ups.beeper.status", "disabled");
dstate_addenum("ups.beeper.status", "muted");
}
val = belkin_nut_read_int(REG_XFER_LO);
if (val!=-1) {
if (val!=-1) {
dstate_setinfo("input.transfer.low", "%d", val);
/* declare variable writable */
@ -941,10 +960,10 @@ void upsdrv_initinfo(void)
dstate_addenum("input.transfer.low", "%d", i);
}
}
}
}
val = belkin_nut_read_int(REG_XFER_HI);
if (val!=-1) {
if (val!=-1) {
dstate_setinfo("input.transfer.high", "%d", val);
/* declare variable writable */
@ -956,7 +975,7 @@ void upsdrv_initinfo(void)
dstate_addenum("input.transfer.high", "%d", i);
}
}
}
}
/* declare handlers for instand commands and writable variables */
upsh.instcmd = instcmd;
@ -997,7 +1016,7 @@ void upsdrv_updateinfo(void)
dstate_setinfo("output.voltage", "%.1f", 0.1*ov);
status_init();
if (bs & BS_ONBATTERY) {
status_set("OB"); /* on battery, including tests */
} else if (ov > 0) {
@ -1039,13 +1058,13 @@ void upsdrv_updateinfo(void)
/* new read everything else */
val = belkin_nut_read_int(REG_XFER_LO);
if (val!=-1) {
dstate_setinfo("input.transfer.low", "%d", val);
if (val!=-1) {
dstate_setinfo("input.transfer.low", "%d", val);
}
val = belkin_nut_read_int(REG_XFER_HI);
if (val!=-1) {
dstate_setinfo("input.transfer.high", "%d", val);
if (val!=-1) {
dstate_setinfo("input.transfer.high", "%d", val);
}
val = belkin_nut_read_int(REG_VOLTSENS);
@ -1060,7 +1079,7 @@ void upsdrv_updateinfo(void)
val = belkin_nut_read_int(REG_ALARMSTATUS);
if (val!=-1) {
dstate_setinfo("ups.beeper.status", "%s", val==1 ? "disabled" : val&1 ? "muted" : "enabled");
dstate_setinfo("ups.beeper.status", "%s", (val==1) ? "disabled" : (val&1) ? "muted" : "enabled");
}
val = belkin_nut_read_int(REG_SHUTDOWNTIMER);
@ -1132,7 +1151,7 @@ void upsdrv_shutdown(void)
/* Note: this UPS cannot (apparently) be put into "soft
shutdown" mode; thus the -k option should not normally be
used; instead, a workaround using the "-x wait" option
should be used; see belkinunv(8) for details.
should be used; see belkinunv(8) for details.
In case somebody uses the -k option, the best we can do
here is a timed shutdown; this will wake up the attached
@ -1145,7 +1164,7 @@ void upsdrv_shutdown(void)
option instead, as suggested on the belkinunv(8) man
page. */
upslogx(LOG_WARNING, "You are using the -k option, which is broken for this driver.\nShutting down for 10 minutes and hoping for the best");
upslogx(LOG_WARNING, "You are using the -k option, which is broken for this driver.\nShutting down for 10 minutes and hoping for the best");
belkin_nut_write_int(REG_RESTARTTIMER, 10); /* 10 minutes */
belkin_nut_write_int(REG_SHUTDOWNTIMER, 1); /* 1 second */
@ -1155,8 +1174,8 @@ int instcmd(const char *cmdname, const char *extra)
{
int r;
/* We use test.failure.start to initiate a "deep battery test".
This does not really simulate a 'power failure', because we
/* We use test.failure.start to initiate a "deep battery test".
This does not really simulate a 'power failure', because we
won't start shutdown procedures during a test.
We use test.battery.start to initiate a "10-second battery test". */
@ -1177,35 +1196,43 @@ int instcmd(const char *cmdname, const char *extra)
if (!strcasecmp(cmdname, "test.failure.start")) {
r = belkin_nut_write_int(REG_TESTSTATUS, 2);
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "test.failure.stop")) {
r = belkin_nut_write_int(REG_TESTSTATUS, 3);
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "test.battery.start")) {
r = belkin_nut_write_int(REG_TESTSTATUS, 1);
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "test.battery.stop")) {
r = belkin_nut_write_int(REG_TESTSTATUS, 3);
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "beeper.disable")) {
r = belkin_nut_write_int(REG_ALARMSTATUS, 1);
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "beeper.enable")) {
r = belkin_nut_write_int(REG_ALARMSTATUS, 2);
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "beeper.mute")) {
r = belkin_nut_write_int(REG_ALARMSTATUS, 3);
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "shutdown.stayoff")) {
r = belkin_nut_write_int(REG_RESTARTTIMER, 0);
r |= belkin_nut_write_int(REG_SHUTDOWNTIMER, 1); /* 1 second */
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "shutdown.reboot")) {
@ -1217,11 +1244,13 @@ int instcmd(const char *cmdname, const char *extra)
the UPS will stay off between 60 and 120 seconds */
r = belkin_nut_write_int(REG_RESTARTTIMER, 2); /* 2 minutes */
r |= belkin_nut_write_int(REG_SHUTDOWNTIMER, 1); /* 1 second */
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "shutdown.reboot.graceful")) {
r = belkin_nut_write_int(REG_RESTARTTIMER, 2); /* 2 minutes */
r |= belkin_nut_write_int(REG_SHUTDOWNTIMER, 40); /* 40 seconds */
if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname);
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
}
if (!strcasecmp(cmdname, "reset.input.minmax")) {
@ -1231,7 +1260,7 @@ int instcmd(const char *cmdname, const char *extra)
return STAT_INSTCMD_HANDLED;
}
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}

View file

@ -1,4 +1,4 @@
/*
/*
bestfcom.c - model specific routines for Best Power F-Command ups models
This module is yet another rewritten mangle of the bestuferrups
@ -45,7 +45,7 @@
#include "serial.h"
#define DRIVER_NAME "Best Ferrups/Fortress driver"
#define DRIVER_VERSION "0.12"
#define DRIVER_VERSION "0.13"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -83,7 +83,7 @@ upsdrv_info_t upsdrv_info = {
#include <unistd.h>
/* Blob of UPS configuration data from the formatconfig string */
struct {
static struct {
int valid; /* set to 1 when this is filled in */
float idealbvolts; /* various interesting battery voltages */
@ -114,24 +114,24 @@ void upsdrv_initinfo (void)
*/
dstate_setinfo("ups.mfr", "%s", "Best Power");
switch(fc.model) {
case MExxxx:
dstate_setinfo("ups.model", "%s ME%d", fc.name, fc.va);
break;
case MDxxxx:
dstate_setinfo("ups.model", "%s MD%d", fc.name, fc.va);
break;
case FDxxxx:
dstate_setinfo("ups.model", "%s FD%d", fc.name, fc.va);
break;
case FExxxx:
dstate_setinfo("ups.model", "%s FE%d", fc.name, fc.va);
break;
case LIxxxx:
dstate_setinfo("ups.model", "%s LI%d", fc.name, fc.va);
break;
default:
fatalx(EXIT_FAILURE, "Unknown model - oops!"); /* Will never get here, upsdrv_initups() will catch */
}
case MExxxx:
dstate_setinfo("ups.model", "%s ME%d", fc.name, fc.va);
break;
case MDxxxx:
dstate_setinfo("ups.model", "%s MD%d", fc.name, fc.va);
break;
case FDxxxx:
dstate_setinfo("ups.model", "%s FD%d", fc.name, fc.va);
break;
case FExxxx:
dstate_setinfo("ups.model", "%s FE%d", fc.name, fc.va);
break;
case LIxxxx:
dstate_setinfo("ups.model", "%s LI%d", fc.name, fc.va);
break;
default:
fatalx(EXIT_FAILURE, "Unknown model - oops!"); /* Will never get here, upsdrv_initups() will catch */
}
dstate_setinfo("ups.power.nominal", "%d", fc.va);
dstate_setinfo("ups.realpower.nominal", "%d", fc.watts);
@ -162,7 +162,7 @@ void upsdrv_initinfo (void)
/* atoi() without the freebie octal conversion */
int bcd2i (const char *bcdstring, const int bcdlen)
static int bcd2i (const char *bcdstring, const int bcdlen)
{
int i, digit, total = 0, factor = 1;
for (i = 1; i < bcdlen; i++)
@ -181,7 +181,8 @@ int bcd2i (const char *bcdstring, const int bcdlen)
#define POLL_ALERT "{"
static void alert_handler(char ch)
{
char buf[256];
char buf[SMALLBUF];
NUT_UNUSED_VARIABLE(ch);
/* Received an Inverter status alarm :
* "\r\n{Inverter: On}\r\n=>"
@ -195,10 +196,10 @@ static void alert_handler(char ch)
time^M^M^JFeb 20, 22:13:32^M^J^M^J=>id^M^JUnit ID "ME3.1K12345"^M^J^M^J=>
----------------------------------------------------
*/
static int execute(const char *cmd, char *result, int resultsize)
static ssize_t execute(const char *cmd, char *result, size_t resultsize)
{
int ret;
char buf[256];
ssize_t ret;
char buf[SMALLBUF];
unsigned char ch;
/* Check for the Inverter status alarm if pending :
@ -250,11 +251,32 @@ void upsdrv_updateinfo(void)
if (! fc.valid) {
upsdebugx(1, "upsupdate run before ups_ident() read ups config");
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
/* NOTE: This assert() always fails because of "0":
* error: will never be executed [-Werror,-Wunreachable-code]
* ((0) ? (void) (0) : __assert_fail ("0", "bestfcom.c", 254, __PRETTY_FUNCTION__));
* ^
*/
assert(0);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic pop
#endif
}
if (execute("f\r", fstring, sizeof(fstring)) >= 80) {
int inverter=0, charger=0, vin=0, vout=0, btimeleft=0, linestat=0,
int inverter=0, charger=0, vin=0, vout=0, btimeleft=0, linestat=0,
alstat=0, vaout=0;
double ampsout=0.0, vbatt=0.0, battpercent=0.0, loadpercent=0.0,
@ -269,7 +291,7 @@ void upsdrv_updateinfo(void)
/* Charger status. 0=off 1=on */
charger = bcd2i(&fstring[18], 2);
/* Input Voltage. integer number */
vin = bcd2i(&fstring[24], 4);
@ -277,7 +299,7 @@ void upsdrv_updateinfo(void)
vout = bcd2i(&fstring[28], 4);
/* Battery voltage. int times 10 */
vbatt = ((double)bcd2i(&fstring[50], 4) / 10.0);
vbatt = ((double)(bcd2i(&fstring[50], 4)) / 10.0);
/* Alarm status reg 1. Bitmask */
alstat = bcd2i(&fstring[20], 2);
@ -286,14 +308,14 @@ void upsdrv_updateinfo(void)
alstat = alstat | (bcd2i(&fstring[22], 2) << 8);
/* AC line frequency */
acfreq = ((double)bcd2i(&fstring[54], 4) / 100.0);
acfreq = ((double)(bcd2i(&fstring[54], 4)) / 100.0);
/* Runtime remaining (UPS reports minutes) */
btimeleft = bcd2i(&fstring[58], 4) * 60;
if (fc.model != FDxxxx) {
/* Iout. int times 10 */
ampsout = ((double)bcd2i(&fstring[36], 4) / 10.0);
ampsout = ((double)(bcd2i(&fstring[36], 4)) / 10.0);
/* Volt-amps out. int */
vaout = bcd2i(&fstring[40], 6);
@ -304,40 +326,40 @@ void upsdrv_updateinfo(void)
}
if (fc.model != LIxxxx) {
upstemp = (double) bcd2i(&fstring[62], 4);
upstemp = (double)(bcd2i(&fstring[62], 4));
}
/* Percent Load */
switch(fc.model) {
case LIxxxx:
case FDxxxx:
case FExxxx:
case MExxxx:
if (execute("d 16\r", tmp, sizeof(tmp)) > 0) {
int l;
sscanf(tmp, "16 FullLoad%% %d", &l);
loadpercent = (double) l;
}
break;
case MDxxxx:
if (execute("d 22\r", tmp, sizeof(tmp)) > 0) {
int l;
sscanf(tmp, "22 FullLoad%% %d", &l);
loadpercent = (double) l;
}
break;
default: /* Will never happen, caught in upsdrv_initups() */
fatalx(EXIT_FAILURE, "Unknown model in upsdrv_updateinfo()");
case LIxxxx:
case FDxxxx:
case FExxxx:
case MExxxx:
if (execute("d 16\r", tmp, sizeof(tmp)) > 0) {
int l;
sscanf(tmp, "16 FullLoad%% %d", &l);
loadpercent = (double) l;
}
break;
case MDxxxx:
if (execute("d 22\r", tmp, sizeof(tmp)) > 0) {
int l;
sscanf(tmp, "22 FullLoad%% %d", &l);
loadpercent = (double) l;
}
break;
default: /* Will never happen, caught in upsdrv_initups() */
fatalx(EXIT_FAILURE, "Unknown model in upsdrv_updateinfo()");
}
/* Compute battery percent left based on battery voltages. */
battpercent = ((vbatt - fc.emptyvolts)
battpercent = ((vbatt - fc.emptyvolts)
/ (fc.idealbvolts - fc.emptyvolts) * 100.0);
if (battpercent < 0.0)
if (battpercent < 0.0)
battpercent = 0.0;
else if (battpercent > 100.0)
battpercent = 100.0;
/* Compute status string */
{
int lowbatt, lowvolts, overload, replacebatt, boosting, trimming;
@ -353,7 +375,7 @@ void upsdrv_updateinfo(void)
lowvolts = (vbatt <= fc.lowvolts);
status_init();
if (inverter) {
if (inverter_status < 1) {
upsdebugx(1, "Inverter On, charger: %d battery time left: %d",
@ -444,7 +466,7 @@ void upsdrv_shutdown(void)
{
/* NB: hard-wired password */
ser_send(upsfd, "pw377\r");
ser_send(upsfd, "off 1 a\r"); /* power off in 1 second and restart when line power returns */
ser_send(upsfd, "o 10 a\r"); /* power off in 10 seconds and restart when line power returns, FE7K required a min of 5 seconds for off to function */
}
/* list flags and values that you want to receive via -x */
@ -477,10 +499,10 @@ static void sync_serial(void) {
static void setup_serial(void)
{
struct termios tio;
if (tcgetattr(upsfd, &tio) == -1)
fatal_with_errno(EXIT_FAILURE, "tcgetattr");
tio.c_iflag = IXON | IXOFF;
tio.c_oflag = 0;
tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
@ -525,11 +547,11 @@ Version: 8.07
Released: 08/01/1995
*/
void upsdrv_init_nofc(void)
static void upsdrv_init_nofc(void)
{
char tmp[256], rstring[1024];
/* This is a Best UPS
/* This is a Best UPS
* Set initial values for old Fortress???
*/
@ -577,7 +599,8 @@ void upsdrv_init_nofc(void)
}
} else
if (strstr(rstring, "Model: FE")
|| strstr(rstring, "Model: FE")){
|| strstr(rstring, "Model: FE"))
{
fc.model = FExxxx;
fc.type = FERRUPS;
snprintf(fc.name, sizeof(fc.name), "%s", "Ferrups");
@ -586,56 +609,55 @@ void upsdrv_init_nofc(void)
/* How does the old Fortress respond to this? */
upsdebugx(2, "Old Best Fortress???");
/* fc.model = FORTRESS; */
}
}
if (fc.model == UNKNOWN) {
fatalx(EXIT_FAILURE, "Unknown model %s in upsdrv_init_nofc()", rstring);
}
switch(fc.model) {
case MExxxx:
case MDxxxx:
case FDxxxx:
/* determine shutdown battery voltage */
if (execute("d 27\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "27 LowBatt %f", &fc.emptyvolts);
}
/* determine near low battery voltage */
if (execute("d 30\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "30 NLBatt %f", &fc.lowvolts);
}
/* determine fully charged battery voltage */
if (execute("d 28\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "28 Hi Batt %f", &fc.fullvolts);
}
fc.fullvolts = 13.70;
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
case FExxxx:
if (execute("d 45\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "45 RatedVA %d", &fc.va); /* 4300 */
}
if (execute("d 46\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "46 RatedW %d", &fc.watts); /* 3000 */
}
if (execute("d 65\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "65 LoBatV %f", &fc.emptyvolts); /* 41.00 */
}
if (execute("d 66\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "66 NLBatV %f", &fc.lowvolts); /* 44.00 */
}
if (execute("d 67\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "67 HiBatV %f", &fc.fullvolts); /* 59.60 */
}
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
if (fc.va < 1.0) {
fatalx(EXIT_FAILURE, "Error determining Ferrups UPS rating.");
}
break;
default:
fatalx(EXIT_FAILURE, "Unknown model %s in upsdrv_init_nofc()", rstring);
break;
case MExxxx:
case MDxxxx:
case FDxxxx:
/* determine shutdown battery voltage */
if (execute("d 27\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "27 LowBatt %f", &fc.emptyvolts);
}
/* determine near low battery voltage */
if (execute("d 30\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "30 NLBatt %f", &fc.lowvolts);
}
/* determine fully charged battery voltage */
if (execute("d 28\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "28 Hi Batt %f", &fc.fullvolts);
}
fc.fullvolts = 13.70;
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
case FExxxx:
if (execute("d 45\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "45 RatedVA %d", &fc.va); /* 4300 */
}
if (execute("d 46\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "46 RatedW %d", &fc.watts); /* 3000 */
}
if (execute("d 65\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "65 LoBatV %f", &fc.emptyvolts); /* 41.00 */
}
if (execute("d 66\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "66 NLBatV %f", &fc.lowvolts); /* 44.00 */
}
if (execute("d 67\r", tmp, sizeof(tmp)) > 0) {
sscanf(tmp, "67 HiBatV %f", &fc.fullvolts); /* 59.60 */
}
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
if (fc.va < 1.0) {
fatalx(EXIT_FAILURE, "Error determining Ferrups UPS rating.");
}
break;
default:
fatalx(EXIT_FAILURE, "Unknown model %s in upsdrv_init_nofc()", rstring);
}
fc.valid = 1;
}
@ -657,7 +679,7 @@ Model: [0,1] => 00 = unk, 01 = Patriot/SPS, 02 = FortressII, 03 = Ferrups, 04 =
[2,3] => 00 = LI520, 01 = LI720, 02 = LI1020, 03 = LI1420, 07 = ???
*/
void upsdrv_init_fc(const char *fcstring)
static void upsdrv_init_fc(const char *fcstring)
{
char tmp[256];
@ -709,24 +731,24 @@ void upsdrv_init_fc(const char *fcstring)
}
switch(fc.model) {
case LIxxxx:
fc.va = bcd2i(&fcstring[11], 5);
fc.watts = bcd2i(&fcstring[16], 5);
case LIxxxx:
fc.va = bcd2i(&fcstring[11], 5);
fc.watts = bcd2i(&fcstring[16], 5);
/* determine shutdown battery voltage */
fc.emptyvolts= ((double)bcd2i(&fcstring[57], 4) / 10.0);
/* determine shutdown battery voltage */
fc.emptyvolts= ((double)(bcd2i(&fcstring[57], 4)) / 10.0);
/* determine fully charged battery voltage */
fc.lowvolts= ((double)bcd2i(&fcstring[53], 4) / 10.0);
/* determine fully charged battery voltage */
fc.lowvolts= ((double)(bcd2i(&fcstring[53], 4)) / 10.0);
/* determine fully charged battery voltage */
fc.fullvolts= ((double)bcd2i(&fcstring[49], 4) / 10.0);
/* determine fully charged battery voltage */
fc.fullvolts= ((double)(bcd2i(&fcstring[49], 4)) / 10.0);
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
default:
fatalx(EXIT_FAILURE, "Unknown model %s in upsdrv_init_fc()", tmp);
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
default:
fatalx(EXIT_FAILURE, "Unknown model %s in upsdrv_init_fc()", tmp);
}
fc.valid = 1;
}

View file

@ -22,6 +22,7 @@
#include "main.h"
#include "serial.h"
#include "nut_stdint.h"
#define UPSDELAY 50000 /* 50 ms delay required for reliable operation */
#define SER_WAIT_SEC 2 /* allow 2.0 sec for ser_get calls */
@ -34,7 +35,7 @@
#endif
#define DRIVER_NAME "Best Fortress UPS driver"
#define DRIVER_VERSION "0.05"
#define DRIVER_VERSION "0.06"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -66,16 +67,16 @@ void upsdrv_initinfo(void)
dstate_setinfo("ups.delay.shutdown", "10"); /* write only */
/* tunable via front panel: (european voltage level)
parameter factory default range
INFO_LOWXFER 196 V p7=nnn 160-210
INFO_HIGHXFER 254 V p8=nnn 215-274
INFO_LOBATTIME 2 min p2=n 1-5
parameter factory default range
INFO_LOWXFER 196 V p7=nnn 160-210
INFO_HIGHXFER 254 V p8=nnn 215-274
INFO_LOBATTIME 2 min p2=n 1-5
comm mode p6=0 dumb DONT USE (will lose access to parameter setting!)
p6=1 B1200
p6=2 B2400
P6=3 B4800
p6=4 B9600
p6=1 B1200
p6=2 B2400
P6=3 B4800
p6=4 B9600
maybe cycle through speeds to autodetect?
echo off e0
@ -116,7 +117,7 @@ static int checksum (char * s)
int sum;
for (i = 40, sum = 0; s[0] && s[1] && i > 0; i--, s += 2) {
sum += (fromhex (s[0]) << 4) + fromhex (s[1]);
}
}
return sum;
}
@ -126,7 +127,8 @@ static inline int setinfo_int (const char *key, const char * s, size_t len)
char buf[10];
int val;
if (len > sizeof(buf)) len = sizeof(buf)-1;
if (len > sizeof(buf))
len = sizeof(buf)-1;
strncpy (buf, s, len);
buf[len] = 0;
val = atoi(buf);
@ -141,7 +143,8 @@ static inline void setinfo_int_minutes (const char *key, const char * s, size_t
{
char buf[10];
if (len > sizeof(buf)) len = sizeof(buf)-1;
if (len > sizeof(buf))
len = sizeof(buf)-1;
strncpy (buf, s, len);
buf[len] = 0;
dstate_setinfo (key, "%d", 60*atoi (buf));
@ -151,47 +154,85 @@ static inline void setinfo_int_minutes (const char *key, const char * s, size_t
static inline void setinfo_float (const char *key, const char * fmt, const char * s, size_t len, double factor)
{
char buf[10];
if (len > sizeof(buf)) len = sizeof(buf)-1;
if (len > sizeof(buf))
len = sizeof(buf)-1;
strncpy (buf, s, len);
buf[len] = 0;
dstate_setinfo (key, fmt, factor * (double)atoi (buf));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
dstate_setinfo (key, fmt, factor * (double)(atoi (buf)));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
}
static int upssend(const char *fmt,...) {
int ret;
int ret;
char buf[1024], *p;
va_list ap;
va_list ap;
unsigned int sent = 0;
int d_usec = UPSDELAY;
useconds_t d_usec = UPSDELAY;
va_start(ap, fmt);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
ret = vsnprintf(buf, sizeof(buf), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
if ((ret < 1) || (ret >= (int) sizeof(buf)))
upslogx(LOG_WARNING, "ser_send_pace: vsnprintf needed more "
"than %d bytes", (int)sizeof(buf));
for (p = buf; *p; p++) {
for (p = buf; *p && sent < INT_MAX - 1; p++) {
if (write(upsfd, p, 1) != 1)
return -1;
if (d_usec)
/* Note: LGTM.com analysis warns that here
* "Comparison is always true because d_usec >= 2"
* since we initialize with UPSDELAY above.
* Do not remove this check just in case that
* initialization changes, or run-time value
* becomes modified, in later iterations.
*/
if (d_usec > 0)
usleep(d_usec);
sent++;
if (sent >= INT_MAX) {
upslogx(LOG_WARNING, "ser_send_pace: sent more than INT_MAX, aborting");
}
}
return sent;
return (int)sent;
}
static int upsrecv(char *buf,size_t bufsize,char ec,const char *ic)
static ssize_t upsrecv(char *buf,size_t bufsize,char ec,const char *ic)
{
return ser_get_line(upsfd, buf, bufsize - 1, ec, ic,
SER_WAIT_SEC, SER_WAIT_USEC);
SER_WAIT_SEC, SER_WAIT_USEC);
}
static int upsflushin(int f,int verbose,const char *ignset)
static ssize_t upsflushin(int f, int verbose, const char *ignset)
{
NUT_UNUSED_VARIABLE(f);
return ser_flush_in(upsfd, ignset, verbose);
}
@ -199,12 +240,13 @@ static int upsflushin(int f,int verbose,const char *ignset)
void upsdrv_updateinfo(void)
{
char temp[256];
char *p;
char *p = NULL;
int loadva;
int len, recv;
size_t len = 0;
ssize_t recv;
int retry;
char ch;
int checksum_ok, is_online=1, is_off, low_batt, trimming, boosting;
int checksum_ok = -1, is_online = 1, is_off, low_batt, trimming, boosting;
upsdebugx(1, "upsdrv_updateinfo");
@ -221,8 +263,8 @@ void upsdrv_updateinfo(void)
}
} while (temp[2] == 0);
upsdebugx(1, "upsdrv_updateinfo: received %i bytes (try %i)", recv, retry);
upsdebug_hex(5, "buffer", temp, recv);
upsdebugx(1, "upsdrv_updateinfo: received %zi bytes (try %i)", recv, retry);
upsdebug_hex(5, "buffer", temp, (size_t)recv);
/* syslog (LOG_DAEMON | LOG_NOTICE,"ups: got %d chars '%s'\n", recv, temp + 2); */
/* status example:
@ -237,7 +279,7 @@ void upsdrv_updateinfo(void)
/* last bytes are a checksum:
interpret response as hex string, sum of all bytes must be zero
*/
checksum_ok = (checksum (temp+2) & 0xff) == 0;
checksum_ok = ( (checksum (temp+2) & 0xff) == 0 );
/* setinfo (INFO_, ""); */
/* I can't figure out why this is missing the first two chars.
@ -255,12 +297,19 @@ void upsdrv_updateinfo(void)
sleep(SER_WAIT_SEC);
}
if (!checksum_ok) {
upsdebugx(2, "checksum corruption");
upsdebug_hex(3, "buffer", temp, len);
if (!p || len < 1 || checksum_ok < 0) {
upsdebugx(2, "pointer to data not initialized after processing");
dstate_datastale();
return;
}
if (!checksum_ok) {
upsdebugx(2, "checksum corruption");
upsdebug_hex(3, "buffer", temp, (size_t)len);
dstate_datastale();
return;
}
/* upslogx(LOG_INFO, "updateinfo: %s", p); */
setinfo_int ("input.voltage", p+24,4);
@ -309,9 +358,11 @@ void upsdrv_updateinfo(void)
/* all UPS tunable parameters are set with command
'p%d=%s'
*/
int setparam (int parameter, int dlen, const char * data)
static int setparam (int parameter, int dlen, const char * data)
{
char reply[80];
/* Note the use of "%*s" - parameter (int)dlen specifies
* the string width reserved for data */
upssend ("p%d=%*s\r", parameter, dlen, data);
if (upsrecv (reply, sizeof(reply), ENDCHAR, "") < 0) return 0;
return strncmp (reply, "OK", 2) == 0;
@ -338,7 +389,7 @@ static void autorestart (int restart)
/* set UPS parameters */
static int upsdrv_setvar (const char *var, const char * data) {
int parameter;
int len = strlen(data);
size_t len = strlen(data);
upsdebugx(1, "Setvar: %s %s", var, data);
if (strcmp("input.transfer.low", var) == 0) {
parameter = 7;
@ -354,8 +405,9 @@ static int upsdrv_setvar (const char *var, const char * data) {
return STAT_SET_UNKNOWN;
}
ups_setsuper (1);
if (setparam (parameter, len, data)) {
dstate_setinfo (var, "%*s", len, data);
assert (len < INT_MAX);
if (setparam (parameter, (int)len, data)) {
dstate_setinfo (var, "%*s", (int)len, data);
}
ups_setsuper (0);
return STAT_SET_HANDLED;
@ -396,7 +448,7 @@ static int instcmd (const char *cmdname, const char *extra)
upssend ("OFF%s\r", p);
return STAT_INSTCMD_HANDLED;
}
upslogx(LOG_INFO, "instcmd: unknown command %s", cmdname);
upslogx(LOG_INFO, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}
@ -411,7 +463,7 @@ void upsdrv_makevartable(void)
addvar (VAR_VALUE, "max_load", "rated VA load VA");
}
struct {
static struct {
const char * val;
speed_t speed;
} speed_table[] = {

View file

@ -22,7 +22,7 @@
#include "bestpower-mib.h"
#define BESTPOWER_MIB_VERSION "0.1"
#define BESTPOWER_MIB_VERSION "0.4"
#define BESTPOWER_OID_MODEL_NAME ".1.3.6.1.4.1.2947.1.1.2.0"
/*
@ -32,30 +32,37 @@
/* TODO: find the right sysOID for this MIB
* #define BESTPOWER_SYSOID ".1.3.6.1.4.1.2947???"
*/
#define BESTPOWER_SYSOID BESTPOWER_OID_MODEL_NAME
static info_lkp_t bestpower_power_status[] = {
{ 1, "OL" },
{ 2, "OB" },
{ 0, NULL }
{ 1, "OL", NULL, NULL },
{ 2, "OB", NULL, NULL },
{ 0, NULL, NULL, NULL }
} ;
/* Snmp2NUT lookup table for Best Power MIB */
static snmp_info_t bestpower_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device page */
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ups",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/*.1.3.6.1.4.1.2947.1.1.1.0 = STRING: "Ferrups"
.1.3.6.1.4.1.2947.1.1.2.0 = STRING: "FE850VA"*/
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, BESTPOWER_OID_MODEL_NAME,
"Best Ferrups", SU_FLAG_STATIC, NULL, NULL },
"Best Ferrups", SU_FLAG_STATIC, NULL },
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2947.1.1.5.0",
"", SU_FLAG_STATIC, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2947.1.1.7.0",
"", SU_FLAG_STATIC, NULL },
"", SU_FLAG_STATIC, NULL },
{ "ups.power", 0, 1, ".1.3.6.1.4.1.2947.1.1.3.0", "",
0, NULL },
{ "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2947.1.1.8.0", "",
@ -77,8 +84,8 @@ static snmp_info_t bestpower_mib[] = {
0, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL, NULL }
{ NULL, 0, 0, NULL, NULL, 0, NULL }
} ;
mib2nut_info_t bestpower = { "bestpower", BESTPOWER_MIB_VERSION, NULL,
BESTPOWER_OID_MODEL_NAME, bestpower_mib };
BESTPOWER_OID_MODEL_NAME, bestpower_mib, BESTPOWER_SYSOID, NULL };

View file

@ -1,4 +1,4 @@
/*
/*
bestuferrups.c - model specific routines for Best Power Micro-Ferrups
This module is a 40% rewritten mangle of the bestfort module by
@ -33,7 +33,7 @@
#include "serial.h"
#define DRIVER_NAME "Best Ferrups Series ME/RE/MD driver"
#define DRIVER_VERSION "0.03"
#define DRIVER_VERSION "0.04"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -61,46 +61,46 @@ upsdrv_info_t upsdrv_info = {
#include <string.h>
#include <unistd.h>
int debugging = 0;
static int debugging = 0;
/* Blob of UPS configuration data from the formatconfig string */
struct {
int valid; /* set to 1 when this is filled in */
static struct {
int valid; /* set to 1 when this is filled in */
float idealbvolts; /* various interestin battery voltages */
float fullvolts;
float emptyvolts;
int va; /* capacity of UPS in Volt-Amps */
int watts; /* capacity of UPS in watts */
int model; /* enumerated model type */
float idealbvolts; /* various interestin battery voltages */
float fullvolts;
float emptyvolts;
int va; /* capacity of UPS in Volt-Amps */
int watts; /* capacity of UPS in watts */
int model; /* enumerated model type */
} fc;
/* Forward decls */
/* Set up all the funky shared memory stuff used to communicate with upsd */
void upsdrv_initinfo (void)
void upsdrv_initinfo (void)
{
/* now set up room for all future variables that are supported */
dstate_setinfo("ups.mfr", "%s", "Best Power");
switch(fc.model) {
case ME3100:
dstate_setinfo("ups.model", "Micro Ferrups (ME) %d", fc.va);
break;
case MD1KVA:
dstate_setinfo("ups.model", "Micro Ferrups (MD) %d", fc.va);
break;
case RE1800:
dstate_setinfo("ups.model", "Micro Ferrups (RE) %d", fc.va);
break;
default:
fatalx(EXIT_FAILURE, "UPS model not matched!"); /* Will never get here, upsdrv_initups() will catch */
}
fprintf(stderr, "Best Power %s detected\n",
switch(fc.model)
{
case ME3100:
dstate_setinfo("ups.model", "Micro Ferrups (ME) %d", fc.va);
break;
case MD1KVA:
dstate_setinfo("ups.model", "Micro Ferrups (MD) %d", fc.va);
break;
case RE1800:
dstate_setinfo("ups.model", "Micro Ferrups (RE) %d", fc.va);
break;
default:
fatalx(EXIT_FAILURE, "UPS model not matched!"); /* Will never get here, upsdrv_initups() will catch */
}
fprintf(stderr, "Best Power %s detected\n",
dstate_getinfo("ups.model"));
fprintf(stderr, "Battery voltages %5.1f nominal, %5.1f full, %5.1f empty\n",
fprintf(stderr, "Battery voltages %5.1f nominal, %5.1f full, %5.1f empty\n",
fc.idealbvolts,
fc.fullvolts,
fc.emptyvolts);
@ -114,236 +114,259 @@ time^M^M^JFeb 20, 22:13:32^M^J^M^J=>id^M^JUnit ID "ME3.1K12345"^M^J^M^J=>
----------------------------------------------------
*/
static int execute(const char *cmd, char *result, int resultsize)
static ssize_t execute(const char *cmd, char *result, size_t resultsize)
{
int ret;
char buf[256];
ser_send(upsfd, "%s", cmd);
ser_get_line(upsfd, buf, sizeof(buf), '\012', "", 3, 0);
ret = ser_get_line(upsfd, result, resultsize, '\015', "\012", 3, 0);
ser_get_line(upsfd, buf, sizeof(buf), '>', "", 3, 0);
return ret;
ssize_t ret;
char buf[256];
ser_send(upsfd, "%s", cmd);
ser_get_line(upsfd, buf, sizeof(buf), '\012', "", 3, 0);
ret = ser_get_line(upsfd, result, resultsize, '\015', "\012", 3, 0);
ser_get_line(upsfd, buf, sizeof(buf), '>', "", 3, 0);
return ret;
}
void upsdrv_updateinfo(void)
{
char fstring[512];
char fstring[512];
if (! fc.valid) {
fprintf(stderr,
"upsupdate run before ups_ident() read ups config\n");
assert(0);
}
if (! fc.valid) {
fprintf(stderr,
"upsupdate run before ups_ident() read ups config\n");
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
/* NOTE: This assert() always fails because of "0":
* error: will never be executed [-Werror,-Wunreachable-code]
* ((0) ? (void) (0) : __assert_fail ("0", "bestuferrups.c", 138, __PRETTY_FUNCTION__));
* ^
*/
assert(0);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic pop
#endif
}
if (execute("f\r", fstring, sizeof(fstring)) > 0) {
int inverter=0, charger=0, vin=0, vout=0, btimeleft=0, linestat=0,
alstat=0, vaout=0;
double ampsout=0.0, vbatt=0.0, battpercent=0.0, loadpercent=0.0,
hstemp=0.0, acfreq=0.0, ambtemp=0.0;
char tmp[16];
if (execute("f\r", fstring, sizeof(fstring)) > 0) {
int inverter=0, charger=0, vin=0, vout=0, btimeleft=0, linestat=0,
alstat=0, vaout=0;
double ampsout=0.0, vbatt=0.0, battpercent=0.0, loadpercent=0.0,
hstemp=0.0, acfreq=0.0, ambtemp=0.0;
char tmp[16];
/* Inverter status. 0=off 1=on */
memcpy(tmp, fstring+16, 2);
tmp[2] = '\0';
inverter = atoi(tmp);
/* Inverter status: 0=off 1=on */
memcpy(tmp, fstring+16, 2);
tmp[2] = '\0';
inverter = atoi(tmp);
/* Charger status. 0=off 1=on */
memcpy(tmp, fstring+18, 2);
tmp[2] = '\0';
charger = atoi(tmp);
/* Input Voltage. integer number */
memcpy(tmp, fstring+24, 4);
tmp[4] = '\0';
vin = atoi(tmp);
/* Charger status: 0=off 1=on */
memcpy(tmp, fstring+18, 2);
tmp[2] = '\0';
charger = atoi(tmp);
/* Output Voltage. integer number */
memcpy(tmp, fstring+28, 4);
tmp[4] = '\0';
vout = atoi(tmp);
/* Input Voltage. integer number */
memcpy(tmp, fstring+24, 4);
tmp[4] = '\0';
vin = atoi(tmp);
/* Iout. int times 10 */
memcpy(tmp, fstring+36, 4);
tmp[4] = '\0';
ampsout = ((double)(atoi(tmp)) / 10.0);
/* Output Voltage. integer number */
memcpy(tmp, fstring+28, 4);
tmp[4] = '\0';
vout = atoi(tmp);
/* Battery voltage. int times 10 */
memcpy(tmp, fstring+50, 4);
tmp[4] = '\0';
vbatt = ((double)(atoi(tmp)) / 10.0);
/* Iout: int times 10 */
memcpy(tmp, fstring+36, 4);
tmp[4] = '\0';
ampsout = ((double)(atoi(tmp)) / 10.0);
/* Volt-amps out. int */
memcpy(tmp, fstring+40, 6);
tmp[6] = '\0';
vaout = atoi(tmp);
/* Battery voltage: int times 10 */
memcpy(tmp, fstring+50, 4);
tmp[4] = '\0';
vbatt = ((double)(atoi(tmp)) / 10.0);
/* Line status. Bitmask */
memcpy(tmp, fstring+72, 2);
tmp[2] = '\0';
linestat = atoi(tmp);
/* Volt-amps out: int */
memcpy(tmp, fstring+40, 6);
tmp[6] = '\0';
vaout = atoi(tmp);
/* Alarm status reg 1. Bitmask */
memcpy(tmp, fstring+20, 2);
tmp[2] = '\0';
alstat = atoi(tmp);
/* Line status. Bitmask */
memcpy(tmp, fstring+72, 2);
tmp[2] = '\0';
linestat = atoi(tmp);
/* Alarm status reg 2. Bitmask */
memcpy(tmp, fstring+22, 2);
tmp[2] = '\0';
alstat = alstat | (atoi(tmp) << 8);
/* Alarm status reg 1. Bitmask */
memcpy(tmp, fstring+20, 2);
tmp[2] = '\0';
alstat = atoi(tmp);
/* AC line frequency */
memcpy(tmp, fstring+54, 4);
tmp[4]= '\0';
acfreq = ((double)(atoi(tmp)) / 100.0);
/* Alarm status reg 2. Bitmask */
memcpy(tmp, fstring+22, 2);
tmp[2] = '\0';
alstat = alstat | (atoi(tmp) << 8);
/* Runtime remaining */
memcpy(tmp, fstring+58, 4);
tmp[4]= '\0';
btimeleft = atoi(tmp);
/* AC line frequency */
memcpy(tmp, fstring+54, 4);
tmp[4]= '\0';
acfreq = ((double)(atoi(tmp)) / 100.0);
/* UPS Temperature */
memcpy(tmp, fstring+62, 4);
tmp[4]= '\0';
ambtemp = (double)(atoi(tmp));
/* Runtime remaining */
memcpy(tmp, fstring+58, 4);
tmp[4]= '\0';
btimeleft = atoi(tmp);
/* Percent Load */
switch(fc.model) {
case ME3100:
if (execute("d 16\r", fstring, sizeof(fstring)) > 0) {
int l;
sscanf(fstring, "16 FullLoad%% %d", &l);
loadpercent = (double) l;
}
break;
case RE1800:
if (execute("d 16\r", fstring, sizeof(fstring)) > 0) {
int l;
sscanf(fstring, "16 FullLoad%% %d", &l);
loadpercent = (double) l;
}
if (execute("d 12\r", fstring, sizeof(fstring)) > 0) {
int l;
sscanf(fstring, "12 HS Temp %dC", &l);
hstemp = (double) l;
}
break;
case MD1KVA:
if (execute("d 22\r", fstring, sizeof(fstring)) > 0) {
int l;
sscanf(fstring, "22 FullLoad%% %d", &l);
loadpercent = (double) l;
}
break;
default: /* Will never happen, caught in upsdrv_initups() */
fatalx(EXIT_FAILURE, "Unknown model in upsdrv_updateinfo()");
}
/* Compute battery percent left based on battery voltages. */
battpercent = ((vbatt - fc.emptyvolts)
/ (fc.fullvolts - fc.emptyvolts) * 100.0);
if (battpercent < 0.0)
battpercent = 0.0;
else if (battpercent > 100.0)
battpercent = 100.0;
/* Compute status string */
{
int lowbatt, overload, replacebatt, boosting, trimming;
/* UPS Temperature */
memcpy(tmp, fstring+62, 4);
tmp[4]= '\0';
ambtemp = (double)(atoi(tmp));
lowbatt = alstat & (1<<1);
overload = alstat & (1<<6);
replacebatt = alstat & (1<<10);
boosting = inverter && (linestat & (1<<2)) && (vin < 115);
trimming = inverter && (linestat & (1<<2)) && (vin > 115);
/* Percent Load */
switch(fc.model)
{
case ME3100:
if (execute("d 16\r", fstring, sizeof(fstring)) > 0) {
int l;
sscanf(fstring, "16 FullLoad%% %d", &l);
loadpercent = (double) l;
}
break;
case RE1800:
if (execute("d 16\r", fstring, sizeof(fstring)) > 0) {
int l;
sscanf(fstring, "16 FullLoad%% %d", &l);
loadpercent = (double) l;
}
if (execute("d 12\r", fstring, sizeof(fstring)) > 0) {
int l;
sscanf(fstring, "12 HS Temp %dC", &l);
hstemp = (double) l;
}
break;
case MD1KVA:
if (execute("d 22\r", fstring, sizeof(fstring)) > 0) {
int l;
sscanf(fstring, "22 FullLoad%% %d", &l);
loadpercent = (double) l;
}
break;
default: /* Will never happen, caught in upsdrv_initups() */
fatalx(EXIT_FAILURE, "Unknown model in upsdrv_updateinfo()");
}
/* Compute battery percent left based on battery voltages. */
battpercent = ((vbatt - fc.emptyvolts)
/ (fc.fullvolts - fc.emptyvolts) * 100.0);
if (battpercent < 0.0)
battpercent = 0.0;
else if (battpercent > 100.0)
battpercent = 100.0;
status_init();
if (inverter)
status_set("OB");
else
status_set("OL");
/* Compute status string */
{
int lowbatt, overload, replacebatt, boosting, trimming;
if (lowbatt)
status_set("LB");
lowbatt = alstat & (1<<1);
overload = alstat & (1<<6);
replacebatt = alstat & (1<<10);
boosting = inverter && (linestat & (1<<2)) && (vin < 115);
trimming = inverter && (linestat & (1<<2)) && (vin > 115);
if (trimming)
status_set("TRIM");
status_init();
if (boosting)
status_set("BOOST");
if (inverter)
status_set("OB");
else
status_set("OL");
if (replacebatt)
status_set("RB");
if (lowbatt)
status_set("LB");
if (overload)
status_set("OVER");
if (trimming)
status_set("TRIM");
status_commit();
}
if (boosting)
status_set("BOOST");
if (debugging) {
fprintf(stderr,
"Poll: inverter %d charger %d vin %d vout %d vaout %d btimeleft %d\n",
inverter, charger, vin, vout, vaout, btimeleft);
fprintf(stderr,
" ampsout %5.1f vbatt %5.1f batpcnt %5.1f loadpcnt %5.1f upstemp %5.1f acfreq %5.2f ambtemp %5.1f\n",
ampsout, vbatt, battpercent, loadpercent, hstemp, acfreq, ambtemp);
if (replacebatt)
status_set("RB");
}
if (overload)
status_set("OVER");
/* Stuff information into info structures */
status_commit();
}
dstate_setinfo("input.voltage", "%05.1f", (double)vin);
dstate_setinfo("output.voltage", "%05.1f", (double)vout);
dstate_setinfo("battery.charge", "%02.1f", battpercent);
dstate_setinfo("ups.load", "%02.1f", loadpercent);
dstate_setinfo("battery.voltage", "%02.1f", vbatt);
dstate_setinfo("input.frequency", "%05.2f", (double)acfreq);
dstate_setinfo("ups.temperature", "%05.1f", (double)hstemp);
dstate_setinfo("battery.runtime", "%d", btimeleft);
dstate_setinfo("ambient.temperature", "%05.1f", (double)ambtemp);
/* FIXME: change to upsdebugx() and friends */
if (debugging) {
fprintf(stderr,
"Poll: inverter %d charger %d vin %d vout %d vaout %d btimeleft %d\n",
inverter, charger, vin, vout, vaout, btimeleft);
fprintf(stderr,
" ampsout %5.1f vbatt %5.1f batpcnt %5.1f loadpcnt %5.1f upstemp %5.1f acfreq %5.2f ambtemp %5.1f\n",
ampsout, vbatt, battpercent, loadpercent, hstemp, acfreq, ambtemp);
dstate_dataok();
/* Tim: With out this return, it always falls over to the
datastate() at the end of the function */
return;
} else {
}
dstate_datastale();
/* Stuff information into info structures */
} /* if (execute("f\r", fstring, sizeof(fstring)) > 0) */
dstate_setinfo("input.voltage", "%05.1f", (double)vin);
dstate_setinfo("output.voltage", "%05.1f", (double)vout);
dstate_setinfo("battery.charge", "%02.1f", battpercent);
dstate_setinfo("ups.load", "%02.1f", loadpercent);
dstate_setinfo("battery.voltage", "%02.1f", vbatt);
dstate_setinfo("input.frequency", "%05.2f", (double)acfreq);
dstate_setinfo("ups.temperature", "%05.1f", (double)hstemp);
dstate_setinfo("battery.runtime", "%d", btimeleft);
dstate_setinfo("ambient.temperature", "%05.1f", (double)ambtemp);
dstate_datastale();
return;
dstate_dataok();
/* Tim: With out this return, it always falls over to the
datastate() at the end of the function */
return;
} else {
dstate_datastale();
} /* if (execute("f\r", fstring, sizeof(fstring)) > 0) */
dstate_datastale();
return;
}
static void ups_sync(void)
{
char buf[256];
char buf[256];
printf ("Syncing: ");
fflush (stdout);
printf ("Syncing: ");
fflush (stdout);
/* A bit better sanity might be good here. As is, we expect the
human to observe the time being totally not a time. */
/* A bit better sanity might be good here. As is, we expect the
human to observe the time being totally not a time. */
if (execute("time\r", buf, sizeof(buf)) > 0) {
fprintf(stderr, "UPS Time: %s\n", buf);
} else {
fatalx(EXIT_FAILURE, "Error connecting to UPS");
}
if (execute("time\r", buf, sizeof(buf)) > 0) {
fprintf(stderr, "UPS Time: %s\n", buf);
} else {
fatalx(EXIT_FAILURE, "Error connecting to UPS");
}
}
/* power down the attached load immediately */
void upsdrv_shutdown(void)
{
/* NB: hard-wired password */
ser_send(upsfd, "pw377\r");
ser_send(upsfd, "off 1 a\r"); /* power off in 1 second and restart when line power returns */
ser_send(upsfd, "pw377\r");
ser_send(upsfd, "off 1 a\r"); /* power off in 1 second and restart when line power returns */
}
/* list flags and values that you want to receive via -x */
@ -369,12 +392,12 @@ static void sync_serial(void) {
/* Begin code stolen from bestups.c */
static void setup_serial(void)
{
struct termios tio;
{
struct termios tio;
if (tcgetattr(upsfd, &tio) == -1)
fatal_with_errno(EXIT_FAILURE, "tcgetattr");
tio.c_iflag = IXON | IXOFF;
tio.c_oflag = 0;
tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
@ -399,99 +422,100 @@ static void setup_serial(void)
void upsdrv_initups ()
{
char temp[256], fcstring[512];
char temp[256], fcstring[512];
upsfd = ser_open(device_path);
ser_set_speed(upsfd, device_path, B1200);
setup_serial();
ups_sync();
upsfd = ser_open(device_path);
ser_set_speed(upsfd, device_path, B1200);
setup_serial();
ups_sync();
fc.model = UNKNOWN;
/* Obtain Model */
if (execute("id\r", fcstring, sizeof(fcstring)) < 1) {
fatalx(EXIT_FAILURE, "Failed execute in ups_ident()");
}
/* response is a one-line packed string starting with $ */
if (memcmp(fcstring, "Unit", 4)) {
fatalx(EXIT_FAILURE,
"Bad response from formatconfig command in ups_ident()\n"
"id: %s\n", fcstring
);
}
fc.model = UNKNOWN;
/* Obtain Model */
if (execute("id\r", fcstring, sizeof(fcstring)) < 1) {
fatalx(EXIT_FAILURE, "Failed execute in ups_ident()");
}
if (debugging)
fprintf(stderr, "id: %s\n", fcstring);
/* chars 4:2 are a two-digit ascii hex enumerated model code */
memcpy(temp, fcstring+9, 2);
temp[2] = '\0';
/* response is a one-line packed string starting with $ */
if (memcmp(fcstring, "Unit", 4)) {
fatalx(EXIT_FAILURE,
"Bad response from formatconfig command in ups_ident()\n"
"id: %s\n", fcstring
);
}
if (memcmp(temp, "ME", 2) == 0) {
fc.model = ME3100;
} else if ((memcmp(temp, "RE", 2) == 0)) {
fc.model = RE1800;
} else if (memcmp(temp, "C1", 2) == 0) {
/* Better way to identify unit is using "d 15\r", which results in
"15 M# MD1KVA", "id\r" yields "Unit ID "C1K03588"" */
fc.model = MD1KVA;
}
switch(fc.model) {
case ME3100:
fc.va = 3100;
fc.watts = 2200;
/* determine shutdown battery voltage */
if (execute("d 29\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "29 LowBat %f", &fc.emptyvolts);
}
/* determine fully charged battery voltage */
if (execute("d 31\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "31 HiBatt %f", &fc.fullvolts);
}
fc.fullvolts = 54.20;
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
case RE1800:
fc.va = 1800;
fc.watts = 1200;
/* determine shutdown battery voltage */
if (execute("d 29\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "29 LowBat %f", &fc.emptyvolts);
}
/* determine fully charged battery voltage */
if (execute("d 31\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "31 HiBatt %f", &fc.fullvolts);
}
fc.fullvolts = 54.20;
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
case MD1KVA:
fc.va = 1100;
fc.watts = 770; /* Approximate, based on 0.7 power factor */
/* determine shutdown battery voltage */
if (execute("d 27\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "27 LowBatt %f", &fc.emptyvolts);
}
/* determine fully charged battery voltage */
if (execute("d 28\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "28 Hi Batt %f", &fc.fullvolts);
}
fc.fullvolts = 13.70;
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
default:
fatalx(EXIT_FAILURE, "Uknown model %s in ups_ident()", temp);
}
/* FIXME: upsdebugx() */
if (debugging)
fprintf(stderr, "id: %s\n", fcstring);
fc.valid = 1;
return;
/* chars 4:2 are a two-digit ascii hex enumerated model code */
memcpy(temp, fcstring+9, 2);
temp[2] = '\0';
if (memcmp(temp, "ME", 2) == 0) {
fc.model = ME3100;
} else if ((memcmp(temp, "RE", 2) == 0)) {
fc.model = RE1800;
} else if (memcmp(temp, "C1", 2) == 0) {
/* Better way to identify unit is using "d 15\r", which results in
"15 M# MD1KVA", "id\r" yields "Unit ID "C1K03588"" */
fc.model = MD1KVA;
}
switch(fc.model) {
case ME3100:
fc.va = 3100;
fc.watts = 2200;
/* determine shutdown battery voltage */
if (execute("d 29\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "29 LowBat %f", &fc.emptyvolts);
}
/* determine fully charged battery voltage */
if (execute("d 31\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "31 HiBatt %f", &fc.fullvolts);
}
fc.fullvolts = 54.20;
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
case RE1800:
fc.va = 1800;
fc.watts = 1200;
/* determine shutdown battery voltage */
if (execute("d 29\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "29 LowBat %f", &fc.emptyvolts);
}
/* determine fully charged battery voltage */
if (execute("d 31\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "31 HiBatt %f", &fc.fullvolts);
}
fc.fullvolts = 54.20;
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
case MD1KVA:
fc.va = 1100;
fc.watts = 770; /* Approximate, based on 0.7 power factor */
/* determine shutdown battery voltage */
if (execute("d 27\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "27 LowBatt %f", &fc.emptyvolts);
}
/* determine fully charged battery voltage */
if (execute("d 28\r", fcstring, sizeof(fcstring)) > 0) {
sscanf(fcstring, "28 Hi Batt %f", &fc.fullvolts);
}
fc.fullvolts = 13.70;
/* determine "ideal" voltage by a guess */
fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
break;
default:
fatalx(EXIT_FAILURE, "Unknown model %s in ups_ident()", temp);
}
fc.valid = 1;
return;
}
void upsdrv_cleanup(void)
{
ser_close(upsfd, device_path);
ser_close(upsfd, device_path);
}

View file

@ -1,5 +1,10 @@
/* bestups.c - model specific routines for Best-UPS Fortress models
OBSOLETION WARNING: Please to not base new development on this
codebase, instead create a new subdriver for nutdrv_qx which
generally covers all Megatec/Qx protocol family and aggregates
device support from such legacy drivers over time.
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
ID config option by Jason White <jdwhite@jdwhite.org>
@ -23,7 +28,7 @@
#include "serial.h"
#define DRIVER_NAME "Best UPS driver"
#define DRIVER_VERSION "1.06"
#define DRIVER_VERSION "1.07"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -122,13 +127,14 @@ static int instcmd(const char *cmdname, const char *extra)
return STAT_INSTCMD_HANDLED;
}
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}
static int get_ident(char *buf, size_t bufsize)
{
int i, ret;
int i;
ssize_t ret;
char *ID;
ID = getval("ID"); /* user-supplied override from ups.conf */
@ -142,7 +148,7 @@ static int get_ident(char *buf, size_t bufsize)
for (i = 0; i < MAXTRIES; i++) {
ser_send_pace(upsfd, UPSDELAY, "\rID\r");
ret = ser_get_line(upsfd, buf, bufsize, ENDCHAR, "",
ret = ser_get_line(upsfd, buf, bufsize, ENDCHAR, "",
SER_WAIT_SEC, SER_WAIT_USEC);
if (ret > 0)
@ -210,7 +216,7 @@ static void ups_ident(void)
if ((!model) || (!rating)) {
fatalx(EXIT_FAILURE, "Didn't get a valid ident string");
}
model_set(model, rating);
/* Battery voltage multiplier */
@ -240,12 +246,13 @@ static void ups_ident(void)
static void ups_sync(void)
{
char buf[256];
int i, ret;
int i;
ssize_t ret;
for (i = 0; i < MAXTRIES; i++) {
ser_send_pace(upsfd, UPSDELAY, "\rQ1\r");
ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, "",
ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, "",
SER_WAIT_SEC, SER_WAIT_USEC);
/* return once we get something that looks usable */
@ -263,7 +270,7 @@ void upsdrv_initinfo(void)
ups_sync();
ups_ident();
printf("Detected %s %s on %s\n", dstate_getinfo("ups.mfr"),
printf("Detected %s %s on %s\n", dstate_getinfo("ups.mfr"),
dstate_getinfo("ups.model"), device_path);
/* paranoia - cancel any shutdown that might already be running */
@ -277,13 +284,14 @@ void upsdrv_initinfo(void)
static int ups_on_line(void)
{
int i, ret;
int i;
ssize_t ret;
char temp[256], pstat[32];
for (i = 0; i < MAXTRIES; i++) {
ser_send_pace(upsfd, UPSDELAY, "\rQ1\r");
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, "",
ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, "",
SER_WAIT_SEC, SER_WAIT_USEC);
/* Q1 must return 46 bytes starting with a ( */
@ -303,7 +311,7 @@ static int ups_on_line(void)
upslogx(LOG_ERR, "Status read failed: assuming on battery");
return 0; /* on battery */
}
}
void upsdrv_shutdown(void)
{
@ -319,10 +327,10 @@ void upsdrv_shutdown(void)
void upsdrv_updateinfo(void)
{
char involt[16], outvolt[16], loadpct[16], acfreq[16],
char involt[16], outvolt[16], loadpct[16], acfreq[16],
battvolt[16], upstemp[16], pstat[16], buf[256];
float bvoltp;
int ret;
ssize_t ret;
ret = ser_send_pace(upsfd, UPSDELAY, "\rQ1\r");
@ -335,7 +343,7 @@ void upsdrv_updateinfo(void)
/* these things need a long time to respond completely */
usleep(200000);
ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, "",
ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, "",
SER_WAIT_SEC, SER_WAIT_USEC);
if (ret < 1) {
@ -345,13 +353,13 @@ void upsdrv_updateinfo(void)
}
if (ret < 46) {
ser_comm_fail("Poll failed: short read (got %d bytes)", ret);
ser_comm_fail("Poll failed: short read (got %zd bytes)", ret);
dstate_datastale();
return;
}
if (ret > 46) {
ser_comm_fail("Poll failed: response too long (got %d bytes)",
ser_comm_fail("Poll failed: response too long (got %zd bytes)",
ret);
dstate_datastale();
return;
@ -366,7 +374,7 @@ void upsdrv_updateinfo(void)
ser_comm_good();
sscanf(buf, "%*c%s %*s %s %s %s %s %s %s", involt, outvolt,
sscanf(buf, "%*c%s %*s %s %s %s %s %s %s", involt, outvolt,
loadpct, acfreq, battvolt, upstemp, pstat);
/* Guesstimation of battery charge left (inaccurate) */
@ -428,6 +436,15 @@ void upsdrv_makevartable(void)
void upsdrv_initups(void)
{
upsdebugx(0,
"Please note that this driver is deprecated and will not receive\n"
"new development. If it works for managing your devices - fine,\n"
"but if you are running it to try setting up a new device, please\n"
"consider the newer nutdrv_qx instead, which should handle all 'Qx'\n"
"protocol variants for NUT. (Please also report if your device works\n"
"with this driver, but nutdrv_qx would not actually support it with\n"
"any subdriver!)\n");
upsfd = ser_open(device_path);
ser_set_speed(upsfd, device_path, B2400);
}

View file

@ -1,6 +1,11 @@
/*
* blazer.c: driver core for Megatec/Q1 protocol based UPSes
*
* OBSOLETION WARNING: Please to not base new development on this
* codebase, instead create a new subdriver for nutdrv_qx which
* generally covers all Megatec/Qx protocol family and aggregates
* device support from such legacy drivers over time.
*
* A document describing the protocol implemented by this driver can be
* found online at http://www.networkupstools.org/ups-protocols/megatec.html
*
@ -25,11 +30,10 @@
#include "main.h"
#include "blazer.h"
#include "nut_float.h"
#include <math.h>
static int ondelay = 3; /* minutes */
static int offdelay = 30; /* seconds */
static long ondelay = 3; /* minutes */
static long offdelay = 30; /* seconds */
static int proto;
static int online = 1;
@ -78,7 +82,7 @@ static const struct {
{ "mustek", "QS\r", "F\r", "I\r" },
{ "megatec/old", "D\r", "F\r", "I\r" },
{ "zinto", "Q1\r", "F\r", "FW?\r" },
{ NULL }
{ NULL, NULL, NULL, NULL }
};
@ -177,7 +181,7 @@ static int blazer_status(const char *cmd)
{ "input.frequency", "%.1f", strtod },
{ "battery.voltage", "%.2f", blazer_battery },
{ "ups.temperature", "%.1f", strtod },
{ NULL }
{ NULL, NULL, NULL }
};
char buf[SMALLBUF], *val, *last = NULL;
@ -211,7 +215,20 @@ static int blazer_status(const char *cmd)
continue;
}
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
dstate_setinfo(status[i].var, status[i].fmt, status[i].conv(val, NULL));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
}
if (!val) {
@ -304,7 +321,7 @@ static int blazer_rating(const char *cmd)
{ "input.current.nominal", "%.1f", strtod },
{ "battery.voltage.nominal", "%.1f", blazer_packs },
{ "input.frequency.nominal", "%.0f", strtod },
{ NULL }
{ NULL, NULL, NULL }
};
char buf[SMALLBUF], *val, *last = NULL;
@ -338,7 +355,20 @@ static int blazer_rating(const char *cmd)
continue;
}
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
dstate_setinfo(rating[i].var, rating[i].fmt, rating[i].conv(val, NULL));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
}
return 0;
@ -354,7 +384,7 @@ static int blazer_vendor(const char *cmd)
{ "ups.mfr", 15 },
{ "ups.model", 10 },
{ "ups.firmware", 10 },
{ NULL }
{ NULL, 0 }
};
char buf[SMALLBUF];
@ -401,7 +431,7 @@ static int blazer_instcmd(const char *cmdname, const char *extra)
{ "test.battery.start.deep", "TL\r" },
{ "test.battery.start.quick", "T\r" },
{ "test.battery.stop", "CT\r" },
{ NULL }
{ NULL, NULL }
};
char buf[SMALLBUF] = "";
@ -450,18 +480,18 @@ static int blazer_instcmd(const char *cmdname, const char *extra)
if (ondelay == 0) {
if (offdelay < 60) {
snprintf(buf, sizeof(buf), "S.%d\r", offdelay / 6);
snprintf(buf, sizeof(buf), "S.%ld\r", offdelay / 6);
} else {
snprintf(buf, sizeof(buf), "S%02d\r", offdelay / 60);
snprintf(buf, sizeof(buf), "S%02ld\r", offdelay / 60);
}
} else if (offdelay < 60) {
snprintf(buf, sizeof(buf), "S.%dR%04d\r", offdelay / 6, ondelay);
snprintf(buf, sizeof(buf), "S.%ldR%04ld\r", offdelay / 6, ondelay);
} else {
snprintf(buf, sizeof(buf), "S%02dR%04d\r", offdelay / 60, ondelay);
snprintf(buf, sizeof(buf), "S%02ldR%04ld\r", offdelay / 60, ondelay);
}
@ -474,20 +504,22 @@ static int blazer_instcmd(const char *cmdname, const char *extra)
*/
if (offdelay < 60) {
snprintf(buf, sizeof(buf), "S.%dR0000\r", offdelay / 6);
snprintf(buf, sizeof(buf), "S.%ldR0000\r", offdelay / 6);
} else {
snprintf(buf, sizeof(buf), "S%02dR0000\r", offdelay / 60);
snprintf(buf, sizeof(buf), "S%02ldR0000\r", offdelay / 60);
}
} else if (!strcasecmp(cmdname, "test.battery.start")) {
int delay = extra ? strtol(extra, NULL, 10) : 10;
long delay = extra ? strtol(extra, NULL, 10) : 10;
if ((delay < 1) || (delay > 99)) {
upslogx(LOG_ERR, "instcmd: command [%s] failed, delay [%s] out of range", cmdname, extra);
upslogx(LOG_ERR,
"instcmd: command [%s] failed, delay [%s] out of range",
cmdname, extra);
return STAT_INSTCMD_FAILED;
}
snprintf(buf, sizeof(buf), "T%02d\r", delay);
snprintf(buf, sizeof(buf), "T%02ld\r", delay);
} else {
upslogx(LOG_ERR, "instcmd: command [%s] not found", cmdname);
return STAT_INSTCMD_UNKNOWN;
@ -536,7 +568,7 @@ void blazer_initups(void)
}
if ((ondelay < 0) || (ondelay > 9999)) {
fatalx(EXIT_FAILURE, "Start delay '%d' out of range [0..9999]", ondelay);
fatalx(EXIT_FAILURE, "Start delay '%ld' out of range [0..9999]", ondelay);
}
val = getval("offdelay");
@ -545,7 +577,7 @@ void blazer_initups(void)
}
if ((offdelay < 12) || (offdelay > 600)) {
fatalx(EXIT_FAILURE, "Shutdown delay '%d' out of range [12..600]", offdelay);
fatalx(EXIT_FAILURE, "Shutdown delay '%ld' out of range [12..600]", offdelay);
}
/* Truncate to nearest setable value */
@ -573,7 +605,7 @@ static void blazer_initbattery(void)
/* If no values were provided by the user in ups.conf, try to guesstimate
* battery.charge, but announce it! */
if ((batt.volt.nom != 1) && ((batt.volt.high == -1) || (batt.volt.low == -1))) {
if ( (!d_equal(batt.volt.nom, 1)) && ((d_equal(batt.volt.high, -1)) || (d_equal(batt.volt.low, -1)))) {
upslogx(LOG_INFO, "No values provided for battery high/low voltages in ups.conf\n");
/* Basic formula, which should cover most cases */
@ -583,7 +615,7 @@ static void blazer_initbattery(void)
/* Publish these data too */
dstate_setinfo("battery.voltage.low", "%.2f", batt.volt.low);
dstate_setinfo("battery.voltage.high", "%.2f", batt.volt.high);
upslogx(LOG_INFO, "Using 'guestimation' (low: %f, high: %f)!", batt.volt.low, batt.volt.high);
}
@ -664,9 +696,18 @@ void blazer_initinfo(void)
const char *protocol = getval("protocol");
int retry;
upsdebugx(0,
"Please note that this driver is deprecated and will not receive\n"
"new development. If it works for managing your devices - fine,\n"
"but if you are running it to try setting up a new device, please\n"
"consider the newer nutdrv_qx instead, which should handle all 'Qx'\n"
"protocol variants for NUT. (Please also report if your device works\n"
"with this driver, but nutdrv_qx would not actually support it with\n"
"any subdriver!)\n");
for (proto = 0; command[proto].status; proto++) {
int ret;
int ret = -1;
if (protocol && strcasecmp(protocol, command[proto].name)) {
upsdebugx(2, "Skipping %s protocol...", command[proto].name);
@ -698,7 +739,7 @@ void blazer_initinfo(void)
}
if (command[proto].rating && !testvar("norating")) {
int ret;
int ret = -1;
for (retry = 1; retry <= MAXTRIES; retry++) {
@ -718,7 +759,7 @@ void blazer_initinfo(void)
}
if (command[proto].vendor && !testvar("novendor")) {
int ret;
int ret = -1;
for (retry = 1; retry <= MAXTRIES; retry++) {
@ -739,8 +780,8 @@ void blazer_initinfo(void)
blazer_initbattery();
dstate_setinfo("ups.delay.start", "%d", 60 * ondelay);
dstate_setinfo("ups.delay.shutdown", "%d", offdelay);
dstate_setinfo("ups.delay.start", "%ld", 60 * ondelay);
dstate_setinfo("ups.delay.shutdown", "%ld", offdelay);
dstate_addcmd("beeper.toggle");
dstate_addcmd("load.off");
@ -808,6 +849,8 @@ void upsdrv_updateinfo(void)
dstate_dataok();
}
void upsdrv_shutdown(void)
__attribute__((noreturn));
void upsdrv_shutdown(void)
{
@ -835,7 +878,7 @@ void upsdrv_shutdown(void)
continue;
}
fatalx(EXIT_SUCCESS, "Shutting down in %d seconds", offdelay);
fatalx(EXIT_SUCCESS, "Shutting down in %ld seconds", offdelay);
}

View file

@ -1,6 +1,11 @@
/*
* blazer.h: defines/macros for Megatec/Q1 protocol based UPSes
*
* OBSOLETION WARNING: Please to not base new development on this
* codebase, instead create a new subdriver for nutdrv_qx which
* generally covers all Megatec/Qx protocol family and aggregates
* device support from such legacy drivers over time.
*
* A document describing the protocol implemented by this driver can be
* found online at "http://www.networkupstools.org/protocols/megatec.html".
*
@ -40,7 +45,7 @@
* Returns < 0 on error, 0 on timeout and the number of bytes send/read on
* success.
*/
int blazer_command(const char *cmd, char *buf, size_t buflen);
ssize_t blazer_command(const char *cmd, char *buf, size_t buflen);
void blazer_makevartable(void);
void blazer_initups(void);

View file

@ -1,6 +1,11 @@
/*
* blazer_ser.c: support for Megatec/Q1 serial protocol based UPSes
*
* OBSOLETION WARNING: Please to not base new development on this
* codebase, instead create a new subdriver for nutdrv_qx which
* generally covers all Megatec/Qx protocol family and aggregates
* device support from such legacy drivers over time.
*
* A document describing the protocol implemented by this driver can be
* found online at "http://www.networkupstools.org/protocols/megatec.html".
*
@ -26,7 +31,7 @@
#include "blazer.h"
#define DRIVER_NAME "Megatec/Q1 protocol serial driver"
#define DRIVER_VERSION "1.57"
#define DRIVER_VERSION "1.58"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -44,10 +49,10 @@ upsdrv_info_t upsdrv_info = {
* Returns < 0 on error, 0 on timeout and the number of bytes read on
* success.
*/
int blazer_command(const char *cmd, char *buf, size_t buflen)
ssize_t blazer_command(const char *cmd, char *buf, size_t buflen)
{
#ifndef TESTING
int ret;
ssize_t ret;
ser_flush_io(upsfd);
@ -90,10 +95,11 @@ int blazer_command(const char *cmd, char *buf, size_t buflen)
continue;
}
return snprintf(buf, buflen, "%s", testing[i].answer);
/* TODO: Range-check int vs ssize_t values */
return (ssize_t)snprintf(buf, buflen, "%s", testing[i].answer);
}
return snprintf(buf, buflen, "%s", testing[i].cmd);
return (ssize_t)snprintf(buf, buflen, "%s", testing[i].cmd);
#endif
}
@ -124,7 +130,7 @@ void upsdrv_initups(void)
{ "reverse", 0, 1 },
{ "both", 1, 1 },
{ "none", 0, 0 },
{ NULL }
{ NULL, 0, 0 }
};
int i;

View file

@ -1,11 +1,17 @@
/*
* blazer_usb.c: support for Megatec/Q1 USB protocol based UPSes
*
* OBSOLETION WARNING: Please to not base new development on this
* codebase, instead create a new subdriver for nutdrv_qx which
* generally covers all Megatec/Qx protocol family and aggregates
* device support from such legacy drivers over time.
*
* A document describing the protocol implemented by this driver can be
* found online at "http://www.networkupstools.org/protocols/megatec.html".
*
* Copyright (C) 2003-2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* Copyright (C) 2011-2012 Arnaud Quette <arnaud.quette@free.fr>
* Copyright (C) 2016 Eaton
*
* 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
@ -23,12 +29,12 @@
*/
#include "main.h"
#include "libusb.h"
#include "nut_libusb.h"
#include "usb-common.h"
#include "blazer.h"
#define DRIVER_NAME "Megatec/Q1 protocol USB driver"
#define DRIVER_VERSION "0.12"
#define DRIVER_VERSION "0.14"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -61,15 +67,15 @@ static int cypress_command(const char *cmd, char *buf, size_t buflen)
memset(tmp, 0, sizeof(tmp));
snprintf(tmp, sizeof(tmp), "%s", cmd);
for (i = 0; i < strlen(tmp); i += ret) {
for (i = 0; i < strlen(tmp); i += (size_t)ret) {
/* Write data in 8-byte chunks */
/* ret = usb->set_report(udev, 0, (unsigned char *)&tmp[i], 8); */
ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
0x09, 0x200, 0, &tmp[i], 8, 5000);
0x09, 0x200, 0, (usb_ctrl_charbuf)&tmp[i], 8, 5000);
if (ret <= 0) {
upsdebugx(3, "send: %s", ret ? usb_strerror() : "timeout");
upsdebugx(3, "send: %s", ret ? nut_usb_strerror(ret) : "timeout");
return ret;
}
}
@ -78,24 +84,27 @@ static int cypress_command(const char *cmd, char *buf, size_t buflen)
memset(buf, 0, buflen);
for (i = 0; (i <= buflen-8) && (strchr(buf, '\r') == NULL); i += ret) {
for (i = 0; (i <= buflen-8) && (strchr(buf, '\r') == NULL); i += (size_t)ret) {
/* Read data in 8-byte chunks */
/* ret = usb->get_interrupt(udev, (unsigned char *)&buf[i], 8, 1000); */
ret = usb_interrupt_read(udev, 0x81, &buf[i], 8, 1000);
ret = usb_interrupt_read(udev,
0x81,
(usb_ctrl_charbuf)&buf[i], 8, 1000);
/*
* Any errors here mean that we are unable to read a reply (which
* will happen after successfully writing a command to the UPS)
*/
if (ret <= 0) {
upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
upsdebugx(3, "read: %s", ret ? nut_usb_strerror(ret) : "timeout");
return ret;
}
}
upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
return i;
/* TODO: Range-check before cast */
return (int)i;
}
@ -109,7 +118,9 @@ static int phoenix_command(const char *cmd, char *buf, size_t buflen)
/* Read data in 8-byte chunks */
/* ret = usb->get_interrupt(udev, (unsigned char *)tmp, 8, 1000); */
ret = usb_interrupt_read(udev, 0x81, tmp, 8, 1000);
ret = usb_interrupt_read(udev,
0x81,
(usb_ctrl_charbuf)&tmp, 8, 1000);
/*
* This USB to serial implementation is crappy. In order to read correct
@ -118,32 +129,34 @@ static int phoenix_command(const char *cmd, char *buf, size_t buflen)
*/
switch (ret)
{
case -EPIPE: /* Broken pipe */
case ERROR_PIPE: /** Pipe error or Broken pipe */
usb_clear_halt(udev, 0x81);
case -ETIMEDOUT: /* Connection timed out */
break;
case ERROR_TIMEOUT: /** Operation or Connection timed out */
break;
}
if (ret < 0) {
upsdebugx(3, "flush: %s", usb_strerror());
upsdebugx(3, "flush: %s", nut_usb_strerror(ret));
break;
}
upsdebug_hex(4, "dump", tmp, ret);
upsdebug_hex(4, "dump", tmp, (size_t)ret);
}
memset(tmp, 0, sizeof(tmp));
snprintf(tmp, sizeof(tmp), "%s", cmd);
for (i = 0; i < strlen(tmp); i += ret) {
for (i = 0; i < strlen(tmp); i += (size_t)ret) {
/* Write data in 8-byte chunks */
/* ret = usb->set_report(udev, 0, (unsigned char *)&tmp[i], 8); */
ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
0x09, 0x200, 0, &tmp[i], 8, 1000);
0x09, 0x200, 0, (usb_ctrl_charbuf)&tmp[i], 8, 1000);
if (ret <= 0) {
upsdebugx(3, "send: %s", ret ? usb_strerror() : "timeout");
upsdebugx(3, "send: %s", ret ? nut_usb_strerror(ret) : "timeout");
return ret;
}
}
@ -152,24 +165,27 @@ static int phoenix_command(const char *cmd, char *buf, size_t buflen)
memset(buf, 0, buflen);
for (i = 0; (i <= buflen-8) && (strchr(buf, '\r') == NULL); i += ret) {
for (i = 0; (i <= buflen-8) && (strchr(buf, '\r') == NULL); i += (size_t)ret) {
/* Read data in 8-byte chunks */
/* ret = usb->get_interrupt(udev, (unsigned char *)&buf[i], 8, 1000); */
ret = usb_interrupt_read(udev, 0x81, &buf[i], 8, 1000);
ret = usb_interrupt_read(udev,
0x81,
(usb_ctrl_charbuf)&buf[i], 8, 1000);
/*
* Any errors here mean that we are unable to read a reply (which
* will happen after successfully writing a command to the UPS)
*/
if (ret <= 0) {
upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
upsdebugx(3, "read: %s", ret ? nut_usb_strerror(ret) : "timeout");
return ret;
}
}
upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
return i;
/* TODO: Range-check before cast */
return (int)i;
}
@ -181,14 +197,14 @@ static int ippon_command(const char *cmd, char *buf, size_t buflen)
snprintf(tmp, sizeof(tmp), "%s", cmd);
for (i = 0; i < strlen(tmp); i += ret) {
for (i = 0; i < strlen(tmp); i += (size_t)ret) {
/* Write data in 8-byte chunks */
ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
0x09, 0x2, 0, &tmp[i], 8, 1000);
0x09, 0x2, 0, (usb_ctrl_charbuf)&tmp[i], 8, 1000);
if (ret <= 0) {
upsdebugx(3, "send: %s", (ret != -ETIMEDOUT) ? usb_strerror() : "Connection timed out");
upsdebugx(3, "send: %s", (ret != ERROR_TIMEOUT) ? nut_usb_strerror(ret) : "Connection timed out");
return ret;
}
}
@ -196,14 +212,16 @@ static int ippon_command(const char *cmd, char *buf, size_t buflen)
upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);
/* Read all 64 bytes of the reply in one large chunk */
ret = usb_interrupt_read(udev, 0x81, tmp, sizeof(tmp), 1000);
ret = usb_interrupt_read(udev,
0x81,
(usb_ctrl_charbuf)&tmp, sizeof(tmp), 1000);
/*
* Any errors here mean that we are unable to read a reply (which
* will happen after successfully writing a command to the UPS)
*/
if (ret <= 0) {
upsdebugx(3, "read: %s", (ret != -ETIMEDOUT) ? usb_strerror() : "Connection timed out");
upsdebugx(3, "read: %s", (ret != ERROR_TIMEOUT) ? nut_usb_strerror(ret) : "Connection timed out");
return ret;
}
@ -243,7 +261,7 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen)
{ "Q\r", 0x07, '\r' },
{ "C\r", 0x0b, '\r' },
{ "CT\r", 0x0b, '\r' },
{ NULL }
{ NULL, 0, '\0' }
};
int i;
@ -262,14 +280,16 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen)
if (langid_fix != -1) {
/* Apply langid_fix value */
ret = usb_get_string(udev, command[i].index, langid_fix, buf, buflen);
ret = usb_get_string(udev, command[i].index, langid_fix,
(usb_ctrl_charbuf)buf, buflen);
}
else {
ret = usb_get_string_simple(udev, command[i].index, buf, buflen);
ret = usb_get_string_simple(udev, command[i].index,
(usb_ctrl_charbuf)buf, buflen);
}
if (ret <= 0) {
upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
upsdebugx(3, "read: %s", ret ? nut_usb_strerror(ret) : "timeout");
return ret;
}
@ -279,7 +299,7 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen)
if (langid_fix != -1) {
/* Limit this check, at least for now */
/* Invalid receive size - message corrupted */
if (ret != buf[0])
if (ret != buf[0])
{
upsdebugx(1, "size mismatch: %d / %d", ret, buf[0]);
continue;
@ -288,7 +308,7 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen)
/* Simple unicode -> ASCII inplace conversion
* FIXME: this code is at least shared with mge-shut/libshut
* Create a common function? */
unsigned int di, si, size = buf[0];
size_t di, si, size = (size_t)buf[0];
for (di = 0, si = 2; si < size; si += 2) {
if (di >= (buflen - 1))
break;
@ -299,7 +319,9 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen)
buf[di++] = buf[si];
}
buf[di] = 0;
ret = di;
/* with buf a char* array, practical "size" limit and
* so "di" are small enough to cast to int */
ret = (int)di;
}
/* "UPS No Ack" has a special meaning */
@ -326,6 +348,8 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen)
static void *cypress_subdriver(USBDevice_t *device)
{
NUT_UNUSED_VARIABLE(device);
subdriver_command = &cypress_command;
return NULL;
}
@ -333,6 +357,8 @@ static void *cypress_subdriver(USBDevice_t *device)
static void *ippon_subdriver(USBDevice_t *device)
{
NUT_UNUSED_VARIABLE(device);
subdriver_command = &ippon_command;
return NULL;
}
@ -340,6 +366,8 @@ static void *ippon_subdriver(USBDevice_t *device)
static void *krauler_subdriver(USBDevice_t *device)
{
NUT_UNUSED_VARIABLE(device);
subdriver_command = &krauler_command;
return NULL;
}
@ -347,6 +375,8 @@ static void *krauler_subdriver(USBDevice_t *device)
static void *phoenix_subdriver(USBDevice_t *device)
{
NUT_UNUSED_VARIABLE(device);
subdriver_command = &phoenix_command;
return NULL;
}
@ -365,13 +395,16 @@ static usb_device_id_t blazer_usb_id[] = {
{ USB_DEVICE(0x06da, 0x0601), &phoenix_subdriver }, /* Online Zinto A */
{ USB_DEVICE(0x0f03, 0x0001), &cypress_subdriver }, /* Unitek Alpha 1200Sx */
{ USB_DEVICE(0x14f0, 0x00c9), &phoenix_subdriver }, /* GE EP series */
/* end of list */
{-1, -1, NULL}
/* Terminating entry */
{ 0, 0, NULL }
};
static int device_match_func(USBDevice_t *hd, void *privdata)
{
NUT_UNUSED_VARIABLE(privdata);
if (subdriver_command) {
return 1;
}
@ -403,10 +436,10 @@ static USBDeviceMatcher_t device_matcher = {
* Returns < 0 on error, 0 on timeout and the number of bytes read on
* success.
*/
int blazer_command(const char *cmd, char *buf, size_t buflen)
ssize_t blazer_command(const char *cmd, char *buf, size_t buflen)
{
#ifndef TESTING
int ret;
ssize_t ret;
if (udev == NULL) {
ret = usb->open(&udev, &usbdevice, reopen_matcher, NULL);
@ -423,36 +456,50 @@ int blazer_command(const char *cmd, char *buf, size_t buflen)
switch (ret)
{
case -EBUSY: /* Device or resource busy */
case ERROR_BUSY: /* Device or resource busy */
fatal_with_errno(EXIT_FAILURE, "Got disconnected by another driver");
#ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */
#endif
#if WITH_LIBUSB_0_1 /* limit to libusb 0.1 implementation */
case -EPERM: /* Operation not permitted */
fatal_with_errno(EXIT_FAILURE, "Permissions problem");
# ifndef HAVE___ATTRIBUTE__NORETURN
exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */
# endif
#endif /* WITH_LIBUSB_0_1 */
case -EPIPE: /* Broken pipe */
case ERROR_PIPE: /* Broken pipe */
if (usb_clear_halt(udev, 0x81) == 0) {
upsdebugx(1, "Stall condition cleared");
break;
}
#ifdef ETIME
#if (defined ETIME) && ETIME && WITH_LIBUSB_0_1
goto fallthrough_case_etime;
case -ETIME: /* Timer expired */
fallthrough_case_etime:
#endif
if (usb_reset(udev) == 0) {
upsdebugx(1, "Device reset handled");
}
case -ENODEV: /* No such device */
case -EACCES: /* Permission denied */
case -EIO: /* I/O error */
goto fallthrough_case_reconnect;
case ERROR_NO_DEVICE: /* No such device */
case ERROR_ACCESS: /* Permission denied */
case ERROR_IO: /* I/O error */
#if WITH_LIBUSB_0_1 /* limit to libusb 0.1 implementation */
case -ENXIO: /* No such device or address */
case -ENOENT: /* No such file or directory */
#endif
case ERROR_NOT_FOUND: /* No such file or directory */
fallthrough_case_reconnect:
/* Uh oh, got to reconnect! */
usb->close(udev);
udev = NULL;
break;
case -ETIMEDOUT: /* Connection timed out */
case -EOVERFLOW: /* Value too large for defined data type */
#ifdef EPROTO
case ERROR_TIMEOUT: /* Connection timed out */
case ERROR_OVERFLOW: /* Value too large for defined data type */
#if EPROTO && WITH_LIBUSB_0_1
case -EPROTO: /* Protocol error */
#endif
default:
@ -460,7 +507,7 @@ int blazer_command(const char *cmd, char *buf, size_t buflen)
}
return ret;
#else
#else /* if TESTING: */
const struct {
const char *command;
const char *answer;
@ -481,16 +528,41 @@ int blazer_command(const char *cmd, char *buf, size_t buflen)
continue;
}
return snprintf(buf, buflen, "%s", testing[i].answer);
/* TODO: Range-check int vs ssize_t values */
return (ssize_t)snprintf(buf, buflen, "%s", testing[i].answer);
}
return snprintf(buf, buflen, "%s", testing[i].command);
#endif
return (ssize_t)snprintf(buf, buflen, "%s", testing[i].command);
#endif /* TESTING */
}
#ifndef TESTING
static const struct subdriver_t {
const char *name;
int (*command)(const char *cmd, char *buf, size_t buflen);
} subdriver[] = {
{ "cypress", &cypress_command },
{ "phoenix", &phoenix_command },
{ "ippon", &ippon_command },
{ "krauler", &krauler_command },
{ NULL, NULL }
};
#endif /* TESTING */
void upsdrv_help(void)
{
#ifndef TESTING
printf("\nAcceptable values for 'subdriver' via -x or ups.conf in this driver: ");
size_t i;
for (i = 0; subdriver[i].name != NULL; i++) {
if (i>0)
printf(", ");
printf("%s", subdriver[i].name);
}
printf("\n\n");
#endif /* TESTING */
printf("Read The Fine Manual ('man 8 blazer_usb')\n");
}
@ -509,37 +581,30 @@ void upsdrv_makevartable(void)
void upsdrv_initups(void)
{
#ifndef TESTING
const struct {
const char *name;
int (*command)(const char *cmd, char *buf, size_t buflen);
} subdriver[] = {
{ "cypress", &cypress_command },
{ "phoenix", &phoenix_command },
{ "ippon", &ippon_command },
{ "krauler", &krauler_command },
{ NULL }
};
int ret, langid;
char tbuf[255]; /* Some devices choke on size > 255 */
char *regex_array[6];
char *regex_array[7];
char *subdrv = getval("subdriver");
warn_if_bad_usb_port_filename(device_path);
regex_array[0] = getval("vendorid");
regex_array[1] = getval("productid");
regex_array[2] = getval("vendor");
regex_array[3] = getval("product");
regex_array[4] = getval("serial");
regex_array[5] = getval("bus");
regex_array[6] = getval("device");
/* check for language ID workaround (#1) */
if (getval("langid_fix")) {
/* skip "0x" prefix and set back to hexadecimal */
if (sscanf(getval("langid_fix") + 2, "%x", &langid_fix) != 1) {
unsigned int u_langid_fix;
if ( (sscanf(getval("langid_fix") + 2, "%x", &u_langid_fix) != 1) || (u_langid_fix > INT_MAX) ) {
upslogx(LOG_NOTICE, "Error enabling language ID workaround");
}
else {
langid_fix = (int)u_langid_fix;
upsdebugx(2, "language ID workaround enabled (using '0x%x')", langid_fix);
}
}
@ -618,13 +683,13 @@ void upsdrv_initups(void)
* in the descriptor. See USB 2.0 specification, section 9.6.7, for
* more information on this.
* This should allow automatic application of the workaround */
ret = usb_get_string(udev, 0, 0, tbuf, sizeof(tbuf));
ret = usb_get_string(udev, 0, 0, (usb_ctrl_charbuf)tbuf, sizeof(tbuf));
if (ret >= 4) {
langid = tbuf[2] | (tbuf[3] << 8);
langid = (unsigned char)tbuf[2] | ((unsigned char)tbuf[3] << 8);
upsdebugx(1, "First supported language ID: 0x%x (please report to the NUT maintainer!)", langid);
}
}
#endif
#endif /* TESTING */
blazer_initups();
}
@ -645,5 +710,6 @@ void upsdrv_cleanup(void)
free(usbdevice.Product);
free(usbdevice.Serial);
free(usbdevice.Bus);
#endif
free(usbdevice.Device);
#endif /* TESTING */
}

View file

@ -20,13 +20,14 @@
#include "main.h"
#include "parseconf.h"
#include "nut_stdint.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define DRIVER_NAME "clone outlet UPS Driver"
#define DRIVER_VERSION "0.01"
#define DRIVER_VERSION "0.02"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -66,7 +67,7 @@ static int dumpdone = 0;
static PCONF_CTX_t sock_ctx;
static time_t last_heard = 0, last_ping = 0, last_connfail = 0;
static int parse_args(int numargs, char **arg)
static int parse_args(size_t numargs, char **arg)
{
if (numargs < 1) {
return 0;
@ -142,13 +143,28 @@ static int parse_args(int numargs, char **arg)
static int sstate_connect(void)
{
int ret, fd;
ssize_t ret;
int fd, len;
const char *dumpcmd = "DUMPALL\n";
struct sockaddr_un sa;
memset(&sa, '\0', sizeof(sa));
sa.sun_family = AF_UNIX;
snprintf(sa.sun_path, sizeof(sa.sun_path), "%s/%s", dflt_statepath(), device_path);
len = snprintf(sa.sun_path, sizeof(sa.sun_path), "%s/%s", dflt_statepath(), device_path);
if (len < 0) {
fatalx(EXIT_FAILURE, "Can't create a unix domain socket: "
"failed to prepare the pathname");
}
if ((uintmax_t)len >= (uintmax_t)sizeof(sa.sun_path)) {
fatalx(EXIT_FAILURE,
"Can't create a unix domain socket: pathname '%s/%s' "
"is too long (%zu) for 'struct sockaddr_un->sun_path' "
"on this system (%zu)",
dflt_statepath(), device_path,
strlen(dflt_statepath()) + 1 + strlen(device_path),
sizeof(sa.sun_path));
}
fd = socket(AF_UNIX, SOCK_STREAM, 0);
@ -231,7 +247,7 @@ static void sstate_disconnect(void)
static int sstate_sendline(const char *buf)
{
int ret;
ssize_t ret;
if (upsfd < 0) {
return -1; /* failed */
@ -250,7 +266,8 @@ static int sstate_sendline(const char *buf)
static int sstate_readline(void)
{
int i, ret;
int i;
ssize_t ret;
char buf[SMALLBUF];
if (upsfd < 0) {

View file

@ -18,15 +18,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "main.h"
#include "parseconf.h"
#include "attribute.h"
#include "nut_stdint.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define DRIVER_NAME "Clone UPS driver"
#define DRIVER_VERSION "0.02"
#define DRIVER_VERSION "0.03"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -39,8 +42,8 @@ upsdrv_info_t upsdrv_info = {
static struct {
struct {
int start;
int shutdown;
long start;
long shutdown;
} timer;
char status[ST_MAX_VALUE_LEN];
} ups = { { -1, -1 }, "WAIT" };
@ -57,7 +60,7 @@ static struct {
} battery = { { 0, 0 }, { 0, 0 } };
static int dumpdone = 0, online = 1, outlet = 1;
static int offdelay = 120, ondelay = 30;
static long offdelay = 120, ondelay = 30;
static PCONF_CTX_t sock_ctx;
static time_t last_poll = 0, last_heard = 0,
@ -66,7 +69,7 @@ static time_t last_poll = 0, last_heard = 0,
static int instcmd(const char *cmdname, const char *extra);
static int parse_args(int numargs, char **arg)
static int parse_args(size_t numargs, char **arg)
{
if (numargs < 1) {
return 0;
@ -156,13 +159,28 @@ static int parse_args(int numargs, char **arg)
static int sstate_connect(void)
{
int ret, fd;
ssize_t ret;
int fd, len;
const char *dumpcmd = "DUMPALL\n";
struct sockaddr_un sa;
memset(&sa, '\0', sizeof(sa));
sa.sun_family = AF_UNIX;
snprintf(sa.sun_path, sizeof(sa.sun_path), "%s/%s", dflt_statepath(), device_path);
len = snprintf(sa.sun_path, sizeof(sa.sun_path), "%s/%s", dflt_statepath(), device_path);
if (len < 0) {
fatalx(EXIT_FAILURE, "Can't create a unix domain socket: "
"failed to prepare the pathname");
}
if ((uintmax_t)len >= (uintmax_t)sizeof(sa.sun_path)) {
fatalx(EXIT_FAILURE,
"Can't create a unix domain socket: pathname '%s/%s' "
"is too long (%zu) for 'struct sockaddr_un->sun_path' "
"on this system (%zu)",
dflt_statepath(), device_path,
strlen(dflt_statepath()) + 1 + strlen(device_path),
sizeof(sa.sun_path));
}
fd = socket(AF_UNIX, SOCK_STREAM, 0);
@ -245,7 +263,7 @@ static void sstate_disconnect(void)
static int sstate_sendline(const char *buf)
{
int ret;
ssize_t ret;
if (upsfd < 0) {
return -1; /* failed */
@ -264,7 +282,8 @@ static int sstate_sendline(const char *buf)
static int sstate_readline(void)
{
int i, ret;
int i;
ssize_t ret;
char buf[SMALLBUF];
if (upsfd < 0) {
@ -381,7 +400,7 @@ static int instcmd(const char *cmdname, const char *extra)
return STAT_INSTCMD_HANDLED;
}
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}
@ -434,11 +453,11 @@ void upsdrv_initinfo(void)
battery.runtime.low = strtod(val, NULL);
}
dstate_setinfo("ups.delay.shutdown", "%d", offdelay);
dstate_setinfo("ups.delay.start", "%d", ondelay);
dstate_setinfo("ups.delay.shutdown", "%ld", offdelay);
dstate_setinfo("ups.delay.start", "%ld", ondelay);
dstate_setinfo("ups.timer.shutdown", "%d", ups.timer.shutdown);
dstate_setinfo("ups.timer.start", "%d", ups.timer.start);
dstate_setinfo("ups.timer.shutdown", "%ld", ups.timer.shutdown);
dstate_setinfo("ups.timer.start", "%ld", ups.timer.start);
upsh.instcmd = instcmd;
upsh.setvar = setvar;
@ -513,13 +532,16 @@ void upsdrv_updateinfo(void)
}
}
dstate_setinfo("ups.timer.shutdown", "%d", ups.timer.shutdown);
dstate_setinfo("ups.timer.start", "%d", ups.timer.start);
dstate_setinfo("ups.timer.shutdown", "%ld", ups.timer.shutdown);
dstate_setinfo("ups.timer.start", "%ld", ups.timer.start);
last_poll = now;
}
void upsdrv_shutdown(void)
__attribute__((noreturn));
void upsdrv_shutdown(void)
{
fatalx(EXIT_FAILURE, "shutdown not supported");

View file

@ -30,12 +30,10 @@
#include "compaq-mib.h"
#define CPQPOWER_MIB_VERSION "1.6"
#define CPQPOWER_MIB_VERSION "1.66"
#define DEFAULT_ONDELAY 30
#define DEFAULT_OFFDELAY 20
#define STR_DEFAULT_ONDELAY "30"
#define STR_DEFAULT_OFFDELAY "20"
#define DEFAULT_ONDELAY "30"
#define DEFAULT_OFFDELAY "20"
/* Note: RFC-1628 (UPS MIB) is also supported on these devices! */
@ -82,90 +80,91 @@
#define CPQPOWER_OID_ALARM_OB ".1.3.6.1.4.1.232.165.3.7.3.0" /* UPS-MIB::upsOnBattery */
#define CPQPOWER_OID_ALARM_LB ".1.3.6.1.4.1.232.165.3.7.4.0" /* UPS-MIB::upsLowBattery */
#define IETF_OID_AGENTREV ".1.3.6.1.2.1.33.1.1.4.0" /* UPS-MIB::upsIdentAgentSoftwareVersion.0 */
/* Not used, as no longer supported by MIB ver. 1.76 (Github issue 118)
static info_lkp_t cpqpower_alarm_ob[] = {
{ 1, "OB" },
{ 0, NULL }
{ 1, "OB", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
*/
/* Not used, as no longer supported by MIB ver. 1.76 (Github issue 118)
static info_lkp_t cpqpower_alarm_lb[] = {
{ 1, "LB" },
{ 0, NULL }
{ 1, "LB", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
*/
/* Defines for CPQPOWER_OID_POWER_STATUS (1) */
static info_lkp_t cpqpower_pwr_info[] = {
{ 1, "" /* other */ },
{ 2, "OFF" /* none */ },
{ 3, "OL" /* normal */ },
{ 4, "OL BYPASS" /* bypass */ },
{ 5, "OB" /* battery */ },
{ 6, "OL BOOST" /* booster */ },
{ 7, "OL TRIM" /* reducer */ },
{ 8, "OL" /* parallelCapacity */ },
{ 9, "OL" /* parallelRedundant */ },
{ 10, "OL" /* HighEfficiencyMode */ },
{ 0, NULL }
{ 1, "" /* other */, NULL, NULL },
{ 2, "OFF" /* none */, NULL, NULL },
{ 3, "OL" /* normal */, NULL, NULL },
{ 4, "OL BYPASS" /* bypass */, NULL, NULL },
{ 5, "OB" /* battery */, NULL, NULL },
{ 6, "OL BOOST" /* booster */, NULL, NULL },
{ 7, "OL TRIM" /* reducer */, NULL, NULL },
{ 8, "OL" /* parallelCapacity */, NULL, NULL },
{ 9, "OL" /* parallelRedundant */, NULL, NULL },
{ 10, "OL" /* HighEfficiencyMode */, NULL, NULL },
{ 0, NULL, NULL, NULL }
} ;
static info_lkp_t cpqpower_mode_info[] = {
{ 1, "" },
{ 2, "" },
{ 3, "normal" },
{ 4, "" },
{ 5, "" },
{ 6, "" },
{ 7, "" },
{ 8, "parallel capacity" },
{ 9, "parallel redundancy" },
{10, "high efficiency" },
{ 0, NULL }
{ 1, "", NULL, NULL },
{ 2, "", NULL, NULL },
{ 3, "normal", NULL, NULL },
{ 4, "", NULL, NULL },
{ 5, "", NULL, NULL },
{ 6, "", NULL, NULL },
{ 7, "", NULL, NULL },
{ 8, "parallel capacity", NULL, NULL },
{ 9, "parallel redundancy", NULL, NULL },
{10, "high efficiency", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t cpqpower_battery_abm_status[] = {
{ 1, "CHRG" },
{ 2, "DISCHRG" },
/* { 3, "Floating" }, */
/* { 4, "Resting" }, */
/* { 5, "Unknown" }, */
{ 0, NULL }
{ 1, "CHRG", NULL, NULL },
{ 2, "DISCHRG", NULL, NULL },
/* { 3, "Floating", NULL, NULL }, */
/* { 4, "Resting", NULL, NULL }, */
/* { 5, "Unknown", NULL, NULL }, */
{ 0, NULL, NULL, NULL }
} ;
/* Defines for CPQPOWER_OID_UPS_TEST_RES */
static info_lkp_t cpqpower_test_res_info[] = {
{ 1, "Unknown" },
{ 2, "Done and passed" },
{ 3, "Done and error" },
{ 4, "In progress" },
{ 5, "Not supported" },
{ 6, "Inhibited" },
{ 7, "Scheduled" },
{ 0, NULL }
{ 1, "Unknown", NULL, NULL },
{ 2, "Done and passed", NULL, NULL },
{ 3, "Done and error", NULL, NULL },
{ 4, "In progress", NULL, NULL },
{ 5, "Not supported", NULL, NULL },
{ 6, "Inhibited", NULL, NULL },
{ 7, "Scheduled", NULL, NULL },
{ 0, NULL, NULL, NULL }
} ;
#define CPQPOWER_START_TEST 1
#define CPQPOWER_START_TEST "1"
static info_lkp_t cpqpower_outlet_status_info[] = {
{ 1, "on" },
{ 2, "off" },
{ 3, "pendingOff" }, /* transitional status */
{ 4, "pendingOn" }, /* transitional status */
{ 5, "unknown" },
{ 0, NULL }
{ 1, "on", NULL, NULL },
{ 2, "off", NULL, NULL },
{ 3, "pendingOff", NULL, NULL }, /* transitional status */
{ 4, "pendingOn", NULL, NULL }, /* transitional status */
{ 5, "unknown", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* Ugly hack: having the matching OID present means that the outlet is
* switchable. So, it should not require this value lookup */
static info_lkp_t cpqpower_outlet_switchability_info[] = {
{ 1, "yes" },
{ 2, "yes" },
{ 3, "yes" },
{ 4, "yes" },
{ 0, NULL }
{ 1, "yes", NULL, NULL },
{ 2, "yes", NULL, NULL },
{ 3, "yes", NULL, NULL },
{ 4, "yes", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
#define CPQPOWER_OID_SD_AFTER_DELAY ".1.3.6.1.4.1.232.165.3.8.1.0" /* UPS-MIB::upsControlOutputOffDelay */
@ -174,6 +173,12 @@ static info_lkp_t cpqpower_outlet_switchability_info[] = {
/* Snmp2NUT lookup table */
static snmp_info_t cpqpower_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* UPS page */
/* info_type, info_flags, info_len, OID, dfl, flags, oid2info, setvar */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, CPQPOWER_OID_MFR_NAME, "HP/Compaq", SU_FLAG_STATIC, NULL },
@ -183,7 +188,9 @@ static snmp_info_t cpqpower_mib[] = {
/* FIXME: split between firmware and firmware.aux ("00.01.0019;00.01.0004")
* UPS Firmware Revision : 00.01.0004
* Communication Board Firmware Revision : 00.01.0019 */
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, CPQPOWER_OID_FIRMREV, "", SU_FLAG_STATIC, NULL },
/* FIXME: the 2 "firmware" entries below should be SU_FLAG_SEMI_STATIC */
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, CPQPOWER_OID_FIRMREV, "", 0, NULL },
{ "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_AGENTREV, "", 0, NULL },
{ "ups.load", 0, 1.0, CPQPOWER_OID_LOAD_LEVEL, "", 0, NULL },
{ "ups.realpower", 0, 1.0, CPQPOWER_OID_OUT_POWER, "", SU_OUTPUT_1, NULL },
{ "ups.realpower", 0, 1.0, ".1.3.6.1.4.1.232.165.3.9.3.0", "", SU_OUTPUT_1, NULL },
@ -213,8 +220,8 @@ static snmp_info_t cpqpower_mib[] = {
* flywheel(7)
* fuelcell(8) */
{ "ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.8.1.0", STR_DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.8.2.0", STR_DEFAULT_ONDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.8.1.0", DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.8.2.0", DEFAULT_ONDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.timer.shutdown", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", "", SU_FLAG_OK, NULL },
{ "ups.timer.start", 0, 1, ".1.3.6.1.4.1.232.165.3.8.2.0", "", SU_FLAG_OK, NULL },
@ -232,7 +239,7 @@ static snmp_info_t cpqpower_mib[] = {
{ "battery.status", 0, 0.1, ".1.3.6.1.4.1.232.165.3.2.5.0", "", 0, NULL }, */
/* Input page */
{ "input.phases", 0, 1.0, CPQPOWER_OID_IN_LINES, "", SU_FLAG_SETINT, NULL, &input_phases },
{ "input.phases", 0, 1.0, CPQPOWER_OID_IN_LINES, "", 0, NULL },
/* { "input.phase", 0, 1.0, CPQPOWER_OID_IN_PHASE, "", SU_OUTPUT_1, NULL }, */
{ "input.frequency", 0, 0.1, CPQPOWER_OID_IN_FREQ , "", 0, NULL },
{ "input.voltage", 0, 1.0, CPQPOWER_OID_IN_VOLTAGE, "", SU_OUTPUT_1, NULL },
@ -254,7 +261,7 @@ static snmp_info_t cpqpower_mib[] = {
{ "input.quality", 0, 1.0, CPQPOWER_OID_IN_LINEBADS, "", 0, NULL },
/* Output page */
{ "output.phases", 0, 1.0, CPQPOWER_OID_OUT_LINES, "", SU_FLAG_SETINT, NULL, &output_phases },
{ "output.phases", 0, 1.0, CPQPOWER_OID_OUT_LINES, "", 0, NULL },
/* { "output.phase", 0, 1.0, CPQPOWER_OID_OUT_PHASE, "", SU_OUTPUT_1, NULL }, */
{ "output.frequency", 0, 0.1, CPQPOWER_OID_OUT_FREQUENCY, "", 0, NULL },
/* FIXME: handle multiplier (0.1 there) */
@ -291,42 +298,42 @@ static snmp_info_t cpqpower_mib[] = {
/* outlet template definition */
/* FIXME always true? */
{ "outlet.%i.switchable", ST_FLAG_STRING, 3, ".1.3.6.1.4.1.232.165.3.10.2.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, &cpqpower_outlet_switchability_info[0], NULL },
{ "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL, NULL },
/* { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_NAME ".%i", NULL, SU_OUTLET, NULL, NULL }, */
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.3.10.2.1.2.%i", NULL, SU_FLAG_OK | SU_OUTLET, &cpqpower_outlet_status_info[0], NULL },
{ "outlet.%i.switchable", ST_FLAG_STRING, 3, ".1.3.6.1.4.1.232.165.3.10.2.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, &cpqpower_outlet_switchability_info[0] },
{ "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL },
/* { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_NAME ".%i", NULL, SU_OUTLET, NULL }, */
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.3.10.2.1.2.%i", NULL, SU_FLAG_OK | SU_OUTLET, &cpqpower_outlet_status_info[0] },
/* FIXME: come up with a suitable varname!
* - The delay after going On Battery until the Receptacle is automatically turned Off.
* A value of -1 means that this Output should never be turned Off automatically, but must be turned Off only by command.
* { "outlet.%i.autoswitch.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.10.2.1.5.%i", STR_DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, // upsRecepAutoOffDelay
* { "outlet.%i.autoswitch.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.10.2.1.5.%i", DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, // upsRecepAutoOffDelay
* - Seconds delay after the Outlet is signaled to turn On before the Output is Automatically turned ON.
* A value of -1 means that this Output should never be turned On automatically, but only when specifically commanded to do so.
* { "outlet.%i.autoswitch.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.10.2.1.5.%i", STR_DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, // upsRecepAutoOnDelay
* { "outlet.%i.autoswitch.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.10.2.1.5.%i", DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, // upsRecepAutoOnDelay
*/
/* FIXME: also define .stop (as for 'shutdown.reboot')
* and .delay */
{ "outlet.%i.load.off", 0, 0, ".1.3.6.1.4.1.232.165.3.10.2.1.3.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.on", 0, 0, ".1.3.6.1.4.1.232.165.3.10.2.1.4.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.3.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL },
{ "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.4.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL },
/* FIXME: also define a .delay or map to "outlet.%i.delay.shutdown" */
{ "outlet.%i.load.cycle", 0, 0, ".1.3.6.1.4.1.232.165.3.10.2.1.7.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.7.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL },
/* instant commands. */
/* We need to duplicate load.{on,off} Vs load.{on,off}.delay, since
* "0" cancels the shutdown, so we put "1" (second) for immediate off! */
{ "load.off", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", "", SU_TYPE_CMD, NULL },
{ "load.on", 0, 1, ".1.3.6.1.4.1.232.165.3.8.2.0", "", SU_TYPE_CMD, NULL },
{ "shutdown.stop", 0, 0, ".1.3.6.1.4.1.232.165.3.8.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "load.off", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", "1", SU_TYPE_CMD, NULL },
{ "load.on", 0, 1, ".1.3.6.1.4.1.232.165.3.8.2.0", "1", SU_TYPE_CMD, NULL },
{ "shutdown.stop", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", "0", SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* FIXME: need ups.{timer,delay}.{start,shutdown} param counterparts! */
{ "load.off.delay", 0, DEFAULT_OFFDELAY, ".1.3.6.1.4.1.232.165.3.8.1.0", "", SU_TYPE_CMD, NULL },
{ "load.on.delay", 0, DEFAULT_ONDELAY, ".1.3.6.1.4.1.232.165.3.8.2.0", "", SU_TYPE_CMD, NULL },
{ "load.off.delay", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", DEFAULT_OFFDELAY, SU_TYPE_CMD, NULL },
{ "load.on.delay", 0, 1, ".1.3.6.1.4.1.232.165.3.8.2.0", DEFAULT_ONDELAY, SU_TYPE_CMD, NULL },
/* { CMD_SHUTDOWN, 0, CPQPOWER_OFF_GRACEFUL, CPQPOWER_OID_OFF, "", 0, NULL }, */
{ "shutdown.reboot", 0, 0, ".1.3.6.1.4.1.232.165.3.8.6.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "test.battery.start", 0, CPQPOWER_START_TEST, ".1.3.6.1.4.1.232.165.3.7.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "shutdown.reboot", 0, 1, ".1.3.6.1.4.1.232.165.3.8.6.0", "0", SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "test.battery.start", 0, 1, ".1.3.6.1.4.1.232.165.3.7.1.0", CPQPOWER_START_TEST, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t compaq = { "cpqpower", CPQPOWER_MIB_VERSION, NULL, CPQPOWER_OID_MFR_NAME, cpqpower_mib, CPQPOWER_SYSOID };
mib2nut_info_t compaq = { "cpqpower", CPQPOWER_MIB_VERSION, NULL, CPQPOWER_OID_MFR_NAME, cpqpower_mib, CPQPOWER_SYSOID, NULL };

View file

@ -24,15 +24,23 @@
*/
#include "main.h" /* for getval() */
#include "nut_float.h"
#include "hidparser.h" /* for FindObject_with_ID_Node() */
#include "usbhid-ups.h"
#include "cps-hid.h"
#include "usb-common.h"
#define CPS_HID_VERSION "CyberPower HID 0.4"
#define CPS_HID_VERSION "CyberPower HID 0.6"
/* Cyber Power Systems */
#define CPS_VENDORID 0x0764
/* Values for correcting the HID on some models
* where LogMin and LogMax are set incorrectly in the HID.
*/
#define CPS_VOLTAGE_LOGMIN 0
#define CPS_VOLTAGE_LOGMAX 511 /* Includes safety margin. */
/*! Battery voltage scale factor.
* For some devices, the reported battery voltage is off by factor
* of 1.5 so we need to apply a scale factor to it to get the real
@ -49,6 +57,8 @@ static const double battery_voltage_sanity_check = 1.4;
static void *cps_battery_scale(USBDevice_t *device)
{
NUT_UNUSED_VARIABLE(device);
might_need_battery_scale = 1;
return NULL;
}
@ -63,7 +73,7 @@ static usb_device_id_t cps_usb_device_table[] = {
{ USB_DEVICE(CPS_VENDORID, 0x0601), NULL },
/* Terminating entry */
{ -1, -1, NULL }
{ 0, 0, NULL }
};
/*! Adjusts @a battery_scale if voltage is well above nominal.
@ -84,7 +94,7 @@ static void cps_adjust_battery_scale(double batt_volt)
}
batt_volt_nom = strtod(batt_volt_nom_str, NULL);
if(batt_volt_nom == 0) {
if(d_equal(batt_volt_nom, 0)) {
upsdebugx(3, "%s: 'battery.voltage.nominal' is %s", __func__, batt_volt_nom_str);
return;
}
@ -114,7 +124,7 @@ static const char *cps_battvolt_fun(double value)
}
static info_lkp_t cps_battvolt[] = {
{ 0, NULL, &cps_battvolt_fun }
{ 0, NULL, &cps_battvolt_fun, NULL }
};
/* returns statically allocated string - must not use it again before
@ -130,7 +140,7 @@ static const char *cps_battcharge_fun(double value)
}
static info_lkp_t cps_battcharge[] = {
{ 0, NULL, &cps_battcharge_fun }
{ 0, NULL, &cps_battcharge_fun, NULL }
};
/* --------------------------------------------------------------- */
@ -193,12 +203,14 @@ static hid_info_t cps_hid2nut[] = {
{ "BOOL", 0, 0, "UPS.Output.Overload", NULL, NULL, 0, overload_info },
/* Input page */
{ "input.frequency", 0, 0, "UPS.Input.Frequency", NULL, "%.1f", 0, NULL },
{ "input.voltage.nominal", 0, 0, "UPS.Input.ConfigVoltage", NULL, "%.0f", 0, NULL },
{ "input.voltage", 0, 0, "UPS.Input.Voltage", NULL, "%.1f", 0, NULL },
{ "input.transfer.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "input.transfer.high", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
/* Output page */
{ "output.frequency", 0, 0, "UPS.Output.Frequency", NULL, "%.1f", 0, NULL },
{ "output.voltage", 0, 0, "UPS.Output.Voltage", NULL, "%.1f", 0, NULL },
{ "output.voltage.nominal", 0, 0, "UPS.Output.ConfigVoltage", NULL, "%.0f", 0, NULL },
@ -257,6 +269,62 @@ static int cps_claim(HIDDevice_t *hd) {
}
}
/* CPS Models like CP900EPFCLCD return a syntactically legal but incorrect
* Report Descriptor whereby the Input High Transfer Max/Min values
* are used for the Output Voltage Usage Item limits.
* Additionally the Input Voltage LogMax is set incorrectly for EU models.
* This corrects them by finding and applying fixed
* voltage limits as being more appropriate.
*/
static int cps_fix_report_desc(HIDDevice_t *pDev, HIDDesc_t *pDesc_arg) {
HIDData_t *pData;
int vendorID = pDev->VendorID;
int productID = pDev->ProductID;
if (vendorID != CPS_VENDORID || productID != 0x0501) {
return 0;
}
upsdebugx(3, "Attempting Report Descriptor fix for UPS: Vendor: %04x, Product: %04x", vendorID, productID);
/* Apply the fix cautiously by looking for input voltage, high voltage transfer and output voltage report usages.
* If the output voltage log min/max equals high voltage transfer log min/max then the bug is present.
* To fix it Set both the input and output voltages to pre-defined settings.
*/
if ((pData=FindObject_with_ID_Node(pDesc_arg, 16, USAGE_POW_HIGH_VOLTAGE_TRANSFER))) {
long hvt_logmin = pData->LogMin;
long hvt_logmax = pData->LogMax;
upsdebugx(4, "Report Descriptor: hvt input LogMin: %ld LogMax: %ld", hvt_logmin, hvt_logmax);
if ((pData=FindObject_with_ID_Node(pDesc_arg, 18, USAGE_POW_VOLTAGE))) {
long output_logmin = pData->LogMin;
long output_logmax = pData->LogMax;
upsdebugx(4, "Report Descriptor: output LogMin: %ld LogMax: %ld",
output_logmin, output_logmax);
if (hvt_logmin == output_logmin && hvt_logmax == output_logmax) {
pData->LogMin = CPS_VOLTAGE_LOGMIN;
pData->LogMax = CPS_VOLTAGE_LOGMAX;
upsdebugx(3, "Fixing Report Descriptor. Set Output Voltage LogMin = %d, LogMax = %d",
CPS_VOLTAGE_LOGMIN , CPS_VOLTAGE_LOGMAX);
if ((pData=FindObject_with_ID_Node(pDesc_arg, 15, USAGE_POW_VOLTAGE))) {
long input_logmin = pData->LogMin;
long input_logmax = pData->LogMax;
upsdebugx(4, "Report Descriptor: input LogMin: %ld LogMax: %ld",
input_logmin, input_logmax);
upsdebugx(3, "Fixing Report Descriptor. Set Input Voltage LogMin = %d, LogMax = %d",
CPS_VOLTAGE_LOGMIN , CPS_VOLTAGE_LOGMAX);
}
return 1;
}
}
}
return 0;
}
subdriver_t cps_subdriver = {
CPS_HID_VERSION,
cps_claim,
@ -265,4 +333,5 @@ subdriver_t cps_subdriver = {
cps_format_model,
cps_format_mfr,
cps_format_serial,
cps_fix_report_desc,
};

View file

@ -1,7 +1,7 @@
/* cyberpower-mib.c - data to monitor Cyberpower RMCARD
*
* Copyright (C) 2010 - Eric Schultz <paradxum@mentaljynx.com>
*
*
* derived (i.e. basically copied and modified) of bestpower by:
* Copyright (C) 2010 - Arnaud Quette <arnaud.quette@free.fr>
*
@ -24,58 +24,153 @@
#include "cyberpower-mib.h"
#define CYBERPOWER_MIB_VERSION "0.1"
#define CYBERPOWER_MIB_VERSION "0.51"
#define CYBERPOWER_OID_MODEL_NAME ".1.3.6.1.4.1.3808.1.1.1.1.1.1.0"
#define CYBERPOWER_SYSOID ".1.3.6.1.4.1.3808"
/* CPS-MIB::ups */
#define CYBERPOWER_SYSOID ".1.3.6.1.4.1.3808.1.1.1"
/* https://www.cyberpowersystems.com/products/software/mib-files/ */
/* Per CPS MIB 2.9 upsBaseOutputStatus OBJECT-TYPE: */
static info_lkp_t cyberpower_power_status[] = {
{ 2, "OL" },
{ 3, "OB" },
{ 4, "OL" },
{ 5, "OL" },
{ 7, "OL" },
{ 1, "NULL" },
{ 6, "NULL" },
{ 0, NULL }
{ 1, "NULL", NULL, NULL }, /* unknown */
{ 2, "OL", NULL, NULL }, /* onLine */
{ 3, "OB", NULL, NULL }, /* onBattery */
{ 4, "OL BOOST", NULL, NULL }, /* onBoost */
{ 5, "OFF", NULL, NULL }, /* onSleep */
{ 6, "OFF", NULL, NULL }, /* off */
{ 7, "OL", NULL, NULL }, /* rebooting */
{ 8, "OL", NULL, NULL }, /* onECO */
{ 9, "OL BYPASS", NULL, NULL }, /* onBypass */
{ 10, "OL TRIM", NULL, NULL }, /* onBuck */
{ 11, "OL OVER", NULL, NULL }, /* onOverload */
{ 0, NULL, NULL, NULL }
} ;
static info_lkp_t cyberpower_battery_status[] = {
{ 1, "", NULL, NULL }, /* unknown */
{ 2, "", NULL, NULL }, /* batteryNormal */
{ 3, "LB", NULL, NULL }, /* batteryLow */
{ 0, NULL, NULL, NULL }
} ;
static info_lkp_t cyberpower_cal_status[] = {
{ 1, "", NULL, NULL }, /* Calibration Successful */
{ 2, "", NULL, NULL }, /* Calibration Invalid */
{ 3, "CAL", NULL, NULL }, /* Calibration in progress */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t cyberpower_battrepl_status[] = {
{ 1, "", NULL, NULL }, /* No battery needs replacing */
{ 2, "RB", NULL, NULL }, /* Batteries need to be replaced */
{ 0, NULL, NULL, NULL }
};
/* Snmp2NUT lookup table for CyberPower MIB */
static snmp_info_t cyberpower_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device page */
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ups",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "CYBERPOWER",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, CYBERPOWER_OID_MODEL_NAME,
"CyberPower", SU_FLAG_STATIC, NULL, NULL },
"CyberPower", SU_FLAG_STATIC, NULL },
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.1.2.3.0",
"", SU_FLAG_STATIC, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.1.2.1.0",
"", SU_FLAG_STATIC, NULL },
"", SU_FLAG_STATIC, NULL },
{ "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.1.2.2.0", "",
0, NULL },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.4.1.1.0", "",
0 /*SU_STATUS_PWR*/, &cyberpower_power_status[0] },
SU_FLAG_OK | SU_STATUS_PWR, &cyberpower_power_status[0] },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.2.1.1.0", "",
SU_FLAG_OK | SU_STATUS_BATT, &cyberpower_battery_status[0] },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.7.2.7.0", "",
SU_FLAG_OK | SU_STATUS_CAL, &cyberpower_cal_status[0] },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.2.2.5.0", "",
SU_FLAG_OK | SU_STATUS_RB, &cyberpower_battrepl_status[0] },
{ "ups.load", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.4.2.3.0", "",
0, NULL },
/* Battery runtime is expressed in minutes */
{ "battery.runtime", 0, 60.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.4.0", "",
/* Battery runtime is expressed in seconds */
{ "battery.runtime", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.4.0", "",
0, NULL },
/* The elapsed time in seconds since the
* UPS has switched to battery power */
{ "battery.runtime.elapsed", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.1.2.0", "",
0, NULL },
/* Different generations/models reported "battery.voltage" by different OIDs: */
{ "battery.voltage", 0, 0.1, ".1.3.6.1.2.1.33.1.2.5.0", "",
0, NULL },
{ "battery.voltage", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.2.2.2.0", "",
0, NULL },
{ "battery.voltage.nominal", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.8.0", "",
0, NULL },
/* Different generations/models reported "battery.current" by different OIDs: */
{ "battery.current", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.4.2.4.0", "",
0, NULL },
{ "battery.current", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.2.2.7.0", "",
0, NULL },
{ "battery.charge", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.1.0", "",
0, NULL },
{ "battery.temperature", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.3.0", "",
0, NULL },
{ "input.voltage", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.3.2.1.0", "",
0, NULL },
{ "input.frequency", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.3.2.4.0", "",
0, NULL },
{ "output.voltage", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.4.2.1.0", "",
0, NULL },
{ "output.frequency", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.4.2.2.0", "",
0, NULL },
{ "output.current", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.4.2.4.0", "",
0, NULL },
/* Delays affecting instant commands */
/* upsAdvanceConfigReturnDelay */
{ "ups.delay.start", ST_FLAG_RW, 1.0, ".1.3.6.1.4.1.3808.1.1.1.5.2.9.0", "0",
SU_FLAG_OK | SU_TYPE_TIME, NULL },
/* Not provided by CPS-MIB */
{ "ups.delay.reboot", 0, 1.0, NULL, "0",
SU_FLAG_OK | SU_FLAG_ABSENT, NULL },
/* upsAdvanceConfigSleepDelay */
{ "ups.delay.shutdown", ST_FLAG_RW, 1.0, ".1.3.6.1.4.1.3808.1.1.1.5.2.11.0", "60",
SU_FLAG_OK | SU_TYPE_TIME, NULL },
/* instant commands. */
/* upsAdvanceControlUpsOff */
{ "load.off", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.1.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* upsAdvanceControlTurnOnUPS */
{ "load.on", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* upsAdvanceControlUpsOff */
{ "shutdown.stayoff", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* upsAdvanceControlUpsSleep */
{ "shutdown.return", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.6.2.3.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* upsAdvanceControlSimulatePowerFail */
{ "test.failure.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.4.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* upsAdvanceTestIndicators */
{ "test.panel.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.5.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* upsAdvanceTestDiagnostics */
{ "test.battery.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.2.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* upsAdvanceTestRuntimeCalibration */
{ "calibrate.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
{ "calibrate.stop", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL, NULL }
{ NULL, 0, 0, NULL, NULL, 0, NULL }
} ;
mib2nut_info_t cyberpower = { "cyberpower", CYBERPOWER_MIB_VERSION, NULL,
CYBERPOWER_OID_MODEL_NAME, cyberpower_mib, CYBERPOWER_SYSOID };
CYBERPOWER_OID_MODEL_NAME, cyberpower_mib, CYBERPOWER_SYSOID, NULL };

323
drivers/delta_ups-hid.c Normal file
View file

@ -0,0 +1,323 @@
/* delta_ups-hid.c - data mapping subdriver to monitor Delta UPS USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2012 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2013 Charles Lepple <clepple+nut@gmail.com>
* 2020 Luka Kovacic <luka.kovacic@builtin.io>
* 2021 Jungeon Kim <me@jungeon.kim>
*
* 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 "config.h" /* must be first */
#include "usbhid-ups.h"
#include "delta_ups-hid.h"
#include "main.h" /* for getval() */
#include "usb-common.h"
#define DELTA_UPS_HID_VERSION "Delta UPS HID 0.6"
/* Delta UPS */
#define DELTA_UPS_VENDORID 0x05dd
/* USB IDs device table */
static usb_device_id_t delta_ups_usb_device_table[] = {
/* Delta RT Series, Single Phase, 1/2/3 kVA */
/* Delta UPS Amplon R Series, Single Phase UPS, 1/2/3 kVA */
{ USB_DEVICE(DELTA_UPS_VENDORID, 0x041b), NULL },
/* Terminating entry */
{ 0, 0, NULL }
};
/* --------------------------------------------------------------- */
/* Vendor-specific usage table */
/* --------------------------------------------------------------- */
/* DELTA usage table */
static usage_lkp_t delta_ups_usage_lkp[] = {
{ "DELTA1", 0x00000000 },
{ "DELTA2", 0xff000055 },
/* { "DELTA3", 0xffff0010 }, */
{ "DeltaCustom", 0xffff0010 },
{ "DELTA4", 0xffff0056 },
/* { "DELTA5", 0xffff0057 }, */
{ "DeltaConfigTransferLowMax", 0xffff0057 },
/* { "DELTA6", 0xffff0058 }, */
{ "DeltaConfigTransferLowMin", 0xffff0058 },
/* { "DELTA7", 0xffff0059 }, */
{ "DeltaConfigTransferHighMax", 0xffff0059 },
/* { "DELTA8", 0xffff005a }, */
{ "DeltaConfigTransferHighMin", 0xffff005a },
{ "DELTA9", 0xffff0060 },
/* { "DELTA10", 0xffff0061 }, */
{ "DeltaConfigExternalBatteryPack", 0xffff0061 },
{ "DELTA11", 0xffff0062 },
{ "DELTA12", 0xffff0063 },
{ "DELTA13", 0xffff0064 },
{ "DELTA14", 0xffff0065 },
{ "DELTA15", 0xffff0066 },
{ "DELTA16", 0xffff0067 },
{ "DELTA17", 0xffff0068 },
/* { "DELTA18", 0xffff0075 }, */
{ "DeltaModelName", 0xffff0075 },
{ "DELTA19", 0xffff0076 },
/* { "DELTA20", 0xffff007c }, */
{ "DeltaUPSType", 0xffff007c },
{ "DELTA21", 0xffff007d },
/* { "DELTA22", 0xffff0081 }, */
{ "DeltaConfigStartPowerRestoreDelay", 0xffff0081 },
/* { "DELTA23", 0xffff0091 }, */
{ "DeltaOutputSource", 0xffff0091 },
{ "DELTA24", 0xffff0092 },
{ "DELTA25", 0xffff0093 },
{ "DELTA26", 0xffff0094 },
{ "DELTA27", 0xffff0095 },
{ "DELTA28", 0xffff0096 },
{ "DELTA29", 0xffff0097 },
{ "DELTA30", 0xffff0098 },
{ "DELTA31", 0xffff0099 },
{ "DELTA32", 0xffff009a },
/* { "DELTA33", 0xffff009b }, */
{ "DeltaConfigSensitivity", 0xffff009b },
/* { "DELTA34", 0xffff009c }, */
{ "DeltaConfigStartPowerRestore", 0xffff009c },
/* Terminating entry */
{ NULL, 0 }
};
static usage_tables_t delta_ups_utab[] = {
delta_ups_usage_lkp,
hid_usage_lkp,
NULL,
};
/* --------------------------------------------------------------- */
/* Helper lookup tables and mapping functions */
/* --------------------------------------------------------------- */
static info_lkp_t delta_ups_sensitivity_info[] = {
{ 0, "normal", NULL, NULL },
{ 1, "reduced", NULL, NULL },
{ 2, "low", NULL, NULL },
/* Terminating entry */
{ 0, NULL, NULL, NULL }
};
static const char *delta_ups_type_fun(double value)
{
static const char* upstypes[] = {
"online",
"offline",
"line-interactive",
"3-phase",
"split-phase"
};
int type = (int)value & 0xf;
if (type == 6) {
type = 4;
} else if (2 < type && type <= 5) {
type -= 2;
}
if (type < 0 || type > 4) {
return NULL;
}
return upstypes[type];
}
static info_lkp_t delta_ups_type_info[] = {
{ 0, NULL, delta_ups_type_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t delta_ups_output_source_info[] = {
{ 0, "normal", NULL, NULL },
{ 1, "battery", NULL, NULL },
{ 2, "bypass/reserve", NULL, NULL },
{ 3, "reducing", NULL, NULL },
{ 4, "boosting", NULL, NULL },
{ 5, "manual bypass", NULL, NULL },
{ 6, "other", NULL, NULL },
{ 7, "no output", NULL, NULL },
{ 8, "on eco", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* --------------------------------------------------------------- */
/* HID2NUT lookup table */
/* --------------------------------------------------------------- */
static hid_info_t delta_ups_hid2nut[] = {
{ "input.sensitivity", ST_FLAG_RW, 0, "UPS.DeltaCustom.[1].DeltaConfigSensitivity", NULL, "%s", 0, delta_ups_sensitivity_info },
{ "input.voltage.nominal", 0, 0, "UPS.PowerSummary.Input.ConfigVoltage", NULL, "%.1f", HU_FLAG_SEMI_STATIC, NULL },
{ "input.voltage", 0, 0, "UPS.PowerSummary.Input.Voltage", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "input.voltage", 0, 0, "UPS.PowerConverter.Input.Voltage", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "input.transfer.low", ST_FLAG_RW, 0, "UPS.PowerConverter.Output.LowVoltageTransfer", NULL, "%.1f", 0, NULL },
{ "input.transfer.high", ST_FLAG_RW, 0, "UPS.PowerConverter.Output.HighVoltageTransfer", NULL, "%.1f", 0, NULL },
{ "input.transfer.low.min", 0, 0, "UPS.PowerConverter.Output.DeltaConfigTransferLowMin", NULL, "%.1f", HU_FLAG_STATIC, NULL },
{ "input.transfer.low.max", 0, 0, "UPS.PowerConverter.Output.DeltaConfigTransferLowMax", NULL, "%.1f", HU_FLAG_STATIC, NULL },
{ "input.transfer.high.min", 0, 0, "UPS.PowerConverter.Output.DeltaConfigTransferHighMin", NULL, "%.1f", HU_FLAG_STATIC, NULL },
{ "input.transfer.high.max", 0, 0, "UPS.PowerConverter.Output.DeltaConfigTransferHighMax", NULL, "%.1f", HU_FLAG_STATIC, NULL },
/* FIXME: Check vs hardware, is this an "input" or "outlet/outpu" value after all? */
{ "input.source", 0, 0, "UPS.OutletSystem.Outlet.DeltaOutputSource", NULL, "%s", 0, delta_ups_output_source_info },
{ "input.frequency", 0, 0, "UPS.PowerConverter.Input.Frequency", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "battery.voltage.nominal", 0, 0, "UPS.BatterySystem.Battery.ConfigVoltage", NULL, "%.1f", HU_FLAG_STATIC, NULL },
{ "battery.voltage", 0, 0, "UPS.BatterySystem.Battery.Voltage", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL },
{ "battery.charge", 0, 0, "UPS.BatterySystem.Battery.RemainingCapacity", NULL, "%.0f", 0, NULL },
{ "battery.charge.low", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
/* { "battery.charge.low", 0, 0, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, */
{ "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "battery.temperature", 0, 0, "UPS.BatterySystem.Temperature", NULL, "%s", HU_FLAG_QUICK_POLL, kelvin_celsius_conversion },
{ "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL },
{ "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", HU_FLAG_STATIC, stringid_conversion },
{ "battery.capacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "battery.capacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "output.voltage.nominal", 0, 0, "UPS.Flow.ConfigVoltage", NULL, "%.1f", HU_FLAG_SEMI_STATIC, NULL },
{ "output.frequency.nominal", 0, 0, "UPS.Flow.ConfigFrequency", NULL, "%.1f", HU_FLAG_SEMI_STATIC, NULL },
{ "output.voltage", 0, 0, "UPS.PowerConverter.Output.Voltage", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "output.frequency", 0, 0, "UPS.PowerConverter.Output.Frequency", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "output.current", 0, 0, "UPS.PowerConverter.Output.Current", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "ups.beeper.status", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "%s", HU_FLAG_QUICK_POLL, beeper_info },
{ "ups.test.result", 0, 0, "UPS.BatterySystem.Test", NULL, "%s", 0, test_read_info },
{ "ups.type", 0, 0, "UPS.DeltaCustom.[1].DeltaUPSType", NULL, "%s", HU_FLAG_STATIC, delta_ups_type_info },
{ "ups.start.auto", ST_FLAG_RW, 0, "UPS.DeltaCustom.[1].DeltaConfigStartPowerRestore", NULL, "%s", 0, yes_no_info },
{ "ups.power.nominal", 0, 0, "UPS.Flow.ConfigApparentPower", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "ups.realpower", 0, 0, "UPS.OutletSystem.Outlet.ActivePower", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "ups.realpower", 0, 0, "UPS.PowerConverter.Output.ActivePower", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
{ "ups.load", 0, 0, "UPS.OutletSystem.Outlet.PercentLoad", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL },
/* Per comments to PR #807 these 3 declarations are populated elsewhere,
* by delta_ups_format_*() functions hooks; see:
* https://github.com/networkupstools/nut/pull/807#discussion_r501496383
*/
/* { "ups.mfr", 0, 0, "UPS.PowerSummary.iManufacturer", NULL, "%s", HU_FLAG_STATIC, stringid_conversion },
{ "ups.model", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%s", HU_FLAG_STATIC, stringid_conversion },
{ "ups.serial", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%s", HU_FLAG_STATIC, stringid_conversion },
*/
{ "ups.delay.start", ST_FLAG_RW, 0, "UPS.OutletSystem.Outlet.DeltaConfigStartPowerRestoreDelay", NULL, "%.0f", 0, NULL },
/* mge-hid.c simlar configurable settings:
{ "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL },
{ "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL },
...
{ "ups.timer.shutdown", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL },
*/
{ "ups.timer.start", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL },
{ "ups.timer.shutdown", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL },
{ "ups.timer.reboot", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Good", NULL, NULL, HU_FLAG_QUICK_POLL, off_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.InternalFailure", NULL, NULL, HU_FLAG_QUICK_POLL, commfault_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, NULL, HU_FLAG_QUICK_POLL, shutdownimm_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FullyCharged", NULL, NULL, HU_FLAG_QUICK_POLL, fullycharged_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FullyDischarged", NULL, NULL, HU_FLAG_QUICK_POLL, depleted_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.NeedReplacement", NULL, NULL, HU_FLAG_QUICK_POLL, replacebatt_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.VoltageOutOfRange", NULL, NULL, HU_FLAG_QUICK_POLL, vrange_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.Buck", NULL, NULL, HU_FLAG_QUICK_POLL, trim_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.Boost", NULL, NULL, HU_FLAG_QUICK_POLL, boost_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.Overload", NULL, NULL, HU_FLAG_QUICK_POLL, overload_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.Used", NULL, NULL, HU_FLAG_QUICK_POLL, nobattery_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.OverTemperature", NULL, NULL, HU_FLAG_QUICK_POLL, overheat_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.InternalFailure", NULL, NULL, HU_FLAG_QUICK_POLL, commfault_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.AwaitingPower", NULL, NULL, HU_FLAG_QUICK_POLL, awaitingpower_info },
{ "beeper.on", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL },
{ "beeper.off", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL },
{ "beeper.enable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL },
{ "beeper.disable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "1", HU_TYPE_CMD, NULL },
{ "beeper.mute", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL },
/* 10 seconds battery test */
{ "test.battery.start.quick", 0, 0, "UPS.BatterySystem.Test", NULL, "1", HU_TYPE_CMD, NULL },
/* test until battery low */
{ "test.battery.start.deep", 0, 0, "UPS.BatterySystem.Test", NULL, "2", HU_TYPE_CMD, NULL },
{ "test.battery.stop", 0, 0, "UPS.BatterySystem.Test", NULL, "3", HU_TYPE_CMD, NULL },
{ "load.on.delay", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL },
{ "load.off.delay", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL },
{ "shutdown.stop", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL },
{ "shutdown.reboot", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL },
/* Terminating entry */
{ NULL, 0, 0, NULL, NULL, NULL, 0, NULL }
};
static const char *delta_ups_format_mfr(HIDDevice_t *hd) {
return hd->Vendor ? hd->Vendor : "Delta";
}
static const char *delta_ups_format_model(HIDDevice_t *hd) {
static char model[SMALLBUF];
HIDGetItemString(udev, "UPS.DeltaCustom.[1].DeltaModelName", model, sizeof(model), delta_ups_utab);
if (strlen(model) < 1) {
return hd->Product;
}
return model;
}
static const char *delta_ups_format_serial(HIDDevice_t *hd) {
return hd->Serial;
}
/* this function allows the subdriver to "claim" a device: return 1 if
* the device is supported by this subdriver, else 0. */
static int delta_ups_claim(HIDDevice_t *hd) {
int status = is_usb_device_supported(delta_ups_usb_device_table, hd);
switch (status) {
case SUPPORTED:
return 1;
case POSSIBLY_SUPPORTED:
/* by default, reject, unless the productid option is given */
if (getval("productid")) {
return 1;
}
possibly_supported("Delta", hd);
return 0;
case NOT_SUPPORTED:
default:
return 0;
}
}
subdriver_t delta_ups_subdriver = {
DELTA_UPS_HID_VERSION,
delta_ups_claim,
delta_ups_utab,
delta_ups_hid2nut,
delta_ups_format_model,
delta_ups_format_mfr,
delta_ups_format_serial,
fix_report_desc,
};

31
drivers/delta_ups-hid.h Normal file
View file

@ -0,0 +1,31 @@
/* delta_ups-hid.h - data mapping subdriver to monitor Delta UPS USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2009 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2021 Jungeon Kim <me@jungeon.kim>
*
* 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
*/
#ifndef DELTA_UPS_HID_H
#define DELTA_UPS_HID_H
#include "usbhid-ups.h"
extern subdriver_t delta_ups_subdriver;
#endif /* DELTA_UPS_HID_H */

View file

@ -7,7 +7,7 @@
* gen-snmp-subdriver.sh script. It must be customized!
*
* MIB reference: http://www.networkupstools.org/ups-protocols/snmp/DeltaUPSv4.mib
*
*
* 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
@ -25,38 +25,38 @@
#include "delta_ups-mib.h"
#define DELTA_UPS_MIB_VERSION "0.2"
#define DELTA_UPS_MIB_VERSION "0.5"
#define DELTA_UPS_SYSOID ".1.3.6.1.4.1.2254.2.4"
/* To create a value lookup structure (as needed on the 2nd line of the example
* below), use the following kind of declaration, outside of the present snmp_info_t[]:
* static info_lkp_t onbatt_info[] = {
* { 1, "OB" },
* { 2, "OL" },
* { 0, NULL }
* static info_lkp_t delta_ups_onbatt_info[] = {
* { 1, "OB", NULL, NULL },
* { 2, "OL", NULL, NULL },
* { 0, NULL, NULL, NULL }
* };
*/
static info_lkp_t delta_ups_upstype_info[] = {
{ 1, "on-line" },
{ 2, "off-line" },
{ 3, "line-interactive" },
{ 4, "3phase" },
{ 5, "splite-phase" },
{ 0, NULL }
{ 1, "on-line", NULL, NULL },
{ 2, "off-line", NULL, NULL },
{ 3, "line-interactive", NULL, NULL },
{ 4, "3phase", NULL, NULL },
{ 5, "splite-phase", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t delta_ups_pwr_info[] = {
{ 0, "OL" }, /* normal */
{ 1, "OB" }, /* battery */
{ 2, "BYPASS" }, /* bypass */
{ 3, "TRIM" }, /* reducing */
{ 4, "BOOST" }, /* boosting */
{ 5, "BYPASS" }, /* manualBypass */
/*{ 6, "NULL" },*/ /* other */
{ 7, "OFF" }, /* none */
{ 0, NULL }
{ 0, "OL", NULL, NULL }, /* normal */
{ 1, "OB", NULL, NULL }, /* battery */
{ 2, "BYPASS", NULL, NULL }, /* bypass */
{ 3, "TRIM", NULL, NULL }, /* reducing */
{ 4, "BOOST", NULL, NULL }, /* boosting */
{ 5, "BYPASS", NULL, NULL }, /* manualBypass */
/*{ 6, "NULL", NULL, NULL },*/ /* other */
{ 7, "OFF", NULL, NULL }, /* none */
{ 0, NULL, NULL, NULL }
} ;
/* DELTA_UPS Snmp2NUT lookup table */
@ -73,21 +73,25 @@ static snmp_info_t delta_ups_mib[] = {
* dfl: default value
* flags: snmp-ups internal flags (FIXME: ...)
* oid2info: lookup table between OID and NUT values
* setvar: variable to set for SU_FLAG_SETINT
*
* Example:
* { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.1", "", SU_INPUT_1, NULL },
* { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.705.1.7.3.0", "", SU_FLAG_OK | SU_STATUS_BATT, onbatt_info },
* { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.705.1.7.3.0", "", SU_FLAG_OK | SU_STATUS_BATT, delta_ups_onbatt_info },
*
* To create a value lookup structure (as needed on the 2nd line), use the
* following kind of declaration, outside of the present snmp_info_t[]:
* static info_lkp_t onbatt_info[] = {
* static info_lkp_t delta_ups_onbatt_info[] = {
* { 1, "OB" },
* { 2, "OL" },
* { 0, NULL }
* };
*/
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* dupsIdentManufacturer.0 = STRING: "Socomec" */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2254.2.4.1.1.0", NULL, SU_FLAG_OK, NULL },
/* dupsIdentModel.0 = STRING: "NETYS RT 1/1 UPS" */
@ -358,4 +362,4 @@ static snmp_info_t delta_ups_mib[] = {
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t delta_ups = { "delta_ups", DELTA_UPS_MIB_VERSION, NULL, NULL, delta_ups_mib, DELTA_UPS_SYSOID };
mib2nut_info_t delta_ups = { "delta_ups", DELTA_UPS_MIB_VERSION, NULL, NULL, delta_ups_mib, DELTA_UPS_SYSOID, NULL };

View file

@ -1,9 +1,9 @@
/* dstate.c - Network UPS Tools driver-side state management
Copyright (C)
2003 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
2012 Arnaud Quette <arnaud.quette@free.fr>
2003 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
2012 - 2017 Arnaud Quette <arnaud.quette@free.fr>
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
@ -20,6 +20,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h" /* must be the first header */
#include <stdio.h>
#include <stdarg.h>
#include <sys/stat.h>
@ -32,10 +34,12 @@
#include "dstate.h"
#include "state.h"
#include "parseconf.h"
#include "attribute.h"
#include "nut_stdint.h"
static int sockfd = -1, stale = 1, alarm_active = 0, ignorelb = 0;
static char *sockfn = NULL;
static char status_buf[ST_MAX_VALUE_LEN], alarm_buf[LARGEBUF];
static char status_buf[ST_MAX_VALUE_LEN], alarm_buf[ST_MAX_VALUE_LEN];
static st_tree_t *dtree_root = NULL;
static conn_t *connhead = NULL;
static cmdlist_t *cmdhead = NULL;
@ -43,6 +47,9 @@
struct ups_handler upsh;
/* this may be a frequent stumbling point for new users, so be verbose here */
static void sock_fail(const char *fn)
__attribute__((noreturn));
static void sock_fail(const char *fn)
{
int sockerr;
@ -70,7 +77,7 @@ static void sock_fail(const char *fn)
user->pw_name, (int)user->pw_uid);
printf("Things to try:\n\n");
printf(" - set different owners or permissions on %s\n\n",
printf(" - set different owners or permissions on %s\n\n",
dflt_statepath());
printf(" - run this as some other user "
"(try -u <username>)\n");
@ -87,9 +94,9 @@ static void sock_fail(const char *fn)
printf(" - mkdir %s\n", dflt_statepath());
break;
}
/*
* there - that wasn't so bad. every helpful line of code here
* there - that wasn't so bad. every helpful line of code here
* prevents one more "help me" mail to the list a year from now
*/
@ -102,6 +109,8 @@ static int sock_open(const char *fn)
int ret, fd;
struct sockaddr_un ssaddr;
check_unix_socket_filename(fn);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
@ -163,13 +172,26 @@ static void sock_disconnect(conn_t *conn)
static void send_to_all(const char *fmt, ...)
{
int ret;
ssize_t ret;
char buf[ST_SOCK_BUF_LEN];
size_t buflen;
va_list ap;
conn_t *conn, *cnext;
va_start(ap, fmt);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
ret = vsnprintf(buf, sizeof(buf), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
if (ret < 1) {
@ -177,45 +199,132 @@ static void send_to_all(const char *fmt, ...)
return;
}
upsdebugx(5, "%s: %.*s", __func__, ret-1, buf);
if (ret <= INT_MAX)
upsdebugx(5, "%s: %.*s", __func__, (int)(ret-1), buf);
buflen = strlen(buf);
if (buflen >= SSIZE_MAX) {
/* Can't compare buflen to ret... though should not happen with ST_SOCK_BUF_LEN */
upslog_with_errno(LOG_NOTICE, "%s failed: buffered message too large", __func__);
return;
}
for (conn = connhead; conn; conn = cnext) {
cnext = conn->next;
ret = write(conn->fd, buf, strlen(buf));
ret = write(conn->fd, buf, buflen);
if (ret != (int)strlen(buf)) {
upsdebugx(1, "write %d bytes to socket %d failed", (int)strlen(buf), conn->fd);
if ((ret < 1) || (ret != (ssize_t)buflen)) {
upsdebugx(0, "WARNING: %s: write %zd bytes to "
"socket %d failed (ret=%zd), disconnecting: %s",
__func__, buflen, conn->fd, ret, strerror(errno));
upsdebugx(6, "failed write: %s", buf);
sock_disconnect(conn);
/* TOTHINK: Maybe fallback elsewhere in other cases? */
if (ret < 0 && errno == EAGAIN && do_synchronous == -1) {
upsdebugx(0, "%s: synchronous mode was 'auto', "
"will try 'on' for next connections",
__func__);
do_synchronous = 1;
}
dstate_setinfo("driver.parameter.synchronous", "%s",
(do_synchronous==1)?"yes":((do_synchronous==0)?"no":"auto"));
} else {
upsdebugx(6, "%s: write %zd bytes to socket %d succeeded "
"(ret=%zd): %s",
__func__, buflen, conn->fd, ret, buf);
}
}
}
static int send_to_one(conn_t *conn, const char *fmt, ...)
{
int ret;
ssize_t ret;
va_list ap;
char buf[ST_SOCK_BUF_LEN];
size_t buflen;
va_start(ap, fmt);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
ret = vsnprintf(buf, sizeof(buf), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
upsdebugx(2, "%s: sending %.*s", __func__, (int)strcspn(buf, "\n"), buf);
if (ret < 1) {
upsdebugx(2, "%s: nothing to write", __func__);
return 1;
}
upsdebugx(5, "%s: %.*s", __func__, ret-1, buf);
ret = write(conn->fd, buf, strlen(buf));
if (ret != (int)strlen(buf)) {
upsdebugx(1, "write %d bytes to socket %d failed", (int)strlen(buf), conn->fd);
sock_disconnect(conn);
buflen = strlen(buf);
if (buflen >= SSIZE_MAX) {
/* Can't compare buflen to ret... though should not happen with ST_SOCK_BUF_LEN */
upslog_with_errno(LOG_NOTICE, "%s failed: buffered message too large", __func__);
return 0; /* failed */
}
if (ret <= INT_MAX)
upsdebugx(5, "%s: %.*s", __func__, (int)(ret-1), buf);
/*
upsdebugx(0, "%s: writing %zd bytes to socket %d: %s",
__func__, buflen, conn->fd, buf);
*/
ret = write(conn->fd, buf, buflen);
if (ret < 0) {
/* Hacky bugfix: throttle down for upsd to read that */
upsdebugx(1, "%s: had to throttle down to retry "
"writing %zd bytes to socket %d "
"(ret=%zd, errno=%d, strerror=%s): %s",
__func__, buflen, conn->fd,
ret, errno, strerror(errno),
buf);
usleep(200);
ret = write(conn->fd, buf, buflen);
if (ret == (ssize_t)buflen) {
upsdebugx(1, "%s: throttling down helped", __func__);
}
}
if ((ret < 1) || (ret != (ssize_t)buflen)) {
upsdebugx(0, "WARNING: %s: write %zd bytes to "
"socket %d failed (ret=%zd), disconnecting: %s",
__func__, buflen, conn->fd, ret, strerror(errno));
upsdebugx(6, "failed write: %s", buf);
sock_disconnect(conn);
/* TOTHINK: Maybe fallback elsewhere in other cases? */
if (ret < 0 && errno == EAGAIN && do_synchronous == -1) {
upsdebugx(0, "%s: synchronous mode was 'auto', "
"will try 'on' for next connections",
__func__);
do_synchronous = 1;
}
dstate_setinfo("driver.parameter.synchronous", "%s",
(do_synchronous==1)?"yes":((do_synchronous==0)?"no":"auto"));
return 0; /* failed */
} else {
upsdebugx(6, "%s: write %zd bytes to socket %d succeeded "
"(ret=%zd): %s",
__func__, buflen, conn->fd, ret, buf);
}
return 1; /* OK */
}
@ -224,7 +333,7 @@ static void sock_connect(int sock)
int fd, ret;
conn_t *conn;
struct sockaddr_un sa;
#if defined(__hpux) && !defined(_XOPEN_SOURCE_EXTENDED)
#if defined(__hpux) && !defined(_XOPEN_SOURCE_EXTENDED)
int salen;
#else
socklen_t salen;
@ -237,8 +346,15 @@ static void sock_connect(int sock)
return;
}
/* enable nonblocking I/O */
if (!do_synchronous) {
/* enable nonblocking I/O?
* -1 = auto (try async, allow fallback to sync)
* 0 = async
* 1 = sync
*/
if (do_synchronous < 1) {
upsdebugx(0, "%s: enabling asynchronous mode (%s)",
__func__, (do_synchronous<0)?"auto":"fixed");
ret = fcntl(fd, F_GETFL, 0);
if (ret < 0) {
@ -253,7 +369,10 @@ static void sock_connect(int sock)
upslog_with_errno(LOG_ERR, "fcntl set O_NDELAY on unix fd failed");
close(fd);
return;
}
}
}
else {
upsdebugx(0, "%s: keeping default synchronous mode", __func__);
}
conn = xcalloc(1, sizeof(*conn));
@ -309,7 +428,7 @@ static int st_tree_dump_conn(st_tree_t *node, conn_t *conn)
/* provide any auxiliary data */
if (node->aux) {
if (!send_to_one(conn, "SETAUX %s %d\n", node->var, node->aux)) {
if (!send_to_one(conn, "SETAUX %s %ld\n", node->var, node->aux)) {
return 0;
}
}
@ -327,6 +446,9 @@ static int st_tree_dump_conn(st_tree_t *node, conn_t *conn)
if (node->flags & ST_FLAG_STRING) {
snprintfcat(flist, sizeof(flist), " STRING");
}
if (node->flags & ST_FLAG_NUMBER) {
snprintfcat(flist, sizeof(flist), " NUMBER");
}
if (!send_to_one(conn, "SETFLAGS %s\n", flist)) {
return 0;
@ -353,8 +475,17 @@ static int cmd_dump_conn(conn_t *conn)
return 1;
}
static int sock_arg(conn_t *conn, int numarg, char **arg)
static void send_tracking(conn_t *conn, const char *id, int value)
{
send_to_one(conn, "TRACKING %s %i\n", id, value);
}
static int sock_arg(conn_t *conn, size_t numarg, char **arg)
{
upsdebugx(6, "Driver on %s is now handling %s with %zu args",
sockfn, numarg ? arg[0] : "<skipped: no command>", numarg);
if (numarg < 1) {
return 0;
}
@ -391,20 +522,40 @@ static int sock_arg(conn_t *conn, int numarg, char **arg)
return 0;
}
/* INSTCMD <cmdname> [<value>]*/
/* INSTCMD <cmdname> [<cmdparam>] [TRACKING <id>] */
if (!strcasecmp(arg[0], "INSTCMD")) {
int ret;
char *cmdname = arg[1];
char *cmdparam = NULL;
char *cmdid = NULL;
/* Check if <cmdparam> and TRACKING were provided */
if (numarg == 3) {
cmdparam = arg[2];
} else if (numarg == 4 && !strcasecmp(arg[2], "TRACKING")) {
cmdid = arg[3];
} else if (numarg == 5 && !strcasecmp(arg[3], "TRACKING")) {
cmdparam = arg[2];
cmdid = arg[4];
} else if (numarg != 2) {
upslogx(LOG_NOTICE, "Malformed INSTCMD request");
return 0;
}
if (cmdid)
upsdebugx(3, "%s: TRACKING = %s", __func__, cmdid);
/* try the new handler first if present */
if (upsh.instcmd) {
if (numarg > 2) {
upsh.instcmd(arg[1], arg[2]);
return 1;
}
ret = upsh.instcmd(cmdname, cmdparam);
upsh.instcmd(arg[1], NULL);
/* send back execution result */
if (cmdid)
send_tracking(conn, cmdid, ret);
/* The command was handled, status is a separate consideration */
return 1;
}
upslogx(LOG_NOTICE, "Got INSTCMD, but driver lacks a handler");
return 1;
}
@ -413,12 +564,33 @@ static int sock_arg(conn_t *conn, int numarg, char **arg)
return 0;
}
/* SET <var> <value> */
/* SET <var> <value> [TRACKING <id>] */
if (!strcasecmp(arg[0], "SET")) {
int ret;
char *setid = NULL;
/* Check if TRACKING was provided */
if (numarg == 5) {
if (!strcasecmp(arg[3], "TRACKING")) {
setid = arg[4];
}
else {
upslogx(LOG_NOTICE, "Got SET <var> with unsupported parameters (%s/%s)",
arg[3], arg[4]);
return 0;
}
upsdebugx(3, "%s: TRACKING = %s", __func__, setid);
}
/* try the new handler first if present */
if (upsh.setvar) {
upsh.setvar(arg[1], arg[2]);
ret = upsh.setvar(arg[1], arg[2]);
/* send back execution result */
if (setid)
send_tracking(conn, setid, ret);
/* The command was handled, status is a separate consideration */
return 1;
}
@ -432,7 +604,7 @@ static int sock_arg(conn_t *conn, int numarg, char **arg)
static void sock_read(conn_t *conn)
{
int i, ret;
ssize_t ret, i;
char buf[SMALLBUF];
ret = read(conn->fd, buf, sizeof(buf));
@ -463,7 +635,7 @@ static void sock_read(conn_t *conn)
upslogx(LOG_INFO, "Unknown command on socket: ");
for (arg = 0; arg < conn->ctx.numargs; arg++) {
for (arg = 0; arg < conn->ctx.numargs && arg < INT_MAX; arg++) {
upslogx(LOG_INFO, "arg %d: %s", (int)arg, conn->ctx.arglist[arg]);
}
}
@ -502,12 +674,19 @@ static void sock_close(void)
/* interface */
void dstate_init(const char *prog, const char *devname)
char * dstate_init(const char *prog, const char *devname)
{
char sockname[SMALLBUF];
/* do this here for now */
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif
signal(SIGPIPE, SIG_IGN);
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES)
# pragma GCC diagnostic pop
#endif
if (devname) {
snprintf(sockname, sizeof(sockname), "%s/%s-%s", dflt_statepath(), prog, devname);
@ -518,6 +697,9 @@ void dstate_init(const char *prog, const char *devname)
sockfd = sock_open(sockname);
upsdebugx(2, "dstate_init: sock %s open on fd %d", sockname, sockfd);
/* NOTE: Caller must free this string */
return xstrdup(sockname);
}
/* returns 1 if timeout expired or data is available on UPS fd, 0 otherwise */
@ -565,7 +747,7 @@ int dstate_poll_fds(struct timeval timeout, int extrafd)
timeout.tv_sec -= now.tv_sec;
timeout.tv_usec -= now.tv_usec;
}
ret = select(maxfd + 1, &rfds, NULL, NULL, &timeout);
if (ret == 0) {
@ -614,7 +796,19 @@ int dstate_setinfo(const char *var, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
vsnprintf(value, sizeof(value), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
ret = state_setinfo(&dtree_root, var, value);
@ -633,7 +827,19 @@ int dstate_addenum(const char *var, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
vsnprintf(value, sizeof(value), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
va_end(ap);
ret = state_addenum(dtree_root, var, value);
@ -652,7 +858,9 @@ int dstate_addrange(const char *var, const int min, const int max)
ret = state_addrange(dtree_root, var, min, max);
if (ret == 1) {
send_to_all("ADDRANGE %s %i %i\n", var, min, max);
send_to_all("ADDRANGE %s %i %i\n", var, min, max);
/* Also add the "NUMBER" flag for ranges */
dstate_addflags(var, ST_FLAG_NUMBER);
}
return ret;
@ -693,11 +901,51 @@ void dstate_setflags(const char *var, int flags)
snprintfcat(flist, sizeof(flist), " STRING");
}
if (flags & ST_FLAG_NUMBER) {
snprintfcat(flist, sizeof(flist), " NUMBER");
}
/* update listeners */
send_to_all("SETFLAGS %s\n", flist);
}
void dstate_setaux(const char *var, int aux)
void dstate_addflags(const char *var, const int addflags)
{
int flags = state_getflags(dtree_root, var);
if (flags == -1) {
upslogx(LOG_ERR, "%s: cannot get flags of '%s'", __func__, var);
return;
}
/* Already set */
if ((flags & addflags) == addflags)
return;
flags |= addflags;
dstate_setflags(var, flags);
}
void dstate_delflags(const char *var, const int delflags)
{
int flags = state_getflags(dtree_root, var);
if (flags == -1) {
upslogx(LOG_ERR, "%s: cannot get flags of '%s'", __func__, var);
return;
}
/* Already not set */
if (!(flags & delflags))
return;
flags &= ~delflags;
dstate_setflags(var, flags);
}
void dstate_setaux(const char *var, long aux)
{
st_tree_t *sttmp;
@ -716,7 +964,7 @@ void dstate_setaux(const char *var, int aux)
sttmp->aux = aux;
/* update listeners */
send_to_all("SETAUX %s %d\n", var, aux);
send_to_all("SETAUX %s %ld\n", var, aux);
}
const char *dstate_getinfo(const char *var)
@ -772,7 +1020,7 @@ int dstate_delrange(const char *var, const int min, const int max)
/* update listeners */
if (ret == 1) {
send_to_all("DELRANGE %s \"%i %i\"\n", var, min, max);
send_to_all("DELRANGE %s %i %i\n", var, min, max);
}
return ret;
@ -796,7 +1044,7 @@ void dstate_free(void)
{
state_infofree(dtree_root);
dtree_root = NULL;
state_cmdfree(cmdhead);
cmdhead = NULL;
@ -901,17 +1149,111 @@ void status_commit(void)
void alarm_init(void)
{
memset(alarm_buf, 0, sizeof(alarm_buf));
/* reinit global counter */
alarm_active = 0;
device_alarm_init();
}
#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC)
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC)
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
void alarm_set(const char *buf)
{
int ret;
if (strlen(alarm_buf) > 0) {
snprintfcat(alarm_buf, sizeof(alarm_buf), " %s", buf);
ret = snprintfcat(alarm_buf, sizeof(alarm_buf), " %s", buf);
} else {
snprintfcat(alarm_buf, sizeof(alarm_buf), "%s", buf);
ret = snprintfcat(alarm_buf, sizeof(alarm_buf), "%s", buf);
}
if (ret < 0) {
/* Should we also try to print the potentially unusable buf?
* Generally - likely not. But if it is short enough...
* Note: LARGEBUF was the original limit mismatched vs alarm_buf
* size before PR #986.
*/
char alarm_tmp[LARGEBUF];
memset(alarm_tmp, 0, sizeof(alarm_tmp));
/* A bit of complexity to keep both (int)snprintf(...) and (size_t)sizeof(...) happy */
int ibuflen = snprintf(alarm_tmp, sizeof(alarm_tmp), "%s", buf);
size_t buflen;
if (ibuflen < 0) {
alarm_tmp[0] = 'N';
alarm_tmp[1] = '/';
alarm_tmp[2] = 'A';
alarm_tmp[3] = '\0';
buflen = strlen(alarm_tmp);
} else {
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
/* Note for gating macros above: unsuffixed HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP
* means support of contexts both inside and outside function body, so the push
* above and pop below (outside this finction) are not used.
*/
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS
/* Note that the individual warning pragmas for use inside function bodies
* are named without a _INSIDEFUNC suffix, for simplicity and legacy reasons
*/
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
if ((unsigned long long int)ibuflen < SIZE_MAX) {
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
# pragma GCC diagnostic pop
#endif
buflen = (size_t)ibuflen;
} else {
buflen = SIZE_MAX;
}
}
upslogx(LOG_ERR, "%s: error setting alarm_buf to: %s%s",
__func__, alarm_tmp, ( (buflen < sizeof(alarm_tmp)) ? "" : "...<truncated>" ) );
} else if ((size_t)ret > sizeof(alarm_buf)) {
char alarm_tmp[LARGEBUF];
memset(alarm_tmp, 0, sizeof(alarm_tmp));
int ibuflen = snprintf(alarm_tmp, sizeof(alarm_tmp), "%s", buf);
size_t buflen;
if (ibuflen < 0) {
alarm_tmp[0] = 'N';
alarm_tmp[1] = '/';
alarm_tmp[2] = 'A';
alarm_tmp[3] = '\0';
buflen = strlen(alarm_tmp);
} else {
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
if ((unsigned long long int)ibuflen < SIZE_MAX) {
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
# pragma GCC diagnostic pop
#endif
buflen = (size_t)ibuflen;
} else {
buflen = SIZE_MAX;
}
}
upslogx(LOG_WARNING, "%s: result was truncated while setting or appending "
"alarm_buf (limited to %zu bytes), with message: %s%s",
__func__, sizeof(alarm_buf), alarm_tmp,
( (buflen < sizeof(alarm_tmp)) ? "" : "...<also truncated>" ));
}
}
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
# pragma GCC diagnostic pop
#endif
/* write the status_buf into the info array */
void alarm_commit(void)
@ -924,3 +1266,259 @@ void alarm_commit(void)
alarm_active = 0;
}
}
void device_alarm_init(void)
{
/* only clear the buffer, don't touch the alarms counter */
memset(alarm_buf, 0, sizeof(alarm_buf));
}
/* same as above, but writes to "device.X.ups.alarm" or "ups.alarm" */
void device_alarm_commit(const int device_number)
{
char info_name[20];
memset(info_name, 0, 20);
if (device_number != 0) /* would then go into "device.%i.alarm" */
snprintf(info_name, 20, "device.%i.ups.alarm", device_number);
else /* would then go into "device.alarm" */
snprintf(info_name, 20, "ups.alarm");
/* Daisychain subdevices note:
* increase the counter when alarms are present on a subdevice, but
* don't decrease the count. Otherwise, we may not get the ALARM flag
* in ups.status, while there are some alarms present on device.X */
if (strlen(alarm_buf) > 0) {
dstate_setinfo(info_name, "%s", alarm_buf);
alarm_active++;
} else {
dstate_delinfo(info_name);
}
}
/* For devices where we do not have phase-count info (no mapping provided
* in the tables), nor in the device data/protocol, we can still guesstimate
* and report a value. This routine may also replace an existing value, e.g.
* if we've found new data disproving old one (e.g. if the 3-phase UPS was
* disbalanced when the driver was started, so we thought it is 1-phase in
* practice, and then the additional lines came up loaded, hence the bools
* "may_reevaluate" and the readonly flag "may_change_dstate" (so the caller
* can query the current apparent situation, without changing any dstates).
* It is up to callers to decide if they already have data they want to keep.
* The "xput_prefix" is e.g. "input." or "input.bypass." or "output." with
* the trailing dot where applicable - we use this string verbatim below.
* The "inited_phaseinfo" and "num_phases" are addresses of caller's own
* variables to store the flag (if we have successfully inited) and the
* discovered amount of phases, or NULL if caller does not want to track it.
*
* NOTE: The code below can detect if the device is 1, 2 (split phase) or 3
* phases.
*
* Returns:
* -1 Runtime/input error (non fatal, but routine was skipped)
* 0 Nothing changed: could not determine a value
* 1 A phase value was just determined (and set, if not read-only mode)
* 2 Nothing changed: already inited (and may_reevaluate==false)
* 3 Nothing changed: detected a value but it is already published
* as a dstate; populated inited_phaseinfo and num_phases though
*/
int dstate_detect_phasecount(
const char *xput_prefix,
const int may_change_dstate,
int *inited_phaseinfo,
int *num_phases,
const int may_reevaluate
) {
/* If caller does not want either of these back - loopback the values below */
int local_inited_phaseinfo = 0, local_num_phases = -1;
/* Temporary local value storage */
int old_num_phases = -1, detected_phaseinfo = 0;
if (!inited_phaseinfo)
inited_phaseinfo = &local_inited_phaseinfo;
if (!num_phases)
num_phases = &local_num_phases;
old_num_phases = *num_phases;
upsdebugx(3, "Entering %s('%s', %i, %i, %i, %i)", __func__,
xput_prefix, may_change_dstate, *inited_phaseinfo, *num_phases, may_reevaluate);
if (!(*inited_phaseinfo) || may_reevaluate) {
const char *v1, *v2, *v3, *v0,
*v1n, *v2n, *v3n,
*v12, *v23, *v31,
*c1, *c2, *c3, *c0;
char buf[MAX_STRING_SIZE]; /* For concatenation of "xput_prefix" with items we want to query */
size_t xput_prefix_len;
size_t bufrw_max;
char *bufrw_ptr = NULL;
if (!xput_prefix) {
upsdebugx(0, "%s(): Bad xput_prefix was passed: it is NULL - function skipped", __func__);
return -1;
}
xput_prefix_len = strlen(xput_prefix);
if (xput_prefix_len < 1) {
upsdebugx(0, "%s(): Bad xput_prefix was passed: it is empty - function skipped", __func__);
return -1;
}
bufrw_max = sizeof(buf) - xput_prefix_len;
if (bufrw_max <= 15) {
/* We need to append max ~13 chars per below, so far */
upsdebugx(0, "%s(): Bad xput_prefix was passed: it is too long - function skipped", __func__);
return -1;
}
memset(buf, 0, sizeof(buf));
strncpy(buf, xput_prefix, sizeof(buf));
bufrw_ptr = buf + xput_prefix_len ;
/* We either have defined and non-zero (numeric) values below, or NULLs.
* Note that as "zero" we should expect any valid numeric representation
* of a zero value as some drivers may save strangely formatted values.
* For now, we limit the level of paranoia with missing dstate entries,
* empty entries, and actual single zero character as contents of the
* string. Other obscure cases (string of multiple zeroes, a floating
* point zero, surrounding whitespace etc. may be solved if the need
* does arise in the future. Arguably, drivers' translation/mapping
* tables should take care of this with converion routine and numeric
* data type flags. */
#define dstate_getinfo_nonzero(var, suffix) \
do { strncpy(bufrw_ptr, suffix, bufrw_max); \
if ( (var = dstate_getinfo(buf)) ) { \
if ( (var[0] == '0' && var[1] == '\0') || \
(var[0] == '\0') ) { \
var = NULL; \
} \
} \
} while(0)
dstate_getinfo_nonzero(v1, "L1.voltage");
dstate_getinfo_nonzero(v2, "L2.voltage");
dstate_getinfo_nonzero(v3, "L3.voltage");
dstate_getinfo_nonzero(v1n, "L1-N.voltage");
dstate_getinfo_nonzero(v2n, "L2-N.voltage");
dstate_getinfo_nonzero(v3n, "L3-N.voltage");
dstate_getinfo_nonzero(v1n, "L1-N.voltage");
dstate_getinfo_nonzero(v12, "L1-L2.voltage");
dstate_getinfo_nonzero(v23, "L2-L3.voltage");
dstate_getinfo_nonzero(v31, "L3-L1.voltage");
dstate_getinfo_nonzero(c1, "L1.current");
dstate_getinfo_nonzero(c2, "L2.current");
dstate_getinfo_nonzero(c3, "L3.current");
dstate_getinfo_nonzero(v0, "voltage");
dstate_getinfo_nonzero(c0, "current");
if ( (v1 && v2 && !v3) ||
(v1n && v2n && !v3n) ||
(c1 && c2 && !c3) ||
(v12 && !v23 && !v31) ) {
upsdebugx(5, "%s(): determined a 2-phase case", __func__);
*num_phases = 2;
*inited_phaseinfo = 1;
detected_phaseinfo = 1;
} else if ( (v1 && v2 && v3) ||
(v1n && v2n && v3n) ||
(c1 && (c2 || c3)) ||
(c2 && (c1 || c3)) ||
(c3 && (c1 || c2)) ||
v12 || v23 || v31 ) {
upsdebugx(5, "%s(): determined a 3-phase case", __func__);
*num_phases = 3;
*inited_phaseinfo = 1;
detected_phaseinfo = 1;
} else if ( /* We definitely have only one non-zero line */
!v12 && !v23 && !v31 && (
(c0 && !c1 && !c2 && !c3) ||
(v0 && !v1 && !v2 && !v3) ||
(c1 && !c2 && !c3) ||
(!c1 && c2 && !c3) ||
(!c1 && !c2 && c3) ||
(v1 && !v2 && !v3) ||
(!v1 && v2 && !v3) ||
(!v1 && !v2 && v3) ||
(v1n && !v2n && !v3n) ||
(!v1n && v2n && !v3n) ||
(!v1n && !v2n && v3n) ) ) {
*num_phases = 1;
*inited_phaseinfo = 1;
detected_phaseinfo = 1;
upsdebugx(5, "%s(): determined a 1-phase case", __func__);
} else {
upsdebugx(5, "%s(): could not determine the phase case", __func__);
}
if (detected_phaseinfo) {
const char *oldphases;
strncpy(bufrw_ptr, "phases", bufrw_max);
oldphases = dstate_getinfo(buf);
if (oldphases) {
if (atoi(oldphases) == *num_phases) {
/* Technically, a bit has changed: we have set the flag which may have been missing before */
upsdebugx(5, "%s(): Nothing changed, with a valid reason; dstate already published with the same value: %s=%s (detected %d)",
__func__, buf, oldphases, *num_phases);
return 3;
}
}
if ( (*num_phases != old_num_phases) || (!oldphases) ) {
if (may_change_dstate) {
dstate_setinfo(buf, "%d", *num_phases);
upsdebugx(3, "%s(): calculated non-XML value for NUT variable %s was set to %d",
__func__, buf, *num_phases);
} else {
upsdebugx(3, "%s(): calculated non-XML value for NUT variable %s=%d but did not set its dstate (read-only request)",
__func__, buf, *num_phases);
}
return 1;
}
}
upsdebugx(5, "%s(): Nothing changed: could not determine a value", __func__);
return 0;
}
upsdebugx(5, "%s(): Nothing changed, with a valid reason; already inited", __func__);
return 2;
}
/* Dump the data tree (in upsc-like format) to stdout */
/* Actual implementation */
static int dstate_tree_dump(const st_tree_t *node)
{
int ret;
if (!node) {
return 1; /* not an error */
}
if (node->left) {
ret = dstate_tree_dump(node->left);
if (!ret) {
return 0; /* write failed in the child */
}
}
printf("%s: %s\n", node->var, node->val);
if (node->right) {
return dstate_tree_dump(node->right);
}
return 1; /* everything's OK here ... */
}
/* Dump the data tree (in upsc-like format) to stdout */
/* Public interface */
void dstate_dump(void)
{
upsdebugx(3, "Entering %s", __func__);
const st_tree_t *node = (const st_tree_t *)dstate_getroot();
dstate_tree_dump(node);
}

View file

@ -2,7 +2,7 @@
Copyright (C)
2003 Russell Kroll <rkroll@exploits.org>
2012 Arnaud Quette <arnaud.quette@free.fr>
2012-2017 Arnaud Quette <arnaud.quette@free.fr>
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
@ -22,6 +22,7 @@
#ifndef DSTATE_H_SEEN
#define DSTATE_H_SEEN 1
#include "timehead.h"
#include "state.h"
#include "attribute.h"
@ -31,6 +32,10 @@
#define DS_LISTEN_BACKLOG 16
#define DS_MAX_READ 256 /* don't read forever from upsd */
#ifndef MAX_STRING_SIZE
#define MAX_STRING_SIZE 128
#endif
/* track client connections */
typedef struct conn_s {
int fd;
@ -45,7 +50,7 @@ typedef struct conn_s {
* Defaults to nonblocking, for backward compatibility */
extern int do_synchronous;
void dstate_init(const char *prog, const char *devname);
char * dstate_init(const char *prog, const char *devname);
int dstate_poll_fds(struct timeval timeout, int extrafd);
int dstate_setinfo(const char *var, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
@ -53,7 +58,9 @@ int dstate_addenum(const char *var, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
int dstate_addrange(const char *var, const int min, const int max);
void dstate_setflags(const char *var, int flags);
void dstate_setaux(const char *var, int aux);
void dstate_addflags(const char *var, const int addflags);
void dstate_delflags(const char *var, const int delflags);
void dstate_setaux(const char *var, long aux);
const char *dstate_getinfo(const char *var);
void dstate_addcmd(const char *cmdname);
int dstate_delinfo(const char *var);
@ -82,5 +89,16 @@ void status_commit(void);
void alarm_init(void);
void alarm_set(const char *buf);
void alarm_commit(void);
void device_alarm_init(void);
void device_alarm_commit(const int device_number);
int dstate_detect_phasecount(
const char *xput_prefix,
const int may_change_dstate,
int *inited_phaseinfo,
int *num_phases,
const int may_reevaluate);
void dstate_dump(void);
#endif /* DSTATE_H_SEEN */

View file

@ -29,18 +29,22 @@
* * poll the "port" file for change
*/
#include "config.h" /* must be the first header */
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <string.h>
#include "main.h"
#include "parseconf.h"
#include "nut_stdint.h"
#include "upsclient.h"
#include "dummy-ups.h"
#define DRIVER_NAME "Device simulation and repeater driver"
#define DRIVER_VERSION "0.14"
#define DRIVER_VERSION "0.15"
/* driver description structure */
upsdrv_info_t upsdrv_info =
@ -52,16 +56,40 @@ upsdrv_info_t upsdrv_info =
{ NULL }
};
#define MODE_NONE 0
#define MODE_DUMMY 1 /* use the embedded defintion or a definition file */
#define MODE_REPEATER 2 /* use libupsclient to repeat an UPS */
#define MODE_META 3 /* consolidate data from several UPSs (TBS) */
enum drivermode {
MODE_NONE = 0,
int mode=MODE_NONE;
/* use the embedded defintion or a definition file, parsed in a
* loop again and again (often with TIMER lines to delay changes)
* Default mode for files with *.seq naming pattern
* (legacy-compatibility note: and other patterns except *.dev)
*/
MODE_DUMMY_LOOP,
/* use the embedded defintion or a definition file, parsed once
*
* This allows to spin up a dummy device with initial readings
* and retain in memory whatever SET VAR was sent by clients later.
* This is also less stressful on system resources to run the dummy.
*
* Default mode for files with *.dev naming pattern
*/
MODE_DUMMY_ONCE,
/* use libupsclient to repeat another UPS */
MODE_REPEATER,
/* consolidate data from several UPSs (TBS) */
MODE_META
};
typedef enum drivermode drivermode_t;
static drivermode_t mode = MODE_NONE;
/* parseconf context, for dummy mode using a file */
PCONF_CTX_t *ctx=NULL;
time_t next_update = -1;
static PCONF_CTX_t *ctx = NULL;
static time_t next_update = -1;
static struct stat datafile_stat;
#define MAX_STRING_SIZE 128
@ -77,7 +105,7 @@ static int upsclient_update_vars(void);
/* connection information */
static char *client_upsname = NULL, *hostname = NULL;
static UPSCONN_t *ups = NULL;
static int port;
static uint16_t port;
/* Driver functions */
@ -87,7 +115,8 @@ void upsdrv_initinfo(void)
switch (mode)
{
case MODE_DUMMY:
case MODE_DUMMY_ONCE:
case MODE_DUMMY_LOOP:
/* Initialise basic essential variables */
for ( item = nut_data ; item->info_type != NULL ; item++ )
{
@ -111,6 +140,7 @@ void upsdrv_initinfo(void)
dstate_dataok();
break;
case MODE_META:
case MODE_REPEATER:
/* Obtain the target name */
@ -139,10 +169,35 @@ void upsdrv_initinfo(void)
}
/* FIXME: commands and settable variable! */
break;
default:
case MODE_NONE:
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT
# pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
# pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunreachable-code"
# pragma clang diagnostic ignored "-Wcovered-switch-default"
#endif
/* All enum cases defined as of the time of coding
* have been covered above. Handle later definitions,
* memory corruptions and buggy inputs below...
*/
default:
fatalx(EXIT_FAILURE, "no suitable definition found!");
break;
#ifdef __clang__
# pragma clang diagnostic pop
#endif
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic pop
#endif
}
upsh.instcmd = instcmd;
@ -157,11 +212,48 @@ void upsdrv_updateinfo(void)
switch (mode)
{
case MODE_DUMMY:
case MODE_DUMMY_LOOP:
/* Now get user's defined variables */
if (parse_data_file(upsfd) >= 0)
dstate_dataok();
break;
case MODE_DUMMY_ONCE:
/* less stress on the sys */
if (ctx == NULL && next_update == -1) {
struct stat fs;
char fn[SMALLBUF];
if (device_path[0] == '/')
snprintf(fn, sizeof(fn), "%s", device_path);
else
snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path);
if (0 != fstat (upsfd, &fs) && 0 != stat (fn, &fs)) {
upsdebugx(2, "Can't open %s currently", fn);
/* retry ASAP until we get a file */
memset(&datafile_stat, 0, sizeof(struct stat));
next_update = 1;
} else {
if (datafile_stat.st_mtim.tv_sec != fs.st_mtim.tv_sec) {
upsdebugx(2, "upsdrv_updateinfo: input file was already read once to the end, but changed later - re-reading");
/* updated file => retry ASAP */
next_update = 1;
datafile_stat = fs;
}
}
}
if (ctx == NULL && next_update == -1) {
upsdebugx(2, "upsdrv_updateinfo: NO-OP: input file was already read once to the end");
dstate_dataok();
} else {
/* initial parsing interrupted by e.g. TIMER line */
if (parse_data_file(upsfd) >= 0)
dstate_dataok();
}
break;
case MODE_META:
case MODE_REPEATER:
if (upsclient_update_vars() > 0)
@ -182,19 +274,48 @@ void upsdrv_updateinfo(void)
}
}
break;
case MODE_NONE:
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT
# pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
# pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunreachable-code"
# pragma clang diagnostic ignored "-Wcovered-switch-default"
#endif
/* All enum cases defined as of the time of coding
* have been covered above. Handle later definitions,
* memory corruptions and buggy inputs below...
*/
default:
break;
#ifdef __clang__
# pragma clang diagnostic pop
#endif
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic pop
#endif
}
}
void upsdrv_shutdown(void)
__attribute__((noreturn));
void upsdrv_shutdown(void)
{
fatalx(EXIT_FAILURE, "shutdown not supported");
}
static int instcmd(const char *cmdname, const char *extra)
{
{
/*
if (!strcasecmp(cmdname, "test.battery.stop")) {
ser_send_buf(upsfd, ...);
@ -206,7 +327,7 @@ static int instcmd(const char *cmdname, const char *extra)
* if (mode == MODE_META) => ?
*/
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}
@ -216,13 +337,30 @@ void upsdrv_help(void)
void upsdrv_makevartable(void)
{
addvar(VAR_VALUE, "mode", "Specify mode instead of guessing it from port value (dummy = dummy-loop, dummy-once, repeater)"); /* meta */
}
void upsdrv_initups(void)
{
const char *val;
val = dstate_getinfo("driver.parameter.mode");
if (val) {
if (!strcmp(val, "dummy-loop")
&& !strcmp(val, "dummy-once")
&& !strcmp(val, "dummy")
&& !strcmp(val, "repeater")
/* && !strcmp(val, "meta") */
) {
fatalx(EXIT_FAILURE, "Unsupported mode was specified: %s", val);
}
}
/* check the running mode... */
if (strchr(device_path, '@'))
{
if ( (!val && strchr(device_path, '@'))
|| (val && !strcmp(val, "repeater"))
/*|| (val && !strcmp(val, "meta")) */
) {
upsdebugx(1, "Repeater mode");
mode = MODE_REPEATER;
dstate_setinfo("driver.parameter.mode", "repeater");
@ -230,9 +368,95 @@ void upsdrv_initups(void)
}
else
{
upsdebugx(1, "Dummy (simulation) mode");
mode = MODE_DUMMY;
dstate_setinfo("driver.parameter.mode", "dummy");
char fn[SMALLBUF];
mode = MODE_NONE;
if (val) {
if (!strcmp(val, "dummy-loop")) {
upsdebugx(2, "Dummy (simulation) mode looping infinitely was explicitly requested");
mode = MODE_DUMMY_LOOP;
} else
if (!strcmp(val, "dummy-once")) {
upsdebugx(2, "Dummy (simulation) mode with data read once was explicitly requested");
mode = MODE_DUMMY_ONCE;
} else
if (!strcmp(val, "dummy")) {
upsdebugx(2, "Dummy (simulation) mode default (looping infinitely) was explicitly requested");
mode = MODE_DUMMY_LOOP;
}
}
if (mode == MODE_NONE) {
if (str_ends_with(device_path, ".seq")) {
upsdebugx(2, "Dummy (simulation) mode with a sequence file name pattern (looping infinitely)");
mode = MODE_DUMMY_LOOP;
} else if (str_ends_with(device_path, ".dev")) {
upsdebugx(2, "Dummy (simulation) mode with a device data dump file name pattern (read once)");
mode = MODE_DUMMY_ONCE;
}
}
/* Report decisions similar to those above,
* just a bit shorter and at another level */
switch (mode) {
case MODE_DUMMY_ONCE:
upsdebugx(1, "Dummy (simulation) mode using data read once");
dstate_setinfo("driver.parameter.mode", "dummy-once");
break;
case MODE_DUMMY_LOOP:
upsdebugx(1, "Dummy (simulation) mode looping infinitely");
dstate_setinfo("driver.parameter.mode", "dummy-loop");
break;
case MODE_NONE:
case MODE_REPEATER:
case MODE_META:
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT
# pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
# pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunreachable-code"
# pragma clang diagnostic ignored "-Wcovered-switch-default"
#endif
/* All enum cases defined as of the time of coding
* have been covered above. Handle later definitions,
* memory corruptions and buggy inputs below...
*/
default:
/* This was the only mode until MODE_DUMMY_LOOP
* got split from MODE_DUMMY_ONCE in NUT v2.8.0
* so we keep the previously known mode string
* and it remains default when we are not sure
*/
upsdebugx(1, "Dummy (simulation) mode default (looping infinitely)");
mode = MODE_DUMMY_LOOP;
dstate_setinfo("driver.parameter.mode", "dummy");
break;
#ifdef __clang__
# pragma clang diagnostic pop
#endif
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic pop
#endif
}
if (device_path[0] == '/')
snprintf(fn, sizeof(fn), "%s", device_path);
else
snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path);
if (0 != fstat (upsfd, &datafile_stat) && 0 != stat (device_path, &datafile_stat)) {
upsdebugx(2, "Can't open %s currently", device_path);
}
}
}
@ -326,7 +550,7 @@ static int setvar(const char *varname, const char *val)
static int upsclient_update_vars(void)
{
int ret;
unsigned int numq, numa;
size_t numq, numa;
const char *query[4];
char **answer;
@ -347,7 +571,7 @@ static int upsclient_update_vars(void)
/* VAR <upsname> <varname> <val> */
if (numa < 4)
{
upsdebugx(1, "Error: insufficient data (got %d args, need at least 4)", numa);
upsdebugx(1, "Error: insufficient data (got %zu args, need at least 4)", numa);
}
upsdebugx(5, "Received: %s %s %s %s",
@ -399,6 +623,7 @@ static int is_valid_data(const char* varname)
static int is_valid_value(const char* varname, const char *value)
{
dummy_info_t *item;
NUT_UNUSED_VARIABLE(value);
if ( (item = find_info(varname)) != NULL)
{
@ -423,13 +648,14 @@ static void upsconf_err(const char *errmsg)
/* for dummy mode
* parse the definition file and process its content
*/
static int parse_data_file(int upsfd)
*/
static int parse_data_file(int arg_upsfd)
{
char fn[SMALLBUF];
char *ptr, var_value[MAX_STRING_SIZE];
int value_args = 0, counter;
size_t value_args = 0, counter;
time_t now;
NUT_UNUSED_VARIABLE(arg_upsfd);
time(&now);
@ -531,7 +757,7 @@ static int parse_data_file(int upsfd)
ctx->arglist[0], var_value, ctx->errmsg);
}
else
{
{
upsdebugx(3, "parse_data_file: added \"%s\" with value \"%s\"",
ctx->arglist[0], var_value);
}

View file

@ -18,8 +18,11 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUT_DUMMY_UPS_H_SEEN
#define NUT_DUMMY_UPS_H_SEEN 1
/* This file lists all valid data with their type and info.
*
*
* These are then enabled through a definition file, specified
* as the "port" parameter (only the file name, not the path).
*
@ -113,7 +116,9 @@ typedef struct {
/* --------------------------------------------------------------- */
/* FIXME: need to enforce value check with enum or bounds */
dummy_info_t nut_data[] =
/* This array is only used from dummy-ups.c (there's a namesake
* for apcupsd-ups.c defined elsewhere) */
static dummy_info_t nut_data[] =
{
/* Essential variables, loaded before parsing the definition file */
{ "ups.mfr", ST_FLAG_STRING | ST_FLAG_RW, 32, "Dummy Manufacturer", DU_FLAG_INIT, NULL },
@ -234,3 +239,5 @@ beeper.disable
/* end of structure. */
{ NULL, 0, 0, NULL, DU_FLAG_NONE, NULL }
};
#endif /* NUT_DUMMY_UPS_H_SEEN */

View file

@ -1,8 +1,9 @@
/* eaton_ats-mib.c - subdriver to monitor eaton_ats SNMP devices with NUT
/* eaton-ats16-nm2-mib.c - subdriver to monitor Eaton ATS16 SNMP devices with NUT
* using newer Network-M2 cards
*
* Copyright (C)
* 2011 - 2012 Arnaud Quette <arnaud.quette@free.fr>
* 2016 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2011-2012 Arnaud Quette <arnaud.quette@free.fr>
* 2016-2020 Eaton (author: Arnaud Quette <ArnaudQuette@Eaton.com>)
*
* Note: this subdriver was initially generated as a "stub" by the
* gen-snmp-subdriver script. It must be customized!
@ -22,80 +23,95 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "eaton-ats-mib.h"
#include "eaton-ats16-nm2-mib.h"
#define EATON_ATS_MIB_VERSION "0.11"
#define EATON_ATS16_NM2_MIB_VERSION "0.22"
#define EATON_ATS_SYSOID ".1.3.6.1.4.1.534.10"
#define EATON_ATS_MODEL ".1.3.6.1.4.1.534.10.2.1.2.0"
#define EATON_ATS16_NM2_SYSOID ".1.3.6.1.4.1.534.10.2" /* newer Network-M2 */
#define EATON_ATS16_NM2_MODEL ".1.3.6.1.4.1.534.10.2.1.2.0"
static info_lkp_t ats_source_info[] = {
{ 1, "init" },
{ 2, "diagnosis" },
{ 3, "off" },
{ 4, "1" },
{ 5, "2" },
{ 6, "safe" },
{ 7, "fault" },
{ 0, NULL }
static info_lkp_t eaton_ats16_nm2_source_info[] = {
{ 1, "init", NULL, NULL },
{ 2, "diagnosis", NULL, NULL },
{ 3, "off", NULL, NULL },
{ 4, "1", NULL, NULL },
{ 5, "2", NULL, NULL },
{ 6, "safe", NULL, NULL },
{ 7, "fault", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ats_sensitivity_info[] = {
{ 1, "normal" },
{ 2, "high" },
{ 3, "low" },
{ 0, NULL }
static info_lkp_t eaton_ats16_nm2_sensitivity_info[] = {
{ 1, "normal", NULL, NULL },
{ 2, "high", NULL, NULL },
{ 3, "low", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ats_input_frequency_status_info[] = {
{ 1, "good" }, /* No threshold triggered */
{ 2, "out-of-range" }, /* Frequency out of range triggered */
{ 0, NULL }
static info_lkp_t eaton_ats16_nm2_input_frequency_status_info[] = {
{ 1, "good", NULL, NULL }, /* No threshold triggered */
{ 2, "out-of-range", NULL, NULL }, /* Frequency out of range triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ats_input_voltage_status_info[] = {
{ 1, "good" }, /* No threshold triggered */
{ 2, "derated-range" }, /* Voltage derated */
{ 3, "out-of-range" }, /* Voltage out of range triggered */
{ 4, "unknown" }, /* "missing" */
{ 0, NULL }
static info_lkp_t eaton_ats16_nm2_input_voltage_status_info[] = {
{ 1, "good", NULL, NULL }, /* No threshold triggered */
{ 2, "derated-range", NULL, NULL }, /* Voltage derated */
{ 3, "out-of-range", NULL, NULL }, /* Voltage out of range triggered */
{ 4, "unknown", NULL, NULL }, /* "missing" */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ats_test_result_info[] = {
{ 1, "done and passed" },
{ 2, "done and warning" },
{ 3, "done and error" },
{ 4, "aborted" },
{ 5, "in progress" },
{ 6, "no test initiated" },
{ 0, NULL }
static info_lkp_t eaton_ats16_nm2_test_result_info[] = {
{ 1, "done and passed", NULL, NULL },
{ 2, "done and warning", NULL, NULL },
{ 3, "done and error", NULL, NULL },
{ 4, "aborted", NULL, NULL },
{ 5, "in progress", NULL, NULL },
{ 6, "no test initiated", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ats_output_status_info[] = {
{ 1, "OFF" }, /* Output not powered */
{ 2, "OL" }, /* Output powered */
{ 0, NULL }
static info_lkp_t eaton_ats16_nm2_output_status_info[] = {
{ 1, "OFF", NULL, NULL }, /* Output not powered */
{ 2, "OL", NULL, NULL }, /* Output powered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t eaton_ats16_ambient_drycontacts_info[] = {
{ -1, "unknown", NULL, NULL },
{ 1, "opened", NULL, NULL },
{ 2, "closed", NULL, NULL },
{ 3, "opened", NULL, NULL }, /* openWithNotice */
{ 4, "closed", NULL, NULL }, /* closedWithNotice */
{ 0, NULL, NULL, NULL }
};
/* EATON_ATS Snmp2NUT lookup table */
static snmp_info_t eaton_ats_mib[] = {
static snmp_info_t eaton_ats16_nm2_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device collection */
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* ats2IdentManufacturer.0 = STRING: EATON */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.1.0", "Eaton", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.1.0", "Eaton", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2IdentModel.0 = STRING: Eaton ATS */
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.2.0", "ATS", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.2.0", "ATS", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* FIXME: RFC for device.firmware! */
/* FIXME: the 2 "firmware" entries below should be SU_FLAG_SEMI_STATIC */
/* ats2IdentFWVersion.0 = STRING: 00.00.0009 */
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.3.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.3.0", NULL, SU_FLAG_OK, NULL },
/* FIXME: RFC for device.firmware.aux! */
/* ats2IdentRelease.0 = STRING: JF */
{ "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.4.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
/* ats2IdentRelease.0 = STRING: 1.7.5 */
{ "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.7.0", NULL, SU_FLAG_OK, NULL },
/* ats2IdentSerialNumber.0 = STRING: GA04F23009 */
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2IdentPartNumber.0 = STRING: EATS16N */
{ "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.6.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.6.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2IdentAgentVersion.0 = STRING: 301F23C28 */
/* { "unmapped.ats2IdentAgentVersion", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, */
/* ats2InputDephasing.0 = INTEGER: 2 degrees */
@ -103,143 +119,162 @@ static snmp_info_t eaton_ats_mib[] = {
/* Input collection */
/* ats2InputIndex.source1 = INTEGER: source1(1) */
{ "input.1.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "input.1.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2InputIndex.source2 = INTEGER: source2(2) */
{ "input.2.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.2", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "input.2.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.2", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2InputVoltage.source1 = INTEGER: 2292 0.1 V */
{ "input.1.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.1.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputVoltage.source2 = INTEGER: 2432 0.1 V */
{ "input.2.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.2.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusVoltage.source1 = INTEGER: normalRange(1) */
{ "input.1.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.1", NULL, SU_FLAG_OK, ats_input_voltage_status_info, NULL },
{ "input.1.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.1", NULL, SU_FLAG_OK, eaton_ats16_nm2_input_voltage_status_info },
/* ats2InputStatusVoltage.source2 = INTEGER: normalRange(1) */
{ "input.2.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.2", NULL, SU_FLAG_OK, ats_input_voltage_status_info, NULL },
{ "input.2.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.2", NULL, SU_FLAG_OK, eaton_ats16_nm2_input_voltage_status_info },
/* ats2InputFrequency.source1 = INTEGER: 500 0.1 Hz */
{ "input.1.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.1.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputFrequency.source2 = INTEGER: 500 0.1 Hz */
{ "input.2.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.2.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusFrequency.source1 = INTEGER: good(1) */
{ "input.1.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.1", NULL, SU_FLAG_OK, ats_input_frequency_status_info, NULL },
{ "input.1.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.1", NULL, SU_FLAG_OK, eaton_ats16_nm2_input_frequency_status_info },
/* ats2InputStatusFrequency.source2 = INTEGER: good(1) */
{ "input.2.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.2", NULL, SU_FLAG_OK, ats_input_frequency_status_info, NULL },
{ "input.2.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.2", NULL, SU_FLAG_OK, eaton_ats16_nm2_input_frequency_status_info },
/* ats2ConfigSensitivity.0 = INTEGER: normal(1) */
{ "input.sensitivity", ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.6.0", NULL, SU_FLAG_OK, &ats_sensitivity_info[0], NULL },
{ "input.sensitivity", ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.6.0", NULL, SU_FLAG_OK, &eaton_ats16_nm2_sensitivity_info[0] },
/* ats2OperationMode.0 = INTEGER: source1(4) */
{ "input.source", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.2.4.0", NULL, SU_FLAG_OK, ats_source_info, NULL },
{ "input.source", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.2.4.0", NULL, SU_FLAG_OK, eaton_ats16_nm2_source_info },
/* ats2ConfigPreferred.0 = INTEGER: source1(1) */
{ "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.5.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.5.0", NULL, SU_FLAG_OK, NULL },
/* ats2InputDephasing = INTEGER: 181 */
{ "input.phase.shift", 0, 1, ".1.3.6.1.4.1.534.10.2.2.1.1.0", NULL, SU_FLAG_OK, NULL },
/* Output collection */
/* ats2OutputVoltage.0 = INTEGER: 2304 0.1 V */
{ "output.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "output.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigOutputVoltage.0 = INTEGER: 230 1 V */
{ "output.voltage.nominal", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.4.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "output.voltage.nominal", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.4.0", NULL, SU_FLAG_OK, NULL },
/* ats2OutputCurrent.0 = INTEGER: 5 0.1 A */
{ "output.current", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "output.current", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.2.0", NULL, SU_FLAG_OK, NULL },
/* UPS collection */
/* FIXME: RFC for device.test.result! */
/* ats2ConfigTransferTest.0 = INTEGER: noTestInitiated(6) */
{ "ups.test.result", 0, 1, ".1.3.6.1.4.1.534.10.2.4.8.0", NULL, SU_FLAG_OK, ats_test_result_info, NULL },
{ "ups.test.result", 0, 1, ".1.3.6.1.4.1.534.10.2.4.8.0", NULL, SU_FLAG_OK, eaton_ats16_nm2_test_result_info },
/* FIXME: RFC for device.status! */
/* ats2StatusOutput.0 = INTEGER: outputPowered(2) */
{ "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.2.0", NULL, SU_FLAG_OK, ats_output_status_info, NULL },
{ "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.2.0", NULL, SU_FLAG_OK, eaton_ats16_nm2_output_status_info },
/* Ambient collection */
/* ats2EnvRemoteTemp.0 = INTEGER: 0 degrees Centigrade */
{ "ambient.temperature", 0, 1, ".1.3.6.1.4.1.534.10.2.5.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature", 0, 1, ".1.3.6.1.4.1.534.10.2.5.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteTempLowerLimit.0 = INTEGER: 5 degrees Centigrade */
{ "ambient.temperature.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.5.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.5.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteTempUpperLimit.0 = INTEGER: 40 degrees Centigrade */
{ "ambient.temperature.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.6.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.6.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteHumidity.0 = INTEGER: 0 percent */
{ "ambient.humidity", 0, 1, ".1.3.6.1.4.1.534.10.2.5.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity", 0, 1, ".1.3.6.1.4.1.534.10.2.5.2.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteHumidityLowerLimit.0 = INTEGER: 5 percent */
{ "ambient.humidity.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.7.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.7.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteHumidityUpperLimit.0 = INTEGER: 90 percent */
{ "ambient.humidity.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.8.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.8.0", NULL, SU_FLAG_OK, NULL },
/* Dry contacts on EMP001 TH module */
/* ats2ContactState.1 = INTEGER: open(1) */
{ "ambient.contacts.1.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.10.2.5.4.1.3.1",
NULL, SU_FLAG_OK, &eaton_ats16_ambient_drycontacts_info[0] },
/* ats2ContactState.2 = INTEGER: open(1) */
{ "ambient.contacts.2.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.10.2.5.4.1.3.2",
NULL, SU_FLAG_OK, &eaton_ats16_ambient_drycontacts_info[0] },
#if 0 /* FIXME: Remaining data to be processed */
/* ats2InputStatusDephasing.0 = INTEGER: normal(1) */
{ "unmapped.ats2InputStatusDephasing", 0, 1, ".1.3.6.1.4.1.534.10.2.3.1.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusDephasing", 0, 1, ".1.3.6.1.4.1.534.10.2.3.1.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusIndex.source1 = INTEGER: source1(1) */
{ "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusIndex.source2 = INTEGER: source2(2) */
{ "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusGood.source1 = INTEGER: voltageAndFreqNormalRange(2) */
{ "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusGood.source2 = INTEGER: voltageAndFreqNormalRange(2) */
{ "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusInternalFailure.source1 = INTEGER: good(1) */
{ "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusInternalFailure.source2 = INTEGER: good(1) */
{ "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusUsed.source1 = INTEGER: poweringLoad(2) */
{ "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusUsed.source2 = INTEGER: notPoweringLoad(1) */
{ "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.2", NULL, SU_FLAG_OK, NULL },
/* ats2StatusInternalFailure.0 = INTEGER: good(1) */
{ "unmapped.ats2StatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2StatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusOverload.0 = INTEGER: noOverload(1) */
{ "unmapped.ats2StatusOverload", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.3.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2StatusOverload", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.3.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusOverTemperature.0 = INTEGER: noOverTemperature(1) */
{ "unmapped.ats2StatusOverTemperature", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.4.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2StatusOverTemperature", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.4.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusShortCircuit.0 = INTEGER: noShortCircuit(1) */
{ "unmapped.ats2StatusShortCircuit", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.5.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2StatusShortCircuit", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.5.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusCommunicationLost.0 = INTEGER: good(1) */
{ "unmapped.ats2StatusCommunicationLost", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.6.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2StatusCommunicationLost", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.6.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusConfigurationFailure.0 = INTEGER: good(1) */
{ "unmapped.ats2StatusConfigurationFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.7.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2StatusConfigurationFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.7.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigTimeRTC.0 = Wrong Type (should be Counter32): Gauge32: 19191036 */
{ "unmapped.ats2ConfigTimeRTC", 0, 1, ".1.3.6.1.4.1.534.10.2.4.1.1.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigTimeRTC", 0, 1, ".1.3.6.1.4.1.534.10.2.4.1.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigTimeTextDate.0 = STRING: 08/11/1970 */
{ "unmapped.ats2ConfigTimeTextDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigTimeTextDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.2.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigTimeTextTime.0 = STRING: 02/50/36 */
{ "unmapped.ats2ConfigTimeTextTime", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.3.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigTimeTextTime", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.3.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigInputVoltageRating.0 = INTEGER: 1 1 V */
{ "unmapped.ats2ConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.2.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.2.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigInputFrequencyRating.0 = INTEGER: 50 Hz */
{ "unmapped.ats2ConfigInputFrequencyRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.3.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigInputFrequencyRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.3.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigTransferMode.0 = INTEGER: standard(1) */
{ "unmapped.ats2ConfigTransferMode", 0, 1, ".1.3.6.1.4.1.534.10.2.4.7.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigTransferMode", 0, 1, ".1.3.6.1.4.1.534.10.2.4.7.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigBrownoutLow.0 = INTEGER: 202 1 V */
{ "unmapped.ats2ConfigBrownoutLow", 0, 1, ".1.3.6.1.4.1.534.10.2.4.9.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigBrownoutLow", 0, 1, ".1.3.6.1.4.1.534.10.2.4.9.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigBrownoutLowDerated.0 = INTEGER: 189 1 V */
{ "unmapped.ats2ConfigBrownoutLowDerated", 0, 1, ".1.3.6.1.4.1.534.10.2.4.10.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigBrownoutLowDerated", 0, 1, ".1.3.6.1.4.1.534.10.2.4.10.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigBrownoutHigh.0 = INTEGER: 258 1 V */
{ "unmapped.ats2ConfigBrownoutHigh", 0, 1, ".1.3.6.1.4.1.534.10.2.4.11.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigBrownoutHigh", 0, 1, ".1.3.6.1.4.1.534.10.2.4.11.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigHysteresisVoltage.0 = INTEGER: 5 1 V */
{ "unmapped.ats2ConfigHysteresisVoltage", 0, 1, ".1.3.6.1.4.1.534.10.2.4.12.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ConfigHysteresisVoltage", 0, 1, ".1.3.6.1.4.1.534.10.2.4.12.0", NULL, SU_FLAG_OK, NULL },
/* Ambient collection */
/* ats2EnvNumContacts.0 = INTEGER: 2 */
{ "unmapped.ats2EnvNumContacts", 0, 1, ".1.3.6.1.4.1.534.10.2.5.3.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2EnvNumContacts", 0, 1, ".1.3.6.1.4.1.534.10.2.5.3.0", NULL, SU_FLAG_OK, NULL },
/* ats2ContactIndex.1 = INTEGER: 1 */
{ "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.1", NULL, SU_FLAG_OK, NULL },
/* ats2ContactIndex.2 = INTEGER: 2 */
{ "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.2", NULL, SU_FLAG_OK, NULL },
/* ats2ContactType.1 = INTEGER: notUsed(4) */
{ "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.1", NULL, SU_FLAG_OK, NULL },
/* ats2ContactType.2 = INTEGER: notUsed(4) */
{ "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.2", NULL, SU_FLAG_OK, NULL },
/* ats2ContactState.1 = INTEGER: open(1) */
{ "unmapped.ats2ContactState", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.3.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ContactState", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.3.1", NULL, SU_FLAG_OK, NULL },
/* ats2ContactState.2 = INTEGER: open(1) */
{ "unmapped.ats2ContactState", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.3.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ContactState", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.3.2", NULL, SU_FLAG_OK, NULL },
/* ats2ContactDescr.1 = STRING: Input #1 */
{ "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.1", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.1", NULL, SU_FLAG_OK, NULL },
/* ats2ContactDescr.2 = STRING: Input #2 */
{ "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.2", NULL, SU_FLAG_OK, NULL, NULL },
{ "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.2", NULL, SU_FLAG_OK, NULL },
#endif /* if 0 */
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t eaton_ats = { "eaton_ats", EATON_ATS_MIB_VERSION, NULL, EATON_ATS_MODEL, eaton_ats_mib, ".1.3.6.1.4.1.705.1" };
/* FIXME: Eaton ATS need to be fixed for the sysOID (currently .1.3.6.1.4.1.705.1!) */
/* mib2nut_info_t eaton_ats = { "eaton_ats", EATON_ATS_MIB_VERSION, NULL, EATON_ATS_MODEL, eaton_ats_mib, EATON_ATS_SYSOID }; */
/* Note: keep the legacy definition intact, to avoid breaking compatibility */
/* FIXME: The lines below are duplicated to fix an issue with the code generator (nut-snmpinfo.py -> line is discarding) */
/* Note:
* due to a bug in tools/nut-snmpinfo.py, prepending a 2nd mib2nut_info_t
* declaration with a comment line results in data extraction not being
* done for all entries in the file. Hence the above comment line being
* after its belonging declaration! */
/*mib2nut_info_t eaton_ats16_nm2 = { "eaton_ats16_nm2", EATON_ATS16_NM2_MIB_VERSION, NULL, EATON_ATS16_NM2_MODEL, eaton_ats16_nm2_mib, EATON_ATS16_NM2_SYSOID, NULL };*/
mib2nut_info_t eaton_ats16_nm2 = { "eaton_ats16_nm2", EATON_ATS16_NM2_MIB_VERSION, NULL, EATON_ATS16_NM2_MODEL, eaton_ats16_nm2_mib, EATON_ATS16_NM2_SYSOID, NULL };

View file

@ -0,0 +1,30 @@
/* eaton_ats16-nm2-mib.h - subdriver to monitor Eaton ATS16 NM2 SNMP devices with NUT
*
* Copyright (C)
* 2011-2012 Arnaud Quette <arnaud.quette@free.fr>
* 2016-2017 Eaton (author: Arnaud Quette <ArnaudQuette@Eaton.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
*/
#ifndef EATON_ATS16_NM2_MIB_H
#define EATON_ATS16_NM2_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t eaton_ats16_nm2;
#endif /* EATON_ATS16_NM2_MIB_H */

View file

@ -0,0 +1,275 @@
/* eaton-ats16-nmc-mib.c - subdriver to monitor Eaton ATS16 NMC SNMP devices with NUT
* using legacy NMC cards
*
* Copyright (C)
* 2011-2012 Arnaud Quette <arnaud.quette@free.fr>
* 2016-2020 Eaton (author: Arnaud Quette <ArnaudQuette@Eaton.com>)
*
* Note: this subdriver was initially generated as a "stub" by the
* gen-snmp-subdriver script. It must be customized!
*
* 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 "eaton-ats16-nmc-mib.h"
#define EATON_ATS16_NMC_MIB_VERSION "0.21"
#define EATON_ATS16_NMC_SYSOID ".1.3.6.1.4.1.705.1" /* legacy NMC */
#define EATON_ATS16_NMC_MODEL ".1.3.6.1.4.1.534.10.2.1.2.0"
static info_lkp_t eaton_ats16_nmc_source_info[] = {
{ 1, "init", NULL, NULL },
{ 2, "diagnosis", NULL, NULL },
{ 3, "off", NULL, NULL },
{ 4, "1", NULL, NULL },
{ 5, "2", NULL, NULL },
{ 6, "safe", NULL, NULL },
{ 7, "fault", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t eaton_ats16_nmc_sensitivity_info[] = {
{ 1, "normal", NULL, NULL },
{ 2, "high", NULL, NULL },
{ 3, "low", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t eaton_ats16_nmc_input_frequency_status_info[] = {
{ 1, "good", NULL, NULL }, /* No threshold triggered */
{ 2, "out-of-range", NULL, NULL }, /* Frequency out of range triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t eaton_ats16_nmc_input_voltage_status_info[] = {
{ 1, "good", NULL, NULL }, /* No threshold triggered */
{ 2, "derated-range", NULL, NULL }, /* Voltage derated */
{ 3, "out-of-range", NULL, NULL }, /* Voltage out of range triggered */
{ 4, "unknown", NULL, NULL }, /* "missing" */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t eaton_ats16_nmc_test_result_info[] = {
{ 1, "done and passed", NULL, NULL },
{ 2, "done and warning", NULL, NULL },
{ 3, "done and error", NULL, NULL },
{ 4, "aborted", NULL, NULL },
{ 5, "in progress", NULL, NULL },
{ 6, "no test initiated", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t eaton_ats16_nmc_output_status_info[] = {
{ 1, "OFF", NULL, NULL }, /* Output not powered */
{ 2, "OL", NULL, NULL }, /* Output powered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t eaton_ats16_ambient_drycontacts_info[] = {
{ -1, "unknown", NULL, NULL },
{ 1, "opened", NULL, NULL },
{ 2, "closed", NULL, NULL },
{ 3, "opened", NULL, NULL }, /* openWithNotice */
{ 4, "closed", NULL, NULL }, /* closedWithNotice */
{ 0, NULL, NULL, NULL }
};
/* EATON_ATS_NMC Snmp2NUT lookup table */
static snmp_info_t eaton_ats16_nmc_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device collection */
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* ats2IdentManufacturer.0 = STRING: EATON */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.1.0", "Eaton", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2IdentModel.0 = STRING: Eaton ATS */
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.2.0", "ATS", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* FIXME: RFC for device.firmware! */
/* FIXME: the 2 "firmware" entries below should be SU_FLAG_SEMI_STATIC */
/* ats2IdentFWVersion.0 = STRING: 00.00.0009 */
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.3.0", NULL, SU_FLAG_OK, NULL },
/* FIXME: RFC for device.firmware.aux! */
/* ats2IdentRelease.0 = STRING: JF */
{ "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.4.0", NULL, SU_FLAG_OK, NULL },
/* ats2IdentSerialNumber.0 = STRING: GA04F23009 */
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2IdentPartNumber.0 = STRING: EATS16N */
{ "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.6.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2IdentAgentVersion.0 = STRING: 301F23C28 */
/* { "unmapped.ats2IdentAgentVersion", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, */
/* ats2InputDephasing.0 = INTEGER: 2 degrees */
/* { "unmapped.ats2InputDephasing", 0, 1, ".1.3.6.1.4.1.534.10.2.2.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, */
/* Input collection */
/* ats2InputIndex.source1 = INTEGER: source1(1) */
{ "input.1.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2InputIndex.source2 = INTEGER: source2(2) */
{ "input.2.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.2", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* ats2InputVoltage.source1 = INTEGER: 2292 0.1 V */
{ "input.1.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputVoltage.source2 = INTEGER: 2432 0.1 V */
{ "input.2.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusVoltage.source1 = INTEGER: normalRange(1) */
{ "input.1.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.1", NULL, SU_FLAG_OK, eaton_ats16_nmc_input_voltage_status_info },
/* ats2InputStatusVoltage.source2 = INTEGER: normalRange(1) */
{ "input.2.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.2", NULL, SU_FLAG_OK, eaton_ats16_nmc_input_voltage_status_info },
/* ats2InputFrequency.source1 = INTEGER: 500 0.1 Hz */
{ "input.1.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputFrequency.source2 = INTEGER: 500 0.1 Hz */
{ "input.2.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusFrequency.source1 = INTEGER: good(1) */
{ "input.1.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.1", NULL, SU_FLAG_OK, eaton_ats16_nmc_input_frequency_status_info },
/* ats2InputStatusFrequency.source2 = INTEGER: good(1) */
{ "input.2.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.2", NULL, SU_FLAG_OK, eaton_ats16_nmc_input_frequency_status_info },
/* ats2ConfigSensitivity.0 = INTEGER: normal(1) */
{ "input.sensitivity", ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.6.0", NULL, SU_FLAG_OK, &eaton_ats16_nmc_sensitivity_info[0] },
/* ats2OperationMode.0 = INTEGER: source1(4) */
{ "input.source", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.2.4.0", NULL, SU_FLAG_OK, eaton_ats16_nmc_source_info },
/* ats2ConfigPreferred.0 = INTEGER: source1(1) */
{ "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.5.0", NULL, SU_FLAG_OK, NULL },
/* ats2InputDephasing = INTEGER: 181 */
{ "input.phase.shift", 0, 1, ".1.3.6.1.4.1.534.10.2.2.1.1.0", NULL, SU_FLAG_OK, NULL },
/* Output collection */
/* ats2OutputVoltage.0 = INTEGER: 2304 0.1 V */
{ "output.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigOutputVoltage.0 = INTEGER: 230 1 V */
{ "output.voltage.nominal", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.4.0", NULL, SU_FLAG_OK, NULL },
/* ats2OutputCurrent.0 = INTEGER: 5 0.1 A */
{ "output.current", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.2.0", NULL, SU_FLAG_OK, NULL },
/* UPS collection */
/* FIXME: RFC for device.test.result! */
/* ats2ConfigTransferTest.0 = INTEGER: noTestInitiated(6) */
{ "ups.test.result", 0, 1, ".1.3.6.1.4.1.534.10.2.4.8.0", NULL, SU_FLAG_OK, eaton_ats16_nmc_test_result_info },
/* FIXME: RFC for device.status! */
/* ats2StatusOutput.0 = INTEGER: outputPowered(2) */
{ "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.2.0", NULL, SU_FLAG_OK, eaton_ats16_nmc_output_status_info },
/* Ambient collection */
/* ats2EnvRemoteTemp.0 = INTEGER: 0 degrees Centigrade */
{ "ambient.temperature", 0, 0.1, ".1.3.6.1.4.1.534.10.2.5.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteTempLowerLimit.0 = INTEGER: 5 degrees Centigrade */
{ "ambient.temperature.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.5.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteTempUpperLimit.0 = INTEGER: 40 degrees Centigrade */
{ "ambient.temperature.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.6.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteHumidity.0 = INTEGER: 0 percent */
{ "ambient.humidity", 0, 0.1, ".1.3.6.1.4.1.534.10.2.5.2.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteHumidityLowerLimit.0 = INTEGER: 5 percent */
{ "ambient.humidity.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.7.0", NULL, SU_FLAG_OK, NULL },
/* ats2EnvRemoteHumidityUpperLimit.0 = INTEGER: 90 percent */
{ "ambient.humidity.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.8.0", NULL, SU_FLAG_OK, NULL },
/* Dry contacts on EMP001 TH module */
/* ats2ContactState.1 = INTEGER: open(1) */
{ "ambient.contacts.1.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.10.2.5.4.1.3.1",
NULL, SU_FLAG_OK, &eaton_ats16_ambient_drycontacts_info[0] },
/* ats2ContactState.2 = INTEGER: open(1) */
{ "ambient.contacts.2.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.10.2.5.4.1.3.2",
NULL, SU_FLAG_OK, &eaton_ats16_ambient_drycontacts_info[0]},
#if 0 /* FIXME: Remaining data to be processed */
/* ats2InputStatusDephasing.0 = INTEGER: normal(1) */
{ "unmapped.ats2InputStatusDephasing", 0, 1, ".1.3.6.1.4.1.534.10.2.3.1.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusIndex.source1 = INTEGER: source1(1) */
{ "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusIndex.source2 = INTEGER: source2(2) */
{ "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusGood.source1 = INTEGER: voltageAndFreqNormalRange(2) */
{ "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusGood.source2 = INTEGER: voltageAndFreqNormalRange(2) */
{ "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusInternalFailure.source1 = INTEGER: good(1) */
{ "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusInternalFailure.source2 = INTEGER: good(1) */
{ "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.2", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusUsed.source1 = INTEGER: poweringLoad(2) */
{ "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.1", NULL, SU_FLAG_OK, NULL },
/* ats2InputStatusUsed.source2 = INTEGER: notPoweringLoad(1) */
{ "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.2", NULL, SU_FLAG_OK, NULL },
/* ats2StatusInternalFailure.0 = INTEGER: good(1) */
{ "unmapped.ats2StatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusOverload.0 = INTEGER: noOverload(1) */
{ "unmapped.ats2StatusOverload", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.3.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusOverTemperature.0 = INTEGER: noOverTemperature(1) */
{ "unmapped.ats2StatusOverTemperature", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.4.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusShortCircuit.0 = INTEGER: noShortCircuit(1) */
{ "unmapped.ats2StatusShortCircuit", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.5.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusCommunicationLost.0 = INTEGER: good(1) */
{ "unmapped.ats2StatusCommunicationLost", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.6.0", NULL, SU_FLAG_OK, NULL },
/* ats2StatusConfigurationFailure.0 = INTEGER: good(1) */
{ "unmapped.ats2StatusConfigurationFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.7.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigTimeRTC.0 = Wrong Type (should be Counter32): Gauge32: 19191036 */
{ "unmapped.ats2ConfigTimeRTC", 0, 1, ".1.3.6.1.4.1.534.10.2.4.1.1.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigTimeTextDate.0 = STRING: 08/11/1970 */
{ "unmapped.ats2ConfigTimeTextDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.2.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigTimeTextTime.0 = STRING: 02/50/36 */
{ "unmapped.ats2ConfigTimeTextTime", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.3.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigInputVoltageRating.0 = INTEGER: 1 1 V */
{ "unmapped.ats2ConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.2.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigInputFrequencyRating.0 = INTEGER: 50 Hz */
{ "unmapped.ats2ConfigInputFrequencyRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.3.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigTransferMode.0 = INTEGER: standard(1) */
{ "unmapped.ats2ConfigTransferMode", 0, 1, ".1.3.6.1.4.1.534.10.2.4.7.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigBrownoutLow.0 = INTEGER: 202 1 V */
{ "unmapped.ats2ConfigBrownoutLow", 0, 1, ".1.3.6.1.4.1.534.10.2.4.9.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigBrownoutLowDerated.0 = INTEGER: 189 1 V */
{ "unmapped.ats2ConfigBrownoutLowDerated", 0, 1, ".1.3.6.1.4.1.534.10.2.4.10.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigBrownoutHigh.0 = INTEGER: 258 1 V */
{ "unmapped.ats2ConfigBrownoutHigh", 0, 1, ".1.3.6.1.4.1.534.10.2.4.11.0", NULL, SU_FLAG_OK, NULL },
/* ats2ConfigHysteresisVoltage.0 = INTEGER: 5 1 V */
{ "unmapped.ats2ConfigHysteresisVoltage", 0, 1, ".1.3.6.1.4.1.534.10.2.4.12.0", NULL, SU_FLAG_OK, NULL },
/* Ambient collection */
/* ats2EnvNumContacts.0 = INTEGER: 2 */
{ "unmapped.ats2EnvNumContacts", 0, 1, ".1.3.6.1.4.1.534.10.2.5.3.0", NULL, SU_FLAG_OK, NULL },
/* ats2ContactIndex.1 = INTEGER: 1 */
{ "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.1", NULL, SU_FLAG_OK, NULL },
/* ats2ContactIndex.2 = INTEGER: 2 */
{ "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.2", NULL, SU_FLAG_OK, NULL },
/* ats2ContactType.1 = INTEGER: notUsed(4) */
{ "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.1", NULL, SU_FLAG_OK, NULL },
/* ats2ContactType.2 = INTEGER: notUsed(4) */
{ "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.2", NULL, SU_FLAG_OK, NULL },
/* ats2ContactDescr.1 = STRING: Input #1 */
{ "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.1", NULL, SU_FLAG_OK, NULL },
/* ats2ContactDescr.2 = STRING: Input #2 */
{ "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.2", NULL, SU_FLAG_OK, NULL },
#endif /* if 0 */
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
/* Note: keep the legacy definition intact, to avoid breaking compatibility */
/* FIXME: The lines below are duplicated to fix an issue with the code generator (nut-snmpinfo.py -> line is discarding) */
/* Note:
* due to a bug in tools/nut-snmpinfo.py, prepending a 2nd mib2nut_info_t
* declaration with a comment line results in data extraction not being
* done for all entries in the file. Hence the above comment line being
* after its belonging declaration! */
/*mib2nut_info_t eaton_ats16_nmc = { "eaton_ats16_nmc", EATON_ATS16_NMC_MIB_VERSION, NULL, EATON_ATS16_NMC_MODEL, EATON_ATS16_NMC_mib, EATON_ATS16_NMC_SYSOID, NULL }; */
mib2nut_info_t eaton_ats16_nmc = { "eaton_ats16_nmc", EATON_ATS16_NMC_MIB_VERSION, NULL, EATON_ATS16_NMC_MODEL, eaton_ats16_nmc_mib, EATON_ATS16_NMC_SYSOID, NULL };

View file

@ -0,0 +1,30 @@
/* eaton_ats16-nmc-mib.h - subdriver to monitor Eaton ATS16 NMC SNMP devices with NUT
*
* Copyright (C)
* 2011-2012 Arnaud Quette <arnaud.quette@free.fr>
* 2016-2017 Eaton (author: Arnaud Quette <ArnaudQuette@Eaton.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
*/
#ifndef EATON_ATS16_NMC_MIB_H
#define EATON_ATS16_NMC_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t eaton_ats16_nmc;
#endif /* EATON_ATS16_NMC_MIB_H */

372
drivers/eaton-ats30-mib.c Normal file
View file

@ -0,0 +1,372 @@
/* eaton-ats30-mib.c - subdriver to monitor eaton_ats30 SNMP devices with NUT
*
* Copyright (C) 2017 Eaton
* Author: Tomas Halman <TomasHalman@eaton.com>
* 2011-2012 Arnaud Quette <arnaud.quette@free.fr>
*
* Note: this subdriver was initially generated as a "stub" by the
* gen-snmp-subdriver script. It must be customized!
*
* 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 "eaton-ats30-mib.h"
#define EATON_ATS30_MIB_VERSION "0.03"
#define EATON_ATS30_SYSOID ".1.3.6.1.4.1.534.10.1"
#define EATON_ATS30_MODEL ".1.3.6.1.4.1.534.10.1.2.1.0"
static info_lkp_t eaton_ats30_source_info[] = {
{ 1, "init", NULL, NULL },
{ 2, "diagnosis", NULL, NULL },
{ 3, "off", NULL, NULL },
{ 4, "1", NULL, NULL },
{ 5, "2", NULL, NULL },
{ 6, "safe", NULL, NULL },
{ 7, "fault", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t eaton_ats30_input_sensitivity[] = {
{ 1, "high", NULL, NULL },
{ 2, "low", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/*
* bitmap values of atsStatus.atsFailureIndicator
*
* 1 atsFailureSwitchFault N/A
* 2 atsFailureNoOutput OFF
* 3 atsFailureOutputOC OVER
* 4 atsFailureOverTemperature N/A
*/
static info_lkp_t eaton_ats30_status_info[] = {
{ 0, "OL", NULL, NULL },
{ 1, "OL", NULL, NULL }, /* SwitchFault */
{ 2, "OFF", NULL, NULL }, /* NoOutput */
{ 3, "OFF", NULL, NULL }, /* SwitchFault + NoOutput */
{ 4, "OL OVER", NULL, NULL }, /* OutputOC */
{ 5, "OL OVER", NULL, NULL }, /* OutputOC + SwitchFault */
{ 6, "OFF OVER", NULL, NULL }, /* OutputOC + NoOutput */
{ 7, "OFF OVER", NULL, NULL }, /* OutputOC + SwitchFault + NoOutput */
{ 8, "OL", NULL, NULL }, /* OverTemperature */
{ 9, "OL", NULL, NULL }, /* OverTemperature + SwitchFault */
{ 10, "OFF", NULL, NULL }, /* OverTemperature + NoOutput */
{ 11, "OFF", NULL, NULL }, /* OverTemperature + SwitchFault + NoOutput */
{ 12, "OL OVER", NULL, NULL }, /* OverTemperature + OutputOC */
{ 13, "OL OVER", NULL, NULL }, /* OverTemperature + OutputOC + SwitchFault */
{ 14, "OFF OVER", NULL, NULL }, /* OverTemperature + OutputOC + NoOutput */
{ 15, "OFF OVER", NULL, NULL }, /* OverTemperature + OutputOC + SwitchFault + NoOutput */
{ 0, NULL, NULL, NULL }
};
/* EATON_ATS30 Snmp2NUT lookup table */
static snmp_info_t eaton_ats30_mib[] = {
/* device type: ats */
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.1.1.0 = STRING: "Eaton" */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.1.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* enterprises.534.10.1.1.2.0 = STRING: "01.12.13b" -- SNMP agent version */
/* { "device.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.1.2.0", NULL, SU_FLAG_OK, NULL }, */
/* enterprises.534.10.1.1.3.1.0 = INTEGER: 1 */
/* { "unmapped.enterprise", 0, 1, ".1.3.6.1.4.1.534.10.1.1.3.1.0", NULL, SU_FLAG_OK, NULL }, */
/* enterprises.534.10.1.2.1.0 = STRING: "STS30002SR10019 " */
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* enterprises.534.10.1.2.2.0 = STRING: "1A0003AR00.00.00" -- Firmware */
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.2.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.2.3.0 = STRING: "2014-09-17 " -- Release date */
/* { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.3.0", NULL, SU_FLAG_OK, NULL }, */
/* enterprises.534.10.1.2.4.0 = STRING: "JA00E52021 " */
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.4.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.2.5.0 = STRING: " " -- Device ID codes */
/* { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.5.0", NULL, SU_FLAG_OK, NULL }, */
/* ats measure */
/* =========== */
/* enterprises.534.10.1.3.1.1.1.1 = INTEGER: 1 */
{ "input.1.id", 0, 1, ".1.3.6.1.4.1.534.10.1.3.1.1.1.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.1.1.1.2 = INTEGER: 2 */
{ "input.2.id", 0, 1, ".1.3.6.1.4.1.534.10.1.3.1.1.1.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.1.1.2.1 = INTEGER: 2379 */
{ "input.1.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.2.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.1.1.2.2 = INTEGER: 0 */
{ "input.2.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.2.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.1.1.3.1 = INTEGER: 500 */
{ "input.1.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.3.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.1.1.3.2 = INTEGER: 0 */
{ "input.2.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.3.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.2.1.0 = INTEGER: 2375 */
{ "output.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.2.1.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.2.2.0 = INTEGER: 0 */
{ "output.current", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.2.2.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.3.0 = INTEGER: 25 -- internal temperature in celsius */
{ "ups.temperature", 0, 1, ".1.3.6.1.4.1.534.10.1.3.3.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.4.0 = INTEGER: 77 -- internal temperature in fahrenheit */
/* { "ups.temperatureF", 0, 1, ".1.3.6.1.4.1.534.10.1.3.4.0", NULL, SU_FLAG_OK, NULL }, */
/* enterprises.534.10.1.3.5.0 = INTEGER: 37937541 */
{ "device.uptime", 0, 1, ".1.3.6.1.4.1.534.10.1.3.5.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.3.6.0 = INTEGER: 284 */
/* { "unmapped.atsMessureTransferedTimes", 0, 1, ".1.3.6.1.4.1.534.10.1.3.6.0", NULL, SU_FLAG_OK, NULL }, */
/* enterprises.534.10.1.3.7.0 = INTEGER: 4 */
{ "input.source", 0, 1, ".1.3.6.1.4.1.534.10.1.3.7.0", NULL, SU_FLAG_OK, eaton_ats30_source_info },
/* atsStatus */
/* ========= */
#if 0
/* NOTE: Unused OIDs are left as comments for potential future improvements */
/* enterprises.534.10.1.4.1.0 = INTEGER: 7 */
{ "unmapped.atsInputFlowIndicator", 0, 1, ".1.3.6.1.4.1.534.10.1.4.1.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.2.1.1.1 = INTEGER: 1 -- atsInputFlowTable start */
{ "unmapped.atsInputFlowIndex.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.2.1.1.2 = INTEGER: 2 */
{ "unmapped.atsInputFlowIndex.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.2.1.2.1 = INTEGER: 1 */
{ "unmapped.atsInputFlowRelay.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.2.1.2.2 = INTEGER: 2 */
{ "unmapped.atsInputFlowRelay.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.2.1.3.1 = INTEGER: 1 */
{ "unmapped.atsInputFlowSCR.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.2.1.3.2 = INTEGER: 2 */
{ "unmapped.atsInputFlowSCR.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.2.1.4.1 = INTEGER: 1 */
{ "unmapped.atsInputFlowParallelRelay.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.2.1.4.2 = INTEGER: 2 */
{ "unmapped.atsInputFlowParallelRelay.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.4.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.3.0 = INTEGER: 58720256 */
{ "unmapped.atsInputFailureIndicator", 0, 1, ".1.3.6.1.4.1.534.10.1.4.3.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.1.1 = INTEGER: 1 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.1.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.1.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.1.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.2.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.2.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.2.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.2.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.3.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.3.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.3.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.3.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.4.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.4.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.4.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.4.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.5.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.5.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.5.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.5.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.6.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.6.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.6.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.6.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.7.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.7.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.7.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.7.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.8.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.8.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.8.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.8.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.9.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.9.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.9.2 = INTEGER: 1 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.9.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.10.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.10.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.10.2 = INTEGER: 1 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.10.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.11.1 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.11.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.4.1.11.2 = INTEGER: 1 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.11.2", NULL, SU_FLAG_OK, NULL },
#endif /* 0 */
/* enterprises.atsFailureIndicator = INTEGER: 0 */
{ "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.1.4.5.0", NULL, SU_FLAG_OK, eaton_ats30_status_info },
#if 0
/* enterprises.534.10.1.4.6.1.0 = INTEGER: 2 -- atsFailure start */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.1.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.6.2.0 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.2.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.6.3.0 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.3.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.4.6.4.0 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.4.0", NULL, SU_FLAG_OK, NULL },
#endif /* 0 */
/* atsLog */
/* ====== */
#if 0
/* We are not interested in log */
/* enterprises.534.10.1.5.1.0 = INTEGER: 272 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.1.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.1 = INTEGER: 1 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.3 = INTEGER: 3 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.3", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.4 = INTEGER: 4 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.4", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.5 = INTEGER: 5 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.5", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.6 = INTEGER: 6 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.6", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.7 = INTEGER: 7 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.7", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.8 = INTEGER: 8 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.8", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.9 = INTEGER: 9 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.9", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.1.10 = INTEGER: 10 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.10", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.1 = INTEGER: 1482323677 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.2 = INTEGER: 1480076955 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.3 = INTEGER: 1480069128 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.3", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.4 = INTEGER: 1480069093 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.4", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.5 = INTEGER: 1478693745 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.5", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.6 = INTEGER: 1478693741 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.6", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.7 = INTEGER: 1466604406 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.7", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.8 = INTEGER: 1466604386 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.8", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.9 = INTEGER: 1466604386 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.9", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.2.10 = INTEGER: 1463038288 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.10", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.1 = INTEGER: 41 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.2 = INTEGER: 41 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.3 = INTEGER: 44 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.3", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.4 = INTEGER: 44 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.4", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.5 = INTEGER: 44 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.5", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.6 = INTEGER: 41 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.6", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.7 = INTEGER: 41 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.7", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.8 = INTEGER: 46 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.8", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.9 = INTEGER: 45 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.9", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.3.10 = INTEGER: 41 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.10", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.1 = STRING: "12:34:37 12/21/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.2 = STRING: "12:29:15 11/25/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.3 = STRING: "10:18:48 11/25/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.3", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.4 = STRING: "10:18:13 11/25/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.4", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.5 = STRING: "12:15:45 11/09/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.5", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.6 = STRING: "12:15:41 11/09/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.6", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.7 = STRING: "14:06:46 06/22/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.7", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.8 = STRING: "14:06:26 06/22/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.8", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.9 = STRING: "14:06:26 06/22/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.9", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.5.2.1.4.10 = STRING: "07:31:28 05/12/2016" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.10", NULL, SU_FLAG_OK, NULL },
#endif /* 0 */
/* atsConfig */
/* ========= */
#if 0
/* enterprises.534.10.1.6.1.1.0 = INTEGER: 538562409 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.1.1.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.1.2.0 = STRING: "01/24/2017" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.6.1.2.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.1.3.0 = STRING: "08:40:09" */
{ "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.6.1.3.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.1.1 = INTEGER: 1 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.1.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.1.2 = INTEGER: 2 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.1.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.2.1 = INTEGER: 1700 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.2.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.2.2 = INTEGER: 1700 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.2.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.3.1 = INTEGER: 1800 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.3.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.3.2 = INTEGER: 1800 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.3.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.4.1 = INTEGER: 2640 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.4.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.4.2 = INTEGER: 2640 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.4.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.5.1 = INTEGER: 3000 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.5.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.5.2 = INTEGER: 3000 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.5.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.6.1 = INTEGER: 50 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.6.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.6.2 = INTEGER: 50 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.6.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.7.1 = INTEGER: 40 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.7.1", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.2.1.7.2 = INTEGER: 40 */
{ "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.7.2", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.3.0 = INTEGER: 2640 */
{ "unmapped.atsConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.1.6.3.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.4.0 = INTEGER: 26 */
{ "unmapped.atsConfigRandomTime", 0, 1, ".1.3.6.1.4.1.534.10.1.6.4.0", NULL, SU_FLAG_OK, NULL },
#endif /* 0 */
/* enterprises.534.10.1.6.5.0 = INTEGER: 1 */
{ "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.1.6.5.0", NULL, SU_FLAG_OK, NULL },
/* enterprises.534.10.1.6.6.0 = INTEGER: 2 */
{ "input.sensitivity", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.1.6.6.0", NULL, SU_FLAG_OK, eaton_ats30_input_sensitivity },
/* enterprises.534.10.1.6.7.0 = INTEGER: 2 */
/* { "unmapped.atsConfigTest", 0, 1, ".1.3.6.1.4.1.534.10.1.6.7.0", NULL, SU_FLAG_OK, NULL }, */
/* atsUpgrade */
/* ========== */
#if 0
/* We are not interested in atsUpgrade */
/* enterprises.534.10.1.7.1.0 = INTEGER: 1 */
/* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.1.0", NULL, SU_FLAG_OK, NULL }, */
/* enterprises.534.10.1.7.2.0 = INTEGER: 1 */
/* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.2.0", NULL, SU_FLAG_OK, NULL }, */
/* enterprises.534.10.1.7.3.0 = INTEGER: 0 */
/* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.3.0", NULL, SU_FLAG_OK, NULL }, */
#endif /* 0 */
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t eaton_ats30 = { "eaton_ats30", EATON_ATS30_MIB_VERSION, NULL, EATON_ATS30_MODEL, eaton_ats30_mib, EATON_ATS30_SYSOID, NULL };

29
drivers/eaton-ats30-mib.h Normal file
View file

@ -0,0 +1,29 @@
/* eaton_ats30-mib.h - subdriver to monitor eaton_ats30 SNMP devices with NUT
*
* Copyright (C) 2017 Eaton
* Author: Tomas Halman <TomasHalman@eaton.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
*/
#ifndef EATON_ATS30_MIB_H
#define EATON_ATS30_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t eaton_ats30;
#endif /* EATON_ATS30_MIB_H */

View file

@ -1,750 +0,0 @@
/* eaton-mib.c - data to monitor Eaton ePDUs:
* G1 Aphel based ePDUs (Basic and Complex)
* G1 Pulizzi Monitored and Switched ePDUs
* G2 Marlin SW / MI / MO / MA
* G3 Shark SW / MI / MO / MA
*
* Copyright (C) 2008 - 2015
* Arnaud Quette <arnaud.quette@gmail.com>
* Arnaud Quette <ArnaudQuette@Eaton.com>
*
* Supported by Eaton <http://www.eaton.com>
* and previously MGE Office Protection Systems <http://www.mgeops.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
*
*/
#include "eaton-mib.h"
#define EATON_APHEL_MIB_VERSION "0.47"
/* APHEL-GENESIS-II-MIB (monitored ePDU)
* *************************************
* Note: There is also a basic XML interface, but not worth
* implementing in netxml-ups!
*/
#define APHEL1_OID_MIB ".1.3.6.1.4.1.17373"
#define APHEL1_SYSOID APHEL1_OID_MIB
#define APHEL1_OID_MODEL_NAME ".1.3.6.1.4.1.17373.3.1.1.0"
#define APHEL1_OID_FIRMREV ".1.3.6.1.4.1.17373.3.1.2.0"
#define APHEL1_OID_DEVICE_NAME ".1.3.6.1.4.1.17373.3.1.3.0"
#define APHEL1_OID_UNIT_MACADDR ".1.3.6.1.4.1.17373.3.1.4.0"
/* needs concat .<outlet-index>.0 */
#define APHEL1_OID_OUTLET_CURRENT ".1.3.6.1.4.1.17373.3.2"
/* Snmp2NUT lookup table for GenesisII MIB */
static snmp_info_t eaton_aphel_genesisII_mib[] = {
/* Device page */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_MODEL_NAME,
"Eaton Powerware ePDU Monitored", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_UNIT_MACADDR, "unknown",
0, NULL, NULL },
/* UPS page */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_MODEL_NAME,
"Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.id", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_DEVICE_NAME,
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_FIRMREV, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
/* Outlet page */
/* we can't use template since there is no counterpart to outlet.count */
{ "outlet.1.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".1.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "outlet.2.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".2.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "outlet.3.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".3.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "outlet.4.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".4.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "outlet.5.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".5.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "outlet.6.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".6.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "outlet.7.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".7.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "outlet.8.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".8.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL, NULL }
};
/* APHEL PDU-MIB - Revelation MIB (Managed ePDU)
* ********************************************* */
#define AR_BASE_OID ".1.3.6.1.4.1.534.6.6.6"
#define APHEL2_SYSOID AR_BASE_OID
#define APHEL2_OID_MODEL_NAME AR_OID_MODEL_NAME
#define AR_OID_MODEL_NAME AR_BASE_OID ".1.1.12.0"
#define AR_OID_DEVICE_NAME AR_BASE_OID ".1.1.13.0"
#define AR_OID_FIRMREV AR_BASE_OID ".1.1.1.0"
#define AR_OID_SERIAL AR_BASE_OID ".1.1.2.0"
#define AR_OID_UNIT_MACADDR AR_BASE_OID ".1.1.6.0"
#define AR_OID_UNIT_CURRENT AR_BASE_OID ".1.3.1.1"
#define AR_OID_UNIT_VOLTAGE AR_BASE_OID ".1.3.1.2"
#define AR_OID_UNIT_ACTIVEPOWER AR_BASE_OID ".1.3.1.3"
#define AR_OID_UNIT_APPARENTPOWER AR_BASE_OID ".1.3.1.4"
#define AR_OID_UNIT_CPUTEMPERATURE AR_BASE_OID ".1.3.1.5.0"
#define AR_OID_OUTLET_INDEX AR_BASE_OID ".1.2.2.1.1"
#define AR_OID_OUTLET_NAME AR_BASE_OID ".1.2.2.1.2"
#define AR_OID_OUTLET_STATUS AR_BASE_OID ".1.2.2.1.3"
static info_lkp_t outlet_status_info[] = {
{ -1, "error" },
{ 0, "off" },
{ 1, "on" },
{ 2, "cycling" }, /* transitional status */
{ 0, NULL }
};
#define DO_OFF 0
#define DO_ON 1
#define DO_CYCLE 2
#define AR_OID_OUTLET_COUNT AR_BASE_OID ".1.2.1.0"
#define AR_OID_OUTLET_CURRENT AR_BASE_OID ".1.2.2.1.4"
#define AR_OID_OUTLET_MAXCURRENT AR_BASE_OID ".1.2.2.1.5"
#define AR_OID_OUTLET_VOLTAGE AR_BASE_OID ".1.2.2.1.6"
#define AR_OID_OUTLET_ACTIVEPOWER AR_BASE_OID ".1.2.2.1.7"
#define AR_OID_OUTLET_APPARENTPOWER AR_BASE_OID ".1.2.2.1.8"
#define AR_OID_OUTLET_POWERFACTOR AR_BASE_OID ".1.2.2.1.9"
/* Snmp2NUT lookup table for Eaton Revelation MIB */
static snmp_info_t eaton_aphel_revelation_mib[] = {
/* Device collection */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_MODEL_NAME,
"Eaton Powerware ePDU Managed", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_SERIAL, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_UNIT_MACADDR, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
/* UPS collection */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_MODEL_NAME,
"Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.id", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_DEVICE_NAME,
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_SERIAL, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_FIRMREV, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "ups.temperature", 0, 1, AR_OID_UNIT_CPUTEMPERATURE, NULL, 0, NULL, NULL },
/* Outlet collection */
{ "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.count", 0, 1, AR_OID_OUTLET_COUNT, "0", 0, NULL },
{ "outlet.current", 0, 0.001, AR_OID_UNIT_CURRENT ".0", NULL, 0, NULL, NULL },
{ "outlet.voltage", 0, 0.001, AR_OID_UNIT_VOLTAGE ".0", NULL, 0, NULL, NULL },
{ "outlet.realpower", 0, 1.0, AR_OID_UNIT_ACTIVEPOWER ".0", NULL, 0, NULL, NULL },
{ "outlet.power", 0, 1.0, AR_OID_UNIT_APPARENTPOWER ".0", NULL, 0, NULL, NULL },
/* outlet template definition
* Caution: the index of the data start at 0, while the name is +1
* ie outlet.1 => <OID>.0 */
{ "outlet.%i.switchable", 0, 1, AR_OID_OUTLET_INDEX ".%i", "yes", SU_FLAG_STATIC | SU_OUTLET, NULL, NULL },
{ "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL, NULL },
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_NAME ".%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_STATUS ".%i", NULL, SU_FLAG_OK | SU_OUTLET, &outlet_status_info[0], NULL },
{ "outlet.%i.current", 0, 0.001, AR_OID_OUTLET_CURRENT ".%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.current.maximum", 0, 0.001, AR_OID_OUTLET_MAXCURRENT ".%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.realpower", 0, 1.0, AR_OID_OUTLET_ACTIVEPOWER ".%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.voltage", 0, 1.0, AR_OID_OUTLET_VOLTAGE ".%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.powerfactor", 0, 0.01, AR_OID_OUTLET_POWERFACTOR ".%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.power", 0, 1.0, AR_OID_OUTLET_APPARENTPOWER ".%i", NULL, SU_OUTLET, NULL, NULL },
/* FIXME:
* - delay for startup/shutdown sequence
* - support for multiple Ambient sensors ( max. 8), starting at index '0'
* ambient.%i.temperature => .1.3.6.1.4.1.534.6.6.6.2.2.1.3.%i
* ambient.%i.humidity => .1.3.6.1.4.1.534.6.6.6.2.4.1.3.%i
*/
/* Ambient collection */
/* We use critical levels, for both temperature and humidity,
* since warning levels are also available! */
{ "ambient.temperature", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.2.1.3.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.low", 0, 1.0, "1.3.6.1.4.1.534.6.6.6.2.2.1.6.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.high", 0, 1.0, "1.3.6.1.4.1.534.6.6.6.2.2.1.7.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.3.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.low", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.6.0", NULL, SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.high", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.7.0", NULL, SU_FLAG_OK, NULL, NULL },
/* instant commands. */
/* Note that load.cycle might be replaced by / mapped on shutdown.reboot */
/* no counterpart found!
{ "outlet.load.off", 0, DO_OFF, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL },
{ "outlet.load.on", 0, DO_ON, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL },
{ "outlet.load.cycle", 0, DO_CYCLE, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL }, */
{ "outlet.%i.load.off", 0, DO_OFF, AR_OID_OUTLET_STATUS ".%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.on", 0, DO_ON, AR_OID_OUTLET_STATUS ".%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.cycle", 0, DO_CYCLE, AR_OID_OUTLET_STATUS ".%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL, NULL }
};
/* Eaton PDU-MIB - Marlin MIB
* ************************** */
#define EATON_MARLIN_MIB_VERSION "0.37"
#define EATON_MARLIN_SYSOID ".1.3.6.1.4.1.534.6.6.7"
#define EATON_MARLIN_OID_MODEL_NAME ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.0"
static info_lkp_t marlin_outlet_status_info[] = {
{ 0, "off" },
{ 1, "on" },
{ 2, "pendingOff" }, /* transitional status */
{ 3, "pendingOn" }, /* transitional status */
{ 0, NULL }
};
static info_lkp_t marlin_outletgroups_status_info[] = {
{ 0, "off" },
{ 1, "on" },
{ 2, "rebooting" }, /* transitional status */
{ 3, "mixed" }, /* transitional status, not sure what it means! */
{ 0, NULL }
};
/* Ugly hack: having the matching OID present means that the outlet is
* switchable. So, it should not require this value lookup */
static info_lkp_t outlet_switchability_info[] = {
{ -1, "yes" },
{ 0, "yes" },
{ 0, NULL }
};
static info_lkp_t marlin_ambient_presence_info[] = {
{ -1, "unknown" },
{ 0, "no" }, /* disconnected */
{ 1, "yes" }, /* connected */
{ 0, NULL }
};
static info_lkp_t marlin_threshold_status_info[] = {
{ 0, "good" }, /* No threshold triggered */
{ 1, "warning-low" }, /* Warning low threshold triggered */
{ 2, "critical-low" }, /* Critical low threshold triggered */
{ 3, "warning-high" }, /* Warning high threshold triggered */
{ 4, "critical-high" }, /* Critical high threshold triggered */
{ 0, NULL }
};
static info_lkp_t marlin_threshold_frequency_status_info[] = {
{ 0, "good" }, /* No threshold triggered */
{ 1, "out-of-range" }, /* Frequency out of range triggered */
{ 0, NULL }
};
static info_lkp_t marlin_ambient_drycontacts_info[] = {
{ -1, "unknown" },
{ 0, "open" },
{ 1, "closed" },
{ 0, NULL }
};
static info_lkp_t marlin_threshold_voltage_alarms_info[] = {
{ 0, "" }, /* No threshold triggered */
{ 1, "low voltage warning!" }, /* Warning low threshold triggered */
{ 2, "low voltage critical!" }, /* Critical low threshold triggered */
{ 3, "high voltage warning!" }, /* Warning high threshold triggered */
{ 4, "high voltage critical!" }, /* Critical high threshold triggered */
{ 0, NULL }
};
static info_lkp_t marlin_threshold_current_alarms_info[] = {
{ 0, "" }, /* No threshold triggered */
{ 1, "low current warning!" }, /* Warning low threshold triggered */
{ 2, "low current critical!" }, /* Critical low threshold triggered */
{ 3, "high current warning!" }, /* Warning high threshold triggered */
{ 4, "high current critical!" }, /* Critical high threshold triggered */
{ 0, NULL }
};
static info_lkp_t marlin_threshold_frequency_alarm_info[] = {
{ 0, "" }, /* No threshold triggered */
{ 1, "frequency out of range!" }, /* Frequency out of range triggered */
{ 0, NULL }
};
static info_lkp_t marlin_threshold_temperature_alarms_info[] = {
{ 0, "" }, /* No threshold triggered */
{ 1, "low temperature warning!" }, /* Warning low threshold triggered */
{ 2, "low temperature critical!" }, /* Critical low threshold triggered */
{ 3, "high temperature warning!" }, /* Warning high threshold triggered */
{ 4, "high temperature critical!" }, /* Critical high threshold triggered */
{ 0, NULL }
};
static info_lkp_t marlin_threshold_humidity_alarms_info[] = {
{ 0, "" }, /* No threshold triggered */
{ 1, "low humidity warning!" }, /* Warning low threshold triggered */
{ 2, "low humidity critical!" }, /* Critical low threshold triggered */
{ 3, "high humidity warning!" }, /* Warning high threshold triggered */
{ 4, "high humidity critical!" }, /* Critical high threshold triggered */
{ 0, NULL }
};
static info_lkp_t marlin_outlet_group_type_info[] = {
{ 0, "unknown" },
{ 1, "breaker1pole" },
{ 2, "breaker2pole" },
{ 3, "breaker3pole" },
{ 4, "outlet-section" },
{ 5, "user-defined" },
{ 0, NULL }
};
/* Snmp2NUT lookup table for Eaton Marlin MIB */
static snmp_info_t eaton_marlin_mib[] = {
/* Device collection */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.0",
"Eaton Powerware ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.4.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.3.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.2.2.1.6.2",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
/* UPS collection */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.4.1.534.6.6.7.1.2.1.2.0",
"Eaton Powerware ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
/* FIXME: use unitName.0 (ePDU)?
* { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_DEVICE_NAME,
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, */
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.4.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.5.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
/* FIXME: needs a date reformating callback
* 2011-8-29,16:27:25.0,+1:0
* Hex-STRING: 07 DB 08 1D 10 0C 36 00 2B 01 00 00
* { "ups.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.8.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
* { "ups.time", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.8.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
*/
/* Input collection */
/* Historically, some of these data were previously published as
* outlet.{realpower,...}
* However, it's more suitable and logic to have these on input.{...}
*/
{ "input.phases", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.20.0", NULL, SU_FLAG_STATIC | SU_FLAG_SETINT, NULL, &input_phases },
/* FIXME: to be implemented
* inputType.0.1 iso.3.6.1.4.1.534.6.6.7.3.1.1.2.0.1
* singlePhase (1), ... split phase, three phase delta, or three phase wye
*/
/* Frequency is measured globally */
{ "input.frequency", 0, 0.1, ".1.3.6.1.4.1.534.6.6.7.3.1.1.3.0.1", NULL, 0, NULL, NULL },
{ "input.frequency.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.1.1.4.0.1", NULL, SU_FLAG_OK, &marlin_threshold_frequency_status_info[0], NULL },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.1.1.4.0.1", NULL, SU_FLAG_OK, &marlin_threshold_frequency_alarm_info[0], NULL },
/* inputCurrentPercentLoad (measured globally)
* Current percent load, based on the rated current capacity */
/* FIXME: input.load is mapped on input.L1.load for both single and 3phase !!! */
{ "input.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.0.1.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L1.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.0.1.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L2.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.0.1.2", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L3.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.0.1.3", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
/* FIXME:
* - Voltage is only measured per phase, as mV!
* so input.voltage == input.L1.voltage for both single and 3phase
* - As per NUT namespace (http://www.networkupstools.org/docs/developer-guide.chunked/apas01.html#_valid_contexts)
* Voltage has to be expressed either phase-phase or phase-neutral
* This is depending on OID inputVoltageMeasType
* INTEGER {singlePhase (1),phase1toN (2),phase2toN (3),phase3toN (4),phase1to2 (5),phase2to3 (6),phase3to1 (7)
* => RFC input.Lx.voltage.context */
{ "input.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.0.1.1", NULL, 0, NULL, NULL },
{ "input.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.0.1.1", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.0.1.1", NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0], NULL },
{ "input.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.5.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.6.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.7.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.8.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L1.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.0.1.1", NULL, 0, NULL, NULL },
{ "input.L1.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.0.1.1", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "L1.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.0.1.1", NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0], NULL },
{ "input.L1.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.5.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L1.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.6.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L1.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.7.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L1.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.8.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L2.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.0.1.2", NULL, 0, NULL, NULL },
{ "input.L2.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.0.1.2", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.0.1.2", NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0], NULL },
{ "input.L2.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.5.0.1.2", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L2.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.6.0.1.2", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L2.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.7.0.1.2", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L2.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.8.0.1.2", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L3.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.0.1.3", NULL, 0, NULL, NULL },
{ "input.L3.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.0.1.3", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "L3.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.0.1.3", NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0], NULL },
{ "input.L3.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.5.0.1.3", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L3.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.6.0.1.3", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L3.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.7.0.1.3", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L3.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.8.0.1.3", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
/* FIXME:
* - input.current is mapped on input.L1.current for both single and 3phase !!! */
{ "input.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.0.1.1", NULL, 0, NULL, NULL },
{ "input.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.3.0.1.1", NULL, 0, NULL, NULL },
{ "input.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.0.1.1", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.0.1.1", NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0], NULL },
{ "input.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.6.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.7.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.8.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.9.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L1.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.0.1.1", NULL, 0, NULL, NULL },
{ "input.L1.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.3.0.1.1", NULL, 0, NULL, NULL },
{ "input.L1.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.0.1.1", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "L1.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.0.1.1", NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0], NULL },
{ "input.L1.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.6.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L1.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.7.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L1.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.8.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L1.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.9.0.1.1", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L2.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.0.1.2", NULL, 0, NULL, NULL },
{ "input.L2.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.3.0.1.2", NULL, 0, NULL, NULL },
{ "input.L2.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.0.1.2", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.0.1.2", NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0], NULL },
{ "input.L2.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.6.0.1.2", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L2.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.7.0.1.2", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L2.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.8.0.1.2", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L2.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.9.0.1.2", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L3.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.0.1.3", NULL, 0, NULL, NULL },
{ "input.L3.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.3.0.1.3", NULL, 0, NULL, NULL },
{ "input.L3.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.0.1.3", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "L3.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.0.1.3", NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0], NULL },
{ "input.L3.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.6.0.1.3", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L3.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.7.0.1.3", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L3.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.8.0.1.3", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
{ "input.L3.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.9.0.1.3", NULL, SU_FLAG_NEGINVALID, NULL, NULL },
/* Sum of all phases realpower, valid for Shark 1ph/3ph only */
{ "input.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.5.1.4.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL, NULL },
/* Fallback 1: Sum of all phases realpower, valid for Marlin 3ph only */
{ "input.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.0.1.4", NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL, NULL },
/* Fallback 2: Sum of the phase realpower, valid for Marlin 1ph only */
{ "input.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.0.1.2", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L1.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.0.1.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L2.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.0.1.2", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L3.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.0.1.3", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
/* Sum of all phases apparent power, valid for Shark 1ph/3ph only */
{ "input.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.5.1.3.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL, NULL },
/* Fallback 1: Sum of all phases realpower, valid for Marlin 3ph only */
{ "input.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.0.1.4", NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL, NULL },
/* Fallback 2: Sum of the phase realpower, valid for Marlin 1ph only */
{ "input.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.0.1.2", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L1.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.0.1.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L2.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.0.1.2", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "input.L3.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.0.1.3", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
/* Ambient collection */
{ "ambient.present", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.1.1.3.0.1", NULL, SU_FLAG_OK, &marlin_ambient_presence_info[0], NULL },
{ "ambient.temperature.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.1.1.5.0.1", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.1.1.5.0.1", NULL, SU_FLAG_OK, &marlin_threshold_temperature_alarms_info[0], NULL },
{ "ambient.temperature", 0, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.4.0.1", NULL, SU_FLAG_OK, NULL, NULL },
/* Low and high threshold use the respective critical levels */
{ "ambient.temperature.low", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.7.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.low.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.7.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.low.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.6.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.high", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.9.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.high.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.8.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.temperature.high.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.9.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.2.1.5.0.1", NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.2.1.5.0.1", NULL, SU_FLAG_OK, &marlin_threshold_humidity_alarms_info[0], NULL },
{ "ambient.humidity", 0, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.4.0.1", NULL, SU_FLAG_OK, NULL, NULL },
/* Low and high threshold use the respective critical levels */
{ "ambient.humidity.low", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.7.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.low.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.6.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.low.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.7.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.high", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.9.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.high.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.8.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
{ "ambient.humidity.high.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.9.0.1", NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL },
/* Dry contacts on TH module */
{ "ambient.contacts.1.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.3.1.4.0.1", NULL, SU_FLAG_OK, &marlin_ambient_drycontacts_info[0], NULL },
{ "ambient.contacts.2.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.3.1.4.0.2", NULL, SU_FLAG_OK, &marlin_ambient_drycontacts_info[0], NULL },
/* Outlet collection */
{ "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "outlet.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.22.0", "0", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
/* The below ones are the same as the input.* equivalent */
/* FIXME: transition period, TO BE REMOVED, moved to input.* */
{ "outlet.frequency", 0, 0.1, ".1.3.6.1.4.1.534.6.6.7.3.1.1.3.0.1", NULL, 0, NULL, NULL },
{ "outlet.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.0.1.1", NULL, 0, NULL, NULL },
{ "outlet.current", 0, 0.01, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.0.1.1", NULL, 0, NULL, NULL },
{ "outlet.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.0.1.4", NULL, 0, NULL, NULL },
{ "outlet.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.0.1.4", NULL, 0, NULL, NULL },
/* outlet template definition
* Indexes start from 1, ie outlet.1 => <OID>.1 */
/* Note: the first definition is used to determine the base index (ie 0 or 1) */
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.1.1.3.0.%i", NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, NULL, NULL },
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.6.1.2.0.%i",
NULL, SU_FLAG_OK | SU_OUTLET, &marlin_outlet_status_info[0], NULL },
/* FIXME: or use ".1.3.6.1.4.1.534.6.6.7.6.1.1.2.0.1", though it's related to groups! */
{ "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL, NULL },
/* FIXME: the last part of the OID gives the group number (i.e. %i.1 means "group 1")
* Need to address that, without multiple declaration (%i.%i, SU_OUTLET | SU_OUTLET_GROUP)? */
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.0.%i.1", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET, NULL, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.0.%i.2", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET, NULL, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.0.%i.3", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET, NULL, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.0.%i.4", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET, NULL, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.0.%i.5", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET, NULL, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.0.%i.6", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET, NULL, NULL },
{ "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.3.0.%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.4.1.4.0.%i", NULL, SU_OUTLET, &marlin_threshold_status_info[0], NULL },
{ "outlet.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.4.1.4.0.%i", NULL, SU_OUTLET, &marlin_threshold_current_alarms_info[0], NULL },
{ "outlet.%i.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.5.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL, NULL },
{ "outlet.%i.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.6.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL, NULL },
{ "outlet.%i.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.7.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL, NULL },
{ "outlet.%i.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.8.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL, NULL },
{ "outlet.%i.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.6.5.1.3.0.%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.2.0.%i", NULL, SU_OUTLET, NULL, NULL },
{ "outlet.%i.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.3.1.3.0.%i", NULL, SU_OUTLET, &marlin_threshold_status_info[0], NULL },
{ "outlet.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.3.1.3.0.%i", NULL, SU_OUTLET, &marlin_threshold_voltage_alarms_info[0], NULL },
{ "outlet.%i.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.4.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL, NULL },
{ "outlet.%i.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.5.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL, NULL },
{ "outlet.%i.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.6.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL, NULL },
{ "outlet.%i.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.7.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET, NULL, NULL },
{ "outlet.%i.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.6.5.1.2.0.%i", NULL, SU_OUTLET, NULL, NULL },
/* FIXME: handle non switchable units (only measurements), which do not expose this OID */
{ "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.6.1.3.0.%i", "no", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK, &outlet_switchability_info[0], NULL },
/* TODO: handle statistics
* outletWh.0.1
* outletWhTimer.0.1
*/
/* Outlet groups collection */
{ "outlet.group.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.21.0", "0", SU_FLAG_STATIC, NULL, NULL },
/* outlet groups template definition
* Indexes start from 1, ie outlet.group.1 => <OID>.1 */
/* Note: the first definition is used to determine the base index (ie 0 or 1) */
/* groupID.0.1 = OctetString: A */
{ "outlet.group.%i.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.1.1.2.0.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, NULL, NULL },
/* groupName.0.1 = OctetString: Factory Group 1 */
/* FIXME: SU_FLAG_SEMI_STATIC or SU_FLAG_SETTING => refreshed from time to time or upon call to setvar */
{ "outlet.group.%i.name", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.1.1.3.0.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, NULL, NULL },
/* groupType.0.1 = Integer: outletSection (4) */
{ "outlet.group.%i.type", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.1.1.4.0.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &marlin_outlet_group_type_info[0], NULL },
/* groupControlStatus.0.1 = Integer: on (1) */
{ "outlet.group.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.6.1.2.0.%i",
NULL, SU_FLAG_OK | SU_OUTLET_GROUP, &marlin_outletgroups_status_info[0], NULL },
/* groupChildCount.0.1 = Integer: 12 */
{ "outlet.group.%i.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.5.1.1.6.0.%i", NULL, SU_OUTLET_GROUP, NULL, NULL },
/* groupVoltage.0.1 = Integer: 243080 */
{ "outlet.group.%i.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.3.0.%i", NULL, SU_OUTLET_GROUP, NULL, NULL },
/* groupVoltageThStatus.0.1 = Integer: good (0) */
{ "outlet.group.%i.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.3.1.4.0.%i", NULL, SU_OUTLET_GROUP, &marlin_threshold_status_info[0], NULL },
{ "outlet.group.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.3.1.4.0.%i", NULL, SU_OUTLET_GROUP, &marlin_threshold_voltage_alarms_info[0], NULL },
{ "outlet.group.%i.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.5.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
{ "outlet.group.%i.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.6.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
{ "outlet.group.%i.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.7.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
{ "outlet.group.%i.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.8.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
/* groupCurrent.0.1 = Integer: 0 */
{ "outlet.group.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.3.0.%i", NULL, SU_OUTLET_GROUP, NULL, NULL },
/* groupCurrentCapacity.0.1 = Integer: 16000 */
{ "outlet.group.%i.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.2.0.%i", NULL, SU_OUTLET_GROUP, NULL, NULL },
/* groupCurrentThStatus.0.1 = Integer: good (0) */
{ "outlet.group.%i.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.4.1.4.0.%i", NULL, SU_OUTLET_GROUP, &marlin_threshold_status_info[0], NULL },
{ "outlet.group.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.4.1.4.0.%i", NULL, SU_OUTLET_GROUP, &marlin_threshold_current_alarms_info[0], NULL },
/* groupCurrentPercentLoad.0.1 = Integer: 0 */
{ "outlet.group.%i.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.5.4.1.10.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
/* groupCurrentThLowerWarning.0.1 = Integer: 0 */
{ "outlet.group.%i.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.5.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
/* groupCurrentThLowerCritical.0.1 = Integer: -1 */
{ "outlet.group.%i.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.6.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
/* groupCurrentThUpperWarning.0.1 = Integer: 12800 */
{ "outlet.group.%i.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.7.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
/* groupCurrentThUpperCritical.0.1 = Integer: 16000 */
{ "outlet.group.%i.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.8.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
/* groupWatts.0.1 = Integer: 2670 */
{ "outlet.group.%i.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.5.5.1.3.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
/* groupVA.0.1 = Integer: 3132 */
{ "outlet.group.%i.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.5.5.1.2.0.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL },
/* instant commands. */
/* Notes:
* - load.cycle might be replaced by / mapped on shutdown.reboot
* - outletControl{Off,On,Reboot}Cmd values:
* 0-n : Timer
* -1 : Cancel
* we currently use "0", so instant On | Off | Reboot... */
/* no counterpart found!
{ "outlet.load.off", 0, DO_OFF, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL },
{ "outlet.load.on", 0, DO_ON, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL },
{ "outlet.load.cycle", 0, DO_CYCLE, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL }, */
/* TODO: handle delays */
{ "outlet.%i.load.off", 0, 0, ".1.3.6.1.4.1.534.6.6.7.6.6.1.3.0.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.on", 0, 0, ".1.3.6.1.4.1.534.6.6.7.6.6.1.4.0.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
{ "outlet.%i.load.cycle", 0, 0, ".1.3.6.1.4.1.534.6.6.7.6.6.1.5.0.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL },
/* TODO: handle delays
* 0-n :Time in seconds until the group command is issued
* -1:Cancel a pending group-level Off/On/Reboot command */
/* groupControlOffCmd.0.1 = Integer: -1 */
{ "outlet.group.%i.load.off", 0, 0, ".1.3.6.1.4.1.534.6.6.7.5.6.1.3.0.%i", NULL, SU_TYPE_CMD | SU_OUTLET_GROUP, NULL, NULL },
/* groupControl0nCmd.0.1 = Integer: -1 */
{ "outlet.group.%i.load.on", 0, 0, ".1.3.6.1.4.1.534.6.6.7.5.6.1.4.0.%i", NULL, SU_TYPE_CMD | SU_OUTLET_GROUP, NULL, NULL },
/* groupControlRebootCmd.0.1 = Integer: -1 */
{ "outlet.group.%i.load.cycle", 0, 0, ".1.3.6.1.4.1.534.6.6.7.5.6.1.5.0.%i", NULL, SU_TYPE_CMD | SU_OUTLET_GROUP, NULL, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL, NULL }
};
/* Pulizzi Monitored ePDU (Basic model, SNMP only)
* FIXME: to be completed
*
* Warning: there are 2 versions:
* - SA built MI.mib (old MIB)
* #define PULIZZI1_OID_MIB ".1.3.6.1.4.1.20677.3.1.1"
* #define PULIZZI1_OID_MODEL_NAME ".1.3.6.1.4.1.20677.3.1.1.1.2.0"
* - Eaton-Powerware-Monitored-ePDU_1.0.E.mib (new MIB) Vertical SW
*/
/* Pulizzi Switched ePDU */
#define EATON_PULIZZI_SW_MIB_VERSION "0.2"
#define PULIZZI_SW_OID_MIB ".1.3.6.1.4.1.20677.3.1.1"
#define PULIZZI_SW_OID_MODEL_NAME ".1.3.6.1.4.1.20677.2.1.1.0"
/* Some buggy FW also report sysOID = ".1.3.6.1.4.1.20677.1" */
#define EATON_PULIZZI_SWITCHED1_SYSOID ".1.3.6.1.4.1.20677.1"
#define EATON_PULIZZI_SWITCHED2_SYSOID ".1.3.6.1.4.1.20677.2"
static info_lkp_t pulizzi_sw_outlet_status_info[] = {
{ 1, "on" },
{ 2, "off" },
{ 0, NULL }
};
/* simply remap the above status to "yes" */
static info_lkp_t pulizzi_sw_outlet_switchability_info[] = {
{ 1, "yes" },
{ 2, "yes" },
{ 0, NULL }
};
/* Snmp2NUT lookup table for Eaton Pulizzi Switched ePDU MIB */
static snmp_info_t eaton_pulizzi_switched_mib[] = {
/* Device page */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, PULIZZI_SW_OID_MODEL_NAME,
"Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.2.6.0",
"unknown", 0, NULL, NULL },
/* UPS page */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, PULIZZI_SW_OID_MODEL_NAME,
"Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
/* FIXME: to be moved to the device collection! */
{ "ups.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.1.4.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
{ "ups.time", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.1.3.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL },
/* Outlet page */
/* Note: outlet.count is deduced, with guestimate_outlet_count() */
{ "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.current", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.2.0", NULL, 0, NULL, NULL },
{ "outlet.voltage", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.1.0", NULL, 0, NULL, NULL },
{ "outlet.power", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.3.0", NULL, 0, NULL, NULL },
/* outlet template definition
* Notes:
* - indexes start from 1, ie outlet.1 => <OID>.1
* - the first definition is used to determine the base index (ie 0 or 1)
* - outlet.count is estimated, based on the below OID iteration capabilities */
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.1.%i.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, NULL, NULL },
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.3.%i.0",
NULL, SU_FLAG_OK | SU_OUTLET, &pulizzi_sw_outlet_status_info[0], NULL },
{ "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL, NULL },
/* we use the same OID as outlet.n.status..., to expose switchability */
{ "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.3.%i.0", "yes", SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, &pulizzi_sw_outlet_switchability_info[0], NULL },
/* FIXME: need to be added to the namespace! */
{ "outlet.%i.delay.reboot", ST_FLAG_RW, 1, ".1.3.6.1.4.1.20677.2.6.1.%i.5.0", NULL, SU_OUTLET, NULL, NULL },
/* "outlet1SequenceTime" is used for global sequence */
{ "outlet.%i.delay.start", ST_FLAG_RW, 1, ".1.3.6.1.4.1.20677.2.6.1.%i.4.0", NULL, SU_OUTLET, NULL, NULL },
/* instant commands. */
/* FIXME: not exposed as "outlet.load...", or otherwise specific processing applies (template instanciation) */
{ "load.on", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", NULL, SU_TYPE_CMD, NULL, NULL },
{ "load.off", 0, 2, ".1.3.6.1.4.1.20677.2.6.2.1.0", NULL, SU_TYPE_CMD, NULL, NULL },
{ "load.on.delay", 0, 3, ".1.3.6.1.4.1.20677.2.6.2.1.0", NULL, SU_TYPE_CMD, NULL, NULL },
{ "load.off.delay", 0, 4, ".1.3.6.1.4.1.20677.2.6.2.1.0", NULL, SU_TYPE_CMD, NULL, NULL },
/* WARNING: outlet 1 => index 2! */
{ "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.%i.0", NULL, SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL, NULL },
{ "outlet.%i.load.off", 0, 2, ".1.3.6.1.4.1.20677.2.6.2.%i.0", NULL, SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL, NULL },
{ "outlet.%i.load.cycle", 0, 3, ".1.3.6.1.4.1.20677.2.6.2.%i.0", NULL, SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL, NULL }
};
mib2nut_info_t aphel_genesisII = { "aphel_genesisII", EATON_APHEL_MIB_VERSION, NULL, APHEL1_OID_MODEL_NAME, eaton_aphel_genesisII_mib, APHEL1_SYSOID };
mib2nut_info_t aphel_revelation = { "aphel_revelation", EATON_APHEL_MIB_VERSION, NULL, APHEL2_OID_MODEL_NAME, eaton_aphel_revelation_mib, APHEL2_SYSOID };
mib2nut_info_t eaton_marlin = { "eaton_epdu", EATON_MARLIN_MIB_VERSION, NULL, EATON_MARLIN_OID_MODEL_NAME, eaton_marlin_mib, EATON_MARLIN_SYSOID };
/*mib2nut_info_t pulizzi_monitored = { "pulizzi_monitored", EATON_PULIZZI_MIB_VERSION, NULL, PULIZZI1_OID_MODEL_NAME, eaton_pulizzi_monitored_mib, PULIZZI1_OID_MIB };*/
mib2nut_info_t pulizzi_switched1 = { "pulizzi_switched1", EATON_PULIZZI_SW_MIB_VERSION, NULL, EATON_PULIZZI_SWITCHED1_SYSOID, eaton_pulizzi_switched_mib, EATON_PULIZZI_SWITCHED1_SYSOID };
mib2nut_info_t pulizzi_switched2 = { "pulizzi_switched2", EATON_PULIZZI_SW_MIB_VERSION, NULL, EATON_PULIZZI_SWITCHED1_SYSOID, eaton_pulizzi_switched_mib, EATON_PULIZZI_SWITCHED2_SYSOID };

View file

@ -1,13 +0,0 @@
#ifndef EATON_MIB_H
#define EATON_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t aphel_genesisII;
extern mib2nut_info_t aphel_revelation;
extern mib2nut_info_t eaton_marlin;
extern mib2nut_info_t pulizzi_switched1;
extern mib2nut_info_t pulizzi_switched2;
#endif /* EATON_MIB_H */

View file

@ -0,0 +1,95 @@
/* eaton-pdu-genesis2-mib.c - data to monitor Eaton ePDUs branded as:
* G1 Aphel based ePDUs (Basic) - GenesisII
*
* Copyright (C) 2008 - 2019
* Arnaud Quette <arnaud.quette@gmail.com>
* Arnaud Quette <ArnaudQuette@Eaton.com>
* Copyright (C) 2015 - 2017
* Jim Klimov <EvgenyKlimov@Eaton.com>
*
* Supported by Eaton <http://www.eaton.com>
* and previously MGE Office Protection Systems <http://www.mgeops.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
*
*/
#include "eaton-pdu-genesis2-mib.h"
#define EATON_APHEL_GENESIS2_MIB_VERSION "0.52"
/* APHEL-GENESIS-II-MIB (monitored ePDU)
* *************************************
* Note: There is also a basic XML interface, but not worth
* implementing in netxml-ups!
*/
#define APHEL1_OID_MIB ".1.3.6.1.4.1.17373"
#define APHEL1_SYSOID APHEL1_OID_MIB
#define APHEL1_OID_MODEL_NAME ".1.3.6.1.4.1.17373.3.1.1.0"
#define APHEL1_OID_FIRMREV ".1.3.6.1.4.1.17373.3.1.2.0"
#define APHEL1_OID_DEVICE_NAME ".1.3.6.1.4.1.17373.3.1.3.0"
#define APHEL1_OID_UNIT_MACADDR ".1.3.6.1.4.1.17373.3.1.4.0"
/* needs concat .<outlet-index>.0 */
#define APHEL1_OID_OUTLET_CURRENT ".1.3.6.1.4.1.17373.3.2"
/* Snmp2NUT lookup table for GenesisII MIB */
static snmp_info_t eaton_aphel_genesisII_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device page */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_MODEL_NAME,
"Eaton Powerware ePDU Monitored", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_UNIT_MACADDR, "unknown",
0, NULL },
/* UPS page */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_MODEL_NAME,
"Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.id", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_DEVICE_NAME,
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_FIRMREV, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* Outlet page */
/* we can't use template since there is no counterpart to outlet.count */
{ "outlet.1.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".1.0", NULL, SU_FLAG_NEGINVALID, NULL },
{ "outlet.2.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".2.0", NULL, SU_FLAG_NEGINVALID, NULL },
{ "outlet.3.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".3.0", NULL, SU_FLAG_NEGINVALID, NULL },
{ "outlet.4.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".4.0", NULL, SU_FLAG_NEGINVALID, NULL },
{ "outlet.5.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".5.0", NULL, SU_FLAG_NEGINVALID, NULL },
{ "outlet.6.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".6.0", NULL, SU_FLAG_NEGINVALID, NULL },
{ "outlet.7.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".7.0", NULL, SU_FLAG_NEGINVALID, NULL },
{ "outlet.8.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".8.0", NULL, SU_FLAG_NEGINVALID, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t aphel_genesisII = { "aphel_genesisII", EATON_APHEL_GENESIS2_MIB_VERSION, NULL, APHEL1_OID_MODEL_NAME, eaton_aphel_genesisII_mib, APHEL1_SYSOID, NULL };

View file

@ -0,0 +1,32 @@
/* eaton-pdu-genesis2-mib.h - subdriver to monitor Eaton ePDU SNMP devices with NUT
*
* Copyright (C)
* 2010 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2011 - 2012 Arnaud Quette <arnaud.quette@free.fr>
* 2017 Arnaud Quette <ArnaudQuette@eaton.com>
* 2017 Jim Klimov <EvgenyKlimov@eaton.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
*/
#ifndef EATON_EPDU_GENESIS_MIB_H
#define EATON_EPDU_GENESIS_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t aphel_genesisII;
#endif /* EATON_EPDU_GENESIS_MIB_H */

View file

@ -0,0 +1,91 @@
/* eaton-pdu-marlin-helpers.c - helper routines for eaton-pdu-marlin-mib.c
* to monitor Eaton ePDUs branded as:
* G2 Marlin SW / MI / MO / MA
* G3 Shark SW / MI / MO / MA
*
* Copyright (C) 2017-2019
* Arnaud Quette <ArnaudQuette@Eaton.com>
* Copyright (C) 2017
* Jim Klimov <EvgenyKlimov@Eaton.com>
*
* Supported by Eaton <http://www.eaton.com>
* and previously MGE Office Protection Systems <http://www.mgeops.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
*
*/
#include "config.h" /* must be the first header */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "eaton-pdu-marlin-helpers.h"
#include "dstate.h"
#include "common.h"
/* Allow access to temperature_unit */
#include "snmp-ups.h"
/* Take string "unitsPresent" (ex: "0,3,4,5"), and count the amount
* of "," separators+1 using an inline function */
long marlin_device_count_fun(const char *daisy_dev_list)
{
long count = 0, i;
for (i = 0; daisy_dev_list[i] != '\0'; i++) {
if (daisy_dev_list[i] == ',') {
/* Each comma means a new device in the list */
count ++;
}
}
if (i > 0 && (daisy_dev_list[i - 1] != ',') ) {
/* Non-empty string => at least one device, and no trailing commas */
count ++;
}
upsdebugx(3, "%s: counted devices in '%s', got %ld",
__func__, daisy_dev_list, count);
return count;
}
/* Temperature unit consideration:
* only store the device unit, for converting to Celsius.
* Don't publish the device unit, since NUT will publish
* as Celsius in all cases */
const char *eaton_sensor_temperature_unit_fun(void *raw_snmp_value)
{
long snmp_value = *((long*)raw_snmp_value);
switch (snmp_value) {
case 0:
/* store the value, for temperature processing */
temperature_unit = TEMPERATURE_KELVIN;
break;
case 1:
/* store the value, for temperature processing */
temperature_unit = TEMPERATURE_CELSIUS;
break;
case 2:
/* store the value, for temperature processing */
temperature_unit = TEMPERATURE_FAHRENHEIT;
break;
default:
/* store the value, for temperature processing */
temperature_unit = TEMPERATURE_UNKNOWN;
break;
}
return "celsius";
}

View file

@ -0,0 +1,29 @@
/* eaton-pdu-marlin-helpers.h - helper for subdriver to monitor certain
* Eaton ePDU SNMP devices with NUT
*
* Copyright (C)
* 2017-2019 Arnaud Quette <ArnaudQuette@eaton.com>
* 2017 Jim Klimov <EvgenyKlimov@eaton.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
*/
#ifndef EATON_EPDU_MARLIN_HELPERS_H
#define EATON_EPDU_MARLIN_HELPERS_H
long marlin_device_count_fun(const char *daisy_dev_list);
const char *eaton_sensor_temperature_unit_fun(void *raw_snmp_value);
#endif /* EATON_EPDU_MARLIN_HELPERS_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,32 @@
/* eaton-pdu-marlin-mib.h - subdriver to monitor Eaton ePDU SNMP devices with NUT
*
* Copyright (C)
* 2010 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2011 - 2012 Arnaud Quette <arnaud.quette@free.fr>
* 2017 Arnaud Quette <ArnaudQuette@eaton.com>
* 2017 Jim Klimov <EvgenyKlimov@eaton.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
*/
#ifndef EATON_EPDU_MARLIN_MIB_H
#define EATON_EPDU_MARLIN_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t eaton_marlin;
#endif /* EATON_EPDU_MARLIN_MIB_H */

View file

@ -0,0 +1,142 @@
/* eaton-pdu-pulizzi-mib.c - data to monitor Eaton ePDUs branded as:
* G1 Pulizzi Monitored and Switched ePDUs
*
* Copyright (C) 2008 - 2017
* Arnaud Quette <arnaud.quette@gmail.com>
* Arnaud Quette <ArnaudQuette@Eaton.com>
* Copyright (C) 2015 - 2017
* Jim Klimov <EvgenyKlimov@Eaton.com>
*
* Supported by Eaton <http://www.eaton.com>
* and previously MGE Office Protection Systems <http://www.mgeops.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
*
*/
#include "eaton-pdu-pulizzi-mib.h"
/* Pulizzi Monitored ePDU (Basic model, SNMP only)
* FIXME: to be completed
*
* Warning: there are 2 versions:
* - SA built MI.mib (old MIB)
* #define PULIZZI1_OID_MIB ".1.3.6.1.4.1.20677.3.1.1"
* #define PULIZZI1_OID_MODEL_NAME ".1.3.6.1.4.1.20677.3.1.1.1.2.0"
* - Eaton-Powerware-Monitored-ePDU_1.0.E.mib (new MIB) Vertical SW
*/
/* Pulizzi Switched ePDU */
#define EATON_PULIZZI_SW_MIB_VERSION "0.5"
#define PULIZZI_SW_OID_MIB ".1.3.6.1.4.1.20677.3.1.1"
#define PULIZZI_SW_OID_MODEL_NAME ".1.3.6.1.4.1.20677.2.1.1.0"
/* Some buggy FW also report sysOID = ".1.3.6.1.4.1.20677.1" */
#define EATON_PULIZZI_SWITCHED1_SYSOID ".1.3.6.1.4.1.20677.1"
#define EATON_PULIZZI_SWITCHED2_SYSOID ".1.3.6.1.4.1.20677.2"
static info_lkp_t pulizzi_sw_outlet_status_info[] = {
{ 1, "on", NULL, NULL },
{ 2, "off", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* simply remap the above status to "yes" */
static info_lkp_t pulizzi_sw_outlet_switchability_info[] = {
{ 1, "yes", NULL, NULL },
{ 2, "yes", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* Snmp2NUT lookup table for Eaton Pulizzi Switched ePDU MIB */
static snmp_info_t eaton_pulizzi_switched_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device page */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, PULIZZI_SW_OID_MODEL_NAME,
"Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.2.6.0",
"unknown", 0, NULL },
/* UPS page */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, PULIZZI_SW_OID_MODEL_NAME,
"Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* FIXME: to be moved to the device collection! */
{ "ups.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.1.4.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.time", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.1.3.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* Outlet page */
/* Note: outlet.count is deduced, with guestimate_outlet_count() */
{ "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.current", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.2.0", NULL, 0, NULL },
{ "outlet.voltage", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.1.0", NULL, 0, NULL },
{ "outlet.power", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.3.0", NULL, 0, NULL },
/* outlet template definition
* Notes:
* - indexes start from 1, ie outlet.1 => <OID>.1
* - the first definition is used to determine the base index (ie 0 or 1)
* - outlet.count is estimated, based on the below OID iteration capabilities */
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.1.%i.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, NULL },
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.3.%i.0",
NULL, SU_FLAG_OK | SU_OUTLET, &pulizzi_sw_outlet_status_info[0] },
{ "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL },
/* we use the same OID as outlet.n.status..., to expose switchability */
{ "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.3.%i.0", "yes", SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, &pulizzi_sw_outlet_switchability_info[0] },
/* FIXME: need to be added to the namespace! */
{ "outlet.%i.delay.reboot", ST_FLAG_RW, 1, ".1.3.6.1.4.1.20677.2.6.1.%i.5.0", NULL, SU_OUTLET, NULL },
/* "outlet1SequenceTime" is used for global sequence */
{ "outlet.%i.delay.start", ST_FLAG_RW, 1, ".1.3.6.1.4.1.20677.2.6.1.%i.4.0", NULL, SU_OUTLET, NULL },
/* instant commands. */
/* FIXME: not exposed as "outlet.load...", or otherwise specific processing applies (template instanciation) */
{ "load.on", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", "1", SU_TYPE_CMD, NULL },
{ "load.off", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", "2", SU_TYPE_CMD, NULL },
{ "load.on.delay", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", "3", SU_TYPE_CMD, NULL },
{ "load.off.delay", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", "4", SU_TYPE_CMD, NULL },
/* WARNING: outlet 1 => index 2, so SU_CMD_OFFSET! */
{ "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.%i.0", "1", SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL },
{ "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.%i.0", "2", SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL },
{ "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.%i.0", "3", SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
/*mib2nut_info_t pulizzi_monitored = { "pulizzi_monitored", EATON_PULIZZI_MIB_VERSION, NULL, PULIZZI1_OID_MODEL_NAME, eaton_pulizzi_monitored_mib, PULIZZI1_OID_MIB };*/
mib2nut_info_t pulizzi_switched1 = { "pulizzi_switched1", EATON_PULIZZI_SW_MIB_VERSION, NULL, EATON_PULIZZI_SWITCHED1_SYSOID, eaton_pulizzi_switched_mib, EATON_PULIZZI_SWITCHED1_SYSOID, NULL };
mib2nut_info_t pulizzi_switched2 = { "pulizzi_switched2", EATON_PULIZZI_SW_MIB_VERSION, NULL, EATON_PULIZZI_SWITCHED1_SYSOID, eaton_pulizzi_switched_mib, EATON_PULIZZI_SWITCHED2_SYSOID, NULL };

View file

@ -0,0 +1,33 @@
/* eaton-pdu-pulizzi-mib.h - subdriver to monitor Eaton ePDU SNMP devices with NUT
*
* Copyright (C)
* 2010 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2011 - 2012 Arnaud Quette <arnaud.quette@free.fr>
* 2017 Arnaud Quette <ArnaudQuette@eaton.com>
* 2017 Jim Klimov <EvgenyKlimov@eaton.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
*/
#ifndef EATON_EPDU_PULIZZI_MIB_H
#define EATON_EPDU_PULIZZI_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t pulizzi_switched1;
extern mib2nut_info_t pulizzi_switched2;
#endif /* EATON_EPDU_PULIZZI_MIB_H */

View file

@ -0,0 +1,182 @@
/* eaton-pdu-revelation-mib.c - data to monitor Eaton ePDUs branded as:
* G1 Aphel based ePDUs (Complex) - Revelation
*
* Copyright (C) 2008 - 2017
* Arnaud Quette <arnaud.quette@gmail.com>
* Arnaud Quette <ArnaudQuette@Eaton.com>
* Copyright (C) 2015 - 2017
* Jim Klimov <EvgenyKlimov@Eaton.com>
*
* Supported by Eaton <http://www.eaton.com>
* and previously MGE Office Protection Systems <http://www.mgeops.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
*
*/
#include "eaton-pdu-revelation-mib.h"
#define EATON_APHEL_REVELATION_MIB_VERSION "0.52"
/* APHEL PDU-MIB - Revelation MIB (Managed ePDU)
* ********************************************* */
#define AR_BASE_OID ".1.3.6.1.4.1.534.6.6.6"
#define APHEL2_SYSOID AR_BASE_OID
#define APHEL2_OID_MODEL_NAME AR_OID_MODEL_NAME
#define AR_OID_MODEL_NAME AR_BASE_OID ".1.1.12.0"
#define AR_OID_DEVICE_NAME AR_BASE_OID ".1.1.13.0"
#define AR_OID_FIRMREV AR_BASE_OID ".1.1.1.0"
#define AR_OID_SERIAL AR_BASE_OID ".1.1.2.0"
#define AR_OID_UNIT_MACADDR AR_BASE_OID ".1.1.6.0"
#define AR_OID_UNIT_CURRENT AR_BASE_OID ".1.3.1.1"
#define AR_OID_UNIT_VOLTAGE AR_BASE_OID ".1.3.1.2"
#define AR_OID_UNIT_ACTIVEPOWER AR_BASE_OID ".1.3.1.3"
#define AR_OID_UNIT_APPARENTPOWER AR_BASE_OID ".1.3.1.4"
#define AR_OID_UNIT_CPUTEMPERATURE AR_BASE_OID ".1.3.1.5.0"
#define AR_OID_OUTLET_INDEX AR_BASE_OID ".1.2.2.1.1"
#define AR_OID_OUTLET_NAME AR_BASE_OID ".1.2.2.1.2"
#define AR_OID_OUTLET_STATUS AR_BASE_OID ".1.2.2.1.3"
static info_lkp_t revelation_outlet_status_info[] = {
{ -1, "error", NULL, NULL },
{ 0, "off", NULL, NULL },
{ 1, "on", NULL, NULL },
{ 2, "cycling", NULL, NULL }, /* transitional status */
{ 0, NULL, NULL, NULL }
};
/* Ugly hack: having the matching OID present means that the outlet is
* switchable. So, it should not require this value lookup */
static info_lkp_t revelation_outlet_switchability_info[] = {
{ -1, "yes", NULL, NULL },
{ 0, "yes", NULL, NULL },
{ 1, "yes", NULL, NULL },
{ 2, "yes", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
#define DO_OFF "0"
#define DO_ON "1"
#define DO_CYCLE "2"
#define AR_OID_OUTLET_COUNT AR_BASE_OID ".1.2.1.0"
#define AR_OID_OUTLET_CURRENT AR_BASE_OID ".1.2.2.1.4"
#define AR_OID_OUTLET_MAXCURRENT AR_BASE_OID ".1.2.2.1.5"
#define AR_OID_OUTLET_VOLTAGE AR_BASE_OID ".1.2.2.1.6"
#define AR_OID_OUTLET_ACTIVEPOWER AR_BASE_OID ".1.2.2.1.7"
#define AR_OID_OUTLET_APPARENTPOWER AR_BASE_OID ".1.2.2.1.8"
#define AR_OID_OUTLET_POWERFACTOR AR_BASE_OID ".1.2.2.1.9"
/* Snmp2NUT lookup table for Eaton Revelation MIB */
static snmp_info_t eaton_aphel_revelation_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device collection */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_MODEL_NAME,
"Eaton Powerware ePDU Managed", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_SERIAL, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_UNIT_MACADDR, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* hardwareRev.0 = Integer: 26 */
/* FIXME: not compliant! to be RFC'ed */
{ "device.revision", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.6.1.1.7.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* UPS collection */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_MODEL_NAME,
"Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.id", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_DEVICE_NAME,
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_SERIAL, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_FIRMREV, "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.temperature", 0, 1, AR_OID_UNIT_CPUTEMPERATURE, NULL, 0, NULL },
/* Outlet collection */
{ "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.count", 0, 1, AR_OID_OUTLET_COUNT, "0", 0, NULL },
{ "outlet.current", 0, 0.001, AR_OID_UNIT_CURRENT ".0", NULL, 0, NULL },
{ "outlet.voltage", 0, 0.001, AR_OID_UNIT_VOLTAGE ".0", NULL, 0, NULL },
{ "outlet.realpower", 0, 1.0, AR_OID_UNIT_ACTIVEPOWER ".0", NULL, 0, NULL },
{ "outlet.power", 0, 1.0, AR_OID_UNIT_APPARENTPOWER ".0", NULL, 0, NULL },
/* outlet template definition
* Caution: the index of the data start at 0, while the name is +1
* ie outlet.1 => <OID>.0 */
{ "outlet.%i.switchable", 0, 1, AR_OID_OUTLET_STATUS ".%i", "yes", SU_FLAG_STATIC | SU_OUTLET, &revelation_outlet_switchability_info[0] },
{ "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL },
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_NAME ".%i", NULL, SU_OUTLET, NULL },
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_STATUS ".%i", NULL, SU_FLAG_OK | SU_OUTLET, &revelation_outlet_status_info[0] },
{ "outlet.%i.current", 0, 0.001, AR_OID_OUTLET_CURRENT ".%i", NULL, SU_OUTLET, NULL },
{ "outlet.%i.current.maximum", 0, 0.001, AR_OID_OUTLET_MAXCURRENT ".%i", NULL, SU_OUTLET, NULL },
{ "outlet.%i.realpower", 0, 1.0, AR_OID_OUTLET_ACTIVEPOWER ".%i", NULL, SU_OUTLET, NULL },
{ "outlet.%i.voltage", 0, 1.0, AR_OID_OUTLET_VOLTAGE ".%i", NULL, SU_OUTLET, NULL },
{ "outlet.%i.powerfactor", 0, 0.01, AR_OID_OUTLET_POWERFACTOR ".%i", NULL, SU_OUTLET, NULL },
{ "outlet.%i.power", 0, 1.0, AR_OID_OUTLET_APPARENTPOWER ".%i", NULL, SU_OUTLET, NULL },
/* FIXME:
* - delay for startup/shutdown sequence
* - support for multiple Ambient sensors ( max. 8), starting at index '0'
* ambient.%i.temperature => .1.3.6.1.4.1.534.6.6.6.2.2.1.3.%i
* ambient.%i.humidity => .1.3.6.1.4.1.534.6.6.6.2.4.1.3.%i
*/
/* Ambient collection */
/* We use critical levels, for both temperature and humidity,
* since warning levels are also available! */
{ "ambient.temperature", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.2.1.3.0", NULL, SU_FLAG_OK, NULL },
{ "ambient.temperature.low", 0, 1.0, "1.3.6.1.4.1.534.6.6.6.2.2.1.6.0", NULL, SU_FLAG_OK, NULL },
{ "ambient.temperature.high", 0, 1.0, "1.3.6.1.4.1.534.6.6.6.2.2.1.7.0", NULL, SU_FLAG_OK, NULL },
{ "ambient.humidity", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.3.0", NULL, SU_FLAG_OK, NULL },
{ "ambient.humidity.low", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.6.0", NULL, SU_FLAG_OK, NULL },
{ "ambient.humidity.high", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.7.0", NULL, SU_FLAG_OK, NULL },
/* instant commands. */
/* Note that load.cycle might be replaced by / mapped on shutdown.reboot */
/* no counterpart found!
{ "outlet.load.off", 0, DO_OFF, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL },
{ "outlet.load.on", 0, DO_ON, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL },
{ "outlet.load.cycle", 0, DO_CYCLE, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL }, */
{ "outlet.%i.load.off", 0, 1, AR_OID_OUTLET_STATUS ".%i", DO_OFF, SU_TYPE_CMD | SU_OUTLET, NULL },
{ "outlet.%i.load.on", 0, 1, AR_OID_OUTLET_STATUS ".%i", DO_ON, SU_TYPE_CMD | SU_OUTLET, NULL },
{ "outlet.%i.load.cycle", 0, 1, AR_OID_OUTLET_STATUS ".%i", DO_CYCLE, SU_TYPE_CMD | SU_OUTLET, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t aphel_revelation = { "aphel_revelation", EATON_APHEL_REVELATION_MIB_VERSION, NULL, APHEL2_OID_MODEL_NAME, eaton_aphel_revelation_mib, APHEL2_SYSOID, NULL };

View file

@ -0,0 +1,32 @@
/* eaton-pdu-revelation-mib.h - subdriver to monitor Eaton ePDU SNMP devices with NUT
*
* Copyright (C)
* 2010 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2011 - 2012 Arnaud Quette <arnaud.quette@free.fr>
* 2017 Arnaud Quette <ArnaudQuette@eaton.com>
* 2017 Jim Klimov <EvgenyKlimov@eaton.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
*/
#ifndef EATON_EPDU_REVELATION_MIB_H
#define EATON_EPDU_REVELATION_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t aphel_revelation;
#endif /* EATON_EPDU_REVELATION_MIB_H */

View file

@ -0,0 +1,191 @@
/* emerson-avocent-pdu-mib.c - subdriver to monitor Emerson Avocent PDUs with NUT
*
* Copyright (C)
* 2008-2018 Arnaud Quette <arnaud.quette@gmail.com>
* 2009 Opengear <support@opengear.com>
* 2017-2019 Eaton (Arnaud Quette <ArnaudQuette@Eaton.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
*
*/
#define OPENGEAR_MULTIPLE_BANKS 1
#include "emerson-avocent-pdu-mib.h"
#define EMERSON_AVOCENT_MIB_VERSION "1.3"
#define EMERSON_AVOCENT_SYSOID ".1.3.6.1.4.1.10418.17.1.7"
#define EMERSON_AVOCENT_OID_MODEL_NAME ".1.3.6.1.4.1.10418.17.2.1.2.0"
/* FIXME: Avocent PM's seem to have 3 temperature sensors (index 1, 2, 3)
* for the embedded temperature (equivalent to ups.temperature) */
#define AVOCENT_OID_UNIT_TEMPERATURE ".1.3.6.1.4.1.10418.17.2.5.3.1.17.1.1"
/* Same as above for humidity... */
#define AVOCENT_OID_UNIT_HUMIDITY ".1.3.6.1.4.1.10418.17.2.5.3.1.24.1"
#define AVOCENT_OID_OUTLET_COUNT ".1.3.6.1.4.1.10418.17.2.5.3.1.8.%i.%i"
/* FIXME: This is actually pmPowerMgmtPDUTableCurrent1Value */
#define AVOCENT_OID_UNIT_CURRENT ".1.3.6.1.4.1.10418.17.2.5.3.1.10.1.1"
/* FIXME: This is actually pmPowerMgmtPDUTableVoltage1Value */
#define AVOCENT_OID_UNIT_VOLTAGE ".1.3.6.1.4.1.10418.17.2.5.3.1.31.1.1"
#define AVOCENT_OID_UNIT_MACADDR ".1.3.6.1.2.1.2.2.1.6.1"
#ifdef OPENGEAR_MULTIPLE_BANKS
#define AVOCENT_OID_OUTLET_ID ".1.3.6.1.4.1.10418.17.2.5.5.1.3"
#define AVOCENT_OID_OUTLET_NAME ".1.3.6.1.4.1.10418.17.2.5.5.1.4"
#define AVOCENT_OID_OUTLET_STATUS ".1.3.6.1.4.1.10418.17.2.5.5.1.5"
/* This the actual value for the Current of the sensor. */
#define AVOCENT_OID_OUTLET_LOAD ".1.3.6.1.4.1.10418.17.2.5.5.1.50"
#define AVOCENT_OID_OUTLET_CONTROL ".1.3.6.1.4.1.10418.17.2.5.5.1.6"
#else
#define AVOCENT_OID_OUTLET_ID ".1.3.6.1.4.1.10418.17.2.5.5.1.3.1.1"
#define AVOCENT_OID_OUTLET_NAME ".1.3.6.1.4.1.10418.17.2.5.5.1.4.1.1"
#define AVOCENT_OID_OUTLET_STATUS ".1.3.6.1.4.1.10418.17.2.5.5.1.5.1.1"
#define AVOCENT_OID_OUTLET_LOAD ".1.3.6.1.4.1.10418.17.2.5.5.1.50.1.1"
#define AVOCENT_OID_OUTLET_CONTROL ".1.3.6.1.4.1.10418.17.2.5.5.1.6.1.1"
#endif
static info_lkp_t avocent_outlet_status_info[] = {
{ 1, "off", NULL, NULL },
{ 2, "on", NULL, NULL },
/* { 3, "offLocked", NULL, NULL },
{ 4, "onLocked", NULL, NULL },
{ 5, "offCycle", NULL, NULL },
{ 6, "onPendingOff", NULL, NULL },
{ 7, "offPendingOn", NULL, NULL },
{ 8, "onPendingCycle", NULL, NULL },
{ 9, "notSet", NULL, NULL },
{ 10, "onFixed", NULL, NULL },
{ 11, "offShutdown", NULL, NULL },
{ 12, "tripped", NULL, NULL },*/
{ 0, NULL, NULL, NULL }
};
static snmp_info_t emerson_avocent_pdu_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device page */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Avocent",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.5.3.1.5.1.%i", /* EMERSON_AVOCENT_OID_MODEL_NAME */
"Avocent SNMP PDU", SU_FLAG_ABSENT | SU_FLAG_OK | SU_FLAG_NAINVALID, NULL },
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.1.4.0", "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* Daisychained devices support
* Notes: this definition is used to:
* - estimate the number of devices, based on the below OID iteration capabilities
* - determine the base index of the SNMP OID (ie 0 or 1) */
{ "device.count", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.2.1.4.1",
"1", SU_FLAG_STATIC, NULL },
/* UPS page */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Avocent",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, EMERSON_AVOCENT_OID_MODEL_NAME,
"Avocent SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.1.1.0",
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.1.4.0", "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.1.7.0", "",
SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.macaddr", ST_FLAG_STRING, SU_INFOSIZE, AVOCENT_OID_UNIT_MACADDR,
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* Outlet page */
{ "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.count", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.3.1.8.1.%i", "0", SU_FLAG_STATIC | SU_FLAG_ZEROINVALID | SU_FLAG_OK, NULL },
/* outlets */
/* NOTE: there is a bug in Avocent FW:
* index '0' should not respond (and is not in subtree mode) but answers
* to unitary get, since OIDs start at index '1'.
*Use the status data below to test since '0' is not a supported value */
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.10418.17.2.5.5.1.5.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1 | SU_FLAG_ZEROINVALID, &avocent_outlet_status_info[0] },
{ "outlet.%i.id", 0, 1,
".1.3.6.1.4.1.10418.17.2.5.5.1.3.1.%i.%i", NULL, SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
{ "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.10418.17.2.5.5.1.4.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1 | SU_FLAG_NAINVALID, NULL },
/* pmPowerMgmtOutletsTableCurrentValue.1.1.1; Value (Integer): 0 */
{ "outlet.%i.current", 0, 0.1,
".1.3.6.1.4.1.10418.17.2.5.5.1.50.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pmPowerMgmtOutletsTableCurrentHighCritical.1.1.1; Value (Integer): 160 */
{ "outlet.%i.current.high.critical", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.10418.17.2.5.5.1.100.1.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pmPowerMgmtOutletsTableCurrentHighWarning.1.1.1; Value (Integer): 120 */
{ "outlet.%i.current.high.warning", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.10418.17.2.5.5.1.101.1.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pmPowerMgmtOutletsTableCurrentLowWarning.1.1.1; Value (Integer): 0 */
{ "outlet.%i.current.low.warning", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.10418.17.2.5.5.1.102.1.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pmPowerMgmtOutletsTableCurrentLowCritical.1.1.1; Value (Integer): 0 */
{ "outlet.%i.current.low.critical", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.10418.17.2.5.5.1.103.1.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pmPowerMgmtOutletsTablePowerValue.1.1.1; Value (Integer): 0 */
{ "outlet.%i.realpower", 0, 0.1,
".1.3.6.1.4.1.10418.17.2.5.5.1.60.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pmPowerMgmtOutletsTableVoltageValue.1.1.1; Value (Integer): 238 */
{ "outlet.%i.voltage", 0, 1,
".1.3.6.1.4.1.10418.17.2.5.5.1.70.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* TODO: handle statistics
* pmPowerMgmtOutletsTableEnergyValue.1.1.1; Value (Integer): 0 (Wh)
* pmPowerMgmtOutletsTableEnergyStartTime.1.1.1; Value (OctetString): 2018-02-13 10:40:09
* pmPowerMgmtOutletsTableEnergyReset.1.1.1; Value (Integer): noAction (1)
*/
/* Outlet groups collection */
/* pmPowerMgmtNumberOfOutletGroup.0; Value (Integer): 0 */
{ "outlet.group.count", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.6.%i",
"0", SU_FLAG_STATIC | SU_TYPE_DAISY_1, NULL },
/* TODO: support for "Banks" (not sure to understand what is this?!)
* pmPowerMgmtTotalNumberOfBanks.0; Value (Integer): 6
* pmPowerMgmtBanksTableName.1.1.1; Value (OctetString): 18-bf-ffP0_1_A
*/
/* According to MIB Power Control values are:
* noAction(1),
* powerOn(2),
* powerOff(3),
* powerCycle(4),
* powerLock(5),
* powerUnlock(6)
*/
{ "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.5.1.6.1.%i.%i", "4", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
{ "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.5.1.6.1.%i.%i", "3", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
{ "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.5.1.6.1.%i.%i", "2", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t emerson_avocent_pdu = { "emerson_avocent_pdu", EMERSON_AVOCENT_MIB_VERSION, NULL, EMERSON_AVOCENT_OID_MODEL_NAME, emerson_avocent_pdu_mib, EMERSON_AVOCENT_SYSOID, NULL };

View file

@ -0,0 +1,31 @@
/* emerson-avocent-pdu-mib.h - subdriver to monitor Emerson Avocent PDUs with NUT
*
* Copyright (C)
* 2008-2018 Arnaud Quette <arnaud.quette@gmail.com>
* 2009 Opengear <support@opengear.com>
* 2018 Eaton (Arnaud Quette <ArnaudQuette@Eaton.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
*/
#ifndef EMERSON_AVOCENT_PDU_MIB_H
#define EMERSON_AVOCENT_PDU_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t emerson_avocent_pdu;
#endif /* EMERSON_AVOCENT_PDU_MIB_H */

View file

@ -52,9 +52,10 @@
#include "main.h"
#include "serial.h"
#include "nut_stdint.h"
#define DRIVER_NAME "ETA PRO driver"
#define DRIVER_VERSION "0.04"
#define DRIVER_VERSION "0.05"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -112,7 +113,10 @@ etapro_get_response(const char *resp_type)
upslogx(LOG_ERR, "bad response format (%s)", tmp);
return -1;
}
return val;
if (val > INT_MAX) {
upslogx(LOG_WARNING, "got value too big in response");
}
return (int)val;
}
static void
@ -190,7 +194,7 @@ static int instcmd(const char *cmdname, const char *extra)
return STAT_INSTCMD_HANDLED;
}
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}

787
drivers/ever-hid.c Normal file
View file

@ -0,0 +1,787 @@
/* ever-hid.c - subdriver to monitor EVER USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2012 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2013 Charles Lepple <clepple+nut@gmail.com>
* 2017 EVER Power Systems [https://ever.eu/]
* 2020 - 2022 Jim Klimov <jimklimov+nut@gmail.com>
*
* Note: this subdriver was initially generated as a "stub" by the
* gen-usbhid-subdriver script. It must be customized.
*
* 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 "config.h" /* must be first */
#include "usbhid-ups.h"
#include "ever-hid.h"
#include "main.h" /* for getval() */
#include "usb-common.h"
#define EVER_HID_VERSION "Ever HID 0.1"
/* FIXME: experimental flag to be put in upsdrv_info */
/* Ever */
#define EVER_VENDORID 0x2e51
/* ST Microelectronics */
#define STMICRO_VENDORID 0x0483
/* USB IDs device table */
static usb_device_id_t ever_usb_device_table[] = {
{ USB_DEVICE(STMICRO_VENDORID, 0xa113), NULL },
{ USB_DEVICE(EVER_VENDORID, 0xffff), NULL},
{ USB_DEVICE(EVER_VENDORID, 0x0000), NULL},
/* Terminating entry */
{ 0, 0, NULL }
};
/* --------------------------------------------------------------- */
/* Vendor-specific usage table */
/* --------------------------------------------------------------- */
static const char *ever_format_hardware_fun(double value)
{
/*TODO - add exception handling for v1.0b0B */
const char* hard_rev[27] = {"0", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
static char model[10];
snprintf(model, sizeof(model), "rev.%sv%02u",
(&hard_rev[ ((unsigned int)value & 0xFF00)>>8 ])[0],
(unsigned int)value & 0xFF );
return model;
}
static const char *ever_format_version_fun(double value)
{
/*upsdebugx(1, "UPS ups_firmware_conversion_fun VALUE: %d", (long)value ); */
static char model[10];
snprintf(model, sizeof(model), "v%X.%Xb%02d",
((unsigned int)value & 0xF000)>>12,
((unsigned int)value & 0xF00)>>8,
((int)value & 0xFF) );
return model;
}
static const char *ever_mac_address_fun(double value)
{
NUT_UNUSED_VARIABLE(value);
int mac_adress_report_id = 210;
int len = reportbuf->len[mac_adress_report_id];
const void *buf = reportbuf->data[mac_adress_report_id];
static char line[100];
line[0] = '\0';
int n = 0; /* number of characters currently in line */
int i; /* number of bytes output from buffer */
/* skip first elemnt which is a report id */
for (i = 1; i < len; i++) {
n = snprintfcat(line, sizeof(line), n ? ":%02x" : "%02x",
((unsigned char *)buf)[i]);
}
return line;
}
static const char *ever_ip_address_fun(double value)
{
NUT_UNUSED_VARIABLE(value);
static int report_counter = 1;
int report_id = 211;
if(report_counter == 1)
report_id = 211; /* notification dest ip */
else if(report_counter == 2)
report_id = 230; /* ip address */
else if(report_counter == 3)
report_id = 231; /* network mask */
else if(report_counter == 4)
report_id = 232; /* default gateway */
report_counter== 4 ? report_counter=1 : report_counter++;
int len = reportbuf->len[report_id];
const void *buf = reportbuf->data[report_id];
static char line[100];
line[0] = '\0';
int n = 0; /* number of characters currently in line */
int i; /* number of bytes output from buffer */
/*skip first element which is a report id */
for (i = 1; i < len; i++)
{
n = snprintfcat(line, sizeof(line), n ? ".%d" : "%d",
((unsigned char *)buf)[i]);
}
return line;
}
static const char *ever_packets_fun(double value)
{
NUT_UNUSED_VARIABLE(value);
static int report_counter = 1;
int report_id = 215;
if(report_counter == 1 )
report_id = 215;
else if(report_counter == 2 )
report_id = 216;
else if(report_counter == 3 )
report_id = 217;
else if(report_counter == 4 )
report_id = 218;
report_counter== 4 ? report_counter=1 : report_counter++;
int len = reportbuf->len[report_id];
const unsigned char *buf = reportbuf->data[report_id];
static char line[100];
line[0] = '\0';
/*skip first elemnt which is a report id */
if(len < 5)
return "";
int res = (int)buf[1];
res |= (int)buf[2] << 8;
res |= (int)buf[3] << 16;
res |= (int)buf[4] << 24;
snprintf(line, sizeof(line), "%d", res);
return line;
}
static const char* ever_workmode_fun(double value)
{
NUT_UNUSED_VARIABLE(value);
int workmode_report_id = 74;
int workmode = -1;
const unsigned char *buf = reportbuf->data[workmode_report_id];
static char line[100];
line[0] = '\0';
/*skip first element which is a report id */
snprintfcat(line, sizeof(line), "%d", buf[1]);
workmode = atoi(line);
switch(workmode)
{
case 1:
return "UNKNOWN";
case 2:
return "STOP";
case 4:
return "ONLINE";
case 8:
return "ONBATTERY";
case 16:
return "WATCH";
case 32:
return "WAITING";
case 64:
return "EMERGENCY";
default:
return "UNKNOWN";
}
}
static const char* ever_messages_fun(double value)
{
NUT_UNUSED_VARIABLE(value);
int messages_report_id = 75;
const unsigned char *buf = reportbuf->data[messages_report_id];
static char line[200];
line[0] = '\0';
/*skip first element which is a report id */
int messages = (int)buf[1];
messages |= (int)buf[2] << 8;
int n = 0; /* number of characters currently in line */
/* duplicate of ups.status: OB LB */
/*
if(messages & 0x01)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "OVERLOAD");
if(messages & 0x02)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "BATTERY_LOW");
*/
if(messages & 0x04)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "BOOST");
if(messages & 0x08)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "BUCK");
if(messages & 0x10)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "BOOST_BLOCKED");
if(messages & 0x20)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "BUCK_BLOCKED");
if(messages & 0x40)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "CHARGING");
if(messages & 0x80)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "FAN_ON");
if(messages & 0x100)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "EPO_BLOCKED");
if(messages & 0x200)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "NEED_REPLACMENT");
if(messages & 0x400 || messages & 0x800)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "OVERHEAT");
if(messages & 0x1000)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "WAITING_FOR_MIN_CHARGE");
if(messages & 0x2000)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "MAINS_OUT_OF_RANGE");
return line;
}
static const char* ever_alarms_fun(double value)
{
NUT_UNUSED_VARIABLE(value);
int alarms_report_id = 76;
const unsigned char *buf = reportbuf->data[alarms_report_id];
static char line[200];
line[0] = '\0';
/*skip first element which is a report id */
int alarms = (int)buf[1];
alarms |= (int)buf[2] << 8;
int n = 0; /* number of characters currently in line */
if(alarms & 0x01)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "OVERLOAD");
if(alarms & 0x02)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "SHORT-CIRCUIT");
if(alarms & 0x04 || alarms & 0x08)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "OVERHEAT");
if(alarms & 0x10)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "EPO");
if(alarms & 0x20)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "INERNAL_ERROR");
if(alarms & 0x40)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "REVERSE_POWER_SUPPLY");
if(alarms & 0x80)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "NO_INETERNAL_COMM");
if(alarms & 0x100)
n = snprintfcat(line, sizeof(line), n ? " %s" : "%s", "CRITICAL_BATT_VOLTAGE");
return line;
}
static const char* ever_on_off_fun(double value)
{
NUT_UNUSED_VARIABLE(value);
int workmode_report_id = 74;
int workmode = -1;
const unsigned char *buf = reportbuf->data[workmode_report_id];
static char line[100];
line[0] = '\0';
/*skip first element which is a report id */
snprintfcat(line, sizeof(line), "%d", buf[1]);
workmode = atoi(line);
if(workmode != 0x04 && workmode != 0x08)
return "off";
return "!off";
}
static info_lkp_t ever_format_hardware[] = {
{ 0, NULL, ever_format_hardware_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ever_format_version[] = {
{ 0, NULL, ever_format_version_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ever_mac_address[] = {
{ 0, NULL, ever_mac_address_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ever_ip_address[] = {
{ 0, NULL, ever_ip_address_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ever_packets[] = {
{ 0, NULL, ever_packets_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ever_workmode[] = {
{ 0, NULL, ever_workmode_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ever_messages[] = {
{ 0, NULL, ever_messages_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ever_alarms[] = {
{ 0, NULL, ever_alarms_fun, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ever_on_off_info[] = {
{ 0, NULL, ever_on_off_fun, NULL },
{ 0, NULL, NULL, NULL }
};
/* EVER usage table */
static usage_lkp_t ever_usage_lkp[] = {
{ "EVER1", 0x00000000 },
{ "EVER2", 0xff000000 },
{ "EVER3", 0xff000001 },
{ "EVER4", 0xff000002 },
{ "EVER5", 0xff000003 },
{ "EVER6", 0xff000004 },
{ "EVER7", 0xff000005 },
{ "EVER8", 0xff000006 },
{ "EVER9", 0xff000007 },
{ "EVER10", 0xff000008 },
{ "EVER11", 0xff000009 },
{ "EVER12", 0xff000010 },
{ "EVER13", 0xff000011 },
{ "EVER14", 0xff000012 },
{ "EVER15", 0xff000013 },
{ "EVER16", 0xff000014 },
{ "EVER17", 0xff000015 },
{ "EVER18", 0xff000016 },
{ "EVER19", 0xff000017 },
{ "EVER20", 0xff000018 },
{ "EVER21", 0xff000019 },
{ "EVER22", 0xff00001a },
{ "EVER23", 0xff00001b },
{ "EVER24", 0xff00001c },
{ "EVER25", 0xff00001d },
{ "EVER26", 0xff00001e },
{ "EVER27", 0xff00001f },
{ "EVER28", 0xff000020 },
{ "EVER29", 0xff000021 },
{ "EVER30", 0xff000022 },
{ "EVER31", 0xff000023 },
{ "EVER32", 0xff000030 },
{ "EVER33", 0xff000031 },
{ "EVER34", 0xff000032 },
{ "EVER35", 0xff000033 },
{ "EVER36", 0xff000034 },
{ "EVER37", 0xff000035 },
{ "EVER38", 0xff000036 },
{ "EVER39", 0xff000037 },
{ "EVER40", 0xff000038 },
{ "EVER41", 0xff000039 },
{ "EVER42", 0xff000040 },
{ "EVER43", 0xff000041 },
{ "EVER44", 0xff000042 },
{ "EVER45", 0xff000043 },
{ "EVER46", 0xff000044 },
{ "EVER47", 0xff000045 },
{ "EVER48", 0xff000046 },
{ "EVER49", 0xff000050 },
{ "EVER50", 0xff000051 },
{ "EVER51", 0xff000052 },
{ "EVER52", 0xff000053 },
{ "EVER53", 0xff000054 },
{ "EVER54", 0xff000060 },
{ "EVER55", 0xff000061 },
{ "EVER56", 0xff000062 },
{ "EVER57", 0xff000063 },
{ "EVER58", 0xff000064 },
{ "EVER59", 0xff000066 },
{ "EVER60", 0xff000067 },
{ "EVER61", 0xff000068 },
{ "EVER62", 0xff000069 },
{ "EVER63", 0xff00006a },
{ "EVER64", 0xff00006b },
{ "EVER65", 0xff00006c },
{ "EVER66", 0xff00006d },
{ "EVER67", 0xff00006e },
{ "EVER68", 0xff00006f },
{ "EVER69", 0xff000070 },
{ "EVER70", 0xff000071 },
{ "EVER71", 0xff000072 },
{ "EVER72", 0xff000073 },
{ "EVER73", 0xff000074 },
{ "EVER74", 0xff000075 },
{ "EVER75", 0xff000076 },
{ "EVER76", 0xff000077 },
{ "EVER77", 0xff000078 },
{ "EVER78", 0xff000079 },
{ "EVER79", 0xff00007a },
{ "EVER80", 0xff00007b },
{ "EVER81", 0xff00007c },
{ "EVER82", 0xff00007d },
{ "EVER83", 0xff00007e },
{ "EVER84", 0xff00007f },
{ "EVER85", 0xff000080 },
{ "EVER86", 0xff000081 },
{ "EVER87", 0xff000082 },
{ "EVER88", 0xff000083 },
{ "EVER89", 0xff000084 },
{ "EVER90", 0xff000085 },
{ "EVER91", 0xff000086 },
{ "EVER92", 0xff000087 },
{ "EVER93", 0xff000088 },
{ "EVER94", 0xff000089 },
{ "EVER95", 0xff00008a },
{ "EVER96", 0xff00008b },
{ "EVER97", 0xff000090 },
{ "EVER98", 0xff000091 },
{ "EVER99", 0xff000092 },
{ "EVER100", 0xff000093 },
{ "EVER101", 0xff000094 },
{ "EVER102", 0xff000095 },
{ "EVER103", 0xff000096 },
{ "EVER104", 0xff000097 },
{ NULL, 0 }
};
static usage_tables_t ever_utab[] = {
ever_usage_lkp,
hid_usage_lkp,
NULL,
};
/* --------------------------------------------------------------- */
/* HID2NUT lookup table */
/* --------------------------------------------------------------- */
static hid_info_t ever_hid2nut[] = {
/* Note: fields marked with "experimental." prefix were proposed without
* an exact match vs. docs/nut-names.txt definitions. PRs are welcome to
* analyze and map those values into standard NUT variable names, or to
* raise discussion on mailing lists and define new names via consensus.
* There is a lot of interesting info listed below.
*
* Note: mappings that were applied below (as committed 2022-02-09) may
* be wrong and are based mostly on cursory reading of original names.
* In particular, not sure if the skipped "id.*" fields were identifiers
* or some "internal device" etc.
*/
/* experimental: "NUT variable names" do not currently have
* any battery.*id data points: */
{ "experimental.battery.batteryid", 0, 0, "UPS.BatterySystem.Battery.BatteryID", NULL, "%.0f", 0, NULL },
{ "experimental.battery.systemid", 0, 0, "UPS.BatterySystem.BatterySystemID", NULL, "%.0f", 0, NULL },
{ "experimental.battery.chargerid", 0, 0, "UPS.BatterySystem.Charger.ChargerID", NULL, "%.0f", 0, NULL },
{ "experimental.battery.input_flowid", 0, 0, "UPS.BatterySystem.Input.FlowID", NULL, "%.0f", 0, NULL },
{ "experimental.battery.input_id", 0, 0, "UPS.BatterySystem.Input.InputID", NULL, "%.0f", 0, NULL },
{ "experimental.battery.output_flowid", 0, 0, "UPS.BatterySystem.Output.FlowID", NULL, "%.0f", 0, NULL },
{ "experimental.battery.output_id", 0, 0, "UPS.BatterySystem.Output.OutputID", NULL, "%.0f", 0, NULL },
/* experimental: "NUT variable names" do not currently have
* any id (nor version) data points for FW/HW of components: */
/* not implemented*/
/* { "experimental.id.ups_type", 0, 0, "UPS.EVER1.EVER12", NULL, "%s", 0, ever_format_model }, */
{ "experimental.id.firmware_version_inverter", 0, 0, "UPS.EVER1.EVER13", NULL, "%s", 0, ever_format_version },
{ "experimental.id.firmware_version_interfaces", 0, 0, "UPS.EVER1.EVER14", NULL, "%s", 0, ever_format_version },
{ "experimental.id.hardware_version", 0, 0, "UPS.EVER1.EVER15", NULL, "%s", 0, ever_format_hardware },
{ "experimental.id.protocol_version_inverter", 0, 0, "UPS.EVER1.EVER16", NULL, "%s", 0, ever_format_version },
{ "experimental.id.protocol_version_interfaces", 0, 0, "UPS.EVER1.EVER17", NULL, "%s", 0, ever_format_version },
/* WAS: "experimental.inverter_info.heatsink_temperature" */
{ "ups.temperature", 0, 0, "UPS.EVER1.EVER42", NULL, "%s", 0, kelvin_celsius_conversion },
/* WAS: "experimental.inverter_info.battery_temperature" */
{ "battery.temperature", 0, 0, "UPS.EVER1.EVER43", NULL, "%s", 0, kelvin_celsius_conversion },
/* WAS: "experimental.ups_info.output_powerfactor" */
{ "powerfactor", 0, 0, "UPS.EVER1.EVER44", NULL, "%.0f", 0, NULL },
/* experimental: Should these be HU_TYPE_CMD entries?
* Or are they really settings? */
{ "experimental.control.ups_on", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER45.EVER46", NULL, "%.0f", 0, NULL },
{ "experimental.control.clear_fault", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER45.EVER47", NULL, "%.0f", 0, NULL },
{ "experimental.control.clear_battery_fault", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER45.EVER48", NULL, "%.0f", 0, NULL },
{ "experimental.control.epo_blocked", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER49.EVER50", NULL, "%.0f", 0, NULL },
{ "experimental.control.green_mode", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER49.EVER51", NULL, "%.0f", 0, NULL },
{ "experimental.control.button_sound", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER49.EVER52", NULL, "%.0f", 0, NULL },
{ "experimental.control.audible_alarm", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER49.EVER53", NULL, "%.0f", 0, NULL },
/* WAS: "experimental.config.output_voltage" */
{ "output.voltage", ST_FLAG_RW | ST_FLAG_STRING, 3, "UPS.EVER1.EVER54", NULL, "%.0f", 0, NULL },
/* not implemented*/
/*
{ "experimental.config.min_output_voltage", ST_FLAG_RW | ST_FLAG_STRING, 3, "UPS.EVER1.EVER55", NULL, "%.0f", 0, NULL },
{ "experimental.config.max_output_voltage", ST_FLAG_RW | ST_FLAG_STRING, 3, "UPS.EVER1.EVER56", NULL, "%.0f", 0, NULL },
{ "experimental.config.min_output_frequency", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER57", NULL, "%.1f", 0, NULL },
{ "experimental.config.max_output_frequency", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.EVER1.EVER58", NULL, "%.1f", 0, NULL },
*/
/* experimental: what units is this counted in?
* is "ups.load.high" a suitable mapping here? or "battery.voltage.high"?
*/
{ "experimental.config.overload_clearance_threshold", ST_FLAG_RW | ST_FLAG_STRING, 2, "UPS.EVER1.EVER59", NULL, "%.0f", 0, NULL },
{ "experimental.config.stb_charge", ST_FLAG_RW | ST_FLAG_STRING, 2, "UPS.EVER1.EVER60", NULL, "%.0f", 0, NULL },
/* WAS: "experimental.config.number_of_ebms"
* Should this be a string? rw?
*/
{ "battery.packs.external", ST_FLAG_RW | ST_FLAG_STRING, 1, "UPS.EVER1.EVER61", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.mains_loss_counter", 0, 0, "UPS.EVER1.EVER62", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.lowering_AVR_trigger_counter", 0, 0, "UPS.EVER1.EVER63", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.rising_AVR_trigger_counter", 0, 0, "UPS.EVER1.EVER64", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.overload_counter", 0, 0, "UPS.EVER1.EVER65", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.short_circuit_counter", 0, 0, "UPS.EVER1.EVER66", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.discharge_counter", 0, 0, "UPS.EVER1.EVER67", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.overheat_counter", 0, 0, "UPS.EVER1.EVER68", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.mains_operation_time", 0, 0, "UPS.EVER1.EVER69", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.autonomous_operation_time", 0, 0, "UPS.EVER1.EVER70", NULL, "%.0f", 0, NULL },
{ "experimental.statistics.overload_operation_time", 0, 0, "UPS.EVER1.EVER71", NULL, "%.0f", 0, NULL },
{ "experimental.networkcard.mac_address", 0, 0, "UPS.EVER1.EVER72", NULL, "%s", 0, ever_mac_address },
{ "experimental.networkcard.notification_destination_ip", 0, 0, "UPS.EVER1.EVER73", NULL, "%s", 0, ever_ip_address },
{ "experimental.networkcard.send_packets", 0, 0, "UPS.EVER1.EVER77", NULL, "%s", 0, ever_packets },
{ "experimental.networkcard.received_packets", 0, 0, "UPS.EVER1.EVER78", NULL, "%s", 0, ever_packets },
{ "experimental.networkcard.send_packets_err", 0, 0, "UPS.EVER1.EVER79", NULL, "%s", 0, ever_packets },
{ "experimental.networkcard.received_packets_err", 0, 0, "UPS.EVER1.EVER80", NULL, "%s", 0, ever_packets },
{ "experimental.networkcard.config_dhcp_enabled", 0, 0, "UPS.EVER1.EVER85.EVER86", NULL, "%.0f", 0, NULL },
{ "experimental.networkcard.config_ethernet_enabled", 0, 0, "UPS.EVER1.EVER85.EVER87", NULL, "%.0f", 0, NULL },
{ "experimental.networkcard.config_http_enabled", 0, 0, "UPS.EVER1.EVER85.EVER88", NULL, "%.0f", 0, NULL },
{ "experimental.networkcard.config_snmp_enabled", 0, 0, "UPS.EVER1.EVER85.EVER89", NULL, "%.0f", 0, NULL },
{ "experimental.networkcard.config_snmp_trap_enabled", 0, 0, "UPS.EVER1.EVER85.EVER90", NULL, "%.0f", 0, NULL },
{ "experimental.networkcard.config_readonly", 0, 0, "UPS.EVER1.EVER85.EVER91", NULL, "%.0f", 0, NULL },
{ "experimental.networkcard.config_restart_eth", 0, 0, "UPS.EVER1.EVER85.EVER96", NULL, "%.0f", 0, NULL },
{ "experimental.networkcard.ip_address", 0, 0, "UPS.EVER1.EVER93", NULL, "%s", 0, ever_ip_address },
{ "experimental.networkcard.network_mask", 0, 0, "UPS.EVER1.EVER94", NULL, "%s", 0, ever_ip_address },
{ "experimental.networkcard.default_gateway", 0, 0, "UPS.EVER1.EVER95", NULL, "%s", 0, ever_ip_address },
/* WAS: "experimental.id.config_active_power" */
{ "ups.realpower.nominal", 0, 0, "UPS.Flow.ConfigActivePower", NULL, "%.0f", 0, NULL },
/* WAS: "experimental.id.config_apparent_power"
* Other HID subdrivers use "ups.power.nominal" mostly (often HU_FLAG_STATIC);
* once of each: "ups.realpower.nominal", "ups.realpower".
* Is this even a run-time value or a hardware property?
*/
{ "ups.power.nominal", 0, 0, "UPS.Flow.ConfigApparentPower", NULL, "%.0f", 0, NULL },
/* WAS: "experimental.ups.config_frequency"
* Here and next: is this about input or output?..
* Other drivers have "input.frequency.nominal" on numbered Flows
* As a "nominal", should it be HU_FLAG_SEMI_STATIC or HU_FLAG_STATIC maybe?
* Note there are non-nominal values in "powerconverter" below,
* so the questions here may be somewhat irrelevant...
*/
{ "output.frequency.nominal", 0, 0, "UPS.Flow.ConfigFrequency", NULL, "%.0f", 0, NULL },
/* WAS: "experimental.ups.config_voltage" */
{ "output.voltage.nominal", 0, 0, "UPS.Flow.ConfigVoltage", NULL, "%.0f", 0, NULL },
{ "experimental.ups.flow_id", 0, 0, "UPS.Flow.FlowID", NULL, "%.0f", 0, NULL },
/* NOTE: NUT variable names define "outlet.n.*" names for numbering all
* separately manageable outlets; the numberless value (or outlet.0.*)
* is reserved to represent common properties of all outlets, if there
* are more than one outlet (group).
* Mapping below arbitrarily assigns n=1 but really this should be tied
* to actual outlet counts (see %i mappings in other drivers).
*/
/* WAS: experimental.outlet.outlet_id */
{ "outlet.1.id", 0, 0, "UPS.OutletSystem.Outlet.OutletID", NULL, "%.0f", 0, NULL },
/* WAS: */
{ "experimental.outlet.1.present", 0, 0, "UPS.OutletSystem.Outlet.PresentStatus.Present", NULL, "%.0f", 0, yes_no_info },
{ "outlet.1.switchable", 0, 0, "UPS.OutletSystem.Outlet.PresentStatus.Switchable", NULL, "%.0f", 0, yes_no_info },
/* WAS: experimental.outlet.switch_on_off */
{ "outlet.1.status", 0, 0, "UPS.OutletSystem.Outlet.PresentStatus.SwitchOn/Off", NULL, "%.0f", 0, NULL },
{ "experimental.outlet.1.undefined", 0, 0, "UPS.OutletSystem.Outlet.PresentStatus.Undefined", NULL, "%.0f", 0, NULL },
{ "experimental.outlet.1.system_id", 0, 0, "UPS.OutletSystem.OutletSystemID", NULL, "%.0f", 0, NULL },
/* experimental: Should these be HU_TYPE_CMD entries?
* Or are they really settings? */
{ "experimental.outlet.1.switch_off_control", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.OutletSystem.Outlet.SwitchOffControl", NULL, "%.0f", 0, NULL },
{ "experimental.outlet.1.switch_on_control", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.OutletSystem.Outlet.SwitchOnControl", NULL, "%.0f", 0, NULL },
{ "experimental.powerconverter.input_flow_id", 0, 0, "UPS.PowerConverter.Input.FlowID", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powerconverter.input_frequency */
{ "input.frequency", 0, 0, "UPS.PowerConverter.Input.Frequency", NULL, "%.0f", 0, NULL },
{ "experimental.powerconverter.input_id", 0, 0, "UPS.PowerConverter.Input.InputID", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powerconverter.input_voltage */
{ "input.voltage", 0, 0, "UPS.PowerConverter.Input.Voltage", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powerconverter.output_active_power */
{ "ups.realpower", 0, 0, "UPS.PowerConverter.Output.ActivePower", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powerconverter.output_apparent_power */
{ "ups.power", 0, 0, "UPS.PowerConverter.Output.ApparentPower", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powerconverter.output_current */
{ "output.current", 0, 0, "UPS.PowerConverter.Output.Current", NULL, "%.0f", 0, NULL },
{ "experimental.powerconverter.output_flowid", 0, 0, "UPS.PowerConverter.Output.FlowID", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powerconverter.output_frequency */
{ "output.frequency", 0, 0, "UPS.PowerConverter.Output.Frequency", NULL, "%.0f", 0, NULL },
{ "experimental.powerconverter.output_id", 0, 0, "UPS.PowerConverter.Output.OutputID", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powerconverter.output_percent_load
* Note: several original readings map into "ups.load", first served wins
*/
{ "ups.load", 0, 0, "UPS.PowerConverter.Output.PercentLoad", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powerconverter.output_voltage */
{ "output.voltage", 0, 0, "UPS.PowerConverter.Output.Voltage", NULL, "%.0f", 0, NULL },
{ "experimental.powerconverter.powerconverterid", 0, 0, "UPS.PowerConverter.PowerConverterID", NULL, "%.0f", 0, NULL },
{ "experimental.powersummary.capacity_granularity_1", 0, 0, "UPS.PowerSummary.CapacityGranularity1", NULL, "%.0f", 0, NULL },
{ "experimental.powersummary.capacity_granularity_2", 0, 0, "UPS.PowerSummary.CapacityGranularity2", NULL, "%.0f", 0, NULL },
/* WAS: */
{ "experimental.powersummary.capacity_mode", 0, 0, "UPS.PowerSummary.CapacityMode", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.delay_before_shutdown */
{ "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL },
/* WAS: experimental.powersummary.design_capacity */
{ "battery.capacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL },
{ "experimental.powersummary.flow_id", 0, 0, "UPS.PowerSummary.FlowID", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.full_charge_capacity */
{ "battery.capacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.idevice_chemistry */
{ "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.percent_load
* Note: several original readings map into "ups.load", first served wins
*/
{ "ups.load", 0, 0, "UPS.PowerSummary.PercentLoad", NULL, "%.0f", 0, NULL },
{ "experimental.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.remaining_capacity */
{ "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.remaining_time_limit */
{ "battery.runtime.low", ST_FLAG_RW | ST_FLAG_NUMBER, 0, "UPS.PowerSummary.RemainingTimeLimit", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.run_time_to_empty */
{ "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.voltage */
{ "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.0f", 0, NULL },
/* WAS: experimental.powersummary.delay_before_shutdown */
{ "ups.timer.shutdown", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL },
/* not implemented*/
/* { "unmapped.ups.powersummary.powersummaryid", 0, 0, "UPS.PowerSummary.PowerSummaryID", NULL, "%.0f", 0, NULL }, */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.AwaitingPower", NULL, NULL, HU_FLAG_QUICK_POLL, awaitingpower_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BatteryPresent", NULL, NULL, 0, nobattery_info },
/* not implemented*/
/* { "experimental.ups.presentstatus.belowremainingcapacitylimit", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, "%.0f", 0, NULL }, */
/* { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Boost", NULL, NULL, 0, boost_info }, */
/* { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Buck", NULL, NULL, 0, trim_info }, */
/* { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info }, */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.CommunicationLost", NULL, NULL, 0, commfault_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info },
/* not implemented*/
/* { "experimental.ups.powersummary.presentstatus.good", 0, 0, "UPS.PowerSummary.PresentStatus.Good", NULL, "%.0f", 0, NULL }, */
/* { "experimental.ups.powersummary.presentstatus.internalfailure", 0, 0, "UPS.PowerSummary.PresentStatus.InternalFailure", NULL, "%.0f", 0, NULL }, */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.NeedReplacement", NULL, NULL, 0, replacebatt_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Overload", NULL, NULL, HU_FLAG_QUICK_POLL, overload_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.OverTemperature", NULL, NULL, 0, overheat_info },
/* not implemented*/
/* { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.RemainingTimeLimitExpired", NULL, NULL, 0, lowbatt_info }, */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, NULL, 0, shutdownimm_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER18.EVER19", NULL, NULL, 0, overload_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER18.EVER20", NULL, NULL, 0, lowbatt_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER18.EVER21", NULL, NULL, 0, boost_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER18.EVER22", NULL, NULL, 0, trim_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER18.EVER25", NULL, NULL, 0, charging_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER18.EVER28", NULL, NULL, 0, replacebatt_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER32.EVER33", NULL, NULL, 0, overload_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER32.EVER40", NULL, "%.0f", 0, commfault_info },
{ "BOOL", 0, 0, "UPS.EVER1.EVER97.EVER102", NULL, "%s", 0, ever_on_off_info },
/* ever workmodes, messages & alarms */
{ "experimental.status.workmode", 0, 0, "UPS.EVER1.EVER97.EVER98", NULL, "%s", 0, ever_workmode },
{ "experimental.status.messages", 0, 0, "UPS.EVER1.EVER18.EVER28", NULL, NULL, 0, ever_messages },
{ "experimental.status.alarms", 0, 0, "UPS.EVER1.EVER32.EVER33", NULL, NULL, 0, ever_alarms },
/* instant commands */
/* experimental: With the same fields here, are the commands different?
* Per NUT command names, should be: documented load.off stays off, like
* shutdown.stayoff, but shutdown.return may return if wall power comes back!
* In many drivers, similar command with "-1" instead of DEFAULT_OFFDELAY
* serves as a shutdown.stop (to abort a pending shutdown).
*/
{ "load.off.delay", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL },
{ "shutdown.return", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, NULL, 0, NULL }
};
static const char *ever_format_model(HIDDevice_t *hd) {
return hd->Product;
}
static const char *ever_format_mfr(HIDDevice_t *hd) {
return hd->Vendor ? hd->Vendor : "Ever";
}
static const char *ever_format_serial(HIDDevice_t *hd) {
return hd->Serial;
}
/* this function allows the subdriver to "claim" a device: return 1 if the device is supported by this subdriver, else 0. */
static int ever_claim(HIDDevice_t *hd)
{
int status = is_usb_device_supported(ever_usb_device_table, hd);
switch (status)
{
case POSSIBLY_SUPPORTED:
/* by default, reject, unless the productid option is given */
if (getval("productid")) {
return 1;
}
possibly_supported("Ever", hd);
return 0;
case SUPPORTED:
return 1;
case NOT_SUPPORTED:
default:
return 0;
}
}
subdriver_t ever_subdriver = {
EVER_HID_VERSION,
ever_claim,
ever_utab,
ever_hid2nut,
ever_format_model,
ever_format_mfr,
ever_format_serial,
fix_report_desc,
};

32
drivers/ever-hid.h Normal file
View file

@ -0,0 +1,32 @@
/* everhid-hid.h - subdriver to monitor Everhid USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2009 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2017 EVER Power Systems [https://ever.eu/]
* 2020 - 2022 Jim Klimov <jimklimov+nut@gmail.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
*/
#ifndef EVER_HID_H
#define EVER_HID_H
#include "usbhid-ups.h"
extern subdriver_t ever_subdriver;
#endif /* EVER_HID_H */

View file

@ -1,4 +1,4 @@
/* everups.c - support for Ever UPS models
/* everups.c - support for Ever UPS models (serial)
Copyright (C) 2001 Bartek Szady <bszx@bszxdomain.edu.eu.org>
@ -20,8 +20,8 @@
#include "main.h"
#include "serial.h"
#define DRIVER_NAME "Ever UPS driver"
#define DRIVER_VERSION "0.03"
#define DRIVER_NAME "Ever UPS driver (serial)"
#define DRIVER_VERSION "0.04"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -64,9 +64,9 @@ static int InitUpsType(void)
static const char *GetTypeUpsName(void)
{
switch(upstype)
{
case 67: return "NET 500-DPC";
switch(upstype)
{
case 67: return "NET 500-DPC";
case 68: return "NET 700-DPC";
case 69: return "NET 1000-DPC";
case 70: return "NET 1400-DPC";
@ -95,7 +95,7 @@ void upsdrv_updateinfo(void)
unsigned long acuV;
unsigned long lineV;
double fVal;
if (!Code(2)) {
upslog_with_errno(LOG_INFO, "Code failed");
dstate_datastale();
@ -106,7 +106,7 @@ void upsdrv_updateinfo(void)
ser_get_char(upsfd, recBuf, 3, 0);
if ((recBuf[0] & 1) !=0)
standby=1;
else
else
battery=(recBuf[0] &4) !=0;
if (Code(1)) { /*Accumulator voltage value*/
ser_send_char(upsfd, 189);

View file

@ -25,7 +25,7 @@
#include "usbhid-ups.h"
#include "explore-hid.h"
#define EXPLORE_HID_VERSION "EXPLORE HID 0.1"
#define EXPLORE_HID_VERSION "EXPLORE HID 0.2"
static usage_tables_t explore_utab[] = {
hid_usage_lkp,
@ -57,11 +57,13 @@ static const char *explore_format_serial(HIDDevice_t *hd) {
/* this function allows the subdriver to "claim" a device: return 1 if
* the device is supported by this subdriver, else 0. */
static int explore_claim(HIDDevice_t *hd) {
if (testvar("explore")) {
return 1;
} else {
return 0;
}
NUT_UNUSED_VARIABLE(hd);
if (testvar("explore")) {
return 1;
} else {
return 0;
}
}
subdriver_t explore_subdriver = {
@ -72,4 +74,5 @@ subdriver_t explore_subdriver = {
explore_format_model,
explore_format_mfr,
explore_format_serial,
fix_report_desc,
};

View file

@ -2,7 +2,9 @@
*
* SEC UPS Driver ported to the new NUT API for Gamatronic UPS Usage.
*
* Copyright (C)
* TODO: Replace lots of printf() by upslogx() or upsdebugx() below!
*
* Copyright (C)
* 2001 John Marley <John.Marley@alcatel.com.au>
* 2002 Jules Taplin <jules@netsitepro.co.uk>
* 2002 Eric Lawson <elawson@inficad.com>
@ -24,13 +26,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "main.h"
#include "serial.h"
#include "serial.h"
#include "gamatronic.h"
#include "nut_stdint.h"
#define DRIVER_NAME "Gamatronic UPS driver"
#define DRIVER_VERSION "0.02"
#define DRIVER_VERSION "0.03"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -45,274 +48,279 @@ upsdrv_info_t upsdrv_info = {
{ NULL }
};
#define ENDCHAR '\r'
#define IGNCHARS ""
#define SER_WAIT_SEC 1 /* allow 3.0 sec for ser_get calls */
#define ENDCHAR '\r'
#define IGNCHARS ""
#define SER_WAIT_SEC 1 /* allow 3.0 sec for ser_get calls */
#define SER_WAIT_USEC 0
int sec_upsrecv (char *buf)
static int sec_upsrecv (char *buf)
{
char lenbuf[4];
int ret;
char lenbuf[4];
int ret;
ser_get_line(upsfd, buf, 140, ENDCHAR, IGNCHARS,SER_WAIT_SEC, SER_WAIT_USEC);
if (buf[0] == SEC_MSG_STARTCHAR){
switch (buf[1]){
case SEC_NAK:
return(-1);
case SEC_ACK:
return(0);
case SEC_DATAMSG:
strncpy(lenbuf,buf+2,3);
ret = atoi(lenbuf);
if (ret > 0){
strcpy(buf,buf+5);
return(ret);}
else return (-2);
default:
return(-2);
ser_get_line(upsfd, buf, 140, ENDCHAR, IGNCHARS,SER_WAIT_SEC, SER_WAIT_USEC);
if (buf[0] == SEC_MSG_STARTCHAR) {
switch (buf[1]) {
case SEC_NAK:
return(-1);
case SEC_ACK:
return(0);
case SEC_DATAMSG:
strncpy(lenbuf, buf+2, 3);
lenbuf[3] = '\0';
ret = atoi(lenbuf);
if (ret > 0) {
strcpy(buf,buf+5);
return(ret);
}
else return (-2);
default:
return(-2);
}
}
else
{ return (-2); }
}
else
return (-2);
}
int sec_cmd(const char mode, const char *command, char *msgbuf, int *buflen)
static ssize_t sec_cmd(const char mode, const char *command, char *msgbuf, ssize_t *buflen)
{
char msg[140];
int ret;
char msg[140];
ssize_t ret;
memset(msg, 0, sizeof(msg));
memset(msg, 0, sizeof(msg));
/* create the message string */
if (*buflen > 0) {
snprintf(msg, sizeof(msg), "%c%c%03d%s%s", SEC_MSG_STARTCHAR,
mode, (*buflen)+3, command, msgbuf);
}
else {
snprintf(msg, sizeof(msg), "%c%c003%s", SEC_MSG_STARTCHAR,
mode, command);
}
upsdebugx(1, "PC-->UPS: \"%s\"",msg);
ret = ser_send(upsfd, "%s", msg);
upsdebugx(1, " send returned: %d",ret);
/* create the message string */
if (*buflen > 0) {
snprintf(msg, sizeof(msg), "%c%c%03zd%s%s", SEC_MSG_STARTCHAR,
mode, (*buflen)+3, command, msgbuf);
}
else {
snprintf(msg, sizeof(msg), "%c%c003%s", SEC_MSG_STARTCHAR,
mode, command);
}
upsdebugx(1, "PC-->UPS: \"%s\"",msg);
ret = ser_send(upsfd, "%s", msg);
if (ret == -1) return -1;
upsdebugx(1, " send returned: %zd",ret);
ret = sec_upsrecv(msg);
if (ret == -1) return -1;
ret = sec_upsrecv(msg);
if (ret < 0) return -1;
if (ret < 0) return -1;
if (ret >= 0) {
strncpy(msgbuf, msg, ret);
strncpy(msgbuf, msg, (size_t)ret);
upsdebugx(1, "UPS<--PC: \"%s\"",msg);
}
/* *(msgbuf+ret) = '\0';*/
*buflen = ret;
return ret;
/*
*(msgbuf+ret) = '\0';
*/
*buflen = ret;
return ret;
}
void addquery(const char *cmd, int field, int varnum, int pollflag)
static void addquery(const char *cmd, int field, int varnum, int pollflag)
{
int q;
int q;
for (q=0; q<SEC_QUERYLIST_LEN; q++) {
if (sec_querylist[q].command == NULL) {
/* command has not been recorded yet */
sec_querylist[q].command = cmd;
sec_querylist[q].pollflag = pollflag;
upsdebugx(1, " Query %d is %s",q,cmd);
for (q=0; q<SEC_QUERYLIST_LEN; q++) {
if (sec_querylist[q].command == NULL) {
/* command has not been recorded yet */
sec_querylist[q].command = cmd;
sec_querylist[q].pollflag = pollflag;
upsdebugx(1, " Query %d is %s",q,cmd);
}
if (sec_querylist[q].command == cmd) {
sec_querylist[q].varnum[field-1] = varnum;
upsdebugx(1, " Querying varnum %d",varnum);
break;
}
}
if (sec_querylist[q].command == cmd) {
sec_querylist[q].varnum[field-1] = varnum;
upsdebugx(1, " Querying varnum %d",varnum);
break;
}
}
}
void sec_setinfo(int varnum, char *value)
{
if (*sec_varlist[varnum].setcmd){/*Not empty*/
static void sec_setinfo(int varnum, char *value)
{
if (*sec_varlist[varnum].setcmd)
{ /*Not empty*/
if (sec_varlist[varnum].flags == FLAG_STRING) {
dstate_setinfo(sec_varlist[varnum].setcmd,"%s", value);
}
else if (sec_varlist[varnum].unit == 1) {
dstate_setinfo(sec_varlist[varnum].setcmd,"%s", value);
}
else if (sec_varlist[varnum].flags == FLAG_MULTI) {
if (atoi(value) < 0) {
dstate_setinfo(sec_varlist[varnum].setcmd,"0");
if (atoi(value) < 0) {
dstate_setinfo(sec_varlist[varnum].setcmd,"0");
}
else
{dstate_setinfo(sec_varlist[varnum].setcmd,"%d", atoi(value) * sec_varlist[varnum].unit);
else {
dstate_setinfo(sec_varlist[varnum].setcmd,"%d", atoi(value) * sec_varlist[varnum].unit);
}
}
else {
dstate_setinfo(sec_varlist[varnum].setcmd,"%.1f", atof(value) / sec_varlist[varnum].unit);}
}
else {
dstate_setinfo(sec_varlist[varnum].setcmd,"%.1f", atof(value) / sec_varlist[varnum].unit);
}
}
}
void update_pseudovars( void )
static void update_pseudovars( void )
{
status_init();
if(strcmp(sec_varlist[9].value,"1")== 0) {
status_set("OFF");
status_set("OFF");
}
if(strcmp(sec_varlist[76].value,"0")== 0) {
status_set("OL");
status_set("OL");
}
if(strcmp(sec_varlist[76].value,"1")== 0) {
status_set("OB");
status_set("OB");
}
if(strcmp(sec_varlist[76].value,"2")== 0) {
status_set("BYPASS");
status_set("BYPASS");
}
if(strcmp(sec_varlist[76].value,"3")== 0) {
status_set("TRIM");
status_set("TRIM");
}
if(strcmp(sec_varlist[76].value,"4")== 0) {
status_set("BOOST");
status_set("BOOST");
}
if(strcmp(sec_varlist[10].value,"1")== 0) {
status_set("OVER");
status_set("OVER");
}
if(strcmp(sec_varlist[22].value,"1")== 0) {
status_set("LB");
status_set("LB");
}
if(strcmp(sec_varlist[19].value,"2")== 0) {
status_set("RB");
status_set("RB");
}
status_commit();
}
void sec_poll ( int pollflag ) {
int msglen,f,q;
char retbuf[140],*n,*r;
for (q=0; q<SEC_QUERYLIST_LEN; q++) {
if (sec_querylist[q].command == NULL) break;
if (sec_querylist[q].pollflag != pollflag) continue;
msglen = 0;
sec_cmd(SEC_POLLCMD, sec_querylist[q].command, retbuf, &msglen);
r = retbuf;
*(r+msglen) = '\0';
for (f=0; f<SEC_MAXFIELDS; f++) {
n = strchr(r, ',');
if (n != NULL) *n = '\0';
if (sqv(q,f) > 0) {
if (strcmp(sec_varlist[sqv(q,f)].value, r) != 0 ) {
static void sec_poll ( int pollflag ) {
ssize_t msglen;
int f, q;
char retbuf[140], *n, *r;
snprintf(sec_varlist[sqv(q,f)].value,
sizeof(sec_varlist[sqv(q,f)].value), "%s", r);
sec_setinfo(sqv(q,f), r);
for (q=0; q<SEC_QUERYLIST_LEN; q++) {
if (sec_querylist[q].command == NULL) break;
if (sec_querylist[q].pollflag != pollflag) continue;
msglen = 0;
sec_cmd(SEC_POLLCMD, sec_querylist[q].command, retbuf, &msglen);
r = retbuf;
*(r+msglen) = '\0';
for (f=0; f<SEC_MAXFIELDS; f++) {
n = strchr(r, ',');
if (n != NULL) *n = '\0';
if (sqv(q,f) > 0) {
if (strcmp(sec_varlist[sqv(q,f)].value, r) != 0) {
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic ignored "-Wformat-truncation"
#endif
/* NOTE: We intentionally limit the amount
* of characters picked from "r" buffer
* into respectively sized "*.value"
*/
int len = snprintf(sec_varlist[sqv(q,f)].value,
sizeof(sec_varlist[sqv(q,f)].value), "%s", r);
if (len < 0) {
upsdebugx(1, "%s: got an error while extracting value", __func__);
}
if ((intmax_t)len > (intmax_t)sizeof(sec_varlist[sqv(q,f)].value)
|| (intmax_t)strnlen(r, sizeof(retbuf)) > (intmax_t)sizeof(sec_varlist[sqv(q,f)].value)
) {
upsdebugx(1, "%s: value was truncated", __func__);
}
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_TRUNCATION
#pragma GCC diagnostic pop
#endif
sec_setinfo(sqv(q,f), r);
}
/* If SEC VAR is alarm and it's on, add it to the alarm property */
if (sec_varlist[sqv(q,f)].flags & FLAG_ALARM && strcmp(r,"1")== 0) {
alarm_set(sec_varlist[sqv(q,f)].name);
}
}
if (n == NULL) break;
r = n+1;
}
/* If SEC VAR is alarm and its on, add it to the alarm property */
if (sec_varlist[sqv(q,f)].flags & FLAG_ALARM && strcmp(r,"1")== 0) {
alarm_set(sec_varlist[sqv(q,f)].name); }
}
if (n == NULL) break;
r = n+1;
}
}
}
}
void upsdrv_initinfo(void)
{
int msglen, v;
char *a,*p,avail_list[300];
/* find out which variables/commands this UPS supports */
msglen = 0;
sec_cmd(SEC_POLLCMD, SEC_AVAILP1, avail_list, &msglen);
p = avail_list + msglen;
if (p != avail_list) *p++ = ',';
msglen = 0;
sec_cmd(SEC_POLLCMD, SEC_AVAILP2, p, &msglen);
*(p+msglen) = '\0';
if (strlen(avail_list) == 0){
fatalx(EXIT_FAILURE, "No available variables found!");}
a = avail_list;
while ((p = strtok(a, ",")) != NULL) {
a = NULL;
v = atoi(p);
/* don't bother adding a write-only variable */
if (sec_varlist[v].flags == FLAG_WONLY) continue;
addquery(sec_varlist[v].cmd, sec_varlist[v].field, v, sec_varlist[v].poll);
}
/* poll one time values */
sec_poll(FLAG_POLLONCE);
printf("UPS: %s %s\n", dstate_getinfo("ups.mfr"), dstate_getinfo("ups.model"));
ssize_t msglen;
int v;
char *a, *p, avail_list[300];
/* find out which variables/commands this UPS supports */
msglen = 0;
sec_cmd(SEC_POLLCMD, SEC_AVAILP1, avail_list, &msglen);
p = avail_list + msglen;
if (p != avail_list) *p++ = ',';
msglen = 0;
sec_cmd(SEC_POLLCMD, SEC_AVAILP2, p, &msglen);
*(p+msglen) = '\0';
if (strlen(avail_list) == 0) {
fatalx(EXIT_FAILURE, "No available variables found!");
}
a = avail_list;
while ((p = strtok(a, ",")) != NULL) {
a = NULL;
v = atoi(p);
/* don't bother adding a write-only variable */
if (sec_varlist[v].flags == FLAG_WONLY) continue;
addquery(sec_varlist[v].cmd, sec_varlist[v].field, v, sec_varlist[v].poll);
}
/* poll one time values */
sec_poll(FLAG_POLLONCE);
printf("UPS: %s %s\n", dstate_getinfo("ups.mfr"), dstate_getinfo("ups.model"));
}
void upsdrv_updateinfo(void)
{
alarm_init();
/* poll status values values */
sec_poll(FLAG_POLL);
alarm_commit();
update_pseudovars();
dstate_dataok();
}
void upsdrv_shutdown(void)
{
int msg_len;
ssize_t msglen;
char msgbuf[SMALLBUF];
msg_len = snprintf(msgbuf, sizeof(msgbuf), "-1");
sec_cmd(SEC_SETCMD, SEC_SHUTDOWN, msgbuf, &msg_len);
msglen = snprintf(msgbuf, sizeof(msgbuf), "-1");
sec_cmd(SEC_SETCMD, SEC_SHUTDOWN, msgbuf, &msglen);
msg_len = snprintf(msgbuf, sizeof(msgbuf), "1");
sec_cmd(SEC_SETCMD, SEC_AUTORESTART, msgbuf, &msg_len);
msglen = snprintf(msgbuf, sizeof(msgbuf), "1");
sec_cmd(SEC_SETCMD, SEC_AUTORESTART, msgbuf, &msglen);
msg_len = snprintf(msgbuf, sizeof(msgbuf), "2");
sec_cmd(SEC_SETCMD, SEC_SHUTTYPE,msgbuf, &msg_len);
msglen = snprintf(msgbuf, sizeof(msgbuf), "2");
sec_cmd(SEC_SETCMD, SEC_SHUTTYPE,msgbuf, &msglen);
msg_len = snprintf(msgbuf, sizeof(msgbuf), "5");
sec_cmd(SEC_SETCMD, SEC_SHUTDOWN, msgbuf, &msg_len);
msglen = snprintf(msgbuf, sizeof(msgbuf), "5");
sec_cmd(SEC_SETCMD, SEC_SHUTDOWN, msgbuf, &msglen);
}
/*
static int instcmd(const char *cmdname, const char *extra)
int instcmd(const char *cmdname, const char *extra)
{
if (!strcasecmp(cmdname, "test.battery.stop")) {
ser_send_buf(upsfd, ...);
@ -338,40 +346,39 @@ void upsdrv_makevartable(void)
/* addvar(VAR_VALUE, "foo", "Override foo setting"); */
}
void setup_serial(const char *port)
static void setup_serial(const char *port)
{
char temp[140];
int i,ret;
char temp[140];
int i;
ssize_t ret;
/* Detect the ups baudrate */
for (i=0; i<5; i++) {
ser_set_speed(upsfd, device_path,baud_rates[i].rate);
ret = ser_send(upsfd, "^P003MAN");
ret = sec_upsrecv(temp);
if (ret >= -1) break;
/* Detect the ups baudrate */
for (i=0; i<5; i++) {
ser_set_speed(upsfd, device_path, baud_rates[i].rate);
ret = ser_send(upsfd, "^P003MAN");
ret = sec_upsrecv(temp);
if (ret >= -1) break;
}
}
if (i == 5) {
printf("Can't talk to UPS on port %s!\n",port);
printf("Check the cabling and portname and try again\n");
printf("Please note that this driver only support UPS Models with SEC Protorol\n");
ser_close(upsfd, device_path);
exit (1);
}
printf("Connected to UPS on %s baudrate: %d\n",port, baud_rates[i].name);
if (i == 5) {
printf("Can't talk to UPS on port %s!\n",port);
printf("Check the cabling and portname and try again\n");
printf("Please note that this driver only support UPS Models with SEC Protocol\n");
ser_close(upsfd, device_path);
exit (1);
}
else
printf("Connected to UPS on %s baudrate: %zu\n",
port, baud_rates[i].name);
}
void upsdrv_initups(void)
{
upsfd = ser_open(device_path);
setup_serial(device_path);
upsfd = ser_open(device_path);
setup_serial(device_path);
/* upsfd = ser_open(device_path); */
/* ser_set_speed(upsfd, device_path, B1200); */
/* probe ups type */
/* to get variables and flags from the command line, use this:
@ -399,12 +406,10 @@ void upsdrv_initups(void)
/* the upsh handlers can't be done here, as they get initialized
* shortly after upsdrv_initups returns to main.
*/
}
void upsdrv_cleanup(void)
{
/* free(dynamic_mem); */
ser_close(upsfd, device_path);
ser_close(upsfd, device_path);
}

View file

@ -2,13 +2,13 @@
*
* SEC UPS Driver ported to the new NUT API for Gamatronic UPS Usage.
*
* Copyright (C)
* Copyright (C)
* 2001 John Marley <John.Marley@alcatel.com.au>
* 2002 Jules Taplin <jules@netsitepro.co.uk>
* 2002 Eric Lawson <elawson@inficad.com>
* 2005 Arnaud Quette <http://arnaud.quette.free.fr/contact.html>
* 2005 Nadav Moskovitch <blutz@walla.com / http://www.gamatronic.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
@ -24,7 +24,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef NUT_GAMATRONIC_H_SEEN
#define NUT_GAMATRONIC_H_SEEN 1
#define SEC_MSG_STARTCHAR '^'
#define SEC_POLLCMD 'P'
#define SEC_SETCMD 'S'
@ -63,10 +66,11 @@
#define FLAG_POLL 0 /* For commands that polled normaly */
#define FLAG_POLLONCE 1 /* For commands that only polled once */
/* Some baud rates for setup_serial() */
struct {
int rate;
int name;
static struct {
speed_t rate; /* Value like B19200 defined in termios.h; note: NOT the bitrate numerically */
size_t name; /* Actual rate... WHY is this "name" - number to print interactively? */
} baud_rates[] = {
{ B1200, 1200 },
{ B2400, 2400 },
@ -80,7 +84,7 @@ struct {
/* macro for checking whether a variable is supported */
struct {
typedef struct {
const char *setcmd; /* INFO_x define from shared.h */
const char *name; /* Human readable text (also in shared-tables.h) */
int unit; /* Variable should be divided by this */
@ -90,108 +94,110 @@ struct {
int poll; /* poll flag */
int flags; /* Flags for addinfo() */
char value[SEC_MAX_VARSIZE];
} sec_varlist[] = {
{ "", "", 0, "", 0, 0, 0, 0 },
/*setcmd name unit cmd field size poll flags */
{ "", "Awaiting Power ", 1, SEC_ALARMSTAT, 13, 2, 0, FLAG_ALARM},
{ "", "Bypass Bad ", 1, SEC_ALARMSTAT, 5, 2, 0, FLAG_ALARM},
{ "", "Charger Failure ", 1, SEC_ALARMSTAT, 8, 2, 0, FLAG_ALARM},
{ "", "Fan Failure ", 1, SEC_ALARMSTAT, 10, 2, 0, FLAG_ALARM},
{ "", "Fuse Failure ", 1, SEC_ALARMSTAT, 11, 2, 0, FLAG_ALARM},
{ "", "General Fault ", 1, SEC_ALARMSTAT, 12, 2, 0, FLAG_ALARM},
{ "", "Input Bad ", 1, SEC_ALARMSTAT, 2, 2, 0, FLAG_ALARM},
{ "", "Output Bad ", 1, SEC_ALARMSTAT, 3, 2, 0, FLAG_ALARM},
{ "", "Output Off ", 1, SEC_ALARMSTAT, 6, 2, 0, FLAG_ALARM},
{ "", "Overload ", 1, SEC_ALARMSTAT, 4, 2, 0, FLAG_ALARM},
{ "", "Shutdown Imminent ", 1, SEC_ALARMSTAT, 15, 2, 0, FLAG_ALARM},
{ "", "Shutdown Pending ", 1, SEC_ALARMSTAT, 14, 2, 0, FLAG_ALARM},
{ "", "System Off ", 1, SEC_ALARMSTAT, 9, 2, 0, FLAG_ALARM},
{ "", "Temperature ", 1, SEC_ALARMSTAT, 1, 2, 0, FLAG_ALARM},
{ "", "UPS Shutdown ", 1, SEC_ALARMSTAT, 7, 2, 0, FLAG_ALARM},
{ "", "Audible Alarm", 1, SEC_NOMINAL, 8, 4, FLAG_POLLONCE, FLAG_RW},
{ "", "Auto Restart", 1, SEC_AUTORESTART, 1, 2, FLAG_POLLONCE, FLAG_RW},
{ "", "Battery Charge", 1, SEC_BATTSTAT, 3, 4, 0, 0},
{ "", "Battery Condition", 1, SEC_BATTSTAT, 1, 3, 0, 0},
{ "battery.current", "Battery Current", 10, SEC_BATTSTAT, 8, 9999, 0, 0 },
{ "battery.date", "Battery Installed", 1, SEC_NOMINAL, 11, 8, FLAG_POLLONCE, FLAG_STRING},
{ "", "Battery Status", 1, SEC_BATTSTAT, 2, 3, 0, 0 },
{ "battery.temperature", "Battery Temperature", 1, SEC_BATTSTAT, 9, 99, 0, 0 },
{ "battery.voltage", "Battery Voltage", 10, SEC_BATTSTAT, 7, 9999, 0, 0 },
{ "", "Bypass Current 1", 10, SEC_BYPASSSTAT, 4, 9999, 0, 0 },
{ "", "Bypass Current 2", 10, SEC_BYPASSSTAT, 7, 9999, 0, 0 },
{ "", "Bypass Current 3", 10, SEC_BYPASSSTAT, 10, 9999, 0, 0 },
{ "", "Bypass Frequency", 10, SEC_BYPASSSTAT, 1, 999, 0, 0 },
{ "", "Bypass Num Lines", 1, SEC_BYPASSSTAT, 2, 9, 0, 0 },
{ "", "Bypass Power 1", 1, SEC_BYPASSSTAT, 5, 99999, 0, 0 },
{ "", "Bypass Power 2", 1, SEC_BYPASSSTAT, 8, 99999, 0, 0 },
{ "", "Bypass Power 3", 1, SEC_BYPASSSTAT, 11, 99999, 0, 0 },
{ "", "Bypass Voltage 1", 10, SEC_BYPASSSTAT, 3, 9999, 0, 0 },
{ "", "Bypass Voltage 2", 10, SEC_BYPASSSTAT, 6, 9999, 0, 0 },
{ "", "Bypass Voltage 3", 10, SEC_BYPASSSTAT, 9, 9999, 0, 0 },
{ "battery.charge", "Estimated Charge", 1, SEC_BATTSTAT, 6, 999, 0, 0 },
{ "battery.runtime.low", "Estimated Minutes", 60, SEC_BATTSTAT, 5, 999, 0, FLAG_MULTI },
{ "input.transfer.high", "High Volt Xfer Pt", 1, SEC_NOMINAL, 10, 999, FLAG_POLLONCE, FLAG_STRING},
{ "ups.id", "Identification", 1, SEC_UPSID, 1, 64, FLAG_POLLONCE, FLAG_STRING},
{ "", "Input Current 1", 10, SEC_INPUTSTAT, 5, 9999, 0, 0 },
{ "", "Input Current 2", 10, SEC_INPUTSTAT, 9, 9999, 0, 0 },
{ "", "Input Current 3", 10, SEC_INPUTSTAT, 13, 9999, 0, 0 },
{ "input.frequency", "Input Frequency 1", 10, SEC_INPUTSTAT, 3, 999, 0, 0 },
{ "", "Input Frequency 2", 10, SEC_INPUTSTAT, 7, 999, 0, 0 },
{ "", "Input Frequency 3", 10, SEC_INPUTSTAT, 11, 999, 0, 0 },
{ "", "Input Line Bads", 1, SEC_INPUTSTAT, 1, 999, 0, 0 },
{ "", "Input Num Lines", 1, SEC_INPUTSTAT, 2, 9, 0, 0 },
{ "", "Input Power 1", 1, SEC_INPUTSTAT, 6, 99999, 0, 0 },
{ "", "Input Power 2", 1, SEC_INPUTSTAT, 10, 99999, 0, 0 },
{ "", "Input Power 3", 1, SEC_INPUTSTAT, 14, 99999, 0, 0 },
{ "input.voltage", "Input Voltage 1", 10, SEC_INPUTSTAT, 4, 9999, 0, 0 },
{ "", "Input Voltage 2", 10, SEC_INPUTSTAT, 8, 9999, 0, 0 },
{ "", "Input Voltage 3", 10, SEC_INPUTSTAT, 12, 9999, 0, 0 },
{ "input.transfer.low", "Low Volt Xfer Pt", 1, SEC_NOMINAL, 9, 999, FLAG_POLLONCE, FLAG_STRING},
{ "ups.mfr", "Manufacturer", 1, SEC_MFR, 1, 32, FLAG_POLLONCE, FLAG_STRING},
{ "ups.model", "Model", 1, SEC_MOD, 1, 64, FLAG_POLLONCE, FLAG_STRING},
{ "", "Nominal Battery Life", 1, SEC_NOMINAL, 12, 99999, FLAG_POLLONCE, FLAG_STRING},
{ "", "Nominal Input Frequency", 10, SEC_NOMINAL, 2, 999, FLAG_POLLONCE, FLAG_RW},
{ "input.voltage.nominal", "Nominal Input Voltage", 1, SEC_NOMINAL, 1, 999, FLAG_POLLONCE, FLAG_STRING},
{ "", "Nominal Low Battery Time", 1, SEC_NOMINAL, 7, 99, FLAG_POLLONCE, FLAG_STRING},
{ "", "Nominal Output Frequency", 10, SEC_NOMINAL, 4, 999, FLAG_POLLONCE, FLAG_RW},
{ "", "Nominal Output Power", 1, SEC_NOMINAL, 6, 99999, FLAG_POLLONCE, FLAG_STRING},
{ "", "Nominal Output Voltage", 1, SEC_NOMINAL, 3, 999, FLAG_POLLONCE, FLAG_STRING},
{ "ups.power.nominal", "Nominal VA Rating", 1, SEC_NOMINAL, 5, 99999, FLAG_POLLONCE, FLAG_STRING},
{ "output.current", "Output Current 1", 10, SEC_OUTPUTSTAT, 5, 9999, 0, 0 },
{ "", "Output Current 2", 10, SEC_OUTPUTSTAT, 9, 9999, 0, 0 },
{ "", "Output Current 3", 10, SEC_OUTPUTSTAT, 13, 9999, 0, 0 },
{ "output.frequency", "Output Frequency", 10, SEC_OUTPUTSTAT, 2, 999, 0, 0 },
{ "ups.load", "Output Load 1", 1, SEC_OUTPUTSTAT, 7, 999, 0, 0 },
{ "", "Output Load 2", 1, SEC_OUTPUTSTAT, 11, 999, 0, 0 },
{ "", "Output Load 3", 1, SEC_OUTPUTSTAT, 15, 999, 0, 0 },
{ "", "Output Num Lines", 1, SEC_OUTPUTSTAT, 3, 9, 0, 0 },
{ "", "Output Power 1", 1, SEC_OUTPUTSTAT, 6, 99999, 0, 0 },
{ "", "Output Power 2", 1, SEC_OUTPUTSTAT, 10, 99999, 0, 0 },
{ "", "Output Power 3", 1, SEC_OUTPUTSTAT, 14, 99999, 0, 0 },
{ "", "Output Source", 1, SEC_OUTPUTSTAT, 1, 6, 0, 0},
{ "output.voltage", "Output Voltage 1", 10, SEC_OUTPUTSTAT, 4, 9999, 0, 0 },
{ "", "Output Voltage 2", 10, SEC_OUTPUTSTAT, 8, 9999, 0, 0 },
{ "", "Output Voltage 3", 10, SEC_OUTPUTSTAT, 12, 9999, 0, 0 },
{ "", "Reboot With Duration", 1, SEC_REBOOT, 1, 9999999, FLAG_POLLONCE, FLAG_WONLY},
{ "battery.runtime", "Seconds on Battery", 1, SEC_BATTSTAT, 4, 99999, 0, 0 },
{ "", "Shutdown Type", 1, SEC_SHUTTYPE, 1, 2, FLAG_POLLONCE, FLAG_RW},
{ "ups.delay.shutdown", "Shutdown After Delay", 1, SEC_STARTDELAY, 1, 9999999, FLAG_POLLONCE, FLAG_WONLY},
{ "ups.firmware", "Software Version", 1, SEC_VERSION, 1, 32, FLAG_POLLONCE, FLAG_STRING},
{ "", "Startup After Delay", 1, SEC_STARTDELAY, 1, 9999999, FLAG_POLLONCE, FLAG_WONLY},
{ "", "Test Results Detail", 1, SEC_TESTRESULT, 2, 64, FLAG_POLLONCE, FLAG_STRING},
{ "", "Test Results Summary", 1, SEC_TESTRESULT, 1, 6, FLAG_POLLONCE, 0},
{ "", "Test Type", 1, SEC_TEST, 1, 5, FLAG_POLLONCE, FLAG_WONLY},
{ "", "Baud Rate", 1, SEC_BAUDRATE, 1, 19200, FLAG_POLLONCE, FLAG_RW},
} sec_varlist_t;
static sec_varlist_t sec_varlist[] = {
{ "", "", 0, "", 0, 0, 0, 0, "" },
/*setcmd name unit cmd field size poll flags value */
{ "", "Awaiting Power ", 1, SEC_ALARMSTAT, 13, 2, 0, FLAG_ALARM, ""},
{ "", "Bypass Bad ", 1, SEC_ALARMSTAT, 5, 2, 0, FLAG_ALARM, ""},
{ "", "Charger Failure ", 1, SEC_ALARMSTAT, 8, 2, 0, FLAG_ALARM, ""},
{ "", "Fan Failure ", 1, SEC_ALARMSTAT, 10, 2, 0, FLAG_ALARM, ""},
{ "", "Fuse Failure ", 1, SEC_ALARMSTAT, 11, 2, 0, FLAG_ALARM, ""},
{ "", "General Fault ", 1, SEC_ALARMSTAT, 12, 2, 0, FLAG_ALARM, ""},
{ "", "Input Bad ", 1, SEC_ALARMSTAT, 2, 2, 0, FLAG_ALARM, ""},
{ "", "Output Bad ", 1, SEC_ALARMSTAT, 3, 2, 0, FLAG_ALARM, ""},
{ "", "Output Off ", 1, SEC_ALARMSTAT, 6, 2, 0, FLAG_ALARM, ""},
{ "", "Overload ", 1, SEC_ALARMSTAT, 4, 2, 0, FLAG_ALARM, ""},
{ "", "Shutdown Imminent ", 1, SEC_ALARMSTAT, 15, 2, 0, FLAG_ALARM, ""},
{ "", "Shutdown Pending ", 1, SEC_ALARMSTAT, 14, 2, 0, FLAG_ALARM, ""},
{ "", "System Off ", 1, SEC_ALARMSTAT, 9, 2, 0, FLAG_ALARM, ""},
{ "", "Temperature ", 1, SEC_ALARMSTAT, 1, 2, 0, FLAG_ALARM, ""},
{ "", "UPS Shutdown ", 1, SEC_ALARMSTAT, 7, 2, 0, FLAG_ALARM, ""},
{ "", "Audible Alarm", 1, SEC_NOMINAL, 8, 4, FLAG_POLLONCE, FLAG_RW, ""},
{ "", "Auto Restart", 1, SEC_AUTORESTART, 1, 2, FLAG_POLLONCE, FLAG_RW, ""},
{ "", "Battery Charge", 1, SEC_BATTSTAT, 3, 4, 0, 0, ""},
{ "", "Battery Condition", 1, SEC_BATTSTAT, 1, 3, 0, 0, ""},
{ "battery.current", "Battery Current", 10, SEC_BATTSTAT, 8, 9999, 0, 0, ""},
{ "battery.date", "Battery Installed", 1, SEC_NOMINAL, 11, 8, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Battery Status", 1, SEC_BATTSTAT, 2, 3, 0, 0, ""},
{ "battery.temperature", "Battery Temperature", 1, SEC_BATTSTAT, 9, 99, 0, 0, ""},
{ "battery.voltage", "Battery Voltage", 10, SEC_BATTSTAT, 7, 9999, 0, 0, ""},
{ "", "Bypass Current 1", 10, SEC_BYPASSSTAT, 4, 9999, 0, 0, ""},
{ "", "Bypass Current 2", 10, SEC_BYPASSSTAT, 7, 9999, 0, 0, ""},
{ "", "Bypass Current 3", 10, SEC_BYPASSSTAT, 10, 9999, 0, 0, ""},
{ "", "Bypass Frequency", 10, SEC_BYPASSSTAT, 1, 999, 0, 0, ""},
{ "", "Bypass Num Lines", 1, SEC_BYPASSSTAT, 2, 9, 0, 0, ""},
{ "", "Bypass Power 1", 1, SEC_BYPASSSTAT, 5, 99999, 0, 0, ""},
{ "", "Bypass Power 2", 1, SEC_BYPASSSTAT, 8, 99999, 0, 0, ""},
{ "", "Bypass Power 3", 1, SEC_BYPASSSTAT, 11, 99999, 0, 0, ""},
{ "", "Bypass Voltage 1", 10, SEC_BYPASSSTAT, 3, 9999, 0, 0, ""},
{ "", "Bypass Voltage 2", 10, SEC_BYPASSSTAT, 6, 9999, 0, 0, ""},
{ "", "Bypass Voltage 3", 10, SEC_BYPASSSTAT, 9, 9999, 0, 0, ""},
{ "battery.charge", "Estimated Charge", 1, SEC_BATTSTAT, 6, 999, 0, 0, ""},
{ "battery.runtime.low", "Estimated Minutes", 60, SEC_BATTSTAT, 5, 999, 0, FLAG_MULTI, ""},
{ "input.transfer.high", "High Volt Xfer Pt", 1, SEC_NOMINAL, 10, 999, FLAG_POLLONCE, FLAG_STRING, ""},
{ "ups.id", "Identification", 1, SEC_UPSID, 1, 64, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Input Current 1", 10, SEC_INPUTSTAT, 5, 9999, 0, 0, ""},
{ "", "Input Current 2", 10, SEC_INPUTSTAT, 9, 9999, 0, 0, ""},
{ "", "Input Current 3", 10, SEC_INPUTSTAT, 13, 9999, 0, 0, ""},
{ "input.frequency", "Input Frequency 1", 10, SEC_INPUTSTAT, 3, 999, 0, 0, ""},
{ "", "Input Frequency 2", 10, SEC_INPUTSTAT, 7, 999, 0, 0, ""},
{ "", "Input Frequency 3", 10, SEC_INPUTSTAT, 11, 999, 0, 0, ""},
{ "", "Input Line Bads", 1, SEC_INPUTSTAT, 1, 999, 0, 0, ""},
{ "", "Input Num Lines", 1, SEC_INPUTSTAT, 2, 9, 0, 0, ""},
{ "", "Input Power 1", 1, SEC_INPUTSTAT, 6, 99999, 0, 0, ""},
{ "", "Input Power 2", 1, SEC_INPUTSTAT, 10, 99999, 0, 0, ""},
{ "", "Input Power 3", 1, SEC_INPUTSTAT, 14, 99999, 0, 0, ""},
{ "input.voltage", "Input Voltage 1", 10, SEC_INPUTSTAT, 4, 9999, 0, 0, ""},
{ "", "Input Voltage 2", 10, SEC_INPUTSTAT, 8, 9999, 0, 0, ""},
{ "", "Input Voltage 3", 10, SEC_INPUTSTAT, 12, 9999, 0, 0, ""},
{ "input.transfer.low", "Low Volt Xfer Pt", 1, SEC_NOMINAL, 9, 999, FLAG_POLLONCE, FLAG_STRING, ""},
{ "ups.mfr", "Manufacturer", 1, SEC_MFR, 1, 32, FLAG_POLLONCE, FLAG_STRING, ""},
{ "ups.model", "Model", 1, SEC_MOD, 1, 64, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Nominal Battery Life", 1, SEC_NOMINAL, 12, 99999, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Nominal Input Frequency", 10, SEC_NOMINAL, 2, 999, FLAG_POLLONCE, FLAG_RW, ""},
{ "input.voltage.nominal", "Nominal Input Voltage", 1, SEC_NOMINAL, 1, 999, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Nominal Low Battery Time", 1, SEC_NOMINAL, 7, 99, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Nominal Output Frequency", 10, SEC_NOMINAL, 4, 999, FLAG_POLLONCE, FLAG_RW, ""},
{ "", "Nominal Output Power", 1, SEC_NOMINAL, 6, 99999, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Nominal Output Voltage", 1, SEC_NOMINAL, 3, 999, FLAG_POLLONCE, FLAG_STRING, ""},
{ "ups.power.nominal", "Nominal VA Rating", 1, SEC_NOMINAL, 5, 99999, FLAG_POLLONCE, FLAG_STRING, ""},
{ "output.current", "Output Current 1", 10, SEC_OUTPUTSTAT, 5, 9999, 0, 0, ""},
{ "", "Output Current 2", 10, SEC_OUTPUTSTAT, 9, 9999, 0, 0, ""},
{ "", "Output Current 3", 10, SEC_OUTPUTSTAT, 13, 9999, 0, 0, ""},
{ "output.frequency", "Output Frequency", 10, SEC_OUTPUTSTAT, 2, 999, 0, 0, ""},
{ "ups.load", "Output Load 1", 1, SEC_OUTPUTSTAT, 7, 999, 0, 0, ""},
{ "", "Output Load 2", 1, SEC_OUTPUTSTAT, 11, 999, 0, 0, ""},
{ "", "Output Load 3", 1, SEC_OUTPUTSTAT, 15, 999, 0, 0, ""},
{ "", "Output Num Lines", 1, SEC_OUTPUTSTAT, 3, 9, 0, 0, ""},
{ "", "Output Power 1", 1, SEC_OUTPUTSTAT, 6, 99999, 0, 0, ""},
{ "", "Output Power 2", 1, SEC_OUTPUTSTAT, 10, 99999, 0, 0, ""},
{ "", "Output Power 3", 1, SEC_OUTPUTSTAT, 14, 99999, 0, 0, ""},
{ "", "Output Source", 1, SEC_OUTPUTSTAT, 1, 6, 0, 0, ""},
{ "output.voltage", "Output Voltage 1", 10, SEC_OUTPUTSTAT, 4, 9999, 0, 0, ""},
{ "", "Output Voltage 2", 10, SEC_OUTPUTSTAT, 8, 9999, 0, 0, ""},
{ "", "Output Voltage 3", 10, SEC_OUTPUTSTAT, 12, 9999, 0, 0, ""},
{ "", "Reboot With Duration", 1, SEC_REBOOT, 1, 9999999, FLAG_POLLONCE, FLAG_WONLY, ""},
{ "battery.runtime", "Seconds on Battery", 1, SEC_BATTSTAT, 4, 99999, 0, 0, ""},
{ "", "Shutdown Type", 1, SEC_SHUTTYPE, 1, 2, FLAG_POLLONCE, FLAG_RW, ""},
{ "ups.delay.shutdown", "Shutdown After Delay", 1, SEC_STARTDELAY, 1, 9999999, FLAG_POLLONCE, FLAG_WONLY, ""},
{ "ups.firmware", "Software Version", 1, SEC_VERSION, 1, 32, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Startup After Delay", 1, SEC_STARTDELAY, 1, 9999999, FLAG_POLLONCE, FLAG_WONLY, ""},
{ "", "Test Results Detail", 1, SEC_TESTRESULT, 2, 64, FLAG_POLLONCE, FLAG_STRING, ""},
{ "", "Test Results Summary", 1, SEC_TESTRESULT, 1, 6, FLAG_POLLONCE, 0, ""},
{ "", "Test Type", 1, SEC_TEST, 1, 5, FLAG_POLLONCE, FLAG_WONLY, ""},
{ "", "Baud Rate", 1, SEC_BAUDRATE, 1, 19200, FLAG_POLLONCE, FLAG_RW, ""},
};
/* a type for the supported variables */
#define SEC_QUERYLIST_LEN 17
#define SEC_MAXFIELDS 16
#define SEC_POLL 1
#define SEC_POLLONCE 0
#define SEC_POLL 1
#define SEC_POLLONCE 0
struct {
static struct {
const char *command; /* sec command */
int varnum[SEC_MAXFIELDS]; /* sec variable number for each field */
int pollflag;
@ -199,3 +205,4 @@ struct {
#define sqv(a,b) sec_querylist[a].varnum[b]
#endif /* NUT_GAMATRONIC_H_SEEN */

1099
drivers/generic_modbus.c Normal file

File diff suppressed because it is too large Load diff

111
drivers/generic_modbus.h Normal file
View file

@ -0,0 +1,111 @@
/* generic_modbus.h - Driver for generic UPS connected via modbus RIO
*
* Copyright (C)
* 2021 Dimitris Economou <dimitris.s.economou@gmail.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
*
*/
#ifndef NUT_GENERIC_MODBUS_H
#define NUT_GENERIC_MODBUS_H
/* UPS device details */
#define DEVICE_MFR "UNKNOWN"
#define DEVICE_MODEL "unknown"
/* serial access parameters */
#define BAUD_RATE 9600
#define PARITY 'N'
#define DATA_BIT 8
#define STOP_BIT 1
/*
* modbus response and byte timeouts
* us: 1 - 999999
*/
#define MODRESP_TIMEOUT_s 0
#define MODRESP_TIMEOUT_us 200000
#define MODBYTE_TIMEOUT_s 0
#define MODBYTE_TIMEOUT_us 50000
/* modbus access parameters */
#define MODBUS_SLAVE_ID 5
/* shutdown repeat on error */
#define FSD_REPEAT_CNT 3
/* shutdown repeat interval in ms */
#define FSD_REPEAT_INTRV 1500
/* definition of register type */
enum regtype {
COIL = 0,
INPUT_B,
INPUT_R,
HOLDING
};
typedef enum regtype regtype_t;
/* UPS device state enum */
enum devstate {
OL_T = 0,
OB_T,
LB_T,
HB_T,
RB_T,
CHRG_T,
DISCHRG_T,
BYPASS_T,
CAL_T,
OFF_T,
OVER_T,
TRIM_T,
BOOST_T,
FSD_T
};
typedef enum devstate devstate_t;
/* UPS state signal attributes */
struct sigattr {
int addr; /* register address */
regtype_t type; /* register type */
int noro; /* 1: normally open contact 0: normally closed contact. */
/* noro is used to indicate the logical ON or OFF in regard
of the contact state. if noro is set to 1 then ON corresponds
to an open contact */
};
typedef struct sigattr sigattr_t;
#define NUMOF_SIG_STATES 14
#define NOTUSED -1
/* define the duration of the shutdown pulse */
#define SHTDOWN_PULSE_DURATION NOTUSED
/*
* associate PULS signals to NUT device states
*
* Ready contact <--> 1:HB, 0:CHRG
* Buffering contact <--> 1:OB, 0:OL
* Battery-low <--> 1:LB
* Replace Battery <--> 1:RB
* Inhibit buffering <--> 1:FSD
*/
#endif /* NUT_GENERIC_MODBUS_H */

View file

@ -17,14 +17,17 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h" /* must be first */
#include <sys/ioctl.h>
#include "main.h"
#include "serial.h"
#include "genericups.h"
#include "nut_stdint.h"
#define DRIVER_NAME "Generic contact-closure UPS driver"
#define DRIVER_VERSION "1.36"
#define DRIVER_VERSION "1.38"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -82,6 +85,11 @@ static void parse_output_signals(const char *value, int *line)
fatalx(EXIT_FAILURE, "Can't override output with DSR (not an output)");
}
if (strstr(value, "NULL") || strstr(value, "none")) {
upsdebugx(3, "%s: disable", __func__);
*line = 0;
}
if(*line == old_line) {
upslogx(LOG_NOTICE, "%s: output overrides specified, but no effective difference - check for typos?", __func__);
}
@ -155,6 +163,12 @@ static void parse_input_signals(const char *value, int *line, int *val)
fatalx(EXIT_FAILURE, "Can't override input with ST (not an input)");
}
if (strstr(value, "NULL") || strstr(value, "none")) {
*line = 0;
*val = 0;
upsdebugx(3, "%s: disable", __func__);
}
if((*line == old_line) && (*val == old_val)) {
upslogx(LOG_NOTICE, "%s: input overrides specified, but no effective difference - check for typos?", __func__);
}
@ -187,12 +201,22 @@ void upsdrv_initinfo(void)
parse_input_signals(v, &upstab[upstype].line_bl, &upstab[upstype].val_bl);
upsdebugx(2, "parse_input_signals: LB overridden with %s\n", v);
}
if ((v = getval("RB")) != NULL) {
parse_input_signals(v, &upstab[upstype].line_rb, &upstab[upstype].val_rb);
upsdebugx(2, "parse_input_signals: RB overridden with %s\n", v);
}
if ((v = getval("BYPASS")) != NULL) {
parse_input_signals(v, &upstab[upstype].line_bypass, &upstab[upstype].val_bypass);
upsdebugx(2, "parse_input_signals: BYPASS overridden with %s\n", v);
}
}
/* normal idle loop - keep up with the current state of the UPS */
void upsdrv_updateinfo(void)
{
int flags, ol, bl, ret;
int flags, ol, bl, rb, bypass, ret;
ret = ioctl(upsfd, TIOCMGET, &flags);
@ -203,8 +227,13 @@ void upsdrv_updateinfo(void)
return;
}
/* Always online when OL is disabled */
ol = ((flags & upstab[upstype].line_ol) == upstab[upstype].val_ol);
bl = ((flags & upstab[upstype].line_bl) == upstab[upstype].val_bl);
/* Always have the flags cleared when other status flags are disabled */
bl = upstab[upstype].line_bl != 0 && ((flags & upstab[upstype].line_bl) == upstab[upstype].val_bl);
rb = upstab[upstype].line_rb != 0 && ((flags & upstab[upstype].line_rb) == upstab[upstype].val_rb);
bypass = upstab[upstype].line_bypass != 0 && ((flags & upstab[upstype].line_bypass) == upstab[upstype].val_bypass);
status_init();
@ -218,9 +247,17 @@ void upsdrv_updateinfo(void)
status_set("OB"); /* on battery */
}
if (rb) {
status_set("RB"); /* replace battery */
}
if (bypass) {
status_set("BYPASS"); /* battery bypass */
}
status_commit();
upsdebugx(5, "ups.status: %s %s\n", ol ? "OL" : "OB", bl ? "BL" : "");
upsdebugx(5, "ups.status: %s %s %s %s\n", ol ? "OL" : "OB", bl ? "BL" : "", rb ? "RB" : "", bypass ? "BYPASS" : "");
ser_comm_good();
dstate_dataok();
@ -299,14 +336,37 @@ void upsdrv_shutdown(void)
}
if (getval("sdtime")) {
int sdtime;
long sdtime;
sdtime = strtol(getval("sdtime"), (char **) NULL, 10);
upslogx(LOG_INFO, "Holding shutdown signal for %d seconds...\n",
upslogx(LOG_INFO, "Holding shutdown signal for %ld seconds...\n",
sdtime);
sleep(sdtime);
if (sdtime > 0) {
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
/* Different platforms, different sizes, none fits all... */
if (sizeof(long) > sizeof(unsigned int) && sdtime < (long)UINT_MAX) {
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic pop
#endif
sleep((unsigned int)sdtime);
} else {
sleep(UINT_MAX);
}
}
}
}
@ -324,6 +384,8 @@ void upsdrv_makevartable(void)
addvar(VAR_VALUE, "CP", "Override cable power setting");
addvar(VAR_VALUE, "OL", "Override on line signal");
addvar(VAR_VALUE, "LB", "Override low battery signal");
addvar(VAR_VALUE, "RB", "Override replace battery signal");
addvar(VAR_VALUE, "BYPASS", "Override battery bypass signal");
addvar(VAR_VALUE, "SD", "Override shutdown setting");
addvar(VAR_VALUE, "sdtime", "Hold time for shutdown value (seconds)");
}
@ -342,7 +404,7 @@ void upsdrv_initups(void)
}
/* don't hang up on last close */
tio.c_cflag &= ~HUPCL;
tio.c_cflag &= ~((tcflag_t)HUPCL);
if (tcsetattr(upsfd, TCSANOW, &tio)) {
fatal_with_errno(EXIT_FAILURE, "tcsetattr");

View file

@ -17,13 +17,18 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
struct {
#ifndef NUT_GENERICUPS_H_SEEN
#define NUT_GENERICUPS_H_SEEN 1
static struct {
const char *mfr; /* value for INFO_MFR */
const char *model; /* value for INFO_MODEL */
const char *desc; /* used in -h listing */
int line_norm;
int line_ol, val_ol;
int line_bl, val_bl;
int line_rb, val_rb;
int line_bypass, val_bypass;
int line_sd;
} upstab[] =
{
@ -34,6 +39,8 @@ struct {
TIOCM_DTR | TIOCM_RTS, /* cable power: DTR + RTS */
TIOCM_CTS, 0, /* online: CTS off */
TIOCM_CD, TIOCM_CD, /* low battery: CD on */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_RTS /* shutdown: RTS */
},
@ -44,6 +51,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_RNG, 0, /* online: RNG off */
TIOCM_CD, TIOCM_CD, /* low battery: CD on */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_RTS /* shutdown: RTS */
},
@ -54,9 +63,11 @@ struct {
TIOCM_RTS, /* cable power: RTS */
TIOCM_CTS, 0, /* online: CTS off */
TIOCM_CD, TIOCM_CD, /* low battery: CD on */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_DTR|TIOCM_RTS /* shutdown: DTR + RTS */
},
/* Type 3 */
{ "PowerTech",
"Comp1000",
@ -64,6 +75,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, 0, /* online: CTS off */
TIOCM_CD, TIOCM_CD, /* low battery: CD on */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_DTR | TIOCM_RTS /* shutdown: DTR + RTS */
},
@ -74,6 +87,8 @@ struct {
TIOCM_RTS, /* cable power: RTS */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
0 /* shutdown: none */
},
@ -84,6 +99,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_DTR | TIOCM_RTS /* shutdown: DTR + RTS */
},
@ -94,16 +111,20 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_RTS /* shutdown: set RTS */
},
/* Type 7 */
{ "CyberPower",
"Power99",
"CyberPower Power99",
"CyberPower Power99",
TIOCM_RTS, /* cable power: RTS */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_DTR /* shutdown: set DTR */
},
@ -114,6 +135,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
-1 /* shutdown: unknown */
},
@ -124,6 +147,8 @@ struct {
0, /* cable power: none */
TIOCM_CD, 0, /* online: CD off */
TIOCM_CTS, TIOCM_CTS, /* low battery: CTS on */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_RTS /* shutdown: RTS */
},
@ -134,6 +159,8 @@ struct {
TIOCM_RTS, /* cable power: RTS */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_DTR /* shutdown: DTR */
},
@ -144,6 +171,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, 0, /* online: CTS off */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_ST /* shutdown: ST */
},
@ -154,9 +183,11 @@ struct {
TIOCM_RTS, /* cable power: RTS */
TIOCM_CTS, 0, /* online: CTS off */
TIOCM_CD, TIOCM_CD, /* low battery: CD on */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_DTR /* shutdown: raise DTR */
},
/* Type 13 */
{ "RPT",
"Repoteck",
@ -164,6 +195,8 @@ struct {
TIOCM_DTR | TIOCM_RTS, /* cable power: DTR + RTS */
TIOCM_CD, TIOCM_CD, /* On-line : DCD on */
TIOCM_CTS, 0, /* Battery low: CTS off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_ST /* shutdown: TX BREA */
},
@ -174,6 +207,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CD, TIOCM_CD, /* online: CD on */
TIOCM_CTS, 0, /* low battery: CTS off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_RTS /* shutdown: raise RTS */
},
@ -184,6 +219,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_ST /* shutdown: ST (break) */
},
@ -194,6 +231,8 @@ struct {
TIOCM_DTR | TIOCM_RTS, /* cable power: DTR + RTS */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
-1 /* shutdown: unknown */
},
@ -204,6 +243,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
-1 /* shutdown: unknown */
},
@ -214,6 +255,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, TIOCM_CD, /* low battery: CAR on */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
-1 /* shutdown: none */
},
@ -224,6 +267,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: DCD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_RTS /* shutdown: set RTS */
},
@ -235,6 +280,8 @@ struct {
TIOCM_DTR, /* cable power: DTR */
TIOCM_CTS, 0, /* online: CTS off */
TIOCM_CD, TIOCM_CD, /* low battery: CD on */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_ST /* shutdown: ST (break) */
},
@ -246,9 +293,11 @@ struct {
TIOCM_RTS, /* cable power: RTS */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_RTS | TIOCM_DTR /* shutdown: RTS+DTR */
},
/* Type 22 (duplicate from 7)*/
{ "Gamatronic Electronic Industries",
"Generic Alarm UPS",
@ -256,9 +305,23 @@ struct {
TIOCM_RTS, /* cable power: RTS */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
0, 0, /* replace battery: none */
0, 0, /* battery bypass: none */
TIOCM_DTR /* shutdown: DTR */
},
/* Type 23 */
{ "Generic",
"Generic FTTx Battery Backup",
"FTTx (Fiber to the x) battery backup with 4-wire telemetry interface",
TIOCM_RTS, /* cable power: RTS */
TIOCM_CTS, TIOCM_CTS, /* online: CTS on */
TIOCM_CD, 0, /* low battery: CD off */
TIOCM_RI, 0, /* replace battery: RI off */
TIOCM_DSR, 0, /* battery bypass: DSR off */
0 /* shutdown: none */
},
/* add any new entries directly above this line */
{ NULL,
@ -267,6 +330,10 @@ struct {
0,
0, 0,
0, 0,
0, 0,
0, 0,
0
}
};
#endif /* NUT_GENERICUPS_H_SEEN */

View file

@ -22,10 +22,11 @@
*
* -------------------------------------------------------------------------- */
#include "config.h" /* must be first */
#include <string.h>
#include <stdlib.h>
#include "config.h"
#include "hidparser.h"
#include "nut_stdint.h" /* for int8_t, int16_t, int32_t */
#include "common.h" /* for fatalx() */
@ -35,13 +36,16 @@ static const uint8_t ItemSize[4] = { 0, 1, 2, 4 };
/*
* HIDParser struct
* -------------------------------------------------------------------------- */
/* FIXME? Should this structure remain with reasonable fixed int types,
* or changed to align with libusb API version and usb_ctrl_* typedefs?
*/
typedef struct {
const unsigned char *ReportDesc; /* Report Descriptor */
int ReportDescSize; /* Size of Report Descriptor */
size_t ReportDescSize; /* Size of Report Descriptor */
uint16_t Pos; /* Store current pos in descriptor */
uint8_t Item; /* Store current Item */
long Value; /* Store current Value */
uint32_t Value; /* Store current Value */
HIDData_t Data; /* Store current environment */
@ -56,7 +60,7 @@ typedef struct {
/* return 1 + the position of the leftmost "1" bit of an int, or 0 if
none. */
static inline unsigned int hibit(unsigned int x)
static inline unsigned int hibit(unsigned long x)
{
unsigned int res = 0;
@ -91,7 +95,7 @@ static void ResetLocalState(HIDParser_t* pParser)
/*
* GetReportOffset
*
* Return pointer on current offset value for Report designed by
* Return pointer on current offset value for Report designed by
* ReportID/ReportType
* -------------------------------------------------------------------------- */
static uint8_t *GetReportOffset(HIDParser_t* pParser, const uint8_t ReportID, const uint8_t ReportType)
@ -121,10 +125,10 @@ static uint8_t *GetReportOffset(HIDParser_t* pParser, const uint8_t ReportID, co
}
/*
* FormatValue(long Value, uint8_t Size)
* FormatValue(uint32_t Value, uint8_t Size)
* Format Value to fit with long format with respect of negative values
* -------------------------------------------------------------------------- */
static long FormatValue(long Value, uint8_t Size)
static long FormatValue(uint32_t Value, uint8_t Size)
{
switch(Size)
{
@ -135,7 +139,7 @@ static long FormatValue(long Value, uint8_t Size)
case 4:
return (long)(int32_t)Value;
default:
return Value;
return (long)Value;
}
}
@ -143,34 +147,23 @@ static long FormatValue(long Value, uint8_t Size)
* HIDParse(HIDParser_t* pParser, HIDData_t *pData)
*
* Analyse Report descriptor stored in HIDParser struct and store local and
* global context.
* global context.
* Return in pData the last object found.
* Return -1 when there is no other Item to parse, 1 if a new object was found
* or 0 if a continuation of a previous object was found.
* -------------------------------------------------------------------------- */
static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
{
int Found = -1;
int Found = -1, i;
while ((Found < 0) && (pParser->Pos < pParser->ReportDescSize)) {
/* Get new pParser->Item if current pParser->Count is empty */
if (pParser->Count == 0) {
pParser->Item = pParser->ReportDesc[pParser->Pos++];
pParser->Value = 0;
#if WORDS_BIGENDIAN
{
int i;
unsigned long valTmp = 0;
for (i = 0; i < ItemSize[pParser->Item & SIZE_MASK]; i++) {
memcpy(&valTmp, &pParser->ReportDesc[(pParser->Pos)+i], 1);
pParser->Value += valTmp >> ((3-i)*8);
valTmp = 0;
}
for (i = 0; i < ItemSize[pParser->Item & SIZE_MASK]; i++) {
pParser->Value += (uint32_t)(pParser->ReportDesc[(pParser->Pos)+i]) << (8*i);
}
#else
memcpy(&pParser->Value, &pParser->ReportDesc[pParser->Pos], ItemSize[pParser->Item & SIZE_MASK]);
#endif
/* Pos on next item */
pParser->Pos += ItemSize[pParser->Item & SIZE_MASK];
}
@ -187,7 +180,7 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
if ((pParser->Item & SIZE_MASK) > 2) {
pParser->UsageTab[pParser->UsageSize] = pParser->Value;
} else {
pParser->UsageTab[pParser->UsageSize] = (pParser->UPage << 16) | (pParser->Value & 0xFFFF);
pParser->UsageTab[pParser->UsageSize] = ((HIDNode_t)(pParser->UPage) << 16) | (pParser->Value & 0xFFFF);
}
/* Increment Usage stack size */
@ -201,10 +194,10 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
/* Unstack UPage/Usage from UsageTab (never remove the last) */
if (pParser->UsageSize > 0) {
int i;
for (i = 0; i < pParser->UsageSize; i++) {
pParser->UsageTab[i] = pParser->UsageTab[i+1];
int j;
for (j = 0; j < pParser->UsageSize; j++) {
pParser->UsageTab[j] = pParser->UsageTab[j+1];
}
/* Remove Usage */
@ -222,15 +215,15 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
case ITEM_END_COLLECTION :
pParser->Data.Path.Size--;
/* Remove Index if any */
if((pParser->Data.Path.Node[pParser->Data.Path.Size] & 0xffff0000) == 0x00ff0000) {
pParser->Data.Path.Size--;
}
ResetLocalState(pParser);
break;
case ITEM_FEATURE:
case ITEM_INPUT:
case ITEM_OUTPUT:
@ -241,7 +234,7 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
/* It is a continuation of a previous object */
Found = 0;
}
/* Get new pParser->Count from global value */
if(pParser->Count == 0) {
pParser->Count = pParser->ReportCount;
@ -250,87 +243,109 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
/* Get UPage/Usage from UsageTab and store them in pParser->Data.Path */
pParser->Data.Path.Node[pParser->Data.Path.Size] = pParser->UsageTab[0];
pParser->Data.Path.Size++;
/* Unstack UPage/Usage from UsageTab (never remove the last) */
if(pParser->UsageSize > 0) {
int i;
for (i = 0; i < pParser->UsageSize; i++) {
pParser->UsageTab[i] = pParser->UsageTab[i+1];
int j;
for (j = 0; j < pParser->UsageSize; j++) {
pParser->UsageTab[j] = pParser->UsageTab[j+1];
}
/* Remove Usage */
pParser->UsageSize--;
}
/* Copy data type */
pParser->Data.Type = (uint8_t)(pParser->Item & ITEM_MASK);
/* Copy data attribute */
pParser->Data.Attribute = (uint8_t)pParser->Value;
/* Store offset */
pParser->Data.Offset = *GetReportOffset(pParser, pParser->Data.ReportID, (uint8_t)(pParser->Item & ITEM_MASK));
/* Get Object in pData */
/* -------------------------------------------------------------------------- */
memcpy(pData, &pParser->Data, sizeof(HIDData_t));
/* -------------------------------------------------------------------------- */
/* Increment Report Offset */
*GetReportOffset(pParser, pParser->Data.ReportID, (uint8_t)(pParser->Item & ITEM_MASK)) += pParser->Data.Size;
/* Remove path last node */
pParser->Data.Path.Size--;
/* Decrement count */
pParser->Count--;
if (pParser->Count == 0) {
ResetLocalState(pParser);
}
break;
case ITEM_REP_ID :
pParser->Data.ReportID = (uint8_t)pParser->Value;
break;
case ITEM_REP_SIZE :
pParser->Data.Size = (uint8_t)pParser->Value;
break;
case ITEM_REP_COUNT :
pParser->ReportCount = (uint8_t)pParser->Value;
break;
case ITEM_UNIT_EXP :
pParser->Data.UnitExp = (int8_t)pParser->Value;
if (pParser->Data.UnitExp > 7) {
pParser->Data.UnitExp |= 0xF0;
}
break;
case ITEM_UNIT :
pParser->Data.Unit = pParser->Value;
/* TOTHINK: Are there cases where Unit is not-signed,
* but a Value too big becomes signed after casting --
* and unintentionally so? */
pParser->Data.Unit = (long)pParser->Value;
break;
case ITEM_LOG_MIN :
pParser->Data.LogMin = FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
break;
case ITEM_LOG_MAX :
pParser->Data.LogMax = FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
/* HACK: If treating the value as signed (FormatValue(...)) results in a LogMax that is
* less than the LogMin value then it is likely that the LogMax value has been
* incorrectly encoded by the UPS firmware (field too short and overflowed into sign
* bit). In that case, reinterpret it as an unsigned number and log the problem.
* This hack is not correct in the sense that it only looks at the LogMin value for
* this item, whereas the HID spec says that Logical values persist in global state.
*/
if (pParser->Data.LogMax < pParser->Data.LogMin) {
upslogx(LOG_WARNING,
"%s: LogMax is less than LogMin. "
"Vendor HID report descriptor may be incorrect; "
"interpreting LogMax %ld as %u in ReportID: 0x%02x",
__func__,
pParser->Data.LogMax,
pParser->Value,
pParser->Data.ReportID);
pParser->Data.LogMax = (long) pParser->Value;
}
break;
case ITEM_PHY_MIN :
pParser->Data.PhyMin=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
pParser->Data.have_PhyMin = 1;
break;
case ITEM_PHY_MAX :
pParser->Data.PhyMax=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
pParser->Data.have_PhyMax = 1;
break;
case ITEM_LONG :
/* can't handle long items, but should at least skip them */
pParser->Pos += (uint8_t)(pParser->Value & 0xff);
@ -344,8 +359,13 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
upslogx(LOG_ERR, "%s: Report descriptor too big", __func__);
if(pParser->UsageSize >= USAGE_TAB_SIZE)
upslogx(LOG_ERR, "%s: HID Usage too high", __func__);
/* FIXME: comparison is always false due to limited range of data type [-Werror=type-limits]
* with ReportID beint uint8_t and MAX_REPORT being 500 currently */
/*
if(pParser->Data.ReportID >= MAX_REPORT)
upslogx(LOG_ERR, "%s: Too many HID reports", __func__);
*/
return Found;
}
@ -355,14 +375,14 @@ static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
* Get pData characteristics from pData->Path
* Return TRUE if object was found
* -------------------------------------------------------------------------- */
int FindObject(HIDDesc_t *pDesc, HIDData_t *pData)
int FindObject(HIDDesc_t *pDesc_arg, HIDData_t *pData)
{
HIDData_t *pFoundData = FindObject_with_Path(pDesc, &pData->Path, pData->Type);
HIDData_t *pFoundData = FindObject_with_Path(pDesc_arg, &pData->Path, pData->Type);
if (!pFoundData) {
return 0;
}
memcpy(pData, pFoundData, sizeof(*pData));
return 1;
}
@ -371,24 +391,24 @@ int FindObject(HIDDesc_t *pDesc, HIDData_t *pData)
* FindObject_with_Path
* Get pData item with given Path and Type. Return NULL if not found.
* -------------------------------------------------------------------------- */
HIDData_t *FindObject_with_Path(HIDDesc_t *pDesc, HIDPath_t *Path, uint8_t Type)
HIDData_t *FindObject_with_Path(HIDDesc_t *pDesc_arg, HIDPath_t *Path, uint8_t Type)
{
int i;
size_t i;
for (i = 0; i < pDesc_arg->nitems; i++) {
HIDData_t *pData = &pDesc_arg->item[i];
for (i = 0; i < pDesc->nitems; i++) {
HIDData_t *pData = &pDesc->item[i];
if (pData->Type != Type) {
continue;
}
if (memcmp(pData->Path.Node, Path->Node, (Path->Size) * sizeof(HIDNode_t))) {
continue;
}
return pData;
}
return NULL;
}
@ -397,50 +417,85 @@ HIDData_t *FindObject_with_Path(HIDDesc_t *pDesc, HIDPath_t *Path, uint8_t Type)
* Get pData item with given ReportID, Offset, and Type. Return NULL
* if not found.
* -------------------------------------------------------------------------- */
HIDData_t *FindObject_with_ID(HIDDesc_t *pDesc, uint8_t ReportID, uint8_t Offset, uint8_t Type)
HIDData_t *FindObject_with_ID(HIDDesc_t *pDesc_arg, uint8_t ReportID, uint8_t Offset, uint8_t Type)
{
int i;
size_t i;
for (i = 0; i < pDesc_arg->nitems; i++) {
HIDData_t *pData = &pDesc_arg->item[i];
for (i = 0; i < pDesc->nitems; i++) {
HIDData_t *pData = &pDesc->item[i];
if (pData->ReportID != ReportID) {
continue;
}
if (pData->Type != Type) {
continue;
}
if (pData->Offset != Offset) {
continue;
}
return pData;
}
return NULL;
}
/*
* FindObject_with_ID_Node
* Get pData item with given ReportID and Node. Return NULL if not found.
* -------------------------------------------------------------------------- */
HIDData_t *FindObject_with_ID_Node(HIDDesc_t *pDesc_arg, uint8_t ReportID, HIDNode_t Node)
{
size_t i;
for (i = 0; i < pDesc_arg->nitems; i++) {
HIDData_t *pData = &pDesc_arg->item[i];
if (pData->ReportID != ReportID) {
continue;
}
HIDPath_t * pPath = &pData->Path;
uint8_t size = pPath->Size;
if (size == 0 || pPath->Node[size-1] != Node) {
continue;
}
return pData;
}
return NULL;
}
/*
* GetValue
* Extract data from a report stored in Buf.
* Use Value, Offset, Size and LogMax of pData.
* Return response in Value.
* Use Offset, Size, LogMin, and LogMax of pData.
* Return response in *pValue.
* -------------------------------------------------------------------------- */
void GetValue(const unsigned char *Buf, HIDData_t *pData, long *pValue)
{
/* Note: https://github.com/networkupstools/nut/issues/1023
This conversion code can easily be sensitive to 32- vs 64- bit
compilation environments. Consider the possibility of overflow
in 32-bit representations when computing with extreme values,
for example LogMax-LogMin+1.
Test carefully in both environments if changing any declarations.
*/
int Weight, Bit;
long value = 0, rawvalue;
long range, mask, signbit, b, m;
unsigned long mask, signbit, magMax, magMin;
long value = 0;
Bit = pData->Offset + 8; /* First byte of report is report ID */
for (Weight = 0; Weight < pData->Size; Weight++, Bit++) {
int State = Buf[Bit >> 3] & (1 << (Bit & 7));
if(State) {
value += (1 << Weight);
value += (1L << Weight);
}
}
@ -466,49 +521,25 @@ void GetValue(const unsigned char *Buf, HIDData_t *pData, long *pValue)
"throwing away higher-order bits" exacly means, so we try to do
something sensible. -PS */
rawvalue = value; /* remember this for later */
/* determine representation without sign bit */
magMax = pData->LogMax >= 0 ? (unsigned long)(pData->LogMax) : (unsigned long)(-(pData->LogMax + 1));
magMin = pData->LogMin >= 0 ? (unsigned long)(pData->LogMin) : (unsigned long)(-(pData->LogMin + 1));
/* figure out how many bits are significant */
range = pData->LogMax - pData->LogMin + 1;
if (range <= 0) {
/* makes no sense, give up */
*pValue = value;
return;
}
b = hibit(range-1);
/* calculate where the sign bit will be if needed */
signbit = 1L << hibit(magMax > magMin ? magMax : magMin);
/* throw away insignificant bits; the result is >= 0 */
mask = (1 << b) - 1;
signbit = 1 << (b - 1);
value = value & mask;
/* but only include sign bit in mask if negative numbers are involved */
mask = (signbit - 1) | ((pData->LogMin < 0) ? signbit : 0);
/* throw away excess high order bits (which may contain garbage) */
value = (long)((unsigned long)(value) & mask);
/* sign-extend it, if appropriate */
if (pData->LogMin < 0 && (value & signbit) != 0) {
if (pData->LogMin < 0 && ((unsigned long)(value) & signbit) != 0) {
value |= ~mask;
}
/* if the resulting value is in the desired range, stop */
if (value >= pData->LogMin && value <= pData->LogMax) {
*pValue = value;
return;
}
/* else, try to reach interval by adjusting high-order bits */
m = (value - pData->LogMin) & mask;
value = pData->LogMin + m;
if (value <= pData->LogMax) {
*pValue = value;
return;
}
/* if everything else failed, sign-extend the original raw value,
and simply round it to the closest point in the interval. */
value = rawvalue;
mask = (1 << pData->Size) - 1;
signbit = 1 << (pData->Size - 1);
if (pData->LogMin < 0 && (value & signbit) != 0) {
value |= ~mask;
}
/* clamp returned value to range [LogMin..LogMax] */
if (value < pData->LogMin) {
value = pData->LogMin;
} else if (value > pData->LogMax) {
@ -527,11 +558,11 @@ void GetValue(const unsigned char *Buf, HIDData_t *pData, long *pValue)
void SetValue(const HIDData_t *pData, unsigned char *Buf, long Value)
{
int Weight, Bit;
Bit = pData->Offset + 8; /* First byte of report is report ID */
for (Weight = 0; Weight < pData->Size; Weight++, Bit++) {
int State = Value & (1 << Weight);
long State = Value & (1L << Weight);
if (State) {
Buf[Bit >> 3] |= (1 << (Bit & 7));
@ -547,78 +578,109 @@ void SetValue(const HIDData_t *pData, unsigned char *Buf, long Value)
Output: parsed data structure. Returns allocated HIDDesc structure
on success, NULL on failure with errno set. Note: the value
returned by this function must be freed with Free_ReportDesc(). */
HIDDesc_t *Parse_ReportDesc(const unsigned char *ReportDesc, const int n)
HIDDesc_t *Parse_ReportDesc(const usb_ctrl_charbuf ReportDesc, const usb_ctrl_charbufsize n)
{
int ret;
HIDDesc_t *pDesc;
int ret = 0;
HIDDesc_t *pDesc_var;
HIDParser_t *parser;
pDesc = calloc(1, sizeof(*pDesc));
if (!pDesc) {
pDesc_var = calloc(1, sizeof(*pDesc_var));
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE
# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#pragma clang diagnostic ignored "-Wtautological-compare"
#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
if (!pDesc_var
|| n < 0 || (uintmax_t)n > SIZE_MAX
) {
return NULL;
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
# pragma GCC diagnostic pop
#endif
pDesc->item = calloc(MAX_REPORT, sizeof(*pDesc->item));
if (!pDesc->item) {
Free_ReportDesc(pDesc);
pDesc_var->item = calloc(MAX_REPORT, sizeof(*pDesc_var->item));
if (!pDesc_var->item) {
Free_ReportDesc(pDesc_var);
return NULL;
}
parser = calloc(1, sizeof(*parser));
if (!parser) {
Free_ReportDesc(pDesc);
Free_ReportDesc(pDesc_var);
return NULL;
}
parser->ReportDesc = ReportDesc;
parser->ReportDescSize = n;
parser->ReportDesc = (const unsigned char *)ReportDesc;
parser->ReportDescSize = (const size_t)n;
for (pDesc->nitems = 0; pDesc->nitems < MAX_REPORT; pDesc->nitems += ret) {
int id, max;
for (pDesc_var->nitems = 0; pDesc_var->nitems < MAX_REPORT; pDesc_var->nitems += (size_t)ret) {
uint8_t id;
size_t max;
ret = HIDParse(parser, &pDesc->item[pDesc->nitems]);
ret = HIDParse(parser, &pDesc_var->item[pDesc_var->nitems]);
if (ret < 0) {
break;
}
id = pDesc->item[pDesc->nitems].ReportID;
id = pDesc_var->item[pDesc_var->nitems].ReportID;
/* calculate bit range of this item within report */
max = pDesc->item[pDesc->nitems].Offset + pDesc->item[pDesc->nitems].Size;
max = pDesc_var->item[pDesc_var->nitems].Offset + pDesc_var->item[pDesc_var->nitems].Size;
/* convert to bytes */
max = (max + 7) >> 3;
/* update report length */
if (max > pDesc->replen[id]) {
pDesc->replen[id] = max;
if (max > pDesc_var->replen[id]) {
pDesc_var->replen[id] = max;
}
}
/* Sanity check: are there remaining HID objects that can't
* be processed? */
if ((pDesc->nitems == MAX_REPORT) && (parser->Pos < parser->ReportDescSize))
if ((pDesc_var->nitems == MAX_REPORT) && (parser->Pos < parser->ReportDescSize))
upslogx(LOG_ERR, "ERROR in %s: Too many HID objects", __func__);
free(parser);
if (pDesc->nitems == 0) {
Free_ReportDesc(pDesc);
if (pDesc_var->nitems == 0) {
Free_ReportDesc(pDesc_var);
return NULL;
}
pDesc->item = realloc(pDesc->item, pDesc->nitems * sizeof(*pDesc->item));
pDesc_var->item = realloc(pDesc_var->item, pDesc_var->nitems * sizeof(*pDesc_var->item));
return pDesc;
return pDesc_var;
}
/* free a parsed report descriptor, as allocated by Parse_ReportDesc() */
void Free_ReportDesc(HIDDesc_t *pDesc)
void Free_ReportDesc(HIDDesc_t *pDesc_arg)
{
if (!pDesc) {
if (!pDesc_arg) {
return;
}
free(pDesc->item);
free(pDesc);
free(pDesc_arg->item);
free(pDesc_arg);
}

View file

@ -22,8 +22,8 @@
*
* -------------------------------------------------------------------------- */
#ifndef HIDPARS_H
#define HIDPARS_H
#ifndef NUT_HID_PARSER_H_SEEN
#define NUT_HID_PARSER_H_SEEN
#ifdef __cplusplus
@ -32,27 +32,38 @@ extern "C" {
/* *INDENT-ON* */
#endif /* __cplusplus */
#include "config.h"
#include "hidtypes.h"
/* Include "usb-common.h" or "libshut.h" as appropriate, to define the
* usb_ctrl_* types used below according to the backend USB API version
*/
#ifdef SHUT_MODE
# include "libshut.h"
#else
# include "usb-common.h"
#endif
/*
* Parse_ReportDesc
* -------------------------------------------------------------------------- */
HIDDesc_t *Parse_ReportDesc(const unsigned char *ReportDesc, const int n);
HIDDesc_t *Parse_ReportDesc(const usb_ctrl_charbuf ReportDesc, const usb_ctrl_charbufsize n);
/*
* Free_ReportDesc
* -------------------------------------------------------------------------- */
void Free_ReportDesc(HIDDesc_t *pDesc);
void Free_ReportDesc(HIDDesc_t *pDesc_arg);
/*
* FindObject
* -------------------------------------------------------------------------- */
int FindObject(HIDDesc_t *pDesc, HIDData_t *pData);
int FindObject(HIDDesc_t *pDesc_arg, HIDData_t *pData);
HIDData_t *FindObject_with_Path(HIDDesc_t *pDesc, HIDPath_t *Path, uint8_t Type);
HIDData_t *FindObject_with_Path(HIDDesc_t *pDesc_arg, HIDPath_t *Path, uint8_t Type);
HIDData_t *FindObject_with_ID(HIDDesc_t *pDesc, uint8_t ReportID, uint8_t Offset, uint8_t Type);
HIDData_t *FindObject_with_ID(HIDDesc_t *pDesc_arg, uint8_t ReportID, uint8_t Offset, uint8_t Type);
HIDData_t *FindObject_with_ID_Node(HIDDesc_t *pDesc_arg, uint8_t ReportID, HIDNode_t Node);
/*
* GetValue
* -------------------------------------------------------------------------- */
@ -70,4 +81,4 @@ void SetValue(const HIDData_t *pData, unsigned char *Buf, long Value);
/* *INDENT-ON* */
#endif /* __cplusplus */
#endif
#endif /* NUT_HID_PARSER_H_SEEN */

View file

@ -91,6 +91,186 @@ extern "C" {
#define ATTR_DATA_CST 0x01
#define ATTR_NVOL_VOL 0x80
/* Usage Pages */
/* For more details, please see docs/hid-subdrivers.txt */
#define PAGE_POWER_DEVICE 0x84
#define PAGE_BATTERY_SYSTEM 0x85
/* Usage within Power Device page */
#define USAGE_POW_UNDEFINED 0x00840000
#define USAGE_POW_I_NAME 0x00840001
#define USAGE_POW_PRESENT_STATUS 0x00840002
#define USAGE_POW_CHANGED_STATUS 0x00840003
#define USAGE_POW_UPS 0x00840004
#define USAGE_POW_POWER_SUPPLY 0x00840005
#define USAGE_POW_PERIPHERAL_DEVICE 0x00840006
#define USAGE_POW_BATTERY_SYSTEM 0x00840010
#define USAGE_POW_BATTERY_SYSTEM_ID 0x00840011
#define USAGE_POW_BATTERY 0x00840012
#define USAGE_POW_BATTERY_ID 0x00840013
#define USAGE_POW_CHARGER 0x00840014
#define USAGE_POW_CHARGER_ID 0x00840015
#define USAGE_POW_POWER_CONVERTER 0x00840016
#define USAGE_POW_POWER_CONVERTER_ID 0x00840017
#define USAGE_POW_OUTLET_SYSTEM 0x00840018
#define USAGE_POW_OUTLET_SYSTEM_ID 0x00840019
#define USAGE_POW_INPUT 0x0084001A
#define USAGE_POW_INPUT_ID 0x0084001B
#define USAGE_POW_OUTPUT 0x0084001C
#define USAGE_POW_OUTPUT_ID 0x0084001D
#define USAGE_POW_FLOW 0x0084001E
#define USAGE_POW_FLOW_ID 0x0084001F
#define USAGE_POW_OUTLET 0x00840020
#define USAGE_POW_OUTLET_ID 0x00840021
#define USAGE_POW_GANG 0x00840022
#define USAGE_POW_GANG_ID 0x00840023
#define USAGE_POW_POWER_SUMMARY 0x00840024
#define USAGE_POW_POWER_SUMMARY_ID 0x00840025
#define USAGE_POW_VOLTAGE 0x00840030
#define USAGE_POW_CURRENT 0x00840031
#define USAGE_POW_FREQUENCY 0x00840032
#define USAGE_POW_APPARENT_POWER 0x00840033
#define USAGE_POW_ACTIVE_POWER 0x00840034
#define USAGE_POW_PERCENT_LOAD 0x00840035
#define USAGE_POW_TEMPERATURE 0x00840036
#define USAGE_POW_HUMIDITY 0x00840037
#define USAGE_POW_BAD_COUNT 0x00840038
#define USAGE_POW_CONFIG_VOLTAGE 0x00840040
#define USAGE_POW_CONFIG_CURRENT 0x00840041
#define USAGE_POW_CONFIG_FREQUENCY 0x00840042
#define USAGE_POW_CONFIG_APPARENT_POWER 0x00840043
#define USAGE_POW_CONFIG_ACTIVE_POWER 0x00840044
#define USAGE_POW_CONFIG_PERCENT_LOAD 0x00840045
#define USAGE_POW_CONFIG_TEMPERATURE 0x00840046
#define USAGE_POW_CONFIG_HUMIDITY 0x00840047
#define USAGE_POW_SWITCH_ON_CONTROL 0x00840050
#define USAGE_POW_SWITCH_OFF_CONTROL 0x00840051
#define USAGE_POW_TOGGLE_CONTROL 0x00840052
#define USAGE_POW_LOW_VOLTAGE_TRANSFER 0x00840053
#define USAGE_POW_HIGH_VOLTAGE_TRANSFER 0x00840054
#define USAGE_POW_DELAY_BEFORE_REBOOT 0x00840055
#define USAGE_POW_DELAY_BEFORE_STARTUP 0x00840056
#define USAGE_POW_DELAY_BEFORE_SHUTDOWN 0x00840057
#define USAGE_POW_TEST 0x00840058
#define USAGE_POW_MODULE_RESET 0x00840059
#define USAGE_POW_AUDIBLE_ALARM_CONTROL 0x0084005A
#define USAGE_POW_PRESENT 0x00840060
#define USAGE_POW_GOOD 0x00840061
#define USAGE_POW_INTERNAL_FAILURE 0x00840062
#define USAGE_POW_VOLTAGE_OUT_OF_RANGE 0x00840063
#define USAGE_POW_FREQUENCY_OUT_OF_RANGE 0x00840064
#define USAGE_POW_OVERLOAD 0x00840065
#define USAGE_POW_OVER_CHARGED 0x00840066
#define USAGE_POW_OVER_TEMPERATURE 0x00840067
#define USAGE_POW_SHUTDOWN_REQUESTED 0x00840068
#define USAGE_POW_SHUTDOWN_IMMINENT 0x00840069
#define USAGE_POW_SWITCH_ON_OFF 0x0084006B
#define USAGE_POW_SWITCHABLE 0x0084006C
#define USAGE_POW_USED 0x0084006D
#define USAGE_POW_BOOST 0x0084006E
#define USAGE_POW_BUCK 0x0084006F
#define USAGE_POW_INITIALIZED 0x00840070
#define USAGE_POW_TESTED 0x00840071
#define USAGE_POW_AWAITING_POWER 0x00840072
#define USAGE_POW_COMMUNICATION_LOST 0x00840073
#define USAGE_POW_I_MANUFACTURER 0x008400FD
#define USAGE_POW_I_PRODUCT 0x008400FE
#define USAGE_POW_I_SERIAL_NUMBER 0x008400FF
/* Usage within Battery System page */
#define USAGE_BAT_UNDEFINED 0x00850000
#define USAGE_BAT_SMB_BATTERY_MODE 0x00850001
#define USAGE_BAT_SMB_BATTERY_STATUS 0x00850002
#define USAGE_BAT_SMB_ALARM_WARNING 0x00850003
#define USAGE_BAT_SMB_CHARGER_MODE 0x00850004
#define USAGE_BAT_SMB_CHARGER_STATUS 0x00850005
#define USAGE_BAT_SMB_CHARGER_SPEC_INFO 0x00850006
#define USAGE_BAT_SMB_SELECTOR_STATE 0x00850007
#define USAGE_BAT_SMB_SELECTOR_PRESETS 0x00850008
#define USAGE_BAT_SMB_SELECTOR_INFO 0x00850009
#define USAGE_BAT_OPTIONAL_MFG_FUNCTION_1 0x00850010
#define USAGE_BAT_OPTIONAL_MFG_FUNCTION_2 0x00850011
#define USAGE_BAT_OPTIONAL_MFG_FUNCTION_3 0x00850012
#define USAGE_BAT_OPTIONAL_MFG_FUNCTION_4 0x00850013
#define USAGE_BAT_OPTIONAL_MFG_FUNCTION_5 0x00850014
#define USAGE_BAT_CONNECTION_TO_SMBUS 0x00850015
#define USAGE_BAT_OUTPUT_CONNECTION 0x00850016
#define USAGE_BAT_CHARGER_CONNECTION 0x00850017
#define USAGE_BAT_BATTERY_INSERTION 0x00850018
#define USAGE_BAT_USE_NEXT 0x00850019
#define USAGE_BAT_OK_TO_USE 0x0085001A
#define USAGE_BAT_BATTERY_SUPPORTED 0x0085001B
#define USAGE_BAT_SELECTOR_REVISION 0x0085001C
#define USAGE_BAT_CHARGING_INDICATOR 0x0085001D
#define USAGE_BAT_MANUFACTURER_ACCESS 0x00850028
#define USAGE_BAT_REMAINING_CAPACITY_LIMIT 0x00850029
#define USAGE_BAT_REMAINING_TIME_LIMIT 0x0085002A
#define USAGE_BAT_AT_RATE 0x0085002B
#define USAGE_BAT_CAPACITY_MODE 0x0085002C
#define USAGE_BAT_BROADCAST_TO_CHARGER 0x0085002D
#define USAGE_BAT_PRIMARY_BATTERY 0x0085002E
#define USAGE_BAT_CHARGE_CONTROLLER 0x0085002F
#define USAGE_BAT_TERMINATE_CHARGE 0x00850040
#define USAGE_BAT_TERMINATE_DISCHARGE 0x00850041
#define USAGE_BAT_BELOW_REMAINING_CAPACITY_LIMIT 0x00850042
#define USAGE_BAT_REMAINING_TIME_LIMIT_EXPIRED 0x00850043
#define USAGE_BAT_CHARGING 0x00850044
#define USAGE_BAT_DISCHARGING 0x00850045
#define USAGE_BAT_FULLY_CHARGED 0x00850046
#define USAGE_BAT_FULLY_DISCHARGED 0x00850047
#define USAGE_BAT_CONDITIONING_FLAG 0x00850048
#define USAGE_BAT_AT_RATE_OK 0x00850049
#define USAGE_BAT_SMB_ERROR_CODE 0x0085004A
#define USAGE_BAT_NEED_REPLACEMENT 0x0085004B
#define USAGE_BAT_AT_RATE_TIME_TO_FULL 0x00850060
#define USAGE_BAT_AT_RATE_TIME_TO_EMPTY 0x00850061
#define USAGE_BAT_AVERAGE_CURRENT 0x00850062
#define USAGE_BAT_MAX_ERROR 0x00850063
#define USAGE_BAT_RELATIVE_STATE_OF_CHARGE 0x00850064
#define USAGE_BAT_ABSOLUTE_STATE_OF_CHARGE 0x00850065
#define USAGE_BAT_REMAINING_CAPACITY 0x00850066
#define USAGE_BAT_FULL_CHARGE_CAPACITY 0x00850067
#define USAGE_BAT_RUN_TIME_TO_EMPTY 0x00850068
#define USAGE_BAT_AVERAGE_TIME_TO_EMPTY 0x00850069
#define USAGE_BAT_AVERAGE_TIME_TO_FULL 0x0085006A
#define USAGE_BAT_CYCLE_COUNT 0x0085006B
#define USAGE_BAT_BATT_PACK_MODEL_LEVEL 0x00850080
#define USAGE_BAT_INTERNAL_CHARGE_CONTROLLER 0x00850081
#define USAGE_BAT_PRIMARY_BATTERY_SUPPORT 0x00850082
#define USAGE_BAT_DESIGN_CAPACITY 0x00850083
#define USAGE_BAT_SPECIFICATION_INFO 0x00850084
#define USAGE_BAT_MANUFACTURER_DATE 0x00850085
#define USAGE_BAT_SERIAL_NUMBER 0x00850086
#define USAGE_BAT_I_MANUFACTURER_NAME 0x00850087
#define USAGE_BAT_I_DEVICE_NAME 0x00850088
#define USAGE_BAT_I_DEVICE_CHEMISTRY 0x00850089
#define USAGE_BAT_MANUFACTURER_DATA 0x0085008A
#define USAGE_BAT_RECHARGEABLE 0x0085008B
#define USAGE_BAT_WARNING_CAPACITY_LIMIT 0x0085008C
#define USAGE_BAT_CAPACITY_GRANULARITY_1 0x0085008D
#define USAGE_BAT_CAPACITY_GRANULARITY_2 0x0085008E
#define USAGE_BAT_I_OEMINFORMATION 0x0085008F
#define USAGE_BAT_INHIBIT_CHARGE 0x008500C0
#define USAGE_BAT_ENABLE_POLLING 0x008500C1
#define USAGE_BAT_RESET_TO_ZERO 0x008500C2
#define USAGE_BAT_AC_PRESENT 0x008500D0
#define USAGE_BAT_BATTERY_PRESENT 0x008500D1
#define USAGE_BAT_POWER_FAIL 0x008500D2
#define USAGE_BAT_ALARM_INHIBITED 0x008500D3
#define USAGE_BAT_THERMISTOR_UNDER_RANGE 0x008500D4
#define USAGE_BAT_THERMISTOR_HOT 0x008500D5
#define USAGE_BAT_THERMISTOR_COLD 0x008500D6
#define USAGE_BAT_THERMISTOR_OVER_RANGE 0x008500D7
#define USAGE_BAT_VOLTAGE_OUT_OF_RANGE 0x008500D8
#define USAGE_BAT_CURRENT_OUT_OF_RANGE 0x008500D9
#define USAGE_BAT_CURRENT_NOT_REGULATED 0x008500DA
#define USAGE_BAT_VOLTAGE_NOT_REGULATED 0x008500DB
#define USAGE_BAT_MASTER_MODE 0x008500DC
#define USAGE_BAT_CHARGER_SELECTOR_SUPPORT 0x008500F0
#define USAGE_BAT_CHARGER_SPEC 0x008500F1
#define USAGE_BAT_LEVEL_2 0x008500F2
#define USAGE_BAT_LEVEL_3 0x008500F3
/*
* HIDNode_t struct
*
@ -111,7 +291,7 @@ typedef struct {
/*
* HIDData struct
*
* Describe a HID Data with its location in report
* Describe a HID Data with its location in report
* -------------------------------------------------------------------------- */
typedef struct {
HIDPath_t Path; /* HID Path */
@ -140,9 +320,9 @@ typedef struct {
* Holds a parsed report descriptor
* -------------------------------------------------------------------------- */
typedef struct {
int nitems; /* number of items in descriptor */
size_t nitems; /* number of items in descriptor */
HIDData_t *item; /* list of items */
int replen[256]; /* list of report lengths, in byte */
size_t replen[256]; /* list of report lengths, in byte */
} HIDDesc_t;
#ifdef __cplusplus

899
drivers/hpe-pdu-mib.c Normal file
View file

@ -0,0 +1,899 @@
/* hpe-pdu-mib.c - subdriver to monitor HPE ePDU SNMP devices with NUT
*
* Copyright (C)
* 2011 - 2016 Arnaud Quette <arnaud.quette@free.fr>
* 2019 Arnaud Quette <ArnaudQuette@eaton.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
*
*/
#include "hpe-pdu-mib.h"
#include "dstate.h"
#define HPE_EPDU_MIB_VERSION "0.33"
#define HPE_EPDU_MIB_SYSOID ".1.3.6.1.4.1.232.165.7"
#define HPE_EPDU_OID_MODEL_NAME ".1.3.6.1.4.1.232.165.7.1.2.1.3.0"
static info_lkp_t hpe_pdu_outlet_status_info[] = {
{ 1, "off", NULL, NULL },
{ 2, "on", NULL, NULL },
{ 3, "pendingOff", NULL, NULL }, /* transitional status */
{ 4, "pendingOn", NULL, NULL }, /* transitional status */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_outletgroups_status_info[] = {
{ 1, "N/A", NULL, NULL }, /* notApplicable, if group.type == outlet-section */
{ 2, "on", NULL, NULL }, /* breakerOn */
{ 3, "off", NULL, NULL }, /* breakerOff */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_outlet_switchability_info[] = {
{ 1, "yes", NULL, NULL },
{ 2, "no", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* The physical type of outlet */
static info_lkp_t hpe_pdu_outlet_type_info[] = {
{ 0, "unknown", NULL, NULL },
{ 1, "iecC13", NULL, NULL },
{ 2, "iecC19", NULL, NULL },
{ 10, "uk", NULL, NULL },
{ 11, "french", NULL, NULL },
{ 12, "schuko", NULL, NULL },
{ 20, "nema515", NULL, NULL },
{ 21, "nema51520", NULL, NULL },
{ 22, "nema520", NULL, NULL },
{ 23, "nemaL520", NULL, NULL },
{ 24, "nemaL530", NULL, NULL },
{ 25, "nema615", NULL, NULL },
{ 26, "nema620", NULL, NULL },
{ 27, "nemaL620", NULL, NULL },
{ 28, "nemaL630", NULL, NULL },
{ 29, "nemaL715", NULL, NULL },
{ 30, "rf203p277", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_ambient_presence_info[] = {
{ -1, "unknown", NULL, NULL },
{ 1, "no", NULL, NULL }, /* disconnected */
{ 2, "yes", NULL, NULL }, /* connected */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_threshold_status_info[] = {
{ 1, "good", NULL, NULL }, /* No threshold triggered */
{ 2, "warning-low", NULL, NULL }, /* Warning low threshold triggered */
{ 3, "critical-low", NULL, NULL }, /* Critical low threshold triggered */
{ 4, "warning-high", NULL, NULL }, /* Warning high threshold triggered */
{ 5, "critical-high", NULL, NULL }, /* Critical high threshold triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_threshold_frequency_status_info[] = {
{ 1, "good", NULL, NULL }, /* No threshold triggered */
{ 2, "out-of-range", NULL, NULL }, /* Frequency out of range triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_ambient_drycontacts_info[] = {
{ -1, "unknown", NULL, NULL },
{ 0, "unknown", NULL, NULL },
{ 1, "open", NULL, NULL },
{ 2, "closed", NULL, NULL },
{ 3, "bad", NULL, NULL }, /* FIXME: what to do with that? */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_threshold_voltage_alarms_info[] = {
{ 1, "", NULL, NULL }, /* No threshold triggered */
{ 2, "low voltage warning!", NULL, NULL }, /* Warning low threshold triggered */
{ 3, "low voltage critical!", NULL, NULL }, /* Critical low threshold triggered */
{ 4, "high voltage warning!", NULL, NULL }, /* Warning high threshold triggered */
{ 5, "high voltage critical!", NULL, NULL }, /* Critical high threshold triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_threshold_current_alarms_info[] = {
{ 1, "", NULL, NULL }, /* No threshold triggered */
{ 2, "low current warning!", NULL, NULL }, /* Warning low threshold triggered */
{ 3, "low current critical!", NULL, NULL }, /* Critical low threshold triggered */
{ 4, "high current warning!", NULL, NULL }, /* Warning high threshold triggered */
{ 5, "high current critical!", NULL, NULL }, /* Critical high threshold triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_threshold_frequency_alarm_info[] = {
{ 1, "", NULL, NULL }, /* No threshold triggered */
{ 2, "frequency out of range!", NULL, NULL }, /* Frequency out of range triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_threshold_temperature_alarms_info[] = {
{ 1, "", NULL, NULL }, /* No threshold triggered */
{ 2, "low temperature warning!", NULL, NULL }, /* Warning low threshold triggered */
{ 3, "low temperature critical!", NULL, NULL }, /* Critical low threshold triggered */
{ 4, "high temperature warning!", NULL, NULL }, /* Warning high threshold triggered */
{ 5, "high temperature critical!", NULL, NULL }, /* Critical high threshold triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_threshold_humidity_alarms_info[] = {
{ 1, "", NULL, NULL }, /* No threshold triggered */
{ 2, "low humidity warning!", NULL, NULL }, /* Warning low threshold triggered */
{ 3, "low humidity critical!", NULL, NULL }, /* Critical low threshold triggered */
{ 4, "high humidity warning!", NULL, NULL }, /* Warning high threshold triggered */
{ 5, "high humidity critical!", NULL, NULL }, /* Critical high threshold triggered */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_outlet_group_type_info[] = {
{ 0, "unknown", NULL, NULL },
{ 1, "unknown", NULL, NULL },
{ 2, "breaker1pole", NULL, NULL },
{ 3, "breaker2pole", NULL, NULL },
{ 4, "breaker3pole", NULL, NULL },
{ 5, "outlet-section", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_input_type_info[] = {
{ 1, "1", NULL, NULL }, /* singlePhase */
{ 2, "2", NULL, NULL }, /* splitPhase */
{ 3, "3", NULL, NULL }, /* threePhaseDelta */
{ 4, "3", NULL, NULL }, /* threePhaseWye */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t hpe_pdu_outlet_group_phase_info[] = {
{ 1, "L1", NULL, NULL }, /* singlePhase */
{ 2, "L1", NULL, NULL }, /* phase1toN */
{ 3, "L2", NULL, NULL }, /* phase2toN */
{ 4, "L3", NULL, NULL }, /* phase3toN */
{ 5, "L1", NULL, NULL }, /* phase1to2 */
{ 6, "L2", NULL, NULL }, /* phase2to3 */
{ 7, "L3", NULL, NULL }, /* phase3to1 */
{ 0, NULL, NULL, NULL }
};
/* Snmp2NUT lookup table for HPE PDU MIB */
static snmp_info_t hpe_pdu_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* Device collection */
{ "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "HPE",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* pdu2Model.0 = STRING: "HP 8.6kVA 208V 30A 3Ph NA/JP maPDU" */
{ "device.model", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.1.2.1.3.%i",
"HPE ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* pdu2SerialNumber.0 = STRING: "CN94230105" */
{ "device.serial", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.1.2.1.7.%i",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* pdu2PartNumber.0 = STRING: "H8B52A" */
{ "device.part", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.1.2.1.6.%i",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* For daisychain, there is only 1 physical interface! */
{ "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.2.2.1.6.2",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* Daisychained devices support
* Notes: this definition is used to:
* - estimate the number of devices, based on the below OID iteration capabilities
* - determine the base index of the SNMP OID (ie 0 or 1) */
/* pdu2NumberPDU.0 = INTEGER: 1 */
{ "device.count", 0, 1,
".1.3.6.1.4.1.232.165.7.1.1.0",
"1", SU_FLAG_STATIC, NULL },
/* UPS collection */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "HPE",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.1.2.1.3.%i",
"HPE ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* FIXME: use unitName.0 (ePDU)?
* { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_DEVICE_NAME,
"unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, */
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.1.2.1.7.%i",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* FIXME: this entry should be SU_FLAG_SEMI_STATIC */
/* pdu2FirmwareVersion.0 = STRING: "02.00.0043" */
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.1.2.1.5.%i",
"", SU_FLAG_OK, NULL },
{ "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* FIXME: needs a date reformating callback
* 2011-8-29,16:27:25.0,+1:0
* Hex-STRING: 07 DB 08 1D 10 0C 36 00 2B 01 00 00
* { "ups.date", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.1.2.1.8.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
* { "ups.time", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.1.2.1.8.0",
"", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
*/
/* Input collection */
/* Note: for daisychain mode, we must handle phase(s) per device, not as a whole */
/* pdu2InputType.0 = INTEGER: threePhaseWye(4) */
{ "input.phases", 0, 1, ".1.3.6.1.4.1.232.165.7.2.1.1.1.%i",
NULL, SU_FLAG_STATIC, &hpe_pdu_input_type_info[0] },
/* Frequency is measured globally */
/* pdu2InputFrequency.0 = INTEGER: 500 */
{ "input.frequency", 0, 0.1, ".1.3.6.1.4.1.232.165.7.2.1.1.2.%i",
NULL, 0, NULL },
/* pdu2InputFrequencyStatus.0 = INTEGER: good(1) */
{ "input.frequency.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.1.1.3.%i",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_frequency_status_info[0] },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.1.1.3.%i",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_frequency_alarm_info[0] },
/* inputCurrentPercentLoad (measured globally)
* Current percent load, based on the rated current capacity */
/* FIXME: input.load is mapped on input.L1.load for both single and 3phase !!! */
{ "input.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.%i.1.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2InputPhaseCurrentPercentLoad.0.1 = INTEGER: 0 */
{ "input.L1.load", 0, 1.0, ".1.3.6.1.4.1.232.165.7.2.2.1.18.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2InputPhaseCurrentPercentLoad.0.2 = INTEGER: 0 */
{ "input.L1.load", 0, 1.0, ".1.3.6.1.4.1.232.165.7.2.2.1.18.%i.2",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2InputPhaseCurrentPercentLoad.0.3 = INTEGER: 0 */
{ "input.L1.load", 0, 1.0, ".1.3.6.1.4.1.232.165.7.2.2.1.18.%i.3",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* FIXME:
* - Voltage is only measured per phase, as mV!
* so input.voltage == input.L1.voltage for both single and 3phase
* - As per NUT namespace (http://www.networkupstools.org/docs/developer-guide.chunked/apas01.html#_valid_contexts)
* Voltage has to be expressed either phase-phase or phase-neutral
* This is depending on OID inputVoltageMeasType
* INTEGER {singlePhase (1),phase1toN (2),phase2toN (3),phase3toN (4),phase1to2 (5),phase2to3 (6),phase3to1 (7)
* => RFC input.Lx.voltage.context */
/* pdu2InputPhaseVoltage.0.1 = INTEGER: 216790 */
{ "input.voltage", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.2.1.3.%i.1",
NULL, 0, NULL },
/* pdu2InputPhaseVoltageThStatus.0.1 = INTEGER: good(1) */
{ "input.voltage.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_voltage_alarms_info[0] },
/* pdu2InputPhaseVoltageThLowerWarning.0.1 = INTEGER: 190000 */
{ "input.voltage.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.5.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThLowerCritical.0.1 = INTEGER: 180000 */
{ "input.voltage.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.6.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThUpperWarning.0.1 = INTEGER: 255000 */
{ "input.voltage.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.7.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThUpperCritical.0.1 = INTEGER: 265000 */
{ "input.voltage.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.8.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltage.0.1 = INTEGER: 216790 */
{ "input.L1.voltage", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.2.1.3.%i.1",
NULL, 0, NULL },
/* pdu2InputPhaseVoltageThStatus.0.1 = INTEGER: good(1) */
{ "input.L1.voltage.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "L1.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_voltage_alarms_info[0] },
/* pdu2InputPhaseVoltageThLowerWarning.0.1 = INTEGER: 190000 */
{ "input.L1.voltage.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.5.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThLowerCritical.0.1 = INTEGER: 180000 */
{ "input.L1.voltage.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.6.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThUpperWarning.0.1 = INTEGER: 255000 */
{ "input.L1.voltage.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.7.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThUpperCritical.0.1 = INTEGER: 265000 */
{ "input.L1.voltage.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.8.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltage.0.2 = INTEGER: 216790 */
{ "input.L2.voltage", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.2.1.3.%i.2",
NULL, 0, NULL },
/* pdu2InputPhaseVoltageThStatus.0.2 = INTEGER: good(1) */
{ "input.L2.voltage.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.2",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.2",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_voltage_alarms_info[0] },
/* pdu2InputPhaseVoltageThLowerWarning.0.2 = INTEGER: 190000 */
{ "input.L2.voltage.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.5.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThLowerCritical.0.2 = INTEGER: 180000 */
{ "input.L2.voltage.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.6.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThUpperWarning.0.2 = INTEGER: 255000 */
{ "input.L2.voltage.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.7.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThUpperCritical.0.2 = INTEGER: 265000 */
{ "input.L2.voltage.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.8.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltage.0.3 = INTEGER: 216790 */
{ "input.L3.voltage", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.2.1.3.%i.3",
NULL, 0, NULL },
/* pdu2InputPhaseVoltageThStatus.0.3 = INTEGER: good(1) */
{ "input.L3.voltage.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.3",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "L3.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.3",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_voltage_alarms_info[0] },
/* pdu2InputPhaseVoltageThLowerWarning.0.3 = INTEGER: 190000 */
{ "input.L3.voltage.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.5.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThLowerCritical.0.3 = INTEGER: 180000 */
{ "input.L3.voltage.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.6.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThUpperWarning.0.3 = INTEGER: 255000 */
{ "input.L3.voltage.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.7.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseVoltageThUpperCritical.0.3 = INTEGER: 265000 */
{ "input.L3.voltage.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.8.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* FIXME:
* - input.current is mapped on input.L1.current for both single and 3phase !!! */
/* pdu2InputPhaseCurrent.0.1 = INTEGER: 185 */
{ "input.current", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.11.%i.1",
NULL, 0, NULL },
/* pdu2InputPhaseCurrentRating.0.1 = INTEGER: 24000 */
{ "input.current.nominal", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.10.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThStatus.0.1 = INTEGER: good(1) */
{ "input.current.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_current_alarms_info[0] },
/* pdu2InputPhaseCurrentThLowerWarning.0.1 = INTEGER: 0 */
{ "input.current.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.13.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThLowerCritical.0.1 = INTEGER: -1 */
{ "input.current.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.14.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThUpperWarning.0.1 = INTEGER: 19200 */
{ "input.current.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.15.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThUpperCritical.0.1 = INTEGER: 24000 */
{ "input.current.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.16.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrent.0.1 = INTEGER: 185 */
{ "input.L1.current", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.11.%i.1",
NULL, 0, NULL },
/* pdu2InputPhaseCurrentRating.0.1 = INTEGER: 24000 */
{ "input.L1.current.nominal", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.10.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThStatus.0.1 = INTEGER: good(1) */
{ "input.L1.current.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "L1.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_current_alarms_info[0] },
/* pdu2InputPhaseCurrentThLowerWarning.0.1 = INTEGER: 0 */
{ "input.L1.current.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.13.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThLowerCritical.0.1 = INTEGER: -1 */
{ "input.L1.current.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.14.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThUpperWarning.0.1 = INTEGER: 19200 */
{ "input.L1.current.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.15.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThUpperCritical.0.1 = INTEGER: 24000 */
{ "input.L1.current.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.16.%i.1",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrent.0.2 = INTEGER: 185 */
{ "input.L2.current", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.11.%i.2",
NULL, 0, NULL },
/* pdu2InputPhaseCurrentRating.0.2 = INTEGER: 24000 */
{ "input.L2.current.nominal", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.10.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThStatus.0.2 = INTEGER: good(1) */
{ "input.L2.current.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.2",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.2",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_current_alarms_info[0] },
/* pdu2InputPhaseCurrentThLowerWarning.0.2 = INTEGER: 0 */
{ "input.L2.current.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.13.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThLowerCritical.0.2 = INTEGER: -1 */
{ "input.L2.current.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.14.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThUpperWarning.0.2 = INTEGER: 19200 */
{ "input.L2.current.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.15.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThUpperCritical.0.2 = INTEGER: 24000 */
{ "input.L2.current.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.16.%i.2",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrent.0.3 = INTEGER: 185 */
{ "input.L3.current", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.11.%i.3",
NULL, 0, NULL },
/* pdu2InputPhaseCurrentRating.0.3 = INTEGER: 24000 */
{ "input.L3.current.nominal", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.10.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThStatus.0.3 = INTEGER: good(1) */
{ "input.L3.current.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.3",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.2",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_current_alarms_info[0] },
/* pdu2InputPhaseCurrentThLowerWarning.0.3 = INTEGER: 0 */
{ "input.L3.current.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.13.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThLowerCritical.0.3 = INTEGER: -1 */
{ "input.L3.current.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.14.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThUpperWarning.0.3 = INTEGER: 19200 */
{ "input.L3.current.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.15.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPhaseCurrentThUpperCritical.0.3 = INTEGER: 24000 */
{ "input.L3.current.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.2.2.1.16.%i.3",
NULL, SU_FLAG_NEGINVALID, NULL },
/* pdu2InputPowerWatts.0 = INTEGER: 19 */
{ "input.realpower", 0, 1.0,
".1.3.6.1.4.1.232.165.7.2.1.1.5.%i",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL },
/* pdu2InputPhasePowerWatts.0.1 = INTEGER: 19 */
{ "input.L1.realpower", 0, 1.0,
".1.3.6.1.4.1.232.165.7.2.2.1.21.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2InputPhasePowerWatts.0.2 = INTEGER: 0 */
{ "input.L2.realpower", 0, 1.0,
".1.3.6.1.4.1.232.165.7.2.2.1.21.%i.2",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2InputPhasePowerWatts.0.3 = INTEGER: 0 */
{ "input.L3.realpower", 0, 1.0,
".1.3.6.1.4.1.232.165.7.2.2.1.21.%i.3",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* Sum of all phases apparent power, valid for Shark 1ph/3ph only */
/* pdu2InputPowerVA.0 = INTEGER: 39 */
{ "input.power", 0, 1.0,
".1.3.6.1.4.1.232.165.7.2.1.1.4.%i",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL },
/* pdu2InputPhasePowerVA.0.1 = INTEGER: 40 */
{ "input.L1.power", 0, 1.0,
".1.3.6.1.4.1.232.165.7.2.2.1.20.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2InputPhasePowerVA.0.2 = INTEGER: 0 */
{ "input.L2.power", 0, 1.0,
".1.3.6.1.4.1.232.165.7.2.2.1.20.%i.2",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2InputPhasePowerVA.0.3 = INTEGER: 0 */
{ "input.L3.power", 0, 1.0,
".1.3.6.1.4.1.232.165.7.2.2.1.20.%i.3",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* TODO: handle statistics */
/* pdu2InputPowerWattHour.0 = INTEGER: 91819
{ "unmapped.pdu2InputPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.7.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, */
/* pdu2InputPowerWattHourTimer.0 = STRING: "16/10/2017,17:58:53"
{ "unmapped.pdu2InputPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.2.1.1.7.0", NULL, SU_FLAG_OK, NULL }, */
/* pdu2InputPowerFactor.0 = INTEGER: 483 */
{ "input.powerfactor", 0, 0.001,
".1.3.6.1.4.1.232.165.7.2.1.1.8.%i",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* Ambient collection */
/* pdu2TemperatureProbeStatus.0.1 = INTEGER: disconnected(1) */
{ "ambient.present", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.4.2.1.3.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_ambient_presence_info[0] },
/* pdu2TemperatureThStatus.0.1 = INTEGER: good(1) */
{ "ambient.temperature.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.4.2.1.5.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.4.2.1.5.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_temperature_alarms_info[0] },
/* pdu2TemperatureValue.0.1 = INTEGER: 0 */
{ "ambient.temperature", 0, 0.1,
".1.3.6.1.4.1.232.165.7.4.2.1.4.%i.1",
NULL, SU_FLAG_OK, NULL },
/* Low and high threshold use the respective critical levels */
/* pdu2TemperatureThLowerCritical.0.1 = INTEGER: 50 */
{ "ambient.temperature.low", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.2.1.7.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
{ "ambient.temperature.low.critical", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.2.1.7.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2TemperatureThLowerWarning.0.1 = INTEGER: 100 */
{ "ambient.temperature.low.warning", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.2.1.6.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2TemperatureThUpperCritical.0.1 = INTEGER: 650 */
{ "ambient.temperature.high", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.2.1.9.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
{ "ambient.temperature.high.critical", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.2.1.9.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2TemperatureThUpperWarning.0.1 = INTEGER: 200 */
{ "ambient.temperature.high.warning", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.2.1.8.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2HumidityThStatus.0.1 = INTEGER: good(1) */
{ "ambient.humidity.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.4.3.1.5.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] },
{ "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.4.3.1.5.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_threshold_humidity_alarms_info[0] },
/* pdu2HumidityValue.0.1 = INTEGER: 0 */
{ "ambient.humidity", 0, 0.1,
".1.3.6.1.4.1.232.165.7.4.3.1.4.%i.1",
NULL, SU_FLAG_OK, NULL },
/* Low and high threshold use the respective critical levels */
/* pdu2HumidityThLowerCritical.0.1 = INTEGER: 100 */
{ "ambient.humidity.low", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.3.1.7.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
{ "ambient.humidity.low.critical", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.3.1.7.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2HumidityThLowerWarning.0.1 = INTEGER: 200 */
{ "ambient.humidity.low.warning", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.3.1.6.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2HumidityThUpperWarning.0.1 = INTEGER: 250 */
{ "ambient.humidity.high.warning", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.3.1.8.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* pdu2HumidityThUpperCritical.0.1 = INTEGER: 900 */
{ "ambient.humidity.high", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.3.1.9.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
{ "ambient.humidity.high.critical", ST_FLAG_RW, 0.1,
".1.3.6.1.4.1.232.165.7.4.3.1.9.%i.1",
NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL },
/* Dry contacts on TH module */
/* pdu2ContactState.0.1 = INTEGER: contactBad(3) */
{ "ambient.contacts.1.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.4.4.1.4.%i.1",
NULL, SU_FLAG_OK, &hpe_pdu_ambient_drycontacts_info[0] },
/* pdu2ContactState.0.2 = INTEGER: contactBad(3) */
{ "ambient.contacts.2.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.4.4.1.4.%i.2",
NULL, SU_FLAG_OK, &hpe_pdu_ambient_drycontacts_info[0] },
/* Outlet collection */
{ "outlet.id", 0, 1, NULL,
"0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
{ "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
/* pdu2OutletCount.0 = INTEGER: 24 */
{ "outlet.count", 0, 1,
".1.3.6.1.4.1.232.165.7.1.2.1.12.%i",
"0", SU_FLAG_STATIC | SU_FLAG_OK, NULL },
/* outlet template definition
* Indexes start from 1, ie outlet.1 => <OID>.1 */
/* Note: the first definition is used to determine the base index (ie 0 or 1) */
/* pdu2OutletName.0.%i = STRING: "Outlet L1-%i" */
{ "outlet.%i.desc", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.5.1.1.2.%i.%i",
NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletControlStatus.0.%i = INTEGER: on(2) */
{ "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.5.2.1.1.%i.%i",
NULL, SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, &hpe_pdu_outlet_status_info[0] },
/* Numeric identifier of the outlet, tied to the whole unit */
{ "outlet.%i.id", 0, 1, NULL, "%i",
SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
#if 0
/* FIXME: the last part of the OID gives the group number (i.e. %i.1 means "group 1")
* Need to address that, without multiple declaration (%i.%i, SU_OUTLET | SU_OUTLET_GROUP)? */
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.1",
NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.2",
NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.3",
NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.4",
NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.5",
NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
{ "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.6",
NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
#endif
/* pdu2OutletCurrent.0.%i = INTEGER: 0 */
{ "outlet.%i.current", 0, 0.001,
".1.3.6.1.4.1.232.165.7.5.1.1.5.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletCurrentThStatus.0.%i = INTEGER: good(1) */
{ "outlet.%i.current.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.5.1.1.6.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, &hpe_pdu_threshold_status_info[0] },
{ "outlet.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.5.1.1.6.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, &hpe_pdu_threshold_current_alarms_info[0] },
/* pdu2OutletCurrentThLowerWarning.0.%i = INTEGER: 0 */
{ "outlet.%i.current.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.5.1.1.7.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletCurrentThLowerCritical.0.%i = INTEGER: -1 */
{ "outlet.%i.current.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.5.1.1.8.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletCurrentThUpperWarning.0.1 = INTEGER: 8000 */
{ "outlet.%i.current.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.5.1.1.9.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletCurrentThUpperCritical.0.1 = INTEGER: 10000 */
{ "outlet.%i.current.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.5.1.1.10.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletWatts.0.1 = INTEGER: 0 */
{ "outlet.%i.realpower", 0, 1.0,
".1.3.6.1.4.1.232.165.7.5.1.1.14.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletVA.0.%i = INTEGER: 0 */
{ "outlet.%i.power", 0, 1.0,
".1.3.6.1.4.1.232.165.7.5.1.1.13.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletControlSwitchable.0.%i = INTEGER: switchable(1) */
{ "outlet.%i.switchable", ST_FLAG_RW, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.5.2.1.8.%i.%i",
"no", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK | SU_TYPE_DAISY_1,
&hpe_pdu_outlet_switchability_info[0] },
/* pdu2OutletType.0.%i = INTEGER: iecC13(1) */
{ "outlet.%i.type", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.5.1.1.3.%i.%i",
"unknown", SU_FLAG_STATIC | SU_OUTLET | SU_TYPE_DAISY_1,
&hpe_pdu_outlet_type_info[0] },
/* pdu2OutletPowerFactor.0.%i = INTEGER: 1000 */
{ "outlet.%i.powerfactor", 0, 0.001,
".1.3.6.1.4.1.232.165.7.5.1.1.17.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* TODO: handle statistics */
/* pdu2OutletWh.0.1 = INTEGER: 1167
* Note: setting this to zero resets the counter and timestamp => instcmd ???counter???.reset
{ "unmapped.pdu2OutletWh", 0, 1, ".1.3.6.1.4.1.232.165.7.5.1.1.15.%i.%i", NULL, SU_FLAG_OK, NULL }, */
/* pdu2OutletWhTimer.0.1 = STRING: "25/03/2016,09:03:26"
{ "unmapped.pdu2OutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.5.1.1.16.%i.%i", NULL, SU_FLAG_OK, NULL }, */
/* Outlet groups collection */
/* pdu2GroupCount.0 = INTEGER: 3 */
{ "outlet.group.count", 0, 1,
".1.3.6.1.4.1.232.165.7.1.2.1.11.%i",
"0", SU_FLAG_STATIC | SU_TYPE_DAISY_1, NULL },
/* outlet groups template definition
* Indexes start from 1, ie outlet.group.1 => <OID>.1 */
/* Note: the first definition is used to determine the base index (ie 0 or 1) */
/* pdu2GroupIndex.0.%i = INTEGER: %i */
{ "outlet.group.%i.id", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.1.%i.%i",
NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupName.0.%i = STRING: "Section L1" */
{ "outlet.group.%i.name", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.2.%i.%i",
NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupType.0.%i = INTEGER: breaker2pole(3) */
{ "outlet.group.%i.type", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.3.%i.%i",
NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, &hpe_pdu_outlet_group_type_info[0] },
/* pdu2GroupVoltageMeasType.0.1 = INTEGER: phase1to2(5) */
{ "outlet.group.%i.phase", 0, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.4.%i.%i",
NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1,
&hpe_pdu_outlet_group_phase_info[0] },
/* pdu2groupBreakerStatus.0.%i = INTEGER: breakerOn(2) */
{ "outlet.group.%i.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.27.%i.%i",
NULL, SU_FLAG_OK | SU_FLAG_NAINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1,
&hpe_pdu_outletgroups_status_info[0] },
/* pdu2GroupOutletCount.0.%i = INTEGER: 8 */
{ "outlet.group.%i.count", 0, 1,
".1.3.6.1.4.1.232.165.7.3.1.1.26.%i.%i",
NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupVoltage.0.%i = INTEGER: 216760 */
{ "outlet.group.%i.voltage", 0, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.5.%i.%i",
NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupVoltageThStatus.0.%i = INTEGER: good(1) */
{ "outlet.group.%i.voltage.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.6.%i.%i",
NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1,
&hpe_pdu_threshold_status_info[0] },
{ "outlet.group.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.6.%i.%i",
NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1,
&hpe_pdu_threshold_voltage_alarms_info[0] },
/* pdu2GroupVoltageThLowerWarning.0.%i = INTEGER: 190000 */
{ "outlet.group.%i.voltage.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.7.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupVoltageThLowerCritical.0.%i = INTEGER: 180000 */
{ "outlet.group.%i.voltage.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.8.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupVoltageThUpperWarning.0.%i = INTEGER: 255000 */
{ "outlet.group.%i.voltage.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.9.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupVoltageThUpperCritical.0.%i = INTEGER: 265000 */
{ "outlet.group.%i.voltage.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.10.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupCurrent.0.%i = INTEGER: 0 */
{ "outlet.group.%i.current", 0, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.12.%i.%i",
NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2groupCurrentRating.0.%i = INTEGER: 16000 */
{ "outlet.group.%i.current.nominal", 0, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.11.%i.%i",
NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupCurrentThStatus.0.%i = INTEGER: good(1) */
{ "outlet.group.%i.current.status", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.13.%i.%i",
NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1,
&hpe_pdu_threshold_status_info[0] },
{ "outlet.group.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE,
".1.3.6.1.4.1.232.165.7.3.1.1.13.%i.%i",
NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1,
&hpe_pdu_threshold_current_alarms_info[0] },
/* pdu2GroupCurrentThLowerWarning.0.%i = INTEGER: 0 */
{ "outlet.group.%i.current.low.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.14.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupCurrentThLowerCritical.0.%i = INTEGER: -1 */
{ "outlet.group.%i.current.low.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.15.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupCurrentThUpperWarning.0.%i = INTEGER: 12800 */
{ "outlet.group.%i.current.high.warning", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.16.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupCurrentThUpperCritical.0.%i = INTEGER: 16000 */
{ "outlet.group.%i.current.high.critical", ST_FLAG_RW, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.17.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupCurrentPercentLoad.0.%i = INTEGER: 0 */
{ "outlet.group.%i.load", 0, 1.0,
".1.3.6.1.4.1.232.165.7.3.1.1.19.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupPowerWatts.0.%i = INTEGER: 0 */
{ "outlet.group.%i.realpower", 0, 1.0,
".1.3.6.1.4.1.232.165.7.3.1.1.21.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupPowerVA.0.%i = INTEGER: 0 */
{ "outlet.group.%i.power", 0, 1.0,
".1.3.6.1.4.1.232.165.7.3.1.1.20.%i.%i",
NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL },
/* pdu2GroupPowerFactor.0.%i = INTEGER: 1000 */
{ "outlet.group.%i.powerfactor", 0, 0.001,
".1.3.6.1.4.1.232.165.7.3.1.1.24.%i.%i",
NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* TODO: handle statistics */
/* pdu2GroupPowerWattHour.0.%i = INTEGER: 1373
* Note: setting this to zero resets the counter and timestamp => instcmd .reset
{ "unmapped.pdu2GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.7.3.1.1.22.%i.%i", NULL, SU_FLAG_OK, NULL }, */
/* pdu2GroupPowerWattHourTimer.0.%i = STRING: "25/03/2016,09:01:16"
{ "unmapped.pdu2GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.3.1.1.23.%i.%i", NULL, SU_FLAG_OK, NULL }, */
/* instant commands. */
/* TODO: handle delays (outlet.%i.{on,off}.delay) */
/* pdu2OutletControlOffCmd.0.%i = INTEGER: -1 */
{ "outlet.%i.load.off", 0, 1,
".1.3.6.1.4.1.232.165.7.5.2.1.2.%i.%i",
"0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletControlOnCmd.0.%i = INTEGER: -1 */
{ "outlet.%i.load.on", 0, 1,
".1.3.6.1.4.1.232.165.7.5.2.1.3.%i.%i",
"0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletControlRebootCmd.0.%i = INTEGER: -1 */
{ "outlet.%i.load.cycle", 0, 1,
".1.3.6.1.4.1.232.165.7.5.2.1.4.%i.%i",
"0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* Delayed version, parameter is mandatory (so dfl is NULL)! */
/* pdu2OutletControlOffCmd.0.%i = INTEGER: -1 */
{ "outlet.%i.load.off.delay", 0, 1,
".1.3.6.1.4.1.232.165.7.5.2.1.2.%i.%i",
NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletControlOnCmd.0.%i = INTEGER: -1 */
{ "outlet.%i.load.on.delay", 0, 1,
".1.3.6.1.4.1.232.165.7.5.2.1.3.%i.%i",
NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* pdu2OutletControlRebootCmd.0.%i = INTEGER: -1 */
{ "outlet.%i.load.cycle.delay", 0, 1,
".1.3.6.1.4.1.232.165.7.5.2.1.4.%i.%i",
NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t hpe_pdu = { "hpe_epdu", HPE_EPDU_MIB_VERSION, NULL, HPE_EPDU_OID_MODEL_NAME, hpe_pdu_mib, HPE_EPDU_MIB_SYSOID, NULL };

30
drivers/hpe-pdu-mib.h Normal file
View file

@ -0,0 +1,30 @@
/* hpe-pdu-mib.h - subdriver to monitor HPE ePDU SNMP devices with NUT
*
* Copyright (C)
* 2011 - 2016 Arnaud Quette <arnaud.quette@free.fr>
* 2019 Arnaud Quette <ArnaudQuette@eaton.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
*/
#ifndef HPE_EPDU_MIB_H
#define HPE_EPDU_MIB_H
#include "main.h"
#include "snmp-ups.h"
extern mib2nut_info_t hpe_pdu;
#endif /* HPE_EPDU_MIB_H */

View file

@ -21,90 +21,95 @@
#include "huawei-mib.h"
#define HUAWEI_MIB_VERSION "0.1"
#define HUAWEI_MIB_VERSION "0.4"
#define HUAWEI_SYSOID ".1.3.6.1.4.1.8072.3.2.10"
#define HUAWEI_UPSMIB ".1.3.6.1.4.1.2011"
#define HUAWEI_OID_MODEL_NAME ".1.3.6.1.4.1.2011.6.174.1.2.100.1.2.1"
/* To create a value lookup structure (as needed on the 2nd line of the example
* below), use the following kind of declaration, outside of the present snmp_info_t[]:
* static info_lkp_t onbatt_info[] = {
* { 1, "OB" },
* { 2, "OL" },
* { 0, NULL }
* static info_lkp_t huawei_onbatt_info[] = {
* { 1, "OB", NULL, NULL },
* { 2, "OL", NULL, NULL },
* { 0, NULL, NULL, NULL }
* };
*/
static info_lkp_t supplymethod_info[] = {
{ 1, "" }, /* no supply */
{ 2, "OL BYPASS" },
{ 3, "OL" },
{ 4, "OB" },
{ 5, "" }, /* combined */
{ 6, "OL ECO" },
{ 7, "OB ECO" },
{ 0, NULL }
static info_lkp_t huawei_supplymethod_info[] = {
{ 1, "", NULL, NULL }, /* no supply */
{ 2, "OL BYPASS", NULL, NULL },
{ 3, "OL", NULL, NULL },
{ 4, "OB", NULL, NULL },
{ 5, "", NULL, NULL }, /* combined */
{ 6, "OL ECO", NULL, NULL },
{ 7, "OB ECO", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t battstate_info[] = {
{ 1, "" }, /* not connected */
{ 2, "" }, /* not charging or discharging */
{ 3, "" }, /* hibernation */
{ 4, "" }, /* float */
{ 5, "CHRG" }, /* equalized charging */
{ 6, "DISCHRG" },
{ 0, NULL }
static info_lkp_t huawei_battstate_info[] = {
{ 1, "", NULL, NULL }, /* not connected */
{ 2, "", NULL, NULL }, /* not charging or discharging */
{ 3, "", NULL, NULL }, /* hibernation */
{ 4, "", NULL, NULL }, /* float */
{ 5, "CHRG", NULL, NULL }, /* equalized charging */
{ 6, "DISCHRG", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t phase_info[] = {
{ 1, "1" },
{ 2, "3" },
{ 0, NULL }
static info_lkp_t huawei_phase_info[] = {
{ 1, "1", NULL, NULL },
{ 2, "3", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t voltrating_info[] = {
{ 1, "200" },
{ 2, "208" },
{ 3, "220" },
{ 4, "380" },
{ 5, "400" },
{ 6, "415" },
{ 7, "480" },
{ 8, "600" },
{ 9, "690" },
{ 0, NULL }
static info_lkp_t huawei_voltrating_info[] = {
{ 1, "200", NULL, NULL },
{ 2, "208", NULL, NULL },
{ 3, "220", NULL, NULL },
{ 4, "380", NULL, NULL },
{ 5, "400", NULL, NULL },
{ 6, "415", NULL, NULL },
{ 7, "480", NULL, NULL },
{ 8, "600", NULL, NULL },
{ 9, "690", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t freqrating_info[] = {
{ 1, "50" },
{ 2, "60" },
{ 0, NULL }
static info_lkp_t huawei_freqrating_info[] = {
{ 1, "50", NULL, NULL },
{ 2, "60", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t pwrrating_info[] = {
{ 1, "80000" },
{ 2, "100000" },
{ 3, "120000" },
{ 4, "160000" },
{ 5, "200000" },
{ 6, "30000" },
{ 7, "40000" },
{ 8, "60000" },
{ 9, "2400000" },
{ 10, "2500000" },
{ 11, "2800000" },
{ 12, "3000000" },
{ 0, NULL }
static info_lkp_t huawei_pwrrating_info[] = {
{ 1, "80000", NULL, NULL },
{ 2, "100000", NULL, NULL },
{ 3, "120000", NULL, NULL },
{ 4, "160000", NULL, NULL },
{ 5, "200000", NULL, NULL },
{ 6, "30000", NULL, NULL },
{ 7, "40000", NULL, NULL },
{ 8, "60000", NULL, NULL },
{ 9, "2400000", NULL, NULL },
{ 10, "2500000", NULL, NULL },
{ 11, "2800000", NULL, NULL },
{ 12, "3000000", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ietf_test_result_info[] = {
{ 1, "done and passed" },
{ 2, "done and warning" },
{ 3, "done and error" },
{ 4, "aborted" },
{ 5, "in progress" },
{ 6, "no test initiated" },
{ 0, NULL }
/* Note: This is currently identical to ietf_test_result_info from IETF MIB
* We rename it here to a) allow evolution that may become incompatible;
* b) avoid namespace conflicts, especially with DMF loader of named objects
*/
static info_lkp_t huawei_test_result_info[] = {
{ 1, "done and passed", NULL, NULL },
{ 2, "done and warning", NULL, NULL },
{ 3, "done and error", NULL, NULL },
{ 4, "aborted", NULL, NULL },
{ 5, "in progress", NULL, NULL },
{ 6, "no test initiated", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
@ -122,21 +127,25 @@ static snmp_info_t huawei_mib[] = {
* dfl: default value
* flags: snmp-ups internal flags (FIXME: ...)
* oid2info: lookup table between OID and NUT values
* setvar: variable to set for SU_FLAG_SETINT
*
* Example:
* { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.1", "", SU_INPUT_1, NULL },
* { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.705.1.7.3.0", "", SU_FLAG_OK | SU_STATUS_BATT, onbatt_info },
* { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.705.1.7.3.0", "", SU_FLAG_OK | SU_STATUS_BATT, huawei_onbatt_info },
*
* To create a value lookup structure (as needed on the 2nd line), use the
* following kind of declaration, outside of the present snmp_info_t[]:
* static info_lkp_t onbatt_info[] = {
* static info_lkp_t huawei_onbatt_info[] = {
* { 1, "OB" },
* { 2, "OL" },
* { 0, NULL }
* };
*/
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* UPS page */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Huawei", SU_FLAG_ABSENT | SU_FLAG_OK, NULL },
@ -148,16 +157,16 @@ static snmp_info_t huawei_mib[] = {
{ "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.2.100.1.3.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.2.100.1.5.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL },
{ "ups.status", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.2.101.1.1.1", NULL, SU_FLAG_OK, supplymethod_info },
{ "ups.status", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.2.101.1.3.1", NULL, SU_STATUS_BATT | SU_FLAG_OK, battstate_info },
{ "ups.status", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.2.101.1.1.1", NULL, SU_FLAG_OK, huawei_supplymethod_info },
{ "ups.status", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.2.101.1.3.1", NULL, SU_STATUS_BATT | SU_FLAG_OK, huawei_battstate_info },
{ "ups.test.result", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.33.1.7.3.0", "", 0, ietf_test_result_info },
{ "ups.test.result", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.33.1.7.3.0", "", 0, huawei_test_result_info },
/* Input page */
/* hwUpsCtrlInputStandard listed in MIB but not present on tested UPS5000-E */
{ "input.phases", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.102.100.1.8", "3", SU_FLAG_ABSENT | SU_FLAG_OK, phase_info },
{ "input.phases", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.102.100.1.8", "3", SU_FLAG_ABSENT | SU_FLAG_OK, huawei_phase_info },
{ "input.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.3.100.1.1.1", NULL, SU_FLAG_OK, NULL },
{ "input.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.3.100.1.2.1", NULL, SU_FLAG_OK, NULL },
@ -183,7 +192,7 @@ static snmp_info_t huawei_mib[] = {
/* Output page */
/* hwUpsCtrlOutputStandard listed in MIB but not present on tested UPS5000-E */
{ "output.phases", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.102.100.1.9", "3", SU_FLAG_ABSENT | SU_FLAG_OK, phase_info },
{ "output.phases", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.102.100.1.9", "3", SU_FLAG_ABSENT | SU_FLAG_OK, huawei_phase_info },
{ "output.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.1.1", NULL, SU_FLAG_OK, NULL },
{ "output.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.2.1", NULL, SU_FLAG_OK, NULL },
@ -207,9 +216,9 @@ static snmp_info_t huawei_mib[] = {
{ "output.L2.power.percent", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.15.1", NULL, SU_FLAG_OK, NULL },
{ "output.L3.power.percent", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.16.1", NULL, SU_FLAG_OK, NULL },
{ "output.voltage.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.17.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, voltrating_info },
{ "output.frequency.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.18.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, freqrating_info },
{ "output.power.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.2.100.1.6.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, pwrrating_info },
{ "output.voltage.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.17.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, huawei_voltrating_info },
{ "output.frequency.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.18.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, huawei_freqrating_info },
{ "output.power.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.2.100.1.6.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, huawei_pwrrating_info },
{ "output.L1.powerfactor", 0, 0.01, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.19.1", NULL, SU_FLAG_OK, NULL },
{ "output.L2.powerfactor", 0, 0.01, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.20.1", NULL, SU_FLAG_OK, NULL },
@ -231,4 +240,4 @@ static snmp_info_t huawei_mib[] = {
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t huawei = { "huawei", HUAWEI_MIB_VERSION, NULL, NULL, huawei_mib, HUAWEI_SYSOID };
mib2nut_info_t huawei = { "huawei", HUAWEI_MIB_VERSION, NULL, HUAWEI_OID_MODEL_NAME, huawei_mib, HUAWEI_SYSOID, NULL };

2122
drivers/huawei-ups2000.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -23,12 +23,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h" /* must be first */
#include "usbhid-ups.h"
#include "idowell-hid.h"
#include "main.h" /* for getval() */
#include "usb-common.h"
#define IDOWELL_HID_VERSION "iDowell HID 0.1"
#define IDOWELL_HID_VERSION "iDowell HID 0.2"
/* FIXME: experimental flag to be put in upsdrv_info */
/* iDowell */
@ -40,7 +42,7 @@ static usb_device_id_t idowell_usb_device_table[] = {
{ USB_DEVICE(IDOWELL_VENDORID, 0x0300), NULL },
/* Terminating entry */
{ -1, -1, NULL }
{ 0, 0, NULL }
};
/* --------------------------------------------------------------- */
@ -102,7 +104,7 @@ static hid_info_t idowell_hid2nut[] = {
{ "ups.timer.shutdown", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL},
{ "ups.load", 0, 0, "UPS.PowerSummary.PercentLoad", NULL, "%.0f", 0, NULL },
{ "ups.power.nominal", 0, 0, "UPS.Flow.[4].ConfigApparentPower", NULL, "%.0f", HU_FLAG_STATIC, NULL },
/* input page */
{ "input.transfer.high", 0, 0, "UPS.PowerConverter.Output.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "input.transfer.low", 0, 0, "UPS.PowerConverter.Output.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_STATIC, NULL },
@ -166,4 +168,5 @@ subdriver_t idowell_subdriver = {
idowell_format_model,
idowell_format_mfr,
idowell_format_serial,
fix_report_desc,
};

View file

@ -26,81 +26,97 @@
#include "ietf-mib.h"
#define IETF_MIB_VERSION "1.5"
#define IETF_MIB_VERSION "1.54"
/* SNMP OIDs set */
#define IETF_OID_UPS_MIB "1.3.6.1.2.1.33.1."
#define IETF_SYSOID ".1.3.6.1.2.1.33"
/* NOTE: Currently the Tripplite UPSes await user-validation of their
* real SNMP OID tree, so temporarily the IETF tree is used as "tripplite"
* for the mapping purposes; the devices ave their entry point OID though.
* For more details see:
* https://github.com/networkupstools/nut/issues/309
* https://github.com/networkupstools/nut/issues/171
* Also related to:
* https://github.com/networkupstools/nut/issues/270
*/
#define TRIPPLITE_SYSOID ".1.3.6.1.4.1.850.1"
/* #define DEBUG */
static info_lkp_t ietf_battery_info[] = {
{ 1, "" /* unknown */ },
{ 2, "" /* batteryNormal */},
{ 3, "LB" /* batteryLow */ },
{ 4, "LB" /* batteryDepleted */ },
{ 0, NULL }
{ 1, "" /* unknown */, NULL, NULL },
{ 2, "" /* batteryNormal */, NULL, NULL },
{ 3, "LB" /* batteryLow */, NULL, NULL },
{ 4, "LB" /* batteryDepleted */, NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ietf_power_source_info[] = {
{ 1, "" /* other */ },
{ 2, "OFF" /* none */ },
{ 3, "OL" /* normal */ },
{ 4, "OL BYPASS" /* bypass */ },
{ 5, "OB" /* battery */ },
{ 6, "OL BOOST" /* booster */ },
{ 7, "OL TRIM" /* reducer */ },
{ 0, NULL }
{ 1, "" /* other */, NULL, NULL },
{ 2, "OFF" /* none */, NULL, NULL },
{ 3, "OL" /* normal */, NULL, NULL },
{ 4, "OL BYPASS" /* bypass */, NULL, NULL },
{ 5, "OB" /* battery */, NULL, NULL },
{ 6, "OL BOOST" /* booster */, NULL, NULL },
{ 7, "OL TRIM" /* reducer */, NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ietf_overload_info[] = {
{ 1, "OVER" }, /* output overload */
{ 0, NULL }
{ 1, "OVER", NULL, NULL }, /* output overload */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ietf_test_active_info[] = {
{ 1, "" }, /* upsTestNoTestsInitiated */
{ 2, "" }, /* upsTestAbortTestInProgress */
{ 3, "TEST" }, /* upsTestGeneralSystemsTest */
{ 4, "TEST" }, /* upsTestQuickBatteryTest */
{ 5, "CAL" }, /* upsTestDeepBatteryCalibration */
{ 0, NULL }
{ 1, "", NULL, NULL }, /* upsTestNoTestsInitiated */
{ 2, "", NULL, NULL }, /* upsTestAbortTestInProgress */
{ 3, "TEST", NULL, NULL }, /* upsTestGeneralSystemsTest */
{ 4, "TEST", NULL, NULL }, /* upsTestQuickBatteryTest */
{ 5, "CAL", NULL, NULL }, /* upsTestDeepBatteryCalibration */
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ietf_test_result_info[] = {
{ 1, "done and passed" },
{ 2, "done and warning" },
{ 3, "done and error" },
{ 4, "aborted" },
{ 5, "in progress" },
{ 6, "no test initiated" },
{ 0, NULL }
{ 1, "done and passed", NULL, NULL },
{ 2, "done and warning", NULL, NULL },
{ 3, "done and error", NULL, NULL },
{ 4, "aborted", NULL, NULL },
{ 5, "in progress", NULL, NULL },
{ 6, "no test initiated", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
#ifdef DEBUG
static info_lkp_t ietf_shutdown_type_info[] = {
{ 1, "output" },
{ 2, "system" },
{ 0, NULL }
{ 1, "output", NULL, NULL },
{ 2, "system", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
#endif
static info_lkp_t ietf_yes_no_info[] = {
{ 1, "yes" },
{ 2, "no" },
{ 0, NULL }
{ 1, "yes", NULL, NULL },
{ 2, "no", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
static info_lkp_t ietf_beeper_status_info[] = {
{ 1, "disabled" },
{ 2, "enabled" },
{ 3, "muted" },
{ 0, NULL }
{ 1, "disabled", NULL, NULL },
{ 2, "enabled", NULL, NULL },
{ 3, "muted", NULL, NULL },
{ 0, NULL, NULL, NULL }
};
/* Snmp2NUT lookup table info_type, info_flags, info_len, OID, dfl, flags, oid2info, setvar */
static snmp_info_t ietf_mib[] = {
/* standard MIB items */
{ "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL },
{ "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL },
{ "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL },
/* The Device Identification group */
{ "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "1.1.0", "Generic", SU_FLAG_STATIC, NULL }, /* upsIdentManufacturer */
{ "ups.model", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "1.2.0", "Generic SNMP UPS", SU_FLAG_STATIC, NULL }, /* upsIdentModel */
@ -125,7 +141,7 @@ static snmp_info_t ietf_mib[] = {
#ifdef DEBUG
{ "debug.upsInputLineBads", 0, 1.0, IETF_OID_UPS_MIB "3.1.0", "", 0, NULL }, /* upsInputLineBads */
#endif
{ "input.phases", 0, 1.0, IETF_OID_UPS_MIB "3.2.0", "", SU_FLAG_SETINT, NULL, &input_phases }, /* upsInputNumLines */
{ "input.phases", 0, 1.0, IETF_OID_UPS_MIB "3.2.0", "", 0, NULL }, /* upsInputNumLines */
#ifdef DEBUG
{ "debug.upsInputLineIndex", 0, 1.0, IETF_OID_UPS_MIB "3.3.1.1.1", "", SU_INPUT_1, NULL }, /* upsInputLineIndex */
{ "debug.[1].upsInputLineIndex", 0, 1.0, IETF_OID_UPS_MIB "3.3.1.1.1", "", SU_INPUT_3, NULL },
@ -152,7 +168,7 @@ static snmp_info_t ietf_mib[] = {
/* Output Group */
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "4.1.0", "", SU_STATUS_PWR, ietf_power_source_info }, /* upsOutputSource */
{ "output.frequency", 0, 0.1, IETF_OID_UPS_MIB "4.2.0", "", 0, NULL }, /* upsOutputFrequency */
{ "output.phases", 0, 1.0, IETF_OID_UPS_MIB "4.3.0", "", SU_FLAG_SETINT, NULL, &output_phases }, /* upsOutputNumLines */
{ "output.phases", 0, 1.0, IETF_OID_UPS_MIB "4.3.0", "", 0, NULL }, /* upsOutputNumLines */
#ifdef DEBUG
{ "debug.upsOutputLineIndex", 0, 1.0, IETF_OID_UPS_MIB "4.4.1.1.1", "", SU_OUTPUT_1, NULL }, /* upsOutputLineIndex */
{ "debug.[1].upsOutputLineIndex", 0, 1.0, IETF_OID_UPS_MIB "4.4.1.1.1", "", SU_OUTPUT_3, NULL },
@ -177,7 +193,7 @@ static snmp_info_t ietf_mib[] = {
{ "output.L3.power.percent", 0, 1.0, IETF_OID_UPS_MIB "4.4.1.5.3", "", SU_OUTPUT_3, NULL },
/* Bypass Group */
{ "input.bypass.phases", 0, 1.0, IETF_OID_UPS_MIB "5.2.0", "", SU_FLAG_SETINT, NULL, &bypass_phases }, /* upsBypassNumLines */
{ "input.bypass.phases", 0, 1.0, IETF_OID_UPS_MIB "5.2.0", "", 0, NULL }, /* upsBypassNumLines */
{ "input.bypass.frequency", 0, 0.1, IETF_OID_UPS_MIB "5.1.0", "", SU_BYPASS_1 | SU_BYPASS_3, NULL }, /* upsBypassFrequency */
#ifdef DEBUG
{ "debug.upsBypassLineIndex", 0, 1.0, IETF_OID_UPS_MIB "5.3.1.1.1", "", SU_BYPASS_1, NULL }, /* upsBypassLineIndex */
@ -231,10 +247,10 @@ static snmp_info_t ietf_mib[] = {
/* Test Group */
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "7.1.0", "", 0, ietf_test_active_info }, /* upsTestId */
{ "test.battery.stop", 0, 0, IETF_OID_UPS_MIB "7.1.0", IETF_OID_UPS_MIB "7.7.2", SU_TYPE_CMD, NULL }, /* upsTestAbortTestInProgress */
{ "test.battery.start", 0, 0, IETF_OID_UPS_MIB "7.1.0", IETF_OID_UPS_MIB "7.7.3", SU_TYPE_CMD, NULL }, /* upsTestGeneralSystemsTest */
{ "test.battery.start.quick", 0, 0, IETF_OID_UPS_MIB "7.1.0", IETF_OID_UPS_MIB "7.7.4", SU_TYPE_CMD, NULL }, /* upsTestQuickBatteryTest */
{ "test.battery.start.deep", 0, 0, IETF_OID_UPS_MIB "7.1.0", IETF_OID_UPS_MIB "7.7.5", SU_TYPE_CMD, NULL }, /* upsTestDeepBatteryCalibration */
{ "test.battery.stop", 0, 1, IETF_OID_UPS_MIB "7.1.0", "0", SU_TYPE_CMD, NULL }, /* upsTestAbortTestInProgress */
{ "test.battery.start", 0, 1, IETF_OID_UPS_MIB "7.1.0", "0", SU_TYPE_CMD, NULL }, /* upsTestGeneralSystemsTest */
{ "test.battery.start.quick", 0, 1, IETF_OID_UPS_MIB "7.1.0", "0", SU_TYPE_CMD, NULL }, /* upsTestQuickBatteryTest */
{ "test.battery.start.deep", 0, 1, IETF_OID_UPS_MIB "7.1.0", "0", SU_TYPE_CMD, NULL }, /* upsTestDeepBatteryCalibration */
#ifdef DEBUG
{ "debug.upsTestSpinLock", 0, 1.0, IETF_OID_UPS_MIB "7.2.0", "", 0, NULL }, /* upsTestSpinLock */
#endif
@ -250,9 +266,9 @@ static snmp_info_t ietf_mib[] = {
{ "debug.upsShutdownType", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "8.1.0", "", 0, ietf_shutdown_type_info }, /* upsShutdownType */
#endif
{ "ups.timer.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 8, IETF_OID_UPS_MIB "8.2.0", "", 0, NULL }, /* upsShutdownAfterDelay*/
{ "load.off", 0, 0, IETF_OID_UPS_MIB "8.2.0", "", SU_TYPE_CMD, NULL },
{ "load.off", 0, 1, IETF_OID_UPS_MIB "8.2.0", "0", SU_TYPE_CMD, NULL },
{ "ups.timer.start", ST_FLAG_STRING | ST_FLAG_RW, 8, IETF_OID_UPS_MIB "8.3.0", "", 0, NULL }, /* upsStartupAfterDelay */
{ "load.on", 0, 0, IETF_OID_UPS_MIB "8.3.0", "", SU_TYPE_CMD, NULL },
{ "load.on", 0, 1, IETF_OID_UPS_MIB "8.3.0", "0", SU_TYPE_CMD, NULL },
{ "ups.timer.reboot", ST_FLAG_STRING | ST_FLAG_RW, 8, IETF_OID_UPS_MIB "8.4.0", "", 0, NULL }, /* upsRebootWithDuration */
{ "ups.start.auto", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "8.5.0", "", 0, ietf_yes_no_info }, /* upsAutoRestart */
@ -265,9 +281,9 @@ static snmp_info_t ietf_mib[] = {
{ "output.realpower.nominal", 0, 1.0, IETF_OID_UPS_MIB "9.6.0", "", 0, NULL }, /* upsConfigOutputPower */
{ "battery.runtime.low", 0, 60.0, IETF_OID_UPS_MIB "9.7.0", "", 0, NULL }, /* upsConfigLowBattTime */
{ "ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "9.8.0", "", 0, ietf_beeper_status_info }, /* upsConfigAudibleStatus */
{ "beeper.disable", 0, 1, IETF_OID_UPS_MIB "9.8.0", "", SU_TYPE_CMD, NULL },
{ "beeper.enable", 0, 2, IETF_OID_UPS_MIB "9.8.0", "", SU_TYPE_CMD, NULL },
{ "beeper.mute", 0, 3, IETF_OID_UPS_MIB "9.8.0", "", SU_TYPE_CMD, NULL },
{ "beeper.disable", 0, 1, IETF_OID_UPS_MIB "9.8.0", "1", SU_TYPE_CMD, NULL },
{ "beeper.enable", 0, 1, IETF_OID_UPS_MIB "9.8.0", "2", SU_TYPE_CMD, NULL },
{ "beeper.mute", 0, 1, IETF_OID_UPS_MIB "9.8.0", "3", SU_TYPE_CMD, NULL },
{ "input.transfer.low", 0, 1.0, IETF_OID_UPS_MIB "9.9.0", "", 0, NULL }, /* upsConfigLowVoltageTransferPoint */
{ "input.transfer.high", 0, 1.0, IETF_OID_UPS_MIB "9.10.0", "", 0, NULL }, /* upsConfigHighVoltageTransferPoint */
@ -275,5 +291,12 @@ static snmp_info_t ietf_mib[] = {
{ NULL, 0, 0, NULL, NULL, 0, NULL }
};
mib2nut_info_t ietf = { "ietf", IETF_MIB_VERSION, IETF_OID_UPS_MIB "4.1.0", IETF_OID_UPS_MIB "1.1.0", ietf_mib, IETF_SYSOID };
mib2nut_info_t tripplite_ietf = { "ietf", IETF_MIB_VERSION, NULL, NULL, ietf_mib, TRIPPLITE_SYSOID };
/* FIXME: Rename the structure here (or even relocate to new file)
* and in snmp-ups.c when the real TrippLite mappings get defined. */
/* FIXME: Duplicate the line below to fix an issue with the code generator (nut-snmpinfo.py -> line is discarding) */
/*mib2nut_info_t tripplite_ietf = { "tripplite", IETF_MIB_VERSION, NULL, NULL, ietf_mib, TRIPPLITE_SYSOID, NULL };*/
mib2nut_info_t tripplite_ietf = { "tripplite", IETF_MIB_VERSION, NULL, NULL, ietf_mib, TRIPPLITE_SYSOID, NULL };
/* FIXME: Duplicate the line below to fix an issue with the code generator (nut-snmpinfo.py -> line is discarding) */
/*mib2nut_info_t ietf = { "ietf", IETF_MIB_VERSION, IETF_OID_UPS_MIB "4.1.0", IETF_OID_UPS_MIB "1.1.0", ietf_mib, IETF_SYSOID, NULL };*/
mib2nut_info_t ietf = { "ietf", IETF_MIB_VERSION, IETF_OID_UPS_MIB "4.1.0", IETF_OID_UPS_MIB "1.1.0", ietf_mib, IETF_SYSOID, NULL };

View file

@ -27,7 +27,7 @@
#include <string.h>
#define DRIVER_NAME "ISBMEX UPS driver"
#define DRIVER_VERSION "0.06"
#define DRIVER_VERSION "0.07"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -40,6 +40,7 @@ upsdrv_info_t upsdrv_info = {
{ NULL }
};
/* FIXME: Replace with proper upsdebugx() et al */
#define xDEBUG
#ifdef DEBUG
@ -52,7 +53,7 @@ upsdrv_info_t upsdrv_info = {
#define MAXTRIES 15
/* #define IGNCHARS "" */
float lagrange(unsigned int vbyte)
static float lagrange(unsigned int vbyte)
{
float f0, f1, f2, f3, f4, f5, f6;
float a, b, c, d, e, g, h;
@ -100,7 +101,7 @@ float lagrange(unsigned int vbyte)
return a + b + c + d + e + g + h;
}
float interpol(float vbytes)
static float interpol(float vbytes)
{
const int x[7]={75,83,87,98,103,118,145};
const float f[7]={96.0,102.0,105.0,113.0,116.0,124.0,140.0};
@ -141,173 +142,187 @@ void upsdrv_initinfo(void)
dstate_setinfo("input.transfer.high", "140.0"); /* defined */
dstate_setinfo("output.voltage", "120.0"); /* defined */
/* addinfo(INFO_, "", 0, 0); */
/*printf("Using %s %s on %s\n", getdata(INFO_MFR), getdata(INFO_MODEL), device_path);*/
/* addinfo(INFO_, "", 0, 0); */
/*printf("Using %s %s on %s\n", getdata(INFO_MFR), getdata(INFO_MODEL), device_path);*/
}
static const char *getpacket(int *we_know){
fd_set readfds;
struct timeval tv;
int bytes_per_packet=0;
int ret;
static const char *packet_id=NULL;
static char buf[256];
const char *s;
ssize_t r;
fd_set readfds;
struct timeval tv;
int bytes_per_packet=0;
int ret;
static const char *packet_id=NULL;
static char buf[256];
const char *s;
ssize_t r;
bytes_per_packet=*we_know;
D(printf("getpacket with %d\n",bytes_per_packet);)
FD_ZERO(&readfds);
FD_SET(upsfd,&readfds);
bytes_per_packet=*we_know;
D(printf("getpacket with %d\n",bytes_per_packet);)
FD_ZERO(&readfds);
FD_SET(upsfd,&readfds);
/* Wait up to 2 seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
ret=select(upsfd+1, &readfds, NULL, NULL, &tv);
if (!ret) {
s="Nothing received from UPS. Check cable conexion";
upslogx(LOG_ERR, "%s", s);
D(printf("%s\n",s);)
return NULL;
}
tv.tv_sec = 5;
tv.tv_usec = 0;
r=read(upsfd,buf,255);
D(printf("%d bytes read: ",r);)
buf[r]=0;
if (bytes_per_packet && r < bytes_per_packet){
ssize_t rr;
D(printf("short read...\n");)
usleep(500000);
tv.tv_sec = 2;
tv.tv_usec = 0;
ret=select(upsfd+1, &readfds, NULL, NULL, &tv);
if (!ret) return NULL;
rr=read(upsfd,buf+r,255-r);
r += rr;
if (r < bytes_per_packet) return NULL;
}
if (!bytes_per_packet){ /* packet size determination */
/* if (r%10 && r%9) {
printf("disregarding incomplete packet\n");
return NULL;
}*/
if (r%10==0) *we_know=10;
else if (r%9==0) *we_know=9;
return NULL;
}
/* by here we have bytes_per_packet and a complete packet */
/* lets check if within the complete packet we have a valid packet */
if (bytes_per_packet == 10) packet_id="&&&"; else packet_id="***";
s=strstr(buf,packet_id);
/* check validity of packet */
if (!s) {
s="isbmex: no valid packet signature!";
upslogx(LOG_ERR, "%s", s);
D(printf("%s\n",s);)
*we_know=0;
return NULL;
}
D(if (s != buf) printf("overlapping packet received\n");)
if ((int) strlen(s) < bytes_per_packet) {
D(printf("incomplete packet information\n");)
return NULL;
}
ret=select(upsfd+1, &readfds, NULL, NULL, &tv);
if (!ret) {
s="Nothing received from UPS. Check cable conexion";
upslogx(LOG_ERR, "%s", s);
D(printf("%s\n",s);)
return NULL;
}
r=read(upsfd,buf,255);
D(printf("%zd bytes read: ",r);)
buf[r]=0;
if (bytes_per_packet && r < bytes_per_packet){
ssize_t rr;
D(printf("short read...\n");)
usleep(500000);
tv.tv_sec = 2;
tv.tv_usec = 0;
ret=select(upsfd+1, &readfds, NULL, NULL, &tv);
if (!ret) return NULL;
/* Casting is okay since bytes_per_packet is small
* and r is smaller, so 255-r is positive */
assert (r <= 255);
rr = read(upsfd, buf+r, (size_t)(255-r));
r += rr;
if (r < bytes_per_packet) return NULL;
}
if (!bytes_per_packet){ /* packet size determination */
/*
if (r%10 && r%9) {
printf("disregarding incomplete packet\n");
return NULL;
}
*/
if (r%10==0)
*we_know=10;
else if (r%9==0)
*we_know=9;
return NULL;
}
/* by here we have bytes_per_packet and a complete packet */
/* lets check if within the complete packet we have a valid packet */
if (bytes_per_packet == 10)
packet_id="&&&";
else
packet_id="***";
s=strstr(buf,packet_id);
/* check validity of packet */
if (!s) {
s="isbmex: no valid packet signature!";
upslogx(LOG_ERR, "%s", s);
D(printf("%s\n",s);)
*we_know=0;
return NULL;
}
D(if (s != buf) printf("overlapping packet received\n");)
if ((int) strlen(s) < bytes_per_packet) {
D(printf("incomplete packet information\n");)
return NULL;
}
#ifdef DEBUG
printf("Got signal:");
{int i;for (i=0;i<strlen(s);i++) printf(" <%d>",(unsigned char)s[i]);}
printf("\n");
printf("Got signal:");
{int i;for (i=0;i<strlen(s);i++) printf(" <%d>",(unsigned char)s[i]);}
printf("\n");
#endif
return s;
return s;
}
void upsdrv_updateinfo(void)
{
static float high_volt=-1, low_volt=999;
const char *buf=NULL;
char buf2[17];
int i;
static int bytes_per_packet=0;
static float high_volt=-1, low_volt=999;
const char *buf=NULL;
char buf2[17];
int i;
static int bytes_per_packet=0;
for (i=0;i<5;i++) {
if ((buf=getpacket(&bytes_per_packet)) != NULL) break;
}
if (!bytes_per_packet || !buf) {
dstate_datastale();
for (i=0;i<5;i++) {
if ((buf=getpacket(&bytes_per_packet)) != NULL) break;
}
if (!bytes_per_packet || !buf) {
dstate_datastale();
return;
}
/* do the parsing */
{
float in_volt,battpct,acfreq;
double d;
D(printf("parsing (%d bytes per packet)\n",bytes_per_packet);)
/* input voltage :*/
if (bytes_per_packet==9) {
in_volt = lagrange((unsigned char)buf[3]);
} else {
in_volt = interpol(sqrt((float)((unsigned char)buf[3]*256+(unsigned char)buf[4])));
}
snprintf(buf2,16,"%5.1f",in_volt);
D(printf("utility=%s\n",buf2);)
dstate_setinfo("input.voltage", "%s", buf2);
if (in_volt >= high_volt) high_volt=in_volt;
snprintf(buf2,16,"%5.1f",high_volt);
D(printf("highvolt=%s\n",buf2);)
dstate_setinfo("input.voltage.maximum", "%s", buf2);
if (in_volt <= low_volt) low_volt=in_volt;
snprintf(buf2,16,"%5.1f",low_volt);
D(printf("lowvolt=%s\n",buf2);)
dstate_setinfo("input.voltage.minimum", "%s", buf2);
battpct = ((double)((unsigned char)buf[(bytes_per_packet==10)?5:4])-168.0)*(100.0/(215.0-168.0));
snprintf(buf2,16,"%5.1f",battpct);
D(printf("battpct=%s\n",buf2);)
dstate_setinfo("battery.charge", "%s", buf2);
d=(unsigned char)buf[(bytes_per_packet==10)?6:5]*256
+ (unsigned char)buf[(bytes_per_packet==10)?7:6];
acfreq = 1000000/d;
snprintf(buf2,16,"%5.2f",acfreq);
D(printf("acfreq=%s\n",buf2);)
dstate_setinfo("input.frequency", "%s", buf2);
D(printf("status: ");)
status_init();
switch (buf[(bytes_per_packet==10)?8:7]){
case 48: break; /* normal operation */
case 49: D(printf("BOOST ");)
status_set("BOOST");
break;
case 50: D(printf("TRIM ");)
status_set("TRIM");
break;
default: break;
}
switch (buf[(bytes_per_packet==10)?9:8]){
case 48: D(printf("OL ");)
status_set("OL");
break;
case 50: D(printf("LB ");)
status_set("LB");
/* break; */
/* FIXME? Can this device set independently LB and OB? */
goto fallthrough_LB_means_OB;
/* FALLTHRU */
case 49:
fallthrough_LB_means_OB:
D(printf("OB ");)
status_set("OB");
break;
default: break;
}
D(printf("\n");)
status_commit();
}
dstate_dataok();
return;
}
/* do the parsing */
{
float in_volt,battpct,acfreq;
double d;
D(printf("parsing (%d bytes per packet)\n",bytes_per_packet);)
/* input voltage :*/
if (bytes_per_packet==9) {
in_volt = lagrange((unsigned char)buf[3]);
} else {
in_volt = interpol(sqrt((float)((unsigned char)buf[3]*256+(unsigned char)buf[4])));
}
snprintf(buf2,16,"%5.1f",in_volt);
D(printf("utility=%s\n",buf2);)
dstate_setinfo("input.voltage", "%s", buf2);
if (in_volt >= high_volt) high_volt=in_volt;
snprintf(buf2,16,"%5.1f",high_volt);
D(printf("highvolt=%s\n",buf2);)
dstate_setinfo("input.voltage.maximum", "%s", buf2);
if (in_volt <= low_volt) low_volt=in_volt;
snprintf(buf2,16,"%5.1f",low_volt);
D(printf("lowvolt=%s\n",buf2);)
dstate_setinfo("input.voltage.minimum", "%s", buf2);
battpct = ((double)((unsigned char)buf[(bytes_per_packet==10)?5:4])-168.0)*(100.0/(215.0-168.0));
snprintf(buf2,16,"%5.1f",battpct);
D(printf("battpct=%s\n",buf2);)
dstate_setinfo("battery.charge", "%s", buf2);
d=(unsigned char)buf[(bytes_per_packet==10)?6:5]*256
+ (unsigned char)buf[(bytes_per_packet==10)?7:6];
acfreq = 1000000/d;
snprintf(buf2,16,"%5.2f",acfreq);
D(printf("acfreq=%s\n",buf2);)
dstate_setinfo("input.frequency", "%s", buf2);
D(printf("status: ");)
status_init();
switch (buf[(bytes_per_packet==10)?8:7]){
case 48: break; /* normal operation */
case 49: D(printf("BOOST ");)
status_set("BOOST");
break;
case 50: D(printf("TRIM ");)
status_set("TRIM");
default: break;
}
switch (buf[(bytes_per_packet==10)?9:8]){
case 48: D(printf("OL ");)
status_set("OL");
break;
case 50: D(printf("LB ");)
status_set("LB");
case 49: D(printf("OB ");)
status_set("OB");
break;
default: break;
}
D(printf("\n");)
status_commit();
}
dstate_dataok();
return;
}
void upsdrv_shutdown(void)
@ -316,9 +331,9 @@ void upsdrv_shutdown(void)
* contact closure. Some ISB models with serial
* support support contact closure, some don't.
* If yours does support it, then a 12V signal
* on pin 9 does the trick (only when ups is
* on pin 9 does the trick (only when ups is
* on OB condition) */
/*
/*
* here try to do the pin 9 trick, if it does not
* work, else:*/
/* fatalx(EXIT_FAILURE, "Shutdown only supported with the Generic Driver, type 6 and special cable"); */

View file

@ -18,11 +18,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "main.h"
#include "serial.h"
#include "attribute.h"
#define DRIVER_NAME "IVT Solar Controller driver"
#define DRIVER_VERSION "0.02"
#define DRIVER_VERSION "0.03"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -49,10 +51,11 @@ static struct {
float temperature;
} battery;
static int ivt_status(void)
static ssize_t ivt_status(void)
{
char reply[SMALLBUF];
int ret, i, j = 0;
int i, j = 0;
ssize_t ret;
ser_flush_io(upsfd);
@ -73,7 +76,7 @@ static int ivt_status(void)
upsdebugx(3, "send: F");
sleep(1); /* allow controller some time to digest this */
/*
* read: R:12,57;- 1,1;20;12,57;13,18;- 2,1; 1,5;\n
*/
@ -90,7 +93,7 @@ static int ivt_status(void)
}
upsdebugx(3, "read: %.*s", (int)strcspn(reply, "\r\n"), reply);
upsdebug_hex(4, " \\_", reply, ret);
upsdebug_hex(4, " \\_", reply, (size_t)ret);
for (i = 0; i < ret; i++) {
switch(reply[i])
@ -112,7 +115,7 @@ static int ivt_status(void)
ret = sscanf(reply, "R:%f;%f;%f;%f;%f;%f;%f;", &battery.voltage.act, &battery.current.act, &battery.temperature,
&battery.voltage.min, &battery.voltage.max, &battery.current.min, &battery.current.max);
upsdebugx(3, "Parsed %d parameters from reply", ret);
upsdebugx(3, "Parsed %zd parameters from reply", ret);
return ret;
}
@ -123,10 +126,10 @@ static int instcmd(const char *cmdname, const char *extra)
return STAT_INSTCMD_HANDLED;
}
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
return STAT_INSTCMD_UNKNOWN;
}
void upsdrv_initinfo(void)
{
if (ivt_status() < 7) {
@ -177,6 +180,9 @@ void upsdrv_updateinfo(void)
dstate_dataok();
}
void upsdrv_shutdown(void)
__attribute__((noreturn));
void upsdrv_shutdown(void)
{
while (1) {

236
drivers/legrand-hid.c Normal file
View file

@ -0,0 +1,236 @@
/* legrand-hid.c - subdriver to monitor Legrand USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2012 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2013 Charles Lepple <clepple+nut@gmail.com>
* 2018 Gabriele Taormina <gabriele.taormina@legrand.com>, for Legrand
*
* 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 "common.h"
#include "usbhid-ups.h"
#include "legrand-hid.h"
#include "main.h"
#include "usb-common.h"
#define LEGRAND_HID_VERSION "Legrand HID 0.2"
/* Legrand VendorID and ProductID */
#define LEGRAND_VID 0x1cb0 /* Legrand */
#define LEGRAND_PID_PDU 0x0038 /* Keor PDU model (800VA) */
#define LEGRAND_PID_SP 0x0032 /* Keor SP model (600, 800, 1000, 1500, 2000VA version) */
static void *disable_interrupt_pipe(USBDevice_t *device)
{
NUT_UNUSED_VARIABLE(device);
if (!use_interrupt_pipe)
return NULL;
use_interrupt_pipe = FALSE;
upslogx(LOG_INFO, "interrupt pipe disabled (add 'pollonly' flag to 'ups.conf' to get rid of this message)");
return NULL;
}
/* USB IDs device table */
static usb_device_id_t legrand_usb_device_table[] = {
{ USB_DEVICE(LEGRAND_VID, LEGRAND_PID_PDU), disable_interrupt_pipe }, /* Legrand Keor PDU */
{ USB_DEVICE(LEGRAND_VID, LEGRAND_PID_SP), disable_interrupt_pipe }, /* Legrand Keor SP */
/* Terminating entry */
{ 0, 0, NULL }
};
/* --------------------------------------------------------------- */
/* Vendor-specific usage table */
/* --------------------------------------------------------------- */
/* LEGRAND usage table */
static usage_lkp_t legrand_usage_lkp[] = {
{ NULL, 0 }
};
static usage_tables_t legrand_utab[] = {
legrand_usage_lkp,
hid_usage_lkp,
NULL,
};
static const char *legrand_times10(double value)
{
static char buf[20];
snprintf(buf, sizeof(buf), "%0.1f", value * 10);
return buf;
}
static info_lkp_t legrand_times10_info[] = {
{ 0, NULL, legrand_times10, NULL },
{ 0, NULL, NULL, NULL }
};
static const char *legrand_times100k(double value)
{
static char buf[20];
snprintf(buf, sizeof(buf), "%0.1f", value * 100000);
return buf;
}
static info_lkp_t legrand_times100k_info[] = {
{ 0, NULL, legrand_times100k, NULL },
{ 0, NULL, NULL, NULL }
};
static const char *legrand_times1M(double value)
{
static char buf[20];
snprintf(buf, sizeof(buf), "%0.1f", value * 1000000);
return buf;
}
static info_lkp_t legrand_times1M_info[] = {
{ 0, NULL, legrand_times1M, NULL },
{ 0, NULL, NULL, NULL }
};
static const char *legrand_times10M(double value)
{
static char buf[20];
snprintf(buf, sizeof(buf), "%0.1f", value * 10000000);
return buf;
}
static info_lkp_t legrand_times10M_info[] = {
{ 0, NULL, legrand_times10M, NULL },
{ 0, NULL, NULL, NULL }
};
/* --------------------------------------------------------------- */
/* HID2NUT lookup table */
/* --------------------------------------------------------------- */
static hid_info_t legrand_hid2nut[] = {
/* Input Data */
{ "input.voltage", 0, 0, "UPS.Input.Voltage", NULL, "%.0f", 0, NULL },
{ "input.voltage", 0, 0, "UPS.PowerConverter.Input.Voltage", NULL, "%.0f", 0, legrand_times1M_info },
{ "input.transfer.high", 0, 0, "UPS.Input.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "input.transfer.high", 0, 0, "UPS.PowerConverter.Output.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_STATIC, legrand_times10_info },
{ "input.transfer.low", 0, 0, "UPS.Input.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "input.transfer.low", 0, 0, "UPS.PowerConverter.Output.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "input.voltage.nominal", 0, 0, "UPS.Input.ConfigVoltage", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "input.voltage.nominal", 0, 0, "UPS.Flow.ConfigVoltage", NULL, "%.0f", HU_FLAG_STATIC, NULL },
/* Battery Data */
{ "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.0f", HU_FLAG_STATIC, divide_by_10_conversion },
{ "battery.voltage.nominal", 0, 0, "UPS.BatterySystem.Battery.ConfigVoltage", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.0f", 0, divide_by_10_conversion },
{ "battery.voltage", 0, 0, "UPS.BatterySystem.Battery.Voltage", NULL, "%.0f", 0, legrand_times100k_info },
{ "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL },
{ "battery.runtime", 0, 0, "UPS.PowerSummary.RuntimeToEmpty", NULL, "%.0f", 0, NULL },
{ "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "battery.charge.low", 0, 0, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_STATIC, NULL },
/* Output Data */
{ "output.voltage", 0, 0, "UPS.Output.Voltage", NULL, "%.0f", 0, NULL },
{ "output.voltage", 0, 0, "UPS.PowerConverter.Output.Voltage", NULL, "%.0f", 0, legrand_times10M_info },
{ "output.frequency", 0, 0, "UPS.Output.Frequency", NULL, "%.0f", 0, NULL },
{ "ups.load", 0, 0, "UPS.Output.PercentLoad", NULL, "%.0f", 0, NULL },
{ "ups.load", 0, 0, "UPS.OutletSystem.Outlet.PercentLoad", NULL, "%.0f", 0, NULL },
{ "ups.realpower.nominal", 0, 0, "UPS.Output.ConfigActivePower", NULL, "%.0f", HU_FLAG_STATIC, NULL },
{ "ups.realpower.nominal", 0, 0, "UPS.Flow.ConfigApparentPower", NULL, "%.0f", HU_FLAG_STATIC, NULL },
/* UPS Status */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info },
{ "BOOL", 0, 0, "UPS.Output.Overload", NULL, NULL, HU_FLAG_QUICK_POLL, overload_info },
/* Delays */
{ "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.OutletSystem.Outlet.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL },
{ "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.OutletSystem.Outlet.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL },
{ "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL },
{ "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL },
{ "load.off.delay", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL },
{ "load.on.delay", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL },
{ "load.off.delay", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL },
{ "load.on.delay", 0, 0, "UPS.Output.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL },
/* Battery Testing */
{ "test.battery.start.quick", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "1", HU_TYPE_CMD, NULL },
{ "test.battery.start.deep", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "2", HU_TYPE_CMD, NULL },
{ "test.battery.stop", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "3", HU_TYPE_CMD, NULL },
{ "test.battery.start.quick", 0, 0, "UPS.Output.Test", NULL, "1", HU_TYPE_CMD, NULL },
{ "test.battery.start.deep", 0, 0, "UPS.Output.Test", NULL, "2", HU_TYPE_CMD, NULL },
{ "test.battery.stop", 0, 0, "UPS.Output.Test", NULL, "3", HU_TYPE_CMD, NULL },
/* Buzzer */
{ "beeper.enable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL },
{ "beeper.disable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL },
/* end of structure. */
{ NULL, 0, 0, NULL, NULL, NULL, 0, NULL }
};
static const char *legrand_format_model(HIDDevice_t *hd)
{
return hd->Product;
}
static const char *legrand_format_mfr(HIDDevice_t *hd)
{
return hd->Vendor ? hd->Vendor : "Legrand";
}
static const char *legrand_format_serial(HIDDevice_t *hd)
{
return hd->Serial;
}
/* this function allows the subdriver to "claim" a device: return 1 if
* the device is supported by this subdriver, else 0. */
static int legrand_claim(HIDDevice_t *hd)
{
int status = is_usb_device_supported(legrand_usb_device_table, hd);
switch (status)
{
case POSSIBLY_SUPPORTED:
/* by default, reject, unless the productid option is given */
if (getval("productid"))
return 1;
possibly_supported("Legrand", hd);
return 0;
case SUPPORTED:
return 1;
case NOT_SUPPORTED:
default:
return 0;
}
}
subdriver_t legrand_subdriver = {
LEGRAND_HID_VERSION,
legrand_claim,
legrand_utab,
legrand_hid2nut,
legrand_format_model,
legrand_format_mfr,
legrand_format_serial,
fix_report_desc,
};

Some files were not shown because too many files have changed in this diff Show more