Rob wrote:
I'm trying to get more information about the problems with the CP1200AVR and am connecting to the device through the USB cable. Since I haven't received the working driver yet (someone modified the cpsups driver), I figured I'd start trying to play with some drivers and ran them in debug mode. Here's the output from the newhidups run:

/lib/nut/newhidups -u root -a Lysander -DDDD
Network UPS Tools: 0.28 USB communication driver 0.28 - core 0.30 (2.1.0)

debug level is '4'
Checking device (0764/0005) (001/008)
- VendorID: 0764
- ProductID: 0005
- Manufacturer: unknown
- Product: unknown
- Serial Number: unknown
- Bus: 001
Trying to match device
Device matches
failed to claim USB device, trying 2 more time(s)...
detaching kernel driver from USB device...
trying again to claim USB device...
Unable to get HID descriptor (error sending control message: Connection timed out)

Running the driver seems to cause issues with the 2.6.17 kernel as the /dev/usb/hiddev0 device disappears after the failed attempt to access the UPS. This doesn't happen with the 2.0.3 version of the driver (but that version also doesn't even recognize the UPS.

The failure to claim the USB device seems troubling to me, unless that error is because the device node is disappearing after the device check (which itself it troubling).

I also tried the cpsups driver, but it complains thusly:
cpsups -a Lysander -u root -DDDD
Network UPS Tools -  CyberPower text protocol UPS driver .04 (2.1.0)
Warning: This is an experimental driver.
Some features may not function correctly.

debug level is '4'
tcgetattr(/dev/usb/hiddev0): Invalid argument

genericups with usbtype=22 complains:
genericups -a Lysander -u root -DDDD
Network UPS Tools - Generic UPS driver 1.32 (2.1.0)
debug level is '4'
UPS type: Gamatronic UPSs with alarm interface
ioctl TIOCMSET: Invalid argument

So it looks like the newhidups is the most likely to get working. Is that a fair assessment? Is the problem with the device node a known problem? Is there a way to get the dump of the communication traffic going on between the PC and the UPS? Any ideas on where to go next?

Rob

Rob wrote:
Yes, I'd be very interested in getting a copy of your driver which works
with the CP1200AVR.   Does your cpsups driver support USB connections or
only serial?  Also, which NUT release is it based on/work with (2.0.x or
2.1)?

Rob

-------- Original Message --------
Subject: Re: [Nut-upsuser] CyberPower CP1200AVR/BC1200D problems
From: doug reynolds <[EMAIL PROTECTED]>
Date: Thu, July 20, 2006 9:07 pm
To: Rob <[EMAIL PROTECTED]>
Cc: [email protected]

Rob wrote:
I recently purchased a CyberPower CP1200AVR UPS and am trying to get NUT 2.0.3 or NUT 2.1.0 to work with the newhidups driver, but am having little success. Before I purchased I did some googling and saw people talking about problems so I'm guessing it may not be supported yet? I did find some posts about people getting it to (sort of) work with some hacks, but couldn't tell if they ever got submitted to the NUT development team. I also found some posts about the CyberPower 900AVR/BC900D having issues, and it looks like I am having the same problems as the person trying to use that UPS. Namely, I see these messages in syslog:

kernel: usb 1-2: usbfs: USBDEVFS_CONTROL failed cmd newhidups rqt 128 rq 6 len 255 ret -110

I don't have much experience in protocol decoding, but I am a software engineer and I'd like to help get this UPS supported by NUT. Does anyone know the status of the support for the CyberPower CP1200AVR or have anything new to try?
i got mine working fairly well with the cpsups with a couple change to the code... email me if you would like a copy of my driver.
oops.  sorry, been busy.. here is the driver mods I came up with..
other than the type definition, I removed the leading \r's from the commands sent to the UPS. seems to work pretty good.. haven't had a whole lot of time to test thoroughly.. another gentleman on this list mentioned what he did, so I went through the code and this is what I came up with..

/* cpsups.c - model specific routines for CyberPower text protocol UPSes

  Copyright (C) 2003  Walt Holman <[EMAIL PROTECTED]>
  with thanks to Russell Kroll <[EMAIL PROTECTED]>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

/* This driver started out as the bestups.c driver from 1.5.11 -
* I've hacked it up every which way to get it to function
* with a CPS1100AVR. Thanks go to the guys at
* http://networkupstools.org for creating a very nice toolset.
*/

