一
在 Linux 上用 NUT@2.8.0 管理 APC BK650M2-CH 时,NUT 包中 upsmonitor 会频繁警告电池电量低和需要更换电池:
UPS ups Battery needs replacement.
UPS ups battery level low.
但是 UPS 和电池都是全新的,报警时电池电量也是 100%,不得不怀疑是 NUT 软件的问题。
二
起初查到的是 wiki 上的内容,建议是使用 upscmd
进行自检
upscmd -u admin -p password ups@localhost:3002 test.battery.start.quick
quick 和 deep 的自检、电池生产日期更新都尝试过,仍然报警。
三
后来看到 GitHub 上的 issue 提到是 NUT 和 APC firmware 之间的不兼容,
有个可行的临时方法:
即在 apc.conf
中加上 pollonly
的选项(仅单向从 UPS 获取信息)。
REF
TL;DR I got rid of the incorrect status values by adding pollonly for my UPS in ups.conf. I am on nut v2.8.2 and the UPS is a brand new APC BX1200MI.
Once my UPS is fully charged and on-line, the nominal data bytes for the report with ID 0x16 is 16 0c 00 00 00. The few bits that are set in these databytes correspond correctly to UPS.PowerSummary.PresentStatus.BatteryPresent and UPS.PowerSummary.PresentStatus.ACPresent (OL). As as side note, my UPS is actually only returning three bytes for this report (i.e., 16 0c 00) and the remaining two (zero)bytes are being padded by nut on the fly. These two padding bytes are, however, defined as constants in the UPS' report descriptor, so they are nevertheless ignored.
Incorrect status values for my UPS only show up when report ID 0x16 is being received in file_report_buffer() in drivers/libhid.c. These HID events correspond to situations, when the reports come in from the UPS without the reports being requested. Running in debug mode, I see that these non-requested reports come in sizes of 512 bytes while nut usually is expecting much less. For example, receiving report 0x16 will show up in the debug log as [D2] file_report_buffer: expected 5 bytes, but got 512 instead. Most of the bytes included in these 512 bytes are leftovers from old buffers and in my case the first five bytes for 0x16 usually is 16 0d 0d c6 db. In addition to BatteryPresent and ACPresent these would incorrectly indicate UPS.PowerSummary.PresentStatus.Charging (CHRG) and UPS.PowerSummary.PresentStatus.VoltageNotRegulated. Occasionally I also get other incorrect datavalues corresponding for example to UPS.PowerSummary.PresentStatus.NeedReplacement (RB).
By setting pollonly in my UPS config, I can make the parameter use_interrupt_pipe become FALSE. This in turn will lead to all those strange non-requested reports being ignored by nut (in upsdrv_updateinfo() in drivers/usbhid-ups.c).