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

« back to all changes in this revision

Viewing changes to drivers/metasys.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Quette
  • Date: 2005-10-07 23:35:55 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051007233555-yreo209eww1bo665
Tags: 2.0.2-2
* debian/nut-cgi.postinst: load confmodule
* debian/nut-hidups/*: remove this unneeded directory
* debian/control:
  - Update build dependency from libsnmp5-dev to libsnmp9-dev (closes:
  #326410)
  - Changes nut-usb wrong dependency from libusb-dev to libusb-0.1-4 (closes:
  #320315)
  - add debconf (>= 0.5.00) and adduser to nut/nut-cgi Depends
* debian/copyright: update the FSF address and the Authors
* debian/po/vi.po: add the Vietnamese translation for debconf, from Clytie
  Siddall ((closes: #316327)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   metasys.c - driver for Meta System UPS
 
3
 
 
4
   Copyright (C) 2004  Fabio Di Niro <fabio.diniro@email.it>
 
5
 
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 2 of the License, or
 
9
   (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program; if not, write to the Free Software
 
18
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
19
*/
 
20
 
 
21
/* Uncomment if you want to read additional Meta System UPS data */
 
22
/* 
 
23
#define EXTRADATA 
 
24
*/
 
25
 
 
26
#include "main.h"
 
27
#include "serial.h"
 
28
#include <string.h>
 
29
 
 
30
 
 
31
#define DRV_VERSION     "0.05"
 
32
 
 
33
/* Autorestart flag */
 
34
int autorestart = 0;
 
35
int nominal_power = 0;
 
36
 
 
37
/* ups commands */
 
38
#define UPS_INFO                        0x00
 
39
#define UPS_OUTPUT_DATA                 0x01
 
40
#define UPS_INPUT_DATA                  0x02
 
41
#define UPS_STATUS                      0x03
 
42
#define UPS_BATTERY_DATA                0x04
 
43
#define UPS_HISTORY_DATA                0x05
 
44
#define UPS_GET_SCHEDULING              0x06
 
45
#define UPS_EVENT_LIST                  0x07
 
46
#define UPS_GET_TIMES_ON_BATTERY        0x08
 
47
#define UPS_GET_NEUTRAL_SENSE           0x09
 
48
#define UPS_SET_SCHEDULING              0x0a
 
49
#define UPS_SET_NEUTRAL_SENSE           0x0b
 
50
#define UPS_SET_TIMES_ON_BATTERY        0x0c
 
51
#define UPS_SET_BUZZER_MUTE             0x0d
 
52
#define UPS_SET_BATTERY_TEST            0x0e
 
53
 
 
54
static int instcmd(const char *cmdname, const char *extra);
 
55
 
 
56
/*
 
57
        Metasystem UPS data transfer are made with packet of the format:
 
58
        STX             DATA_LENGHT             DATA            CHECKSUM
 
59
        where:
 
60
        STX is 0x02 and is the start of transmission byte
 
61
        DATA_LENGHT is number of data bytes + the checksum byte
 
62
        DATA ......
 
63
        CHECKSUM is the sum modulus 256 of all DATA bytes + DATA_LENGHT
 
64
        
 
65
        The answer from the UPS have the same packet format and the first
 
66
        data byte is equal to the command that the ups is answering to
 
67
*/
 
68
int get_word(char *buffer) {            /* return an integer reading a word in the supplied buffer */
 
69
        unsigned char a, b;
 
70
        int result;
 
71
        
 
72
        a = buffer[0];
 
73
        b = buffer[1];
 
74
        result = b*256 + a;
 
75
        return result;
 
76
}
 
77
 
 
78
 
 
79
long int get_long(char *buffer) {       /* return a long integer reading 4 bytes in the supplied buffer */
 
80
        unsigned char a, b, c, d;
 
81
        long int result;
 
82
        a=(unsigned char)buffer[0];
 
83
        b=(unsigned char)buffer[1];
 
84
        c=(unsigned char)buffer[2];
 
85
        d=(unsigned char)buffer[3];
 
86
        result = (256*256*256*d) + (256*256*c) + (256*b) + a;
 
87
        return result;
 
88
}       
 
89
        
 
90
void send_zeros() {                             /* send 100 times the value 0x00.....it seems to be used for resetting */
 
91
        char buf[100];                          /* the ups serial port */
 
92
        int i;
 
93
        
 
94
        memset(buf, '\0', sizeof(buf));
 
95
        i = ser_send_buf(upsfd, buf, sizeof(buf));
 
96
        return;
 
97
}
 
98
 
 
99
 
 
100
/* was used just for the debug process */
 
101
void dump_buffer(char *buffer, int buf_len) {
 
102
        int i;
 
103
        for (i = 0; i < buf_len; i++) { 
 
104
                printf("byte %d: %x\n", i, (unsigned char)buffer[i]);   
 
105
        }       
 
106
        return;
 
107
}
 
108
 
 
109
/* send a read command to the UPS, it retries 5 times before give up
 
110
   it's a 4 byte request (STX, LENGHT, COMMAND and CHECKSUM) */
 
111
void send_read_command(char command) {
 
112
        int retry, sent;
 
113
        char buf[4];
 
114
        retry = 0;
 
115
        sent = 0;
 
116
        while ((sent != 4) && (retry < 5)) {
 
117
                buf[0]=0x02;                    /* STX Start of Transmission */
 
118
                buf[1]=0x02;                    /* data lenght(data + checksum byte) */
 
119
                buf[2]=command;                 /* command to send */
 
120
                buf[3]=buf[1] + buf[2]; /* checksum (sum modulus 256 of data bytes + lenght) */
 
121
                if (retry == 4) send_zeros();   /* last retry is preceded by a serial reset...*/
 
122
                sent = ser_send_buf(upsfd, buf, 4);
 
123
                retry += 1;
 
124
        }       
 
125
}
 
126
 
 
127
/* send a write command to the UPS, the write command and the value to be written are passed 
 
128
   with a char* buffer 
 
129
   it retries 5 times before give up */
 