/* hack version for 1200VA
* by DJR
*/

#include "cpsups.h"

#define DRV_VERSION ".04"

static void model_set(const char *abbr, const char *rating)
{

       /*
        * Added: Brad Sawatzky <[EMAIL PROTECTED]> 02Jun04
* NOTE: I have no idea how to set the runtime parameter... I basically
        * scaled up linearly from the 1100 and 500 entries based on the
        * 'voltage'.  The realtime runtime calculated under load looks
        * reasonable.
        */
   if (!strcmp(abbr, "#1500VA    ")) {
           dstate_setinfo("ups.mfr", "%s", "CyberPower");
           dstate_setinfo("ups.model", "CPS1500AVR %s", rating);
       dstate_setinfo("ups.runtime", "%s", "90");
       dstate_setinfo("ups.power.nominal", "%s", "1500");
           return;
   }

// define the type of ups, and match it to the string returned, #BC1200

   if (!strcmp(abbr, "#BC1200    ")) {
       dstate_setinfo("ups.mfr", "%s", "CyberPower");
       dstate_setinfo("ups.model", "CPS1200VA %s", rating);
       dstate_setinfo("ups.runtime", "%s", "70");
       dstate_setinfo("ups.power.nominal", "%s", "1200");
       return;
   }

   if (!strcmp(abbr, "#1100VA    ")) {
           dstate_setinfo("ups.mfr", "%s", "CyberPower");
           dstate_setinfo("ups.model", "CPS1100VA %s", rating);
       dstate_setinfo("ups.runtime", "%s", "60");
       dstate_setinfo("ups.power.nominal", "%s", "1100");
           return;
   }

   /* Added: Armin Diehl <[EMAIL PROTECTED]> 14Dec04 */
   if (!strcmp(abbr, "#1000VA    ")) {
       dstate_setinfo("ups.mfr", "%s", "MicroDowell");
       dstate_setinfo("ups.model", "B.Box BP 1000 %s", rating);
       dstate_setinfo("ups.runtime", "%s", "50");
       dstate_setinfo("ups.voltage", "%s", "1000");
       return;
   }
if (!strcmp(abbr, "#825VA ")) {
       dstate_setinfo("ups.mfr", "%s", "CyberPower");
       dstate_setinfo("ups.model", "CPS825VA %s", rating);
       dstate_setinfo("ups.runtime", "%s", "29");
       dstate_setinfo("ups.power.nominal", "%s", "825");
       return;
   }

   /* Added: Armin Diehl <[EMAIL PROTECTED]> 14Dec04 */
   if (!strcmp(abbr, "#750VA     ")) {
       dstate_setinfo("ups.mfr", "%s", "MicroDowell");
       dstate_setinfo("ups.model", "B.Box BP 750 %s", rating);
       dstate_setinfo("ups.runtime", "%s", "29");
       dstate_setinfo("ups.voltage", "%s", "825");
       return;
   }

   if (!strcmp(abbr, "#500VA     ")) {
               dstate_setinfo("ups.mfr", "%s", "CyberPower");
               dstate_setinfo("ups.model", "OP500TE %s", rating);
               dstate_setinfo("ups.runtime", "%s", "16.5");
               dstate_setinfo("ups.power.nominal", "%s", "500");
       return;
   }

   dstate_setinfo("ups.mfr", "%s", "Unknown");
   dstate_setinfo("ups.model", "Unknown %s (%s)", abbr, rating);
   dstate_setinfo("ups.runtime", "%s", "1");
   dstate_setinfo("ups.power.nominal", "%s", "1");

   printf("Unknown model detected - please report this ID: '%s'\n", abbr);
}

static int instcmd(const char *cmdname, const char *extra)
{
   /* The following commands also appear to be valid on the CPS1100 */

   if (!strcasecmp(cmdname, "test.battery.stop")) {
       ser_send_pace(upsfd, UPSDELAY, "CT\r");
       return STAT_INSTCMD_HANDLED;
   }

   if (!strcasecmp(cmdname, "test.battery.start")) {
       ser_send_pace(upsfd, UPSDELAY, "T\r");
       return STAT_INSTCMD_HANDLED;
   }

   upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
   return STAT_INSTCMD_UNKNOWN;
}


