~ubuntu-branches/ubuntu/saucy/nut/saucy

« back to all changes in this revision

Viewing changes to models/bestfort.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Quette
  • Date: 2004-05-28 13:10:01 UTC
  • mto: (16.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040528131001-yj2m9qcez4ya2w14
Tags: upstream-1.4.2
ImportĀ upstreamĀ versionĀ 1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   bestfort.c - model specific routines for Best Power Fortress (some
3
 
   don't speak to bestups, which does some entirely different protocol
4
 
   than this one that my Fortress LI 1020 speaks).  I think I've got a
5
 
   "traditional" Fortress as opposed to one of the other dozen-odd
6
 
   lines Best Power has made or acquired over the years.  The protocol
7
 
   here is documented in Best's document FTS502b.  Just ask and
8
 
   they'll send it to you as a PDF.
9
 
 
10
 
   This module is a 75% rewritten mangle of the bestups module by
11
 
   Russell.  It lost the "test battery" command since my fortress does
12
 
   this automagically each week at 2am.  It gained a -D aka debugging
13
 
   option to not background and summarize stuff from each poll.
14
 
 
15
 
   Warning: I have not tested the -k function.
16
 
 
17
 
   Copyright (C) 2000  Grant Taylor <gtaylor@picante.com>
18
 
   Copyright (C) 1999  Russell Kroll <rkroll@exploits.org>
19
 
 
20
 
   This program is free software; you can redistribute it and/or modify
21
 
   it under the terms of the GNU General Public License as published by
22
 
   the Free Software Foundation; either version 2 of the License, or
23
 
   (at your option) any later version.
24
 
 
25
 
   This program is distributed in the hope that it will be useful,
26
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
 
   GNU General Public License for more details.
29
 
 
30
 
   You should have received a copy of the GNU General Public License
31
 
   along with this program; if not, write to the Free Software
32
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33
 
 
34
 
*/
35
 
 
36
 
#include <errno.h>
37
 
#include <fcntl.h>
38
 
#include <stdio.h>
39
 
#include <signal.h>
40
 
#include <stdlib.h>
41
 
#include <string.h>
42
 
#include <unistd.h>
43
 
#include <sys/file.h>
44
 
#include <sys/stat.h>
45
 
#include <sys/ioctl.h>
46
 
#include <sys/types.h>
47
 
#include <sys/termios.h>
48
 
#include <assert.h>
49
 
 
50
 
#include "config.h"
51
 
#include "proto.h"
52
 
#include "shared.h"
53
 
#include "version.h"
54
 
#include "upscommon.h"
55
 
#include "common.h"
56
 
 
57
 
#define INFOMAX  16
58
 
 
59
 
int debugging = 0;
60
 
 
61
 
        int     shmok = 1;
62
 
 
63
 
/* Model ID strings.  The Fortress returns an enumerated integer value
64
 
   for model type. */
65
 
static const int num_models = 5;
66
 
static char *models[] = {"Unknown",
67
 
                         "Patriot/SPS",
68
 
                         "Fortress",
69
 
                         "FERRUPS",
70
 
                         "UNITY/I single-phase" };
71
 
 
72
 
/* Blob of UPS configuration data from the formatconfig string */
73
 
struct {
74
 
  int valid;                    /* set to 1 when this is filled in */
75
 
 
76
 
  double idealbvolts;           /* various interestin battery voltages */
77
 
  double fullvolts;
78
 
  double emptyvolts;
79
 
  int va;                       /* capacity of UPS in Volt-Amps */
80
 
  int watts;                    /* capacity of UPS in watts */
81
 
  int model;                    /* enumerated model type */
82
 
} fc;
83
 
 
84
 
 
85
 
/* Forward decls */
86
 
void setup_serial(void);
87
 
int readupsline (char *buf);
88
 
int execute_int(char *cmd, char *response);
89
 
 
90
 
/* Set up all the funky shared memory stuff used to communicate with upsd */
91
 
void initinfo (void)
92
 
{
93
 
        create_info (INFOMAX, shmok);
94
 
 
95
 
        /* now set up room for all future variables that are supported */
96
 
        addinfo (INFO_MFR, "", 0, 0);
97
 
        addinfo (INFO_MODEL, "", 0, 0);
98
 
        addinfo (INFO_UTILITY, "", 0, 0);
99
 
        addinfo (INFO_BATTPCT, "", 0, 0);
100
 
        addinfo (INFO_STATUS, "", 0, 0);
101
 
        addinfo (INFO_LOADPCT, "", 0, 0);
102
 
}
103
 
 
104
 
/* TODO: adapt to the standard upscommon open/send/recv calls */
105
 
 
106
 
/* This seems unlikely, as the current ones don't handle the
107
 
   unterminated line containing the prompt that you get back after
108
 
   each command.  Perhaps the thing is to make our own or something;
109
 
   the standard calls are nice in that they use alarms to do timeouts
110
 
   and such.  OTOH, the Fortress *always* babbles back at you giving
111
 
   at least a prompt...   */
112
 
 
113
 
int open_ups(char *filename)
114
 
{
115
 
  chdir("/dev");
116
 
 
117
 
  upsfd = open(filename, O_RDWR | O_NDELAY);
118
 
  if (upsfd == -1)
119
 
    fatal("open");
120
 
  
121
 
  setup_serial();
122
 
  
123
 
  return upsfd;
124
 
}
125
 
 
126
 
void setup_serial(void)
127
 
{       
128
 
  struct        termios tio;
129
 
 
130
 
  /* Zero out the structure to prevent confusion.  It took me forever
131
 
     to figure out why my serial reading routines read everything from
132
 
     the UPS perfectly, except for the infuriating detail that all the
133
 
     `0's were missing: since it didn't wipe the c_cc part clean, the
134
 
     VSTART character got set to `0', so that got eaten.  The (horrid)
135
 
     example code from Best Power was immune to this problem since
136
 
     everything is a (n implicitly initialized) global.  */
137
 
 
138
 
  memset(&tio, 0, sizeof(tio));
139
 
  
140
 
  tio.c_iflag = IXON | IXOFF;
141
 
  tio.c_oflag = 0;
142
 
  tio.c_cflag = (B1200 | CS8 | CREAD | HUPCL | CLOCAL);
143
 
  tio.c_lflag = 0;
144
 
  tio.c_cc[VMIN] = 1;
145
 
  tio.c_cc[VTIME] = 0;
146
 
  tio.c_cc[VSTART] = 17;        /* CTRL('q'); is not portable */
147
 
 
148
 
  if (tcsetattr (upsfd, TCSANOW, &tio) == -1)
149
 
    fatal("tcsetattr");
150
 
}
151
 
 
152
 
char readchar (void)
153
 
{
154
 
  char  c='z';
155
 
  int   ret;
156
 
 
157
 
 
158
 
  /* It's not obvious that O_NDELAY was useful.  We should probably do
159
 
     selects with timeouts or set a timer against blocking i/o or
160
 
     something.  Luckily UPS's aren't prone to goign missing.  */
161
 
 
162
 
 readspot:
163
 
  ret = read (upsfd, &c, 1);
164
 
 
165
 
  if (ret > 0) {
166
 
    return (c & 0x7f);
167
 
  } else {
168
 
    if (errno == EAGAIN) {
169
 
      sleep(1);
170
 
      goto readspot;
171
 
    }
172
 
 
173
 
    perror("read error in readchar()");
174
 
    return 0;
175
 
  }
176
 
}
177
 
 
178
 
/* Run a command.  Put the response, or empty string if none, into
179
 
   buffer response.  God help you if the buffer is too short.  It
180
 
   would be best to not execute a continuous statement like
181
 
   `contstatus' ;) */
182
 
 
183
 
int execute(char *cmd, char *response)
184
 
{
185
 
  char junkbuf[256];
186
 
 
187
 
  /* First synchronize with a control-c and backspace.  Then we'll be
188
 
     at a "clean" prompt and ready to go. */
189
 
 
190
 
  return execute_int("\x08\x03", junkbuf) || execute_int(cmd,response);
191
 
}
192
 
 
193
 
int execute_int(char *cmd, char *response)
194
 
{
195
 
  int ret, prompt;
196
 
  char *ptr, linebuf[256];
197
 
  
198
 
  /* First send command string plus the \r */
199
 
  ptr = cmd;
200
 
  while (*ptr) {
201
 
  writespot1:
202
 
    ret = write(upsfd, ptr++, 1);
203
 
    if (ret == -1) {
204
 
      if (errno == EAGAIN) 
205
 
        goto writespot1;
206
 
 
207
 
      perror("execute(): write() failed");
208
 
      return -1;
209
 
    }
210
 
  }
211
 
 
212
 
 writespot2:
213
 
  ret = write(upsfd, "\r", 1);  /* carriage return */
214
 
  if (ret == -1) {
215
 
    if (errno==EAGAIN) 
216
 
      goto writespot2;
217
 
 
218
 
    perror("execute(): write() failed");
219
 
    return -1;
220
 
  }
221
 
 
222
 
  /* OK, now we read.  We expect to see what we just wrote, followed
223
 
     by some or no output, followed by a prompt ending in "=> " */
224
 
 
225
 
  if (strlen(cmd) && cmd[0] != '\x08') {
226
 
    int lineoffset = 0;
227
 
    do {                        /* read until we see our command */
228
 
      prompt = readupsline(linebuf);
229
 
      lineoffset = strlen(cmd) - strlen(linebuf);
230
 
    } while (0 != strcmp(cmd,linebuf+lineoffset) && prompt != -1);
231
 
  }
232
 
 
233
 
  response[0] = '\0';
234
 
  do {
235
 
    prompt = readupsline(linebuf);
236
 
 
237
 
    if (prompt) {
238
 
      /* the next prompt */
239
 
    } else if (strlen(linebuf) > 1 && linebuf[0] != '\r') {
240
 
      /* interesting output */
241
 
      strcat(response, linebuf);
242
 
      strcat(response, "\r");
243
 
    }
244
 
  } while (prompt == 0);
245
 
 
246
 
  return ((prompt == -1) ? -1 : 0);
247
 
}
248
 
 
249
 
/* 
250
 
   read a line from the UPS, terminated by either a '\r' or by a =>
251
 
   (the prompt).
252
 
 
253
 
   return -1 for error
254
 
   return 0 for normal lines
255
 
   return 1 for prompt lines
256
 
 */
257
 
int readupsline (char *buf)
258
 
{
259
 
  char  ch, *p;
260
 
  int l;
261
 
  
262
 
  p = buf;
263
 
  *p = '\0';
264
 
  l=0;
265
 
  
266
 
  while ((ch = readchar ())) {
267
 
    if (ch == '\n')
268
 
      continue;         /* absorb duplicate nl/crs */
269
 
    
270
 
    l++;
271
 
    
272
 
    /* done on carriage return/newline, don't include cr */
273
 
    if (ch == '\n' ||  ch == '\r') {
274
 
      *p = '\0';
275
 
      return 0;
276
 
    }
277
 
    
278
 
    /* include this character */
279
 
    *p++ = ch;
280
 
    
281
 
    /* done if last two chars are '=>' */
282
 
    if (l >= 2) {
283
 
      char *prompt = p-2;
284
 
      if (0 == memcmp(prompt, "=>", 2)) {
285
 
        *p = '\0';
286
 
        return 1;               /* one for prompt line */
287
 
      }
288
 
    }
289
 
  }
290
 
  
291
 
  *p = '\0';
292
 
  return -1;
293
 
}
294
 
 
295
 
void ups_sync(void)
296
 
{
297
 
  char  buf[256];
298
 
 
299
 
  printf ("Syncing: ");
300
 
  fflush (stdout);
301
 
 
302
 
  /* A bit better sanity might be good here.  As is, we expect the
303
 
     human to observe the time being totally not a time. */
304
 
 
305
 
  if (0 == execute("time", buf)) {
306
 
    fprintf(stderr, "UPS Time: %s\n", buf);
307
 
  } else {
308
 
    fprintf(stderr, "Error connecting to UPS.\n");
309
 
    exit(1);
310
 
  }
311
 
}
312
 
 
313
 
/* power down the attached load immediately */
314
 
void forceshutdown(char *port)
315
 
{
316
 
  char  temp[256];
317
 
 
318
 
  upslogx(LOG_INFO, "Initiating UPS shutdown\n");
319
 
  printf ("Initiating forced UPS shutdown!\n");
320
 
  
321
 
  open_ups(port);
322
 
  
323
 
  /* shutdown in 5 seconds, autostart later */
324
 
  execute("shutdown autostart 5", temp);
325
 
  
326
 
  printf ("Waiting for poweroff...\n");
327
 
  sleep (90);
328
 
  printf ("Hmm, did the shutdown fail?  Oh well...\n");
329
 
  exit (1);                               
330
 
}
331
 
 
332
 
void usage (char *prog)
333
 
{
334
 
  printf ("usage: %s [-h] [-k] [-D] <device>\n", prog);
335
 
  printf ("Example: %s /dev/ttyS0\n", prog);
336
 
  exit (1);
337
 
}
338
 
 
339
 
void help (char *prog)
340
 
{
341
 
  printf ("usage: %s [-h] [-k] <device>\n", prog);
342
 
  printf ("\n");
343
 
  printf ("-h       - display this help\n");
344
 
  printf ("-k       - force shutdown\n");
345
 
  printf ("-D       - run in foreground for debugging/testing\n");
346
 
  printf ("<device> - /dev entry corresponding to UPS port\n");
347
 
}
348
 
 
349
 
 
350
 
 
351
 
void ups_ident (void)
352
 
{
353
 
  char  temp[256], fcstring[512];
354
 
 
355
 
  /* Obtain Model */
356
 
  if (0 != execute("fc", fcstring)) {
357
 
    fprintf(stderr, "Failed execute in ups_ident()\n");
358
 
    exit(1);
359
 
  }
360
 
  
361
 
  /* response is a  one-line packed string starting with $ */
362
 
  if (fcstring[0] != '$') {
363
 
    fprintf(stderr,
364
 
            "Bad response from formatconfig command in ups_ident()\n");
365
 
    exit(1);
366
 
  }
367
 
 
368
 
  if (debugging)
369
 
    fprintf(stderr, "fc: %s\n", fcstring);
370
 
  
371
 
  /* chars 4:2  are a two-digit ascii hex enumerated model code */
372
 
  memcpy(temp, fcstring+3, 2);
373
 
  temp[2] = '\0';
374
 
  sscanf(temp, "%x", &fc.model);
375
 
 
376
 
  if (fc.model >= num_models) {
377
 
    fprintf(stderr,
378
 
            "Unknown model 0x%x in ups_ident()\n",
379
 
            fc.model);
380
 
    exit(1);
381
 
  }
382
 
  
383
 
  /* chars 12:5 are five-digit ascii decimal VA rating */
384
 
  memcpy(temp, fcstring+11, 5);
385
 
  temp[5] = '\0';
386
 
  fc.va = atoi(temp);
387
 
  
388
 
  /* chars 17:5 are 5-dig ascii deciaml watts rating */
389
 
  memcpy(temp, fcstring+16, 5);
390
 
  temp[5] = '\0';
391
 
  fc.watts = atoi(temp);
392
 
  
393
 
  /* chars 46:4 are ascii decimal xxx.x nominal battery volt */
394
 
  memcpy(temp, fcstring+45, 4);
395
 
  temp[4] = '\0';
396
 
  fc.idealbvolts = atof(temp) / 10.0;
397
 
  
398
 
  /* chars 50:4 are full charge battery voltage */
399
 
  memcpy(temp, fcstring+49, 4);
400
 
  temp[4] = '\0';
401
 
  fc.fullvolts = atof(temp) / 10.0;
402
 
  
403
 
  /* chars 58:4 are empty battery voltage */
404
 
  memcpy(temp, fcstring+57, 4);
405
 
  temp[4] = '\0';
406
 
  fc.emptyvolts = atof(temp) / 10.0;
407
 
  
408
 
  setinfo(INFO_MFR, "%s", "Best Power");
409
 
  setinfo(INFO_MODEL, "%s %d", models[fc.model], fc.va);
410
 
  
411
 
  fc.valid = 1;
412
 
  
413
 
  printf("Best Power %s detected\n", getdata(INFO_MODEL));
414
 
  printf("Battery voltages %5.1f nominal, %5.1f full, %5.1f empty\n", 
415
 
         fc.idealbvolts,
416
 
         fc.fullvolts,
417
 
         fc.emptyvolts);
418
 
  
419
 
  return;
420
 
}
421
 
 
422
 
void ups_update (void)
423
 
{
424
 
  char fstring[512];
425
 
 
426
 
  if (! fc.valid) {
427
 
    fprintf(stderr, 
428
 
            "upsupdate run before ups_ident() read ups config\n");
429
 
    assert(0);
430
 
  }
431
 
 
432
 
  if (0==execute("format",fstring)) {
433
 
    int inverter=0, charger=0, 
434
 
      vin=0, btimeleft=0,
435
 
      linestat=0, alstat=0, vaout=0;
436
 
    double ampsout=0.0, vbatt=0.0, battpercent=0.0, loadpercent=0.0;
437
 
    char tmp[16], statstr[128];
438
 
 
439
 
    /* Inverter status.  0=off 1=on */
440
 
    memcpy(tmp, fstring+16, 2);
441
 
    tmp[2] = '\0';
442
 
    inverter = atoi(tmp);
443
 
 
444
 
    /* Charger status.  0=off 1=on */
445
 
    memcpy(tmp, fstring+18, 2);
446
 
    tmp[2] = '\0';
447
 
    charger = atoi(tmp);
448
 
    
449
 
    /* Input Voltage. integer number */
450
 
    memcpy(tmp, fstring+24, 4);
451
 
    tmp[4] = '\0';
452
 
    vin = atoi(tmp);
453
 
 
454
 
    /* Iout.  int times 10 */
455
 
    memcpy(tmp, fstring+36, 4);
456
 
    tmp[4] = '\0';
457
 
    ampsout = ((double)(atoi(tmp)) / 10.0);
458
 
 
459
 
    /* Battery voltage.  int times 10 */
460
 
    memcpy(tmp, fstring+50, 4);
461
 
    tmp[4] = '\0';
462
 
    vbatt = ((double)(atoi(tmp)) / 10.0);
463
 
 
464
 
    /* Volt-amps out.  int  */
465
 
    memcpy(tmp, fstring+40, 6);
466
 
    tmp[6] = '\0';
467
 
    vaout = atoi(tmp);
468
 
 
469
 
    /* Line status.  Bitmask */
470
 
    memcpy(tmp, fstring+72, 2);
471
 
    tmp[2] = '\0';
472
 
    linestat = atoi(tmp);
473
 
 
474
 
    /* Alarm status reg 1.  Bitmask */
475
 
    memcpy(tmp, fstring+20, 2);
476
 
    tmp[2] = '\0';
477
 
    alstat = atoi(tmp);
478
 
 
479
 
    /* Alarm status reg 2.  Bitmask */
480
 
    memcpy(tmp, fstring+22, 2);
481
 
    tmp[2] = '\0';
482
 
    alstat = alstat | (atoi(tmp) << 8);
483
 
 
484
 
 
485
 
    /* Get various assorted parameters */
486
 
 
487
 
    /* Runtime */
488
 
    if (0 == execute("p 9", fstring)) {
489
 
      sscanf(fstring, "09 Runtime %dm", &btimeleft);
490
 
    }
491
 
 
492
 
    /* Percent Load */
493
 
    if (0 == execute("p 16", fstring)) {
494
 
      int l;
495
 
      sscanf(fstring, "16 FullLoad%% %d", &l);
496
 
      loadpercent = (double) l;
497
 
    }
498
 
    
499
 
    /* Compute battery percent left based on battery voltages. */
500
 
    battpercent = ((vbatt - fc.emptyvolts) 
501
 
                   / (fc.fullvolts - fc.emptyvolts) * 100.0);
502
 
    if (battpercent < 0.0) 
503
 
      battpercent = 0.0;
504
 
    else if (battpercent > 100.0)
505
 
      battpercent = 100.0;
506
 
    
507
 
    /* Compute status string */
508
 
    {
509
 
      int lowbatt, overload, replacebatt, boosting, trimming;
510
 
 
511
 
      lowbatt = alstat & (1<<1);
512
 
      overload = alstat & (1<<6);
513
 
      replacebatt = alstat & (1<<10);
514
 
      boosting = inverter && (linestat & (1<<2)) && (vin < 115);
515
 
      trimming = inverter && (linestat & (1<<2)) && (vin > 115);
516
 
 
517
 
      strcpy(tmp, inverter ? "OB" : "OL");
518
 
      if (lowbatt) strcat (tmp, " LB");
519
 
      if (trimming) strcat (tmp, " TRIM");
520
 
      if (boosting) strcat (tmp, " BOOST");
521
 
      if (replacebatt) strcat (tmp, " RB");
522
 
      if (overload) strcat (tmp, " OVER");
523
 
 
524
 
      strlcpy(statstr, tmp, sizeof(statstr));
525
 
 
526
 
    }
527
 
 
528
 
 
529
 
    if (debugging) {
530
 
      fprintf(stderr,
531
 
              "Poll: inverter %d charger %d vin %d vaout %d btimeleft %d\n",
532
 
              inverter, charger, vin, vaout, btimeleft);
533
 
      fprintf(stderr,
534
 
              "      ampsout %5.1f vbatt %5.1f batpcnt %5.1f loadpcnt %5.1f\n",
535
 
              ampsout, vbatt, battpercent, loadpercent);
536
 
      fprintf(stderr,
537
 
              "      STATUS '%s'\n", statstr);
538
 
 
539
 
    }
540
 
 
541
 
 
542
 
 
543
 
    /* Stuff information into info structures */
544
 
 
545
 
    setinfo(INFO_STATUS, "%s", statstr);
546
 
 
547
 
    setinfo(INFO_BATTPCT, "%02.1f", battpercent);
548
 
 
549
 
    setinfo(INFO_LOADPCT, "%03.1f", loadpercent);
550
 
 
551
 
    setinfo(INFO_UTILITY, "%05.1f", (double)vin);
552
 
 
553
 
    writeinfo();
554
 
 
555
 
 
556
 
  }
557
 
 
558
 
  return;
559
 
}
560
 
 
561
 
int main (int argc, char **argv)
562
 
{
563
 
        char    *prog, *portname;
564
 
        int     i;
565
 
 
566
 
        printf ("Network UPS Tools - Best Fortress driver 0.1 (%s)\n", 
567
 
                UPS_VERSION);
568
 
        openlog ("bestfort", LOG_PID, LOG_FACILITY);
569
 
        prog = argv[0];
570
 
 
571
 
        while ((i = getopt(argc, argv, "+hk:D")) != EOF) {
572
 
                switch (i) {
573
 
                        case 'k':
574
 
                                forceshutdown(optarg);
575
 
                                break;
576
 
                        case 'D':
577
 
                          debugging = 1;
578
 
                                break;
579
 
                        case 'h':
580
 
                                help(prog);
581
 
                                break;
582
 
                        default:
583
 
                                usage(prog);
584
 
                                break;
585
 
                }
586
 
        }
587
 
 
588
 
        argc -= optind;
589
 
        argv += optind;
590
 
 
591
 
        if (argc != 1) {
592
 
                help (prog);
593
 
                exit (1);
594
 
        }
595
 
 
596
 
        droproot();
597
 
 
598
 
        portname = NULL;
599
 
        for (i = strlen(argv[0]); i >= 0; i--)
600
 
                if (argv[0][i] == '/') {
601
 
                        portname = &argv[0][i+1];
602
 
                        break;
603
 
                }
604
 
 
605
 
        if (portname == NULL) {
606
 
                printf ("Unable to abbreviate %s\n", argv[0]);
607
 
                exit (1);
608
 
        }
609
 
 
610
 
        snprintf (statefn, sizeof(statefn), "%s/bestfort-%s", STATEPATH,
611
 
                  portname);
612
 
 
613
 
        open_ups(portname);
614
 
 
615
 
        ups_sync();             /* get a prompt */
616
 
 
617
 
        initinfo();
618
 
        createmsgq();
619
 
 
620
 
#if 0
621
 
        setuphandlers();        /* seems uneeded? */
622
 
#endif
623
 
 
624
 
        ups_ident();            /* run formatconfig command and
625
 
                                   extract fixed information into
626
 
                                   global fc. struct */
627
 
 
628
 
#if 0
629
 
        /* Fortress does automagical testing monthly */
630
 
        addinfo (INFO_INSTCMD, "", 0, CMD_BTEST0);
631
 
        addinfo (INFO_INSTCMD, "", 0, CMD_BTEST1);
632
 
#endif
633
 
 
634
 
        printf ("Detected %s %s on %s\n", 
635
 
                getdata(INFO_MFR), 
636
 
                getdata(INFO_MODEL), 
637
 
                argv[0]);
638
 
 
639
 
        if (!debugging)
640
 
          background();
641
 
 
642
 
        for (;;) {
643
 
          ups_update();
644
 
          
645
 
          if (getupsmsg(2))       /* TODO: remove debug scaffolding */
646
 
            upslogx(LOG_INFO, "Received a message from upsd\n");
647
 
          
648
 
        }
649
 
 
650
 
        return 0;
651
 
}
652
 
 
653
 
 
654
 
#if 0
655
 
void instcmd (int auxcmd, int dlen, char *data)
656
 
{
657
 
  assert(0);
658
 
 
659
 
        /* TODO: reply to upsd? */
660
 
 
661
 
        switch (auxcmd) {
662
 
                case CMD_BTEST0:        /* stop battery test */
663
 
                        break;
664
 
                case CMD_BTEST1:        /* start battery test */
665
 
                        break;
666
 
                default:
667
 
                        upslogx(LOG_INFO, "instcmd: unknown type 0x%04x\n",
668
 
                                auxcmd);
669
 
        }
670
 
}
671
 
 
672
 
void setuphandlers()
673
 
{
674
 
  assert(0);
675
 
  /*    upsh.instcmd = instcmd; */
676
 
}
677
 
#endif /* 0 */
678