Logo Search packages:      
Sourcecode: nut version File versions

oneac.c

/*vim ts=4*/

/*
 * NUT Oneac EG and ON model specific drivers for UPS units using
 * the Oneac Advanced Interface.  If your UPS is equipped with the
 * Oneac Basic Interface, use the genericups driver
*/

/*
   Copyright (C) 2003  by Eric Lawson <elawson@inficad.com>

   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
*/

/* 28 November 2003.  Eric Lawson
 * More or less complete re-write for NUT 1.5.9 
 * This was somewhat easier than trying to beat the old driver code 
 * into submission
*/

#define DRV_VERSION "0.4"
#define SECS 2          /*wait time*/
#define USEC 0          /*rest of wait time*/

#include "main.h"
#include "serial.h"
#include "oneac.h"

void do_battery_test(void)
{
      char buffer[256];

      if (getval("testtime") == NULL)
            snprintf(buffer, 3, "%s", DEFAULT_BAT_TEST_TIME);
      else {
            snprintf(buffer, 3, "%s", getval("testtime"));

      /*the UPS wants this value to always be two characters long*/
      /*so put a zero in front of the string, if needed....      */
            if (strlen(buffer) < 2) {
                  buffer[2] = '\0';
                  buffer[1] = buffer[0];
                  buffer[0] = '0';
            }
      }
      ser_send(upsfd,"%s%s%s",BAT_TEST_PREFIX,buffer,COMMAND_END);
}


/****************************************************************
 *below are the commands that are called by main (part of the   *
 *Above, are functions used only in this oneac driver           *
 ***************************************************************/