130
void send_write_command(char *command, int command_lenght) {
 
131
        int i, retry, sent, checksum;
 
132
        char raw_buf[255];
 
133
        
 
134
        /* prepares the raw data */
 
135
        raw_buf[0] = 0x02;              /* STX byte */
 
136
        raw_buf[1] = (unsigned char)(command_lenght + 1);               /* data lenght + checksum */
 
137
        memcpy(raw_buf+2, command, command_lenght);
 
138
        command_lenght += 2;
 
139
        
 
140
        /* calculate checksum */
 
141
        checksum = 0;
 
142
        for (i = 1; i < command_lenght; i++) checksum += (unsigned char)raw_buf[i];
 
143
        checksum = checksum % 256;
 
144
        raw_buf[command_lenght] = (unsigned char)checksum;
 
145
        command_lenght +=1;
 
146
        
 
147
        retry = 0;
 
148
        sent = 0;
 
149
        while ((sent != (command_lenght)) && (retry < 5)) {
 
150
                if (retry == 4) send_zeros();   /* last retry is preceded by a serial reset... */
 
151
                sent = ser_send_buf(upsfd, raw_buf, (command_lenght));
 
152
                if (sent != (command_lenght)) printf("Error sending command %d\n", (unsigned char)raw_buf[2]);
 
153
                retry += 1;
 
154
        }       
 
155
}
 
156
 
 
157
 
 
158
/* get the answer of a command from the ups */
 
159
int get_answer(char *data) {
 
160
        char my_buf[255];       /* packet has a maximum lenght of 256 bytes */
 
161
        int packet_lenght, checksum, i, res;
 
162
        /* Read STX byte */
 
163
        res = ser_get_char(upsfd, my_buf, 1, 0);
 
164
        if (res != 1) {
 
165
                ser_comm_fail("Receive error (STX): %d!!!\n", res);
 
166
                return -1;      
 
167
        }
 
168
        if ((unsigned char)my_buf[0] != 0x02) {
 
169
                ser_comm_fail("Receive error (STX): packet not on start!!\n");
 
170
                return -1;      
 
171
        }
 
172
        /* Read data lenght byte */
 
173
        res = ser_get_char(upsfd, my_buf, 1, 0);
 
174
        if (res != 1) {
 
175
                ser_comm_fail("Receive error (lenght): %d!!!\n", res);
 
176
                return -1;      
 
177
        }
 
178
        packet_lenght = (unsigned char)my_buf[0];
 
179
        if (packet_lenght < 2) {
 
180
                ser_comm_fail("Receive error (lenght): packet lenght %d!!!\n", packet_lenght);
 
181
                return -1;      
 
182
        }
 
183
        /* Try to read all the remainig bytes (packet_lenght) */
 
184
        res = ser_get_buf_len(upsfd, my_buf, packet_lenght, 1, 0);
 
185
        if (res != packet_lenght) {
 
186
                ser_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res, packet_lenght);
 
187
                return -1;      
 
188
        }
 
189
                
 
190
        /* now we have the whole answer from the ups, we can checksum it 
 
191
           checksum byte is equal to the sum modulus 256 of all the data bytes + packet_lenght 
 
192
           (no STX no checksum byte itself) */
 
193
        checksum = packet_lenght;
 
194
        for (i = 0; i < (packet_lenght - 1); i++) checksum += (unsigned char)my_buf[i];  
 
195
        checksum = checksum % 256;
 
196
        if ((unsigned char)my_buf[packet_lenght-1] != checksum) {
 
197
                ser_comm_fail("checksum error! got %x instad of %x, received %d bytes \n", (unsigned char)my_buf[packet_lenght - 1], checksum, packet_lenght);
 
198
                dump_buffer(my_buf, packet_lenght);
 
199
                return -1;
 
200
        }
 
201
        packet_lenght-=1;               /* get rid of the checksum byte */
 
202
        memcpy(data, my_buf, packet_lenght);
 
203
        return packet_lenght;
 
204
}
 
205
 
 
206
/* send a read command and try get the answer, if something fails, it retries (5 times max)
 
207
   if it is on the 4th or 5th retry, it will flush the serial before sending commands
 
208
   it returns the lenght of the received answer or -1 in case of failure */
 
209
int command_read_sequence(char command, char *data) {
 
210
        int bytes_read = 0;
 
211
        int retry = 0;
 
212
        
 
213
        while ((bytes_read < 1) && (retry < 5)) {
 
214
                send_read_command(command);
 
215
                bytes_read = get_answer(data);
 
216
                if (retry > 2) ser_flush_in(upsfd, "", 0);
 
217
                retry += 1;
 
218
        }
 
219
        if (((unsigned char)data[0] != command) || (retry == 5)) {
 
220
                ser_comm_fail("Error executing command %d\n", command);
 
221
                return -1;
 
222
                dstate_datastale();
 
223
        }
 
224
        ser_comm_good();
 
225
        return bytes_read;
 
226
}
 
227
 
 
228
/* send a write command and try get the answer, if something fails, it retries (5 times max)
 
229
   if it is on the 4th or 5th retry, it will flush the serial before sending commands
 
230
   it returns the lenght of the received answer or -1 in case of failure */
 
231
int command_write_sequence(char *command, int command_lenght, char *answer) {
 
232
        int bytes_read = 0;
 
233
        int retry = 0;
 
234
        
 
235
        while ((bytes_read < 1) && (retry < 5)) {
 
236
                send_write_command(command, command_lenght);
 
237
                bytes_read = get_answer(answer);
 
238
                if (retry > 2) ser_flush_in(upsfd, "", 0);
 
239
                retry += 1;
 
240
        }
 
241
        if (((unsigned char)answer[0] != (unsigned char)command[0]) || (retry == 5)) {
 
242
                ser_comm_fail("Error executing command N.%d\n", (unsigned char)command[0]);
 
243
                dstate_datastale();
 
244
                return -1;
 
245
        }
 
246
        ser_comm_good();
 
247
        return bytes_read;
 
248
}
 
249
 
 
250
void upsdrv_initinfo(void)
 
