Imported Upstream version 2.7.3

This commit is contained in:
Arnaud Quette 2015-04-30 15:53:36 +02:00
parent a356b56d11
commit fd413a3168
283 changed files with 14978 additions and 6511 deletions

View file

@ -1,7 +1,8 @@
/* mge-hid.c - data to monitor Eaton / MGE HID (USB and serial) devices
*
* Copyright (C) 2003 - 2012
* Arnaud Quette <arnaud.quette@free.fr>
* Copyright (C)
* 2003 - 2015 Arnaud Quette <arnaud.quette@free.fr>
* 2015 Arnaud Quette <ArnaudQuette@Eaton.com>
*
* Sponsored by MGE UPS SYSTEMS <http://www.mgeups.com>
*
@ -36,7 +37,7 @@
#include "usbhid-ups.h"
#include "mge-hid.h"
#define MGE_HID_VERSION "MGE HID 1.33"
#define MGE_HID_VERSION "MGE HID 1.38"
/* (prev. MGE Office Protection Systems, prev. MGE UPS SYSTEMS) */
/* Eaton */
@ -121,6 +122,223 @@ static int country_code = COUNTRY_UNKNOWN;
static char mge_scratch_buf[20];
/* ABM - Advanced Battery Monitoring
***********************************
* Synthesis table
* HID data | Charger in ABM mode | Charger in Constant mode
* UPS.BatterySystem.Charger.ABMEnable | 1 | 0
* UPS.PowerSummary.PresentStatus.ACPresent | On utility | On battery | On utility | On battery
* Charger ABM mode | Charging | Floating | Resting | Discharging | Disabled | Disabled
* UPS.BatterySystem.Charger.Mode | 1 | 3 | 4 | 2 | 6 | 6
* UPS.PowerSummary.PresentStatus.Charging | 1 | 1 | 1 | 0 | 1 | 0
* UPS.PowerSummary.PresentStatus.Discharging | 0 |  0 |  0 | 1 | 0 | 1
*
* Notes (from David G. Miller) to understand ABM status:
* When supporting ABM, when a UPS powers up or returns from battery, or
* ends the ABM rest mode, it enters charge mode.
* Some UPSs run a different charger reference voltage during charge mode
* but all the newer models should not be doing that, but basically once
* the battery voltage reaches the charger reference level (should be 2.3
* volts/cell), the charger is considered in float mode. Some UPSs will not
* annunciate float mode until the charger power starts falling from the maximum
* level indicating the battery is truly at the float voltage or in float mode.
* The %charge level is based on battery voltage and the charge mode timer
* (should be 48 hours) and some UPSs add in a value thats related to charger
* power output. So you can have UPS that enters float mode with anywhere
* from 80% or greater battery capacity.
* float mode is not important from the softwares perspective, its there to
* help determine if the charger is advancing correctly.
* So in float mode, the charger is charging the battery, so by definition you
* can assert the CHRG flag in NUT when in float mode or charge mode.
* When in rest mode the charger is not delivering anything to the battery,
* but it will when the ABM cycle(28 days) ends, or a battery discharge occurs
* and utility returns. This is when the ABM status should be resting.
* If a battery failure is detected that disables the charger, it should be
* reporting off in the ABM charger status.
* Of course when delivering load power from the battery, the ABM status is
* discharging.
*/
#define ABM_UNKNOWN -1
#define ABM_DISABLED 0
#define ABM_ENABLED 1
/* Internal flag to process battery status (CHRG/DISCHRG) and ABM */
static int advanced_battery_monitoring = ABM_UNKNOWN;
/* Used to store internally if ABM is enabled or not */
static const char *eaton_abm_enabled_fun(double value)
{
advanced_battery_monitoring = value;
upsdebugx(2, "ABM is %s", (advanced_battery_monitoring==1)?"enabled":"disabled");
/* Return NULL, not to get the value published! */
return NULL;
}
static info_lkp_t eaton_abm_enabled_info[] = {
{ 0, "dummy", eaton_abm_enabled_fun },
{ 0, NULL, NULL }
};
/* Note 1: This point will need more clarification! */
# if 0
/* Used to store internally if ABM is enabled or not (for legacy units) */
static const char *eaton_abm_enabled_legacy_fun(double value)
{
advanced_battery_monitoring = value;
upsdebugx(2, "ABM is %s (legacy data)", (advanced_battery_monitoring==1)?"enabled":"disabled");
/* Return NULL, not to get the value published! */
return NULL;
}
static info_lkp_t eaton_abm_enabled_legacy_info[] = {
{ 0, "dummy", eaton_abm_enabled_legacy_fun },
{ 0, NULL, NULL }
};
#endif /* if 0 */
/* Used to process ABM flags, for battery.charger.status */
static const char *eaton_abm_status_fun(double value)
{
/* Don't process if ABM is disabled */
if (advanced_battery_monitoring == ABM_DISABLED) {
/* Clear any previously published data, in case
* the user has switched off ABM */
dstate_delinfo("battery.charger.status");
return NULL;
}
upsdebugx(2, "ABM numeric status: %i", (int)value);
switch ((long)value)
{
case 1:
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "charging");
break;
case 2:
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "discharging");
break;
case 3:
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "floating");
break;
case 4:
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "resting");
break;
case 6: /* ABM Charger Disabled */
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "off");
break;
case 5: /* Undefined - ABM is not activated */
default:
/* Return NULL, not to get the value published! */
return NULL;
}
upsdebugx(2, "ABM string status: %s", mge_scratch_buf);
return mge_scratch_buf;
}
static info_lkp_t eaton_abm_status_info[] = {
{ 1, "dummy", eaton_abm_status_fun },
{ 0, NULL, NULL }
};
/* Used to process ABM flags, for ups.status (CHRG/DISCHRG/RB) */
static const char *eaton_abm_chrg_dischrg_fun(double value)
{
/* Don't process if ABM is disabled */
if (advanced_battery_monitoring == ABM_DISABLED)
return NULL;
switch ((long)value)
{
case 1: /* charging status */
case 3: /* floating status */
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "chrg");
break;
case 2:
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "dischrg");
break;
case 6: /* ABM Charger Disabled */
case 4: /* resting, nothing to publish! (?) */
case 5: /* Undefined - ABM is not activated */
default:
/* Return NULL, not to get the value published! */
return NULL;
}
upsdebugx(2, "ABM CHRG/DISCHRG legacy string status (ups.status): %s", mge_scratch_buf);
return mge_scratch_buf;
}
static info_lkp_t eaton_abm_chrg_dischrg_info[] = {
{ 1, "dummy", eaton_abm_chrg_dischrg_fun },
{ 0, NULL, NULL }
};
/* ABM also implies that standard CHRG/DISCHRG are processed according
* to weither ABM is enabled or not...
* If ABM is disabled, we publish these legacy status
* Otherwise, we don't publish on ups.status, but only battery.charger.status */
/* FIXME: we may prefer to publish the CHRG/DISCHRG status
* on battery.charger.status?! */
static const char *eaton_abm_check_dischrg_fun(double value)
{
if (advanced_battery_monitoring == ABM_DISABLED)
{
if (value == 1) {
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "dischrg");
}
else {
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "!dischrg");
}
}
else {
/* Else, ABM is enabled, we should return NULL,
* not to get the value published!
* However, clear flags that would persist in case of prior
* publication in ABM-disabled mode */
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "!dischrg");
}
return mge_scratch_buf;
}
static info_lkp_t eaton_discharging_info[] = {
{ 1, "dummy", eaton_abm_check_dischrg_fun },
{ 0, NULL, NULL }
};
static const char *eaton_abm_check_chrg_fun(double value)
{
if (advanced_battery_monitoring == ABM_DISABLED)
{
if (value == 1) {
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "chrg");
}
else {
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "!chrg");
}
}
else {
/* Else, ABM is enabled, we should return NULL,
* not to get the value published!
* However, clear flags that would persist in case of prior
* publication in ABM-disabled mode */
snprintf(mge_scratch_buf, sizeof(mge_scratch_buf), "%s", "!chrg");
}
return mge_scratch_buf;
}
static info_lkp_t eaton_charging_info[] = {
{ 1, "dummy", eaton_abm_check_chrg_fun },
{ 0, NULL, NULL }
};
/* The HID path 'UPS.PowerSummary.Time' reports Unix time (ie the number of
* seconds since 1970-01-01 00:00:00. This has to be split between ups.date and
* ups.time */
@ -880,6 +1098,21 @@ static hid_info_t mge_hid2nut[] =
{ "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%s", HU_FLAG_STATIC, mge_battery_voltage_nominal },
{ "battery.protection", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.BatterySystem.Battery.DeepDischargeProtection", NULL, "%s", HU_FLAG_SEMI_STATIC, yes_no_info },
{ "battery.energysave", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.PowerConverter.Input.[3].EnergySaving", NULL, "%s", HU_FLAG_SEMI_STATIC, yes_no_info },
{ "battery.energysave.load", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.PowerConverter.Input.[3].ConfigPercentLoad", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
/* Current implementation */
{ "battery.energysave.delay", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.PowerConverter.Input.[3].EnergySaving.ShutdownTimer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
/* Newer implementation */
{ "battery.energysave.delay", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.PowerConverter.Input.[3].ShutdownTimer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
{ "battery.energysave.realpower", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.PowerConverter.Input.[3].ConfigActivePower", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL },
/* ABM (Advanced Battery Monitoring) processing
* Must be processed before the BOOL status */
/* Not published, just to store in internal var. advanced_battery_monitoring */
{ "battery.charger.status", 0, 0, "UPS.BatterySystem.Charger.ABMEnable", NULL, "%.0f", HU_FLAG_QUICK_POLL, eaton_abm_enabled_info },
/* Same as the one above, but for legacy units */
/* Refer to Note 1 (This point will need more clarification!)
{ "battery.charger.status", 0, 0, "UPS.BatterySystem.Charger.PresentStatus.Used", NULL, "%.0f", HU_FLAG_QUICK_POLL, eaton_abm_enabled_legacy_info }, */
/* This data is the actual ABM status information */
{ "battery.charger.status", 0, 0, "UPS.BatterySystem.Charger.Mode", NULL, "%.0f", HU_FLAG_QUICK_POLL, eaton_abm_status_info },
/* UPS page */
{ "ups.efficiency", 0, 0, "UPS.PowerConverter.Output.Efficiency", NULL, "%.0f", 0, NULL },
@ -922,8 +1155,11 @@ static hid_info_t mge_hid2nut[] =
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.Input.[3].PresentStatus.Used", NULL, NULL, 0, mge_onbatt_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.Used", NULL, NULL, 0, online_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info },
/* These 2 ones are used when ABM is disabled */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, eaton_discharging_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, eaton_charging_info },
/* And this one when ABM is enabled (same as battery.charger.status) */
{ "BOOL", 0, 0, "UPS.BatterySystem.Charger.Mode", NULL, "%.0f", HU_FLAG_QUICK_POLL, eaton_abm_chrg_dischrg_info },
/* FIXME: on Dell, the above requires an "AND" with "UPS.BatterySystem.Charger.Mode = 1" */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info },
/* Output overload, Level 1 (FIXME: add the level?) */
@ -940,11 +1176,6 @@ static hid_info_t mge_hid2nut[] =
{ "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.VoltageOutOfRange", NULL, NULL, 0, vrange_info },
{ "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.FrequencyOutOfRange", NULL, NULL, 0, frange_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Good", NULL, NULL, 0, off_info },
#if 0
/* TODO: UPS.BatterySystem.Charger.PresentStatus.Used is related to ABM */
{ "BOOL", 0, 0, "UPS.BatterySystem.Charger.PresentStatus.Used", NULL, NULL, 0, off_info },
/* FIXME: on Dell, the above requires an "AND" with "UPS.BatterySystem.Charger.Mode = 4 (ABM Resting)" */
#endif
{ "BOOL", 0, 0, "UPS.PowerConverter.Input.[2].PresentStatus.Used", NULL, NULL, 0, bypass_auto_info }, /* Automatic bypass */
{ "BOOL", 0, 0, "UPS.PowerConverter.Input.[4].PresentStatus.Used", NULL, NULL, 0, bypass_manual_info }, /* Manual bypass */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FanFailure", NULL, NULL, 0, fanfail_info },