static int get_ident(char *buf, size_t bufsize)
{
   int    i, ret;

   for (i = 0; i < MAXTRIES; i++) {
       ser_send_pace(upsfd, UPSDELAY, "P4\r");

       ret = ser_get_line(upsfd, buf, bufsize, ENDCHAR, "",
           SER_WAIT_SEC, SER_WAIT_USEC);

       if (ret > 0)
           upsdebugx(2, "get_ident: got [%s]", buf);

       /* buf must start with # and be in the range [25-27] */
       if ((ret > 0) && (buf[0] == '#') && (strlen(buf) >= 25) &&
           (strlen(buf) <= 50))
           return 1;

       sleep(1);
   }

   upslogx(LOG_INFO, "Giving up on hardware detection after %d tries",
       MAXTRIES);

   return 0;
}

static int scan_poll_values(char *buf)
{
   char values[20][200], *pos;
   int i = 0, battremain, length, rseconds;
   double rminutes;

/*    These are used to hold status of UPS.
*    val1 = online/onbattery status
*/
    char temp1=values[6][0];
   char *tmp1=&temp1;

   while ((pollstatusmap[i].end != 0))
   {
       pos = &buf[pollstatusmap[i].begin];
       length = pollstatusmap[i].end + 1 - pollstatusmap[i].begin;
       strncpy(values[i],pos,length);
       i++;
   }

   if ((*tmp1 & CPS_STAT_OL) && !(*tmp1 & CPS_STAT_OB))
       status_set("OL");

   if (*tmp1 & CPS_STAT_OB)
       status_set("OB");

   if (*tmp1 & CPS_STAT_CAL)
       status_set("CAL");

   if (*tmp1 & CPS_STAT_LB)
       status_set("LB");

   if (*tmp1 == 0)
       status_set("OFF");


   pos = values[3];
battremain = strtol(dstate_getinfo("ups.power.nominal"),NULL,10) * (strtod(pos,NULL)/100);

   /* Figure out runtime minutes */
   rminutes = strtod(dstate_getinfo("ups.runtime"),NULL) *
       ((battremain * ( 1 - (strtod (values[2],NULL) / 100 ))) /
        strtol(dstate_getinfo("ups.power.nominal"),NULL,10));
   rseconds = ((int)(rminutes*100) - ((int)rminutes)*100) * 0.6 ;

       dstate_setinfo("input.voltage", "%g", strtod(values[0],NULL));
       dstate_setinfo("output.voltage", "%g", strtod(values[1],NULL));
       dstate_setinfo("ups.load", "%li", strtol(values[2],NULL,10));
       dstate_setinfo("input.frequency", "%g", strtod(values[5],NULL));
       dstate_setinfo("ups.temperature", "%li", strtol(values[4],NULL,10));
   dstate_setinfo("battery.charge", "%02.1f", strtod(values[3],NULL));
   dstate_setinfo("battery.runtime", "%2.0f:%02d", rminutes, rseconds);

   status_commit();
   dstate_dataok();
   return 0;
}

static void ups_ident(void)
{
   char    buf[256], *ptr, *com, *model, *rating;
   int    i;

   if (!get_ident(buf, sizeof(buf)))
       fatalx("Unable to detect a CyberPower text protocol UPS");

   model = rating = NULL;

   ptr = buf;

   /* Leaving this in place for future */
   for (i = 0; i < 2; i++) {
       com = strchr(ptr, ',');

       if (com)
           *com = '\0';

       switch (i) {
           case 0: model = ptr;
               break;
           case 1: rating = ptr;
               break;
           default:
               break;
       }

       if (com)
           ptr = com + 1;
   }

   if (!model)
       fatalx("Didn't get a valid ident string");

   model_set(model, rating);
}

static void ups_sync(void)
{
   char    buf[256];
   int    i, ret;

   for (i = 0; i < MAXTRIES; i++) {
       ser_send_pace(upsfd, UPSDELAY, "P4\r");
       upsdebugx(3, "ups_sync: send [%s]", "\P4\\r");

       ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, "",
           SER_WAIT_SEC, SER_WAIT_USEC);
       upsdebugx(3, "ups_sync: got ret %d [%s]", ret, buf);

       /* return once we get something that looks usable */
       if ((ret > 0) && (buf[0] == '#')) {
upsdebugx(3, "ups_sync: got line beginning with #, looks usable, returning");
           return;
       }

       usleep(250000);
   }

   fatalx("Unable to detect a CyberPower text protocol UPS");
}

