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

« back to all changes in this revision

Viewing changes to models/upseyeux.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
 
/* The attached microdowell.h has also textual details about what this * program does, the
2
 
 copyrights and such.  */
3
 
 
4
 
#define INFO_MAX 16
5
 
 
6
 
#include "upseyeux.h"
7
 
 
8
 
static int ups_model_ok (char *buf, unsigned buflen);
9
 
static int polling_ok (char *buf, unsigned buflen);
10
 
static int read_raw_data (int upsfd, char *buf, int buflen);
11
 
 
12
 
void set_flag (int *val, int flag)
13
 
{
14
 
        *val = (*val |= flag);
15
 
}
16
 
        
17
 
void clear_flag (int *val, int flag)  
18
 
{
19
 
        *val = (*val ^= (*val & flag));
20
 
}
21
 
 
22
 
int is_set (int num, int flag)
23
 
{
24
 
        return ((num & flag) == flag);
25
 
}
26
 
 
27
 
static int setupstime ()
28
 
{
29
 
        time_t          now;
30
 
        struct tm       *timeptr;
31
 
        unsigned char   upshour;
32
 
        
33
 
        time (&now);
34
 
        timeptr = localtime (&now);
35
 
 
36
 
        if (upssendchar (CMD_SETTIMER) != 1)
37
 
                return (-1);
38
 
        usleep (CHAR_DELAY);
39
 
        upshour = (unsigned char) ((timeptr->tm_wday - 1) * 24 + timeptr->tm_hour);
40
 
        if (upssendchar (upshour) != 1)
41
 
                return (-1);
42
 
        usleep (CHAR_DELAY);
43
 
        if (upssendchar ((unsigned char)timeptr->tm_min) != 1)
44
 
                return (-1);
45
 
        usleep (CHAR_DELAY);
46
 
        if (upssendchar ((unsigned char)timeptr->tm_sec) != 1)
47
 
                return (-1);
48
 
        usleep (CHAR_DELAY);
49
 
        
50
 
        return (1);     
51
 
}
52
 
 
53
 
/* power down the attached load immediately */
54
 
static int forceshutdown (unsigned int sddelay)
55
 
{
56
 
        unsigned char data;
57
 
        
58
 
        printf ("Initiating forced UPS shutdown!\n");
59
 
        
60
 
        if (upssendchar (CMD_SCHEDULING) != 1)
61
 
                return (-1);
62
 
        usleep (CHAR_DELAY);
63
 
        
64
 
        data = 255;
65
 
        if (upssendchar (data) != 1)
66
 
                return (-1);
67
 
        usleep (CHAR_DELAY);
68
 
        
69
 
        data = 0;
70
 
        if (upssendchar (data) != 1)
71
 
                return (-1);
72
 
        usleep (CHAR_DELAY);
73
 
        
74
 
        data = 255;
75
 
        if (upssendchar (data) != 1)
76
 
                return (-1);
77
 
        usleep (CHAR_DELAY);
78
 
        
79
 
        if (sddelay == 0)
80
 
                sddelay = 60;
81
 
        if ((myups.upsmodel > 21) && (myups.upsmodel <100))
82
 
                sddelay = sddelay / 2 + 1;
83
 
        else if (myups.upsmodel > 130) 
84
 
                sddelay = sddelay / 4 + 1;
85
 
        
86
 
        data = (unsigned char)sddelay;
87
 
        if (upssendchar (data) != 1)
88
 
                return (-1);
89
 
        usleep (CHAR_DELAY);
90
 
        
91
 
        data = 0;
92
 
        if (upssendchar (data) != 1)
93
 
                return (-1);
94
 
        sleep (2);
95
 
        
96
 
        if (upssendchar (CMD_STDBY) != 1)
97
 
                return (-1);
98
 
        usleep (CHAR_DELAY);
99
 
        if (is_set(myups.status, ST_ONBATT)) {
100
 
                if (upssendchar (CMD_BEND) != 1)
101
 
                        return (-1);
102
 
                usleep (CHAR_DELAY);
103
 
        }
104
 
 
105
 
        exit (1);
106
 
}
107
 
 
108
 