251
{
 
252
        char my_answer[255], serial[13];
 
253
        int res, i;
 
254
 
 
255
        /* Initial setup of variables */
 
256
#ifdef EXTRADATA
 
257
         dstate_setinfo("output.power", "%d", -1);
 
258
        dstate_setflags("output.power", ST_FLAG_RW);
 
259
#endif
 
260
         dstate_setinfo("output.voltage", "%d", -1);
 
261
        dstate_setflags("output.voltage", ST_FLAG_RW);
 
262
         dstate_setinfo("output.current", "%d", -1);
 
263
        dstate_setflags("output.current", ST_FLAG_RW);
 
264
#ifdef EXTRADATA
 
265
         dstate_setinfo("output.current.peak", "%2.2f", -1);    
 
266
        dstate_setflags("output.current.peak", ST_FLAG_RW);
 
267
         dstate_setinfo("input.power", "%d", -1);
 
268
        dstate_setflags("input.power", ST_FLAG_RW);
 
269
#endif
 
270
         dstate_setinfo("input.voltage", "%d", -1);
 
271
        dstate_setflags("input.voltage", ST_FLAG_RW);
 
272
#ifdef EXTRADATA
 
273
         dstate_setinfo("input.current", "%2.2f", -1);
 
274
        dstate_setflags("input.current", ST_FLAG_RW);
 
275
         dstate_setinfo("input.current.peak", "%2.2f", -1);     
 
276
        dstate_setflags("input.current.peak", ST_FLAG_RW);
 
277
#endif
 
278
         dstate_setinfo("battery.voltage", "%d", -1);
 
279
        dstate_setflags("battery.voltage", ST_FLAG_RW);
 
280
#ifdef EXTRADATA
 
281
         dstate_setinfo("battery.voltage.low", "%2.2f", -1);
 
282
        dstate_setflags("battery.voltage.low", ST_FLAG_RW);
 
283
         dstate_setinfo("battery.voltage.exhaust", "%2.2f", -1);
 
284
        dstate_setflags("battery.voltage.exhaust", ST_FLAG_RW);
 
285
         dstate_setinfo("ups.total.runtime", "retrieving...");
 
286
        dstate_setflags("ups.total.runtime", ST_FLAG_STRING | ST_FLAG_RW);
 
287
          dstate_setaux("ups.total.runtime", 20);
 
288
         dstate_setinfo("ups.inverter.runtime", "retrieving...");
 
289
        dstate_setflags("ups.inverter.runtime", ST_FLAG_STRING | ST_FLAG_RW);
 
290
          dstate_setaux("ups.inverter.runtime", 20);
 
291
         dstate_setinfo("ups.inverter.interventions", "%d", -1);
 
292
        dstate_setflags("ups.inverter.interventions", ST_FLAG_RW);
 
293
         dstate_setinfo("battery.full.discharges", "%d", -1);
 
294
        dstate_setflags("battery.full.discharges", ST_FLAG_RW);
 
295
         dstate_setinfo("ups.bypass.interventions", "%d", -1);
 
296
        dstate_setflags("ups.bypass.interventions", ST_FLAG_RW);
 
297
         dstate_setinfo("ups.overheatings", "%d", -1);
 
298
        dstate_setflags("ups.overheatings", ST_FLAG_RW);
 
299
#endif
 
300
         dstate_setinfo("ups.load", "%d", -1);
 
301
        dstate_setflags("ups.load", ST_FLAG_RW);
 
302
         dstate_setinfo("ups.delay.shutdown", "%d", -1);
 
303
        dstate_setflags("ups.delay.shutdown", ST_FLAG_RW);
 
304
         dstate_setinfo("ups.delay.start", "%d", -1);
 
305
        dstate_setflags("ups.delay.start", ST_FLAG_RW);
 
306
         dstate_setinfo("ups.temperature", "%d", -1);
 
307
        dstate_setflags("ups.temperature", ST_FLAG_RW);
 
308
         dstate_setinfo("ups.test.result", "not yet done...");
 
309
        dstate_setflags("ups.test.result", ST_FLAG_STRING | ST_FLAG_RW);
 
310
          dstate_setaux("ups.test.result", 20);
 
311
        
 
312
        /* Fixed variables */
 
313
        dstate_setinfo("driver.version.internal", "%s", DRV_VERSION);
 
314
        /* UPS INFO READ */
 
315
        res = command_read_sequence(UPS_INFO, my_answer);
 
316
        if (res < 0) fatal("Could not communicate with the ups");
 
317
        /* the manufacturer is hard coded into the driver, the model type is in the second 
 
318
                byte of the answer, the third byte identifies the model version */
 
319
        dstate_setinfo("ups.mfr", "Meta System");
 
320
        i = (unsigned char)my_answer[1] * 10 + (unsigned char)my_answer[2];
 
321
        switch (i) {    
 
322
                case 11:
 
323
                        dstate_setinfo("ups.model", "%s", "HF Line (1 board)");
 
324
                        nominal_power = 630;
 
325
                        break;
 
326
                case 12:
 
327
                        dstate_setinfo("ups.model", "%s", "HF Line (2 boards)");
 
328
                        nominal_power = 1260;
 
329
                        break;
 
330
                case 13:
 
331
                        dstate_setinfo("ups.model", "%s", "HF Line (3 boards)");
 
332
                        nominal_power = 1890;
 
333
                        break;
 
334
                case 14:
 
335
                        dstate_setinfo("ups.model", "%s", "HF Line (4 boards)");
 
336
                        nominal_power = 2520;
 
337
                        break;
 
338
                case 21:
 
339
                        dstate_setinfo("ups.model", "%s", "ECO Network 750/1000");
 
340
                        nominal_power = 500;
 
341
                        break;  
 
342
                case 22:
 
343
                        dstate_setinfo("ups.model", "%s", "ECO Network 1050/1500");
 
344
                        nominal_power = 700;
 
345
                        break;  
 
346
                case 23:
 
347
                        dstate_setinfo("ups.model", "%s", "ECO Network 1500/2000");
 
348
                        nominal_power = 1000;
 
349
                        break;  
 
350
                case 24:
 
351
                        dstate_setinfo("ups.model", "%s", "ECO Network 1800/2500");
 
352
                        nominal_power = 1200;
 
353
                        break;  
 
354
                case 25:
 
355
                        dstate_setinfo("ups.model", "%s", "ECO Network 2100/3000");
 
356
                        nominal_power = 1400;
 
357
                        break;  
 
358
                case 31:
 
359
                        dstate_setinfo("ups.model", "%s", "ECO 308");
 
360
                        nominal_power = 500;
 
361
                        break;  
 
362
                case 32:
 
363
                        dstate_setinfo("ups.model", "%s", "ECO 311");
 
364
                        nominal_power = 700;
 
365
                        break;  
 
366
                case 44:
 
367
                        dstate_setinfo("ups.model", "%s", "HF Line (4 boards)/2");
 
368
                        nominal_power = 2520;
 
369
                        break;
 
370
                case 45:
 
371
                        dstate_setinfo("ups.model", "%s", "HF Line (5 boards)/2");
 
372
                        nominal_power = 3150;
 
373
                        break;
 
374
                case 46:
 
375
                        dstate_setinfo("ups.model", "%s", "HF Line (6 boards)/2");
 
376
                        nominal_power = 3780;
 
377
                        break;
 
378
                case 47:
 
379
                        dstate_setinfo("ups.model", "%s", "HF Line (7 boards)/2");
 
380
                        nominal_power = 4410;
 
381
                        break;
 
382
                case 48:
 
383
                        dstate_setinfo("ups.model", "%s", "HF Line (8 boards)/2");
 
384
                        nominal_power = 5040;
 
385
                        break;
 
386
                case 51:
 
387
                        dstate_setinfo("ups.model", "%s", "HF Millennium 810");
 
388
                        nominal_power = 700;
 
389
                        break;
 
390
                case 52:
 
391
                        dstate_setinfo("ups.model", "%s", "HF Millennium 820");
 
392
                        nominal_power = 1400;
 
393
                        break;
 
394
                case 61:
 
395
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 910");
 
396
                        nominal_power = 700;
 
397
                        break;
 
398
                case 62:
 
399
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 920");
 
400
                        nominal_power = 1400;
 
401
                        break;
 
402
                case 63:
 
403
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 930");
 
404
                        nominal_power = 2100;
 
405
                        break;
 
406
                case 64:
 
407
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 940");
 
408
                        nominal_power = 2800;
 
409
                        break;
 
410
                case 74:
 
411
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 940/2");
 
412
                        nominal_power = 2800;
 
413
                        break;
 
414
                case 75:
 
415
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 950/2");
 
416
                        nominal_power = 3500;
 
417
                        break;
 
418
                case 76:
 
419
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 960/2");
 
420
                        nominal_power = 4200;
 
421
                        break;
 
422
                case 77:
 
423
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 970/2");
 
424
                        nominal_power = 4900;
 
425
                        break;
 
426
                case 78:
 
427
                        dstate_setinfo("ups.model", "%s", "HF TOP Line 980/2");
 
428
                        nominal_power = 5600;
 
429
                        break;
 
430
                case 81:
 
431
                        dstate_setinfo("ups.model", "%s", "ECO 508");
 
432
                        nominal_power = 500;
 
433
                        break;
 
434
                case 82:
 
435
                        dstate_setinfo("ups.model", "%s", "ECO 511");
 
436
                        nominal_power = 700;
 
437
                        break;
 
438
                case 83:
 
439
                        dstate_setinfo("ups.model", "%s", "ECO 516");
 
440
                        nominal_power = 1000;
 
441
                        break;
 
442
                case 84:
 
443
                        dstate_setinfo("ups.model", "%s", "ECO 519");
 
444
                        nominal_power = 1200;
 
445
                        break;
 
446
                case 85:
 
447
                        dstate_setinfo("ups.model", "%s", "ECO 522");
 
448
                        nominal_power = 1400;
 
449
                        break;
 
450
                case 91:
 
451
                        dstate_setinfo("ups.model", "%s", "ECO 305 / Harviot 530 SX");
 
452
                        nominal_power = 330;
 
453
                        break;
 
454
                case 92:
 
455
                        dstate_setinfo("ups.model", "%s", "ORDINATORE 2");
 
456
                        nominal_power = 330;
 
457
                        break;
 
458
                case 93:
 
459
                        dstate_setinfo("ups.model", "%s", "Harviot 730 SX");
 
460
                        nominal_power = 430;
 
461
                        break;
 
462
                case 101:
 
463
                        dstate_setinfo("ups.model", "%s", "ECO 308 SX / SX Interactive / Ordinatore");
 
464
                        nominal_power = 500;
 
465
                        break;
 
466
                case 102:
 
467
                        dstate_setinfo("ups.model", "%s", "ECO 311 SX / SX Interactive");
 
468
                        nominal_power = 700;
 
469
                        break;
 
470
                case 111:
 
471
                        dstate_setinfo("ups.model", "%s", "ally HF 800 / BI-TWICE 800");
 
472
                        nominal_power = 560;
 
473
                        break;
 
474
                case 112:
 
475
                        dstate_setinfo("ups.model", "%s", "ally HF 1600");
 
476
                        nominal_power = 1120;
 
477
                        break;
 
478
                case 121:
 
479
                        dstate_setinfo("ups.model", "%s", "ally HF 1000 / BI-TWICE 1000");
 
480
                        nominal_power = 700;
 
481
                        break;
 
482
                case 122:
 
483
                        dstate_setinfo("ups.model", "%s", "ally HF 2000");
 
484
                        nominal_power = 1400;
 
485
                        break;
 
486
                case 131:
 
487
                        dstate_setinfo("ups.model", "%s", "ally HF 1250 / BI-TWICE 1250");
 
488
                        nominal_power = 875;
 
489
                        break;
 
490
                case 132:
 
491
                        dstate_setinfo("ups.model", "%s", "ally HF 2500");
 
492
                        nominal_power = 1750;
 
493
                        break;
 
494
                case 141:
 
495
                        dstate_setinfo("ups.model", "%s", "Megaline 1250");
 
496
                        nominal_power = 875;
 
497
                        break;
 
498
                case 142:
 
499
                        dstate_setinfo("ups.model", "%s", "Megaline 2500");
 
500
                        nominal_power = 1750;
 
501
                        break;
 
502
                case 143:
 
503
                        dstate_setinfo("ups.model", "%s", "Megaline 3750");
 
504
                        nominal_power = 2625;
 
505
                        break;
 
506
                case 144:
 
507
                        dstate_setinfo("ups.model", "%s", "Megaline 5000");
 
508
                        nominal_power = 3500;
 
509
                        break;
 
510
                case 154:
 
511
                        dstate_setinfo("ups.model", "%s", "Megaline 5000 / 2");
 
512
                        nominal_power = 3500;
 
513
                        break;
 
514
                case 155:
 
515
                        dstate_setinfo("ups.model", "%s", "Megaline 6250 / 2");
 
516
                        nominal_power = 4375;
 
517
                        break;
 
518
                case 156:
 
519
                        dstate_setinfo("ups.model", "%s", "Megaline 7500 / 2");
 
520
                        nominal_power = 5250;
 
521
                        break;
 
522
                case 157:
 
523
                        dstate_setinfo("ups.model", "%s", "Megaline 8750 / 2");
 
524
                        nominal_power = 6125;
 
525
                        break;
 
526
                case 158:
 
527
                        dstate_setinfo("ups.model", "%s", "Megaline 10000 / 2");
 
528
                        nominal_power = 7000;
 
529
                        break;
 
530
 
 
531
                default:
 
532
                        fatal("Unknown UPS");
 
533
                        break;
 
534
        } 
 
535
                
 
536
        /* Get the serial number */
 
537
        memcpy(serial, my_answer + 7, res - 7);
 
538
        /* serial number start from the 8th byte */
 
539
        serial[12]=0;           /* terminate string */
 
540
        dstate_setinfo("ups.serial", serial);
 
541
        
 
542
        /* get the ups firmware. The major number is in the 5th byte, the minor is in the 6th */
 
543
        dstate_setinfo("ups.firmware", "%u.%u", (unsigned char)my_answer[5], (unsigned char)my_answer[6]);
 
544
 
 
545
        printf("Detected %s [%s] v.%s on %s\n", dstate_getinfo("ups.model"), dstate_getinfo("ups.serial"), dstate_getinfo("ups.firmware"), device_path);
 
546
        
 
547
        /* Add instant commands */
 
548
        dstate_addcmd("shutdown.return");
 
549
        dstate_addcmd("shutdown.stayoff");
 
550
        dstate_addcmd("shutdown.stop");
 
551
        dstate_addcmd("test.failure.start");
 
552
        dstate_addcmd("test.failure.stop");
 
553
        dstate_addcmd("test.battery.start");
 
554
        dstate_addcmd("beeper.on");
 
555
        dstate_addcmd("beeper.off");
 
556
        upsh.instcmd = instcmd;
 
557
        return;
 
558
}
 
