1 /*
2 * riello_ser.c: support for Riello serial protocol based UPSes
3 *
4 * A document describing the protocol implemented by this driver can be
5 * found online at "http://www.networkupstools.org/ups-protocols/riello/PSGPSER-0104.pdf"
6 * and "http://www.networkupstools.org/ups-protocols/riello/PSSENTR-0100.pdf".
7 *
8 * Copyright (C) 2012 - Elio Parisi <e.parisi@riello-ups.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Reference of the derivative work: blazer driver
25 */
26
27 #include <string.h>
28 #include <stdint.h>
29
30 #include "config.h"
31 #include "main.h"
32 #include "serial.h"
33 #include "timehead.h"
34 #include "hidparser.h"
35 #include "hidtypes.h"
36 #include "common.h" /* for upsdebugx() etc */
37 #include "riello.h"
38
39 #define DRIVER_NAME "Riello serial driver"
40 #define DRIVER_VERSION "0.03"
41
42 /* driver description structure */
43 upsdrv_info_t upsdrv_info = {
44 DRIVER_NAME,
45 DRIVER_VERSION,
46 "Elio Parisi <e.parisi@riello-ups.com>",
47 DRV_EXPERIMENTAL,
48 { NULL }
49 };
50
51 uint8_t bufOut[BUFFER_SIZE];
52 uint8_t bufIn[BUFFER_SIZE];
53
54 uint8_t gpser_error_control;
55 uint8_t typeRielloProtocol;
56
57 uint8_t input_monophase;
58 uint8_t output_monophase;
59
60 extern uint8_t commbyte;
61 extern uint8_t wait_packet;
62 extern uint8_t foundnak;
63 extern uint8_t foundbadcrc;
64 extern uint8_t buf_ptr_length;
65 extern uint8_t requestSENTR;
66
67 TRielloData DevData;
68
69 /**********************************************************************
70 * char_read (char *bytes, int size, int read_timeout)
71 *
72 * reads size bytes from the serial port
73 *
74 * bytes - buffer to store the data
75 * size - size of the data to get
76 * read_timeout - serial timeout (in milliseconds)
77 *
78 * return -1 on error, -2 on timeout, nb_bytes_readen on success
79 *
80 *********************************************************************/
char_read(char * bytes,int size,int read_timeout)81 static int char_read (char *bytes, int size, int read_timeout)
82 {
83 struct timeval serial_timeout;
84 fd_set readfs;
85 int readen = 0;
86 int rc = 0;
87
88 FD_ZERO (&readfs);
89 FD_SET (upsfd, &readfs);
90
91 serial_timeout.tv_usec = (read_timeout % 1000) * 1000;
92 serial_timeout.tv_sec = (read_timeout / 1000);
93
94 rc = select (upsfd + 1, &readfs, NULL, NULL, &serial_timeout);
95 if (0 == rc)
96 return -2; /* timeout */
97
98 if (FD_ISSET (upsfd, &readfs)) {
99 int now = read (upsfd, bytes, size - readen);
100
101 if (now < 0) {
102 return -1;
103 }
104 else {
105 bytes += now;
106 readen += now;
107 }
108 }
109 else {
110 return -1;
111 }
112 return readen;
113 }
114
115 /**********************************************************************
116 * serial_read (int read_timeout)
117 *
118 * return data one byte at a time
119 *
120 * read_timeout - serial timeout (in milliseconds)
121 *
122 * returns 0 on success, -1 on error, -2 on timeout
123 *
124 **********************************************************************/
serial_read(int read_timeout,u_char * readbuf)125 int serial_read (int read_timeout, u_char *readbuf)
126 {
127 static u_char cache[512];
128 static u_char *cachep = cache;
129 static u_char *cachee = cache;
130 int recv;
131 *readbuf = '\0';
132
133 /* if still data in cache, get it */
134 if (cachep < cachee) {
135 *readbuf = *cachep++;
136 return 0;
137 /* return (int) *cachep++; */
138 }
139 recv = char_read ((char *)cache, 1, read_timeout);
140
141 if ((recv == -1) || (recv == -2))
142 return recv;
143
144 cachep = cache;
145 cachee = cache + recv;
146 cachep = cache;
147 cachee = cache + recv;
148
149 if (recv) {
150 upsdebugx(5,"received: %02x", *cachep);
151 *readbuf = *cachep++;
152 return 0;
153 }
154 return -1;
155 }
156
riello_serialcomm(uint8_t * bufIn,uint8_t typedev)157 void riello_serialcomm(uint8_t* bufIn, uint8_t typedev)
158 {
159 time_t realt, nowt;
160 uint8_t commb = 0;
161
162 realt = time(NULL);
163 while (wait_packet) {
164 serial_read(1000, &commb);
165 nowt = time(NULL);
166 commbyte = commb;
167 riello_parse_serialport(typedev, bufIn, gpser_error_control);
168
169 if ((nowt - realt) > 4)
170 break;
171 }
172 }
173
get_ups_nominal()174 int get_ups_nominal()
175 {
176 uint8_t length;
177
178 riello_init_serial();
179
180 length = riello_prepare_gn(&bufOut[0], gpser_error_control);
181
182 if (ser_send_buf(upsfd, bufOut, length) == 0) {
183 upsdebugx (3, "Communication error while writing to port");
184 return -1;
185 }
186
187 riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
188
189 if (!wait_packet && foundbadcrc) {
190 upsdebugx (3, "Get nominal Ko: bad CRC or Checksum");
191 return -1;
192 }
193
194 /* mandatory */
195 if (!wait_packet && foundnak) {
196 upsdebugx (3, "Get nominal Ko: command not supported");
197 return -1;
198 }
199
200 upsdebugx (3, "Get nominal Ok: received byte %u", buf_ptr_length);
201
202 riello_parse_gn(&bufIn[0], &DevData);
203
204 return 0;
205 }
206
get_ups_status()207 int get_ups_status()
208 {
209 uint8_t numread, length;
210
211 riello_init_serial();
212
213 length = riello_prepare_rs(&bufOut[0], gpser_error_control);
214
215 if (ser_send_buf(upsfd, bufOut, length) == 0) {
216 upsdebugx (3, "Communication error while writing to port");
217 return -1;
218 }
219
220 if (input_monophase)
221 numread = LENGTH_RS_MM;
222 else if (output_monophase)
223 numread = LENGTH_RS_TM;
224 else
225 numread = LENGTH_RS_TT;
226
227 riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
228
229 if (!wait_packet && foundbadcrc) {
230 upsdebugx (3, "Get status Ko: bad CRC or Checksum");
231 return -1;
232 }
233
234 /* mandatory */
235 if (!wait_packet && foundnak) {
236 upsdebugx (3, "Get status Ko: command not supported");
237 return -1;
238 }
239
240 upsdebugx (3, "Get status Ok: received byte %u", buf_ptr_length);
241
242 riello_parse_rs(&bufIn[0], &DevData, numread);
243
244 return 0;
245 }
246
get_ups_extended()247 int get_ups_extended()
248 {
249 uint8_t length;
250
251 riello_init_serial();
252
253 length = riello_prepare_re(&bufOut[0], gpser_error_control);
254
255 if (ser_send_buf(upsfd, bufOut, length) == 0) {
256 upsdebugx (3, "Communication error while writing to port");
257 return -1;
258 }
259
260 riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
261
262 if (!wait_packet && foundbadcrc) {
263 upsdebugx (3, "Get extended Ko: bad CRC or Checksum");
264 return -1;
265 }
266
267 /* optonal */
268 if (!wait_packet && foundnak) {
269 upsdebugx (3, "Get extended Ko: command not supported");
270 return 0;
271 }
272
273 upsdebugx (3, "Get extended Ok: received byte %u", buf_ptr_length);
274
275 riello_parse_re(&bufIn[0], &DevData);
276
277 return 0;
278 }
279
get_ups_statuscode()280 int get_ups_statuscode()
281 {
282 uint8_t length;
283
284 riello_init_serial();
285
286 length = riello_prepare_rc(&bufOut[0], gpser_error_control);
287
288 if (ser_send_buf(upsfd, bufOut, length) == 0) {
289 upsdebugx (3, "Communication error while writing to port");
290 return -1;
291 }
292
293 riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
294
295 if (!wait_packet && foundbadcrc) {
296 upsdebugx (3, "Get statuscode Ko: bad CRC or Checksum");
297 return -1;
298 }
299
300 /* optional */
301 if (!wait_packet && foundnak) {
302 upsdebugx (3, "Get statuscode Ko: command not supported");
303 return 0;
304 }
305
306 upsdebugx (3, "Get statuscode Ok: received byte %u", buf_ptr_length);
307
308 riello_parse_rc(&bufIn[0], &DevData);
309
310 return 0;
311 }
312
get_ups_sentr()313 int get_ups_sentr()
314 {
315 uint8_t length;
316
317 riello_init_serial();
318
319 bufOut[0] = requestSENTR;
320
321 if (requestSENTR == SENTR_EXT176) {
322 bufOut[1] = 103;
323 bufOut[2] = 1;
324 bufOut[3] = 0;
325 bufOut[4] = 24;
326 length = 5;
327 }
328 else
329 length = 1;
330
331 if (ser_send_buf(upsfd, bufOut, length) == 0) {
332 upsdebugx (3, "Communication error while writing to port");
333 return -1;
334 }
335
336 riello_serialcomm(&bufIn[0], DEV_RIELLOSENTRY);
337
338 if (!wait_packet && foundbadcrc) {
339 upsdebugx (3, "Get sentry Ko: bad CRC or Checksum");
340 return -1;
341 }
342
343 /* mandatory */
344 if (!wait_packet && foundnak) {
345 upsdebugx (3, "Get sentry Ko: command not supported");
346 return -1;
347 }
348
349 upsdebugx (3, "Get sentry Ok: received byte %u", buf_ptr_length);
350
351 riello_parse_sentr(&bufIn[0], &DevData);
352
353 return 0;
354 }
355
riello_instcmd(const char * cmdname,const char * extra)356 int riello_instcmd(const char *cmdname, const char *extra)
357 {
358 uint8_t length;
359 uint16_t delay;
360 const char *delay_char;
361
362 if (!riello_test_bit(&DevData.StatusCode[0], 1)) {
363 if (!strcasecmp(cmdname, "load.off")) {
364 delay = 0;
365 riello_init_serial();
366
367 if (typeRielloProtocol == DEV_RIELLOGPSER)
368 length = riello_prepare_cs(bufOut, gpser_error_control, delay);
369 else
370 length = riello_prepare_shutsentr(bufOut, delay);
371
372 if (ser_send_buf(upsfd, bufOut, length) == 0) {
373 upsdebugx (3, "Command load.off communication error");
374 return STAT_INSTCMD_FAILED;
375 }
376
377 riello_serialcomm(&bufIn[0], typeRielloProtocol);
378 if (!wait_packet && foundbadcrc) {
379 upsdebugx (3, "Command load.off Ko: bad CRC or Checksum");
380 return STAT_INSTCMD_FAILED;
381 }
382
383 if (!wait_packet && foundnak) {
384 upsdebugx (3, "Command load.off Ko: command not supported");
385 return STAT_INSTCMD_FAILED;
386 }
387
388 upsdebugx (3, "Command load.off Ok");
389 return STAT_INSTCMD_HANDLED;
390 }
391
392 if (!strcasecmp(cmdname, "load.off.delay")) {
393 delay_char = dstate_getinfo("ups.delay.shutdown");
394 delay = atoi(delay_char);
395 riello_init_serial();
396
397 if (typeRielloProtocol == DEV_RIELLOGPSER)
398 length = riello_prepare_cs(bufOut, gpser_error_control, delay);
399 else
400 length = riello_prepare_shutsentr(bufOut, delay);
401
402 if (ser_send_buf(upsfd, bufOut, length) == 0) {
403 upsdebugx (3, "Command load.off delay communication error");
404 return STAT_INSTCMD_FAILED;
405 }
406
407 riello_serialcomm(&bufIn[0], typeRielloProtocol);
408 if (!wait_packet && foundbadcrc) {
409 upsdebugx (3, "Command load.off.delay Ko: bad CRC or Checksum");
410 return STAT_INSTCMD_FAILED;
411 }
412
413 if (!wait_packet && foundnak) {
414 upsdebugx (3, "Command load.off.delay Ko: command not supported");
415 return STAT_INSTCMD_FAILED;
416 }
417
418 upsdebugx (3, "Command load.off delay Ok");
419 return STAT_INSTCMD_HANDLED;
420 }
421
422 if (!strcasecmp(cmdname, "load.on")) {
423 delay = 0;
424 riello_init_serial();
425
426 if (typeRielloProtocol == DEV_RIELLOGPSER)
427 length = riello_prepare_cr(bufOut, gpser_error_control, delay);
428 else {
429 length = riello_prepare_setrebsentr(bufOut, delay);
430
431 if (ser_send_buf(upsfd, bufOut, length) == 0) {
432 upsdebugx (3, "Command load.on communication error");
433 return STAT_INSTCMD_FAILED;
434 }
435
436 riello_serialcomm(&bufIn[0], typeRielloProtocol);
437 if (!wait_packet && foundbadcrc) {
438 upsdebugx (3, "Command load.on Ko: bad CRC or Checksum");
439 return STAT_INSTCMD_FAILED;
440 }
441
442 if (!wait_packet && foundnak) {
443 upsdebugx (3, "Command load.on Ko: command not supported");
444 return STAT_INSTCMD_FAILED;
445 }
446
447 length = riello_prepare_rebsentr(bufOut, delay);
448 }
449
450 if (ser_send_buf(upsfd, bufOut, length) == 0) {
451 upsdebugx (3, "Command load.on communication error");
452 return STAT_INSTCMD_FAILED;
453 }
454
455 riello_serialcomm(&bufIn[0], typeRielloProtocol);
456 if (!wait_packet && foundbadcrc) {
457 upsdebugx (3, "Command load.on Ko: bad CRC or Checksum");
458 return STAT_INSTCMD_FAILED;
459 }
460
461 if (!wait_packet && foundnak) {
462 upsdebugx (3, "Command load.on Ko: command not supported");
463 return STAT_INSTCMD_FAILED;
464 }
465
466 upsdebugx (3, "Command load.on Ok");
467 return STAT_INSTCMD_HANDLED;
468 }
469
470 if (!strcasecmp(cmdname, "load.on.delay")) {
471 delay_char = dstate_getinfo("ups.delay.reboot");
472 delay = atoi(delay_char);
473 riello_init_serial();
474
475 if (typeRielloProtocol == DEV_RIELLOGPSER)
476 length = riello_prepare_cr(bufOut, gpser_error_control, delay);
477 else {
478 length = riello_prepare_setrebsentr(bufOut, delay);
479
480 if (ser_send_buf(upsfd, bufOut, length) == 0) {
481 upsdebugx (3, "Command load.on delay communication error");
482 return STAT_INSTCMD_FAILED;
483 }
484
485 riello_serialcomm(&bufIn[0], typeRielloProtocol);
486 if (!wait_packet && foundbadcrc) {
487 upsdebugx (3, "Command load.on delay Ko: bad CRC or Checksum");
488 return STAT_INSTCMD_FAILED;
489 }
490
491 if (!wait_packet && foundnak) {
492 upsdebugx (3, "Command load.on delay Ko: command not supported");
493 return STAT_INSTCMD_FAILED;
494 }
495
496 length = riello_prepare_rebsentr(bufOut, delay);
497 }
498
499 if (ser_send_buf(upsfd, bufOut, length) == 0) {
500 upsdebugx (3, "Command load.on delay communication error");
501 return STAT_INSTCMD_FAILED;
502 }
503
504 riello_serialcomm(&bufIn[0], typeRielloProtocol);
505 if (!wait_packet && foundbadcrc) {
506 upsdebugx (3, "Command load.on.delay Ko: bad CRC or Checksum");
507 return STAT_INSTCMD_FAILED;
508 }
509
510 if (!wait_packet && foundnak) {
511 upsdebugx (3, "Command load.on.delay Ko: command not supported");
512 return STAT_INSTCMD_FAILED;
513 }
514
515 upsdebugx (3, "Command load.on delay Ok");
516 return STAT_INSTCMD_HANDLED;
517 }
518 }
519 else {
520 if (!strcasecmp(cmdname, "shutdown.return")) {
521 delay_char = dstate_getinfo("ups.delay.shutdown");
522 delay = atoi(delay_char);
523 riello_init_serial();
524
525 if (typeRielloProtocol == DEV_RIELLOGPSER)
526 length = riello_prepare_cs(bufOut, gpser_error_control, delay);
527 else
528 length = riello_prepare_shutsentr(bufOut, delay);
529
530 if (ser_send_buf(upsfd, bufOut, length) == 0) {
531 upsdebugx (3, "Command shutdown.return communication error");
532 return STAT_INSTCMD_FAILED;
533 }
534
535 riello_serialcomm(&bufIn[0], typeRielloProtocol);
536 if (!wait_packet && foundbadcrc) {
537 upsdebugx (3, "Command shutdown.return Ko: bad CRC or Checksum");
538 return STAT_INSTCMD_FAILED;
539 }
540
541 if (!wait_packet && foundnak) {
542 upsdebugx (3, "Command shutdown.return Ko: command not supported");
543 return STAT_INSTCMD_FAILED;
544 }
545
546 upsdebugx (3, "Command shutdown.return Ok");
547 return STAT_INSTCMD_HANDLED;
548 }
549 }
550
551 if (!strcasecmp(cmdname, "shutdown.stop")) {
552 riello_init_serial();
553
554 if (typeRielloProtocol == DEV_RIELLOGPSER)
555 length = riello_prepare_cd(bufOut, gpser_error_control);
556 else
557 length = riello_prepare_cancelsentr(bufOut);
558
559 if (ser_send_buf(upsfd, bufOut, length) == 0) {
560 upsdebugx (3, "Command shutdown.stop communication error");
561 return STAT_INSTCMD_FAILED;
562 }
563
564 riello_serialcomm(&bufIn[0], typeRielloProtocol);
565 if (!wait_packet && foundbadcrc) {
566 upsdebugx (3, "Command shutdown.stop Ko: bad CRC or Checksum");
567 return STAT_INSTCMD_FAILED;
568 }
569
570 if (!wait_packet && foundnak) {
571 upsdebugx (3, "Command shutdown.stop Ko: command not supported");
572 return STAT_INSTCMD_FAILED;
573 }
574
575 upsdebugx (3, "Command shutdown.stop Ok");
576 return STAT_INSTCMD_HANDLED;
577 }
578
579 if (!strcasecmp(cmdname, "test.panel.start")) {
580 riello_init_serial();
581 length = riello_prepare_tp(bufOut, gpser_error_control);
582
583 if (ser_send_buf(upsfd, bufOut, length) == 0) {
584 upsdebugx (3, "Command test.panel.start communication error");
585 return STAT_INSTCMD_FAILED;
586 }
587
588 riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
589 if (!wait_packet && foundbadcrc) {
590 upsdebugx (3, "Command test.panel.start Ko: bad CRC or Checksum");
591 return STAT_INSTCMD_FAILED;
592 }
593
594 if (!wait_packet && foundnak) {
595 upsdebugx (3, "Command test.panel.start Ko: command not supported");
596 return STAT_INSTCMD_FAILED;
597 }
598
599 upsdebugx (3, "Command test.panel.start Ok");
600 return STAT_INSTCMD_HANDLED;
601 }
602
603 if (!strcasecmp(cmdname, "test.battery.start")) {
604 riello_init_serial();
605 if (typeRielloProtocol == DEV_RIELLOGPSER)
606 length = riello_prepare_tb(bufOut, gpser_error_control);
607 else
608 length = riello_prepare_tbsentr(bufOut);
609
610 if (ser_send_buf(upsfd, bufOut, length) == 0) {
611 upsdebugx (3, "Command test.battery.start communication error");
612 return STAT_INSTCMD_FAILED;
613 }
614
615 riello_serialcomm(&bufIn[0], typeRielloProtocol);
616 if (!wait_packet && foundbadcrc) {
617 upsdebugx (3, "Command battery.start Ko: bad CRC or Checksum");
618 return STAT_INSTCMD_FAILED;
619 }
620
621 if (!wait_packet && foundnak) {
622 upsdebugx (3, "Command battery.start Ko: command not supported");
623 return STAT_INSTCMD_FAILED;
624 }
625
626 upsdebugx (3, "Command test.battery.start Ok");
627 return STAT_INSTCMD_HANDLED;
628 }
629
630 upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
631 return STAT_INSTCMD_UNKNOWN;
632 }
633
start_ups_comm()634 int start_ups_comm()
635 {
636 uint8_t length;
637
638 upsdebugx (2, "entering start_ups_comm()\n");
639
640 riello_init_serial();
641
642 if (typeRielloProtocol == DEV_RIELLOGPSER) {
643 length = riello_prepare_gi(&bufOut[0]);
644
645 if (ser_send_buf(upsfd, bufOut, length) == 0) {
646 upsdebugx (3, "Communication error while writing to port");
647 return -1;
648 }
649
650 riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
651 }
652 else {
653 bufOut[0] = 192;
654 length = 1;
655
656 if (ser_send_buf(upsfd, bufOut, length) == 0) {
657 upsdebugx (3, "Communication error while writing to port");
658 return -1;
659 }
660
661 riello_serialcomm(&bufIn[0], DEV_RIELLOSENTRY);
662 }
663
664 if (!wait_packet && foundbadcrc) {
665 upsdebugx (3, "Get identif Ko: bad CRC or Checksum");
666 return 1;
667 }
668
669 if (!wait_packet && foundnak) {
670 upsdebugx (3, "Get identif Ko: command not supported");
671 return 1;
672 }
673
674 upsdebugx (3, "Get identif Ok: received byte %u", buf_ptr_length);
675 return 0;
676
677 }
678
upsdrv_initinfo(void)679 void upsdrv_initinfo(void)
680 {
681 int ret;
682
683 ret = start_ups_comm();
684
685 if (ret < 0)
686 fatalx(EXIT_FAILURE, "No communication with UPS");
687 else if (ret > 0)
688 fatalx(EXIT_FAILURE, "Bad checksum or NACK");
689 else
690 upsdebugx(2, "Communication with UPS established");
691
692 if (typeRielloProtocol == DEV_RIELLOGPSER)
693 riello_parse_gi(&bufIn[0], &DevData);
694 else
695 riello_parse_sentr(&bufIn[0], &DevData);
696
697 gpser_error_control = DevData.Identif_bytes[4]-0x30;
698 if ((DevData.Identif_bytes[0] == '1') || (DevData.Identif_bytes[0] == '2'))
699 input_monophase = 1;
700 else {
701 input_monophase = 0;
702 dstate_setinfo("input.phases", "%u", 3);
703 dstate_setinfo("input.phases", "%u", 3);
704 dstate_setinfo("input.bypass.phases", "%u", 3);
705 }
706 if ((DevData.Identif_bytes[0] == '1') || (DevData.Identif_bytes[0] == '3'))
707 output_monophase = 1;
708 else {
709 output_monophase = 0;
710 dstate_setinfo("output.phases", "%u", 3);
711 }
712
713 dstate_setinfo("device.mfr", "RPS S.p.a.");
714 dstate_setinfo("device.model", "%s", (unsigned char*) DevData.ModelStr);
715 dstate_setinfo("device.serial", "%s", (unsigned char*) DevData.Identification);
716 dstate_setinfo("device.type", "ups");
717
718 dstate_setinfo("ups.mfr", "RPS S.p.a.");
719 dstate_setinfo("ups.model", "%s", (unsigned char*) DevData.ModelStr);
720 dstate_setinfo("ups.serial", "%s", (unsigned char*) DevData.Identification);
721 dstate_setinfo("ups.firmware", "%s", (unsigned char*) DevData.Version);
722
723 if (typeRielloProtocol == DEV_RIELLOGPSER) {
724 if (get_ups_nominal() == 0) {
725 dstate_setinfo("ups.realpower.nominal", "%u", DevData.NomPowerKW);
726 dstate_setinfo("ups.power.nominal", "%u", DevData.NomPowerKVA);
727 dstate_setinfo("output.voltage.nominal", "%u", DevData.NominalUout);
728 dstate_setinfo("output.frequency.nominal", "%.1f", DevData.NomFout/10.0);
729 dstate_setinfo("battery.voltage.nominal", "%u", DevData.NomUbat);
730 dstate_setinfo("battery.capacity", "%u", DevData.NomBatCap);
731 }
732 }
733 else {
734 if (get_ups_sentr() == 0) {
735 dstate_setinfo("ups.realpower.nominal", "%u", DevData.NomPowerKW);
736 dstate_setinfo("ups.power.nominal", "%u", DevData.NomPowerKVA);
737 dstate_setinfo("output.voltage.nominal", "%u", DevData.NominalUout);
738 dstate_setinfo("output.frequency.nominal", "%.1f", DevData.NomFout/10.0);
739 dstate_setinfo("battery.voltage.nominal", "%u", DevData.NomUbat);
740 dstate_setinfo("battery.capacity", "%u", DevData.NomBatCap);
741 }
742 }
743
744
745 /* commands ----------------------------------------------- */
746 dstate_addcmd("load.off");
747 dstate_addcmd("load.on");
748 dstate_addcmd("load.off.delay");
749 dstate_addcmd("load.on.delay");
750 dstate_addcmd("shutdown.return");
751 dstate_addcmd("shutdown.stop");
752 dstate_addcmd("test.battery.start");
753
754 if (typeRielloProtocol == DEV_RIELLOGPSER)
755 dstate_addcmd("test.panel.start");
756
757 /* install handlers */
758 /* upsh.setvar = hid_set_value; setvar; */
759 upsh.instcmd = riello_instcmd;
760 }
761
upsdrv_updateinfo(void)762 void upsdrv_updateinfo(void)
763 {
764 uint8_t getextendedOK;
765 static int countlost = 0;
766 int stat;
767
768 upsdebugx(1, "countlost %d",countlost);
769
770 if (countlost > 0){
771 upsdebugx(1, "Communication with UPS is lost: status read failed!");
772
773 if (countlost == COUNTLOST) {
774 dstate_datastale();
775 upslogx(LOG_WARNING, "Communication with UPS is lost: status read failed!");
776 }
777 }
778
779 if (typeRielloProtocol == DEV_RIELLOGPSER)
780 stat = get_ups_status();
781 else
782 stat = get_ups_sentr();
783
784 if (stat < 0) {
785 if (countlost < COUNTLOST)
786 countlost++;
787 return;
788 }
789
790 if (typeRielloProtocol == DEV_RIELLOGPSER) {
791 if (get_ups_extended() == 0)
792 getextendedOK = 1;
793 else
794 getextendedOK = 0;
795 }
796 else
797 getextendedOK = 1;
798
799 if (countlost == COUNTLOST)
800 upslogx(LOG_NOTICE, "Communication with UPS is re-established!");
801
802 dstate_setinfo("input.frequency", "%.2f", DevData.Finp/10.0);
803 dstate_setinfo("input.bypass.frequency", "%.2f", DevData.Fbypass/10.0);
804 dstate_setinfo("output.frequency", "%.2f", DevData.Fout/10.0);
805 dstate_setinfo("battery.voltage", "%.1f", DevData.Ubat/10.0);
806 dstate_setinfo("battery.charge", "%u", DevData.BatCap);
807 dstate_setinfo("battery.runtime", "%u", DevData.BatTime*60);
808 dstate_setinfo("ups.temperature", "%u", DevData.Tsystem);
809
810 if (input_monophase) {
811 dstate_setinfo("input.voltage", "%u", DevData.Uinp1);
812 dstate_setinfo("input.bypass.voltage", "%u", DevData.Ubypass1);
813 }
814 else {
815 dstate_setinfo("input.L1-N.voltage", "%u", DevData.Uinp1);
816 dstate_setinfo("input.L2-N.voltage", "%u", DevData.Uinp2);
817 dstate_setinfo("input.L3-N.voltage", "%u", DevData.Uinp3);
818 dstate_setinfo("input.bypass.L1-N.voltage", "%u", DevData.Ubypass1);
819 dstate_setinfo("input.bypass.L2-N.voltage", "%u", DevData.Ubypass2);
820 dstate_setinfo("input.bypass.L3-N.voltage", "%u", DevData.Ubypass3);
821 }
822
823 if (output_monophase) {
824 dstate_setinfo("output.voltage", "%u", DevData.Uout1);
825 dstate_setinfo("output.power.percent", "%u", DevData.Pout1);
826 dstate_setinfo("ups.load", "%u", DevData.Pout1);
827 }
828 else {
829 dstate_setinfo("output.L1-N.voltage", "%u", DevData.Uout1);
830 dstate_setinfo("output.L2-N.voltage", "%u", DevData.Uout2);
831 dstate_setinfo("output.L3-N.voltage", "%u", DevData.Uout3);
832 dstate_setinfo("output.L1.power.percent", "%u", DevData.Pout1);
833 dstate_setinfo("output.L2.power.percent", "%u", DevData.Pout2);
834 dstate_setinfo("output.L3.power.percent", "%u", DevData.Pout3);
835 dstate_setinfo("ups.load", "%u", (DevData.Pout1+DevData.Pout2+DevData.Pout3)/3);
836 }
837
838 status_init();
839
840 /* AC Fail */
841 if (riello_test_bit(&DevData.StatusCode[0], 1))
842 status_set("OB");
843 else
844 status_set("OL");
845
846 /* LowBatt */
847 if ((riello_test_bit(&DevData.StatusCode[0], 1)) &&
848 (riello_test_bit(&DevData.StatusCode[0], 0)))
849 status_set("LB");
850
851 /* Standby */
852 if (!riello_test_bit(&DevData.StatusCode[0], 3))
853 status_set("OFF");
854
855 /* On Bypass */
856 if (riello_test_bit(&DevData.StatusCode[1], 3))
857 status_set("BYPASS");
858
859 /* Overload */
860 if (riello_test_bit(&DevData.StatusCode[4], 2))
861 status_set("OVER");
862
863 /* Buck */
864 if (riello_test_bit(&DevData.StatusCode[1], 0))
865 status_set("TRIM");
866
867 /* Boost */
868 if (riello_test_bit(&DevData.StatusCode[1], 1))
869 status_set("BOOST");
870
871 /* Replace battery */
872 if (riello_test_bit(&DevData.StatusCode[2], 0))
873 status_set("RB");
874
875 /* Charging battery */
876 if (riello_test_bit(&DevData.StatusCode[2], 2))
877 status_set("CHRG");
878
879 status_commit();
880
881 dstate_dataok();
882
883 if (getextendedOK) {
884 dstate_setinfo("output.L1.power", "%u", DevData.Pout1VA);
885 dstate_setinfo("output.L2.power", "%u", DevData.Pout2VA);
886 dstate_setinfo("output.L3.power", "%u", DevData.Pout3VA);
887 dstate_setinfo("output.L1.realpower", "%u", DevData.Pout1W);
888 dstate_setinfo("output.L2.realpower", "%u", DevData.Pout2W);
889 dstate_setinfo("output.L3.realpower", "%u", DevData.Pout3W);
890 dstate_setinfo("output.L1.current", "%u", DevData.Iout1);
891 dstate_setinfo("output.L2.current", "%u", DevData.Iout2);
892 dstate_setinfo("output.L3.current", "%u", DevData.Iout3);
893 }
894
895 poll_interval = 2;
896
897 countlost = 0;
898 /* if (get_ups_statuscode() != 0)
899 upsdebugx(2, "Communication is lost");
900 else {
901 }*/
902
903 /*
904 * poll_interval = 2;
905 */
906 }
907
upsdrv_shutdown(void)908 void upsdrv_shutdown(void)
909 {
910 /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */
911 int retry;
912
913 /* maybe try to detect the UPS here, but try a shutdown even if
914 it doesn't respond at first if possible */
915
916 /* replace with a proper shutdown function */
917
918
919 /* you may have to check the line status since the commands
920 for toggling power are frequently different for OL vs. OB */
921
922 /* OL: this must power cycle the load if possible */
923
924 /* OB: the load must remain off until the power returns */
925 upsdebugx(2, "upsdrv Shutdown execute");
926
927 for (retry = 1; retry <= MAXTRIES; retry++) {
928
929 if (riello_instcmd("shutdown.stop", NULL) != STAT_INSTCMD_HANDLED) {
930 continue;
931 }
932
933 if (riello_instcmd("shutdown.return", NULL) != STAT_INSTCMD_HANDLED) {
934 continue;
935 }
936
937 fatalx(EXIT_SUCCESS, "Shutting down");
938 }
939
940 fatalx(EXIT_FAILURE, "Shutdown failed!");
941 }
942
943
944 /*
945 static int setvar(const char *varname, const char *val)
946 {
947 if (!strcasecmp(varname, "ups.test.interval")) {
948 ser_send_buf(upsfd, ...);
949 return STAT_SET_HANDLED;
950 }
951
952 upslogx(LOG_NOTICE, "setvar: unknown variable [%s]", varname);
953 return STAT_SET_UNKNOWN;
954 }
955 */
956
upsdrv_help(void)957 void upsdrv_help(void)
958 {
959 }
960
961 /* list flags and values that you want to receive via -x */
upsdrv_makevartable(void)962 void upsdrv_makevartable(void)
963 {
964 /* allow '-x xyzzy' */
965 /* addvar(VAR_FLAG, "xyzzy", "Enable xyzzy mode"); */
966
967 /* allow '-x foo=<some value>' */
968 /* addvar(VAR_VALUE, "foo", "Override foo setting"); */
969 }
970
upsdrv_initups(void)971 void upsdrv_initups(void)
972 {
973 upsdebugx(2, "entering upsdrv_initups()");
974
975 upsfd = ser_open(device_path);
976
977 riello_comm_setup(device_path);
978
979 /* probe ups type */
980
981 /* to get variables and flags from the command line, use this:
982 *
983 * first populate with upsdrv_buildvartable above, then...
984 *
985 * set flag foo : /bin/driver -x foo
986 * set variable 'cable' to '1234' : /bin/driver -x cable=1234
987 *
988 * to test flag foo in your code:
989 *
990 * if (testvar("foo"))
991 * do_something();
992 *
993 * to show the value of cable:
994 *
995 * if ((cable = getval("cable")))
996 * printf("cable is set to %s\n", cable);
997 * else
998 * printf("cable is not set!\n");
999 *
1000 * don't use NULL pointers - test the return result first!
1001 */
1002
1003 /* the upsh handlers can't be done here, as they get initialized
1004 * shortly after upsdrv_initups returns to main.
1005 */
1006
1007 /* don't try to detect the UPS here */
1008
1009 /* initialise communication */
1010 }
1011
upsdrv_cleanup(void)1012 void upsdrv_cleanup(void)
1013 {
1014 /* free(dynamic_mem); */
1015 ser_close(upsfd, device_path);
1016 }
1017
riello_comm_setup(const char * port)1018 void riello_comm_setup(const char *port)
1019 {
1020 uint8_t length;
1021
1022 upsdebugx(2, "set baudrate 9600");
1023 ser_set_speed(upsfd, device_path, B9600);
1024
1025 upsdebugx(2, "try to detect SENTR");
1026 riello_init_serial();
1027 bufOut[0] = 192;
1028 ser_send_buf(upsfd, bufOut, 1);
1029
1030 riello_serialcomm(&bufIn[0], DEV_RIELLOSENTRY);
1031
1032 if (buf_ptr_length == 103) {
1033 typeRielloProtocol = DEV_RIELLOSENTRY;
1034 upslogx(LOG_INFO, "Connected to UPS SENTR on %s with baudrate %d", port, 9600);
1035 return;
1036 }
1037
1038 upsdebugx(2, "try to detect GPSER");
1039 riello_init_serial();
1040 length = riello_prepare_gi(&bufOut[0]);
1041
1042 ser_send_buf(upsfd, bufOut, length);
1043
1044 riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
1045
1046 if (!wait_packet && !foundbadcrc && !foundnak) {
1047 typeRielloProtocol = DEV_RIELLOGPSER;
1048 upslogx(LOG_INFO, "Connected to UPS GPSER on %s with baudrate %d", port, 9600);
1049 return;
1050 }
1051
1052 upsdebugx(2, "set baudrate 1200");
1053 ser_set_speed(upsfd, device_path, B1200);
1054
1055 upsdebugx(2, "try to detect SENTR");
1056 riello_init_serial();
1057 bufOut[0] = 192;
1058 ser_send_buf(upsfd, bufOut, 1);
1059
1060 riello_serialcomm(&bufIn[0], DEV_RIELLOSENTRY);
1061
1062 if (buf_ptr_length == 103) {
1063 typeRielloProtocol = DEV_RIELLOSENTRY;
1064 upslogx(LOG_INFO, "Connected to UPS SENTR on %s with baudrate %d", port, 1200);
1065 return;
1066 }
1067
1068 upsdebugx(2, "try to detect GPSER");
1069 riello_init_serial();
1070 length = riello_prepare_gi(&bufOut[0]);
1071
1072 ser_send_buf(upsfd, bufOut, length);
1073
1074 riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
1075
1076 if (!wait_packet && !foundbadcrc && !foundnak) {
1077 typeRielloProtocol = DEV_RIELLOGPSER;
1078 upslogx(LOG_INFO, "Connected to UPS GPSER on %s with baudrate %d", port, 1200);
1079 return;
1080 }
1081
1082 fatalx(EXIT_FAILURE, "Can't connect to the UPS on port %s!\n", port);
1083 }
1084
1085