Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Jan 1997 21:16:32 -0600 (CST)
From:      "Gil Kloepfer Jr." <gil@limbic.gc2.kloepfer.org>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   misc/2617: upsmon - UPS monitor utility submission
Message-ID:  <199701300316.VAA07446@limbic.gc2.kloepfer.org>
Resent-Message-ID: <199701300320.TAA14923@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         2617
>Category:       misc
>Synopsis:       Utility submission - upsmon - UPS monitor program
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan 29 19:20:02 PST 1997
>Last-Modified:
>Originator:     Gil Kloepfer Jr.
>Organization:
None
>Release:        FreeBSD 2.1-STABLE i386
>Environment:

	FreeBSD 2.1.5-RELEASE (and likely all 2.*.* versions)
	TrippLite UPS system with LAN 2.1 interface

>Description:

	Utility provides the capability to monitor the UPS and send
	users/administrators status messgages as well as semi-gracefully
	shut the system down when battery power is low.

>How-To-Repeat:

	N/A

>Fix:
	
	The following is a shar of the code, makefile, and manual page,
	and a message I originally sent to Jordan Hubbard originally
	submitting the program.  He recommended I submit it in this
	way with a followup e-mail to the -hackers list.

	See the manual page for electrical details.

	Yes, I know it isn't as flexible as it should be as far as
	support for other UPS systems.  This is a good start though, and
	if someone sends me the specs for other UPS systems, I may be able
	to write the code and cabling for that UPS, and I'll build up
	the code to something more extensible.

   To: jkh@freebsd.org
   From: Gil Kloepfer Jr. <gil@gc2.kloepfer.org>
   Date: Mon, 27 Jan 1997 21:35:06 -0600 (CST)
   Subject: Software submission: upsmon.c
   
   Jordan-
   
   I'm not sure what the best way to submit software to the FreeBSD project
   is, and you're the release coordinator...  I figure you'll probably
   know who should look at this.
   
   That said, this may or may not be useful for the project.  I seem to
   recall linux has something called powerd that allows UPS systems to
   be monitored.  I had some of my own ideas in mind and decided to write
   a UPS monitor program for my Tripp Lite UPS without looking at any of
   it.  I could have wasted my time...  In any case, I wrote a man page
   and a makefile for it.  I thought someone may find it useful.
   
   Please let me know whether or not this makes sense to put into FreeBSD
   in some form.  Constructive comments welcome, of course!
   
   I included the whole thing as a shar file since it wasn't very big...
   
   ---
   Gil Kloepfer
   gil@gc2.kloepfer.org
   http://www.gc2.kloepfer.org/

