nut-debian/drivers/rhino.c

790 lines
19 KiB
C
Raw Normal View History

2010-03-26 01:20:59 +02:00
/* rhino.c - driver for Microsol Rhino UPS hardware
Copyright (C) 2004 Silvino B. Magalhães <sbm2yk@gmail.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
2004/11/13 - Version 0.10 - Initial release
2005/07/07 - Version 0.20 - Initial rhino commands tests
2005/10/25 - Version 0.30 - Operational-1 release
2005/10/26 - Version 0.40 - Operational-2 release
2005/11/29 - Version 0.50 - rhino commands release
2022-07-10 10:23:45 +03:00
2010-03-26 01:20:59 +02:00
http://www.microsol.com.br
*/
2022-07-10 10:23:45 +03:00
#include "config.h" /* must be the first header */
2010-03-26 01:20:59 +02:00
#include <stdio.h>
#include "main.h"
#include "serial.h"
2022-07-10 10:23:45 +03:00
#include "nut_float.h"
2010-03-26 01:20:59 +02:00
#include "timehead.h"
#define DRIVER_NAME "Microsol Rhino UPS driver"
2022-07-10 10:23:45 +03:00
#define DRIVER_VERSION "0.52"
2010-03-26 01:20:59 +02:00
/* driver description structure */
upsdrv_info_t upsdrv_info = {
DRIVER_NAME,
DRIVER_VERSION,
"Silvino B. Magalhaes <sbm2yk@gmail.com>",
DRV_STABLE,
{ NULL }
};
#define UPSDELAY 500 /* 0.5 ms delay */
typedef int bool_t;
#define false 0
#define true 1
/* rhino commands */
#define CMD_INON 0x0001
#define CMD_INOFF 0x0002
#define CMD_SHUT 0x0004
#define CMD_OUTON 0x0003
#define CMD_OUTOFF 0x0004
#define CMD_PASSON 0x0005
#define CMD_PASSOFF 0x0006
#define CMD_UPSCONT 0x0053
2011-06-01 23:31:49 +03:00
/* xoff - xon protocol */
#define _SOH = 0x01; /* start of header */
#define _EOT = 0x04; /* end of transmission */
#define _ACK = 0x06; /* acknoledge (positive) */
#define _DLE = 0x10; /* data link escape */
#define _XOn = 0x11; /* transmit on */
#define _XOff = 0x13; /* transmit off */
#define _NAK = 0x15; /* negative acknoledge */
#define _SYN = 0x16; /* synchronous idle */
#define _CAN = 0x18; /* cancel */
2010-03-26 01:20:59 +02:00
static int const pacsize = 37; /* size of receive data package */
/* autonomy calcule */
2011-06-01 23:31:49 +03:00
static double const AmpH = 40; /* Amperes-hora da bateria */
static double const VbatMin = 126; /* Tensão mínina das baterias */
static double const VbatNom = 144; /* Tensão nominal das baterias */
static double const FM = 0.32; /* Fator multiplicativo de correção da autonomia */
static double const FA = -2; /* Fator aditivo de correção da autonomia */
static double const ConstInt = 250; /* Consumo interno sem o carregador */
static double const Vin = 220; /* Tensão de entrada */
2010-03-26 01:20:59 +02:00
static int Day, Month, Year;
static int dian=0, mesn=0, anon=0, weekn=0;
static int ihour,imin, isec;
/* unsigned char DaysOnWeek; */
/* char seman[4]; */
/* int FExpansaoBateria; */
2011-06-01 23:31:49 +03:00
/* internal variables */
/* package handshake variables */
2010-03-26 01:20:59 +02:00
/* int ContadorEstouro; */
static bool_t detected;
static bool_t SourceFail, Out110, RedeAnterior, OcorrenciaDeFalha;
static bool_t RetornoDaRede, SuperAquecimento, SuperAquecimentoAnterior;
static bool_t OverCharge, OldOverCharge, CriticBatt, OldCritBatt;
static bool_t Flag_inversor, BypassOn, InputOn, OutputOn;
static bool_t LowBatt, oldInversorOn;
/* data vetor from received and configuration data package - not used yet
unsigned char Dados[ 161 ]; */
/* identification group */
static int RhinoModel; /*, imodel; */
static int PotenciaNominal, PowerFactor;
/* input group */
static double AppPowerIn, UtilPowerIn, InFreq, InCurrent;
static double LimInfEntrada, LimSupEntrada, ValorNominalEntrada;
static int FatorPotEntrada;
/* output group */
static double OutVoltage, InVoltage, OutCurrent, AppPowerOut;
static double UtilPowerOut, OutFreq, LimInfSaida, LimSupSaida, ValorNominalSaida;
static int FatorPotSaida;
/* battery group */
static int Autonomy, Waiting;
static double BattVoltage, Temperature, LimInfBattSrc, LimSupBattSrc;
static double LimInfBattInv, LimSupBattInv, BattNonValue;
/* general group */
static int BoostVolt, Rendimento;
/* status group */
static unsigned char StatusEntrada, StatusSaida, StatusBateria;
/* events group */
static unsigned char EventosRede, EventosSaida, EventosBateria;
2011-06-01 23:31:49 +03:00
/* Grupo de Programação */
2010-03-26 01:20:59 +02:00
/* Methods */
2011-01-26 11:35:08 +02:00
static void ScanReceivePack(void);
2010-03-26 01:20:59 +02:00
static int AutonomyCalc( int );
2022-07-10 10:23:45 +03:00
static void CommReceive(const unsigned char*, ssize_t);
2011-01-26 11:35:08 +02:00
static void getbaseinfo(void);
static void getupdateinfo(void);
2022-07-10 10:23:45 +03:00
2010-03-26 01:20:59 +02:00
static unsigned char RecPack[37];
/* comment on english language */
/* #define PORTUGUESE */
/* The following Portuguese strings are in UTF-8. */
#ifdef PORTUGUESE
#define M_UNKN "Modêlo rhino desconhecido\n"
#define NO_RHINO "Rhino não detectado! abortando ...\n"
#define UPS_DATE "Data no UPS %4d/%02d/%02d\n"
#define SYS_DATE "Data do Sistema %4d/%02d/%02d dia da semana %s\n"
#define ERR_PACK "Pacote errado\n"
#define NO_EVENT "Não há eventos\n"
#define UPS_TIME "Hora interna UPS %0d:%02d:%02d\n"
#else
#define M_UNKN "Unknown rhino model\n"
#define NO_RHINO "Rhino not detected! aborting ...\n"
#define UPS_DATE "UPS Date %4d/%02d/%02d\n"
#define SYS_DATE "System Date %4d/%02d/%02d day of week %s\n"
#define ERR_PACK "Wrong package\n"
#define NO_EVENT "No events\n"
#define UPS_TIME "UPS internal Time %0d:%02d:%02d\n"
#endif
static int
AutonomyCalc( int ia ) /* all models */
{
2022-07-10 10:23:45 +03:00
int result = 0;
double auton, calc, currin;
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
if( ia )
2010-03-26 01:20:59 +02:00
{
2022-07-10 10:23:45 +03:00
if( d_equal(BattVoltage, 0) )
result = 0;
else
{
calc = ( OutVoltage * OutCurrent )* 1.0 / ( 0.08 * BattVoltage );
auton = pow( calc, 1.18 );
if( d_equal(auton, 0) )
result = 0;
else
{
auton = 1.0 / auton;
auton = auton * 11.07;
calc = ( BattVoltage * 1.0 / 10 ) - 168;
result = (int) ( auton * calc * 2.5 );
}
}
}
else
{
currin = ( UtilPowerOut + ConstInt ) *1.0 / Vin;
auton = ( ( ( AmpH *1.0 / currin ) * 60 * ( ( BattVoltage - VbatMin ) * 1.0 /( VbatNom - VbatMin ) ) * FM ) + FA );
if( ( BattVoltage > 129 ) && ( BattVoltage < 144 ) )
result = 133;
else
result = (int) auton;
}
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
return result;
2010-03-26 01:20:59 +02:00
}
/* Treat received package */
static void
ScanReceivePack( void )
{
2022-07-10 10:23:45 +03:00
/* model independent data */
Year = RecPack[31] + ( RecPack[32] * 100 );
Month = RecPack[30];
Day = RecPack[29];
/* UPS internal time */
ihour = RecPack[26];
imin = RecPack[27];
isec = RecPack[28];
/* Flag1 */
/* SobreTemp = ( ( 0x01 & RecPack[33]) = 0x01 ); */
/* OutputOn = ( ( 0x02 & RecPack[33]) = 0x02 ); OutputOn */
/* InputOn = ( ( 0x04 & RecPack[33]) = 0x04 ); InputOn */
/* ByPassOn = ( ( 0x08 & RecPack[33]) = 0x08 ); BypassOn */
/* Auto_HAB = ( ( 0x10 & RecPack[33]) = 0x10 ); */
/* Timer_HAB = ( ( 0x20 & RecPack[33]) = 0x20 ); */
/* Boost_Ligado = ( ( 0x40 & RecPack[33]) = 0x40 ); */
/* Bateria_Desc = ( ( 0x80 & RecPack[33]) = 0x80 ); */
/* Flag2 */
/* Quad_Ant_Ent = ( ( 0x01 & RecPack[34]) = 0x01 ); */
/* Quadratura = ( ( 0x02 & RecPack[34]) = 0x02 ); */
/* Termino_XMODEM = ( ( 0x04 & RecPack[34]) = 0x04 ); */
/* Em_Sincronismo = ( ( 0x08 & RecPack[34]) = 0x08 ); */
/* Out110 = ( ( 0x10 & RecPack[34]) = 0x10 ); Out110 */
/* Exec_Beep = ( ( 0x20 & RecPack[34]) = 0x20 ); */
/* LowBatt = ( ( 0x40 & RecPack[34]) = 0x40 ); LowBatt */
/* Boost_Sobre = ( ( 0x80 & RecPack[34]) = 0x80 ); */
/* Flag3 */
/* OverCharge = ( ( 0x01 & RecPack[35]) = 0x01 ); OverCharge */
/* SourceFail = ( ( 0x02 & RecPack[35]) = 0x02 ); SourceFail */
/* RedeAnterior = ( ( 0x04 & RecPack[35]) = 0x04 ); */
/* Cmd_Executado = ( ( 0x08 & RecPack[35]) = 0x08 ); */
/* Exec_Autoteste = ( ( 0x10 & RecPack[35]) = 0x10 ); */
/* Quad_Ant_Sai = ( ( 0x20 & RecPack[35]) = 0x20 ); */
/* ComandoSerial = ( ( 0x40 & RecPack[35]) = 0x40 ); */
/* SobreTensao = ( ( 0x80 & RecPack[35]) = 0x80 ); */
OutputOn = ( ( 0x02 & RecPack[33] ) == 0x02 );
InputOn = ( ( 0x04 & RecPack[33] ) == 0x04 );
BypassOn = ( ( 0x08 & RecPack[33] ) == 0x08 );
Out110 = ( ( 0x10 & RecPack[34] ) == 0x10 );
LowBatt = ( ( 0x40 & RecPack[34] ) == 0x40 );
OverCharge = ( ( 0x01 & RecPack[35] ) == 0x01 );
SourceFail = ( ( 0x02 & RecPack[35] ) == 0x02 );
/* model dependent data read */
PowerFactor = 800;
if( RecPack[0] == 0xC2 )
{
LimInfBattSrc = 174;
LimSupBattSrc = 192;/* 180????? carregador eh 180 (SCOPOS) */
LimInfBattInv = 174;
LimSupBattInv = 192;/* 170????? (SCOPOS) */
}
else
{
LimInfBattSrc = 138;
LimSupBattSrc = 162;/* 180????? carregador eh 180 (SCOPOS) */
LimInfBattInv = 126;
LimSupBattInv = 156;/* 170????? (SCOPOS) */
}
BattNonValue = 144;
/* VersaoInterna = "R10" + IntToStr( RecPack[1] ); */
InVoltage = RecPack[2];
InCurrent = RecPack[3];
UtilPowerIn = RecPack[4] + RecPack[5] * 256;
AppPowerIn = RecPack[6] + RecPack[7] * 256;
FatorPotEntrada = RecPack[8];
InFreq = ( RecPack[9] + RecPack[10] * 256 ) * 1.0 / 10;
OutVoltage = RecPack[11];
OutCurrent = RecPack[12];
UtilPowerOut = RecPack[13] + RecPack[14] * 256;
AppPowerOut = RecPack[15] + RecPack[16] * 256;
FatorPotSaida = RecPack[17];
OutFreq = ( RecPack[18] + RecPack[19] * 256 ) * 1.0 / 10;
BattVoltage = RecPack[20];
BoostVolt = RecPack[21] + RecPack[22] * 256;
Temperature = ( 0x7F & RecPack[23] );
Rendimento = RecPack[24];
/* model independent data */
if( ( BattVoltage < LimInfBattInv ) )
CriticBatt = true;
if( BypassOn )
OutVoltage = ( InVoltage * 1.0 / 2 ) + 5;
if( SourceFail && RedeAnterior ) /* falha pela primeira vez */
OcorrenciaDeFalha = true;
if( !( SourceFail ) && !( RedeAnterior ) ) /* retorno da rede */
RetornoDaRede = true;
if( RedeAnterior == !( SourceFail ) )
{
RetornoDaRede = false;
OcorrenciaDeFalha = false;
}
RedeAnterior = !( SourceFail );
LimInfSaida = 75;
LimSupSaida = 150;
ValorNominalSaida = 110;
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
LimInfEntrada = 190;
LimSupEntrada = 250;
ValorNominalEntrada = 220;
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
if( SourceFail )
{
StatusEntrada = 2;
RecPack[8] = 200; /* ?????????????????????????????????? */
}
else
{
StatusEntrada = 1;
RecPack[8] = 99; /* ??????????????????????????????????? */
}
if( OutputOn ) /* Output Status */
StatusSaida = 2;
else
StatusSaida = 1;
if( OverCharge )
StatusSaida = 3;
if( CriticBatt ) /* Battery Status */
StatusBateria = 4;
else
StatusBateria = 1;
EventosRede = 0;
if( OcorrenciaDeFalha )
EventosRede = 1;
if( RetornoDaRede )
EventosRede = 2;
/* verify InversorOn */
if( Flag_inversor )
{
oldInversorOn = InputOn;
Flag_inversor = false;
}
EventosSaida = 0;
if( InputOn && !( oldInversorOn ) )
EventosSaida = 26;
if( oldInversorOn && !( InputOn ) )
EventosSaida = 27;
oldInversorOn = InputOn;
if( SuperAquecimento && !( SuperAquecimentoAnterior ) )
EventosSaida = 12;
if( SuperAquecimentoAnterior && !( SuperAquecimento ) )
EventosSaida = 13;
SuperAquecimentoAnterior = SuperAquecimento;
EventosBateria = 0;
OldCritBatt = CriticBatt;
if( OverCharge && !( OldOverCharge ) )
EventosSaida = 10;
if( OldOverCharge && !( OverCharge ) )
EventosSaida = 11;
OldOverCharge = OverCharge;
/* autonomy calc. */
if( RecPack[ 0 ] == 0xC2 )
Autonomy = AutonomyCalc( 1 );
else
Autonomy = AutonomyCalc( 0 );
2010-03-26 01:20:59 +02:00
}
static void
2022-07-10 10:23:45 +03:00
CommReceive(const unsigned char *bufptr, ssize_t size)
2010-03-26 01:20:59 +02:00
{
2022-07-10 10:23:45 +03:00
int i, i_end, CheckSum, chk;
if( size == 37 )
Waiting = 0;
printf("CommReceive size = %zd waiting = %d\n", size, Waiting );
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
switch( Waiting )
{
/* normal package */
case 0:
{
if( size == 37 )
{
i_end = 37;
for( i = 0 ; i < i_end ; ++i )
{
RecPack[i] = *bufptr;
bufptr++;
}
/* CheckSum verify */
CheckSum = 0;
i_end = 36;
for( i = 0 ; i < i_end ; ++i )
{
chk = RecPack[ i ];
CheckSum = CheckSum + chk;
}
CheckSum = CheckSum % 256;
ser_flush_in(upsfd,"",0); /* clean port */
/* correct package */
if( ( RecPack[0] == 0xC0 || RecPack[0] == 0xC1 || RecPack[0] == 0xC2 || RecPack[0] == 0xC3 )
&& ( RecPack[ 36 ] == CheckSum ) )
{
if(!(detected))
{
RhinoModel = RecPack[0];
detected = true;
}
switch( RhinoModel )
{
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
{
ScanReceivePack();
break;
}
default:
{
printf( M_UNKN );
break;
}
}
}
}
break;
}
case 1:
{
/* dumping package, nothing to do yet */
Waiting = 0;
break;
}
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
}
Waiting = 0;
2010-03-26 01:20:59 +02:00
}
2022-07-10 10:23:45 +03:00
static ssize_t
send_command( unsigned char cmd )
2010-03-26 01:20:59 +02:00
{
2022-07-10 10:23:45 +03:00
static const size_t sizes = 19, iend = 18;
size_t i, kount; /*, j, uc; */
unsigned char chk, checksum = 0;
ssize_t ret = -1;
unsigned char ch, *psend = NULL;
if ( !(psend = xmalloc(sizeof(char) * sizes)) ) {
upslogx(LOG_ERR, "send_command() failed to allocate buffer");
return -1;
}
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
/* mounting buffer to send */
2010-03-26 01:20:59 +02:00
2012-01-24 12:22:33 +02:00
for(i = 0; i < iend; i++ )
2010-03-26 01:20:59 +02:00
{
2012-01-24 12:22:33 +02:00
if ( i == 0 )
chk = 0x01;
else
{
2022-07-10 10:23:45 +03:00
if( i == 1 )
2012-01-24 12:22:33 +02:00
chk = cmd;
else
chk = 0x00; /* 0x20; */
}
ch = chk;
psend[i] = ch; /* psend[0 - 17] */
2022-07-10 10:23:45 +03:00
if( i > 0 ) /* psend[0] not computed */
2012-01-24 12:22:33 +02:00
checksum = checksum + chk;
2010-03-26 01:20:59 +02:00
}
2012-01-24 12:22:33 +02:00
ch = checksum;
2022-07-10 10:23:45 +03:00
ch = (~( ch) ); /* not ch */
2012-01-24 12:22:33 +02:00
psend[iend] = ch;
2010-03-26 01:20:59 +02:00
2012-01-24 12:22:33 +02:00
/* send five times the command */
kount = 0;
while ( kount < 5 )
2010-03-26 01:20:59 +02:00
{
2012-01-24 12:22:33 +02:00
/* ret = ser_send_buf_pace(upsfd, UPSDELAY, psend, sizes ); */ /* optional delay */
for(i = 0 ; i < sizes ; i++)
{
ret = ser_send_char( upsfd, psend[i] );
/* usleep ( UPSDELAY ); sending without delay */
}
usleep( UPSDELAY ); /* delay between sent command */
kount++;
2010-03-26 01:20:59 +02:00
}
2022-07-10 10:23:45 +03:00
free (psend);
2012-01-24 12:22:33 +02:00
return ret;
2010-03-26 01:20:59 +02:00
}
static void sendshut( void )
{
int i;
for(i=0; i < 30000; i++)
2022-07-10 10:23:45 +03:00
usleep( UPSDELAY ); /* 15 seconds delay */
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
if ( send_command( CMD_SHUT ) < 1 )
upslogx(LOG_ERR, "Ups shutdown command sending failed");
else
upslogx(LOG_NOTICE, "Ups shutdown command sent");
2010-03-26 01:20:59 +02:00
printf("Ups shutdown command sent\n");
}
static void getbaseinfo(void)
{
2022-07-10 10:23:45 +03:00
unsigned char temp[256];
2010-03-26 01:20:59 +02:00
unsigned char Pacote[37];
2022-07-10 10:23:45 +03:00
ssize_t tam, i, j=0;
2012-06-01 16:55:19 +03:00
time_t tmt;
2010-03-26 01:20:59 +02:00
struct tm *now;
2022-07-10 10:23:45 +03:00
struct tm tmbuf;
2011-01-26 11:35:08 +02:00
const char *Model;
2010-03-26 01:20:59 +02:00
2012-06-01 16:55:19 +03:00
time( &tmt );
2022-07-10 10:23:45 +03:00
now = localtime_r( &tmt, &tmbuf );
2010-03-26 01:20:59 +02:00
dian = now->tm_mday;
mesn = now->tm_mon+1;
anon = now->tm_year+1900;
2022-07-10 10:23:45 +03:00
weekn = now->tm_wday;
2010-03-26 01:20:59 +02:00
/* trying detect rhino model */
while ( ( !detected ) && ( j < 10 ) )
2022-07-10 10:23:45 +03:00
{
temp[0] = 0; /* flush temp buffer */
tam = ser_get_buf_len(upsfd, temp, pacsize, 3, 0);
if( tam == 37 )
{
for( i = 0 ; i < tam ; i++ )
{
Pacote[i] = temp[i];
}
}
j++;
if( tam == 37)
CommReceive(Pacote, tam);
else
CommReceive(temp, tam);
}
2010-03-26 01:20:59 +02:00
if( (!detected) )
2022-07-10 10:23:45 +03:00
{
fatalx(EXIT_FAILURE, NO_RHINO );
}
2010-03-26 01:20:59 +02:00
switch( RhinoModel )
2022-07-10 10:23:45 +03:00
{
case 0xC0:
{
Model = "Rhino 20.0 kVA";
PotenciaNominal = 20000;
break;
}
case 0xC1:
{
Model = "Rhino 10.0 kVA";
PotenciaNominal = 10000;
break;
}
case 0xC2:
{
Model = "Rhino 6.0 kVA";
PotenciaNominal = 6000;
break;
}
case 0xC3:
{
Model = "Rhino 7.5 kVA";
PotenciaNominal = 7500;
break;
}
default:
{
Model = "Rhino unknown model";
PotenciaNominal = 0;
break;
}
}
2010-03-26 01:20:59 +02:00
/* manufacturer and model */
dstate_setinfo("ups.mfr", "%s", "Microsol");
dstate_setinfo("ups.model", "%s", Model);
/*
dstate_setinfo("input.transfer.low", "%03.1f", InDownLim); LimInfBattInv ?
dstate_setinfo("input.transfer.high", "%03.1f", InUpLim); LimSupBattInv ?
*/
2011-06-01 23:31:49 +03:00
dstate_addcmd("shutdown.stayoff"); /* CMD_SHUT */
2010-03-26 01:20:59 +02:00
/* there is no reserved words for CMD_INON and CMD_INOFF yet */
2011-06-01 23:31:49 +03:00
/* dstate_addcmd("input.on"); */ /* CMD_INON = 1 */
/* dstate_addcmd("input.off"); */ /* CMD_INOFF = 2 */
2010-03-26 01:20:59 +02:00
dstate_addcmd("load.on"); /* CMD_OUTON = 3 */
dstate_addcmd("load.off"); /* CMD_OUTOFF = 4 */
dstate_addcmd("bypass.start"); /* CMD_PASSON = 5 */
dstate_addcmd("bypass.stop"); /* CMD_PASSOFF = 6 */
printf("Detected %s on %s\n", dstate_getinfo("ups.model"), device_path);
}
static void getupdateinfo(void)
{
2022-07-10 10:23:45 +03:00
unsigned char temp[256];
ssize_t tam;
2010-03-26 01:20:59 +02:00
temp[0] = 0; /* flush temp buffer */
tam = ser_get_buf_len(upsfd, temp, pacsize, 3, 0);
CommReceive(temp, tam);
}
static int instcmd(const char *cmdname, const char *extra)
{
2022-07-10 10:23:45 +03:00
ssize_t ret = 0;
2010-03-26 01:20:59 +02:00
if (!strcasecmp(cmdname, "shutdown.stayoff"))
2022-07-10 10:23:45 +03:00
{
/* shutdown now (one way) */
/* send_command( CMD_SHUT ); */
sendshut();
return STAT_INSTCMD_HANDLED;
}
2010-03-26 01:20:59 +02:00
if (!strcasecmp(cmdname, "load.on"))
2022-07-10 10:23:45 +03:00
{
/* liga Saida */
ret = send_command( 3 );
if ( ret < 1 )
upslogx(LOG_ERR, "send_command 3 failed");
return STAT_INSTCMD_HANDLED;
}
2010-03-26 01:20:59 +02:00
if (!strcasecmp(cmdname, "load.off"))
2022-07-10 10:23:45 +03:00
{
/* desliga Saida */
ret = send_command( 4 );
if ( ret < 1 )
upslogx(LOG_ERR, "send_command 4 failed");
return STAT_INSTCMD_HANDLED;
}
2010-03-26 01:20:59 +02:00
if (!strcasecmp(cmdname, "bypass.start"))
2022-07-10 10:23:45 +03:00
{
/* liga Bypass */
ret = send_command( 5 );
if ( ret < 1 )
upslogx(LOG_ERR, "send_command 5 failed");
return STAT_INSTCMD_HANDLED;
}
2010-03-26 01:20:59 +02:00
if (!strcasecmp(cmdname, "bypass.stop"))
2022-07-10 10:23:45 +03:00
{
/* desliga Bypass */
ret = send_command( 6 );
if ( ret < 1 )
upslogx(LOG_ERR, "send_command 6 failed");
return STAT_INSTCMD_HANDLED;
}
2010-03-26 01:20:59 +02:00
2022-07-10 10:23:45 +03:00
upslogx(LOG_NOTICE, "instcmd: unknown command [%s] [%s]", cmdname, extra);
2010-03-26 01:20:59 +02:00
return STAT_INSTCMD_UNKNOWN;
}
void upsdrv_initinfo(void)
{
getbaseinfo();
upsh.instcmd = instcmd;
}
void upsdrv_updateinfo(void)
{
2022-07-10 10:23:45 +03:00
getupdateinfo(); /* new package for updates */
2010-03-26 01:20:59 +02:00
dstate_setinfo("output.voltage", "%03.1f", OutVoltage);
dstate_setinfo("input.voltage", "%03.1f", InVoltage);
dstate_setinfo("battery.voltage", "%02.1f", BattVoltage);
/* output and bypass tests */
if( OutputOn )
2022-07-10 10:23:45 +03:00
dstate_setinfo("outlet.switchable", "%s", "yes");
2010-03-26 01:20:59 +02:00
else
2022-07-10 10:23:45 +03:00
dstate_setinfo("outlet.switchable", "%s", "no");
2010-03-26 01:20:59 +02:00
if( BypassOn )
2022-07-10 10:23:45 +03:00
dstate_setinfo("outlet.1.switchable", "%s", "yes");
2010-03-26 01:20:59 +02:00
else
2022-07-10 10:23:45 +03:00
dstate_setinfo("outlet.1.switchable", "%s", "no");
2010-03-26 01:20:59 +02:00
status_init();
if (!SourceFail )
2022-07-10 10:23:45 +03:00
status_set("OL"); /* on line */
2010-03-26 01:20:59 +02:00
else
2022-07-10 10:23:45 +03:00
status_set("OB"); /* on battery */
2010-03-26 01:20:59 +02:00
if (Autonomy < 5 )
2022-07-10 10:23:45 +03:00
status_set("LB"); /* low battery */
2010-03-26 01:20:59 +02:00
status_commit();
dstate_setinfo("ups.temperature", "%2.2f", Temperature);
dstate_setinfo("input.frequency", "%2.1f", InFreq);
dstate_dataok();
}
/* power down the attached load immediately */
void upsdrv_shutdown(void)
{
/* basic idea: find out line status and send appropriate command */
/* on line: send normal shutdown, ups will return by itself on utility */
/* on battery: send shutdown+return, ups will cycle and return soon */
2011-06-01 23:31:49 +03:00
if (!SourceFail) /* on line */
2022-07-10 10:23:45 +03:00
{
/* FIXME: Both legs of the if-clause send CMD_SHUT, where is the "forcing"? */
printf("On line, forcing shutdown command...\n");
/* send_command( CMD_SHUT ); */
sendshut();
}
2010-03-26 01:20:59 +02:00
else
2022-07-10 10:23:45 +03:00
{
printf("On battery, sending normal shutdown command...\n");
/* send_command( CMD_SHUT ); */
sendshut();
}
2010-03-26 01:20:59 +02:00
}
void upsdrv_help(void)
{
}
void upsdrv_makevartable(void)
{
addvar(VAR_VALUE, "battext", "Battery Extension (0-80)min");
}
void upsdrv_initups(void)
{
upsfd = ser_open(device_path);
ser_set_speed(upsfd, device_path, B19200);
/* dtr and rts setting */
ser_set_dtr(upsfd, 1);
ser_set_rts(upsfd, 0);
}
void upsdrv_cleanup(void)
{
ser_close(upsfd, device_path);
}