download oneac.c
Language: C
License: GPL
Copyright: (C) 2003 by Eric Lawson
LOC: 194
Project Info
nut
Server: Debian-SVN
Type: svn
...an‑SVN\n\nut\trunk\drivers\
   al175.c
   al175.h
   apc-hid.c
   apc-hid.h
   apccmib.h
   apcsmart.c
   apcsmart.h
   bcmxcp.c
   bcmxcp.h
   bcmxcp_io.h
   bcmxcp_ser.c
   bcmxcp_usb.c
   belkin-hid.c
   belkin-hid.h
   belkin.c
   belkin.h
   belkinunv.c
   belkinunv.h
   bestfcom.c
   bestfcom.h
   bestuferrups.c
   bestuferrups.h
   bestups.c
   bestups.h
   cpsups.c
   cpsups.h
   cyberpower.c
   cyberpower.h
   dstate-hal.c
   dstate-hal.h
   dstate.c
   dstate.h
   dummy-ups.c
   dummy-ups.h
   energizerups.c
   etapro.c
   etapro.h
   everups.c
   everups.h
   explore-hid.c
   explore-hid.h
   gamatronic.c
   gamatronic.h
   genericups.c
   genericups.h
   hidparser.c
   hidparser.h
   hidtypes.h
   ietfmib.h
   isbmex.c
   isbmex.h
   libhid.c
   libhid.h
   libshut.c
   libshut.h
   libusb.c
   libusb.h
   liebert.c
   liebert.h
   main-hal.c
   main-hal.h
   main.c
   main.h
   Makefile.am
   masterguard.c
   masterguard.h
   megatec.c
   megatec.h
   megatec_usb.c
   metasys.c
   metasys.h
   mge-hid.c
   mge-hid.h
   mge-shut.c
   mge-shut.h
   mge-utalk.c
   mge-utalk.h
   mgemib.h
   netvisionmib.h
   nitram.c
   nitram.h
   nut_usb.c
   nut_usb.h
   oneac.c
   oneac.h
   optiups.c
   optiups.h
   powercom.c
   powercom.h
   powerpanel.c
   powerpanel.h
   pwmib.h
   rhino.c
   safenet.c
   safenet.h
   serial.c
   serial.h
   skel.c
   snmp-ups.c
   snmp-ups.h
   solis.c
   solis.h
   tripplite-hid.c
   tripplite-hid.h
   tripplite.c
   tripplite.h
   tripplite_usb.c
   tripplitesu.c
   tripplitesu.h
   upscode2.c
   upscode2.h
   upsdrvctl.c
   usbhid-ups.c
   usbhid-ups.h
   victronups.c
   victronups.h

/*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);
}

About Koders | Resources | Downloads | Support | Black Duck | Submit Project | Terms of Service | DMCA | Privacy Policy | Site Map| Contact Us