-- Cut Here --
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	upsmon.c
#	upsmon.8
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
X#
X# Makefile for upsmon
X#
X# Copyright (c) 1997 Gilbert C. Kloepfer, Jr.
X# All rights reserved.
X#
X# Redistribution and use in source and binary forms, with or without
X# modification, are permitted provided that the following conditions
X# are met:
X#
X# 1. Redistributions of source code must retain the above copyright
X#    notice, this list of conditions and the following disclaimer.
X#
X# 2. Redistributions in binary form must reproduce the above copyright
X#    notice, this list of conditions and the following disclaimer in the
X#    documentation and/or other materials provided with the distribution.
X#
X# 3. All advertising materials mentioning features or use of this software
X#    in products other than the FreeBSD operating system must display
X#    the following acknowledgement:
X#
X#    This product includes software developed by Gilbert C. Kloepfer, Jr.
X#
X# 4. The name of the author may not be used to endorse or promote products
X#    derived from this software without specific prior written permission.
X#
X# THIS SOFTWARE IS PROVIDED BY GILBERT C. KLOEPFER, JR. (THE AUTHOR)
X# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
X# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
X# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
X# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
X# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
X# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
X# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
X# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
X# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
X# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X#
X#	$Id: Makefile,v 1.1 1997/01/28 03:20:55 gil Exp $
X#
X
XPROG=		upsmon
XSRCS=		upsmon.c
XMAN8=		upsmon.8
XNOSHARED=	true
XBINDIR=		/sbin
X
X.include <bsd.prog.mk>
END-of-Makefile
echo x - upsmon.c
sed 's/^X//' >upsmon.c << 'END-of-upsmon.c'
X/*
X * Copyright (c) 1997 Gilbert C. Kloepfer, Jr.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X *
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X *
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * 3. All advertising materials mentioning features or use of this software
X *    in products other than the FreeBSD operating system must display
X *    the following acknowledgement:
X *
X *    This product includes software developed by Gilbert C. Kloepfer, Jr.
X *
X * 4. The name of the author may not be used to endorse or promote products
X *    derived from this software without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY GILBERT C. KLOEPFER, JR. (THE AUTHOR)
X * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
X * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
X * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
X * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
X * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
X * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
X * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
X * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
X * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
X * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X *
X *	$Id: upsmon.c,v 1.2 1997/01/28 03:26:38 gil Exp $
X *
X */
X
X#include <stdio.h>
X#include <unistd.h>
X#include <stdlib.h>
X#include <fcntl.h>
X#include <termios.h>
X#include <sys/ioctl.h>
X#include <sys/time.h>
X#include <syslog.h>
X#include <stdarg.h>
X#include <signal.h>
X
Xint get_serstat(int);
Xvoid delay(int), sys_shutdown(), runit(char *,...);
X
X#define	STATE_ONLINE	1
X#define	STATE_TRANSBATT	2
X#define	STATE_BATTERY	3
X#define	STATE_TRANSLINE	4
X#define	STATE_LOWBATT	5
X
X#define	ON		1
X#define	OFF		0
X#define	forever		for(;;)
X
X#define	set_dtr(FD,STA)	{ int bits = TIOCM_DTR; \
X			  if (STA == ON) \
X				(void)ioctl(FD, TIOCMBIS, &bits); \
X			  else \
X				(void)ioctl(FD, TIOCMBIC, &bits); \
X			}
X
X#define	set_rts(FD,STA)	{ int bits = TIOCM_RTS; \
X			  if (STA == ON) \
X				(void)ioctl(FD, TIOCMBIS, &bits); \
X			  else \
X				(void)ioctl(FD, TIOCMBIC, &bits); \
X			}
X
X#define	set_td(FD,STA)	{ if (STA == ON) \
X				(void)ioctl(FD, TIOCSBRK, 0); \
X			  else \
X				(void)ioctl(FD, TIOCCBRK, 0); \
X			}
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int			fd, savstat, statemach;
X	char			*ctltty;
X	struct termios		tioblk;
X
X
X	if (argc != 2 || *argv[1] == '\0') {
X		(void)fprintf(stderr, "usage: %s {tty port}\n", argv[0]);
X		exit(1);
X	}
X	ctltty = argv[1];
X
X	openlog("upsmon", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);
X
X	fd = open(ctltty, O_RDWR|O_NONBLOCK|O_EXCL);
X	if (fd < 0) {
X		syslog(LOG_ALERT, "cannot open %s: %m (aborting)", ctltty);
X		exit(2);
X	}
X
X	/*
X	 * Set the tty port in raw mode and turn off any flow control or
X	 * other modem signalling that may interfere with the monitor's
X	 * ability to directly control the tty port's control lines
X	 */
X
X	if (tcgetattr(fd, &tioblk) < 0) {
X		syslog(LOG_ALERT, "cannot tcgetattr %s: %m (aborting)", ctltty);
X		exit(2);
X	}
X
X	cfmakeraw(&tioblk);
X	tioblk.c_cflag |= CLOCAL;
X	tioblk.c_cflag &= ~(CRTS_IFLOW | CDTR_IFLOW |
X	                    CCTS_OFLOW | CDSR_OFLOW | CCAR_OFLOW);
X
X	if (tcsetattr(fd, TCSAFLUSH, &tioblk) < 0) {
X		syslog(LOG_ALERT, "cannot tcgetattr %s: %m (aborting)", ctltty);
X		exit(2);
X	}
X
X	/*
X	 * Everything passing OK, we should now make ourself a daemon
X	 */
X
X	if (daemon(0,0) < 0) {
X		syslog(LOG_ALERT, "daemon library call failed: %m (aborting)");
X		exit(2);
X	}
X
X	/*
X	 *
X	 * Quick review of control signals:
X	 *
X	 * CTS = Common for line fail relay.  Common also feeds emitter
X	 *       of low battery NPN phototransistor
X	 *
X	 * TD  = anode of inverter cutoff LED (usually off (-))
X	 *
X	 * RTS = Positive pull-up supply for DCD, NO input of line fail
X	 *       relay.  Almost always ON (+) except when testing line fail
X	 *       relay reading integrity.
X	 *
X	 * GND = cathode of inverter cutoff LED
X	 *
X	 * DTR = NC input of line fail relay.  Usually OFF (-) except when
X	 *       testing line fail relay signal integrity (pulsed)
X	 *
X	 * DCD = Follows state of line fail relay.  Line fail relay signal.
X	 *       Since low battery is only valid on line fail closed, we
X	 *       can pulse DTR on battery power to test this signal.
X	 */
X
X	/*
X	 * Initial check to see if we are communicating with the UPS.
X	 *
X	 * A good basic check is to see that DCD is asserted (+) when
X	 * RTS is asserted and vice versa.  We can also simulate some
X	 * activity on some of the signal lines to make sure that the
X	 * cable is functioning.
X	 *
X	 * If the cable is bad, or we're already on battery power for
X	 * some reason, print a message explaining the problem and
X	 * exit the monitor.  We don't want to monitor a system
X	 * already on battery since that would be a truly odd
X	 * situation, in addition to being a possible cable fault
X	 * that could bring down a bunch of systems already running.
X	 */
X
X	set_td(fd, OFF);
X	set_rts(fd, ON);
X	set_dtr(fd, OFF);
X
X	delay(10);
X	savstat = get_serstat(fd);
X	if (!(savstat & TIOCM_CTS)) {
X		syslog(LOG_ALERT, "CTS not on - Bad cable connection or already on battery power (aborting)");
X		exit(2);
X	}
X
X	if (!(savstat & TIOCM_CAR)) {
X		syslog(LOG_ALERT, "DCD not on - Probable bad UPS monitor cable (aborting)");
X		exit(2);
X	}
X
X	set_rts(fd, OFF);
X	delay(10);
X	if (get_serstat(fd) & TIOCM_CTS) {
X		syslog(LOG_ALERT, "CTS not off - Bad cable connection (aborting)");
X		exit(2);
X	}
X
X	syslog(LOG_NOTICE, "UPS monitoring started");
X
X	statemach = STATE_ONLINE;
X
X	forever {
X		/*
X		 * Reset monitoring lines to initial values
X		 *
X		 * TD  = off (-)
X		 * DTR = off (-)
X		 * RTS = on (+)
X		 */
X
X		set_td(fd, OFF);
X		set_dtr(fd, OFF);
X		set_rts(fd, ON);
X		delay(10);
X
X		switch(statemach) {
X		case STATE_ONLINE:  /* On AC line power */
X			savstat = get_serstat(fd);
X			if (!(savstat & TIOCM_CTS)) {
X				delay(500);
X				if (get_serstat(fd) & TIOCM_CTS)
X					break;
X				statemach = STATE_TRANSBATT;
X				break;
X			}
X
X			if (!(savstat & TIOCM_CAR)) {
X				syslog(LOG_ALERT, "DCD not on in Online state - Possible cable fault (aborting)");
X				exit(2);
X			}
X
X			delay(1000);
X			break;
X
X		case STATE_TRANSBATT:  /* Transition to battery power */
X			set_dtr(fd, ON);
X			delay(10);
X			if (!(get_serstat(fd) & TIOCM_CTS)) {
X				syslog(LOG_ALERT, "Battery Transition CTS sanity check identified cable fault (aborting)");
X				exit(2);
X			}
X			set_dtr(fd, OFF);
X			syslog(LOG_CRIT, "On battery power");
X			delay(1000);
X			statemach = STATE_BATTERY;
X			break;
X
X		case STATE_BATTERY:  /* On battery power */
X			if (get_serstat(fd) & TIOCM_CTS) {
X				delay(500);
X				if (get_serstat(fd) & TIOCM_CTS) {
X					statemach = STATE_TRANSLINE;
X					break;
X				}
X			}
X
X			/*
X			 * Check for DCD off.  This means that battery
X			 * power is low.  Note the ridiculous number of
X			 * sanity checks is a very paranoid precaution
X			 * against unnecessary shutdowns.  There'd be nothing
X			 * worse than having a battery backup system which
X			 * basically shutdown everything without reason!
X			 *
X			 * We could identify cable faults here, but I'm
X			 * going to assume transient failure and be a little
X			 * lazy.
X			 */
X
X			if (!(get_serstat(fd) & TIOCM_CAR)) {
X				delay(500);
X				if (get_serstat(fd) & TIOCM_CAR)
X					break;
X				set_dtr(fd, ON);
X				delay(50);
X				if (get_serstat(fd) & TIOCM_CAR) {
X					set_dtr(fd, OFF);
X					if (!(get_serstat(fd) & TIOCM_CAR)) {
X						statemach = STATE_LOWBATT;
X						break;
X					}
X				}
X			}
X
X			/*
X			 * We're gonna do a little cable check here though.
X			 * Briefly toggle DTR to see if CTS follows it.  If
X			 * it doesn't, it means the cable fell out, because
X			 * even if a race condition put the UPS back online,
X			 * RTS is still ON so it wouldn't make a difference.
X			 * We will take another reading a few ms apart on
X			 * a failure to make sure the bad reading isn't
X			 * due to relay contact bounce.
X			 *
X			 * It would be nice to do something more intelligent
X			 * than just aborting the monitor on a cable fault,
X			 * but if there IS a cable fault, then we can't be
X			 * positively sure that the transition to battery
X			 * power wasn't a manifestation of a bad cable also.
X			 */
X
X			set_dtr(fd, ON);
X			delay(10);
X			if (!(get_serstat(fd) & TIOCM_CTS)) {
X				delay(10);
X				if (!(get_serstat(fd) & TIOCM_CTS)) {
X					syslog(LOG_ALERT, "Battery mode cable check noted cable fault (aborting)\n");
X					exit(2);
X				}
X			}
X			set_dtr(fd, OFF);
X
X			delay(1000);
X			break;
X
X		case STATE_TRANSLINE:  /* Transition back to AC line power */
X			syslog(LOG_WARNING, "AC Power restored");
X			delay(1000);
X			statemach = STATE_ONLINE;
X			break;
X
X		case STATE_LOWBATT:  /* Low battery -- Shut down the system */
X			syslog(LOG_EMERG, "UPS low battery power detected - Shutting down the system!!");
X			delay(2000);
X			sys_shutdown();
X			set_td(fd, ON);
X			delay(5000);
X
X			/*
X			 * If we get here, it means the power did NOT shut
X			 * off.  This could mean the AC power got restored
X			 * while we were shutting down the system.  It could
X			 * also mean there is a cable or UPS problem.
X			 *
X			 * If the AC power looks like it came back, reboot
X			 * the system.  If it looks like a cable problem,
X			 * halt the system and wait for a manual
X			 * reboot.
X			 */
X
X			set_dtr(fd, OFF);
X			set_rts(fd, ON);
X			if (get_serstat(fd) & TIOCM_CTS)
X				runit("/sbin/reboot", NULL);
X			else
X				runit("/sbin/halt", NULL);
X			break;
X
X			/* If we get here, give up...just die... */
X
X			exit(2);
X		}
X	}
X
X	/* NOTREACHED */
X}
X
X
Xint
Xget_serstat(fd)
Xint fd;
X{
X	int		ttsigs;
X
X	if (ioctl(fd, TIOCMGET, &ttsigs) < 0) {
X		syslog(LOG_ALERT, "get_serstat TIOCMGET failed - %m (aborting)");
X		exit(2);
X	}
X
X	return(ttsigs);
X}
X
Xvoid
Xdelay(ms_time)
Xint ms_time;
X{
X	int		ret;
X	struct timeval	sto;
X
X	sto.tv_sec = ms_time / 1000;
X	sto.tv_usec = (ms_time % 1000) * 1000;
X	ret = select(0, NULL, NULL, NULL, &sto);
X	if (ret < 0) {
X		syslog(LOG_ALERT, "select failed in delay() - %m (aborting)");
X		exit(2);
X	}
X}
X
X
X/*
X * This shutdown routine is not the best nor is it the safest, but it only
X * gets called under the most extreme of circumstances.
X *
X * The reason we shut the system down in this way is because it is extremely
X * hardware-dependent to shut down the power as part of the boot system
X * call, as well as requiring some tricky modifications to the kernel code.
X * Rather than embed this kind of magic in the kernel, we will perform as
X * graceful a shutdown as possible under the circumstances, with the
X * understanding that this should not get called unless we are ready to lose
X * AC power and would otherwise trash the system in some unpredictable way.
X */
X
Xvoid
Xsys_shutdown()
X{
X	(void)kill(1,  SIGTSTP);  /* Tell init to stop respawning gettys */
X	delay(500);
X	(void)kill(-1, SIGTERM);  /* Send termination signal to all */
X	delay(5000);
X	(void)kill(-1, SIGTERM);  /* Send it again, just to make sure */
X	delay(2000);
X	(void)kill(-1, SIGHUP);   /* Force interactive users off */
X	delay(2000);
X	(void)kill(-1, SIGKILL);  /* Forcefully kick everything else */
X	delay(5000);
X
X	runit("/sbin/umount", "-a", NULL);  /* Unmount all disks */
X
X	sync();  sync();  sync();  /* Sync root fs */
X	delay(500);
X
X	/* System is shut down for all cases and purposes */
X}
X
X
X/*
X * This is an alternative to the system(3) library routine that doesn't
X * invoke the shell for each command.  This is preferable under the
X * circumstances in which it will get run -- namely to perform
X * housekeeping tasks before killing the system
X *
X * Number of args limited to 50.  It's quick and dirty.
X */
X
Xvoid
Xrunit(char *prog, ...)
X{
X	int		narg = 0, status;
X	va_list		ap;
X	char		*argvec[51], *arg;
X
X	argvec[narg++] = prog;
X
X	va_start(ap, prog);
X	arg = va_arg(ap, char *);
X	while (arg) {
X		argvec[narg++] = arg;
X		arg = va_arg(ap, char *);
X	}
X	argvec[narg++] = NULL;
X
X	va_end(ap);
X
X	switch(fork()) {
X	case -1:  /* Error */
X		syslog(LOG_ALERT, "cannot fork %s in run(): %m", prog);
X		return;
X
X	case 0:  /* Child */
X		(void)execv(prog, argvec);
X		exit(1);
X
X	default:  /* Parent */
X		(void)wait(&status);
X	}
X
X	return;
X}
END-of-upsmon.c
echo x - upsmon.8
sed 's/^X//' >upsmon.8 << 'END-of-upsmon.8'
X.\" Copyright (c) 1997 Gilbert C. Kloepfer, Jr.
X.\" All rights reserved.
X.\"
X.\" Redistribution and use in source and binary forms, with or without
X.\" modification, are permitted provided that the following conditions
X.\" are met:
X.\"
X.\" 1. Redistributions of source code must retain the above copyright
X.\"    notice, this list of conditions and the following disclaimer.
X.\"
X.\" 2. Redistributions in binary form must reproduce the above copyright
X.\"    notice, this list of conditions and the following disclaimer in the
X.\"    documentation and/or other materials provided with the distribution.
X.\"
X.\" 3. All advertising materials mentioning features or use of this software
X.\"    in products other than the FreeBSD operating system must display
X.\"    the following acknowledgement:
X.\"
X.\"    This product includes software developed by Gilbert C. Kloepfer, Jr.
X.\"
X.\" 4. The name of the author may not be used to endorse or promote products
X.\"    derived from this software without specific prior written permission.
X.\"
X.\" THIS SOFTWARE IS PROVIDED BY GILBERT C. KLOEPFER, JR. (THE AUTHOR)
X.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
X.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
X.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
X.\" AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
X.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
X.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
X.\" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
X.\" OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
X.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
X.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X.\"
X.\" $Id: upsmon.8,v 1.1 1997/01/28 03:20:55 gil Exp $
X.\"
X.Dd January 27, 1997
X.Dt UPSMON 8
X.Os BSD
X.Sh NAME
X.Nm upsmon
X.Nd monitor uninterruptable power systems (UPS)
X.Sh SYNOPSIS
X.Nm upsmon
X.Ar tty_device
X.Sh DESCRIPTION
XThe
X.Nm upsmon
Xutility monitors the status of a battery-powered Uninterruptable
XPower System (UPS) and notifies system users of power-related alerts
Xgenerated by the UPS when available.  When batteries are dangerously
Xdrained (as indicated by the UPS),
X.Nm upsmon
Xwill also automatically bring the system to a quiescent state and
Xinterrupt backup power.
X.Pp
X.Nm upsmon
Xutilizes (abuses?) a serial
X.Xr tty 4
Xdevice in such a manner as to be able to examine and manipulate
Xindividual bits on the UPS status/control interface.  The serial
X.Xr tty 4
Xdevice was used due to its low cost and relatively standard device
Xcontrol functions.
X.Pp
X.Nm upsmon
Xmakes checks of the UPS monitor interface cable to assure that the
Xsignals it receives are valid in order to avoid spirious system
Xshutdowns and false warnings.
X.Sh INTERFACE DESCRIPTION
XThe
X.Ar Tripp Lite LAN 2.1
Xinterface was used in the design of this software.  Serial I/O
Xconnections were made as follows:
X.Pp
X.Bd -literal -offset left
X
X   RS232       Tripp Lite
XSignal Name    LAN 2.1 Sig/Pin       Description
X
X    CTS        Common       (1)   Common relay &
X                                  Low Battery NPN collector
X
X    TxD        Inv Shut +   (2)   Inverter shutdown LED anode
X
X    RTS        Line Fail    (3)   Disconnected from Common when
X               Relay NO           AC line fails or UPS power is off.
X                                  This signal is also used by this
X                                  application to provide positive
X                                  pull-up power for the low battery
X                                  phototransistor.
X
X    GND        Inv Shut -   (4)   Inverter shutdown LED cathode
X
X    DTR        Line Fail    (5)   Connected to Common when AC line
X               Relay NC           fails or UPS power is off
X
X    DCD        Low Battery  (6)   Emitter of NPN phototransistor
X                                  conducts to Common when on
X                                  battery power and battery is low
X
X    RxD, DSR   (no connection)
X
XCable requires 6.2K ohm resistor between pins #3 and #6 (RS232 RTS
Xand DCD).  This acts as a pull-up resistor for the low battery
Xphototransistor output.
X
X.Ed
X.Sh CAVEATS
X.Nm upsmon
Xwas designed to function with the 
X.Ar Tripp Lite LAN 2.1
Xspecification.  However, porting (via hardware or modification of
Xthis software) can be performed to make this function with other
Xvendors' UPS systems.  Different vendors support different levels
Xof functionality on their status ports.
X.Pp
XEmergency system shutdown before poweroff is handled as well
Xas possible by a user-mode program.  Since embedding
Xhardware-specific kernel code to perform the poweroff function
Xwould make this software more sloppy than it already is, a
Xcompromise was made when shutting the system down.  Before triggering
Xthe
X.Ar inverter-off
Xfunction, all
X.Xr getty 8
Xrespawns are stopped by sending a SIGTSTP to
X.Xr init 8 ,
Xall user processes are killed much like is done in
X.Xr shutdown 8 ,
Xall filesystems (except root) are unmounted by performing a
X.Xr umount 8
Xcommand, the root filesystem is flushed through
X.Xr sync 2 ,
Xand power is then interrupted.  This is better than shutting off the
Xpower with all the filesystems mounted and the system active, but
Xisn't as good as shutting it down with the standard system shutdown
Xcommands.
X.Pp
XBecause of the previous paragraph,
X.Nm upsmon
Xmust be compiled static (no shared libraries), and must reside
Xsomewhere on the root filesystem (probably /sbin).
X.Sh SEE ALSO
X.Xr tty 4 ,
X.Xr init 8 ,
X.Xr shutdown 8 ,
X.Xr umount 8
X.Sh BUGS
XThe tty device interface was never meant to be used in this way.
X.Pp
XShutdown is less than perfect, and could theoretically corrupt a
Xroot filesystem under extremely rare circumstances.
X.Pp
XThere is no protection against rabid UPS or serial port failures.
X.Sh AUTHOR
XGil Kloepfer, Jr., ngk@gc2.kloepfer.org
END-of-upsmon.8
exit


>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199701300316.VAA07446>