static void help (const char *prog)
109
 
{
110
 
        printf ("usage:\n"
111
 
                "\t%s [-h]\n"
112
 
                "\t%s [-d <num>] -k <device>\n"
113
 
                "\t%s [-l <num>] [-b <num>] <device>\n", prog, prog, prog);
114
 
        printf ("\n"
115
 
                "    -h       - display this help\n"
116
 
                "\n"
117
 
                "    -d <num> - wait <num> seconds after sending shutdown command\n"
118
 
                "    -k       - force shutdown\n"
119
 
                "\n"
120
 
                "    -l <num> - line voltage. Default is 230 (volts)\n"
121
 
                "    -b <num> - battery run time (s) \n"
122
 
                "\n"
123
 
                "    <device> - /dev entry corresponding to UPS port\n"
124
 
                "\n");
125
 
        exit (0);
126
 
}
127
 
 
128
 
static void initinfo (char *ident, char *model, char *serial_num)
129
 
{
130
 
        unsigned char   i, ret;
131
 
        int             ret0 = 0;
132
 
        char            raw_data[NUM_OF_BYTES_FROM_UPS];
133
 
 
134
 
        create_info(INFO_MAX, SHMOK);
135
 
 
136
 
        /* write constant data for this model */
137
 
        
138
 
        addinfo (INFO_MFR, "MicroDowell", FLAG_STRING, 12);
139
 
 
140
 
        for (i = 0; (i < 5) && (ret0 == 0); i++) 
141
 
        {
142
 
                if (upssendchar (SEND_MODEL) != 1) { 
143
 
                        /* upslogx(LOG_NOTICE, "%s writing error", argv[0]); */
144
 
                } else {
145
 
                        ret = read_raw_data(upsfd, raw_data, NUM_MODEL_BYTES);
146
 
                        ret0 = ups_model_ok(raw_data, ret);
147
 
                }
148
 
        }
149
 
        if (ret0 == 0) {
150
 
                printf ("Unable to identify MicroDowell UPS connected: %d \n",ret0);
151
 
                fatalx("Unable to identify MicroDowell UPS connected");
152
 
        } else {
153
 
                myups.upsmodel = ret0;
154
 
                ret0 = 0;
155
 
                for (i = 0; (i < 5) && (ret0 == 0); i++) 
156
 
                {
157
 
                        if (upssendchar (SEND_DATA) != 1) { 
158
 
                                /* upslogx(LOG_NOTICE, "%s writing error", argv[0]); */
159
 
                        } else {
160
 
                                ret = read_raw_data(upsfd, raw_data, NUM_POLLING_BYTES);
161
 
                                ret0 = polling_ok(raw_data, ret);
162
 
                        }
163
 
                }       
164
 
        }
165
 
        
166
 
        if (ret0 == 0) {
167
 
                printf ("Unable to communicate with MicroDowell UPS connected. \n");
168
 
                fatalx("Unable to communicate with MicroDowell UPS connected");
169
 
        } else {
170
 
                printf ("Communication with MicroDowell UPS started. \n");
171
 
        }
172
 
        
173
 
        /* add other things to monitor */
174
 
 
175
 
        addinfo (INFO_ACFREQ, "", 0, 0);
176
 
        addinfo (INFO_BATTVOLT, "", 0, 0);
177
 
        addinfo (INFO_LOADPCT, "", 0, 0);
178
 
        addinfo (INFO_STATUS, "", 0, 0);
179
 
        addinfo (INFO_UTILITY, "", 0, 0);
180
 
        addinfo (INFO_UPSTEMP, "", 0, 0);
181
 
 
182
 
        /* now add the instant commands */
183
 
 
184
 
        addinfo (INFO_INSTCMD, "", 0, CMD_ON);
185
 
        addinfo (INFO_INSTCMD, "", 0, CMD_OFF);
186
 
        addinfo (INFO_INSTCMD, "", 0, CMD_BTEST1);
187
 
 
188
 
        updateinfo (line_voltage, raw_data);
189
 
}
190
 
 
191
 
