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

« back to all changes in this revision

Viewing changes to drivers/powercom.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2005-07-20 19:48:50 UTC
  • mto: (16.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20050720194850-oo61wjr33rrx2mre
Tags: upstream-2.0.2
ImportĀ upstreamĀ versionĀ 2.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 *    This model is based on PowerCom (www.powercom.com) models.
8
8
 *  -Socomec Sicon Egys 420
9
9
 *
10
 
 * Read docs/powercom.txt for other models and manufactures
11
 
 *
12
 
 * $Id: - will be filled in on next CVS add/update $
13
 
 *
14
 
 * Status:
15
 
 *  20011022/Revision 0.1 - Peter Bieringer <pb@bieringer.de>
16
 
 *   - porting done, looks like working
17
 
 *  20011208/Revision 0.2 - Peter Bieringer <pb@bieringer.de>
18
 
 *   - add some debug code
19
 
 *   - add new option "subtype"
20
 
 *   - add support for a 16 byte sending UPS (KP625AP)
21
 
 *   - shutdown function checked, but 'Trust' wakes up after a few seconds...
22
 
 *  20020629/Revision 0.3 - Simon Rozman <simon@rozman.net>
23
 
 *   - add different serial port init. for each subtype
24
 
 *   - add support for Socomec Sycon Egys 420
25
 
 *   - add support for different calculation parameters for each subtype
26
 
 *   - add support for output voltage and output frequency monitoring
27
 
 *  20020701/Revision 0.4 - Simon Rozman <simon@rozman.net>,
28
 
 *                                          proposed by Shaul Karl
29
 
 *   - subtypes specific info moved to struct subtype
30
 
 *  20030506/Revision 0.5 - Shaul Karl <shaulka@bezeqint.net>
31
 
 *   - converted to dstate
32
 
 *   - modify the validation code
33
 
 *   - replace subtype with type
34
 
 *      
 
10
 * $Id: powercom.c,v 1.1.1.1 2005/01/27 14:33:20 aquette Exp $
 
11
 *
35
12
 * Copyrights:
36
13
 * (C) 2002 Simon Rozman <simon@rozman.net>
37
 
 *  Added support for Egys
38
 
 
39
 
 * (C) 2001 Peter Bieringer <pb@bieringer.de>
40
 
 *  Porting old style "powercom" to new style "newpowercom"
41
 
 *  
42
 
 * (C) 2000  Shaul Karl <shaulk@israsrv.net.il>
43
 
 *  Creating old style "powercom"
44
 
 *   Heavily based on
45
 
 *    ups-trust425+625.c - model specific routines for Trust UPS 425/625
46
 
 *    Copyright (C) 1999  Peter Bieringer <pb@bieringer.de>
 
14
 * (C) 1999  Peter Bieringer <pb@bieringer.de>
47
15
 *                              
48
16
 * This program is free software; you can redistribute it and/or modify
49
17
 * it under the terms of the GNU General Public License as published by
62
30
 */ 
63
31
 
64
32
#include "main.h"
 
33
#include "serial.h"
65
34
#include "powercom.h"
66
35
 
67
 
#define POWERCOM_DRIVER_VERSION      "$Revision: 0.5 $"
 
36
#define POWERCOM_DRIVER_VERSION      "$ Revision: 0.5 $"
68
37
#define NUM_OF_SUBTYPES              (sizeof (types) / sizeof (*types))
69
38
 
70
39
/* variables used by module */
71
 
static unsigned char powercom_raw_data[MAX_NUM_OF_BYTES_FROM_UPS]; /* raw data reveived from UPS */
72
 
static unsigned int  powercom_linevoltage = 230U; /* line voltage, can be defined via command line option */
73
 
static char *powercom_manufacturer = "PowerCom";
74
 
static char *powercom_modelname    = "Unknown";
75
 
static char *powercom_serialnumber = "Unknown";
76
 
static char *powercom_type_name    = "Trust";
77
 
static unsigned int type_index = 0;
 
40
static unsigned char raw_data[MAX_NUM_OF_BYTES_FROM_UPS]; /* raw data reveived from UPS */
 
41
static unsigned int linevoltage = 230U; /* line voltage, can be defined via command line option */
 
42
static const char *manufacturer = "PowerCom";
 
43
static const char *modelname    = "Unknown";
 
44
static const char *serialnumber = "Unknown";
 
45
static unsigned int type = 0;
78
46
 
79
47
/* forward declaration of functions used to setup flow control */
80
 
static void dtr0rts1 ();
81
 
static void no_flow_control ();
 
48
static void dtr0rts1 (void);
 
49
static void dtr1 (void);
 
50
static void no_flow_control (void);
82
51
 
83
52
/* struct defining types */
84
53
static struct type types[] = {
85
54
        {
86
55
                "Trust",
87
56
                11,
88
 
                dtr0rts1,
89
 
                { { 5, 0 }, { 7, 0 }, { 8, 0 } },
 
57
                                {  "dtr0rts1", dtr0rts1 },
 
58
                { { 5U, 0U }, { 7U, 0U }, { 8U, 0U } },
 
59
                { { 0U, 10U }, 'n' },
90
60
                {  0.00020997, 0.00020928 },
91
61
                {  6.1343, -0.3808,  4.3110,  0.1811 },
92
62
                {  5.0000,  0.3268,  -825.00,  4.5639, -835.82 },
95
65
        {
96
66
                "KP625AP",
97
67
                16,
98
 
                dtr0rts1,
99
 
                { { 5, 0x80 }, { 7, 0 }, { 8, 0 } },
 
68
                                {  "dtr0rts1", dtr0rts1 },
 
69
                { { 5U, 0x80U }, { 7U, 0U }, { 8U, 0U } },
 
70
                { { 0U, 10U }, 'n' },
100
71
                {  0.00020997, 0.00020928 },
101
72
                {  6.1343, -0.3808,  4.3110,  0.1811 },
102
73
                {  5.0000,  0.3268,  -825.00,  4.5639, -835.82 },
105
76
        {
106
77
                "KIN2200AP",
107
78
                16,
108
 
                dtr0rts1,
109
 
                { { 7, 0 }, { 8, 0 }, { 8, 0 } },
 
79
                                {  "dtr0rts1", dtr0rts1 },
 
80
                { { 7U, 0U }, { 8U, 0U }, { 8U, 0U } },
 
81
                { { 0U, 10U }, 'n' },
110
82
                {  0.00020997, 0.0 },
111
83
                {  6.1343, -0.3808,  1.075,  0.1811 },
112
84
                {  5.0000,  0.3268,  -825.00,  0.46511, 0 },
115
87
        {
116
88
                "Egys",
117
89
                16,
118
 
                no_flow_control,
119
 
                { { 5, 0x80 }, { 7, 0 }, { 8, 0 } },
 
90
                                {  "no_flow_control", no_flow_control },
 
91
                { { 5U, 0x80U }, { 7U, 0U }, { 8U, 0U } },
 
92
                { { 0U, 10U }, 'n' },
120
93
                {  0.00020997, 0.00020928 },
121
94
                {  6.1343, -0.3808,  1.3333,  0.6667 },
122
95
                {  5.0000,  0.3268,  -825.00,  2.2105, -355.37 },
123
96
                {  1.9216, -0.0977,  0.9545,  0.0000 },
124
97
        },
 
98
        {
 
99
                "KIN525AP",
 
100
                16,
 
101
                                {  "dtr1", dtr1 },
 
102
                { { 5U, 0x80U }, { 7U, 0U }, { 8U, 0U } },
 
103
                { { 0U, 10U }, 'y' },
 
104
                {  0.00020997, 0.00020928 },
 
105
                {  6.1343, -0.3808,  4.3110,  0.1811 },
 
106
                {  5.0000,  0.3268,  -825.00,  4.5639, -835.82 },
 
107
                {  1.9216, -0.0977,  0.9545,  0.0000 },
 
108
        },
 
109
        {
 
110
                "KIN1500AP",
 
111
                16,
 
112
                                {  "no_flow_control", no_flow_control },
 
113
                { { 7U, 0U }, { 8U, 0U }, { 8U, 0U } },
 
114
                { { 0U, 10U }, 'n' },
 
115
                {  0.00020997, 0.0 },
 
116
                {  6.1343, -0.3808,  1.075,  0.1811 },
 
117
                {  5.0000,  0.3268,  -825.00,  0.46511, 0 },
 
118
                {  1.9216, -0.0977,  0.82857,  0.0000 },
 
119
        },
125
120
};
126
121
 
127
122
 
128
 
/* used external variables */
129
 
extern int sddelay;          /* shutdown delay, set by "-d $delay" in main.c */
130
 
extern int do_forceshutdown; /* shutdown delay, set by "-k" in main.c */
131
 
 
132
 
 
133
123
/*
134
124
 * local used functions
135
125
 */
136
126
 
137
 
static void powercom_shutdown(void)
 
127
static void shutdown(void)
138
128
{
139
129
        printf ("Initiating UPS shutdown!\n");
140
130
        
141
 
        upssendchar (SHUTDOWN);
142
 
        upssendchar (SEC_FOR_POWERKILL);
 
131
        ser_send_char (upsfd, SHUTDOWN);
 
132
        if (types[type].shutdown_arguments.minutesShouldBeUsed != 'n') 
 
133
            ser_send_char (upsfd, types[type].shutdown_arguments.delay[0]);
 
134
        ser_send_char (upsfd, types[type].shutdown_arguments.delay[1]);
143
135
                        
144
136
        exit (0);
145
137
}
146
138
 
147
 
 
148
139
/* registered instant commands */
149
140
static int instcmd (const char *cmdname, const char *extra)
150
141
{
151
142
        if (!strcasecmp(cmdname, "test.battery.start")) { 
152
 
            upssendchar (BATTERY_TEST);
 
143
            ser_send_char (upsfd, BATTERY_TEST);
153
144
            return STAT_INSTCMD_HANDLED;
154
145
    }
155
146
 
157
148
    return STAT_INSTCMD_UNKNOWN;
158
149
}
159
150
 
160
 
 
161
 
/* wait for buflen bytes from upsfd and store in buf */
162
 
static int read_raw_data (int upsfd, unsigned char *buf, int buflen)
163
 
{
164
 
        int     counter = 0;
165
 
        struct  sigaction sa;
166
 
        sigset_t pow_sigmask;
167
 
 
168
 
        sa.sa_handler = timeout;
169
 
        sigemptyset (&pow_sigmask);
170
 
        sa.sa_mask = pow_sigmask;
171
 
        sa.sa_flags = 0;
172
 
        sigaction (SIGALRM, &sa, NULL);
173
 
 
174
 
        alarm (3);
175
 
 
176
 
        for (counter = 0; counter < buflen; counter++) 
177
 
 
178
 
                if (!(read (upsfd, buf + counter, 1))) {
179
 
 
180
 
                        alarm (0);
181
 
                        signal (SIGALRM, SIG_IGN);
182
 
                        return counter;
183
 
                        
184
 
                }
185
 
 
186
 
        nolongertimeout();
187
 
                
188
 
        return counter;
189
 
}
190
 
                        
191
 
 
192
151
/* set DTR and RTS lines on a serial port to supply a passive
193
152
 * serial interface: DTR to 0 (-V), RTS to 1 (+V)
194
153
 */
195
 
static void dtr0rts1 ()
 
154
static void dtr0rts1 (void)
196
155
{
197
156
        int dtr_bit = TIOCM_DTR;
198
157
        int rts_bit = TIOCM_RTS;
204
163
        ioctl(upsfd, TIOCMBIS, &rts_bit);
205
164
}
206
165
 
 
166
/* set DTR line on a serial port for KIN525AP
 
167
 * serial interface: DTR to 1 (+V)
 
168
 */
 
169
static void dtr1 (void)
 
170
{
 
171
        int dtr_bit = TIOCM_DTR;
 
172
 
 
173
        upsdebugx(2, "DTR => 1");
 
174
 
 
175
        /* set DTR to high */
 
176
        ioctl(upsfd, TIOCMBIS, &dtr_bit);
 
177
}
207
178
 
208
179
/* clear any flow control */
209
 
static void no_flow_control ()
 
180
static void no_flow_control (void)
210
181
{
211
182
        struct termios tio;
212
183
        
222
193
        tcsetattr(upsfd, TCSANOW, &tio);
223
194
}
224
195
 
225
 
 
226
196
/* sane check for returned buffer */
227
197
static int validate_raw_data (void)
228
198
{
229
199
        int i = 0, 
230
 
            num_of_tests = 
231
 
                        sizeof types[0].validation / 
232
 
                                    sizeof types[0].validation[0];
 
200
    num_of_tests = 
 
201
                sizeof types[0].validation / sizeof types[0].validation[0];
233
202
        
234
203
        for (i = 0;
235
204
                 i < num_of_tests  && 
236
 
                   powercom_raw_data[
237
 
                   types[type_index].validation[i].index_of_byte
238
 
                                ] ==
239
 
                           types[type_index].validation[i].required_value;
 
205
                   raw_data[
 
206
                        types[type].validation[i].index_of_byte] ==
 
207
                               types[type].validation[i].required_value;
240
208
                 i++)  ;
241
209
        return (i < num_of_tests) ? 1 : 0;
242
210
}
254
222
        int     i, c;
255
223
        
256
224
        /* send trigger char to UPS */
257
 
        if (upssendchar (SEND_DATA) != 1) {
 
225
        if (ser_send_char (upsfd, SEND_DATA) != 1) {
258
226
                upslogx(LOG_NOTICE, "writing error");
259
227
                dstate_datastale();
260
228
                return;
261
229
        } else {
262
 
                upsdebugx(5, "Num of bytes requested for reading from UPS: %d", types[type_index].num_of_bytes_from_ups);
 
230
                upsdebugx(5, "Num of bytes requested for reading from UPS: %d", types[type].num_of_bytes_from_ups);
263
231
 
264
 
                c = read_raw_data(upsfd, powercom_raw_data, types[type_index].num_of_bytes_from_ups);
 
232
                c = ser_get_buf_len(upsfd, raw_data,
 
233
                        types[type].num_of_bytes_from_ups, 3, 0);
265
234
        
266
 
                if (c != types[type_index].num_of_bytes_from_ups) {
267
 
                        upslogx(LOG_NOTICE, "data receiving error (%d instead of %d bytes)", c, types[type_index].num_of_bytes_from_ups);
 
235
                if (c != types[type].num_of_bytes_from_ups) {
 
236
                        upslogx(LOG_NOTICE, "data receiving error (%d instead of %d bytes)", c, types[type].num_of_bytes_from_ups);
268
237
                        dstate_datastale();
269
238
                        return;
270
239
                } else
275
244
        /* optional dump of raw data */
276
245
        if (nut_debug_level > 4) {
277
246
                printf("Raw data from UPS:\n");
278
 
                for (i = 0; i < types[type_index].num_of_bytes_from_ups; i++) {
279
 
                        printf("%2d 0x%02x (%c)\n", i, powercom_raw_data[i], powercom_raw_data[i]>=0x20 ? powercom_raw_data[i] : ' ');
 
247
                for (i = 0; i < types[type].num_of_bytes_from_ups; i++) {
 
248
                        printf("%2d 0x%02x (%c)\n", i, raw_data[i], raw_data[i]>=0x20 ? raw_data[i] : ' ');
280
249
                };
281
250
        };
282
251
 
289
258
        
290
259
        /* input.frequency */
291
260
        upsdebugx(3, "input.frequency   (raw data): [raw: %u]",
292
 
                                    powercom_raw_data[INPUT_FREQUENCY]);
 
261
                                    raw_data[INPUT_FREQUENCY]);
293
262
        dstate_setinfo("input.frequency", "%02.2f",
294
 
            powercom_raw_data[INPUT_FREQUENCY] ? 
295
 
                        1.0 / (types[type_index].freq[0] *
296
 
                        powercom_raw_data[INPUT_FREQUENCY] +
297
 
                                types[type_index].freq[1]) : 0);
 
263
            raw_data[INPUT_FREQUENCY] ? 
 
264
                        1.0 / (types[type].freq[0] *
 
265
                        raw_data[INPUT_FREQUENCY] +
 
266
                                types[type].freq[1]) : 0);
298
267
        upsdebugx(2, "input.frequency: %s", dstate_getinfo("input.frequency"));
299
268
 
300
269
        /* output.frequency */
301
270
        upsdebugx(3, "output.frequency   (raw data): [raw: %u]",
302
 
                                    powercom_raw_data[OUTPUT_FREQUENCY]);
 
271
                                    raw_data[OUTPUT_FREQUENCY]);
303
272
        dstate_setinfo("output.frequency", "%02.2f",
304
 
            powercom_raw_data[OUTPUT_FREQUENCY] ? 
305
 
                        1.0 / (types[type_index].freq[0] *
306
 
                        powercom_raw_data[OUTPUT_FREQUENCY] +
307
 
                                types[type_index].freq[1]) : 0);
 
273
            raw_data[OUTPUT_FREQUENCY] ? 
 
274
                        1.0 / (types[type].freq[0] *
 
275
                        raw_data[OUTPUT_FREQUENCY] +
 
276
                                types[type].freq[1]) : 0);
308
277
        upsdebugx(2, "output.frequency: %s", dstate_getinfo("output.frequency"));
309
278
 
310
279
        /* ups.load */  
311
280
        upsdebugx(3, "ups.load  (raw data): [raw: %u]",
312
 
                                    powercom_raw_data[UPS_LOAD]);
 
281
                                    raw_data[UPS_LOAD]);
313
282
        dstate_setinfo("ups.load", "%03.1f", 
314
 
            tmp = powercom_raw_data[STATUS_A] & MAINS_FAILURE ?
315
 
                        types[type_index].loadpct[0] *
316
 
                    powercom_raw_data[UPS_LOAD] +
317
 
                        types[type_index].loadpct[1] :
318
 
                        types[type_index].loadpct[2] *
319
 
                    powercom_raw_data[UPS_LOAD] +
320
 
                        types[type_index].loadpct[3]);
 
283
            tmp = raw_data[STATUS_A] & MAINS_FAILURE ?
 
284
                        types[type].loadpct[0] * raw_data[UPS_LOAD] +
 
285
                                            types[type].loadpct[1] :
 
286
                        types[type].loadpct[2] * raw_data[UPS_LOAD] +
 
287
                                            types[type].loadpct[3]);
321
288
        upsdebugx(2, "ups.load: %s", dstate_getinfo("ups.load"));
322
289
 
323
290
        /* battery.charge */
324
291
        upsdebugx(3, "battery.charge (raw data): [raw: %u]",
325
 
                                    powercom_raw_data[BATTERY_CHARGE]);
 
292
                                    raw_data[BATTERY_CHARGE]);
326
293
        dstate_setinfo("battery.charge", "%03.1f",
327
 
            powercom_raw_data[STATUS_A] & MAINS_FAILURE ?
328
 
                        types[type_index].battpct[0] *
329
 
                    powercom_raw_data[BATTERY_CHARGE] +
330
 
                                types[type_index].battpct[1] * tmp +
331
 
                                        types[type_index].battpct[2] :
332
 
                        types[type_index].battpct[3] *
333
 
                    powercom_raw_data[BATTERY_CHARGE] +
334
 
                                        types[type_index].battpct[4]);
 
294
            raw_data[STATUS_A] & MAINS_FAILURE ?
 
295
                        types[type].battpct[0] * raw_data[BATTERY_CHARGE] +
 
296
                        types[type].battpct[1] * tmp + types[type].battpct[2] :
 
297
                        types[type].battpct[3] * raw_data[BATTERY_CHARGE] +
 
298
                                                           types[type].battpct[4]);
