>
>
> On Oct 26, 2009, at 9:44 PM, "Gino Putrino"
> <[email protected]
>  > wrote:
>
>> Hi,
>>  I just acquired a Ritmo AS-800VA.
>> Unfortunately, it doesn't work out of the box with nut - so I had to
>> do a
>> bit of reverse engineering on the protocol to get it working. Am now
>> posting my findings here in the hope it will get this added to the
>> next
>> release.
>>
>> There are also 1000VA and 12000VA versions that this should work with.
>>
>> The protocol is very similar to the megatec protocol - although
>> simpler.
>> Like megatec - it responds to a 'Q1' request.
>> The response is slightly different - instead of the megatec 46
>> character
>> reply string - the ritmo unit replies with a 35 character string of
>> the
>> form:
>>
>> (AAA BBB CCC DD.D EE.E FFF GGGGGGGG
>>
>> Where:
>>    AAA is input voltage
>>    BBB is output voltage
>>    CCC is load - not sure what the range is - when my server plugged
>> in and
>> running - this is 4
>>    DD.D is input frequency
>>    EE.E is output frequency
>>    FFF is battery voltage - seems to be 195 when fully charged -
>> about 160
>> when flat.
>>    GGGGGGGG is a bit mask of the form b7b6b5b4b3b2b1b0. So far I've
>> only
>> established b7=1 when on battery power, b6=1 when battery level is
>> critical. Have not seen the remaining bits change from 0.
>>
>> A sample response to the "Q1" request when my server is running
>> normally is:
>> (233 233 004 50.0 50.0 195 00000000
>>
>> The unit does not respond to any of the other megatec queries.
>>
> Including the "I" query? (For identifying the vendor and model)
>
> Also, it is easier for us to analyze proposed code patches if they are
> sent in the form of a unified diff ("diff -u file.old.c file.c"). This
> is especially true if the driver in question has had changes since the
> last release.
>

Hi Charles,
    Unfortunately - yes - including the "I" query. The unit just times out
when I send that. Also, the windows software that came with the unit
that I snooped on doesn't send it at all.

Anyway- here is the unified diff.

Regards,
-Gino
--- megatec.original.c	2009-02-17 18:20:48.000000000 +0900
+++ megatec.c	2009-10-18 21:22:26.000000000 +0800
@@ -62,6 +62,7 @@
 /* The expected reply lengths */
 #define F_CMD_REPLY_LEN  21
 #define Q1_CMD_REPLY_LEN 46
+#define Q1_RITMO_CMD_REPLY_LEN 35
 #define I_CMD_REPLY_LEN  38
 
 #define IDENT_MAXTRIES   5
@@ -126,6 +127,7 @@
 	float freq;
 	float battvolt;
 	float temp;
+	float outfreq;
 	char flags[N_FLAGS + 1];
 } QueryValues_t;
 
@@ -436,6 +438,7 @@
 	char field[FIELD_BUFFER_LEN];
 	char *anchor;
 	int ret;
+	int protocolToUse;	//0 = megatec, 1 = ritmo
 
 	upsdebugx(2, "Asking for UPS status [Q1]...");
 	ser_flush_io(upsfd);
@@ -443,7 +446,9 @@
 	usleep(READ_PACE);
 
 	/*
-	 * Expected reply: "(MMM.M NNN.N PPP.P QQQ RR.R S.SS TT.T b7b6b5b4b3b2b1b0<cr>"
+	 * Expected reply
+	 * (protocol 0 megatec) : "(MMM.M NNN.N PPP.P QQQ RR.R S.SS TT.T b7b6b5b4b3b2b1b0<cr>"
+	 * (protocol 1 ritmo)   : "(MMM NNN PPP QQ.Q RR.R SS.S TTT b7b6b5b4b3b2b1b0<cr>"
 	 */
 	ret = ser_get_line(upsfd, buffer, RECV_BUFFER_LEN, ENDCHAR, IGNCHARS, READ_TIMEOUT, 0);
 
@@ -459,7 +464,11 @@
 		return -1;
 	}
 