void instcmd (int auxcmd, int dlen, char *data)
192
 
{
193
 
        /* TODO: reply to upsd? */
194
 
        switch (auxcmd) {
195
 
                case CMD_ON:        
196
 
                        break;
197
 
                case CMD_OFF:        
198
 
                        break;
199
 
                case CMD_BTEST1:
200
 
                        if (upssendchar (CMD_BATTEST) != 1)
201
 
                                printf ("Unable to start battery test \n");
202
 
                        break;
203
 
                default:
204
 
                        upslogx(LOG_INFO, "instcmd: unknown type 0x%04x",
205
 
                                auxcmd);
206
 
        }
207
 
}
208
 
 
209
 
static int ups_model_ok (char *buf, unsigned buflen)
210
 
{
211
 
        char upsSerial[5];
212
 
        int upsRelease = 0;
213
 
        
214
 
        if ((buflen==NUM_MODEL_BYTES) && (buf[0]==91) &&
215
 
            (buf[NUM_MODEL_BYTES-1]==93) && (buf[1]==10))
216
 
        {
217
 
                if ((buf[2] == 'S') && (buf[3] == 'H'))
218
 
                {
219
 
                        upsRelease = (buf[4] - '0') * 10 + buf[6] - '0';
220
 
                        if (upsRelease < 40)
221
 
                                addinfo (INFO_MODEL, "BBox Pro PnP", FLAG_STRING, 12);
222
 
                        else
223
 
                                addinfo (INFO_MODEL, "BBox Pro USB", FLAG_STRING, 12);
224
 
                        sprintf (upsSerial, "SH%c.%c", buf[4], buf[6]);
225
 
                        addinfo (INFO_SERIAL, upsSerial, FLAG_STRING, 5);
226
 
                        return (100 + upsRelease);
227
 
                }
228
 
                else if ((buf[2] == 'M') && (buf[3] == 'D'))
229
 
                {
230
 
                        upsRelease = (buf[4] - '0') * 10 + buf[6] - '0';
231
 
                        if (upsRelease < 30)
232
 
                                addinfo (INFO_MODEL, "BBox Interactive PnP", FLAG_STRING, 20);
233
 
                        else
234
 
                                addinfo (INFO_MODEL, "BBox Interactive USB", FLAG_STRING, 20);
235
 
                        sprintf (upsSerial, "MD%c.%c", buf[4], buf[6]);
236
 
                        addinfo (INFO_SERIAL, upsSerial, FLAG_STRING, 5);
237
 
                        return (upsRelease);
238
 
                }
239
 
                else if ((buf[2] == 'B') && (buf[3] == '5'))
240
 
                {
241
 
                        upsRelease = (buf[4] - '0') * 10 + buf[6] - '0';
242
 
                        addinfo (INFO_MODEL, "HiBox USB", FLAG_STRING, 9);
243
 
                        sprintf (upsSerial, "B5%c.%c", buf[4], buf[6]);                 
244
 
                        addinfo (INFO_SERIAL, upsSerial, FLAG_STRING, 5);
245
 
                        return (upsRelease);
246
 
                }
247
 
                else       
248
 
                        return (0);
249
 
        }
250
 
        else
251
 
                return (0);
252
 
}
253
 
 
254
 
 
255
 
static int polling_ok (char *buf, unsigned buflen)
256
 
