[Nut-upsdev] Sweex 1000VA UPS (Lakeview Research)

Arjen de Korte nut+devel at de-korte.org
Tue Dec 16 21:57:50 UTC 2008


Citeren Peter van Valderen <dosperios at gmail.com>:

> I was not aware that it had been imported into the trunk. Last time I
> looked noone seemed to have done anything with the driver or have any
> interest, so I figured there was no point. If there's any real
> interest in keeping it in the trunk, I can have a look with my device
> to see if I have the same problem mentioned above. If so, it should
> probably be fixable pretty easily.

In addition to the issues already mentioned, there are some others  
(maybe not so easy to fix):

1) It is not allowed to call upsdrv_initups() in the reconnect  
function. In upsdrv_initups() one should exit() from the driver if the  
UPS is not found. However, once you have reached upsdrv_updateinfo()  
the driver must not exit() if the UPS isn't found, but rather attempt  
to reconnect forever.

2) Similar to the above, the behavior of (re)connecting to the UPS  
must be different in upsdrv_initups() and upsdrv_updateinfo(). In the  
first case, one would probably retry several times (32 now) before  
deciding the UPS isn't there. In the latter case, the driver should  
attempt only once for each call to upsdrv_updateinfo() and return  
immediately if things don't work out. You don't have time to do  
repeated attempts here, otherwise the server will not hear from the  
driver too long.

3) Similar to the above, reading garbage data should be limited to  
once per pass upon reconnecting, like the below rudimentary example:

#define IGNORE_QUERY	5

static int	ignore = 0;

[...]

void upsdrv_updateinfo(void)
{
	char	reply[REPLY_PACKETSIZE];
	int	ret;

	if ((ignore == IGNORE_QUERY) && (reconnect() != SUCCESS)) {
		usb_comm_fail("Reconnecting to UPS failed");
		return;
	}

	ret = query_ups(reply);

	if (ret < 4) {
		usb_comm_fail("Query to UPS failed");
		dstate_datastale();
		ignore = IGNORE_QUERY;
		return;
	}

	usb_comm_good();
	dstate_dataok();

	if (ignore > 0) {
		ignore--;
		return;
	}

	[...]

4) Don't use upslog*() too often. System administrators don't like it  
if their syslog is spammed with information that is for debugging  
purposes only.

5) For the usb_control_msg() and usb_interrupt_read() calls, make a  
difference between error (ret < 0) and timeout (ret == 0), like in the  
following example:

	ret = usb_control_msg(upsdev, STATUS_REQUESTTYPE, REQUEST_VALUE,
		MESSAGE_VALUE, INDEX_VALUE, query, sizeof(query), 1000);

	if (ret < 0) {
		upsdebug_with_errno(3, "send");
		return ret;
	}

	if (ret == 0) {
		upsdebugx(3, "send: timeout");
		return ret;
	}

	upsdebug_hex(3, "send", query, ret);

Similarly, you would do the same after the usb_interrupt_read() call.  
This will help in diagnosing communication problems should this ever  
be needed.

6) Watch out with sleep() in the driver. With a timeout value of 1  
second in the usb_* calls, adding another 3 seconds will already bring  
you dangerously close to the five (5) seconds that are allowed in  
upsdrv_updateinfo().

Best regards, Arjen
-- 
Please keep list traffic on the list




More information about the Nut-upsdev mailing list