[Nut-upsdev] using upscode2 driver with Powerware 5119 RM

Steve Golson sgolson at trilobyte.com
Wed Mar 3 19:03:46 UTC 2010


I've got a Powerware 5119 RM UPS.

driver.list says to use "genericups upstype=20", however I know this UPS 
supports the UPS Code II protocol, so I wanted to use the upscode2 driver. It 
took some hacking but finally it works.

I'm using NUT 2.4.1 and upscode2 driver version 0.87 (however the latest r2350 
version of upscode2.c isn't significantly different, so I think all my results 
still apply).

Here's the hardware:
Apple G5 Xserve running Mac OS X Server 10.5.8
IOGEAR GUC2322 USB-to-serial adapter (uses Moschip 78XX)
Powerware Model PW5119, P/N 05144717-5501, purchased 12/2000 so maybe old 
firmware?

Here's what upsc says about this UPS:
ups.mfr: Powerware
ups.model: UPS 1440 VA FW -0039
ups.power.nominal: 1440.00
ups.serial: TS381A0198

Here's what I have in ups.conf:
	driver = upscode2
	port = /dev/tty.MCS78XX_Port0.0
	manufacturer = "Powerware"
	desc = "Powerware 5119 RM on myhostname"
	output_pace = 300
	use_crlf

Setting output_pace to 300 seemed to make communications more robust. YMMV. 
UPS Code II spec says you need use_crlf, but it seems to work even without it.

The upscode2 driver worked great for normal status, except it failed to power 
down the UPS. After much debugging I discovered the following problems:

1. The driver successfully sends the UPPC powerdown command, followed by the 
security string, and then exits. However the UPS ignored the UPPC command and 
never shut down. By performing a UPTP command right after the UPPC then the 
UPPC is recognized! Maybe the UPS doesn't like the serial communication being 
dropped so abruptly?

2. UPS Code II spec says you can view the values of UPSD and UPPC by sending 
the command string followed by a parameter of "0". However for my UPS this 
sets the value to 0! In order to view the value you must send "0000". So in 
upsc_commandlist I changed

   upsc_getvalue(cp->upsc, "0", cp->upsp, cp->cmd, NULL);

to

   upsc_getvalue(cp->upsc, "0000", cp->upsp, cp->cmd, NULL);

and all works correctly.

3. I want to specify a custom shutdown delay value. I can use upsrw

   upsrw -s ups.delay.shutdown=60 -u admin -p password UPSNAME

and the parameter is correctly stored into the UPS using UPSD. And you can 
read this value back (if you fixed item 2. above). I do this at boot time.

However the driver ignores my setting, and forces UPSD to have a value of "1" 
just before issuing the UPPC shutdown command. Removing this UPSD allows the 
custom value to be used correctly.

Also I changed the shutdown messages so the ups.delay.* values are reported.


With all that, here's what upsdrv_shutdown looks like:

void upsdrv_shutdown(void)
{
	if (upsc_commandlist()) {
		if (!can_upsd || !can_uppc) {
			fatalx(LOG_EMERG, "Shutdown called, but UPS does not support it");
		}
	} else {
		upslogx(LOG_EMERG, "Can't determine if shutdown is supported, attempting 
anyway");
	}

	upslogx(LOG_EMERG, "Emergency shutdown");

	char msg[100];
	snprintf(msg, 100, "UPS will reboot %ld seconds after shutdown", 
strtol(dstate_getinfo("ups.delay.reboot"),NULL,10));
	upslogx(LOG_EMERG, msg);
	snprintf(msg, 100, "UPS shutting down in %ld seconds...", 
strtol(dstate_getinfo("ups.delay.shutdown"),NULL,10));
	upslogx(LOG_EMERG, msg);

	upscsend("UPPC");	/* Powercycle UPS */
	upscsend("IJHLDMGCIU"); /* security code */

	/* do something so connection doesn't drop right after UPPC command */
	upsc_getvalue("UPTP", NULL, "NNAME", "ups.model", NULL);
}

I'm sure a real C hacker could find a cleaner/better/elegant way to print the 
messages, but hey I'm a hardware guy. I'm just happy it's all working.

-seg



More information about the Nut-upsdev mailing list