{
257
 
        if ((buflen==NUM_POLLING_BYTES) && (buf[0]==91) && 
258
 
            (buf[NUM_POLLING_BYTES-1]==93) && (buf[1]==1))
259
 
        {
260
 
                return (1);
261
 
        }
262
 
        else
263
 
        {
264
 
                return (0);
265
 
        }
266
 
}
267
 
 
268
 
/* wait for buflen bytes from upsfd and store in buf */
269
 
static int read_raw_data (int upsfd, char *buf, int buflen)
270
 
{
271
 
        int     counter = 0;
272
 
        int     ret;
273
 
        struct  sigaction sa;
274
 
        sigset_t sigmask;
275
 
 
276
 
        sa.sa_handler = timeout;
277
 
        sigemptyset (&sigmask);
278
 
        sa.sa_mask = sigmask;
279
 
        sa.sa_flags = 0;
280
 
        sigaction (SIGALRM, &sa, NULL);
281
 
 
282
 
        alarm (3);
283
 
 
284
 
        for (counter = 0; counter < buflen; counter++) 
285
 
        {
286
 
                
287
 
                ret = (read (upsfd, buf + counter, 1));
288
 
                sleep (0);
289
 
                alarm (0);
290
 
                signal (SIGALRM, SIG_IGN);
291
 
                if (ret < 0) {
292
 
                        return counter;
293
 
                }
294
 
                else {
295
 
                }
296
 
        }
297
 
        nolongertimeout();
298
 
        return counter;
299
 
}
300
 
                        
301
 
static void setuphandlers(void)
302
 
{
303
 
        upsh.instcmd = instcmd;
304
 
}
305
 
 
306
 
static void updateinfo (unsigned int line_voltage, char *raw_data)
307
 