-	if (ret < Q1_CMD_REPLY_LEN) {
+	if (ret >= Q1_CMD_REPLY_LEN) {
+		protocolToUse = 0;
+	} else if (ret == Q1_RITMO_CMD_REPLY_LEN) {
+		protocolToUse = 1;
+	} else {
 		upsdebugx(2, "Q1 => FAILED [short read]");
 		upsdebug_hex(3, "Q1 detail", (unsigned char *)buffer, ret);
 
@@ -474,35 +483,67 @@
 	}
 
 	upsdebugx(2, "Q1 => OK [%s]", buffer);
+	if (protocolToUse == 0) {
+		anchor = copy_field(field, &buffer[1], 5);
+		values->ivolt = atof(field);
 
-	anchor = copy_field(field, &buffer[1], 5);
-	values->ivolt = atof(field);
+		anchor = copy_field(field, anchor + 1, 5);
+		values->fvolt = atof(field);
 
-	anchor = copy_field(field, anchor + 1, 5);
-	values->fvolt = atof(field);
+		anchor = copy_field(field, anchor + 1, 5);
+		values->ovolt = atof(field);
 
-	anchor = copy_field(field, anchor + 1, 5);
-	values->ovolt = atof(field);
+		anchor = copy_field(field, anchor + 1, 3);
+		values->load = atof(field);
 
-	anchor = copy_field(field, anchor + 1, 3);
-	values->load = atof(field);
+		anchor = copy_field(field, anchor + 1, 4);
+		values->freq = atof(field);
 
-	anchor = copy_field(field, anchor + 1, 4);
-	values->freq = atof(field);
+		anchor = copy_field(field, anchor + 1, 4);
+		values->battvolt = atof(field);
 
-	anchor = copy_field(field, anchor + 1, 4);
-	values->battvolt = atof(field);
+		anchor = copy_field(field, anchor + 1, 4);
+		values->temp = atof(field);
 
-	anchor = copy_field(field, anchor + 1, 4);
-	values->temp = atof(field);
+		values->outfreq = 0.0;
 
-	anchor = copy_field(values->flags, anchor + 1, N_FLAGS);
+		anchor = copy_field(values->flags, anchor + 1, N_FLAGS);
+
+		if (strlen(values->flags) < N_FLAGS) {
+			upsdebugx(2, "Q1 => FAILED [flags error]");
+			return -1;
+		}
+	} else if (protocolToUse == 1) {
+		anchor = copy_field(field, &buffer[1], 3);
+		values->ivolt = atof(field);
+
+		anchor = copy_field(field, anchor + 1, 3);
+		values->ovolt = atof(field);
+
+		anchor = copy_field(field, anchor + 1, 3);
+		values->load = atof(field);
+		
+
+		anchor = copy_field(field, anchor + 1, 4);
+		values->outfreq = atof(field);
 
-	if (strlen(values->flags) < N_FLAGS) {
-		upsdebugx(2, "Q1 => FAILED [flags error]");
-		return -1;
-	}
 
+		anchor = copy_field(field, anchor + 1, 4);
+		values->freq = atof(field);
+
+		anchor = copy_field(field, anchor + 1, 3);
+		values->battvolt = atof(field);
+
+		values->fvolt = 0.0;
+		values->temp = 0.0;
+
+		anchor = copy_field(values->flags, anchor + 1, N_FLAGS);
+
+		if (strlen(values->flags) < N_FLAGS) {
+			upsdebugx(2, "Q1 => FAILED [flags error]");
+			return -1;
+		}		
+	}
 	upsdebugx(2, "Q1 VALUES => [%.1f %.1f %.1f %.1f %.1f %.1f %.1f %s]",
 	          values->ivolt, values->fvolt, values->ovolt, values->load,
 	          values->freq, values->battvolt, values->temp, values->flags);
@@ -711,6 +752,7 @@
 	dstate_setinfo("output.voltage", "%.1f", query.ovolt);
 	dstate_setinfo("ups.load", "%.1f", query.load);
 	dstate_setinfo("input.frequency", "%.1f", query.freq);
+	dstate_setinfo("output.frequency", "%.1f", query.outfreq);
 
 	/*
 	 * The battery voltage multiplier should only be applied to battery.voltage
_______________________________________________
Nut-upsdev mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/nut-upsdev

Reply via email to