diff --git a/NEWS.adoc b/NEWS.adoc index 024a8e57dd..6bbdac000d 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -752,6 +752,7 @@ Release notes for NUT 2.8.4 - what's new since 2.8.3 * The time stamp and inter-frame delay accounting was fixed, alleviating one of the problems reported in issue #2609. [PR #2982] * Fix missing variables due to mismatching format string. [PR #3013] + * Add CHRG and DISCHRG status. [PR #3014] - `bcmxcp` driver updates: * The latching on to a previous replace battery status was fixed, with its diff --git a/drivers/apc_modbus.c b/drivers/apc_modbus.c index 9554922512..39dac0c596 100644 --- a/drivers/apc_modbus.c +++ b/drivers/apc_modbus.c @@ -95,6 +95,7 @@ static int is_usb = 0; static int is_open = 0; static double power_nominal; static double realpower_nominal; +static double battery_charge; static int64_t last_send_time = 0; /* Function declarations */ @@ -894,7 +895,7 @@ static apc_modbus_register_t apc_modbus_register_map_status[] = { static apc_modbus_register_t apc_modbus_register_map_dynamic[] = { { "battery.runtime", 128, 2, APC_VT_UINT, APC_VF_NONE, NULL, "%" PRIu64, 0, NULL }, - { "battery.charge", 130, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 9, NULL }, + { "battery.charge", 130, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 9, &battery_charge }, { "battery.voltage", 131, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 5, NULL }, { "battery.date.maintenance", 133, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_date_conversion, NULL, 0, NULL }, { "battery.temperature", 135, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 7, NULL }, @@ -1790,6 +1791,8 @@ void upsdrv_initinfo(void) void upsdrv_updateinfo(void) { uint16_t regbuf[44]; + uint64_t ups_status; + uint64_t bat_system_err; uint64_t value; char var_name[64]; size_t i, ri; @@ -1809,32 +1812,32 @@ void upsdrv_updateinfo(void) /* Status Data */ if (_apc_modbus_read_registers(modbus_ctx, 0, 27, regbuf)) { /* UPSStatus_BF, 2 registers */ - _apc_modbus_to_uint64(®buf[0], 2, &value); - if (value & (1 << 1)) { + _apc_modbus_to_uint64(®buf[0], 2, &ups_status); + if (ups_status & (1 << 1)) { status_set("OL"); } - if (value & (1 << 2)) { + if (ups_status & (1 << 2)) { status_set("OB"); } - if (value & (1 << 3)) { + if (ups_status & (1 << 3)) { status_set("BYPASS"); } - if (value & (1 << 4)) { + if (ups_status & (1 << 4)) { status_set("OFF"); } - if (value & (1 << 5)) { + if (ups_status & (1 << 5)) { alarm_set("General fault"); } - if (value & (1 << 6)) { + if (ups_status & (1 << 6)) { alarm_set("Input not acceptable"); } - if (value & (1 << 7)) { + if (ups_status & (1 << 7)) { status_set("TEST"); } - if (value & (1 << 13)) { + if (ups_status & (1 << 13)) { buzzmode_set("vendor:apc:HE"); /* High efficiency / ECO mode*/ } - if (value & (1 << 21)) { + if (ups_status & (1 << 21)) { status_set("OVER"); } @@ -1863,8 +1866,8 @@ void upsdrv_updateinfo(void) } /* BatterySystemError_BF, 1 register */ - _apc_modbus_to_uint64(®buf[18], 1, &value); - if (value & (1 << 1)) { /* NeedsReplacement */ + _apc_modbus_to_uint64(®buf[22], 1, &bat_system_err); + if (bat_system_err & (1 << 1)) { /* NeedsReplacement */ status_set("RB"); } @@ -1874,6 +1877,17 @@ void upsdrv_updateinfo(void) status_set("CAL"); } + /* No battery error ? */ + if (bat_system_err == 0) { + if (ups_status & (1 << 1)) { + status_set("CHRG"); + } + if (ups_status & (1 << 2)) { + status_set("DISCHRG"); + } + + } + _apc_modbus_process_registers(apc_modbus_register_map_status, regbuf, 27, 0); } else { dstate_datastale(); @@ -1882,16 +1896,24 @@ void upsdrv_updateinfo(void) /* Dynamic Data */ if (_apc_modbus_read_registers(modbus_ctx, 128, 44, regbuf)) { + _apc_modbus_process_registers(apc_modbus_register_map_dynamic, regbuf, 44, 128); + /* InputStatus_BF, 1 register */ _apc_modbus_to_uint64(®buf[22], 1, &value); + if (value & (1 << 0)) { + // Acceptable input + if (battery_charge < 100.0) { + status_set("CHRG"); + } + } else { + status_set("DISCHRG"); + } if (value & (1 << 5)) { status_set("BOOST"); } if (value & (1 << 6)) { status_set("TRIM"); } - - _apc_modbus_process_registers(apc_modbus_register_map_dynamic, regbuf, 44, 128); } else { dstate_datastale(); return;