{
308
 
        char    val[32];
309
 
        unsigned char loadpct;
310
 
        
311
 
        myups.acfreq = 61440.0 / ((255 - (unsigned char)raw_data[ACFREQ_H]) * 256 + (256 - (unsigned char)raw_data[ACFREQ_L]));
312
 
        setinfo(INFO_ACFREQ, "%04.1f", myups.acfreq); 
313
 
 
314
 
        myups.utility = 1.84 * (unsigned char)raw_data[UTILITY]; 
315
 
        setinfo(INFO_UTILITY, "%05.1f", myups.utility);
316
 
 
317
 
        myups.battvolt = (1.0 * (unsigned char)raw_data[BATTVOLT]) / 16.82;
318
 
        if (myups.upsmodel > 100)
319
 
                myups.battvolt *= 2.0;
320
 
        setinfo(INFO_BATTVOLT, "%05.2f", myups.battvolt);
321
 
        
322
 
        myups.loadpct = 0;
323
 
        if (myups.upsmodel > 100)
324
 
        {
325
 
                *val = 0;
326
 
                loadpct = (unsigned char)raw_data[LOADPCT];
327
 
                if (loadpct < LOAD_T0)
328
 
                {
329
 
                        strcat(val, "0  ");
330
 
                }
331
 
                else if ((loadpct >= LOAD_T0) && (loadpct < LOAD_T1))
332
 
                {
333
 
                        strcat(val, "25 ");
334
 
                        myups.loadpct += 25;
335
 
                }
336
 
                else if ((loadpct >= LOAD_T1) && (loadpct < LOAD_T2))
337
 
                {
338
 
                        strcat(val, "50 ");
339
 
                        myups.loadpct += 50;
340
 
                }
341
 
                else if ((loadpct >= LOAD_T2) && (loadpct < LOAD_T3))
342
 
                {
343
 
                        strcat(val, "75 ");
344
 
                        myups.loadpct += 75;
345
 
                }
346
 
                else if ((loadpct >= LOAD_T3) && (loadpct < LOAD_T4))
347
 
                {
348
 
                        strcat(val, "100");
349
 
                        myups.loadpct += 100;
350
 
                }
351
 
                else if (loadpct >= LOAD_T4) 
352
 
                {
353
 
                        strcat(val, "120");
354
 
                        myups.loadpct += 120;
355
 
                }
356
 
                setinfo(INFO_LOADPCT, "%s", val);
357
 
        }
358
 
        else
359
 
        {
360
 
                *val = 0;
361
 
                myups.upstemp = 27.0;
362
 
                strcat(val, "27.0");
363
 
                setinfo(INFO_UPSTEMP, "%s", val);
364
 
        }
365
 
        
366
 
        myups.upshour = (unsigned char)raw_data[UPS_HOUR];
367
 
        myups.upsmin = (unsigned char)raw_data[UPS_MIN];
368
 
        myups.upssec = (unsigned char)raw_data[UPS_SEC];
369
 
        myups.houron = (unsigned char)raw_data[UPS_HOUR_ON];
370
 
        myups.minon = (unsigned char)raw_data[UPS_MIN_ON];
371
 
        myups.houroff = (unsigned char)raw_data[UPS_HOUR_OFF];
372
 
        myups.sddelay = (unsigned char)raw_data[SD_DELAY];
373
 
 
374
 
        *val = 0;
375
 
        
376
 
        if (!(raw_data[STATUS] & MAINS_FAILURE))
377
 
        {
378
 
                strcat(val, "OL ");
379
 
                myups.battruntime = 0;
380
 
                if (!is_set(myups.status, ST_ONLINE))
381
 
                {
382
 
                        set_flag (&myups.status, ST_ONLINE);
383
 
                        clear_flag (&myups.status, ST_ONBATT);
384
 
                }
385
 
        }
386
 
        else 
387
 
        {
388
 
                strcat(val, "OB ");
389
 
                if (!is_set(myups.status, ST_ONBATT))
390
 
                {
391
 
                        set_flag (&myups.status, ST_ONBATT);
392
 
                        clear_flag (&myups.status, ST_ONLINE);
393
 
                }
394
 
                if (myups.maxbattruntime > 0) {
395
 
                        if (++myups.battruntime > myups.maxbattruntime) {
396
 
                                strcat(val, "LB ");
397
 
                                set_flag (&myups.status, ST_LOWBATT);
398
 
                        }
399
 
                                
400
 
                }
401
 
        }
402
 
        
403
 
        if (raw_data[STATUS] & LOW_BAT)
404
 
        {
405
 
                strcat(val, "LB ");
406
 
                if (!is_set(myups.status, ST_LOWBATT))
407
 
                {
408
 
                        set_flag (&myups.status, ST_LOWBATT);
409
 
                }
410
 
        }
411
 
        if (raw_data[STATUS] & END_BAT)
412
 
                strcat(val, "EB ");
413
 
 
414
 
        if (raw_data[STATUS] & HIGH_TEMP)
415
 
                strcat(val, "HT ");
416
 
 
417
 
        if (raw_data[STATUS] & DANGER_TEMP)
418
 
                strcat(val, "DT ");
419
 
 
420
 
        *(val + strlen(val)) = 0;
421
 
        setinfo(INFO_STATUS, "%s", val);
422
 
        
423
 
        writeinfo();
424
 
}
425
 
 
426
 
 
427
 
int main (int argc, char **argv)
428
 
