/* returns < 0 on errors, 0 on timeout and > 0 on success. */ static int upscrecv(char *buf) { int res; /* NOTE: the serial port is set to use Canonical Mode Input Processing, which means ser_get_buf() either returns one line terminated with ENDCHAR, an error or times out. */ while (1) { res = ser_get_buf(upsfd, buf, UPSC_BUFLEN, input_timeout_sec, 0); if (res != 1) { break; } /* Only one character, must be ENDCHAR */ upsdebugx(3, "upscrecv: Empty line"); } if (res < 0) { upsdebug_with_errno(3, "upscrecv"); } else if (res == 0) { upsdebugx(3, "upscrecv: Timeout"); } else { upsdebugx(3, "upscrecv: %u bytes:\t'%s'", res-1, str_rtrim(buf, ENDCHAR)); } return res; }
/* * Generic command processing function. Send a command and read a reply. * Returns < 0 on error, 0 on timeout and the number of bytes read on * success. */ int blazer_command(const char *cmd, char *buf, size_t buflen) { #ifndef TESTING int ret; ser_flush_io(upsfd); ret = ser_send(upsfd, "%s", cmd); if (ret <= 0) { upsdebugx(3, "send: %s", ret ? strerror(errno) : "timeout"); return ret; } upsdebugx(3, "send: '%.*s'", (int)strcspn(cmd, "\r"), cmd); ret = ser_get_buf(upsfd, buf, buflen, SER_WAIT_SEC, 0); if (ret <= 0) { upsdebugx(3, "read: %s", ret ? strerror(errno) : "timeout"); return ret; } upsdebugx(3, "read: '%.*s'", (int)strcspn(buf, "\r"), buf); return ret; #else const struct { const char *cmd; const char *answer; } testing[] = { { "Q1\r", "(215.0 195.0 230.0 014 49.0 2.27 30.0 00101000\r" }, { "F\r", "#230.0 000 024.0 50.0\r" }, { "I\r", "#NOT_A_LIVE_UPS TESTING TESTING \r" }, { NULL } }; int i; memset(buf, 0, buflen); for (i = 0; cmd && testing[i].cmd; i++) { if (strcasecmp(cmd, testing[i].cmd)) { continue; } return snprintf(buf, buflen, "%s", testing[i].answer); } return snprintf(buf, buflen, "%s", testing[i].cmd); #endif }
static int ivt_status(void) { char reply[SMALLBUF]; int ret, i, j = 0; ser_flush_io(upsfd); /* * send: F\n */ ret = ser_send(upsfd, "F"); if (ret < 0) { upsdebug_with_errno(3, "send"); return -1; } if (ret == 0) { upsdebug_with_errno(3, "send: timeout"); return -1; } upsdebugx(3, "send: F"); sleep(1); /* allow controller some time to digest this */ /* * read: R:12,57;- 1,1;20;12,57;13,18;- 2,1; 1,5;\n */ ret = ser_get_buf(upsfd, reply, sizeof(reply), 1, 0); if (ret < 0) { upsdebug_with_errno(3, "read"); return -1; } if (ret == 0) { upsdebugx(3, "read: timeout"); return -1; } upsdebugx(3, "read: %.*s", (int)strcspn(reply, "\r\n"), reply); upsdebug_hex(4, " \\_", reply, ret); for (i = 0; i < ret; i++) { switch(reply[i]) { case ',': /* convert ',' to '.' */ reply[j++] = '.'; break; case ' ': /* skip over white space */ case '\0': /* skip over null characters */ break; default: /* leave the rest as is */ reply[j++] = reply[i]; break; } } reply[j++] = '\0'; ret = sscanf(reply, "R:%f;%f;%f;%f;%f;%f;%f;", &battery.voltage.act, &battery.current.act, &battery.temperature, &battery.voltage.min, &battery.voltage.max, &battery.current.min, &battery.current.max); upsdebugx(3, "Parsed %d parameters from reply", ret); return ret; }