335
299
        upsdebugx(2, "battery.charge: %s", dstate_getinfo("battery_charge"));
336
300
 
337
301
        /* input.voltage */     
338
302
        upsdebugx(3, "input.voltage (raw data): [raw: %u]",
339
 
                                    powercom_raw_data[INPUT_VOLTAGE]);
 
303
                                    raw_data[INPUT_VOLTAGE]);
340
304
        dstate_setinfo("input.voltage", "%03.1f",
341
 
            tmp = powercom_linevoltage >= 220 ?
342
 
                        types[type_index].voltage[0] *
343
 
                    powercom_raw_data[INPUT_VOLTAGE] +
344
 
                                    types[type_index].voltage[1] :
345
 
                        types[type_index].voltage[2] *
346
 
                    powercom_raw_data[INPUT_VOLTAGE] +
347
 
                                    types[type_index].voltage[3]);
 
305
            tmp = linevoltage >= 220 ?
 
306
                        types[type].voltage[0] * raw_data[INPUT_VOLTAGE] +
 
307
                                                        types[type].voltage[1] :
 
308
                        types[type].voltage[2] * raw_data[INPUT_VOLTAGE] +
 
309
                                                        types[type].voltage[3]);
348
310
        upsdebugx(2, "input.voltage: %s", dstate_getinfo("input.voltage"));