{
429
 
        char            *portname, *prog,
430
 
                        *ups_model = 0, *ups_serial_num = 0,
431
 
                        *ups_ident = 0;
432
 
        char            raw_data[NUM_OF_BYTES_FROM_UPS];
433
 
        int             i, shutdown_now = 0;
434
 
        unsigned int    numpollko = 0;
435
 
        unsigned int    pollcount = 0;
436
 
        
437
 
        printf ("Network UPS Tools - MicroDowell UPS driver 0.01 (%s)\n",
438
 
                                                                UPS_VERSION);
439
 
        openlog ("MicroDowell", LOG_CONS | LOG_PID, LOG_FACILITY);
440
 
 
441
 
        prog = argv[0];
442
 
 
443
 
        if (argc == 1)
444
 
                help (prog);
445
 
 
446
 
        while ((i = getopt(argc, argv, "+hkd:l:b:")) != EOF) {
447
 
                switch (i) {
448
 
                        case 'd':                                
449
 
                                sddelay = atoi (optarg);
450
 
                                break;
451
 
                        case 'k':
452
 
                                shutdown_now = 1;
453
 
                                break;
454
 
                        case 'l':
455
 
                                line_voltage = atoi(optarg);
456
 
                                break;
457
 
                        case 'b':
458
 
                                myups.maxbattruntime = atoi(optarg);
459
 
                                if (myups.maxbattruntime > 0)
460
 
                                        myups.maxbattruntime /= 2;      
461
 
                                break;
462
 
                        case 'h':
463
 
                                help(prog);
464
 
                                break;
465
 
                        default:
466
 
                                help (prog);
467
 
                                break;
468
 
                }
469
 
        }
470
 
 
471
 
        argc -= optind;
472
 
        argv += optind;
473
 
 
474
 
        droproot(); 
475
 
 
476
 
        portname = NULL;
477
 
        for (i = strlen(argv[0]); i >= 0; i--)
478
 
                if (argv[0][i] == '/') {
479
 
                        portname = &argv[0][i+1];
480
 
                        break;
481
 
                }
482
 
 
483
 
        if (portname == NULL)
484
 
                fatalx("Unable to abbreviate %s", argv[0]);
485
 
 
486
 
        open_serial (argv[0], B1200);
487
 
        
488
 
        snprintf (statefn, sizeof(statefn), "%s/microdowell-%s", STATEPATH,
489
 
                  portname);
490
 
        
491
 
        initinfo(ups_ident, ups_model, ups_serial_num);
492
 
 
493
 
        if (shutdown_now)
494
 
                forceshutdown (sddelay);
495
 
        
496
 
        createmsgq();           /* try to create IPC message queue */
497
 
 
498
 
        setuphandlers();
499
 
 
500
 
        background();
501
 
 
502
 
        if (setupstime () < 0)
503
 
                printf ("Unable to set timer \n");
504
 
        for (;;) {
505
 
                if (upssendchar (SEND_DATA) != 1) { 
506
 
                        upslogx(LOG_NOTICE, "%s writing error", argv[0]);
507
 
                        numpollko++;
508
 
                }
509
 
                else if (read_raw_data(upsfd, raw_data,NUM_POLLING_BYTES) == NUM_POLLING_BYTES) {
510
 
                        if (polling_ok (raw_data, NUM_POLLING_BYTES) == 1) {
511
 
                                if (is_set(myups.status, ST_BADCOM)) {
512
 
                                        clear_flag (&myups.status, ST_BADCOM);                          
513
 
                                        printf ("UPS communication established \n");
514
 
                                } 
515
 
                                updateinfo (line_voltage, raw_data);
516
 
                                numpollko = 0;
517
 
                        }
518
 
                        else {
519
 
                                numpollko++;
520
 
                        }
521
 
                }
522
 
                else {
523
 
                        numpollko++;
524
 
                }
525
 
                if (numpollko > NUM_POLLS_KO) {
526
 
                        numpollko = 0;
527
 
                        if (!is_set(myups.status, ST_BADCOM)) {
528
 
                                myups.status = 0;
529
 
                                set_flag (&myups.status, ST_BADCOM);
530
 
                                printf ("UPS communication lost \n");
531
 
                        } 
532
 
                }
533
 
                if (++pollcount >= 1800) {
534
 
                        if (setupstime () < 0)
535
 
                                printf ("Unable to set timer \n");
536
 
                        pollcount = 0;
537
 
                }
538
 
                
539
 
                /* wait up to 2 seconds for a message from the upsd */
540
 
                if (getupsmsg(2))
541
 
                        upslogx(LOG_INFO, "Received a message from upsd");
542
 
        }
543
 
}