Augie Henriques wrote:
Hi.
I would like to use a UPS in our QNX 4 system. I would like to have
automatic shutdown, if the user doesn’t take any action when power is lost.
Are there any UPSs that have drivers/source demos that will do this?
Has anyone gotten the APC UPS Simple Signaling Daemon (SSD) to work in QNX
4?
Thanks
Augie
Here is my apcd for APC Smart UPS Series
---------------------------Makefile---------------------------------------------
Makefile for apcd
SHELL=/bin/sh
CFLAGS = -ms -Otax -w4
all: apcd.c Makefile
cc -o apcd $(INIT) $(CFLAGS) apcd.c
usemsg apcd apcd.c
chmod 700 apcd
rm *.o
---------------------------apcd.c-----------------------------------------------
/----------------------------------------------------------------------------/
#ifdef __USAGE
%C &
APC-Modul V1.01, (c) Copyright Joerg Hering 1984,2000
-d=[] using Device Prefix ; default /dev/ser1
-i=[] using APC polling intervall ; default 10 sec
-t=[] using Shutdown Temperatur critical ; default 55 C
-l=[] using Shutdown lower loading ; default 20 percent
-v verbose
Example: apcd -d=/dev/ser2 -i=5 -l=30 &
#endif
/----------------------------------------------------------------------------/
#define TRUE 1
#define FALSE 0
#define N_BYTES 20
#define UPS_CALIBRATION 0x01
#define UPS_SLEEPING 0x02
#define UPS_EXT_POWER 0x08
#define UPS_ON_BATTERIE 0x10
#define UPS_CRITICAL 0x40
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <process.h>
#include <signal.h>
#include <time.h>
#include <fcntl.h>
#include <termios.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/dev.h>
#include <sys/proxy.h>
#include <sys/kernel.h>
#include <sys/name.h>
#include <sys/proc_msg.h>
#include <sys/sched.h>
/--------------------------------------------------------------------------/
/* Vorwaertsreferenzen /
void main(int argc,char argv[]);
static int InitApc(char device);
static void StopApc(void);
static int ScanApc(void);
static void StateApc(void);
static void WriteToApc(int dev,char data);
static char ReadFromApc(int dev);
static void shutdown(void);
/--------------------------------------------------------------------------/
/ Variablen /
static pid_t timer_proxy;
static int dev,ApcStatus=0,ApcLoad=0,ApcTemp=0,verbose,poll,Load,Temp;
/--------------------------------------------------------------------------/
static void terminate(int signal)
{
switch(signal)
{
case SIGTERM:StopApc();
default:break;
}
exit(0);
}
/--------------------------------------------------------------------------*/
void main(int argc,char *argv[])
{
pid_t pid;
timer_t id;
int run,i,count,pending;
struct itimerspec timer;
struct sigevent event;
char name[10];
for(i=_SIGMIN;i<=_SIGMAX;++i)
if(i!=SIGTERM&&i!=SIGPWR)
signal(i,SIG_IGN);
signal(SIGTERM,&terminate);
signal(SIGPWR,&terminate);
strcpy(name,"/dev/ser1");
for(strcpy(name,"/dev/ser1"),Load=20,Temp=55,poll=10,verbose=FALSE,i=argc;i>1;i–)
{
if(!strnicmp("-D=",argv[i-1],3))
strcpy(name,argv[i-1]+3);
if(!strnicmp("-L=",argv[i-1],3))
Load=atoi(argv[i-1]+3);
if(!strnicmp("-T=",argv[i-1],3))
Temp=atoi(argv[i-1]+3);
if(!strnicmp("-V",argv[i-1],2))
verbose=TRUE;
if(!strnicmp("-I=",argv[i-1],3))
poll=atoi(argv[i-1]+3);
}
if((dev=InitApc(name))==-1)
{
syslog(LOG_INFO,“apcd: can’t open %s …”,name);
exit(-1);
}
if(!ScanApc())
{
StopApc();
syslog(LOG_INFO,“apcd: no APC-UPS found …”);
exit(-2);
}
// n sec Timer
timer_proxy=qnx_proxy_attach(0,0,0,-1);
event.sigev_signo=-timer_proxy;
id=timer_create(CLOCK_REALTIME,&event);
timer.it_value.tv_sec =1L; //nach 1 sec 1.Data
timer.it_value.tv_nsec =0L;
timer.it_interval.tv_sec =poll;
timer.it_interval.tv_nsec=0L;
timer_settime(id,0,&timer,NULL);
//…
// hier msg loop …
for(pending=run=TRUE,count=0;run;)
{
pid=Receive(0,NULL,0);
if(pid==-1)
continue;
//…
// n sec Timer
if(pid==timer_proxy)
{
StateApc();
Creceive(timer_proxy,NULL,0); // evtl. Timerueberlauf abfangen
continue;
}
Reply(pid,NULL,0);
//…
}
qnx_proxy_detach(timer_proxy);
timer_delete(id);
StopApc();
}
/--------------------------------------------------------------------------/
static void WriteToApc(int dev,char data)
{
tcflow(dev,TCOONHW);
write(dev,data,strlen(data));
tcdrain(dev);
tcflow(dev,TCOOFFHW);
}
/--------------------------------------------------------------------------/
static char ReadFromApc(int dev)
{
static char buffer[80];
int n;
tcflow(dev,TCIONHW);
n=dev_read(dev,&buffer,sizeof(buffer),sizeof(buffer),1,10,0,0);
if(n)
buffer[n-1]=’\0’;
tcflow(dev,TCIOFFHW);
return(n?&buffer:NULL);
}
/--------------------------------------------------------------------------/
static int InitApc(char device)
{
struct termios tty;
dev=open(device,O_RDWR);
if(dev!=-1)
{
if(tcgetattr(dev,&tty)!=-1)
{
cfsetospeed(&tty,(speed_t)2400);
cfsetispeed(&tty,(speed_t)2400);
tty.c_cflag=(tty.c_cflag&~CSIZE)|CS8;
tty.c_cflag&=~(PARENB|PARODD);
tty.c_cc[VMIN]=N_BYTES;
tcsetattr(dev,TCSANOW,&tty);
tcflush(dev,TCIOFLUSH);
}
}
return(dev);
}
/--------------------------------------------------------------------------/
static void StopApc(void)
{
close(dev);
}
/--------------------------------------------------------------------------*/
static int ScanApc(void)
{
int rc=FALSE;
char *p,sn[20],batstat[20],upsload[20],linefr[20],linevolt[20],outvolt[20],
temp[20],battvolt[20],battrepdate[20];
WriteToApc(dev,“Y”); // set to SMART Mode
if((p=ReadFromApc(dev))!=NULL)
if(!strncmp(p,“SM”,2))
{
rc=TRUE;
if(verbose)
{
WriteToApc(dev,“n”); // Seriennummer
if((p=ReadFromApc(dev))!=NULL)
strcpy(sn,p);
WriteToApc(dev,“f”); // BattStatus
if((p=ReadFromApc(dev))!=NULL)
strcpy(batstat,p);
WriteToApc(dev,“P”); // UPS load
if((p=ReadFromApc(dev))!=NULL)
strcpy(upsload,p);
WriteToApc(dev,“F”); // Line Frequency
if((p=ReadFromApc(dev))!=NULL)
strcpy(linefr,p);
WriteToApc(dev,“L”); // Line Voltage
if((p=ReadFromApc(dev))!=NULL)
strcpy(linevolt,p);
WriteToApc(dev,“O”); // Output Voltage
if((p=ReadFromApc(dev))!=NULL)
strcpy(outvolt,p);
WriteToApc(dev,“C”); // Temperatur
if((p=ReadFromApc(dev))!=NULL)
strcpy(temp,p);
WriteToApc(dev,“B”); // Batt Voltage
if((p=ReadFromApc(dev))!=NULL)
strcpy(battvolt,p);
WriteToApc(dev,“x”); // Batt Repl Date
if((p=ReadFromApc(dev))!=NULL)
strcpy(battrepdate,p);
syslog(LOG_INFO,“apcd: Sn: %s”,sn);
syslog(LOG_INFO,“apcd: Last Batt-Replacement: %s”,battrepdate);
syslog(LOG_INFO,“apcd: Batt State %3.1f %%”,atof(batstat));
syslog(LOG_INFO,“apcd: UPS Load %3.1f %%”,atof(upsload));
syslog(LOG_INFO,“apcd: Line Frequ %3.1f Hz”,atof(linefr));
syslog(LOG_INFO,“apcd: Line Voltage %3.1f V”,atof(linevolt));
syslog(LOG_INFO,“apcd: Outp Voltage %3.1f V”,atof(outvolt));
syslog(LOG_INFO,“apcd: Batt Voltage %3.1f V”,atof(battvolt));
syslog(LOG_INFO,“apcd: Inside Temp. %3.1f degree Celsius”,atof(temp));
}
}
return(rc);
}
/--------------------------------------------------------------------------/
static void StateApc(void)
{
int tmpStatus,tmpLoad,tmpTemp;
char *p;
WriteToApc(dev,“C”); // Temperatur
if((p=ReadFromApc(dev))!=NULL)
if(*p!=’!’&&*p!=’$’&&*p!=’%’&&*p!=’+’)
tmpTemp=atoi(p);
WriteToApc(dev,“f”); // BattStatus
if((p=ReadFromApc(dev))!=NULL)
if(*p!=’!’&&*p!=’$’&&*p!=’%’&&*p!=’+’)
tmpLoad=atoi(p);
if(tmpTemp!=ApcTemp)
{
ApcTemp=tmpTemp;
if(verbose)
syslog(LOG_INFO,“apcd: UPS temp %d degree Celsius …”,ApcTemp);
}
if(tmpLoad!=ApcLoad)
{
ApcLoad=tmpLoad;
if(verbose)
syslog(LOG_INFO,“apcd: UPS load %d %% …”,ApcLoad);
}
WriteToApc(dev,“Q”); // Statusbyte
if((p=ReadFromApc(dev))!=NULL)
if(p!=’!’&&p!=’$’&&p!=’%’&&p!=’+’)
{
sscanf(p,"%X",&tmpStatus);
if(tmpStatus!=ApcStatus)
{
ApcStatus=tmpStatus;
if(ApcStatus&UPS_CALIBRATION)
syslog(LOG_INFO,“apcd: UPS is in calibration …”);
if(ApcStatus&UPS_EXT_POWER)
syslog(LOG_INFO,“apcd: UPS has external power …”);
if(ApcStatus&UPS_ON_BATTERIE)
syslog(LOG_WARNING,“apcd: UPS is running on battery …”);
if(ApcStatus&UPS_CRITICAL)
syslog(LOG_WARNING,“apcd: UPS battery critical !!!”);
}
}
if((ApcStatus&UPS_CRITICAL&&ApcStatus&UPS_ON_BATTERIE)||
((ApcStatus&UPS_ON_BATTERIE)&&(ApcLoad<Load||ApcTemp>Temp)))
{
syslog(LOG_WARNING,“apcd: shutting down the APC and System !!!”);
WriteToApc(dev,“S”); // Power mit Rueckkehr
sleep(2);
shutdown();
}
}
/--------------------------------------------------------------------------/
static void shutdown(void)
{
struct sched_param param;
sigset_t bits;
union
{
struct _proc_shutdown s;
struct _proc_shutdown_reply r;
}msg;
bits=~0L;
sigprocmask(SIG_BLOCK,&bits,0);
msg.s.type=_PROC_SHUTDOWN;
msg.s.signum=SIGPWR;
Send(PROC_PID,&msg.s,&msg.r,sizeof(msg.s),sizeof(msg.r));
sleep(2);
param.sched_priority=PRIO_FIFO_MAX;
sched_setscheduler(0,SCHED_FIFO,¶m);
}
/--------------------------------------------------------------------------/
--------------------------------end----------------------------------------------
–
Joerg Hering
e-mail: jhering@avecs-bergen.de
Avecs-Bergen@t-online.de
privat: hering.ruegen@t-online.de
Avecs Bergen GmbH
Billrothstrasse 11a
D-18528 Bergen auf Ruegen
Tel: +49 3838 2119101
Fax: +49 3838 2119105
URL: http://www.avecs-bergen.de