Imported Upstream version 2.6.1

This commit is contained in:
Arnaud Quette 2011-06-01 22:31:49 +02:00
parent 459aaf9392
commit a367d9bc54
178 changed files with 4651 additions and 3279 deletions

View file

@ -68,7 +68,6 @@ DIST_COMMON = $(dist_noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 \

View file

@ -146,16 +146,38 @@ static usage_lkp_t apc_usage_lkp[] = {
{ "APCProbe1", 0xff860007 },
{ "APCProbe2", 0xff860008 },
{ "APCBattReplaceDate", 0xff860016 },
/* usage seen in dumps but unknown:
* - ff860018
* Path: UPS.Battery.ff860018, Type: Feature, ReportID: 0x48, Offset: 0, Size: 32, Value: 0
*/
{ "APCBattCapBeforeStartup", 0xff860019 }, /* FIXME: exploit */
/* usage seen in dumps but unknown:
* - ff86001a
* Path: UPS.Battery.ff86001a, Type: Input, ReportID: 0x1b, Offset: 0, Size: 8, Value: 3
* Path: UPS.Battery.ff86001a, Type: Feature, ReportID: 0x1b, Offset: 0, Size: 8, Value: 3
* - ff86001b
* Path: UPS.Battery.ff86001b, Type: Input, ReportID: 0x1c, Offset: 0, Size: 8, Value: 0
* Path: UPS.Battery.ff86001b, Type: Feature, ReportID: 0x1c, Offset: 0, Size: 8, Value: 0
* - ff860023
* Path: UPS.ff860001.ff860023, Type: Feature, ReportID: 0x60, Offset: 0, Size: 16, Value: 0
* - ff860024
* Path: UPS.Battery.ff860024, Type: Feature, ReportID: 0x47, Offset: 0, Size: 8, Value: 245
* Path: UPS.PowerConverter.ff860024, Type: Feature, ReportID: 0x51, Offset: 0, Size: 8, Value: 145
* - ff860025
* Path: UPS.ff860001.ff860025, Type: Feature, ReportID: 0x62, Offset: 0, Size: 32, Value: 0
* - ff860026
* Path: UPS.ff860001.ff860026, Type: Feature, ReportID: 0x61, Offset: 0, Size: 8, Value: 10
* - ff860027
* Path: UPS.ff860027, Type: Feature, ReportID: 0x3e, Offset: 0, Size: 32, Value: 0
* - ff860028
* Path: UPS.ff860028, Type: Feature, ReportID: 0x3f, Offset: 0, Size: 32, Value: 0
* - ff860030
* Path: UPS.Output.ff860030, Type: Feature, ReportID: 0x42, Offset: 0, Size: 16, Value: 5.8
*/
{ "APC_UPS_FirmwareRevision", 0xff860042 },
{ "APCLineFailCause", 0xff860052 },
{ "APCStatusFlag", 0xff860060 },
{ "APCSensitivity", 0xff860061 },
/* usage seen in dumps but unknown:
* - ff860027, ff860028
* Path: UPS.ff860027, Type: Feature, ReportID: 0x3e, Offset: 0,
* Size: 32, Value:0.000000
*/
{ "APCPanelTest", 0xff860072 }, /* FIXME: exploit */
{ "APCShutdownAfterDelay", 0xff860076 }, /* FIXME: exploit */
{ "APC_USB_FirmwareRevision", 0xff860079 }, /* FIXME: exploit */
@ -164,14 +186,24 @@ static usage_lkp_t apc_usage_lkp[] = {
{ "APCDelayBeforeStartup", 0xff86007e }, /* FIXME: exploit */
/* usage seen in dumps but unknown:
* - ff860080
* Path: UPS.PresentStatus.ff860080, Type: Input, ReportID: 0x33,
* Offset: 12, Size: 1, Value: 0.000000
* - ff86001a
* Path: UPS.Battery.ff86001a, Type: Input, ReportID: 0x1b,
* Offset: 0, Size: 8, Value: 3.000000
* - ff86001b
* Path: UPS.Battery.ff86001b, Type: Input, ReportID: 0x1c,
* Offset: 0, Size: 8, Value: 0.000000
* Path: UPS.PresentStatus.ff860080, Type: Input, ReportID: 0x33, Offset: 12, Size: 1, Value: 0
* Path: UPS.PresentStatus.ff860080, Type: Feature, ReportID: 0x33, Offset: 12, Size: 1, Value: 0
* Path: UPS.PowerSummary.PresentStatus.ff860080, Type: Input, ReportID: 0x07, Offset: 12, Size: 1, Value: 0
* Path: UPS.PowerSummary.PresentStatus.ff860080, Type: Feature, ReportID: 0x07, Offset: 12, Size: 1, Value: 0
* - ff860090, ff860091
* Path: UPS.ff860090.ff860091, Type: Feature, ReportID: 0x8c, Offset: 0, Size: 8, Value: 1.000000
* - ff860092
* Path: UPS.ff860090.ff860092, Type: Feature, ReportID: 0x8d, Offset: 0, Size: 8, Value: 25.000000
* - ff860093
* Path: UPS.ff860090.ff860093, Type: Feature, ReportID: 0x8e, Offset: 0, Size: 8, Value: 83.000000
* - ff860094
* Path: UPS.ff860090.ff860094, Type: Feature, ReportID: 0x8f, Offset: 0, Size: 8, Value: 0.000000
* - ff860095
* Path: UPS.ff860090.ff860095, Type: Feature, ReportID: 0x90, Offset: 0, Size: 8, Value: 1.000000
* - ff860096
* Path: UPS.ff860090.ff860096, Type: Feature, ReportID: 0x91, Offset: 0, Size: 16, Value: 4.000000
* - ff860097
* Path: UPS.ff860090.ff860097, Type: Feature, ReportID: 0x92, Offset: 0, Size: 16, Value: 4.000000
*/
/* Note (Arnaud): BUP stands for BackUPS Pro
@ -269,12 +301,12 @@ static hid_info_t apc_hid2nut[] = {
{ "ups.timer.start", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL},
{ "ups.timer.shutdown", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL},
{ "ups.timer.reboot", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL},
{ "ups.test.result", 0, 0, "UPS.Battery.Test", NULL, "%s", 0, test_read_info },
{ "ups.beeper.status", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "%s", 0, beeper_info },
{ "ups.mfr.date", 0, 0, "UPS.ManufacturerDate", NULL, "%s", 0, date_conversion },
{ "ups.mfr.date", 0, 0, "UPS.PowerSummary.ManufacturerDate", NULL, "%s", 0, date_conversion }, /* Back-UPS 500 */
{ "ups.realpower.nominal", 0, 0, "UPS.PowerConverter.ConfigActivePower", NULL, "%.0f", 0, NULL },
{ "ups.realpower.nominal", 0, 0, "UPS.PowerConverter.ConfigActivePower", NULL, "%.0f", 0, NULL },
{ "ups.realpower.nominal", 0, 0, "UPS.Output.ConfigActivePower", NULL, "%.0f", 0, NULL },
/* the below one need to be discussed as we might need to complete
* the ups.test sub collection
@ -306,13 +338,18 @@ static hid_info_t apc_hid2nut[] = {
/* Input page */
{ "input.voltage", 0, 0, "UPS.Input.Voltage", NULL, "%.1f", 0, NULL },
{ "input.voltage.nominal", 0, 0, "UPS.Input.ConfigVoltage", NULL, "%.0f", 0, NULL },
{ "input.transfer.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "input.transfer.high", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
/* used by APC BackUPS RS */
{ "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 },
{ "output.current", 0, 0, "UPS.Output.Current", NULL, "%.2f", 0, NULL },
{ "output.frequency", 0, 0, "UPS.Output.Frequency", NULL, "%.1f", 0, NULL },
/* Environmental page */
{ "ambient.temperature", 0, 0, "UPS.APCEnvironment.APCProbe1.Temperature", NULL, "%s", 0, kelvin_celsius_conversion },
@ -352,7 +389,9 @@ static hid_info_t apc_hid2nut[] = {
{ "load.on.delay", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL },
{ "shutdown.stop", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL },
{ "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 },

View file

@ -24,7 +24,7 @@
#include "apcsmart.h"
#define DRIVER_NAME "APC Smart protocol driver"
#define DRIVER_VERSION "2.03"
#define DRIVER_VERSION "2.1"
static upsdrv_info_t table_info = {
"APC command table",
@ -38,8 +38,9 @@ static upsdrv_info_t table_info = {
upsdrv_info_t upsdrv_info = {
DRIVER_NAME,
DRIVER_VERSION,
"Russell Kroll <rkroll@exploits.org>\n" \
"Nigel Metheringham <Nigel.Metheringham@Intechnology.co.uk>",
"Russell Kroll <rkroll@exploits.org>\n"
"Nigel Metheringham <Nigel.Metheringham@Intechnology.co.uk>\n"
"Michal Soltys <soltys@ziu.info>",
DRV_STABLE,
{ &table_info, NULL }
};
@ -73,7 +74,7 @@ static apc_vartab_t *vartab_lookup_name(const char *var)
/* FUTURE: change to use function pointers */
/* convert APC formatting to NUT formatting */
static const char *convert_data(apc_vartab_t *cmd_entry, char *upsval)
static const char *convert_data(apc_vartab_t *cmd_entry, const char *upsval)
{
static char tmp[128];
int tval;
@ -178,6 +179,16 @@ static void alert_handler(char ch)
ups_status |= APC_STAT_RB;
break;
case '?': /* set OVER */
upsdebugx(4, "alert_handler: OVER");
ups_status |= APC_STAT_OVER;
break;
case '=': /* clear OVER */
upsdebugx(4, "alert_handler: not OVER");
ups_status &= ~APC_STAT_OVER;
break;
default:
upsdebugx(4, "alert_handler got 0x%02x (unhandled)", ch);
break;
@ -252,8 +263,10 @@ static int query_ups(const char *var, int first)
return 0;
}
/* already known to not be supported? */
if (vt->flags & APC_IGNORE)
/*
* not first run and already known to not be supported ?
*/
if (!first && !(vt->flags & APC_PRESENT))
return 0;
/* empty the input buffer (while allowing the alert handler to run) */
@ -278,11 +291,10 @@ static int query_ups(const char *var, int first)
ser_comm_good();
if ((ret < 1) || (!strcmp(temp, "NA"))) { /* not supported */
vt->flags |= APC_IGNORE;
if ((ret < 1) || (!strcmp(temp, "NA"))) /* not supported */
return 0;
}
vt->flags |= APC_PRESENT;
ptr = convert_data(vt, temp);
dstate_setinfo(vt->name, "%s", ptr);
@ -293,7 +305,7 @@ static void do_capabilities(void)
{
const char *ptr, *entptr;
char upsloc, temp[512], cmd, loc, etmp[16], *endtemp;
int nument, entlen, i, matrix, ret;
int nument, entlen, i, matrix, ret, valid;
apc_vartab_t *vt;
upsdebugx(1, "APC - About to get capabilities string");
@ -324,7 +336,7 @@ static void do_capabilities(void)
/* This should never happen since we only call
this if the REQ_CAPABILITIES command is supported
*/
upslogx(LOG_ERR, "ERROR: APC cannot do capabilites but said it could!");
upslogx(LOG_ERR, "ERROR: APC cannot do capabilities but said it could!");
return;
}
@ -333,8 +345,8 @@ static void do_capabilities(void)
endtemp = &temp[0] + strlen(temp);
if (temp[0] != '#') {
printf("Unrecognized capability start char %c\n", temp[0]);
printf("Please report this error [%s]\n", temp);
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!",
temp[0]);
@ -377,9 +389,10 @@ static void do_capabilities(void)
entptr = &ptr[4];
vt = vartab_lookup_char(cmd);
valid = vt && ((loc == upsloc) || (loc == '4'));
/* mark this as writable */
if (vt && ((loc == upsloc) || (loc == '4'))) {
if (valid) {
upsdebugx(1, "Supported capability: %02x (%c) - %s",
cmd, loc, vt->name);
@ -390,11 +403,10 @@ static void do_capabilities(void)
}
for (i = 0; i < nument; i++) {
snprintf(etmp, entlen + 1, "%s", entptr);
if (vt && ((loc == upsloc) || (loc == '4')))
dstate_addenum(vt->name, "%s",
convert_data(vt, etmp));
if (valid) {
snprintf(etmp, entlen + 1, "%s", entptr);
dstate_addenum(vt->name, "%s", convert_data(vt, etmp));
}
entptr += entlen;
}
@ -430,7 +442,6 @@ static int update_status(void)
ups_status = strtol(buf, 0, 16) & 0xff;
ups_status_set();
status_commit();
dstate_dataok();
return 1;
@ -466,10 +477,6 @@ static void protocol_verify(unsigned char cmd)
{
int i, found;
/* we might not care about this one */
if (strchr(CMD_IGN_CHARS, cmd))
return;
/* see if it's a variable */
for (i = 0; apc_vartab[i].name != NULL; i++) {
@ -531,27 +538,28 @@ static int firmware_table_lookup(void)
unsigned int i, j;
char buf[SMALLBUF];
upsdebugx(1, "Attempting firmware lookup");
upsdebugx(1, "Attempting firmware lookup using command 'V'");
ret = ser_send_char(upsfd, 'b');
ret = ser_send_char(upsfd, 'V');
if (ret != 1) {
upslog_with_errno(LOG_ERR, "getbaseinfo: ser_send_char failed");
upslog_with_errno(LOG_ERR, "firmware_table_lookup: ser_send_char failed");
return 0;
}
ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, IGNCHARS,
SER_WAIT_SEC, SER_WAIT_USEC);
/* see if this is an older version like an APC600 which doesn't
* response to 'a' or 'b' queries
/*
* Some UPSes support both 'V' and 'b'. As 'b' doesn't always return
* firmware version, we attempt that only if 'V' doesn't work.
*/
if ((ret < 1) || (!strcmp(buf, "NA"))) {
upsdebugx(1, "Attempting to contact older Smart-UPS version");
ret = ser_send_char(upsfd, 'V');
upsdebugx(1, "Attempting firmware lookup using command 'b'");
ret = ser_send_char(upsfd, 'b');
if (ret != 1) {
upslog_with_errno(LOG_ERR, "getbaseinfo: ser_send_char failed");
upslog_with_errno(LOG_ERR, "firmware_table_lookup: ser_send_char failed");
return 0;
}
@ -562,10 +570,10 @@ static int firmware_table_lookup(void)
upslog_with_errno(LOG_ERR, "firmware_table_lookup: ser_get_line failed");
return 0;
}
upsdebugx(2, "Firmware: [%s]", buf);
}
upsdebugx(2, "Firmware: [%s]", buf);
/* this will be reworked if we get a lot of these things */
if (!strcmp(buf, "451.2.I")) {
quirk_capability_overflow = 1;
@ -602,6 +610,10 @@ static void getbaseinfo(void)
int ret = 0;
char *alrts, *cmds, temp[512];
/*
* try firmware lookup first; we could start with 'a', but older models
* sometimes return other things than a command set
*/
if (firmware_table_lookup() == 1)
return;
@ -622,7 +634,6 @@ static void getbaseinfo(void)
SER_WAIT_SEC, SER_WAIT_USEC);
if ((ret < 1) || (!strcmp(temp, "NA"))) {
/* We have an old dumb UPS - go to specific code for old stuff */
oldapcsetup();
return;
@ -774,101 +785,276 @@ static int smartmode(void)
return 0; /* failure */
}
/*
* all shutdown commands should respond with 'OK' or '*'
*/
static int sdok(void)
{
char temp[16];
ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, IGNCHARS, SER_WAIT_SEC, SER_WAIT_USEC);
upsdebugx(4, "sdok: got \"%s\"", temp);
if (!strcmp(temp, "*") || !strcmp(temp, "OK")) {
upsdebugx(4, "Last issued shutdown command succeeded");
return 1;
}
upsdebugx(1, "Last issued shutdown command failed");
return 0;
}
/* soft hibernate: S - working only when OB, otherwise ignored */
static int sdcmd_S(int dummy)
{
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
upsdebugx(1, "Issuing soft hibernate");
ser_send_char(upsfd, APC_CMD_SOFTDOWN);
return sdok();
}
/* soft hibernate, hack version for CS 350 */
static int sdcmd_CS(int tval)
{
upsdebugx(1, "Using CS 350 'force OB' shutdown method");
if (tval & APC_STAT_OL) {
upsdebugx(1, "On-line - forcing OB temporarily");
ser_send_char(upsfd, 'U');
usleep(UPSDELAY);
}
return sdcmd_S(tval);
}
/*
* hard hibernate: @nnn / @nn
* note: works differently for older and new models, see help function for
* detailed info
*/
static int sdcmd_ATn(int cnt)
{
int n = 0, mmax, ret;
const char *strval;
char timer[4];
mmax = cnt == 2 ? 99 : 999;
if ((strval = getval("wugrace"))) {
errno = 0;
n = strtol(strval, NULL, 10);
if (errno || n < 0 || n > mmax)
n = 0;
}
snprintf(timer, sizeof(timer), "%.*d", cnt, n);
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
upsdebugx(1, "Issuing hard hibernate with %d minutes additional wakeup delay", n*6);
ser_send_char(upsfd, APC_CMD_GRACEDOWN);
usleep(CMDLONGDELAY);
ser_send_pace(upsfd, UPSDELAY, "%s", timer);
ret = sdok();
if (ret || cnt == 3)
return ret;
/*
* "tricky" part - we tried @nn variation and it (unsurprisingly)
* failed; we have to abort the sequence with something bogus to have
* the clean state; newer upses will respond with 'NO', older will be
* silent (YMMV);
*/
ser_send_char(upsfd, APC_CMD_GRACEDOWN);
usleep(UPSDELAY);
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
return 0;
}
/* shutdown: K - delayed poweroff */
static int sdcmd_K(int dummy)
{
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
upsdebugx(1, "Issuing delayed poweroff");
ser_send_char(upsfd, APC_CMD_SHUTDOWN);
usleep(CMDLONGDELAY);
ser_send_char(upsfd, APC_CMD_SHUTDOWN);
return sdok();
}
/* shutdown: Z - immediate poweroff */
static int sdcmd_Z(int dummy)
{
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
upsdebugx(1, "Issuing immediate poweroff");
ser_send_char(upsfd, APC_CMD_OFF);
usleep(CMDLONGDELAY);
ser_send_char(upsfd, APC_CMD_OFF);
return sdok();
}
static int (*sdlist[])(int) = {
sdcmd_S,
sdcmd_ATn, /* for @nnn version */
sdcmd_K,
sdcmd_Z,
sdcmd_CS,
sdcmd_ATn, /* for @nn version */
};
#define SDIDX_S 0
#define SDIDX_AT3N 1
#define SDIDX_K 2
#define SDIDX_Z 3
#define SDIDX_CS 4
#define SDIDX_AT2N 5
#define SDCNT 6
static void upsdrv_shutdown_simple(int status)
{
unsigned int sdtype = 0;
char *strval;
if ((strval = getval("sdtype"))) {
errno = 0;
sdtype = strtol(strval, NULL, 10);
if (errno || sdtype < 0 || sdtype > 6)
sdtype = 0;
}
switch (sdtype) {
case 6: /* hard hibernate */
sdcmd_ATn(3);
break;
case 5: /* "hack nn" hard hibernate */
sdcmd_ATn(2);
break;
case 4: /* special hack for CS 350 and similar models */
sdcmd_CS(status);
break;
case 3: /* delayed poweroff */
sdcmd_K(0);
break;
case 2: /* instant poweroff */
sdcmd_Z(0);
break;
case 1:
/*
* Send a combined set of shutdown commands which can work
* better if the UPS gets power during shutdown process
* Specifically it sends both the soft shutdown 'S' and the
* hard hibernate '@nnn' commands
*/
upsdebugx(1, "UPS - currently %s - sending soft/hard hibernate commands",
(status & APC_STAT_OL) ? "on-line" : "on battery");
/* S works only when OB */
if ((status & APC_STAT_OB) && sdcmd_S(0))
break;
sdcmd_ATn(3);
break;
default:
/*
* Send @nnn or S, depending on OB / OL status
*/
if (status & APC_STAT_OL) /* on line */
sdcmd_ATn(3);
else
sdcmd_S(0);
}
}
static void upsdrv_shutdown_advanced(int status)
{
const char *strval;
const char deforder[] = {48 + SDIDX_S,
48 + SDIDX_AT3N,
48 + SDIDX_K,
48 + SDIDX_Z,
0};
size_t i;
int n;
strval = getval("advorder");
/* sanitize advorder */
if (!strval || !strlen(strval) || strlen(strval) > SDCNT)
strval = deforder;
for (i = 0; i < strlen(strval); i++) {
if (strval[i] - 48 < 0 || strval[i] - 48 >= SDCNT) {
strval = deforder;
break;
}
}
/*
* try each method in the list with a little bit of handling in certain
* cases
*/
for (i = 0; i < strlen(strval); i++) {
switch (strval[i] - 48) {
case SDIDX_CS:
n = status;
break;
case SDIDX_AT3N:
n = 3;
break;
case SDIDX_AT2N:
default:
n = 2;
}
if (sdlist[strval[i] - 48](n))
break; /* finish if command succeeded */
}
}
/* power down the attached load immediately */
void upsdrv_shutdown(void)
{
char temp[32];
int ret, tval, sdtype = 0;
int ret, status;
if (!smartmode())
printf("Detection failed. Trying a shutdown command anyway.\n");
upsdebugx(1, "SM detection failed. Trying a shutdown command anyway");
/* check the line status */
ret = ser_send_char(upsfd, APC_STATUS);
if (ret == 1) {
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 < 1) {
printf("Status read failed! Assuming on battery state\n");
tval = APC_STAT_LB | APC_STAT_OB;
upsdebugx(1, "Status read failed ! Assuming on battery state");
status = APC_STAT_LB | APC_STAT_OB;
} else {
tval = strtol(temp, 0, 16);
status = strtol(temp, 0, 16);
}
} else {
printf("Status request failed; assuming on battery state\n");
tval = APC_STAT_LB | APC_STAT_OB;
upsdebugx(1, "Status request failed; assuming on battery state");
status = APC_STAT_LB | APC_STAT_OB;
}
if (testvar("sdtype"))
sdtype = atoi(getval("sdtype"));
switch (sdtype) {
case 4: /* special hack for CS 350 and similar models */
printf("Using CS 350 'force OB' shutdown method\n");
if (tval & APC_STAT_OL) {
printf("On line - forcing OB temporarily\n");
ser_send_char(upsfd, 'U');
}
ser_send_char(upsfd, 'S');
break;
case 3: /* shutdown with grace period */
printf("Sending delayed power off command to UPS\n");
ser_send_char(upsfd, APC_CMD_SHUTDOWN);
usleep(CMDLONGDELAY);
ser_send_char(upsfd, APC_CMD_SHUTDOWN);
break;
case 2: /* instant shutdown */
printf("Sending power off command to UPS\n");
ser_send_char(upsfd, APC_CMD_OFF);
usleep(CMDLONGDELAY);
ser_send_char(upsfd, APC_CMD_OFF);
break;
case 1:
/* Send a combined set of shutdown commands which can work better */
/* if the UPS gets power during shutdown process */
/* Specifically it sends both the soft shutdown 'S' */
/* and the powerdown after grace period - '@000' commands */
printf("UPS - currently %s - sending shutdown/powerdown\n",
(tval & APC_STAT_OL) ? "on-line" : "on battery");
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
ser_send_pace(upsfd, UPSDELAY, "S@000");
break;
default:
/* @000 - shutdown after 'p' grace period */
/* - returns after 000 minutes (i.e. right away) */
/* S - shutdown after 'p' grace period, only on battery */
/* returns after 'e' charge % plus 'r' seconds */
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
if (tval & APC_STAT_OL) { /* on line */
printf("On line, sending shutdown+return command...\n");
ser_send_pace(upsfd, UPSDELAY, "@000");
}
else {
printf("On battery, sending normal shutdown command...\n");
ser_send_char(upsfd, APC_CMD_SOFTDOWN);
}
}
if (testvar("advorder") && strcasecmp(getval("advorder"), "no"))
upsdrv_shutdown_advanced(status);
else
upsdrv_shutdown_simple(status);
}
/* 940-0095B support: set DTR, lower RTS */
@ -921,6 +1107,7 @@ static int setvar_enum(apc_vartab_t *vt, const char *val)
char orig[256], temp[256];
const char *ptr;
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
ret = ser_send_char(upsfd, vt->cmd);
if (ret != 1) {
@ -1015,7 +1202,6 @@ static int setvar_string(apc_vartab_t *vt, const char *val)
char temp[256];
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
ret = ser_send_char(upsfd, vt->cmd);
if (ret != 1) {
@ -1118,6 +1304,7 @@ static int do_cmd(apc_cmdtab_t *ct)
int ret;
char buf[SMALLBUF];
ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
ret = ser_send_char(upsfd, ct->cmd);
if (ret != 1) {
@ -1222,7 +1409,9 @@ static void setuphandlers(void)
void upsdrv_makevartable(void)
{
addvar(VAR_VALUE, "cable", "Specify alternate cable (940-0095B)");
addvar(VAR_VALUE, "sdtype", "Specify shutdown type (1-3)");
addvar(VAR_VALUE, "wugrace", "Hard hibernate's wakeup grace");
addvar(VAR_VALUE, "sdtype", "Specify simple shutdown method (0-6)");
addvar(VAR_VALUE, "advorder", "Enable advanced shutdown control");
}
void upsdrv_initups(void)
@ -1234,9 +1423,8 @@ void upsdrv_initups(void)
cable = getval("cable");
if (cable)
if (!strcasecmp(cable, ALT_CABLE_1))
init_serial_0095B();
if (cable && !strcasecmp(cable, ALT_CABLE_1))
init_serial_0095B();
/* make sure we wake up if the UPS sends alert chars to us */
extrafd = upsfd;
@ -1244,18 +1432,12 @@ void upsdrv_initups(void)
void upsdrv_help(void)
{
printf("\nShutdown types:\n");
printf(" 0: soft shutdown or powerdown, depending on battery status\n");
printf(" 1: soft shutdown followed by powerdown\n");
printf(" 2: instant power off\n");
printf(" 3: power off with grace period\n");
printf(" 4: 'force OB' hack method for CS 350\n");
printf("Modes 0-1 will make the UPS come back when power returns\n");
printf("Modes 2-3 will make the UPS stay turned off when power returns\n");
}
void upsdrv_initinfo(void)
{
const char *pmod, *pser;
if (!smartmode()) {
fatalx(EXIT_FAILURE,
"Unable to detect an APC Smart protocol UPS on port %s\n"
@ -1268,8 +1450,12 @@ void upsdrv_initinfo(void)
getbaseinfo();
printf("Detected %s [%s] on %s\n", dstate_getinfo("ups.model"),
dstate_getinfo("ups.serial"), device_path);
if (!(pmod = dstate_getinfo("ups.model")))
pmod = "\"unknown model\"";
if (!(pser = dstate_getinfo("ups.serial")))
pser = "unknown serial";
upsdebugx(1, "Detected %s [%s] on %s", pmod, pser, device_path);
setuphandlers();
}

View file

@ -23,20 +23,22 @@
#include "serial.h"
#include "timehead.h"
#define APC_TABLE_VERSION "version 2.1"
#define APC_TABLE_VERSION "version 2.2"
/* Basic UPS reply line structure */
#define ENDCHAR 10 /* APC ends responses with LF */
/* these two are only used during startup */
#define IGNCHARS "\015+$|!~%?=*#&" /* special characters to ignore */
/* characters ignored by default */
#define IGNCHARS "\015+$|!~%?=#&" /* special characters to ignore */
/* these one is used only during startup, due to ^Z sending certain characters such as # */
#define MINIGNCHARS "\015+$|!" /* minimum set of special characters to ignore */
/* normal polls: characters we don't want to parse (including a few alerts) */
#define POLL_IGNORE "\015?=*&|"
#define POLL_IGNORE "\015&|"
/* alert characters we care about - OL, OB, LB, not LB, RB */
#define POLL_ALERT "$!%+#"
/* alert characters we care about - OL, OB, LB, not LB, RB, OVER, not OVER */
#define POLL_ALERT "$!%+#?="
#define UPSDELAY 50000 /* slow down multicharacter commands */
#define CMDLONGDELAY 1500000 /* some commands need a 1.5s gap for safety */
@ -77,7 +79,6 @@
/* Driver command table flag values */
#define APC_POLL 0x0001 /* Poll this variable regularly */
#define APC_IGNORE 0x0002 /* Never poll this */
#define APC_PRESENT 0x0004 /* Capability seen on this UPS */
#define APC_RW 0x0010 /* read-write variable */
@ -109,15 +110,11 @@ typedef struct {
apc_vartab_t apc_vartab[] = {
{ "ups.firmware.old", 0, 'V' },
{ "ups.firmware", 0, 'b' },
{ "ups.firmware.aux", 0, 'v' },
{ "ups.model", 0, 0x01 },
/* FUTURE: depends on variable naming scheme */
#if 0
{ "ups.model.code", 0, 'V' },
#endif
{ "ups.serial", 0, 'n' },
{ "ups.mfr.date", 0, 'm' },
@ -207,6 +204,7 @@ apc_vartab_t apc_vartab[] = {
#define APC_CMD_CALTOGGLE 'D'
#define APC_CMD_SHUTDOWN 'K'
#define APC_CMD_SOFTDOWN 'S'
#define APC_CMD_GRACEDOWN '@'
#define APC_CMD_SIMPWF 'U'
#define APC_CMD_BTESTTOGGLE 'W'
#define APC_CMD_OFF 'Z'
@ -232,6 +230,8 @@ apc_cmdtab_t apc_cmdtab[] =
{ "test.battery.start", 0, APC_CMD_BTESTTOGGLE },
{ "test.battery.stop", 0, APC_CMD_BTESTTOGGLE },
{ "shutdown.return.grace",
APC_NASTY, APC_CMD_GRACEDOWN },
{ "shutdown.return", APC_NASTY, APC_CMD_SOFTDOWN },
{ "shutdown.stayoff", APC_NASTY|APC_REPEAT, APC_CMD_SHUTDOWN },
@ -244,9 +244,6 @@ apc_cmdtab_t apc_cmdtab[] =
{ NULL, 0, 0 }
};
/* things to ignore in protocol_verify - useless variables, etc. */
#define CMD_IGN_CHARS "\032-78@.,~\047\177QHRTYayz)1IJ"
/* compatibility with hardware that doesn't do APC_CMDSET ('a') */
struct {
@ -255,33 +252,40 @@ struct {
int flags;
} compat_tab[] = {
/* APC Matrix */
{ "0XI", "789ABCDEFGKLMNOPQRSTUVWXYZcefgjklmnopqrsuwxz/<>\\^\014\026", 0 },
{ "0XM", "789ABCDEFGKLMNOPQRSTUVWXYZcefgjklmnopqrsuwxz/<>\\^\014\026", 0 },
{ "0ZI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz/<>", 0 },
{ "5UI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz/<>", 0 },
{ "5ZM", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz/<>", 0 },
/* APC600 */
{ "6QD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "6QI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "6QI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "6TD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "6TI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
/* SmartUPS 900 */
{ "7QD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "7QI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "7TD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "7TI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
/* SmartUPS 1250. */
{ "7QD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "7QI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "7TD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "7TI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
/* SmartUPS 900I */
{ "7II", "79ABCEFGKLMNOPQSUVWXYZcfg", 0 },
/* SmartUPS 2000I */
{ "9II", "79ABCEFGKLMNOPQSUVWXYZcfg", 0 },
{ "9GI", "79ABCEFGKLMNOPQSUVWXYZcfg", 0 },
/* SmartUPS 1250 */
{ "8QD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "8QI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "8TD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "8TI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "8TD", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
{ "8TI", "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
/* CS 350 */
{ "5.4.D", "\1ABPQRSUYbdfgjmnx9", 0 },
/* Smart-UPS 600 */
{ "D9", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D8", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D7", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D6", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D5", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D4", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D9", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D8", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D7", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D6", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D5", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ "D4", "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
{ NULL, NULL, 0 },
};

View file

@ -120,7 +120,7 @@ TODO List:
#include "bcmxcp.h"
#define DRIVER_NAME "BCMXCP UPS driver"
#define DRIVER_VERSION "0.23"
#define DRIVER_VERSION "0.24"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -1176,17 +1176,20 @@ void upsdrv_initinfo(void)
iIndex += 1;
/* Size of command list block */
cmd_list_len = get_word(answer+iIndex);
if (iIndex < res)
cmd_list_len = get_word(answer+iIndex);
upsdebugx(2, "Length of command list: %d\n", cmd_list_len);
iIndex += 2;
/* Size of outlet monitoring block */
outlet_block_len = get_word(answer+iIndex);
if (iIndex < res)
outlet_block_len = get_word(answer+iIndex);
upsdebugx(2, "Length of outlet_block: %d\n", outlet_block_len);
iIndex += 2;
/* Size of the alarm block */
alarm_block_len = get_word(answer+iIndex);
if (iIndex < res)
alarm_block_len = get_word(answer+iIndex);
upsdebugx(2, "Length of alarm_block: %d\n", alarm_block_len);
/* End of UPS ID block request */
@ -1209,7 +1212,8 @@ void upsdrv_initinfo(void)
init_limit();
/* Get information on UPS commands */
init_command_map();
if (cmd_list_len)
init_command_map();
/* FIXME: leave up to init_command_map() to add instant commands? */
dstate_addcmd("shutdown.return");

View file

@ -6,7 +6,7 @@
#define PW_MAX_BAUD 5
#define SUBDRIVER_NAME "RS-232 communication subdriver"
#define SUBDRIVER_VERSION "0.17"
#define SUBDRIVER_VERSION "0.18"
/* communication driver description structure */
upsdrv_info_t comm_upsdrv_info = {
@ -47,8 +47,10 @@ static void send_command(unsigned char *command, int command_length)
while (retry++ < PW_MAX_TRY) {
if (retry == PW_MAX_TRY)
if (retry == PW_MAX_TRY) {
ser_send_char(upsfd, 0x1d); /* last retry is preceded by a ESC.*/
usleep(250000);
}
sent = ser_send_buf(upsfd, sbuf, command_length);
@ -82,7 +84,7 @@ int get_answer(unsigned char *data, unsigned char command)
res = ser_get_char(upsfd, my_buf, 1, 0);
if (res != 1) {
upsdebugx(1,"Receive error (PW_COMMAND_START_BYTE): %d!!!\n", res);
upsdebugx(1,"Receive error (PW_COMMAND_START_BYTE): %d, cmd=%x!!!\n", res, command);
return -1;
}
@ -250,6 +252,7 @@ void upsdrv_comm_good()
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;
@ -274,6 +277,10 @@ void pw_comm_setup(const char *port)
send_write_command(AUT, 4);
usleep(500000);
ret = command_sequence(&command, 1, answer);
if (ret <= 0) {
usleep(500000);
ret = command_sequence(&id_command, 1, answer);
}
if (ret > 0) {
upslogx(LOG_INFO, "Connected to UPS on %s with baudrate %d", port, baud);
@ -293,6 +300,10 @@ void pw_comm_setup(const char *port)
send_write_command(AUT, 4);
usleep(500000);
ret = command_sequence(&command, 1, answer);
if (ret <= 0) {
usleep(500000);
ret = command_sequence(&id_command, 1, answer);
}
if (ret > 0) {
upslogx(LOG_INFO, "Connected to UPS on %s with baudrate %d", port, pw_baud_rates[i].name);

View file

@ -160,7 +160,7 @@ int get_answer(unsigned char *data, unsigned char command)
{
/* Clear any possible endpoint stalls */
usb_clear_halt(upsdev, 0x81);
//continue; // FIXME: seems a break would be better!
/* continue; */ /* FIXME: seems a break would be better! */
break;
}

View file

@ -186,7 +186,7 @@ static int blazer_status(const char *cmd)
* 01234567890123456789012345678901234567890123456
* 0 1 2 3 4
*/
if (blazer_command(cmd, buf, sizeof(buf)) < 47) {
if (blazer_command(cmd, buf, sizeof(buf)) < 46) {
upsdebugx(2, "%s: short reply", __func__);
return -1;
}
@ -691,6 +691,9 @@ void upsdrv_updateinfo(void)
if (blazer_status(command[proto].status)) {
if (retry < MAXTRIES) {
upsdebugx(1, "Communications with UPS lost: status read failed!");
retry++;
} else if (retry == MAXTRIES) {
upslogx(LOG_WARNING, "Communications with UPS lost: status read failed!");
retry++;
} else {
@ -723,7 +726,7 @@ void upsdrv_updateinfo(void)
lastpoll = now;
}
if (retry) {
if (retry > MAXTRIES) {
upslogx(LOG_NOTICE, "Communications with UPS re-established");
}

View file

@ -255,16 +255,17 @@ static int krauler_command(const char *cmd, char *buf, size_t buflen)
/* "UPS No Ack" has a special meaning */
if (!strcasecmp(buf, "UPS No Ack")) {
upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
continue;
}
/* Replace the first byte of what we received with the correct one */
buf[0] = command[i].prefix;
upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
return ret;
}
upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
return 0;
}
@ -295,13 +296,21 @@ static void *krauler_subdriver(void)
}
static void *phoenix_subdriver(void)
{
subdriver_command = &phoenix_command;
return NULL;
}
static usb_device_id_t blazer_usb_id[] = {
{ USB_DEVICE(0x05b8, 0x0000), &cypress_subdriver }, /* Agiler UPS */
{ USB_DEVICE(0x0001, 0x0000), &krauler_subdriver }, /* Krauler UP-M500VA */
{ USB_DEVICE(0xffff, 0x0000), &krauler_subdriver }, /* Ablerex 625L USB */
{ 0x0001, 0x0000, &krauler_subdriver }, /* Krauler UP-M500VA */
{ 0xffff, 0x0000, &krauler_subdriver }, /* Ablerex 625L USB */
{ USB_DEVICE(0x0665, 0x5161), &cypress_subdriver }, /* Belkin F6C1200-UNV */
{ USB_DEVICE(0x06da, 0x0003), &ippon_subdriver }, /* Mustek Powermust */
{ USB_DEVICE(0x0f03, 0x0001), &cypress_subdriver }, /* Unitek Alpha 1200Sx */
{ USB_DEVICE(0x14f0, 0x00c9), &phoenix_subdriver }, /* GE EP series */
/* end of list */
{-1, -1, NULL}
};

View file

@ -74,6 +74,22 @@ static info_lkp_t cps_battvolt[] = {
{ 0, NULL, &cps_battvolt_fun }
};
/* returns statically allocated string - must not use it again before
done with result! */
static const char *cps_battcharge_fun(double value)
{
static char buf[8];
/* clamp battery charge to 100% */
snprintf(buf, sizeof(buf), "%.0f", value < 100.0 ? value : 100.0);
return buf;
}
static info_lkp_t cps_battcharge[] = {
{ 0, NULL, &cps_battcharge_fun }
};
/* --------------------------------------------------------------- */
/* Vendor-specific usage table */
/* --------------------------------------------------------------- */
@ -106,7 +122,7 @@ static hid_info_t cps_hid2nut[] = {
{ "battery.mfr.date", 0, 0, "UPS.PowerSummary.iOEMInformation", NULL, "%s", 0, stringid_conversion },
{ "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", 0, NULL },
{ "battery.charge.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL },
{ "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%s", 0, cps_battcharge },
{ "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL },
{ "battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.RemainingTimeLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.0f", 0, NULL },

View file

@ -32,7 +32,7 @@
#include "state.h"
#include "parseconf.h"
static int sockfd = -1, stale = 1, alarm_active = 0;
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[ST_MAX_VALUE_LEN];
static st_tree_t *dtree_root = NULL;
@ -223,8 +223,11 @@ static void sock_connect(int sock)
int fd, ret;
conn_t *conn;
struct sockaddr_un sa;
#if defined(__hpux) && !defined(_XOPEN_SOURCE_EXTENDED)
int salen;
#else
socklen_t salen;
#endif
salen = sizeof(sa);
fd = accept(sock, (struct sockaddr *) &sa, &salen);
@ -639,7 +642,12 @@ void dstate_setflags(const char *var, int flags)
sttmp = state_tree_find(dtree_root, var);
if (!sttmp) {
upslogx(LOG_ERR, "dstate_setflags: base variable (%s) does not exist", var);
upslogx(LOG_ERR, "%s: base variable (%s) does not exist", __func__, var);
return;
}
if (sttmp->flags & ST_FLAG_IMMUTABLE) {
upslogx(LOG_WARNING, "%s: base variable (%s) is immutable", __func__, var);
return;
}
@ -792,12 +800,21 @@ int dstate_is_stale(void)
/* clean out the temp space for a new pass */
void status_init(void)
{
if (dstate_getinfo("driver.flag.ignorelb")) {
ignorelb = 1;
}
memset(status_buf, 0, sizeof(status_buf));
}
/* add a status element */
void status_set(const char *buf)
{
if (ignorelb && !strcasecmp(buf, "LB")) {
upsdebugx(2, "%s: ignoring LB flag from device", __func__);
return;
}
/* separate with a space if multiple elements are present */
if (strlen(status_buf) > 0) {
snprintfcat(status_buf, sizeof(status_buf), " %s", buf);
@ -809,6 +826,31 @@ void status_set(const char *buf)
/* write the status_buf into the externally visible dstate storage */
void status_commit(void)
{
while (ignorelb) {
const char *val, *low;
val = dstate_getinfo("battery.charge");
low = dstate_getinfo("battery.charge.low");
if (val && low && (strtol(val, NULL, 10) < strtol(low, NULL, 10))) {
snprintfcat(status_buf, sizeof(status_buf), " LB");
upsdebugx(2, "%s: appending LB flag [charge '%s' below '%s']", __func__, val, low);
break;
}
val = dstate_getinfo("battery.runtime");
low = dstate_getinfo("battery.runtime.low");
if (val && low && (strtol(val, NULL, 10) < strtol(low, NULL, 10))) {
snprintfcat(status_buf, sizeof(status_buf), " LB");
upsdebugx(2, "%s: appending LB flag [runtime '%s' below '%s']", __func__, val, low);
break;
}
/* LB condition not detected */
break;
}
if (alarm_active) {
dstate_setinfo("ups.status", "ALARM %s", status_buf);
} else {

View file

@ -375,7 +375,7 @@ static int is_valid_data(const char* varname)
* enforcing controls! We also need a way to automate
* the update / sync process (with cmdvartab?!) */
upsdebugx(1, "Unknown data. Commiting anyway...");
upsdebugx(1, "Unknown data. Committing anyway...");
return 1;
/* return 0;*/
}
@ -395,7 +395,7 @@ static int is_valid_value(const char* varname, const char *value)
* enforcing controls! We also need a way to automate
* the update / sync process (with cmdvartab?) */
upsdebugx(1, "Unknown data. Commiting value anyway...");
upsdebugx(1, "Unknown data. Committing value anyway...");
return 1;
/* return 0;*/
}
@ -412,7 +412,7 @@ static void upsconf_err(const char *errmsg)
static int parse_data_file(int upsfd)
{
char fn[SMALLBUF];
char *ptr, *var_value = (char*) xmalloc(MAX_STRING_SIZE);
char *ptr, var_value[MAX_STRING_SIZE];
int value_args = 0, counter;
time_t now;
@ -501,13 +501,13 @@ static int parse_data_file(int upsfd)
}
else
{
memset(var_value, 0, MAX_STRING_SIZE);
for (counter = 1, value_args = ctx->numargs ;
counter < value_args ; counter++)
{
if (counter != 1) /* don't append the first space separator */
strncat(var_value, " ", 1);
strncat(var_value, ctx->arglist[counter], MAX_STRING_SIZE);
if (counter == 1) /* don't append the first space separator */
snprintf(var_value, sizeof(var_value), "%s", ctx->arglist[counter]);
else
snprintfcat(var_value, sizeof(var_value), " %s", ctx->arglist[counter]);
}
if (setvar(ctx->arglist[0], var_value) == STAT_SET_UNKNOWN)
@ -529,7 +529,6 @@ static int parse_data_file(int upsfd)
pconf_finish(ctx);
free(ctx);
ctx=NULL;
free(var_value);
}
return 1;
}

View file

@ -1,6 +1,6 @@
/* eaton-mib.c - data to monitor Eaton Aphel PDUs (Basic and Complex)
*
* Copyright (C) 2008
* Copyright (C) 2008 - 2010
* Arnaud Quette <ArnaudQuette@Eaton.com>
*
* Sponsored by Eaton <http://www.eaton.com>
@ -25,7 +25,7 @@
#include "eaton-mib.h"
#define EATON_APHEL_MIB_VERSION "0.4"
#define EATON_APHEL_MIB_VERSION "0.45"
/* APHEL-GENESIS-II-MIB (monitored ePDU)
* *************************************
@ -87,8 +87,6 @@ static snmp_info_t eaton_aphel_genesisII_mib[] = {
#define APHEL2_OID_MODEL_NAME AR_OID_MODEL_NAME
/* Common Aphel / Raritan declaration */
#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"
@ -180,12 +178,21 @@ static snmp_info_t eaton_aphel_revelation_mib[] = {
/* FIXME:
* - delay for startup/shutdown sequence
* - support for Ambient page
temperatureSensorCount" src="snmp:$sysoid.2.1.0
ambient.temperature src="snmp:$sysoid.2.2.1.3.$indiceSensor => seems dumb!
ambient.humidity src="snmp:$sysoid.2.4.1.3.$indiceSensor
* - 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 page */
/* 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!

View file

@ -142,12 +142,12 @@ void upsdrv_initinfo(void)
*/
if ((v = getval("OL")) != NULL) {
parse_input_signals(v, &upstab[upstype].line_ol, &upstab[upstype].val_ol);
upsdebugx(2, "parse_input_signals: OL overriden with %s\n", v);
upsdebugx(2, "parse_input_signals: OL overridden with %s\n", v);
}
if ((v = getval("LB")) != NULL) {
parse_input_signals(v, &upstab[upstype].line_bl, &upstab[upstype].val_bl);
upsdebugx(2, "parse_input_signals: LB overriden with %s\n", v);
upsdebugx(2, "parse_input_signals: LB overridden with %s\n", v);
}
}
@ -318,12 +318,12 @@ void upsdrv_initups(void)
*/
if ((v = getval("CP")) != NULL) {
parse_output_signals(v, &upstab[upstype].line_norm);
upsdebugx(2, "parse_output_signals: CP overriden with %s\n", v);
upsdebugx(2, "parse_output_signals: CP overridden with %s\n", v);
}
if ((v = getval("SD")) != NULL) {
parse_output_signals(v, &upstab[upstype].line_sd);
upsdebugx(2, "parse_output_signals: SD overriden with %s\n", v);
upsdebugx(2, "parse_output_signals: SD overridden with %s\n", v);
}
if (ioctl(upsfd, TIOCMSET, &upstab[upstype].line_norm)) {

View file

@ -141,7 +141,6 @@ static int refresh_report_buffer(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDDa
{
int id = pData->ReportID;
int r;
unsigned char buf[SMALLBUF];
if (rbuf->ts[id] + age > time(NULL)) {
/* buffered report is still good; nothing to do */
@ -149,17 +148,14 @@ static int refresh_report_buffer(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDDa
return 0;
}
r = comm_driver->get_report(udev, id, buf, sizeof(buf));
r = comm_driver->get_report(udev, id, rbuf->data[id], rbuf->len[id]);
if (r <= 0) {
return -1;
}
/* broken report descriptors are common, so store whatever we can */
memcpy(rbuf->data[id], buf, (r < rbuf->len[id]) ? r : rbuf->len[id]);
if (rbuf->len[id] != r) {
upsdebugx(2, "%s: expected %d bytes, but got %d instead", __func__, rbuf->len[id], r);
upsdebug_hex(3, "Report[err]", buf, r);
upsdebug_hex(3, "Report[err]", rbuf->data[id], r);
} else {
upsdebug_hex(3, "Report[get]", rbuf->data[id], rbuf->len[id]);
}
@ -399,7 +395,7 @@ char *HIDGetIndexString(hid_dev_handle_t udev, const int Index, char *buf, size_
if (comm_driver->get_string(udev, Index, buf, buflen) < 1)
buf[0] = '\0';
return buf;
return rtrim(buf, '\n');
}
/* Return pointer to indexed string from HID path (empty if not found)

View file

@ -23,8 +23,58 @@
#include "timehead.h"
#include "nut_stdint.h"
#define sivann
#define IsBitSet(val, bit) ((val) & (1 << (bit)))
#define DRIVER_NAME "Liebert ESP-II serial UPS driver"
#define DRIVER_VERSION "0.02"
#define DRIVER_VERSION "0.03"
#define UPS_SHUTDOWN_DELAY 12 /* it means UPS will be shutdown 120 sec */
#define SHUTDOWN_CMD_LEN 8
/* values for sending to UPS */
enum mult_enum {
M_10,
M_0_1,
M_VOLTAGE_I,
M_VOLTAGE_O,
M_VOLTAGE_B,
M_CURRENT_I,
M_CURRENT_O,
M_CURRENT_B,
M_LOAD_VA,
M_LOAD_WATT,
M_FREQUENCY,
M_VOLT_DC,
M_TEMPERATURE,
M_CURRENT_DC ,
M_BAT_RUNTIME,
M_NOMPOWER,
M_POWER,
M_REALPOWER,
M_LOADPERC
};
static float multi[19]={
10.0,
0.1,
0.1, /* volt */
0.1,
0.1,
0.1, /* curr */
0.1,
0.1,
100.0, /* va */
100.0, /* W */
0.01, /* FREQ */
0.1, /* V DC*/
0.1, /* TEMP*/
0.01, /* CUR DC*/
60.0, /* BAT RUNTIME*/
100.0, /* NOMPOWER*/
100.0, /* POWER*/
100.0, /* REAL POWER*/
1.0 /* LOADPERC*/
};
static int instcmd(const char *cmdname, const char *extra);
static int setvar(const char *varname, const char *val);
@ -33,7 +83,8 @@ static int setvar(const char *varname, const char *val);
upsdrv_info_t upsdrv_info = {
DRIVER_NAME,
DRIVER_VERSION,
"Richard Gregory <r.gregory liv ac uk>",
"Richard Gregory <r.gregory liv ac uk>\n" \
"Robert Jobbagy <jobbagy.robert at gmail dot com",
DRV_EXPERIMENTAL,
{ NULL }
};
@ -46,7 +97,17 @@ static const unsigned char
cmd_bitfield3[] = { 1,148,2,1,3,155 }, /* CHECK_AIR_FILTER (10), BAD_BYPASS_PWR (8), OUTPUT_OVERVOLTAGE (7), OUTPUT_UNDERVOLTAGE (6), LOW_BATTERY (5), CHARGER_FAIL (3), SHUTDOWN_PENDING (2), BAD_INPUT_FREQ (1), UPS_OVERLOAD (0) */
cmd_bitfield7[] = { 1,148,2,1,7,159 }, /* AMBIENT_OVERTEMP (2) */
cmd_battestres[] = { 1,148,2,1,12,164 }, /* BATTERY_TEST_RESULT */
cmd_selftestres[] = { 1,148,2,1,13,165 }; /* SELF_TEST_RESULT */
cmd_selftestres[] = { 1,148,2,1,13,165 }, /* SELF_TEST_RESULT */
cmd_upstype[] = { 1,136,2,1,1,141}, /* type bits + number of phases in bit groups*/
cmd_scaling1[] = { 1,131,2,1,2,137}, /* part of multiplier information*/
/* Shutdown commands by Robert Jobbagy */
cmd_setOutOffMode[] = { 1,156,4,1,6,0,1,169}, /* UPS OutOffMode command */
cmd_setOutOffDelay[] = {1,156,4,1,5,0,UPS_SHUTDOWN_DELAY,167+UPS_SHUTDOWN_DELAY}, /* UPS Shutdown with delay */
cmd_sysLoadKey[] = {1,156,2,1,7,167}, /* UPS SysLoadKey */
cmd_shutdown[] = {1,156,4,1,136,76,76,194}; /* UPS shutdown */
static int num_inphases = 1, num_outphases = 1;
static char cksum(const char *buf, const size_t len)
{
@ -60,22 +121,22 @@ static char cksum(const char *buf, const size_t len)
return sum;
}
static int do_command(const unsigned char *command, char *reply)
static int do_command(const unsigned char *command, char *reply, int cmd_len)
{
int ret;
ret = ser_send_buf(upsfd, command, 6);
ret = ser_send_buf(upsfd, command, cmd_len);
if (ret < 0) {
upsdebug_with_errno(2, "send");
return -1;
} else if (ret < 6) {
} else if (ret < cmd_len) {
upsdebug_hex(2, "send: truncated", command, ret);
return -1;
}
upsdebug_hex(2, "send", command, ret);
ret = ser_get_buf(upsfd, reply, 8, 1, 0);
ret = ser_get_buf_len(upsfd, reply, 8, 1, 0); /* it needs that this driver works with USB to Serial cable */
if (ret < 0) {
upsdebug_with_errno(2, "read");
return -1;
@ -95,49 +156,111 @@ void upsdrv_initinfo(void)
{
struct {
const char *var;
const int len;
unsigned char len;
} vartab[] = {
{ "ups.model", 15 },
{ "ups.firmware", 8 },
{ "ups.serial", 10 },
{ "ups.mfr.date", 4 },
{ "ups.model",15 },
{ "ups.firmware",8 },
{ "ups.serial",10 },
{ "ups.mfr.date",4 },
{ NULL }
};
char buf[LARGEBUF];
int i, index;
int i,bitn,vari,ret=0,offset=4,readok=0;
char command[6], reply[8];
unsigned int value;
dstate_setinfo("ups.mfr", "%s", "Liebert");
for (i = 0; i < 37; i++) {
char command[6], reply[8];
int ret;
for (vari = 0; vartab[vari].var; vari++) {
upsdebugx(1, "reading: %s", vartab[vari].var);
snprintf(command, sizeof(command), "\x01\x88\x02\x01%c", i+4);
for (i = 0; i < vartab[vari].len; i++) {
snprintf(command, sizeof(command), "\x01\x88\x02\x01%c", i+offset);
command[5] = cksum(command, 5);
ret = do_command((unsigned char *)command, reply);
if (ret == 8) {
ret = do_command((unsigned char *)command, reply, 6);
if (ret < 8) {
upsdebug_hex(2, "send: truncated", command, ret);
break;
}
buf[i<<1] = reply[6];
buf[(i<<1)+1] = reply[5];
} else {
buf[i<<1] = '\0';
buf[(i<<1)+1] = '\0';
}
}
buf[i<<1] = 0;
upsdebugx(1, "return: %d (8=success)", ret);
if (strlen(buf) == 0) {
if (ret == 8) { /* last command successful */
dstate_setinfo(vartab[vari].var,"%s",buf);
readok++;
}
offset+=vartab[vari].len;
} /* for */
if (!readok) {
fatalx(EXIT_FAILURE, "ESP-II capable UPS not detected");
}
for (index = 0, i = 0; vartab[i].var; index += vartab[i].len, i++) {
char val[SMALLBUF];
/* determine number of input & output phases and ups type */
memcpy(command,cmd_upstype,6);
ret = do_command((unsigned char *)command, reply, 6);
if (ret < 8) {
upsdebug_hex(2, "send: phase detection: truncated", command, ret);
}
else {
/* input: from bit 0 to bit 1 (2 bits) */
for (value=0,bitn=0;bitn<2;bitn++) {
if (IsBitSet(reply[6],(unsigned short int)bitn)) /* bit range measurement on LSByte*/
value+=(1<<(unsigned short int)(bitn - 0));
}
num_inphases=value;
dstate_setinfo("input.phases", "%d", value);
snprintf(val, sizeof(val), "%.*s", vartab[i].len, &buf[index]);
/* output: from bit 4 to bit 5 (2 bits)*/
for (value=0,bitn=4;bitn<6;bitn++) {
if (IsBitSet(reply[6],(unsigned short int)bitn)) /* bit range measurement on LSByte*/
value+=(1<<(unsigned short int)(bitn - 4));
}
num_outphases=value;
dstate_setinfo("output.phases", "%d", value);
dstate_setinfo(vartab[i].var, "%s", rtrim(val, ' '));
if (reply[5] & (1<<4)) { /* ISOFFLINE */
dstate_setinfo("ups.type", "offline") ;
}
else if (reply[5] & (1<<5)) { /* ISINTERACTIVE */
dstate_setinfo("ups.type", "line-interactive") ;
}
else {
dstate_setinfo("ups.type", "online") ;
}
}
/* determine scaling */
/* full scaling output not defined yet, but we can differentiate sets of
* multipliers based on a sample scaling reading */
memcpy(command,cmd_scaling1,6);
ret = do_command((unsigned char *)command, reply, 6);
if (ret < 8) {
upsdebug_hex(2, "send: scaling detection: truncated", command, ret);
}
else { /* add here multipliers that differentiate between models */
switch (reply[6]) {
case 1: /* GXT-2 */
multi[M_FREQUENCY]=0.1;
multi[M_VOLT_DC]=1.0;
multi[M_POWER]=1.0;
multi[M_NOMPOWER]=1.0;
break;
case 2: /* NXe */
multi[M_FREQUENCY]=0.01;
multi[M_VOLT_DC]=0.1;
multi[M_POWER]=100.0;
multi[M_NOMPOWER]=100.0;
break;
default: /* the default values from definition of multi will be used */
break;
}
}
upsh.instcmd = instcmd;
@ -146,55 +269,145 @@ void upsdrv_initinfo(void)
void upsdrv_updateinfo(void)
{
struct {
typedef struct {
const unsigned char cmd[6];
const char *var;
const char *fmt;
const double mult;
} vartab[] = {
{ { 1,149,2,1,4,157 }, "battery.charge", "%.0f", 1.0 },
{ { 1,149,2,1,1,154 }, "battery.runtime", "%.0f", 60 },
{ { 1,149,2,1,2,155 }, "battery.voltage", "%.1f", 0.1 },
{ { 1,149,2,1,3,156 }, "battery.current", "%.2f", 0.01 },
{ { 1,149,2,1,12,165 }, "battery.temperature", "%.1f", 0.1 },
{ { 1,161,2,1,13,178 }, "battery.voltage.nominal", "%.1f", 0.1 },
{ { 1,149,2,1,7,160 }, "ups.load", "%.0f", 1.0 },
{ { 1,149,2,1,6,159 }, "ups.power", "%.0f", 1.0 },
{ { 1,161,2,1,8,173 }, "ups.power.nominal", "%.0f", 1.0 },
{ { 1,149,2,1,5,158 }, "ups.realpower", "%.0f", 1.0 },
{ { 1,149,2,1,14,167 }, "ups.temperature", "%.1f", 0.1 },
{ { 1,144,2,1,1,149 }, "input.voltage", "%.1f", 0.1 },
{ { 1,149,2,1,8,161 }, "input.frequency", "%.1f", 0.1 },
{ { 1,149,2,1,10,163 }, "input.frequency.nominal", "%.1f", 0.1 },
{ { 1,144,2,1,5,153 }, "input.bypass.voltage", "%.1f", 0.1 },
{ { 1,144,2,1,3,151 }, "output.voltage", "%.1f", 0.1 },
{ { 1,149,2,1,9,162 }, "output.frequency", "%.1f", 0.1 },
{ { 1,144,2,1,4,152 }, "output.current", "%.1f", 0.1 },
const int multindex;
} cmd_s;
static cmd_s vartab[] = { /* common vars */
{ { 1,149,2,1,1,154 }, "battery.runtime", "%.0f", M_BAT_RUNTIME },
{ { 1,149,2,1,2,155 }, "battery.voltage", "%.1f", M_VOLT_DC },
{ { 1,149,2,1,3,156 }, "battery.current", "%.2f", M_CURRENT_DC },
{ { 1,161,2,1,13,178 }, "battery.voltage.nominal", "%.1f", M_VOLT_DC },
{ { 1,149,2,1,12,165 }, "battery.temperature", "%.1f", M_TEMPERATURE },
{ { 1,149,2,1,14,167 }, "ups.temperature", "%.1f", M_TEMPERATURE },
{ { 1,161,2,1,8,173 }, "ups.power.nominal", "%.0f", M_NOMPOWER },
{ { 1,161,2,1,4,169 }, "ups.delay.start", "%.0f", M_10 },
{ { 1,161,2,1,14,179 },"battery.runtime.low", "%.0f", M_BAT_RUNTIME },
{ { 1,149,2,1,8,161 }, "input.frequency", "%.1f", M_FREQUENCY },
{ { 1,149,2,1,10,163 }, "input.bypass.frequency", "%.1f", M_FREQUENCY },
{ { 1,161,2,1,9,174 }, "input.frequency.nominal", "%.1f", M_FREQUENCY },
{ { 1,149,2,1,9,162 }, "output.frequency", "%.1f", M_FREQUENCY },
{ { 1,161,2,1,10,175 }, "output.frequency.nominal", "%.1f", M_FREQUENCY },
{ { 0 }, NULL, NULL, 0 }
};
static cmd_s vartab1o[] = { /* 1-phase out */
{ { 1,149,2,1,7,160 }, "ups.load", "%.0f", M_LOADPERC },
{ { 1,149,2,1,6,159 }, "ups.power", "%.0f", M_POWER },
{ { 1,149,2,1,5,158 }, "ups.realpower", "%.0f", M_POWER },
{ { 1,144,2,1,3,151 }, "output.voltage", "%.1f", M_VOLTAGE_O },
{ { 1,144,2,1,4,152 }, "output.current", "%.1f", M_CURRENT_O },
{ { 0 }, NULL, NULL, 0 }
};
static cmd_s vartab1i[] = { /* 1-phase in*/
{ { 1,144,2,1,1,149 }, "input.voltage", "%.1f", M_VOLTAGE_I },
{ { 1,144,2,1,5,153 }, "input.bypass.voltage", "%.1f", M_VOLTAGE_B },
{ { 1,144,2,1,6,154 }, "input.bypass.current", "%.1f", M_CURRENT_B },
{ { 0 }, NULL, NULL, 0 }
};
static cmd_s vartab3o[] = { /*3-phase out */
{ { 1,144,2,1,24,172 }, "ups.L1.load", "%.0f", M_LOADPERC },
{ { 1,145,2,1,24,173 }, "ups.L2.load", "%.0f", M_LOADPERC },
{ { 1,146,2,1,24,174 }, "ups.L3.load", "%.0f", M_LOADPERC },
{ { 1,144,2,1,22,170 }, "ups.L1.power", "%.0f", M_POWER },
{ { 1,145,2,1,22,171 }, "ups.L2.power", "%.0f", M_POWER },
{ { 1,146,2,1,22,172 }, "ups.L3.power", "%.0f", M_POWER },
{ { 1,144,2,1,21,169 }, "ups.L1.realpower", "%.0f", M_POWER },
{ { 1,145,2,1,21,170 }, "ups.L2.realpower", "%.0f", M_POWER },
{ { 1,146,2,1,21,171 }, "ups.L3.realpower", "%.0f", M_POWER },
{ { 1,144,2,1,3,151 }, "output.L1-N.voltage", "%.1f", M_VOLTAGE_O },
{ { 1,145,2,1,3,152 }, "output.L2-N.voltage", "%.1f", M_VOLTAGE_O },
{ { 1,146,2,1,3,153 }, "output.L3-N.voltage", "%.1f", M_VOLTAGE_O },
{ { 1,144,2,1,14,162 }, "output.L1.crestfactor", "%.1f", M_0_1 },
{ { 1,145,2,1,14,163 }, "output.L2.crestfactor", "%.1f", M_0_1 },
{ { 1,146,2,1,14,164 }, "output.L3.crestfactor", "%.1f", M_0_1 },
{ { 0 }, NULL, NULL, 0 }
};
static cmd_s vartab3i[] = { /*3-phase in */
{ { 1,144,2,1,1,149 }, "input.L1-N.voltage", "%.1f", M_VOLTAGE_I },
{ { 1,145,2,1,1,150 }, "input.L2-N.voltage", "%.1f", M_VOLTAGE_I },
{ { 1,146,2,1,1,151 }, "input.L3-N.voltage", "%.1f", M_VOLTAGE_I },
{ { 1,144,2,1,5,153 }, "input.L1-N.bypass.voltage", "%.1f", M_VOLTAGE_B },
{ { 1,145,2,1,5,154 }, "input.L2-N.bypass.voltage", "%.1f", M_VOLTAGE_B },
{ { 1,146,2,1,5,155 }, "input.L3-N.bypass.voltage", "%.1f", M_VOLTAGE_B },
{ { 1,144,2,1,6,154 }, "input.L1-N.bypass.current", "%.1f", M_CURRENT_B },
{ { 1,145,2,1,6,155 }, "input.L2-N.bypass.current", "%.1f", M_CURRENT_B },
{ { 1,146,2,1,6,156 }, "input.L3-N.bypass.current", "%.1f", M_CURRENT_B },
{ { 1,144,2,1,2,150 }, "input.L1.current", "%.1f", M_CURRENT_I },
{ { 1,145,2,1,2,151 }, "input.L2.current", "%.1f", M_CURRENT_I },
{ { 1,146,2,1,2,152 }, "input.L3.current", "%.1f", M_CURRENT_I },
{ { 0 }, NULL, NULL, 0 }
};
static cmd_s * cmdin_p;
static cmd_s * cmdout_p;
const char *val;
char reply[8];
int ret, i;
for (i = 0; vartab[i].var; i++) {
int16_t val;
ret = do_command(vartab[i].cmd, reply);
ret = do_command(vartab[i].cmd, reply, 6);
if (ret < 8) {
continue;
}
val = (unsigned char)reply[5];
val <<= 8;
val += (unsigned char)reply[6];
dstate_setinfo(vartab[i].var, vartab[i].fmt, val * multi[vartab[i].multindex]);
}
dstate_setinfo(vartab[i].var, vartab[i].fmt, val * vartab[i].mult);
if (num_inphases>1){
cmdin_p=vartab3i;
}
else {
cmdin_p=vartab1i;
}
if (num_outphases>1){
cmdout_p=vartab3o;
}
else {
cmdout_p=vartab1o;
}
for (i = 0; cmdin_p[i].var; i++) {
int16_t val;
ret = do_command(cmdin_p[i].cmd, reply, 6);
if (ret < 8) {
continue;
}
val = (unsigned char)reply[5];
val <<= 8;
val += (unsigned char)reply[6];
dstate_setinfo(cmdin_p[i].var, cmdin_p[i].fmt, val * multi[cmdin_p[i].multindex]);
}
for (i = 0; cmdout_p[i].var; i++) {
int16_t val;
ret = do_command(cmdout_p[i].cmd, reply, 6);
if (ret < 8) {
continue;
}
val = (unsigned char)reply[5];
val <<= 8;
val += (unsigned char)reply[6];
dstate_setinfo(cmdout_p[i].var, cmdout_p[i].fmt, val * multi[cmdout_p[i].multindex]);
}
status_init();
ret = do_command(cmd_bitfield1, reply);
ret = do_command(cmd_bitfield1, reply, 6);
if (ret < 8) {
upslogx(LOG_ERR, "Failed reading bitfield #1");
dstate_datastale();
@ -217,7 +430,7 @@ void upsdrv_updateinfo(void)
}
}
ret = do_command(cmd_bitfield2, reply);
ret = do_command(cmd_bitfield2, reply, 6);
if (ret < 8) {
upslogx(LOG_ERR, "Failed reading bitfield #2");
dstate_datastale();
@ -240,7 +453,7 @@ void upsdrv_updateinfo(void)
status_set("TRIM");
}
ret = do_command(cmd_bitfield3, reply);
ret = do_command(cmd_bitfield3, reply, 6);
if (ret < 8) {
upslogx(LOG_ERR, "Failed reading bitfield #3");
dstate_datastale();
@ -262,8 +475,13 @@ void upsdrv_updateinfo(void)
void upsdrv_shutdown(void)
{
/* replace with a proper shutdown function */
fatalx(EXIT_FAILURE, "shutdown not supported");
char reply[8];
if(!(do_command(cmd_setOutOffMode, reply, 8) != -1) &&
(do_command(cmd_setOutOffDelay, reply, 8) != -1) &&
(do_command(cmd_sysLoadKey, reply, 6) != -1) &&
(do_command(cmd_shutdown, reply, 8) != -1))
upslogx(LOG_ERR, "Failed to shutdown UPS");
}
static int instcmd(const char *cmdname, const char *extra)

View file

@ -29,8 +29,8 @@
#define LIEBERT_HID_VERSION "Liebert HID 0.3"
/* FIXME: experimental flag to be put in upsdrv_info */
/* Liebert */
#define LIEBERT_VENDORID 0x06da
/* Phoenixtec */
#define LIEBERT_VENDORID 0x06da
/* USB IDs device table */
static usb_device_id_t liebert_usb_device_table[] = {

View file

@ -258,6 +258,11 @@ static int main_arg(char *var, char *val)
return 1; /* handled */
}
if (!strcmp(var, "ignorelb")) {
dstate_setinfo("driver.flag.ignorelb", "enabled");
return 1; /* handled */
}
/* any other flags are for the driver code */
if (!val)
return 0;
@ -600,6 +605,28 @@ int main(int argc, char **argv)
upsdrv_initinfo();
upsdrv_updateinfo();
if (dstate_getinfo("driver.flag.ignorelb")) {
int have_lb_method = 0;
if (dstate_getinfo("battery.charge") && dstate_getinfo("battery.charge.low")) {
upslogx(LOG_INFO, "using 'battery.charge' to set battery low state");
have_lb_method++;
}
if (dstate_getinfo("battery.runtime") && dstate_getinfo("battery.runtime.low")) {
upslogx(LOG_INFO, "using 'battery.runtime' to set battery low state");
have_lb_method++;
}
if (!have_lb_method) {
fatalx(EXIT_FAILURE,
"The 'ignorelb' flag is set, but there is no way to determine the\n"
"battery state of charge.\n\n"
"Only set this flag if both 'battery.charge' and 'battery.charge.low'\n"
"and/or 'battery.runtime' and 'battery.runtime.low' are available.\n");
}
}
/* now we can start servicing requests */
dstate_init(progname, upsname);

View file

@ -62,12 +62,12 @@ static int instcmd(const char *cmdname, const char *extra);
/*
Metasystem UPS data transfer are made with packet of the format:
STX DATA_LENGHT DATA CHECKSUM
STX DATA_LENGTH DATA CHECKSUM
where:
STX is 0x02 and is the start of transmission byte
DATA_LENGHT is number of data bytes + the checksum byte
DATA_LENGTH is number of data bytes + the checksum byte
DATA ......
CHECKSUM is the sum modulus 256 of all DATA bytes + DATA_LENGHT
CHECKSUM is the sum modulus 256 of all DATA bytes + DATA_LENGTH
The answer from the UPS have the same packet format and the first
data byte is equal to the command that the ups is answering to
@ -114,7 +114,7 @@ void dump_buffer(unsigned char *buffer, int buf_len) {
}
/* send a read command to the UPS, it retries 5 times before give up
it's a 4 byte request (STX, LENGHT, COMMAND and CHECKSUM) */
it's a 4 byte request (STX, LENGTH, COMMAND and CHECKSUM) */
void send_read_command(char command) {
int retry, sent;
unsigned char buf[4];
@ -122,9 +122,9 @@ void send_read_command(char command) {
sent = 0;
while ((sent != 4) && (retry < 5)) {
buf[0]=0x02; /* STX Start of Transmission */
buf[1]=0x02; /* data lenght(data + checksum byte) */
buf[1]=0x02; /* data length(data + checksum byte) */
buf[2]=command; /* command to send */
buf[3]=buf[1] + buf[2]; /* checksum (sum modulus 256 of data bytes + lenght) */
buf[3]=buf[1] + buf[2]; /* checksum (sum modulus 256 of data bytes + length) */
if (retry == 4) send_zeros(); /* last retry is preceded by a serial reset...*/
sent = ser_send_buf(upsfd, buf, 4);
retry += 1;
@ -134,29 +134,29 @@ void send_read_command(char command) {
/* send a write command to the UPS, the write command and the value to be written are passed
with a char* buffer
it retries 5 times before give up */
void send_write_command(unsigned char *command, int command_lenght) {
void send_write_command(unsigned char *command, int command_length) {
int i, retry, sent, checksum;
unsigned char raw_buf[255];
/* prepares the raw data */
raw_buf[0] = 0x02; /* STX byte */
raw_buf[1] = (unsigned char)(command_lenght + 1); /* data lenght + checksum */
memcpy(raw_buf+2, command, command_lenght);
command_lenght += 2;
raw_buf[1] = (unsigned char)(command_length + 1); /* data length + checksum */
memcpy(raw_buf+2, command, command_length);
command_length += 2;
/* calculate checksum */
checksum = 0;
for (i = 1; i < command_lenght; i++) checksum += raw_buf[i];
for (i = 1; i < command_length; i++) checksum += raw_buf[i];
checksum = checksum % 256;
raw_buf[command_lenght] = (unsigned char)checksum;
command_lenght +=1;
raw_buf[command_length] = (unsigned char)checksum;
command_length +=1;
retry = 0;
sent = 0;
while ((sent != (command_lenght)) && (retry < 5)) {
while ((sent != (command_length)) && (retry < 5)) {
if (retry == 4) send_zeros(); /* last retry is preceded by a serial reset... */
sent = ser_send_buf(upsfd, raw_buf, (command_lenght));
if (sent != (command_lenght)) printf("Error sending command %d\n", raw_buf[2]);
sent = ser_send_buf(upsfd, raw_buf, (command_length));
if (sent != (command_length)) printf("Error sending command %d\n", raw_buf[2]);
retry += 1;
}
}
@ -164,8 +164,8 @@ void send_write_command(unsigned char *command, int command_lenght) {
/* get the answer of a command from the ups */
int get_answer(unsigned char *data) {
unsigned char my_buf[255]; /* packet has a maximum lenght of 256 bytes */
int packet_lenght, checksum, i, res;
unsigned char my_buf[255]; /* packet has a maximum length of 256 bytes */
int packet_length, checksum, i, res;
/* Read STX byte */
res = ser_get_char(upsfd, my_buf, 1, 0);
if (res < 1) {
@ -176,43 +176,43 @@ int get_answer(unsigned char *data) {
ser_comm_fail("Receive error (STX): packet not on start!!\n");
return -1;
}
/* Read data lenght byte */
/* Read data length byte */
res = ser_get_char(upsfd, my_buf, 1, 0);
if (res < 1) {
ser_comm_fail("Receive error (lenght): %d!!!\n", res);
ser_comm_fail("Receive error (length): %d!!!\n", res);
return -1;
}
packet_lenght = my_buf[0];
if (packet_lenght < 2) {
ser_comm_fail("Receive error (lenght): packet lenght %d!!!\n", packet_lenght);
packet_length = my_buf[0];
if (packet_length < 2) {
ser_comm_fail("Receive error (length): packet length %d!!!\n", packet_length);
return -1;
}
/* Try to read all the remainig bytes (packet_lenght) */
res = ser_get_buf_len(upsfd, my_buf, packet_lenght, 1, 0);
if (res != packet_lenght) {
ser_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res, packet_lenght);
/* Try to read all the remainig bytes (packet_length) */
res = ser_get_buf_len(upsfd, my_buf, packet_length, 1, 0);
if (res != packet_length) {
ser_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res, packet_length);
return -1;
}
/* now we have the whole answer from the ups, we can checksum it
checksum byte is equal to the sum modulus 256 of all the data bytes + packet_lenght
checksum byte is equal to the sum modulus 256 of all the data bytes + packet_length
(no STX no checksum byte itself) */
checksum = packet_lenght;
for (i = 0; i < (packet_lenght - 1); i++) checksum += my_buf[i];
checksum = packet_length;
for (i = 0; i < (packet_length - 1); i++) checksum += my_buf[i];
checksum = checksum % 256;
if (my_buf[packet_lenght-1] != checksum) {
ser_comm_fail("checksum error! got %x instad of %x, received %d bytes \n", my_buf[packet_lenght - 1], checksum, packet_lenght);
dump_buffer(my_buf, packet_lenght);
if (my_buf[packet_length-1] != checksum) {
ser_comm_fail("checksum error! got %x instad of %x, received %d bytes \n", my_buf[packet_length - 1], checksum, packet_length);
dump_buffer(my_buf, packet_length);
return -1;
}
packet_lenght-=1; /* get rid of the checksum byte */
memcpy(data, my_buf, packet_lenght);
return packet_lenght;
packet_length-=1; /* get rid of the checksum byte */
memcpy(data, my_buf, packet_length);
return packet_length;
}
/* send a read command and try get the answer, if something fails, it retries (5 times max)
if it is on the 4th or 5th retry, it will flush the serial before sending commands
it returns the lenght of the received answer or -1 in case of failure */
it returns the length of the received answer or -1 in case of failure */
int command_read_sequence(unsigned char command, unsigned char *data) {
int bytes_read = 0;
int retry = 0;
@ -234,13 +234,13 @@ int command_read_sequence(unsigned char command, unsigned char *data) {
/* send a write command and try get the answer, if something fails, it retries (5 times max)
if it is on the 4th or 5th retry, it will flush the serial before sending commands
it returns the lenght of the received answer or -1 in case of failure */
int command_write_sequence(unsigned char *command, int command_lenght, unsigned char *answer) {
it returns the length of the received answer or -1 in case of failure */
int command_write_sequence(unsigned char *command, int command_length, unsigned char *answer) {
int bytes_read = 0;
int retry = 0;
while ((bytes_read < 1) && (retry < 5)) {
send_write_command(command, command_lenght);
send_write_command(command, command_length);
bytes_read = get_answer(answer);
if (retry > 2) ser_flush_in(upsfd, "", 0);
retry += 1;

View file

@ -26,7 +26,7 @@
#include "usbhid-ups.h"
#include "mge-hid.h"
#define MGE_HID_VERSION "MGE HID 1.19"
#define MGE_HID_VERSION "MGE HID 1.21"
/* (prev. MGE Office Protection Systems, prev. MGE UPS SYSTEMS) */
/* Eaton */
@ -35,6 +35,9 @@
/* Dell */
#define DELL_VENDORID 0x047c
/* Powerware */
#define POWERWARE_VENDORID 0x0592
#ifndef SHUT_MODE
#include "usb-common.h"
@ -47,6 +50,9 @@ static usb_device_id_t mge_usb_device_table[] = {
/* various models */
{ USB_DEVICE(DELL_VENDORID, 0xffff), NULL },
/* PW 9140 */
{ USB_DEVICE(POWERWARE_VENDORID, 0x0004), NULL },
/* Terminating entry */
{ -1, -1, NULL }
};
@ -492,7 +498,8 @@ static usage_lkp_t mge_usage_lkp[] = {
{ "HighHumidity", 0xffff0082 },
{ "LowTemperature", 0xffff0083 },
{ "HighTemperature", 0xffff0084 },
/* 0xffff0085-0xffff008f => Reserved */
/* 0xffff0085-0xffff008f (minus 0xffff0086) => Reserved */
{ "Efficiency", 0xffff0086 },
{ "Count", 0xffff0090 },
{ "Timer", 0xffff0091 },
{ "Interval", 0xffff0092 },
@ -582,11 +589,17 @@ static models_name_t mge_model_names [] =
{ "PROTECTIONCENTER", "500", MGE_DEFAULT, "Protection Center 500" },
{ "PROTECTIONCENTER", "675", MGE_DEFAULT, "Protection Center 675" },
/* Protection Station */
/* Protection Station, supports Eco control */
{ "Protection Station", "500", MGE_PEGASUS, NULL },
{ "Protection Station", "650", MGE_PEGASUS, NULL },
{ "Protection Station", "800", MGE_PEGASUS, NULL },
/* Ellipse ECO, also supports Eco control */
{ "Ellipse ECO", "650", MGE_PEGASUS, NULL },
{ "Ellipse ECO", "800", MGE_PEGASUS, NULL },
{ "Ellipse ECO", "1200", MGE_PEGASUS, NULL },
{ "Ellipse ECO", "1600", MGE_PEGASUS, NULL },
/* Evolution models */
{ "Evolution", "500", MGE_DEFAULT, "Pulsar Evolution 500" },
{ "Evolution", "800", MGE_DEFAULT, "Pulsar Evolution 800" },
@ -689,6 +702,7 @@ static hid_info_t mge_hid2nut[] =
{ "battery.charge.restart", ST_FLAG_RW | ST_FLAG_STRING, 3, "UPS.PowerSummary.RestartLevel", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "battery.capacity", 0, 0, "UPS.BatterySystem.Battery.DesignCapacity", NULL, "%s", HU_FLAG_STATIC, mge_battery_capacity }, /* conversion needed from As to Ah */
{ "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL },
{ "battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.RemainingTimeLimit", NULL, "%.0f", 0, NULL },
{ "battery.runtime.elapsed", 0, 0, "UPS.StatisticSystem.Input.[1].Statistic.[1].Time", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL },
{ "battery.temperature", 0, 0, "UPS.BatterySystem.Battery.Temperature", NULL, "%s", 0, kelvin_celsius_conversion },
{ "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", HU_FLAG_STATIC, stringid_conversion },
@ -700,6 +714,7 @@ static hid_info_t mge_hid2nut[] =
{ "battery.energysave", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.PowerConverter.Input.[3].EnergySaving", NULL, "%s", HU_FLAG_SEMI_STATIC, yes_no_info },
/* UPS page */
{ "ups.efficiency", 0, 0, "UPS.PowerConverter.Output.Efficiency", NULL, "%.0f", 0, NULL },
{ "ups.firmware", 0, 0, "UPS.PowerSummary.iVersion", NULL, "%s", HU_FLAG_STATIC, stringid_conversion },
{ "ups.load", 0, 0, "UPS.PowerSummary.PercentLoad", NULL, "%.0f", 0, NULL },
{ "ups.load.high", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.Flow.[4].ConfigPercentLoad", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
@ -767,7 +782,7 @@ static hid_info_t mge_hid2nut[] =
/* Battery DC voltage too high! */
{ "BOOL", 0, 0, "UPS.BatterySystem.Battery.PresentStatus.VoltageTooHigh", NULL, NULL, 0, battvolthi_info },
{ "BOOL", 0, 0, "UPS.BatterySystem.Charger.PresentStatus.VoltageTooLow", NULL, NULL, 0, battvoltlo_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.VoltageTooLow", NULL, NULL, 0, battvoltlo_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.VoltageTooLow", NULL, NULL, 0, mge_onbatt_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.InternalFailure", NULL, NULL, 0, commfault_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.OverTemperature", NULL, NULL, 0, overheat_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, NULL, 0, shutdownimm_info },

View file

@ -221,13 +221,13 @@ unsigned char * CmdSerial(unsigned char *OutBuffer, int Len, unsigned char *RetB
unsigned char *p ;
int BuffLen ;
// The default error code (no received character)
/* The default error code (no received character) */
ErrCode = ERR_COM_NO_CHARS ;
SendCmdToSerial(OutBuffer, Len) ;
usleep(10000) ; // small delay (1/100 s))
usleep(10000) ; /* small delay (1/100 s) */
// get chars until timeout
/* get chars until timeout */
BuffLen = 0 ;
while (ser_get_char(upsfd, TmpBuff, 0, 10000) == 1)
{

View file

@ -7,7 +7,7 @@
* This model is based on PowerCom (www.powercom.com) models.
* -Socomec Sicon Egys 420
*
* $Id: powercom.c 2336 2010-02-11 20:16:43Z adkorte-guest $
* $Id: powercom.c 2990 2011-05-19 18:34:09Z aquette $
*
* Copyrights:
* (C) 2002 Simon Rozman <simon@rozman.net>
@ -51,6 +51,15 @@
* - strange battery level on BNT1200AP in online mode( & may be on other models)
* - i don't know how connect to IMP|IMD USB
* - i havn't specs for BNT 100-120V models. Add BNT-other type for it
*
* rev 0.13: Keven Ates <atescomp@gmail.com>
* - Modified functions to work for BNT-other 100-120V models.
* - Modified BNT-other type defaults to work for the BNT 1500A 120VA model.
* - Documented the type[] values purpose in a condensed format.
* - BNT-other can be used to perform a complete user override of values for all PowerCom models, detected or not.
*
* Tested on: BNT-1500A
*
*/
#include "main.h"
@ -59,7 +68,7 @@
#include "math.h"
#define DRIVER_NAME "PowerCom protocol UPS driver"
#define DRIVER_VERSION "0.12"
#define DRIVER_VERSION "0.13"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@ -92,7 +101,28 @@ static unsigned int type = 0;
static void dtr0rts1 (void);
static void no_flow_control (void);
/* struct defining types */
/* struct defining types
* ---------------------
* See powercom.h for detailed information and functions.
*
* The following type defaults use this definition:
*
* "TypeID",
* ByteCount,
* { "FlowControlString", FlowControlFuncPtr },
* { { ValidationIndex, ValidationValue },
* { ValidationIndex, ValidationValue },
* { ValidationIndex, ValidationValue } },
* { { DelayShutdownMinutes, DelayShutdownSeconds },
* UseMinutesChar'y''n' },
* { FrequencyFactor, FrequencyConstant },
* { OfflineLoadFactor, OfflineLoadConstant,
* OnlineLoadFactor, OnlineLoadConstant },
* { OfflineBatteryFactor, OfflineLoad%Factor, OfflineBatteryConstant,
* OnlineBatteryFactor, OnlineBatteryConstant },
* { 240VoltageFactor, 240VoltageConstant,
* 120VoltageFactor, 120VoltageConstant },
*/
static struct type types[] = {
{
"Trust",
@ -166,10 +196,10 @@ static struct type types[] = {
{ "no_flow_control", no_flow_control },
{ { 8U, 0U }, { 8U, 0U }, { 8U, 0U } },
{ { 1U, 30U }, 'y' },
{ 0.00020803, 0.0 },
{ 1.4474, 0.0, 0.8594, 0.0 },
{ 5.0000, 0.3268, -825.00, 0.46511, 0 },
{ 1.9216, -0.0977, 0.82857, 0.0000 },
{ 0.00027778, 0.0000 },
{ 1.0000, 0.0000, 1.0000, 0.0000 },
{ 1.0000, 0.0000, 0.0000, 1.0000, 0.0000 },
{ 2.0000, 0.0000, 2.0000, 0.0000 },
},
};
@ -217,10 +247,10 @@ enum status {
OFF = 128U
};
unsigned int voltages[]={100,110,115,120,0,0,0,200,220,230,240};
unsigned int BNTmodels[]={0,400,500,600,800,801,1000,1200,1500,2000};
unsigned int KINmodels[]={0,425,500,525,625,800,1000,1200,1500,1600,2200,2200,2500,3000,5000};
unsigned int IMPmodels[]={0,425,525,625,825,1025,1200,1500,2000};
unsigned int voltages[]={100,110,115,120,0,0,0,200,220,230,240,0,0,0,0,0};
unsigned int BNTmodels[]={0,400,500,600,800,801,1000,1200,1500,2000,0,0,0,0,0,0};
unsigned int KINmodels[]={0,425,500,525,625,800,1000,1200,1500,1600,2200,2200,2500,3000,5000,0};
unsigned int IMPmodels[]={0,425,525,625,825,1025,1200,1500,2000,0,0,0,0,0,0,0};
/*
* local used functions
@ -338,6 +368,7 @@ static int ups_getinfo(void)
/* optional dump of raw data */
if (nut_debug_level > 4) {
/* FIXME: use upsdebug_hex() ? */
printf("Raw data from UPS:\n");
for (i = 0; i < types[type].num_of_bytes_from_ups; i++) {
printf("%2d 0x%02x (%c)\n", i, raw_data[i], raw_data[i]>=0x20 ? raw_data[i] : ' ');
@ -475,7 +506,7 @@ static float output_voltage(void)
static float input_freq(void)
{
if ( !strncmp(types[type].name, "BNT",3) || !strcmp(types[type].name, "KIN"))
if ( !strcmp(types[type].name, "BNT") || !strcmp(types[type].name, "KIN"))
return 4807.0/raw_data[INPUT_FREQUENCY];
else if ( !strcmp(types[type].name, "IMP"))
return raw_data[INPUT_FREQUENCY];
@ -487,7 +518,7 @@ static float input_freq(void)
static float output_freq(void)
{
if ( !strncmp(types[type].name, "BNT",3) || !strcmp(types[type].name, "KIN"))
if ( !strcmp(types[type].name, "BNT") || !strcmp(types[type].name, "KIN"))
return 4807.0/raw_data[OUTPUT_FREQUENCY];
else if ( !strcmp(types[type].name, "IMP"))
return raw_data[OUTPUT_FREQUENCY];
@ -574,7 +605,7 @@ static float batt_level(void)
int bat0,bat29,bat100,model;
float battval;
if ( !strncmp(types[type].name, "BNT",3) ) {
if ( !strcmp(types[type].name, "BNT") ) {
bat0=157;
bat29=165;
bat100=193;
@ -617,11 +648,13 @@ static float batt_level(void)
}
if ( !strcmp(types[type].name, "IMP"))
return raw_data[BATTERY_CHARGE];
return raw_data[STATUS_A] & ONLINE ?
return raw_data[STATUS_A] & ONLINE ? /* Are we on battery power? */
/* Yes */
types[type].battpct[0] * raw_data[BATTERY_CHARGE] +
types[type].battpct[1] * load_level() + types[type].battpct[2] :
/* No */
types[type].battpct[3] * raw_data[BATTERY_CHARGE] +
types[type].battpct[4];
types[type].battpct[4];
}
/*
@ -852,27 +885,31 @@ void upsdrv_initups(void)
/* setup flow control */
types[type].flowControl.setup_flow_control();
/* Setup Model and LineVoltage */
if (!strncmp(types[type].name, "BNT",3) || !strcmp(types[type].name, "KIN") || !strcmp(types[type].name, "IMP")){
if (!ups_getinfo()) return;
if (raw_data[UPSVERSION]==0xFF){
/* Give "BNT-other" a chance! */
if (raw_data[MODELNAME]==0x42 || raw_data[MODELNAME]==0x4B){
model=BNTmodels[raw_data[MODELNUMBER]/16];
if (!strcmp(types[type].name, "BNT-other"))
types[type].name="BNT-other";
else if (raw_data[MODELNAME]==0x42)
types[type].name="BNT";
else if (raw_data[MODELNAME]==0x4B){
types[type].name="KIN";
model=KINmodels[raw_data[MODELNUMBER]/16];
}
}
else if (raw_data[UPSVERSION]==0xFF){
types[type].name="IMP";
model=IMPmodels[raw_data[MODELNUMBER]/16];
}
if (raw_data[MODELNAME]==0x42){
if (!strcmp(types[type].name, "BNT-other"))
types[type].name="BNT-other";
else
types[type].name="BNT";
model=BNTmodels[raw_data[MODELNUMBER]/16];
}
if (raw_data[MODELNAME]==0x4B){
types[type].name="KIN";
model=KINmodels[raw_data[MODELNUMBER]/16];
}
linevoltage=voltages[raw_data[MODELNUMBER]%16];
snprintf(buf,sizeof(buf),"%s-%dAP",types[type].name,model);
modelname=buf;
upsdebugx(1,"Detected: %s , %dV",modelname,linevoltage);
if (!strcmp(modelname, "Unknown"))
modelname=buf;
upsdebugx(1,"Detected: %s , %dV",buf,linevoltage);
if (ser_send_char (upsfd, BATTERY_TEST) != 1) {
upslogx(LOG_NOTICE, "writing error");
dstate_datastale();
@ -922,23 +959,65 @@ void upsdrv_initups(void)
/* display help */
void upsdrv_help(void)
{
printf("You must specify type in ups.conf\n");
printf("Type of UPS like 'Trust', 'Egys', 'KP625AP', 'IMP', 'KIN' or 'BNT' or 'BNT-other' (default: 'Trust')\n");
printf("BNT-other - it's a special type for BNT 100-120V models \n");
printf("You can additional cpecify next variables:\n");
printf(" shutdownArguments: The number of delay arguments and their values for the shutdown operation\n");
printf("Also, you can specify next variables (not work for 'IMP', 'KIN' or 'BNT', because detected automatically or known\n");
printf(" manufacturer: Specify manufacturer name (default: 'PowerCom')\n");
printf(" modelname: Specify model name, because it cannot detect automagically (default: Unknown)\n");
printf(" serialnumber: Specify serial number, because it cannot detect automatically (default: Unknown)\n");
printf(" linevoltage: Specify line voltage (110-120 or 220-240 V), if it cannot detect automatically (default: 230 V)\n");
printf(" numOfBytesFromUPS: The number of bytes in a UPS frame\n");
printf(" methodOfFlowControl: The flow control method engaged by the UPS\n");
printf(" validationSequence: 3 pairs to be used for validating the UPS\n");
printf(" voltage: A quad to convert the raw data to human readable voltage\n");
printf(" frequency: A pair to convert the raw data to human readable freqency\n");
printf(" batteryPercentage: A 5 tuple to convert the raw data to human readable battery percentage\n");
printf(" loadPercentage: A quad to convert the raw data to human readable load percentage\n");
// 1 2 3 4 5 6 7 8
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890 MAX
printf("\n");
printf("Specify UPS information in the ups.conf file.\n");
printf(" type: Type of UPS: 'Trust','Egys','KP625AP','IMP','KIN','BNT',\n");
printf(" 'BNT-other' (default: 'Trust')\n");
printf(" 'BNT-other' is a special type intended for BNT 100-120V models,\n");
printf(" but can be used to override ALL models.\n");
printf("You can additional specify these variables:\n");
printf(" manufacturer: Manufacturer name (default: 'PowerCom')\n");
printf(" modelname: Model name (default: 'Unknown' or autodetected)\n");
printf(" serialnumber: Serial number (default: Unknown)\n");
printf(" shutdownArguments: 3 delay arguments for the shutdown operation:\n");
printf(" {{Minutes,Seconds},UseMinutes?}\n");
printf(" where Minutes and Seconds are integer, UseMinutes? is either\n");
printf(" 'y' or 'n'.\n");
printf("You can specify these variables if not automagically detected for types\n");
printf(" 'IMP','KIN','BNT'\n");
printf(" linevoltage: Line voltage: 110-120 or 220-240 (default: 230)\n");
printf(" numOfBytesFromUPS: Number of bytes in a UPS frame: 16 is common, 11 for 'Trust'\n");
printf(" methodOfFlowControl: Flow control method for UPS:\n");
printf(" 'dtr0rts1', 'dtr1' or 'no_flow_control'\n");
printf(" validationSequence: 3 pairs of validation values: {{I,V},{I,V},{I,V}}\n");
printf(" where I is the index into BytesFromUPS (see numOfBytesFromUPS)\n");
printf(" and V is the value for the ByteIndex to match.\n");
printf(" frequency: Input & Output Frequency conversion values: {A, B}\n");
printf(" used in function: 1/(A*x+B)\n");
printf(" If the raw value x IS the frequency, then A=1/(x^2), B=0\n");
printf(" loadPercentage: Load conversion values for Battery and Line load: {BA,BB,LA,LB}\n");
printf(" used in function: A*x+B\n");
printf(" If the raw value x IS the Load Percent, then A=1, B=0\n");
printf(" batteryPercentage: Battery conversion values for Battery and Line power:\n");
printf(" {A,B,C,D,E}\n");
printf(" used in functions: (Battery) A*x+B*y+C, (Line) D*x+E\n");
printf(" If the raw value x IS the Battery Percent, then\n");
printf(" A=1, B=0, C=0, D=1, E=0\n");
printf(" voltage: Voltage conversion values for 240 and 120 voltage:\n");
printf(" {240A,240B,120A,120B}\n");
printf(" used in function: A*x+B\n");
printf(" If the raw value x IS HALF the Voltage, then A=2, B=0\n\n");
printf("Example for BNT1500AP in ups.conf:\n");
printf("[BNT1500AP]\n");
printf(" driver = powercom\n");
printf(" port = /dev/ttyS0\n");
printf(" desc = \"PowerCom BNT 1500 AP\"\n");
printf(" manufacturer = PowerCom\n");
printf(" modelname = BNT1500AP\n");
printf(" serialnumber = 13245678900\n");
printf(" type = BNT-other\n");
printf("# linevoltage = 120\n");
printf("# numOfBytesFromUPS = 16\n");
printf("# methodOfFlowControl = no_flow_control\n");
printf("# validationSequence = {{8,0},{8,0},{8,0}}\n");
printf("# shutdownArguments = {{1,30},y}\n");
printf("# frequency = {0.00027778,0.0000}\n");
printf("# loadPercentage = {1.0000,0.0,1.0000,0.0}\n");
printf("# batteryPercentage = {1.0000,0.0000,0.0000,1.0000,0.0000}\n");
printf("# voltage = {2.0000,0.0000,2.0000,0.0000}\n");
return;
}
@ -962,20 +1041,36 @@ void upsdrv_initinfo(void)
/* define possible arguments */
void upsdrv_makevartable(void)
{
addvar(VAR_VALUE, "manufacturer", "Specify manufacturer name (default: 'PowerCom')");
addvar(VAR_VALUE, "linevoltage", "Specify line voltage (110-120 or 220-240 V), if it cannot detect automatically (default: 230 V)");
addvar(VAR_VALUE, "modelname", "Specify model name, because it cannot detect automagically (default: Unknown)");
addvar(VAR_VALUE, "serialnumber", "Specify serial number, because it cannot detect automatically (default: Unknown)");
addvar(VAR_VALUE, "type", "Type of UPS like 'Trust', 'Egys', 'KP625AP', 'IMP', 'KIN' or 'BNT' or 'BNT-other' (default: 'Trust')");
addvar(VAR_VALUE, "numOfBytesFromUPS", "The number of bytes in a UPS frame");
addvar(VAR_VALUE, "methodOfFlowControl", "The flow control method engaged by the UPS");
addvar(VAR_VALUE, "shutdownArguments", "The number of delay arguments and their values for the shutdown operation");
addvar(VAR_VALUE, "validationSequence", "3 pairs to be used for validating the UPS");
// 1 2 3 4 5 6 7 8
//2345678901234567890123456789012345678901234567890123456789012345678901234567890 MAX
addvar(VAR_VALUE, "type",
"Type of UPS: 'Trust','Egys','KP625AP','IMP','KIN','BNT','BNT-other'\n"
" (default: 'Trust')");
addvar(VAR_VALUE, "manufacturer",
"Manufacturer name (default: 'PowerCom')");
addvar(VAR_VALUE, "modelname",
"Model name [cannot be detected] (default: Unknown)");
addvar(VAR_VALUE, "serialnumber",
"Serial number [cannot be detected] (default: Unknown)");
addvar(VAR_VALUE, "shutdownArguments",
"Delay values for shutdown: Minutes, Seconds, UseMinutes?'y'or'n'");
addvar(VAR_VALUE, "linevoltage",
"Line voltage 110-120 or 220-240 V (default: 230)");
addvar(VAR_VALUE, "numOfBytesFromUPS",
"The number of bytes in a UPS frame");
addvar(VAR_VALUE, "methodOfFlowControl",
"Flow control method for UPS: 'dtr0rts1' or 'no_flow_control'");
addvar(VAR_VALUE, "validationSequence",
"Validation values: ByteIndex, ByteValue x 3");
if ( strcmp(types[type].name, "KIN") && strcmp(types[type].name, "BNT") && strcmp(types[type].name, "IMP")) {
addvar(VAR_VALUE, "voltage", "A quad to convert the raw data to human readable voltage");
addvar(VAR_VALUE, "frequency", "A pair to convert the raw data to human readable freqency");
addvar(VAR_VALUE, "batteryPercentage", "A 5 tuple to convert the raw data to human readable battery percentage");
addvar(VAR_VALUE, "loadPercentage", "A quad to convert the raw data to human readable load percentage");
addvar(VAR_VALUE, "frequency",
"Frequency conversion values: FreqFactor, FreqConst");
addvar(VAR_VALUE, "loadPercentage",
"Load conversion values: OffFactor, OffConst, OnFactor, OnConst");
addvar(VAR_VALUE, "batteryPercentage",
"Battery conversion values: OffFactor, LoadFactor, OffConst, OnFactor, OnConst");
addvar(VAR_VALUE, "voltage",
"Voltage conversion values: 240VFactor, 240VConst, 120VFactor, 120VConst");
}
}

View file

@ -1,7 +1,7 @@
/*
* powercom.h - defines for the newpowercom.c driver
*
* $Id: powercom.h 2627 2010-10-26 21:09:34Z adkorte-guest $
* $Id: powercom.h 2984 2011-05-13 13:18:34Z aquette $
*
* Copyrights:
* (C) 2002 Simon Rozman <simon@rozman.net>
@ -62,39 +62,39 @@ struct type {
* the COUNTER commands while others are known to work with the
* seconds argument alone.
*/
struct deley_for_power_kill {
struct delay_for_power_kill {
unsigned int delay[2]; /* { minutes, seconds } */
unsigned char minutesShouldBeUsed;
/* 'n' in case the minutes value, which is deley[0], should
/* 'n' in case the minutes value, which is delay[0], should
* be skipped and not sent to the UPS.
*/
} shutdown_arguments;
/* parameters to calculate input and output freq., one pair for
* each type:
* Each pair defines parameters for 1/(A*x+B) to calculate freq.
* from raw data
/* parameters to calculate input and output freq., one pair used for
* both input and output functions:
* The pair [0],[1] defines parameters for 1/(A*x+B) to calculate freq.
* from raw data 'x'.
*/
float freq[2];
/* parameters to calculate load %, two pairs for each type:
* First pair defines the parameters for A*x+B to calculate load
* from raw data when offline and the second pair is used when
* First pair [0],[1] defines the parameters for A*x+B to calculate load
* from raw data when offline and the second pair [2],[3] is used when
* online
*/
float loadpct[4];
/* parameters to calculate battery %, five parameters for each type:
* First three params defines the parameters for A*x+B*y+C to calculate
* First three params [0],[1],[2] defines the parameters for A*x+B*y+C to calculate
* battery % (x is raw data, y is load %) when offline.
* Fourth and fifth parameters are used to calculate D*y+E when online.
* Fourth and fifth parameters [3],[4] are used to calculate D*x+E when online.
*/
float battpct[5];
/* parameters to calculate utility and output voltage, two pairs for
* each type:
* First pair defines the parameters for A*x+B to calculate utility
* from raw data when line voltage is >=220 and the second pair
* First pair [0],[1] defines the parameters for A*x+B to calculate utility
* from raw data when line voltage is >=220 and the second pair [2],[3]
* is used otherwise.
*/
float voltage[4];

View file

@ -22,7 +22,7 @@
2005/10/26 - Version 0.40 - Operational-2 release
2005/11/29 - Version 0.50 - rhino commands release
http://www.microsol.com.br
*/
@ -63,28 +63,27 @@ typedef int bool_t;
#define CMD_PASSOFF 0x0006
#define CMD_UPSCONT 0x0053
/* xoff - xon protocol
#define _SOH = 0x01; // start of header
#define _EOT = 0x04; // end of transmission
#define _ACK = 0x06; // acknoledge (positive)
#define _DLE = 0x10; // data link escape
#define _XOn = 0x11; // transmit on
#define _XOff = 0x13; // transmit off
#define _NAK = 0x15; // negative acknoledge
#define _SYN = 0x16; // synchronous idle
#define _CAN = 0x18; // cancel
*/
/* xoff - xon protocol */
#define _SOH = 0x01; /* start of header */
#define _EOT = 0x04; /* end of transmission */
#define _ACK = 0x06; /* acknoledge (positive) */
#define _DLE = 0x10; /* data link escape */
#define _XOn = 0x11; /* transmit on */
#define _XOff = 0x13; /* transmit off */
#define _NAK = 0x15; /* negative acknoledge */
#define _SYN = 0x16; /* synchronous idle */
#define _CAN = 0x18; /* cancel */
static int const pacsize = 37; /* size of receive data package */
/* autonomy calcule */
static double const AmpH = 40; // Amperes-hora da bateria
static double const VbatMin = 126; // Tensão mínina das baterias
static double const VbatNom = 144; // Tensão nominal das baterias
static double const FM = 0.32; // Fator multiplicativo de correção da autonomia
static double const FA = -2; // Fator aditivo de correção da autonomia
static double const ConstInt = 250; // Consumo interno sem o carregador
static double const Vin = 220; // Tensão de entrada
static double const AmpH = 40; /* Amperes-hora da bateria */
static double const VbatMin = 126; /* Tensão mínina das baterias */
static double const VbatNom = 144; /* Tensão nominal das baterias */
static double const FM = 0.32; /* Fator multiplicativo de correção da autonomia */
static double const FA = -2; /* Fator aditivo de correção da autonomia */
static double const ConstInt = 250; /* Consumo interno sem o carregador */
static double const Vin = 220; /* Tensão de entrada */
static int Day, Month, Year;
static int dian=0, mesn=0, anon=0, weekn=0;
@ -93,8 +92,8 @@ static int ihour,imin, isec;
/* char seman[4]; */
/* int FExpansaoBateria; */
// internal variables
// package handshake ariables
/* internal variables */
/* package handshake variables */
/* int ContadorEstouro; */
static bool_t detected;
static bool_t SourceFail, Out110, RedeAnterior, OcorrenciaDeFalha;
@ -125,7 +124,7 @@ static int BoostVolt, Rendimento;
static unsigned char StatusEntrada, StatusSaida, StatusBateria;
/* events group */
static unsigned char EventosRede, EventosSaida, EventosBateria;
// Grupo de Programação
/* Grupo de Programação */
/* Methods */
static void ScanReceivePack(void);
@ -261,16 +260,16 @@ ScanReceivePack( void )
if( RecPack[0] ==0xC2 )
{
LimInfBattSrc = 174;
LimSupBattSrc = 192;//180????? carregador eh 180 (SCOPOS)
LimSupBattSrc = 192;/* 180????? carregador eh 180 (SCOPOS) */
LimInfBattInv = 174;
LimSupBattInv = 192;//170????? (SCOPOS)
LimSupBattInv = 192;/* 170????? (SCOPOS) */
}
else
{
LimInfBattSrc = 138;
LimSupBattSrc = 162;//180????? carregador eh 180 (SCOPOS)
LimSupBattSrc = 162;/* 180????? carregador eh 180 (SCOPOS) */
LimInfBattInv = 126;
LimSupBattInv = 156;//170????? (SCOPOS)
LimSupBattInv = 156;/* 170????? (SCOPOS) */
}
BattNonValue = 144;
@ -300,10 +299,10 @@ ScanReceivePack( void )
if( BypassOn )
OutVoltage = ( InVoltage * 1.0 / 2 ) + 5;
if( SourceFail && RedeAnterior ) // falha pela primeira vez
if( SourceFail && RedeAnterior ) /* falha pela primeira vez */
OcorrenciaDeFalha = true;
if( !( SourceFail ) && !( RedeAnterior ) ) // retorno da rede
if( !( SourceFail ) && !( RedeAnterior ) ) /* retorno da rede */
RetornoDaRede = true;
if( !( SourceFail ) == RedeAnterior )
@ -333,7 +332,7 @@ ScanReceivePack( void )
RecPack[8] = 99; /* ??????????????????????????????????? */
}
if( OutputOn ) // Output Status
if( OutputOn ) /* Output Status */
StatusSaida = 2;
else
StatusSaida = 1;
@ -341,7 +340,7 @@ ScanReceivePack( void )
if( OverCharge )
StatusSaida = 3;
if( CriticBatt ) // Battery Status
if( CriticBatt ) /* Battery Status */
StatusBateria = 4;
else
StatusBateria = 1;
@ -494,7 +493,7 @@ send_command( int cmd )
if( i == 1)
chk = cmd;
else
chk = 0x00; // 0x20;
chk = 0x00; /* 0x20; */
}
ch = chk;
@ -511,7 +510,7 @@ send_command( int cmd )
kount = 0;
while ( kount < 5 )
{
/* ret = ser_send_buf_pace(upsfd, UPSDELAY, psend, sizes );// optional delay */
/* ret = ser_send_buf_pace(upsfd, UPSDELAY, psend, sizes ); */ /* optional delay */
for(i=0; i < 19; i++)
{
@ -564,7 +563,7 @@ static void getbaseinfo(void)
while ( ( !detected ) && ( j < 10 ) )
{
temp[0] = 0; // flush temp buffer
temp[0] = 0; /* flush temp buffer */
tam = ser_get_buf_len(upsfd, temp, pacsize, 3, 0);
if( tam == 37 )
{
@ -628,10 +627,10 @@ static void getbaseinfo(void)
dstate_setinfo("input.transfer.high", "%03.1f", InUpLim); LimSupBattInv ?
*/
dstate_addcmd("shutdown.stayoff"); // CMD_SHUT
dstate_addcmd("shutdown.stayoff"); /* CMD_SHUT */
/* there is no reserved words for CMD_INON and CMD_INOFF yet */
/* dstate_addcmd("input.on"); // CMD_INON = 1 */
/* dstate_addcmd("input.off"); // CMD_INOFF = 2 */
/* dstate_addcmd("input.on"); */ /* CMD_INON = 1 */
/* dstate_addcmd("input.off"); */ /* CMD_INOFF = 2 */
dstate_addcmd("load.on"); /* CMD_OUTON = 3 */
dstate_addcmd("load.off"); /* CMD_OUTOFF = 4 */
dstate_addcmd("bypass.start"); /* CMD_PASSON = 5 */
@ -671,7 +670,7 @@ static int instcmd(const char *cmdname, const char *extra)
if (!strcasecmp(cmdname, "shutdown.stayoff"))
{
// shutdown now (one way)
/* shutdown now (one way) */
/* send_command( CMD_SHUT ); */
sendshut();
return STAT_INSTCMD_HANDLED;
@ -679,7 +678,7 @@ static int instcmd(const char *cmdname, const char *extra)
if (!strcasecmp(cmdname, "load.on"))
{
// liga Saida
/* liga Saida */
ret = send_command( 3 );
if ( ret < 1 )
upslogx(LOG_ERR, "send_command 3 failed");
@ -688,7 +687,7 @@ static int instcmd(const char *cmdname, const char *extra)
if (!strcasecmp(cmdname, "load.off"))
{
// desliga Saida
/* desliga Saida */
ret = send_command( 4 );
if ( ret < 1 )
upslogx(LOG_ERR, "send_command 4 failed");
@ -697,7 +696,7 @@ static int instcmd(const char *cmdname, const char *extra)
if (!strcasecmp(cmdname, "bypass.start"))
{
// liga Bypass
/* liga Bypass */
ret = send_command( 5 );
if ( ret < 1 )
upslogx(LOG_ERR, "send_command 5 failed");
@ -706,7 +705,7 @@ static int instcmd(const char *cmdname, const char *extra)
if (!strcasecmp(cmdname, "bypass.stop"))
{
// desliga Bypass
/* desliga Bypass */
ret = send_command( 6 );
if ( ret < 1 )
upslogx(LOG_ERR, "send_command 6 failed");
@ -771,7 +770,7 @@ void upsdrv_shutdown(void)
/* on line: send normal shutdown, ups will return by itself on utility */
/* on battery: send shutdown+return, ups will cycle and return soon */
if (!SourceFail) // on line
if (!SourceFail) /* on line */
{
printf("On line, forcing shutdown command...\n");
send_command( CMD_SHUT );

View file

@ -484,7 +484,7 @@ bool_t nut_snmp_get_str(const char *OID, char *buf, size_t buf_len, info_lkp_t *
len = snprintf(buf, buf_len, "%ld", *pdu->variables->val.integer / 100);
break;
default:
upslogx(LOG_ERR, "[%s] unhandled ASN 0x%x recieved from %s",
upslogx(LOG_ERR, "[%s] unhandled ASN 0x%x received from %s",
upsname?upsname:device_name, pdu->variables->type, OID);
return FALSE;
break;
@ -524,7 +524,7 @@ bool_t nut_snmp_get_int(const char *OID, long *pval)
value = *pdu->variables->val.integer / 100;
break;
default:
upslogx(LOG_ERR, "[%s] unhandled ASN 0x%x recieved from %s",
upslogx(LOG_ERR, "[%s] unhandled ASN 0x%x received from %s",
upsname?upsname:device_name, pdu->variables->type, OID);
return FALSE;
break;
@ -1459,7 +1459,7 @@ static int parse_mibconf_args(int numargs, char **arg)
if (ret == FALSE)
upslogx(LOG_ERR, "su_setvar: cannot set value %s for %s", arg[4], arg[3]);
else
upsdebugx(1, "su_setvar: sucessfully set %s to \"%s\"", arg[0], arg[4]);
upsdebugx(1, "su_setvar: successfully set %s to \"%s\"", arg[0], arg[4]);
return 1;
}

View file

@ -282,23 +282,12 @@ static unsigned char revertdays( unsigned char dweek )
static int IsHour( char *strx, int qual )
{
char shora[3], smin[3], sep[2];
int hora=0, min = 0, len = 0;
int hora=0, min = 0;
len = strlen( strx );
if ( len != 5 )
return -1;
sscanf( strx, "%2s%1s%2s", shora, sep, smin);
if( sep[0] != ':' )
return -1;
if( (!isdigit( shora[0] )) || (!isdigit( shora[1] )) )
return -1;
if( (!isdigit( smin[0] )) || (!isdigit( smin[1] )) )
if ((strlen(strx) != 5) || (sscanf(strx, "%d:%d", &hora, &min) != 2)) {
return -1;
}
hora = atoi( shora );
min = atoi( smin );
if( qual ) {
dhour = hora;
dmin = min;
@ -408,7 +397,7 @@ static int IsToday( unsigned char dweek, int nweek)
switch ( nweek )
{
case 0: // sunday
case 0: /* sunday */
return ( ( ( dweek & 0x40 ) == 0x40 ) );
case 1:
return ( ( ( dweek & 0x20 ) == 0x20 ) );
@ -420,7 +409,7 @@ static int IsToday( unsigned char dweek, int nweek)
return ( ( ( dweek & 0x04 ) == 0x04 ) );
case 5:
return ( ( ( dweek & 0x02 ) == 0x02 ) );
case 6: // saturday
case 6: /* saturday */
return ( ( ( dweek & 0x01 ) == 0x01 ) );
}
@ -802,7 +791,7 @@ static void getbaseinfo(void)
#else
char DaysOfWeek[7][4]={"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
#endif
char mycmd[8]; // , ch;
char mycmd[8];
char *str1, *str2, *str3, *str4, *strx;
unsigned char Pacote[25];
int i, i1=0, i2=0, j=0, tam, tpac=25;
@ -871,7 +860,7 @@ static void getbaseinfo(void)
}
}
} // end prgups 1 - 2
} /* end prgups 1 - 2 */
/* dummy read attempt to sync - throw it out */
snprintf(mycmd, sizeof(mycmd), "%c%c",CMD_UPSCONT, ENDCHAR);
@ -879,7 +868,7 @@ static void getbaseinfo(void)
/* trying detect solis model */
while ( ( !detected ) && ( j < 20 ) ) {
temp[0] = 0; // flush temp buffer
temp[0] = 0; /* flush temp buffer */
tam = ser_get_buf_len(upsfd, temp, tpac, 3, 0);
if( tam == 25 ) {
for( i = 0 ; i < tam ; i++ ) {
@ -1011,17 +1000,17 @@ static int instcmd(const char *cmdname, const char *extra)
{
if (!strcasecmp(cmdname, "shutdown.return")) {
// shutdown and restart
ser_send_char(upsfd, CMD_SHUTRET); // 0xDE
// ser_send_char(upsfd, ENDCHAR);
/* shutdown and restart */
ser_send_char(upsfd, CMD_SHUTRET); /* 0xDE */
/* ser_send_char(upsfd, ENDCHAR); */
return STAT_INSTCMD_HANDLED;
}
if (!strcasecmp(cmdname, "shutdown.stayoff"))
{
// shutdown now (one way)
ser_send_char(upsfd, CMD_SHUT); // 0xDD
// ser_send_char(upsfd, ENDCHAR);
/* shutdown now (one way) */
ser_send_char(upsfd, CMD_SHUT); /* 0xDD */
/* ser_send_char(upsfd, ENDCHAR); */
return STAT_INSTCMD_HANDLED;
}
@ -1082,7 +1071,7 @@ void upsdrv_shutdown(void)
/* on battery: send normal shutdown, ups will return by itself on utility */
/* on line: send shutdown+return, ups will cycle and return soon */
if (!SourceFail) { // on line
if (!SourceFail) { /* on line */
printf("On line, sending shutdown+return command...\n");
ser_send_char(upsfd, CMD_SHUTRET );

View file

@ -71,7 +71,10 @@ void USBFreeExactMatcher(USBDeviceMatcher_t *matcher);
void USBFreeRegexMatcher(USBDeviceMatcher_t *matcher);
/* dummy USB function and macro, inspired from the Linux kernel
* this allows USB information extraction */
* this allows USB information extraction
* CAUTION: only use with *valid* device identifiers, Ie the following is not
* valid (from blazer_usb, krauler subdriver): 0x0001:0x0000
*/
#define USB_DEVICE(vendorID, productID) vendorID, productID
typedef struct {