349
311
        
350
312
        /* output.voltage */    
351
313
        upsdebugx(3, "input.voltage (raw data): [raw: %u]",
352
 
                                    powercom_raw_data[OUTPUT_VOLTAGE]);
 
314
                                    raw_data[OUTPUT_VOLTAGE]);
353
315
        dstate_setinfo("output.voltage", "%03.1f",
354
 
            powercom_linevoltage >= 220 ?
355
 
                        types[type_index].voltage[0] *
356
 
                    powercom_raw_data[OUTPUT_VOLTAGE] +
357
 
                                    types[type_index].voltage[1] :
358
 
                        types[type_index].voltage[2] *
359
 
                    powercom_raw_data[OUTPUT_VOLTAGE] +
360
 
                                    types[type_index].voltage[3]);
 
316
            linevoltage >= 220 ?
 
317
                        types[type].voltage[0] * raw_data[OUTPUT_VOLTAGE] +
 
318
                                                        types[type].voltage[1] :
 
319
                        types[type].voltage[2] * raw_data[OUTPUT_VOLTAGE] +
 
320
                                                        types[type].voltage[3]);
361
321
        upsdebugx(2, "output.voltage: %s", dstate_getinfo("output.voltage"));
362
322
 
363
323
        status_init();
364
324
        