void upsdrv_initinfo(void)
{
   int ret;
   char temp[256];

   ups_sync();
   ups_ident();

   printf("Detected %s %s on %s\n", dstate_getinfo("ups.mfr"),
       dstate_getinfo("ups.model"), device_path);

   /* paranoia - cancel any shutdown that might already be running */
ser_send_pace(upsfd, UPSDELAY, "C\r"); /* Need a readback so the first poll doesn't fail */ ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, "", SER_WAIT_SEC, SER_WAIT_USEC);

   upsh.instcmd = instcmd;

   dstate_setinfo("driver.version.internal", "%s", DRV_VERSION);
   dstate_addcmd("test.battery.start");
   dstate_addcmd("test.battery.stop");
}

static int ups_on_line(void)
{
   int    i, ret;
   char    temp[256];

   for (i = 0; i < MAXTRIES; i++) {
       ser_send_pace(upsfd, UPSDELAY, "D\r");

       ret = ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, "",
           SER_WAIT_SEC, SER_WAIT_USEC);

       /* D must return 34 bytes starting with a # */
       if ((ret > 0) && (temp[0] == '#') && (strlen(temp) == 34)) {

           char * pos = &temp[pollstatusmap[POLL_UPSSTATUS].begin];

           if ((*pos & CPS_STAT_OL) && !(*pos & CPS_STAT_OB))
               return(1);    /* on line */

           return 0;    /* on battery */
       }

       sleep(1);
   }

   upslogx(LOG_ERR, "Status read failed: assuming on battery");

   return 0;    /* on battery */
}

void upsdrv_shutdown(void)
{
   int ret;
   char    buf[256];

   ups_sync();

   printf("The UPS will shut down in approximately one minute.\n");

   if (ups_on_line())
       printf("The UPS will restart in about one minute.\n");
   else
       printf("The UPS will restart when power returns.\n");

   /* Although this is straight from the bestups.c driver, the UPS
    * does indeed shutdown correctly. */

   ser_send_pace(upsfd, UPSDELAY, "S01R0001\r");

   ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, "",
                      SER_WAIT_SEC, SER_WAIT_USEC);

   if ((ret < 1) || (buf[0] != '#'))
printf ("Warning: got unexpected reply to shutdown command, shutdown may fail\n");
}

void upsdrv_updateinfo(void)
{
   char    buf[256];
   int    ret;

   ret = ser_send_pace(upsfd, UPSDELAY, "D\r");

   if (ret < 1) {
       ser_comm_fail("ser_send_pace failed");
       dstate_datastale();
       return;
   }

   /* these things need a long time to respond completely */
   usleep(200000);

   ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, "",
       SER_WAIT_SEC, SER_WAIT_USEC);

   if (ret < 1) {
       ser_comm_fail(NULL);
       dstate_datastale();
       return;
   }

   if (ret < 34) {
       if (ret == 2)         /* We need to retry this read right away    */
       {
ret = ser_get_line(upsfd, buf, sizeof(buf), ENDCHAR, "", SER_WAIT_SEC, SER_WAIT_USEC);
           if (ret < 34) {
ser_comm_fail("Poll failed: short read (got %d bytes)", ret);
               dstate_datastale();
               return;
           }
       } else {
           ser_comm_fail("Poll failed: short read (got %d bytes)", ret);
           dstate_datastale();
           return;
       }
   }

   if (ret > 34) {
       upslogx(LOG_INFO, "String too long...");
       ser_comm_fail("Poll failed: response too long (got %d bytes)",
           ret);
       dstate_datastale();
       return;
   }

   if (buf[0] != '#') {
       ser_comm_fail("Poll failed: invalid start character (got %02x)",
           buf[0]);
       dstate_datastale();
       return;
   }

   ser_comm_good();

   scan_poll_values(buf);

   status_init();

}

void upsdrv_help(void)
{
}

void upsdrv_makevartable(void)
{
}

void upsdrv_banner(void)
{
printf("Network UPS Tools - CyberPower text protocol UPS driver %s (%s)\n",
       DRV_VERSION, UPS_VERSION);
   experimental_driver = 1;    /* Causes a warning message to be printed */
}

void upsdrv_initups(void)
{
   upsfd = ser_open(device_path);
   ser_set_speed(upsfd, device_path, B2400);

}

void upsdrv_cleanup(void)
{
   ser_close(upsfd, device_path);
}


_______________________________________________
Nut-upsuser mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/nut-upsuser

Reply via email to