int instcmd(const char *cmdname, const char *extra)
{
      if (!strcasecmp(cmdname, "test.failure.start")) {
            ser_send(upsfd,"%s%s",SIM_PWR_FAIL,COMMAND_END);
            return STAT_INSTCMD_HANDLED;
      }

      if (!strcasecmp(cmdname, "test.battery.start")) {
            do_battery_test();
            return STAT_INSTCMD_HANDLED;
      }

      if (!strcasecmp(cmdname, "test.battery.stop")) {
            ser_send(upsfd,"%s00%s",BAT_TEST_PREFIX,COMMAND_END);
            return STAT_INSTCMD_HANDLED;
      }

      if (!strcasecmp(cmdname, "reset.input.minmax")) {
            ser_send(upsfd,"%c%s",RESET_MIN_MAX, COMMAND_END);
            return STAT_INSTCMD_HANDLED;
      }

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


void upsdrv_initinfo(void)
{
      char buffer[256];
      ser_flush_in(upsfd,"",0);
      ser_send(upsfd,"%c%s",GET_MFR,COMMAND_END);
      ser_get_line(upsfd, buffer, sizeof(buffer),ENDCHAR,IGNCHARS,SECS,USEC);
      if(strncmp(buffer,MFGR, sizeof(MFGR)))
            fatalx("Unable to connect to ONEAC UPS on %s\n",device_path);     
 
      dstate_setinfo("ups.mfr", "ONEAC");
      dstate_addcmd("test.battery.start");
      dstate_addcmd("test.battery.stop");
      dstate_addcmd("test.failure.start");
      dstate_addcmd("reset.input.minmax");


      upsh.instcmd = instcmd;

      /*set some stuff that shouldn't change after initialization*/
      /*this stuff is common to both the EG and ON family of UPS */

      /*firmware revision*/
      ser_send(upsfd,"%c%s", GET_VERSION, COMMAND_END);
      ser_get_line(upsfd, buffer, sizeof(buffer),ENDCHAR,IGNCHARS,SECS,USEC);
      dstate_setinfo("ups.firmware", "%.3s",buffer);

      /*nominal AC frequency setting --either 50 or 60*/
      ser_send(upsfd,"%c%s", GET_NOM_FREQ, COMMAND_END);
      ser_get_line(upsfd,buffer,sizeof(buffer),ENDCHAR,IGNCHARS,SECS,USEC);
      dstate_setinfo("input.frequency", "%.2s", buffer);


      /*UPS Model (either ON, or EG series of UPS)*/
      
      ser_send(upsfd,"%c%s", GET_FAMILY,COMMAND_END);
      ser_get_line(upsfd,buffer,sizeof(buffer),ENDCHAR,IGNCHARS,SECS,USEC);
      dstate_setinfo("ups.model", "%.2s",buffer);
      printf("Found %.2s family of Oneac UPS\n", buffer);

      if (strncmp(buffer,FAMILY_ON,2) || strncmp(buffer,FAMILY_EG,2) == 0)
            printf("Unknown family of UPS. Assuming EG capabilities.\n");

      /*The ON series of UPS supports more stuff than does the EG.
      *Take care of the ON only stuff here
      */
      if(strncmp (dstate_getinfo("ups.model"), FAMILY_ON, 2) == 0) {
            /*now set the ON specific "static" parameters*/

                  /*nominal input voltage*/

            ser_send(upsfd,"%c%s",GET_NOM_VOLTAGE,COMMAND_END);
            ser_get_line(upsfd,buffer,sizeof(buffer),ENDCHAR,IGNCHARS,SECS,USEC);

            switch (buffer[0]) {
                  case V120AC:
                        dstate_setinfo("output.voltage.nominal", 
                              "120");
                        break;

                  case V230AC:
                        dstate_setinfo("output.voltage.nominal", 
                              "240");
                        break;

                  default:
                        upslogx(LOG_INFO,"Oneac: "
                              "Invalid voltage parameter from UPS");
            }
      }
}

void upsdrv_updateinfo(void)
{
      char buffer[256];
      int ret_value;


      ser_flush_in(upsfd,"",0);  /*just in case*/
      ser_send (upsfd,"%c%s",GET_ALL,COMMAND_END);
      ret_value = ser_get_line(upsfd,buffer,sizeof(buffer),ENDCHAR,
                  IGNCHARS,SECS,USEC);
      
      upsdebugx (2,"upsrecv_updateinfo: upsrecv returned: %s\n",buffer);
      if (ret_value == -1)
      {
            ser_comm_fail("Oneac UPS Comm failure on port %s",device_path);
            dstate_datastale();
      }
      else
      {
            status_init();
            /*take care of the UPS status information*/
            switch (buffer[12]) {
                  case NORMAL :
                        status_set("OL");
                        break;
                  case ON_BAT_LOW_LINE :
                  case ON_BAT_HI_LINE  :
                        status_set("OB");
                        break;
                  case LO_BAT_LOW_LINE :
                  case LO_BAT_HI_LINE  :
                        status_set("OB LB");
                        break;
                  case TOO_HOT :
                        status_set("OVER OB LB");
                        break;
                  case FIX_ME :
                        dstate_setinfo("ups.test.result","UPS Internal Failure");
                        break;
                  case BAD_BAT :
                        status_set("RB");
                        break;
                  default :                     /*cry for attention, fake a status*/
                                                      /*Would another status be better?*/
                        upslogx (LOG_ERR, "Oneac: Unknown UPS status");
                        status_set("OL");
            }

            /*take care of the reason why the UPS last transfered to battery*/
            switch (buffer[13]) {
                  case XFER_BLACKOUT :
                        dstate_setinfo("input.transfer.reason",   "Blackout");
                        break;
                  case XFER_LOW_VOLT :
                        dstate_setinfo("input.transfer.reason",
                              "Low Input Voltage");
                        break;
                  case XFER_HI_VOLT :
                        dstate_setinfo("input.transfer.reason",
                              "High Input Voltage");
                        break;
                  case NO_VALUE_YET :
                        dstate_setinfo("input.transfer.reason", 
                              "No transfer yet.");
                        break;
                  default :
                        upslogx(LOG_INFO,"Oneac: Unknown reason for UPS battery"
                        " transfer");
            }
            /* now update info for only the ON family of UPS*/

            if (strncmp(dstate_getinfo("ups.model"), FAMILY_ON, 2) == 0) {
                  dstate_setinfo("ups.load", "0%.2s",buffer+31);

                  /*run time left. */

/* I've commented this out until I either figure out how to convert
 * to an actual time, or I decide I can't do that and remove this code

                  if(buffer[10] == YES)
                        dstate_setinfo("batt.runtime", "0%.2s",buffer+33);
                  else dstate_setinfo("batt.runtime", "100");
*/

                  dstate_setinfo("input.voltage", "%.3s",buffer+35);
                  dstate_setinfo("input.voltage.minimum", "%.3s",buffer+38);
                  dstate_setinfo("input.voltage.maximum", "%.3s",buffer+41);
                  dstate_setinfo("output.voltage", "%.3s",buffer+44);
                  if (buffer[47] == YES) status_set("BOOST");
            }
            status_commit();
            dstate_dataok();
            ser_comm_good();
      }
}
void upsdrv_shutdown(void)
{
      ser_send(upsfd,"%s",SHUTDOWN);
}


void upsdrv_help(void)
{
      printf("\n---------\nNOTE:\n");
      printf("You must set the UPS interface card DIP switch to 9600BPS\n");
}

void upsdrv_makevartable(void)
{
      addvar(VAR_VALUE,"testtime",
            "Change battery test time from 2 minute default.");
}

void upsdrv_banner(void)
{
      printf("Network UPS Tools - Oneac EG/ON UPS driver %s (%s)\n\n", 
            DRV_VERSION, UPS_VERSION);
      experimental_driver = 1;      /*causes a warning to be printed*/
}

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

/*get the UPS in the right frame of mind*/
      
      ser_send(upsfd,"%s", COMMAND_END);
      sleep (1);
      ser_send(upsfd,"%s", COMMAND_END);
      sleep (1);
}

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

Generated by  Doxygen 1.6.0   Back to index