2
metasys.c - driver for Meta System UPS
4
Copyright (C) 2004 Fabio Di Niro <fabio.diniro@email.it>
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.
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.
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
21
/* Uncomment if you want to read additional Meta System UPS data */
31
#define DRV_VERSION "0.05"
33
/* Autorestart flag */
35
int nominal_power = 0;
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
54
static int instcmd(const char *cmdname, const char *extra);
57
Metasystem UPS data transfer are made with packet of the format:
58
STX DATA_LENGHT DATA CHECKSUM
60
STX is 0x02 and is the start of transmission byte
61
DATA_LENGHT is number of data bytes + the checksum byte
63
CHECKSUM is the sum modulus 256 of all DATA bytes + DATA_LENGHT
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
68
int get_word(char *buffer) { /* return an integer reading a word in the supplied buffer */
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;
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;
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 */
94
memset(buf, '\0', sizeof(buf));
95
i = ser_send_buf(upsfd, buf, sizeof(buf));
100
/* was used just for the debug process */
101
void dump_buffer(char *buffer, int buf_len) {
103
for (i = 0; i < buf_len; i++) {
104
printf("byte %d: %x\n", i, (unsigned char)buffer[i]);
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) {
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);
127
/* send a write command to the UPS, the write command and the value to be written are passed
129
it retries 5 times before give up */
130
void send_write_command(char *command, int command_lenght) {
131
int i, retry, sent, checksum;
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);
140
/* calculate checksum */
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;
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]);
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;
163
res = ser_get_char(upsfd, my_buf, 1, 0);
165
ser_comm_fail("Receive error (STX): %d!!!\n", res);
168
if ((unsigned char)my_buf[0] != 0x02) {
169
ser_comm_fail("Receive error (STX): packet not on start!!\n");
172
/* Read data lenght byte */
173
res = ser_get_char(upsfd, my_buf, 1, 0);
175
ser_comm_fail("Receive error (lenght): %d!!!\n", res);
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);
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);
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);
201
packet_lenght-=1; /* get rid of the checksum byte */
202
memcpy(data, my_buf, packet_lenght);
203
return packet_lenght;
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) {
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);
219
if (((unsigned char)data[0] != command) || (retry == 5)) {
220
ser_comm_fail("Error executing command %d\n", command);
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) {
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);
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]);
250
void upsdrv_initinfo(void)
252
char my_answer[255], serial[13];
255
/* Initial setup of variables */
257
dstate_setinfo("output.power", "%d", -1);
258
dstate_setflags("output.power", ST_FLAG_RW);
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);
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);
270
dstate_setinfo("input.voltage", "%d", -1);
271
dstate_setflags("input.voltage", ST_FLAG_RW);
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);
278
dstate_setinfo("battery.voltage", "%d", -1);
279
dstate_setflags("battery.voltage", ST_FLAG_RW);
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);
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);
312
/* Fixed variables */
313
dstate_setinfo("driver.version.internal", "%s", DRV_VERSION);
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];
323
dstate_setinfo("ups.model", "%s", "HF Line (1 board)");
327
dstate_setinfo("ups.model", "%s", "HF Line (2 boards)");
328
nominal_power = 1260;
331
dstate_setinfo("ups.model", "%s", "HF Line (3 boards)");
332
nominal_power = 1890;
335
dstate_setinfo("ups.model", "%s", "HF Line (4 boards)");
336
nominal_power = 2520;
339
dstate_setinfo("ups.model", "%s", "ECO Network 750/1000");
343
dstate_setinfo("ups.model", "%s", "ECO Network 1050/1500");
347
dstate_setinfo("ups.model", "%s", "ECO Network 1500/2000");
348
nominal_power = 1000;
351
dstate_setinfo("ups.model", "%s", "ECO Network 1800/2500");
352
nominal_power = 1200;
355
dstate_setinfo("ups.model", "%s", "ECO Network 2100/3000");
356
nominal_power = 1400;
359
dstate_setinfo("ups.model", "%s", "ECO 308");
363
dstate_setinfo("ups.model", "%s", "ECO 311");
367
dstate_setinfo("ups.model", "%s", "HF Line (4 boards)/2");
368
nominal_power = 2520;
371
dstate_setinfo("ups.model", "%s", "HF Line (5 boards)/2");
372
nominal_power = 3150;
375
dstate_setinfo("ups.model", "%s", "HF Line (6 boards)/2");
376
nominal_power = 3780;
379
dstate_setinfo("ups.model", "%s", "HF Line (7 boards)/2");
380
nominal_power = 4410;
383
dstate_setinfo("ups.model", "%s", "HF Line (8 boards)/2");
384
nominal_power = 5040;
387
dstate_setinfo("ups.model", "%s", "HF Millennium 810");
391
dstate_setinfo("ups.model", "%s", "HF Millennium 820");
392
nominal_power = 1400;
395
dstate_setinfo("ups.model", "%s", "HF TOP Line 910");
399
dstate_setinfo("ups.model", "%s", "HF TOP Line 920");
400
nominal_power = 1400;
403
dstate_setinfo("ups.model", "%s", "HF TOP Line 930");
404
nominal_power = 2100;
407
dstate_setinfo("ups.model", "%s", "HF TOP Line 940");
408
nominal_power = 2800;
411
dstate_setinfo("ups.model", "%s", "HF TOP Line 940/2");
412
nominal_power = 2800;
415
dstate_setinfo("ups.model", "%s", "HF TOP Line 950/2");
416
nominal_power = 3500;
419
dstate_setinfo("ups.model", "%s", "HF TOP Line 960/2");
420
nominal_power = 4200;
423
dstate_setinfo("ups.model", "%s", "HF TOP Line 970/2");
424
nominal_power = 4900;
427
dstate_setinfo("ups.model", "%s", "HF TOP Line 980/2");
428
nominal_power = 5600;
431
dstate_setinfo("ups.model", "%s", "ECO 508");
435
dstate_setinfo("ups.model", "%s", "ECO 511");
439
dstate_setinfo("ups.model", "%s", "ECO 516");
440
nominal_power = 1000;
443
dstate_setinfo("ups.model", "%s", "ECO 519");
444
nominal_power = 1200;
447
dstate_setinfo("ups.model", "%s", "ECO 522");
448
nominal_power = 1400;
451
dstate_setinfo("ups.model", "%s", "ECO 305 / Harviot 530 SX");
455
dstate_setinfo("ups.model", "%s", "ORDINATORE 2");
459
dstate_setinfo("ups.model", "%s", "Harviot 730 SX");
463
dstate_setinfo("ups.model", "%s", "ECO 308 SX / SX Interactive / Ordinatore");
467
dstate_setinfo("ups.model", "%s", "ECO 311 SX / SX Interactive");
471
dstate_setinfo("ups.model", "%s", "ally HF 800 / BI-TWICE 800");
475
dstate_setinfo("ups.model", "%s", "ally HF 1600");
476
nominal_power = 1120;
479
dstate_setinfo("ups.model", "%s", "ally HF 1000 / BI-TWICE 1000");
483
dstate_setinfo("ups.model", "%s", "ally HF 2000");
484
nominal_power = 1400;
487
dstate_setinfo("ups.model", "%s", "ally HF 1250 / BI-TWICE 1250");
491
dstate_setinfo("ups.model", "%s", "ally HF 2500");
492
nominal_power = 1750;
495
dstate_setinfo("ups.model", "%s", "Megaline 1250");
499
dstate_setinfo("ups.model", "%s", "Megaline 2500");
500
nominal_power = 1750;
503
dstate_setinfo("ups.model", "%s", "Megaline 3750");
504
nominal_power = 2625;
507
dstate_setinfo("ups.model", "%s", "Megaline 5000");
508
nominal_power = 3500;
511
dstate_setinfo("ups.model", "%s", "Megaline 5000 / 2");
512
nominal_power = 3500;
515
dstate_setinfo("ups.model", "%s", "Megaline 6250 / 2");
516
nominal_power = 4375;
519
dstate_setinfo("ups.model", "%s", "Megaline 7500 / 2");
520
nominal_power = 5250;
523
dstate_setinfo("ups.model", "%s", "Megaline 8750 / 2");
524
nominal_power = 6125;
527
dstate_setinfo("ups.model", "%s", "Megaline 10000 / 2");
528
nominal_power = 7000;
532
fatal("Unknown UPS");
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);
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]);
545
printf("Detected %s [%s] v.%s on %s\n", dstate_getinfo("ups.model"), dstate_getinfo("ups.serial"), dstate_getinfo("ups.firmware"), device_path);
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;
560
void upsdrv_updateinfo(void)
564
int day, hour, minute;
570
/* GET Output data */
571
res = command_read_sequence(UPS_OUTPUT_DATA, my_answer);
573
printf("Could not communicate with the ups");
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);
582
dstate_setinfo("ups.load", "%s", "not available");
585
dstate_setinfo("output.power", "%d", int_num);
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");
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");
597
float_num = (float)(float_num/10);
598
dstate_setinfo("output.current", "%2.2f", float_num);
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");
606
float_num = (float)(float_num/10);
607
dstate_setinfo("output.current.peak", "%2.2f", float_num);
614
res = command_read_sequence(UPS_INPUT_DATA, my_answer);
616
printf("Could not communicate with the ups");
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");
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");
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");
637
float_num = (float)(float_num/10);
638
dstate_setinfo("input.current", "%2.2f", float_num);
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");
645
float_num = (float)(float_num/10);
646
dstate_setinfo("input.current.peak", "%2.2f", float_num);
652
/* GET Battery data */
653
res = command_read_sequence(UPS_BATTERY_DATA, my_answer);
655
printf("Could not communicate with the ups");
659
float_num = get_word(&my_answer[1]);
660
float_num = (float)(float_num/10);
661
dstate_setinfo("battery.voltage", "%2.2f", float_num);
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);
675
/* GET history data */
676
res = command_read_sequence(UPS_HISTORY_DATA, my_answer);
678
printf("Could not communicate with the ups");
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);
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);
715
/* GET times on battery */
716
res = command_read_sequence(UPS_GET_TIMES_ON_BATTERY, my_answer);
718
printf("Could not communicate with the ups");
721
autorestart = (unsigned char)my_answer[5];
726
res = command_read_sequence(UPS_GET_SCHEDULING, my_answer);
728
printf("Could not communicate with the ups");
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);
736
dstate_setinfo("ups.delay.shutdown", "%ld", long_num);
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);
743
dstate_setinfo("ups.delay.start", "%ld", long_num);
749
res = command_read_sequence(UPS_STATUS, my_answer);
751
printf("Could not communicate with the ups");
754
/* ups temperature */
756
if ((unsigned char)my_answer[3] > 0) {
757
dstate_setinfo("ups.temperature", "%d", (unsigned char)my_answer[3]);
759
dstate_setinfo("ups.temperature", "%s", "not available");
763
switch ((unsigned char)my_answer[1]) { /* byte 1 = STATUS */
765
status_set("OL"); /* running on mains power */
768
status_set("OB"); /* running on battery power */
771
status_set("LB"); /* battery reserve */
773
case 0x03: /* bypass engaged */
774
case 0x04: /* manual bypass engaged */
778
printf("status unknown \n");
781
switch ((unsigned char)my_answer[2]) { /* byte 2 = FAULTS */
782
case 0x00: /* all right */
784
case 0x01: /* overload */
787
case 0x02: /* overheat */
789
case 0x03: /* hardware fault */
791
case 0x04: /* battery charger failure (overcharging) */
793
case 0x05: /* replace batteries */
797
printf("status unknown \n");
806
void upsdrv_shutdown(void)
808
char command[10], answer[10];
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 */
815
command[0]=UPS_SET_TIMES_ON_BATTERY;
816
command[1]=0x00; /* max time on */
817
command[2]=0x00; /* battery */
819
command[3]=0x00; /* max time after */
820
command[4]=0x00; /* battery reserve */
822
command[5]=0x01; /* autorestart after battery depleted enabled */
823
command_write_sequence(command, 6, answer);
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 */
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);
841
/* you may have to check the line status since the commands
842
for toggling power are frequently different for OL vs. OB */
844
/* OL: this must power cycle the load if possible */
846
/* OB: the load must remain off until the power returns */
850
static int instcmd(const char *cmdname, const char *extra)
852
char command[10], answer[10];
855
if (!strcasecmp(cmdname, "shutdown.return")) {
856
/* Same stuff as upsdrv_shutdown() */
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);
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 */
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;
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 */
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;
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) */
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;
913
if (!strcasecmp(cmdname, "test.failure.start")) {
914
/* force ups on battery power */
915
command[0]=UPS_SET_BATTERY_TEST;
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;
924
if (!strcasecmp(cmdname, "test.failure.stop")) {
925
/* restore standard mode (mains power) */
926
command[0]=UPS_SET_BATTERY_TEST;
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;
935
if (!strcasecmp(cmdname, "test.battery.start")) {
936
/* launch battery test */
937
command[0]=UPS_SET_BATTERY_TEST;
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);
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");
950
dstate_setinfo("ups.test.result", "Battery charge: 20%%");
953
dstate_setinfo("ups.test.result", "Battery charge: 40%%");
956
dstate_setinfo("ups.test.result", "Battery charge: 60%%");
959
dstate_setinfo("ups.test.result", "Battery charge: 80%%");
962
dstate_setinfo("ups.test.result", "Battery charge: 100%%");
965
dstate_setinfo("ups.test.result", "Bad battery pack: replace");
968
dstate_setinfo("ups.test.result", "Impossible to test");
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;
977
if (!strcasecmp(cmdname, "beeper.on")) {
978
/* set buzzer to not muted */
979
command[0]=UPS_SET_BUZZER_MUTE;
983
2 = read current status */
984
command_write_sequence(command, 2, answer);
985
return STAT_INSTCMD_HANDLED;
988
if (!strcasecmp(cmdname, "beeper.off")) {
989
/* set buzzer to muted */
990
command[0]=UPS_SET_BUZZER_MUTE;
994
2 = read current status */
995
command_write_sequence(command, 2, answer);
996
return STAT_INSTCMD_HANDLED;
997
return STAT_INSTCMD_HANDLED;
1000
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
1001
return STAT_INSTCMD_UNKNOWN;
1005
void upsdrv_help(void)
1009
/* list flags and values that you want to receive via -x */
1010
void upsdrv_makevartable(void)
1012
/* allow '-x xyzzy' */
1013
/* addvar(VAR_FLAG, "xyzzy", "Enable xyzzy mode"); */
1015
/* allow '-x foo=<some value>' */
1016
/* addvar(VAR_VALUE, "foo", "Override foo setting"); */
1020
void upsdrv_banner(void)
1022
printf("Network UPS Tools - Metasystem UPS driver %s \n\n",
1026
void upsdrv_initups(void)
1028
upsfd = ser_open(device_path);
1029
ser_set_speed(upsfd, device_path, B2400);
1033
void upsdrv_cleanup(void)
1035
ser_close(upsfd, device_path);