Skip to content

Commit 55a6624

Browse files
committed
drivers/powercom-hid.c: add Output section shutdown for RPT/BNT-AP series
Some Powercom UPS models (e.g. RPT-800AP, BNT-AP) experience unreliable shutdown.return behavior when using the PowerSummary section (UPS.PowerSummary.DelayBeforeShutdown, ReportID 0x0f). While the initial shutdown command works, after several shutdown.return cycles the UPS fails to restart and remains in a powered-off state instead of turning back on. Comparison with the vendor's UPSMON PRO software behavior (by reading back register values via NUT debug mode) revealed that the vendor software uses the Output section register (UPS.Output.DelayBeforeShutdown, ReportID 0x23) instead. This 8-bit register accepts a discrete delay index (1-18) per the protocol specification: Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Value 12s 18s 24s 30s 36s 42s 48s 54s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m Using the Output section register provides reliable shutdown.return behavior across repeated cycles. This commit adds: - powercom_shutdown_output_nuf(): converts offdelay seconds to the nearest discrete delay index for the Output section register. - shutdown.return and shutdown.stayoff command mappings via UPS.Output.DelayBeforeShutdown, placed before the existing PowerSummary mappings so they take priority on affected models. The existing PowerSummary shutdown commands are preserved as fallback for models that use them (e.g. SKP, IMP, VGD series). Note: the Output section shutdown is silent, unlike the PowerSummary shutdown which produces audible warning beeps (double short beeps) during the countdown before powering off. Tested on: Powercom RPT-800AP (VendorID 0x0d9f, ProductID 0x0004) Signed-off-by: Vladyslav Andreichykov <vladdrako007@gmail.com>
1 parent b0b3898 commit 55a6624

1 file changed

Lines changed: 63 additions & 0 deletions

File tree

drivers/powercom-hid.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,66 @@ static info_lkp_t powercom_shutdown_info[] = {
241241
{ 0, NULL, powercom_shutdown_fun, powercom_shutdown_nuf }
242242
};
243243

244+
/* Output section shutdown: uses discrete delay index (1-18) for
245+
* UPS.Output.DelayBeforeShutdown (ReportID 0x23, 8-bit).
246+
* Some Powercom UPS models (e.g. RPT-800AP, BNT-AP series) handle
247+
* shutdown more reliably via the Output section registers than via
248+
* PowerSummary. The native UPSMON PRO software uses these registers.
249+
*
250+
* Delay index table (from protocol spec):
251+
* Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
252+
* Value 12s 18s 24s 30s 36s 42s 48s 54s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m
253+
*/
254+
static double powercom_shutdown_output_nuf(const char *value)
255+
{
256+
const char *s = dstate_getinfo("ups.delay.shutdown");
257+
const char *cfg = getval("offdelay");
258+
int iv;
259+
uint8_t command;
260+
261+
if (value && *value)
262+
iv = atoi(value);
263+
else if (cfg && *cfg)
264+
iv = atoi(cfg);
265+
else if (s && *s)
266+
iv = atoi(s);
267+
else
268+
iv = 60;
269+
270+
/* Convert seconds to discrete delay index per protocol spec */
271+
if (iv <= 12) command = 1;
272+
else if (iv <= 18) command = 2;
273+
else if (iv <= 24) command = 3;
274+
else if (iv <= 30) command = 4;
275+
else if (iv <= 36) command = 5;
276+
else if (iv <= 42) command = 6;
277+
else if (iv <= 48) command = 7;
278+
else if (iv <= 54) command = 8;
279+
else if (iv <= 60) command = 9;
280+
else if (iv <= 120) command = 10;
281+
else if (iv <= 180) command = 11;
282+
else if (iv <= 240) command = 12;
283+
else if (iv <= 300) command = 13;
284+
else if (iv <= 360) command = 14;
285+
else if (iv <= 420) command = 15;
286+
else if (iv <= 480) command = 16;
287+
else if (iv <= 540) command = 17;
288+
else command = 18;
289+
290+
upsdebugx(3, "%s: offdelay=%d -> discrete index=%d (ReportID 0x23)",
291+
__func__, iv, command);
292+
293+
return (double)command;
294+
}
295+
296+
static info_lkp_t powercom_shutdown_output_info[] = {
297+
{ 0, NULL, powercom_shutdown_fun, powercom_shutdown_output_nuf }
298+
};
299+
300+
static info_lkp_t powercom_stayoff_output_info[] = {
301+
{ 0, NULL, NULL, powercom_shutdown_output_nuf }
302+
};
303+
244304
static double powercom_stayoff_nuf(const char *value)
245305
{
246306
const char *s = dstate_getinfo("ups.delay.shutdown");
@@ -657,6 +717,9 @@ static hid_info_t powercom_hid2nut[] = {
657717
{ "beeper.enable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "1", HU_TYPE_CMD, NULL },
658718
{ "beeper.disable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "0", HU_TYPE_CMD, NULL },
659719
{ "test.battery.start.quick", 0, 0, "UPS.Battery.Test", NULL, "1", HU_TYPE_CMD, NULL },
720+
/* Output section shutdown (more reliable on RPT/BNT-AP series) */
721+
{ "shutdown.return", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, NULL, HU_TYPE_CMD, powercom_shutdown_output_info },
722+
{ "shutdown.stayoff", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, NULL, HU_TYPE_CMD, powercom_stayoff_output_info },
660723
{ "load.on.delay", 0, 0, "UPS.PowerSummary.DelayBeforeStartup", NULL, NULL, HU_TYPE_CMD, powercom_startup_info },
661724
{ "shutdown.return", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, NULL, HU_TYPE_CMD, powercom_shutdown_info },
662725
{ "shutdown.stayoff", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, NULL, HU_TYPE_CMD, powercom_stayoff_info },

0 commit comments

Comments
 (0)