559
 
 
560
void upsdrv_updateinfo(void)
 
561
{
 
562
        int res, int_num;
 
563
#ifdef EXTRADATA
 
564
        int day, hour, minute;
 
565
#endif
 
566
        float float_num;
 
567
        long int long_num;
 
568
        char my_answer[255];
 
569
        
 
570
        /* GET Output data */
 
571
        res = command_read_sequence(UPS_OUTPUT_DATA, my_answer);
 
572
        if (res < 0) {
 
573
                printf("Could not communicate with the ups");
 
574
                dstate_datastale();
 
575
        } else {
 
576
                /* Active power */
 
577
                int_num = get_word(&my_answer[1]);
 
578
                if (nominal_power != 0) {
 
579
                        float_num = (float)((int_num * 100)/nominal_power);
 
580
                        dstate_setinfo("ups.load", "%2.1f", float_num);
 
581
                } else {
 
582
                        dstate_setinfo("ups.load", "%s", "not available");
 
583
                }       
 
584
#ifdef EXTRADATA
 
585
                dstate_setinfo("output.power", "%d", int_num);
 
586
#endif
 
587
                /* voltage */
 
588
                int_num = get_word(&my_answer[3]);
 
589
                if (int_num > 0) dstate_setinfo("output.voltage", "%d", int_num);
 
590
                if (int_num == -1) dstate_setinfo("output.voltage", "%s", "overrange");
 
591
                if (int_num == -2) dstate_setinfo("output.voltage", "%s", "not available");
 
592
                /* current */
 
593
                float_num = get_word(&my_answer[5]);
 
594
                if (float_num == -1) dstate_setinfo("output.current", "%s", "overrange");
 
595
                if (float_num == -2) dstate_setinfo("output.current", "%s", "not available");
 
596
                if (float_num > 0) {
 
597
                        float_num = (float)(float_num/10);
 
598
                        dstate_setinfo("output.current", "%2.2f", float_num);
 
599
                }
 
600
#ifdef EXTRADATA
 
601
                /* peak current */
 
602
                float_num = get_word(&my_answer[7]);
 
603
                if (float_num == -1) dstate_setinfo("output.current.peak", "%s", "overrange");
 
604
                if (float_num == -2) dstate_setinfo("output.current.peak", "%s", "not available");
 
605
                if (float_num > 0) {
 
606
                        float_num = (float)(float_num/10);
 
607
                        dstate_setinfo("output.current.peak", "%2.2f", float_num);
 
608
                }
 
609
                
 
610
#endif
 
611
        }
 
612
                
 
613
        /* GET Input data */
 
614
        res = command_read_sequence(UPS_INPUT_DATA, my_answer);
 
615
        if (res < 0){
 
616
                printf("Could not communicate with the ups");
 
617
                dstate_datastale();
 
618
        } else {
 
619
#ifdef EXTRADATA
 
620
                /* Active power */
 
621
                int_num = get_word(&my_answer[1]);
 
622
                if (int_num > 0) dstate_setinfo("input.power", "%d", int_num);
 
623
                if (int_num == -1) dstate_setinfo("input.power", "%s", "overrange");
 
624
                if (int_num == -2) dstate_setinfo("input.power", "%s", "not available");
 
625
#endif
 
626
                /* voltage */
 
627
                int_num = get_word(&my_answer[3]);
 
628
                if (int_num > 0) dstate_setinfo("input.voltage", "%d", int_num);
 
629
                if (int_num == -1) dstate_setinfo("input.voltage", "%s", "overrange");
 
630
                if (int_num == -2) dstate_setinfo("input.voltage", "%s", "not available");
 
631
#ifdef EXTRADATA
 
632
                /* current */
 
633
                float_num = get_word(&my_answer[5]);
 
634
                if (float_num == -1) dstate_setinfo("input.current", "%s", "overrange");
 
635
                if (float_num == -2) dstate_setinfo("input.current", "%s", "not available");
 
636
                if (float_num > 0) {
 
637
                        float_num = (float)(float_num/10);
 
638
                        dstate_setinfo("input.current", "%2.2f", float_num);
 
639
                }
 
640
                /* peak current */
 
641
                float_num = get_word(&my_answer[7]);
 
642
                if (float_num == -1) dstate_setinfo("input.current.peak", "%s", "overrange");
 
643
                if (float_num == -2) dstate_setinfo("input.current.peak", "%s", "not available");
 
644
                if (float_num > 0) {
 
645
                        float_num = (float)(float_num/10);
 
646
                        dstate_setinfo("input.current.peak", "%2.2f", float_num);
 
647
                }
 
648
#endif
 
649
        }
 
650
        
 
651
        
 
652
        /* GET Battery data */
 
653
        res = command_read_sequence(UPS_BATTERY_DATA, my_answer);
 
654
        if (res < 0) {
 
655
                printf("Could not communicate with the ups");
 
656
                dstate_datastale();
 
657
        } else {
 
658
                /* Actual value */
 
659
                float_num = get_word(&my_answer[1]);
 
660
                float_num = (float)(float_num/10);
 
661
                dstate_setinfo("battery.voltage", "%2.2f", float_num);
 
662
#ifdef EXTRADATA
 
663
                /* reserve threshold */
 
664
                float_num = get_word(&my_answer[3]);
 
665
                float_num = (float)(float_num/10);
 
666
                dstate_setinfo("battery.voltage.low", "%2.2f", float_num);
 
667
                /* exhaust threshold */
 
668
                float_num = get_word(&my_answer[5]);
 
669
                float_num = (float)(float_num/10);
 
670
                dstate_setinfo("battery.voltage.exhaust", "%2.2f", float_num);
 
671
#endif
 
672
        }
 
673
        
 
674
#ifdef EXTRADATA
 
675
        /* GET history data */
 
676
        res = command_read_sequence(UPS_HISTORY_DATA, my_answer);
 
677
        if (res < 0) {
 
678
                printf("Could not communicate with the ups");
 
679
                dstate_datastale();
 
680
        } else {
 
681
                /* ups total runtime */
 
682
                long_num = get_long(&my_answer[1]);
 
683
                day = (int)(long_num / 86400);
 
684
                long_num -= (long)(day*86400);
 
685
                hour = (int)(long_num / 3600);
 
686
                long_num -= (long)(hour*3600);
 
687
                minute = (int)(long_num / 60);
 
688
                long_num -= (minute*60);
 
689
                dstate_setinfo("ups.total.runtime", "%d days %dh %dm %lds", day, hour, minute, long_num);
 
690
                
 
691
                /* ups inverter runtime */
 
692
                long_num = get_long(&my_answer[5]);
 
693
                day = (int)(long_num / 86400);
 
694
                long_num -= (long)(day*86400);
 
695
                hour = (int)(long_num / 3600);
 
696
                long_num -= (long)(hour*3600);
 
697
                minute = (int)(long_num / 60);
 
698
                long_num -= (minute*60);
 
699
                dstate_setinfo("ups.inverter.runtime", "%d days %dh %dm %lds", day, hour, minute, long_num);
 
700
                /* ups inverter interventions */
 
701
                dstate_setinfo("ups.inverter.interventions", "%d", get_word(&my_answer[9]));
 
702
                /* battery full discharges */
 
703
                dstate_setinfo("battery.full.discharges", "%d", get_word(&my_answer[11]));
 
704
                /* ups bypass / stabilizer interventions */
 
705
                int_num = get_word(&my_answer[13]);
 
706
                if (int_num == -2) dstate_setinfo("ups.bypass.interventions", "%s", "not avaliable");
 
707
                if (int_num >= 0) dstate_setinfo("ups.bypass.interventions", "%d", int_num);
 
708
                /* ups overheatings */
 
709
                int_num = get_word(&my_answer[15]);
 
710
                if (int_num == -2) dstate_setinfo("ups.overheatings", "%s", "not avalilable");
 
711
                if (int_num >= 0) dstate_setinfo("ups.overheatings", "%d", int_num);
 
712
        }
 
713
#endif
 
714
        
 
715
        /* GET times on battery */
 
716
        res = command_read_sequence(UPS_GET_TIMES_ON_BATTERY, my_answer);
 
717
        if (res < 0) {
 
718
                printf("Could not communicate with the ups");
 
719
                dstate_datastale();
 
720
        } else {
 
721
                autorestart = (unsigned char)my_answer[5];
 
722
        }
 
723
        
 
724
        
 
725
        /* GET schedule */
 
726
        res = command_read_sequence(UPS_GET_SCHEDULING, my_answer);
 
727
        if (res < 0) {
 
728
                printf("Could not communicate with the ups");
 
729
                dstate_datastale();
 
730
        } else {
 
731
                /* time remaining to shutdown */
 
732
                long_num = get_long(&my_answer[1]);
 
733
                if (long_num == -1) {
 
734
                        dstate_setinfo("ups.delay.shutdown", "%d", 120);        
 
735
                } else {
 
736
                        dstate_setinfo("ups.delay.shutdown", "%ld", long_num);
 
737
                }
 
738
                /* time remaining to restart  */
 
739
                long_num = get_long(&my_answer[5]);
 
740
                if (long_num == -1) {
 
741
                        dstate_setinfo("ups.delay.start", "%d", 0);     
 
742
                } else {
 
743
                        dstate_setinfo("ups.delay.start", "%ld", long_num);
 
744
                }       
 
745
        }
 
746
        
 
747
        
 
748
        /* GET ups status */
 
749
        res = command_read_sequence(UPS_STATUS, my_answer);
 
750
        if (res < 0) {
 
751
                printf("Could not communicate with the ups");
 
752
                dstate_datastale();
 
753
        } else {
 
754
                /* ups temperature */
 
755
                my_answer[3] -=128;
 
756
                if ((unsigned char)my_answer[3] > 0) {
 
757
                        dstate_setinfo("ups.temperature", "%d", (unsigned char)my_answer[3]);
 
758
                } else {
 
759
                        dstate_setinfo("ups.temperature", "%s", "not available");
 
760
                }       
 
761
                /* Status */
 
762
                status_init();
 
763
                switch ((unsigned char)my_answer[1]) {  /* byte 1 = STATUS */
 
764
                        case 0x00:
 
765
                                status_set("OL"); /* running on mains power */
 
766
                                break;
 
767
                        case 0x01:
 
768
                                status_set("OB"); /* running on battery power */
 
769
                                break;
 
770
                        case 0x02:
 
771
                                status_set("LB"); /* battery reserve */
 
772
                                break;
 
773
                        case 0x03:                      /* bypass engaged */
 
774
                        case 0x04:                      /* manual bypass engaged */
 
775
                                status_set("BY");
 
776
                                break;
 
777
                        default:
 
778
                                printf("status unknown \n");
 
779
                                break;
 
780
                } 
 
781
                switch ((unsigned char)my_answer[2]) {          /* byte 2 = FAULTS */
 
782
                        case 0x00:                              /* all right */
 
783
                                break;
 
784
                        case 0x01:                              /* overload */
 
785
                                status_set("OVER");
 
786
                                break;
 
787
                        case 0x02:                              /* overheat */
 
788
                                break;
 
789
                        case 0x03:                              /* hardware fault */
 
790
                                break;
 
791
                        case 0x04:                              /* battery charger failure (overcharging) */
 
792
                                break;
 
793
                        case 0x05:                              /* replace batteries */
 
794
                                status_set("RB");
 
795
                                break;
 
796
                        default:
 
797
                                printf("status unknown \n");
 
798
                                break;
 
799
                }
 
800
                status_commit();        
 
801
                dstate_dataok();
 
802
        }
 
803
        return;
 
804
}
 
805
 
 
806
void upsdrv_shutdown(void)
 
807
{
 
808
        char command[10], answer[10];
 
809
        
 
810
        
 
811
        /* Ensure that the ups is configured for automatically
 
812
           restart after a complete battery discharge 
 
813
           and when the power comes back after a shutdown */
 
814
        if (! autorestart) {
 
815
                command[0]=UPS_SET_TIMES_ON_BATTERY;
 
816
                command[1]=0x00;                                        /* max time on  */ 
 
817
                command[2]=0x00;                                        /* battery */
 
818
                
 
819
                command[3]=0x00;                                        /* max time after */
 
820
                command[4]=0x00;                                        /* battery reserve */
 
821
                
 
822
                command[5]=0x01;                                        /* autorestart after battery depleted enabled */
 
823
                command_write_sequence(command, 6, answer);
 
824
        }
 
825
        
 
826
        /* shedule a shutdown in 120 seconds */
 
827
        command[0]=UPS_SET_SCHEDULING;          
 
828
        command[1]=0x96;                                        /* remaining  */
 
829
        command[2]=0x00;                                        /* time          */
 
830
        command[3]=0x00;                                        /* to */
 
831
        command[4]=0x00;                                        /* shutdown 150 secs */
 
832
                        
 
833
        /* restart time has been set to 1 instead of 0 for avoiding
 
834
                a bug in some ups firmware */
 
835
        command[5]=0x01;                                        /* programmed */
 
836
        command[6]=0x00;                                        /* time          */
 
837
        command[7]=0x00;                                        /* to */
 
838
        command[8]=0x00;                                        /* restart 1 sec */
 
839
        command_write_sequence(command, 9, answer);
 
840
 
 
841
        /* you may have to check the line status since the commands
 
842
           for toggling power are frequently different for OL vs. OB */
 
843
 
 
844
        /* OL: this must power cycle the load if possible */
 
845
 
 
846
        /* OB: the load must remain off until the power returns */
 
847
}
 