365
325
        *val = 0;
366
 
        if (!(powercom_raw_data[STATUS_A] & MAINS_FAILURE)) {
367
 
                !(powercom_raw_data[STATUS_A] & OFF) ? 
 
326
        if (!(raw_data[STATUS_A] & MAINS_FAILURE)) {
 
327
                !(raw_data[STATUS_A] & OFF) ? 
368
328
                        status_set("OL") : status_set("OFF");
369
329
        } else {
370
330
                status_set("OB");
371
331
        }
372
332
 
373
 
        if (powercom_raw_data[STATUS_A] & LOW_BAT)  status_set("LB");
 
333
        if (raw_data[STATUS_A] & LOW_BAT)  status_set("LB");
374
334
 
375
 
        if (powercom_raw_data[STATUS_A] & AVR_ON) {
376
 
                tmp < powercom_linevoltage ? 
 
335
        if (raw_data[STATUS_A] & AVR_ON) {
 
336
                tmp < linevoltage ? 
377
337
                        status_set("BOOST") : status_set("TRIM");
378
338
        }
379
339
 
380
 
        if (powercom_raw_data[STATUS_A] & OVERLOAD)  status_set("OVER");
381
 
 
382
 
        if (powercom_raw_data[STATUS_B] & BAD_BAT)  status_set("RB");
383
 
 
384
 
        if (powercom_raw_data[STATUS_B] & TEST)  status_set("TEST");
 
340
        if (raw_data[STATUS_A] & OVERLOAD)  status_set("OVER");
 
341
 
 
342
        if (raw_data[STATUS_B] & BAD_BAT)  status_set("RB");
 
343
 
 
344
        if (raw_data[STATUS_B] & TEST)  status_set("TEST");
385
345
 
386
346
        status_commit();
387
347
 
389
349
        dstate_dataok();
390
350
}
391
351
 
392
 
 
393
352
/* shutdown UPS */
394
353
void upsdrv_shutdown(void)
395
354
{
396
 
        if (do_forceshutdown == 1) {
397
 
                /* power down the attached load immediately */
398
 
                printf("Forced UPS shutdown triggered, do it...\n");
399
 
                powercom_shutdown();
400
 
        } else {
401
 
                /* power down the attached load after the given delay */
402
 
                printf("UPS shutdown with '%d' seconds delay triggered, wait now...\n", sddelay);
403
 
                sleep(sddelay);
404
 
                powercom_shutdown();
405
 
        };
 
355
        /* power down the attached load immediately */
 
356
        printf("Forced UPS shutdown triggered, do it...\n");
 
357
        shutdown();
406
358
}
407
359
 
408
 
 
409
360
/* initialize UPS */
410
361
void upsdrv_initups(void)
411
362
{
412
 
        int tmp, i;
 
363
        int tmp;
 
364
        unsigned int i;
413
365
 
414
366
        /* check manufacturer name from arguments */
415
 
        if (getval("manufacturer") != NULL) {
416
 
                powercom_manufacturer = getval("manufacturer");
417
 
        };
 
367
        if (getval("manufacturer") != NULL) 
 
368
                manufacturer = getval("manufacturer");
418
369
        
419
370
        /* check model name from arguments */
420
 
        if (getval("modelname") != NULL) {
421
 
                powercom_modelname = getval("modelname");
422
 
        };
 
371
        if (getval("modelname") != NULL) 
 
372
                modelname = getval("modelname");
423
373
        
424
374
        /* check serial number from arguments */
425
 
        if (getval("serialnumber") != NULL) {
426
 
                powercom_serialnumber = getval("serialnumber");
427
 
        };
 
375
        if (getval("serialnumber") != NULL) 
 
376
                serialnumber = getval("serialnumber");
428
377
        
429
378
        /* get and check type */
430
379
        if (getval("type") != NULL) {
431
 
                powercom_type_name = getval("type");
432
 
                for (i = 0; i < NUM_OF_SUBTYPES; i++) {
433
 
                        if (strcmp(types[i].name, powercom_type_name) == 0)
434
 
                                break;
435
 
                };
436
 
                if (i < NUM_OF_SUBTYPES) {
437
 
                        /* we found a type */
438
 
                        type_index = i; 
439
 
                } else {
440
 
                        /* no such type exists */
441
 
                        printf("Given UPS type '%s' isn't valid!\n", powercom_type_name);
 
380
                for (i = 0; 
 
381
                         i < NUM_OF_SUBTYPES  &&  strcmp(types[i].name, getval("type"));
 
382
                         i++) ;
 
383
                if (i >= NUM_OF_SUBTYPES) {
 
384
                        printf("Given UPS type '%s' isn't valid!\n", getval("type"));
442
385
                        exit (1);
443
 
                };
 
386
                }
 
387
                type = i;       
444
388
        };
445
389
        
446
390
        /* check line voltage from arguments */
450
394
                        printf("Given line voltage '%d' is out of range (110-120 or 220-240 V)\n", tmp);
451
395
                        exit (1);
452
396
                };
453
 
                powercom_linevoltage  = (unsigned int) tmp;
 
397
                linevoltage = (unsigned int) tmp;
454
398
        };
455
399
 
 
400
        if (getval("numOfBytesFromUPS") != NULL) {
 
401
                tmp = atoi(getval("numOfBytesFromUPS"));
 
402
                if (! (tmp > 0 && tmp <= MAX_NUM_OF_BYTES_FROM_UPS) ) {
 
403
                        printf("Given numOfBytesFromUPS '%d' is out of range (1 to %d)\n",
 
404
                       tmp, MAX_NUM_OF_BYTES_FROM_UPS);
 
405
                        exit (1);
 
406
                };
 
407
                types[type].num_of_bytes_from_ups = (unsigned char) tmp;
 
408
        }
 
409
 
 
410
        if (getval("methodOfFlowControl") != NULL) {
 
411
                for (i = 0; 
 
412
                         i < NUM_OF_SUBTYPES  &&  
 
413
                                        strcmp(types[i].flowControl.name,
 
414
                                                        getval("methodOfFlowControl"));
 
415
                         i++) ;
 
416
                if (i >= NUM_OF_SUBTYPES) {
 
417
                        printf("Given methodOfFlowControl '%s' isn't valid!\n", 
 
418
                                        getval("methodOfFlowControl"));
 
419
                        exit (1);
 
420
                };
 
421
                types[type].flowControl = types[i].flowControl; 
 
422
        }
 
423
 
 
424
        if (getval("validationSequence")  &&
 
425
            sscanf(getval("validationSequence"),
 
426
                                        "{{%u,%x},{%u,%x},{%u,%x}}",
 
427
                                        &types[type].validation[0].index_of_byte,
 
428
                                        &types[type].validation[0].required_value,
 
429
                                        &types[type].validation[1].index_of_byte,
 
430
                                        &types[type].validation[1].required_value,
 
431
                                        &types[type].validation[2].index_of_byte,
 
432
                                        &types[type].validation[2].required_value
 
433
                              ) < 6
 
434
           ) {
 
435
                printf("Given validationSequence '%s' isn't valid!\n", 
 
436
                                                                         getval("validationSequence"));
 
437
                exit (1);
 
438
        }
 
439
 
 
440
        if (getval("shutdownArguments")  &&
 
441
            sscanf(getval("shutdownArguments"), "{{%u,%u},%c}",
 
442
                        &types[type].shutdown_arguments.delay[0],
 
443
                        &types[type].shutdown_arguments.delay[1],
 
444
                        &types[type].shutdown_arguments.minutesShouldBeUsed 
 
445
                  ) < 3
 
446
           ) {
 
447
            printf("Given shutdownArguments '%s' isn't valid!\n", 
 
448
                                                                         getval("shutdownArguments"));
 
449
                exit (1);
 
450
        } 
 
451
 
 
452
        if (getval("frequency")  &&
 
453
            sscanf(getval("frequency"), "{%f,%f}",
 
454
                                        &types[type].freq[0], &types[type].freq[1]
 
455
                      ) < 2
 
456
           ) {
 
457
                printf("Given frequency '%s' isn't valid!\n", 
 
458
                                                                                getval("frequency"));
 
459
                exit (1);
 
460
        }
 
461
 
 
462
        if (getval("loadPercentage")  && 
 
463
            sscanf(getval("loadPercentage"), "{%f,%f,%f,%f}",
 
464
                    &types[type].loadpct[0], &types[type].loadpct[1],
 
465
                    &types[type].loadpct[2], &types[type].loadpct[3]
 
466
                      ) < 4
 
467
           ) {
 
468
                printf("Given loadPercentage '%s' isn't valid!\n", 
 
469
                                                                         getval("loadPercentage"));
 
470
                exit (1);
 
471
        }
 
472
 
 
473
        if (getval("batteryPercentage")  && 
 
474
            sscanf(getval("batteryPercentage"), "{%f,%f,%f,%f,%f}",
 
475
                        &types[type].battpct[0], &types[type].battpct[1],
 
476
                        &types[type].battpct[2], &types[type].battpct[3],
 
477
                        &types[type].battpct[4]
 
478
                      ) < 5
 
479
           ) {
 
480
                printf("Given batteryPercentage '%s' isn't valid!\n", 
 
481
                                                                         getval("batteryPercentage"));
 
482
                exit (1);
 
483
        }
 
484
 
 
485
        if (getval("voltage")  &&
 
486
            sscanf(getval("voltage"), "{%f,%f,%f,%f}",
 
487
                    &types[type].voltage[0], &types[type].voltage[1],
 
488
                    &types[type].voltage[2], &types[type].voltage[3]
 
489
                                  ) < 4
 
490
           ) {
 
491
                printf("Given voltage '%s' isn't valid!\n", getval("voltage"));
 
492
                exit (1);
 
493
        }
 
494
 
456
495
        upsdebugx(1, "Values of arguments:");
457
 
        upsdebugx(1, " manufacturer : '%s'", powercom_manufacturer);
458
 
        upsdebugx(1, " model name   : '%s'", powercom_modelname);
459
 
        upsdebugx(1, " serial number: '%s'", powercom_serialnumber);
460
 
        upsdebugx(1, " line voltage : '%u'", powercom_linevoltage);
461
 
        upsdebugx(1, " type         : '%s'", powercom_type_name);
 
496
        upsdebugx(1, " manufacturer            : '%s'", manufacturer);
 
497
        upsdebugx(1, " model name              : '%s'", modelname);
 
498
        upsdebugx(1, " serial number           : '%s'", serialnumber);
 
499
        upsdebugx(1, " line voltage            : '%u'", linevoltage);
 
500
        upsdebugx(1, " type                    : '%s'", types[type].name);
 
501
        upsdebugx(1, " number of bytes from UPS: '%u'", 
 
502
                                types[type].num_of_bytes_from_ups);
 
503
        upsdebugx(1, " method of flow control  : '%s'", 
 
504
                            types[type].flowControl.name);
 
505
        upsdebugx(1, " validation sequence: '{{%u,%#x},{%u,%#x},{%u,%#x}}'",
 
506
                                    types[type].validation[0].index_of_byte,
 
507
                                    types[type].validation[0].required_value,
 
508
                                    types[type].validation[1].index_of_byte,
 
509
                                    types[type].validation[1].required_value,
 
510
                                    types[type].validation[2].index_of_byte,
 
511
                                    types[type].validation[2].required_value);
 
512
        upsdebugx(1, " shutdown arguments: '{{%u,%u},%c}'",
 
513
                        types[type].shutdown_arguments.delay[0],
 
514
                        types[type].shutdown_arguments.delay[1],
 
515
                        types[type].shutdown_arguments.minutesShouldBeUsed); 
 
516
        upsdebugx(1, " frequency calculation coefficients: '{%f,%f}'",
 
517
                                        types[type].freq[0], types[type].freq[1]);
 
518
        upsdebugx(1, " load percentage calculation coefficients: "
 
519
                 "'{%f,%f,%f,%f}'",
 
520
                        types[type].loadpct[0], types[type].loadpct[1],
 
521
                        types[type].loadpct[2], types[type].loadpct[3]);
 
522
        upsdebugx(1, " battery percentage calculation coefficients: " 
 
523
                 "'{%f,%f,%f,%f,%f}'",
 
524
                        types[type].battpct[0], types[type].battpct[1],
 
525
                        types[type].battpct[2], types[type].battpct[3],
 
526
                        types[type].battpct[4]);
 
527
    upsdebugx(1, " voltage calculation coefficients: '{%f,%f}'",
 
528
                            types[type].voltage[2], types[type].voltage[3]);
462
529
 
463
530
        /* open serial port */
464
 
        open_serial (device_path, B1200);
 
531
        upsfd = ser_open(device_path);
 
532
        ser_set_speed(upsfd, device_path, B1200);
465
533
        
466
534
        /* setup flow control */
467
 
        types[type_index].setup_flow_control();
 
535
        types[type].flowControl.setup_flow_control();
468
536
}
469
537
 
470
 
 
471
538
/* display help */
472
539
void upsdrv_help(void)
473
540
{
475
542
        return;
476
543
}
477
544
 
478
 
 
479
545
/* display banner */
480
546
void upsdrv_banner(void)
481
547
{
482
 
        printf ("Network UPS Tools (version %s) - PowerCom and similars protocol driver\n",
483
 
                UPS_VERSION);
484
 
        printf ("\tDriver %s\n",
485
 
                POWERCOM_DRIVER_VERSION);
 
548
        printf("Network UPS Tools - PowerCom and similars protocol UPS driver %s (%s)\n\n", 
 
549
                POWERCOM_DRIVER_VERSION, UPS_VERSION);
486
550
}
487
551
 
488
 
 
489
552
/* initialize information */
490
553
void upsdrv_initinfo(void)
491
554
{
492
555
        /* write constant data for this model */
493
 
        dstate_setinfo ("ups.mfr", "%s", powercom_manufacturer);
494
 
        dstate_setinfo ("ups.model", "%s", powercom_modelname);
495
 
        dstate_setinfo ("ups.serial", "%s", powercom_serialnumber);
496
 
        dstate_setinfo ("ups.model.type", "%s", powercom_type_name);
497
 
        dstate_setinfo ("input.voltage.nominal", "%u", powercom_linevoltage);
 
556
        dstate_setinfo("driver.version.internal", "%s", POWERCOM_DRIVER_VERSION);
 
557
        dstate_setinfo ("ups.mfr", "%s", manufacturer);
 
558
        dstate_setinfo ("ups.model", "%s", modelname);
 
559
        dstate_setinfo ("ups.serial", "%s", serialnumber);
 
560
        dstate_setinfo ("ups.model.type", "%s", types[type].name);
 
561
        dstate_setinfo ("input.voltage.nominal", "%u", linevoltage);
498
562
 
499
563
        /* now add the instant commands */
500
564
    dstate_addcmd ("test.battery.start");
501
 
        upsh.new_instcmd = instcmd;
 
565
        upsh.instcmd = instcmd;
502
566
}
503
567
 
504
 
 
505
568
/* define possible arguments */
506
569
void upsdrv_makevartable(void)
507
570
{
509
572
        addvar(VAR_VALUE, "linevoltage",   "Specify line voltage (110-120 or 220-240 V), because it cannot detect automagically (default: 230 V)");
510
573
        addvar(VAR_VALUE, "modelname",     "Specify model name, because it cannot detect automagically (default: Unknown)");
511
574
        addvar(VAR_VALUE, "serialnumber",  "Specify serial number, because it cannot detect automagically (default: Unknown)");
512
 
        addvar(VAR_VALUE, "type",       "Type of UPS like 'Trust', 'KP625AP', 'KIN2200AP' or 'Egys' (default: 'Trust')");
 
575
        addvar(VAR_VALUE, "type",       "Type of UPS like 'Trust', 'KP625AP', 'KIN2200AP', 'Egys', 'KIN525AP' or 'KIN1500AP' (default: 'Trust')");
 
576
        addvar(VAR_VALUE, "numOfBytesFromUPS",  "The number of bytes in a UPS frame");
 
577
        addvar(VAR_VALUE, "voltage",  "A quad to convert the raw data to human readable voltage");
 
578
        addvar(VAR_VALUE, "methodOfFlowControl",  "The flow control method engaged by the UPS");
 
579
        addvar(VAR_VALUE, "frequency",  "A pair to convert the raw data to human readable freqency");
 
580
        addvar(VAR_VALUE, "batteryPercentage",  "A 5 tuple to convert the raw data to human readable battery percentage");
 
581
        addvar(VAR_VALUE, "loadPercentage",  "A quad to convert the raw data to human readable load percentage");
 
582
        addvar(VAR_VALUE, "validationSequence",  "3 pairs to be used for validating the UPS");  
 
583
        addvar(VAR_VALUE, "shutdownArguments",  "The number of delay arguments and their values for the shutdown operation");
513
584
}
514
585
 
515
 
 
516
 
 
517
586
void upsdrv_cleanup(void)
518
587
{
 
588
        ser_close(upsfd, device_path);
519
589
}