On Tue, Jul 1, 2014 at 3:12 PM, Steve Ballantyne
<steve.ballant...@gmail.com> wrote:
> On Tue, Jul 1, 2014 at 9:17 AM, Steve Ballantyne
> <steve.ballant...@gmail.com> wrote:
>> How would I go about providing you this stuff?  Can you point me to
>> something that would help trace out the USB data?

Tracing the data on Windows is not my speciality, but there are a few
messages in the NUT archives (can't remember whether nut-upsdev or
-upsuser, but the search form at
http://www.networkupstools.org/support.html hits both). The basic idea
is to configure the USB sniffer software to monitor your UPS, then you
would take notes on what the Windows software reports as you do a
similar test to what you posted.

A few people have done this by running Windows in a VM, and monitoring
on the Linux host side. Others have installed the sniffer software
into Windows itself. The details are going to depend on what you find
to be a more palatable challenge. The free Windows sniffer software is
mostly from the XP era, so with a newer OS, YMMV.

I don't know if the serial port will be easier or harder to deal with.

> I thought I would try to make sense of the ups.debug data.  All I have
> really figured out is that the fourth hex segment for S is a 00 for
> plugged in and a 01 for on-battery. Which the driver already knows.
> The rest is a mystery to me.  But I played around with unplugging and
> running the load down, and then recharging, etc.  Here are my notes
> and observations.  NC = "no change".  I am assuming that those fields
> are the make/model/serial number, etc.
>
> S fourth segment = 00 for on-power, 01 for on-battery

How far down did you let the battery go? I don't usually recommend
running it down all the way very often, but it would be good to do
that at least once to verify the LB flag. On yours, I think that would
look like "S: 00 ..."

The "01 04" seems to be the state before a self-test on yours as well
as on the ASCII version of the SMARTPRO protocol. See comments around
"switch(s_value_2) {" in the source code.

> UNPLUGD a while
> ups.debug.D: 00 00 00 7d 0d 00 00 '.......'  <---- 4th segment = 125

Looks like the first pairs of digits are the input voltage, and "00
7d" = 125V out.

> ups.debug.L: 06 00 00 07 58 58 0d '....XX.'  <---- 1st segment = 6

Not sure, but I have a feeling that one of 06 or 07 is a percent load.

Lots of good progress here! I tried to enable a few more commands for
your model. For instance, the "M" values seem to be min/max voltage,
so there is a "reset.input.minmax" command to use with upscmd.  Also,
you can trigger a battery test with "test.battery.start". I assume the
work the same way as on Protocol 3003 :-)

The attached patch is meant to be applied on top of the previous
patch. If it's easier, I can diff it against Git master.
commit 6b8ba2223c23c797613bdcacdbb16282b587d87a
Author: Charles Lepple <clepple+...@gmail.com>
Date:   Tue Jul 1 16:44:32 2014 -0400

    tripplite_usb: Additional 3005 protocol support
    
    http://news.gmane.org/find-root.php?message_id=CAFeiwyG8HCfg%2dQqxcwhnm1Yo0z0F0BLyOPCYX%2d4yMMFg8sB4QQ%40mail.gmail.com

diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c
index 9518467..808ba71 100644
--- a/drivers/tripplite_usb.c
+++ b/drivers/tripplite_usb.c
@@ -133,7 +133,7 @@
 #include "usb-common.h"
 
 #define DRIVER_NAME		"Tripp Lite OMNIVS / SMARTPRO driver"
-#define DRIVER_VERSION	"0.24"
+#define DRIVER_VERSION	"0.25"
 
 /* driver description structure */
 upsdrv_info_t	upsdrv_info = {
@@ -205,6 +205,21 @@ static int is_binary_protocol()
 	}
 }
 
