new upstream 2.8.0
This commit is contained in:
parent
fc7f4b43c1
commit
b2b0c9995a
836 changed files with 137090 additions and 30018 deletions
|
@ -2,7 +2,8 @@
|
|||
|
||||
Copyright (C)
|
||||
2008-2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
|
||||
2009 Arnaud Quette <ArnaudQuette@Eaton.com>
|
||||
2009-2021 Eaton (author: Arnaud Quette <ArnaudQuette@Eaton.com>)
|
||||
2017 Eaton (author: Jim Klimov <EvgenyKlimov@Eaton.com>)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -19,6 +20,8 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h" /* must be the first header */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -30,18 +33,29 @@
|
|||
|
||||
#include "netxml-ups.h"
|
||||
#include "mge-xml.h"
|
||||
#include "main.h" /* for testvar() */
|
||||
|
||||
#define MGE_XML_VERSION "MGEXML/0.36"
|
||||
|
||||
#define MGE_XML_VERSION "MGEXML/0.25"
|
||||
#define MGE_XML_INITUPS "/"
|
||||
#define MGE_XML_INITINFO "/mgeups/product.xml /product.xml /ws/product.xml"
|
||||
|
||||
#define ST_FLAG_RW 0x0001
|
||||
#define ST_FLAG_STATIC 0x0002
|
||||
|
||||
extern int shutdown_duration;
|
||||
|
||||
static int mge_ambient_value = 0;
|
||||
|
||||
/* The number of phases is not present in XML data as a separate node,
|
||||
* but we can infer it from presence of non-zero data on several
|
||||
* per-line nodes. */
|
||||
static int
|
||||
inited_phaseinfo_in = 0,
|
||||
inited_phaseinfo_bypass = 0,
|
||||
inited_phaseinfo_out = 0,
|
||||
num_inphases = -1,
|
||||
num_bypassphases = -1,
|
||||
num_outphases = -1;
|
||||
|
||||
static char mge_scratch_buf[256];
|
||||
|
||||
static char var[128];
|
||||
|
@ -49,6 +63,9 @@ static char val[128];
|
|||
|
||||
static int mge_shutdown_pending = 0;
|
||||
|
||||
/* This flag flips to 0 when/if we post the detailed deprecation message */
|
||||
static int mge_report_deprecation__convert_deci = 1;
|
||||
|
||||
typedef enum {
|
||||
ROOTPARENT = NE_XML_STATEROOT,
|
||||
|
||||
|
@ -114,9 +131,9 @@ typedef struct {
|
|||
NULL if no further processing is required) */
|
||||
} xml_info_t;
|
||||
|
||||
static const char *online_info(const char *val)
|
||||
static const char *online_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(ONLINE);
|
||||
} else {
|
||||
STATUS_CLR(ONLINE);
|
||||
|
@ -125,9 +142,9 @@ static const char *online_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *discharging_info(const char *val)
|
||||
static const char *discharging_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(DISCHRG);
|
||||
/* Workaround NMC bug: both charging and discharging set to 1 */
|
||||
if(STATUS_BIT(CHRG)) {
|
||||
|
@ -140,9 +157,9 @@ static const char *discharging_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *charging_info(const char *val)
|
||||
static const char *charging_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(CHRG);
|
||||
} else {
|
||||
STATUS_CLR(CHRG);
|
||||
|
@ -151,9 +168,9 @@ static const char *charging_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *lowbatt_info(const char *val)
|
||||
static const char *lowbatt_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(LOWBATT);
|
||||
} else {
|
||||
STATUS_CLR(LOWBATT);
|
||||
|
@ -162,9 +179,9 @@ static const char *lowbatt_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *overload_info(const char *val)
|
||||
static const char *overload_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(OVERLOAD);
|
||||
} else {
|
||||
STATUS_CLR(OVERLOAD);
|
||||
|
@ -173,9 +190,9 @@ static const char *overload_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *replacebatt_info(const char *val)
|
||||
static const char *replacebatt_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(REPLACEBATT);
|
||||
} else {
|
||||
STATUS_CLR(REPLACEBATT);
|
||||
|
@ -184,9 +201,9 @@ static const char *replacebatt_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *trim_info(const char *val)
|
||||
static const char *trim_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(TRIM);
|
||||
} else {
|
||||
STATUS_CLR(TRIM);
|
||||
|
@ -195,9 +212,9 @@ static const char *trim_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *boost_info(const char *val)
|
||||
static const char *boost_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(BOOST);
|
||||
} else {
|
||||
STATUS_CLR(BOOST);
|
||||
|
@ -206,9 +223,9 @@ static const char *boost_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *bypass_aut_info(const char *val)
|
||||
static const char *bypass_aut_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(BYPASSAUTO);
|
||||
} else {
|
||||
STATUS_CLR(BYPASSAUTO);
|
||||
|
@ -217,9 +234,9 @@ static const char *bypass_aut_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *bypass_man_info(const char *val)
|
||||
static const char *bypass_man_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(BYPASSMAN);
|
||||
} else {
|
||||
STATUS_CLR(BYPASSMAN);
|
||||
|
@ -228,9 +245,9 @@ static const char *bypass_man_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *off_info(const char *val)
|
||||
static const char *off_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '0') {
|
||||
if (arg_val[0] == '0') {
|
||||
STATUS_SET(OFF);
|
||||
} else {
|
||||
STATUS_CLR(OFF);
|
||||
|
@ -242,9 +259,9 @@ static const char *off_info(const char *val)
|
|||
/* note: this value is reverted (0=set, 1=not set). We report "battery
|
||||
not installed" rather than "battery installed", so that devices
|
||||
that don't implement this variable have a battery by default */
|
||||
static const char *nobattery_info(const char *val)
|
||||
static const char *nobattery_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '0') {
|
||||
if (arg_val[0] == '0') {
|
||||
STATUS_SET(NOBATTERY);
|
||||
} else {
|
||||
STATUS_CLR(NOBATTERY);
|
||||
|
@ -253,9 +270,9 @@ static const char *nobattery_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *fanfail_info(const char *val)
|
||||
static const char *fanfail_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(FANFAIL);
|
||||
} else {
|
||||
STATUS_CLR(FANFAIL);
|
||||
|
@ -265,9 +282,9 @@ static const char *fanfail_info(const char *val)
|
|||
}
|
||||
|
||||
#if 0
|
||||
static const char *shutdownimm_info(const char *val)
|
||||
static const char *shutdownimm_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(SHUTDOWNIMM);
|
||||
} else {
|
||||
STATUS_CLR(SHUTDOWNIMM);
|
||||
|
@ -277,9 +294,9 @@ static const char *shutdownimm_info(const char *val)
|
|||
}
|
||||
#endif
|
||||
|
||||
static const char *overheat_info(const char *val)
|
||||
static const char *overheat_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(OVERHEAT);
|
||||
} else {
|
||||
STATUS_CLR(OVERHEAT);
|
||||
|
@ -288,9 +305,9 @@ static const char *overheat_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *commfault_info(const char *val)
|
||||
static const char *commfault_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(COMMFAULT);
|
||||
} else {
|
||||
STATUS_CLR(COMMFAULT);
|
||||
|
@ -299,9 +316,9 @@ static const char *commfault_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *internalfailure_info(const char *val)
|
||||
static const char *internalfailure_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(INTERNALFAULT);
|
||||
} else {
|
||||
STATUS_CLR(INTERNALFAULT);
|
||||
|
@ -310,9 +327,9 @@ static const char *internalfailure_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *battvoltlo_info(const char *val)
|
||||
static const char *battvoltlo_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(BATTVOLTLO);
|
||||
} else {
|
||||
STATUS_CLR(BATTVOLTLO);
|
||||
|
@ -321,9 +338,9 @@ static const char *battvoltlo_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *battvolthi_info(const char *val)
|
||||
static const char *battvolthi_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(BATTVOLTHI);
|
||||
} else {
|
||||
STATUS_CLR(BATTVOLTHI);
|
||||
|
@ -332,9 +349,9 @@ static const char *battvolthi_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *chargerfail_info(const char *val)
|
||||
static const char *chargerfail_info(const char *arg_val)
|
||||
{
|
||||
if ((val[0] == '1') || !strncasecmp(val, "Yes", 3)) {
|
||||
if ((arg_val[0] == '1') || !strncasecmp(arg_val, "Yes", 3)) {
|
||||
STATUS_SET(CHARGERFAIL);
|
||||
} else {
|
||||
STATUS_CLR(CHARGERFAIL);
|
||||
|
@ -343,9 +360,9 @@ static const char *chargerfail_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *vrange_info(const char *val)
|
||||
static const char *vrange_info(const char *arg_val)
|
||||
{
|
||||
if ((val[0] == '1') || !strncasecmp(val, "Yes", 3)) {
|
||||
if ((arg_val[0] == '1') || !strncasecmp(arg_val, "Yes", 3)) {
|
||||
STATUS_SET(VRANGE);
|
||||
} else {
|
||||
STATUS_CLR(VRANGE);
|
||||
|
@ -354,9 +371,9 @@ static const char *vrange_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *frange_info(const char *val)
|
||||
static const char *frange_info(const char *arg_val)
|
||||
{
|
||||
if ((val[0] == '1') || !strncasecmp(val, "Yes", 3)) {
|
||||
if ((arg_val[0] == '1') || !strncasecmp(arg_val, "Yes", 3)) {
|
||||
STATUS_SET(FRANGE);
|
||||
} else {
|
||||
STATUS_CLR(FRANGE);
|
||||
|
@ -365,9 +382,9 @@ static const char *frange_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *fuse_fault_info(const char *val)
|
||||
static const char *fuse_fault_info(const char *arg_val)
|
||||
{
|
||||
if (val[0] == '1') {
|
||||
if (arg_val[0] == '1') {
|
||||
STATUS_SET(FUSEFAULT);
|
||||
} else {
|
||||
STATUS_CLR(FUSEFAULT);
|
||||
|
@ -376,88 +393,112 @@ static const char *fuse_fault_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *yes_no_info(const char *val)
|
||||
static const char *yes_no_info(const char *arg_val)
|
||||
{
|
||||
switch(val[0])
|
||||
switch(arg_val[0])
|
||||
{
|
||||
case '1':
|
||||
return "yes";
|
||||
case '0':
|
||||
return "no";
|
||||
default:
|
||||
upsdebugx(2, "%s: unexpected value [%s]", __func__, val);
|
||||
upsdebugx(2, "%s: unexpected value [%s]", __func__, arg_val);
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *on_off_info(const char *val)
|
||||
static const char *on_off_info(const char *arg_val)
|
||||
{
|
||||
switch(val[0])
|
||||
switch(arg_val[0])
|
||||
{
|
||||
case '1':
|
||||
return "on";
|
||||
case '0':
|
||||
return "off";
|
||||
default:
|
||||
upsdebugx(2, "%s: unexpected value [%s]", __func__, val);
|
||||
upsdebugx(2, "%s: unexpected value [%s]", __func__, arg_val);
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *convert_deci(const char *val)
|
||||
static const char *convert_deci(const char *arg_val)
|
||||
{
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%.1f", 0.1 * (float)atoi(val));
|
||||
/* Note: this routine was needed for original MGE devices, before the company
|
||||
* was bought out and split in 2007 between Eaton (1ph devices) and Schneider
|
||||
* (3ph devices). Those firmwares back when the driver was written apparently
|
||||
* served 10x the measured values. Not sure if any such units are in service
|
||||
* now (with same FW, and with no upgrade path). Reign of XML/PDC is waning.
|
||||
* For currently known NetXML servers, the value served is good without more
|
||||
* conversions. If older devices pop up in the field, we can add an estimation
|
||||
* by e.g. reported voltage and amps (to be an order of magnitude for power).
|
||||
* Alternately we can look at model names and/or firmware versions or release
|
||||
* dates, if we get those and if we know enough to map them to either logic. */
|
||||
|
||||
return mge_scratch_buf;
|
||||
if (testvar("do_convert_deci")) {
|
||||
/* Old code for old devices: */
|
||||
if (mge_report_deprecation__convert_deci) {
|
||||
upslogx(LOG_NOTICE, "%s() is now deprecated, so values from XML are normally not decimated. This driver instance has however configured do_convert_deci in your ups.conf, so this behavior for old MGE NetXML-capable devices is preserved.", __func__);
|
||||
mge_report_deprecation__convert_deci = 0;
|
||||
}
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%.1f", 0.1 * (float)(atoi(arg_val)));
|
||||
return mge_scratch_buf;
|
||||
}
|
||||
|
||||
if (mge_report_deprecation__convert_deci) {
|
||||
upslogx(LOG_NOTICE, "%s() is now deprecated, so values from XML are not decimated. If you happen to have an old MGE NetXML-capable device that now shows measurements 10x too big, and a firmware update does not solve this, please inform NUT devs via the issue tracker at %s with details about your hardware and firmware versions. Also try to enable do_convert_deci in your ups.conf", __func__, PACKAGE_BUGREPORT );
|
||||
mge_report_deprecation__convert_deci = 0;
|
||||
}
|
||||
upsdebugx(5, "%s() is now deprecated, so value '%s' is not decimated. If this change broke your setup, please see details logged above.", __func__, arg_val);
|
||||
return arg_val;
|
||||
}
|
||||
|
||||
/* Ignore a zero value if the UPS is not switched off */
|
||||
static const char *ignore_if_zero(const char *val)
|
||||
static const char *ignore_if_zero(const char *arg_val)
|
||||
{
|
||||
if (atoi(val) == 0) {
|
||||
if (atoi(arg_val) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return convert_deci(val);
|
||||
return convert_deci(arg_val);
|
||||
}
|
||||
|
||||
/* Set the 'ups.date' from the combined value
|
||||
* (ex. 2008/03/01 15:23:26) and return the time */
|
||||
static const char *split_date_time(const char *val)
|
||||
static const char *split_date_time(const char *arg_val)
|
||||
{
|
||||
char *last = NULL;
|
||||
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", val);
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", arg_val);
|
||||
dstate_setinfo("ups.date", "%s", strtok_r(mge_scratch_buf, " -", &last));
|
||||
|
||||
return strtok_r(NULL, " ", &last);
|
||||
}
|
||||
|
||||
static const char *url_convert(const char *val)
|
||||
static const char *url_convert(const char *arg_val)
|
||||
{
|
||||
char buf[256], *last = NULL;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", val);
|
||||
snprintf(buf, sizeof(buf), "%s", arg_val);
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "/%s", strtok_r(buf, " \r\n\t", &last));
|
||||
|
||||
return mge_scratch_buf;
|
||||
}
|
||||
|
||||
static const char *mge_battery_capacity(const char *val)
|
||||
static const char *mge_battery_capacity(const char *arg_val)
|
||||
{
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%.2f", (float)atoi(val) / 3600);
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%.2f", (float)(atoi(arg_val)) / 3600.0);
|
||||
return mge_scratch_buf;
|
||||
}
|
||||
|
||||
static const char *mge_powerfactor_conversion(const char *val)
|
||||
static const char *mge_powerfactor_conversion(const char *arg_val)
|
||||
{
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%.2f", (float)atoi(val) / 100);
|
||||
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%.2f", (float)(atoi(arg_val)) / 100.0);
|
||||
return mge_scratch_buf;
|
||||
}
|
||||
|
||||
static const char *mge_beeper_info(const char *val)
|
||||
static const char *mge_beeper_info(const char *arg_val)
|
||||
{
|
||||
switch (atoi(val))
|
||||
switch (atoi(arg_val))
|
||||
{
|
||||
case 1:
|
||||
return "disabled";
|
||||
|
@ -469,9 +510,9 @@ static const char *mge_beeper_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *mge_upstype_conversion(const char *val)
|
||||
static const char *mge_upstype_conversion(const char *arg_val)
|
||||
{
|
||||
switch (atoi(val))
|
||||
switch (atoi(arg_val))
|
||||
{
|
||||
case 1:
|
||||
return "offline / line interactive";
|
||||
|
@ -487,9 +528,9 @@ static const char *mge_upstype_conversion(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *mge_sensitivity_info(const char *val)
|
||||
static const char *mge_sensitivity_info(const char *arg_val)
|
||||
{
|
||||
switch (atoi(val))
|
||||
switch (atoi(arg_val))
|
||||
{
|
||||
case 0:
|
||||
return "normal";
|
||||
|
@ -501,9 +542,10 @@ static const char *mge_sensitivity_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *mge_test_result_info(const char *val)
|
||||
static const char *mge_test_result_info(const char *arg_val)
|
||||
{
|
||||
switch (atoi(val))
|
||||
STATUS_CLR(CAL);
|
||||
switch (atoi(arg_val))
|
||||
{
|
||||
case 1:
|
||||
return "done and passed";
|
||||
|
@ -514,6 +556,7 @@ static const char *mge_test_result_info(const char *val)
|
|||
case 4:
|
||||
return "aborted";
|
||||
case 5:
|
||||
STATUS_SET(CAL);
|
||||
return "in progress";
|
||||
case 6:
|
||||
return "no test initiated";
|
||||
|
@ -523,12 +566,31 @@ static const char *mge_test_result_info(const char *val)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *mge_ambient_info(const char *val)
|
||||
static const char *mge_ambient_info(const char *arg_val)
|
||||
{
|
||||
switch (mge_ambient_value)
|
||||
{
|
||||
case 1:
|
||||
return val;
|
||||
return arg_val;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *mge_drycontact_info(const char *arg_val)
|
||||
{
|
||||
/* these values should theoretically be obtained through
|
||||
* Environment.Input[1].State[x].Description
|
||||
* Examples:
|
||||
* <OBJECT name="Environment.Input[1].State[0].Description">open</OBJECT>
|
||||
* <OBJECT name="Environment.Input[1].State[1].Description">closed</OBJECT>
|
||||
*/
|
||||
switch (atoi(arg_val))
|
||||
{
|
||||
case 0:
|
||||
return "opened";
|
||||
case 1:
|
||||
return "closed";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -552,9 +614,9 @@ static const char *mge_timer_shutdown(const char *delay_before_shutoff)
|
|||
return val;
|
||||
}
|
||||
|
||||
static const char *mge_shutdown_imminent(const char *val)
|
||||
static const char *mge_shutdown_imminent(const char *arg_val)
|
||||
{
|
||||
const int shutdown_delay = atoi(val);
|
||||
const int shutdown_delay = atoi(arg_val);
|
||||
|
||||
/* shutdown is already managed by mge_timer_shutdown, give up */
|
||||
if(mge_shutdown_pending) {
|
||||
|
@ -563,7 +625,7 @@ static const char *mge_shutdown_imminent(const char *val)
|
|||
|
||||
/* We may have "NONE" or "-1" or ?? as value
|
||||
* We also double check both the string and numeric values to be zero!*/
|
||||
if ((val) && (val[0] == '0') && (shutdown_delay == 0)) {
|
||||
if ((arg_val) && (arg_val[0] == '0') && (shutdown_delay == 0)) {
|
||||
STATUS_SET(SHUTDOWNIMM);
|
||||
} else {
|
||||
STATUS_CLR(SHUTDOWNIMM);
|
||||
|
@ -885,12 +947,10 @@ static xml_info_t mge_xml2nut[] = {
|
|||
{ "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", 0, 0, NULL },
|
||||
{ "battery.runtime.low", ST_FLAG_RW, 0, "System.RunTimeToEmptyLimit", 0, 0, NULL },
|
||||
{ "battery.temperature", 0, 0, "UPS.BatterySystem.Battery.Temperature", 0, 0, NULL },
|
||||
{ "battery.packs.external", 0, 0, "UPS.BatterySystem.Battery.Count", 0, 0, NULL },
|
||||
{ "battery.type", ST_FLAG_STATIC, 0, "UPS.PowerSummary.iDeviceChemistry", 0, 0, NULL },
|
||||
{ "battery.type", ST_FLAG_STATIC, 0, "UPS.PowerSummary.iDeviceChemistery", 0, 0, NULL }, /* [sic] */
|
||||
{ "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", 0, 0, NULL },
|
||||
{ "battery.voltage.nominal", ST_FLAG_STATIC, 0, "UPS.BatterySystem.ConfigVoltage", 0, 0, NULL },
|
||||
{ "battery.voltage.nominal", ST_FLAG_STATIC, 0, "UPS.PowerSummary.ConfigVoltage", 0, 0, NULL }, /* mge_battery_voltage_nominal */
|
||||
{ "battery.current", 0, 0, "UPS.PowerSummary.Current", 0, 0, NULL },
|
||||
{ "battery.protection", 0, 0, "UPS.BatterySystem.Battery.DeepDischargeProtection", 0, 0, yes_no_info },
|
||||
{ "battery.energysave", 0, 0, "UPS.PowerConverter.Input[3].EnergySaving", 0, 0, yes_no_info },
|
||||
|
||||
|
@ -911,7 +971,7 @@ static xml_info_t mge_xml2nut[] = {
|
|||
{ "ups.delay.shutdown", ST_FLAG_RW, 0, "System.ShutdownDuration", 0, 0, NULL },
|
||||
{ "ups.timer.start", ST_FLAG_RW, 0, "UPS.PowerSummary.DelayBeforeStartup", 0, 0, NULL},
|
||||
{ "ups.timer.shutdown", ST_FLAG_RW, 0, "UPS.PowerSummary.DelayBeforeShutdown", 0, 0, mge_timer_shutdown },
|
||||
/* Catch shutdown imminent criteria, keep it after
|
||||
/* Catch shutdown imminent criteria, keep it after
|
||||
UPS.PowerSummary.DelayBeforeShutdown managment */
|
||||
{ NULL, 0, 0, "System.RunTimeToShutdown", 0, 0, mge_shutdown_imminent },
|
||||
{ "ups.timer.reboot", 0, 0, "UPS.PowerSummary.DelayBeforeReboot", 0, 0, NULL },
|
||||
|
@ -920,15 +980,15 @@ static xml_info_t mge_xml2nut[] = {
|
|||
{ "ups.beeper.status", 0 ,0, "UPS.BatterySystem.Battery.AudibleAlarmControl", 0, 0, mge_beeper_info },
|
||||
{ "ups.beeper.status", 0 ,0, "UPS.PowerSummary.AudibleAlarmControl", 0, 0, mge_beeper_info },
|
||||
{ "ups.temperature", 0, 0, "UPS.PowerSummary.Temperature", 0, 0, NULL },
|
||||
{ "ups.power", 0, 0, "UPS.PowerConverter.Output.ApparentPower", 0, 0, NULL },
|
||||
{ "ups.L1.power", 0, 0, "UPS.PowerConverter.Output.Phase[1].ApparentPower", 0, 0, ignore_if_zero },
|
||||
{ "ups.L2.power", 0, 0, "UPS.PowerConverter.Output.Phase[2].ApparentPower", 0, 0, ignore_if_zero },
|
||||
{ "ups.L3.power", 0, 0, "UPS.PowerConverter.Output.Phase[3].ApparentPower", 0, 0, ignore_if_zero },
|
||||
{ "ups.power.nominal", ST_FLAG_STATIC, 0, "UPS.Flow[4].ConfigApparentPower", 0, 0, NULL },
|
||||
{ "ups.power", 0, 0, "UPS.PowerConverter.Output.ApparentPower", 0, 0, NULL },
|
||||
{ "ups.L1.power", 0, 0, "UPS.PowerConverter.Output.Phase[1].ApparentPower", 0, 0, NULL },
|
||||
{ "ups.L2.power", 0, 0, "UPS.PowerConverter.Output.Phase[2].ApparentPower", 0, 0, NULL },
|
||||
{ "ups.L3.power", 0, 0, "UPS.PowerConverter.Output.Phase[3].ApparentPower", 0, 0, NULL },
|
||||
{ "ups.realpower", 0, 0, "UPS.PowerConverter.Output.ActivePower", 0, 0, NULL },
|
||||
{ "ups.L1.realpower", 0, 0, "UPS.PowerConverter.Output.Phase[1].ActivePower", 0, 0, ignore_if_zero },
|
||||
{ "ups.L2.realpower", 0, 0, "UPS.PowerConverter.Output.Phase[2].ActivePower", 0, 0, ignore_if_zero },
|
||||
{ "ups.L3.realpower", 0, 0, "UPS.PowerConverter.Output.Phase[3].ActivePower", 0, 0, ignore_if_zero },
|
||||
{ "ups.L1.realpower", 0, 0, "UPS.PowerConverter.Output.Phase[1].ActivePower", 0, 0, NULL },
|
||||
{ "ups.L2.realpower", 0, 0, "UPS.PowerConverter.Output.Phase[2].ActivePower", 0, 0, NULL },
|
||||
{ "ups.L3.realpower", 0, 0, "UPS.PowerConverter.Output.Phase[3].ActivePower", 0, 0, NULL },
|
||||
{ "ups.realpower.nominal", ST_FLAG_STATIC, 0, "UPS.Flow[4].ConfigActivePower", 0, 0, NULL },
|
||||
{ "ups.start.auto", 0, 0, "UPS.PowerConverter.Input[1].AutomaticRestart", 0, 0, yes_no_info },
|
||||
{ "ups.start.battery", 0, 0, "UPS.PowerConverter.Input[3].StartOnBattery", 0, 0, yes_no_info },
|
||||
|
@ -1018,6 +1078,8 @@ static xml_info_t mge_xml2nut[] = {
|
|||
{ "ambient.temperature.low", ST_FLAG_RW, 0, "Environment.Temperature.LowThreshold", 0, 0, NULL },
|
||||
{ "ambient.temperature.maximum", 0, 0, "Environment.PresentStatus.HighTemperature", 0, 0, mge_ambient_info },
|
||||
{ "ambient.temperature.minimum", 0, 0, "Environment.PresentStatus.LowTemperature", 0, 0, mge_ambient_info },
|
||||
{ "ambient.contacts.1.status", 0, 0, "Environment.Input[1].PresentStatus.State", 0, 0, mge_drycontact_info },
|
||||
{ "ambient.contacts.2.status", 0, 0, "Environment.Input[2].PresentStatus.State", 0, 0, mge_drycontact_info },
|
||||
|
||||
/* Outlet page (using MGE UPS SYSTEMS - PowerShare technology) */
|
||||
{ "outlet.id", 0, 0, "UPS.OutletSystem.Outlet[1].OutletID", 0, 0, NULL },
|
||||
|
@ -1077,6 +1139,8 @@ static xml_info_t mge_xml2nut[] = {
|
|||
static int mge_xml_startelm_cb(void *userdata, int parent, const char *nspace, const char *name, const char **atts)
|
||||
{
|
||||
int state = _UNEXPECTED;
|
||||
NUT_UNUSED_VARIABLE(userdata);
|
||||
NUT_UNUSED_VARIABLE(nspace);
|
||||
|
||||
switch(parent)
|
||||
{
|
||||
|
@ -1085,6 +1149,7 @@ static int mge_xml_startelm_cb(void *userdata, int parent, const char *nspace, c
|
|||
/* name="Network Management Card" type="Mosaic M" version="BA" */
|
||||
/* name="Network Management Card" type="Transverse" version="GB (SN 49EH29101)" */
|
||||
/* name="Monitored ePDU" type="Monitored ePDU" version="Version Upgrade" */
|
||||
/* name="PDU Network Management Card" type="SCOB" version="02.00.0036" signature="34008876" protocol="XML.V4" */
|
||||
int i;
|
||||
for (i = 0; atts[i] && atts[i+1]; i += 2) {
|
||||
if (!strcasecmp(atts[i], "name")) {
|
||||
|
@ -1108,6 +1173,13 @@ static int mge_xml_startelm_cb(void *userdata, int parent, const char *nspace, c
|
|||
}
|
||||
dstate_setinfo("ups.firmware.aux", "%s", val);
|
||||
}
|
||||
/* netxml-ups currently only supports XML version 3 (for UPS),
|
||||
* and not version 4 (for UPS and PDU)! */
|
||||
if (!strcasecmp(atts[i], "protocol")) {
|
||||
if (!strcasecmp(atts[i+1], "XML.V4")) {
|
||||
fatalx(EXIT_FAILURE, "XML v4 protocol is not supported!");
|
||||
}
|
||||
}
|
||||
}
|
||||
state = PRODUCT_INFO;
|
||||
break;
|
||||
|
@ -1310,8 +1382,12 @@ static int mge_xml_startelm_cb(void *userdata, int parent, const char *nspace, c
|
|||
state = XC_GENERAL;
|
||||
break;
|
||||
}
|
||||
/* FIXME? Is the fall-through to handling "GENERAL" intended?
|
||||
* was so in legacy code before the goto below... */
|
||||
goto fallthrough_case_general;
|
||||
|
||||
case XC_GENERAL:
|
||||
fallthrough_case_general:
|
||||
if (!strcasecmp(name, "STARTUP")) {
|
||||
/* config="CENTRALIZED" */
|
||||
state = XC_STARTUP;
|
||||
|
@ -1345,6 +1421,8 @@ static int mge_xml_startelm_cb(void *userdata, int parent, const char *nspace, c
|
|||
/* Character data callback; may return non-zero to abort the parse. */
|
||||
static int mge_xml_cdata_cb(void *userdata, int state, const char *cdata, size_t len)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(userdata);
|
||||
|
||||
/* skip empty lines */
|
||||
if ((len == 1) && (cdata[0] == '\n')) {
|
||||
upsdebugx(3, "%s: cdata ignored (state = %d)", __func__, state);
|
||||
|
@ -1373,6 +1451,8 @@ static int mge_xml_endelm_cb(void *userdata, int state, const char *nspace, cons
|
|||
{
|
||||
xml_info_t *info;
|
||||
const char *value;
|
||||
NUT_UNUSED_VARIABLE(userdata);
|
||||
NUT_UNUSED_VARIABLE(nspace);
|
||||
|
||||
/* ignore objects for which no value was set */
|
||||
if (strlen(val) == 0) {
|
||||
|
@ -1400,6 +1480,7 @@ static int mge_xml_endelm_cb(void *userdata, int state, const char *nspace, cons
|
|||
|
||||
if (info->convert) {
|
||||
value = info->convert(val);
|
||||
upsdebugx(4, "-> XML variable %s [%s] which maps to NUT variable %s was converted to value %s for the NUT driver state", var, val, info->nutname, value);
|
||||
} else {
|
||||
value = val;
|
||||
}
|
||||
|
@ -1413,6 +1494,25 @@ static int mge_xml_endelm_cb(void *userdata, int state, const char *nspace, cons
|
|||
|
||||
upsdebugx(3, "-> XML variable %s [%s] doesn't map to any NUT variable", var, val);
|
||||
break;
|
||||
|
||||
case PI_GET_OBJECT:
|
||||
case GET_OBJECT:
|
||||
/* We've just got a snapshot of all runtime data, saved well into
|
||||
* dstate's already, so can estimate missing values if needed. */
|
||||
|
||||
/* For phase setup, we assume it does not change during run-time.
|
||||
* Essentially this means that once we've detected it is N-phase,
|
||||
* it stays this way for the rest of the driver run/life-time. */
|
||||
/* To change this behavior just flip the maychange flag to "1" */
|
||||
|
||||
dstate_detect_phasecount("input.", 1,
|
||||
&inited_phaseinfo_in, &num_inphases, 0);
|
||||
dstate_detect_phasecount("input.bypass.", 1,
|
||||
&inited_phaseinfo_bypass, &num_bypassphases, 0);
|
||||
dstate_detect_phasecount("output.", 1,
|
||||
&inited_phaseinfo_out, &num_outphases, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue