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

« back to all changes in this revision

Viewing changes to drivers/victronups.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
1
/*
2
2
 *
3
 
 *  newvictron.c - Model specific routines for IMV/Victron  units
 
3
 *  victron.c - Model specific routines for GE/IMV/Victron  units
4
4
 *  Match, Match Lite, NetUps
5
 
 *  Revision 0.1.3.2
 
5
 *  Revision 0.1.9
6
6
 *           
7
7
 * Copyright (C) 1999  Russell Kroll <rkroll@exploits.org>
8
8
 * Copyright (C) 2000  Radek Benedikt <benedikt@lphard.cz>
10
10
 * Copyright (C) 2001  Daniel.Prynych <Daniel.Prynych@hornet.cz>
11
11
 * porting to now style "newvictron"
12
12
 * Copyright (C) 2003  Gert Lynge <gert@lynge.org>
13
 
 * Removes \n from data (was causing periodic misreadings of temperature
14
 
 * and voltage levels)
 
13
 * Porting to new serial functions. Now removes \n from data (was causing
 
14
 * periodic misreadings of temperature and voltage levels)
 
15
 * Copyright (C) 2004  Gert Lynge <gert@lynge.org>
 
16
 * Implemented some Instant Commands.
 
17
 *
15
18
 * This program is free software; you can redistribute it and/or modify
16
19
 * it under the terms of the GNU General Public License as published by
17
20
 * the Free Software Foundation; either version 2 of the License, or
29
32
 *
30
33
 */
31
34
 
32
 
#define DRV_VERSION "0.1.3.2"
 
35
#define DRV_VERSION "0.1.9"
33
36
 
34
37
#include "main.h"
 
38
#include "serial.h"
35
39
 
36
40
#define ENDCHAR '\r'
37
 
#define IGNCHARS        "\n"
 
41
#define IGNCHARS "\n"
38
42
 
39
43
#define UPS_DELAY 150000
40
44
#define UPS_LONG_DELAY 450000
44
48
#define VICTRON_OB 2
45
49
#define VICTRON_LB 4
46
50
 
 
51
#define VICTRON_NO_TEST         1
 
52
#define VICTRON_ABORT_TEST      2
 
53
#define VICTRON_SYSTEM_TEST     3
 
54
#define VICTRON_BATTERY_TEST    4
 
55
#define VICTRON_CALIBRATION     5
 
56
#define VICTRON_BYPASS_TEST     101
 
57
 
47
58
#define LENGTH_TEMP 256
48
59
 
49
60
int  sdwdelay = 0;  /* shutdown after 0 second */
50
61
 
51
 
extern  int     sddelay; /* doba po kterou ceka driver po vypnuti ups */
52
 
extern  char    upssend_endchar;
53
 
extern  int     upsc_debug;
54
62
char *model_name;
55
63
 
56
 
 
 
64
static int start_is_datastale = 1;
 
65
 
 
66
static int exist_ups_serial = 0;
 
67
static int exist_ups_temperature = 0;
 
68
static int exist_output_current = 0;
 
69
static int exist_battery_charge = 0;
 
70
static int exist_battery_current = 0;
 
71
static int exist_battery_temperature = 0;
 
72
static int exist_battery_runtime = 0;
 
73
 
 
74
static int test_in_progress = VICTRON_NO_TEST;
 
75
 
 
76
static int get_data (const char *out_string, char *in_string)
 
77
{
 
78
        int ret_code;
 
79
        ser_send(upsfd, "%s%c", out_string, ENDCHAR);
 
80
        usleep (UPS_DELAY);
 
81
        ret_code = ser_get_line(upsfd, in_string, LENGTH_TEMP, ENDCHAR, 
 
82
                                IGNCHARS, 3, 0);
 
83
        if (ret_code < 1) {            
 
84
                dstate_datastale();
 
85
                return -1;
 
86
        }
 
87
        return 0;
 
88
}
 
89
 
 
90
static int instcmd(const char *cmdname, const char *extra)
 
91
{
 
92
        char temp[ LENGTH_TEMP ]; 
 
93
 
 
94
        if(!strcasecmp(cmdname, "calibrate.start"))
 
95
        {
 
96
                if(get_data("vTi5!",temp))
 
97
                {
 
98
                        upsdebugx(1, "instcmd: ser_send calibrate.start failed");
 
99
                        return STAT_INSTCMD_UNKNOWN; /* Or Failed when it get defined */
 
100
                }
 
101
                else
 
102
                {
 
103
                        upsdebugx(1, "instcmd: calibrate.start returned: %s", temp);
 
104
                        test_in_progress = VICTRON_CALIBRATION;
 
105
                        return STAT_INSTCMD_HANDLED;
 
106
                }
 
107
        }               
 
108
        else if(!strcasecmp(cmdname, "calibrate.stop"))
 
109
        {
 
110
                if(get_data("vTi2!",temp))
 
111
                {
 
112
                        upsdebugx(1, "instcmd: ser_send calibrate.stop failed");
 
113
                        return STAT_INSTCMD_UNKNOWN; /* Or Failed when it get defined */
 
114
                }
 
115
                else
 
116
                {
 
117
                        upsdebugx(1, "instcmd: calibrate.stop returned: %s", temp);
 
118
                        return STAT_INSTCMD_HANDLED;
 
119
                }
 
120
        }               
 
121
        else if(!strcasecmp(cmdname, "test.battery.stop"))
 
122
        {
 
123
                if(get_data("vTi2!",temp))
 
124
                {
 
125
                        upsdebugx(1, "instcmd: ser_send test.battery.stop failed");
 
126
                        return STAT_INSTCMD_UNKNOWN; /* Or Failed when it get defined */
 
127
                }
 
128
                else
 
129
                {
 
130
                        upsdebugx(1, "instcmd: test.battery.stop returned: %s", temp);
 
131
                        return STAT_INSTCMD_HANDLED;
 
132
                }
 
133
        }
 
134
        else if(!strcasecmp(cmdname, "test.battery.start"))
 
135
        {
 
136
                if(get_data("vTi4!",temp))
 
137
                {
 
138
                        upsdebugx(1, "instcmd: ser_send test.battery.start failed");
 
139
                        return STAT_INSTCMD_UNKNOWN; /* Or Failed when it get defined */
 
140
                }
 
141
                else
 
142
                {
 
143
                        upsdebugx(1, "instcmd: test.battery.start returned: %s", temp);
 
144
                        test_in_progress = VICTRON_BATTERY_TEST;
 
145
                        return STAT_INSTCMD_HANDLED;
 
146
                }
 
147
        }
 
148
        else if(!strcasecmp(cmdname, "test.panel.stop"))
 
149
        {
 
150
                if(get_data("vTi2!",temp))
 
151
                {
 
152
                        upsdebugx(1, "instcmd: ser_send test.panel.stop failed");
 
153
                        return STAT_INSTCMD_UNKNOWN; /* Or Failed when it get defined */
 
154
                }
 
155
                else
 
156
                {
 
157
                        upsdebugx(1, "instcmd: test.panel.stop returned: %s", temp);
 
158
                        return STAT_INSTCMD_HANDLED;
 
159
                }
 
160
        }
 
161
        else if(!strcasecmp(cmdname, "test.panel.start"))
 
162
        {
 
163
                if(get_data("vTi3!",temp))
 
164
                {
 
165
                        upsdebugx(1, "instcmd: ser_send test.panel.start failed");
 
166
                        return STAT_INSTCMD_UNKNOWN; /* Or Failed when it get defined */
 
167
                }
 
168
                else
 
169
                {
 
170
                        upsdebugx(1, "instcmd: test.panel.start returned: %s", temp);
 
171
                        test_in_progress = VICTRON_SYSTEM_TEST;
 
172
                        return STAT_INSTCMD_HANDLED;
 
173
                }
 
174
        }
 
175
        else if(!strcasecmp(cmdname, "bypass.stop"))
 
176
        {
 
177
                if(get_data("vTi2!",temp))
 
178
                {
 
179
                        upsdebugx(1, "instcmd: ser_send bypass.stop failed");
 
180
                        return STAT_INSTCMD_UNKNOWN; /* Or Failed when it get defined */
 
181
                }
 
182
                else
 
183
                {
 
184
                        upsdebugx(1, "instcmd: bypass.stop returned: %s", temp);
 
185
                        return STAT_INSTCMD_HANDLED;
 
186
                }
 
187
        }
 
188
        else if(!strcasecmp(cmdname, "bypass.start"))
 
189
        {
 
190
                if(get_data("vTi101!",temp))
 
191
                {
 
192
                        upsdebugx(1, "instcmd: ser_send bypass.start failed");
 
193
                        return STAT_INSTCMD_UNKNOWN; /* Or Failed when it get defined */
 
194
                }
 
195
                else
 
196
                {
 
197
                        upsdebugx(1, "instcmd: bypass.start returned: %s", temp);
 
198
                        test_in_progress = VICTRON_BYPASS_TEST;
 
199
                        return STAT_INSTCMD_HANDLED;
 
200
                }
 
201
        }
 
202
        else
 
203
        {
 
204
                upsdebugx(1, "instcmd: unknown command: %s", cmdname);
 
205
                return STAT_INSTCMD_UNKNOWN;
 
206
        }
 
207
}
 
208
        
57
209
void upsdrv_initinfo(void)
58
210
{
 
211
        
59
212
        dstate_setinfo("driver.version.internal", "%s", DRV_VERSION);
60
213
        if (model_name)
61
214
                dstate_setinfo("ups.model", "%s", model_name);
62
215
 
63
 
}
64
 
 
65
 
int get_data (const char *out_string, char *in_string)
66
 
{
67
 
        int ret_code;   
68
 
        upssend (out_string);
69
 
        usleep (UPS_DELAY);
70
 
        ret_code = upsrecv (in_string, LENGTH_TEMP, ENDCHAR, IGNCHARS);
71
 
 
72
 
        if (ret_code < 1) {            
73
 
                dstate_datastale();
74
 
                return -1;
75
 
        }
76
 
        return 0;
77
 
}
 
216
        upsh.instcmd = instcmd;
 
217
 
 
218
        dstate_addcmd("test.battery.start");
 
219
        dstate_addcmd("test.battery.stop");
 
220
        dstate_addcmd("calibrate.start");
 
221
        dstate_addcmd("calibrate.stop");
 
222
        dstate_addcmd("test.panel.start");      /* We need a GeneralSystemTest, but use this one instead */
 
223
        dstate_addcmd("test.panel.stop");       /* We need a GeneralSystemTest, but use this one instead */
 
224
        dstate_addcmd("bypass.start");
 
225
        dstate_addcmd("bypass.stop");
 
226
}
 
227
 
78
228
 
79
229
void upsdrv_updateinfo(void)
80
230
{
81
231
        int flags; 
82
232
        char temp[ LENGTH_TEMP ]; 
83
 
 
 
233
        char test_result[ 255 ];
 
234
        int runtime_sec = -1;
 
235
 
 
236
        if (start_is_datastale)
 
237
                {
 
238
                if (get_data("vDS?",temp)) return;
 
239
                if (strcmp(temp+3,"NA"))
 
240
                        exist_ups_serial=1;
 
241
 
 
242
                if (get_data("vBT?",temp)) return;
 
243
                if (strcmp(temp+3,"NA"))
 
244
                        exist_ups_temperature =1;
 
245
        
 
246
                if (get_data("vO0I?",temp)) return;
 
247
                if (strcmp(temp+4,"NA"))
 
248
                        exist_output_current =1;
 
249
 
 
250
                if (get_data("vBC?",temp)) return;
 
251
                if (strcmp(temp+3,"NA"))
 
252
                        exist_battery_charge = 1;
 
253
        
 
254
                if (get_data("vBI?",temp)) return;
 
255
                if (strcmp(temp+3,"NA"))
 
256
                        exist_battery_charge = 1;
 
257
 
 
258
                if (get_data("vBT?",temp)) return;
 
259
                if (strcmp(temp+3,"NA"))
 
260
                        exist_battery_temperature = 1;
 
261
 
 
262
                if (get_data("vBt?",temp)) return;
 
263
                if (strcmp(temp+3,"NA"))
 
264
                        exist_battery_runtime = 1;
 
265
 
 
266
                start_is_datastale = 0;
 
267
                }
 
268
 
 
269
 
 
270
 
 
271
        
84
272
        /* ups.status */ 
85
273
        if (get_data("vAa?",temp)) return;
86
274
        flags = atoi (temp+3);
100
288
                status_set("OB");
101
289
        else
102
290
                status_set("OL");
 
291
          
 
292
        /* Get UPS test results */
 
293
        if (get_data("vTr?",temp)) return;
 
294
        if (get_data("vTd?",test_result)) return;
 
295
        
 
296
        switch(atoi(temp+3))
 
297
        {
 
298
                case 1:
 
299
                upsdebugx(1, "upsdrv_updateinfo: test %i result = Done, Passed: %s",test_in_progress,test_result+3);
 
300
                test_in_progress = VICTRON_NO_TEST;
 
301
                break;
 
302
 
 
303
                case 2:
 
304
                upsdebugx(1, "upsdrv_updateinfo: test %i result = Done, Warning: %s",test_in_progress,test_result+3);
 
305
                test_in_progress = VICTRON_NO_TEST;
 
306
                break;
 
307
 
 
308
                case 3:
 
309
                upsdebugx(1, "upsdrv_updateinfo: test %i result = Done, Error: %s",test_in_progress,test_result+3);
 
310
                test_in_progress = VICTRON_NO_TEST;
 
311
                break;
 
312
 
 
313
                case 4:
 
314
                upsdebugx(1, "upsdrv_updateinfo: test %i result = Aborted: %s",test_in_progress,test_result+3);
 
315
                test_in_progress = VICTRON_NO_TEST;
 
316
                break;
 
317
 
 
318
                case 5:
 
319
                if(test_in_progress==VICTRON_CALIBRATION)
 
320
                        status_set("CAL");              /* calibration in progress*/
 
321
                upsdebugx(1, "upsdrv_updateinfo: test %i result = In Progress: %s",
 
322
                        test_in_progress,test_result+3);
 
323
                break;
 
324
 
 
325
                case 6:
 
326
                upsdebugx(1, "upsdrv_updateinfo: test result = No test initiated: %s",
 
327
                        test_result+3);
 
328
                break;
 
329
                
 
330
                default:
 
331
                upsdebugx(1, "upsdrv_updateinfo: unknown test result: %s / %s",temp+3,test_result+3);
 
332
                break;
 
333
        }
103
334
 
104
335
        status_commit();
105
336
        /* dstate_dataok(); */
106
337
 
107
 
        upsdebugx(1, "ups.status = %s\n", dstate_getinfo("ups.status"));
 
338
        upsdebugx(1, "upsdrv_updateinfo: ups.status = %s\n", dstate_getinfo("ups.status"));
108
339
  
109
340
 
110
341
        /************** ups.x ***************************/
126
357
 
127
358
 
128
359
        /* ups.serial */
129
 
        if (get_data("vDS?",temp)) return;
130
 
        if (strcmp(temp+3,"NA"))
 
360
        if (exist_ups_serial)
 
361
                {
 
362
                if (get_data("vDS?",temp)) return;
131
363
                dstate_setinfo("ups.serial", "%s", temp+3);
 
364
                }
132
365
        upsdebugx(1, "ups.serial >%s<>%s<\n",temp,temp+3);   
133
366
 
134
367
        /* ups.firmware */ 
137
370
        upsdebugx(1, "ups.firmware >%s<>%s<\n",temp,temp+3);   
138
371
 
139
372
        /* ups.temperature */
140
 
        if (get_data("vBT?",temp)) return;
141
 
        if (strcmp(temp+3,"NA"))
 
373
        if (exist_ups_temperature)
 
374
                {
 
375
                if (get_data("vBT?",temp)) return;
142
376
                dstate_setinfo("ups.temperature", "%s", temp+3);
 
377
                }
143
378
        upsdebugx(1, "ups.temperature >%s<>%s<\n",temp,temp+3);   
144
379
 
145
380
        /* ups.load */
198
433
 
199
434
 
200
435
        /* output.current */
201
 
        if (get_data("vO0I?",temp)) return;
202
 
        if (strcmp(temp+4,"NA"))
 
436
        if (exist_output_current)
 
437
                {
 
438
                if (get_data("vO0I?",temp)) return;
203
439
                dstate_setinfo("output.current", "%2.1f", atof(temp+4) / 10.0);
 
440
                }
204
441
        upsdebugx(1, "output.current >%s<>%s<\n",temp,temp+4);   
205
442
   
206
443
   
207
444
        /*************** battery.x *******************************/
208
445
   
209
446
        /* battery charge */
210
 
        if (get_data("vBC?",temp)) return;
211
 
        if (strcmp(temp+3,"NA"))
 
447
        if (exist_battery_charge)
 
448
                {
 
449
                if (get_data("vBC?",temp)) return;
212
450
                dstate_setinfo("battery.charge", "%s", temp+3);
 
451
                }
213
452
        upsdebugx(1, "battery.charge >%s<>%s<\n",temp,temp+3);   
214
453
                                                                    
215
454
        /* battery.voltage */
219
458
        
220
459
 
221
460
        /* battery.current */
222
 
        if (get_data("vBI?",temp)) return;
223
 
        if (strcmp(temp+3,"NA"))
 
461
        if (exist_battery_current)
 
462
                {
 
463
                if (get_data("vBI?",temp)) return;
224
464
                dstate_setinfo("battery.current", "%2.1f", atof(temp+3) / 10.0);
 
465
                }
225
466
        upsdebugx(1, "battery.current >%s<>%s<\n",temp,temp+3);   
226
467
 
227
468
        /* battery.temperature */
228
 
        if (get_data("vBT?",temp)) return;
229
 
        if (strcmp(temp+3,"NA"))
 
469
        if (exist_battery_temperature)
 
470
                {
 
471
                if (get_data("vBT?",temp)) return;
230
472
                dstate_setinfo("battery.temperature", "%s", temp+3);
 
473
                }
231
474
        upsdebugx(1, "battery.temperature >%s<>%s<\n",temp,temp+3);   
232
475
 
 
476
 
233
477
        /* battery.runtime */
234
 
        if (get_data("vBt?",temp)) return;
235
 
        if (strcmp(temp+3,"NA"))
236
 
                dstate_setinfo("battery.runtime", "%s", temp+3);
237
 
        upsdebugx(1, "battery.runtime >%s<>%s<\n",temp,temp+3);   
 
478
        if (exist_battery_runtime)
 
479
                {
 
480
                if (get_data("vBt?",temp)) return;
 
481
                runtime_sec = strtol(temp+3, NULL, 10)*60;
 
482
                snprintf(temp, sizeof(temp), "%d", runtime_sec);
 
483
                dstate_setinfo("battery.runtime", "%s", temp);
 
484
                }
 
485
        upsdebugx(1, "battery.runtime >%s<>%d<\n",temp,runtime_sec);   
238
486
 
239
487
        dstate_dataok();
240
488
}
241
489
 
242
490
void upsdrv_shutdown(void)
243
491
{
244
 
        upssend ("vCc0!");
245
 
        usleep (UPS_DELAY);
246
 
                 
247
 
        upssend ("vCb%i!",sdwdelay);
248
 
}
249
 
 
250
 
 
251
 
void instcmd (int auxcmd, int dlen, char *data)
252
 
{
253
 
        /* TODO: reply to upsd? */
254
 
 
255
 
        switch (auxcmd) {
256
 
                /* case test.battery.stop:      * stop battery test *
257
 
                 *      upssend("vTi2");
258
 
                 *      break;
259
 
                 * case test.battery.start:     * start battery test *
260
 
                 *      upssend("vTi4");
261
 
                 *      break;
262
 
                 * case calibrate.stop:         * stop calibration *
263
 
                 *      upssend("vTi2");
264
 
                 *      break;
265
 
                 * case calibrate.start:        * start calibration *
266
 
                 *      upssend("vTi5");
267
 
                 *      break;
268
 
                 */
269
 
                default:
270
 
                        upslogx(LOG_INFO, "instcmd: unknown type 0x%04x", auxcmd);
271
 
        }
272
 
}
273
 
 
 
492
        ser_send(upsfd, "vCc0!%c", ENDCHAR);
 
493
        usleep(UPS_DELAY);
 
494
 
 
495
        ser_send(upsfd, "vCb%i!%c", sdwdelay, ENDCHAR); 
 
496
}
274
497
 
275
498
void upsdrv_help(void)
276
499
{
285
508
 
286
509
void upsdrv_banner(void)
287
510
{
288
 
        printf("Network UPS Tools - New Victron UPS driver %s (%s)\n\n",
 
511
        printf("Network UPS Tools - GE/IMV/Victron UPS driver %s (%s)\n\n",
289
512
                DRV_VERSION, UPS_VERSION);
290
513
}
291
514
 
292
515
void upsdrv_initups(void)
293
516
{
294
517
        char temp[ LENGTH_TEMP ], *usd = NULL;  /* = NULL je dulezite jen pro prekladac */
295
 
 
296
 
        upssend_endchar=ENDCHAR;
297
 
        if (nut_debug_level > 1) upsc_debug = nut_debug_level - 1; /* docasne reseni */
 
518
        
298
519
   
299
 
        upssend_delay = 0; /* zpozdeni mezi odeslanim jednotlivych znaku bude 0 sec */ 
300
 
        open_serial(device_path, B1200); 
301
 
 
302
 
    
 
520
        upsfd = ser_open(device_path);
 
521
        ser_set_speed(upsfd, device_path, B1200);
 
522
 
 
523
 
303
524
        if ((usd = getval("usd"))) sdwdelay=atoi(usd);
304
525
      
305
526
        model_name = getval("modelname"); /* kdyz modelname nebylo zadano je vraceno NULL*/ 
309
530
    
310
531
        /* inicializace a synchronizace UPS */
311
532
 
312
 
        upssendchar (ENDCHAR);
313
 
        usleep (UPS_LONG_DELAY);
314
 
        upssend ("?");
315
 
        usleep (UPS_LONG_DELAY);
316
 
        upsrecv (temp, sizeof(temp), ENDCHAR, IGNCHARS);
317
 
        upssend ("?");
318
 
        usleep (UPS_LONG_DELAY);
319
 
        upsrecv (temp, sizeof(temp), ENDCHAR, IGNCHARS);
320
 
        upssend ("?");
 
533
        ser_send_char(upsfd, ENDCHAR);
 
534
        usleep (UPS_LONG_DELAY);
 
535
        ser_send(upsfd, "?%c", ENDCHAR);
 
536
        usleep (UPS_LONG_DELAY);
 
537
        ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, IGNCHARS, 3, 0);
 
538
        ser_send(upsfd, "?%c", ENDCHAR);
 
539
        usleep (UPS_LONG_DELAY);
 
540
        ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, IGNCHARS, 3, 0);
 
541
        ser_send(upsfd, "?%c", ENDCHAR);
321
542
        usleep (UPS_DELAY);
322
 
        upsrecv (temp, sizeof(temp), ENDCHAR, IGNCHARS);
 
543
        ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, IGNCHARS, 3, 0);
323
544
 
324
545
 
325
546
        /* the upsh handlers can't be done here, as they get initialized
329
550
 
330
551
void upsdrv_cleanup(void)
331
552
{
 
553
        ser_close(upsfd, device_path);
332
554
}