+/*! Is this the "SMART" family of protocols?
+ * TODO: Add 3004?
+ */
+static int is_smart_protocol()
+{
+	switch(tl_model) {
+	case TRIPP_LITE_SMARTPRO:
+	case TRIPP_LITE_SMART_0004:
+	case TRIPP_LITE_SMART_3005:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
 /*!@brief If a character is not printable, return a dot. */
 #define toprint(x) (isalnum((unsigned)x) ? (x) : '.')
 
@@ -321,6 +336,36 @@ static int hex2d(const unsigned char *start, unsigned int len)
 	return strtol((char *)buf, NULL, 16);
 }
 
+/*!@brief Convert N characters from big-endian binary to decimal
+ *
+ * @param start		Beginning of string to convert
+ * @param len		Maximum number of characters to consider (max 32)
+ *
+ * @a len characters of @a start are shifted into an accumulator.
+ *
+ * We assume len < sizeof(int), and that value > 0.
+ *
+ * @return the value
+ */
+static unsigned int bin2d(const unsigned char *start, unsigned int len)
+{
+	unsigned int value = 0, index = 0;
+	for(index = 0; index < len; index++) {
+		value <<= 8;
+		value |= start[len];
+	}
+
+	return value;
+}
+
+static int hex_or_bin2d(const unsigned char *start, unsigned int len)
+{
+	if(is_binary_protocol()) {
+		return bin2d(start, len);
+	}
+	return hex2d(start, len);
+}
+
 /*!@brief Dump message in both hex and ASCII
  *
  * @param[in] msg	Buffer to dump
@@ -428,11 +473,12 @@ void decode_v(const unsigned char *value)
 		switchable_load_banks = lb - '0';
 	} else {
 		if(is_binary_protocol()) {
-			switchable_load_banks = value[4];
-		}
-		if( lb != 'X' ) {
-			upslogx(2, "Unknown number of switchable load banks: 0x%02x",
+			switchable_load_banks = lb;
+		} else {
+			if( lb != 'X' ) {
+				upslogx(2, "Unknown number of switchable load banks: 0x%02x",
 					(unsigned int)lb);
+			}
 		}
 	}
 	upsdebugx(2, "Switchable load banks: %d", switchable_load_banks);
@@ -692,7 +738,7 @@ static int instcmd(const char *cmdname, const char *extra)
 {
 	unsigned char buf[10];
 
-	if(tl_model == TRIPP_LITE_SMARTPRO || tl_model == TRIPP_LITE_SMART_0004) {
+	if(is_smart_protocol()) {
 		if (!strcasecmp(cmdname, "test.battery.start")) {
 			send_cmd((const unsigned char *)"A", 2, buf, sizeof buf);
 			return STAT_INSTCMD_HANDLED;
@@ -992,7 +1038,7 @@ void upsdrv_initinfo(void)
 	dstate_setaux("ups.delay.reboot", 3);
 #endif
 
-	if(tl_model == TRIPP_LITE_SMARTPRO || tl_model == TRIPP_LITE_SMART_0004) {
+	if(is_smart_protocol()) {
 		dstate_addcmd("test.battery.start");
 		dstate_addcmd("reset.input.minmax");
 	}
@@ -1085,10 +1131,7 @@ void upsdrv_updateinfo(void)
 
 	/* - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */
 
-	if(tl_model == TRIPP_LITE_SMARTPRO || 
-		tl_model == TRIPP_LITE_OMNIVS_2001 ||
-		tl_model == TRIPP_LITE_SMART_0004 ||
-		tl_model == TRIPP_LITE_SMART_3005) {
+	if(is_smart_protocol() || tl_model == TRIPP_LITE_OMNIVS_2001) {
 
 		unsigned int s_value_2 = s_value[2];
 
@@ -1194,7 +1237,8 @@ void upsdrv_updateinfo(void)
 
 	/* - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */
 
-	if( tl_model == TRIPP_LITE_SMARTPRO || tl_model == TRIPP_LITE_SMART_0004 ) {
+	if( is_smart_protocol() ) {
+
 		ret = send_cmd(d_msg, sizeof(d_msg), d_value, sizeof(d_value));
 		if(ret <= 0) {
 			dstate_datastale();
@@ -1203,10 +1247,10 @@ void upsdrv_updateinfo(void)
 		}
 
 		dstate_setinfo("input.voltage", "%d",
-				hex2d(d_value+1, 2) * input_voltage_scaled / 120);
+				hex_or_bin2d(d_value+1, 2) * input_voltage_scaled / 120);
 
 		/* TODO: factor out the two constants */
-		bv_12V = hex2d(d_value+3, 2) / 10.0 ;
+		bv_12V = hex_or_bin2d(d_value+3, 2) / 10.0 ;
 		battery_voltage = bv_12V * battery_voltage_nominal / 12.0;
 
 		dstate_setinfo("battery.voltage", "%.2f", battery_voltage);
@@ -1215,7 +1259,7 @@ void upsdrv_updateinfo(void)
 
 		ret = send_cmd(m_msg, sizeof(m_msg), m_value, sizeof(m_value));
 
-                if(m_value[5] != 0x0d) { /* we only expect 4 hex digits */
+                if(m_value[5] != 0x0d) { /* we only expect 4 hex/binary digits */
 			dstate_setinfo("ups.debug.M", "%s", hexascdump(m_value+1, 7));
 		}
 
@@ -1225,8 +1269,8 @@ void upsdrv_updateinfo(void)
 			return;
 		}
 
-		dstate_setinfo("input.voltage.minimum", "%3d", hex2d(m_value+1, 2));
-		dstate_setinfo("input.voltage.maximum", "%3d", hex2d(m_value+3, 2));
+		dstate_setinfo("input.voltage.minimum", "%3d", hex_or_bin2d(m_value+1, 2));
+		dstate_setinfo("input.voltage.maximum", "%3d", hex_or_bin2d(m_value+3, 2));
 
 		/* - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */
 
@@ -1257,8 +1301,10 @@ void upsdrv_updateinfo(void)
 			dstate_setinfo("input.frequency", "%.1f", freq / 10.0);
 		}
 
-		/* I'm guessing this is a calibration constant of some sort. */
-		dstate_setinfo("ups.temperature", "%.1f", (unsigned)(hex2d(t_value+1, 2)) * 0.3636 - 21);
+		if( tl_model != TRIPP_LITE_SMART_3005 ) {
+			/* I'm guessing this is a calibration constant of some sort. */
+			dstate_setinfo("ups.temperature", "%.1f", (unsigned)(hex2d(t_value+1, 2)) * 0.3636 - 21);
+		}
 	}
 
 	/* - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */
_______________________________________________
Nut-upsuser mailing list
Nut-upsuser@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsuser

Reply via email to