848
 
 
849
 
 
850
static int instcmd(const char *cmdname, const char *extra)
 
851
{
 
852
        char command[10], answer[10];
 
853
        int res;
 
854
        
 
855
        if (!strcasecmp(cmdname, "shutdown.return")) {
 
856
                /* Same stuff as upsdrv_shutdown() */
 
857
                if (! autorestart) {
 
858
                        command[0]=UPS_SET_TIMES_ON_BATTERY;
 
859
                        command[1]=0x00;                                        /* max time on  */ 
 
860
                        command[2]=0x00;                                        /* battery */
 
861
                        command[3]=0x00;                                        /* max time after */
 
862
                        command[4]=0x00;                                        /* battery reserve */
 
863
                        command[5]=0x01;                                        /* autorestart after battery depleted enabled */
 
864
                        command_write_sequence(command, 6, answer);
 
865
                }
 
866
                /* shedule a shutdown in 30 seconds */
 
867
                command[0]=UPS_SET_SCHEDULING;          
 
868
                command[1]=0x1e;                                        /* remaining  */
 
869
                command[2]=0x00;                                        /* time          */
 
870
                command[3]=0x00;                                        /* to */
 
871
                command[4]=0x00;                                        /* shutdown 30 secs */
 
872
                                
 
873
                command[5]=0x01;                                        /* programmed */
 
874
                command[6]=0x00;                                        /* time          */
 
875
                command[7]=0x00;                                        /* to */
 
876
                command[8]=0x00;                                        /* restart 1 sec */
 
877
                command_write_sequence(command, 9, answer);
 
878
                return STAT_INSTCMD_HANDLED;
 
879
        }
 
880
        
 
881
        if (!strcasecmp(cmdname, "shutdown.stayoff")) {
 
882
                /* shedule a shutdown in 30 seconds with no restart (-1) */
 
883
                command[0]=UPS_SET_SCHEDULING;          
 
884
                command[1]=0x1e;                                        /* remaining  */
 
885
                command[2]=0x00;                                        /* time          */
 
886
                command[3]=0x00;                                        /* to */
 
887
                command[4]=0x00;                                        /* shutdown 150 secs */
 
888
                                
 
889
                command[5]=0xff;                                        /* programmed */
 
890
                command[6]=0xff;                                        /* time          */
 
891
                command[7]=0xff;                                        /* to */
 
892
                command[8]=0xff;                                        /* restart -1 no restart*/
 
893
                command_write_sequence(command, 9, answer);
 
894
                return STAT_INSTCMD_HANDLED;
 
895
        }
 
896
        
 
897
        if (!strcasecmp(cmdname, "shutdown.stop")) {
 
898
                /* set shutdown and restart time to -1 (no shutdown, no restart) */
 
899
                command[0]=UPS_SET_SCHEDULING;          
 
900
                command[1]=0xff;                                        /* remaining  */
 
901
                command[2]=0xff;                                        /* time          */
 
902
                command[3]=0xff;                                        /* to */
 
903
                command[4]=0xff;                                        /* shutdown -1 (no shutdown) */
 
904
                                
 
905
                command[5]=0xff;                                        /* programmed */
 
906
                command[6]=0xff;                                        /* time          */
 
907
                command[7]=0xff;                                        /* to */
 
908
                command[8]=0xff;                                        /* restart -1 no restart */
 
909
                command_write_sequence(command, 9, answer);
 
910
                return STAT_INSTCMD_HANDLED;
 
911
        }
 
912
 
 
913
        if (!strcasecmp(cmdname, "test.failure.start")) {
 
914
                /* force ups on battery power */
 
915
                command[0]=UPS_SET_BATTERY_TEST;        
 
916
                command[1]=0x01;                                        
 
917
                /* 0 = perform battery test
 
918
                   1 = force UPS on battery power
 
919
                   2 = restore standard mode (mains power) */
 
920
                command_write_sequence(command, 2, answer);
 
921
                return STAT_INSTCMD_HANDLED;
 
922
        }
 
923
        
 
924
        if (!strcasecmp(cmdname, "test.failure.stop")) {
 
925
                /* restore standard mode (mains power) */
 
926
                command[0]=UPS_SET_BATTERY_TEST;
 
927
                command[1]=0x02;                                        
 
928
                /* 0 = perform battery test
 
929
                   1 = force UPS on battery power
 
930
                   2 = restore standard mode (mains power) */
 
931
                command_write_sequence(command, 2, answer);
 
932
                return STAT_INSTCMD_HANDLED;
 
933
        }
 
934
        
 
935
        if (!strcasecmp(cmdname, "test.battery.start")) {
 
936
                /* launch battery test */
 
937
                command[0]=UPS_SET_BATTERY_TEST;                
 
938
                command[1]=0x00;                                        
 
939
                /* 0 = perform battery test
 
940
                   1 = force UPS on battery power
 
941
                   2 = restore standard mode (mains power) */
 
942
                send_write_command(command, 2);
 
943
                sleep(15);
 
944
                res = get_answer(answer);
 
945
                switch ((unsigned char)answer[1]) {             /* byte 1 = Test result */
 
946
                        case 0x00:                              /* all right */
 
947
                                dstate_setinfo("ups.test.result", "OK");
 
948
                                break;
 
949
                        case 0x01:                              
 
950
                                dstate_setinfo("ups.test.result", "Battery charge: 20%%");
 
951
                                break;
 
952
                        case 0x02:                              
 
953
                                dstate_setinfo("ups.test.result", "Battery charge: 40%%");
 
954
                                break;
 
955
                        case 0x03:                              
 
956
                                dstate_setinfo("ups.test.result", "Battery charge: 60%%");
 
957
                                break;
 
958
                        case 0x04:                              
 
959
                                dstate_setinfo("ups.test.result", "Battery charge: 80%%");
 
960
                                break;
 
961
                        case 0x05:                              
 
962
                                dstate_setinfo("ups.test.result", "Battery charge: 100%%");
 
963
                                break;
 
964
                        case 0xfe:                              
 
965
                                dstate_setinfo("ups.test.result", "Bad battery pack: replace");
 
966
                                break;
 
967
                        default:
 
968
                                dstate_setinfo("ups.test.result", "Impossible to test");
 
969
                                break;
 
970
                }
 
971
                dstate_dataok();
 
972
                upslogx(LOG_NOTICE, "instcmd: test battery returned with %d bytes", res);
 
973
                upslogx(LOG_NOTICE, "test battery byte 1 = %x", (unsigned char)answer[1]);
 
974
                return STAT_INSTCMD_HANDLED;
 
975
        }
 
976
        
 
977
        if (!strcasecmp(cmdname, "beeper.on")) {
 
978
                /* set buzzer to not muted */
 
979
                command[0]=UPS_SET_BUZZER_MUTE;         
 
980
                command[1]=0x00;                                        
 
981
                /* 0 = not muted
 
982
                   1 = muted
 
983
                   2 = read current status */
 
984
                command_write_sequence(command, 2, answer);
 
985
                return STAT_INSTCMD_HANDLED;
 
986
        }
 
987
        
 
988
        if (!strcasecmp(cmdname, "beeper.off")) {
 
989
                /* set buzzer to muted */
 
990
                command[0]=UPS_SET_BUZZER_MUTE;         
 
991
                command[1]=0x01;                                        
 
992
                /* 0 = not muted
 
993
                   1 = muted
 
994
                   2 = read current status */
 
995
                command_write_sequence(command, 2, answer);
 
996
                return STAT_INSTCMD_HANDLED;
 
997
                return STAT_INSTCMD_HANDLED;
 
998
        }       
 
999
        
 
1000
        upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
 
1001
        return STAT_INSTCMD_UNKNOWN;
 
1002
}
 
1003
 
 
1004
 
 
1005
void upsdrv_help(void)
 
1006
{
 
1007
}
 
1008
 
 
1009
/* list flags and values that you want to receive via -x */
 
1010
void upsdrv_makevartable(void)
 
1011
{
 
1012
        /* allow '-x xyzzy' */
 
1013
        /* addvar(VAR_FLAG, "xyzzy", "Enable xyzzy mode"); */
 
1014
 
 
1015
        /* allow '-x foo=<some value>' */
 
1016
        /* addvar(VAR_VALUE, "foo", "Override foo setting"); */
 
1017
 
 
1018
}
 
1019
 
 
1020
void upsdrv_banner(void)
 
1021
{
 
1022
        printf("Network UPS Tools - Metasystem UPS driver %s \n\n", 
 
1023
                DRV_VERSION);
 
1024
}
 
1025
 
 
1026
void upsdrv_initups(void)
 
1027
{
 
1028
        upsfd = ser_open(device_path); 
 
1029
        ser_set_speed(upsfd, device_path, B2400); 
 
1030
        send_zeros();
 
1031
}
 
1032
 
 
1033
void upsdrv_cleanup(void)
 
1034
{
 
1035
        ser_close(upsfd, device_path); 
 
1036
}